From b75f5a6b3bc3ccb126460dd9eeaa535aea05cb27 Mon Sep 17 00:00:00 2001
From: hanfi <ccc@spahan.ch>
Date: Fri, 11 Aug 2023 00:28:24 +0200
Subject: [PATCH] item endpoint requires auth now

---
 dist/bundle.js | 2 +-
 src/js/main.js | 9 +++++++--
 2 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/dist/bundle.js b/dist/bundle.js
index b7fb7e1..f05bd2d 100644
--- a/dist/bundle.js
+++ b/dist/bundle.js
@@ -1 +1 @@
-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  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\n                .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\n                            .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\n            .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\n            .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\n                    .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 Error(\'Expected Uint8Array\');\n    if (lengths.length > 0 && !lengths.includes(b.length))\n        throw new Error(`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 WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don\'t declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// 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\nconst u8a = (a) => a instanceof Uint8Array;\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([0xca, 0xfe, 0x01, 0x23])) // \'cafe0123\'\n */\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}\n/**\n * @example hexToBytes(\'cafe0123\') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nfunction hexToBytes(hex) {\n    if (typeof hex !== \'string\')\n        throw new Error(\'hex string expected, got \' + typeof hex);\n    const len = hex.length;\n    if (len % 2)\n        throw new Error(\'padded hex string expected, got unpadded hex of length \' + len);\n    const array = new Uint8Array(len / 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}\n/**\n * @example utf8ToBytes(\'abc\') // new Uint8Array([97, 98, 99])\n */\nfunction utils_utf8ToBytes(str) {\n    if (typeof str !== \'string\')\n        throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n    return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nfunction toBytes(data) {\n    if (typeof data === \'string\')\n        data = utils_utf8ToBytes(data);\n    if (!u8a(data))\n        throw new Error(`expected Uint8Array, got ${typeof data}`);\n    return data;\n}\n/**\n * Copies several Uint8Arrays into one.\n */\nfunction utils_concatBytes(...arrays) {\n    const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));\n    let pad = 0; // walk through each item, ensure they have proper type\n    arrays.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}\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 Error(\'Options should be object or undefined\');\n    const merged = Object.assign(defaults, opts);\n    return merged;\n}\nfunction wrapConstructor(hashCons) {\n    const hashC = (msg) => hashCons().update(toBytes(msg)).digest();\n    const tmp = hashCons();\n    hashC.outputLen = tmp.outputLen;\n    hashC.blockLen = tmp.blockLen;\n    hashC.create = () => hashCons();\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}\nfunction wrapXOFConstructorWithOpts(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 `crypto.getRandomValues`, which defers to OS.\n */\nfunction utils_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) => wrapXOFConstructorWithOpts((opts = {}) => new Keccak(blockLen, suffix, opts.dkLen === undefined ? outputLen : opts.dkLen, true));\nconst shake128 = genShake(0x1f, 168, 128 / 8);\nconst sha3_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) */\n// 100 lines of code in the file are duplicated from noble-hashes (utils).\n// This is OK: `abstract` directory does not use noble-hashes.\n// User may opt-in into using different hashing library. This way, noble-hashes\n// won\'t be included into their bundle.\nconst utils_0n = BigInt(0);\nconst utils_1n = BigInt(1);\nconst utils_2n = BigInt(2);\nconst utils_u8a = (a) => a instanceof Uint8Array;\nconst utils_hexes = Array.from({ length: 256 }, (v, i) => i.toString(16).padStart(2, \'0\'));\n/**\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // \'cafe0123\'\n */\nfunction utils_bytesToHex(bytes) {\n    if (!utils_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/**\n * @example hexToBytes(\'cafe0123\') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nfunction utils_hexToBytes(hex) {\n    if (typeof hex !== \'string\')\n        throw new Error(\'hex string expected, got \' + typeof hex);\n    const len = hex.length;\n    if (len % 2)\n        throw new Error(\'padded hex string expected, got unpadded hex of length \' + len);\n    const array = new Uint8Array(len / 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// BE: Big Endian, LE: Little Endian\nfunction utils_bytesToNumberBE(bytes) {\n    return hexToNumber(utils_bytesToHex(bytes));\n}\nfunction utils_bytesToNumberLE(bytes) {\n    if (!utils_u8a(bytes))\n        throw new Error(\'Uint8Array expected\');\n    return hexToNumber(utils_bytesToHex(Uint8Array.from(bytes).reverse()));\n}\nfunction numberToBytesBE(n, len) {\n    return utils_hexToBytes(n.toString(16).padStart(len * 2, \'0\'));\n}\nfunction utils_numberToBytesLE(n, len) {\n    return numberToBytesBE(n, len).reverse();\n}\n// Unpadded, rarely used\nfunction numberToVarBytesBE(n) {\n    return utils_hexToBytes(numberToHexUnpadded(n));\n}\n/**\n * Takes hex string or Uint8Array, converts to Uint8Array.\n * Validates output length.\n * Will throw error for other types.\n * @param title descriptive title for an error e.g. \'private key\'\n * @param hex hex string or Uint8Array\n * @param expectedLength optional, will compare to result array\'s length\n * @returns\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 (utils_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/**\n * Copies several Uint8Arrays into one.\n */\nfunction abstract_utils_concatBytes(...arrays) {\n    const r = new Uint8Array(arrays.reduce((sum, a) => sum + a.length, 0));\n    let pad = 0; // walk through each item, ensure they have proper type\n    arrays.forEach((a) => {\n        if (!utils_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}\n/**\n * @example utf8ToBytes(\'abc\') // new Uint8Array([97, 98, 99])\n */\nfunction abstract_utils_utf8ToBytes(str) {\n    if (typeof str !== \'string\')\n        throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n    return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n// Bit operations\n/**\n * Calculates amount of bits in a bigint.\n * Same as `n.toString(2).length`\n */\nfunction bitLen(n) {\n    let len;\n    for (len = 0; n > utils_0n; n >>= utils_1n, len += 1)\n        ;\n    return len;\n}\n/**\n * Gets single bit at position.\n * NOTE: first bit position is 0 (same as arrays)\n * Same as `!!+Array.from(n.toString(2)).reverse()[pos]`\n */\nfunction bitGet(n, pos) {\n    return (n >> BigInt(pos)) & utils_1n;\n}\n/**\n * Sets single bit at position.\n */\nconst bitSet = (n, pos, value) => {\n    return n | ((value ? utils_1n : utils_0n) << BigInt(pos));\n};\n/**\n * Calculate mask for N bits. Not using ** operator with bigints because of old engines.\n * Same as BigInt(`0b${Array(i).fill(\'1\').join(\'\')}`)\n */\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 abstract_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 utils_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 modular_mod(a, b) {\n    const result = a % b;\n    return result >= modular_0n ? result : b + result;\n}\n/**\n * Efficiently raise num to power and do modular division.\n * Unsafe in some contexts: uses ladder, so can expose bigint bits.\n * @example\n * pow(2n, 6n, 11n) // 64n % 11n == 9n\n */\n// TODO: use field version && remove\nfunction modular_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 modular_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    // Euclidean 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 = modular_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 modular_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 && modular_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) => (modular_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 utils_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) => modular_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) => modular_mod(-num, ORDER),\n        eql: (lhs, rhs) => lhs === rhs,\n        sqr: (num) => modular_mod(num * num, ORDER),\n        add: (lhs, rhs) => modular_mod(lhs + rhs, ORDER),\n        sub: (lhs, rhs) => modular_mod(lhs - rhs, ORDER),\n        mul: (lhs, rhs) => modular_mod(lhs * rhs, ORDER),\n        pow: (num, power) => FpPow(f, num, power),\n        div: (lhs, rhs) => modular_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 ? utils_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 negligible.\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 * @param groupOrder size of subgroup - (e.g. curveFn.CURVE.n)\n * @param isLE interpret hash bytes as LE num\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 modular_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    utils_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    utils_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) - edwards_1n);\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; // x_0, last bit\n            if (!zip215 && x === edwards_0n && isLastByteOdd)\n                // if x=0 and x_0 = 1, fail\n                throw new Error(\'Point.fromHex: x=0 and x_0=1\');\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_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 modular_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 = abstract_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 = abstract_utils_concatBytes(R, utils_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        if (!zip215 && A.isSmallOrder())\n            return false;\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_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 = 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 bytesToNumberLE(u);\n    }\n    function decodeScalar(n) {\n        const bytes = 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 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 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 = (/* unused pure expression or super */ null && (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(concatBytes(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 = 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(concatBytes(Z_pad, msg, l_i_b_str, i2osp(0, 1), DST_prime));\n    b[0] = H(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(concatBytes(...args));\n    }\n    const pseudo_random_bytes = 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(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 hash_to_curve_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(() => sha3_shake256.create({ dkLen: 114 }));\nconst shake256_64 = wrapConstructor(() => sha3_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 = (modular_pow2(b3, _3n, P) * b3) % P;\n    const b9 = (modular_pow2(b6, _3n, P) * b3) % P;\n    const b11 = (modular_pow2(b9, _2n, P) * b2) % P;\n    const b22 = (modular_pow2(b11, _11n, P) * b11) % P;\n    const b44 = (modular_pow2(b22, _22n, P) * b22) % P;\n    const b88 = (modular_pow2(b44, _44n, P) * b44) % P;\n    const b176 = (modular_pow2(b88, _88n, P) * b88) % P;\n    const b220 = (modular_pow2(b176, _44n, P) * b44) % P;\n    const b222 = (modular_pow2(b220, _2n, P) * b2) % P;\n    const b223 = (modular_pow2(b222, _1n, P) * x) % P;\n    return (modular_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: utils_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 utils_concatBytes(utils_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 = modular_mod(u * u * v, P); // u²v\n        const u3v = modular_mod(u2v * u, P); // u³v\n        const u5v3 = modular_mod(u3v * u2v * v, P); // u⁵v³\n        const root = ed448_pow_Pminus3div4(u5v3);\n        const x = modular_mod(u3v * root, P);\n        // Verify that root is exists\n        const x2 = modular_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: modular_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 = /* @__PURE__ */ (/* unused pure expression or super */ null && ((() => 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,\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 edwardsToMontgomeryPub(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}\nconst edwardsToMontgomery = (/* unused pure expression or super */ null && (edwardsToMontgomeryPub)); // deprecated\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 htf = /* @__PURE__ */ (/* unused pure expression or super */ null && ((() => 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}))()));\nconst hashToCurve = /* @__PURE__ */ (/* unused pure expression or super */ null && ((() => htf.hashToCurve)()));\nconst encodeToCurve = /* @__PURE__ */ (/* unused pure expression or super */ null && ((() => htf.encodeToCurve)()));\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 */.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    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 fetch(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 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        case 8:\n          response = _context17.sent;\n          if (!(response.status == 200)) {\n            _context17.next = 16;\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            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            console.log("Receiver verify success");\n          } else {\n            alert("Could not verify signature.");\n            console.log("Could not verify signature.");\n          }\n          _context17.next = 17;\n          break;\n        case 16:\n          if (response.status == 404) {\n            alert("Item not found.");\n          } else {\n            checkResponseForError(response, "Failed to get item from backend.");\n          }\n        case 17:\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() {\n  return _onPageLoad.apply(this, arguments);\n}\nfunction _onPageLoad() {\n  _onPageLoad = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20() {\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          loadStorages(document.location.search.substring(1));\n        case 11:\n        case "end":\n          return _context20.stop();\n      }\n    }, _callee20);\n  }));\n  return _onPageLoad.apply(this, arguments);\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMjQ0LmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0VEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3YwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQy9DQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN2S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2pwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1REE7QUFDQTs7QUNEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzFKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4UUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDeFdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN4YUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNUpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdEtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN0TkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2NvcmUuanM/NGIzYiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9zdHJpbmdzLmpzPzE0YTMiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdXRpbHMuanM/NjE2NCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS96eGluZy1odG1sNS1xcmNvZGUtZGVjb2Rlci5qcz80MzFmIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL25hdGl2ZS1iYXItY29kZS1kZXRlY3Rvci5qcz9kZTljIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2NvZGUtZGVjb2Rlci5qcz9lODI0Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2NhbWVyYS9jb3JlLWltcGwuanM/Yjc2YiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvZmFjdG9yaWVzLmpzPzdlYzciLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vY2FtZXJhL3JldHJpZXZlci5qcz81MzAyIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3N0YXRlLW1hbmFnZXIuanM/ZDkxYiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9odG1sNS1xcmNvZGUuanM/NGMyMCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9pbWFnZS1hc3NldHMuanM/MWM4ZCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9zdG9yYWdlLmpzPzc5ODQiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdWkuanM/NzE5ZCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvcGVybWlzc2lvbnMuanM/NzAwOSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL3NjYW4tdHlwZS1zZWxlY3Rvci5qcz9hYmVlIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvYmFzZS5qcz80MTRmIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvdG9yY2gtYnV0dG9uLmpzPzMzMDMiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdWkvc2Nhbm5lci9maWxlLXNlbGVjdGlvbi11aS5qcz85NWFlIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvY2FtZXJhLXNlbGVjdGlvbi11aS5qcz83M2RkIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvY2FtZXJhLXpvb20tdWkuanM/ZTZmMSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9odG1sNS1xcmNvZGUtc2Nhbm5lci5qcz84NWQ1Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2luZGV4LmpzPzc4NGUiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9oYXNoZXMvZXNtL19hc3NlcnQuanM/ZDg4YyIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vX3U2NC5qcz84NzhlIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvaGFzaGVzL2VzbS9jcnlwdG8uanM/YzNkNyIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vdXRpbHMuanM/MmJiYyIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vc2hhMy5qcz9mNDU4Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC91dGlscy5qcz83OGRhIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9tb2R1bGFyLmpzP2ZmMzQiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2Fic3RyYWN0L2N1cnZlLmpzPzc1NGEiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2Fic3RyYWN0L2Vkd2FyZHMuanM/NmYxZCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvbW9udGdvbWVyeS5qcz83NTdkIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9oYXNoLXRvLWN1cnZlLmpzPzhmYTQiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2VkNDQ4LmpzPzJjMGIiLCJ3ZWJwYWNrOi8vbGliLy4vc3JjL2pzL21haW4uanM/MDAzYSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgdmFyIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cztcbihmdW5jdGlvbiAoSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKSB7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlFSX0NPREVcIl0gPSAwXSA9IFwiUVJfQ09ERVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJBWlRFQ1wiXSA9IDFdID0gXCJBWlRFQ1wiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJDT0RBQkFSXCJdID0gMl0gPSBcIkNPREFCQVJcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiQ09ERV8zOVwiXSA9IDNdID0gXCJDT0RFXzM5XCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIkNPREVfOTNcIl0gPSA0XSA9IFwiQ09ERV85M1wiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJDT0RFXzEyOFwiXSA9IDVdID0gXCJDT0RFXzEyOFwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJEQVRBX01BVFJJWFwiXSA9IDZdID0gXCJEQVRBX01BVFJJWFwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJNQVhJQ09ERVwiXSA9IDddID0gXCJNQVhJQ09ERVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJJVEZcIl0gPSA4XSA9IFwiSVRGXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIkVBTl8xM1wiXSA9IDldID0gXCJFQU5fMTNcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiRUFOXzhcIl0gPSAxMF0gPSBcIkVBTl84XCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlBERl80MTdcIl0gPSAxMV0gPSBcIlBERl80MTdcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiUlNTXzE0XCJdID0gMTJdID0gXCJSU1NfMTRcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiUlNTX0VYUEFOREVEXCJdID0gMTNdID0gXCJSU1NfRVhQQU5ERURcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiVVBDX0FcIl0gPSAxNF0gPSBcIlVQQ19BXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlVQQ19FXCJdID0gMTVdID0gXCJVUENfRVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJVUENfRUFOX0VYVEVOU0lPTlwiXSA9IDE2XSA9IFwiVVBDX0VBTl9FWFRFTlNJT05cIjtcbn0pKEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyB8fCAoSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzID0ge30pKTtcbnZhciBodG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNUZXh0TWFwID0gbmV3IE1hcChbXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5RUl9DT0RFLCBcIlFSX0NPREVcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5BWlRFQywgXCJBWlRFQ1wiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREFCQVIsIFwiQ09EQUJBUlwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMzksIFwiQ09ERV8zOVwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsIFwiQ09ERV85M1wiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMTI4LCBcIkNPREVfMTI4XCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuREFUQV9NQVRSSVgsIFwiREFUQV9NQVRSSVhcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5NQVhJQ09ERSwgXCJNQVhJQ09ERVwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLklURiwgXCJJVEZcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsIFwiRUFOXzEzXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzgsIFwiRUFOXzhcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5QREZfNDE3LCBcIlBERl80MTdcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfMTQsIFwiUlNTXzE0XCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTX0VYUEFOREVELCBcIlJTU19FWFBBTkRFRFwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19BLCBcIlVQQ19BXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0UsIFwiVVBDX0VcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfRUFOX0VYVEVOU0lPTiwgXCJVUENfRUFOX0VYVEVOU0lPTlwiXVxuXSk7XG5leHBvcnQgdmFyIERlY29kZWRUZXh0VHlwZTtcbihmdW5jdGlvbiAoRGVjb2RlZFRleHRUeXBlKSB7XG4gICAgRGVjb2RlZFRleHRUeXBlW0RlY29kZWRUZXh0VHlwZVtcIlVOS05PV05cIl0gPSAwXSA9IFwiVU5LTk9XTlwiO1xuICAgIERlY29kZWRUZXh0VHlwZVtEZWNvZGVkVGV4dFR5cGVbXCJVUkxcIl0gPSAxXSA9IFwiVVJMXCI7XG59KShEZWNvZGVkVGV4dFR5cGUgfHwgKERlY29kZWRUZXh0VHlwZSA9IHt9KSk7XG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhmb3JtYXQpIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMpLmluY2x1ZGVzKGZvcm1hdCk7XG59XG5leHBvcnQgdmFyIEh0bWw1UXJjb2RlU2NhblR5cGU7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU2NhblR5cGUpIHtcbiAgICBIdG1sNVFyY29kZVNjYW5UeXBlW0h0bWw1UXJjb2RlU2NhblR5cGVbXCJTQ0FOX1RZUEVfQ0FNRVJBXCJdID0gMF0gPSBcIlNDQU5fVFlQRV9DQU1FUkFcIjtcbiAgICBIdG1sNVFyY29kZVNjYW5UeXBlW0h0bWw1UXJjb2RlU2NhblR5cGVbXCJTQ0FOX1RZUEVfRklMRVwiXSA9IDFdID0gXCJTQ0FOX1RZUEVfRklMRVwiO1xufSkoSHRtbDVRcmNvZGVTY2FuVHlwZSB8fCAoSHRtbDVRcmNvZGVTY2FuVHlwZSA9IHt9KSk7XG52YXIgSHRtbDVRcmNvZGVDb25zdGFudHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlQ29uc3RhbnRzKCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZUNvbnN0YW50cy5HSVRIVUJfUFJPSkVDVF9VUkwgPSBcImh0dHBzOi8vZ2l0aHViLmNvbS9tZWJqYXMvaHRtbDUtcXJjb2RlXCI7XG4gICAgSHRtbDVRcmNvZGVDb25zdGFudHMuU0NBTl9ERUZBVUxUX0ZQUyA9IDI7XG4gICAgSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9ESVNBQkxFX0ZMSVAgPSBmYWxzZTtcbiAgICBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1JFTUVNQkVSX0xBU1RfQ0FNRVJBX1VTRUQgPSB0cnVlO1xuICAgIEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRSA9IFtcbiAgICAgICAgSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfQ0FNRVJBLFxuICAgICAgICBIdG1sNVFyY29kZVNjYW5UeXBlLlNDQU5fVFlQRV9GSUxFXG4gICAgXTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVDb25zdGFudHM7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVDb25zdGFudHMgfTtcbnZhciBRcmNvZGVSZXN1bHRGb3JtYXQgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFFyY29kZVJlc3VsdEZvcm1hdChmb3JtYXQsIGZvcm1hdE5hbWUpIHtcbiAgICAgICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7XG4gICAgICAgIHRoaXMuZm9ybWF0TmFtZSA9IGZvcm1hdE5hbWU7XG4gICAgfVxuICAgIFFyY29kZVJlc3VsdEZvcm1hdC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdE5hbWU7XG4gICAgfTtcbiAgICBRcmNvZGVSZXN1bHRGb3JtYXQuY3JlYXRlID0gZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICBpZiAoIWh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1RleHRNYXAuaGFzKGZvcm1hdCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiXCIuY29uY2F0KGZvcm1hdCwgXCIgbm90IGluIGh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1RleHRNYXBcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBRcmNvZGVSZXN1bHRGb3JtYXQoZm9ybWF0LCBodG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNUZXh0TWFwLmdldChmb3JtYXQpKTtcbiAgICB9O1xuICAgIHJldHVybiBRcmNvZGVSZXN1bHRGb3JtYXQ7XG59KCkpO1xuZXhwb3J0IHsgUXJjb2RlUmVzdWx0Rm9ybWF0IH07XG52YXIgSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkoKSB7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeS5jcmVhdGVGcm9tVGV4dCA9IGZ1bmN0aW9uIChkZWNvZGVkVGV4dCkge1xuICAgICAgICB2YXIgcXJjb2RlUmVzdWx0ID0ge1xuICAgICAgICAgICAgdGV4dDogZGVjb2RlZFRleHRcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRlY29kZWRUZXh0OiBkZWNvZGVkVGV4dCxcbiAgICAgICAgICAgIHJlc3VsdDogcXJjb2RlUmVzdWx0XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkuY3JlYXRlRnJvbVFyY29kZVJlc3VsdCA9IGZ1bmN0aW9uIChxcmNvZGVSZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRlY29kZWRUZXh0OiBxcmNvZGVSZXN1bHQudGV4dCxcbiAgICAgICAgICAgIHJlc3VsdDogcXJjb2RlUmVzdWx0XG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5O1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeSB9O1xuZXhwb3J0IHZhciBIdG1sNVFyY29kZUVycm9yVHlwZXM7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlRXJyb3JUeXBlcykge1xuICAgIEh0bWw1UXJjb2RlRXJyb3JUeXBlc1tIdG1sNVFyY29kZUVycm9yVHlwZXNbXCJVTktXT1dOX0VSUk9SXCJdID0gMF0gPSBcIlVOS1dPV05fRVJST1JcIjtcbiAgICBIdG1sNVFyY29kZUVycm9yVHlwZXNbSHRtbDVRcmNvZGVFcnJvclR5cGVzW1wiSU1QTEVNRU5UQVRJT05fRVJST1JcIl0gPSAxXSA9IFwiSU1QTEVNRU5UQVRJT05fRVJST1JcIjtcbiAgICBIdG1sNVFyY29kZUVycm9yVHlwZXNbSHRtbDVRcmNvZGVFcnJvclR5cGVzW1wiTk9fQ09ERV9GT1VORF9FUlJPUlwiXSA9IDJdID0gXCJOT19DT0RFX0ZPVU5EX0VSUk9SXCI7XG59KShIdG1sNVFyY29kZUVycm9yVHlwZXMgfHwgKEh0bWw1UXJjb2RlRXJyb3JUeXBlcyA9IHt9KSk7XG52YXIgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5KCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZUVycm9yRmFjdG9yeS5jcmVhdGVGcm9tID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLFxuICAgICAgICAgICAgdHlwZTogSHRtbDVRcmNvZGVFcnJvclR5cGVzLlVOS1dPV05fRVJST1JcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHJldHVybiBIdG1sNVFyY29kZUVycm9yRmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZUVycm9yRmFjdG9yeSB9O1xudmFyIEJhc2VMb2dnZ2VyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXNlTG9nZ2dlcih2ZXJib3NlKSB7XG4gICAgICAgIHRoaXMudmVyYm9zZSA9IHZlcmJvc2U7XG4gICAgfVxuICAgIEJhc2VMb2dnZ2VyLnByb3RvdHlwZS5sb2cgPSBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQmFzZUxvZ2dnZXIucHJvdG90eXBlLndhcm4gPSBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEJhc2VMb2dnZ2VyLnByb3RvdHlwZS5sb2dFcnJvciA9IGZ1bmN0aW9uIChtZXNzYWdlLCBpc0V4cGVyaW1lbnRhbCkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlIHx8IGlzRXhwZXJpbWVudGFsID09PSB0cnVlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBCYXNlTG9nZ2dlci5wcm90b3R5cGUubG9nRXJyb3JzID0gZnVuY3Rpb24gKGVycm9ycykge1xuICAgICAgICBpZiAoZXJyb3JzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgXCJMb2dnZXIjbG9nRXJyb3IgY2FsbGVkIHdpdGhvdXQgYXJndW1lbnRzXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcnMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gQmFzZUxvZ2dnZXI7XG59KCkpO1xuZXhwb3J0IHsgQmFzZUxvZ2dnZXIgfTtcbmV4cG9ydCBmdW5jdGlvbiBpc051bGxPclVuZGVmaW5lZChvYmopIHtcbiAgICByZXR1cm4gKHR5cGVvZiBvYmogPT09IFwidW5kZWZpbmVkXCIpIHx8IG9iaiA9PT0gbnVsbDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjbGlwKHZhbHVlLCBtaW5WYWx1ZSwgbWF4VmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPiBtYXhWYWx1ZSkge1xuICAgICAgICByZXR1cm4gbWF4VmFsdWU7XG4gICAgfVxuICAgIGlmICh2YWx1ZSA8IG1pblZhbHVlKSB7XG4gICAgICAgIHJldHVybiBtaW5WYWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29yZS5qcy5tYXAiLCJ2YXIgSHRtbDVRcmNvZGVTdHJpbmdzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZVN0cmluZ3MoKSB7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5jb2RlUGFyc2VFcnJvciA9IGZ1bmN0aW9uIChleGNlcHRpb24pIHtcbiAgICAgICAgcmV0dXJuIFwiUVIgY29kZSBwYXJzZSBlcnJvciwgZXJyb3IgPSBcIi5jb25jYXQoZXhjZXB0aW9uKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5lcnJvckdldHRpbmdVc2VyTWVkaWEgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIFwiRXJyb3IgZ2V0dGluZyB1c2VyTWVkaWEsIGVycm9yID0gXCIuY29uY2F0KGVycm9yKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5vbmx5RGV2aWNlU3VwcG9ydGVkRXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlRoZSBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IG5hdmlnYXRvci5tZWRpYURldmljZXMgLCBvbmx5IFwiXG4gICAgICAgICAgICArIFwic3VwcG9ydGVkIGNhbWVyYUlkT3JDb25maWcgaW4gdGhpcyBjYXNlIGlzIGRldmljZUlkIHBhcmFtZXRlciBcIlxuICAgICAgICAgICAgKyBcIihzdHJpbmcpLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLmNhbWVyYVN0cmVhbWluZ05vdFN1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQ2FtZXJhIHN0cmVhbWluZyBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBicm93c2VyLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLnVuYWJsZVRvUXVlcnlTdXBwb3J0ZWREZXZpY2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJVbmFibGUgdG8gcXVlcnkgc3VwcG9ydGVkIGRldmljZXMsIHVua25vd24gZXJyb3IuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVN0cmluZ3MuaW5zZWN1cmVDb250ZXh0Q2FtZXJhUXVlcnlFcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQ2FtZXJhIGFjY2VzcyBpcyBvbmx5IHN1cHBvcnRlZCBpbiBzZWN1cmUgY29udGV4dCBsaWtlIGh0dHBzIFwiXG4gICAgICAgICAgICArIFwib3IgbG9jYWxob3N0LlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLnNjYW5uZXJQYXVzZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNjYW5uZXIgcGF1c2VkXCI7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTdHJpbmdzO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU3RyaW5ncyB9O1xudmFyIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MoKSB7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2Nhbm5pbmdTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNjYW5uaW5nXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmlkbGVTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIklkbGVcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZXJyb3JTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkVycm9yXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnBlcm1pc3Npb25TdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlBlcm1pc3Npb25cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Mubm9DYW1lcmFGb3VuZEVycm9yU3RhdHVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJObyBDYW1lcmFzXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmxhc3RNYXRjaCA9IGZ1bmN0aW9uIChkZWNvZGVkVGV4dCkge1xuICAgICAgICByZXR1cm4gXCJMYXN0IE1hdGNoOiBcIi5jb25jYXQoZGVjb2RlZFRleHQpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jb2RlU2Nhbm5lclRpdGxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJDb2RlIFNjYW5uZXJcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY2FtZXJhUGVybWlzc2lvblRpdGxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJSZXF1ZXN0IENhbWVyYSBQZXJtaXNzaW9uc1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFQZXJtaXNzaW9uUmVxdWVzdGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiUmVxdWVzdGluZyBjYW1lcmEgcGVybWlzc2lvbnMuLi5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Mubm9DYW1lcmFGb3VuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiTm8gY2FtZXJhIGZvdW5kXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TdG9wU2Nhbm5pbmdUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTdG9wIFNjYW5uaW5nXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TdGFydFNjYW5uaW5nVGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU3RhcnQgU2Nhbm5pbmdcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPbkJ1dHRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU3dpdGNoIE9uIFRvcmNoXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT2ZmQnV0dG9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTd2l0Y2ggT2ZmIFRvcmNoXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT25GYWlsZWRNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJGYWlsZWQgdG8gdHVybiBvbiB0b3JjaFwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9mZkZhaWxlZE1lc3NhZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkZhaWxlZCB0byB0dXJuIG9mZiB0b3JjaFwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FuQnV0dG9uU2Nhbm5pbmdTdGFydGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiTGF1bmNoaW5nIENhbWVyYS4uLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50ZXh0SWZDYW1lcmFTY2FuU2VsZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNjYW4gYW4gSW1hZ2UgRmlsZVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50ZXh0SWZGaWxlU2NhblNlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTY2FuIHVzaW5nIGNhbWVyYSBkaXJlY3RseVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zZWxlY3RDYW1lcmEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNlbGVjdCBDYW1lcmFcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbkNob29zZUltYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJDaG9vc2UgSW1hZ2VcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbkNob29zZUFub3RoZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkNob29zZSBBbm90aGVyXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTZWxlY3Rpb25Ob0ltYWdlU2VsZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIk5vIGltYWdlIGNob29zZW5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuYW5vbnltb3VzQ2FtZXJhUHJlZml4ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJBbm9ueW1vdXMgQ2FtZXJhXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmRyYWdBbmREcm9wTWVzc2FnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiT3IgZHJvcCBhbiBpbWFnZSB0byBzY2FuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmRyYWdBbmREcm9wTWVzc2FnZU9ubHlJbWFnZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIk9yIGRyb3AgYW4gaW1hZ2UgdG8gc2NhbiAob3RoZXIgZmlsZXMgbm90IHN1cHBvcnRlZClcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muem9vbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiem9vbVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5sb2FkaW5nSW1hZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkxvYWRpbmcgaW1hZ2UuLi5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY2FtZXJhU2NhbkFsdFRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkNhbWVyYSBiYXNlZCBzY2FuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTY2FuQWx0VGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiRnVsZSBiYXNlZCBzY2FuXCI7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncztcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH07XG52YXIgTGlicmFyeUluZm9TdHJpbmdzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaWJyYXJ5SW5mb1N0cmluZ3MoKSB7XG4gICAgfVxuICAgIExpYnJhcnlJbmZvU3RyaW5ncy5wb3dlcmVkQnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlBvd2VyZWQgYnkgXCI7XG4gICAgfTtcbiAgICBMaWJyYXJ5SW5mb1N0cmluZ3MucmVwb3J0SXNzdWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJSZXBvcnQgaXNzdWVzXCI7XG4gICAgfTtcbiAgICByZXR1cm4gTGlicmFyeUluZm9TdHJpbmdzO1xufSgpKTtcbmV4cG9ydCB7IExpYnJhcnlJbmZvU3RyaW5ncyB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3RyaW5ncy5qcy5tYXAiLCJ2YXIgVmlkZW9Db25zdHJhaW50c1V0aWwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFZpZGVvQ29uc3RyYWludHNVdGlsKCkge1xuICAgIH1cbiAgICBWaWRlb0NvbnN0cmFpbnRzVXRpbC5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCA9IGZ1bmN0aW9uICh2aWRlb0NvbnN0cmFpbnRzLCBsb2dnZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2aWRlb0NvbnN0cmFpbnRzICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICB2YXIgdHlwZW9mVmlkZW9Db25zdHJhaW50cyA9IHR5cGVvZiB2aWRlb0NvbnN0cmFpbnRzO1xuICAgICAgICAgICAgbG9nZ2VyLmxvZ0Vycm9yKFwidmlkZW9Db25zdHJhaW50cyBzaG91bGQgYmUgb2YgdHlwZSBvYmplY3QsIHRoZSBcIlxuICAgICAgICAgICAgICAgICsgXCJvYmplY3QgcGFzc2VkIGlzIG9mIHR5cGUgXCIuY29uY2F0KHR5cGVvZlZpZGVvQ29uc3RyYWludHMsIFwiLlwiKSwgdHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJhbm5lZEtleXMgPSBbXG4gICAgICAgICAgICBcImF1dG9HYWluQ29udHJvbFwiLFxuICAgICAgICAgICAgXCJjaGFubmVsQ291bnRcIixcbiAgICAgICAgICAgIFwiZWNob0NhbmNlbGxhdGlvblwiLFxuICAgICAgICAgICAgXCJsYXRlbmN5XCIsXG4gICAgICAgICAgICBcIm5vaXNlU3VwcHJlc3Npb25cIixcbiAgICAgICAgICAgIFwic2FtcGxlUmF0ZVwiLFxuICAgICAgICAgICAgXCJzYW1wbGVTaXplXCIsXG4gICAgICAgICAgICBcInZvbHVtZVwiXG4gICAgICAgIF07XG4gICAgICAgIHZhciBiYW5uZWRrZXlzU2V0ID0gbmV3IFNldChiYW5uZWRLZXlzKTtcbiAgICAgICAgdmFyIGtleXNJblZpZGVvQ29uc3RyYWludHMgPSBPYmplY3Qua2V5cyh2aWRlb0NvbnN0cmFpbnRzKTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzXzEgPSBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzOyBfaSA8IGtleXNJblZpZGVvQ29uc3RyYWludHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBrZXkgPSBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKGJhbm5lZGtleXNTZXQuaGFzKGtleSkpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIubG9nRXJyb3IoXCJcIi5jb25jYXQoa2V5LCBcIiBpcyBub3Qgc3VwcG9ydGVkIHZpZGVvQ29uc3RhaW50cy5cIiksIHRydWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIHJldHVybiBWaWRlb0NvbnN0cmFpbnRzVXRpbDtcbn0oKSk7XG5leHBvcnQgeyBWaWRlb0NvbnN0cmFpbnRzVXRpbCB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dXRpbHMuanMubWFwIiwiaW1wb3J0ICogYXMgWlhpbmcgZnJvbSBcIi4uL3RoaXJkX3BhcnR5L3p4aW5nLWpzLnVtZFwiO1xuaW1wb3J0IHsgUXJjb2RlUmVzdWx0Rm9ybWF0LCBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMgfSBmcm9tIFwiLi9jb3JlXCI7XG52YXIgWlhpbmdIdG1sNVFyY29kZURlY29kZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyKHJlcXVlc3RlZEZvcm1hdHMsIHZlcmJvc2UsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLmZvcm1hdE1hcCA9IG5ldyBNYXAoW1xuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5RUl9DT0RFLCBaWGluZy5CYXJjb2RlRm9ybWF0LlFSX0NPREVdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5BWlRFQywgWlhpbmcuQmFyY29kZUZvcm1hdC5BWlRFQ10sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREFCQVIsIFpYaW5nLkJhcmNvZGVGb3JtYXQuQ09EQUJBUl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMzksIFpYaW5nLkJhcmNvZGVGb3JtYXQuQ09ERV8zOV0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsIFpYaW5nLkJhcmNvZGVGb3JtYXQuQ09ERV85M10sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMTI4LFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuQ09ERV8xMjhcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkRBVEFfTUFUUklYLFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuREFUQV9NQVRSSVhcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLk1BWElDT0RFLFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuTUFYSUNPREVcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLklURiwgWlhpbmcuQmFyY29kZUZvcm1hdC5JVEZdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsIFpYaW5nLkJhcmNvZGVGb3JtYXQuRUFOXzEzXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzgsIFpYaW5nLkJhcmNvZGVGb3JtYXQuRUFOXzhdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5QREZfNDE3LCBaWGluZy5CYXJjb2RlRm9ybWF0LlBERl80MTddLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfMTQsIFpYaW5nLkJhcmNvZGVGb3JtYXQuUlNTXzE0XSxcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTX0VYUEFOREVELFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuUlNTX0VYUEFOREVEXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfQSwgWlhpbmcuQmFyY29kZUZvcm1hdC5VUENfQV0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19FLCBaWGluZy5CYXJjb2RlRm9ybWF0LlVQQ19FXSxcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0VBTl9FWFRFTlNJT04sXG4gICAgICAgICAgICAgICAgWlhpbmcuQmFyY29kZUZvcm1hdC5VUENfRUFOX0VYVEVOU0lPTlxuICAgICAgICAgICAgXVxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5yZXZlcnNlRm9ybWF0TWFwID0gdGhpcy5jcmVhdGVSZXZlcnNlRm9ybWF0TWFwKCk7XG4gICAgICAgIGlmICghWlhpbmcpIHtcbiAgICAgICAgICAgIHRocm93IFwiVXNlIGh0bWw1cXJjb2RlLm1pbi5qcyB3aXRob3V0IGVkaXQsIFpYaW5nIG5vdCBmb3VuZC5cIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdmFyIGZvcm1hdHMgPSB0aGlzLmNyZWF0ZVpYaW5nRm9ybWF0cyhyZXF1ZXN0ZWRGb3JtYXRzKTtcbiAgICAgICAgdmFyIGhpbnRzID0gbmV3IE1hcCgpO1xuICAgICAgICBoaW50cy5zZXQoWlhpbmcuRGVjb2RlSGludFR5cGUuUE9TU0lCTEVfRk9STUFUUywgZm9ybWF0cyk7XG4gICAgICAgIGhpbnRzLnNldChaWGluZy5EZWNvZGVIaW50VHlwZS5UUllfSEFSREVSLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuaGludHMgPSBoaW50cztcbiAgICB9XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmRlY29kZUFzeW5jID0gZnVuY3Rpb24gKGNhbnZhcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKF90aGlzLmRlY29kZShjYW52YXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmRlY29kZSA9IGZ1bmN0aW9uIChjYW52YXMpIHtcbiAgICAgICAgdmFyIHp4aW5nRGVjb2RlciA9IG5ldyBaWGluZy5NdWx0aUZvcm1hdFJlYWRlcih0aGlzLnZlcmJvc2UsIHRoaXMuaGludHMpO1xuICAgICAgICB2YXIgbHVtaW5hbmNlU291cmNlID0gbmV3IFpYaW5nLkhUTUxDYW52YXNFbGVtZW50THVtaW5hbmNlU291cmNlKGNhbnZhcyk7XG4gICAgICAgIHZhciBiaW5hcnlCaXRtYXAgPSBuZXcgWlhpbmcuQmluYXJ5Qml0bWFwKG5ldyBaWGluZy5IeWJyaWRCaW5hcml6ZXIobHVtaW5hbmNlU291cmNlKSk7XG4gICAgICAgIHZhciByZXN1bHQgPSB6eGluZ0RlY29kZXIuZGVjb2RlKGJpbmFyeUJpdG1hcCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0ZXh0OiByZXN1bHQudGV4dCxcbiAgICAgICAgICAgIGZvcm1hdDogUXJjb2RlUmVzdWx0Rm9ybWF0LmNyZWF0ZSh0aGlzLnRvSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKHJlc3VsdC5mb3JtYXQpKSxcbiAgICAgICAgICAgIGRlYnVnRGF0YTogdGhpcy5jcmVhdGVEZWJ1Z0RhdGEoKVxuICAgICAgICB9O1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmNyZWF0ZVJldmVyc2VGb3JtYXRNYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuZm9ybWF0TWFwLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXksIF8pIHtcbiAgICAgICAgICAgIHJlc3VsdC5zZXQodmFsdWUsIGtleSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLnRvSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzID0gZnVuY3Rpb24gKHp4aW5nRm9ybWF0KSB7XG4gICAgICAgIGlmICghdGhpcy5yZXZlcnNlRm9ybWF0TWFwLmhhcyh6eGluZ0Zvcm1hdCkpIHtcbiAgICAgICAgICAgIHRocm93IFwicmV2ZXJzZUZvcm1hdE1hcCBkb2Vzbid0IGhhdmUgXCIuY29uY2F0KHp4aW5nRm9ybWF0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZXZlcnNlRm9ybWF0TWFwLmdldCh6eGluZ0Zvcm1hdCk7XG4gICAgfTtcbiAgICBaWGluZ0h0bWw1UXJjb2RlRGVjb2Rlci5wcm90b3R5cGUuY3JlYXRlWlhpbmdGb3JtYXRzID0gZnVuY3Rpb24gKHJlcXVlc3RlZEZvcm1hdHMpIHtcbiAgICAgICAgdmFyIHp4aW5nRm9ybWF0cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHJlcXVlc3RlZEZvcm1hdHNfMSA9IHJlcXVlc3RlZEZvcm1hdHM7IF9pIDwgcmVxdWVzdGVkRm9ybWF0c18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHJlcXVlc3RlZEZvcm1hdCA9IHJlcXVlc3RlZEZvcm1hdHNfMVtfaV07XG4gICAgICAgICAgICBpZiAodGhpcy5mb3JtYXRNYXAuaGFzKHJlcXVlc3RlZEZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICB6eGluZ0Zvcm1hdHMucHVzaCh0aGlzLmZvcm1hdE1hcC5nZXQocmVxdWVzdGVkRm9ybWF0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5sb2dFcnJvcihcIlwiLmNvbmNhdChyZXF1ZXN0ZWRGb3JtYXQsIFwiIGlzIG5vdCBzdXBwb3J0ZWQgYnlcIilcbiAgICAgICAgICAgICAgICAgICAgKyBcIlpYaW5nSHRtbDVRcmNvZGVTaGltXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB6eGluZ0Zvcm1hdHM7XG4gICAgfTtcbiAgICBaWGluZ0h0bWw1UXJjb2RlRGVjb2Rlci5wcm90b3R5cGUuY3JlYXRlRGVidWdEYXRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4geyBkZWNvZGVyTmFtZTogXCJ6eGluZy1qc1wiIH07XG4gICAgfTtcbiAgICByZXR1cm4gWlhpbmdIdG1sNVFyY29kZURlY29kZXI7XG59KCkpO1xuZXhwb3J0IHsgWlhpbmdIdG1sNVFyY29kZURlY29kZXIgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXp4aW5nLWh0bWw1LXFyY29kZS1kZWNvZGVyLmpzLm1hcCIsInZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbmltcG9ydCB7IFFyY29kZVJlc3VsdEZvcm1hdCwgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcIi4vY29yZVwiO1xudmFyIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZShyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpIHtcbiAgICAgICAgdGhpcy5mb3JtYXRNYXAgPSBuZXcgTWFwKFtcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUVJfQ09ERSwgXCJxcl9jb2RlXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5BWlRFQywgXCJhenRlY1wiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09EQUJBUiwgXCJjb2RhYmFyXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LCBcImNvZGVfMzlcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsIFwiY29kZV85M1wiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09ERV8xMjgsIFwiY29kZV8xMjhcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkRBVEFfTUFUUklYLCBcImRhdGFfbWF0cml4XCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5JVEYsIFwiaXRmXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsIFwiZWFuXzEzXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fOCwgXCJlYW5fOFwiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUERGXzQxNywgXCJwZGY0MTdcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19BLCBcInVwY19hXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfRSwgXCJ1cGNfZVwiXVxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5yZXZlcnNlRm9ybWF0TWFwID0gdGhpcy5jcmVhdGVSZXZlcnNlRm9ybWF0TWFwKCk7XG4gICAgICAgIGlmICghQmFyY29kZURldGVjdG9yRGVsZWdhdGUuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJVc2UgaHRtbDVxcmNvZGUubWluLmpzIHdpdGhvdXQgZWRpdCwgVXNlIFwiXG4gICAgICAgICAgICAgICAgKyBcIkJhcmNvZGVEZXRlY3RvckRlbGVnYXRlIG9ubHkgaWYgaXQgaXNTdXBwb3J0ZWQoKTtcIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdmFyIGZvcm1hdHMgPSB0aGlzLmNyZWF0ZUJhcmNvZGVEZXRlY3RvckZvcm1hdHMocmVxdWVzdGVkRm9ybWF0cyk7XG4gICAgICAgIHRoaXMuZGV0ZWN0b3IgPSBuZXcgQmFyY29kZURldGVjdG9yKGZvcm1hdHMpO1xuICAgICAgICBpZiAoIXRoaXMuZGV0ZWN0b3IpIHtcbiAgICAgICAgICAgIHRocm93IFwiQmFyY29kZURldGVjdG9yIGRldGVjdG9yIG5vdCBzdXBwb3J0ZWRcIjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5pc1N1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCEoXCJCYXJjb2RlRGV0ZWN0b3JcIiBpbiB3aW5kb3cpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGR1bW15RGV0ZWN0b3IgPSBuZXcgQmFyY29kZURldGVjdG9yKHsgZm9ybWF0czogW1wicXJfY29kZVwiXSB9KTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBkdW1teURldGVjdG9yICE9PSBcInVuZGVmaW5lZFwiO1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLmRlY29kZUFzeW5jID0gZnVuY3Rpb24gKGNhbnZhcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYmFyY29kZXMsIGxhcmdlc3RCYXJjb2RlO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gWzQsIHRoaXMuZGV0ZWN0b3IuZGV0ZWN0KGNhbnZhcyldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBiYXJjb2RlcyA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYmFyY29kZXMgfHwgYmFyY29kZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJObyBiYXJjb2RlIG9yIFFSIGNvZGUgZGV0ZWN0ZWQuXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXJnZXN0QmFyY29kZSA9IHRoaXMuc2VsZWN0TGFyZ2VzdEJhcmNvZGUoYmFyY29kZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IGxhcmdlc3RCYXJjb2RlLnJhd1ZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXQ6IFFyY29kZVJlc3VsdEZvcm1hdC5jcmVhdGUodGhpcy50b0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhsYXJnZXN0QmFyY29kZS5mb3JtYXQpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVidWdEYXRhOiB0aGlzLmNyZWF0ZURlYnVnRGF0YSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLnNlbGVjdExhcmdlc3RCYXJjb2RlID0gZnVuY3Rpb24gKGJhcmNvZGVzKSB7XG4gICAgICAgIHZhciBsYXJnZXN0QmFyY29kZSA9IG51bGw7XG4gICAgICAgIHZhciBtYXhBcmVhID0gMDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBiYXJjb2Rlc18xID0gYmFyY29kZXM7IF9pIDwgYmFyY29kZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBiYXJjb2RlID0gYmFyY29kZXNfMVtfaV07XG4gICAgICAgICAgICB2YXIgYXJlYSA9IGJhcmNvZGUuYm91bmRpbmdCb3gud2lkdGggKiBiYXJjb2RlLmJvdW5kaW5nQm94LmhlaWdodDtcbiAgICAgICAgICAgIGlmIChhcmVhID4gbWF4QXJlYSkge1xuICAgICAgICAgICAgICAgIG1heEFyZWEgPSBhcmVhO1xuICAgICAgICAgICAgICAgIGxhcmdlc3RCYXJjb2RlID0gYmFyY29kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWxhcmdlc3RCYXJjb2RlKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk5vIGxhcmdlc3QgYmFyY29kZSBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsYXJnZXN0QmFyY29kZTtcbiAgICB9O1xuICAgIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLnByb3RvdHlwZS5jcmVhdGVCYXJjb2RlRGV0ZWN0b3JGb3JtYXRzID0gZnVuY3Rpb24gKHJlcXVlc3RlZEZvcm1hdHMpIHtcbiAgICAgICAgdmFyIGZvcm1hdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCByZXF1ZXN0ZWRGb3JtYXRzXzEgPSByZXF1ZXN0ZWRGb3JtYXRzOyBfaSA8IHJlcXVlc3RlZEZvcm1hdHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciByZXF1ZXN0ZWRGb3JtYXQgPSByZXF1ZXN0ZWRGb3JtYXRzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9ybWF0TWFwLmhhcyhyZXF1ZXN0ZWRGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0cy5wdXNoKHRoaXMuZm9ybWF0TWFwLmdldChyZXF1ZXN0ZWRGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJcIi5jb25jYXQocmVxdWVzdGVkRm9ybWF0LCBcIiBpcyBub3Qgc3VwcG9ydGVkIGJ5XCIpXG4gICAgICAgICAgICAgICAgICAgICsgXCJCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBmb3JtYXRzOiBmb3JtYXRzIH07XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUudG9IdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMgPSBmdW5jdGlvbiAoYmFyY29kZURldGVjdG9yRm9ybWF0KSB7XG4gICAgICAgIGlmICghdGhpcy5yZXZlcnNlRm9ybWF0TWFwLmhhcyhiYXJjb2RlRGV0ZWN0b3JGb3JtYXQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcInJldmVyc2VGb3JtYXRNYXAgZG9lc24ndCBoYXZlIFwiLmNvbmNhdChiYXJjb2RlRGV0ZWN0b3JGb3JtYXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJldmVyc2VGb3JtYXRNYXAuZ2V0KGJhcmNvZGVEZXRlY3RvckZvcm1hdCk7XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUuY3JlYXRlUmV2ZXJzZUZvcm1hdE1hcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5mb3JtYXRNYXAuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSwgXykge1xuICAgICAgICAgICAgcmVzdWx0LnNldCh2YWx1ZSwga2V5KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUuY3JlYXRlRGVidWdEYXRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4geyBkZWNvZGVyTmFtZTogXCJCYXJjb2RlRGV0ZWN0b3JcIiB9O1xuICAgIH07XG4gICAgcmV0dXJuIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlO1xufSgpKTtcbmV4cG9ydCB7IEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1uYXRpdmUtYmFyLWNvZGUtZGV0ZWN0b3IuanMubWFwIiwidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgWlhpbmdIdG1sNVFyY29kZURlY29kZXIgfSBmcm9tIFwiLi96eGluZy1odG1sNS1xcmNvZGUtZGVjb2RlclwiO1xuaW1wb3J0IHsgQmFyY29kZURldGVjdG9yRGVsZWdhdGUgfSBmcm9tIFwiLi9uYXRpdmUtYmFyLWNvZGUtZGV0ZWN0b3JcIjtcbnZhciBIdG1sNVFyY29kZVNoaW0gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlU2hpbShyZXF1ZXN0ZWRGb3JtYXRzLCB1c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCwgdmVyYm9zZSwgbG9nZ2VyKSB7XG4gICAgICAgIHRoaXMuRVhFQ1VUSU9OU19UT19SRVBPUlRfUEVSRk9STUFOQ0UgPSAxMDA7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9ucyA9IDA7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9uUmVzdWx0cyA9IFtdO1xuICAgICAgICB0aGlzLndhc1ByaW1hcnlEZWNvZGVyVXNlZEluTGFzdERlY29kZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgICAgICBpZiAodXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWRcbiAgICAgICAgICAgICYmIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMucHJpbWFyeURlY29kZXIgPSBuZXcgQmFyY29kZURldGVjdG9yRGVsZWdhdGUocmVxdWVzdGVkRm9ybWF0cywgdmVyYm9zZSwgbG9nZ2VyKTtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5RGVjb2RlciA9IG5ldyBaWGluZ0h0bWw1UXJjb2RlRGVjb2RlcihyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wcmltYXJ5RGVjb2RlciA9IG5ldyBaWGluZ0h0bWw1UXJjb2RlRGVjb2RlcihyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU2hpbS5wcm90b3R5cGUuZGVjb2RlQXN5bmMgPSBmdW5jdGlvbiAoY2FudmFzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzdGFydFRpbWU7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2EudHJ5cy5wdXNoKFsxLCAsIDMsIDRdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgdGhpcy5nZXREZWNvZGVyKCkuZGVjb2RlQXN5bmMoY2FudmFzKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjogcmV0dXJuIFsyLCBfYS5zZW50KCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBvc3NpYmx5TG9nUGVyZm9ybWFuY2Uoc3RhcnRUaW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbN107XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDogcmV0dXJuIFsyXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNoaW0ucHJvdG90eXBlLmRlY29kZVJvYnVzdGx5QXN5bmMgPSBmdW5jdGlvbiAoY2FudmFzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzdGFydFRpbWUsIGVycm9yXzE7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2EudHJ5cy5wdXNoKFsxLCAzLCA0LCA1XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQsIHRoaXMucHJpbWFyeURlY29kZXIuZGVjb2RlQXN5bmMoY2FudmFzKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjogcmV0dXJuIFsyLCBfYS5zZW50KCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl8xID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2Vjb25kYXJ5RGVjb2Rlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgdGhpcy5zZWNvbmRhcnlEZWNvZGVyLmRlY29kZUFzeW5jKGNhbnZhcyldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3JfMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wb3NzaWJseUxvZ1BlcmZvcm1hbmNlKHN0YXJ0VGltZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzddO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6IHJldHVybiBbMl07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTaGltLnByb3RvdHlwZS5nZXREZWNvZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuc2Vjb25kYXJ5RGVjb2Rlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeURlY29kZXI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMud2FzUHJpbWFyeURlY29kZXJVc2VkSW5MYXN0RGVjb2RlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgdGhpcy53YXNQcmltYXJ5RGVjb2RlclVzZWRJbkxhc3REZWNvZGUgPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeURlY29kZXI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53YXNQcmltYXJ5RGVjb2RlclVzZWRJbkxhc3REZWNvZGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Vjb25kYXJ5RGVjb2RlcjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2hpbS5wcm90b3R5cGUucG9zc2libHlMb2dQZXJmb3JtYW5jZSA9IGZ1bmN0aW9uIChzdGFydFRpbWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhlY3V0aW9uVGltZSA9IHBlcmZvcm1hbmNlLm5vdygpIC0gc3RhcnRUaW1lO1xuICAgICAgICB0aGlzLmV4ZWN1dGlvblJlc3VsdHMucHVzaChleGVjdXRpb25UaW1lKTtcbiAgICAgICAgdGhpcy5leGVjdXRpb25zKys7XG4gICAgICAgIHRoaXMucG9zc2libHlGbHVzaFBlcmZvcm1hbmNlUmVwb3J0KCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNoaW0ucHJvdG90eXBlLnBvc3NpYmx5Rmx1c2hQZXJmb3JtYW5jZVJlcG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZXhlY3V0aW9ucyA8IHRoaXMuRVhFQ1VUSU9OU19UT19SRVBPUlRfUEVSRk9STUFOQ0UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc3VtID0gMDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuZXhlY3V0aW9uUmVzdWx0czsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBleGVjdXRpb25UaW1lID0gX2FbX2ldO1xuICAgICAgICAgICAgc3VtICs9IGV4ZWN1dGlvblRpbWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1lYW4gPSBzdW0gLyB0aGlzLmV4ZWN1dGlvblJlc3VsdHMubGVuZ3RoO1xuICAgICAgICBjb25zb2xlLmxvZyhcIlwiLmNvbmNhdChtZWFuLCBcIiBtcyBmb3IgXCIpLmNvbmNhdCh0aGlzLmV4ZWN1dGlvblJlc3VsdHMubGVuZ3RoLCBcIiBsYXN0IHJ1bnMuXCIpKTtcbiAgICAgICAgdGhpcy5leGVjdXRpb25zID0gMDtcbiAgICAgICAgdGhpcy5leGVjdXRpb25SZXN1bHRzID0gW107XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTaGltO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2hpbSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29kZS1kZWNvZGVyLmpzLm1hcCIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG52YXIgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkobmFtZSwgdHJhY2spIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy50cmFjayA9IHRyYWNrO1xuICAgIH1cbiAgICBBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLmlzU3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMudHJhY2suZ2V0Q2FwYWJpbGl0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubmFtZSBpbiB0aGlzLnRyYWNrLmdldENhcGFiaWxpdGllcygpO1xuICAgIH07XG4gICAgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5hcHBseSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgY29uc3RyYWludCA9IHt9O1xuICAgICAgICBjb25zdHJhaW50W3RoaXMubmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnRzID0geyBhZHZhbmNlZDogW2NvbnN0cmFpbnRdIH07XG4gICAgICAgIHJldHVybiB0aGlzLnRyYWNrLmFwcGx5Q29uc3RyYWludHMoY29uc3RyYWludHMpO1xuICAgIH07XG4gICAgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS52YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNldHRpbmdzID0gdGhpcy50cmFjay5nZXRTZXR0aW5ncygpO1xuICAgICAgICBpZiAodGhpcy5uYW1lIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICB2YXIgc2V0dGluZ1ZhbHVlID0gc2V0dGluZ3NbdGhpcy5uYW1lXTtcbiAgICAgICAgICAgIHJldHVybiBzZXR0aW5nVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICByZXR1cm4gQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5O1xufSgpKTtcbnZhciBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5KG5hbWUsIHRyYWNrKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBuYW1lLCB0cmFjaykgfHwgdGhpcztcbiAgICB9XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLm1pbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2FwYWJpbGl0aWVzKCkubWluO1xuICAgIH07XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLm1heCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2FwYWJpbGl0aWVzKCkubWF4O1xuICAgIH07XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLnN0ZXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENhcGFiaWxpdGllcygpLnN0ZXA7XG4gICAgfTtcbiAgICBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUuYXBwbHkgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnQgPSB7fTtcbiAgICAgICAgY29uc3RyYWludFt0aGlzLm5hbWVdID0gdmFsdWU7XG4gICAgICAgIHZhciBjb25zdHJhaW50cyA9IHsgYWR2YW5jZWQ6IFtjb25zdHJhaW50XSB9O1xuICAgICAgICByZXR1cm4gdGhpcy50cmFjay5hcHBseUNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzKTtcbiAgICB9O1xuICAgIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5nZXRDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmFpbElmTm90U3VwcG9ydGVkKCk7XG4gICAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSB0aGlzLnRyYWNrLmdldENhcGFiaWxpdGllcygpO1xuICAgICAgICB2YXIgY2FwYWJpbGl0eSA9IGNhcGFiaWxpdGllc1t0aGlzLm5hbWVdO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbWluOiBjYXBhYmlsaXR5Lm1pbixcbiAgICAgICAgICAgIG1heDogY2FwYWJpbGl0eS5tYXgsXG4gICAgICAgICAgICBzdGVwOiBjYXBhYmlsaXR5LnN0ZXAsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUuZmFpbElmTm90U3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiXCIuY29uY2F0KHRoaXMubmFtZSwgXCIgY2FwYWJpbGl0eSBub3Qgc3VwcG9ydGVkXCIpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5O1xufShBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkpKTtcbnZhciBab29tRmVhdHVyZUltcGwgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhab29tRmVhdHVyZUltcGwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gWm9vbUZlYXR1cmVJbXBsKHRyYWNrKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBcInpvb21cIiwgdHJhY2spIHx8IHRoaXM7XG4gICAgfVxuICAgIHJldHVybiBab29tRmVhdHVyZUltcGw7XG59KEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5KSk7XG52YXIgVG9yY2hGZWF0dXJlSW1wbCA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFRvcmNoRmVhdHVyZUltcGwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVG9yY2hGZWF0dXJlSW1wbCh0cmFjaykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgXCJ0b3JjaFwiLCB0cmFjaykgfHwgdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIFRvcmNoRmVhdHVyZUltcGw7XG59KEFic3RyYWN0Q2FtZXJhQ2FwYWJpbGl0eSkpO1xudmFyIENhbWVyYUNhcGFiaWxpdGllc0ltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUNhcGFiaWxpdGllc0ltcGwodHJhY2spIHtcbiAgICAgICAgdGhpcy50cmFjayA9IHRyYWNrO1xuICAgIH1cbiAgICBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsLnByb3RvdHlwZS56b29tRmVhdHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab29tRmVhdHVyZUltcGwodGhpcy50cmFjayk7XG4gICAgfTtcbiAgICBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsLnByb3RvdHlwZS50b3JjaEZlYXR1cmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgVG9yY2hGZWF0dXJlSW1wbCh0aGlzLnRyYWNrKTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsO1xufSgpKTtcbnZhciBSZW5kZXJlZENhbWVyYUltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFJlbmRlcmVkQ2FtZXJhSW1wbChwYXJlbnRFbGVtZW50LCBtZWRpYVN0cmVhbSwgY2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuaXNDbG9zZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5wYXJlbnRFbGVtZW50ID0gcGFyZW50RWxlbWVudDtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IGNhbGxiYWNrcztcbiAgICAgICAgdGhpcy5zdXJmYWNlID0gdGhpcy5jcmVhdGVWaWRlb0VsZW1lbnQodGhpcy5wYXJlbnRFbGVtZW50LmNsaWVudFdpZHRoKTtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmQodGhpcy5zdXJmYWNlKTtcbiAgICB9XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5jcmVhdGVWaWRlb0VsZW1lbnQgPSBmdW5jdGlvbiAod2lkdGgpIHtcbiAgICAgICAgdmFyIHZpZGVvRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJ2aWRlb1wiKTtcbiAgICAgICAgdmlkZW9FbGVtZW50LnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQod2lkdGgsIFwicHhcIik7XG4gICAgICAgIHZpZGVvRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgICB2aWRlb0VsZW1lbnQubXV0ZWQgPSB0cnVlO1xuICAgICAgICB2aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKFwibXV0ZWRcIiwgXCJ0cnVlXCIpO1xuICAgICAgICB2aWRlb0VsZW1lbnQucGxheXNJbmxpbmUgPSB0cnVlO1xuICAgICAgICByZXR1cm4gdmlkZW9FbGVtZW50O1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5zZXR1cFN1cmZhY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3VyZmFjZS5vbmFib3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgXCJSZW5kZXJlZENhbWVyYUltcGwgdmlkZW8gc3VyZmFjZSBvbmFib3J0KCkgY2FsbGVkXCI7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc3VyZmFjZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgXCJSZW5kZXJlZENhbWVyYUltcGwgdmlkZW8gc3VyZmFjZSBvbmVycm9yKCkgY2FsbGVkXCI7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBvblZpZGVvU3RhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgdmlkZW9XaWR0aCA9IF90aGlzLnN1cmZhY2UuY2xpZW50V2lkdGg7XG4gICAgICAgICAgICB2YXIgdmlkZW9IZWlnaHQgPSBfdGhpcy5zdXJmYWNlLmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgIF90aGlzLmNhbGxiYWNrcy5vblJlbmRlclN1cmZhY2VSZWFkeSh2aWRlb1dpZHRoLCB2aWRlb0hlaWdodCk7XG4gICAgICAgICAgICBfdGhpcy5zdXJmYWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJwbGF5aW5nXCIsIG9uVmlkZW9TdGFydCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc3VyZmFjZS5hZGRFdmVudExpc3RlbmVyKFwicGxheWluZ1wiLCBvblZpZGVvU3RhcnQpO1xuICAgICAgICB0aGlzLnN1cmZhY2Uuc3JjT2JqZWN0ID0gdGhpcy5tZWRpYVN0cmVhbTtcbiAgICAgICAgdGhpcy5zdXJmYWNlLnBsYXkoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgbWVkaWFTdHJlYW0sIG9wdGlvbnMsIGNhbGxiYWNrcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgcmVuZGVyZWRDYW1lcmEsIGFzcGVjdFJhdGlvQ29uc3RyYWludDtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQ2FtZXJhID0gbmV3IFJlbmRlcmVkQ2FtZXJhSW1wbChwYXJlbnRFbGVtZW50LCBtZWRpYVN0cmVhbSwgY2FsbGJhY2tzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucy5hc3BlY3RSYXRpbykgcmV0dXJuIFszLCAyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzcGVjdFJhdGlvQ29uc3RyYWludCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3BlY3RSYXRpbzogb3B0aW9ucy5hc3BlY3RSYXRpb1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgcmVuZGVyZWRDYW1lcmEuZ2V0Rmlyc3RUcmFja09yRmFpbCgpLmFwcGx5Q29uc3RyYWludHMoYXNwZWN0UmF0aW9Db25zdHJhaW50KV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMjtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRDYW1lcmEuc2V0dXBTdXJmYWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIHJlbmRlcmVkQ2FtZXJhXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmZhaWxJZkNsb3NlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNDbG9zZWQpIHtcbiAgICAgICAgICAgIHRocm93IFwiVGhlIFJlbmRlcmVkQ2FtZXJhIGhhcyBhbHJlYWR5IGJlZW4gY2xvc2VkLlwiO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldEZpcnN0VHJhY2tPckZhaWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmFpbElmQ2xvc2VkKCk7XG4gICAgICAgIGlmICh0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk5vIHZpZGVvIHRyYWNrcyBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLnBhdXNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZhaWxJZkNsb3NlZCgpO1xuICAgICAgICB0aGlzLnN1cmZhY2UucGF1c2UoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUucmVzdW1lID0gZnVuY3Rpb24gKG9uUmVzdW1lQ2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5mYWlsSWZDbG9zZWQoKTtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG9uVmlkZW9SZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KG9uUmVzdW1lQ2FsbGJhY2ssIDIwMCk7XG4gICAgICAgICAgICAkdGhpcy5zdXJmYWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJwbGF5aW5nXCIsIG9uVmlkZW9SZXN1bWUpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnN1cmZhY2UuYWRkRXZlbnRMaXN0ZW5lcihcInBsYXlpbmdcIiwgb25WaWRlb1Jlc3VtZSk7XG4gICAgICAgIHRoaXMuc3VyZmFjZS5wbGF5KCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmlzUGF1c2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZhaWxJZkNsb3NlZCgpO1xuICAgICAgICByZXR1cm4gdGhpcy5zdXJmYWNlLnBhdXNlZDtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuZ2V0U3VyZmFjZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5mYWlsSWZDbG9zZWQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3VyZmFjZTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuZ2V0UnVubmluZ1RyYWNrQ2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdFRyYWNrT3JGYWlsKCkuZ2V0Q2FwYWJpbGl0aWVzKCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja1NldHRpbmdzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdFRyYWNrT3JGYWlsKCkuZ2V0U2V0dGluZ3MoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuYXBwbHlWaWRlb0NvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNvbnN0cmFpbnRzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBpZiAoXCJhc3BlY3RSYXRpb1wiIGluIGNvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiQ2hhbmdpbmcgJ2FzcGVjdFJhdGlvJyBpbiBydW4tdGltZSBpcyBub3QgeWV0IHN1cHBvcnRlZC5cIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIFsyLCB0aGlzLmdldEZpcnN0VHJhY2tPckZhaWwoKS5hcHBseUNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc0Nsb3NlZCkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgXykge1xuICAgICAgICAgICAgdmFyIHRyYWNrcyA9ICR0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gICAgICAgICAgICB2YXIgdHJhY2tzVG9DbG9zZSA9IHRyYWNrcy5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgdHJhY2tzQ2xvc2VkID0gMDtcbiAgICAgICAgICAgICR0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbiAodmlkZW9UcmFjaykge1xuICAgICAgICAgICAgICAgICR0aGlzLm1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKHZpZGVvVHJhY2spO1xuICAgICAgICAgICAgICAgIHZpZGVvVHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICsrdHJhY2tzQ2xvc2VkO1xuICAgICAgICAgICAgICAgIGlmICh0cmFja3NDbG9zZWQgPj0gdHJhY2tzVG9DbG9zZSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5pc0Nsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQoJHRoaXMuc3VyZmFjZSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldENhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsKHRoaXMuZ2V0Rmlyc3RUcmFja09yRmFpbCgpKTtcbiAgICB9O1xuICAgIHJldHVybiBSZW5kZXJlZENhbWVyYUltcGw7XG59KCkpO1xudmFyIENhbWVyYUltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUltcGwobWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cbiAgICBDYW1lcmFJbXBsLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgb3B0aW9ucywgY2FsbGJhY2tzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gWzIsIFJlbmRlcmVkQ2FtZXJhSW1wbC5jcmVhdGUocGFyZW50RWxlbWVudCwgdGhpcy5tZWRpYVN0cmVhbSwgb3B0aW9ucywgY2FsbGJhY2tzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYW1lcmFJbXBsLmNyZWF0ZSA9IGZ1bmN0aW9uICh2aWRlb0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjb25zdHJhaW50cywgbWVkaWFTdHJlYW07XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIm5hdmlnYXRvci5tZWRpYURldmljZXMgbm90IHN1cHBvcnRlZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiB2aWRlb0NvbnN0cmFpbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cyldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgbmV3IENhbWVyYUltcGwobWVkaWFTdHJlYW0pXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhSW1wbDtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFJbXBsIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jb3JlLWltcGwuanMubWFwIiwidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgQ2FtZXJhSW1wbCB9IGZyb20gXCIuL2NvcmUtaW1wbFwiO1xudmFyIENhbWVyYUZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUZhY3RvcnkoKSB7XG4gICAgfVxuICAgIENhbWVyYUZhY3RvcnkuZmFpbElmTm90U3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFuYXZpZ2F0b3IubWVkaWFEZXZpY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwibmF2aWdhdG9yLm1lZGlhRGV2aWNlcyBub3Qgc3VwcG9ydGVkXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBbMiwgbmV3IENhbWVyYUZhY3RvcnkoKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYW1lcmFGYWN0b3J5LnByb3RvdHlwZS5jcmVhdGUgPSBmdW5jdGlvbiAodmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFsyLCBDYW1lcmFJbXBsLmNyZWF0ZSh2aWRlb0NvbnN0cmFpbnRzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhRmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFGYWN0b3J5IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1mYWN0b3JpZXMuanMubWFwIiwidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTdHJpbmdzIH0gZnJvbSBcIi4uL3N0cmluZ3NcIjtcbnZhciBDYW1lcmFSZXRyaWV2ZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVJldHJpZXZlcigpIHtcbiAgICB9XG4gICAgQ2FtZXJhUmV0cmlldmVyLnJldHJpZXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlcykge1xuICAgICAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhRGV2aWNlcygpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtc3QgPSBNZWRpYVN0cmVhbVRyYWNrO1xuICAgICAgICBpZiAoTWVkaWFTdHJlYW1UcmFjayAmJiBtc3QuZ2V0U291cmNlcykge1xuICAgICAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhU3RyZWFtVHJhY2soKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQ2FtZXJhUmV0cmlldmVyLnJlamVjdFdpdGhFcnJvcigpO1xuICAgIH07XG4gICAgQ2FtZXJhUmV0cmlldmVyLnJlamVjdFdpdGhFcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVycm9yTWVzc2FnZSA9IEh0bWw1UXJjb2RlU3RyaW5ncy51bmFibGVUb1F1ZXJ5U3VwcG9ydGVkRGV2aWNlcygpO1xuICAgICAgICBpZiAoIUNhbWVyYVJldHJpZXZlci5pc0h0dHBzT3JMb2NhbGhvc3QoKSkge1xuICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gSHRtbDVRcmNvZGVTdHJpbmdzLmluc2VjdXJlQ29udGV4dENhbWVyYVF1ZXJ5RXJyb3IoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3JNZXNzYWdlKTtcbiAgICB9O1xuICAgIENhbWVyYVJldHJpZXZlci5pc0h0dHBzT3JMb2NhbGhvc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChsb2NhdGlvbi5wcm90b2NvbCA9PT0gXCJodHRwczpcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhvc3QgPSBsb2NhdGlvbi5ob3N0LnNwbGl0KFwiOlwiKVswXTtcbiAgICAgICAgcmV0dXJuIGhvc3QgPT09IFwiMTI3LjAuMC4xXCIgfHwgaG9zdCA9PT0gXCJsb2NhbGhvc3RcIjtcbiAgICB9O1xuICAgIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhRGV2aWNlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGNsb3NlQWN0aXZlU3RyZWFtcywgbWVkaWFTdHJlYW0sIGRldmljZXMsIHJlc3VsdHMsIF9pLCBkZXZpY2VzXzEsIGRldmljZTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlQWN0aXZlU3RyZWFtcyA9IGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHJhY2tzID0gc3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCB0cmFja3NfMSA9IHRyYWNrczsgX2kgPCB0cmFja3NfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyYWNrID0gdHJhY2tzXzFbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5lbmFibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnJlbW92ZVRyYWNrKHRyYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7IGF1ZGlvOiBmYWxzZSwgdmlkZW86IHRydWUgfSldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VzID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChfaSA9IDAsIGRldmljZXNfMSA9IGRldmljZXM7IF9pIDwgZGV2aWNlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZSA9IGRldmljZXNfMVtfaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSBcInZpZGVvaW5wdXRcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IGRldmljZS5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2UubGFiZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VBY3RpdmVTdHJlYW1zKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgcmVzdWx0c107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FtZXJhUmV0cmlldmVyLmdldENhbWVyYXNGcm9tTWVkaWFTdHJlYW1UcmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCBfKSB7XG4gICAgICAgICAgICB2YXIgY2FsbGJhY2sgPSBmdW5jdGlvbiAoc291cmNlSW5mb3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgc291cmNlSW5mb3NfMSA9IHNvdXJjZUluZm9zOyBfaSA8IHNvdXJjZUluZm9zXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzb3VyY2VJbmZvID0gc291cmNlSW5mb3NfMVtfaV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2VJbmZvLmtpbmQgPT09IFwidmlkZW9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZDogc291cmNlSW5mby5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogc291cmNlSW5mby5sYWJlbFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgbXN0ID0gTWVkaWFTdHJlYW1UcmFjaztcbiAgICAgICAgICAgIG1zdC5nZXRTb3VyY2VzKGNhbGxiYWNrKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhUmV0cmlldmVyO1xufSgpKTtcbmV4cG9ydCB7IENhbWVyYVJldHJpZXZlciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cmV0cmlldmVyLmpzLm1hcCIsImV4cG9ydCB2YXIgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGU7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlKSB7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbXCJVTktOT1dOXCJdID0gMF0gPSBcIlVOS05PV05cIjtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZVtIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZVtcIk5PVF9TVEFSVEVEXCJdID0gMV0gPSBcIk5PVF9TVEFSVEVEXCI7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbXCJTQ0FOTklOR1wiXSA9IDJdID0gXCJTQ0FOTklOR1wiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW1wiUEFVU0VEXCJdID0gM10gPSBcIlBBVVNFRFwiO1xufSkoSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUgfHwgKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlID0ge30pKTtcbnZhciBTdGF0ZU1hbmFnZXJJbXBsID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTdGF0ZU1hbmFnZXJJbXBsKCkge1xuICAgICAgICB0aGlzLnN0YXRlID0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuTk9UX1NUQVJURUQ7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOO1xuICAgIH1cbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5kaXJlY3RUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHRoaXMuZmFpbElmVHJhbnNpdGlvbk9uZ29pbmcoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVRyYW5zaXRpb24obmV3U3RhdGUpO1xuICAgICAgICB0aGlzLnN0YXRlID0gbmV3U3RhdGU7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5zdGFydFRyYW5zaXRpb24gPSBmdW5jdGlvbiAobmV3U3RhdGUpIHtcbiAgICAgICAgdGhpcy5mYWlsSWZUcmFuc2l0aW9uT25nb2luZygpO1xuICAgICAgICB0aGlzLnZhbGlkYXRlVHJhbnNpdGlvbihuZXdTdGF0ZSk7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBuZXdTdGF0ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5vbkdvaW5nVHJhbnNhY3Rpb25OZXdTdGF0ZVxuICAgICAgICAgICAgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlVOS05PV04pIHtcbiAgICAgICAgICAgIHRocm93IFwiVHJhbnNhY3Rpb24gaXMgYWxyZWFkeSBjYW5jZWxsZWQsIGNhbm5vdCBleGVjdXRlKCkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRlbXBOZXdTdGF0ZSA9IHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGU7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOO1xuICAgICAgICB0aGlzLmRpcmVjdFRyYW5zaXRpb24odGVtcE5ld1N0YXRlKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlckltcGwucHJvdG90eXBlLmNhbmNlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGVcbiAgICAgICAgICAgID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlRyYW5zYWN0aW9uIGlzIGFscmVhZHkgY2FuY2VsbGVkLCBjYW5ub3QgY2FuY2VsKCkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vbkdvaW5nVHJhbnNhY3Rpb25OZXdTdGF0ZSA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlVOS05PV047XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGU7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5mYWlsSWZUcmFuc2l0aW9uT25nb2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGVcbiAgICAgICAgICAgICE9PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCB0cmFuc2l0aW9uIHRvIGEgbmV3IHN0YXRlLCBhbHJlYWR5IHVuZGVyIHRyYW5zaXRpb25cIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VySW1wbC5wcm90b3R5cGUudmFsaWRhdGVUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHN3aXRjaCAodGhpcy5zdGF0ZSkge1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOOlxuICAgICAgICAgICAgICAgIHRocm93IFwiVHJhbnNpdGlvbiBmcm9tIHVua25vd24gaXMgbm90IGFsbG93ZWRcIjtcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuTk9UX1NUQVJURUQ6XG4gICAgICAgICAgICAgICAgdGhpcy5mYWlsSWZOZXdTdGF0ZUlzKG5ld1N0YXRlLCBbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HOlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5QQVVTRUQ6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlckltcGwucHJvdG90eXBlLmZhaWxJZk5ld1N0YXRlSXMgPSBmdW5jdGlvbiAobmV3U3RhdGUsIGRpc2FsbG93ZWRTdGF0ZXNUb1RyYW5zaXRpb24pIHtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uXzEgPSBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uOyBfaSA8IGRpc2FsbG93ZWRTdGF0ZXNUb1RyYW5zaXRpb25fMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBkaXNhbGxvd2VkU3RhdGUgPSBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uXzFbX2ldO1xuICAgICAgICAgICAgaWYgKG5ld1N0YXRlID09PSBkaXNhbGxvd2VkU3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCB0cmFuc2l0aW9uIGZyb20gXCIuY29uY2F0KHRoaXMuc3RhdGUsIFwiIHRvIFwiKS5jb25jYXQobmV3U3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gU3RhdGVNYW5hZ2VySW1wbDtcbn0oKSk7XG52YXIgU3RhdGVNYW5hZ2VyUHJveHkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFN0YXRlTWFuYWdlclByb3h5KHN0YXRlTWFuYWdlcikge1xuICAgICAgICB0aGlzLnN0YXRlTWFuYWdlciA9IHN0YXRlTWFuYWdlcjtcbiAgICB9XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLnN0YXJ0VHJhbnNpdGlvbiA9IGZ1bmN0aW9uIChuZXdTdGF0ZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZU1hbmFnZXIuc3RhcnRUcmFuc2l0aW9uKG5ld1N0YXRlKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5kaXJlY3RUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHRoaXMuc3RhdGVNYW5hZ2VyLmRpcmVjdFRyYW5zaXRpb24obmV3U3RhdGUpO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZU1hbmFnZXIuZ2V0U3RhdGUoKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5jYW5TY2FuRmlsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLmdldFN0YXRlKCkgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLk5PVF9TVEFSVEVEO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLmlzU2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5nZXRTdGF0ZSgpICE9PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5OT1RfU1RBUlRFRDtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5pc1N0cmljdGx5U2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5nZXRTdGF0ZSgpID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5TQ0FOTklORztcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5pc1BhdXNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLmdldFN0YXRlKCkgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlBBVVNFRDtcbiAgICB9O1xuICAgIHJldHVybiBTdGF0ZU1hbmFnZXJQcm94eTtcbn0oKSk7XG5leHBvcnQgeyBTdGF0ZU1hbmFnZXJQcm94eSB9O1xudmFyIFN0YXRlTWFuYWdlckZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFN0YXRlTWFuYWdlckZhY3RvcnkoKSB7XG4gICAgfVxuICAgIFN0YXRlTWFuYWdlckZhY3RvcnkuY3JlYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gbmV3IFN0YXRlTWFuYWdlclByb3h5KG5ldyBTdGF0ZU1hbmFnZXJJbXBsKCkpO1xuICAgIH07XG4gICAgcmV0dXJuIFN0YXRlTWFuYWdlckZhY3Rvcnk7XG59KCkpO1xuZXhwb3J0IHsgU3RhdGVNYW5hZ2VyRmFjdG9yeSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3RhdGUtbWFuYWdlci5qcy5tYXAiLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQmFzZUxvZ2dnZXIsIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeSwgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnksIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cywgaXNWYWxpZEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cywgSHRtbDVRcmNvZGVDb25zdGFudHMsIGlzTnVsbE9yVW5kZWZpbmVkIH0gZnJvbSBcIi4vY29yZVwiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTdHJpbmdzIH0gZnJvbSBcIi4vc3RyaW5nc1wiO1xuaW1wb3J0IHsgVmlkZW9Db25zdHJhaW50c1V0aWwgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTaGltIH0gZnJvbSBcIi4vY29kZS1kZWNvZGVyXCI7XG5pbXBvcnQgeyBDYW1lcmFGYWN0b3J5IH0gZnJvbSBcIi4vY2FtZXJhL2ZhY3Rvcmllc1wiO1xuaW1wb3J0IHsgQ2FtZXJhUmV0cmlldmVyIH0gZnJvbSBcIi4vY2FtZXJhL3JldHJpZXZlclwiO1xuaW1wb3J0IHsgU3RhdGVNYW5hZ2VyRmFjdG9yeSwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUgfSBmcm9tIFwiLi9zdGF0ZS1tYW5hZ2VyXCI7XG52YXIgQ29uc3RhbnRzID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQ29uc3RhbnRzLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENvbnN0YW50cygpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBDb25zdGFudHMuREVGQVVMVF9XSURUSCA9IDMwMDtcbiAgICBDb25zdGFudHMuREVGQVVMVF9XSURUSF9PRkZTRVQgPSAyO1xuICAgIENvbnN0YW50cy5GSUxFX1NDQU5fTUlOX0hFSUdIVCA9IDMwMDtcbiAgICBDb25zdGFudHMuRklMRV9TQ0FOX0hJRERFTl9DQU5WQVNfUEFERElORyA9IDEwMDtcbiAgICBDb25zdGFudHMuTUlOX1FSX0JPWF9TSVpFID0gNTA7XG4gICAgQ29uc3RhbnRzLlNIQURFRF9MRUZUID0gMTtcbiAgICBDb25zdGFudHMuU0hBREVEX1JJR0hUID0gMjtcbiAgICBDb25zdGFudHMuU0hBREVEX1RPUCA9IDM7XG4gICAgQ29uc3RhbnRzLlNIQURFRF9CT1RUT00gPSA0O1xuICAgIENvbnN0YW50cy5TSEFERURfUkVHSU9OX0VMRU1FTlRfSUQgPSBcInFyLXNoYWRlZC1yZWdpb25cIjtcbiAgICBDb25zdGFudHMuVkVSQk9TRSA9IGZhbHNlO1xuICAgIENvbnN0YW50cy5CT1JERVJfU0hBREVSX0RFRkFVTFRfQ09MT1IgPSBcIiNmZmZmZmZcIjtcbiAgICBDb25zdGFudHMuQk9SREVSX1NIQURFUl9NQVRDSF9DT0xPUiA9IFwicmdiKDkwLCAxOTMsIDU2KVwiO1xuICAgIHJldHVybiBDb25zdGFudHM7XG59KEh0bWw1UXJjb2RlQ29uc3RhbnRzKSk7XG52YXIgSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyhjb25maWcsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdGhpcy5mcHMgPSBDb25zdGFudHMuU0NBTl9ERUZBVUxUX0ZQUztcbiAgICAgICAgaWYgKCFjb25maWcpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZUZsaXAgPSBDb25zdGFudHMuREVGQVVMVF9ESVNBQkxFX0ZMSVA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmZwcykge1xuICAgICAgICAgICAgICAgIHRoaXMuZnBzID0gY29uZmlnLmZwcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZUZsaXAgPSBjb25maWcuZGlzYWJsZUZsaXAgPT09IHRydWU7XG4gICAgICAgICAgICB0aGlzLnFyYm94ID0gY29uZmlnLnFyYm94O1xuICAgICAgICAgICAgdGhpcy5hc3BlY3RSYXRpbyA9IGNvbmZpZy5hc3BlY3RSYXRpbztcbiAgICAgICAgICAgIHRoaXMudmlkZW9Db25zdHJhaW50cyA9IGNvbmZpZy52aWRlb0NvbnN0cmFpbnRzO1xuICAgICAgICB9XG4gICAgfVxuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcucHJvdG90eXBlLmlzTWVkaWFTdHJlYW1Db25zdHJhaW50c1ZhbGlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMudmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJFbXB0eSB2aWRlb0NvbnN0cmFpbnRzXCIsIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBWaWRlb0NvbnN0cmFpbnRzVXRpbC5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCh0aGlzLnZpZGVvQ29uc3RyYWludHMsIHRoaXMubG9nZ2VyKTtcbiAgICB9O1xuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcucHJvdG90eXBlLmlzU2hhZGVkQm94RW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICFpc051bGxPclVuZGVmaW5lZCh0aGlzLnFyYm94KTtcbiAgICB9O1xuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcuY3JlYXRlID0gZnVuY3Rpb24gKGNvbmZpZywgbG9nZ2VyKSB7XG4gICAgICAgIHJldHVybiBuZXcgSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyhjb25maWcsIGxvZ2dlcik7XG4gICAgfTtcbiAgICByZXR1cm4gSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZztcbn0oKSk7XG52YXIgSHRtbDVRcmNvZGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlKGVsZW1lbnRJZCwgY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuY2FudmFzRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuaGFzQm9yZGVyU2hhZGVycyA9IG51bGw7XG4gICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycyA9IG51bGw7XG4gICAgICAgIHRoaXMucXJNYXRjaCA9IG51bGw7XG4gICAgICAgIHRoaXMucmVuZGVyZWRDYW1lcmEgPSBudWxsO1xuICAgICAgICB0aGlzLnFyUmVnaW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5sYXN0U2NhbkltYWdlRmlsZSA9IG51bGw7XG4gICAgICAgIHRoaXMuaXNTY2FubmluZyA9IGZhbHNlO1xuICAgICAgICBpZiAoIWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1lbnRJZCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiSFRNTCBFbGVtZW50IHdpdGggaWQ9XCIuY29uY2F0KGVsZW1lbnRJZCwgXCIgbm90IGZvdW5kXCIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWxlbWVudElkID0gZWxlbWVudElkO1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSBmYWxzZTtcbiAgICAgICAgdmFyIGV4cGVyaW1lbnRhbEZlYXR1cmVDb25maWc7XG4gICAgICAgIHZhciBjb25maWdPYmplY3Q7XG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnT3JWZXJib3NpdHlGbGFnID09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgPSBjb25maWdPclZlcmJvc2l0eUZsYWcgPT09IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgICAgICBjb25maWdPYmplY3QgPSBjb25maWdPclZlcmJvc2l0eUZsYWc7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgPSBjb25maWdPYmplY3QudmVyYm9zZSA9PT0gdHJ1ZTtcbiAgICAgICAgICAgIGV4cGVyaW1lbnRhbEZlYXR1cmVDb25maWcgPSBjb25maWdPYmplY3QuZXhwZXJpbWVudGFsRmVhdHVyZXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dnZXIgPSBuZXcgQmFzZUxvZ2dnZXIodGhpcy52ZXJib3NlKTtcbiAgICAgICAgdGhpcy5xcmNvZGUgPSBuZXcgSHRtbDVRcmNvZGVTaGltKHRoaXMuZ2V0U3VwcG9ydGVkRm9ybWF0cyhjb25maWdPclZlcmJvc2l0eUZsYWcpLCB0aGlzLmdldFVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkKGNvbmZpZ09iamVjdCksIHRoaXMudmVyYm9zZSwgdGhpcy5sb2dnZXIpO1xuICAgICAgICB0aGlzLmZvcmV2ZXJTY2FuVGltZW91dDtcbiAgICAgICAgdGhpcy5zaG91bGRTY2FuID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdGF0ZU1hbmFnZXJQcm94eSA9IFN0YXRlTWFuYWdlckZhY3RvcnkuY3JlYXRlKCk7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zdGFydCA9IGZ1bmN0aW9uIChjYW1lcmFJZE9yQ29uZmlnLCBjb25maWd1cmF0aW9uLCBxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFjYW1lcmFJZE9yQ29uZmlnKSB7XG4gICAgICAgICAgICB0aHJvdyBcImNhbWVyYUlkT3JDb25maWcgaXMgcmVxdWlyZWRcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXFyQ29kZVN1Y2Nlc3NDYWxsYmFja1xuICAgICAgICAgICAgfHwgdHlwZW9mIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjayAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHRocm93IFwicXJDb2RlU3VjY2Vzc0NhbGxiYWNrIGlzIHJlcXVpcmVkIGFuZCBzaG91bGQgYmUgYSBmdW5jdGlvbi5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsO1xuICAgICAgICBpZiAocXJDb2RlRXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsID0gcXJDb2RlRXJyb3JDYWxsYmFjaztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHFyQ29kZUVycm9yQ2FsbGJhY2tJbnRlcm5hbFxuICAgICAgICAgICAgICAgID0gdGhpcy52ZXJib3NlID8gdGhpcy5sb2dnZXIubG9nIDogZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbnRlcm5hbENvbmZpZyA9IEludGVybmFsSHRtbDVRcmNvZGVDb25maWcuY3JlYXRlKGNvbmZpZ3VyYXRpb24sIHRoaXMubG9nZ2VyKTtcbiAgICAgICAgdGhpcy5jbGVhckVsZW1lbnQoKTtcbiAgICAgICAgdmFyIHZpZGVvQ29uc3RyYWludHNBdmFpbGFibGVBbmRWYWxpZCA9IGZhbHNlO1xuICAgICAgICBpZiAoaW50ZXJuYWxDb25maWcudmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICAgICAgaWYgKCFpbnRlcm5hbENvbmZpZy5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nRXJyb3IoXCIndmlkZW9Db25zdHJhaW50cycgaXMgbm90IHZhbGlkICdNZWRpYVN0cmVhbUNvbnN0cmFpbnRzLCBcIlxuICAgICAgICAgICAgICAgICAgICArIFwiaXQgd2lsbCBiZSBpZ25vcmVkLidcIiwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2aWRlb0NvbnN0cmFpbnRzQXZhaWxhYmxlQW5kVmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBhcmVWaWRlb0NvbnN0cmFpbnRzRW5hYmxlZCA9IHZpZGVvQ29uc3RyYWludHNBdmFpbGFibGVBbmRWYWxpZDtcbiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmVsZW1lbnRJZCk7XG4gICAgICAgIHZhciByb290RWxlbWVudFdpZHRoID0gZWxlbWVudC5jbGllbnRXaWR0aFxuICAgICAgICAgICAgPyBlbGVtZW50LmNsaWVudFdpZHRoIDogQ29uc3RhbnRzLkRFRkFVTFRfV0lEVEg7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG4gICAgICAgIHRoaXMuc2hvdWxkU2NhbiA9IHRydWU7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbiA9IHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuc3RhcnRUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHZhciB2aWRlb0NvbnN0cmFpbnRzID0gYXJlVmlkZW9Db25zdHJhaW50c0VuYWJsZWRcbiAgICAgICAgICAgICAgICA/IGludGVybmFsQ29uZmlnLnZpZGVvQ29uc3RyYWludHNcbiAgICAgICAgICAgICAgICA6ICR0aGlzLmNyZWF0ZVZpZGVvQ29uc3RyYWludHMoY2FtZXJhSWRPckNvbmZpZyk7XG4gICAgICAgICAgICBpZiAoIXZpZGVvQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICByZWplY3QoXCJ2aWRlb0NvbnN0cmFpbnRzIHNob3VsZCBiZSBkZWZpbmVkXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjYW1lcmFSZW5kZXJpbmdPcHRpb25zID0ge307XG4gICAgICAgICAgICBpZiAoIWFyZVZpZGVvQ29uc3RyYWludHNFbmFibGVkIHx8IGludGVybmFsQ29uZmlnLmFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhUmVuZGVyaW5nT3B0aW9ucy5hc3BlY3RSYXRpbyA9IGludGVybmFsQ29uZmlnLmFzcGVjdFJhdGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlbmRlcmluZ0NhbGxiYWNrcyA9IHtcbiAgICAgICAgICAgICAgICBvblJlbmRlclN1cmZhY2VSZWFkeTogZnVuY3Rpb24gKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5zZXR1cFVpKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgaW50ZXJuYWxDb25maWcpO1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5pc1NjYW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuZm9yZXZlclNjYW4oaW50ZXJuYWxDb25maWcsIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgQ2FtZXJhRmFjdG9yeS5mYWlsSWZOb3RTdXBwb3J0ZWQoKS50aGVuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgICAgICAgICAgICAgZmFjdG9yeS5jcmVhdGUodmlkZW9Db25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoY2FtZXJhKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjYW1lcmEucmVuZGVyKF90aGlzLmVsZW1lbnQsIGNhbWVyYVJlbmRlcmluZ09wdGlvbnMsIHJlbmRlcmluZ0NhbGxiYWNrcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChyZW5kZXJlZENhbWVyYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMucmVuZGVyZWRDYW1lcmEgPSByZW5kZXJlZENhbWVyYTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvU2Nhbm5pbmdTdGF0ZUNoYW5nZVRyYW5zYWN0aW9uLmV4ZWN1dGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEh0bWw1UXJjb2RlU3RyaW5ncy5lcnJvckdldHRpbmdVc2VyTWVkaWEoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgdG9TY2FubmluZ1N0YXRlQ2hhbmdlVHJhbnNhY3Rpb24uY2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEh0bWw1UXJjb2RlU3RyaW5ncy5jYW1lcmFTdHJlYW1pbmdOb3RTdXBwb3J0ZWQoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUucGF1c2UgPSBmdW5jdGlvbiAoc2hvdWxkUGF1c2VWaWRlbykge1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuaXNTdHJpY3RseVNjYW5uaW5nKCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiQ2Fubm90IHBhdXNlLCBzY2FubmVyIGlzIG5vdCBzY2FubmluZy5cIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlTWFuYWdlclByb3h5LmRpcmVjdFRyYW5zaXRpb24oSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEKTtcbiAgICAgICAgdGhpcy5zaG93UGF1c2VkU3RhdGUoKTtcbiAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKHNob3VsZFBhdXNlVmlkZW8pIHx8IHNob3VsZFBhdXNlVmlkZW8gIT09IHRydWUpIHtcbiAgICAgICAgICAgIHNob3VsZFBhdXNlVmlkZW8gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2hvdWxkUGF1c2VWaWRlbyAmJiB0aGlzLnJlbmRlcmVkQ2FtZXJhKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVkQ2FtZXJhLnBhdXNlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5yZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5pc1BhdXNlZCgpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCByZXN1bHQsIHNjYW5uZXIgaXMgbm90IHBhdXNlZC5cIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEpIHtcbiAgICAgICAgICAgIHRocm93IFwicmVuZGVyZWRDYW1lcmEgZG9lc24ndCBleGlzdCB3aGlsZSB0cnlpbmcgcmVzdW1lKClcIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdHJhbnNpdGlvblRvU2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkdGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5kaXJlY3RUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HKTtcbiAgICAgICAgICAgICR0aGlzLmhpZGVQYXVzZWRTdGF0ZSgpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEuaXNQYXVzZWQoKSkge1xuICAgICAgICAgICAgdHJhbnNpdGlvblRvU2Nhbm5pbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbmRlcmVkQ2FtZXJhLnJlc3VtZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0cmFuc2l0aW9uVG9TY2FubmluZygpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuZ2V0U3RhdGUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zdG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuaXNTY2FubmluZygpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCBzdG9wLCBzY2FubmVyIGlzIG5vdCBydW5uaW5nIG9yIHBhdXNlZC5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdG9TdG9wcGVkU3RhdGVUcmFuc2FjdGlvbiA9IHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuc3RhcnRUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLk5PVF9TVEFSVEVEKTtcbiAgICAgICAgdGhpcy5zaG91bGRTY2FuID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLmZvcmV2ZXJTY2FuVGltZW91dCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuZm9yZXZlclNjYW5UaW1lb3V0KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVtb3ZlUXJSZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY2hpbGRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoQ29uc3RhbnRzLlNIQURFRF9SRUdJT05fRUxFTUVOVF9JRCk7XG4gICAgICAgICAgICBpZiAoY2hpbGRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZWxlbWVudC5yZW1vdmVDaGlsZChjaGlsZEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJlZENhbWVyYS5jbG9zZSgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJHRoaXMucmVuZGVyZWRDYW1lcmEgPSBudWxsO1xuICAgICAgICAgICAgaWYgKCR0aGlzLmVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5lbGVtZW50LnJlbW92ZUNoaWxkKCR0aGlzLmNhbnZhc0VsZW1lbnQpO1xuICAgICAgICAgICAgICAgICR0aGlzLmNhbnZhc0VsZW1lbnQgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVtb3ZlUXJSZWdpb24oKTtcbiAgICAgICAgICAgIGlmICgkdGhpcy5xclJlZ2lvbikge1xuICAgICAgICAgICAgICAgICR0aGlzLnFyUmVnaW9uID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkdGhpcy5jb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuY29udGV4dCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0b1N0b3BwZWRTdGF0ZVRyYW5zYWN0aW9uLmV4ZWN1dGUoKTtcbiAgICAgICAgICAgICR0aGlzLmhpZGVQYXVzZWRTdGF0ZSgpO1xuICAgICAgICAgICAgJHRoaXMuaXNTY2FubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zY2FuRmlsZSA9IGZ1bmN0aW9uIChpbWFnZUZpbGUsIHNob3dJbWFnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY2FuRmlsZVYyKGltYWdlRmlsZSwgc2hvd0ltYWdlKVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGh0bWw1cXJjb2RlUmVzdWx0KSB7IHJldHVybiBodG1sNXFyY29kZVJlc3VsdC5kZWNvZGVkVGV4dDsgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2NhbkZpbGVWMiA9IGZ1bmN0aW9uIChpbWFnZUZpbGUsIHNob3dJbWFnZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIWltYWdlRmlsZSB8fCAhKGltYWdlRmlsZSBpbnN0YW5jZW9mIEZpbGUpKSB7XG4gICAgICAgICAgICB0aHJvdyBcImltYWdlRmlsZSBhcmd1bWVudCBpcyBtYW5kYXRvcnkgYW5kIHNob3VsZCBiZSBpbnN0YW5jZSBcIlxuICAgICAgICAgICAgICAgICsgXCJvZiBGaWxlLiBVc2UgJ2V2ZW50LnRhcmdldC5maWxlc1swXScuXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKHNob3dJbWFnZSkpIHtcbiAgICAgICAgICAgIHNob3dJbWFnZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlTWFuYWdlclByb3h5LmNhblNjYW5GaWxlKCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiQ2Fubm90IHN0YXJ0IGZpbGUgc2NhbiAtIG9uZ29pbmcgY2FtZXJhIHNjYW5cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlDbG9zZUxhc3RTY2FuSW1hZ2VGaWxlKCk7XG4gICAgICAgICAgICBfdGhpcy5jbGVhckVsZW1lbnQoKTtcbiAgICAgICAgICAgIF90aGlzLmxhc3RTY2FuSW1hZ2VGaWxlID0gVVJMLmNyZWF0ZU9iamVjdFVSTChpbWFnZUZpbGUpO1xuICAgICAgICAgICAgdmFyIGlucHV0SW1hZ2UgPSBuZXcgSW1hZ2U7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW1hZ2VXaWR0aCA9IGlucHV0SW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgdmFyIGltYWdlSGVpZ2h0ID0gaW5wdXRJbWFnZS5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChfdGhpcy5lbGVtZW50SWQpO1xuICAgICAgICAgICAgICAgIHZhciBjb250YWluZXJXaWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGhcbiAgICAgICAgICAgICAgICAgICAgPyBlbGVtZW50LmNsaWVudFdpZHRoIDogQ29uc3RhbnRzLkRFRkFVTFRfV0lEVEg7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRhaW5lckhlaWdodCA9IE1hdGgubWF4KGVsZW1lbnQuY2xpZW50SGVpZ2h0ID8gZWxlbWVudC5jbGllbnRIZWlnaHQgOiBpbWFnZUhlaWdodCwgQ29uc3RhbnRzLkZJTEVfU0NBTl9NSU5fSEVJR0hUKTtcbiAgICAgICAgICAgICAgICB2YXIgY29uZmlnID0gX3RoaXMuY29tcHV0ZUNhbnZhc0RyYXdDb25maWcoaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQsIGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQpO1xuICAgICAgICAgICAgICAgIGlmIChzaG93SW1hZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpc2libGVDYW52YXMgPSBfdGhpcy5jcmVhdGVDYW52YXNFbGVtZW50KGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQsIFwicXItY2FudmFzLXZpc2libGVcIik7XG4gICAgICAgICAgICAgICAgICAgIHZpc2libGVDYW52YXMuc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQodmlzaWJsZUNhbnZhcyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb250ZXh0XzEgPSB2aXNpYmxlQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb250ZXh0XzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiVW5hYmxlIHRvIGdldCAyZCBjb250ZXh0IGZyb20gY2FudmFzXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29udGV4dF8xLmNhbnZhcy53aWR0aCA9IGNvbnRhaW5lcldpZHRoO1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0XzEuY2FudmFzLmhlaWdodCA9IGNvbnRhaW5lckhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dF8xLmRyYXdJbWFnZShpbnB1dEltYWdlLCAwLCAwLCBpbWFnZVdpZHRoLCBpbWFnZUhlaWdodCwgY29uZmlnLngsIGNvbmZpZy55LCBjb25maWcud2lkdGgsIGNvbmZpZy5oZWlnaHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcGFkZGluZyA9IENvbnN0YW50cy5GSUxFX1NDQU5fSElEREVOX0NBTlZBU19QQURESU5HO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5JbWFnZVdpZHRoID0gTWF0aC5tYXgoaW5wdXRJbWFnZS53aWR0aCwgY29uZmlnLndpZHRoKTtcbiAgICAgICAgICAgICAgICB2YXIgaGlkZGVuSW1hZ2VIZWlnaHQgPSBNYXRoLm1heChpbnB1dEltYWdlLmhlaWdodCwgY29uZmlnLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgdmFyIGhpZGRlbkNhbnZhc1dpZHRoID0gaGlkZGVuSW1hZ2VXaWR0aCArIDIgKiBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5DYW52YXNIZWlnaHQgPSBoaWRkZW5JbWFnZUhlaWdodCArIDIgKiBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5DYW52YXMgPSBfdGhpcy5jcmVhdGVDYW52YXNFbGVtZW50KGhpZGRlbkNhbnZhc1dpZHRoLCBoaWRkZW5DYW52YXNIZWlnaHQpO1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoaGlkZGVuQ2FudmFzKTtcbiAgICAgICAgICAgICAgICB2YXIgY29udGV4dCA9IGhpZGRlbkNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG4gICAgICAgICAgICAgICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiVW5hYmxlIHRvIGdldCAyZCBjb250ZXh0IGZyb20gY2FudmFzXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnRleHQuY2FudmFzLndpZHRoID0gaGlkZGVuQ2FudmFzV2lkdGg7XG4gICAgICAgICAgICAgICAgY29udGV4dC5jYW52YXMuaGVpZ2h0ID0gaGlkZGVuQ2FudmFzSGVpZ2h0O1xuICAgICAgICAgICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKGlucHV0SW1hZ2UsIDAsIDAsIGltYWdlV2lkdGgsIGltYWdlSGVpZ2h0LCBwYWRkaW5nLCBwYWRkaW5nLCBoaWRkZW5JbWFnZVdpZHRoLCBoaWRkZW5JbWFnZUhlaWdodCk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucXJjb2RlLmRlY29kZVJvYnVzdGx5QXN5bmMoaGlkZGVuQ2FudmFzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkuY3JlYXRlRnJvbVFyY29kZVJlc3VsdChyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChyZWplY3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChcIlFSIGNvZGUgcGFyc2UgZXJyb3IsIGVycm9yID0gXCIuY29uY2F0KGV4Y2VwdGlvbikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uZXJyb3IgPSByZWplY3Q7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uYWJvcnQgPSByZWplY3Q7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uc3RhbGxlZCA9IHJlamVjdDtcbiAgICAgICAgICAgIGlucHV0SW1hZ2Uub25zdXNwZW5kID0gcmVqZWN0O1xuICAgICAgICAgICAgaW5wdXRJbWFnZS5zcmMgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGltYWdlRmlsZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNsZWFyRWxlbWVudCgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUuZ2V0Q2FtZXJhcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5yZXRyaWV2ZSgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja0NhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRSdW5uaW5nVHJhY2tDYXBhYmlsaXRpZXMoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncygpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja0NhbWVyYUNhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRDYXBhYmlsaXRpZXMoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5hcHBseVZpZGVvQ29uc3RyYWludHMgPSBmdW5jdGlvbiAodmlkZW9Db25zdGFpbnRzKSB7XG4gICAgICAgIGlmICghdmlkZW9Db25zdGFpbnRzKSB7XG4gICAgICAgICAgICB0aHJvdyBcInZpZGVvQ29uc3RhaW50cyBpcyByZXF1aXJlZCBhcmd1bWVudC5cIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghVmlkZW9Db25zdHJhaW50c1V0aWwuaXNNZWRpYVN0cmVhbUNvbnN0cmFpbnRzVmFsaWQodmlkZW9Db25zdGFpbnRzLCB0aGlzLmxvZ2dlcikpIHtcbiAgICAgICAgICAgIHRocm93IFwiaW52YWxpZCB2aWRlb0NvbnN0YWludHMgcGFzc2VkLCBjaGVjayBsb2dzIGZvciBtb3JlIGRldGFpbHNcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRSZW5kZXJlZENhbWVyYU9yRmFpbCgpLmFwcGx5VmlkZW9Db25zdHJhaW50cyh2aWRlb0NvbnN0YWludHMpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJlbmRlcmVkQ2FtZXJhT3JGYWlsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5yZW5kZXJlZENhbWVyYSA9PSBudWxsKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlNjYW5uaW5nIGlzIG5vdCBpbiBydW5uaW5nIHN0YXRlLCBjYWxsIHRoaXMgQVBJIG9ubHkgd2hlblwiXG4gICAgICAgICAgICAgICAgKyBcIiBRUiBjb2RlIHNjYW5uaW5nIHVzaW5nIGNhbWVyYSBpcyBpbiBydW5uaW5nIHN0YXRlLlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJlbmRlcmVkQ2FtZXJhO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFN1cHBvcnRlZEZvcm1hdHMgPSBmdW5jdGlvbiAoY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgIHZhciBhbGxGb3JtYXRzID0gW1xuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlFSX0NPREUsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQVpURUMsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09EQUJBUixcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09ERV8xMjgsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuREFUQV9NQVRSSVgsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuTUFYSUNPREUsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuSVRGLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkVBTl8xMyxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fOCxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5QREZfNDE3LFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlJTU18xNCxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfRVhQQU5ERUQsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0EsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0UsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0VBTl9FWFRFTlNJT04sXG4gICAgICAgIF07XG4gICAgICAgIGlmICghY29uZmlnT3JWZXJib3NpdHlGbGFnXG4gICAgICAgICAgICB8fCB0eXBlb2YgY29uZmlnT3JWZXJib3NpdHlGbGFnID09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gYWxsRm9ybWF0cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0KSB7XG4gICAgICAgICAgICByZXR1cm4gYWxsRm9ybWF0cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoY29uZmlnT3JWZXJib3NpdHlGbGFnLmZvcm1hdHNUb1N1cHBvcnQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcImNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0IHNob3VsZCBiZSB1bmRlZmluZWQgXCJcbiAgICAgICAgICAgICAgICArIFwib3IgYW4gYXJyYXkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgXCJBdGxlYXN0IDEgZm9ybWF0c1RvU3VwcG9ydCBpcyBuZWVkZWQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHN1cHBvcnRlZEZvcm1hdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0OyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGZvcm1hdCA9IF9hW19pXTtcbiAgICAgICAgICAgIGlmIChpc1ZhbGlkSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICBzdXBwb3J0ZWRGb3JtYXRzLnB1c2goZm9ybWF0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJJbnZhbGlkIGZvcm1hdDogXCIuY29uY2F0KGZvcm1hdCwgXCIgcGFzc2VkIGluIGNvbmZpZywgaWdub3JpbmcuXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoc3VwcG9ydGVkRm9ybWF0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IFwiTm9uZSBvZiBmb3JtYXRzVG9TdXBwb3J0IG1hdGNoIHN1cHBvcnRlZCB2YWx1ZXMuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1cHBvcnRlZEZvcm1hdHM7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuZ2V0VXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChjb25maWcpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKGNvbmZpZy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25maWcudXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQgIT09IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChjb25maWcuZXhwZXJpbWVudGFsRmVhdHVyZXMpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhwZXJpbWVudGFsRmVhdHVyZXMgPSBjb25maWcuZXhwZXJpbWVudGFsRmVhdHVyZXM7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChleHBlcmltZW50YWxGZWF0dXJlcy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBleHBlcmltZW50YWxGZWF0dXJlcy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCAhPT0gZmFsc2U7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUudmFsaWRhdGVRcmJveFNpemUgPSBmdW5jdGlvbiAodmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBpbnRlcm5hbENvbmZpZykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcXJib3hTaXplID0gaW50ZXJuYWxDb25maWcucXJib3g7XG4gICAgICAgIHRoaXMudmFsaWRhdGVRcmJveENvbmZpZyhxcmJveFNpemUpO1xuICAgICAgICB2YXIgcXJEaW1lbnNpb25zID0gdGhpcy50b1FyZGltZW5zaW9ucyh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIHFyYm94U2l6ZSk7XG4gICAgICAgIHZhciB2YWxpZGF0ZU1pblNpemUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgICAgICAgICAgaWYgKHNpemUgPCBDb25zdGFudHMuTUlOX1FSX0JPWF9TSVpFKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJtaW5pbXVtIHNpemUgb2YgJ2NvbmZpZy5xcmJveCcgZGltZW5zaW9uIHZhbHVlIGlzXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcIiBcIi5jb25jYXQoQ29uc3RhbnRzLk1JTl9RUl9CT1hfU0laRSwgXCJweC5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBjb3JyZWN0V2lkdGhCYXNlZE9uUm9vdEVsZW1lbnRTaXplID0gZnVuY3Rpb24gKGNvbmZpZ1dpZHRoKSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnV2lkdGggPiB2aWV3ZmluZGVyV2lkdGgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5sb2dnZXIud2FybihcImBxcmJveC53aWR0aGAgb3IgYHFyYm94YCBpcyBsYXJnZXIgdGhhbiB0aGVcIlxuICAgICAgICAgICAgICAgICAgICArIFwiIHdpZHRoIG9mIHRoZSByb290IGVsZW1lbnQuIFRoZSB3aWR0aCB3aWxsIGJlIHRydW5jYXRlZFwiXG4gICAgICAgICAgICAgICAgICAgICsgXCIgdG8gdGhlIHdpZHRoIG9mIHJvb3QgZWxlbWVudC5cIik7XG4gICAgICAgICAgICAgICAgY29uZmlnV2lkdGggPSB2aWV3ZmluZGVyV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29uZmlnV2lkdGg7XG4gICAgICAgIH07XG4gICAgICAgIHZhbGlkYXRlTWluU2l6ZShxckRpbWVuc2lvbnMud2lkdGgpO1xuICAgICAgICB2YWxpZGF0ZU1pblNpemUocXJEaW1lbnNpb25zLmhlaWdodCk7XG4gICAgICAgIHFyRGltZW5zaW9ucy53aWR0aCA9IGNvcnJlY3RXaWR0aEJhc2VkT25Sb290RWxlbWVudFNpemUocXJEaW1lbnNpb25zLndpZHRoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS52YWxpZGF0ZVFyYm94Q29uZmlnID0gZnVuY3Rpb24gKHFyYm94U2l6ZSkge1xuICAgICAgICBpZiAodHlwZW9mIHFyYm94U2l6ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgcXJib3hTaXplID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocXJib3hTaXplLndpZHRoID09PSB1bmRlZmluZWQgfHwgcXJib3hTaXplLmhlaWdodCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkludmFsaWQgaW5zdGFuY2Ugb2YgUXJEaW1lbnNpb25zIHBhc3NlZCBmb3IgXCJcbiAgICAgICAgICAgICAgICArIFwiJ2NvbmZpZy5xcmJveCcuIEJvdGggJ3dpZHRoJyBhbmQgJ2hlaWdodCcgc2hvdWxkIGJlIHNldC5cIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnRvUXJkaW1lbnNpb25zID0gZnVuY3Rpb24gKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgcXJib3hTaXplKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcXJib3hTaXplID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICByZXR1cm4geyB3aWR0aDogcXJib3hTaXplLCBoZWlnaHQ6IHFyYm94U2l6ZSB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBxcmJveFNpemUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcXJib3hTaXplKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJxcmJveCBjb25maWcgd2FzIHBhc3NlZCBhcyBhIGZ1bmN0aW9uIGJ1dCBpdCBmYWlsZWQgd2l0aCBcIlxuICAgICAgICAgICAgICAgICAgICArIFwidW5rbm93biBlcnJvclwiICsgZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBxcmJveFNpemU7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2V0dXBVaSA9IGZ1bmN0aW9uICh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIGludGVybmFsQ29uZmlnKSB7XG4gICAgICAgIGlmIChpbnRlcm5hbENvbmZpZy5pc1NoYWRlZEJveEVuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy52YWxpZGF0ZVFyYm94U2l6ZSh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIGludGVybmFsQ29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcXJib3hTaXplID0gaXNOdWxsT3JVbmRlZmluZWQoaW50ZXJuYWxDb25maWcucXJib3gpID9cbiAgICAgICAgICAgIHsgd2lkdGg6IHZpZXdmaW5kZXJXaWR0aCwgaGVpZ2h0OiB2aWV3ZmluZGVySGVpZ2h0IH0gOiBpbnRlcm5hbENvbmZpZy5xcmJveDtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVFyYm94Q29uZmlnKHFyYm94U2l6ZSk7XG4gICAgICAgIHZhciBxckRpbWVuc2lvbnMgPSB0aGlzLnRvUXJkaW1lbnNpb25zKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgcXJib3hTaXplKTtcbiAgICAgICAgaWYgKHFyRGltZW5zaW9ucy5oZWlnaHQgPiB2aWV3ZmluZGVySGVpZ2h0KSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFwiW0h0bWw1UXJjb2RlXSBjb25maWcucXJib3ggaGFzIGhlaWdodCB0aGF0IGlzXCJcbiAgICAgICAgICAgICAgICArIFwiZ3JlYXRlciB0aGFuIHRoZSBoZWlnaHQgb2YgdGhlIHZpZGVvIHN0cmVhbS4gU2hhZGluZyB3aWxsIGJlXCJcbiAgICAgICAgICAgICAgICArIFwiIGlnbm9yZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNob3VsZFNoYWRpbmdCZUFwcGxpZWQgPSBpbnRlcm5hbENvbmZpZy5pc1NoYWRlZEJveEVuYWJsZWQoKVxuICAgICAgICAgICAgJiYgcXJEaW1lbnNpb25zLmhlaWdodCA8PSB2aWV3ZmluZGVySGVpZ2h0O1xuICAgICAgICB2YXIgZGVmYXVsdFFyUmVnaW9uID0ge1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICB3aWR0aDogdmlld2ZpbmRlcldpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0OiB2aWV3ZmluZGVySGVpZ2h0XG4gICAgICAgIH07XG4gICAgICAgIHZhciBxclJlZ2lvbiA9IHNob3VsZFNoYWRpbmdCZUFwcGxpZWRcbiAgICAgICAgICAgID8gdGhpcy5nZXRTaGFkZWRSZWdpb25Cb3VuZHModmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBxckRpbWVuc2lvbnMpXG4gICAgICAgICAgICA6IGRlZmF1bHRRclJlZ2lvbjtcbiAgICAgICAgdmFyIGNhbnZhc0VsZW1lbnQgPSB0aGlzLmNyZWF0ZUNhbnZhc0VsZW1lbnQocXJSZWdpb24ud2lkdGgsIHFyUmVnaW9uLmhlaWdodCk7XG4gICAgICAgIHZhciBjb250ZXh0QXR0cmlidXRlcyA9IHsgd2lsbFJlYWRGcmVxdWVudGx5OiB0cnVlIH07XG4gICAgICAgIHZhciBjb250ZXh0ID0gY2FudmFzRWxlbWVudC5nZXRDb250ZXh0KFwiMmRcIiwgY29udGV4dEF0dHJpYnV0ZXMpO1xuICAgICAgICBjb250ZXh0LmNhbnZhcy53aWR0aCA9IHFyUmVnaW9uLndpZHRoO1xuICAgICAgICBjb250ZXh0LmNhbnZhcy5oZWlnaHQgPSBxclJlZ2lvbi5oZWlnaHQ7XG4gICAgICAgIHRoaXMuZWxlbWVudC5hcHBlbmQoY2FudmFzRWxlbWVudCk7XG4gICAgICAgIGlmIChzaG91bGRTaGFkaW5nQmVBcHBsaWVkKSB7XG4gICAgICAgICAgICB0aGlzLnBvc3NpYmx5SW5zZXJ0U2hhZGluZ0VsZW1lbnQodGhpcy5lbGVtZW50LCB2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIHFyRGltZW5zaW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jcmVhdGVTY2FubmVyUGF1c2VkVWlFbGVtZW50KHRoaXMuZWxlbWVudCk7XG4gICAgICAgIHRoaXMucXJSZWdpb24gPSBxclJlZ2lvbjtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgdGhpcy5jYW52YXNFbGVtZW50ID0gY2FudmFzRWxlbWVudDtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5jcmVhdGVTY2FubmVyUGF1c2VkVWlFbGVtZW50ID0gZnVuY3Rpb24gKHJvb3RFbGVtZW50KSB7XG4gICAgICAgIHZhciBzY2FubmVyUGF1c2VkVWlFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5pbm5lclRleHQgPSBIdG1sNVFyY29kZVN0cmluZ3Muc2Nhbm5lclBhdXNlZCgpO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS50b3AgPSBcIjBweFwiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLnpJbmRleCA9IFwiMVwiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLmJhY2tncm91bmQgPSBcInJnYmEoOSwgOSwgOSwgMC40NilcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5jb2xvciA9IFwiI0ZGRUNFQ1wiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuc3R5bGUud2lkdGggPSBcIjEwMCVcIjtcbiAgICAgICAgcm9vdEVsZW1lbnQuYXBwZW5kQ2hpbGQoc2Nhbm5lclBhdXNlZFVpRWxlbWVudCk7XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudCA9IHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQ7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2NhbkNvbnRleHQgPSBmdW5jdGlvbiAocXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlTWFuYWdlclByb3h5LmlzUGF1c2VkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnFyY29kZS5kZWNvZGVBc3luYyh0aGlzLmNhbnZhc0VsZW1lbnQpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICBxckNvZGVTdWNjZXNzQ2FsbGJhY2socmVzdWx0LnRleHQsIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeS5jcmVhdGVGcm9tUXJjb2RlUmVzdWx0KHJlc3VsdCkpO1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlVcGRhdGVTaGFkZXJzKHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlVcGRhdGVTaGFkZXJzKGZhbHNlKTtcbiAgICAgICAgICAgIHZhciBlcnJvck1lc3NhZ2UgPSBIdG1sNVFyY29kZVN0cmluZ3MuY29kZVBhcnNlRXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgcXJDb2RlRXJyb3JDYWxsYmFjayhlcnJvck1lc3NhZ2UsIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5LmNyZWF0ZUZyb20oZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmZvcmV2ZXJTY2FuID0gZnVuY3Rpb24gKGludGVybmFsQ29uZmlnLCBxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLnNob3VsZFNjYW4pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdmlkZW9FbGVtZW50ID0gdGhpcy5yZW5kZXJlZENhbWVyYS5nZXRTdXJmYWNlKCk7XG4gICAgICAgIHZhciB3aWR0aFJhdGlvID0gdmlkZW9FbGVtZW50LnZpZGVvV2lkdGggLyB2aWRlb0VsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgICAgIHZhciBoZWlnaHRSYXRpbyA9IHZpZGVvRWxlbWVudC52aWRlb0hlaWdodCAvIHZpZGVvRWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgICAgIGlmICghdGhpcy5xclJlZ2lvbikge1xuICAgICAgICAgICAgdGhyb3cgXCJxclJlZ2lvbiB1bmRlZmluZWQgd2hlbiBsb2NhbE1lZGlhU3RyZWFtIGlzIHJlYWR5LlwiO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzV2lkdGhPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLndpZHRoICogd2lkdGhSYXRpbztcbiAgICAgICAgdmFyIHNIZWlnaHRPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLmhlaWdodCAqIGhlaWdodFJhdGlvO1xuICAgICAgICB2YXIgc3hPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLnggKiB3aWR0aFJhdGlvO1xuICAgICAgICB2YXIgc3lPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLnkgKiBoZWlnaHRSYXRpbztcbiAgICAgICAgdGhpcy5jb250ZXh0LmRyYXdJbWFnZSh2aWRlb0VsZW1lbnQsIHN4T2Zmc2V0LCBzeU9mZnNldCwgc1dpZHRoT2Zmc2V0LCBzSGVpZ2h0T2Zmc2V0LCAwLCAwLCB0aGlzLnFyUmVnaW9uLndpZHRoLCB0aGlzLnFyUmVnaW9uLmhlaWdodCk7XG4gICAgICAgIHZhciB0cmlnZ2VyTmV4dFNjYW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5mb3JldmVyU2NhblRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5mb3JldmVyU2NhbihpbnRlcm5hbENvbmZpZywgcXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0sIF90aGlzLmdldFRpbWVvdXRGcHMoaW50ZXJuYWxDb25maWcuZnBzKSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2NhbkNvbnRleHQocXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGlzU3VjY2Vzc2Z1bGwpIHtcbiAgICAgICAgICAgIGlmICghaXNTdWNjZXNzZnVsbCAmJiBpbnRlcm5hbENvbmZpZy5kaXNhYmxlRmxpcCAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbnRleHQudHJhbnNsYXRlKF90aGlzLmNvbnRleHQuY2FudmFzLndpZHRoLCAwKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jb250ZXh0LnNjYWxlKC0xLCAxKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5zY2FuQ29udGV4dChxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spXG4gICAgICAgICAgICAgICAgICAgIC5maW5hbGx5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlck5leHRTY2FuKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyTmV4dFNjYW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICBfdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJFcnJvciBoYXBwZW5kIHdoaWxlIHNjYW5uaW5nIGNvbnRleHRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgdHJpZ2dlck5leHRTY2FuKCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmNyZWF0ZVZpZGVvQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FtZXJhSWRPckNvbmZpZykge1xuICAgICAgICBpZiAodHlwZW9mIGNhbWVyYUlkT3JDb25maWcgPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHsgZGV2aWNlSWQ6IHsgZXhhY3Q6IGNhbWVyYUlkT3JDb25maWcgfSB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBjYW1lcmFJZE9yQ29uZmlnID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgIHZhciBmYWNpbmdNb2RlS2V5ID0gXCJmYWNpbmdNb2RlXCI7XG4gICAgICAgICAgICB2YXIgZGV2aWNlSWRLZXkgPSBcImRldmljZUlkXCI7XG4gICAgICAgICAgICB2YXIgYWxsb3dlZEZhY2luZ01vZGVWYWx1ZXNfMSA9IHsgXCJ1c2VyXCI6IHRydWUsIFwiZW52aXJvbm1lbnRcIjogdHJ1ZSB9O1xuICAgICAgICAgICAgdmFyIGV4YWN0S2V5ID0gXCJleGFjdFwiO1xuICAgICAgICAgICAgdmFyIGlzVmFsaWRGYWNpbmdNb2RlVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUgaW4gYWxsb3dlZEZhY2luZ01vZGVWYWx1ZXNfMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiY29uZmlnIGhhcyBpbnZhbGlkICdmYWNpbmdNb2RlJyB2YWx1ZSA9IFwiXG4gICAgICAgICAgICAgICAgICAgICAgICArIFwiJ1wiLmNvbmNhdCh2YWx1ZSwgXCInXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGNhbWVyYUlkT3JDb25maWcpO1xuICAgICAgICAgICAgaWYgKGtleXMubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCInY2FtZXJhSWRPckNvbmZpZycgb2JqZWN0IHNob3VsZCBoYXZlIGV4YWN0bHkgMSBrZXksXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcIiBpZiBwYXNzZWQgYXMgYW4gb2JqZWN0LCBmb3VuZCBcIi5jb25jYXQoa2V5cy5sZW5ndGgsIFwiIGtleXNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIga2V5ID0gT2JqZWN0LmtleXMoY2FtZXJhSWRPckNvbmZpZylbMF07XG4gICAgICAgICAgICBpZiAoa2V5ICE9PSBmYWNpbmdNb2RlS2V5ICYmIGtleSAhPT0gZGV2aWNlSWRLZXkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIk9ubHkgJ1wiLmNvbmNhdChmYWNpbmdNb2RlS2V5LCBcIicgYW5kICdcIikuY29uY2F0KGRldmljZUlkS2V5LCBcIicgXCIpXG4gICAgICAgICAgICAgICAgICAgICsgXCIgYXJlIHN1cHBvcnRlZCBmb3IgJ2NhbWVyYUlkT3JDb25maWcnXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoa2V5ID09PSBmYWNpbmdNb2RlS2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGZhY2luZ01vZGUgPSBjYW1lcmFJZE9yQ29uZmlnLmZhY2luZ01vZGU7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmYWNpbmdNb2RlID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRGYWNpbmdNb2RlVmFsdWUoZmFjaW5nTW9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGZhY2luZ01vZGU6IGZhY2luZ01vZGUgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgZmFjaW5nTW9kZSA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGFjdEtleSBpbiBmYWNpbmdNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZEZhY2luZ01vZGVWYWx1ZShmYWNpbmdNb2RlW1wiXCIuY29uY2F0KGV4YWN0S2V5KV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjaW5nTW9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhY2luZ01vZGVbXCJcIi5jb25jYXQoZXhhY3RLZXkpXVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiJ2ZhY2luZ01vZGUnIHNob3VsZCBiZSBzdHJpbmcgb3Igb2JqZWN0IHdpdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgXCIgXCIuY29uY2F0KGV4YWN0S2V5LCBcIiBhcyBrZXkuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZV8xID0gKHR5cGVvZiBmYWNpbmdNb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJJbnZhbGlkIHR5cGUgb2YgJ2ZhY2luZ01vZGUnID0gXCIuY29uY2F0KHR5cGVfMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGRldmljZUlkID0gY2FtZXJhSWRPckNvbmZpZy5kZXZpY2VJZDtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRldmljZUlkID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZGV2aWNlSWQ6IGRldmljZUlkIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBkZXZpY2VJZCA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGFjdEtleSBpbiBkZXZpY2VJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VJZDogeyBleGFjdDogZGV2aWNlSWRbXCJcIi5jb25jYXQoZXhhY3RLZXkpXSB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCInZGV2aWNlSWQnIHNob3VsZCBiZSBzdHJpbmcgb3Igb2JqZWN0IHdpdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgXCIgXCIuY29uY2F0KGV4YWN0S2V5LCBcIiBhcyBrZXkuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZV8yID0gKHR5cGVvZiBkZXZpY2VJZCk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiSW52YWxpZCB0eXBlIG9mICdkZXZpY2VJZCcgPSBcIi5jb25jYXQodHlwZV8yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHR5cGUgPSAodHlwZW9mIGNhbWVyYUlkT3JDb25maWcpO1xuICAgICAgICB0aHJvdyBcIkludmFsaWQgdHlwZSBvZiAnY2FtZXJhSWRPckNvbmZpZycgPSBcIi5jb25jYXQodHlwZSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuY29tcHV0ZUNhbnZhc0RyYXdDb25maWcgPSBmdW5jdGlvbiAoaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQsIGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQpIHtcbiAgICAgICAgaWYgKGltYWdlV2lkdGggPD0gY29udGFpbmVyV2lkdGhcbiAgICAgICAgICAgICYmIGltYWdlSGVpZ2h0IDw9IGNvbnRhaW5lckhlaWdodCkge1xuICAgICAgICAgICAgdmFyIHhvZmZzZXQgPSAoY29udGFpbmVyV2lkdGggLSBpbWFnZVdpZHRoKSAvIDI7XG4gICAgICAgICAgICB2YXIgeW9mZnNldCA9IChjb250YWluZXJIZWlnaHQgLSBpbWFnZUhlaWdodCkgLyAyO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4OiB4b2Zmc2V0LFxuICAgICAgICAgICAgICAgIHk6IHlvZmZzZXQsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGltYWdlV2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBpbWFnZUhlaWdodFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBmb3JtZXJJbWFnZVdpZHRoID0gaW1hZ2VXaWR0aDtcbiAgICAgICAgICAgIHZhciBmb3JtZXJJbWFnZUhlaWdodCA9IGltYWdlSGVpZ2h0O1xuICAgICAgICAgICAgaWYgKGltYWdlV2lkdGggPiBjb250YWluZXJXaWR0aCkge1xuICAgICAgICAgICAgICAgIGltYWdlSGVpZ2h0ID0gKGNvbnRhaW5lcldpZHRoIC8gaW1hZ2VXaWR0aCkgKiBpbWFnZUhlaWdodDtcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gY29udGFpbmVyV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW1hZ2VIZWlnaHQgPiBjb250YWluZXJIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gKGNvbnRhaW5lckhlaWdodCAvIGltYWdlSGVpZ2h0KSAqIGltYWdlV2lkdGg7XG4gICAgICAgICAgICAgICAgaW1hZ2VIZWlnaHQgPSBjb250YWluZXJIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5sb2coXCJJbWFnZSBkb3duc2FtcGxlZCBmcm9tIFwiXG4gICAgICAgICAgICAgICAgKyBcIlwiLmNvbmNhdChmb3JtZXJJbWFnZVdpZHRoLCBcIlhcIikuY29uY2F0KGZvcm1lckltYWdlSGVpZ2h0KVxuICAgICAgICAgICAgICAgICsgXCIgdG8gXCIuY29uY2F0KGltYWdlV2lkdGgsIFwiWFwiKS5jb25jYXQoaW1hZ2VIZWlnaHQsIFwiLlwiKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb21wdXRlQ2FudmFzRHJhd0NvbmZpZyhpbWFnZVdpZHRoLCBpbWFnZUhlaWdodCwgY29udGFpbmVyV2lkdGgsIGNvbnRhaW5lckhlaWdodCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5jbGVhckVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlTWFuYWdlclByb3h5LmlzU2Nhbm5pbmcoKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJDYW5ub3QgY2xlYXIgd2hpbGUgc2NhbiBpcyBvbmdvaW5nLCBjbG9zZSBpdCBmaXJzdC5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZWxlbWVudElkKTtcbiAgICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnBvc3NpYmx5VXBkYXRlU2hhZGVycyA9IGZ1bmN0aW9uIChxck1hdGNoKSB7XG4gICAgICAgIGlmICh0aGlzLnFyTWF0Y2ggPT09IHFyTWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5oYXNCb3JkZXJTaGFkZXJzXG4gICAgICAgICAgICAmJiB0aGlzLmJvcmRlclNoYWRlcnNcbiAgICAgICAgICAgICYmIHRoaXMuYm9yZGVyU2hhZGVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycy5mb3JFYWNoKGZ1bmN0aW9uIChzaGFkZXIpIHtcbiAgICAgICAgICAgICAgICBzaGFkZXIuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gcXJNYXRjaFxuICAgICAgICAgICAgICAgICAgICA/IENvbnN0YW50cy5CT1JERVJfU0hBREVSX01BVENIX0NPTE9SXG4gICAgICAgICAgICAgICAgICAgIDogQ29uc3RhbnRzLkJPUkRFUl9TSEFERVJfREVGQVVMVF9DT0xPUjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucXJNYXRjaCA9IHFyTWF0Y2g7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUucG9zc2libHlDbG9zZUxhc3RTY2FuSW1hZ2VGaWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5sYXN0U2NhbkltYWdlRmlsZSkge1xuICAgICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh0aGlzLmxhc3RTY2FuSW1hZ2VGaWxlKTtcbiAgICAgICAgICAgIHRoaXMubGFzdFNjYW5JbWFnZUZpbGUgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuY3JlYXRlQ2FudmFzRWxlbWVudCA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0LCBjdXN0b21JZCkge1xuICAgICAgICB2YXIgY2FudmFzV2lkdGggPSB3aWR0aDtcbiAgICAgICAgdmFyIGNhbnZhc0hlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdmFyIGNhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpO1xuICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQoY2FudmFzV2lkdGgsIFwicHhcIik7XG4gICAgICAgIGNhbnZhc0VsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gXCJcIi5jb25jYXQoY2FudmFzSGVpZ2h0LCBcInB4XCIpO1xuICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgY2FudmFzRWxlbWVudC5pZCA9IGlzTnVsbE9yVW5kZWZpbmVkKGN1c3RvbUlkKVxuICAgICAgICAgICAgPyBcInFyLWNhbnZhc1wiIDogY3VzdG9tSWQ7XG4gICAgICAgIHJldHVybiBjYW52YXNFbGVtZW50O1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFNoYWRlZFJlZ2lvbkJvdW5kcyA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0LCBxcmJveFNpemUpIHtcbiAgICAgICAgaWYgKHFyYm94U2l6ZS53aWR0aCA+IHdpZHRoIHx8IHFyYm94U2l6ZS5oZWlnaHQgPiBoZWlnaHQpIHtcbiAgICAgICAgICAgIHRocm93IFwiJ2NvbmZpZy5xcmJveCcgZGltZW5zaW9ucyBzaG91bGQgbm90IGJlIGdyZWF0ZXIgdGhhbiB0aGUgXCJcbiAgICAgICAgICAgICAgICArIFwiZGltZW5zaW9ucyBvZiB0aGUgcm9vdCBIVE1MIGVsZW1lbnQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6ICh3aWR0aCAtIHFyYm94U2l6ZS53aWR0aCkgLyAyLFxuICAgICAgICAgICAgeTogKGhlaWdodCAtIHFyYm94U2l6ZS5oZWlnaHQpIC8gMixcbiAgICAgICAgICAgIHdpZHRoOiBxcmJveFNpemUud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHFyYm94U2l6ZS5oZWlnaHRcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5wb3NzaWJseUluc2VydFNoYWRpbmdFbGVtZW50ID0gZnVuY3Rpb24gKGVsZW1lbnQsIHdpZHRoLCBoZWlnaHQsIHFyYm94U2l6ZSkge1xuICAgICAgICBpZiAoKHdpZHRoIC0gcXJib3hTaXplLndpZHRoKSA8IDEgfHwgKGhlaWdodCAtIHFyYm94U2l6ZS5oZWlnaHQpIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzaGFkaW5nRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB2YXIgcmlnaHRMZWZ0Qm9yZGVyU2l6ZSA9ICh3aWR0aCAtIHFyYm94U2l6ZS53aWR0aCkgLyAyO1xuICAgICAgICB2YXIgdG9wQm90dG9tQm9yZGVyU2l6ZSA9IChoZWlnaHQgLSBxcmJveFNpemUuaGVpZ2h0KSAvIDI7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlckxlZnRcbiAgICAgICAgICAgID0gXCJcIi5jb25jYXQocmlnaHRMZWZ0Qm9yZGVyU2l6ZSwgXCJweCBzb2xpZCByZ2JhKDAsIDAsIDAsIDAuNDgpXCIpO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3JkZXJSaWdodFxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdChyaWdodExlZnRCb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlclRvcFxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdCh0b3BCb3R0b21Cb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlckJvdHRvbVxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdCh0b3BCb3R0b21Cb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJveFNpemluZyA9IFwiYm9yZGVyLWJveFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS50b3AgPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3R0b20gPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5sZWZ0ID0gXCIwcHhcIjtcbiAgICAgICAgc2hhZGluZ0VsZW1lbnQuc3R5bGUucmlnaHQgPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5pZCA9IFwiXCIuY29uY2F0KENvbnN0YW50cy5TSEFERURfUkVHSU9OX0VMRU1FTlRfSUQpO1xuICAgICAgICBpZiAoKHdpZHRoIC0gcXJib3hTaXplLndpZHRoKSA8IDExXG4gICAgICAgICAgICB8fCAoaGVpZ2h0IC0gcXJib3hTaXplLmhlaWdodCkgPCAxMSkge1xuICAgICAgICAgICAgdGhpcy5oYXNCb3JkZXJTaGFkZXJzID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgc21hbGxTaXplID0gNTtcbiAgICAgICAgICAgIHZhciBsYXJnZVNpemUgPSA0MDtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgbGFyZ2VTaXplLCBzbWFsbFNpemUsIC1zbWFsbFNpemUsIG51bGwsIDAsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBsYXJnZVNpemUsIHNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgbnVsbCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBsYXJnZVNpemUsIHNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgMCwgdHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLmluc2VydFNoYWRlckJvcmRlcnMoc2hhZGluZ0VsZW1lbnQsIGxhcmdlU2l6ZSwgc21hbGxTaXplLCBudWxsLCAtc21hbGxTaXplLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICB0aGlzLmluc2VydFNoYWRlckJvcmRlcnMoc2hhZGluZ0VsZW1lbnQsIHNtYWxsU2l6ZSwgbGFyZ2VTaXplICsgc21hbGxTaXplLCAtc21hbGxTaXplLCBudWxsLCAtc21hbGxTaXplLCB0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgc21hbGxTaXplLCBsYXJnZVNpemUgKyBzbWFsbFNpemUsIG51bGwsIC1zbWFsbFNpemUsIC1zbWFsbFNpemUsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBzbWFsbFNpemUsIGxhcmdlU2l6ZSArIHNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBzbWFsbFNpemUsIGxhcmdlU2l6ZSArIHNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5oYXNCb3JkZXJTaGFkZXJzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50LmFwcGVuZChzaGFkaW5nRWxlbWVudCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuaW5zZXJ0U2hhZGVyQm9yZGVycyA9IGZ1bmN0aW9uIChzaGFkZXJFbGVtLCB3aWR0aCwgaGVpZ2h0LCB0b3AsIGJvdHRvbSwgc2lkZSwgaXNMZWZ0KSB7XG4gICAgICAgIHZhciBlbGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZWxlbS5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgZWxlbS5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBDb25zdGFudHMuQk9SREVSX1NIQURFUl9ERUZBVUxUX0NPTE9SO1xuICAgICAgICBlbGVtLnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQod2lkdGgsIFwicHhcIik7XG4gICAgICAgIGVsZW0uc3R5bGUuaGVpZ2h0ID0gXCJcIi5jb25jYXQoaGVpZ2h0LCBcInB4XCIpO1xuICAgICAgICBpZiAodG9wICE9PSBudWxsKSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLnRvcCA9IFwiXCIuY29uY2F0KHRvcCwgXCJweFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYm90dG9tICE9PSBudWxsKSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLmJvdHRvbSA9IFwiXCIuY29uY2F0KGJvdHRvbSwgXCJweFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNMZWZ0KSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLmxlZnQgPSBcIlwiLmNvbmNhdChzaWRlLCBcInB4XCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZWxlbS5zdHlsZS5yaWdodCA9IFwiXCIuY29uY2F0KHNpZGUsIFwicHhcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmJvcmRlclNoYWRlcnMpIHtcbiAgICAgICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycy5wdXNoKGVsZW0pO1xuICAgICAgICBzaGFkZXJFbGVtLmFwcGVuZENoaWxkKGVsZW0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnNob3dQYXVzZWRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRocm93IFwiW2ludGVybmFsIGVycm9yXSBzY2FubmVyIHBhdXNlZCBVSSBlbGVtZW50IG5vdCBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmhpZGVQYXVzZWRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRocm93IFwiW2ludGVybmFsIGVycm9yXSBzY2FubmVyIHBhdXNlZCBVSSBlbGVtZW50IG5vdCBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuZ2V0VGltZW91dEZwcyA9IGZ1bmN0aW9uIChmcHMpIHtcbiAgICAgICAgcmV0dXJuIDEwMDAgLyBmcHM7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGU7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGUgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWh0bWw1LXFyY29kZS5qcy5tYXAiLCJ2YXIgU1ZHX1hNTF9QUkVGSVggPSBcImRhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsXCI7XG5leHBvcnQgdmFyIEFTU0VUX0NBTUVSQV9TQ0FOID0gU1ZHX1hNTF9QUkVGSVggKyBcIlBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSFpwWlhkQ2IzZzlJakFnTUNBek56RXVOalF6SURNM01TNDJORE1pSUhOMGVXeGxQU0psYm1GaWJHVXRZbUZqYTJkeWIzVnVaRHB1WlhjZ01DQXdJRE0zTVM0Mk5ETWdNemN4TGpZME15SWdlRzFzT25Od1lXTmxQU0p3Y21WelpYSjJaU0krUEhCaGRHZ2daRDBpVFRFd05TNHdPRFFnTXpndU1qY3hhREUyTXk0M05qaDJNakJJTVRBMUxqQTROSG9pTHo0OGNHRjBhQ0JrUFNKTk16RXhMalU1TmlBeE9UQXVNVGc1WXkwM0xqUTBNUzA1TGpNME55MHhPQzQwTURNdE1UWXVNakEyTFRNeUxqYzBNeTB5TUM0MU1qSldNekJqTUMweE5pNDFOREl0TVRNdU5EVTRMVE13TFRNd0xUTXdTREV5TlM0d09EUmpMVEUyTGpVME1pQXdMVE13SURFekxqUTFPQzB6TUNBek1IWXhNakF1TVRRemFDMDRMakk1Tm1NdE1UWXVOVFF5SURBdE16QWdNVE11TkRVNExUTXdJRE13ZGpFdU16TXpZVEk1TGpnd05DQXlPUzQ0TURRZ01DQXdJREFnTkM0Mk1ETWdNVFV1T1RNNVl5MDNMak0wSURVdU5EYzBMVEV5TGpFd015QXhOQzR5TWpFdE1USXVNVEF6SURJMExqQTJNWFl4TGpNek0yTXdJRGt1T0RRZ05DNDNOak1nTVRndU5UZzNJREV5TGpFd015QXlOQzR3TmpKaE1qa3VPREVnTWprdU9ERWdNQ0F3SURBdE5DNDJNRE1nTVRVdU9UTTRkakV1TXpNell6QWdNVFl1TlRReUlERXpMalExT0NBek1DQXpNQ0F6TUdnNExqTXlOR011TkRJM0lERXhMall6TVNBM0xqVXdNeUF5TVM0MU9EY2dNVGN1TlRNMElESTJMakUzTnk0NU16RWdNVEF1TlRBeklEUXVNRGcwSURNd0xqRTROeUF4TkM0M05qZ2dORFV1TlRNM1lUa3VPVGc0SURrdU9UZzRJREFnTUNBd0lEZ3VNakUySURRdU1qZzRJRGt1T1RVNElEa3VPVFU0SURBZ01DQXdJRFV1TnpBMExURXVOemt6WXpRdU5UTXpMVE11TVRVMUlEVXVOalV0T1M0ek9EZ2dNaTQwT1RVdE1UTXVPVEl4TFRZdU56azRMVGt1TnpZM0xUa3VOakF5TFRJeUxqWXdPQzB4TUM0M05pMHpNUzQwYURneUxqWTROV011TWpjeUxqUXhOQzQxTkRVdU9ERTRMamd4TlNBeExqSXhJRE11TVRReUlEUXVOVFF4SURrdU16Y3lJRFV1TmpjNUlERXpMamt4TXlBeUxqVXpOQ0EwTGpVME1pMHpMakUwTWlBMUxqWTNOeTA1TGpNM01TQXlMalV6TlMweE15NDVNVE10TVRFdU9URTVMVEUzTGpJeU9TMDRMamM0Tnkwek5TNDRPRFFnT1M0MU9ERXROVGN1TURFeUlETXVNRFkzTFRJdU5qVXlJREV5TGpNd055MHhNUzQzTXpJZ01URXVNakUzTFRJMExqQXpNeTB1T0RJNExUa3VNelF6TFRjdU1UQTVMVEUzTGpFNU5DMHhPQzQyTmprdE1qTXVNek0zWVRrdU9EVTNJRGt1T0RVM0lEQWdNQ0F3TFRFdU1EWXhMUzQwT0RaakxTNDBOall0TGpFNE1pMHhNUzQwTURNdE5DNDFOemt0T1M0M05ERXRNVFV1TnpBMklERXVNREEzTFRZdU56TTNJREUwTGpjMk9DMDRMakkzTXlBeU15NDNOall0Tnk0Mk5qWWdNak11TVRVMklERXVOVFk1SURNNUxqWTVPQ0EzTGpnd015QTBOeTQ0TXpZZ01UZ3VNREkySURVdU56VXlJRGN1TWpJMUlEY3VOakEzSURFMkxqWXlNeUExTGpZM015QXlPQzQzTXpNdExqUXhNeUF5TGpVNE5TMHVPREkwSURVdU1qUXhMVEV1TWpRMUlEY3VPVFU1TFRVdU56VTJJRE0zTGpFNU5DMHhNaTQ1TVRrZ09ETXVORGd6TFRRNUxqZzNJREV4TkM0Mk5qRXROQzR5TWpFZ015NDFOakV0TkM0M05UWWdPUzQ0TnkweExqRTVOQ0F4TkM0d09USmhPUzQ1T0NBNUxqazRJREFnTUNBd0lEY3VOalE0SURNdU5UVXhJRGt1T1RVMUlEa3VPVFUxSURBZ01DQXdJRFl1TkRRMExUSXVNelU0WXpReUxqWTNNaTB6Tmk0d01EVWdOVEF1T0RBeUxUZzRMalV6TXlBMU5pNDNNemN0TVRJMkxqZzRPQzQwTVRVdE1pNDJPRFF1T0RJeExUVXVNekE1SURFdU1qSTVMVGN1T0RZeklESXVPRE0wTFRFM0xqY3lNUzB1TkRVMUxUTXlMalkwTVMwNUxqYzNNaTAwTkM0ek5EVjZiUzB5TXpJdU16QTRJRFF5TGpZeVl5MDFMalV4TkNBd0xURXdMVFF1TkRnMkxURXdMVEV3ZGkweExqTXpNMk13TFRVdU5URTBJRFF1TkRnMkxURXdJREV3TFRFd2FERTFkakl4TGpNek0yZ3RNVFY2YlMweUxqVXROVEl1TmpZMll6QXROUzQxTVRRZ05DNDBPRFl0TVRBZ01UQXRNVEJvTnk0MWRqSXhMak16TTJndE55NDFZeTAxTGpVeE5DQXdMVEV3TFRRdU5EZzJMVEV3TFRFd2RpMHhMak16TTNwdE1UY3VOU0E1TXk0NU9UbG9MVGN1TldNdE5TNDFNVFFnTUMweE1DMDBMalE0TmkweE1DMHhNSFl0TVM0ek16TmpNQzAxTGpVeE5DQTBMalE0TmkweE1DQXhNQzB4TUdnM0xqVjJNakV1TXpNemVtMHpNQzQzT1RZZ01qZ3VPRGczWXkwMUxqVXhOQ0F3TFRFd0xUUXVORGcyTFRFd0xURXdkaTA0TGpJM01XZzVNUzQwTlRkakxTNDROVEVnTmk0Mk5qZ3RMalF6TnlBeE1pNDNPRGN1TnpNeElERTRMakkzTVdndE9ESXVNVGc0ZW0wM09TNDBPREl0TVRFekxqWTVPR010TXk0eE1qUWdNakF1T1RBMklERXlMalF5TnlBek15NHhPRFFnTWpFdU5qSTFJRE0zTGpBMElEVXVORFF4SURJdU9UWTRJRGN1TlRVeElEVXVOalEzSURjdU56QXhJRGN1TVRnNExqSXhJREl1TVRVdE1pNDFOVE1nTlM0Mk9EUXROQzQwTnpjZ055NHlOVEV0TGpRNE1pNHpOemd0TGpreU9TNDRMVEV1TXpNMUlERXVNall4TFRZdU9UZzNJRGN1T1RNMkxURXhMams0TWlBeE5TNDFNaTB4TlM0ME16SWdNakl1TmpnNGFDMDVOeTQxTmpSV016QmpNQzAxTGpVeE5DQTBMalE0TmkweE1DQXhNQzB4TUdneE1qTXVOelk1WXpVdU5URTBJREFnTVRBZ05DNDBPRFlnTVRBZ01UQjJNVE0xTGpVM09XTXRNeTR3TXpJdExqTTRNUzAyTGpFMUxTNDJPVFF0T1M0ek9Ea3RMamt4TkMweU5TNHhOVGt0TVM0Mk9UUXROREl1TXpjZ055NDNORGd0TkRRdU9EazRJREkwTGpZMk5ub2lMejQ4Y0dGMGFDQmtQU0pOTVRjNUxqRXlPU0E0TXk0eE5qZG9MVEkwTGpBMllUVWdOU0F3SURBZ01DMDFJRFYyTWpRdU1EWXhZVFVnTlNBd0lEQWdNQ0ExSURWb01qUXVNRFpoTlNBMUlEQWdNQ0F3SURVdE5WWTRPQzR4TmpkaE5TQTFJREFnTUNBd0xUVXROWHBOTVRjeUxqWXlPU0F4TkRJdU9EWm9MVEV5TGpVMlZqRXpNQzQ0WVRVZ05TQXdJREVnTUMweE1DQXdkakUzTGpBMk1XRTFJRFVnTUNBd0lEQWdOU0ExYURFM0xqVTJZVFVnTlNBd0lERWdNQ0F3TFRFd0xqQXdNWHBOTWpFMkxqVTJPQ0E0TXk0eE5qZG9MVEkwTGpBMllUVWdOU0F3SURBZ01DMDFJRFYyTWpRdU1EWXhZVFVnTlNBd0lEQWdNQ0ExSURWb01qUXVNRFpoTlNBMUlEQWdNQ0F3SURVdE5WWTRPQzR4TmpkaE5TQTFJREFnTUNBd0xUVXROWHB0TFRVZ01qUXVNRFl4YUMweE5DNHdObFk1TXk0eE5qZG9NVFF1TURaMk1UUXVNRFl4ZWsweU1URXVOalk1SURFeU5TNDVNelpJTVRrM0xqUXhZVFVnTlNBd0lEQWdNQzAxSURWMk1UUXVNalUzWVRVZ05TQXdJREFnTUNBMUlEVm9NVFF1TWpVNVlUVWdOU0F3SURBZ01DQTFMVFYyTFRFMExqSTFOMkUxSURVZ01DQXdJREF0TlMwMWVpSXZQand2YzNablBnPT1cIjtcbmV4cG9ydCB2YXIgQVNTRVRfRklMRV9TQ0FOID0gU1ZHX1hNTF9QUkVGSVggKyBcIlBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSFpwWlhkQ2IzZzlJakFnTUNBMU9TNHdNVGdnTlRrdU1ERTRJaUJ6ZEhsc1pUMGlaVzVoWW14bExXSmhZMnRuY205MWJtUTZibVYzSURBZ01DQTFPUzR3TVRnZ05Ua3VNREU0SWlCNGJXdzZjM0JoWTJVOUluQnlaWE5sY25abElqNDhjR0YwYUNCa1BTSnROVGd1TnpReElEVTBMamd3T1MwMUxqazJPUzAyTGpJME5HRXhNQzQzTkNBeE1DNDNOQ0F3SURBZ01DQXlMamd5TFRjdU1qVmpNQzAxTGprMU15MDBMamcwTXkweE1DNDNPVFl0TVRBdU56azJMVEV3TGpjNU5sTXpOQ0F6TlM0ek5qRWdNelFnTkRFdU16RTBJRE00TGpnME15QTFNaTR4TVNBME5DNDNPVFlnTlRJdU1URmpNaTQwTkRFZ01DQTBMalk0T0MwdU9ESTBJRFl1TkRrNUxUSXVNVGsyYkRZdU1EQXhJRFl1TWpjM1lTNDVPVGd1T1RrNElEQWdNQ0F3SURFdU5ERTBMakF6TWlBeElERWdNQ0F3SURBZ0xqQXpNUzB4TGpReE5IcE5NellnTkRFdU16RTBZekF0TkM0NE5TQXpMamswTmkwNExqYzVOaUE0TGpjNU5pMDRMamM1Tm5NNExqYzVOaUF6TGprME5pQTRMamM1TmlBNExqYzVOaTB6TGprME5pQTRMamM1TmkwNExqYzVOaUE0TGpjNU5sTXpOaUEwTmk0eE5qUWdNellnTkRFdU16RTBlazB4TUM0ME16RWdNVFl1TURnNFl6QWdNeTR3TnlBeUxqUTVPQ0ExTGpVMk9DQTFMalUyT1NBMUxqVTJPSE0xTGpVMk9TMHlMalE1T0NBMUxqVTJPUzAxTGpVMk9HTXdMVE11TURjeExUSXVORGs0TFRVdU5UWTVMVFV1TlRZNUxUVXVOVFk1Y3kwMUxqVTJPU0F5TGpRNU9DMDFMalUyT1NBMUxqVTJPWHB0T1M0eE16Z2dNR013SURFdU9UWTRMVEV1TmpBeUlETXVOVFk0TFRNdU5UWTVJRE11TlRZNGN5MHpMalUyT1MweExqWXdNUzB6TGpVMk9TMHpMalUyT0NBeExqWXdNaTB6TGpVMk9TQXpMalUyT1MwekxqVTJPU0F6TGpVMk9TQXhMall3TVNBekxqVTJPU0F6TGpVMk9Yb2lMejQ4Y0dGMGFDQmtQU0p0TXpBdU9EZ3lJREk0TGprNE55QTVMakU0TFRFd0xqQTFOQ0F4TVM0eU5qSWdNVEF1TXpJellURWdNU0F3SURBZ01DQXhMak0xTVMweExqUTNOV3d0TVRJdE1URmhNU0F4SURBZ01DQXdMVEV1TkRFMExqQTJNMnd0T1M0M09UUWdNVEF1TnpJM0xUUXVOelF6TFRRdU56UXpZVEV1TURBeklERXVNREF6SURBZ01DQXdMVEV1TXpZNExTNHdORFJNTmk0ek16a2dNemN1TnpZNFlURWdNU0F3SURFZ01DQXhMak15TWlBeExqVXdNV3d4Tmk0ek1UTXRNVFF1TXpZeUlEY3VNekU1SURjdU16RTRZUzQ1T1RrdU9UazVJREFnTVNBd0lERXVOREUwTFRFdU5ERTBiQzB4TGpneU5TMHhMamd5TkhvaUx6NDhjR0YwYUNCa1BTSk5NekFnTkRZdU5URTRTREoyTFRReWFEVTBkakk0WVRFZ01TQXdJREVnTUNBeUlEQjJMVEk1WVRFZ01TQXdJREFnTUMweExURklNV0V4SURFZ01DQXdJREF0TVNBeGRqUTBZVEVnTVNBd0lEQWdNQ0F4SURGb01qbGhNU0F4SURBZ01TQXdJREF0TW5vaUx6NDhMM04yWno0PVwiO1xuZXhwb3J0IHZhciBBU1NFVF9JTkZPX0lDT05fMTZQWCA9IFNWR19YTUxfUFJFRklYICsgXCJQSE4yWnlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhacFpYZENiM2c5SWpBZ01DQTBOakFnTkRZd0lpQnpkSGxzWlQwaVpXNWhZbXhsTFdKaFkydG5jbTkxYm1RNmJtVjNJREFnTUNBME5qQWdORFl3SWlCNGJXdzZjM0JoWTJVOUluQnlaWE5sY25abElqNDhjR0YwYUNCa1BTSk5Nak13SURCRE1UQXlMamszTlNBd0lEQWdNVEF5TGprM05TQXdJREl6TUhNeE1ESXVPVGMxSURJek1DQXlNekFnTWpNd0lESXpNQzB4TURJdU9UYzBJREl6TUMweU16QlRNelUzTGpBeU5TQXdJREl6TUNBd2VtMHpPQzR6TXpNZ016YzNMak0yWXpBZ09DNDJOell0Tnk0d016UWdNVFV1TnpFdE1UVXVOekVnTVRVdU56Rm9MVFF6TGpFd01XTXRPQzQyTnpZZ01DMHhOUzQzTVMwM0xqQXpOQzB4TlM0M01TMHhOUzQzTVZZeU1ESXVORGMzWXpBdE9DNDJOellnTnk0d016TXRNVFV1TnpFZ01UVXVOekV0TVRVdU56Rm9ORE11TVRBeFl6Z3VOamMySURBZ01UVXVOekVnTnk0d016TWdNVFV1TnpFZ01UVXVOekZXTXpjM0xqTTJlazB5TXpBZ01UVTNZeTB5TVM0MU16a2dNQzB6T1MweE55NDBOakV0TXprdE16bHpNVGN1TkRZeExUTTVJRE01TFRNNUlETTVJREUzTGpRMk1TQXpPU0F6T1MweE55NDBOakVnTXprdE16a2dNemw2SWk4K1BDOXpkbWMrXCI7XG5leHBvcnQgdmFyIEFTU0VUX0NMT1NFX0lDT05fMTZQWCA9IFwiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFCQUFBQUFRQ0FZQUFBQWY4LzloQUFBQUJITkNTVlFJQ0FnSWZBaGtpQUFBQUFsd1NGbHpBQUFBUWdBQUFFSUJhcnFRUkFBQUFCbDBSVmgwVTI5bWRIZGhjbVVBZDNkM0xtbHVhM05qWVhCbExtOXlaNXZ1UEJvQUFBRTFTVVJCVkRpTmZkSTdTME5CRUFYZ0x5YTFvdEZncGJZU2JJU0FncFhZaTZDbWlIOUtDQWlDaGFWZ2E2T2lXUGdmUkRRKzBpdGFHVk5vc1h0bHVXd2N1TXplUGZNNE0zc3E4bGJIQnVid2cxZGM0bTFFL0ovTjRnaERQT0lzZmsvNHhpRWFvNUtYME1jRmxqTjRDOWQ0UVRQWHVZOTlqUDNEc0lvRFBHTTZCWTVpNXlJNVI3TzRxK0ltRmtKWTJEQ2gzY0FIMmtseUIrOUoxeFVNTUFHN2VDaDFhK01yK2s0OGI1ZGlYckZWd3dMdVMrQko5TWZSNytHMEZIT0hoVEhoblhOV1M4N1ZERjRwY25mUUs0RXA3WFNjTkxtUFRaZ1VSTktLWUVOWVdEcHpXMUJoc2NTMVdIUzhDRGdVUkZKUXJXY29GM2MxM0tLYmdnMUJZUWZ5OHhaV0V6VFR3MVFaYkFvS3U4RnFKbmt0ZHU1aGNWU0htY2hpSUx6enVhRFF2akJ6VjJtOHlvaENFMWpIZlB4L3hoVSt5NEcvRDc1RUxsUkpzU1lBQUFBQVNVVk9SSzVDWUlJPVwiO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW1hZ2UtYXNzZXRzLmpzLm1hcCIsInZhciBQZXJzaXN0ZWREYXRhRmFjdG9yeSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUGVyc2lzdGVkRGF0YUZhY3RvcnkoKSB7XG4gICAgfVxuICAgIFBlcnNpc3RlZERhdGFGYWN0b3J5LmNyZWF0ZURlZmF1bHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoYXNQZXJtaXNzaW9uOiBmYWxzZSxcbiAgICAgICAgICAgIGxhc3RVc2VkQ2FtZXJhSWQ6IG51bGxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHJldHVybiBQZXJzaXN0ZWREYXRhRmFjdG9yeTtcbn0oKSk7XG52YXIgUGVyc2lzdGVkRGF0YU1hbmFnZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBlcnNpc3RlZERhdGFNYW5hZ2VyKCkge1xuICAgICAgICB0aGlzLmRhdGEgPSBQZXJzaXN0ZWREYXRhRmFjdG9yeS5jcmVhdGVEZWZhdWx0KCk7XG4gICAgICAgIHZhciBkYXRhID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oUGVyc2lzdGVkRGF0YU1hbmFnZXIuTE9DQUxfU1RPUkFHRV9LRVkpO1xuICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLmhhc0NhbWVyYVBlcm1pc3Npb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRhLmhhc1Blcm1pc3Npb247XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUuZ2V0TGFzdFVzZWRDYW1lcmFJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YS5sYXN0VXNlZENhbWVyYUlkO1xuICAgIH07XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLnNldEhhc1Blcm1pc3Npb24gPSBmdW5jdGlvbiAoaGFzUGVybWlzc2lvbikge1xuICAgICAgICB0aGlzLmRhdGEuaGFzUGVybWlzc2lvbiA9IGhhc1Blcm1pc3Npb247XG4gICAgICAgIHRoaXMuZmx1c2goKTtcbiAgICB9O1xuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLnByb3RvdHlwZS5zZXRMYXN0VXNlZENhbWVyYUlkID0gZnVuY3Rpb24gKGxhc3RVc2VkQ2FtZXJhSWQpIHtcbiAgICAgICAgdGhpcy5kYXRhLmxhc3RVc2VkQ2FtZXJhSWQgPSBsYXN0VXNlZENhbWVyYUlkO1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUucmVzZXRMYXN0VXNlZENhbWVyYUlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRhdGEubGFzdFVzZWRDYW1lcmFJZCA9IG51bGw7XG4gICAgICAgIHRoaXMuZmx1c2goKTtcbiAgICB9O1xuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kYXRhID0gUGVyc2lzdGVkRGF0YUZhY3RvcnkuY3JlYXRlRGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUuZmx1c2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFBlcnNpc3RlZERhdGFNYW5hZ2VyLkxPQ0FMX1NUT1JBR0VfS0VZLCBKU09OLnN0cmluZ2lmeSh0aGlzLmRhdGEpKTtcbiAgICB9O1xuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLkxPQ0FMX1NUT1JBR0VfS0VZID0gXCJIVE1MNV9RUkNPREVfREFUQVwiO1xuICAgIHJldHVybiBQZXJzaXN0ZWREYXRhTWFuYWdlcjtcbn0oKSk7XG5leHBvcnQgeyBQZXJzaXN0ZWREYXRhTWFuYWdlciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3RvcmFnZS5qcy5tYXAiLCJpbXBvcnQgeyBBU1NFVF9DTE9TRV9JQ09OXzE2UFgsIEFTU0VUX0lORk9fSUNPTl8xNlBYIH0gZnJvbSBcIi4vaW1hZ2UtYXNzZXRzXCI7XG5pbXBvcnQgeyBMaWJyYXJ5SW5mb1N0cmluZ3MgfSBmcm9tIFwiLi9zdHJpbmdzXCI7XG52YXIgTGlicmFyeUluZm9EaXYgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExpYnJhcnlJbmZvRGl2KCkge1xuICAgICAgICB0aGlzLmluZm9EaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgIH1cbiAgICBMaWJyYXJ5SW5mb0Rpdi5wcm90b3R5cGUucmVuZGVySW50byA9IGZ1bmN0aW9uIChwYXJlbnQpIHtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUudG9wID0gXCIxMHB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5yaWdodCA9IFwiMTBweFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuekluZGV4ID0gXCIyXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5wYWRkaW5nID0gXCI1cHRcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmJvcmRlciA9IFwiMXB4IHNvbGlkICMxNzE3MTdcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmZvbnRTaXplID0gXCIxMHB0XCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5iYWNrZ3JvdW5kID0gXCJyZ2IoMCAwIDAgLyA2OSUpXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5ib3JkZXJSYWRpdXMgPSBcIjVweFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmZvbnRXZWlnaHQgPSBcIjQwMFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuY29sb3IgPSBcIndoaXRlXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5pbm5lclRleHQgPSBMaWJyYXJ5SW5mb1N0cmluZ3MucG93ZXJlZEJ5KCk7XG4gICAgICAgIHZhciBwcm9qZWN0TGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xuICAgICAgICBwcm9qZWN0TGluay5pbm5lclRleHQgPSBcIlNjYW5BcHBcIjtcbiAgICAgICAgcHJvamVjdExpbmsuaHJlZiA9IFwiaHR0cHM6Ly9zY2FuYXBwLm9yZ1wiO1xuICAgICAgICBwcm9qZWN0TGluay50YXJnZXQgPSBcIm5ld1wiO1xuICAgICAgICBwcm9qZWN0TGluay5zdHlsZS5jb2xvciA9IFwid2hpdGVcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LmFwcGVuZENoaWxkKHByb2plY3RMaW5rKTtcbiAgICAgICAgdmFyIGJyZWFrRWxlbUZpcnN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJyXCIpO1xuICAgICAgICB2YXIgYnJlYWtFbGVtU2Vjb25kID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJyXCIpO1xuICAgICAgICB0aGlzLmluZm9EaXYuYXBwZW5kQ2hpbGQoYnJlYWtFbGVtRmlyc3QpO1xuICAgICAgICB0aGlzLmluZm9EaXYuYXBwZW5kQ2hpbGQoYnJlYWtFbGVtU2Vjb25kKTtcbiAgICAgICAgdmFyIHJlcG9ydElzc3VlTGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xuICAgICAgICByZXBvcnRJc3N1ZUxpbmsuaW5uZXJUZXh0ID0gTGlicmFyeUluZm9TdHJpbmdzLnJlcG9ydElzc3VlcygpO1xuICAgICAgICByZXBvcnRJc3N1ZUxpbmsuaHJlZiA9IFwiaHR0cHM6Ly9naXRodWIuY29tL21lYmphcy9odG1sNS1xcmNvZGUvaXNzdWVzXCI7XG4gICAgICAgIHJlcG9ydElzc3VlTGluay50YXJnZXQgPSBcIm5ld1wiO1xuICAgICAgICByZXBvcnRJc3N1ZUxpbmsuc3R5bGUuY29sb3IgPSBcIndoaXRlXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5hcHBlbmRDaGlsZChyZXBvcnRJc3N1ZUxpbmspO1xuICAgICAgICBwYXJlbnQuYXBwZW5kQ2hpbGQodGhpcy5pbmZvRGl2KTtcbiAgICB9O1xuICAgIExpYnJhcnlJbmZvRGl2LnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICB9O1xuICAgIExpYnJhcnlJbmZvRGl2LnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgIH07XG4gICAgcmV0dXJuIExpYnJhcnlJbmZvRGl2O1xufSgpKTtcbnZhciBMaWJyYXJ5SW5mb0ljb24gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExpYnJhcnlJbmZvSWNvbihvblRhcEluLCBvblRhcE91dCkge1xuICAgICAgICB0aGlzLmlzU2hvd2luZ0luZm9JY29uID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5vblRhcEluID0gb25UYXBJbjtcbiAgICAgICAgdGhpcy5vblRhcE91dCA9IG9uVGFwT3V0O1xuICAgICAgICB0aGlzLmluZm9JY29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImltZ1wiKTtcbiAgICB9XG4gICAgTGlicmFyeUluZm9JY29uLnByb3RvdHlwZS5yZW5kZXJJbnRvID0gZnVuY3Rpb24gKHBhcmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmluZm9JY29uLmFsdCA9IFwiSW5mbyBpY29uXCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3JjID0gQVNTRVRfSU5GT19JQ09OXzE2UFg7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUudG9wID0gXCI0cHhcIjtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5yaWdodCA9IFwiNHB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUub3BhY2l0eSA9IFwiMC42XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUuY3Vyc29yID0gXCJwb2ludGVyXCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUuekluZGV4ID0gXCIyXCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUud2lkdGggPSBcIjE2cHhcIjtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5oZWlnaHQgPSBcIjE2cHhcIjtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5vbm1vdXNlb3ZlciA9IGZ1bmN0aW9uIChfKSB7IHJldHVybiBfdGhpcy5vbkhvdmVySW4oKTsgfTtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5vbm1vdXNlb3V0ID0gZnVuY3Rpb24gKF8pIHsgcmV0dXJuIF90aGlzLm9uSG92ZXJPdXQoKTsgfTtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5vbmNsaWNrID0gZnVuY3Rpb24gKF8pIHsgcmV0dXJuIF90aGlzLm9uQ2xpY2soKTsgfTtcbiAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKHRoaXMuaW5mb0ljb24pO1xuICAgIH07XG4gICAgTGlicmFyeUluZm9JY29uLnByb3RvdHlwZS5vbkhvdmVySW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzU2hvd2luZ0luZm9JY29uKSB7XG4gICAgICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLm9wYWNpdHkgPSBcIjFcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTGlicmFyeUluZm9JY29uLnByb3RvdHlwZS5vbkhvdmVyT3V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1Nob3dpbmdJbmZvSWNvbikge1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5vcGFjaXR5ID0gXCIwLjZcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTGlicmFyeUluZm9JY29uLnByb3RvdHlwZS5vbkNsaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1Nob3dpbmdJbmZvSWNvbikge1xuICAgICAgICAgICAgdGhpcy5pc1Nob3dpbmdJbmZvSWNvbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5vblRhcEluKCk7XG4gICAgICAgICAgICB0aGlzLmluZm9JY29uLnNyYyA9IEFTU0VUX0NMT1NFX0lDT05fMTZQWDtcbiAgICAgICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUub3BhY2l0eSA9IFwiMVwiO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pc1Nob3dpbmdJbmZvSWNvbiA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLm9uVGFwT3V0KCk7XG4gICAgICAgICAgICB0aGlzLmluZm9JY29uLnNyYyA9IEFTU0VUX0lORk9fSUNPTl8xNlBYO1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5vcGFjaXR5ID0gXCIwLjZcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIExpYnJhcnlJbmZvSWNvbjtcbn0oKSk7XG52YXIgTGlicmFyeUluZm9Db250YWluZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExpYnJhcnlJbmZvQ29udGFpbmVyKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmluZm9EaXYgPSBuZXcgTGlicmFyeUluZm9EaXYoKTtcbiAgICAgICAgdGhpcy5pbmZvSWNvbiA9IG5ldyBMaWJyYXJ5SW5mb0ljb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuaW5mb0Rpdi5zaG93KCk7XG4gICAgICAgIH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmluZm9EaXYuaGlkZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgTGlicmFyeUluZm9Db250YWluZXIucHJvdG90eXBlLnJlbmRlckludG8gPSBmdW5jdGlvbiAocGFyZW50KSB7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5yZW5kZXJJbnRvKHBhcmVudCk7XG4gICAgICAgIHRoaXMuaW5mb0ljb24ucmVuZGVySW50byhwYXJlbnQpO1xuICAgIH07XG4gICAgcmV0dXJuIExpYnJhcnlJbmZvQ29udGFpbmVyO1xufSgpKTtcbmV4cG9ydCB7IExpYnJhcnlJbmZvQ29udGFpbmVyIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD11aS5qcy5tYXAiLCJ2YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG52YXIgQ2FtZXJhUGVybWlzc2lvbnMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVBlcm1pc3Npb25zKCkge1xuICAgIH1cbiAgICBDYW1lcmFQZXJtaXNzaW9ucy5oYXNQZXJtaXNzaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGRldmljZXMsIF9pLCBkZXZpY2VzXzEsIGRldmljZTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDogcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZXMgPSBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKF9pID0gMCwgZGV2aWNlc18xID0gZGV2aWNlczsgX2kgPCBkZXZpY2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2aWNlID0gZGV2aWNlc18xW19pXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGV2aWNlLmtpbmQgPT09IFwidmlkZW9pbnB1dFwiICYmIGRldmljZS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIHRydWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgZmFsc2VdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFQZXJtaXNzaW9ucztcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFQZXJtaXNzaW9ucyB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGVybWlzc2lvbnMuanMubWFwIiwiaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FuVHlwZSwgSHRtbDVRcmNvZGVDb25zdGFudHMgfSBmcm9tIFwiLi4vLi4vY29yZVwiO1xudmFyIFNjYW5UeXBlU2VsZWN0b3IgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNjYW5UeXBlU2VsZWN0b3Ioc3VwcG9ydGVkU2NhblR5cGVzKSB7XG4gICAgICAgIHRoaXMuc3VwcG9ydGVkU2NhblR5cGVzID0gdGhpcy52YWxpZGF0ZUFuZFJldHVyblNjYW5UeXBlcyhzdXBwb3J0ZWRTY2FuVHlwZXMpO1xuICAgIH1cbiAgICBTY2FuVHlwZVNlbGVjdG9yLnByb3RvdHlwZS5nZXREZWZhdWx0U2NhblR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1cHBvcnRlZFNjYW5UeXBlc1swXTtcbiAgICB9O1xuICAgIFNjYW5UeXBlU2VsZWN0b3IucHJvdG90eXBlLmhhc01vcmVUaGFuT25lU2NhblR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1cHBvcnRlZFNjYW5UeXBlcy5sZW5ndGggPiAxO1xuICAgIH07XG4gICAgU2NhblR5cGVTZWxlY3Rvci5wcm90b3R5cGUuaXNDYW1lcmFTY2FuUmVxdWlyZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnN1cHBvcnRlZFNjYW5UeXBlczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzY2FuVHlwZSA9IF9hW19pXTtcbiAgICAgICAgICAgIGlmIChTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUoc2NhblR5cGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlID0gZnVuY3Rpb24gKHNjYW5UeXBlKSB7XG4gICAgICAgIHJldHVybiBzY2FuVHlwZSA9PT0gSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfQ0FNRVJBO1xuICAgIH07XG4gICAgU2NhblR5cGVTZWxlY3Rvci5pc0ZpbGVTY2FuVHlwZSA9IGZ1bmN0aW9uIChzY2FuVHlwZSkge1xuICAgICAgICByZXR1cm4gc2NhblR5cGUgPT09IEh0bWw1UXJjb2RlU2NhblR5cGUuU0NBTl9UWVBFX0ZJTEU7XG4gICAgfTtcbiAgICBTY2FuVHlwZVNlbGVjdG9yLnByb3RvdHlwZS52YWxpZGF0ZUFuZFJldHVyblNjYW5UeXBlcyA9IGZ1bmN0aW9uIChzdXBwb3J0ZWRTY2FuVHlwZXMpIHtcbiAgICAgICAgaWYgKCFzdXBwb3J0ZWRTY2FuVHlwZXMgfHwgc3VwcG9ydGVkU2NhblR5cGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWF4RXhwZWN0ZWRWYWx1ZXMgPSBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEUubGVuZ3RoO1xuICAgICAgICBpZiAoc3VwcG9ydGVkU2NhblR5cGVzLmxlbmd0aCA+IG1heEV4cGVjdGVkVmFsdWVzKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk1heCBcIi5jb25jYXQobWF4RXhwZWN0ZWRWYWx1ZXMsIFwiIHZhbHVlcyBleHBlY3RlZCBmb3IgXCIpXG4gICAgICAgICAgICAgICAgKyBcInN1cHBvcnRlZFNjYW5UeXBlc1wiO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc3VwcG9ydGVkU2NhblR5cGVzXzEgPSBzdXBwb3J0ZWRTY2FuVHlwZXM7IF9pIDwgc3VwcG9ydGVkU2NhblR5cGVzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2NhblR5cGUgPSBzdXBwb3J0ZWRTY2FuVHlwZXNfMVtfaV07XG4gICAgICAgICAgICBpZiAoIUh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRVxuICAgICAgICAgICAgICAgIC5pbmNsdWRlcyhzY2FuVHlwZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIlVuc3VwcG9ydGVkIHNjYW4gdHlwZSBcIi5jb25jYXQoc2NhblR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdXBwb3J0ZWRTY2FuVHlwZXM7XG4gICAgfTtcbiAgICByZXR1cm4gU2NhblR5cGVTZWxlY3Rvcjtcbn0oKSk7XG5leHBvcnQgeyBTY2FuVHlwZVNlbGVjdG9yIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zY2FuLXR5cGUtc2VsZWN0b3IuanMubWFwIiwidmFyIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzKCkge1xuICAgIH1cbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQUxMX0VMRU1FTlRfQ0xBU1MgPSBcImh0bWw1LXFyY29kZS1lbGVtZW50XCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9QRVJNSVNTSU9OX0JVVFRPTl9JRCA9IFwiaHRtbDUtcXJjb2RlLWJ1dHRvbi1jYW1lcmEtcGVybWlzc2lvblwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU1RBUlRfQlVUVE9OX0lEID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLWNhbWVyYS1zdGFydFwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU1RPUF9CVVRUT05fSUQgPSBcImh0bWw1LXFyY29kZS1idXR0b24tY2FtZXJhLXN0b3BcIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0lEID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLXRvcmNoXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TRUxFQ1RJT05fU0VMRUNUX0lEID0gXCJodG1sNS1xcmNvZGUtc2VsZWN0LWNhbWVyYVwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5GSUxFX1NFTEVDVElPTl9CVVRUT05fSUQgPSBcImh0bWw1LXFyY29kZS1idXR0b24tZmlsZS1zZWxlY3Rpb25cIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuWk9PTV9TTElERVJfSUQgPSBcImh0bWw1LXFyY29kZS1pbnB1dC1yYW5nZS16b29tXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlNDQU5fVFlQRV9DSEFOR0VfQU5DSE9SX0lEID0gXCJodG1sNS1xcmNvZGUtYW5jaG9yLXNjYW4tdHlwZS1jaGFuZ2VcIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0NMQVNTX1RPUkNIX09OID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLXRvcmNoLW9uXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PRkYgPSBcImh0bWw1LXFyY29kZS1idXR0b24tdG9yY2gtb2ZmXCI7XG4gICAgcmV0dXJuIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcztcbn0oKSk7XG5leHBvcnQgeyBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfTtcbnZhciBCYXNlVWlFbGVtZW50RmFjdG9yeSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQmFzZVVpRWxlbWVudEZhY3RvcnkoKSB7XG4gICAgfVxuICAgIEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiAoZWxlbWVudFR5cGUsIGVsZW1lbnRJZCkge1xuICAgICAgICB2YXIgZWxlbWVudCA9IChkb2N1bWVudC5jcmVhdGVFbGVtZW50KGVsZW1lbnRUeXBlKSk7XG4gICAgICAgIGVsZW1lbnQuaWQgPSBlbGVtZW50SWQ7XG4gICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZChQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQUxMX0VMRU1FTlRfQ0xBU1MpO1xuICAgICAgICBpZiAoZWxlbWVudFR5cGUgPT09IFwiYnV0dG9uXCIpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKFwidHlwZVwiLCBcImJ1dHRvblwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9O1xuICAgIHJldHVybiBCYXNlVWlFbGVtZW50RmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9YmFzZS5qcy5tYXAiLCJ2YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG5pbXBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH0gZnJvbSBcIi4uLy4uL3N0cmluZ3NcIjtcbmltcG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5LCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfSBmcm9tIFwiLi9iYXNlXCI7XG52YXIgVG9yY2hDb250cm9sbGVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUb3JjaENvbnRyb2xsZXIodG9yY2hDYXBhYmlsaXR5LCBidXR0b25Db250cm9sbGVyLCBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuaXNUb3JjaE9uID0gZmFsc2U7XG4gICAgICAgIHRoaXMudG9yY2hDYXBhYmlsaXR5ID0gdG9yY2hDYXBhYmlsaXR5O1xuICAgICAgICB0aGlzLmJ1dHRvbkNvbnRyb2xsZXIgPSBidXR0b25Db250cm9sbGVyO1xuICAgICAgICB0aGlzLm9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2sgPSBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrO1xuICAgIH1cbiAgICBUb3JjaENvbnRyb2xsZXIucHJvdG90eXBlLmlzVG9yY2hFbmFibGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1RvcmNoT247XG4gICAgfTtcbiAgICBUb3JjaENvbnRyb2xsZXIucHJvdG90eXBlLmZsaXBTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGlzVG9yY2hPbkV4cGVjdGVkLCBlcnJvcl8xO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyLmRpc2FibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzVG9yY2hPbkV4cGVjdGVkID0gIXRoaXMuaXNUb3JjaE9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgX2EubGFiZWwgPSAxO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS50cnlzLnB1c2goWzEsIDMsICwgNF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCB0aGlzLnRvcmNoQ2FwYWJpbGl0eS5hcHBseShpc1RvcmNoT25FeHBlY3RlZCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVVpQmFzZWRPbkxhdGVzdFNldHRpbmdzKHRoaXMudG9yY2hDYXBhYmlsaXR5LnZhbHVlKCksIGlzVG9yY2hPbkV4cGVjdGVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMywgNF07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yXzEgPSBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb3BhZ2F0ZUZhaWx1cmUoaXNUb3JjaE9uRXhwZWN0ZWQsIGVycm9yXzEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyLmVuYWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFszLCA0XTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OiByZXR1cm4gWzJdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFRvcmNoQ29udHJvbGxlci5wcm90b3R5cGUudXBkYXRlVWlCYXNlZE9uTGF0ZXN0U2V0dGluZ3MgPSBmdW5jdGlvbiAoaXNUb3JjaE9uLCBpc1RvcmNoT25FeHBlY3RlZCkge1xuICAgICAgICBpZiAoaXNUb3JjaE9uID09PSBpc1RvcmNoT25FeHBlY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyLnNldFRleHQoaXNUb3JjaE9uRXhwZWN0ZWRcbiAgICAgICAgICAgICAgICA/IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPZmZCdXR0b24oKVxuICAgICAgICAgICAgICAgIDogSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9uQnV0dG9uKCkpO1xuICAgICAgICAgICAgdGhpcy5pc1RvcmNoT24gPSBpc1RvcmNoT25FeHBlY3RlZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucHJvcGFnYXRlRmFpbHVyZShpc1RvcmNoT25FeHBlY3RlZCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyLmVuYWJsZSgpO1xuICAgIH07XG4gICAgVG9yY2hDb250cm9sbGVyLnByb3RvdHlwZS5wcm9wYWdhdGVGYWlsdXJlID0gZnVuY3Rpb24gKGlzVG9yY2hPbkV4cGVjdGVkLCBlcnJvcikge1xuICAgICAgICB2YXIgZXJyb3JNZXNzYWdlID0gaXNUb3JjaE9uRXhwZWN0ZWRcbiAgICAgICAgICAgID8gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9uRmFpbGVkTWVzc2FnZSgpXG4gICAgICAgICAgICA6IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPZmZGYWlsZWRNZXNzYWdlKCk7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgZXJyb3JNZXNzYWdlICs9IFwiOyBFcnJvciA9IFwiICsgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKGVycm9yTWVzc2FnZSk7XG4gICAgfTtcbiAgICBUb3JjaENvbnRyb2xsZXIucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmlzVG9yY2hPbiA9IGZhbHNlO1xuICAgIH07XG4gICAgcmV0dXJuIFRvcmNoQ29udHJvbGxlcjtcbn0oKSk7XG52YXIgVG9yY2hCdXR0b24gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFRvcmNoQnV0dG9uKHRvcmNoQ2FwYWJpbGl0eSwgb25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgICB0aGlzLm9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2sgPSBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrO1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uXG4gICAgICAgICAgICA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9JRCk7XG4gICAgICAgIHRoaXMudG9yY2hDb250cm9sbGVyID0gbmV3IFRvcmNoQ29udHJvbGxlcih0b3JjaENhcGFiaWxpdHksIHRoaXMsIG9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2spO1xuICAgIH1cbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIHRvcmNoQnV0dG9uT3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT25CdXR0b24oKTtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gdG9yY2hCdXR0b25PcHRpb25zLmRpc3BsYXk7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uc3R5bGUubWFyZ2luTGVmdCA9IHRvcmNoQnV0dG9uT3B0aW9ucy5tYXJnaW5MZWZ0O1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoXykgeyByZXR1cm4gX19hd2FpdGVyKF90aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gWzQsICR0aGlzLnRvcmNoQ29udHJvbGxlci5mbGlwU3RhdGUoKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkdGhpcy50b3JjaENvbnRyb2xsZXIuaXNUb3JjaEVuYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLnRvcmNoQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PRkYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLnRvcmNoQnV0dG9uLmNsYXNzTGlzdC5hZGQoUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PTik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy50b3JjaEJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fQ0xBU1NfVE9SQ0hfT04pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLnRvcmNoQnV0dG9uLmNsYXNzTGlzdC5hZGQoUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PRkYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7IH0pO1xuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudG9yY2hCdXR0b24pO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLnVwZGF0ZVRvcmNoQ2FwYWJpbGl0eSA9IGZ1bmN0aW9uICh0b3JjaENhcGFiaWxpdHkpIHtcbiAgICAgICAgdGhpcy50b3JjaENvbnRyb2xsZXIgPSBuZXcgVG9yY2hDb250cm9sbGVyKHRvcmNoQ2FwYWJpbGl0eSwgdGhpcywgdGhpcy5vblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKTtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5nZXRUb3JjaEJ1dHRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9yY2hCdXR0b247XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUuc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5lbmFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5zZXRUZXh0ID0gZnVuY3Rpb24gKHRleHQpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5pbm5lclRleHQgPSB0ZXh0O1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmlubmVyVGV4dCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPbkJ1dHRvbigpO1xuICAgICAgICB0aGlzLnRvcmNoQ29udHJvbGxlci5yZXNldCgpO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24uY3JlYXRlID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIHRvcmNoQ2FwYWJpbGl0eSwgdG9yY2hCdXR0b25PcHRpb25zLCBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBidXR0b24gPSBuZXcgVG9yY2hCdXR0b24odG9yY2hDYXBhYmlsaXR5LCBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKTtcbiAgICAgICAgYnV0dG9uLnJlbmRlcihwYXJlbnRFbGVtZW50LCB0b3JjaEJ1dHRvbk9wdGlvbnMpO1xuICAgICAgICByZXR1cm4gYnV0dG9uO1xuICAgIH07XG4gICAgcmV0dXJuIFRvcmNoQnV0dG9uO1xufSgpKTtcbmV4cG9ydCB7IFRvcmNoQnV0dG9uIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD10b3JjaC1idXR0b24uanMubWFwIiwiaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncyB9IGZyb20gXCIuLi8uLi9zdHJpbmdzXCI7XG5pbXBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzIH0gZnJvbSBcIi4vYmFzZVwiO1xudmFyIEZpbGVTZWxlY3Rpb25VaSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRmlsZVNlbGVjdGlvblVpKHBhcmVudEVsZW1lbnQsIHNob3dPblJlbmRlciwgb25GaWxlU2VsZWN0ZWQpIHtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uID0gdGhpcy5jcmVhdGVGaWxlQmFzZWRTY2FuUmVnaW9uKCk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5kaXNwbGF5XG4gICAgICAgICAgICA9IHNob3dPblJlbmRlciA/IFwiYmxvY2tcIiA6IFwibm9uZVwiO1xuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbik7XG4gICAgICAgIHZhciBmaWxlU2NhbkxhYmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImxhYmVsXCIpO1xuICAgICAgICBmaWxlU2NhbkxhYmVsLnNldEF0dHJpYnV0ZShcImZvclwiLCB0aGlzLmdldEZpbGVTY2FuSW5wdXRJZCgpKTtcbiAgICAgICAgZmlsZVNjYW5MYWJlbC5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFwcGVuZENoaWxkKGZpbGVTY2FuTGFiZWwpO1xuICAgICAgICB0aGlzLmZpbGVTZWxlY3Rpb25CdXR0b25cbiAgICAgICAgICAgID0gQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiLCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuRklMRV9TRUxFQ1RJT05fQlVUVE9OX0lEKTtcbiAgICAgICAgdGhpcy5zZXRJbml0aWFsVmFsdWVUb0J1dHRvbigpO1xuICAgICAgICB0aGlzLmZpbGVTZWxlY3Rpb25CdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICBmaWxlU2NhbkxhYmVsLmNsaWNrKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBmaWxlU2NhbkxhYmVsLmFwcGVuZCh0aGlzLmZpbGVTZWxlY3Rpb25CdXR0b24pO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXRcbiAgICAgICAgICAgID0gQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudChcImlucHV0XCIsIHRoaXMuZ2V0RmlsZVNjYW5JbnB1dElkKCkpO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQudHlwZSA9IFwiZmlsZVwiO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQuYWNjZXB0ID0gXCJpbWFnZS8qXCI7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbnB1dC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgIGZpbGVTY2FuTGFiZWwuYXBwZW5kQ2hpbGQodGhpcy5maWxlU2NhbklucHV0KTtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmIChlID09IG51bGwgfHwgZS50YXJnZXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSBlLnRhcmdldDtcbiAgICAgICAgICAgIGlmICh0YXJnZXQuZmlsZXMgJiYgdGFyZ2V0LmZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBmaWxlTGlzdCA9IHRhcmdldC5maWxlcztcbiAgICAgICAgICAgIHZhciBmaWxlID0gZmlsZUxpc3RbMF07XG4gICAgICAgICAgICB2YXIgZmlsZU5hbWUgPSBmaWxlLm5hbWU7XG4gICAgICAgICAgICAkdGhpcy5zZXRJbWFnZU5hbWVUb0J1dHRvbihmaWxlTmFtZSk7XG4gICAgICAgICAgICBvbkZpbGVTZWxlY3RlZChmaWxlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBkcmFnQW5kRHJvcE1lc3NhZ2UgPSB0aGlzLmNyZWF0ZURyYWdBbmREcm9wTWVzc2FnZSgpO1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uYXBwZW5kQ2hpbGQoZHJhZ0FuZERyb3BNZXNzYWdlKTtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJkcmFnZW50ZXJcIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAkdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmJvcmRlclxuICAgICAgICAgICAgICAgID0gJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbkFjdGl2ZUJvcmRlcigpO1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJkcmFnbGVhdmVcIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAkdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmJvcmRlclxuICAgICAgICAgICAgICAgID0gJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbkRlZmF1bHRCb3JkZXIoKTtcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZHJhZ292ZXJcIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAkdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmJvcmRlclxuICAgICAgICAgICAgICAgID0gJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbkFjdGl2ZUJvcmRlcigpO1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJkcm9wXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgICAgICA9ICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25EZWZhdWx0Qm9yZGVyKCk7XG4gICAgICAgICAgICB2YXIgZGF0YVRyYW5zZmVyID0gZXZlbnQuZGF0YVRyYW5zZmVyO1xuICAgICAgICAgICAgaWYgKGRhdGFUcmFuc2Zlcikge1xuICAgICAgICAgICAgICAgIHZhciBmaWxlcyA9IGRhdGFUcmFuc2Zlci5maWxlcztcbiAgICAgICAgICAgICAgICBpZiAoIWZpbGVzIHx8IGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBpc0FueUZpbGVJbWFnZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZpbGUgPSBmaWxlcy5pdGVtKGkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWZpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbWFnZVR5cGUgPSAvaW1hZ2UuKi87XG4gICAgICAgICAgICAgICAgICAgIGlmICghZmlsZS50eXBlLm1hdGNoKGltYWdlVHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlzQW55RmlsZUltYWdlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZpbGVOYW1lID0gZmlsZS5uYW1lO1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5zZXRJbWFnZU5hbWVUb0J1dHRvbihmaWxlTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIG9uRmlsZVNlbGVjdGVkKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICBkcmFnQW5kRHJvcE1lc3NhZ2UuaW5uZXJUZXh0XG4gICAgICAgICAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZHJhZ0FuZERyb3BNZXNzYWdlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWlzQW55RmlsZUltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIGRyYWdBbmREcm9wTWVzc2FnZS5pbm5lclRleHRcbiAgICAgICAgICAgICAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5nc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kcmFnQW5kRHJvcE1lc3NhZ2VPbmx5SW1hZ2VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQuZGlzYWJsZWQgPSB0cnVlO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LmRpc2FibGVkID0gZmFsc2U7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmlzU2hvd2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5kaXNwbGF5ID09PSBcImJsb2NrXCI7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLnJlc2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbnB1dC52YWx1ZSA9IFwiXCI7XG4gICAgICAgIHRoaXMuc2V0SW5pdGlhbFZhbHVlVG9CdXR0b24oKTtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuY3JlYXRlRmlsZUJhc2VkU2NhblJlZ2lvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZpbGVCYXNlZFNjYW5SZWdpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIGZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUubWFyZ2luID0gXCJhdXRvXCI7XG4gICAgICAgIGZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUud2lkdGggPSBcIjgwJVwiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLm1heFdpZHRoID0gXCI2MDBweFwiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmJvcmRlclxuICAgICAgICAgICAgPSB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25EZWZhdWx0Qm9yZGVyKCk7XG4gICAgICAgIGZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUucGFkZGluZyA9IFwiMTBweFwiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLm1hcmdpbkJvdHRvbSA9IFwiMTBweFwiO1xuICAgICAgICByZXR1cm4gZmlsZUJhc2VkU2NhblJlZ2lvbjtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuZmlsZUJhc2VkU2NhblJlZ2lvbkRlZmF1bHRCb3JkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIjZweCBkYXNoZWQgI2ViZWJlYlwiO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5maWxlQmFzZWRTY2FuUmVnaW9uQWN0aXZlQm9yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCI2cHggZGFzaGVkIHJnYigxNTMgMTUxIDE1MSlcIjtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuY3JlYXRlRHJhZ0FuZERyb3BNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZHJhZ0FuZERyb3BNZXNzYWdlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZHJhZ0FuZERyb3BNZXNzYWdlLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmRyYWdBbmREcm9wTWVzc2FnZSgpO1xuICAgICAgICBkcmFnQW5kRHJvcE1lc3NhZ2Uuc3R5bGUuZm9udFdlaWdodCA9IFwiNDAwXCI7XG4gICAgICAgIHJldHVybiBkcmFnQW5kRHJvcE1lc3NhZ2U7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLnNldEltYWdlTmFtZVRvQnV0dG9uID0gZnVuY3Rpb24gKGltYWdlRmlsZU5hbWUpIHtcbiAgICAgICAgdmFyIE1BWF9DSEFSUyA9IDIwO1xuICAgICAgICBpZiAoaW1hZ2VGaWxlTmFtZS5sZW5ndGggPiBNQVhfQ0hBUlMpIHtcbiAgICAgICAgICAgIHZhciBzdGFydDhDaGFycyA9IGltYWdlRmlsZU5hbWUuc3Vic3RyaW5nKDAsIDgpO1xuICAgICAgICAgICAgdmFyIGxlbmd0aF8xID0gaW1hZ2VGaWxlTmFtZS5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgbGFzdDhDaGFycyA9IGltYWdlRmlsZU5hbWUuc3Vic3RyaW5nKGxlbmd0aF8xIC0gOCwgbGVuZ3RoXzEpO1xuICAgICAgICAgICAgaW1hZ2VGaWxlTmFtZSA9IFwiXCIuY29uY2F0KHN0YXJ0OENoYXJzLCBcIi4uLi5cIikuY29uY2F0KGxhc3Q4Q2hhcnMpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuZXdUZXh0ID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uQ2hvb3NlQW5vdGhlcigpXG4gICAgICAgICAgICArIFwiIC0gXCJcbiAgICAgICAgICAgICsgaW1hZ2VGaWxlTmFtZTtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uQnV0dG9uLmlubmVyVGV4dCA9IG5ld1RleHQ7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLnNldEluaXRpYWxWYWx1ZVRvQnV0dG9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5pdGlhbFRleHQgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTZWxlY3Rpb25DaG9vc2VJbWFnZSgpXG4gICAgICAgICAgICArIFwiIC0gXCJcbiAgICAgICAgICAgICsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uTm9JbWFnZVNlbGVjdGVkKCk7XG4gICAgICAgIHRoaXMuZmlsZVNlbGVjdGlvbkJ1dHRvbi5pbm5lclRleHQgPSBpbml0aWFsVGV4dDtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuZ2V0RmlsZVNjYW5JbnB1dElkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJodG1sNS1xcmNvZGUtcHJpdmF0ZS1maWxlc2Nhbi1pbnB1dFwiO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLmNyZWF0ZSA9IGZ1bmN0aW9uIChwYXJlbnRFbGVtZW50LCBzaG93T25SZW5kZXIsIG9uRmlsZVNlbGVjdGVkKSB7XG4gICAgICAgIHZhciBidXR0b24gPSBuZXcgRmlsZVNlbGVjdGlvblVpKHBhcmVudEVsZW1lbnQsIHNob3dPblJlbmRlciwgb25GaWxlU2VsZWN0ZWQpO1xuICAgICAgICByZXR1cm4gYnV0dG9uO1xuICAgIH07XG4gICAgcmV0dXJuIEZpbGVTZWxlY3Rpb25VaTtcbn0oKSk7XG5leHBvcnQgeyBGaWxlU2VsZWN0aW9uVWkgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWZpbGUtc2VsZWN0aW9uLXVpLmpzLm1hcCIsImltcG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5LCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfSBmcm9tIFwiLi9iYXNlXCI7XG5pbXBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH0gZnJvbSBcIi4uLy4uL3N0cmluZ3NcIjtcbnZhciBDYW1lcmFTZWxlY3Rpb25VaSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ2FtZXJhU2VsZWN0aW9uVWkoY2FtZXJhcykge1xuICAgICAgICB0aGlzLnNlbGVjdEVsZW1lbnQgPSBCYXNlVWlFbGVtZW50RmFjdG9yeVxuICAgICAgICAgICAgLmNyZWF0ZUVsZW1lbnQoXCJzZWxlY3RcIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TRUxFQ1RJT05fU0VMRUNUX0lEKTtcbiAgICAgICAgdGhpcy5jYW1lcmFzID0gY2FtZXJhcztcbiAgICAgICAgdGhpcy5vcHRpb25zID0gW107XG4gICAgfVxuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCkge1xuICAgICAgICB2YXIgY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIGNhbWVyYVNlbGVjdGlvbkNvbnRhaW5lci5zdHlsZS5tYXJnaW5SaWdodCA9IFwiMTBweFwiO1xuICAgICAgICB2YXIgbnVtQ2FtZXJhcyA9IHRoaXMuY2FtZXJhcy5sZW5ndGg7XG4gICAgICAgIGlmIChudW1DYW1lcmFzID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBjYW1lcmFzIGZvdW5kXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChudW1DYW1lcmFzID09PSAxKSB7XG4gICAgICAgICAgICBjYW1lcmFTZWxlY3Rpb25Db250YWluZXIuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIHNlbGVjdENhbWVyYVN0cmluZyA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2VsZWN0Q2FtZXJhKCk7XG4gICAgICAgICAgICBjYW1lcmFTZWxlY3Rpb25Db250YWluZXIuaW5uZXJUZXh0XG4gICAgICAgICAgICAgICAgPSBcIlwiLmNvbmNhdChzZWxlY3RDYW1lcmFTdHJpbmcsIFwiIChcIikuY29uY2F0KHRoaXMuY2FtZXJhcy5sZW5ndGgsIFwiKSAgXCIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhbm9ueW1vdXNDYW1lcmFJZCA9IDE7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmNhbWVyYXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2FtZXJhID0gX2FbX2ldO1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gY2FtZXJhLmlkO1xuICAgICAgICAgICAgdmFyIG5hbWVfMSA9IGNhbWVyYS5sYWJlbCA9PSBudWxsID8gdmFsdWUgOiBjYW1lcmEubGFiZWw7XG4gICAgICAgICAgICBpZiAoIW5hbWVfMSB8fCBuYW1lXzEgPT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICBuYW1lXzEgPSBbXG4gICAgICAgICAgICAgICAgICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuYW5vbnltb3VzQ2FtZXJhUHJlZml4KCksXG4gICAgICAgICAgICAgICAgICAgIGFub255bW91c0NhbWVyYUlkKytcbiAgICAgICAgICAgICAgICBdLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgICAgICBvcHRpb24udmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIG9wdGlvbi5pbm5lclRleHQgPSBuYW1lXzE7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMucHVzaChvcHRpb24pO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50LmFwcGVuZENoaWxkKG9wdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuc2VsZWN0RWxlbWVudCk7XG4gICAgICAgIHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyKTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNlbGVjdEVsZW1lbnQuZGlzYWJsZWQgPSB0cnVlO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLmlzRGlzYWJsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdEVsZW1lbnQuZGlzYWJsZWQgPT09IHRydWU7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNlbGVjdEVsZW1lbnQuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0RWxlbWVudC52YWx1ZTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5oYXNWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5vcHRpb25zOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIG9wdGlvbiA9IF9hW19pXTtcbiAgICAgICAgICAgIGlmIChvcHRpb24udmFsdWUgPT09IHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICghdGhpcy5oYXNWYWx1ZSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlwiLmNvbmNhdCh2YWx1ZSwgXCIgaXMgbm90IHByZXNlbnQgaW4gdGhlIGNhbWVyYSBsaXN0LlwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50LnZhbHVlID0gdmFsdWU7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuaGFzU2luZ2xlSXRlbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FtZXJhcy5sZW5ndGggPT09IDE7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUubnVtQ2FtZXJhcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FtZXJhcy5sZW5ndGg7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgY2FtZXJhcykge1xuICAgICAgICB2YXIgY2FtZXJhU2VsZWN0VWkgPSBuZXcgQ2FtZXJhU2VsZWN0aW9uVWkoY2FtZXJhcyk7XG4gICAgICAgIGNhbWVyYVNlbGVjdFVpLnJlbmRlcihwYXJlbnRFbGVtZW50KTtcbiAgICAgICAgcmV0dXJuIGNhbWVyYVNlbGVjdFVpO1xuICAgIH07XG4gICAgcmV0dXJuIENhbWVyYVNlbGVjdGlvblVpO1xufSgpKTtcbmV4cG9ydCB7IENhbWVyYVNlbGVjdGlvblVpIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jYW1lcmEtc2VsZWN0aW9uLXVpLmpzLm1hcCIsImltcG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5LCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfSBmcm9tIFwiLi9iYXNlXCI7XG5pbXBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH0gZnJvbSBcIi4uLy4uL3N0cmluZ3NcIjtcbnZhciBDYW1lcmFab29tVWkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVpvb21VaSgpIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZUNhbGxiYWNrID0gbnVsbDtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dCA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiLCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuWk9PTV9TTElERVJfSUQpO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQudHlwZSA9IFwicmFuZ2VcIjtcbiAgICAgICAgdGhpcy5yYW5nZVRleHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0Lm1pbiA9IFwiMVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQubWF4ID0gXCI1XCI7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC52YWx1ZSA9IFwiMVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3RlcCA9IFwiMC4xXCI7XG4gICAgfVxuICAgIENhbWVyYVpvb21VaS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIHJlbmRlck9uQ3JlYXRlKSB7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUuZGlzcGxheVxuICAgICAgICAgICAgPSByZW5kZXJPbkNyZWF0ZSA/IFwiYmxvY2tcIiA6IFwibm9uZVwiO1xuICAgICAgICB0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyLnN0eWxlLnBhZGRpbmcgPSBcIjVweCAxMHB4XCI7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3R5bGUud2lkdGggPSBcIjUwJVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3R5bGUuaGVpZ2h0ID0gXCI1cHhcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLmJhY2tncm91bmQgPSBcIiNkM2QzZDNcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLm91dGxpbmUgPSBcIm5vbmVcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLm9wYWNpdHkgPSBcIjAuN1wiO1xuICAgICAgICB2YXIgem9vbVN0cmluZyA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muem9vbSgpO1xuICAgICAgICB0aGlzLnJhbmdlVGV4dC5pbm5lclRleHQgPSBcIlwiLmNvbmNhdCh0aGlzLnJhbmdlSW5wdXQudmFsdWUsIFwieCBcIikuY29uY2F0KHpvb21TdHJpbmcpO1xuICAgICAgICB0aGlzLnJhbmdlVGV4dC5zdHlsZS5tYXJnaW5SaWdodCA9IFwiMTBweFwiO1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImlucHV0XCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuICR0aGlzLm9uVmFsdWVDaGFuZ2UoKTsgfSk7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuICR0aGlzLm9uVmFsdWVDaGFuZ2UoKTsgfSk7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5yYW5nZUlucHV0KTtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLnJhbmdlVGV4dCk7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLm9uVmFsdWVDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB6b29tU3RyaW5nID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy56b29tKCk7XG4gICAgICAgIHRoaXMucmFuZ2VUZXh0LmlubmVyVGV4dCA9IFwiXCIuY29uY2F0KHRoaXMucmFuZ2VJbnB1dC52YWx1ZSwgXCJ4IFwiKS5jb25jYXQoem9vbVN0cmluZyk7XG4gICAgICAgIGlmICh0aGlzLm9uQ2hhbmdlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2VDYWxsYmFjayhwYXJzZUZsb2F0KHRoaXMucmFuZ2VJbnB1dC52YWx1ZSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNldFZhbHVlcyA9IGZ1bmN0aW9uIChtaW5WYWx1ZSwgbWF4VmFsdWUsIGRlZmF1bHRWYWx1ZSwgc3RlcCkge1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQubWluID0gbWluVmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0Lm1heCA9IG1heFZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5zdGVwID0gc3RlcC50b1N0cmluZygpO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQudmFsdWUgPSBkZWZhdWx0VmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5vblZhbHVlQ2hhbmdlKCk7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICB9O1xuICAgIENhbWVyYVpvb21VaS5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNldE9uQ2FtZXJhWm9vbVZhbHVlQ2hhbmdlQ2FsbGJhY2sgPSBmdW5jdGlvbiAob25DaGFuZ2VDYWxsYmFjaykge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sgPSBvbkNoYW5nZUNhbGxiYWNrO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLnByb3RvdHlwZS5yZW1vdmVPbkNhbWVyYVpvb21WYWx1ZUNoYW5nZUNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sgPSBudWxsO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLmNyZWF0ZSA9IGZ1bmN0aW9uIChwYXJlbnRFbGVtZW50LCByZW5kZXJPbkNyZWF0ZSkge1xuICAgICAgICB2YXIgY2FtZXJhWm9vbVVpID0gbmV3IENhbWVyYVpvb21VaSgpO1xuICAgICAgICBjYW1lcmFab29tVWkucmVuZGVyKHBhcmVudEVsZW1lbnQsIHJlbmRlck9uQ3JlYXRlKTtcbiAgICAgICAgcmV0dXJuIGNhbWVyYVpvb21VaTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFab29tVWk7XG59KCkpO1xuZXhwb3J0IHsgQ2FtZXJhWm9vbVVpIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jYW1lcmEtem9vbS11aS5qcy5tYXAiLCJpbXBvcnQgeyBIdG1sNVFyY29kZUNvbnN0YW50cywgSHRtbDVRcmNvZGVTY2FuVHlwZSwgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnksIEJhc2VMb2dnZ2VyLCBpc051bGxPclVuZGVmaW5lZCwgY2xpcCwgfSBmcm9tIFwiLi9jb3JlXCI7XG5pbXBvcnQgeyBIdG1sNVFyY29kZSwgfSBmcm9tIFwiLi9odG1sNS1xcmNvZGVcIjtcbmltcG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MsIH0gZnJvbSBcIi4vc3RyaW5nc1wiO1xuaW1wb3J0IHsgQVNTRVRfRklMRV9TQ0FOLCBBU1NFVF9DQU1FUkFfU0NBTiwgfSBmcm9tIFwiLi9pbWFnZS1hc3NldHNcIjtcbmltcG9ydCB7IFBlcnNpc3RlZERhdGFNYW5hZ2VyIH0gZnJvbSBcIi4vc3RvcmFnZVwiO1xuaW1wb3J0IHsgTGlicmFyeUluZm9Db250YWluZXIgfSBmcm9tIFwiLi91aVwiO1xuaW1wb3J0IHsgQ2FtZXJhUGVybWlzc2lvbnMgfSBmcm9tIFwiLi9jYW1lcmEvcGVybWlzc2lvbnNcIjtcbmltcG9ydCB7IFNjYW5UeXBlU2VsZWN0b3IgfSBmcm9tIFwiLi91aS9zY2FubmVyL3NjYW4tdHlwZS1zZWxlY3RvclwiO1xuaW1wb3J0IHsgVG9yY2hCdXR0b24gfSBmcm9tIFwiLi91aS9zY2FubmVyL3RvcmNoLWJ1dHRvblwiO1xuaW1wb3J0IHsgRmlsZVNlbGVjdGlvblVpIH0gZnJvbSBcIi4vdWkvc2Nhbm5lci9maWxlLXNlbGVjdGlvbi11aVwiO1xuaW1wb3J0IHsgQmFzZVVpRWxlbWVudEZhY3RvcnksIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcyB9IGZyb20gXCIuL3VpL3NjYW5uZXIvYmFzZVwiO1xuaW1wb3J0IHsgQ2FtZXJhU2VsZWN0aW9uVWkgfSBmcm9tIFwiLi91aS9zY2FubmVyL2NhbWVyYS1zZWxlY3Rpb24tdWlcIjtcbmltcG9ydCB7IENhbWVyYVpvb21VaSB9IGZyb20gXCIuL3VpL3NjYW5uZXIvY2FtZXJhLXpvb20tdWlcIjtcbnZhciBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXM7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cykge1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbXCJTVEFUVVNfREVGQVVMVFwiXSA9IDBdID0gXCJTVEFUVVNfREVGQVVMVFwiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbXCJTVEFUVVNfU1VDQ0VTU1wiXSA9IDFdID0gXCJTVEFUVVNfU1VDQ0VTU1wiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbXCJTVEFUVVNfV0FSTklOR1wiXSA9IDJdID0gXCJTVEFUVVNfV0FSTklOR1wiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbXCJTVEFUVVNfUkVRVUVTVElOR19QRVJNSVNTSU9OXCJdID0gM10gPSBcIlNUQVRVU19SRVFVRVNUSU5HX1BFUk1JU1NJT05cIjtcbn0pKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cyB8fCAoSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzID0ge30pKTtcbmZ1bmN0aW9uIHRvSHRtbDVRcmNvZGVDYW1lcmFTY2FuQ29uZmlnKGNvbmZpZykge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZwczogY29uZmlnLmZwcyxcbiAgICAgICAgcXJib3g6IGNvbmZpZy5xcmJveCxcbiAgICAgICAgYXNwZWN0UmF0aW86IGNvbmZpZy5hc3BlY3RSYXRpbyxcbiAgICAgICAgZGlzYWJsZUZsaXA6IGNvbmZpZy5kaXNhYmxlRmxpcCxcbiAgICAgICAgdmlkZW9Db25zdHJhaW50czogY29uZmlnLnZpZGVvQ29uc3RyYWludHNcbiAgICB9O1xufVxuZnVuY3Rpb24gdG9IdG1sNVFyY29kZUZ1bGxDb25maWcoY29uZmlnLCB2ZXJib3NlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZm9ybWF0c1RvU3VwcG9ydDogY29uZmlnLmZvcm1hdHNUb1N1cHBvcnQsXG4gICAgICAgIHVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkOiBjb25maWcudXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQsXG4gICAgICAgIGV4cGVyaW1lbnRhbEZlYXR1cmVzOiBjb25maWcuZXhwZXJpbWVudGFsRmVhdHVyZXMsXG4gICAgICAgIHZlcmJvc2U6IHZlcmJvc2VcbiAgICB9O1xufVxudmFyIEh0bWw1UXJjb2RlU2Nhbm5lciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSHRtbDVRcmNvZGVTY2FubmVyKGVsZW1lbnRJZCwgY29uZmlnLCB2ZXJib3NlKSB7XG4gICAgICAgIHRoaXMubGFzdE1hdGNoRm91bmQgPSBudWxsO1xuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZSA9IG51bGw7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZSA9IG51bGw7XG4gICAgICAgIHRoaXMuZmlsZVNlbGVjdGlvblVpID0gbnVsbDtcbiAgICAgICAgdGhpcy5lbGVtZW50SWQgPSBlbGVtZW50SWQ7XG4gICAgICAgIHRoaXMuY29uZmlnID0gdGhpcy5jcmVhdGVDb25maWcoY29uZmlnKTtcbiAgICAgICAgdGhpcy52ZXJib3NlID0gdmVyYm9zZSA9PT0gdHJ1ZTtcbiAgICAgICAgaWYgKCFkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtZW50SWQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkhUTUwgRWxlbWVudCB3aXRoIGlkPVwiLmNvbmNhdChlbGVtZW50SWQsIFwiIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNjYW5UeXBlU2VsZWN0b3IgPSBuZXcgU2NhblR5cGVTZWxlY3Rvcih0aGlzLmNvbmZpZy5zdXBwb3J0ZWRTY2FuVHlwZXMpO1xuICAgICAgICB0aGlzLmN1cnJlbnRTY2FuVHlwZSA9IHRoaXMuc2NhblR5cGVTZWxlY3Rvci5nZXREZWZhdWx0U2NhblR5cGUoKTtcbiAgICAgICAgdGhpcy5zZWN0aW9uU3dhcEFsbG93ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IG5ldyBCYXNlTG9nZ2dlcih0aGlzLnZlcmJvc2UpO1xuICAgICAgICB0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyID0gbmV3IFBlcnNpc3RlZERhdGFNYW5hZ2VyKCk7XG4gICAgICAgIGlmIChjb25maWcucmVtZW1iZXJMYXN0VXNlZENhbWVyYSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5yZXNldCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgcXJDb2RlRXJyb3JDYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmxhc3RNYXRjaEZvdW5kID0gbnVsbDtcbiAgICAgICAgdGhpcy5xckNvZGVTdWNjZXNzQ2FsbGJhY2tcbiAgICAgICAgICAgID0gZnVuY3Rpb24gKGRlY29kZWRUZXh0LCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAocXJDb2RlU3VjY2Vzc0NhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjayhkZWNvZGVkVGV4dCwgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5sYXN0TWF0Y2hGb3VuZCA9PT0gZGVjb2RlZFRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5sYXN0TWF0Y2hGb3VuZCA9IGRlY29kZWRUZXh0O1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRIZWFkZXJNZXNzYWdlKEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MubGFzdE1hdGNoKGRlY29kZWRUZXh0KSwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19TVUNDRVNTKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB0aGlzLnFyQ29kZUVycm9yQ2FsbGJhY2sgPVxuICAgICAgICAgICAgZnVuY3Rpb24gKGVycm9yTWVzc2FnZSwgZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBpZiAocXJDb2RlRXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBxckNvZGVFcnJvckNhbGxiYWNrKGVycm9yTWVzc2FnZSwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIHZhciBjb250YWluZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmVsZW1lbnRJZCk7XG4gICAgICAgIGlmICghY29udGFpbmVyKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkhUTUwgRWxlbWVudCB3aXRoIGlkPVwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCIgbm90IGZvdW5kXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRhaW5lci5pbm5lckhUTUwgPSBcIlwiO1xuICAgICAgICB0aGlzLmNyZWF0ZUJhc2ljTGF5b3V0KGNvbnRhaW5lcik7XG4gICAgICAgIHRoaXMuaHRtbDVRcmNvZGUgPSBuZXcgSHRtbDVRcmNvZGUodGhpcy5nZXRTY2FuUmVnaW9uSWQoKSwgdG9IdG1sNVFyY29kZUZ1bGxDb25maWcodGhpcy5jb25maWcsIHRoaXMudmVyYm9zZSkpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5wYXVzZSA9IGZ1bmN0aW9uIChzaG91bGRQYXVzZVZpZGVvKSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChzaG91bGRQYXVzZVZpZGVvKSB8fCBzaG91bGRQYXVzZVZpZGVvICE9PSB0cnVlKSB7XG4gICAgICAgICAgICBzaG91bGRQYXVzZVZpZGVvID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5nZXRIdG1sNVFyY29kZU9yRmFpbCgpLnBhdXNlKHNob3VsZFBhdXNlVmlkZW8pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5yZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZ2V0SHRtbDVRcmNvZGVPckZhaWwoKS5yZXN1bWUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEh0bWw1UXJjb2RlT3JGYWlsKCkuZ2V0U3RhdGUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlbXB0eUh0bWxDb250YWluZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbWFpbkNvbnRhaW5lciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKF90aGlzLmVsZW1lbnRJZCk7XG4gICAgICAgICAgICBpZiAobWFpbkNvbnRhaW5lcikge1xuICAgICAgICAgICAgICAgIG1haW5Db250YWluZXIuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgICAgICAgICBfdGhpcy5yZXNldEJhc2ljTGF5b3V0KG1haW5Db250YWluZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmh0bWw1UXJjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaHRtbDVRcmNvZGUuaXNTY2FubmluZykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5odG1sNVFyY29kZS5zdG9wKCkudGhlbihmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5odG1sNVFyY29kZS5jbGVhcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZW1wdHlIdG1sQ29udGFpbmVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJVbmFibGUgdG8gc3RvcCBxcmNvZGUgc2Nhbm5lclwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmh0bWw1UXJjb2RlLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgICAgIGVtcHR5SHRtbENvbnRhaW5lcigpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEh0bWw1UXJjb2RlT3JGYWlsKCkuZ2V0UnVubmluZ1RyYWNrQ2FwYWJpbGl0aWVzKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja1NldHRpbmdzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRIdG1sNVFyY29kZU9yRmFpbCgpLmdldFJ1bm5pbmdUcmFja1NldHRpbmdzKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmFwcGx5VmlkZW9Db25zdHJhaW50cyA9IGZ1bmN0aW9uICh2aWRlb0NvbnN0YWludHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SHRtbDVRcmNvZGVPckZhaWwoKS5hcHBseVZpZGVvQ29uc3RyYWludHModmlkZW9Db25zdGFpbnRzKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0SHRtbDVRcmNvZGVPckZhaWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgdGhyb3cgXCJDb2RlIHNjYW5uZXIgbm90IGluaXRpYWxpemVkLlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmh0bWw1UXJjb2RlO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVDb25maWcgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgIGlmIChjb25maWcpIHtcbiAgICAgICAgICAgIGlmICghY29uZmlnLmZwcykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5mcHMgPSBIdG1sNVFyY29kZUNvbnN0YW50cy5TQ0FOX0RFRkFVTFRfRlBTO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbmZpZy5yZW1lbWJlckxhc3RVc2VkQ2FtZXJhICE9PSAoIUh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfUkVNRU1CRVJfTEFTVF9DQU1FUkFfVVNFRCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcucmVtZW1iZXJMYXN0VXNlZENhbWVyYVxuICAgICAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfUkVNRU1CRVJfTEFTVF9DQU1FUkFfVVNFRDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghY29uZmlnLnN1cHBvcnRlZFNjYW5UeXBlcykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5zdXBwb3J0ZWRTY2FuVHlwZXNcbiAgICAgICAgICAgICAgICAgICAgPSBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBmcHM6IEh0bWw1UXJjb2RlQ29uc3RhbnRzLlNDQU5fREVGQVVMVF9GUFMsXG4gICAgICAgICAgICByZW1lbWJlckxhc3RVc2VkQ2FtZXJhOiBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1JFTUVNQkVSX0xBU1RfQ0FNRVJBX1VTRUQsXG4gICAgICAgICAgICBzdXBwb3J0ZWRTY2FuVHlwZXM6IEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRVxuICAgICAgICB9O1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVCYXNpY0xheW91dCA9IGZ1bmN0aW9uIChwYXJlbnQpIHtcbiAgICAgICAgcGFyZW50LnN0eWxlLnBvc2l0aW9uID0gXCJyZWxhdGl2ZVwiO1xuICAgICAgICBwYXJlbnQuc3R5bGUucGFkZGluZyA9IFwiMHB4XCI7XG4gICAgICAgIHBhcmVudC5zdHlsZS5ib3JkZXIgPSBcIjFweCBzb2xpZCBzaWx2ZXJcIjtcbiAgICAgICAgdGhpcy5jcmVhdGVIZWFkZXIocGFyZW50KTtcbiAgICAgICAgdmFyIHFyQ29kZVNjYW5SZWdpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICB2YXIgc2NhblJlZ2lvbklkID0gdGhpcy5nZXRTY2FuUmVnaW9uSWQoKTtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5pZCA9IHNjYW5SZWdpb25JZDtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5zdHlsZS53aWR0aCA9IFwiMTAwJVwiO1xuICAgICAgICBxckNvZGVTY2FuUmVnaW9uLnN0eWxlLm1pbkhlaWdodCA9IFwiMTAwcHhcIjtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICBwYXJlbnQuYXBwZW5kQ2hpbGQocXJDb2RlU2NhblJlZ2lvbik7XG4gICAgICAgIGlmIChTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUodGhpcy5jdXJyZW50U2NhblR5cGUpKSB7XG4gICAgICAgICAgICB0aGlzLmluc2VydENhbWVyYVNjYW5JbWFnZVRvU2NhblJlZ2lvbigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRGaWxlU2NhbkltYWdlVG9TY2FuUmVnaW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHFyQ29kZURhc2hib2FyZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHZhciBkYXNoYm9hcmRJZCA9IHRoaXMuZ2V0RGFzaGJvYXJkSWQoKTtcbiAgICAgICAgcXJDb2RlRGFzaGJvYXJkLmlkID0gZGFzaGJvYXJkSWQ7XG4gICAgICAgIHFyQ29kZURhc2hib2FyZC5zdHlsZS53aWR0aCA9IFwiMTAwJVwiO1xuICAgICAgICBwYXJlbnQuYXBwZW5kQ2hpbGQocXJDb2RlRGFzaGJvYXJkKTtcbiAgICAgICAgdGhpcy5zZXR1cEluaXRpYWxEYXNoYm9hcmQocXJDb2RlRGFzaGJvYXJkKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVzZXRCYXNpY0xheW91dCA9IGZ1bmN0aW9uIChtYWluQ29udGFpbmVyKSB7XG4gICAgICAgIG1haW5Db250YWluZXIuc3R5bGUuYm9yZGVyID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnNldHVwSW5pdGlhbERhc2hib2FyZCA9IGZ1bmN0aW9uIChkYXNoYm9hcmQpIHtcbiAgICAgICAgdGhpcy5jcmVhdGVTZWN0aW9uKGRhc2hib2FyZCk7XG4gICAgICAgIHRoaXMuY3JlYXRlU2VjdGlvbkNvbnRyb2xQYW5lbCgpO1xuICAgICAgICBpZiAodGhpcy5zY2FuVHlwZVNlbGVjdG9yLmhhc01vcmVUaGFuT25lU2NhblR5cGUoKSkge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVTZWN0aW9uU3dhcCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZUhlYWRlciA9IGZ1bmN0aW9uIChkYXNoYm9hcmQpIHtcbiAgICAgICAgdmFyIGhlYWRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIGhlYWRlci5zdHlsZS50ZXh0QWxpZ24gPSBcImxlZnRcIjtcbiAgICAgICAgaGVhZGVyLnN0eWxlLm1hcmdpbiA9IFwiMHB4XCI7XG4gICAgICAgIGRhc2hib2FyZC5hcHBlbmRDaGlsZChoZWFkZXIpO1xuICAgICAgICB2YXIgbGlicmFyeUluZm8gPSBuZXcgTGlicmFyeUluZm9Db250YWluZXIoKTtcbiAgICAgICAgbGlicmFyeUluZm8ucmVuZGVySW50byhoZWFkZXIpO1xuICAgICAgICB2YXIgaGVhZGVyTWVzc2FnZUNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuaWQgPSB0aGlzLmdldEhlYWRlck1lc3NhZ2VDb250YWluZXJJZCgpO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLmZvbnRTaXplID0gXCIxNHB4XCI7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuc3R5bGUucGFkZGluZyA9IFwiMnB4IDEwcHhcIjtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5zdHlsZS5tYXJnaW4gPSBcIjRweFwiO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLmJvcmRlclRvcCA9IFwiMXB4IHNvbGlkICNmNmY2ZjZcIjtcbiAgICAgICAgaGVhZGVyLmFwcGVuZENoaWxkKGhlYWRlck1lc3NhZ2VDb250YWluZXIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVTZWN0aW9uID0gZnVuY3Rpb24gKGRhc2hib2FyZCkge1xuICAgICAgICB2YXIgc2VjdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNlY3Rpb24uaWQgPSB0aGlzLmdldERhc2hib2FyZFNlY3Rpb25JZCgpO1xuICAgICAgICBzZWN0aW9uLnN0eWxlLndpZHRoID0gXCIxMDAlXCI7XG4gICAgICAgIHNlY3Rpb24uc3R5bGUucGFkZGluZyA9IFwiMTBweCAwcHggMTBweCAwcHhcIjtcbiAgICAgICAgc2VjdGlvbi5zdHlsZS50ZXh0QWxpZ24gPSBcImxlZnRcIjtcbiAgICAgICAgZGFzaGJvYXJkLmFwcGVuZENoaWxkKHNlY3Rpb24pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVDYW1lcmFMaXN0VWkgPSBmdW5jdGlvbiAoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIsIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uKSB7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayhmYWxzZSk7XG4gICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFQZXJtaXNzaW9uUmVxdWVzdGluZygpKTtcbiAgICAgICAgdmFyIGNyZWF0ZVBlcm1pc3Npb25CdXR0b25JZk5vdEV4aXN0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghcmVxdWVzdFBlcm1pc3Npb25CdXR0b24pIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5jcmVhdGVQZXJtaXNzaW9uQnV0dG9uKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgSHRtbDVRcmNvZGUuZ2V0Q2FtZXJhcygpLnRoZW4oZnVuY3Rpb24gKGNhbWVyYXMpIHtcbiAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldEhhc1Blcm1pc3Npb24odHJ1ZSk7XG4gICAgICAgICAgICAkdGhpcy5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsodHJ1ZSk7XG4gICAgICAgICAgICAkdGhpcy5yZXNldEhlYWRlck1lc3NhZ2UoKTtcbiAgICAgICAgICAgIGlmIChjYW1lcmFzICYmIGNhbWVyYXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHNjcENhbWVyYVNjYW5SZWdpb24ucmVtb3ZlQ2hpbGQocmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICAgICAgICAgICR0aGlzLnJlbmRlckNhbWVyYVNlbGVjdGlvbihjYW1lcmFzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5ub0NhbWVyYUZvdW5kKCksIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORyk7XG4gICAgICAgICAgICAgICAgY3JlYXRlUGVybWlzc2lvbkJ1dHRvbklmTm90RXhpc3RzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbihmYWxzZSk7XG4gICAgICAgICAgICBpZiAocmVxdWVzdFBlcm1pc3Npb25CdXR0b24pIHtcbiAgICAgICAgICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY3JlYXRlUGVybWlzc2lvbkJ1dHRvbklmTm90RXhpc3RzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKGVycm9yLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkcpO1xuICAgICAgICAgICAgJHRoaXMuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rKHRydWUpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlUGVybWlzc2lvbkJ1dHRvbiA9IGZ1bmN0aW9uIChzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcikge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24gPSBCYXNlVWlFbGVtZW50RmFjdG9yeVxuICAgICAgICAgICAgLmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgdGhpcy5nZXRDYW1lcmFQZXJtaXNzaW9uQnV0dG9uSWQoKSk7XG4gICAgICAgIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmNhbWVyYVBlcm1pc3Npb25UaXRsZSgpO1xuICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24uZGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgJHRoaXMuY3JlYXRlQ2FtZXJhTGlzdFVpKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyLCByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lci5hcHBlbmRDaGlsZChyZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZVBlcm1pc3Npb25zVWkgPSBmdW5jdGlvbiAoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpIHtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgaWYgKFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSh0aGlzLmN1cnJlbnRTY2FuVHlwZSlcbiAgICAgICAgICAgICYmIHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuaGFzQ2FtZXJhUGVybWlzc2lvbnMoKSkge1xuICAgICAgICAgICAgQ2FtZXJhUGVybWlzc2lvbnMuaGFzUGVybWlzc2lvbnMoKS50aGVuKGZ1bmN0aW9uIChoYXNQZXJtaXNzaW9ucykge1xuICAgICAgICAgICAgICAgIGlmIChoYXNQZXJtaXNzaW9ucykge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5jcmVhdGVDYW1lcmFMaXN0VWkoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLmNyZWF0ZVBlcm1pc3Npb25CdXR0b24oc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgJHRoaXMuY3JlYXRlUGVybWlzc2lvbkJ1dHRvbihzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNyZWF0ZVBlcm1pc3Npb25CdXR0b24oc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVTZWN0aW9uQ29udHJvbFBhbmVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VjdGlvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvbklkKCkpO1xuICAgICAgICB2YXIgc2VjdGlvbkNvbnRyb2xQYW5lbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNlY3Rpb24uYXBwZW5kQ2hpbGQoc2VjdGlvbkNvbnRyb2xQYW5lbCk7XG4gICAgICAgIHZhciBzY3BDYW1lcmFTY2FuUmVnaW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgc2NwQ2FtZXJhU2NhblJlZ2lvbi5pZCA9IHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvbkNhbWVyYVNjYW5SZWdpb25JZCgpO1xuICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLnN0eWxlLmRpc3BsYXlcbiAgICAgICAgICAgID0gU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlKHRoaXMuY3VycmVudFNjYW5UeXBlKVxuICAgICAgICAgICAgICAgID8gXCJibG9ja1wiIDogXCJub25lXCI7XG4gICAgICAgIHNlY3Rpb25Db250cm9sUGFuZWwuYXBwZW5kQ2hpbGQoc2NwQ2FtZXJhU2NhblJlZ2lvbik7XG4gICAgICAgIHZhciByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHNjcENhbWVyYVNjYW5SZWdpb24uYXBwZW5kQ2hpbGQocmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICBpZiAodGhpcy5zY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblJlcXVpcmVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlUGVybWlzc2lvbnNVaShzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXJGaWxlU2NhblVpKHNlY3Rpb25Db250cm9sUGFuZWwpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5yZW5kZXJGaWxlU2NhblVpID0gZnVuY3Rpb24gKHBhcmVudCkge1xuICAgICAgICB2YXIgc2hvd09uUmVuZGVyID0gU2NhblR5cGVTZWxlY3Rvci5pc0ZpbGVTY2FuVHlwZSh0aGlzLmN1cnJlbnRTY2FuVHlwZSk7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBvbkZpbGVTZWxlY3RlZCA9IGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICAgICAgICBpZiAoISR0aGlzLmh0bWw1UXJjb2RlKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJodG1sNVFyY29kZSBub3QgZGVmaW5lZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFTY2FuVHlwZVNlbGVjdG9yLmlzRmlsZVNjYW5UeXBlKCR0aGlzLmN1cnJlbnRTY2FuVHlwZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MubG9hZGluZ0ltYWdlKCkpO1xuICAgICAgICAgICAgJHRoaXMuaHRtbDVRcmNvZGUuc2NhbkZpbGVWMihmaWxlLCB0cnVlKVxuICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChodG1sNXFyY29kZVJlc3VsdCkge1xuICAgICAgICAgICAgICAgICR0aGlzLnJlc2V0SGVhZGVyTWVzc2FnZSgpO1xuICAgICAgICAgICAgICAgICR0aGlzLnFyQ29kZVN1Y2Nlc3NDYWxsYmFjayhodG1sNXFyY29kZVJlc3VsdC5kZWNvZGVkVGV4dCwgaHRtbDVxcmNvZGVSZXN1bHQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShlcnJvciwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5xckNvZGVFcnJvckNhbGxiYWNrKGVycm9yLCBIdG1sNVFyY29kZUVycm9yRmFjdG9yeS5jcmVhdGVGcm9tKGVycm9yKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uVWkgPSBGaWxlU2VsZWN0aW9uVWkuY3JlYXRlKHBhcmVudCwgc2hvd09uUmVuZGVyLCBvbkZpbGVTZWxlY3RlZCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnJlbmRlckNhbWVyYVNlbGVjdGlvbiA9IGZ1bmN0aW9uIChjYW1lcmFzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBzY3BDYW1lcmFTY2FuUmVnaW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uQ2FtZXJhU2NhblJlZ2lvbklkKCkpO1xuICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHZhciBjYW1lcmFab29tVWkgPSBDYW1lcmFab29tVWkuY3JlYXRlKHNjcENhbWVyYVNjYW5SZWdpb24sIGZhbHNlKTtcbiAgICAgICAgdmFyIHJlbmRlckNhbWVyYVpvb21VaUlmU3VwcG9ydGVkID0gZnVuY3Rpb24gKGNhbWVyYUNhcGFiaWxpdGllcykge1xuICAgICAgICAgICAgdmFyIHpvb21DYXBhYmlsaXR5ID0gY2FtZXJhQ2FwYWJpbGl0aWVzLnpvb21GZWF0dXJlKCk7XG4gICAgICAgICAgICBpZiAoIXpvb21DYXBhYmlsaXR5LmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYW1lcmFab29tVWkuc2V0T25DYW1lcmFab29tVmFsdWVDaGFuZ2VDYWxsYmFjayhmdW5jdGlvbiAoem9vbVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgem9vbUNhcGFiaWxpdHkuYXBwbHkoem9vbVZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGRlZmF1bHRab29tID0gMTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuZGVmYXVsdFpvb21WYWx1ZUlmU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdFpvb20gPSBfdGhpcy5jb25maWcuZGVmYXVsdFpvb21WYWx1ZUlmU3VwcG9ydGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmYXVsdFpvb20gPSBjbGlwKGRlZmF1bHRab29tLCB6b29tQ2FwYWJpbGl0eS5taW4oKSwgem9vbUNhcGFiaWxpdHkubWF4KCkpO1xuICAgICAgICAgICAgY2FtZXJhWm9vbVVpLnNldFZhbHVlcyh6b29tQ2FwYWJpbGl0eS5taW4oKSwgem9vbUNhcGFiaWxpdHkubWF4KCksIGRlZmF1bHRab29tLCB6b29tQ2FwYWJpbGl0eS5zdGVwKCkpO1xuICAgICAgICAgICAgY2FtZXJhWm9vbVVpLnNob3coKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNhbWVyYVNlbGVjdFVpID0gQ2FtZXJhU2VsZWN0aW9uVWkuY3JlYXRlKHNjcENhbWVyYVNjYW5SZWdpb24sIGNhbWVyYXMpO1xuICAgICAgICB2YXIgY2FtZXJhQWN0aW9uQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIHZhciBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbiA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TVEFSVF9CVVRUT05fSUQpO1xuICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5pbm5lclRleHRcbiAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FuQnV0dG9uU3RhcnRTY2FubmluZ1RleHQoKTtcbiAgICAgICAgY2FtZXJhQWN0aW9uQ29udGFpbmVyLmFwcGVuZENoaWxkKGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uKTtcbiAgICAgICAgdmFyIGNhbWVyYUFjdGlvblN0b3BCdXR0b24gPSBCYXNlVWlFbGVtZW50RmFjdG9yeS5jcmVhdGVFbGVtZW50KFwiYnV0dG9uXCIsIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU1RPUF9CVVRUT05fSUQpO1xuICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TdG9wU2Nhbm5pbmdUZXh0KCk7XG4gICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgY2FtZXJhQWN0aW9uQ29udGFpbmVyLmFwcGVuZENoaWxkKGNhbWVyYUFjdGlvblN0b3BCdXR0b24pO1xuICAgICAgICB2YXIgdG9yY2hCdXR0b247XG4gICAgICAgIHZhciBjcmVhdGVBbmRTaG93VG9yY2hCdXR0b25JZlN1cHBvcnRlZCA9IGZ1bmN0aW9uIChjYW1lcmFDYXBhYmlsaXRpZXMpIHtcbiAgICAgICAgICAgIGlmICghY2FtZXJhQ2FwYWJpbGl0aWVzLnRvcmNoRmVhdHVyZSgpLmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAodG9yY2hCdXR0b24pIHtcbiAgICAgICAgICAgICAgICAgICAgdG9yY2hCdXR0b24uaGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRvcmNoQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdG9yY2hCdXR0b24gPSBUb3JjaEJ1dHRvbi5jcmVhdGUoY2FtZXJhQWN0aW9uQ29udGFpbmVyLCBjYW1lcmFDYXBhYmlsaXRpZXMudG9yY2hGZWF0dXJlKCksIHsgZGlzcGxheTogXCJub25lXCIsIG1hcmdpbkxlZnQ6IFwiNXB4XCIgfSwgZnVuY3Rpb24gKGVycm9yTWVzc2FnZSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKGVycm9yTWVzc2FnZSwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRvcmNoQnV0dG9uLnVwZGF0ZVRvcmNoQ2FwYWJpbGl0eShjYW1lcmFDYXBhYmlsaXRpZXMudG9yY2hGZWF0dXJlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdG9yY2hCdXR0b24uc2hvdygpO1xuICAgICAgICB9O1xuICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLmFwcGVuZENoaWxkKGNhbWVyYUFjdGlvbkNvbnRhaW5lcik7XG4gICAgICAgIHZhciByZXNldENhbWVyYUFjdGlvblN0YXJ0QnV0dG9uID0gZnVuY3Rpb24gKHNob3VsZFNob3cpIHtcbiAgICAgICAgICAgIGlmICghc2hvdWxkU2hvdykge1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5nc1xuICAgICAgICAgICAgICAgICAgICAuc2NhbkJ1dHRvblN0YXJ0U2Nhbm5pbmdUZXh0KCk7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5zdHlsZS5vcGFjaXR5ID0gXCIxXCI7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHNob3VsZFNob3cpIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5pbm5lclRleHRcbiAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2NhbkJ1dHRvblNjYW5uaW5nU3RhcnRpbmcoKTtcbiAgICAgICAgICAgIGNhbWVyYVNlbGVjdFVpLmRpc2FibGUoKTtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLnN0eWxlLm9wYWNpdHkgPSBcIjAuNVwiO1xuICAgICAgICAgICAgaWYgKF90aGlzLnNjYW5UeXBlU2VsZWN0b3IuaGFzTW9yZVRoYW5PbmVTY2FuVHlwZSgpKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rKGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR0aGlzLnJlc2V0SGVhZGVyTWVzc2FnZSgpO1xuICAgICAgICAgICAgdmFyIGNhbWVyYUlkID0gY2FtZXJhU2VsZWN0VWkuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldExhc3RVc2VkQ2FtZXJhSWQoY2FtZXJhSWQpO1xuICAgICAgICAgICAgJHRoaXMuaHRtbDVRcmNvZGUuc3RhcnQoY2FtZXJhSWQsIHRvSHRtbDVRcmNvZGVDYW1lcmFTY2FuQ29uZmlnKCR0aGlzLmNvbmZpZyksICR0aGlzLnFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgJHRoaXMucXJDb2RlRXJyb3JDYWxsYmFjaylcbiAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICAgICAgICAgIHJlc2V0Q2FtZXJhQWN0aW9uU3RhcnRCdXR0b24oZmFsc2UpO1xuICAgICAgICAgICAgICAgIHZhciBjYW1lcmFDYXBhYmlsaXRpZXMgPSAkdGhpcy5odG1sNVFyY29kZS5nZXRSdW5uaW5nVHJhY2tDYW1lcmFDYXBhYmlsaXRpZXMoKTtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLnNob3dUb3JjaEJ1dHRvbklmU3VwcG9ydGVkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZUFuZFNob3dUb3JjaEJ1dHRvbklmU3VwcG9ydGVkKGNhbWVyYUNhcGFiaWxpdGllcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuc2hvd1pvb21TbGlkZXJJZlN1cHBvcnRlZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJDYW1lcmFab29tVWlJZlN1cHBvcnRlZChjYW1lcmFDYXBhYmlsaXRpZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayh0cnVlKTtcbiAgICAgICAgICAgICAgICBjYW1lcmFTZWxlY3RVaS5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICByZXNldENhbWVyYUFjdGlvblN0YXJ0QnV0dG9uKHRydWUpO1xuICAgICAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoZXJyb3IsIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChjYW1lcmFTZWxlY3RVaS5oYXNTaW5nbGVJdGVtKCkpIHtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmNsaWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgIGlmICghJHRoaXMuaHRtbDVRcmNvZGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcImh0bWw1UXJjb2RlIG5vdCBkZWZpbmVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICR0aGlzLmh0bWw1UXJjb2RlLnN0b3AoKVxuICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLnNjYW5UeXBlU2VsZWN0b3IuaGFzTW9yZVRoYW5PbmVTY2FuVHlwZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayh0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FtZXJhU2VsZWN0VWkuZW5hYmxlKCk7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgICAgICAgICBpZiAodG9yY2hCdXR0b24pIHtcbiAgICAgICAgICAgICAgICAgICAgdG9yY2hCdXR0b24ucmVzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgdG9yY2hCdXR0b24uaGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYW1lcmFab29tVWkucmVtb3ZlT25DYW1lcmFab29tVmFsdWVDaGFuZ2VDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIGNhbWVyYVpvb21VaS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgJHRoaXMuaW5zZXJ0Q2FtZXJhU2NhbkltYWdlVG9TY2FuUmVnaW9uKCk7XG4gICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShlcnJvciwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLmdldExhc3RVc2VkQ2FtZXJhSWQoKSkge1xuICAgICAgICAgICAgdmFyIGNhbWVyYUlkID0gJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuZ2V0TGFzdFVzZWRDYW1lcmFJZCgpO1xuICAgICAgICAgICAgaWYgKGNhbWVyYVNlbGVjdFVpLmhhc1ZhbHVlKGNhbWVyYUlkKSkge1xuICAgICAgICAgICAgICAgIGNhbWVyYVNlbGVjdFVpLnNldFZhbHVlKGNhbWVyYUlkKTtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5jbGljaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIucmVzZXRMYXN0VXNlZENhbWVyYUlkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlU2VjdGlvblN3YXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBURVhUX0lGX0NBTUVSQV9TQ0FOX1NFTEVDVEVEID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50ZXh0SWZDYW1lcmFTY2FuU2VsZWN0ZWQoKTtcbiAgICAgICAgdmFyIFRFWFRfSUZfRklMRV9TQ0FOX1NFTEVDVEVEID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50ZXh0SWZGaWxlU2NhblNlbGVjdGVkKCk7XG4gICAgICAgIHZhciBzZWN0aW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uSWQoKSk7XG4gICAgICAgIHZhciBzd2l0Y2hDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBzd2l0Y2hDb250YWluZXIuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgdmFyIHN3aXRjaFNjYW5UeXBlTGluayA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvblN3YXBMaW5rSWQoKSk7XG4gICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5zdHlsZS50ZXh0RGVjb3JhdGlvbiA9IFwidW5kZXJsaW5lXCI7XG4gICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5zdHlsZS5jdXJzb3IgPSBcInBvaW50ZXJcIjtcbiAgICAgICAgc3dpdGNoU2NhblR5cGVMaW5rLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUodGhpcy5jdXJyZW50U2NhblR5cGUpXG4gICAgICAgICAgICAgICAgPyBURVhUX0lGX0NBTUVSQV9TQ0FOX1NFTEVDVEVEIDogVEVYVF9JRl9GSUxFX1NDQU5fU0VMRUNURUQ7XG4gICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCEkdGhpcy5zZWN0aW9uU3dhcEFsbG93ZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAoJHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJTZWN0aW9uIHN3YXAgY2FsbGVkIHdoZW4gbm90IGFsbG93ZWRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR0aGlzLnJlc2V0SGVhZGVyTWVzc2FnZSgpO1xuICAgICAgICAgICAgJHRoaXMuZmlsZVNlbGVjdGlvblVpLnJlc2V0VmFsdWUoKTtcbiAgICAgICAgICAgICR0aGlzLnNlY3Rpb25Td2FwQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSgkdGhpcy5jdXJyZW50U2NhblR5cGUpKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuY2xlYXJTY2FuUmVnaW9uKCk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZ2V0Q2FtZXJhU2NhblJlZ2lvbigpLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgICAkdGhpcy5maWxlU2VsZWN0aW9uVWkuc2hvdygpO1xuICAgICAgICAgICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5pbm5lclRleHQgPSBURVhUX0lGX0ZJTEVfU0NBTl9TRUxFQ1RFRDtcbiAgICAgICAgICAgICAgICAkdGhpcy5jdXJyZW50U2NhblR5cGUgPSBIdG1sNVFyY29kZVNjYW5UeXBlLlNDQU5fVFlQRV9GSUxFO1xuICAgICAgICAgICAgICAgICR0aGlzLmluc2VydEZpbGVTY2FuSW1hZ2VUb1NjYW5SZWdpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICR0aGlzLmNsZWFyU2NhblJlZ2lvbigpO1xuICAgICAgICAgICAgICAgICR0aGlzLmdldENhbWVyYVNjYW5SZWdpb24oKS5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgICAgICAgICAgICR0aGlzLmZpbGVTZWxlY3Rpb25VaS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoU2NhblR5cGVMaW5rLmlubmVyVGV4dCA9IFRFWFRfSUZfQ0FNRVJBX1NDQU5fU0VMRUNURUQ7XG4gICAgICAgICAgICAgICAgJHRoaXMuY3VycmVudFNjYW5UeXBlID0gSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfQ0FNRVJBO1xuICAgICAgICAgICAgICAgICR0aGlzLmluc2VydENhbWVyYVNjYW5JbWFnZVRvU2NhblJlZ2lvbigpO1xuICAgICAgICAgICAgICAgICR0aGlzLnN0YXJ0Q2FtZXJhU2NhbklmUGVybWlzc2lvbkV4aXN0c09uU3dhcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHRoaXMuc2VjdGlvblN3YXBBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHN3aXRjaENvbnRhaW5lci5hcHBlbmRDaGlsZChzd2l0Y2hTY2FuVHlwZUxpbmspO1xuICAgICAgICBzZWN0aW9uLmFwcGVuZENoaWxkKHN3aXRjaENvbnRhaW5lcik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnN0YXJ0Q2FtZXJhU2NhbklmUGVybWlzc2lvbkV4aXN0c09uU3dhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuaGFzQ2FtZXJhUGVybWlzc2lvbnMoKSkge1xuICAgICAgICAgICAgQ2FtZXJhUGVybWlzc2lvbnMuaGFzUGVybWlzc2lvbnMoKS50aGVuKGZ1bmN0aW9uIChoYXNQZXJtaXNzaW9ucykge1xuICAgICAgICAgICAgICAgIGlmIChoYXNQZXJtaXNzaW9ucykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGVybWlzc2lvbkJ1dHRvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCR0aGlzLmdldENhbWVyYVBlcm1pc3Npb25CdXR0b25JZCgpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwZXJtaXNzaW9uQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJQZXJtaXNzaW9uIGJ1dHRvbiBub3QgZm91bmQsIGZhaWw7XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJQZXJtaXNzaW9uIGJ1dHRvbiBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwZXJtaXNzaW9uQnV0dG9uLmNsaWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5zZXRIYXNQZXJtaXNzaW9uKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldEhhc1Blcm1pc3Npb24oZmFsc2UpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVzZXRIZWFkZXJNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWVzc2FnZURpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0SGVhZGVyTWVzc2FnZUNvbnRhaW5lcklkKCkpO1xuICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuc2V0SGVhZGVyTWVzc2FnZSA9IGZ1bmN0aW9uIChtZXNzYWdlVGV4dCwgc2Nhbm5lclN0YXR1cykge1xuICAgICAgICBpZiAoIXNjYW5uZXJTdGF0dXMpIHtcbiAgICAgICAgICAgIHNjYW5uZXJTdGF0dXMgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX0RFRkFVTFQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1lc3NhZ2VEaXYgPSB0aGlzLmdldEhlYWRlck1lc3NhZ2VEaXYoKTtcbiAgICAgICAgbWVzc2FnZURpdi5pbm5lclRleHQgPSBtZXNzYWdlVGV4dDtcbiAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgICBzd2l0Y2ggKHNjYW5uZXJTdGF0dXMpIHtcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19TVUNDRVNTOlxuICAgICAgICAgICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuYmFja2dyb3VuZCA9IFwicmdiYSgxMDYsIDE3NSwgODAsIDAuMjYpXCI7XG4gICAgICAgICAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5jb2xvciA9IFwiIzQ3NzczNVwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkc6XG4gICAgICAgICAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5iYWNrZ3JvdW5kID0gXCJyZ2JhKDIwMywgMzYsIDQ5LCAwLjE0KVwiO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuY29sb3IgPSBcIiNjYjI0MzFcIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19ERUZBVUxUOlxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmJhY2tncm91bmQgPSBcInJnYmEoMCwgMCwgMCwgMClcIjtcbiAgICAgICAgICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmNvbG9yID0gXCJyZ2IoMTcsIDE3LCAxNylcIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsgPSBmdW5jdGlvbiAoc2hvdWxkRGlzcGxheSkge1xuICAgICAgICBpZiAodGhpcy5zY2FuVHlwZVNlbGVjdG9yLmhhc01vcmVUaGFuT25lU2NhblR5cGUoKSkge1xuICAgICAgICAgICAgaWYgKHNob3VsZERpc3BsYXkgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBzaG91bGREaXNwbGF5ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNlY3Rpb25Td2FwQWxsb3dlZCA9IHNob3VsZERpc3BsYXk7XG4gICAgICAgICAgICB0aGlzLmdldERhc2hib2FyZFNlY3Rpb25Td2FwTGluaygpLnN0eWxlLmRpc3BsYXlcbiAgICAgICAgICAgICAgICA9IHNob3VsZERpc3BsYXkgPyBcImlubGluZS1ibG9ja1wiIDogXCJub25lXCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuaW5zZXJ0Q2FtZXJhU2NhbkltYWdlVG9TY2FuUmVnaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcXJDb2RlU2NhblJlZ2lvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0U2NhblJlZ2lvbklkKCkpO1xuICAgICAgICBpZiAodGhpcy5jYW1lcmFTY2FuSW1hZ2UpIHtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uaW5uZXJIVE1MID0gXCI8YnI+XCI7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmFwcGVuZENoaWxkKHRoaXMuY2FtZXJhU2NhbkltYWdlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZSA9IG5ldyBJbWFnZTtcbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uaW5uZXJIVE1MID0gXCI8YnI+XCI7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmFwcGVuZENoaWxkKCR0aGlzLmNhbWVyYVNjYW5JbWFnZSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlLndpZHRoID0gNjQ7XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlLnN0eWxlLm9wYWNpdHkgPSBcIjAuOFwiO1xuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZS5zcmMgPSBBU1NFVF9DQU1FUkFfU0NBTjtcbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2UuYWx0ID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFTY2FuQWx0VGV4dCgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5pbnNlcnRGaWxlU2NhbkltYWdlVG9TY2FuUmVnaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcXJDb2RlU2NhblJlZ2lvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0U2NhblJlZ2lvbklkKCkpO1xuICAgICAgICBpZiAodGhpcy5maWxlU2NhbkltYWdlKSB7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmlubmVySFRNTCA9IFwiPGJyPlwiO1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5hcHBlbmRDaGlsZCh0aGlzLmZpbGVTY2FuSW1hZ2UpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZSA9IG5ldyBJbWFnZTtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmlubmVySFRNTCA9IFwiPGJyPlwiO1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5hcHBlbmRDaGlsZCgkdGhpcy5maWxlU2NhbkltYWdlKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLndpZHRoID0gNjQ7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZS5zdHlsZS5vcGFjaXR5ID0gXCIwLjhcIjtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLnNyYyA9IEFTU0VUX0ZJTEVfU0NBTjtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLmFsdCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNjYW5BbHRUZXh0KCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNsZWFyU2NhblJlZ2lvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHFyQ29kZVNjYW5SZWdpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldFNjYW5SZWdpb25JZCgpKTtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5pbm5lckhUTUwgPSBcIlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRTZWN0aW9uSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCJfX2Rhc2hib2FyZF9zZWN0aW9uXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRTZWN0aW9uQ2FtZXJhU2NhblJlZ2lvbklkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJcIi5jb25jYXQodGhpcy5lbGVtZW50SWQsIFwiX19kYXNoYm9hcmRfc2VjdGlvbl9jc3JcIik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldERhc2hib2FyZFNlY3Rpb25Td2FwTGlua0lkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlNDQU5fVFlQRV9DSEFOR0VfQU5DSE9SX0lEO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRTY2FuUmVnaW9uSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCJfX3NjYW5fcmVnaW9uXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiXCIuY29uY2F0KHRoaXMuZWxlbWVudElkLCBcIl9fZGFzaGJvYXJkXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRIZWFkZXJNZXNzYWdlQ29udGFpbmVySWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCJfX2hlYWRlcl9tZXNzYWdlXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRDYW1lcmFQZXJtaXNzaW9uQnV0dG9uSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQ0FNRVJBX1BFUk1JU1NJT05fQlVUVE9OX0lEO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRDYW1lcmFTY2FuUmVnaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uQ2FtZXJhU2NhblJlZ2lvbklkKCkpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRTZWN0aW9uU3dhcExpbmsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldERhc2hib2FyZFNlY3Rpb25Td2FwTGlua0lkKCkpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRIZWFkZXJNZXNzYWdlRGl2ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXRIZWFkZXJNZXNzYWdlQ29udGFpbmVySWQoKSk7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTY2FubmVyO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aHRtbDUtcXJjb2RlLXNjYW5uZXIuanMubWFwIiwiZXhwb3J0IHsgSHRtbDVRcmNvZGUgfSBmcm9tIFwiLi9odG1sNS1xcmNvZGVcIjtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lciB9IGZyb20gXCIuL2h0bWw1LXFyY29kZS1zY2FubmVyXCI7XG5leHBvcnQgeyBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMgfSBmcm9tIFwiLi9jb3JlXCI7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZSB9IGZyb20gXCIuL3N0YXRlLW1hbmFnZXJcIjtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2NhblR5cGUgfSBmcm9tIFwiLi9jb3JlXCI7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCJleHBvcnQgZnVuY3Rpb24gbnVtYmVyKG4pIHtcbiAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKG4pIHx8IG4gPCAwKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFdyb25nIHBvc2l0aXZlIGludGVnZXI6ICR7bn1gKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBib29sKGIpIHtcbiAgICBpZiAodHlwZW9mIGIgIT09ICdib29sZWFuJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBib29sZWFuLCBub3QgJHtifWApO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVzKGIsIC4uLmxlbmd0aHMpIHtcbiAgICBpZiAoIShiIGluc3RhbmNlb2YgVWludDhBcnJheSkpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgVWludDhBcnJheScpO1xuICAgIGlmIChsZW5ndGhzLmxlbmd0aCA+IDAgJiYgIWxlbmd0aHMuaW5jbHVkZXMoYi5sZW5ndGgpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIFVpbnQ4QXJyYXkgb2YgbGVuZ3RoICR7bGVuZ3Roc30sIG5vdCBvZiBsZW5ndGg9JHtiLmxlbmd0aH1gKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBoYXNoKGhhc2gpIHtcbiAgICBpZiAodHlwZW9mIGhhc2ggIT09ICdmdW5jdGlvbicgfHwgdHlwZW9mIGhhc2guY3JlYXRlICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0hhc2ggc2hvdWxkIGJlIHdyYXBwZWQgYnkgdXRpbHMud3JhcENvbnN0cnVjdG9yJyk7XG4gICAgbnVtYmVyKGhhc2gub3V0cHV0TGVuKTtcbiAgICBudW1iZXIoaGFzaC5ibG9ja0xlbik7XG59XG5leHBvcnQgZnVuY3Rpb24gZXhpc3RzKGluc3RhbmNlLCBjaGVja0ZpbmlzaGVkID0gdHJ1ZSkge1xuICAgIGlmIChpbnN0YW5jZS5kZXN0cm95ZWQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSGFzaCBpbnN0YW5jZSBoYXMgYmVlbiBkZXN0cm95ZWQnKTtcbiAgICBpZiAoY2hlY2tGaW5pc2hlZCAmJiBpbnN0YW5jZS5maW5pc2hlZClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIYXNoI2RpZ2VzdCgpIGhhcyBhbHJlYWR5IGJlZW4gY2FsbGVkJyk7XG59XG5leHBvcnQgZnVuY3Rpb24gb3V0cHV0KG91dCwgaW5zdGFuY2UpIHtcbiAgICBieXRlcyhvdXQpO1xuICAgIGNvbnN0IG1pbiA9IGluc3RhbmNlLm91dHB1dExlbjtcbiAgICBpZiAob3V0Lmxlbmd0aCA8IG1pbikge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGRpZ2VzdEludG8oKSBleHBlY3RzIG91dHB1dCBidWZmZXIgb2YgbGVuZ3RoIGF0IGxlYXN0ICR7bWlufWApO1xuICAgIH1cbn1cbmNvbnN0IGFzc2VydCA9IHtcbiAgICBudW1iZXIsXG4gICAgYm9vbCxcbiAgICBieXRlcyxcbiAgICBoYXNoLFxuICAgIGV4aXN0cyxcbiAgICBvdXRwdXQsXG59O1xuZXhwb3J0IGRlZmF1bHQgYXNzZXJ0O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9X2Fzc2VydC5qcy5tYXAiLCJjb25zdCBVMzJfTUFTSzY0ID0gQmlnSW50KDIgKiogMzIgLSAxKTtcbmNvbnN0IF8zMm4gPSBCaWdJbnQoMzIpO1xuLy8gV2UgYXJlIG5vdCB1c2luZyBCaWdVaW50NjRBcnJheSwgYmVjYXVzZSB0aGV5IGFyZSBleHRyZW1lbHkgc2xvdyBhcyBwZXIgMjAyMlxuZXhwb3J0IGZ1bmN0aW9uIGZyb21CaWcobiwgbGUgPSBmYWxzZSkge1xuICAgIGlmIChsZSlcbiAgICAgICAgcmV0dXJuIHsgaDogTnVtYmVyKG4gJiBVMzJfTUFTSzY0KSwgbDogTnVtYmVyKChuID4+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/IGdsb2JhbFRoaXMuY3J5cHRvIDogdW5kZWZpbmVkO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y3J5cHRvLmpzLm1hcCIsIi8qISBub2JsZS1oYXNoZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbi8vIFdlIHVzZSBXZWJDcnlwdG8gYWthIGdsb2JhbFRoaXMuY3J5cHRvLCB3aGljaCBleGlzdHMgaW4gYnJvd3NlcnMgYW5kIG5vZGUuanMgMTYrLlxuLy8gbm9kZS5qcyB2ZXJzaW9ucyBlYXJsaWVyIHRoYW4gdjE5IGRvbid0IGRlY2xhcmUgaXQgaW4gZ2xvYmFsIHNjb3BlLlxuLy8gRm9yIG5vZGUuanMsIHBhY2thZ2UuanNvbiNleHBvcnRzIGZpZWxkIG1hcHBpbmcgcmV3cml0ZXMgaW1wb3J0XG4vLyBmcm9tIGBjcnlwdG9gIHRvIGBjcnlwdG9Ob2RlYCwgd2hpY2ggaW1wb3J0cyBuYXRpdmUgbW9kdWxlLlxuLy8gTWFrZXMgdGhlIHV0aWxzIHVuLWltcG9ydGFibGUgaW4gYnJvd3NlcnMgd2l0aG91dCBhIGJ1bmRsZXIuXG4vLyBPbmNlIG5vZGUuanMgMTggaXMgZGVwcmVjYXRlZCwgd2UgY2FuIGp1c3QgZHJvcCB0aGUgaW1wb3J0LlxuaW1wb3J0IHsgY3J5cHRvIH0gZnJvbSAnQG5vYmxlL2hhc2hlcy9jcnlwdG8nO1xuY29uc3QgdThhID0gKGEpID0+IGEgaW5zdGFuY2VvZiBVaW50OEFycmF5O1xuLy8gQ2FzdCBhcnJheSB0byBkaWZmZXJlbnQgdHlwZVxuZXhwb3J0IGNvbnN0IHU4ID0gKGFycikgPT4gbmV3IFVpbnQ4QXJyYXkoYXJyLmJ1ZmZlciwgYXJyLmJ5dGVPZmZzZXQsIGFyci5ieXRlTGVuZ3RoKTtcbmV4cG9ydCBjb25zdCB1MzIgPSAoYXJyKSA9PiBuZXcgVWludDMyQXJyYXkoYXJyLmJ1ZmZlciwgYXJyLmJ5dGVPZmZzZXQsIE1hdGguZmxvb3IoYXJyLmJ5dGVMZW5ndGggLyA0KSk7XG4vLyBDYXN0IGFycmF5IHRvIHZpZXdcbmV4cG9ydCBjb25zdCBjcmVhdGVWaWV3ID0gKGFycikgPT4gbmV3IERhdGFWaWV3KGFyci5idWZmZXIsIGFyci5ieXRlT2Zmc2V0LCBhcnIuYnl0ZUxlbmd0aCk7XG4vLyBUaGUgcm90YXRlIHJpZ2h0IChjaXJjdWxhciByaWdodCBzaGlmdCkgb3BlcmF0aW9uIGZvciB1aW50MzJcbmV4cG9ydCBjb25zdCByb3RyID0gKHdvcmQsIHNoaWZ0KSA9PiAod29yZCA8PCAoMzIgLSBzaGlmdCkpIHwgKHdvcmQgPj4+IHNoaWZ0KTtcbi8vIGJpZy1lbmRpYW4gaGFyZHdhcmUgaXMgcmFyZS4gSnVzdCBpbiBjYXNlIHNvbWVvbmUgc3RpbGwgZGVjaWRlcyB0byBydW4gaGFzaGVzOlxuLy8gZWFybHktdGhyb3cgYW4gZXJyb3IgYmVjYXVzZSB3ZSBkb24ndCBzdXBwb3J0IEJFIHlldC5cbmV4cG9ydCBjb25zdCBpc0xFID0gbmV3IFVpbnQ4QXJyYXkobmV3IFVpbnQzMkFycmF5KFsweDExMjIzMzQ0XSkuYnVmZmVyKVswXSA9PT0gMHg0NDtcbmlmICghaXNMRSlcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ05vbiBsaXR0bGUtZW5kaWFuIGhhcmR3YXJlIGlzIG5vdCBzdXBwb3J0ZWQnKTtcbmNvbnN0IGhleGVzID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogMjU2IH0sICh2LCBpKSA9PiBpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpKTtcbi8qKlxuICogQGV4YW1wbGUgYnl0ZXNUb0hleChVaW50OEFycmF5LmZyb20oWzB4Y2EsIDB4ZmUsIDB4MDEsIDB4MjNdKSkgLy8gJ2NhZmUwMTIzJ1xuICovXG5leHBvcnQgZnVuY3Rpb24gYnl0ZXNUb0hleChieXRlcykge1xuICAgIGlmICghdThhKGJ5dGVzKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGV4cGVjdGVkJyk7XG4gICAgLy8gcHJlLWNhY2hpbmcgaW1wcm92ZXMgdGhlIHNwZWVkIDZ4XG4gICAgbGV0IGhleCA9ICcnO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaGV4ICs9IGhleGVzW2J5dGVzW2ldXTtcbiAgICB9XG4gICAgcmV0dXJuIGhleDtcbn1cbi8qKlxuICogQGV4YW1wbGUgaGV4VG9CeXRlcygnY2FmZTAxMjMnKSAvLyBVaW50OEFycmF5LmZyb20oWzB4Y2EsIDB4ZmUsIDB4MDEsIDB4MjNdKVxuICovXG5leHBvcnQgZnVuY3Rpb24gaGV4VG9CeXRlcyhoZXgpIHtcbiAgICBpZiAodHlwZW9mIGhleCAhPT0gJ3N0cmluZycpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGV4IHN0cmluZyBleHBlY3RlZCwgZ290ICcgKyB0eXBlb2YgaGV4KTtcbiAgICBjb25zdCBsZW4gPSBoZXgubGVuZ3RoO1xuICAgIGlmIChsZW4gJSAyKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhZGRlZCBoZXggc3RyaW5nIGV4cGVjdGVkLCBnb3QgdW5wYWRkZWQgaGV4IG9mIGxlbmd0aCAnICsgbGVuKTtcbiAgICBjb25zdCBhcnJheSA9IG5ldyBVaW50OEFycmF5KGxlbiAvIDIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgaiA9IGkgKiAyO1xuICAgICAgICBjb25zdCBoZXhCeXRlID0gaGV4LnNsaWNlKGosIGogKyAyKTtcbiAgICAgICAgY29uc3QgYnl0ZSA9IE51bWJlci5wYXJzZUludChoZXhCeXRlLCAxNik7XG4gICAgICAgIGlmIChOdW1iZXIuaXNOYU4oYnl0ZSkgfHwgYnl0ZSA8IDApXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYnl0ZSBzZXF1ZW5jZScpO1xuICAgICAgICBhcnJheVtpXSA9IGJ5dGU7XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbn1cbi8vIFRoZXJlIGlzIG5vIHNldEltbWVkaWF0ZSBpbiBicm93c2VyIGFuZCBzZXRUaW1lb3V0IGlzIHNsb3cuXG4vLyBjYWxsIG9mIGFzeW5jIGZuIHdpbGwgcmV0dXJuIFByb21pc2UsIHdoaWNoIHdpbGwgYmUgZnVsbGZpbGVkIG9ubHkgb25cbi8vIG5leHQgc2NoZWR1bGVyIHF1ZXVlIHByb2Nlc3Npbmcgc3RlcCBhbmQgdGhpcyBpcyBleGFjdGx5IHdoYXQgd2UgbmVlZC5cbmV4cG9ydCBjb25zdCBuZXh0VGljayA9IGFzeW5jICgpID0+IHsgfTtcbi8vIFJldHVybnMgY29udHJvbCB0byB0aHJlYWQgZWFjaCAndGljaycgbXMgdG8gYXZvaWQgYmxvY2tpbmdcbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhc3luY0xvb3AoaXRlcnMsIHRpY2ssIGNiKSB7XG4gICAgbGV0IHRzID0gRGF0ZS5ub3coKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGl0ZXJzOyBpKyspIHtcbiAgICAgICAgY2IoaSk7XG4gICAgICAgIC8vIERhdGUubm93KCkgaXMgbm90IG1vbm90b25pYywgc28gaW4gY2FzZSBpZiBjbG9jayBnb2VzIGJhY2t3YXJkcyB3ZSByZXR1cm4gcmV0dXJuIGNvbnRyb2wgdG9vXG4gICAgICAgIGNvbnN0IGRpZmYgPSBEYXRlLm5vdygpIC0gdHM7XG4gICAgICAgIGlmIChkaWZmID49IDAgJiYgZGlmZiA8IHRpY2spXG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgYXdhaXQgbmV4dFRpY2soKTtcbiAgICAgICAgdHMgKz0gZGlmZjtcbiAgICB9XG59XG4vKipcbiAqIEBleGFtcGxlIHV0ZjhUb0J5dGVzKCdhYmMnKSAvLyBuZXcgVWludDhBcnJheShbOTcsIDk4LCA5OV0pXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1dGY4VG9CeXRlcyhzdHIpIHtcbiAgICBpZiAodHlwZW9mIHN0ciAhPT0gJ3N0cmluZycpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgdXRmOFRvQnl0ZXMgZXhwZWN0ZWQgc3RyaW5nLCBnb3QgJHt0eXBlb2Ygc3RyfWApO1xuICAgIHJldHVybiBuZXcgVWludDhBcnJheShuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoc3RyKSk7IC8vIGh0dHBzOi8vYnVnemlsLmxhLzE2ODE4MDlcbn1cbi8qKlxuICogTm9ybWFsaXplcyAobm9uLWhleCkgc3RyaW5nIG9yIFVpbnQ4QXJyYXkgdG8gVWludDhBcnJheS5cbiAqIFdhcm5pbmc6IHdoZW4gVWludDhBcnJheSBpcyBwYXNzZWQsIGl0IHdvdWxkIE5PVCBnZXQgY29waWVkLlxuICogS2VlcCBpbiBtaW5kIGZvciBmdXR1cmUgbXV0YWJsZSBvcGVyYXRpb25zLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdG9CeXRlcyhkYXRhKSB7XG4gICAgaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJylcbiAgICAgICAgZGF0YSA9IHV0ZjhUb0J5dGVzKGRhdGEpO1xuICAgIGlmICghdThhKGRhdGEpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGV4cGVjdGVkIFVpbnQ4QXJyYXksIGdvdCAke3R5cGVvZiBkYXRhfWApO1xuICAgIHJldHVybiBkYXRhO1xufVxuLyoqXG4gKiBDb3BpZXMgc2V2ZXJhbCBVaW50OEFycmF5cyBpbnRvIG9uZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbmNhdEJ5dGVzKC4uLmFycmF5cykge1xuICAgIGNvbnN0IHIgPSBuZXcgVWludDhBcnJheShhcnJheXMucmVkdWNlKChzdW0sIGEpID0+IHN1bSArIGEubGVuZ3RoLCAwKSk7XG4gICAgbGV0IHBhZCA9IDA7IC8vIHdhbGsgdGhyb3VnaCBlYWNoIGl0ZW0sIGVuc3VyZSB0aGV5IGhhdmUgcHJvcGVyIHR5cGVcbiAgICBhcnJheXMuZm9yRWFjaCgoYSkgPT4ge1xuICAgICAgICBpZiAoIXU4YShhKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVWludDhBcnJheSBleHBlY3RlZCcpO1xuICAgICAgICByLnNldChhLCBwYWQpO1xuICAgICAgICBwYWQgKz0gYS5sZW5ndGg7XG4gICAgfSk7XG4gICAgcmV0dXJuIHI7XG59XG4vLyBGb3IgcnVudGltZSBjaGVjayBpZiBjbGFzcyBpbXBsZW1lbnRzIGludGVyZmFjZVxuZXhwb3J0IGNsYXNzIEhhc2gge1xuICAgIC8vIFNhZmUgdmVyc2lvbiB0aGF0IGNsb25lcyBpbnRlcm5hbCBzdGF0ZVxuICAgIGNsb25lKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fY2xvbmVJbnRvKCk7XG4gICAgfVxufVxuLy8gQ2hlY2sgaWYgb2JqZWN0IGRvZW5zJ3QgaGF2ZSBjdXN0b20gY29uc3RydWN0b3IgKGxpa2UgVWludDhBcnJheS9BcnJheSlcbmNvbnN0IGlzUGxhaW5PYmplY3QgPSAob2JqKSA9PiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwob2JqKSA9PT0gJ1tvYmplY3QgT2JqZWN0XScgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBPYmplY3Q7XG5leHBvcnQgZnVuY3Rpb24gY2hlY2tPcHRzKGRlZmF1bHRzLCBvcHRzKSB7XG4gICAgaWYgKG9wdHMgIT09IHVuZGVmaW5lZCAmJiAodHlwZW9mIG9wdHMgIT09ICdvYmplY3QnIHx8ICFpc1BsYWluT2JqZWN0KG9wdHMpKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdPcHRpb25zIHNob3VsZCBiZSBvYmplY3Qgb3IgdW5kZWZpbmVkJyk7XG4gICAgY29uc3QgbWVyZ2VkID0gT2JqZWN0LmFzc2lnbihkZWZhdWx0cywgb3B0cyk7XG4gICAgcmV0dXJuIG1lcmdlZDtcbn1cbmV4cG9ydCBmdW5jdGlvbiB3cmFwQ29uc3RydWN0b3IoaGFzaENvbnMpIHtcbiAgICBjb25zdCBoYXNoQyA9IChtc2cpID0+IGhhc2hDb25zKCkudXBkYXRlKHRvQnl0ZXMobXNnKSkuZGlnZXN0KCk7XG4gICAgY29uc3QgdG1wID0gaGFzaENvbnMoKTtcbiAgICBoYXNoQy5vdXRwdXRMZW4gPSB0bXAub3V0cHV0TGVuO1xuICAgIGhhc2hDLmJsb2NrTGVuID0gdG1wLmJsb2NrTGVuO1xuICAgIGhhc2hDLmNyZWF0ZSA9ICgpID0+IGhhc2hDb25zKCk7XG4gICAgcmV0dXJuIGhhc2hDO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHdyYXBDb25zdHJ1Y3RvcldpdGhPcHRzKGhhc2hDb25zKSB7XG4gICAgY29uc3QgaGFzaEMgPSAobXNnLCBvcHRzKSA9PiBoYXNoQ29ucyhvcHRzKS51cGRhdGUodG9CeXRlcyhtc2cpKS5kaWdlc3QoKTtcbiAgICBjb25zdCB0bXAgPSBoYXNoQ29ucyh7fSk7XG4gICAgaGFzaEMub3V0cHV0TGVuID0gdG1wLm91dHB1dExlbjtcbiAgICBoYXNoQy5ibG9ja0xlbiA9IHRtcC5ibG9ja0xlbjtcbiAgICBoYXNoQy5jcmVhdGUgPSAob3B0cykgPT4gaGFzaENvbnMob3B0cyk7XG4gICAgcmV0dXJuIGhhc2hDO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHdyYXBYT0ZDb25zdHJ1Y3RvcldpdGhPcHRzKGhhc2hDb25zKSB7XG4gICAgY29uc3QgaGFzaEMgPSAobXNnLCBvcHRzKSA9PiBoYXNoQ29ucyhvcHRzKS51cGRhdGUodG9CeXRlcyhtc2cpKS5kaWdlc3QoKTtcbiAgICBjb25zdCB0bXAgPSBoYXNoQ29ucyh7fSk7XG4gICAgaGFzaEMub3V0cHV0TGVuID0gdG1wLm91dHB1dExlbjtcbiAgICBoYXNoQy5ibG9ja0xlbiA9IHRtcC5ibG9ja0xlbjtcbiAgICBoYXNoQy5jcmVhdGUgPSAob3B0cykgPT4gaGFzaENvbnMob3B0cyk7XG4gICAgcmV0dXJuIGhhc2hDO1xufVxuLyoqXG4gKiBTZWN1cmUgUFJORy4gVXNlcyBgY3J5cHRvLmdldFJhbmRvbVZhbHVlc2AsIHdoaWNoIGRlZmVycyB0byBPUy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJhbmRvbUJ5dGVzKGJ5dGVzTGVuZ3RoID0gMzIpIHtcbiAgICBpZiAoY3J5cHRvICYmIHR5cGVvZiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgIHJldHVybiBjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzKG5ldyBVaW50OEFycmF5KGJ5dGVzTGVuZ3RoKSk7XG4gICAgfVxuICAgIHRocm93IG5ldyBFcnJvcignY3J5cHRvLmdldFJhbmRvbVZhbHVlcyBtdXN0IGJlIGRlZmluZWQnKTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXV0aWxzLmpzLm1hcCIsImltcG9ydCBhc3NlcnQgZnJvbSAnLi9fYXNzZXJ0LmpzJztcbmltcG9ydCB1NjQgZnJvbSAnLi9fdTY0LmpzJztcbmltcG9ydCB7IEhhc2gsIHUzMiwgdG9CeXRlcywgd3JhcENvbnN0cnVjdG9yLCB3cmFwWE9GQ29uc3RydWN0b3JXaXRoT3B0cywgfSBmcm9tICcuL3V0aWxzLmpzJztcbi8vIFZhcmlvdXMgcGVyIHJvdW5kIGNvbnN0YW50cyBjYWxjdWxhdGlvbnNcbmNvbnN0IFtTSEEzX1BJLCBTSEEzX1JPVEwsIF9TSEEzX0lPVEFdID0gW1tdLCBbXSwgW11dO1xuY29uc3QgXzBuID0gQmlnSW50KDApO1xuY29uc3QgXzFuID0gQmlnSW50KDEpO1xuY29uc3QgXzJuID0gQmlnSW50KDIpO1xuY29uc3QgXzduID0gQmlnSW50KDcpO1xuY29uc3QgXzI1Nm4gPSBCaWdJbnQoMjU2KTtcbmNvbnN0IF8weDcxbiA9IEJpZ0ludCgweDcxKTtcbmZvciAobGV0IHJvdW5kID0gMCwgUiA9IF8xbiwgeCA9IDEsIHkgPSAwOyByb3VuZCA8IDI0OyByb3VuZCsrKSB7XG4gICAgLy8gUGlcbiAgICBbeCwgeV0gPSBbeSwgKDIgKiB4ICsgMyAqIHkpICUgNV07XG4gICAgU0hBM19QSS5wdXNoKDIgKiAoNSAqIHkgKyB4KSk7XG4gICAgLy8gUm90YXRpb25hbFxuICAgIFNIQTNfUk9UTC5wdXNoKCgoKHJvdW5kICsgMSkgKiAocm91bmQgKyAyKSkgLyAyKSAlIDY0KTtcbiAgICAvLyBJb3RhXG4gICAgbGV0IHQgPSBfMG47XG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCA3OyBqKyspIHtcbiAgICAgICAgUiA9ICgoUiA8PCBfMW4pIF4gKChSID4+IF83bikgKiBfMHg3MW4pKSAlIF8yNTZuO1xuICAgICAgICBpZiAoUiAmIF8ybilcbiAgICAgICAgICAgIHQgXj0gXzFuIDw8ICgoXzFuIDw8IEJpZ0ludChqKSkgLSBfMW4pO1xuICAgIH1cbiAgICBfU0hBM19JT1RBLnB1c2godCk7XG59XG5jb25zdCBbU0hBM19JT1RBX0gsIFNIQTNfSU9UQV9MXSA9IHU2NC5zcGxpdChfU0hBM19JT1RBLCB0cnVlKTtcbi8vIExlZnQgcm90YXRpb24gKHdpdGhvdXQgMCwgMzIsIDY0KVxuY29uc3Qgcm90bEggPSAoaCwgbCwgcykgPT4gcyA+IDMyID8gdTY0LnJvdGxCSChoLCBsLCBzKSA6IHU2NC5yb3RsU0goaCwgbCwgcyk7XG5jb25zdCByb3RsTCA9IChoLCBsLCBzKSA9PiBzID4gMzIgPyB1NjQucm90bEJMKGgsIGwsIHMpIDogdTY0LnJvdGxTTChoLCBsLCBzKTtcbi8vIFNhbWUgYXMga2VjY2FrZjE2MDAsIGJ1dCBhbGxvd3MgdG8gc2tpcCBzb21lIHJvdW5kc1xuZXhwb3J0IGZ1bmN0aW9uIGtlY2Nha1Aocywgcm91bmRzID0gMjQpIHtcbiAgICBjb25zdCBCID0gbmV3IFVpbnQzMkFycmF5KDUgKiAyKTtcbiAgICAvLyBOT1RFOiBhbGwgaW5kaWNlcyBhcmUgeDIgc2luY2Ugd2Ugc3RvcmUgc3RhdGUgYXMgdTMyIGluc3RlYWQgb2YgdTY0IChiaWdpbnRzIHRvIHNsb3cgaW4ganMpXG4gICAgZm9yIChsZXQgcm91bmQgPSAyNCAtIHJvdW5kczsgcm91bmQgPCAyNDsgcm91bmQrKykge1xuICAgICAgICAvLyBUaGV0YSDOuFxuICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDEwOyB4KyspXG4gICAgICAgICAgICBCW3hdID0gc1t4XSBeIHNbeCArIDEwXSBeIHNbeCArIDIwXSBeIHNbeCArIDMwXSBeIHNbeCArIDQwXTtcbiAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCAxMDsgeCArPSAyKSB7XG4gICAgICAgICAgICBjb25zdCBpZHgxID0gKHggKyA4KSAlIDEwO1xuICAgICAgICAgICAgY29uc3QgaWR4MCA9ICh4ICsgMikgJSAxMDtcbiAgICAgICAgICAgIGNvbnN0IEIwID0gQltpZHgwXTtcbiAgICAgICAgICAgIGNvbnN0IEIxID0gQltpZHgwICsgMV07XG4gICAgICAgICAgICBjb25zdCBUaCA9IHJvdGxIKEIwLCBCMSwgMSkgXiBCW2lkeDFdO1xuICAgICAgICAgICAgY29uc3QgVGwgPSByb3RsTChCMCwgQjEsIDEpIF4gQltpZHgxICsgMV07XG4gICAgICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IDUwOyB5ICs9IDEwKSB7XG4gICAgICAgICAgICAgICAgc1t4ICsgeV0gXj0gVGg7XG4gICAgICAgICAgICAgICAgc1t4ICsgeSArIDFdIF49IFRsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8vIFJobyAoz4EpIGFuZCBQaSAoz4ApXG4gICAgICAgIGxldCBjdXJIID0gc1syXTtcbiAgICAgICAgbGV0IGN1ckwgPSBzWzNdO1xuICAgICAgICBmb3IgKGxldCB0ID0gMDsgdCA8IDI0OyB0KyspIHtcbiAgICAgICAgICAgIGNvbnN0IHNoaWZ0ID0gU0hBM19ST1RMW3RdO1xuICAgICAgICAgICAgY29uc3QgVGggPSByb3RsSChjdXJILCBjdXJMLCBzaGlmdCk7XG4gICAgICAgICAgICBjb25zdCBUbCA9IHJvdGxMKGN1ckgsIGN1ckwsIHNoaWZ0KTtcbiAgICAgICAgICAgIGNvbnN0IFBJID0gU0hBM19QSVt0XTtcbiAgICAgICAgICAgIGN1ckggPSBzW1BJXTtcbiAgICAgICAgICAgIGN1ckwgPSBzW1BJICsgMV07XG4gICAgICAgICAgICBzW1BJXSA9IFRoO1xuICAgICAgICAgICAgc1tQSSArIDFdID0gVGw7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hpICjPhylcbiAgICAgICAgZm9yIChsZXQgeSA9IDA7IHkgPCA1MDsgeSArPSAxMCkge1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCAxMDsgeCsrKVxuICAgICAgICAgICAgICAgIEJbeF0gPSBzW3kgKyB4XTtcbiAgICAgICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgMTA7IHgrKylcbiAgICAgICAgICAgICAgICBzW3kgKyB4XSBePSB+QlsoeCArIDIpICUgMTBdICYgQlsoeCArIDQpICUgMTBdO1xuICAgICAgICB9XG4gICAgICAgIC8vIElvdGEgKM65KVxuICAgICAgICBzWzBdIF49IFNIQTNfSU9UQV9IW3JvdW5kXTtcbiAgICAgICAgc1sxXSBePSBTSEEzX0lPVEFfTFtyb3VuZF07XG4gICAgfVxuICAgIEIuZmlsbCgwKTtcbn1cbmV4cG9ydCBjbGFzcyBLZWNjYWsgZXh0ZW5kcyBIYXNoIHtcbiAgICAvLyBOT1RFOiB3ZSBhY2NlcHQgYXJndW1lbnRzIGluIGJ5dGVzIGluc3RlYWQgb2YgYml0cyBoZXJlLlxuICAgIGNvbnN0cnVjdG9yKGJsb2NrTGVuLCBzdWZmaXgsIG91dHB1dExlbiwgZW5hYmxlWE9GID0gZmFsc2UsIHJvdW5kcyA9IDI0KSB7XG4gICAgICAgIHN1cGVyKCk7XG4gICAgICAgIHRoaXMuYmxvY2tMZW4gPSBibG9ja0xlbjtcbiAgICAgICAgdGhpcy5zdWZmaXggPSBzdWZmaXg7XG4gICAgICAgIHRoaXMub3V0cHV0TGVuID0gb3V0cHV0TGVuO1xuICAgICAgICB0aGlzLmVuYWJsZVhPRiA9IGVuYWJsZVhPRjtcbiAgICAgICAgdGhpcy5yb3VuZHMgPSByb3VuZHM7XG4gICAgICAgIHRoaXMucG9zID0gMDtcbiAgICAgICAgdGhpcy5wb3NPdXQgPSAwO1xuICAgICAgICB0aGlzLmZpbmlzaGVkID0gZmFsc2U7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gZmFsc2U7XG4gICAgICAgIC8vIENhbiBiZSBwYXNzZWQgZnJvbSB1c2VyIGFzIGRrTGVuXG4gICAgICAgIGFzc2VydC5udW1iZXIob3V0cHV0TGVuKTtcbiAgICAgICAgLy8gMTYwMCA9IDV4NSBtYXRyaXggb2YgNjRiaXQuICAxNjAwIGJpdHMgPT09IDIwMCBieXRlc1xuICAgICAgICBpZiAoMCA+PSB0aGlzLmJsb2NrTGVuIHx8IHRoaXMuYmxvY2tMZW4gPj0gMjAwKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdTaGEzIHN1cHBvcnRzIG9ubHkga2VjY2FrLWYxNjAwIGZ1bmN0aW9uJyk7XG4gICAgICAgIHRoaXMuc3RhdGUgPSBuZXcgVWludDhBcnJheSgyMDApO1xuICAgICAgICB0aGlzLnN0YXRlMzIgPSB1MzIodGhpcy5zdGF0ZSk7XG4gICAgfVxuICAgIGtlY2NhaygpIHtcbiAgICAgICAga2VjY2FrUCh0aGlzLnN0YXRlMzIsIHRoaXMucm91bmRzKTtcbiAgICAgICAgdGhpcy5wb3NPdXQgPSAwO1xuICAgICAgICB0aGlzLnBvcyA9IDA7XG4gICAgfVxuICAgIHVwZGF0ZShkYXRhKSB7XG4gICAgICAgIGFzc2VydC5leGlzdHModGhpcyk7XG4gICAgICAgIGNvbnN0IHsgYmxvY2tMZW4sIHN0YXRlIH0gPSB0aGlzO1xuICAgICAgICBkYXRhID0gdG9CeXRlcyhkYXRhKTtcbiAgICAgICAgY29uc3QgbGVuID0gZGF0YS5sZW5ndGg7XG4gICAgICAgIGZvciAobGV0IHBvcyA9IDA7IHBvcyA8IGxlbjspIHtcbiAgICAgICAgICAgIGNvbnN0IHRha2UgPSBNYXRoLm1pbihibG9ja0xlbiAtIHRoaXMucG9zLCBsZW4gLSBwb3MpO1xuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0YWtlOyBpKyspXG4gICAgICAgICAgICAgICAgc3RhdGVbdGhpcy5wb3MrK10gXj0gZGF0YVtwb3MrK107XG4gICAgICAgICAgICBpZiAodGhpcy5wb3MgPT09IGJsb2NrTGVuKVxuICAgICAgICAgICAgICAgIHRoaXMua2VjY2FrKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuICAgIGZpbmlzaCgpIHtcbiAgICAgICAgaWYgKHRoaXMuZmluaXNoZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIHRoaXMuZmluaXNoZWQgPSB0cnVlO1xuICAgICAgICBjb25zdCB7IHN0YXRlLCBzdWZmaXgsIHBvcywgYmxvY2tMZW4gfSA9IHRoaXM7XG4gICAgICAgIC8vIERvIHRoZSBwYWRkaW5nXG4gICAgICAgIHN0YXRlW3Bvc10gXj0gc3VmZml4O1xuICAgICAgICBpZiAoKHN1ZmZpeCAmIDB4ODApICE9PSAwICYmIHBvcyA9PT0gYmxvY2tMZW4gLSAxKVxuICAgICAgICAgICAgdGhpcy5rZWNjYWsoKTtcbiAgICAgICAgc3RhdGVbYmxvY2tMZW4gLSAxXSBePSAweDgwO1xuICAgICAgICB0aGlzLmtlY2NhaygpO1xuICAgIH1cbiAgICB3cml0ZUludG8ob3V0KSB7XG4gICAgICAgIGFzc2VydC5leGlzdHModGhpcywgZmFsc2UpO1xuICAgICAgICBhc3NlcnQuYnl0ZXMob3V0KTtcbiAgICAgICAgdGhpcy5maW5pc2goKTtcbiAgICAgICAgY29uc3QgYnVmZmVyT3V0ID0gdGhpcy5zdGF0ZTtcbiAgICAgICAgY29uc3QgeyBibG9ja0xlbiB9ID0gdGhpcztcbiAgICAgICAgZm9yIChsZXQgcG9zID0gMCwgbGVuID0gb3V0Lmxlbmd0aDsgcG9zIDwgbGVuOykge1xuICAgICAgICAgICAgaWYgKHRoaXMucG9zT3V0ID49IGJsb2NrTGVuKVxuICAgICAgICAgICAgICAgIHRoaXMua2VjY2FrKCk7XG4gICAgICAgICAgICBjb25zdCB0YWtlID0gTWF0aC5taW4oYmxvY2tMZW4gLSB0aGlzLnBvc091dCwgbGVuIC0gcG9zKTtcbiAgICAgICAgICAgIG91dC5zZXQoYnVmZmVyT3V0LnN1YmFycmF5KHRoaXMucG9zT3V0LCB0aGlzLnBvc091dCArIHRha2UpLCBwb3MpO1xuICAgICAgICAgICAgdGhpcy5wb3NPdXQgKz0gdGFrZTtcbiAgICAgICAgICAgIHBvcyArPSB0YWtlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBvdXQ7XG4gICAgfVxuICAgIHhvZkludG8ob3V0KSB7XG4gICAgICAgIC8vIFNoYTMvS2VjY2FrIHVzYWdlIHdpdGggWE9GIGlzIHByb2JhYmx5IG1pc3Rha2UsIG9ubHkgU0hBS0UgaW5zdGFuY2VzIGNhbiBkbyBYT0ZcbiAgICAgICAgaWYgKCF0aGlzLmVuYWJsZVhPRilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignWE9GIGlzIG5vdCBwb3NzaWJsZSBmb3IgdGhpcyBpbnN0YW5jZScpO1xuICAgICAgICByZXR1cm4gdGhpcy53cml0ZUludG8ob3V0KTtcbiAgICB9XG4gICAgeG9mKGJ5dGVzKSB7XG4gICAgICAgIGFzc2VydC5udW1iZXIoYnl0ZXMpO1xuICAgICAgICByZXR1cm4gdGhpcy54b2ZJbnRvKG5ldyBVaW50OEFycmF5KGJ5dGVzKSk7XG4gICAgfVxuICAgIGRpZ2VzdEludG8ob3V0KSB7XG4gICAgICAgIGFzc2VydC5vdXRwdXQob3V0LCB0aGlzKTtcbiAgICAgICAgaWYgKHRoaXMuZmluaXNoZWQpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2RpZ2VzdCgpIHdhcyBhbHJlYWR5IGNhbGxlZCcpO1xuICAgICAgICB0aGlzLndyaXRlSW50byhvdXQpO1xuICAgICAgICB0aGlzLmRlc3Ryb3koKTtcbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG4gICAgZGlnZXN0KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kaWdlc3RJbnRvKG5ldyBVaW50OEFycmF5KHRoaXMub3V0cHV0TGVuKSk7XG4gICAgfVxuICAgIGRlc3Ryb3koKSB7XG4gICAgICAgIHRoaXMuZGVzdHJveWVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdGF0ZS5maWxsKDApO1xuICAgIH1cbiAgICBfY2xvbmVJbnRvKHRvKSB7XG4gICAgICAgIGNvbnN0IHsgYmxvY2tMZW4sIHN1ZmZpeCwgb3V0cHV0TGVuLCByb3VuZHMsIGVuYWJsZVhPRiB9ID0gdGhpcztcbiAgICAgICAgdG8gfHwgKHRvID0gbmV3IEtlY2NhayhibG9ja0xlbiwgc3VmZml4LCBvdXRwdXRMZW4sIGVuYWJsZVhPRiwgcm91bmRzKSk7XG4gICAgICAgIHRvLnN0YXRlMzIuc2V0KHRoaXMuc3RhdGUzMik7XG4gICAgICAgIHRvLnBvcyA9IHRoaXMucG9zO1xuICAgICAgICB0by5wb3NPdXQgPSB0aGlzLnBvc091dDtcbiAgICAgICAgdG8uZmluaXNoZWQgPSB0aGlzLmZpbmlzaGVkO1xuICAgICAgICB0by5yb3VuZHMgPSByb3VuZHM7XG4gICAgICAgIC8vIFN1ZmZpeCBjYW4gY2hhbmdlIGluIGNTSEFLRVxuICAgICAgICB0by5zdWZmaXggPSBzdWZmaXg7XG4gICAgICAgIHRvLm91dHB1dExlbiA9IG91dHB1dExlbjtcbiAgICAgICAgdG8uZW5hYmxlWE9GID0gZW5hYmxlWE9GO1xuICAgICAgICB0by5kZXN0cm95ZWQgPSB0aGlzLmRlc3Ryb3llZDtcbiAgICAgICAgcmV0dXJuIHRvO1xuICAgIH1cbn1cbmNvbnN0IGdlbiA9IChzdWZmaXgsIGJsb2NrTGVuLCBvdXRwdXRMZW4pID0+IHdyYXBDb25zdHJ1Y3RvcigoKSA9PiBuZXcgS2VjY2FrKGJsb2NrTGVuLCBzdWZmaXgsIG91dHB1dExlbikpO1xuZXhwb3J0IGNvbnN0IHNoYTNfMjI0ID0gZ2VuKDB4MDYsIDE0NCwgMjI0IC8gOCk7XG4vKipcbiAqIFNIQTMtMjU2IGhhc2ggZnVuY3Rpb25cbiAqIEBwYXJhbSBtZXNzYWdlIC0gdGhhdCB3b3VsZCBiZSBoYXNoZWRcbiAqL1xuZXhwb3J0IGNvbnN0IHNoYTNfMjU2ID0gZ2VuKDB4MDYsIDEzNiwgMjU2IC8gOCk7XG5leHBvcnQgY29uc3Qgc2hhM18zODQgPSBnZW4oMHgwNiwgMTA0LCAzODQgLyA4KTtcbmV4cG9ydCBjb25zdCBzaGEzXzUxMiA9IGdlbigweDA2LCA3MiwgNTEyIC8gOCk7XG5leHBvcnQgY29uc3Qga2VjY2FrXzIyNCA9IGdlbigweDAxLCAxNDQsIDIyNCAvIDgpO1xuLyoqXG4gKiBrZWNjYWstMjU2IGhhc2ggZnVuY3Rpb24uIERpZmZlcmVudCBmcm9tIFNIQTMtMjU2LlxuICogQHBhcmFtIG1lc3NhZ2UgLSB0aGF0IHdvdWxkIGJlIGhhc2hlZFxuICovXG5leHBvcnQgY29uc3Qga2VjY2FrXzI1NiA9IGdlbigweDAxLCAxMzYsIDI1NiAvIDgpO1xuZXhwb3J0IGNvbnN0IGtlY2Nha18zODQgPSBnZW4oMHgwMSwgMTA0LCAzODQgLyA4KTtcbmV4cG9ydCBjb25zdCBrZWNjYWtfNTEyID0gZ2VuKDB4MDEsIDcyLCA1MTIgLyA4KTtcbmNvbnN0IGdlblNoYWtlID0gKHN1ZmZpeCwgYmxvY2tMZW4sIG91dHB1dExlbikgPT4gd3JhcFhPRkNvbnN0cnVjdG9yV2l0aE9wdHMoKG9wdHMgPSB7fSkgPT4gbmV3IEtlY2NhayhibG9ja0xlbiwgc3VmZml4LCBvcHRzLmRrTGVuID09PSB1bmRlZmluZWQgPyBvdXRwdXRMZW4gOiBvcHRzLmRrTGVuLCB0cnVlKSk7XG5leHBvcnQgY29uc3Qgc2hha2UxMjggPSBnZW5TaGFrZSgweDFmLCAxNjgsIDEyOCAvIDgpO1xuZXhwb3J0IGNvbnN0IHNoYWtlMjU2ID0gZ2VuU2hha2UoMHgxZiwgMTM2LCAyNTYgLyA4KTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXNoYTMuanMubWFwIiwiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuLy8gMTAwIGxpbmVzIG9mIGNvZGUgaW4gdGhlIGZpbGUgYXJlIGR1cGxpY2F0ZWQgZnJvbSBub2JsZS1oYXNoZXMgKHV0aWxzKS5cbi8vIFRoaXMgaXMgT0s6IGBhYnN0cmFjdGAgZGlyZWN0b3J5IGRvZXMgbm90IHVzZSBub2JsZS1oYXNoZXMuXG4vLyBVc2VyIG1heSBvcHQtaW4gaW50byB1c2luZyBkaWZmZXJlbnQgaGFzaGluZyBsaWJyYXJ5LiBUaGlzIHdheSwgbm9ibGUtaGFzaGVzXG4vLyB3b24ndCBiZSBpbmNsdWRlZCBpbnRvIHRoZWlyIGJ1bmRsZS5cbmNvbnN0IF8wbiA9IEJpZ0ludCgwKTtcbmNvbnN0IF8xbiA9IEJpZ0ludCgxKTtcbmNvbnN0IF8ybiA9IEJpZ0ludCgyKTtcbmNvbnN0IHU4YSA9IChhKSA9PiBhIGluc3RhbmNlb2YgVWludDhBcnJheTtcbmNvbnN0IGhleGVzID0gQXJyYXkuZnJvbSh7IGxlbmd0aDogMjU2IH0sICh2LCBpKSA9PiBpLnRvU3RyaW5nKDE2KS5wYWRTdGFydCgyLCAnMCcpKTtcbi8qKlxuICogQGV4YW1wbGUgYnl0ZXNUb0hleChVaW50OEFycmF5LmZyb20oWzB4Y2EsIDB4ZmUsIDB4MDEsIDB4MjNdKSkgLy8gJ2NhZmUwMTIzJ1xuICovXG5leHBvcnQgZnVuY3Rpb24gYnl0ZXNUb0hleChieXRlcykge1xuICAgIGlmICghdThhKGJ5dGVzKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGV4cGVjdGVkJyk7XG4gICAgLy8gcHJlLWNhY2hpbmcgaW1wcm92ZXMgdGhlIHNwZWVkIDZ4XG4gICAgbGV0IGhleCA9ICcnO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaGV4ICs9IGhleGVzW2J5dGVzW2ldXTtcbiAgICB9XG4gICAgcmV0dXJuIGhleDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJUb0hleFVucGFkZGVkKG51bSkge1xuICAgIGNvbnN0IGhleCA9IG51bS50b1N0cmluZygxNik7XG4gICAgcmV0dXJuIGhleC5sZW5ndGggJiAxID8gYDAke2hleH1gIDogaGV4O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGhleFRvTnVtYmVyKGhleCkge1xuICAgIGlmICh0eXBlb2YgaGV4ICE9PSAnc3RyaW5nJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdoZXggc3RyaW5nIGV4cGVjdGVkLCBnb3QgJyArIHR5cGVvZiBoZXgpO1xuICAgIC8vIEJpZyBFbmRpYW5cbiAgICByZXR1cm4gQmlnSW50KGhleCA9PT0gJycgPyAnMCcgOiBgMHgke2hleH1gKTtcbn1cbi8qKlxuICogQGV4YW1wbGUgaGV4VG9CeXRlcygnY2FmZTAxMjMnKSAvLyBVaW50OEFycmF5LmZyb20oWzB4Y2EsIDB4ZmUsIDB4MDEsIDB4MjNdKVxuICovXG5leHBvcnQgZnVuY3Rpb24gaGV4VG9CeXRlcyhoZXgpIHtcbiAgICBpZiAodHlwZW9mIGhleCAhPT0gJ3N0cmluZycpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGV4IHN0cmluZyBleHBlY3RlZCwgZ290ICcgKyB0eXBlb2YgaGV4KTtcbiAgICBjb25zdCBsZW4gPSBoZXgubGVuZ3RoO1xuICAgIGlmIChsZW4gJSAyKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3BhZGRlZCBoZXggc3RyaW5nIGV4cGVjdGVkLCBnb3QgdW5wYWRkZWQgaGV4IG9mIGxlbmd0aCAnICsgbGVuKTtcbiAgICBjb25zdCBhcnJheSA9IG5ldyBVaW50OEFycmF5KGxlbiAvIDIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgaiA9IGkgKiAyO1xuICAgICAgICBjb25zdCBoZXhCeXRlID0gaGV4LnNsaWNlKGosIGogKyAyKTtcbiAgICAgICAgY29uc3QgYnl0ZSA9IE51bWJlci5wYXJzZUludChoZXhCeXRlLCAxNik7XG4gICAgICAgIGlmIChOdW1iZXIuaXNOYU4oYnl0ZSkgfHwgYnl0ZSA8IDApXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgYnl0ZSBzZXF1ZW5jZScpO1xuICAgICAgICBhcnJheVtpXSA9IGJ5dGU7XG4gICAgfVxuICAgIHJldHVybiBhcnJheTtcbn1cbi8vIEJFOiBCaWcgRW5kaWFuLCBMRTogTGl0dGxlIEVuZGlhblxuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVzVG9OdW1iZXJCRShieXRlcykge1xuICAgIHJldHVybiBoZXhUb051bWJlcihieXRlc1RvSGV4KGJ5dGVzKSk7XG59XG5leHBvcnQgZnVuY3Rpb24gYnl0ZXNUb051bWJlckxFKGJ5dGVzKSB7XG4gICAgaWYgKCF1OGEoYnl0ZXMpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgZXhwZWN0ZWQnKTtcbiAgICByZXR1cm4gaGV4VG9OdW1iZXIoYnl0ZXNUb0hleChVaW50OEFycmF5LmZyb20oYnl0ZXMpLnJldmVyc2UoKSkpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIG51bWJlclRvQnl0ZXNCRShuLCBsZW4pIHtcbiAgICByZXR1cm4gaGV4VG9CeXRlcyhuLnRvU3RyaW5nKDE2KS5wYWRTdGFydChsZW4gKiAyLCAnMCcpKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJUb0J5dGVzTEUobiwgbGVuKSB7XG4gICAgcmV0dXJuIG51bWJlclRvQnl0ZXNCRShuLCBsZW4pLnJldmVyc2UoKTtcbn1cbi8vIFVucGFkZGVkLCByYXJlbHkgdXNlZFxuZXhwb3J0IGZ1bmN0aW9uIG51bWJlclRvVmFyQnl0ZXNCRShuKSB7XG4gICAgcmV0dXJuIGhleFRvQnl0ZXMobnVtYmVyVG9IZXhVbnBhZGRlZChuKSk7XG59XG4vKipcbiAqIFRha2VzIGhleCBzdHJpbmcgb3IgVWludDhBcnJheSwgY29udmVydHMgdG8gVWludDhBcnJheS5cbiAqIFZhbGlkYXRlcyBvdXRwdXQgbGVuZ3RoLlxuICogV2lsbCB0aHJvdyBlcnJvciBmb3Igb3RoZXIgdHlwZXMuXG4gKiBAcGFyYW0gdGl0bGUgZGVzY3JpcHRpdmUgdGl0bGUgZm9yIGFuIGVycm9yIGUuZy4gJ3ByaXZhdGUga2V5J1xuICogQHBhcmFtIGhleCBoZXggc3RyaW5nIG9yIFVpbnQ4QXJyYXlcbiAqIEBwYXJhbSBleHBlY3RlZExlbmd0aCBvcHRpb25hbCwgd2lsbCBjb21wYXJlIHRvIHJlc3VsdCBhcnJheSdzIGxlbmd0aFxuICogQHJldHVybnNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVuc3VyZUJ5dGVzKHRpdGxlLCBoZXgsIGV4cGVjdGVkTGVuZ3RoKSB7XG4gICAgbGV0IHJlcztcbiAgICBpZiAodHlwZW9mIGhleCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlcyA9IGhleFRvQnl0ZXMoaGV4KTtcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RpdGxlfSBtdXN0IGJlIHZhbGlkIGhleCBzdHJpbmcsIGdvdCBcIiR7aGV4fVwiLiBDYXVzZTogJHtlfWApO1xuICAgICAgICB9XG4gICAgfVxuICAgIGVsc2UgaWYgKHU4YShoZXgpKSB7XG4gICAgICAgIC8vIFVpbnQ4QXJyYXkuZnJvbSgpIGluc3RlYWQgb2YgaGFzaC5zbGljZSgpIGJlY2F1c2Ugbm9kZS5qcyBCdWZmZXJcbiAgICAgICAgLy8gaXMgaW5zdGFuY2Ugb2YgVWludDhBcnJheSwgYW5kIGl0cyBzbGljZSgpIGNyZWF0ZXMgKiptdXRhYmxlKiogY29weVxuICAgICAgICByZXMgPSBVaW50OEFycmF5LmZyb20oaGV4KTtcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aXRsZX0gbXVzdCBiZSBoZXggc3RyaW5nIG9yIFVpbnQ4QXJyYXlgKTtcbiAgICB9XG4gICAgY29uc3QgbGVuID0gcmVzLmxlbmd0aDtcbiAgICBpZiAodHlwZW9mIGV4cGVjdGVkTGVuZ3RoID09PSAnbnVtYmVyJyAmJiBsZW4gIT09IGV4cGVjdGVkTGVuZ3RoKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGl0bGV9IGV4cGVjdGVkICR7ZXhwZWN0ZWRMZW5ndGh9IGJ5dGVzLCBnb3QgJHtsZW59YCk7XG4gICAgcmV0dXJuIHJlcztcbn1cbi8qKlxuICogQ29waWVzIHNldmVyYWwgVWludDhBcnJheXMgaW50byBvbmUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb25jYXRCeXRlcyguLi5hcnJheXMpIHtcbiAgICBjb25zdCByID0gbmV3IFVpbnQ4QXJyYXkoYXJyYXlzLnJlZHVjZSgoc3VtLCBhKSA9PiBzdW0gKyBhLmxlbmd0aCwgMCkpO1xuICAgIGxldCBwYWQgPSAwOyAvLyB3YWxrIHRocm91Z2ggZWFjaCBpdGVtLCBlbnN1cmUgdGhleSBoYXZlIHByb3BlciB0eXBlXG4gICAgYXJyYXlzLmZvckVhY2goKGEpID0+IHtcbiAgICAgICAgaWYgKCF1OGEoYSkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgZXhwZWN0ZWQnKTtcbiAgICAgICAgci5zZXQoYSwgcGFkKTtcbiAgICAgICAgcGFkICs9IGEubGVuZ3RoO1xuICAgIH0pO1xuICAgIHJldHVybiByO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGVxdWFsQnl0ZXMoYjEsIGIyKSB7XG4gICAgLy8gV2UgZG9uJ3QgY2FyZSBhYm91dCB0aW1pbmcgYXR0YWNrcyBoZXJlXG4gICAgaWYgKGIxLmxlbmd0aCAhPT0gYjIubGVuZ3RoKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBiMS5sZW5ndGg7IGkrKylcbiAgICAgICAgaWYgKGIxW2ldICE9PSBiMltpXSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdHJ1ZTtcbn1cbi8qKlxuICogQGV4YW1wbGUgdXRmOFRvQnl0ZXMoJ2FiYycpIC8vIG5ldyBVaW50OEFycmF5KFs5NywgOTgsIDk5XSlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHV0ZjhUb0J5dGVzKHN0cikge1xuICAgIGlmICh0eXBlb2Ygc3RyICE9PSAnc3RyaW5nJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1dGY4VG9CeXRlcyBleHBlY3RlZCBzdHJpbmcsIGdvdCAke3R5cGVvZiBzdHJ9YCk7XG4gICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShzdHIpKTsgLy8gaHR0cHM6Ly9idWd6aWwubGEvMTY4MTgwOVxufVxuLy8gQml0IG9wZXJhdGlvbnNcbi8qKlxuICogQ2FsY3VsYXRlcyBhbW91bnQgb2YgYml0cyBpbiBhIGJpZ2ludC5cbiAqIFNhbWUgYXMgYG4udG9TdHJpbmcoMikubGVuZ3RoYFxuICovXG5leHBvcnQgZnVuY3Rpb24gYml0TGVuKG4pIHtcbiAgICBsZXQgbGVuO1xuICAgIGZvciAobGVuID0gMDsgbiA+IF8wbjsgbiA+Pj0gXzFuLCBsZW4gKz0gMSlcbiAgICAgICAgO1xuICAgIHJldHVybiBsZW47XG59XG4vKipcbiAqIEdldHMgc2luZ2xlIGJpdCBhdCBwb3NpdGlvbi5cbiAqIE5PVEU6IGZpcnN0IGJpdCBwb3NpdGlvbiBpcyAwIChzYW1lIGFzIGFycmF5cylcbiAqIFNhbWUgYXMgYCEhK0FycmF5LmZyb20obi50b1N0cmluZygyKSkucmV2ZXJzZSgpW3Bvc11gXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBiaXRHZXQobiwgcG9zKSB7XG4gICAgcmV0dXJuIChuID4+IEJpZ0ludChwb3MpKSAmIF8xbjtcbn1cbi8qKlxuICogU2V0cyBzaW5nbGUgYml0IGF0IHBvc2l0aW9uLlxuICovXG5leHBvcnQgY29uc3QgYml0U2V0ID0gKG4sIHBvcywgdmFsdWUpID0+IHtcbiAgICByZXR1cm4gbiB8ICgodmFsdWUgPyBfMW4gOiBfMG4pIDw8IEJpZ0ludChwb3MpKTtcbn07XG4vKipcbiAqIENhbGN1bGF0ZSBtYXNrIGZvciBOIGJpdHMuIE5vdCB1c2luZyAqKiBvcGVyYXRvciB3aXRoIGJpZ2ludHMgYmVjYXVzZSBvZiBvbGQgZW5naW5lcy5cbiAqIFNhbWUgYXMgQmlnSW50KGAwYiR7QXJyYXkoaSkuZmlsbCgnMScpLmpvaW4oJycpfWApXG4gKi9cbmV4cG9ydCBjb25zdCBiaXRNYXNrID0gKG4pID0+IChfMm4gPDwgQmlnSW50KG4gLSAxKSkgLSBfMW47XG4vLyBEUkJHXG5jb25zdCB1OG4gPSAoZGF0YSkgPT4gbmV3IFVpbnQ4QXJyYXkoZGF0YSk7IC8vIGNyZWF0ZXMgVWludDhBcnJheVxuY29uc3QgdThmciA9IChhcnIpID0+IFVpbnQ4QXJyYXkuZnJvbShhcnIpOyAvLyBhbm90aGVyIHNob3J0Y3V0XG4vKipcbiAqIE1pbmltYWwgSE1BQy1EUkJHIGZyb20gTklTVCA4MDAtOTAgZm9yIFJGQzY5Nzkgc2lncy5cbiAqIEByZXR1cm5zIGZ1bmN0aW9uIHRoYXQgd2lsbCBjYWxsIERSQkcgdW50aWwgMm5kIGFyZyByZXR1cm5zIHNvbWV0aGluZyBtZWFuaW5nZnVsXG4gKiBAZXhhbXBsZVxuICogICBjb25zdCBkcmJnID0gY3JlYXRlSG1hY0RSQkc8S2V5PigzMiwgMzIsIGhtYWMpO1xuICogICBkcmJnKHNlZWQsIGJ5dGVzVG9LZXkpOyAvLyBieXRlc1RvS2V5IG11c3QgcmV0dXJuIEtleSBvciB1bmRlZmluZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUhtYWNEcmJnKGhhc2hMZW4sIHFCeXRlTGVuLCBobWFjRm4pIHtcbiAgICBpZiAodHlwZW9mIGhhc2hMZW4gIT09ICdudW1iZXInIHx8IGhhc2hMZW4gPCAyKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2hhc2hMZW4gbXVzdCBiZSBhIG51bWJlcicpO1xuICAgIGlmICh0eXBlb2YgcUJ5dGVMZW4gIT09ICdudW1iZXInIHx8IHFCeXRlTGVuIDwgMilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdxQnl0ZUxlbiBtdXN0IGJlIGEgbnVtYmVyJyk7XG4gICAgaWYgKHR5cGVvZiBobWFjRm4gIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaG1hY0ZuIG11c3QgYmUgYSBmdW5jdGlvbicpO1xuICAgIC8vIFN0ZXAgQiwgU3RlcCBDOiBzZXQgaGFzaExlbiB0byA4KmNlaWwoaGxlbi84KVxuICAgIGxldCB2ID0gdThuKGhhc2hMZW4pOyAvLyBNaW5pbWFsIG5vbi1mdWxsLXNwZWMgSE1BQy1EUkJHIGZyb20gTklTVCA4MDAtOTAgZm9yIFJGQzY5Nzkgc2lncy5cbiAgICBsZXQgayA9IHU4bihoYXNoTGVuKTsgLy8gU3RlcHMgQiBhbmQgQyBvZiBSRkM2OTc5IDMuMjogc2V0IGhhc2hMZW4sIGluIG91ciBjYXNlIGFsd2F5cyBzYW1lXG4gICAgbGV0IGkgPSAwOyAvLyBJdGVyYXRpb25zIGNvdW50ZXIsIHdpbGwgdGhyb3cgd2hlbiBvdmVyIDEwMDBcbiAgICBjb25zdCByZXNldCA9ICgpID0+IHtcbiAgICAgICAgdi5maWxsKDEpO1xuICAgICAgICBrLmZpbGwoMCk7XG4gICAgICAgIGkgPSAwO1xuICAgIH07XG4gICAgY29uc3QgaCA9ICguLi5iKSA9PiBobWFjRm4oaywgdiwgLi4uYik7IC8vIGhtYWMoaykodiwgLi4udmFsdWVzKVxuICAgIGNvbnN0IHJlc2VlZCA9IChzZWVkID0gdThuKCkpID0+IHtcbiAgICAgICAgLy8gSE1BQy1EUkJHIHJlc2VlZCgpIGZ1bmN0aW9uLiBTdGVwcyBELUdcbiAgICAgICAgayA9IGgodThmcihbMHgwMF0pLCBzZWVkKTsgLy8gayA9IGhtYWMoayB8fCB2IHx8IDB4MDAgfHwgc2VlZClcbiAgICAgICAgdiA9IGgoKTsgLy8gdiA9IGhtYWMoayB8fCB2KVxuICAgICAgICBpZiAoc2VlZC5sZW5ndGggPT09IDApXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGsgPSBoKHU4ZnIoWzB4MDFdKSwgc2VlZCk7IC8vIGsgPSBobWFjKGsgfHwgdiB8fCAweDAxIHx8IHNlZWQpXG4gICAgICAgIHYgPSBoKCk7IC8vIHYgPSBobWFjKGsgfHwgdilcbiAgICB9O1xuICAgIGNvbnN0IGdlbiA9ICgpID0+IHtcbiAgICAgICAgLy8gSE1BQy1EUkJHIGdlbmVyYXRlKCkgZnVuY3Rpb25cbiAgICAgICAgaWYgKGkrKyA+PSAxMDAwKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdkcmJnOiB0cmllZCAxMDAwIHZhbHVlcycpO1xuICAgICAgICBsZXQgbGVuID0gMDtcbiAgICAgICAgY29uc3Qgb3V0ID0gW107XG4gICAgICAgIHdoaWxlIChsZW4gPCBxQnl0ZUxlbikge1xuICAgICAgICAgICAgdiA9IGgoKTtcbiAgICAgICAgICAgIGNvbnN0IHNsID0gdi5zbGljZSgpO1xuICAgICAgICAgICAgb3V0LnB1c2goc2wpO1xuICAgICAgICAgICAgbGVuICs9IHYubGVuZ3RoO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb25jYXRCeXRlcyguLi5vdXQpO1xuICAgIH07XG4gICAgY29uc3QgZ2VuVW50aWwgPSAoc2VlZCwgcHJlZCkgPT4ge1xuICAgICAgICByZXNldCgpO1xuICAgICAgICByZXNlZWQoc2VlZCk7IC8vIFN0ZXBzIEQtR1xuICAgICAgICBsZXQgcmVzID0gdW5kZWZpbmVkOyAvLyBTdGVwIEg6IGdyaW5kIHVudGlsIGsgaXMgaW4gWzEuLm4tMV1cbiAgICAgICAgd2hpbGUgKCEocmVzID0gcHJlZChnZW4oKSkpKVxuICAgICAgICAgICAgcmVzZWVkKCk7XG4gICAgICAgIHJlc2V0KCk7XG4gICAgICAgIHJldHVybiByZXM7XG4gICAgfTtcbiAgICByZXR1cm4gZ2VuVW50aWw7XG59XG4vLyBWYWxpZGF0aW5nIGN1cnZlcyBhbmQgZmllbGRzXG5jb25zdCB2YWxpZGF0b3JGbnMgPSB7XG4gICAgYmlnaW50OiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnYmlnaW50JyxcbiAgICBmdW5jdGlvbjogKHZhbCkgPT4gdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJyxcbiAgICBib29sZWFuOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnYm9vbGVhbicsXG4gICAgc3RyaW5nOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnc3RyaW5nJyxcbiAgICBpc1NhZmVJbnRlZ2VyOiAodmFsKSA9PiBOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWwpLFxuICAgIGFycmF5OiAodmFsKSA9PiBBcnJheS5pc0FycmF5KHZhbCksXG4gICAgZmllbGQ6ICh2YWwsIG9iamVjdCkgPT4gb2JqZWN0LkZwLmlzVmFsaWQodmFsKSxcbiAgICBoYXNoOiAodmFsKSA9PiB0eXBlb2YgdmFsID09PSAnZnVuY3Rpb24nICYmIE51bWJlci5pc1NhZmVJbnRlZ2VyKHZhbC5vdXRwdXRMZW4pLFxufTtcbi8vIHR5cGUgUmVjb3JkPEsgZXh0ZW5kcyBzdHJpbmcgfCBudW1iZXIgfCBzeW1ib2wsIFQ+ID0geyBbUCBpbiBLXTogVDsgfVxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlT2JqZWN0KG9iamVjdCwgdmFsaWRhdG9ycywgb3B0VmFsaWRhdG9ycyA9IHt9KSB7XG4gICAgY29uc3QgY2hlY2tGaWVsZCA9IChmaWVsZE5hbWUsIHR5cGUsIGlzT3B0aW9uYWwpID0+IHtcbiAgICAgICAgY29uc3QgY2hlY2tWYWwgPSB2YWxpZGF0b3JGbnNbdHlwZV07XG4gICAgICAgIGlmICh0eXBlb2YgY2hlY2tWYWwgIT09ICdmdW5jdGlvbicpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgdmFsaWRhdG9yIFwiJHt0eXBlfVwiLCBleHBlY3RlZCBmdW5jdGlvbmApO1xuICAgICAgICBjb25zdCB2YWwgPSBvYmplY3RbZmllbGROYW1lXTtcbiAgICAgICAgaWYgKGlzT3B0aW9uYWwgJiYgdmFsID09PSB1bmRlZmluZWQpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIGlmICghY2hlY2tWYWwodmFsLCBvYmplY3QpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgcGFyYW0gJHtTdHJpbmcoZmllbGROYW1lKX09JHt2YWx9ICgke3R5cGVvZiB2YWx9KSwgZXhwZWN0ZWQgJHt0eXBlfWApO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBmb3IgKGNvbnN0IFtmaWVsZE5hbWUsIHR5cGVdIG9mIE9iamVjdC5lbnRyaWVzKHZhbGlkYXRvcnMpKVxuICAgICAgICBjaGVja0ZpZWxkKGZpZWxkTmFtZSwgdHlwZSwgZmFsc2UpO1xuICAgIGZvciAoY29uc3QgW2ZpZWxkTmFtZSwgdHlwZV0gb2YgT2JqZWN0LmVudHJpZXMob3B0VmFsaWRhdG9ycykpXG4gICAgICAgIGNoZWNrRmllbGQoZmllbGROYW1lLCB0eXBlLCB0cnVlKTtcbiAgICByZXR1cm4gb2JqZWN0O1xufVxuLy8gdmFsaWRhdGUgdHlwZSB0ZXN0c1xuLy8gY29uc3QgbzogeyBhOiBudW1iZXI7IGI6IG51bWJlcjsgYzogbnVtYmVyIH0gPSB7IGE6IDEsIGI6IDUsIGM6IDYgfTtcbi8vIGNvbnN0IHowID0gdmFsaWRhdGVPYmplY3QobywgeyBhOiAnaXNTYWZlSW50ZWdlcicgfSwgeyBjOiAnYmlnaW50JyB9KTsgLy8gT2shXG4vLyAvLyBTaG91bGQgZmFpbCB0eXBlLWNoZWNrXG4vLyBjb25zdCB6MSA9IHZhbGlkYXRlT2JqZWN0KG8sIHsgYTogJ3RtcCcgfSwgeyBjOiAnenonIH0pO1xuLy8gY29uc3QgejIgPSB2YWxpZGF0ZU9iamVjdChvLCB7IGE6ICdpc1NhZmVJbnRlZ2VyJyB9LCB7IGM6ICd6eicgfSk7XG4vLyBjb25zdCB6MyA9IHZhbGlkYXRlT2JqZWN0KG8sIHsgdGVzdDogJ2Jvb2xlYW4nLCB6OiAnYnVnJyB9KTtcbi8vIGNvbnN0IHo0ID0gdmFsaWRhdGVPYmplY3QobywgeyBhOiAnYm9vbGVhbicsIHo6ICdidWcnIH0pO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dXRpbHMuanMubWFwIiwiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuLy8gVXRpbGl0aWVzIGZvciBtb2R1bGFyIGFyaXRobWV0aWNzIGFuZCBmaW5pdGUgZmllbGRzXG5pbXBvcnQgeyBiaXRNYXNrLCBudW1iZXJUb0J5dGVzQkUsIG51bWJlclRvQnl0ZXNMRSwgYnl0ZXNUb051bWJlckJFLCBieXRlc1RvTnVtYmVyTEUsIGVuc3VyZUJ5dGVzLCB2YWxpZGF0ZU9iamVjdCwgfSBmcm9tICcuL3V0aWxzLmpzJztcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgXzBuID0gQmlnSW50KDApLCBfMW4gPSBCaWdJbnQoMSksIF8ybiA9IEJpZ0ludCgyKSwgXzNuID0gQmlnSW50KDMpO1xuLy8gcHJldHRpZXItaWdub3JlXG5jb25zdCBfNG4gPSBCaWdJbnQoNCksIF81biA9IEJpZ0ludCg1KSwgXzhuID0gQmlnSW50KDgpO1xuLy8gcHJldHRpZXItaWdub3JlXG5jb25zdCBfOW4gPSBCaWdJbnQoOSksIF8xNm4gPSBCaWdJbnQoMTYpO1xuLy8gQ2FsY3VsYXRlcyBhIG1vZHVsbyBiXG5leHBvcnQgZnVuY3Rpb24gbW9kKGEsIGIpIHtcbiAgICBjb25zdCByZXN1bHQgPSBhICUgYjtcbiAgICByZXR1cm4gcmVzdWx0ID49IF8wbiA/IHJlc3VsdCA6IGIgKyByZXN1bHQ7XG59XG4vKipcbiAqIEVmZmljaWVudGx5IHJhaXNlIG51bSB0byBwb3dlciBhbmQgZG8gbW9kdWxhciBkaXZpc2lvbi5cbiAqIFVuc2FmZSBpbiBzb21lIGNvbnRleHRzOiB1c2VzIGxhZGRlciwgc28gY2FuIGV4cG9zZSBiaWdpbnQgYml0cy5cbiAqIEBleGFtcGxlXG4gKiBwb3coMm4sIDZuLCAxMW4pIC8vIDY0biAlIDExbiA9PSA5blxuICovXG4vLyBUT0RPOiB1c2UgZmllbGQgdmVyc2lvbiAmJiByZW1vdmVcbmV4cG9ydCBmdW5jdGlvbiBwb3cobnVtLCBwb3dlciwgbW9kdWxvKSB7XG4gICAgaWYgKG1vZHVsbyA8PSBfMG4gfHwgcG93ZXIgPCBfMG4pXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgcG93ZXIvbW9kdWxvID4gMCcpO1xuICAgIGlmIChtb2R1bG8gPT09IF8xbilcbiAgICAgICAgcmV0dXJuIF8wbjtcbiAgICBsZXQgcmVzID0gXzFuO1xuICAgIHdoaWxlIChwb3dlciA+IF8wbikge1xuICAgICAgICBpZiAocG93ZXIgJiBfMW4pXG4gICAgICAgICAgICByZXMgPSAocmVzICogbnVtKSAlIG1vZHVsbztcbiAgICAgICAgbnVtID0gKG51bSAqIG51bSkgJSBtb2R1bG87XG4gICAgICAgIHBvd2VyID4+PSBfMW47XG4gICAgfVxuICAgIHJldHVybiByZXM7XG59XG4vLyBEb2VzIHggXiAoMiBeIHBvd2VyKSBtb2QgcC4gcG93MigzMCwgNCkgPT0gMzAgXiAoMiBeIDQpXG5leHBvcnQgZnVuY3Rpb24gcG93Mih4LCBwb3dlciwgbW9kdWxvKSB7XG4gICAgbGV0IHJlcyA9IHg7XG4gICAgd2hpbGUgKHBvd2VyLS0gPiBfMG4pIHtcbiAgICAgICAgcmVzICo9IHJlcztcbiAgICAgICAgcmVzICU9IG1vZHVsbztcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbi8vIEludmVyc2VzIG51bWJlciBvdmVyIG1vZHVsb1xuZXhwb3J0IGZ1bmN0aW9uIGludmVydChudW1iZXIsIG1vZHVsbykge1xuICAgIGlmIChudW1iZXIgPT09IF8wbiB8fCBtb2R1bG8gPD0gXzBuKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgaW52ZXJ0OiBleHBlY3RlZCBwb3NpdGl2ZSBpbnRlZ2VycywgZ290IG49JHtudW1iZXJ9IG1vZD0ke21vZHVsb31gKTtcbiAgICB9XG4gICAgLy8gRXVjbGlkZWFuIEdDRCBodHRwczovL2JyaWxsaWFudC5vcmcvd2lraS9leHRlbmRlZC1ldWNsaWRlYW4tYWxnb3JpdGhtL1xuICAgIC8vIEZlcm1hdCdzIGxpdHRsZSB0aGVvcmVtIFwiQ1QtbGlrZVwiIHZlcnNpb24gaW52KG4pID0gbl4obS0yKSBtb2QgbSBpcyAzMHggc2xvd2VyLlxuICAgIGxldCBhID0gbW9kKG51bWJlciwgbW9kdWxvKTtcbiAgICBsZXQgYiA9IG1vZHVsbztcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBsZXQgeCA9IF8wbiwgeSA9IF8xbiwgdSA9IF8xbiwgdiA9IF8wbjtcbiAgICB3aGlsZSAoYSAhPT0gXzBuKSB7XG4gICAgICAgIC8vIEpJVCBhcHBsaWVzIG9wdGltaXphdGlvbiBpZiB0aG9zZSB0d28gbGluZXMgZm9sbG93IGVhY2ggb3RoZXJcbiAgICAgICAgY29uc3QgcSA9IGIgLyBhO1xuICAgICAgICBjb25zdCByID0gYiAlIGE7XG4gICAgICAgIGNvbnN0IG0gPSB4IC0gdSAqIHE7XG4gICAgICAgIGNvbnN0IG4gPSB5IC0gdiAqIHE7XG4gICAgICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgICAgICBiID0gYSwgYSA9IHIsIHggPSB1LCB5ID0gdiwgdSA9IG0sIHYgPSBuO1xuICAgIH1cbiAgICBjb25zdCBnY2QgPSBiO1xuICAgIGlmIChnY2QgIT09IF8xbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZlcnQ6IGRvZXMgbm90IGV4aXN0Jyk7XG4gICAgcmV0dXJuIG1vZCh4LCBtb2R1bG8pO1xufVxuLy8gVG9uZWxsaS1TaGFua3MgYWxnb3JpdGhtXG4vLyBQYXBlciAxOiBodHRwczovL2VwcmludC5pYWNyLm9yZy8yMDEyLzY4NS5wZGYgKHBhZ2UgMTIpXG4vLyBQYXBlciAyOiBTcXVhcmUgUm9vdHMgZnJvbSAxOyAyNCwgNTEsIDEwIHRvIERhbiBTaGFua3NcbmV4cG9ydCBmdW5jdGlvbiB0b25lbGxpU2hhbmtzKFApIHtcbiAgICAvLyBMZWdlbmRyZSBjb25zdGFudDogdXNlZCB0byBjYWxjdWxhdGUgTGVnZW5kcmUgc3ltYm9sIChhIHwgcCksXG4gICAgLy8gd2hpY2ggZGVub3RlcyB0aGUgdmFsdWUgb2YgYV4oKHAtMSkvMikgKG1vZCBwKS5cbiAgICAvLyAoYSB8IHApIOKJoSAxICAgIGlmIGEgaXMgYSBzcXVhcmUgKG1vZCBwKVxuICAgIC8vIChhIHwgcCkg4omhIC0xICAgaWYgYSBpcyBub3QgYSBzcXVhcmUgKG1vZCBwKVxuICAgIC8vIChhIHwgcCkg4omhIDAgICAgaWYgYSDiiaEgMCAobW9kIHApXG4gICAgY29uc3QgbGVnZW5kcmVDID0gKFAgLSBfMW4pIC8gXzJuO1xuICAgIGxldCBRLCBTLCBaO1xuICAgIC8vIFN0ZXAgMTogQnkgZmFjdG9yaW5nIG91dCBwb3dlcnMgb2YgMiBmcm9tIHAgLSAxLFxuICAgIC8vIGZpbmQgcSBhbmQgcyBzdWNoIHRoYXQgcCAtIDEgPSBxKigyXnMpIHdpdGggcSBvZGRcbiAgICBmb3IgKFEgPSBQIC0gXzFuLCBTID0gMDsgUSAlIF8ybiA9PT0gXzBuOyBRIC89IF8ybiwgUysrKVxuICAgICAgICA7XG4gICAgLy8gU3RlcCAyOiBTZWxlY3QgYSBub24tc3F1YXJlIHogc3VjaCB0aGF0ICh6IHwgcCkg4omhIC0xIGFuZCBzZXQgYyDiiaEgenFcbiAgICBmb3IgKFogPSBfMm47IFogPCBQICYmIHBvdyhaLCBsZWdlbmRyZUMsIFApICE9PSBQIC0gXzFuOyBaKyspXG4gICAgICAgIDtcbiAgICAvLyBGYXN0LXBhdGhcbiAgICBpZiAoUyA9PT0gMSkge1xuICAgICAgICBjb25zdCBwMWRpdjQgPSAoUCArIF8xbikgLyBfNG47XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiB0b25lbGxpRmFzdChGcCwgbikge1xuICAgICAgICAgICAgY29uc3Qgcm9vdCA9IEZwLnBvdyhuLCBwMWRpdjQpO1xuICAgICAgICAgICAgaWYgKCFGcC5lcWwoRnAuc3FyKHJvb3QpLCBuKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmaW5kIHNxdWFyZSByb290Jyk7XG4gICAgICAgICAgICByZXR1cm4gcm9vdDtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gU2xvdy1wYXRoXG4gICAgY29uc3QgUTFkaXYyID0gKFEgKyBfMW4pIC8gXzJuO1xuICAgIHJldHVybiBmdW5jdGlvbiB0b25lbGxpU2xvdyhGcCwgbikge1xuICAgICAgICAvLyBTdGVwIDA6IENoZWNrIHRoYXQgbiBpcyBpbmRlZWQgYSBzcXVhcmU6IChuIHwgcCkgc2hvdWxkIG5vdCBiZSDiiaEgLTFcbiAgICAgICAgaWYgKEZwLnBvdyhuLCBsZWdlbmRyZUMpID09PSBGcC5uZWcoRnAuT05FKSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgc3F1YXJlIHJvb3QnKTtcbiAgICAgICAgbGV0IHIgPSBTO1xuICAgICAgICAvLyBUT0RPOiB3aWxsIGZhaWwgYXQgRnAyL2V0Y1xuICAgICAgICBsZXQgZyA9IEZwLnBvdyhGcC5tdWwoRnAuT05FLCBaKSwgUSk7IC8vIHdpbGwgdXBkYXRlIGJvdGggeCBhbmQgYlxuICAgICAgICBsZXQgeCA9IEZwLnBvdyhuLCBRMWRpdjIpOyAvLyBmaXJzdCBndWVzcyBhdCB0aGUgc3F1YXJlIHJvb3RcbiAgICAgICAgbGV0IGIgPSBGcC5wb3cobiwgUSk7IC8vIGZpcnN0IGd1ZXNzIGF0IHRoZSBmdWRnZSBmYWN0b3JcbiAgICAgICAgd2hpbGUgKCFGcC5lcWwoYiwgRnAuT05FKSkge1xuICAgICAgICAgICAgaWYgKEZwLmVxbChiLCBGcC5aRVJPKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gRnAuWkVSTzsgLy8gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvVG9uZWxsaSVFMiU4MCU5M1NoYW5rc19hbGdvcml0aG0gKDQuIElmIHQgPSAwLCByZXR1cm4gciA9IDApXG4gICAgICAgICAgICAvLyBGaW5kIG0gc3VjaCBiXigyXm0pPT0xXG4gICAgICAgICAgICBsZXQgbSA9IDE7XG4gICAgICAgICAgICBmb3IgKGxldCB0MiA9IEZwLnNxcihiKTsgbSA8IHI7IG0rKykge1xuICAgICAgICAgICAgICAgIGlmIChGcC5lcWwodDIsIEZwLk9ORSkpXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIHQyID0gRnAuc3FyKHQyKTsgLy8gdDIgKj0gdDJcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIE5PVEU6IHItbS0xIGNhbiBiZSBiaWdnZXIgdGhhbiAzMiwgbmVlZCB0byBjb252ZXJ0IHRvIGJpZ2ludCBiZWZvcmUgc2hpZnQsIG90aGVyd2lzZSB0aGVyZSB3aWxsIGJlIG92ZXJmbG93XG4gICAgICAgICAgICBjb25zdCBnZSA9IEZwLnBvdyhnLCBfMW4gPDwgQmlnSW50KHIgLSBtIC0gMSkpOyAvLyBnZSA9IDJeKHItbS0xKVxuICAgICAgICAgICAgZyA9IEZwLnNxcihnZSk7IC8vIGcgPSBnZSAqIGdlXG4gICAgICAgICAgICB4ID0gRnAubXVsKHgsIGdlKTsgLy8geCAqPSBnZVxuICAgICAgICAgICAgYiA9IEZwLm11bChiLCBnKTsgLy8gYiAqPSBnXG4gICAgICAgICAgICByID0gbTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geDtcbiAgICB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIEZwU3FydChQKSB7XG4gICAgLy8gTk9URTogZGlmZmVyZW50IGFsZ29yaXRobXMgY2FuIGdpdmUgZGlmZmVyZW50IHJvb3RzLCBpdCBpcyB1cCB0byB1c2VyIHRvIGRlY2lkZSB3aGljaCBvbmUgdGhleSB3YW50LlxuICAgIC8vIEZvciBleGFtcGxlIHRoZXJlIGlzIEZwU3FydE9kZC9GcFNxcnRFdmVuIHRvIGNob2ljZSByb290IGJhc2VkIG9uIG9kZG5lc3MgKHVzZWQgZm9yIGhhc2gtdG8tY3VydmUpLlxuICAgIC8vIFAg4omhIDMgKG1vZCA0KVxuICAgIC8vIOKImm4gPSBuXigoUCsxKS80KVxuICAgIGlmIChQICUgXzRuID09PSBfM24pIHtcbiAgICAgICAgLy8gTm90IGFsbCByb290cyBwb3NzaWJsZSFcbiAgICAgICAgLy8gY29uc3QgT1JERVIgPVxuICAgICAgICAvLyAgIDB4MWEwMTExZWEzOTdmZTY5YTRiMWJhN2I2NDM0YmFjZDc2NDc3NGI4NGYzODUxMmJmNjczMGQyYTBmNmIwZjYyNDFlYWJmZmZlYjE1M2ZmZmZiOWZlZmZmZmZmZmZhYWFibjtcbiAgICAgICAgLy8gY29uc3QgTlVNID0gNzIwNTc1OTQwMzc5Mjc4MTZuO1xuICAgICAgICBjb25zdCBwMWRpdjQgPSAoUCArIF8xbikgLyBfNG47XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBzcXJ0M21vZDQoRnAsIG4pIHtcbiAgICAgICAgICAgIGNvbnN0IHJvb3QgPSBGcC5wb3cobiwgcDFkaXY0KTtcbiAgICAgICAgICAgIC8vIFRocm93IGlmIHJvb3QqKjIgIT0gblxuICAgICAgICAgICAgaWYgKCFGcC5lcWwoRnAuc3FyKHJvb3QpLCBuKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0Nhbm5vdCBmaW5kIHNxdWFyZSByb290Jyk7XG4gICAgICAgICAgICByZXR1cm4gcm9vdDtcbiAgICAgICAgfTtcbiAgICB9XG4gICAgLy8gQXRraW4gYWxnb3JpdGhtIGZvciBxIOKJoSA1IChtb2QgOCksIGh0dHBzOi8vZXByaW50LmlhY3Iub3JnLzIwMTIvNjg1LnBkZiAocGFnZSAxMClcbiAgICBpZiAoUCAlIF84biA9PT0gXzVuKSB7XG4gICAgICAgIGNvbnN0IGMxID0gKFAgLSBfNW4pIC8gXzhuO1xuICAgICAgICByZXR1cm4gZnVuY3Rpb24gc3FydDVtb2Q4KEZwLCBuKSB7XG4gICAgICAgICAgICBjb25zdCBuMiA9IEZwLm11bChuLCBfMm4pO1xuICAgICAgICAgICAgY29uc3QgdiA9IEZwLnBvdyhuMiwgYzEpO1xuICAgICAgICAgICAgY29uc3QgbnYgPSBGcC5tdWwobiwgdik7XG4gICAgICAgICAgICBjb25zdCBpID0gRnAubXVsKEZwLm11bChudiwgXzJuKSwgdik7XG4gICAgICAgICAgICBjb25zdCByb290ID0gRnAubXVsKG52LCBGcC5zdWIoaSwgRnAuT05FKSk7XG4gICAgICAgICAgICBpZiAoIUZwLmVxbChGcC5zcXIocm9vdCksIG4pKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgc3F1YXJlIHJvb3QnKTtcbiAgICAgICAgICAgIHJldHVybiByb290O1xuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBQIOKJoSA5IChtb2QgMTYpXG4gICAgaWYgKFAgJSBfMTZuID09PSBfOW4pIHtcbiAgICAgICAgLy8gTk9URTogdG9uZWxsaSBpcyB0b28gc2xvdyBmb3IgYmxzLUZwMiBjYWxjdWxhdGlvbnMgZXZlbiBvbiBzdGFydFxuICAgICAgICAvLyBNZWFucyB3ZSBjYW5ub3QgdXNlIHNxcnQgZm9yIGNvbnN0YW50cyBhdCBhbGwhXG4gICAgICAgIC8vXG4gICAgICAgIC8vIGNvbnN0IGMxID0gRnAuc3FydChGcC5uZWdhdGUoRnAuT05FKSk7IC8vICAxLiBjMSA9IHNxcnQoLTEpIGluIEYsIGkuZS4sIChjMV4yKSA9PSAtMSBpbiBGXG4gICAgICAgIC8vIGNvbnN0IGMyID0gRnAuc3FydChjMSk7ICAgICAgICAgICAgICAgIC8vICAyLiBjMiA9IHNxcnQoYzEpIGluIEYsIGkuZS4sIChjMl4yKSA9PSBjMSBpbiBGXG4gICAgICAgIC8vIGNvbnN0IGMzID0gRnAuc3FydChGcC5uZWdhdGUoYzEpKTsgICAgIC8vICAzLiBjMyA9IHNxcnQoLWMxKSBpbiBGLCBpLmUuLCAoYzNeMikgPT0gLWMxIGluIEZcbiAgICAgICAgLy8gY29uc3QgYzQgPSAoUCArIF83bikgLyBfMTZuOyAgICAgICAgICAgLy8gIDQuIGM0ID0gKHEgKyA3KSAvIDE2ICAgICAgICAjIEludGVnZXIgYXJpdGhtZXRpY1xuICAgICAgICAvLyBzcXJ0ID0gKHgpID0+IHtcbiAgICAgICAgLy8gICBsZXQgdHYxID0gRnAucG93KHgsIGM0KTsgICAgICAgICAgICAgLy8gIDEuIHR2MSA9IHheYzRcbiAgICAgICAgLy8gICBsZXQgdHYyID0gRnAubXVsKGMxLCB0djEpOyAgICAgICAgICAgLy8gIDIuIHR2MiA9IGMxICogdHYxXG4gICAgICAgIC8vICAgY29uc3QgdHYzID0gRnAubXVsKGMyLCB0djEpOyAgICAgICAgIC8vICAzLiB0djMgPSBjMiAqIHR2MVxuICAgICAgICAvLyAgIGxldCB0djQgPSBGcC5tdWwoYzMsIHR2MSk7ICAgICAgICAgICAvLyAgNC4gdHY0ID0gYzMgKiB0djFcbiAgICAgICAgLy8gICBjb25zdCBlMSA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYyKSwgeCk7IC8vICA1LiAgZTEgPSAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICBjb25zdCBlMiA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYzKSwgeCk7IC8vICA2LiAgZTIgPSAodHYzXjIpID09IHhcbiAgICAgICAgLy8gICB0djEgPSBGcC5jbW92KHR2MSwgdHYyLCBlMSk7IC8vICA3LiB0djEgPSBDTU9WKHR2MSwgdHYyLCBlMSkgICMgU2VsZWN0IHR2MiBpZiAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICB0djIgPSBGcC5jbW92KHR2NCwgdHYzLCBlMik7IC8vICA4LiB0djIgPSBDTU9WKHR2NCwgdHYzLCBlMikgICMgU2VsZWN0IHR2MyBpZiAodHYzXjIpID09IHhcbiAgICAgICAgLy8gICBjb25zdCBlMyA9IEZwLmVxdWFscyhGcC5zcXVhcmUodHYyKSwgeCk7IC8vICA5LiAgZTMgPSAodHYyXjIpID09IHhcbiAgICAgICAgLy8gICByZXR1cm4gRnAuY21vdih0djEsIHR2MiwgZTMpOyAvLyAgMTAuICB6ID0gQ01PVih0djEsIHR2MiwgZTMpICAjIFNlbGVjdCB0aGUgc3FydCBmcm9tIHR2MSBhbmQgdHYyXG4gICAgICAgIC8vIH1cbiAgICB9XG4gICAgLy8gT3RoZXIgY2FzZXM6IFRvbmVsbGktU2hhbmtzIGFsZ29yaXRobVxuICAgIHJldHVybiB0b25lbGxpU2hhbmtzKFApO1xufVxuLy8gTGl0dGxlLWVuZGlhbiBjaGVjayBmb3IgZmlyc3QgTEUgYml0IChsYXN0IEJFIGJpdCk7XG5leHBvcnQgY29uc3QgaXNOZWdhdGl2ZUxFID0gKG51bSwgbW9kdWxvKSA9PiAobW9kKG51bSwgbW9kdWxvKSAmIF8xbikgPT09IF8xbjtcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgRklFTERfRklFTERTID0gW1xuICAgICdjcmVhdGUnLCAnaXNWYWxpZCcsICdpczAnLCAnbmVnJywgJ2ludicsICdzcXJ0JywgJ3NxcicsXG4gICAgJ2VxbCcsICdhZGQnLCAnc3ViJywgJ211bCcsICdwb3cnLCAnZGl2JyxcbiAgICAnYWRkTicsICdzdWJOJywgJ211bE4nLCAnc3FyTidcbl07XG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGVGaWVsZChmaWVsZCkge1xuICAgIGNvbnN0IGluaXRpYWwgPSB7XG4gICAgICAgIE9SREVSOiAnYmlnaW50JyxcbiAgICAgICAgTUFTSzogJ2JpZ2ludCcsXG4gICAgICAgIEJZVEVTOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIEJJVFM6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICB9O1xuICAgIGNvbnN0IG9wdHMgPSBGSUVMRF9GSUVMRFMucmVkdWNlKChtYXAsIHZhbCkgPT4ge1xuICAgICAgICBtYXBbdmFsXSA9ICdmdW5jdGlvbic7XG4gICAgICAgIHJldHVybiBtYXA7XG4gICAgfSwgaW5pdGlhbCk7XG4gICAgcmV0dXJuIHZhbGlkYXRlT2JqZWN0KGZpZWxkLCBvcHRzKTtcbn1cbi8vIEdlbmVyaWMgZmllbGQgZnVuY3Rpb25zXG5leHBvcnQgZnVuY3Rpb24gRnBQb3coZiwgbnVtLCBwb3dlcikge1xuICAgIC8vIFNob3VsZCBoYXZlIHNhbWUgc3BlZWQgYXMgcG93IGZvciBiaWdpbnRzXG4gICAgLy8gVE9ETzogYmVuY2htYXJrIVxuICAgIGlmIChwb3dlciA8IF8wbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCBwb3dlciA+IDAnKTtcbiAgICBpZiAocG93ZXIgPT09IF8wbilcbiAgICAgICAgcmV0dXJuIGYuT05FO1xuICAgIGlmIChwb3dlciA9PT0gXzFuKVxuICAgICAgICByZXR1cm4gbnVtO1xuICAgIGxldCBwID0gZi5PTkU7XG4gICAgbGV0IGQgPSBudW07XG4gICAgd2hpbGUgKHBvd2VyID4gXzBuKSB7XG4gICAgICAgIGlmIChwb3dlciAmIF8xbilcbiAgICAgICAgICAgIHAgPSBmLm11bChwLCBkKTtcbiAgICAgICAgZCA9IGYuc3FyKGQpO1xuICAgICAgICBwb3dlciA+Pj0gXzFuO1xuICAgIH1cbiAgICByZXR1cm4gcDtcbn1cbi8vIDAgaXMgbm9uLWludmVydGlibGU6IG5vbi1iYXRjaGVkIHZlcnNpb24gd2lsbCB0aHJvdyBvbiAwXG5leHBvcnQgZnVuY3Rpb24gRnBJbnZlcnRCYXRjaChmLCBudW1zKSB7XG4gICAgY29uc3QgdG1wID0gbmV3IEFycmF5KG51bXMubGVuZ3RoKTtcbiAgICAvLyBXYWxrIGZyb20gZmlyc3QgdG8gbGFzdCwgbXVsdGlwbHkgdGhlbSBieSBlYWNoIG90aGVyIE1PRCBwXG4gICAgY29uc3QgbGFzdE11bHRpcGxpZWQgPSBudW1zLnJlZHVjZSgoYWNjLCBudW0sIGkpID0+IHtcbiAgICAgICAgaWYgKGYuaXMwKG51bSkpXG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICB0bXBbaV0gPSBhY2M7XG4gICAgICAgIHJldHVybiBmLm11bChhY2MsIG51bSk7XG4gICAgfSwgZi5PTkUpO1xuICAgIC8vIEludmVydCBsYXN0IGVsZW1lbnRcbiAgICBjb25zdCBpbnZlcnRlZCA9IGYuaW52KGxhc3RNdWx0aXBsaWVkKTtcbiAgICAvLyBXYWxrIGZyb20gbGFzdCB0byBmaXJzdCwgbXVsdGlwbHkgdGhlbSBieSBpbnZlcnRlZCBlYWNoIG90aGVyIE1PRCBwXG4gICAgbnVtcy5yZWR1Y2VSaWdodCgoYWNjLCBudW0sIGkpID0+IHtcbiAgICAgICAgaWYgKGYuaXMwKG51bSkpXG4gICAgICAgICAgICByZXR1cm4gYWNjO1xuICAgICAgICB0bXBbaV0gPSBmLm11bChhY2MsIHRtcFtpXSk7XG4gICAgICAgIHJldHVybiBmLm11bChhY2MsIG51bSk7XG4gICAgfSwgaW52ZXJ0ZWQpO1xuICAgIHJldHVybiB0bXA7XG59XG5leHBvcnQgZnVuY3Rpb24gRnBEaXYoZiwgbGhzLCByaHMpIHtcbiAgICByZXR1cm4gZi5tdWwobGhzLCB0eXBlb2YgcmhzID09PSAnYmlnaW50JyA/IGludmVydChyaHMsIGYuT1JERVIpIDogZi5pbnYocmhzKSk7XG59XG4vLyBUaGlzIGZ1bmN0aW9uIHJldHVybnMgVHJ1ZSB3aGVuZXZlciB0aGUgdmFsdWUgeCBpcyBhIHNxdWFyZSBpbiB0aGUgZmllbGQgRi5cbmV4cG9ydCBmdW5jdGlvbiBGcElzU3F1YXJlKGYpIHtcbiAgICBjb25zdCBsZWdlbmRyZUNvbnN0ID0gKGYuT1JERVIgLSBfMW4pIC8gXzJuOyAvLyBJbnRlZ2VyIGFyaXRobWV0aWNcbiAgICByZXR1cm4gKHgpID0+IHtcbiAgICAgICAgY29uc3QgcCA9IGYucG93KHgsIGxlZ2VuZHJlQ29uc3QpO1xuICAgICAgICByZXR1cm4gZi5lcWwocCwgZi5aRVJPKSB8fCBmLmVxbChwLCBmLk9ORSk7XG4gICAgfTtcbn1cbi8vIENVUlZFLm4gbGVuZ3Roc1xuZXhwb3J0IGZ1bmN0aW9uIG5MZW5ndGgobiwgbkJpdExlbmd0aCkge1xuICAgIC8vIEJpdCBzaXplLCBieXRlIHNpemUgb2YgQ1VSVkUublxuICAgIGNvbnN0IF9uQml0TGVuZ3RoID0gbkJpdExlbmd0aCAhPT0gdW5kZWZpbmVkID8gbkJpdExlbmd0aCA6IG4udG9TdHJpbmcoMikubGVuZ3RoO1xuICAgIGNvbnN0IG5CeXRlTGVuZ3RoID0gTWF0aC5jZWlsKF9uQml0TGVuZ3RoIC8gOCk7XG4gICAgcmV0dXJuIHsgbkJpdExlbmd0aDogX25CaXRMZW5ndGgsIG5CeXRlTGVuZ3RoIH07XG59XG4vKipcbiAqIEluaXRpYWxpemVzIGEgZ2Fsb2lzIGZpZWxkIG92ZXIgcHJpbWUuIE5vbi1wcmltZXMgYXJlIG5vdCBzdXBwb3J0ZWQgZm9yIG5vdy5cbiAqIERvIG5vdCBpbml0IGluIGxvb3A6IHNsb3cuIFZlcnkgZnJhZ2lsZTogYWx3YXlzIHJ1biBhIGJlbmNobWFyayBvbiBjaGFuZ2UuXG4gKiBNYWpvciBwZXJmb3JtYW5jZSBnYWluczpcbiAqIGEpIG5vbi1ub3JtYWxpemVkIG9wZXJhdGlvbnMgbGlrZSBtdWxOIGluc3RlYWQgb2YgbXVsXG4gKiBiKSBgT2JqZWN0LmZyZWV6ZWBcbiAqIGMpIFNhbWUgb2JqZWN0IHNoYXBlOiBuZXZlciBhZGQgb3IgcmVtb3ZlIGtleXNcbiAqIEBwYXJhbSBPUkRFUiBwcmltZSBwb3NpdGl2ZSBiaWdpbnRcbiAqIEBwYXJhbSBiaXRMZW4gaG93IG1hbnkgYml0cyB0aGUgZmllbGQgY29uc3VtZXNcbiAqIEBwYXJhbSBpc0xFIChkZWY6IGZhbHNlKSBpZiBlbmNvZGluZyAvIGRlY29kaW5nIHNob3VsZCBiZSBpbiBsaXR0bGUtZW5kaWFuXG4gKiBAcGFyYW0gcmVkZWYgb3B0aW9uYWwgZmFzdGVyIHJlZGVmaW5pdGlvbnMgb2Ygc3FydCBhbmQgb3RoZXIgbWV0aG9kc1xuICovXG5leHBvcnQgZnVuY3Rpb24gRmllbGQoT1JERVIsIGJpdExlbiwgaXNMRSA9IGZhbHNlLCByZWRlZiA9IHt9KSB7XG4gICAgaWYgKE9SREVSIDw9IF8wbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBGcCBPUkRFUiA+IDAsIGdvdCAke09SREVSfWApO1xuICAgIGNvbnN0IHsgbkJpdExlbmd0aDogQklUUywgbkJ5dGVMZW5ndGg6IEJZVEVTIH0gPSBuTGVuZ3RoKE9SREVSLCBiaXRMZW4pO1xuICAgIGlmIChCWVRFUyA+IDIwNDgpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRmllbGQgbGVuZ3RocyBvdmVyIDIwNDggYnl0ZXMgYXJlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICBjb25zdCBzcXJ0UCA9IEZwU3FydChPUkRFUik7XG4gICAgY29uc3QgZiA9IE9iamVjdC5mcmVlemUoe1xuICAgICAgICBPUkRFUixcbiAgICAgICAgQklUUyxcbiAgICAgICAgQllURVMsXG4gICAgICAgIE1BU0s6IGJpdE1hc2soQklUUyksXG4gICAgICAgIFpFUk86IF8wbixcbiAgICAgICAgT05FOiBfMW4sXG4gICAgICAgIGNyZWF0ZTogKG51bSkgPT4gbW9kKG51bSwgT1JERVIpLFxuICAgICAgICBpc1ZhbGlkOiAobnVtKSA9PiB7XG4gICAgICAgICAgICBpZiAodHlwZW9mIG51bSAhPT0gJ2JpZ2ludCcpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIGZpZWxkIGVsZW1lbnQ6IGV4cGVjdGVkIGJpZ2ludCwgZ290ICR7dHlwZW9mIG51bX1gKTtcbiAgICAgICAgICAgIHJldHVybiBfMG4gPD0gbnVtICYmIG51bSA8IE9SREVSOyAvLyAwIGlzIHZhbGlkIGVsZW1lbnQsIGJ1dCBpdCdzIG5vdCBpbnZlcnRpYmxlXG4gICAgICAgIH0sXG4gICAgICAgIGlzMDogKG51bSkgPT4gbnVtID09PSBfMG4sXG4gICAgICAgIGlzT2RkOiAobnVtKSA9PiAobnVtICYgXzFuKSA9PT0gXzFuLFxuICAgICAgICBuZWc6IChudW0pID0+IG1vZCgtbnVtLCBPUkRFUiksXG4gICAgICAgIGVxbDogKGxocywgcmhzKSA9PiBsaHMgPT09IHJocyxcbiAgICAgICAgc3FyOiAobnVtKSA9PiBtb2QobnVtICogbnVtLCBPUkRFUiksXG4gICAgICAgIGFkZDogKGxocywgcmhzKSA9PiBtb2QobGhzICsgcmhzLCBPUkRFUiksXG4gICAgICAgIHN1YjogKGxocywgcmhzKSA9PiBtb2QobGhzIC0gcmhzLCBPUkRFUiksXG4gICAgICAgIG11bDogKGxocywgcmhzKSA9PiBtb2QobGhzICogcmhzLCBPUkRFUiksXG4gICAgICAgIHBvdzogKG51bSwgcG93ZXIpID0+IEZwUG93KGYsIG51bSwgcG93ZXIpLFxuICAgICAgICBkaXY6IChsaHMsIHJocykgPT4gbW9kKGxocyAqIGludmVydChyaHMsIE9SREVSKSwgT1JERVIpLFxuICAgICAgICAvLyBTYW1lIGFzIGFib3ZlLCBidXQgZG9lc24ndCBub3JtYWxpemVcbiAgICAgICAgc3FyTjogKG51bSkgPT4gbnVtICogbnVtLFxuICAgICAgICBhZGROOiAobGhzLCByaHMpID0+IGxocyArIHJocyxcbiAgICAgICAgc3ViTjogKGxocywgcmhzKSA9PiBsaHMgLSByaHMsXG4gICAgICAgIG11bE46IChsaHMsIHJocykgPT4gbGhzICogcmhzLFxuICAgICAgICBpbnY6IChudW0pID0+IGludmVydChudW0sIE9SREVSKSxcbiAgICAgICAgc3FydDogcmVkZWYuc3FydCB8fCAoKG4pID0+IHNxcnRQKGYsIG4pKSxcbiAgICAgICAgaW52ZXJ0QmF0Y2g6IChsc3QpID0+IEZwSW52ZXJ0QmF0Y2goZiwgbHN0KSxcbiAgICAgICAgLy8gVE9ETzogZG8gd2UgcmVhbGx5IG5lZWQgY29uc3RhbnQgY21vdj9cbiAgICAgICAgLy8gV2UgZG9uJ3QgaGF2ZSBjb25zdC10aW1lIGJpZ2ludHMgYW55d2F5LCBzbyBwcm9iYWJseSB3aWxsIGJlIG5vdCB2ZXJ5IHVzZWZ1bFxuICAgICAgICBjbW92OiAoYSwgYiwgYykgPT4gKGMgPyBiIDogYSksXG4gICAgICAgIHRvQnl0ZXM6IChudW0pID0+IChpc0xFID8gbnVtYmVyVG9CeXRlc0xFKG51bSwgQllURVMpIDogbnVtYmVyVG9CeXRlc0JFKG51bSwgQllURVMpKSxcbiAgICAgICAgZnJvbUJ5dGVzOiAoYnl0ZXMpID0+IHtcbiAgICAgICAgICAgIGlmIChieXRlcy5sZW5ndGggIT09IEJZVEVTKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRnAuZnJvbUJ5dGVzOiBleHBlY3RlZCAke0JZVEVTfSwgZ290ICR7Ynl0ZXMubGVuZ3RofWApO1xuICAgICAgICAgICAgcmV0dXJuIGlzTEUgPyBieXRlc1RvTnVtYmVyTEUoYnl0ZXMpIDogYnl0ZXNUb051bWJlckJFKGJ5dGVzKTtcbiAgICAgICAgfSxcbiAgICB9KTtcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZShmKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBGcFNxcnRPZGQoRnAsIGVsbSkge1xuICAgIGlmICghRnAuaXNPZGQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmllbGQgZG9lc24ndCBoYXZlIGlzT2RkYCk7XG4gICAgY29uc3Qgcm9vdCA9IEZwLnNxcnQoZWxtKTtcbiAgICByZXR1cm4gRnAuaXNPZGQocm9vdCkgPyByb290IDogRnAubmVnKHJvb3QpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIEZwU3FydEV2ZW4oRnAsIGVsbSkge1xuICAgIGlmICghRnAuaXNPZGQpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgRmllbGQgZG9lc24ndCBoYXZlIGlzT2RkYCk7XG4gICAgY29uc3Qgcm9vdCA9IEZwLnNxcnQoZWxtKTtcbiAgICByZXR1cm4gRnAuaXNPZGQocm9vdCkgPyBGcC5uZWcocm9vdCkgOiByb290O1xufVxuLyoqXG4gKiBGSVBTIDE4NiBCLjQuMS1jb21wbGlhbnQgXCJjb25zdGFudC10aW1lXCIgcHJpdmF0ZSBrZXkgZ2VuZXJhdGlvbiB1dGlsaXR5LlxuICogQ2FuIHRha2UgKG4rOCkgb3IgbW9yZSBieXRlcyBvZiB1bmlmb3JtIGlucHV0IGUuZy4gZnJvbSBDU1BSTkcgb3IgS0RGXG4gKiBhbmQgY29udmVydCB0aGVtIGludG8gcHJpdmF0ZSBzY2FsYXIsIHdpdGggdGhlIG1vZHVsbyBiaWFzIGJlaW5nIG5lZ2xpZ2libGUuXG4gKiBOZWVkcyBhdCBsZWFzdCA0MCBieXRlcyBvZiBpbnB1dCBmb3IgMzItYnl0ZSBwcml2YXRlIGtleS5cbiAqIGh0dHBzOi8vcmVzZWFyY2gua3VkZWxza2lzZWN1cml0eS5jb20vMjAyMC8wNy8yOC90aGUtZGVmaW5pdGl2ZS1ndWlkZS10by1tb2R1bG8tYmlhcy1hbmQtaG93LXRvLWF2b2lkLWl0L1xuICogQHBhcmFtIGhhc2ggaGFzaCBvdXRwdXQgZnJvbSBTSEEzIG9yIGEgc2ltaWxhciBmdW5jdGlvblxuICogQHBhcmFtIGdyb3VwT3JkZXIgc2l6ZSBvZiBzdWJncm91cCAtIChlLmcuIGN1cnZlRm4uQ1VSVkUubilcbiAqIEBwYXJhbSBpc0xFIGludGVycHJldCBoYXNoIGJ5dGVzIGFzIExFIG51bVxuICogQHJldHVybnMgdmFsaWQgcHJpdmF0ZSBzY2FsYXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2hUb1ByaXZhdGVTY2FsYXIoaGFzaCwgZ3JvdXBPcmRlciwgaXNMRSA9IGZhbHNlKSB7XG4gICAgaGFzaCA9IGVuc3VyZUJ5dGVzKCdwcml2YXRlSGFzaCcsIGhhc2gpO1xuICAgIGNvbnN0IGhhc2hMZW4gPSBoYXNoLmxlbmd0aDtcbiAgICBjb25zdCBtaW5MZW4gPSBuTGVuZ3RoKGdyb3VwT3JkZXIpLm5CeXRlTGVuZ3RoICsgODtcbiAgICBpZiAobWluTGVuIDwgMjQgfHwgaGFzaExlbiA8IG1pbkxlbiB8fCBoYXNoTGVuID4gMTAyNClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBoYXNoVG9Qcml2YXRlU2NhbGFyOiBleHBlY3RlZCAke21pbkxlbn0tMTAyNCBieXRlcyBvZiBpbnB1dCwgZ290ICR7aGFzaExlbn1gKTtcbiAgICBjb25zdCBudW0gPSBpc0xFID8gYnl0ZXNUb051bWJlckxFKGhhc2gpIDogYnl0ZXNUb051bWJlckJFKGhhc2gpO1xuICAgIHJldHVybiBtb2QobnVtLCBncm91cE9yZGVyIC0gXzFuKSArIF8xbjtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPW1vZHVsYXIuanMubWFwIiwiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuLy8gQWJlbGlhbiBncm91cCB1dGlsaXRpZXNcbmltcG9ydCB7IHZhbGlkYXRlRmllbGQsIG5MZW5ndGggfSBmcm9tICcuL21vZHVsYXIuanMnO1xuaW1wb3J0IHsgdmFsaWRhdGVPYmplY3QgfSBmcm9tICcuL3V0aWxzLmpzJztcbmNvbnN0IF8wbiA9IEJpZ0ludCgwKTtcbmNvbnN0IF8xbiA9IEJpZ0ludCgxKTtcbi8vIEVsbGlwdGljIGN1cnZlIG11bHRpcGxpY2F0aW9uIG9mIFBvaW50IGJ5IHNjYWxhci4gRnJhZ2lsZS5cbi8vIFNjYWxhcnMgc2hvdWxkIGFsd2F5cyBiZSBsZXNzIHRoYW4gY3VydmUgb3JkZXI6IHRoaXMgc2hvdWxkIGJlIGNoZWNrZWQgaW5zaWRlIG9mIGEgY3VydmUgaXRzZWxmLlxuLy8gQ3JlYXRlcyBwcmVjb21wdXRhdGlvbiB0YWJsZXMgZm9yIGZhc3QgbXVsdGlwbGljYXRpb246XG4vLyAtIHByaXZhdGUgc2NhbGFyIGlzIHNwbGl0IGJ5IGZpeGVkIHNpemUgd2luZG93cyBvZiBXIGJpdHNcbi8vIC0gZXZlcnkgd2luZG93IHBvaW50IGlzIGNvbGxlY3RlZCBmcm9tIHdpbmRvdydzIHRhYmxlICYgYWRkZWQgdG8gYWNjdW11bGF0b3Jcbi8vIC0gc2luY2Ugd2luZG93cyBhcmUgZGlmZmVyZW50LCBzYW1lIHBvaW50IGluc2lkZSB0YWJsZXMgd29uJ3QgYmUgYWNjZXNzZWQgbW9yZSB0aGFuIG9uY2UgcGVyIGNhbGNcbi8vIC0gZWFjaCBtdWx0aXBsaWNhdGlvbiBpcyAnTWF0aC5jZWlsKENVUlZFX09SREVSIC8g8J2RiikgKyAxJyBwb2ludCBhZGRpdGlvbnMgKGZpeGVkIGZvciBhbnkgc2NhbGFyKVxuLy8gLSArMSB3aW5kb3cgaXMgbmVjY2Vzc2FyeSBmb3Igd05BRlxuLy8gLSB3TkFGIHJlZHVjZXMgdGFibGUgc2l6ZTogMnggbGVzcyBtZW1vcnkgKyAyeCBmYXN0ZXIgZ2VuZXJhdGlvbiwgYnV0IDEwJSBzbG93ZXIgbXVsdGlwbGljYXRpb25cbi8vIFRPRE86IFJlc2VhcmNoIHJldHVybmluZyAyZCBKUyBhcnJheSBvZiB3aW5kb3dzLCBpbnN0ZWFkIG9mIGEgc2luZ2xlIHdpbmRvdy4gVGhpcyB3b3VsZCBhbGxvd1xuLy8gd2luZG93cyB0byBiZSBpbiBkaWZmZXJlbnQgbWVtb3J5IGxvY2F0aW9uc1xuZXhwb3J0IGZ1bmN0aW9uIHdOQUYoYywgYml0cykge1xuICAgIGNvbnN0IGNvbnN0VGltZU5lZ2F0ZSA9IChjb25kaXRpb24sIGl0ZW0pID0+IHtcbiAgICAgICAgY29uc3QgbmVnID0gaXRlbS5uZWdhdGUoKTtcbiAgICAgICAgcmV0dXJuIGNvbmRpdGlvbiA/IG5lZyA6IGl0ZW07XG4gICAgfTtcbiAgICBjb25zdCBvcHRzID0gKFcpID0+IHtcbiAgICAgICAgY29uc3Qgd2luZG93cyA9IE1hdGguY2VpbChiaXRzIC8gVykgKyAxOyAvLyArMSwgYmVjYXVzZVxuICAgICAgICBjb25zdCB3aW5kb3dTaXplID0gMiAqKiAoVyAtIDEpOyAvLyAtMSBiZWNhdXNlIHdlIHNraXAgemVyb1xuICAgICAgICByZXR1cm4geyB3aW5kb3dzLCB3aW5kb3dTaXplIH07XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgICBjb25zdFRpbWVOZWdhdGUsXG4gICAgICAgIC8vIG5vbi1jb25zdCB0aW1lIG11bHRpcGxpY2F0aW9uIGxhZGRlclxuICAgICAgICB1bnNhZmVMYWRkZXIoZWxtLCBuKSB7XG4gICAgICAgICAgICBsZXQgcCA9IGMuWkVSTztcbiAgICAgICAgICAgIGxldCBkID0gZWxtO1xuICAgICAgICAgICAgd2hpbGUgKG4gPiBfMG4pIHtcbiAgICAgICAgICAgICAgICBpZiAobiAmIF8xbilcbiAgICAgICAgICAgICAgICAgICAgcCA9IHAuYWRkKGQpO1xuICAgICAgICAgICAgICAgIGQgPSBkLmRvdWJsZSgpO1xuICAgICAgICAgICAgICAgIG4gPj49IF8xbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHdOQUYgcHJlY29tcHV0YXRpb24gd2luZG93LiBVc2VkIGZvciBjYWNoaW5nLlxuICAgICAgICAgKiBEZWZhdWx0IHdpbmRvdyBzaXplIGlzIHNldCBieSBgdXRpbHMucHJlY29tcHV0ZSgpYCBhbmQgaXMgZXF1YWwgdG8gOC5cbiAgICAgICAgICogTnVtYmVyIG9mIHByZWNvbXB1dGVkIHBvaW50cyBkZXBlbmRzIG9uIHRoZSBjdXJ2ZSBzaXplOlxuICAgICAgICAgKiAyXijwnZGK4oiSMSkgKiAoTWF0aC5jZWlsKPCdkZsgLyDwnZGKKSArIDEpLCB3aGVyZTpcbiAgICAgICAgICogLSDwnZGKIGlzIHRoZSB3aW5kb3cgc2l6ZVxuICAgICAgICAgKiAtIPCdkZsgaXMgdGhlIGJpdGxlbmd0aCBvZiB0aGUgY3VydmUgb3JkZXIuXG4gICAgICAgICAqIEZvciBhIDI1Ni1iaXQgY3VydmUgYW5kIHdpbmRvdyBzaXplIDgsIHRoZSBudW1iZXIgb2YgcHJlY29tcHV0ZWQgcG9pbnRzIGlzIDEyOCAqIDMzID0gNDIyNC5cbiAgICAgICAgICogQHJldHVybnMgcHJlY29tcHV0ZWQgcG9pbnQgdGFibGVzIGZsYXR0ZW5lZCB0byBhIHNpbmdsZSBhcnJheVxuICAgICAgICAgKi9cbiAgICAgICAgcHJlY29tcHV0ZVdpbmRvdyhlbG0sIFcpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgd2luZG93cywgd2luZG93U2l6ZSB9ID0gb3B0cyhXKTtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50cyA9IFtdO1xuICAgICAgICAgICAgbGV0IHAgPSBlbG07XG4gICAgICAgICAgICBsZXQgYmFzZSA9IHA7XG4gICAgICAgICAgICBmb3IgKGxldCB3aW5kb3cgPSAwOyB3aW5kb3cgPCB3aW5kb3dzOyB3aW5kb3crKykge1xuICAgICAgICAgICAgICAgIGJhc2UgPSBwO1xuICAgICAgICAgICAgICAgIHBvaW50cy5wdXNoKGJhc2UpO1xuICAgICAgICAgICAgICAgIC8vID0xLCBiZWNhdXNlIHdlIHNraXAgemVyb1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgd2luZG93U2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhc2UgPSBiYXNlLmFkZChwKTtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzLnB1c2goYmFzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHAgPSBiYXNlLmRvdWJsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHBvaW50cztcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEltcGxlbWVudHMgZWMgbXVsdGlwbGljYXRpb24gdXNpbmcgcHJlY29tcHV0ZWQgdGFibGVzIGFuZCB3LWFyeSBub24tYWRqYWNlbnQgZm9ybS5cbiAgICAgICAgICogQHBhcmFtIFcgd2luZG93IHNpemVcbiAgICAgICAgICogQHBhcmFtIHByZWNvbXB1dGVzIHByZWNvbXB1dGVkIHRhYmxlc1xuICAgICAgICAgKiBAcGFyYW0gbiBzY2FsYXIgKHdlIGRvbid0IGNoZWNrIGhlcmUsIGJ1dCBzaG91bGQgYmUgbGVzcyB0aGFuIGN1cnZlIG9yZGVyKVxuICAgICAgICAgKiBAcmV0dXJucyByZWFsIGFuZCBmYWtlIChmb3IgY29uc3QtdGltZSkgcG9pbnRzXG4gICAgICAgICAqL1xuICAgICAgICB3TkFGKFcsIHByZWNvbXB1dGVzLCBuKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBtYXliZSBjaGVjayB0aGF0IHNjYWxhciBpcyBsZXNzIHRoYW4gZ3JvdXAgb3JkZXI/IHdOQUYgYmVoYXZpb3VzIGlzIHVuZGVmaW5lZCBvdGhlcndpc2VcbiAgICAgICAgICAgIC8vIEJ1dCBuZWVkIHRvIGNhcmVmdWxseSByZW1vdmUgb3RoZXIgY2hlY2tzIGJlZm9yZSB3TkFGLiBPUkRFUiA9PSBiaXRzIGhlcmVcbiAgICAgICAgICAgIGNvbnN0IHsgd2luZG93cywgd2luZG93U2l6ZSB9ID0gb3B0cyhXKTtcbiAgICAgICAgICAgIGxldCBwID0gYy5aRVJPO1xuICAgICAgICAgICAgbGV0IGYgPSBjLkJBU0U7XG4gICAgICAgICAgICBjb25zdCBtYXNrID0gQmlnSW50KDIgKiogVyAtIDEpOyAvLyBDcmVhdGUgbWFzayB3aXRoIFcgb25lczogMGIxMTExIGZvciBXPTQgZXRjLlxuICAgICAgICAgICAgY29uc3QgbWF4TnVtYmVyID0gMiAqKiBXO1xuICAgICAgICAgICAgY29uc3Qgc2hpZnRCeSA9IEJpZ0ludChXKTtcbiAgICAgICAgICAgIGZvciAobGV0IHdpbmRvdyA9IDA7IHdpbmRvdyA8IHdpbmRvd3M7IHdpbmRvdysrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gd2luZG93ICogd2luZG93U2l6ZTtcbiAgICAgICAgICAgICAgICAvLyBFeHRyYWN0IFcgYml0cy5cbiAgICAgICAgICAgICAgICBsZXQgd2JpdHMgPSBOdW1iZXIobiAmIG1hc2spO1xuICAgICAgICAgICAgICAgIC8vIFNoaWZ0IG51bWJlciBieSBXIGJpdHMuXG4gICAgICAgICAgICAgICAgbiA+Pj0gc2hpZnRCeTtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgYml0cyBhcmUgYmlnZ2VyIHRoYW4gbWF4IHNpemUsIHdlJ2xsIHNwbGl0IHRob3NlLlxuICAgICAgICAgICAgICAgIC8vICsyMjQgPT4gMjU2IC0gMzJcbiAgICAgICAgICAgICAgICBpZiAod2JpdHMgPiB3aW5kb3dTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIHdiaXRzIC09IG1heE51bWJlcjtcbiAgICAgICAgICAgICAgICAgICAgbiArPSBfMW47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFRoaXMgY29kZSB3YXMgZmlyc3Qgd3JpdHRlbiB3aXRoIGFzc3VtcHRpb24gdGhhdCAnZicgYW5kICdwJyB3aWxsIG5ldmVyIGJlIGluZmluaXR5IHBvaW50OlxuICAgICAgICAgICAgICAgIC8vIHNpbmNlIGVhY2ggYWRkaXRpb24gaXMgbXVsdGlwbGllZCBieSAyICoqIFcsIGl0IGNhbm5vdCBjYW5jZWwgZWFjaCBvdGhlci4gSG93ZXZlcixcbiAgICAgICAgICAgICAgICAvLyB0aGVyZSBpcyBuZWdhdGUgbm93OiBpdCBpcyBwb3NzaWJsZSB0aGF0IG5lZ2F0ZWQgZWxlbWVudCBmcm9tIGxvdyB2YWx1ZVxuICAgICAgICAgICAgICAgIC8vIHdvdWxkIGJlIHRoZSBzYW1lIGFzIGhpZ2ggZWxlbWVudCwgd2hpY2ggd2lsbCBjcmVhdGUgY2FycnkgaW50byBuZXh0IHdpbmRvdy5cbiAgICAgICAgICAgICAgICAvLyBJdCdzIG5vdCBvYnZpb3VzIGhvdyB0aGlzIGNhbiBmYWlsLCBidXQgc3RpbGwgd29ydGggaW52ZXN0aWdhdGluZyBsYXRlci5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB3ZSdyZSBvbnRvIFplcm8gcG9pbnQuXG4gICAgICAgICAgICAgICAgLy8gQWRkIHJhbmRvbSBwb2ludCBpbnNpZGUgY3VycmVudCB3aW5kb3cgdG8gZi5cbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQxID0gb2Zmc2V0O1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldDIgPSBvZmZzZXQgKyBNYXRoLmFicyh3Yml0cykgLSAxOyAvLyAtMSBiZWNhdXNlIHdlIHNraXAgemVyb1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbmQxID0gd2luZG93ICUgMiAhPT0gMDtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25kMiA9IHdiaXRzIDwgMDtcbiAgICAgICAgICAgICAgICBpZiAod2JpdHMgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIG1vc3QgaW1wb3J0YW50IHBhcnQgZm9yIGNvbnN0LXRpbWUgZ2V0UHVibGljS2V5XG4gICAgICAgICAgICAgICAgICAgIGYgPSBmLmFkZChjb25zdFRpbWVOZWdhdGUoY29uZDEsIHByZWNvbXB1dGVzW29mZnNldDFdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwID0gcC5hZGQoY29uc3RUaW1lTmVnYXRlKGNvbmQyLCBwcmVjb21wdXRlc1tvZmZzZXQyXSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEpJVC1jb21waWxlciBzaG91bGQgbm90IGVsaW1pbmF0ZSBmIGhlcmUsIHNpbmNlIGl0IHdpbGwgbGF0ZXIgYmUgdXNlZCBpbiBub3JtYWxpemVaKClcbiAgICAgICAgICAgIC8vIEV2ZW4gaWYgdGhlIHZhcmlhYmxlIGlzIHN0aWxsIHVudXNlZCwgdGhlcmUgYXJlIHNvbWUgY2hlY2tzIHdoaWNoIHdpbGxcbiAgICAgICAgICAgIC8vIHRocm93IGFuIGV4Y2VwdGlvbiwgc28gY29tcGlsZXIgbmVlZHMgdG8gcHJvdmUgdGhleSB3b24ndCBoYXBwZW4sIHdoaWNoIGlzIGhhcmQuXG4gICAgICAgICAgICAvLyBBdCB0aGlzIHBvaW50IHRoZXJlIGlzIGEgd2F5IHRvIEYgYmUgaW5maW5pdHktcG9pbnQgZXZlbiBpZiBwIGlzIG5vdCxcbiAgICAgICAgICAgIC8vIHdoaWNoIG1ha2VzIGl0IGxlc3MgY29uc3QtdGltZTogYXJvdW5kIDEgYmlnaW50IG11bHRpcGx5LlxuICAgICAgICAgICAgcmV0dXJuIHsgcCwgZiB9O1xuICAgICAgICB9LFxuICAgICAgICB3TkFGQ2FjaGVkKFAsIHByZWNvbXB1dGVzTWFwLCBuLCB0cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIGNvbnN0IFcgPSBQLl9XSU5ET1dfU0laRSB8fCAxO1xuICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIHByZWNvbXB1dGVzIG9uIGEgZmlyc3QgcnVuLCByZXVzZSB0aGVtIGFmdGVyXG4gICAgICAgICAgICBsZXQgY29tcCA9IHByZWNvbXB1dGVzTWFwLmdldChQKTtcbiAgICAgICAgICAgIGlmICghY29tcCkge1xuICAgICAgICAgICAgICAgIGNvbXAgPSB0aGlzLnByZWNvbXB1dGVXaW5kb3coUCwgVyk7XG4gICAgICAgICAgICAgICAgaWYgKFcgIT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJlY29tcHV0ZXNNYXAuc2V0KFAsIHRyYW5zZm9ybShjb21wKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMud05BRihXLCBjb21wLCBuKTtcbiAgICAgICAgfSxcbiAgICB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQmFzaWMoY3VydmUpIHtcbiAgICB2YWxpZGF0ZUZpZWxkKGN1cnZlLkZwKTtcbiAgICB2YWxpZGF0ZU9iamVjdChjdXJ2ZSwge1xuICAgICAgICBuOiAnYmlnaW50JyxcbiAgICAgICAgaDogJ2JpZ2ludCcsXG4gICAgICAgIEd4OiAnZmllbGQnLFxuICAgICAgICBHeTogJ2ZpZWxkJyxcbiAgICB9LCB7XG4gICAgICAgIG5CaXRMZW5ndGg6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICAgICAgbkJ5dGVMZW5ndGg6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICB9KTtcbiAgICAvLyBTZXQgZGVmYXVsdHNcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgICAgIC4uLm5MZW5ndGgoY3VydmUubiwgY3VydmUubkJpdExlbmd0aCksXG4gICAgICAgIC4uLmN1cnZlLFxuICAgICAgICAuLi57IHA6IGN1cnZlLkZwLk9SREVSIH0sXG4gICAgfSk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jdXJ2ZS5qcy5tYXAiLCIvKiEgbm9ibGUtY3VydmVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG4vLyBUd2lzdGVkIEVkd2FyZHMgY3VydmUuIFRoZSBmb3JtdWxhIGlzOiBheMKyICsgecKyID0gMSArIGR4wrJ5wrJcbmltcG9ydCB7IG1vZCB9IGZyb20gJy4vbW9kdWxhci5qcyc7XG5pbXBvcnQgKiBhcyB1dCBmcm9tICcuL3V0aWxzLmpzJztcbmltcG9ydCB7IGVuc3VyZUJ5dGVzIH0gZnJvbSAnLi91dGlscy5qcyc7XG5pbXBvcnQgeyB3TkFGLCB2YWxpZGF0ZUJhc2ljIH0gZnJvbSAnLi9jdXJ2ZS5qcyc7XG4vLyBCZSBmcmllbmRseSB0byBiYWQgRUNNQVNjcmlwdCBwYXJzZXJzIGJ5IG5vdCB1c2luZyBiaWdpbnQgbGl0ZXJhbHNcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgXzBuID0gQmlnSW50KDApLCBfMW4gPSBCaWdJbnQoMSksIF8ybiA9IEJpZ0ludCgyKSwgXzhuID0gQmlnSW50KDgpO1xuLy8gdmVyaWZpY2F0aW9uIHJ1bGUgaXMgZWl0aGVyIHppcDIxNSBvciByZmM4MDMyIC8gbmlzdDE4Ni01LiBDb25zdWx0IGZyb21IZXg6XG5jb25zdCBWRVJJRllfREVGQVVMVCA9IHsgemlwMjE1OiB0cnVlIH07XG5mdW5jdGlvbiB2YWxpZGF0ZU9wdHMoY3VydmUpIHtcbiAgICBjb25zdCBvcHRzID0gdmFsaWRhdGVCYXNpYyhjdXJ2ZSk7XG4gICAgdXQudmFsaWRhdGVPYmplY3QoY3VydmUsIHtcbiAgICAgICAgaGFzaDogJ2Z1bmN0aW9uJyxcbiAgICAgICAgYTogJ2JpZ2ludCcsXG4gICAgICAgIGQ6ICdiaWdpbnQnLFxuICAgICAgICByYW5kb21CeXRlczogJ2Z1bmN0aW9uJyxcbiAgICB9LCB7XG4gICAgICAgIGFkanVzdFNjYWxhckJ5dGVzOiAnZnVuY3Rpb24nLFxuICAgICAgICBkb21haW46ICdmdW5jdGlvbicsXG4gICAgICAgIHV2UmF0aW86ICdmdW5jdGlvbicsXG4gICAgICAgIG1hcFRvQ3VydmU6ICdmdW5jdGlvbicsXG4gICAgfSk7XG4gICAgLy8gU2V0IGRlZmF1bHRzXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeyAuLi5vcHRzIH0pO1xufVxuLy8gSXQgaXMgbm90IGdlbmVyaWMgdHdpc3RlZCBjdXJ2ZSBmb3Igbm93LCBidXQgZWQyNTUxOS9lZDQ0OCBnZW5lcmljIGltcGxlbWVudGF0aW9uXG5leHBvcnQgZnVuY3Rpb24gdHdpc3RlZEVkd2FyZHMoY3VydmVEZWYpIHtcbiAgICBjb25zdCBDVVJWRSA9IHZhbGlkYXRlT3B0cyhjdXJ2ZURlZik7XG4gICAgY29uc3QgeyBGcCwgbjogQ1VSVkVfT1JERVIsIHByZWhhc2g6IHByZWhhc2gsIGhhc2g6IGNIYXNoLCByYW5kb21CeXRlcywgbkJ5dGVMZW5ndGgsIGg6IGNvZmFjdG9yLCB9ID0gQ1VSVkU7XG4gICAgY29uc3QgTUFTSyA9IF8ybiA8PCAoQmlnSW50KG5CeXRlTGVuZ3RoICogOCkgLSBfMW4pO1xuICAgIGNvbnN0IG1vZFAgPSBGcC5jcmVhdGU7IC8vIEZ1bmN0aW9uIG92ZXJyaWRlc1xuICAgIC8vIHNxcnQodS92KVxuICAgIGNvbnN0IHV2UmF0aW8gPSBDVVJWRS51dlJhdGlvIHx8XG4gICAgICAgICgodSwgdikgPT4ge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBpc1ZhbGlkOiB0cnVlLCB2YWx1ZTogRnAuc3FydCh1ICogRnAuaW52KHYpKSB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4geyBpc1ZhbGlkOiBmYWxzZSwgdmFsdWU6IF8wbiB9O1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICBjb25zdCBhZGp1c3RTY2FsYXJCeXRlcyA9IENVUlZFLmFkanVzdFNjYWxhckJ5dGVzIHx8ICgoYnl0ZXMpID0+IGJ5dGVzKTsgLy8gTk9PUFxuICAgIGNvbnN0IGRvbWFpbiA9IENVUlZFLmRvbWFpbiB8fFxuICAgICAgICAoKGRhdGEsIGN0eCwgcGhmbGFnKSA9PiB7XG4gICAgICAgICAgICBpZiAoY3R4Lmxlbmd0aCB8fCBwaGZsYWcpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDb250ZXh0cy9wcmUtaGFzaCBhcmUgbm90IHN1cHBvcnRlZCcpO1xuICAgICAgICAgICAgcmV0dXJuIGRhdGE7XG4gICAgICAgIH0pOyAvLyBOT09QXG4gICAgY29uc3QgaW5CaWcgPSAobikgPT4gdHlwZW9mIG4gPT09ICdiaWdpbnQnICYmIF8wbiA8IG47IC8vIG4gaW4gWzEuLl1cbiAgICBjb25zdCBpblJhbmdlID0gKG4sIG1heCkgPT4gaW5CaWcobikgJiYgaW5CaWcobWF4KSAmJiBuIDwgbWF4OyAvLyBuIGluIFsxLi5tYXgtMV1cbiAgICBjb25zdCBpbjBNYXNrUmFuZ2UgPSAobikgPT4gbiA9PT0gXzBuIHx8IGluUmFuZ2UobiwgTUFTSyk7IC8vIG4gaW4gWzAuLk1BU0stMV1cbiAgICBmdW5jdGlvbiBhc3NlcnRJblJhbmdlKG4sIG1heCkge1xuICAgICAgICAvLyBuIGluIFsxLi5tYXgtMV1cbiAgICAgICAgaWYgKGluUmFuZ2UobiwgbWF4KSlcbiAgICAgICAgICAgIHJldHVybiBuO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIHZhbGlkIHNjYWxhciA8ICR7bWF4fSwgZ290ICR7dHlwZW9mIG59ICR7bn1gKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gYXNzZXJ0R0UwKG4pIHtcbiAgICAgICAgLy8gbiBpbiBbMC4uQ1VSVkVfT1JERVItMV1cbiAgICAgICAgcmV0dXJuIG4gPT09IF8wbiA/IG4gOiBhc3NlcnRJblJhbmdlKG4sIENVUlZFX09SREVSKTsgLy8gR0UgPSBwcmltZSBzdWJncm91cCwgbm90IGZ1bGwgZ3JvdXBcbiAgICB9XG4gICAgY29uc3QgcG9pbnRQcmVjb21wdXRlcyA9IG5ldyBNYXAoKTtcbiAgICBmdW5jdGlvbiBpc1BvaW50KG90aGVyKSB7XG4gICAgICAgIGlmICghKG90aGVyIGluc3RhbmNlb2YgUG9pbnQpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHRlbmRlZFBvaW50IGV4cGVjdGVkJyk7XG4gICAgfVxuICAgIC8vIEV4dGVuZGVkIFBvaW50IHdvcmtzIGluIGV4dGVuZGVkIGNvb3JkaW5hdGVzOiAoeCwgeSwgeiwgdCkg4oiLICh4PXgveiwgeT15L3osIHQ9eHkpLlxuICAgIC8vIGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1R3aXN0ZWRfRWR3YXJkc19jdXJ2ZSNFeHRlbmRlZF9jb29yZGluYXRlc1xuICAgIGNsYXNzIFBvaW50IHtcbiAgICAgICAgY29uc3RydWN0b3IoZXgsIGV5LCBleiwgZXQpIHtcbiAgICAgICAgICAgIHRoaXMuZXggPSBleDtcbiAgICAgICAgICAgIHRoaXMuZXkgPSBleTtcbiAgICAgICAgICAgIHRoaXMuZXogPSBlejtcbiAgICAgICAgICAgIHRoaXMuZXQgPSBldDtcbiAgICAgICAgICAgIGlmICghaW4wTWFza1JhbmdlKGV4KSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ggcmVxdWlyZWQnKTtcbiAgICAgICAgICAgIGlmICghaW4wTWFza1JhbmdlKGV5KSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3kgcmVxdWlyZWQnKTtcbiAgICAgICAgICAgIGlmICghaW4wTWFza1JhbmdlKGV6KSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3ogcmVxdWlyZWQnKTtcbiAgICAgICAgICAgIGlmICghaW4wTWFza1JhbmdlKGV0KSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ3QgcmVxdWlyZWQnKTtcbiAgICAgICAgfVxuICAgICAgICBnZXQgeCgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvQWZmaW5lKCkueDtcbiAgICAgICAgfVxuICAgICAgICBnZXQgeSgpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLnRvQWZmaW5lKCkueTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZnJvbUFmZmluZShwKSB7XG4gICAgICAgICAgICBpZiAocCBpbnN0YW5jZW9mIFBvaW50KVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZXh0ZW5kZWQgcG9pbnQgbm90IGFsbG93ZWQnKTtcbiAgICAgICAgICAgIGNvbnN0IHsgeCwgeSB9ID0gcCB8fCB7fTtcbiAgICAgICAgICAgIGlmICghaW4wTWFza1JhbmdlKHgpIHx8ICFpbjBNYXNrUmFuZ2UoeSkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdpbnZhbGlkIGFmZmluZSBwb2ludCcpO1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2ludCh4LCB5LCBfMW4sIG1vZFAoeCAqIHkpKTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgbm9ybWFsaXplWihwb2ludHMpIHtcbiAgICAgICAgICAgIGNvbnN0IHRvSW52ID0gRnAuaW52ZXJ0QmF0Y2gocG9pbnRzLm1hcCgocCkgPT4gcC5leikpO1xuICAgICAgICAgICAgcmV0dXJuIHBvaW50cy5tYXAoKHAsIGkpID0+IHAudG9BZmZpbmUodG9JbnZbaV0pKS5tYXAoUG9pbnQuZnJvbUFmZmluZSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gXCJQcml2YXRlIG1ldGhvZFwiLCBkb24ndCB1c2UgaXQgZGlyZWN0bHlcbiAgICAgICAgX3NldFdpbmRvd1NpemUod2luZG93U2l6ZSkge1xuICAgICAgICAgICAgdGhpcy5fV0lORE9XX1NJWkUgPSB3aW5kb3dTaXplO1xuICAgICAgICAgICAgcG9pbnRQcmVjb21wdXRlcy5kZWxldGUodGhpcyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTm90IHJlcXVpcmVkIGZvciBmcm9tSGV4KCksIHdoaWNoIGFsd2F5cyBjcmVhdGVzIHZhbGlkIHBvaW50cy5cbiAgICAgICAgLy8gQ291bGQgYmUgdXNlZnVsIGZvciBmcm9tQWZmaW5lKCkuXG4gICAgICAgIGFzc2VydFZhbGlkaXR5KCkge1xuICAgICAgICAgICAgY29uc3QgeyBhLCBkIH0gPSBDVVJWRTtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzMCgpKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYmFkIHBvaW50OiBaRVJPJyk7IC8vIFRPRE86IG9wdGltaXplLCB3aXRoIHZhcnMgYmVsb3c/XG4gICAgICAgICAgICAvLyBFcXVhdGlvbiBpbiBhZmZpbmUgY29vcmRpbmF0ZXM6IGF4wrIgKyB5wrIgPSAxICsgZHjCsnnCslxuICAgICAgICAgICAgLy8gRXF1YXRpb24gaW4gcHJvamVjdGl2ZSBjb29yZGluYXRlcyAoWC9aLCBZL1osIFopOiAgKGFYwrIgKyBZwrIpWsKyID0gWuKBtCArIGRYwrJZwrJcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IFgsIGV5OiBZLCBlejogWiwgZXQ6IFQgfSA9IHRoaXM7XG4gICAgICAgICAgICBjb25zdCBYMiA9IG1vZFAoWCAqIFgpOyAvLyBYwrJcbiAgICAgICAgICAgIGNvbnN0IFkyID0gbW9kUChZICogWSk7IC8vIFnCslxuICAgICAgICAgICAgY29uc3QgWjIgPSBtb2RQKFogKiBaKTsgLy8gWsKyXG4gICAgICAgICAgICBjb25zdCBaNCA9IG1vZFAoWjIgKiBaMik7IC8vIFrigbRcbiAgICAgICAgICAgIGNvbnN0IGFYMiA9IG1vZFAoWDIgKiBhKTsgLy8gYVjCslxuICAgICAgICAgICAgY29uc3QgbGVmdCA9IG1vZFAoWjIgKiBtb2RQKGFYMiArIFkyKSk7IC8vIChhWMKyICsgWcKyKVrCslxuICAgICAgICAgICAgY29uc3QgcmlnaHQgPSBtb2RQKFo0ICsgbW9kUChkICogbW9kUChYMiAqIFkyKSkpOyAvLyBa4oG0ICsgZFjCslnCslxuICAgICAgICAgICAgaWYgKGxlZnQgIT09IHJpZ2h0KVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignYmFkIHBvaW50OiBlcXVhdGlvbiBsZWZ0ICE9IHJpZ2h0ICgxKScpO1xuICAgICAgICAgICAgLy8gSW4gRXh0ZW5kZWQgY29vcmRpbmF0ZXMgd2UgYWxzbyBoYXZlIFQsIHdoaWNoIGlzIHgqeT1UL1o6IGNoZWNrIFgqWSA9PSBaKlRcbiAgICAgICAgICAgIGNvbnN0IFhZID0gbW9kUChYICogWSk7XG4gICAgICAgICAgICBjb25zdCBaVCA9IG1vZFAoWiAqIFQpO1xuICAgICAgICAgICAgaWYgKFhZICE9PSBaVClcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JhZCBwb2ludDogZXF1YXRpb24gbGVmdCAhPSByaWdodCAoMiknKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDb21wYXJlIG9uZSBwb2ludCB0byBhbm90aGVyLlxuICAgICAgICBlcXVhbHMob3RoZXIpIHtcbiAgICAgICAgICAgIGlzUG9pbnQob3RoZXIpO1xuICAgICAgICAgICAgY29uc3QgeyBleDogWDEsIGV5OiBZMSwgZXo6IFoxIH0gPSB0aGlzO1xuICAgICAgICAgICAgY29uc3QgeyBleDogWDIsIGV5OiBZMiwgZXo6IFoyIH0gPSBvdGhlcjtcbiAgICAgICAgICAgIGNvbnN0IFgxWjIgPSBtb2RQKFgxICogWjIpO1xuICAgICAgICAgICAgY29uc3QgWDJaMSA9IG1vZFAoWDIgKiBaMSk7XG4gICAgICAgICAgICBjb25zdCBZMVoyID0gbW9kUChZMSAqIFoyKTtcbiAgICAgICAgICAgIGNvbnN0IFkyWjEgPSBtb2RQKFkyICogWjEpO1xuICAgICAgICAgICAgcmV0dXJuIFgxWjIgPT09IFgyWjEgJiYgWTFaMiA9PT0gWTJaMTtcbiAgICAgICAgfVxuICAgICAgICBpczAoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5lcXVhbHMoUG9pbnQuWkVSTyk7XG4gICAgICAgIH1cbiAgICAgICAgbmVnYXRlKCkge1xuICAgICAgICAgICAgLy8gRmxpcHMgcG9pbnQgc2lnbiB0byBhIG5lZ2F0aXZlIG9uZSAoLXgsIHkgaW4gYWZmaW5lIGNvb3JkcylcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQobW9kUCgtdGhpcy5leCksIHRoaXMuZXksIHRoaXMuZXosIG1vZFAoLXRoaXMuZXQpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBGYXN0IGFsZ28gZm9yIGRvdWJsaW5nIEV4dGVuZGVkIFBvaW50LlxuICAgICAgICAvLyBodHRwczovL2h5cGVyZWxsaXB0aWMub3JnL0VGRC9nMXAvYXV0by10d2lzdGVkLWV4dGVuZGVkLmh0bWwjZG91YmxpbmctZGJsLTIwMDgtaHdjZFxuICAgICAgICAvLyBDb3N0OiA0TSArIDRTICsgMSphICsgNmFkZCArIDEqMi5cbiAgICAgICAgZG91YmxlKCkge1xuICAgICAgICAgICAgY29uc3QgeyBhIH0gPSBDVVJWRTtcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IFgxLCBleTogWTEsIGV6OiBaMSB9ID0gdGhpcztcbiAgICAgICAgICAgIGNvbnN0IEEgPSBtb2RQKFgxICogWDEpOyAvLyBBID0gWDEyXG4gICAgICAgICAgICBjb25zdCBCID0gbW9kUChZMSAqIFkxKTsgLy8gQiA9IFkxMlxuICAgICAgICAgICAgY29uc3QgQyA9IG1vZFAoXzJuICogbW9kUChaMSAqIFoxKSk7IC8vIEMgPSAyKloxMlxuICAgICAgICAgICAgY29uc3QgRCA9IG1vZFAoYSAqIEEpOyAvLyBEID0gYSpBXG4gICAgICAgICAgICBjb25zdCB4MXkxID0gWDEgKyBZMTtcbiAgICAgICAgICAgIGNvbnN0IEUgPSBtb2RQKG1vZFAoeDF5MSAqIHgxeTEpIC0gQSAtIEIpOyAvLyBFID0gKFgxK1kxKTItQS1CXG4gICAgICAgICAgICBjb25zdCBHID0gRCArIEI7IC8vIEcgPSBEK0JcbiAgICAgICAgICAgIGNvbnN0IEYgPSBHIC0gQzsgLy8gRiA9IEctQ1xuICAgICAgICAgICAgY29uc3QgSCA9IEQgLSBCOyAvLyBIID0gRC1CXG4gICAgICAgICAgICBjb25zdCBYMyA9IG1vZFAoRSAqIEYpOyAvLyBYMyA9IEUqRlxuICAgICAgICAgICAgY29uc3QgWTMgPSBtb2RQKEcgKiBIKTsgLy8gWTMgPSBHKkhcbiAgICAgICAgICAgIGNvbnN0IFQzID0gbW9kUChFICogSCk7IC8vIFQzID0gRSpIXG4gICAgICAgICAgICBjb25zdCBaMyA9IG1vZFAoRiAqIEcpOyAvLyBaMyA9IEYqR1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2ludChYMywgWTMsIFozLCBUMyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRmFzdCBhbGdvIGZvciBhZGRpbmcgMiBFeHRlbmRlZCBQb2ludHMuXG4gICAgICAgIC8vIGh0dHBzOi8vaHlwZXJlbGxpcHRpYy5vcmcvRUZEL2cxcC9hdXRvLXR3aXN0ZWQtZXh0ZW5kZWQuaHRtbCNhZGRpdGlvbi1hZGQtMjAwOC1od2NkXG4gICAgICAgIC8vIENvc3Q6IDlNICsgMSphICsgMSpkICsgN2FkZC5cbiAgICAgICAgYWRkKG90aGVyKSB7XG4gICAgICAgICAgICBpc1BvaW50KG90aGVyKTtcbiAgICAgICAgICAgIGNvbnN0IHsgYSwgZCB9ID0gQ1VSVkU7XG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYMSwgZXk6IFkxLCBlejogWjEsIGV0OiBUMSB9ID0gdGhpcztcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IFgyLCBleTogWTIsIGV6OiBaMiwgZXQ6IFQyIH0gPSBvdGhlcjtcbiAgICAgICAgICAgIC8vIEZhc3RlciBhbGdvIGZvciBhZGRpbmcgMiBFeHRlbmRlZCBQb2ludHMgd2hlbiBjdXJ2ZSdzIGE9LTEuXG4gICAgICAgICAgICAvLyBodHRwOi8vaHlwZXJlbGxpcHRpYy5vcmcvRUZEL2cxcC9hdXRvLXR3aXN0ZWQtZXh0ZW5kZWQtMS5odG1sI2FkZGl0aW9uLWFkZC0yMDA4LWh3Y2QtNFxuICAgICAgICAgICAgLy8gQ29zdDogOE0gKyA4YWRkICsgMioyLlxuICAgICAgICAgICAgLy8gTm90ZTogSXQgZG9lcyBub3QgY2hlY2sgd2hldGhlciB0aGUgYG90aGVyYCBwb2ludCBpcyB2YWxpZC5cbiAgICAgICAgICAgIGlmIChhID09PSBCaWdJbnQoLTEpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgQSA9IG1vZFAoKFkxIC0gWDEpICogKFkyICsgWDIpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBCID0gbW9kUCgoWTEgKyBYMSkgKiAoWTIgLSBYMikpO1xuICAgICAgICAgICAgICAgIGNvbnN0IEYgPSBtb2RQKEIgLSBBKTtcbiAgICAgICAgICAgICAgICBpZiAoRiA9PT0gXzBuKVxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy5kb3VibGUoKTsgLy8gU2FtZSBwb2ludC4gVGVzdHMgc2F5IGl0IGRvZXNuJ3QgYWZmZWN0IHRpbWluZ1xuICAgICAgICAgICAgICAgIGNvbnN0IEMgPSBtb2RQKFoxICogXzJuICogVDIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IEQgPSBtb2RQKFQxICogXzJuICogWjIpO1xuICAgICAgICAgICAgICAgIGNvbnN0IEUgPSBEICsgQztcbiAgICAgICAgICAgICAgICBjb25zdCBHID0gQiArIEE7XG4gICAgICAgICAgICAgICAgY29uc3QgSCA9IEQgLSBDO1xuICAgICAgICAgICAgICAgIGNvbnN0IFgzID0gbW9kUChFICogRik7XG4gICAgICAgICAgICAgICAgY29uc3QgWTMgPSBtb2RQKEcgKiBIKTtcbiAgICAgICAgICAgICAgICBjb25zdCBUMyA9IG1vZFAoRSAqIEgpO1xuICAgICAgICAgICAgICAgIGNvbnN0IFozID0gbW9kUChGICogRyk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2ludChYMywgWTMsIFozLCBUMyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zdCBBID0gbW9kUChYMSAqIFgyKTsgLy8gQSA9IFgxKlgyXG4gICAgICAgICAgICBjb25zdCBCID0gbW9kUChZMSAqIFkyKTsgLy8gQiA9IFkxKlkyXG4gICAgICAgICAgICBjb25zdCBDID0gbW9kUChUMSAqIGQgKiBUMik7IC8vIEMgPSBUMSpkKlQyXG4gICAgICAgICAgICBjb25zdCBEID0gbW9kUChaMSAqIFoyKTsgLy8gRCA9IFoxKloyXG4gICAgICAgICAgICBjb25zdCBFID0gbW9kUCgoWDEgKyBZMSkgKiAoWDIgKyBZMikgLSBBIC0gQik7IC8vIEUgPSAoWDErWTEpKihYMitZMiktQS1CXG4gICAgICAgICAgICBjb25zdCBGID0gRCAtIEM7IC8vIEYgPSBELUNcbiAgICAgICAgICAgIGNvbnN0IEcgPSBEICsgQzsgLy8gRyA9IEQrQ1xuICAgICAgICAgICAgY29uc3QgSCA9IG1vZFAoQiAtIGEgKiBBKTsgLy8gSCA9IEItYSpBXG4gICAgICAgICAgICBjb25zdCBYMyA9IG1vZFAoRSAqIEYpOyAvLyBYMyA9IEUqRlxuICAgICAgICAgICAgY29uc3QgWTMgPSBtb2RQKEcgKiBIKTsgLy8gWTMgPSBHKkhcbiAgICAgICAgICAgIGNvbnN0IFQzID0gbW9kUChFICogSCk7IC8vIFQzID0gRSpIXG4gICAgICAgICAgICBjb25zdCBaMyA9IG1vZFAoRiAqIEcpOyAvLyBaMyA9IEYqR1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQb2ludChYMywgWTMsIFozLCBUMyk7XG4gICAgICAgIH1cbiAgICAgICAgc3VidHJhY3Qob3RoZXIpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmFkZChvdGhlci5uZWdhdGUoKSk7XG4gICAgICAgIH1cbiAgICAgICAgd05BRihuKSB7XG4gICAgICAgICAgICByZXR1cm4gd25hZi53TkFGQ2FjaGVkKHRoaXMsIHBvaW50UHJlY29tcHV0ZXMsIG4sIFBvaW50Lm5vcm1hbGl6ZVopO1xuICAgICAgICB9XG4gICAgICAgIC8vIENvbnN0YW50LXRpbWUgbXVsdGlwbGljYXRpb24uXG4gICAgICAgIG11bHRpcGx5KHNjYWxhcikge1xuICAgICAgICAgICAgY29uc3QgeyBwLCBmIH0gPSB0aGlzLndOQUYoYXNzZXJ0SW5SYW5nZShzY2FsYXIsIENVUlZFX09SREVSKSk7XG4gICAgICAgICAgICByZXR1cm4gUG9pbnQubm9ybWFsaXplWihbcCwgZl0pWzBdO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5vbi1jb25zdGFudC10aW1lIG11bHRpcGxpY2F0aW9uLiBVc2VzIGRvdWJsZS1hbmQtYWRkIGFsZ29yaXRobS5cbiAgICAgICAgLy8gSXQncyBmYXN0ZXIsIGJ1dCBzaG91bGQgb25seSBiZSB1c2VkIHdoZW4geW91IGRvbid0IGNhcmUgYWJvdXRcbiAgICAgICAgLy8gYW4gZXhwb3NlZCBwcml2YXRlIGtleSBlLmcuIHNpZyB2ZXJpZmljYXRpb24uXG4gICAgICAgIC8vIERvZXMgTk9UIGFsbG93IHNjYWxhcnMgaGlnaGVyIHRoYW4gQ1VSVkUubi5cbiAgICAgICAgbXVsdGlwbHlVbnNhZmUoc2NhbGFyKSB7XG4gICAgICAgICAgICBsZXQgbiA9IGFzc2VydEdFMChzY2FsYXIpOyAvLyAwIDw9IHNjYWxhciA8IENVUlZFLm5cbiAgICAgICAgICAgIGlmIChuID09PSBfMG4pXG4gICAgICAgICAgICAgICAgcmV0dXJuIEk7XG4gICAgICAgICAgICBpZiAodGhpcy5lcXVhbHMoSSkgfHwgbiA9PT0gXzFuKVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgaWYgKHRoaXMuZXF1YWxzKEcpKVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLndOQUYobikucDtcbiAgICAgICAgICAgIHJldHVybiB3bmFmLnVuc2FmZUxhZGRlcih0aGlzLCBuKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDaGVja3MgaWYgcG9pbnQgaXMgb2Ygc21hbGwgb3JkZXIuXG4gICAgICAgIC8vIElmIHlvdSBhZGQgc29tZXRoaW5nIHRvIHNtYWxsIG9yZGVyIHBvaW50LCB5b3Ugd2lsbCBoYXZlIFwiZGlydHlcIlxuICAgICAgICAvLyBwb2ludCB3aXRoIHRvcnNpb24gY29tcG9uZW50LlxuICAgICAgICAvLyBNdWx0aXBsaWVzIHBvaW50IGJ5IGNvZmFjdG9yIGFuZCBjaGVja3MgaWYgdGhlIHJlc3VsdCBpcyAwLlxuICAgICAgICBpc1NtYWxsT3JkZXIoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tdWx0aXBseVVuc2FmZShjb2ZhY3RvcikuaXMwKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gTXVsdGlwbGllcyBwb2ludCBieSBjdXJ2ZSBvcmRlciBhbmQgY2hlY2tzIGlmIHRoZSByZXN1bHQgaXMgMC5cbiAgICAgICAgLy8gUmV0dXJucyBgZmFsc2VgIGlzIHRoZSBwb2ludCBpcyBkaXJ0eS5cbiAgICAgICAgaXNUb3JzaW9uRnJlZSgpIHtcbiAgICAgICAgICAgIHJldHVybiB3bmFmLnVuc2FmZUxhZGRlcih0aGlzLCBDVVJWRV9PUkRFUikuaXMwKCk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ29udmVydHMgRXh0ZW5kZWQgcG9pbnQgdG8gZGVmYXVsdCAoeCwgeSkgY29vcmRpbmF0ZXMuXG4gICAgICAgIC8vIENhbiBhY2NlcHQgcHJlY29tcHV0ZWQgWl4tMSAtIGZvciBleGFtcGxlLCBmcm9tIGludmVydEJhdGNoLlxuICAgICAgICB0b0FmZmluZShpeikge1xuICAgICAgICAgICAgY29uc3QgeyBleDogeCwgZXk6IHksIGV6OiB6IH0gPSB0aGlzO1xuICAgICAgICAgICAgY29uc3QgaXMwID0gdGhpcy5pczAoKTtcbiAgICAgICAgICAgIGlmIChpeiA9PSBudWxsKVxuICAgICAgICAgICAgICAgIGl6ID0gaXMwID8gXzhuIDogRnAuaW52KHopOyAvLyA4IHdhcyBjaG9zZW4gYXJiaXRyYXJpbHlcbiAgICAgICAgICAgIGNvbnN0IGF4ID0gbW9kUCh4ICogaXopO1xuICAgICAgICAgICAgY29uc3QgYXkgPSBtb2RQKHkgKiBpeik7XG4gICAgICAgICAgICBjb25zdCB6eiA9IG1vZFAoeiAqIGl6KTtcbiAgICAgICAgICAgIGlmIChpczApXG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgeDogXzBuLCB5OiBfMW4gfTtcbiAgICAgICAgICAgIGlmICh6eiAhPT0gXzFuKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW52WiB3YXMgaW52YWxpZCcpO1xuICAgICAgICAgICAgcmV0dXJuIHsgeDogYXgsIHk6IGF5IH07XG4gICAgICAgIH1cbiAgICAgICAgY2xlYXJDb2ZhY3RvcigpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgaDogY29mYWN0b3IgfSA9IENVUlZFO1xuICAgICAgICAgICAgaWYgKGNvZmFjdG9yID09PSBfMW4pXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tdWx0aXBseVVuc2FmZShjb2ZhY3Rvcik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ29udmVydHMgaGFzaCBzdHJpbmcgb3IgVWludDhBcnJheSB0byBQb2ludC5cbiAgICAgICAgLy8gVXNlcyBhbGdvIGZyb20gUkZDODAzMiA1LjEuMy5cbiAgICAgICAgc3RhdGljIGZyb21IZXgoaGV4LCB6aXAyMTUgPSBmYWxzZSkge1xuICAgICAgICAgICAgY29uc3QgeyBkLCBhIH0gPSBDVVJWRTtcbiAgICAgICAgICAgIGNvbnN0IGxlbiA9IEZwLkJZVEVTO1xuICAgICAgICAgICAgaGV4ID0gZW5zdXJlQnl0ZXMoJ3BvaW50SGV4JywgaGV4LCBsZW4pOyAvLyBjb3B5IGhleCB0byBhIG5ldyBhcnJheVxuICAgICAgICAgICAgY29uc3Qgbm9ybWVkID0gaGV4LnNsaWNlKCk7IC8vIGNvcHkgYWdhaW4sIHdlJ2xsIG1hbmlwdWxhdGUgaXRcbiAgICAgICAgICAgIGNvbnN0IGxhc3RCeXRlID0gaGV4W2xlbiAtIDFdOyAvLyBzZWxlY3QgbGFzdCBieXRlXG4gICAgICAgICAgICBub3JtZWRbbGVuIC0gMV0gPSBsYXN0Qnl0ZSAmIH4weDgwOyAvLyBjbGVhciBsYXN0IGJpdFxuICAgICAgICAgICAgY29uc3QgeSA9IHV0LmJ5dGVzVG9OdW1iZXJMRShub3JtZWQpO1xuICAgICAgICAgICAgaWYgKHkgPT09IF8wbikge1xuICAgICAgICAgICAgICAgIC8vIHk9MCBpcyBhbGxvd2VkXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBSRkM4MDMyIHByb2hpYml0cyA+PSBwLCBidXQgWklQMjE1IGRvZXNuJ3RcbiAgICAgICAgICAgICAgICBpZiAoemlwMjE1KVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnRJblJhbmdlKHksIE1BU0spOyAvLyB6aXAyMTU9dHJ1ZSBbMS4uUC0xXSAoMl4yNTUtMTktMSBmb3IgZWQyNTUxOSlcbiAgICAgICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgICAgIGFzc2VydEluUmFuZ2UoeSwgRnAuT1JERVIpOyAvLyB6aXAyMTU9ZmFsc2UgWzEuLk1BU0stMV0gKDJeMjU2LTEgZm9yIGVkMjU1MTkpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBFZDI1NTE5OiB4wrIgPSAoecKyLTEpLyhkecKyKzEpIG1vZCBwLiBFZDQ0ODogeMKyID0gKHnCsi0xKS8oZHnCsi0xKSBtb2QgcC4gR2VuZXJpYyBjYXNlOlxuICAgICAgICAgICAgLy8gYXjCsit5wrI9MStkeMKyecKyID0+IHnCsi0xPWR4wrJ5wrItYXjCsiA9PiB5wrItMT14wrIoZHnCsi1hKSA9PiB4wrI9KHnCsi0xKS8oZHnCsi1hKVxuICAgICAgICAgICAgY29uc3QgeTIgPSBtb2RQKHkgKiB5KTsgLy8gZGVub21pbmF0b3IgaXMgYWx3YXlzIG5vbi0wIG1vZCBwLlxuICAgICAgICAgICAgY29uc3QgdSA9IG1vZFAoeTIgLSBfMW4pOyAvLyB1ID0gecKyIC0gMVxuICAgICAgICAgICAgY29uc3QgdiA9IG1vZFAoZCAqIHkyIC0gYSk7IC8vIHYgPSBkIHnCsiArIDEuXG4gICAgICAgICAgICBsZXQgeyBpc1ZhbGlkLCB2YWx1ZTogeCB9ID0gdXZSYXRpbyh1LCB2KTsgLy8g4oiaKHUvdilcbiAgICAgICAgICAgIGlmICghaXNWYWxpZClcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1BvaW50LmZyb21IZXg6IGludmFsaWQgeSBjb29yZGluYXRlJyk7XG4gICAgICAgICAgICBjb25zdCBpc1hPZGQgPSAoeCAmIF8xbikgPT09IF8xbjsgLy8gVGhlcmUgYXJlIDIgc3F1YXJlIHJvb3RzLiBVc2UgeF8wIGJpdCB0byBzZWxlY3QgcHJvcGVyXG4gICAgICAgICAgICBjb25zdCBpc0xhc3RCeXRlT2RkID0gKGxhc3RCeXRlICYgMHg4MCkgIT09IDA7IC8vIHhfMCwgbGFzdCBiaXRcbiAgICAgICAgICAgIGlmICghemlwMjE1ICYmIHggPT09IF8wbiAmJiBpc0xhc3RCeXRlT2RkKVxuICAgICAgICAgICAgICAgIC8vIGlmIHg9MCBhbmQgeF8wID0gMSwgZmFpbFxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignUG9pbnQuZnJvbUhleDogeD0wIGFuZCB4XzA9MScpO1xuICAgICAgICAgICAgaWYgKGlzTGFzdEJ5dGVPZGQgIT09IGlzWE9kZClcbiAgICAgICAgICAgICAgICB4ID0gbW9kUCgteCk7IC8vIGlmIHhfMCAhPSB4IG1vZCAyLCBzZXQgeCA9IHAteFxuICAgICAgICAgICAgcmV0dXJuIFBvaW50LmZyb21BZmZpbmUoeyB4LCB5IH0pO1xuICAgICAgICB9XG4gICAgICAgIHN0YXRpYyBmcm9tUHJpdmF0ZUtleShwcml2S2V5KSB7XG4gICAgICAgICAgICByZXR1cm4gZ2V0RXh0ZW5kZWRQdWJsaWNLZXkocHJpdktleSkucG9pbnQ7XG4gICAgICAgIH1cbiAgICAgICAgdG9SYXdCeXRlcygpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgeCwgeSB9ID0gdGhpcy50b0FmZmluZSgpO1xuICAgICAgICAgICAgY29uc3QgYnl0ZXMgPSB1dC5udW1iZXJUb0J5dGVzTEUoeSwgRnAuQllURVMpOyAvLyBlYWNoIHkgaGFzIDIgeCB2YWx1ZXMgKHgsIC15KVxuICAgICAgICAgICAgYnl0ZXNbYnl0ZXMubGVuZ3RoIC0gMV0gfD0geCAmIF8xbiA/IDB4ODAgOiAwOyAvLyB3aGVuIGNvbXByZXNzaW5nLCBpdCdzIGVub3VnaCB0byBzdG9yZSB5XG4gICAgICAgICAgICByZXR1cm4gYnl0ZXM7IC8vIGFuZCB1c2UgdGhlIGxhc3QgYnl0ZSB0byBlbmNvZGUgc2lnbiBvZiB4XG4gICAgICAgIH1cbiAgICAgICAgdG9IZXgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdXQuYnl0ZXNUb0hleCh0aGlzLnRvUmF3Qnl0ZXMoKSk7IC8vIFNhbWUgYXMgdG9SYXdCeXRlcywgYnV0IHJldHVybnMgc3RyaW5nLlxuICAgICAgICB9XG4gICAgfVxuICAgIFBvaW50LkJBU0UgPSBuZXcgUG9pbnQoQ1VSVkUuR3gsIENVUlZFLkd5LCBfMW4sIG1vZFAoQ1VSVkUuR3ggKiBDVVJWRS5HeSkpO1xuICAgIFBvaW50LlpFUk8gPSBuZXcgUG9pbnQoXzBuLCBfMW4sIF8xbiwgXzBuKTsgLy8gMCwgMSwgMSwgMFxuICAgIGNvbnN0IHsgQkFTRTogRywgWkVSTzogSSB9ID0gUG9pbnQ7XG4gICAgY29uc3Qgd25hZiA9IHdOQUYoUG9pbnQsIG5CeXRlTGVuZ3RoICogOCk7XG4gICAgZnVuY3Rpb24gbW9kTihhKSB7XG4gICAgICAgIHJldHVybiBtb2QoYSwgQ1VSVkVfT1JERVIpO1xuICAgIH1cbiAgICAvLyBMaXR0bGUtZW5kaWFuIFNIQTUxMiB3aXRoIG1vZHVsbyBuXG4gICAgZnVuY3Rpb24gbW9kTl9MRShoYXNoKSB7XG4gICAgICAgIHJldHVybiBtb2ROKHV0LmJ5dGVzVG9OdW1iZXJMRShoYXNoKSk7XG4gICAgfVxuICAgIC8qKiBDb252ZW5pZW5jZSBtZXRob2QgdGhhdCBjcmVhdGVzIHB1YmxpYyBrZXkgYW5kIG90aGVyIHN0dWZmLiBSRkM4MDMyIDUuMS41ICovXG4gICAgZnVuY3Rpb24gZ2V0RXh0ZW5kZWRQdWJsaWNLZXkoa2V5KSB7XG4gICAgICAgIGNvbnN0IGxlbiA9IG5CeXRlTGVuZ3RoO1xuICAgICAgICBrZXkgPSBlbnN1cmVCeXRlcygncHJpdmF0ZSBrZXknLCBrZXksIGxlbik7XG4gICAgICAgIC8vIEhhc2ggcHJpdmF0ZSBrZXkgd2l0aCBjdXJ2ZSdzIGhhc2ggZnVuY3Rpb24gdG8gcHJvZHVjZSB1bmlmb3JtaW5nbHkgcmFuZG9tIGlucHV0XG4gICAgICAgIC8vIENoZWNrIGJ5dGUgbGVuZ3RoczogZW5zdXJlKDY0LCBoKGVuc3VyZSgzMiwga2V5KSkpXG4gICAgICAgIGNvbnN0IGhhc2hlZCA9IGVuc3VyZUJ5dGVzKCdoYXNoZWQgcHJpdmF0ZSBrZXknLCBjSGFzaChrZXkpLCAyICogbGVuKTtcbiAgICAgICAgY29uc3QgaGVhZCA9IGFkanVzdFNjYWxhckJ5dGVzKGhhc2hlZC5zbGljZSgwLCBsZW4pKTsgLy8gY2xlYXIgZmlyc3QgaGFsZiBiaXRzLCBwcm9kdWNlIEZFXG4gICAgICAgIGNvbnN0IHByZWZpeCA9IGhhc2hlZC5zbGljZShsZW4sIDIgKiBsZW4pOyAvLyBzZWNvbmQgaGFsZiBpcyBjYWxsZWQga2V5IHByZWZpeCAoNS4xLjYpXG4gICAgICAgIGNvbnN0IHNjYWxhciA9IG1vZE5fTEUoaGVhZCk7IC8vIFRoZSBhY3R1YWwgcHJpdmF0ZSBzY2FsYXJcbiAgICAgICAgY29uc3QgcG9pbnQgPSBHLm11bHRpcGx5KHNjYWxhcik7IC8vIFBvaW50IG9uIEVkd2FyZHMgY3VydmUgYWthIHB1YmxpYyBrZXlcbiAgICAgICAgY29uc3QgcG9pbnRCeXRlcyA9IHBvaW50LnRvUmF3Qnl0ZXMoKTsgLy8gVWludDhBcnJheSByZXByZXNlbnRhdGlvblxuICAgICAgICByZXR1cm4geyBoZWFkLCBwcmVmaXgsIHNjYWxhciwgcG9pbnQsIHBvaW50Qnl0ZXMgfTtcbiAgICB9XG4gICAgLy8gQ2FsY3VsYXRlcyBFZERTQSBwdWIga2V5LiBSRkM4MDMyIDUuMS41LiBQcml2a2V5IGlzIGhhc2hlZC4gVXNlIGZpcnN0IGhhbGYgd2l0aCAzIGJpdHMgY2xlYXJlZFxuICAgIGZ1bmN0aW9uIGdldFB1YmxpY0tleShwcml2S2V5KSB7XG4gICAgICAgIHJldHVybiBnZXRFeHRlbmRlZFB1YmxpY0tleShwcml2S2V5KS5wb2ludEJ5dGVzO1xuICAgIH1cbiAgICAvLyBpbnQoJ0xFJywgU0hBNTEyKGRvbTIoRiwgQykgfHwgbXNncykpIG1vZCBOXG4gICAgZnVuY3Rpb24gaGFzaERvbWFpblRvU2NhbGFyKGNvbnRleHQgPSBuZXcgVWludDhBcnJheSgpLCAuLi5tc2dzKSB7XG4gICAgICAgIGNvbnN0IG1zZyA9IHV0LmNvbmNhdEJ5dGVzKC4uLm1zZ3MpO1xuICAgICAgICByZXR1cm4gbW9kTl9MRShjSGFzaChkb21haW4obXNnLCBlbnN1cmVCeXRlcygnY29udGV4dCcsIGNvbnRleHQpLCAhIXByZWhhc2gpKSk7XG4gICAgfVxuICAgIC8qKiBTaWducyBtZXNzYWdlIHdpdGggcHJpdmF0ZUtleS4gUkZDODAzMiA1LjEuNiAqL1xuICAgIGZ1bmN0aW9uIHNpZ24obXNnLCBwcml2S2V5LCBvcHRpb25zID0ge30pIHtcbiAgICAgICAgbXNnID0gZW5zdXJlQnl0ZXMoJ21lc3NhZ2UnLCBtc2cpO1xuICAgICAgICBpZiAocHJlaGFzaClcbiAgICAgICAgICAgIG1zZyA9IHByZWhhc2gobXNnKTsgLy8gZm9yIGVkMjU1MTlwaCBldGMuXG4gICAgICAgIGNvbnN0IHsgcHJlZml4LCBzY2FsYXIsIHBvaW50Qnl0ZXMgfSA9IGdldEV4dGVuZGVkUHVibGljS2V5KHByaXZLZXkpO1xuICAgICAgICBjb25zdCByID0gaGFzaERvbWFpblRvU2NhbGFyKG9wdGlvbnMuY29udGV4dCwgcHJlZml4LCBtc2cpOyAvLyByID0gZG9tMihGLCBDKSB8fCBwcmVmaXggfHwgUEgoTSlcbiAgICAgICAgY29uc3QgUiA9IEcubXVsdGlwbHkocikudG9SYXdCeXRlcygpOyAvLyBSID0gckdcbiAgICAgICAgY29uc3QgayA9IGhhc2hEb21haW5Ub1NjYWxhcihvcHRpb25zLmNvbnRleHQsIFIsIHBvaW50Qnl0ZXMsIG1zZyk7IC8vIFIgfHwgQSB8fCBQSChNKVxuICAgICAgICBjb25zdCBzID0gbW9kTihyICsgayAqIHNjYWxhcik7IC8vIFMgPSAociArIGsgKiBzKSBtb2QgTFxuICAgICAgICBhc3NlcnRHRTAocyk7IC8vIDAgPD0gcyA8IGxcbiAgICAgICAgY29uc3QgcmVzID0gdXQuY29uY2F0Qnl0ZXMoUiwgdXQubnVtYmVyVG9CeXRlc0xFKHMsIEZwLkJZVEVTKSk7XG4gICAgICAgIHJldHVybiBlbnN1cmVCeXRlcygncmVzdWx0JywgcmVzLCBuQnl0ZUxlbmd0aCAqIDIpOyAvLyA2NC1ieXRlIHNpZ25hdHVyZVxuICAgIH1cbiAgICBjb25zdCB2ZXJpZnlPcHRzID0gVkVSSUZZX0RFRkFVTFQ7XG4gICAgZnVuY3Rpb24gdmVyaWZ5KHNpZywgbXNnLCBwdWJsaWNLZXksIG9wdGlvbnMgPSB2ZXJpZnlPcHRzKSB7XG4gICAgICAgIGNvbnN0IHsgY29udGV4dCwgemlwMjE1IH0gPSBvcHRpb25zO1xuICAgICAgICBjb25zdCBsZW4gPSBGcC5CWVRFUzsgLy8gVmVyaWZpZXMgRWREU0Egc2lnbmF0dXJlIGFnYWluc3QgbWVzc2FnZSBhbmQgcHVibGljIGtleS4gUkZDODAzMiA1LjEuNy5cbiAgICAgICAgc2lnID0gZW5zdXJlQnl0ZXMoJ3NpZ25hdHVyZScsIHNpZywgMiAqIGxlbik7IC8vIEFuIGV4dGVuZGVkIGdyb3VwIGVxdWF0aW9uIGlzIGNoZWNrZWQuXG4gICAgICAgIG1zZyA9IGVuc3VyZUJ5dGVzKCdtZXNzYWdlJywgbXNnKTtcbiAgICAgICAgaWYgKHByZWhhc2gpXG4gICAgICAgICAgICBtc2cgPSBwcmVoYXNoKG1zZyk7IC8vIGZvciBlZDI1NTE5cGgsIGV0Y1xuICAgICAgICBjb25zdCBzID0gdXQuYnl0ZXNUb051bWJlckxFKHNpZy5zbGljZShsZW4sIDIgKiBsZW4pKTtcbiAgICAgICAgLy8gemlwMjE1OiB0cnVlIGlzIGdvb2QgZm9yIGNvbnNlbnN1cy1jcml0aWNhbCBhcHBzIGFuZCBhbGxvd3MgcG9pbnRzIDwgMl4yNTZcbiAgICAgICAgLy8gemlwMjE1OiBmYWxzZSBmb2xsb3dzIFJGQzgwMzIgLyBOSVNUMTg2LTUgYW5kIHJlc3RyaWN0cyBwb2ludHMgdG8gQ1VSVkUucFxuICAgICAgICBsZXQgQSwgUiwgU0I7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBBID0gUG9pbnQuZnJvbUhleChwdWJsaWNLZXksIHppcDIxNSk7XG4gICAgICAgICAgICBSID0gUG9pbnQuZnJvbUhleChzaWcuc2xpY2UoMCwgbGVuKSwgemlwMjE1KTtcbiAgICAgICAgICAgIFNCID0gRy5tdWx0aXBseVVuc2FmZShzKTsgLy8gMCA8PSBzIDwgbCBpcyBkb25lIGluc2lkZVxuICAgICAgICB9XG4gICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmICghemlwMjE1ICYmIEEuaXNTbWFsbE9yZGVyKCkpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIGNvbnN0IGsgPSBoYXNoRG9tYWluVG9TY2FsYXIoY29udGV4dCwgUi50b1Jhd0J5dGVzKCksIEEudG9SYXdCeXRlcygpLCBtc2cpO1xuICAgICAgICBjb25zdCBSa0EgPSBSLmFkZChBLm11bHRpcGx5VW5zYWZlKGspKTtcbiAgICAgICAgLy8gWzhdW1NdQiA9IFs4XVIgKyBbOF1ba11BJ1xuICAgICAgICByZXR1cm4gUmtBLnN1YnRyYWN0KFNCKS5jbGVhckNvZmFjdG9yKCkuZXF1YWxzKFBvaW50LlpFUk8pO1xuICAgIH1cbiAgICBHLl9zZXRXaW5kb3dTaXplKDgpOyAvLyBFbmFibGUgcHJlY29tcHV0ZXMuIFNsb3dzIGRvd24gZmlyc3QgcHVibGljS2V5IGNvbXB1dGF0aW9uIGJ5IDIwbXMuXG4gICAgY29uc3QgdXRpbHMgPSB7XG4gICAgICAgIGdldEV4dGVuZGVkUHVibGljS2V5LFxuICAgICAgICAvLyBlZDI1NTE5IHByaXZhdGUga2V5cyBhcmUgdW5pZm9ybSAzMmIuIE5vIG5lZWQgdG8gY2hlY2sgZm9yIG1vZHVsbyBiaWFzLCBsaWtlIGluIHNlY3AyNTZrMS5cbiAgICAgICAgcmFuZG9tUHJpdmF0ZUtleTogKCkgPT4gcmFuZG9tQnl0ZXMoRnAuQllURVMpLFxuICAgICAgICAvKipcbiAgICAgICAgICogV2UncmUgZG9pbmcgc2NhbGFyIG11bHRpcGxpY2F0aW9uICh1c2VkIGluIGdldFB1YmxpY0tleSBldGMpIHdpdGggcHJlY29tcHV0ZWQgQkFTRV9QT0lOVFxuICAgICAgICAgKiB2YWx1ZXMuIFRoaXMgc2xvd3MgZG93biBmaXJzdCBnZXRQdWJsaWNLZXkoKSBieSBtaWxsaXNlY29uZHMgKHNlZSBTcGVlZCBzZWN0aW9uKSxcbiAgICAgICAgICogYnV0IGFsbG93cyB0byBzcGVlZC11cCBzdWJzZXF1ZW50IGdldFB1YmxpY0tleSgpIGNhbGxzIHVwIHRvIDIweC5cbiAgICAgICAgICogQHBhcmFtIHdpbmRvd1NpemUgMiwgNCwgOCwgMTZcbiAgICAgICAgICovXG4gICAgICAgIHByZWNvbXB1dGUod2luZG93U2l6ZSA9IDgsIHBvaW50ID0gUG9pbnQuQkFTRSkge1xuICAgICAgICAgICAgcG9pbnQuX3NldFdpbmRvd1NpemUod2luZG93U2l6ZSk7XG4gICAgICAgICAgICBwb2ludC5tdWx0aXBseShCaWdJbnQoMykpO1xuICAgICAgICAgICAgcmV0dXJuIHBvaW50O1xuICAgICAgICB9LFxuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgICAgQ1VSVkUsXG4gICAgICAgIGdldFB1YmxpY0tleSxcbiAgICAgICAgc2lnbixcbiAgICAgICAgdmVyaWZ5LFxuICAgICAgICBFeHRlbmRlZFBvaW50OiBQb2ludCxcbiAgICAgICAgdXRpbHMsXG4gICAgfTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWVkd2FyZHMuanMubWFwIiwiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuaW1wb3J0IHsgbW9kLCBwb3cgfSBmcm9tICcuL21vZHVsYXIuanMnO1xuaW1wb3J0IHsgYnl0ZXNUb051bWJlckxFLCBlbnN1cmVCeXRlcywgbnVtYmVyVG9CeXRlc0xFLCB2YWxpZGF0ZU9iamVjdCB9IGZyb20gJy4vdXRpbHMuanMnO1xuY29uc3QgXzBuID0gQmlnSW50KDApO1xuY29uc3QgXzFuID0gQmlnSW50KDEpO1xuZnVuY3Rpb24gdmFsaWRhdGVPcHRzKGN1cnZlKSB7XG4gICAgdmFsaWRhdGVPYmplY3QoY3VydmUsIHtcbiAgICAgICAgYTogJ2JpZ2ludCcsXG4gICAgfSwge1xuICAgICAgICBtb250Z29tZXJ5Qml0czogJ2lzU2FmZUludGVnZXInLFxuICAgICAgICBuQnl0ZUxlbmd0aDogJ2lzU2FmZUludGVnZXInLFxuICAgICAgICBhZGp1c3RTY2FsYXJCeXRlczogJ2Z1bmN0aW9uJyxcbiAgICAgICAgZG9tYWluOiAnZnVuY3Rpb24nLFxuICAgICAgICBwb3dQbWludXMyOiAnZnVuY3Rpb24nLFxuICAgICAgICBHdTogJ2JpZ2ludCcsXG4gICAgfSk7XG4gICAgLy8gU2V0IGRlZmF1bHRzXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeyAuLi5jdXJ2ZSB9KTtcbn1cbi8vIE5PVEU6IG5vdCByZWFsbHkgbW9udGdvbWVyeSBjdXJ2ZSwganVzdCBidW5jaCBvZiB2ZXJ5IHNwZWNpZmljIG1ldGhvZHMgZm9yIFgyNTUxOS9YNDQ4IChSRkMgNzc0OCwgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzc3NDgpXG4vLyBVc2VzIG9ubHkgb25lIGNvb3JkaW5hdGUgaW5zdGVhZCBvZiB0d29cbmV4cG9ydCBmdW5jdGlvbiBtb250Z29tZXJ5KGN1cnZlRGVmKSB7XG4gICAgY29uc3QgQ1VSVkUgPSB2YWxpZGF0ZU9wdHMoY3VydmVEZWYpO1xuICAgIGNvbnN0IHsgUCB9ID0gQ1VSVkU7XG4gICAgY29uc3QgbW9kUCA9IChuKSA9PiBtb2QobiwgUCk7XG4gICAgY29uc3QgbW9udGdvbWVyeUJpdHMgPSBDVVJWRS5tb250Z29tZXJ5Qml0cztcbiAgICBjb25zdCBtb250Z29tZXJ5Qnl0ZXMgPSBNYXRoLmNlaWwobW9udGdvbWVyeUJpdHMgLyA4KTtcbiAgICBjb25zdCBmaWVsZExlbiA9IENVUlZFLm5CeXRlTGVuZ3RoO1xuICAgIGNvbnN0IGFkanVzdFNjYWxhckJ5dGVzID0gQ1VSVkUuYWRqdXN0U2NhbGFyQnl0ZXMgfHwgKChieXRlcykgPT4gYnl0ZXMpO1xuICAgIGNvbnN0IHBvd1BtaW51czIgPSBDVVJWRS5wb3dQbWludXMyIHx8ICgoeCkgPT4gcG93KHgsIFAgLSBCaWdJbnQoMiksIFApKTtcbiAgICAvLyBjc3dhcCBmcm9tIFJGQzc3NDguIEJ1dCBpdCBpcyBub3QgZnJvbSBSRkM3NzQ4IVxuICAgIC8qXG4gICAgICBjc3dhcChzd2FwLCB4XzIsIHhfMyk6XG4gICAgICAgICAgIGR1bW15ID0gbWFzayhzd2FwKSBBTkQgKHhfMiBYT1IgeF8zKVxuICAgICAgICAgICB4XzIgPSB4XzIgWE9SIGR1bW15XG4gICAgICAgICAgIHhfMyA9IHhfMyBYT1IgZHVtbXlcbiAgICAgICAgICAgUmV0dXJuICh4XzIsIHhfMylcbiAgICBXaGVyZSBtYXNrKHN3YXApIGlzIHRoZSBhbGwtMSBvciBhbGwtMCB3b3JkIG9mIHRoZSBzYW1lIGxlbmd0aCBhcyB4XzJcbiAgICAgYW5kIHhfMywgY29tcHV0ZWQsIGUuZy4sIGFzIG1hc2soc3dhcCkgPSAwIC0gc3dhcC5cbiAgICAqL1xuICAgIGZ1bmN0aW9uIGNzd2FwKHN3YXAsIHhfMiwgeF8zKSB7XG4gICAgICAgIGNvbnN0IGR1bW15ID0gbW9kUChzd2FwICogKHhfMiAtIHhfMykpO1xuICAgICAgICB4XzIgPSBtb2RQKHhfMiAtIGR1bW15KTtcbiAgICAgICAgeF8zID0gbW9kUCh4XzMgKyBkdW1teSk7XG4gICAgICAgIHJldHVybiBbeF8yLCB4XzNdO1xuICAgIH1cbiAgICAvLyBBY2NlcHRzIDAgYXMgd2VsbFxuICAgIGZ1bmN0aW9uIGFzc2VydEZpZWxkRWxlbWVudChuKSB7XG4gICAgICAgIGlmICh0eXBlb2YgbiA9PT0gJ2JpZ2ludCcgJiYgXzBuIDw9IG4gJiYgbiA8IFApXG4gICAgICAgICAgICByZXR1cm4gbjtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCB2YWxpZCBzY2FsYXIgMCA8IHNjYWxhciA8IENVUlZFLlAnKTtcbiAgICB9XG4gICAgLy8geDI1NTE5IGZyb20gNFxuICAgIC8vIFRoZSBjb25zdGFudCBhMjQgaXMgKDQ4NjY2MiAtIDIpIC8gNCA9IDEyMTY2NSBmb3IgY3VydmUyNTUxOS9YMjU1MTlcbiAgICBjb25zdCBhMjQgPSAoQ1VSVkUuYSAtIEJpZ0ludCgyKSkgLyBCaWdJbnQoNCk7XG4gICAgLyoqXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcG9pbnRVIHUgY29vcmRpbmF0ZSAoeCkgb24gTW9udGdvbWVyeSBDdXJ2ZSAyNTUxOVxuICAgICAqIEBwYXJhbSBzY2FsYXIgYnkgd2hpY2ggdGhlIHBvaW50IHdvdWxkIGJlIG11bHRpcGxpZWRcbiAgICAgKiBAcmV0dXJucyBuZXcgUG9pbnQgb24gTW9udGdvbWVyeSBjdXJ2ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG1vbnRnb21lcnlMYWRkZXIocG9pbnRVLCBzY2FsYXIpIHtcbiAgICAgICAgY29uc3QgdSA9IGFzc2VydEZpZWxkRWxlbWVudChwb2ludFUpO1xuICAgICAgICAvLyBTZWN0aW9uIDU6IEltcGxlbWVudGF0aW9ucyBNVVNUIGFjY2VwdCBub24tY2Fub25pY2FsIHZhbHVlcyBhbmQgcHJvY2VzcyB0aGVtIGFzXG4gICAgICAgIC8vIGlmIHRoZXkgaGFkIGJlZW4gcmVkdWNlZCBtb2R1bG8gdGhlIGZpZWxkIHByaW1lLlxuICAgICAgICBjb25zdCBrID0gYXNzZXJ0RmllbGRFbGVtZW50KHNjYWxhcik7XG4gICAgICAgIGNvbnN0IHhfMSA9IHU7XG4gICAgICAgIGxldCB4XzIgPSBfMW47XG4gICAgICAgIGxldCB6XzIgPSBfMG47XG4gICAgICAgIGxldCB4XzMgPSB1O1xuICAgICAgICBsZXQgel8zID0gXzFuO1xuICAgICAgICBsZXQgc3dhcCA9IF8wbjtcbiAgICAgICAgbGV0IHN3O1xuICAgICAgICBmb3IgKGxldCB0ID0gQmlnSW50KG1vbnRnb21lcnlCaXRzIC0gMSk7IHQgPj0gXzBuOyB0LS0pIHtcbiAgICAgICAgICAgIGNvbnN0IGtfdCA9IChrID4+IHQpICYgXzFuO1xuICAgICAgICAgICAgc3dhcCBePSBrX3Q7XG4gICAgICAgICAgICBzdyA9IGNzd2FwKHN3YXAsIHhfMiwgeF8zKTtcbiAgICAgICAgICAgIHhfMiA9IHN3WzBdO1xuICAgICAgICAgICAgeF8zID0gc3dbMV07XG4gICAgICAgICAgICBzdyA9IGNzd2FwKHN3YXAsIHpfMiwgel8zKTtcbiAgICAgICAgICAgIHpfMiA9IHN3WzBdO1xuICAgICAgICAgICAgel8zID0gc3dbMV07XG4gICAgICAgICAgICBzd2FwID0ga190O1xuICAgICAgICAgICAgY29uc3QgQSA9IHhfMiArIHpfMjtcbiAgICAgICAgICAgIGNvbnN0IEFBID0gbW9kUChBICogQSk7XG4gICAgICAgICAgICBjb25zdCBCID0geF8yIC0gel8yO1xuICAgICAgICAgICAgY29uc3QgQkIgPSBtb2RQKEIgKiBCKTtcbiAgICAgICAgICAgIGNvbnN0IEUgPSBBQSAtIEJCO1xuICAgICAgICAgICAgY29uc3QgQyA9IHhfMyArIHpfMztcbiAgICAgICAgICAgIGNvbnN0IEQgPSB4XzMgLSB6XzM7XG4gICAgICAgICAgICBjb25zdCBEQSA9IG1vZFAoRCAqIEEpO1xuICAgICAgICAgICAgY29uc3QgQ0IgPSBtb2RQKEMgKiBCKTtcbiAgICAgICAgICAgIGNvbnN0IGRhY2IgPSBEQSArIENCO1xuICAgICAgICAgICAgY29uc3QgZGFfY2IgPSBEQSAtIENCO1xuICAgICAgICAgICAgeF8zID0gbW9kUChkYWNiICogZGFjYik7XG4gICAgICAgICAgICB6XzMgPSBtb2RQKHhfMSAqIG1vZFAoZGFfY2IgKiBkYV9jYikpO1xuICAgICAgICAgICAgeF8yID0gbW9kUChBQSAqIEJCKTtcbiAgICAgICAgICAgIHpfMiA9IG1vZFAoRSAqIChBQSArIG1vZFAoYTI0ICogRSkpKTtcbiAgICAgICAgfVxuICAgICAgICAvLyAoeF8yLCB4XzMpID0gY3N3YXAoc3dhcCwgeF8yLCB4XzMpXG4gICAgICAgIHN3ID0gY3N3YXAoc3dhcCwgeF8yLCB4XzMpO1xuICAgICAgICB4XzIgPSBzd1swXTtcbiAgICAgICAgeF8zID0gc3dbMV07XG4gICAgICAgIC8vICh6XzIsIHpfMykgPSBjc3dhcChzd2FwLCB6XzIsIHpfMylcbiAgICAgICAgc3cgPSBjc3dhcChzd2FwLCB6XzIsIHpfMyk7XG4gICAgICAgIHpfMiA9IHN3WzBdO1xuICAgICAgICB6XzMgPSBzd1sxXTtcbiAgICAgICAgLy8gel8yXihwIC0gMilcbiAgICAgICAgY29uc3QgejIgPSBwb3dQbWludXMyKHpfMik7XG4gICAgICAgIC8vIFJldHVybiB4XzIgKiAoel8yXihwIC0gMikpXG4gICAgICAgIHJldHVybiBtb2RQKHhfMiAqIHoyKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gZW5jb2RlVUNvb3JkaW5hdGUodSkge1xuICAgICAgICByZXR1cm4gbnVtYmVyVG9CeXRlc0xFKG1vZFAodSksIG1vbnRnb21lcnlCeXRlcyk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlY29kZVVDb29yZGluYXRlKHVFbmMpIHtcbiAgICAgICAgLy8gU2VjdGlvbiA1OiBXaGVuIHJlY2VpdmluZyBzdWNoIGFuIGFycmF5LCBpbXBsZW1lbnRhdGlvbnMgb2YgWDI1NTE5XG4gICAgICAgIC8vIE1VU1QgbWFzayB0aGUgbW9zdCBzaWduaWZpY2FudCBiaXQgaW4gdGhlIGZpbmFsIGJ5dGUuXG4gICAgICAgIC8vIFRoaXMgaXMgdmVyeSB1Z2x5IHdheSwgYnV0IGl0IHdvcmtzIGJlY2F1c2UgZmllbGRMZW4tMSBpcyBvdXRzaWRlIG9mIGJvdW5kcyBmb3IgWDQ0OCwgc28gdGhpcyBiZWNvbWVzIE5PT1BcbiAgICAgICAgLy8gZmllbGRMZW4gLSBzY2FsYXJ5Qnl0ZXMgPSAxIGZvciBYNDQ4IGFuZCA9IDAgZm9yIFgyNTUxOVxuICAgICAgICBjb25zdCB1ID0gZW5zdXJlQnl0ZXMoJ3UgY29vcmRpbmF0ZScsIHVFbmMsIG1vbnRnb21lcnlCeXRlcyk7XG4gICAgICAgIC8vIHVbZmllbGRMZW4tMV0gY3Jhc2hlcyBRdWlja0pTIChUeXBlRXJyb3I6IG91dC1vZi1ib3VuZCBudW1lcmljIGluZGV4KVxuICAgICAgICBpZiAoZmllbGRMZW4gPT09IG1vbnRnb21lcnlCeXRlcylcbiAgICAgICAgICAgIHVbZmllbGRMZW4gLSAxXSAmPSAxMjc7IC8vIDBiMDExMV8xMTExXG4gICAgICAgIHJldHVybiBieXRlc1RvTnVtYmVyTEUodSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlY29kZVNjYWxhcihuKSB7XG4gICAgICAgIGNvbnN0IGJ5dGVzID0gZW5zdXJlQnl0ZXMoJ3NjYWxhcicsIG4pO1xuICAgICAgICBpZiAoYnl0ZXMubGVuZ3RoICE9PSBtb250Z29tZXJ5Qnl0ZXMgJiYgYnl0ZXMubGVuZ3RoICE9PSBmaWVsZExlbilcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRXhwZWN0ZWQgJHttb250Z29tZXJ5Qnl0ZXN9IG9yICR7ZmllbGRMZW59IGJ5dGVzLCBnb3QgJHtieXRlcy5sZW5ndGh9YCk7XG4gICAgICAgIHJldHVybiBieXRlc1RvTnVtYmVyTEUoYWRqdXN0U2NhbGFyQnl0ZXMoYnl0ZXMpKTtcbiAgICB9XG4gICAgZnVuY3Rpb24gc2NhbGFyTXVsdChzY2FsYXIsIHUpIHtcbiAgICAgICAgY29uc3QgcG9pbnRVID0gZGVjb2RlVUNvb3JkaW5hdGUodSk7XG4gICAgICAgIGNvbnN0IF9zY2FsYXIgPSBkZWNvZGVTY2FsYXIoc2NhbGFyKTtcbiAgICAgICAgY29uc3QgcHUgPSBtb250Z29tZXJ5TGFkZGVyKHBvaW50VSwgX3NjYWxhcik7XG4gICAgICAgIC8vIFRoZSByZXN1bHQgd2FzIG5vdCBjb250cmlidXRvcnlcbiAgICAgICAgLy8gaHR0cHM6Ly9jci55cC50by9lY2RoLmh0bWwjdmFsaWRhdGVcbiAgICAgICAgaWYgKHB1ID09PSBfMG4pXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0ludmFsaWQgcHJpdmF0ZSBvciBwdWJsaWMga2V5IHJlY2VpdmVkJyk7XG4gICAgICAgIHJldHVybiBlbmNvZGVVQ29vcmRpbmF0ZShwdSk7XG4gICAgfVxuICAgIC8vIENvbXB1dGVzIHB1YmxpYyBrZXkgZnJvbSBwcml2YXRlLiBCeSBkb2luZyBzY2FsYXIgbXVsdGlwbGljYXRpb24gb2YgYmFzZSBwb2ludC5cbiAgICBjb25zdCBHdUJ5dGVzID0gZW5jb2RlVUNvb3JkaW5hdGUoQ1VSVkUuR3UpO1xuICAgIGZ1bmN0aW9uIHNjYWxhck11bHRCYXNlKHNjYWxhcikge1xuICAgICAgICByZXR1cm4gc2NhbGFyTXVsdChzY2FsYXIsIEd1Qnl0ZXMpO1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgICBzY2FsYXJNdWx0LFxuICAgICAgICBzY2FsYXJNdWx0QmFzZSxcbiAgICAgICAgZ2V0U2hhcmVkU2VjcmV0OiAocHJpdmF0ZUtleSwgcHVibGljS2V5KSA9PiBzY2FsYXJNdWx0KHByaXZhdGVLZXksIHB1YmxpY0tleSksXG4gICAgICAgIGdldFB1YmxpY0tleTogKHByaXZhdGVLZXkpID0+IHNjYWxhck11bHRCYXNlKHByaXZhdGVLZXkpLFxuICAgICAgICB1dGlsczogeyByYW5kb21Qcml2YXRlS2V5OiAoKSA9PiBDVVJWRS5yYW5kb21CeXRlcyhDVVJWRS5uQnl0ZUxlbmd0aCkgfSxcbiAgICAgICAgR3VCeXRlczogR3VCeXRlcyxcbiAgICB9O1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9bW9udGdvbWVyeS5qcy5tYXAiLCJpbXBvcnQgeyBtb2QgfSBmcm9tICcuL21vZHVsYXIuanMnO1xuaW1wb3J0IHsgYnl0ZXNUb051bWJlckJFLCBjb25jYXRCeXRlcywgdXRmOFRvQnl0ZXMsIHZhbGlkYXRlT2JqZWN0IH0gZnJvbSAnLi91dGlscy5qcyc7XG5mdW5jdGlvbiB2YWxpZGF0ZURTVChkc3QpIHtcbiAgICBpZiAoZHN0IGluc3RhbmNlb2YgVWludDhBcnJheSlcbiAgICAgICAgcmV0dXJuIGRzdDtcbiAgICBpZiAodHlwZW9mIGRzdCA9PT0gJ3N0cmluZycpXG4gICAgICAgIHJldHVybiB1dGY4VG9CeXRlcyhkc3QpO1xuICAgIHRocm93IG5ldyBFcnJvcignRFNUIG11c3QgYmUgVWludDhBcnJheSBvciBzdHJpbmcnKTtcbn1cbi8vIE9jdGV0IFN0cmVhbSB0byBJbnRlZ2VyLiBcInNwZWNcIiBpbXBsZW1lbnRhdGlvbiBvZiBvczJpcCBpcyAyLjV4IHNsb3dlciB2cyBieXRlc1RvTnVtYmVyQkUuXG5jb25zdCBvczJpcCA9IGJ5dGVzVG9OdW1iZXJCRTtcbi8vIEludGVnZXIgdG8gT2N0ZXQgU3RyZWFtIChudW1iZXJUb0J5dGVzQkUpXG5mdW5jdGlvbiBpMm9zcCh2YWx1ZSwgbGVuZ3RoKSB7XG4gICAgaWYgKHZhbHVlIDwgMCB8fCB2YWx1ZSA+PSAxIDw8ICg4ICogbGVuZ3RoKSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYGJhZCBJMk9TUCBjYWxsOiB2YWx1ZT0ke3ZhbHVlfSBsZW5ndGg9JHtsZW5ndGh9YCk7XG4gICAgfVxuICAgIGNvbnN0IHJlcyA9IEFycmF5LmZyb20oeyBsZW5ndGggfSkuZmlsbCgwKTtcbiAgICBmb3IgKGxldCBpID0gbGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIHtcbiAgICAgICAgcmVzW2ldID0gdmFsdWUgJiAweGZmO1xuICAgICAgICB2YWx1ZSA+Pj49IDg7XG4gICAgfVxuICAgIHJldHVybiBuZXcgVWludDhBcnJheShyZXMpO1xufVxuZnVuY3Rpb24gc3RyeG9yKGEsIGIpIHtcbiAgICBjb25zdCBhcnIgPSBuZXcgVWludDhBcnJheShhLmxlbmd0aCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGFycltpXSA9IGFbaV0gXiBiW2ldO1xuICAgIH1cbiAgICByZXR1cm4gYXJyO1xufVxuZnVuY3Rpb24gaXNCeXRlcyhpdGVtKSB7XG4gICAgaWYgKCEoaXRlbSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgZXhwZWN0ZWQnKTtcbn1cbmZ1bmN0aW9uIGlzTnVtKGl0ZW0pIHtcbiAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKGl0ZW0pKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ251bWJlciBleHBlY3RlZCcpO1xufVxuLy8gUHJvZHVjZXMgYSB1bmlmb3JtbHkgcmFuZG9tIGJ5dGUgc3RyaW5nIHVzaW5nIGEgY3J5cHRvZ3JhcGhpYyBoYXNoIGZ1bmN0aW9uIEggdGhhdCBvdXRwdXRzIGIgYml0c1xuLy8gaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9kcmFmdC1pcnRmLWNmcmctaGFzaC10by1jdXJ2ZS0xMSNzZWN0aW9uLTUuNC4xXG5leHBvcnQgZnVuY3Rpb24gZXhwYW5kX21lc3NhZ2VfeG1kKG1zZywgRFNULCBsZW5JbkJ5dGVzLCBIKSB7XG4gICAgaXNCeXRlcyhtc2cpO1xuICAgIGlzQnl0ZXMoRFNUKTtcbiAgICBpc051bShsZW5JbkJ5dGVzKTtcbiAgICAvLyBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTE2I3NlY3Rpb24tNS4zLjNcbiAgICBpZiAoRFNULmxlbmd0aCA+IDI1NSlcbiAgICAgICAgRFNUID0gSChjb25jYXRCeXRlcyh1dGY4VG9CeXRlcygnSDJDLU9WRVJTSVpFLURTVC0nKSwgRFNUKSk7XG4gICAgY29uc3QgeyBvdXRwdXRMZW46IGJfaW5fYnl0ZXMsIGJsb2NrTGVuOiByX2luX2J5dGVzIH0gPSBIO1xuICAgIGNvbnN0IGVsbCA9IE1hdGguY2VpbChsZW5JbkJ5dGVzIC8gYl9pbl9ieXRlcyk7XG4gICAgaWYgKGVsbCA+IDI1NSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHhtZCBsZW5ndGgnKTtcbiAgICBjb25zdCBEU1RfcHJpbWUgPSBjb25jYXRCeXRlcyhEU1QsIGkyb3NwKERTVC5sZW5ndGgsIDEpKTtcbiAgICBjb25zdCBaX3BhZCA9IGkyb3NwKDAsIHJfaW5fYnl0ZXMpO1xuICAgIGNvbnN0IGxfaV9iX3N0ciA9IGkyb3NwKGxlbkluQnl0ZXMsIDIpOyAvLyBsZW5faW5fYnl0ZXNfc3RyXG4gICAgY29uc3QgYiA9IG5ldyBBcnJheShlbGwpO1xuICAgIGNvbnN0IGJfMCA9IEgoY29uY2F0Qnl0ZXMoWl9wYWQsIG1zZywgbF9pX2Jfc3RyLCBpMm9zcCgwLCAxKSwgRFNUX3ByaW1lKSk7XG4gICAgYlswXSA9IEgoY29uY2F0Qnl0ZXMoYl8wLCBpMm9zcCgxLCAxKSwgRFNUX3ByaW1lKSk7XG4gICAgZm9yIChsZXQgaSA9IDE7IGkgPD0gZWxsOyBpKyspIHtcbiAgICAgICAgY29uc3QgYXJncyA9IFtzdHJ4b3IoYl8wLCBiW2kgLSAxXSksIGkyb3NwKGkgKyAxLCAxKSwgRFNUX3ByaW1lXTtcbiAgICAgICAgYltpXSA9IEgoY29uY2F0Qnl0ZXMoLi4uYXJncykpO1xuICAgIH1cbiAgICBjb25zdCBwc2V1ZG9fcmFuZG9tX2J5dGVzID0gY29uY2F0Qnl0ZXMoLi4uYik7XG4gICAgcmV0dXJuIHBzZXVkb19yYW5kb21fYnl0ZXMuc2xpY2UoMCwgbGVuSW5CeXRlcyk7XG59XG5leHBvcnQgZnVuY3Rpb24gZXhwYW5kX21lc3NhZ2VfeG9mKG1zZywgRFNULCBsZW5JbkJ5dGVzLCBrLCBIKSB7XG4gICAgaXNCeXRlcyhtc2cpO1xuICAgIGlzQnl0ZXMoRFNUKTtcbiAgICBpc051bShsZW5JbkJ5dGVzKTtcbiAgICAvLyBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTE2I3NlY3Rpb24tNS4zLjNcbiAgICAvLyBEU1QgPSBIKCdIMkMtT1ZFUlNJWkUtRFNULScgfHwgYV92ZXJ5X2xvbmdfRFNULCBNYXRoLmNlaWwoKGxlbkluQnl0ZXMgKiBrKSAvIDgpKTtcbiAgICBpZiAoRFNULmxlbmd0aCA+IDI1NSkge1xuICAgICAgICBjb25zdCBka0xlbiA9IE1hdGguY2VpbCgoMiAqIGspIC8gOCk7XG4gICAgICAgIERTVCA9IEguY3JlYXRlKHsgZGtMZW4gfSkudXBkYXRlKHV0ZjhUb0J5dGVzKCdIMkMtT1ZFUlNJWkUtRFNULScpKS51cGRhdGUoRFNUKS5kaWdlc3QoKTtcbiAgICB9XG4gICAgaWYgKGxlbkluQnl0ZXMgPiA2NTUzNSB8fCBEU1QubGVuZ3RoID4gMjU1KVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGFuZF9tZXNzYWdlX3hvZjogaW52YWxpZCBsZW5JbkJ5dGVzJyk7XG4gICAgcmV0dXJuIChILmNyZWF0ZSh7IGRrTGVuOiBsZW5JbkJ5dGVzIH0pXG4gICAgICAgIC51cGRhdGUobXNnKVxuICAgICAgICAudXBkYXRlKGkyb3NwKGxlbkluQnl0ZXMsIDIpKVxuICAgICAgICAvLyAyLiBEU1RfcHJpbWUgPSBEU1QgfHwgSTJPU1AobGVuKERTVCksIDEpXG4gICAgICAgIC51cGRhdGUoRFNUKVxuICAgICAgICAudXBkYXRlKGkyb3NwKERTVC5sZW5ndGgsIDEpKVxuICAgICAgICAuZGlnZXN0KCkpO1xufVxuLyoqXG4gKiBIYXNoZXMgYXJiaXRyYXJ5LWxlbmd0aCBieXRlIHN0cmluZ3MgdG8gYSBsaXN0IG9mIG9uZSBvciBtb3JlIGVsZW1lbnRzIG9mIGEgZmluaXRlIGZpZWxkIEZcbiAqIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvZHJhZnQtaXJ0Zi1jZnJnLWhhc2gtdG8tY3VydmUtMTEjc2VjdGlvbi01LjNcbiAqIEBwYXJhbSBtc2cgYSBieXRlIHN0cmluZyBjb250YWluaW5nIHRoZSBtZXNzYWdlIHRvIGhhc2hcbiAqIEBwYXJhbSBjb3VudCB0aGUgbnVtYmVyIG9mIGVsZW1lbnRzIG9mIEYgdG8gb3V0cHV0XG4gKiBAcGFyYW0gb3B0aW9ucyBge0RTVDogc3RyaW5nLCBwOiBiaWdpbnQsIG06IG51bWJlciwgazogbnVtYmVyLCBleHBhbmQ6ICd4bWQnIHwgJ3hvZicsIGhhc2g6IEh9YCwgc2VlIGFib3ZlXG4gKiBAcmV0dXJucyBbdV8wLCAuLi4sIHVfKGNvdW50IC0gMSldLCBhIGxpc3Qgb2YgZmllbGQgZWxlbWVudHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNoX3RvX2ZpZWxkKG1zZywgY291bnQsIG9wdGlvbnMpIHtcbiAgICB2YWxpZGF0ZU9iamVjdChvcHRpb25zLCB7XG4gICAgICAgIERTVDogJ3N0cmluZycsXG4gICAgICAgIHA6ICdiaWdpbnQnLFxuICAgICAgICBtOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIGs6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICAgICAgaGFzaDogJ2hhc2gnLFxuICAgIH0pO1xuICAgIGNvbnN0IHsgcCwgaywgbSwgaGFzaCwgZXhwYW5kLCBEU1Q6IF9EU1QgfSA9IG9wdGlvbnM7XG4gICAgaXNCeXRlcyhtc2cpO1xuICAgIGlzTnVtKGNvdW50KTtcbiAgICBjb25zdCBEU1QgPSB2YWxpZGF0ZURTVChfRFNUKTtcbiAgICBjb25zdCBsb2cycCA9IHAudG9TdHJpbmcoMikubGVuZ3RoO1xuICAgIGNvbnN0IEwgPSBNYXRoLmNlaWwoKGxvZzJwICsgaykgLyA4KTsgLy8gc2VjdGlvbiA1LjEgb2YgaWV0ZiBkcmFmdCBsaW5rIGFib3ZlXG4gICAgY29uc3QgbGVuX2luX2J5dGVzID0gY291bnQgKiBtICogTDtcbiAgICBsZXQgcHJiOyAvLyBwc2V1ZG9fcmFuZG9tX2J5dGVzXG4gICAgaWYgKGV4cGFuZCA9PT0gJ3htZCcpIHtcbiAgICAgICAgcHJiID0gZXhwYW5kX21lc3NhZ2VfeG1kKG1zZywgRFNULCBsZW5faW5fYnl0ZXMsIGhhc2gpO1xuICAgIH1cbiAgICBlbHNlIGlmIChleHBhbmQgPT09ICd4b2YnKSB7XG4gICAgICAgIHByYiA9IGV4cGFuZF9tZXNzYWdlX3hvZihtc2csIERTVCwgbGVuX2luX2J5dGVzLCBrLCBoYXNoKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZXhwYW5kID09PSAnX2ludGVybmFsX3Bhc3MnKSB7XG4gICAgICAgIC8vIGZvciBpbnRlcm5hbCB0ZXN0cyBvbmx5XG4gICAgICAgIHByYiA9IG1zZztcbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignZXhwYW5kIG11c3QgYmUgXCJ4bWRcIiBvciBcInhvZlwiJyk7XG4gICAgfVxuICAgIGNvbnN0IHUgPSBuZXcgQXJyYXkoY291bnQpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY291bnQ7IGkrKykge1xuICAgICAgICBjb25zdCBlID0gbmV3IEFycmF5KG0pO1xuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IG07IGorKykge1xuICAgICAgICAgICAgY29uc3QgZWxtX29mZnNldCA9IEwgKiAoaiArIGkgKiBtKTtcbiAgICAgICAgICAgIGNvbnN0IHR2ID0gcHJiLnN1YmFycmF5KGVsbV9vZmZzZXQsIGVsbV9vZmZzZXQgKyBMKTtcbiAgICAgICAgICAgIGVbal0gPSBtb2Qob3MyaXAodHYpLCBwKTtcbiAgICAgICAgfVxuICAgICAgICB1W2ldID0gZTtcbiAgICB9XG4gICAgcmV0dXJuIHU7XG59XG5leHBvcnQgZnVuY3Rpb24gaXNvZ2VueU1hcChmaWVsZCwgbWFwKSB7XG4gICAgLy8gTWFrZSBzYW1lIG9yZGVyIGFzIGluIHNwZWNcbiAgICBjb25zdCBDT0VGRiA9IG1hcC5tYXAoKGkpID0+IEFycmF5LmZyb20oaSkucmV2ZXJzZSgpKTtcbiAgICByZXR1cm4gKHgsIHkpID0+IHtcbiAgICAgICAgY29uc3QgW3hOdW0sIHhEZW4sIHlOdW0sIHlEZW5dID0gQ09FRkYubWFwKCh2YWwpID0+IHZhbC5yZWR1Y2UoKGFjYywgaSkgPT4gZmllbGQuYWRkKGZpZWxkLm11bChhY2MsIHgpLCBpKSkpO1xuICAgICAgICB4ID0gZmllbGQuZGl2KHhOdW0sIHhEZW4pOyAvLyB4TnVtIC8geERlblxuICAgICAgICB5ID0gZmllbGQubXVsKHksIGZpZWxkLmRpdih5TnVtLCB5RGVuKSk7IC8vIHkgKiAoeU51bSAvIHlEZXYpXG4gICAgICAgIHJldHVybiB7IHgsIHkgfTtcbiAgICB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGNyZWF0ZUhhc2hlcihQb2ludCwgbWFwVG9DdXJ2ZSwgZGVmKSB7XG4gICAgaWYgKHR5cGVvZiBtYXBUb0N1cnZlICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ21hcFRvQ3VydmUoKSBtdXN0IGJlIGRlZmluZWQnKTtcbiAgICByZXR1cm4ge1xuICAgICAgICAvLyBFbmNvZGVzIGJ5dGUgc3RyaW5nIHRvIGVsbGlwdGljIGN1cnZlXG4gICAgICAgIC8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvZHJhZnQtaXJ0Zi1jZnJnLWhhc2gtdG8tY3VydmUtMTYjc2VjdGlvbi0zXG4gICAgICAgIGhhc2hUb0N1cnZlKG1zZywgb3B0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgdSA9IGhhc2hfdG9fZmllbGQobXNnLCAyLCB7IC4uLmRlZiwgRFNUOiBkZWYuRFNULCAuLi5vcHRpb25zIH0pO1xuICAgICAgICAgICAgY29uc3QgdTAgPSBQb2ludC5mcm9tQWZmaW5lKG1hcFRvQ3VydmUodVswXSkpO1xuICAgICAgICAgICAgY29uc3QgdTEgPSBQb2ludC5mcm9tQWZmaW5lKG1hcFRvQ3VydmUodVsxXSkpO1xuICAgICAgICAgICAgY29uc3QgUCA9IHUwLmFkZCh1MSkuY2xlYXJDb2ZhY3RvcigpO1xuICAgICAgICAgICAgUC5hc3NlcnRWYWxpZGl0eSgpO1xuICAgICAgICAgICAgcmV0dXJuIFA7XG4gICAgICAgIH0sXG4gICAgICAgIC8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvZHJhZnQtaXJ0Zi1jZnJnLWhhc2gtdG8tY3VydmUtMTYjc2VjdGlvbi0zXG4gICAgICAgIGVuY29kZVRvQ3VydmUobXNnLCBvcHRpb25zKSB7XG4gICAgICAgICAgICBjb25zdCB1ID0gaGFzaF90b19maWVsZChtc2csIDEsIHsgLi4uZGVmLCBEU1Q6IGRlZi5lbmNvZGVEU1QsIC4uLm9wdGlvbnMgfSk7XG4gICAgICAgICAgICBjb25zdCBQID0gUG9pbnQuZnJvbUFmZmluZShtYXBUb0N1cnZlKHVbMF0pKS5jbGVhckNvZmFjdG9yKCk7XG4gICAgICAgICAgICBQLmFzc2VydFZhbGlkaXR5KCk7XG4gICAgICAgICAgICByZXR1cm4gUDtcbiAgICAgICAgfSxcbiAgICB9O1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aGFzaC10by1jdXJ2ZS5qcy5tYXAiLCIvKiEgbm9ibGUtY3VydmVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG5pbXBvcnQgeyBzaGFrZTI1NiB9IGZyb20gJ0Bub2JsZS9oYXNoZXMvc2hhMyc7XG5pbXBvcnQgeyBjb25jYXRCeXRlcywgcmFuZG9tQnl0ZXMsIHV0ZjhUb0J5dGVzLCB3cmFwQ29uc3RydWN0b3IgfSBmcm9tICdAbm9ibGUvaGFzaGVzL3V0aWxzJztcbmltcG9ydCB7IHR3aXN0ZWRFZHdhcmRzIH0gZnJvbSAnLi9hYnN0cmFjdC9lZHdhcmRzLmpzJztcbmltcG9ydCB7IG1vZCwgcG93MiwgRmllbGQgfSBmcm9tICcuL2Fic3RyYWN0L21vZHVsYXIuanMnO1xuaW1wb3J0IHsgbW9udGdvbWVyeSB9IGZyb20gJy4vYWJzdHJhY3QvbW9udGdvbWVyeS5qcyc7XG5pbXBvcnQgeyBjcmVhdGVIYXNoZXIgfSBmcm9tICcuL2Fic3RyYWN0L2hhc2gtdG8tY3VydmUuanMnO1xuLyoqXG4gKiBFZHdhcmRzNDQ4IChub3QgRWQ0NDgtR29sZGlsb2NrcykgY3VydmUgd2l0aCBmb2xsb3dpbmcgYWRkb25zOlxuICogKiBYNDQ4IEVDREhcbiAqIENvbmZvcm1zIHRvIFJGQyA4MDMyIGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL3JmYy9yZmM4MDMyLmh0bWwjc2VjdGlvbi01LjJcbiAqL1xuY29uc3Qgc2hha2UyNTZfMTE0ID0gd3JhcENvbnN0cnVjdG9yKCgpID0+IHNoYWtlMjU2LmNyZWF0ZSh7IGRrTGVuOiAxMTQgfSkpO1xuY29uc3Qgc2hha2UyNTZfNjQgPSB3cmFwQ29uc3RydWN0b3IoKCkgPT4gc2hha2UyNTYuY3JlYXRlKHsgZGtMZW46IDY0IH0pKTtcbmNvbnN0IGVkNDQ4UCA9IEJpZ0ludCgnNzI2ODM4NzI0Mjk1NjA2ODkwNTQ5MzIzODA3ODg4MDA0NTM0MzUzNjQxMzYwNjg3MzE4MDYwMjgxNDkwMTk5MTgwNjEyMzI4MTY2NzMwNzcyNjg2Mzk2MzgzNjk4Njc2NTQ1OTMwMDg4ODg0NDYxODQzNjM3MzYxMDUzNDk4MDE4MzY1NDM5Jyk7XG4vLyBwb3dQbWludXMzZGl2NCBjYWxjdWxhdGVzIHogPSB4XmsgbW9kIHAsIHdoZXJlIGsgPSAocC0zKS80LlxuLy8gVXNlZCBmb3IgZWZmaWNpZW50IHNxdWFyZSByb290IGNhbGN1bGF0aW9uLlxuLy8gKChQLTMpLzQpLnRvU3RyaW5nKDIpIHdvdWxkIHByb2R1Y2UgYml0cyBbMjIzeCAxLCAwLCAyMjJ4IDFdXG5mdW5jdGlvbiBlZDQ0OF9wb3dfUG1pbnVzM2RpdjQoeCkge1xuICAgIGNvbnN0IFAgPSBlZDQ0OFA7XG4gICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgY29uc3QgXzFuID0gQmlnSW50KDEpLCBfMm4gPSBCaWdJbnQoMiksIF8zbiA9IEJpZ0ludCgzKSwgXzExbiA9IEJpZ0ludCgxMSk7XG4gICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgY29uc3QgXzIybiA9IEJpZ0ludCgyMiksIF80NG4gPSBCaWdJbnQoNDQpLCBfODhuID0gQmlnSW50KDg4KSwgXzIyM24gPSBCaWdJbnQoMjIzKTtcbiAgICBjb25zdCBiMiA9ICh4ICogeCAqIHgpICUgUDtcbiAgICBjb25zdCBiMyA9IChiMiAqIGIyICogeCkgJSBQO1xuICAgIGNvbnN0IGI2ID0gKHBvdzIoYjMsIF8zbiwgUCkgKiBiMykgJSBQO1xuICAgIGNvbnN0IGI5ID0gKHBvdzIoYjYsIF8zbiwgUCkgKiBiMykgJSBQO1xuICAgIGNvbnN0IGIxMSA9IChwb3cyKGI5LCBfMm4sIFApICogYjIpICUgUDtcbiAgICBjb25zdCBiMjIgPSAocG93MihiMTEsIF8xMW4sIFApICogYjExKSAlIFA7XG4gICAgY29uc3QgYjQ0ID0gKHBvdzIoYjIyLCBfMjJuLCBQKSAqIGIyMikgJSBQO1xuICAgIGNvbnN0IGI4OCA9IChwb3cyKGI0NCwgXzQ0biwgUCkgKiBiNDQpICUgUDtcbiAgICBjb25zdCBiMTc2ID0gKHBvdzIoYjg4LCBfODhuLCBQKSAqIGI4OCkgJSBQO1xuICAgIGNvbnN0IGIyMjAgPSAocG93MihiMTc2LCBfNDRuLCBQKSAqIGI0NCkgJSBQO1xuICAgIGNvbnN0IGIyMjIgPSAocG93MihiMjIwLCBfMm4sIFApICogYjIpICUgUDtcbiAgICBjb25zdCBiMjIzID0gKHBvdzIoYjIyMiwgXzFuLCBQKSAqIHgpICUgUDtcbiAgICByZXR1cm4gKHBvdzIoYjIyMywgXzIyM24sIFApICogYjIyMikgJSBQO1xufVxuZnVuY3Rpb24gYWRqdXN0U2NhbGFyQnl0ZXMoYnl0ZXMpIHtcbiAgICAvLyBTZWN0aW9uIDU6IExpa2V3aXNlLCBmb3IgWDQ0OCwgc2V0IHRoZSB0d28gbGVhc3Qgc2lnbmlmaWNhbnQgYml0cyBvZiB0aGUgZmlyc3QgYnl0ZSB0byAwLCBhbmQgdGhlIG1vc3RcbiAgICAvLyBzaWduaWZpY2FudCBiaXQgb2YgdGhlIGxhc3QgYnl0ZSB0byAxLlxuICAgIGJ5dGVzWzBdICY9IDI1MjsgLy8gMGIxMTExMTEwMFxuICAgIC8vIGFuZCB0aGUgbW9zdCBzaWduaWZpY2FudCBiaXQgb2YgdGhlIGxhc3QgYnl0ZSB0byAxLlxuICAgIGJ5dGVzWzU1XSB8PSAxMjg7IC8vIDBiMTAwMDAwMDBcbiAgICAvLyBOT1RFOiBpcyBpcyBOT09QIGZvciA1NiBieXRlcyBzY2FsYXJzIChYMjU1MTkvWDQ0OClcbiAgICBieXRlc1s1Nl0gPSAwOyAvLyBCeXRlIG91dHNpZGUgb2YgZ3JvdXAgKDQ1NiBidXRzIHZzIDQ0OCBiaXRzKVxuICAgIHJldHVybiBieXRlcztcbn1cbmNvbnN0IEZwID0gRmllbGQoZWQ0NDhQLCA0NTYsIHRydWUpO1xuY29uc3QgXzRuID0gQmlnSW50KDQpO1xuY29uc3QgRUQ0NDhfREVGID0ge1xuICAgIC8vIFBhcmFtOiBhXG4gICAgYTogQmlnSW50KDEpLFxuICAgIC8vIC0zOTA4MS4gTmVnYXRpdmUgbnVtYmVyIGlzIFAgLSBudW1iZXJcbiAgICBkOiBCaWdJbnQoJzcyNjgzODcyNDI5NTYwNjg5MDU0OTMyMzgwNzg4ODAwNDUzNDM1MzY0MTM2MDY4NzMxODA2MDI4MTQ5MDE5OTE4MDYxMjMyODE2NjczMDc3MjY4NjM5NjM4MzY5ODY3NjU0NTkzMDA4ODg4NDQ2MTg0MzYzNzM2MTA1MzQ5ODAxODMyNjM1OCcpLFxuICAgIC8vIEZpbml0ZSBmaWVsZCDwnZS9cCBvdmVyIHdoaWNoIHdlJ2xsIGRvIGNhbGN1bGF0aW9uczsgMm4qKjQ0OG4gLSAybioqMjI0biAtIDFuXG4gICAgRnAsXG4gICAgLy8gU3ViZ3JvdXAgb3JkZXI6IGhvdyBtYW55IHBvaW50cyBjdXJ2ZSBoYXM7XG4gICAgLy8gMm4qKjQ0Nm4gLSAxMzgxODA2NjgwOTg5NTExNTM1MjAwNzM4Njc0ODUxNTQyNjg4MDMzNjY5MjQ3NDg4MjE3ODYwOTg5NDU0NzUwMzg4NW5cbiAgICBuOiBCaWdJbnQoJzE4MTcwOTY4MTA3MzkwMTcyMjYzNzMzMDk1MTk3MjAwMTEzMzU4ODQxMDM0MDE3MTgyOTUxNTA3MDM3MjU0OTc5NTE0NjAwMzk2MTUzOTU4NTcxNjE5NTc1NTI5MTY5MjM3NTk2MzMxMDI5MzcwOTA5MTY2MjMwNDc3Mzc1NTg1OTY0OTc3OScpLFxuICAgIG5CaXRMZW5ndGg6IDQ1NixcbiAgICAvLyBDb2ZhY3RvclxuICAgIGg6IEJpZ0ludCg0KSxcbiAgICAvLyBCYXNlIHBvaW50ICh4LCB5KSBha2EgZ2VuZXJhdG9yIHBvaW50XG4gICAgR3g6IEJpZ0ludCgnMjI0NTgwMDQwMjk1OTI0MzAwMTg3NjA0MzM0MDk5ODk2MDM2MjQ2Nzg5NjQxNjMyNTY0MTM0MjQ2MTI1NDYxNjg2OTUwNDE1NDY3NDA2MDMyOTA5MDI5MTkyODY5MzU3OTUzMjgyNTc4MDMyMDc1MTQ2NDQ2MTczNjc0NjAyNjM1MjQ3NzEwJyksXG4gICAgR3k6IEJpZ0ludCgnMjk4ODE5MjEwMDc4NDgxNDkyNjc2MDE3OTMwNDQzOTMwNjczNDM3NTQ0MDQwMTU0MDgwMjQyMDk1OTI4MjQxMzcyMzMxNTA2MTg5ODM1ODc2MDAzNTM2ODc4NjU1NDE4Nzg0NzMzOTgyMzAzMjMzNTAzNDYyNTAwNTMxNTQ1MDYyODMyNjYwJyksXG4gICAgLy8gU0hBS0UyNTYoZG9tNChwaGZsYWcsY29udGV4dCl8fHgsIDExNClcbiAgICBoYXNoOiBzaGFrZTI1Nl8xMTQsXG4gICAgcmFuZG9tQnl0ZXMsXG4gICAgYWRqdXN0U2NhbGFyQnl0ZXMsXG4gICAgLy8gZG9tNFxuICAgIGRvbWFpbjogKGRhdGEsIGN0eCwgcGhmbGFnKSA9PiB7XG4gICAgICAgIGlmIChjdHgubGVuZ3RoID4gMjU1KVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb250ZXh0IGlzIHRvbyBiaWc6ICR7Y3R4Lmxlbmd0aH1gKTtcbiAgICAgICAgcmV0dXJuIGNvbmNhdEJ5dGVzKHV0ZjhUb0J5dGVzKCdTaWdFZDQ0OCcpLCBuZXcgVWludDhBcnJheShbcGhmbGFnID8gMSA6IDAsIGN0eC5sZW5ndGhdKSwgY3R4LCBkYXRhKTtcbiAgICB9LFxuICAgIC8vIENvbnN0YW50LXRpbWUgcmF0aW8gb2YgdSB0byB2LiBBbGxvd3MgdG8gY29tYmluZSBpbnZlcnNpb24gYW5kIHNxdWFyZSByb290IHUv4oiadi5cbiAgICAvLyBVc2VzIGFsZ28gZnJvbSBSRkM4MDMyIDUuMS4zLlxuICAgIHV2UmF0aW86ICh1LCB2KSA9PiB7XG4gICAgICAgIGNvbnN0IFAgPSBlZDQ0OFA7XG4gICAgICAgIC8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvcmZjODAzMiNzZWN0aW9uLTUuMi4zXG4gICAgICAgIC8vIFRvIGNvbXB1dGUgdGhlIHNxdWFyZSByb290IG9mICh1L3YpLCB0aGUgZmlyc3Qgc3RlcCBpcyB0byBjb21wdXRlIHRoZVxuICAgICAgICAvLyAgIGNhbmRpZGF0ZSByb290IHggPSAodS92KV4oKHArMSkvNCkuICBUaGlzIGNhbiBiZSBkb25lIHVzaW5nIHRoZVxuICAgICAgICAvLyBmb2xsb3dpbmcgdHJpY2ssIHRvIHVzZSBhIHNpbmdsZSBtb2R1bGFyIHBvd2VyaW5nIGZvciBib3RoIHRoZVxuICAgICAgICAvLyBpbnZlcnNpb24gb2YgdiBhbmQgdGhlIHNxdWFyZSByb290OlxuICAgICAgICAvLyB4ID0gKHUvdileKChwKzEpLzQpICAgPSB1wrN2KHXigbV2wrMpXigocC0zKS80KSAgIChtb2QgcClcbiAgICAgICAgY29uc3QgdTJ2ID0gbW9kKHUgKiB1ICogdiwgUCk7IC8vIHXCsnZcbiAgICAgICAgY29uc3QgdTN2ID0gbW9kKHUydiAqIHUsIFApOyAvLyB1wrN2XG4gICAgICAgIGNvbnN0IHU1djMgPSBtb2QodTN2ICogdTJ2ICogdiwgUCk7IC8vIHXigbV2wrNcbiAgICAgICAgY29uc3Qgcm9vdCA9IGVkNDQ4X3Bvd19QbWludXMzZGl2NCh1NXYzKTtcbiAgICAgICAgY29uc3QgeCA9IG1vZCh1M3YgKiByb290LCBQKTtcbiAgICAgICAgLy8gVmVyaWZ5IHRoYXQgcm9vdCBpcyBleGlzdHNcbiAgICAgICAgY29uc3QgeDIgPSBtb2QoeCAqIHgsIFApOyAvLyB4wrJcbiAgICAgICAgLy8gSWYgdnjCsiA9IHUsIHRoZSByZWNvdmVyZWQgeC1jb29yZGluYXRlIGlzIHguICBPdGhlcndpc2UsIG5vXG4gICAgICAgIC8vIHNxdWFyZSByb290IGV4aXN0cywgYW5kIHRoZSBkZWNvZGluZyBmYWlscy5cbiAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogbW9kKHgyICogdiwgUCkgPT09IHUsIHZhbHVlOiB4IH07XG4gICAgfSxcbn07XG5leHBvcnQgY29uc3QgZWQ0NDggPSB0d2lzdGVkRWR3YXJkcyhFRDQ0OF9ERUYpO1xuLy8gTk9URTogdGhlcmUgaXMgbm8gZWQ0NDhjdHgsIHNpbmNlIGVkNDQ4IHN1cHBvcnRzIGN0eCBieSBkZWZhdWx0XG5leHBvcnQgY29uc3QgZWQ0NDhwaCA9IHR3aXN0ZWRFZHdhcmRzKHsgLi4uRUQ0NDhfREVGLCBwcmVoYXNoOiBzaGFrZTI1Nl82NCB9KTtcbmV4cG9ydCBjb25zdCB4NDQ4ID0gLyogQF9fUFVSRV9fICovICgoKSA9PiBtb250Z29tZXJ5KHtcbiAgICBhOiBCaWdJbnQoMTU2MzI2KSxcbiAgICBtb250Z29tZXJ5Qml0czogNDQ4LFxuICAgIG5CeXRlTGVuZ3RoOiA1NyxcbiAgICBQOiBlZDQ0OFAsXG4gICAgR3U6IEJpZ0ludCg1KSxcbiAgICBwb3dQbWludXMyOiAoeCkgPT4ge1xuICAgICAgICBjb25zdCBQID0gZWQ0NDhQO1xuICAgICAgICBjb25zdCBQbWludXMzZGl2NCA9IGVkNDQ4X3Bvd19QbWludXMzZGl2NCh4KTtcbiAgICAgICAgY29uc3QgUG1pbnVzMyA9IHBvdzIoUG1pbnVzM2RpdjQsIEJpZ0ludCgyKSwgUCk7XG4gICAgICAgIHJldHVybiBtb2QoUG1pbnVzMyAqIHgsIFApOyAvLyBQbWludXMzICogeCA9IFBtaW51czJcbiAgICB9LFxuICAgIGFkanVzdFNjYWxhckJ5dGVzLFxuICAgIHJhbmRvbUJ5dGVzLFxufSkpKCk7XG4vKipcbiAqIENvbnZlcnRzIGVkd2FyZHM0NDggcHVibGljIGtleSB0byB4NDQ4IHB1YmxpYyBrZXkuIFVzZXMgZm9ybXVsYTpcbiAqICogYCh1LCB2KSA9ICgoeS0xKS8oeSsxKSwgc3FydCgxNTYzMjQpKnUveClgXG4gKiAqIGAoeCwgeSkgPSAoc3FydCgxNTYzMjQpKnUvdiwgKDErdSkvKDEtdSkpYFxuICogQGV4YW1wbGVcbiAqICAgY29uc3QgYVB1YiA9IGVkNDQ4LmdldFB1YmxpY0tleSh1dGlscy5yYW5kb21Qcml2YXRlS2V5KCkpO1xuICogICB4NDQ4LmdldFNoYXJlZFNlY3JldChlZHdhcmRzVG9Nb250Z29tZXJ5KGFQdWIpLCBlZHdhcmRzVG9Nb250Z29tZXJ5KHNvbWVvbmVzUHViKSlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGVkd2FyZHNUb01vbnRnb21lcnlQdWIoZWR3YXJkc1B1Yikge1xuICAgIGNvbnN0IHsgeSB9ID0gZWQ0NDguRXh0ZW5kZWRQb2ludC5mcm9tSGV4KGVkd2FyZHNQdWIpO1xuICAgIGNvbnN0IF8xbiA9IEJpZ0ludCgxKTtcbiAgICByZXR1cm4gRnAudG9CeXRlcyhGcC5jcmVhdGUoKHkgLSBfMW4pICogRnAuaW52KHkgKyBfMW4pKSk7XG59XG5leHBvcnQgY29uc3QgZWR3YXJkc1RvTW9udGdvbWVyeSA9IGVkd2FyZHNUb01vbnRnb21lcnlQdWI7IC8vIGRlcHJlY2F0ZWRcbi8vIEhhc2ggVG8gQ3VydmUgRWxsaWdhdG9yMiBNYXBcbmNvbnN0IEVMTDJfQzEgPSAoRnAuT1JERVIgLSBCaWdJbnQoMykpIC8gQmlnSW50KDQpOyAvLyAxLiBjMSA9IChxIC0gMykgLyA0ICAgICAgICAgIyBJbnRlZ2VyIGFyaXRobWV0aWNcbmNvbnN0IEVMTDJfSiA9IEJpZ0ludCgxNTYzMjYpO1xuZnVuY3Rpb24gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfY3VydmU0NDgodSkge1xuICAgIGxldCB0djEgPSBGcC5zcXIodSk7IC8vIDEuICB0djEgPSB1XjJcbiAgICBsZXQgZTEgPSBGcC5lcWwodHYxLCBGcC5PTkUpOyAvLyAyLiAgIGUxID0gdHYxID09IDFcbiAgICB0djEgPSBGcC5jbW92KHR2MSwgRnAuWkVSTywgZTEpOyAvLyAzLiAgdHYxID0gQ01PVih0djEsIDAsIGUxKSAgIyBJZiBaICogdV4yID09IC0xLCBzZXQgdHYxID0gMFxuICAgIGxldCB4ZCA9IEZwLnN1YihGcC5PTkUsIHR2MSk7IC8vIDQuICAgeGQgPSAxIC0gdHYxXG4gICAgbGV0IHgxbiA9IEZwLm5lZyhFTEwyX0opOyAvLyA1LiAgeDFuID0gLUpcbiAgICBsZXQgdHYyID0gRnAuc3FyKHhkKTsgLy8gNi4gIHR2MiA9IHhkXjJcbiAgICBsZXQgZ3hkID0gRnAubXVsKHR2MiwgeGQpOyAvLyA3LiAgZ3hkID0gdHYyICogeGQgICAgICAgICAgIyBneGQgPSB4ZF4zXG4gICAgbGV0IGd4MSA9IEZwLm11bCh0djEsIEZwLm5lZyhFTEwyX0opKTsgLy8gOC4gIGd4MSA9IC1KICogdHYxICAgICAgICAgICMgeDFuICsgSiAqIHhkXG4gICAgZ3gxID0gRnAubXVsKGd4MSwgeDFuKTsgLy8gOS4gIGd4MSA9IGd4MSAqIHgxbiAgICAgICAgICMgeDFuXjIgKyBKICogeDFuICogeGRcbiAgICBneDEgPSBGcC5hZGQoZ3gxLCB0djIpOyAvLyAxMC4gZ3gxID0gZ3gxICsgdHYyICAgICAgICAgIyB4MW5eMiArIEogKiB4MW4gKiB4ZCArIHhkXjJcbiAgICBneDEgPSBGcC5tdWwoZ3gxLCB4MW4pOyAvLyAxMS4gZ3gxID0gZ3gxICogeDFuICAgICAgICAgIyB4MW5eMyArIEogKiB4MW5eMiAqIHhkICsgeDFuICogeGReMlxuICAgIGxldCB0djMgPSBGcC5zcXIoZ3hkKTsgLy8gMTIuIHR2MyA9IGd4ZF4yXG4gICAgdHYyID0gRnAubXVsKGd4MSwgZ3hkKTsgLy8gMTMuIHR2MiA9IGd4MSAqIGd4ZCAgICAgICAgICMgZ3gxICogZ3hkXG4gICAgdHYzID0gRnAubXVsKHR2MywgdHYyKTsgLy8gMTQuIHR2MyA9IHR2MyAqIHR2MiAgICAgICAgICMgZ3gxICogZ3hkXjNcbiAgICBsZXQgeTEgPSBGcC5wb3codHYzLCBFTEwyX0MxKTsgLy8gMTUuICB5MSA9IHR2M15jMSAgICAgICAgICAgICMgKGd4MSAqIGd4ZF4zKV4oKHAgLSAzKSAvIDQpXG4gICAgeTEgPSBGcC5tdWwoeTEsIHR2Mik7IC8vIDE2LiAgeTEgPSB5MSAqIHR2MiAgICAgICAgICAjIGd4MSAqIGd4ZCAqIChneDEgKiBneGReMyleKChwIC0gMykgLyA0KVxuICAgIGxldCB4Mm4gPSBGcC5tdWwoeDFuLCBGcC5uZWcodHYxKSk7IC8vIDE3LiB4Mm4gPSAtdHYxICogeDFuICAgICAgICAjIHgyID0geDJuIC8geGQgPSAtMSAqIHVeMiAqIHgxbiAvIHhkXG4gICAgbGV0IHkyID0gRnAubXVsKHkxLCB1KTsgLy8gMTguICB5MiA9IHkxICogdVxuICAgIHkyID0gRnAuY21vdih5MiwgRnAuWkVSTywgZTEpOyAvLyAxOS4gIHkyID0gQ01PVih5MiwgMCwgZTEpXG4gICAgdHYyID0gRnAuc3FyKHkxKTsgLy8gMjAuIHR2MiA9IHkxXjJcbiAgICB0djIgPSBGcC5tdWwodHYyLCBneGQpOyAvLyAyMS4gdHYyID0gdHYyICogZ3hkXG4gICAgbGV0IGUyID0gRnAuZXFsKHR2MiwgZ3gxKTsgLy8gMjIuICBlMiA9IHR2MiA9PSBneDFcbiAgICBsZXQgeG4gPSBGcC5jbW92KHgybiwgeDFuLCBlMik7IC8vIDIzLiAgeG4gPSBDTU9WKHgybiwgeDFuLCBlMikgICMgSWYgZTIsIHggPSB4MSwgZWxzZSB4ID0geDJcbiAgICBsZXQgeSA9IEZwLmNtb3YoeTIsIHkxLCBlMik7IC8vIDI0LiAgIHkgPSBDTU9WKHkyLCB5MSwgZTIpICAgICMgSWYgZTIsIHkgPSB5MSwgZWxzZSB5ID0geTJcbiAgICBsZXQgZTMgPSBGcC5pc09kZCh5KTsgLy8gMjUuICBlMyA9IHNnbjAoeSkgPT0gMSAgICAgICAgIyBGaXggc2lnbiBvZiB5XG4gICAgeSA9IEZwLmNtb3YoeSwgRnAubmVnKHkpLCBlMiAhPT0gZTMpOyAvLyAyNi4gICB5ID0gQ01PVih5LCAteSwgZTIgWE9SIGUzKVxuICAgIHJldHVybiB7IHhuLCB4ZCwgeW46IHksIHlkOiBGcC5PTkUgfTsgLy8gMjcuIHJldHVybiAoeG4sIHhkLCB5LCAxKVxufVxuZnVuY3Rpb24gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfZWR3YXJkczQ0OCh1KSB7XG4gICAgbGV0IHsgeG4sIHhkLCB5biwgeWQgfSA9IG1hcF90b19jdXJ2ZV9lbGxpZ2F0b3IyX2N1cnZlNDQ4KHUpOyAvLyAxLiAoeG4sIHhkLCB5biwgeWQpID0gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfY3VydmU0NDgodSlcbiAgICBsZXQgeG4yID0gRnAuc3FyKHhuKTsgLy8gMi4gIHhuMiA9IHhuXjJcbiAgICBsZXQgeGQyID0gRnAuc3FyKHhkKTsgLy8gMy4gIHhkMiA9IHhkXjJcbiAgICBsZXQgeGQ0ID0gRnAuc3FyKHhkMik7IC8vIDQuICB4ZDQgPSB4ZDJeMlxuICAgIGxldCB5bjIgPSBGcC5zcXIoeW4pOyAvLyA1LiAgeW4yID0geW5eMlxuICAgIGxldCB5ZDIgPSBGcC5zcXIoeWQpOyAvLyA2LiAgeWQyID0geWReMlxuICAgIGxldCB4RW4gPSBGcC5zdWIoeG4yLCB4ZDIpOyAvLyA3LiAgeEVuID0geG4yIC0geGQyXG4gICAgbGV0IHR2MiA9IEZwLnN1Yih4RW4sIHhkMik7IC8vIDguICB0djIgPSB4RW4gLSB4ZDJcbiAgICB4RW4gPSBGcC5tdWwoeEVuLCB4ZDIpOyAvLyA5LiAgeEVuID0geEVuICogeGQyXG4gICAgeEVuID0gRnAubXVsKHhFbiwgeWQpOyAvLyAxMC4geEVuID0geEVuICogeWRcbiAgICB4RW4gPSBGcC5tdWwoeEVuLCB5bik7IC8vIDExLiB4RW4gPSB4RW4gKiB5blxuICAgIHhFbiA9IEZwLm11bCh4RW4sIF80bik7IC8vIDEyLiB4RW4gPSB4RW4gKiA0XG4gICAgdHYyID0gRnAubXVsKHR2MiwgeG4yKTsgLy8gMTMuIHR2MiA9IHR2MiAqIHhuMlxuICAgIHR2MiA9IEZwLm11bCh0djIsIHlkMik7IC8vIDE0LiB0djIgPSB0djIgKiB5ZDJcbiAgICBsZXQgdHYzID0gRnAubXVsKHluMiwgXzRuKTsgLy8gMTUuIHR2MyA9IDQgKiB5bjJcbiAgICBsZXQgdHYxID0gRnAuYWRkKHR2MywgeWQyKTsgLy8gMTYuIHR2MSA9IHR2MyArIHlkMlxuICAgIHR2MSA9IEZwLm11bCh0djEsIHhkNCk7IC8vIDE3LiB0djEgPSB0djEgKiB4ZDRcbiAgICBsZXQgeEVkID0gRnAuYWRkKHR2MSwgdHYyKTsgLy8gMTguIHhFZCA9IHR2MSArIHR2MlxuICAgIHR2MiA9IEZwLm11bCh0djIsIHhuKTsgLy8gMTkuIHR2MiA9IHR2MiAqIHhuXG4gICAgbGV0IHR2NCA9IEZwLm11bCh4biwgeGQ0KTsgLy8gMjAuIHR2NCA9IHhuICogeGQ0XG4gICAgbGV0IHlFbiA9IEZwLnN1Yih0djMsIHlkMik7IC8vIDIxLiB5RW4gPSB0djMgLSB5ZDJcbiAgICB5RW4gPSBGcC5tdWwoeUVuLCB0djQpOyAvLyAyMi4geUVuID0geUVuICogdHY0XG4gICAgeUVuID0gRnAuc3ViKHlFbiwgdHYyKTsgLy8gMjMuIHlFbiA9IHlFbiAtIHR2MlxuICAgIHR2MSA9IEZwLmFkZCh4bjIsIHhkMik7IC8vIDI0LiB0djEgPSB4bjIgKyB4ZDJcbiAgICB0djEgPSBGcC5tdWwodHYxLCB4ZDIpOyAvLyAyNS4gdHYxID0gdHYxICogeGQyXG4gICAgdHYxID0gRnAubXVsKHR2MSwgeGQpOyAvLyAyNi4gdHYxID0gdHYxICogeGRcbiAgICB0djEgPSBGcC5tdWwodHYxLCB5bjIpOyAvLyAyNy4gdHYxID0gdHYxICogeW4yXG4gICAgdHYxID0gRnAubXVsKHR2MSwgQmlnSW50KC0yKSk7IC8vIDI4LiB0djEgPSAtMiAqIHR2MVxuICAgIGxldCB5RWQgPSBGcC5hZGQodHYyLCB0djEpOyAvLyAyOS4geUVkID0gdHYyICsgdHYxXG4gICAgdHY0ID0gRnAubXVsKHR2NCwgeWQyKTsgLy8gMzAuIHR2NCA9IHR2NCAqIHlkMlxuICAgIHlFZCA9IEZwLmFkZCh5RWQsIHR2NCk7IC8vIDMxLiB5RWQgPSB5RWQgKyB0djRcbiAgICB0djEgPSBGcC5tdWwoeEVkLCB5RWQpOyAvLyAzMi4gdHYxID0geEVkICogeUVkXG4gICAgbGV0IGUgPSBGcC5lcWwodHYxLCBGcC5aRVJPKTsgLy8gMzMuICAgZSA9IHR2MSA9PSAwXG4gICAgeEVuID0gRnAuY21vdih4RW4sIEZwLlpFUk8sIGUpOyAvLyAzNC4geEVuID0gQ01PVih4RW4sIDAsIGUpXG4gICAgeEVkID0gRnAuY21vdih4RWQsIEZwLk9ORSwgZSk7IC8vIDM1LiB4RWQgPSBDTU9WKHhFZCwgMSwgZSlcbiAgICB5RW4gPSBGcC5jbW92KHlFbiwgRnAuT05FLCBlKTsgLy8gMzYuIHlFbiA9IENNT1YoeUVuLCAxLCBlKVxuICAgIHlFZCA9IEZwLmNtb3YoeUVkLCBGcC5PTkUsIGUpOyAvLyAzNy4geUVkID0gQ01PVih5RWQsIDEsIGUpXG4gICAgY29uc3QgaW52ID0gRnAuaW52ZXJ0QmF0Y2goW3hFZCwgeUVkXSk7IC8vIGJhdGNoIGRpdmlzaW9uXG4gICAgcmV0dXJuIHsgeDogRnAubXVsKHhFbiwgaW52WzBdKSwgeTogRnAubXVsKHlFbiwgaW52WzFdKSB9OyAvLyAzOC4gcmV0dXJuICh4RW4sIHhFZCwgeUVuLCB5RWQpXG59XG5jb25zdCBodGYgPSAvKiBAX19QVVJFX18gKi8gKCgpID0+IGNyZWF0ZUhhc2hlcihlZDQ0OC5FeHRlbmRlZFBvaW50LCAoc2NhbGFycykgPT4gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfZWR3YXJkczQ0OChzY2FsYXJzWzBdKSwge1xuICAgIERTVDogJ2Vkd2FyZHM0NDhfWE9GOlNIQUtFMjU2X0VMTDJfUk9fJyxcbiAgICBlbmNvZGVEU1Q6ICdlZHdhcmRzNDQ4X1hPRjpTSEFLRTI1Nl9FTEwyX05VXycsXG4gICAgcDogRnAuT1JERVIsXG4gICAgbTogMSxcbiAgICBrOiAyMjQsXG4gICAgZXhwYW5kOiAneG9mJyxcbiAgICBoYXNoOiBzaGFrZTI1Nixcbn0pKSgpO1xuZXhwb3J0IGNvbnN0IGhhc2hUb0N1cnZlID0gLyogQF9fUFVSRV9fICovICgoKSA9PiBodGYuaGFzaFRvQ3VydmUpKCk7XG5leHBvcnQgY29uc3QgZW5jb2RlVG9DdXJ2ZSA9IC8qIEBfX1BVUkVfXyAqLyAoKCkgPT4gaHRmLmVuY29kZVRvQ3VydmUpKCk7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lZDQ0OC5qcy5tYXAiLCJmdW5jdGlvbiBfdHlwZW9mKG9iaikgeyBcIkBiYWJlbC9oZWxwZXJzIC0gdHlwZW9mXCI7IHJldHVybiBfdHlwZW9mID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgXCJzeW1ib2xcIiA9PSB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID8gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gdHlwZW9mIG9iajsgfSA6IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iaiAmJiBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajsgfSwgX3R5cGVvZihvYmopOyB9XG5mdW5jdGlvbiBfc2xpY2VkVG9BcnJheShhcnIsIGkpIHsgcmV0dXJuIF9hcnJheVdpdGhIb2xlcyhhcnIpIHx8IF9pdGVyYWJsZVRvQXJyYXlMaW1pdChhcnIsIGkpIHx8IF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShhcnIsIGkpIHx8IF9ub25JdGVyYWJsZVJlc3QoKTsgfVxuZnVuY3Rpb24gX25vbkl0ZXJhYmxlUmVzdCgpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBkZXN0cnVjdHVyZSBub24taXRlcmFibGUgaW5zdGFuY2UuXFxuSW4gb3JkZXIgdG8gYmUgaXRlcmFibGUsIG5vbi1hcnJheSBvYmplY3RzIG11c3QgaGF2ZSBhIFtTeW1ib2wuaXRlcmF0b3JdKCkgbWV0aG9kLlwiKTsgfVxuZnVuY3Rpb24gX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KG8sIG1pbkxlbikgeyBpZiAoIW8pIHJldHVybjsgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkobywgbWluTGVuKTsgdmFyIG4gPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobykuc2xpY2UoOCwgLTEpOyBpZiAobiA9PT0gXCJPYmplY3RcIiAmJiBvLmNvbnN0cnVjdG9yKSBuID0gby5jb25zdHJ1Y3Rvci5uYW1lOyBpZiAobiA9PT0gXCJNYXBcIiB8fCBuID09PSBcIlNldFwiKSByZXR1cm4gQXJyYXkuZnJvbShvKTsgaWYgKG4gPT09IFwiQXJndW1lbnRzXCIgfHwgL14oPzpVaXxJKW50KD86OHwxNnwzMikoPzpDbGFtcGVkKT9BcnJheSQvLnRlc3QobikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShvLCBtaW5MZW4pOyB9XG5mdW5jdGlvbiBfYXJyYXlMaWtlVG9BcnJheShhcnIsIGxlbikgeyBpZiAobGVuID09IG51bGwgfHwgbGVuID4gYXJyLmxlbmd0aCkgbGVuID0gYXJyLmxlbmd0aDsgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBuZXcgQXJyYXkobGVuKTsgaSA8IGxlbjsgaSsrKSBhcnIyW2ldID0gYXJyW2ldOyByZXR1cm4gYXJyMjsgfVxuZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkgeyB2YXIgX2kgPSBudWxsID09IGFyciA/IG51bGwgOiBcInVuZGVmaW5lZFwiICE9IHR5cGVvZiBTeW1ib2wgJiYgYXJyW1N5bWJvbC5pdGVyYXRvcl0gfHwgYXJyW1wiQEBpdGVyYXRvclwiXTsgaWYgKG51bGwgIT0gX2kpIHsgdmFyIF9zLCBfZSwgX3gsIF9yLCBfYXJyID0gW10sIF9uID0gITAsIF9kID0gITE7IHRyeSB7IGlmIChfeCA9IChfaSA9IF9pLmNhbGwoYXJyKSkubmV4dCwgMCA9PT0gaSkgeyBpZiAoT2JqZWN0KF9pKSAhPT0gX2kpIHJldHVybjsgX24gPSAhMTsgfSBlbHNlIGZvciAoOyAhKF9uID0gKF9zID0gX3guY2FsbChfaSkpLmRvbmUpICYmIChfYXJyLnB1c2goX3MudmFsdWUpLCBfYXJyLmxlbmd0aCAhPT0gaSk7IF9uID0gITApOyB9IGNhdGNoIChlcnIpIHsgX2QgPSAhMCwgX2UgPSBlcnI7IH0gZmluYWxseSB7IHRyeSB7IGlmICghX24gJiYgbnVsbCAhPSBfaVtcInJldHVyblwiXSAmJiAoX3IgPSBfaVtcInJldHVyblwiXSgpLCBPYmplY3QoX3IpICE9PSBfcikpIHJldHVybjsgfSBmaW5hbGx5IHsgaWYgKF9kKSB0aHJvdyBfZTsgfSB9IHJldHVybiBfYXJyOyB9IH1cbmZ1bmN0aW9uIF9hcnJheVdpdGhIb2xlcyhhcnIpIHsgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgcmV0dXJuIGFycjsgfVxuZnVuY3Rpb24gX3JlZ2VuZXJhdG9yUnVudGltZSgpIHsgXCJ1c2Ugc3RyaWN0XCI7IC8qISByZWdlbmVyYXRvci1ydW50aW1lIC0tIENvcHlyaWdodCAoYykgMjAxNC1wcmVzZW50LCBGYWNlYm9vaywgSW5jLiAtLSBsaWNlbnNlIChNSVQpOiBodHRwczovL2dpdGh1Yi5jb20vZmFjZWJvb2svcmVnZW5lcmF0b3IvYmxvYi9tYWluL0xJQ0VOU0UgKi8gX3JlZ2VuZXJhdG9yUnVudGltZSA9IGZ1bmN0aW9uIF9yZWdlbmVyYXRvclJ1bnRpbWUoKSB7IHJldHVybiBleHBvcnRzOyB9OyB2YXIgZXhwb3J0cyA9IHt9LCBPcCA9IE9iamVjdC5wcm90b3R5cGUsIGhhc093biA9IE9wLmhhc093blByb3BlcnR5LCBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSB8fCBmdW5jdGlvbiAob2JqLCBrZXksIGRlc2MpIHsgb2JqW2tleV0gPSBkZXNjLnZhbHVlOyB9LCAkU3ltYm9sID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgPyBTeW1ib2wgOiB7fSwgaXRlcmF0b3JTeW1ib2wgPSAkU3ltYm9sLml0ZXJhdG9yIHx8IFwiQEBpdGVyYXRvclwiLCBhc3luY0l0ZXJhdG9yU3ltYm9sID0gJFN5bWJvbC5hc3luY0l0ZXJhdG9yIHx8IFwiQEBhc3luY0l0ZXJhdG9yXCIsIHRvU3RyaW5nVGFnU3ltYm9sID0gJFN5bWJvbC50b1N0cmluZ1RhZyB8fCBcIkBAdG9TdHJpbmdUYWdcIjsgZnVuY3Rpb24gZGVmaW5lKG9iaiwga2V5LCB2YWx1ZSkgeyByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5LCB7IHZhbHVlOiB2YWx1ZSwgZW51bWVyYWJsZTogITAsIGNvbmZpZ3VyYWJsZTogITAsIHdyaXRhYmxlOiAhMCB9KSwgb2JqW2tleV07IH0gdHJ5IHsgZGVmaW5lKHt9LCBcIlwiKTsgfSBjYXRjaCAoZXJyKSB7IGRlZmluZSA9IGZ1bmN0aW9uIGRlZmluZShvYmosIGtleSwgdmFsdWUpIHsgcmV0dXJuIG9ialtrZXldID0gdmFsdWU7IH07IH0gZnVuY3Rpb24gd3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCkgeyB2YXIgcHJvdG9HZW5lcmF0b3IgPSBvdXRlckZuICYmIG91dGVyRm4ucHJvdG90eXBlIGluc3RhbmNlb2YgR2VuZXJhdG9yID8gb3V0ZXJGbiA6IEdlbmVyYXRvciwgZ2VuZXJhdG9yID0gT2JqZWN0LmNyZWF0ZShwcm90b0dlbmVyYXRvci5wcm90b3R5cGUpLCBjb250ZXh0ID0gbmV3IENvbnRleHQodHJ5TG9jc0xpc3QgfHwgW10pOyByZXR1cm4gZGVmaW5lUHJvcGVydHkoZ2VuZXJhdG9yLCBcIl9pbnZva2VcIiwgeyB2YWx1ZTogbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KSB9KSwgZ2VuZXJhdG9yOyB9IGZ1bmN0aW9uIHRyeUNhdGNoKGZuLCBvYmosIGFyZykgeyB0cnkgeyByZXR1cm4geyB0eXBlOiBcIm5vcm1hbFwiLCBhcmc6IGZuLmNhbGwob2JqLCBhcmcpIH07IH0gY2F0Y2ggKGVycikgeyByZXR1cm4geyB0eXBlOiBcInRocm93XCIsIGFyZzogZXJyIH07IH0gfSBleHBvcnRzLndyYXAgPSB3cmFwOyB2YXIgQ29udGludWVTZW50aW5lbCA9IHt9OyBmdW5jdGlvbiBHZW5lcmF0b3IoKSB7fSBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvbigpIHt9IGZ1bmN0aW9uIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKCkge30gdmFyIEl0ZXJhdG9yUHJvdG90eXBlID0ge307IGRlZmluZShJdGVyYXRvclByb3RvdHlwZSwgaXRlcmF0b3JTeW1ib2wsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pOyB2YXIgZ2V0UHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YsIE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlID0gZ2V0UHJvdG8gJiYgZ2V0UHJvdG8oZ2V0UHJvdG8odmFsdWVzKFtdKSkpOyBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSAmJiBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSAhPT0gT3AgJiYgaGFzT3duLmNhbGwoTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUsIGl0ZXJhdG9yU3ltYm9sKSAmJiAoSXRlcmF0b3JQcm90b3R5cGUgPSBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSk7IHZhciBHcCA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLnByb3RvdHlwZSA9IEdlbmVyYXRvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEl0ZXJhdG9yUHJvdG90eXBlKTsgZnVuY3Rpb24gZGVmaW5lSXRlcmF0b3JNZXRob2RzKHByb3RvdHlwZSkgeyBbXCJuZXh0XCIsIFwidGhyb3dcIiwgXCJyZXR1cm5cIl0uZm9yRWFjaChmdW5jdGlvbiAobWV0aG9kKSB7IGRlZmluZShwcm90b3R5cGUsIG1ldGhvZCwgZnVuY3Rpb24gKGFyZykgeyByZXR1cm4gdGhpcy5faW52b2tlKG1ldGhvZCwgYXJnKTsgfSk7IH0pOyB9IGZ1bmN0aW9uIEFzeW5jSXRlcmF0b3IoZ2VuZXJhdG9yLCBQcm9taXNlSW1wbCkgeyBmdW5jdGlvbiBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCkgeyB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goZ2VuZXJhdG9yW21ldGhvZF0sIGdlbmVyYXRvciwgYXJnKTsgaWYgKFwidGhyb3dcIiAhPT0gcmVjb3JkLnR5cGUpIHsgdmFyIHJlc3VsdCA9IHJlY29yZC5hcmcsIHZhbHVlID0gcmVzdWx0LnZhbHVlOyByZXR1cm4gdmFsdWUgJiYgXCJvYmplY3RcIiA9PSBfdHlwZW9mKHZhbHVlKSAmJiBoYXNPd24uY2FsbCh2YWx1ZSwgXCJfX2F3YWl0XCIpID8gUHJvbWlzZUltcGwucmVzb2x2ZSh2YWx1ZS5fX2F3YWl0KS50aGVuKGZ1bmN0aW9uICh2YWx1ZSkgeyBpbnZva2UoXCJuZXh0XCIsIHZhbHVlLCByZXNvbHZlLCByZWplY3QpOyB9LCBmdW5jdGlvbiAoZXJyKSB7IGludm9rZShcInRocm93XCIsIGVyciwgcmVzb2x2ZSwgcmVqZWN0KTsgfSkgOiBQcm9taXNlSW1wbC5yZXNvbHZlKHZhbHVlKS50aGVuKGZ1bmN0aW9uICh1bndyYXBwZWQpIHsgcmVzdWx0LnZhbHVlID0gdW53cmFwcGVkLCByZXNvbHZlKHJlc3VsdCk7IH0sIGZ1bmN0aW9uIChlcnJvcikgeyByZXR1cm4gaW52b2tlKFwidGhyb3dcIiwgZXJyb3IsIHJlc29sdmUsIHJlamVjdCk7IH0pOyB9IHJlamVjdChyZWNvcmQuYXJnKTsgfSB2YXIgcHJldmlvdXNQcm9taXNlOyBkZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIl9pbnZva2VcIiwgeyB2YWx1ZTogZnVuY3Rpb24gdmFsdWUobWV0aG9kLCBhcmcpIHsgZnVuY3Rpb24gY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcoKSB7IHJldHVybiBuZXcgUHJvbWlzZUltcGwoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgeyBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCk7IH0pOyB9IHJldHVybiBwcmV2aW91c1Byb21pc2UgPSBwcmV2aW91c1Byb21pc2UgPyBwcmV2aW91c1Byb21pc2UudGhlbihjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZywgY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcpIDogY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcoKTsgfSB9KTsgfSBmdW5jdGlvbiBtYWtlSW52b2tlTWV0aG9kKGlubmVyRm4sIHNlbGYsIGNvbnRleHQpIHsgdmFyIHN0YXRlID0gXCJzdXNwZW5kZWRTdGFydFwiOyByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZCwgYXJnKSB7IGlmIChcImV4ZWN1dGluZ1wiID09PSBzdGF0ZSkgdGhyb3cgbmV3IEVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgcnVubmluZ1wiKTsgaWYgKFwiY29tcGxldGVkXCIgPT09IHN0YXRlKSB7IGlmIChcInRocm93XCIgPT09IG1ldGhvZCkgdGhyb3cgYXJnOyByZXR1cm4gZG9uZVJlc3VsdCgpOyB9IGZvciAoY29udGV4dC5tZXRob2QgPSBtZXRob2QsIGNvbnRleHQuYXJnID0gYXJnOzspIHsgdmFyIGRlbGVnYXRlID0gY29udGV4dC5kZWxlZ2F0ZTsgaWYgKGRlbGVnYXRlKSB7IHZhciBkZWxlZ2F0ZVJlc3VsdCA9IG1heWJlSW52b2tlRGVsZWdhdGUoZGVsZWdhdGUsIGNvbnRleHQpOyBpZiAoZGVsZWdhdGVSZXN1bHQpIHsgaWYgKGRlbGVnYXRlUmVzdWx0ID09PSBDb250aW51ZVNlbnRpbmVsKSBjb250aW51ZTsgcmV0dXJuIGRlbGVnYXRlUmVzdWx0OyB9IH0gaWYgKFwibmV4dFwiID09PSBjb250ZXh0Lm1ldGhvZCkgY29udGV4dC5zZW50ID0gY29udGV4dC5fc2VudCA9IGNvbnRleHQuYXJnO2Vsc2UgaWYgKFwidGhyb3dcIiA9PT0gY29udGV4dC5tZXRob2QpIHsgaWYgKFwic3VzcGVuZGVkU3RhcnRcIiA9PT0gc3RhdGUpIHRocm93IHN0YXRlID0gXCJjb21wbGV0ZWRcIiwgY29udGV4dC5hcmc7IGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oY29udGV4dC5hcmcpOyB9IGVsc2UgXCJyZXR1cm5cIiA9PT0gY29udGV4dC5tZXRob2QgJiYgY29udGV4dC5hYnJ1cHQoXCJyZXR1cm5cIiwgY29udGV4dC5hcmcpOyBzdGF0ZSA9IFwiZXhlY3V0aW5nXCI7IHZhciByZWNvcmQgPSB0cnlDYXRjaChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTsgaWYgKFwibm9ybWFsXCIgPT09IHJlY29yZC50eXBlKSB7IGlmIChzdGF0ZSA9IGNvbnRleHQuZG9uZSA/IFwiY29tcGxldGVkXCIgOiBcInN1c3BlbmRlZFlpZWxkXCIsIHJlY29yZC5hcmcgPT09IENvbnRpbnVlU2VudGluZWwpIGNvbnRpbnVlOyByZXR1cm4geyB2YWx1ZTogcmVjb3JkLmFyZywgZG9uZTogY29udGV4dC5kb25lIH07IH0gXCJ0aHJvd1wiID09PSByZWNvcmQudHlwZSAmJiAoc3RhdGUgPSBcImNvbXBsZXRlZFwiLCBjb250ZXh0Lm1ldGhvZCA9IFwidGhyb3dcIiwgY29udGV4dC5hcmcgPSByZWNvcmQuYXJnKTsgfSB9OyB9IGZ1bmN0aW9uIG1heWJlSW52b2tlRGVsZWdhdGUoZGVsZWdhdGUsIGNvbnRleHQpIHsgdmFyIG1ldGhvZE5hbWUgPSBjb250ZXh0Lm1ldGhvZCwgbWV0aG9kID0gZGVsZWdhdGUuaXRlcmF0b3JbbWV0aG9kTmFtZV07IGlmICh1bmRlZmluZWQgPT09IG1ldGhvZCkgcmV0dXJuIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsLCBcInRocm93XCIgPT09IG1ldGhvZE5hbWUgJiYgZGVsZWdhdGUuaXRlcmF0b3JbXCJyZXR1cm5cIl0gJiYgKGNvbnRleHQubWV0aG9kID0gXCJyZXR1cm5cIiwgY29udGV4dC5hcmcgPSB1bmRlZmluZWQsIG1heWJlSW52b2tlRGVsZWdhdGUoZGVsZWdhdGUsIGNvbnRleHQpLCBcInRocm93XCIgPT09IGNvbnRleHQubWV0aG9kKSB8fCBcInJldHVyblwiICE9PSBtZXRob2ROYW1lICYmIChjb250ZXh0Lm1ldGhvZCA9IFwidGhyb3dcIiwgY29udGV4dC5hcmcgPSBuZXcgVHlwZUVycm9yKFwiVGhlIGl0ZXJhdG9yIGRvZXMgbm90IHByb3ZpZGUgYSAnXCIgKyBtZXRob2ROYW1lICsgXCInIG1ldGhvZFwiKSksIENvbnRpbnVlU2VudGluZWw7IHZhciByZWNvcmQgPSB0cnlDYXRjaChtZXRob2QsIGRlbGVnYXRlLml0ZXJhdG9yLCBjb250ZXh0LmFyZyk7IGlmIChcInRocm93XCIgPT09IHJlY29yZC50eXBlKSByZXR1cm4gY29udGV4dC5tZXRob2QgPSBcInRocm93XCIsIGNvbnRleHQuYXJnID0gcmVjb3JkLmFyZywgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGwsIENvbnRpbnVlU2VudGluZWw7IHZhciBpbmZvID0gcmVjb3JkLmFyZzsgcmV0dXJuIGluZm8gPyBpbmZvLmRvbmUgPyAoY29udGV4dFtkZWxlZ2F0ZS5yZXN1bHROYW1lXSA9IGluZm8udmFsdWUsIGNvbnRleHQubmV4dCA9IGRlbGVnYXRlLm5leHRMb2MsIFwicmV0dXJuXCIgIT09IGNvbnRleHQubWV0aG9kICYmIChjb250ZXh0Lm1ldGhvZCA9IFwibmV4dFwiLCBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZCksIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsLCBDb250aW51ZVNlbnRpbmVsKSA6IGluZm8gOiAoY29udGV4dC5tZXRob2QgPSBcInRocm93XCIsIGNvbnRleHQuYXJnID0gbmV3IFR5cGVFcnJvcihcIml0ZXJhdG9yIHJlc3VsdCBpcyBub3QgYW4gb2JqZWN0XCIpLCBjb250ZXh0LmRlbGVnYXRlID0gbnVsbCwgQ29udGludWVTZW50aW5lbCk7IH0gZnVuY3Rpb24gcHVzaFRyeUVudHJ5KGxvY3MpIHsgdmFyIGVudHJ5ID0geyB0cnlMb2M6IGxvY3NbMF0gfTsgMSBpbiBsb2NzICYmIChlbnRyeS5jYXRjaExvYyA9IGxvY3NbMV0pLCAyIGluIGxvY3MgJiYgKGVudHJ5LmZpbmFsbHlMb2MgPSBsb2NzWzJdLCBlbnRyeS5hZnRlckxvYyA9IGxvY3NbM10pLCB0aGlzLnRyeUVudHJpZXMucHVzaChlbnRyeSk7IH0gZnVuY3Rpb24gcmVzZXRUcnlFbnRyeShlbnRyeSkgeyB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbiB8fCB7fTsgcmVjb3JkLnR5cGUgPSBcIm5vcm1hbFwiLCBkZWxldGUgcmVjb3JkLmFyZywgZW50cnkuY29tcGxldGlvbiA9IHJlY29yZDsgfSBmdW5jdGlvbiBDb250ZXh0KHRyeUxvY3NMaXN0KSB7IHRoaXMudHJ5RW50cmllcyA9IFt7IHRyeUxvYzogXCJyb290XCIgfV0sIHRyeUxvY3NMaXN0LmZvckVhY2gocHVzaFRyeUVudHJ5LCB0aGlzKSwgdGhpcy5yZXNldCghMCk7IH0gZnVuY3Rpb24gdmFsdWVzKGl0ZXJhYmxlKSB7IGlmIChpdGVyYWJsZSkgeyB2YXIgaXRlcmF0b3JNZXRob2QgPSBpdGVyYWJsZVtpdGVyYXRvclN5bWJvbF07IGlmIChpdGVyYXRvck1ldGhvZCkgcmV0dXJuIGl0ZXJhdG9yTWV0aG9kLmNhbGwoaXRlcmFibGUpOyBpZiAoXCJmdW5jdGlvblwiID09IHR5cGVvZiBpdGVyYWJsZS5uZXh0KSByZXR1cm4gaXRlcmFibGU7IGlmICghaXNOYU4oaXRlcmFibGUubGVuZ3RoKSkgeyB2YXIgaSA9IC0xLCBuZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHsgZm9yICg7ICsraSA8IGl0ZXJhYmxlLmxlbmd0aDspIGlmIChoYXNPd24uY2FsbChpdGVyYWJsZSwgaSkpIHJldHVybiBuZXh0LnZhbHVlID0gaXRlcmFibGVbaV0sIG5leHQuZG9uZSA9ICExLCBuZXh0OyByZXR1cm4gbmV4dC52YWx1ZSA9IHVuZGVmaW5lZCwgbmV4dC5kb25lID0gITAsIG5leHQ7IH07IHJldHVybiBuZXh0Lm5leHQgPSBuZXh0OyB9IH0gcmV0dXJuIHsgbmV4dDogZG9uZVJlc3VsdCB9OyB9IGZ1bmN0aW9uIGRvbmVSZXN1bHQoKSB7IHJldHVybiB7IHZhbHVlOiB1bmRlZmluZWQsIGRvbmU6ICEwIH07IH0gcmV0dXJuIEdlbmVyYXRvckZ1bmN0aW9uLnByb3RvdHlwZSA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLCBkZWZpbmVQcm9wZXJ0eShHcCwgXCJjb25zdHJ1Y3RvclwiLCB7IHZhbHVlOiBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgY29uZmlndXJhYmxlOiAhMCB9KSwgZGVmaW5lUHJvcGVydHkoR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUsIFwiY29uc3RydWN0b3JcIiwgeyB2YWx1ZTogR2VuZXJhdG9yRnVuY3Rpb24sIGNvbmZpZ3VyYWJsZTogITAgfSksIEdlbmVyYXRvckZ1bmN0aW9uLmRpc3BsYXlOYW1lID0gZGVmaW5lKEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLCB0b1N0cmluZ1RhZ1N5bWJvbCwgXCJHZW5lcmF0b3JGdW5jdGlvblwiKSwgZXhwb3J0cy5pc0dlbmVyYXRvckZ1bmN0aW9uID0gZnVuY3Rpb24gKGdlbkZ1bikgeyB2YXIgY3RvciA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgZ2VuRnVuICYmIGdlbkZ1bi5jb25zdHJ1Y3RvcjsgcmV0dXJuICEhY3RvciAmJiAoY3RvciA9PT0gR2VuZXJhdG9yRnVuY3Rpb24gfHwgXCJHZW5lcmF0b3JGdW5jdGlvblwiID09PSAoY3Rvci5kaXNwbGF5TmFtZSB8fCBjdG9yLm5hbWUpKTsgfSwgZXhwb3J0cy5tYXJrID0gZnVuY3Rpb24gKGdlbkZ1bikgeyByZXR1cm4gT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKGdlbkZ1biwgR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUpIDogKGdlbkZ1bi5fX3Byb3RvX18gPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgZGVmaW5lKGdlbkZ1biwgdG9TdHJpbmdUYWdTeW1ib2wsIFwiR2VuZXJhdG9yRnVuY3Rpb25cIikpLCBnZW5GdW4ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShHcCksIGdlbkZ1bjsgfSwgZXhwb3J0cy5hd3JhcCA9IGZ1bmN0aW9uIChhcmcpIHsgcmV0dXJuIHsgX19hd2FpdDogYXJnIH07IH0sIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhBc3luY0l0ZXJhdG9yLnByb3RvdHlwZSksIGRlZmluZShBc3luY0l0ZXJhdG9yLnByb3RvdHlwZSwgYXN5bmNJdGVyYXRvclN5bWJvbCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSksIGV4cG9ydHMuQXN5bmNJdGVyYXRvciA9IEFzeW5jSXRlcmF0b3IsIGV4cG9ydHMuYXN5bmMgPSBmdW5jdGlvbiAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QsIFByb21pc2VJbXBsKSB7IHZvaWQgMCA9PT0gUHJvbWlzZUltcGwgJiYgKFByb21pc2VJbXBsID0gUHJvbWlzZSk7IHZhciBpdGVyID0gbmV3IEFzeW5jSXRlcmF0b3Iod3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCksIFByb21pc2VJbXBsKTsgcmV0dXJuIGV4cG9ydHMuaXNHZW5lcmF0b3JGdW5jdGlvbihvdXRlckZuKSA/IGl0ZXIgOiBpdGVyLm5leHQoKS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHsgcmV0dXJuIHJlc3VsdC5kb25lID8gcmVzdWx0LnZhbHVlIDogaXRlci5uZXh0KCk7IH0pOyB9LCBkZWZpbmVJdGVyYXRvck1ldGhvZHMoR3ApLCBkZWZpbmUoR3AsIHRvU3RyaW5nVGFnU3ltYm9sLCBcIkdlbmVyYXRvclwiKSwgZGVmaW5lKEdwLCBpdGVyYXRvclN5bWJvbCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSksIGRlZmluZShHcCwgXCJ0b1N0cmluZ1wiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBcIltvYmplY3QgR2VuZXJhdG9yXVwiOyB9KSwgZXhwb3J0cy5rZXlzID0gZnVuY3Rpb24gKHZhbCkgeyB2YXIgb2JqZWN0ID0gT2JqZWN0KHZhbCksIGtleXMgPSBbXTsgZm9yICh2YXIga2V5IGluIG9iamVjdCkga2V5cy5wdXNoKGtleSk7IHJldHVybiBrZXlzLnJldmVyc2UoKSwgZnVuY3Rpb24gbmV4dCgpIHsgZm9yICg7IGtleXMubGVuZ3RoOykgeyB2YXIga2V5ID0ga2V5cy5wb3AoKTsgaWYgKGtleSBpbiBvYmplY3QpIHJldHVybiBuZXh0LnZhbHVlID0ga2V5LCBuZXh0LmRvbmUgPSAhMSwgbmV4dDsgfSByZXR1cm4gbmV4dC5kb25lID0gITAsIG5leHQ7IH07IH0sIGV4cG9ydHMudmFsdWVzID0gdmFsdWVzLCBDb250ZXh0LnByb3RvdHlwZSA9IHsgY29uc3RydWN0b3I6IENvbnRleHQsIHJlc2V0OiBmdW5jdGlvbiByZXNldChza2lwVGVtcFJlc2V0KSB7IGlmICh0aGlzLnByZXYgPSAwLCB0aGlzLm5leHQgPSAwLCB0aGlzLnNlbnQgPSB0aGlzLl9zZW50ID0gdW5kZWZpbmVkLCB0aGlzLmRvbmUgPSAhMSwgdGhpcy5kZWxlZ2F0ZSA9IG51bGwsIHRoaXMubWV0aG9kID0gXCJuZXh0XCIsIHRoaXMuYXJnID0gdW5kZWZpbmVkLCB0aGlzLnRyeUVudHJpZXMuZm9yRWFjaChyZXNldFRyeUVudHJ5KSwgIXNraXBUZW1wUmVzZXQpIGZvciAodmFyIG5hbWUgaW4gdGhpcykgXCJ0XCIgPT09IG5hbWUuY2hhckF0KDApICYmIGhhc093bi5jYWxsKHRoaXMsIG5hbWUpICYmICFpc05hTigrbmFtZS5zbGljZSgxKSkgJiYgKHRoaXNbbmFtZV0gPSB1bmRlZmluZWQpOyB9LCBzdG9wOiBmdW5jdGlvbiBzdG9wKCkgeyB0aGlzLmRvbmUgPSAhMDsgdmFyIHJvb3RSZWNvcmQgPSB0aGlzLnRyeUVudHJpZXNbMF0uY29tcGxldGlvbjsgaWYgKFwidGhyb3dcIiA9PT0gcm9vdFJlY29yZC50eXBlKSB0aHJvdyByb290UmVjb3JkLmFyZzsgcmV0dXJuIHRoaXMucnZhbDsgfSwgZGlzcGF0Y2hFeGNlcHRpb246IGZ1bmN0aW9uIGRpc3BhdGNoRXhjZXB0aW9uKGV4Y2VwdGlvbikgeyBpZiAodGhpcy5kb25lKSB0aHJvdyBleGNlcHRpb247IHZhciBjb250ZXh0ID0gdGhpczsgZnVuY3Rpb24gaGFuZGxlKGxvYywgY2F1Z2h0KSB7IHJldHVybiByZWNvcmQudHlwZSA9IFwidGhyb3dcIiwgcmVjb3JkLmFyZyA9IGV4Y2VwdGlvbiwgY29udGV4dC5uZXh0ID0gbG9jLCBjYXVnaHQgJiYgKGNvbnRleHQubWV0aG9kID0gXCJuZXh0XCIsIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkKSwgISFjYXVnaHQ7IH0gZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgeyB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV0sIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb247IGlmIChcInJvb3RcIiA9PT0gZW50cnkudHJ5TG9jKSByZXR1cm4gaGFuZGxlKFwiZW5kXCIpOyBpZiAoZW50cnkudHJ5TG9jIDw9IHRoaXMucHJldikgeyB2YXIgaGFzQ2F0Y2ggPSBoYXNPd24uY2FsbChlbnRyeSwgXCJjYXRjaExvY1wiKSwgaGFzRmluYWxseSA9IGhhc093bi5jYWxsKGVudHJ5LCBcImZpbmFsbHlMb2NcIik7IGlmIChoYXNDYXRjaCAmJiBoYXNGaW5hbGx5KSB7IGlmICh0aGlzLnByZXYgPCBlbnRyeS5jYXRjaExvYykgcmV0dXJuIGhhbmRsZShlbnRyeS5jYXRjaExvYywgITApOyBpZiAodGhpcy5wcmV2IDwgZW50cnkuZmluYWxseUxvYykgcmV0dXJuIGhhbmRsZShlbnRyeS5maW5hbGx5TG9jKTsgfSBlbHNlIGlmIChoYXNDYXRjaCkgeyBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHJldHVybiBoYW5kbGUoZW50cnkuY2F0Y2hMb2MsICEwKTsgfSBlbHNlIHsgaWYgKCFoYXNGaW5hbGx5KSB0aHJvdyBuZXcgRXJyb3IoXCJ0cnkgc3RhdGVtZW50IHdpdGhvdXQgY2F0Y2ggb3IgZmluYWxseVwiKTsgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHJldHVybiBoYW5kbGUoZW50cnkuZmluYWxseUxvYyk7IH0gfSB9IH0sIGFicnVwdDogZnVuY3Rpb24gYWJydXB0KHR5cGUsIGFyZykgeyBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7IHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsgaWYgKGVudHJ5LnRyeUxvYyA8PSB0aGlzLnByZXYgJiYgaGFzT3duLmNhbGwoZW50cnksIFwiZmluYWxseUxvY1wiKSAmJiB0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7IHZhciBmaW5hbGx5RW50cnkgPSBlbnRyeTsgYnJlYWs7IH0gfSBmaW5hbGx5RW50cnkgJiYgKFwiYnJlYWtcIiA9PT0gdHlwZSB8fCBcImNvbnRpbnVlXCIgPT09IHR5cGUpICYmIGZpbmFsbHlFbnRyeS50cnlMb2MgPD0gYXJnICYmIGFyZyA8PSBmaW5hbGx5RW50cnkuZmluYWxseUxvYyAmJiAoZmluYWxseUVudHJ5ID0gbnVsbCk7IHZhciByZWNvcmQgPSBmaW5hbGx5RW50cnkgPyBmaW5hbGx5RW50cnkuY29tcGxldGlvbiA6IHt9OyByZXR1cm4gcmVjb3JkLnR5cGUgPSB0eXBlLCByZWNvcmQuYXJnID0gYXJnLCBmaW5hbGx5RW50cnkgPyAodGhpcy5tZXRob2QgPSBcIm5leHRcIiwgdGhpcy5uZXh0ID0gZmluYWxseUVudHJ5LmZpbmFsbHlMb2MsIENvbnRpbnVlU2VudGluZWwpIDogdGhpcy5jb21wbGV0ZShyZWNvcmQpOyB9LCBjb21wbGV0ZTogZnVuY3Rpb24gY29tcGxldGUocmVjb3JkLCBhZnRlckxvYykgeyBpZiAoXCJ0aHJvd1wiID09PSByZWNvcmQudHlwZSkgdGhyb3cgcmVjb3JkLmFyZzsgcmV0dXJuIFwiYnJlYWtcIiA9PT0gcmVjb3JkLnR5cGUgfHwgXCJjb250aW51ZVwiID09PSByZWNvcmQudHlwZSA/IHRoaXMubmV4dCA9IHJlY29yZC5hcmcgOiBcInJldHVyblwiID09PSByZWNvcmQudHlwZSA/ICh0aGlzLnJ2YWwgPSB0aGlzLmFyZyA9IHJlY29yZC5hcmcsIHRoaXMubWV0aG9kID0gXCJyZXR1cm5cIiwgdGhpcy5uZXh0ID0gXCJlbmRcIikgOiBcIm5vcm1hbFwiID09PSByZWNvcmQudHlwZSAmJiBhZnRlckxvYyAmJiAodGhpcy5uZXh0ID0gYWZ0ZXJMb2MpLCBDb250aW51ZVNlbnRpbmVsOyB9LCBmaW5pc2g6IGZ1bmN0aW9uIGZpbmlzaChmaW5hbGx5TG9jKSB7IGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOyBpZiAoZW50cnkuZmluYWxseUxvYyA9PT0gZmluYWxseUxvYykgcmV0dXJuIHRoaXMuY29tcGxldGUoZW50cnkuY29tcGxldGlvbiwgZW50cnkuYWZ0ZXJMb2MpLCByZXNldFRyeUVudHJ5KGVudHJ5KSwgQ29udGludWVTZW50aW5lbDsgfSB9LCBcImNhdGNoXCI6IGZ1bmN0aW9uIF9jYXRjaCh0cnlMb2MpIHsgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgeyB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07IGlmIChlbnRyeS50cnlMb2MgPT09IHRyeUxvYykgeyB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbjsgaWYgKFwidGhyb3dcIiA9PT0gcmVjb3JkLnR5cGUpIHsgdmFyIHRocm93biA9IHJlY29yZC5hcmc7IHJlc2V0VHJ5RW50cnkoZW50cnkpOyB9IHJldHVybiB0aHJvd247IH0gfSB0aHJvdyBuZXcgRXJyb3IoXCJpbGxlZ2FsIGNhdGNoIGF0dGVtcHRcIik7IH0sIGRlbGVnYXRlWWllbGQ6IGZ1bmN0aW9uIGRlbGVnYXRlWWllbGQoaXRlcmFibGUsIHJlc3VsdE5hbWUsIG5leHRMb2MpIHsgcmV0dXJuIHRoaXMuZGVsZWdhdGUgPSB7IGl0ZXJhdG9yOiB2YWx1ZXMoaXRlcmFibGUpLCByZXN1bHROYW1lOiByZXN1bHROYW1lLCBuZXh0TG9jOiBuZXh0TG9jIH0sIFwibmV4dFwiID09PSB0aGlzLm1ldGhvZCAmJiAodGhpcy5hcmcgPSB1bmRlZmluZWQpLCBDb250aW51ZVNlbnRpbmVsOyB9IH0sIGV4cG9ydHM7IH1cbmZ1bmN0aW9uIGFzeW5jR2VuZXJhdG9yU3RlcChnZW4sIHJlc29sdmUsIHJlamVjdCwgX25leHQsIF90aHJvdywga2V5LCBhcmcpIHsgdHJ5IHsgdmFyIGluZm8gPSBnZW5ba2V5XShhcmcpOyB2YXIgdmFsdWUgPSBpbmZvLnZhbHVlOyB9IGNhdGNoIChlcnJvcikgeyByZWplY3QoZXJyb3IpOyByZXR1cm47IH0gaWYgKGluZm8uZG9uZSkgeyByZXNvbHZlKHZhbHVlKTsgfSBlbHNlIHsgUHJvbWlzZS5yZXNvbHZlKHZhbHVlKS50aGVuKF9uZXh0LCBfdGhyb3cpOyB9IH1cbmZ1bmN0aW9uIF9hc3luY1RvR2VuZXJhdG9yKGZuKSB7IHJldHVybiBmdW5jdGlvbiAoKSB7IHZhciBzZWxmID0gdGhpcywgYXJncyA9IGFyZ3VtZW50czsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdmFyIGdlbiA9IGZuLmFwcGx5KHNlbGYsIGFyZ3MpOyBmdW5jdGlvbiBfbmV4dCh2YWx1ZSkgeyBhc3luY0dlbmVyYXRvclN0ZXAoZ2VuLCByZXNvbHZlLCByZWplY3QsIF9uZXh0LCBfdGhyb3csIFwibmV4dFwiLCB2YWx1ZSk7IH0gZnVuY3Rpb24gX3Rocm93KGVycikgeyBhc3luY0dlbmVyYXRvclN0ZXAoZ2VuLCByZXNvbHZlLCByZWplY3QsIF9uZXh0LCBfdGhyb3csIFwidGhyb3dcIiwgZXJyKTsgfSBfbmV4dCh1bmRlZmluZWQpOyB9KTsgfTsgfVxuaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZSwgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcImh0bWw1LXFyY29kZVwiO1xuaW1wb3J0IHsgZWQ0NDggfSBmcm9tIFwiQG5vYmxlL2N1cnZlcy9lZDQ0OFwiO1xuaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSBcImJ1ZmZlclwiO1xudmFyIGN1cnJlbnRseUFkZGluZ0l0ZW1CeVRhZyA9IG5ldyBNYXAoKTtcbnZhciByZWNlaXZlZF9pdGVtcyA9IHt9O1xudmFyIGNvbmZpZztcbnZhciBzY2FubmVyID0gbmV3IEh0bWw1UXJjb2RlU2Nhbm5lcihcInJlYWRlclwiLCB7XG4gIGZwczogMTAsXG4gIHFyYm94OiB7XG4gICAgd2lkdGg6IDI1MCxcbiAgICBoZWlnaHQ6IDI1MFxuICB9LFxuICBzaG93VG9yY2hCdXR0b25JZlN1cHBvcnRlZDogdHJ1ZSxcbiAgZm9ybWF0c1RvU3VwcG9ydDogW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5RUl9DT0RFXSxcbiAgLy90aGVyZSBhcmUgbWFueSBvdGhlciB0eXBlcyBvZiBjb2RlcyBvbiB0aGUgbGFiZWxzIHdlIGRvIG5vdCB3YW50XG4gIHJlbWVtYmVyTGFzdFVzZWRDYW1lcmE6IHRydWVcbn0pO1xudmFyIHNjYW5uZXJfYXVkaW8gPSBuZXcgQXVkaW8oXCIvYmVlcC53YXZcIik7XG5zY2FubmVyX2F1ZGlvLmxvYWQoKTtcbnZhciB0b2FzdERpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiYm90dG9tVG9hc3RcIik7XG5cbi8qXG4gKiBIZWxwZXIgZnVuY3Rpb25zXG4gKi9cbmZ1bmN0aW9uIGh0b2EoaCkge1xuICByZXR1cm4gVWludDhBcnJheS5mcm9tKEJ1ZmZlci5mcm9tKGgsIFwiaGV4XCIpKTtcbn1cbmZ1bmN0aW9uIHRvYXN0KHRpdGxlLCBtZXNzYWdlKSB7XG4gIHRvYXN0RGl2LmNoaWxkcmVuWzBdLmNoaWxkcmVuWzBdLmlubmVySFRNTCA9IHRpdGxlO1xuICB0b2FzdERpdi5jaGlsZHJlblsxXS5pbm5lckhUTUwgPSBtZXNzYWdlO1xuICB0b2FzdERpdi5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZVwiKTtcbiAgdG9hc3REaXYuY2xhc3NMaXN0LmFkZChcInNob3dcIik7XG4gIHRvYXN0RGl2LmNsYXNzTGlzdC5hZGQoXCJzaG93aW5nXCIpO1xuICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICB0b2FzdERpdi5jbGFzc0xpc3QucmVtb3ZlKFwic2hvd1wiKTtcbiAgICB0b2FzdERpdi5jbGFzc0xpc3QucmVtb3ZlKFwic2hvd2luZ1wiKTtcbiAgICB0b2FzdERpdi5jbGFzc0xpc3QuYWRkKFwiaGlkZVwiKTtcbiAgfSwgMzAwMCk7XG59XG5mdW5jdGlvbiBmZXRjaFdpdGhBdXRoKF94LCBfeDIpIHtcbiAgcmV0dXJuIF9mZXRjaFdpdGhBdXRoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfZmV0Y2hXaXRoQXV0aCgpIHtcbiAgX2ZldGNoV2l0aEF1dGggPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUoaW5wdXQsIGluaXQpIHtcbiAgICB2YXIgcmVzcG9uc2U7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUkKF9jb250ZXh0KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dC5wcmV2ID0gX2NvbnRleHQubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKGluaXQgPT0gdW5kZWZpbmVkIHx8IGluaXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgaW5pdCA9IHt9O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaW5pdFtcImhlYWRlcnNcIl0gPT0gbnVsbCkge1xuICAgICAgICAgICAgaW5pdFtcImhlYWRlcnNcIl0gPSB7fTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5nZXRJdGVtKFwiYWNjZXNzX3Rva2VuXCIpKSB7XG4gICAgICAgICAgICBfY29udGV4dC5uZXh0ID0gNTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dC5uZXh0ID0gNTtcbiAgICAgICAgICByZXR1cm4gbG9naW4oKTtcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgIGluaXRbXCJoZWFkZXJzXCJdW1wiQXV0aG9yaXphdGlvblwiXSA9IFwiQmVhcmVyIFwiICsgd2luZG93LnNlc3Npb25TdG9yYWdlLmdldEl0ZW0oXCJhY2Nlc3NfdG9rZW5cIik7XG4gICAgICAgICAgX2NvbnRleHQubmV4dCA9IDg7XG4gICAgICAgICAgcmV0dXJuIGZldGNoKGlucHV0LCBpbml0KTtcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQuc2VudDtcbiAgICAgICAgY2FzZSA5OlxuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyA9PSA0MDEpKSB7XG4gICAgICAgICAgICBfY29udGV4dC5uZXh0ID0gMTk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJGZXRjaCB3aXRoIGF1dGggZmFpbGVkIGZvclwiLCBpbnB1dCk7XG4gICAgICAgICAgX2NvbnRleHQubmV4dCA9IDEzO1xuICAgICAgICAgIHJldHVybiBsb2dpbigpO1xuICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgIGluaXRbXCJoZWFkZXJzXCJdW1wiQXV0aG9yaXphdGlvblwiXSA9IFwiQmVhcmVyIFwiICsgd2luZG93LnNlc3Npb25TdG9yYWdlLmdldEl0ZW0oXCJhY2Nlc3NfdG9rZW5cIik7XG4gICAgICAgICAgX2NvbnRleHQubmV4dCA9IDE2O1xuICAgICAgICAgIHJldHVybiBmZXRjaChpbnB1dCwgaW5pdCk7XG4gICAgICAgIGNhc2UgMTY6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dC5zZW50O1xuICAgICAgICAgIF9jb250ZXh0Lm5leHQgPSA5O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDE5OlxuICAgICAgICAgIHJldHVybiBfY29udGV4dC5hYnJ1cHQoXCJyZXR1cm5cIiwgcmVzcG9uc2UpO1xuICAgICAgICBjYXNlIDIwOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlKTtcbiAgfSkpO1xuICByZXR1cm4gX2ZldGNoV2l0aEF1dGguYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihfeDMsIF94NCkge1xuICByZXR1cm4gX2NoZWNrUmVzcG9uc2VGb3JFcnJvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2NoZWNrUmVzcG9uc2VGb3JFcnJvcigpIHtcbiAgX2NoZWNrUmVzcG9uc2VGb3JFcnJvciA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTIocmVzcG9uc2UsIG1lc3NhZ2UpIHtcbiAgICB2YXIgY29udGVudDtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTIkKF9jb250ZXh0Mikge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQyLnByZXYgPSBfY29udGV4dDIubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDIubmV4dCA9IDc7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQyLm5leHQgPSAzO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBjb250ZW50ID0gX2NvbnRleHQyLnNlbnQ7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJHb3QgUmVzcG9uc2UgRXJyb3I6XCIsIG1lc3NhZ2UsIHJlc3BvbnNlKTtcbiAgICAgICAgICBhbGVydChtZXNzYWdlICsgXCI7IFN0YXR1czogXCIgKyByZXNwb25zZS5zdGF0dXMgKyBcIjsgQ29udGVudDogXCIgKyBjb250ZW50KTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQyLmFicnVwdChcInJldHVyblwiLCBmYWxzZSk7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQyLmFicnVwdChcInJldHVyblwiLCB0cnVlKTtcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Mi5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTIpO1xuICB9KSk7XG4gIHJldHVybiBfY2hlY2tSZXNwb25zZUZvckVycm9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBnZXRDb25maWcoKSB7XG4gIHJldHVybiBfZ2V0Q29uZmlnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfZ2V0Q29uZmlnKCkge1xuICBfZ2V0Q29uZmlnID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMygpIHtcbiAgICB2YXIgY29uZmlnX3JlcXVlc3Q7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUzJChfY29udGV4dDMpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0My5wcmV2ID0gX2NvbnRleHQzLm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmICghKGNvbmZpZyA9PSB1bmRlZmluZWQpKSB7XG4gICAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDEyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0My5uZXh0ID0gMztcbiAgICAgICAgICByZXR1cm4gZmV0Y2goXCJjb25maWcuanNvblwiKTtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGNvbmZpZ19yZXF1ZXN0ID0gX2NvbnRleHQzLnNlbnQ7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkaW5nIGNvbmZpZ1wiKTtcbiAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDc7XG4gICAgICAgICAgcmV0dXJuIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihjb25maWdfcmVxdWVzdCwgXCJDb3VsZCBub3QgbG9hZCBjb25maWdcIik7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICBpZiAoIV9jb250ZXh0My5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDEyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0My5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIGNvbmZpZ19yZXF1ZXN0Lmpzb24oKTtcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICBjb25maWcgPSBfY29udGV4dDMuc2VudDtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBjb25maWdcIik7XG4gICAgICAgIGNhc2UgMTI6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQzLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMyk7XG4gIH0pKTtcbiAgcmV0dXJuIF9nZXRDb25maWcuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIGxvZ2luKF94NSkge1xuICByZXR1cm4gX2xvZ2luLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfbG9naW4oKSB7XG4gIF9sb2dpbiA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTQocGFzc3dvcmRUb1RyeSkge1xuICAgIHZhciBsb2dpblN1Y2Nlc3MsIHBhc3N3b3JkLCBmb3JtLCByZXNwb25zZSwgcmVzdWx0O1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlNCQoX2NvbnRleHQ0KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDQucHJldiA9IF9jb250ZXh0NC5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlBlcmZvcm1pbmcgbG9naW5cIik7XG4gICAgICAgICAgbG9naW5TdWNjZXNzID0gZmFsc2U7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBpZiAocGFzc3dvcmRUb1RyeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlVzaW5nIHBhc3N3b3JkIHRvIHRyeSBmcm9tIHBhcmFtZXRlclwiKTtcbiAgICAgICAgICAgIHBhc3N3b3JkID0gcGFzc3dvcmRUb1RyeTtcbiAgICAgICAgICAgIHBhc3N3b3JkVG9UcnkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUHJvbXB0aW5nIHVzZXIgZm9yIHNoYXJlZCBzZWNyZXQuXCIpO1xuICAgICAgICAgICAgcGFzc3dvcmQgPSBwcm9tcHQoXCJwcm92aWRlIHRoZSBzaGFyZWQgc2VjcmV0XCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgZm9ybS5hcHBlbmQoXCJncmFudF90eXBlXCIsIFwicGFzc3dvcmRcIik7XG4gICAgICAgICAgZm9ybS5hcHBlbmQoXCJ1c2VybmFtZVwiLCBcIndvcmtlclwiKTtcbiAgICAgICAgICBmb3JtLmFwcGVuZChcInBhc3N3b3JkXCIsIHBhc3N3b3JkKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlJlcXVlc3RpbmcgdG9rZW4uXCIpO1xuICAgICAgICAgIF9jb250ZXh0NC5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIGZldGNoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL3Rva2VuXCIsIHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgICAgICBib2R5OiBmb3JtXG4gICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDQuc2VudDtcbiAgICAgICAgICBfY29udGV4dDQubmV4dCA9IDEzO1xuICAgICAgICAgIHJldHVybiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiTG9naW4gZmFpbGVkXCIpO1xuICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgIGlmICghX2NvbnRleHQ0LnNlbnQpIHtcbiAgICAgICAgICAgIF9jb250ZXh0NC5uZXh0ID0gMjA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQ0Lm5leHQgPSAxNjtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDE2OlxuICAgICAgICAgIHJlc3VsdCA9IF9jb250ZXh0NC5zZW50O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiR290IHRva2VuXCIpO1xuICAgICAgICAgIHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5zZXRJdGVtKFwiYWNjZXNzX3Rva2VuXCIsIHJlc3VsdC5hY2Nlc3NfdG9rZW4pO1xuICAgICAgICAgIGxvZ2luU3VjY2VzcyA9IHRydWU7XG4gICAgICAgIGNhc2UgMjA6XG4gICAgICAgICAgaWYgKCFsb2dpblN1Y2Nlc3MpIHtcbiAgICAgICAgICAgIF9jb250ZXh0NC5uZXh0ID0gMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAyMTpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDQuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWU0KTtcbiAgfSkpO1xuICByZXR1cm4gX2xvZ2luLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiB1cGRhdGVJdGVtc1ZpZXcoKSB7XG4gIGNvbnNvbGUubG9nKFwiVXBkYXRpbmcgaXRlbXMgdmlld1wiKTtcbiAgdmFyIGl0ZW1zID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNpdGVtc1wiKTtcbiAgaXRlbXMuaW5uZXJIVE1MID0gXCJcIjtcbiAgZm9yICh2YXIgaXRlbSBpbiByZWNlaXZlZF9pdGVtcykge1xuICAgIHZhciBsaSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJsaVwiKTtcbiAgICBsaS5pbm5lckhUTUwgPSBcIjxkaXYgaWQ9XFxcIml0ZW1fXCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnV1aWQgKyBcIlxcXCIgY2xhc3M9XFxcImFsZXJ0IGFsZXJ0LXN1Y2Nlc3NcXFwiIHJvbGU9XFxcImFsZXJ0XFxcIj5cIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udGFnICsgXCIgKFwiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS5hZGRyZXNzZWUgKyBcIiwgXCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnRlYW0gKyBcIilcIiArIFwiJmVtc3A7PHNwYW4gY2xhc3M9XFxcImJhZGdlIGJhZGdlLWxpZ2h0XFxcIj5cIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLm51bSArIFwiPC9zcGFuPlwiICsgXCImZW1zcDs8YnV0dG9uIGNsYXNzPVxcXCJidG4gYnRuLXByaW1hcnlcXFwiIG9uY2xpY2s9XFxcImxpYi5pbmNyZWFzZUl0ZW1Db3VudCgnXCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnV1aWQgKyBcIicpXFxcIj4rPC9idXR0b24+XCIgKyBcIiZlbXNwOzxidXR0b24gY2xhc3M9XFxcImJ0biBidG4tcHJpbWFyeVxcXCIgb25jbGljaz1cXFwibGliLmRlY3JlYXNlSXRlbUNvdW50KCdcIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udXVpZCArIFwiJylcXFwiPi08L2J1dHRvbj48L2Rpdj5cIjtcbiAgICBpdGVtcy5hcHBlbmRDaGlsZChsaSk7XG4gIH1cbn1cblxuLypcbiAqIHZhcmlvdXMgYWRkIEl0ZW1zIGZ1bmN0aW9uc1xuICovXG5cbmV4cG9ydCBmdW5jdGlvbiBvblRhZ1RleHRVcGRhdGUoX3g2KSB7XG4gIHJldHVybiBfb25UYWdUZXh0VXBkYXRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfb25UYWdUZXh0VXBkYXRlKCkge1xuICBfb25UYWdUZXh0VXBkYXRlID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlNShlbGVtZW50KSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWU1JChfY29udGV4dDUpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0NS5wcmV2ID0gX2NvbnRleHQ1Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmICghKGVsZW1lbnQudmFsdWUubGVuZ3RoID09IDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDUubmV4dCA9IDU7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxlbWVudC5zZXRDdXN0b21WYWxpZGl0eShcIlwiKTtcbiAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoXCJpcy1pbnZhbGlkXCIpO1xuICAgICAgICAgIF9jb250ZXh0NS5uZXh0ID0gMTI7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgNTpcbiAgICAgICAgICBpZiAoIShlbGVtZW50LnZhbHVlLmxlbmd0aCAhPSA2KSkge1xuICAgICAgICAgICAgX2NvbnRleHQ1Lm5leHQgPSAxMTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbGVtZW50LnNldEN1c3RvbVZhbGlkaXR5KFwiQ29kZSBtdXN0IGJlIDYgY2hhcnMgbG9uZy5cIik7XG4gICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QuYWRkKFwiaXMtaW52YWxpZFwiKTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ1LmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSAxMTpcbiAgICAgICAgICB0YWdFbnRlcmVkKGVsZW1lbnQpO1xuICAgICAgICBjYXNlIDEyOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0NS5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTUpO1xuICB9KSk7XG4gIHJldHVybiBfb25UYWdUZXh0VXBkYXRlLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gb25UYWdJbnB1dENoYW5nZWQoX3g3KSB7XG4gIHJldHVybiBfb25UYWdJbnB1dENoYW5nZWQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9vblRhZ0lucHV0Q2hhbmdlZCgpIHtcbiAgX29uVGFnSW5wdXRDaGFuZ2VkID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlNihlbGVtZW50KSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWU2JChfY29udGV4dDYpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0Ni5wcmV2ID0gX2NvbnRleHQ2Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIC8vIEVsZW1lbnQgbG9zdCBmb2N1cyBvciB1c2VyIHByZXNzZWQgZW50ZXJcbiAgICAgICAgICBpZiAoZWxlbWVudC52YWx1ZS5sZW5ndGggPT0gNikge1xuICAgICAgICAgICAgdGFnRW50ZXJlZChlbGVtZW50KTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWxlbWVudC5yZXBvcnRWYWxpZGl0eSgpO1xuICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAxOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Ni5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTYpO1xuICB9KSk7XG4gIHJldHVybiBfb25UYWdJbnB1dENoYW5nZWQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIHRhZ0VudGVyZWQoX3g4KSB7XG4gIHJldHVybiBfdGFnRW50ZXJlZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX3RhZ0VudGVyZWQoKSB7XG4gIF90YWdFbnRlcmVkID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlNyhlbGVtZW50KSB7XG4gICAgdmFyIHRhZywgc3VjYztcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTckKF9jb250ZXh0Nykge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ3LnByZXYgPSBfY29udGV4dDcubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgdGFnID0gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlRhZyBFbnRlcmVkXCIsIHRhZyk7XG4gICAgICAgICAgaWYgKCFjdXJyZW50bHlBZGRpbmdJdGVtQnlUYWcuaGFzKHRhZykpIHtcbiAgICAgICAgICAgIF9jb250ZXh0Ny5uZXh0ID0gNDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ3LmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICAgIGN1cnJlbnRseUFkZGluZ0l0ZW1CeVRhZy5zZXQodGFnLCBcIlwiKTtcbiAgICAgICAgICBfY29udGV4dDcubmV4dCA9IDc7XG4gICAgICAgICAgcmV0dXJuIGFkZEl0ZW1CeVRhZyhlbGVtZW50LnZhbHVlKTtcbiAgICAgICAgY2FzZSA3OlxuICAgICAgICAgIHN1Y2MgPSBfY29udGV4dDcuc2VudDtcbiAgICAgICAgICBpZiAoc3VjYykge1xuICAgICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKFwiaXMtaW52YWxpZFwiKTtcbiAgICAgICAgICAgIGVsZW1lbnQudmFsdWUgPSBcIlwiO1xuICAgICAgICAgICAgZWxlbWVudC5zZXRDdXN0b21WYWxpZGl0eShcIlwiKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZWxlbWVudC5zZXRDdXN0b21WYWxpZGl0eShcIlVua25vd24gaXRlbVwiKTtcbiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZChcImlzLWludmFsaWRcIik7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsZW1lbnQucmVwb3J0VmFsaWRpdHkoKTtcbiAgICAgICAgICBjdXJyZW50bHlBZGRpbmdJdGVtQnlUYWdbXCJkZWxldGVcIl0odGFnKTtcbiAgICAgICAgY2FzZSAxMTpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDcuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWU3KTtcbiAgfSkpO1xuICByZXR1cm4gX3RhZ0VudGVyZWQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBhZGRJdGVtQnlUYWcoX3g5KSB7XG4gIHJldHVybiBfYWRkSXRlbUJ5VGFnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfYWRkSXRlbUJ5VGFnKCkge1xuICBfYWRkSXRlbUJ5VGFnID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlOCh0YWcpIHtcbiAgICB2YXIgcmVzcG9uc2UsIHRyYWNraW5nX2l0ZW07XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWU4JChfY29udGV4dDgpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0OC5wcmV2ID0gX2NvbnRleHQ4Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmICghKHRhZy5sZW5ndGggIT0gNikpIHtcbiAgICAgICAgICAgIF9jb250ZXh0OC5uZXh0ID0gMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICB0aHJvdyBcIkludGVybmFsIEVycm9yOiBUYWcgbm90IGxlbmd0aCA2LlwiO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgdGFnID0gdGFnLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJUcnlpbmcgdG8gYWRkIGl0ZW0gYnkgdGFnOlwiLCB0YWcpO1xuICAgICAgICAgIF9jb250ZXh0OC5uZXh0ID0gNjtcbiAgICAgICAgICByZXR1cm4gZmV0Y2hXaXRoQXV0aChjb25maWcuYmFja2VuZF91cmwgKyBcIi90YWcvXCIgKyB0YWcpO1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDguc2VudDtcbiAgICAgICAgICBpZiAoIShyZXNwb25zZS5zdGF0dXMgPT0gMjAwKSkge1xuICAgICAgICAgICAgX2NvbnRleHQ4Lm5leHQgPSAxODtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDgubmV4dCA9IDEwO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgdHJhY2tpbmdfaXRlbSA9IF9jb250ZXh0OC5zZW50O1xuICAgICAgICAgIGlmICh0cmFja2luZ19pdGVtLnV1aWQgaW4gcmVjZWl2ZWRfaXRlbXMpIHtcbiAgICAgICAgICAgIHJlY2VpdmVkX2l0ZW1zW3RyYWNraW5nX2l0ZW0udXVpZF0ubnVtICs9IDE7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlY2VpdmVkX2l0ZW1zW3RyYWNraW5nX2l0ZW0udXVpZF0gPSB7XG4gICAgICAgICAgICAgIFwibnVtXCI6IDEsXG4gICAgICAgICAgICAgIFwiaXRlbVwiOiB0cmFja2luZ19pdGVtXG4gICAgICAgICAgICB9O1xuICAgICAgICAgIH1cbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgICBzY2FubmVyX2F1ZGlvLnBsYXkoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkFkZGVkIGl0ZW0gYnkgdGFnXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDguYWJydXB0KFwicmV0dXJuXCIsIHRydWUpO1xuICAgICAgICBjYXNlIDE4OlxuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyA9PSA0MDQpKSB7XG4gICAgICAgICAgICBfY29udGV4dDgubmV4dCA9IDIzO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiSXRlbSBub3QgZm91bmRcIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OC5hYnJ1cHQoXCJyZXR1cm5cIiwgZmFsc2UpO1xuICAgICAgICBjYXNlIDIzOlxuICAgICAgICAgIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihyZXNwb25zZSwgXCJGYWlsZWQgdG8gZ2V0IGl0ZW0gZnJvbSBiYWNrZW5kXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDguYWJydXB0KFwicmV0dXJuXCIsIGZhbHNlKTtcbiAgICAgICAgY2FzZSAyNTpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDguc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWU4KTtcbiAgfSkpO1xuICByZXR1cm4gX2FkZEl0ZW1CeVRhZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gaGFuZGxlUXJFcnJvcihfeDEwLCBfeDExKSB7XG4gIHJldHVybiBfaGFuZGxlUXJFcnJvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2hhbmRsZVFyRXJyb3IoKSB7XG4gIF9oYW5kbGVRckVycm9yID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlOShtc2csIGVycikge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlOSQoX2NvbnRleHQ5KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDkucHJldiA9IF9jb250ZXh0OS5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ5LmFicnVwdChcInJldHVyblwiKTtcbiAgICAgICAgY2FzZSAxOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OS5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTkpO1xuICB9KSk7XG4gIHJldHVybiBfaGFuZGxlUXJFcnJvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gZGVib3VuY2VTY2FubmVyKCkge1xuICBpZiAoc2Nhbm5lci5nZXRTdGF0ZSgpICE9IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HKSB7XG4gICAgcmV0dXJuO1xuICB9XG4gIHNjYW5uZXIucGF1c2UoZmFsc2UpO1xuICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICBpZiAoc2Nhbm5lci5nZXRTdGF0ZSgpID09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlBBVVNFRCkge1xuICAgICAgc2Nhbm5lci5yZXN1bWUoKTtcbiAgICB9XG4gIH0sIDEwMDApO1xufVxuZnVuY3Rpb24gaGFuZGxlSXRlbVNjYW5SZXN1bHQoX3gxMikge1xuICByZXR1cm4gX2hhbmRsZUl0ZW1TY2FuUmVzdWx0LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfaGFuZGxlSXRlbVNjYW5SZXN1bHQoKSB7XG4gIF9oYW5kbGVJdGVtU2NhblJlc3VsdCA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTEwKGl0ZW1fdXVpZCkge1xuICAgIHZhciByZXNwb25zZSwgdHJhY2tpbmdfaXRlbTtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTEwJChfY29udGV4dDEwKSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDEwLnByZXYgPSBfY29udGV4dDEwLm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGRlYm91bmNlU2Nhbm5lcigpO1xuICAgICAgICAgIGlmICghKGl0ZW1fdXVpZC5sZW5ndGggPT0gMzYpKSB7XG4gICAgICAgICAgICBfY29udGV4dDEwLm5leHQgPSAyNztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlRyeWluZyB0byBhZGQgaXRlbSBieSB1dWlkIChzY2FubmVkKVwiKTtcbiAgICAgICAgICBpZiAoIShpdGVtX3V1aWQgaW4gcmVjZWl2ZWRfaXRlbXMpKSB7XG4gICAgICAgICAgICBfY29udGV4dDEwLm5leHQgPSAxMDtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICByZWNlaXZlZF9pdGVtc1tpdGVtX3V1aWRdLm51bSArPSAxO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiSW5jcmVhc2VkIGNvdW50IG9mIGV4aXN0aW5nIGl0ZW0gdXVpZFwiKTtcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgICBzY2FubmVyX2F1ZGlvLnBsYXkoKTtcbiAgICAgICAgICBfY29udGV4dDEwLm5leHQgPSAyNTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICByZWNlaXZlZF9pdGVtc1tpdGVtX3V1aWRdID0ge1xuICAgICAgICAgICAgXCJudW1cIjogMSxcbiAgICAgICAgICAgIFwiaXRlbVwiOiBudWxsXG4gICAgICAgICAgfTtcbiAgICAgICAgICBfY29udGV4dDEwLm5leHQgPSAxMztcbiAgICAgICAgICByZXR1cm4gZmV0Y2goY29uZmlnLmJhY2tlbmRfdXJsICsgXCIvaXRlbS9cIiArIGl0ZW1fdXVpZCk7XG4gICAgICAgIGNhc2UgMTM6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDEwLnNlbnQ7XG4gICAgICAgICAgaWYgKCEocmVzcG9uc2Uuc3RhdHVzID09IDIwMCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDE3O1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgMTc6XG4gICAgICAgICAgdHJhY2tpbmdfaXRlbSA9IF9jb250ZXh0MTAuc2VudDtcbiAgICAgICAgICByZWNlaXZlZF9pdGVtc1tpdGVtX3V1aWRdID0ge1xuICAgICAgICAgICAgXCJudW1cIjogMSxcbiAgICAgICAgICAgIFwiaXRlbVwiOiB0cmFja2luZ19pdGVtXG4gICAgICAgICAgfTtcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgICBzY2FubmVyX2F1ZGlvLnBsYXkoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkFkZGVkIGl0ZW0gYnkgdXVpZC5cIik7XG4gICAgICAgICAgX2NvbnRleHQxMC5uZXh0ID0gMjU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjQ6XG4gICAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PSA0MDQpIHtcbiAgICAgICAgICAgIGFsZXJ0KFwiSXRlbSBub3QgZm91bmRcIik7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkl0ZW0gbm90IGZvdW5kXCIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIGdldCBpdGVtIGZyb20gYmFja2VuZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMjU6XG4gICAgICAgICAgX2NvbnRleHQxMC5uZXh0ID0gMjg7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjc6XG4gICAgICAgICAgYWxlcnQoXCJRUiBDb2RlIGlzIG5vdCBhIGJncCBjaGVja2luIGNvZGUuXCIpO1xuICAgICAgICBjYXNlIDI4OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTAuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxMCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9oYW5kbGVJdGVtU2NhblJlc3VsdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGFkZEl0ZW1TY2FuKCkge1xuICByZXR1cm4gX2FkZEl0ZW1TY2FuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfYWRkSXRlbVNjYW4oKSB7XG4gIF9hZGRJdGVtU2NhbiA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTExKCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTEkKF9jb250ZXh0MTEpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTEucHJldiA9IF9jb250ZXh0MTEubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJTdGFydGluZyBzY2FubmVyXCIpO1xuICAgICAgICAgIHNjYW5uZXIucmVuZGVyKGhhbmRsZUl0ZW1TY2FuUmVzdWx0LCBoYW5kbGVRckVycm9yKTtcbiAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0YXJ0U2NhblwiKS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzdG9wU2NhblwiKS5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTEuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxMSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9hZGRJdGVtU2Nhbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BTY2FubmluZ0l0ZW0oKSB7XG4gIHJldHVybiBfc3RvcFNjYW5uaW5nSXRlbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX3N0b3BTY2FubmluZ0l0ZW0oKSB7XG4gIF9zdG9wU2Nhbm5pbmdJdGVtID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTIoKSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxMiQoX2NvbnRleHQxMikge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxMi5wcmV2ID0gX2NvbnRleHQxMi5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlN0b3BwaW5nIHNjYW5uZXJcIik7XG4gICAgICAgICAgc2Nhbm5lci5jbGVhcigpO1xuICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic3RhcnRTY2FuXCIpLnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic3RvcFNjYW5cIikuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxMi5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTEyKTtcbiAgfSkpO1xuICByZXR1cm4gX3N0b3BTY2FubmluZ0l0ZW0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBhZGRJdGVtSW1hZ2UoX3gxMykge1xuICByZXR1cm4gX2FkZEl0ZW1JbWFnZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2FkZEl0ZW1JbWFnZSgpIHtcbiAgX2FkZEl0ZW1JbWFnZSA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTEzKGUpIHtcbiAgICB2YXIgZm9ybSwgcmVzcG9uc2UsIHRyYWNraW5nX2l0ZW07XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxMyQoX2NvbnRleHQxMykge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxMy5wcmV2ID0gX2NvbnRleHQxMy5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkFkZGluZyBpdGVtICBieSBpbWFnZVwiKTtcbiAgICAgICAgICBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgZm9ybS5hcHBlbmQoXCJpbWFnZVwiLCBlLmZpbGVzWzBdKTtcbiAgICAgICAgICBfY29udGV4dDEzLm5leHQgPSA1O1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL2l0ZW0vcmVnaXN0ZXJcIiwge1xuICAgICAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgICAgIGJvZHk6IGZvcm1cbiAgICAgICAgICB9KTtcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQxMy5zZW50O1xuICAgICAgICAgIF9jb250ZXh0MTMubmV4dCA9IDg7XG4gICAgICAgICAgcmV0dXJuIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihyZXNwb25zZSwgXCJGYWlsZWQgdG8gc2F2ZSBpdGVtXCIpO1xuICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgaWYgKCFfY29udGV4dDEzLnNlbnQpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTMubmV4dCA9IDE2O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MTMubmV4dCA9IDExO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgMTE6XG4gICAgICAgICAgdHJhY2tpbmdfaXRlbSA9IF9jb250ZXh0MTMuc2VudDtcbiAgICAgICAgICByZWNlaXZlZF9pdGVtc1t0cmFja2luZ19pdGVtLnV1aWRdID0ge1xuICAgICAgICAgICAgXCJudW1cIjogMSxcbiAgICAgICAgICAgIFwiaXRlbVwiOiB0cmFja2luZ19pdGVtXG4gICAgICAgICAgfTtcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgICBzY2FubmVyX2F1ZGlvLnBsYXkoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkFkZGVkIGl0ZW0gYnkgaW1hZ2UuXCIpO1xuICAgICAgICBjYXNlIDE2OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTMuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxMyk7XG4gIH0pKTtcbiAgcmV0dXJuIF9hZGRJdGVtSW1hZ2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBkZWNyZWFzZUl0ZW1Db3VudChfeDE0KSB7XG4gIHJldHVybiBfZGVjcmVhc2VJdGVtQ291bnQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9kZWNyZWFzZUl0ZW1Db3VudCgpIHtcbiAgX2RlY3JlYXNlSXRlbUNvdW50ID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTQodXVpZCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTQkKF9jb250ZXh0MTQpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTQucHJldiA9IF9jb250ZXh0MTQubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEocmVjZWl2ZWRfaXRlbXNbdXVpZF0gPT0gbnVsbCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTQubmV4dCA9IDM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJUcnlpbmcgdG8gZGVjcmVhc2UgaXRlbSBjb3VudCBvZiB1bmtub3duIGl0ZW1cIiwgdXVpZCk7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTQuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJEZWNyZWFzaW5nIGl0ZW0gY291bnQgb2ZcIiwgdXVpZCk7XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdXVpZF1bXCJudW1cIl0tLTtcbiAgICAgICAgICBpZiAocmVjZWl2ZWRfaXRlbXNbdXVpZF1bXCJudW1cIl0gPD0gMCkge1xuICAgICAgICAgICAgZGVsZXRlIHJlY2VpdmVkX2l0ZW1zW3V1aWRdO1xuICAgICAgICAgIH1cbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgY2FzZSA3OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTQuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxNCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9kZWNyZWFzZUl0ZW1Db3VudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGluY3JlYXNlSXRlbUNvdW50KF94MTUpIHtcbiAgcmV0dXJuIF9pbmNyZWFzZUl0ZW1Db3VudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuXG4vKlxuICogQ2hlY2tpbiB0aGUgc2VsZWN0ZWQgaXRlbXNcbiAqL1xuZnVuY3Rpb24gX2luY3JlYXNlSXRlbUNvdW50KCkge1xuICBfaW5jcmVhc2VJdGVtQ291bnQgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxNSh1dWlkKSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxNSQoX2NvbnRleHQxNSkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxNS5wcmV2ID0gX2NvbnRleHQxNS5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBpZiAoIShyZWNlaXZlZF9pdGVtc1t1dWlkXSA9PSBudWxsKSkge1xuICAgICAgICAgICAgX2NvbnRleHQxNS5uZXh0ID0gMztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlRyeWluZyB0byBpbmNyZWFzZSBpdGVtIGNvdW50IG9mIHVua25vd24gaXRlbVwiLCB1dWlkKTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxNS5hYnJ1cHQoXCJyZXR1cm5cIik7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkluY3JlYXNpbmcgaXRlbSBjb3VudCBvZlwiLCB1dWlkKTtcbiAgICAgICAgICByZWNlaXZlZF9pdGVtc1t1dWlkXVtcIm51bVwiXSsrO1xuICAgICAgICAgIHVwZGF0ZUl0ZW1zVmlldygpO1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxNS5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTE1KTtcbiAgfSkpO1xuICByZXR1cm4gX2luY3JlYXNlSXRlbUNvdW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gY2hlY2tpbkl0ZW1zKCkge1xuICByZXR1cm4gX2NoZWNraW5JdGVtcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2NoZWNraW5JdGVtcygpIHtcbiAgX2NoZWNraW5JdGVtcyA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTE2KCkge1xuICAgIHZhciBzdWNjZXNzZnVsbENvdW50LCBpdGVtLCByZXNwb25zZSwgdHJhY2tpbmdfaXRlbTtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE2JChfY29udGV4dDE2KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE2LnByZXYgPSBfY29udGV4dDE2Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiQ2hlY2tpbmcgaW4gaXRlbXNcIik7XG4gICAgICAgICAgc3VjY2Vzc2Z1bGxDb3VudCA9IDA7XG4gICAgICAgICAgX2NvbnRleHQxNi50MCA9IF9yZWdlbmVyYXRvclJ1bnRpbWUoKS5rZXlzKHJlY2VpdmVkX2l0ZW1zKTtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGlmICgoX2NvbnRleHQxNi50MSA9IF9jb250ZXh0MTYudDAoKSkuZG9uZSkge1xuICAgICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gMTg7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgaXRlbSA9IF9jb250ZXh0MTYudDEudmFsdWU7XG4gICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gNztcbiAgICAgICAgICByZXR1cm4gZmV0Y2hXaXRoQXV0aChjb25maWcuYmFja2VuZF91cmwgKyBcIi9jaGVja2luXCIsIHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICBcIml0ZW1fdXVpZFwiOiByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnV1aWQsXG4gICAgICAgICAgICAgIFwic3RvcmFnZV9uYW1lXCI6IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjc3RvcmFnZV9zZWxlY3RcIikudmFsdWUsXG4gICAgICAgICAgICAgIFwiYW1vdW50XCI6IHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLm51bVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9KTtcbiAgICAgICAgY2FzZSA3OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQxNi5zZW50O1xuICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDEwO1xuICAgICAgICAgIHJldHVybiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIGNoZWNraW4gaXRlbSBcIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udGFnKTtcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICBpZiAoIV9jb250ZXh0MTYuc2VudCkge1xuICAgICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gMTY7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gMTM7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICB0cmFja2luZ19pdGVtID0gX2NvbnRleHQxNi5zZW50O1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgICAgICAgICBkZWxldGUgcmVjZWl2ZWRfaXRlbXNbdHJhY2tpbmdfaXRlbS51dWlkXTtcbiAgICAgICAgICBzdWNjZXNzZnVsbENvdW50Kys7XG4gICAgICAgIGNhc2UgMTY6XG4gICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gMztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxODpcbiAgICAgICAgICB0b2FzdChcIkNoZWNrLUluIHN1Y2Nlc3NmdWxsLlwiLCBcIlRoZSBjaGVjay1pbiBvZiBcIiArIHN1Y2Nlc3NmdWxsQ291bnQgKyBcIiBpdGVtcyBjb21wbGV0ZWQgc3VjY2VzZnVsbHkuXCIpO1xuICAgICAgICAgIHVwZGF0ZUl0ZW1zVmlldygpO1xuICAgICAgICBjYXNlIDIwOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTYuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxNik7XG4gIH0pKTtcbiAgcmV0dXJuIF9jaGVja2luSXRlbXMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIG9uUmVjZXZpZXJTY2FuU3VjY2VzcyhfeDE2KSB7XG4gIHJldHVybiBfb25SZWNldmllclNjYW5TdWNjZXNzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfb25SZWNldmllclNjYW5TdWNjZXNzKCkge1xuICBfb25SZWNldmllclNjYW5TdWNjZXNzID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTcoc2Nhbm5lZENvZGUpIHtcbiAgICB2YXIgX3NjYW5uZWRDb2RlJHNwbGl0LCBfc2Nhbm5lZENvZGUkc3BsaXQyLCB1dWlkLCBzaWduYXR1cmUsIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTckKF9jb250ZXh0MTcpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTcucHJldiA9IF9jb250ZXh0MTcubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgZGVib3VuY2VTY2FubmVyKCk7XG4gICAgICAgICAgX3NjYW5uZWRDb2RlJHNwbGl0ID0gc2Nhbm5lZENvZGUuc3BsaXQoXCIvXCIpLCBfc2Nhbm5lZENvZGUkc3BsaXQyID0gX3NsaWNlZFRvQXJyYXkoX3NjYW5uZWRDb2RlJHNwbGl0LCAyKSwgdXVpZCA9IF9zY2FubmVkQ29kZSRzcGxpdDJbMF0sIHNpZ25hdHVyZSA9IF9zY2FubmVkQ29kZSRzcGxpdDJbMV07XG4gICAgICAgICAgY29uc29sZS5sb2coXCJSZWNlaXZlciBzY2FuIHN1Y2Nlc3NcIik7XG4gICAgICAgICAgc2Nhbm5lcl9hdWRpby5wbGF5KCk7XG4gICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gNjtcbiAgICAgICAgICByZXR1cm4gZ2V0Q29uZmlnKCk7XG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICBfY29udGV4dDE3Lm5leHQgPSA4O1xuICAgICAgICAgIHJldHVybiBmZXRjaChjb25maWcuYmFja2VuZF91cmwgKyBcIi9pdGVtL1wiICsgdXVpZCk7XG4gICAgICAgIGNhc2UgODpcbiAgICAgICAgICByZXNwb25zZSA9IF9jb250ZXh0MTcuc2VudDtcbiAgICAgICAgICBpZiAoIShyZXNwb25zZS5zdGF0dXMgPT0gMjAwKSkge1xuICAgICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gMTY7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gMTI7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxMjpcbiAgICAgICAgICB0cmFja2luZ19pdGVtID0gX2NvbnRleHQxNy5zZW50O1xuICAgICAgICAgIGlmIChlZDQ0OC52ZXJpZnkoaHRvYShzaWduYXR1cmUpLCBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUodHJhY2tpbmdfaXRlbS51dWlkKSwgaHRvYSh0cmFja2luZ19pdGVtLnZlcmlmaWNhdGlvbikpKSB7XG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3V1aWRcIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS51dWlkO1xuICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiN0YWdcIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS50YWc7XG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3N0b3JhZ2VcIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS5zdG9yYWdlO1xuICAgICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNhZGRyZXNzZWVcIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS5hZGRyZXNzZWU7XG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3RlYW1cIikuaW5uZXJIVE1MID0gdHJhY2tpbmdfaXRlbS50ZWFtO1xuICAgICAgICAgICAgY29uc29sZS5sb2coXCJSZWNlaXZlciB2ZXJpZnkgc3VjY2Vzc1wiKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWxlcnQoXCJDb3VsZCBub3QgdmVyaWZ5IHNpZ25hdHVyZS5cIik7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkNvdWxkIG5vdCB2ZXJpZnkgc2lnbmF0dXJlLlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gMTc7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTY6XG4gICAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PSA0MDQpIHtcbiAgICAgICAgICAgIGFsZXJ0KFwiSXRlbSBub3QgZm91bmQuXCIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIGdldCBpdGVtIGZyb20gYmFja2VuZC5cIik7XG4gICAgICAgICAgfVxuICAgICAgICBjYXNlIDE3OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTcuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxNyk7XG4gIH0pKTtcbiAgcmV0dXJuIF9vblJlY2V2aWVyU2NhblN1Y2Nlc3MuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBzY2FuUmVjZWl2ZXIoKSB7XG4gIHJldHVybiBfc2NhblJlY2VpdmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfc2NhblJlY2VpdmVyKCkge1xuICBfc2NhblJlY2VpdmVyID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTgoKSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxOCQoX2NvbnRleHQxOCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxOC5wcmV2ID0gX2NvbnRleHQxOC5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlNjYW5uaW5nIHJlY2VpdmVyLlwiKTtcbiAgICAgICAgICBzY2FubmVyLnJlbmRlcihvblJlY2V2aWVyU2NhblN1Y2Nlc3MsIGhhbmRsZVFyRXJyb3IpO1xuICAgICAgICBjYXNlIDI6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxOC5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTE4KTtcbiAgfSkpO1xuICByZXR1cm4gX3NjYW5SZWNlaXZlci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGxvYWRTdG9yYWdlcyhfeDE3KSB7XG4gIHJldHVybiBfbG9hZFN0b3JhZ2VzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfbG9hZFN0b3JhZ2VzKCkge1xuICBfbG9hZFN0b3JhZ2VzID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTkoc2VsZWN0ZWRTdG9yYWdlKSB7XG4gICAgdmFyIHJlc3BvbnNlLCBzdG9yYWdlcywgc2VsZWN0LCBpLCBvcHRpb247XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxOSQoX2NvbnRleHQxOSkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxOS5wcmV2ID0gX2NvbnRleHQxOS5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlJldHJpZXZpbmcgc3RvcmFnZXNcIik7XG4gICAgICAgICAgX2NvbnRleHQxOS5uZXh0ID0gMztcbiAgICAgICAgICByZXR1cm4gZmV0Y2hXaXRoQXV0aChjb25maWcuYmFja2VuZF91cmwgKyBcIi9zdG9yYWdlc1wiKTtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQxOS5zZW50O1xuICAgICAgICAgIF9jb250ZXh0MTkubmV4dCA9IDY7XG4gICAgICAgICAgcmV0dXJuIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihyZXNwb25zZSwgXCJGYWlsZWQgdG8gbG9hZCBzdG9yYWdlcy5cIik7XG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICBpZiAoIV9jb250ZXh0MTkuc2VudCkge1xuICAgICAgICAgICAgX2NvbnRleHQxOS5uZXh0ID0gMTM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQxOS5uZXh0ID0gOTtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDk6XG4gICAgICAgICAgc3RvcmFnZXMgPSBfY29udGV4dDE5LnNlbnQ7XG4gICAgICAgICAgc2VsZWN0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNzdG9yYWdlX3NlbGVjdFwiKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkdvdCBzdG9yYWdlc1wiKTtcbiAgICAgICAgICBmb3IgKGkgaW4gc3RvcmFnZXMpIHtcbiAgICAgICAgICAgIG9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgICAgICBvcHRpb24udGV4dENvbnRlbnQgPSBzdG9yYWdlc1tpXS5uYW1lO1xuICAgICAgICAgICAgb3B0aW9uLnZhbHVlID0gc3RvcmFnZXNbaV0ubmFtZTtcbiAgICAgICAgICAgIHNlbGVjdC5hcHBlbmRDaGlsZChvcHRpb24pO1xuICAgICAgICAgICAgaWYgKHNlbGVjdGVkU3RvcmFnZSA9PSBzdG9yYWdlc1tpXS5uYW1lKSB7XG4gICAgICAgICAgICAgIHNlbGVjdC52YWx1ZSA9IHNlbGVjdGVkU3RvcmFnZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMTM6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxOS5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTE5KTtcbiAgfSkpO1xuICByZXR1cm4gX2xvYWRTdG9yYWdlcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIG9uUGFnZUxvYWQoKSB7XG4gIHJldHVybiBfb25QYWdlTG9hZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX29uUGFnZUxvYWQoKSB7XG4gIF9vblBhZ2VMb2FkID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMjAoKSB7XG4gICAgdmFyIHB3O1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMjAkKF9jb250ZXh0MjApIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MjAucHJldiA9IF9jb250ZXh0MjAubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgX2NvbnRleHQyMC5uZXh0ID0gMjtcbiAgICAgICAgICByZXR1cm4gZ2V0Q29uZmlnKCk7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBwdyA9IHdpbmRvdy5sb2NhdGlvbi5oYXNoLnN1YnN0cmluZygxKTtcbiAgICAgICAgICBpZiAoIShwdy5sZW5ndGggPiAxKSkge1xuICAgICAgICAgICAgX2NvbnRleHQyMC5uZXh0ID0gODtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSA2O1xuICAgICAgICAgIHJldHVybiBsb2dpbihwdyk7XG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSAxMDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICAgIF9jb250ZXh0MjAubmV4dCA9IDEwO1xuICAgICAgICAgIHJldHVybiBsb2dpbigpO1xuICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgIGxvYWRTdG9yYWdlcyhkb2N1bWVudC5sb2NhdGlvbi5zZWFyY2guc3Vic3RyaW5nKDEpKTtcbiAgICAgICAgY2FzZSAxMTpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDIwLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMjApO1xuICB9KSk7XG4gIHJldHVybiBfb25QYWdlTG9hZC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufSJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==\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
+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  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 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 = 16;\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            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            console.log("Receiver verify success");\n          } else {\n            alert("Could not verify signature.");\n            console.log("Could not verify signature.");\n          }\n          _context17.next = 17;\n          break;\n        case 16:\n          if (response.status == 404) {\n            alert("Item not found.");\n          } else {\n            checkResponseForError(response, "Failed to get item from backend.");\n          }\n        case 17:\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() {\n  return _onPageLoad.apply(this, arguments);\n}\nfunction _onPageLoad() {\n  _onPageLoad = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee20() {\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          loadStorages(document.location.search.substring(1));\n        case 11:\n        case "end":\n          return _context20.stop();\n      }\n    }, _callee20);\n  }));\n  return _onPageLoad.apply(this, arguments);\n}//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMjQ0LmpzIiwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3BLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMxSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7OztBQ2xDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDaEpBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN6SUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0VEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDNURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzNIQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1R0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3YwQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ0xBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25EQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNsSEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM3REE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMvQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ2hDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdktBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ3RLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUNyRkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDckVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDanBCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDTEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDMUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzVEQTtBQUNBOztBQ0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQzdNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDN05BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FDdFdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUMzSkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQ25hQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUM1SkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUN0S0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FDcE5BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZXMiOlsid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2NvcmUuanM/NGIzYiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9zdHJpbmdzLmpzPzE0YTMiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdXRpbHMuanM/NjE2NCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS96eGluZy1odG1sNS1xcmNvZGUtZGVjb2Rlci5qcz80MzFmIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL25hdGl2ZS1iYXItY29kZS1kZXRlY3Rvci5qcz9kZTljIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2NvZGUtZGVjb2Rlci5qcz9lODI0Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2NhbWVyYS9jb3JlLWltcGwuanM/Yjc2YiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvZmFjdG9yaWVzLmpzPzdlYzciLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vY2FtZXJhL3JldHJpZXZlci5qcz81MzAyIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3N0YXRlLW1hbmFnZXIuanM/ZDkxYiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9odG1sNS1xcmNvZGUuanM/NGMyMCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9pbWFnZS1hc3NldHMuanM/MWM4ZCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9zdG9yYWdlLmpzPzc5ODQiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdWkuanM/NzE5ZCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9jYW1lcmEvcGVybWlzc2lvbnMuanM/NzAwOSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS91aS9zY2FubmVyL3NjYW4tdHlwZS1zZWxlY3Rvci5qcz9hYmVlIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvYmFzZS5qcz80MTRmIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvdG9yY2gtYnV0dG9uLmpzPzMzMDMiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL2h0bWw1LXFyY29kZS9lc20vdWkvc2Nhbm5lci9maWxlLXNlbGVjdGlvbi11aS5qcz85NWFlIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvY2FtZXJhLXNlbGVjdGlvbi11aS5qcz83M2RkIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL3VpL3NjYW5uZXIvY2FtZXJhLXpvb20tdWkuanM/ZTZmMSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvaHRtbDUtcXJjb2RlL2VzbS9odG1sNS1xcmNvZGUtc2Nhbm5lci5qcz84NWQ1Iiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9odG1sNS1xcmNvZGUvZXNtL2luZGV4LmpzPzc4NGUiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9oYXNoZXMvZXNtL19hc3NlcnQuanM/NzYwMCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vX3U2NC5qcz9iNjJhIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvaGFzaGVzL2VzbS9jcnlwdG8uanM/MTUzMCIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vdXRpbHMuanM/M2Y5MiIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2hhc2hlcy9lc20vc2hhMy5qcz9hYmNiIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC91dGlscy5qcz8yOTNhIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9tb2R1bGFyLmpzPzRhZDQiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2Fic3RyYWN0L2N1cnZlLmpzPzM5OTgiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2Fic3RyYWN0L2Vkd2FyZHMuanM/YjFhZSIsIndlYnBhY2s6Ly9saWIvLi9ub2RlX21vZHVsZXMvQG5vYmxlL2N1cnZlcy9lc20vYWJzdHJhY3QvbW9udGdvbWVyeS5qcz85ZmVkIiwid2VicGFjazovL2xpYi8uL25vZGVfbW9kdWxlcy9Abm9ibGUvY3VydmVzL2VzbS9hYnN0cmFjdC9oYXNoLXRvLWN1cnZlLmpzPzQ2ZDAiLCJ3ZWJwYWNrOi8vbGliLy4vbm9kZV9tb2R1bGVzL0Bub2JsZS9jdXJ2ZXMvZXNtL2VkNDQ4LmpzPzFhMmEiLCJ3ZWJwYWNrOi8vbGliLy4vc3JjL2pzL21haW4uanM/MDAzYSJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgdmFyIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cztcbihmdW5jdGlvbiAoSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKSB7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlFSX0NPREVcIl0gPSAwXSA9IFwiUVJfQ09ERVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJBWlRFQ1wiXSA9IDFdID0gXCJBWlRFQ1wiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJDT0RBQkFSXCJdID0gMl0gPSBcIkNPREFCQVJcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiQ09ERV8zOVwiXSA9IDNdID0gXCJDT0RFXzM5XCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIkNPREVfOTNcIl0gPSA0XSA9IFwiQ09ERV85M1wiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJDT0RFXzEyOFwiXSA9IDVdID0gXCJDT0RFXzEyOFwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJEQVRBX01BVFJJWFwiXSA9IDZdID0gXCJEQVRBX01BVFJJWFwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJNQVhJQ09ERVwiXSA9IDddID0gXCJNQVhJQ09ERVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJJVEZcIl0gPSA4XSA9IFwiSVRGXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIkVBTl8xM1wiXSA9IDldID0gXCJFQU5fMTNcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiRUFOXzhcIl0gPSAxMF0gPSBcIkVBTl84XCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlBERl80MTdcIl0gPSAxMV0gPSBcIlBERl80MTdcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiUlNTXzE0XCJdID0gMTJdID0gXCJSU1NfMTRcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiUlNTX0VYUEFOREVEXCJdID0gMTNdID0gXCJSU1NfRVhQQU5ERURcIjtcbiAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW1wiVVBDX0FcIl0gPSAxNF0gPSBcIlVQQ19BXCI7XG4gICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tcIlVQQ19FXCJdID0gMTVdID0gXCJVUENfRVwiO1xuICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1tIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNbXCJVUENfRUFOX0VYVEVOU0lPTlwiXSA9IDE2XSA9IFwiVVBDX0VBTl9FWFRFTlNJT05cIjtcbn0pKEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyB8fCAoSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzID0ge30pKTtcbnZhciBodG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNUZXh0TWFwID0gbmV3IE1hcChbXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5RUl9DT0RFLCBcIlFSX0NPREVcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5BWlRFQywgXCJBWlRFQ1wiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREFCQVIsIFwiQ09EQUJBUlwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMzksIFwiQ09ERV8zOVwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsIFwiQ09ERV85M1wiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMTI4LCBcIkNPREVfMTI4XCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuREFUQV9NQVRSSVgsIFwiREFUQV9NQVRSSVhcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5NQVhJQ09ERSwgXCJNQVhJQ09ERVwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLklURiwgXCJJVEZcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsIFwiRUFOXzEzXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzgsIFwiRUFOXzhcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5QREZfNDE3LCBcIlBERl80MTdcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfMTQsIFwiUlNTXzE0XCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTX0VYUEFOREVELCBcIlJTU19FWFBBTkRFRFwiXSxcbiAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19BLCBcIlVQQ19BXCJdLFxuICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0UsIFwiVVBDX0VcIl0sXG4gICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfRUFOX0VYVEVOU0lPTiwgXCJVUENfRUFOX0VYVEVOU0lPTlwiXVxuXSk7XG5leHBvcnQgdmFyIERlY29kZWRUZXh0VHlwZTtcbihmdW5jdGlvbiAoRGVjb2RlZFRleHRUeXBlKSB7XG4gICAgRGVjb2RlZFRleHRUeXBlW0RlY29kZWRUZXh0VHlwZVtcIlVOS05PV05cIl0gPSAwXSA9IFwiVU5LTk9XTlwiO1xuICAgIERlY29kZWRUZXh0VHlwZVtEZWNvZGVkVGV4dFR5cGVbXCJVUkxcIl0gPSAxXSA9IFwiVVJMXCI7XG59KShEZWNvZGVkVGV4dFR5cGUgfHwgKERlY29kZWRUZXh0VHlwZSA9IHt9KSk7XG5leHBvcnQgZnVuY3Rpb24gaXNWYWxpZEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhmb3JtYXQpIHtcbiAgICByZXR1cm4gT2JqZWN0LnZhbHVlcyhIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMpLmluY2x1ZGVzKGZvcm1hdCk7XG59XG5leHBvcnQgdmFyIEh0bWw1UXJjb2RlU2NhblR5cGU7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU2NhblR5cGUpIHtcbiAgICBIdG1sNVFyY29kZVNjYW5UeXBlW0h0bWw1UXJjb2RlU2NhblR5cGVbXCJTQ0FOX1RZUEVfQ0FNRVJBXCJdID0gMF0gPSBcIlNDQU5fVFlQRV9DQU1FUkFcIjtcbiAgICBIdG1sNVFyY29kZVNjYW5UeXBlW0h0bWw1UXJjb2RlU2NhblR5cGVbXCJTQ0FOX1RZUEVfRklMRVwiXSA9IDFdID0gXCJTQ0FOX1RZUEVfRklMRVwiO1xufSkoSHRtbDVRcmNvZGVTY2FuVHlwZSB8fCAoSHRtbDVRcmNvZGVTY2FuVHlwZSA9IHt9KSk7XG52YXIgSHRtbDVRcmNvZGVDb25zdGFudHMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlQ29uc3RhbnRzKCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZUNvbnN0YW50cy5HSVRIVUJfUFJPSkVDVF9VUkwgPSBcImh0dHBzOi8vZ2l0aHViLmNvbS9tZWJqYXMvaHRtbDUtcXJjb2RlXCI7XG4gICAgSHRtbDVRcmNvZGVDb25zdGFudHMuU0NBTl9ERUZBVUxUX0ZQUyA9IDI7XG4gICAgSHRtbDVRcmNvZGVDb25zdGFudHMuREVGQVVMVF9ESVNBQkxFX0ZMSVAgPSBmYWxzZTtcbiAgICBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1JFTUVNQkVSX0xBU1RfQ0FNRVJBX1VTRUQgPSB0cnVlO1xuICAgIEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRSA9IFtcbiAgICAgICAgSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfQ0FNRVJBLFxuICAgICAgICBIdG1sNVFyY29kZVNjYW5UeXBlLlNDQU5fVFlQRV9GSUxFXG4gICAgXTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVDb25zdGFudHM7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGVDb25zdGFudHMgfTtcbnZhciBRcmNvZGVSZXN1bHRGb3JtYXQgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFFyY29kZVJlc3VsdEZvcm1hdChmb3JtYXQsIGZvcm1hdE5hbWUpIHtcbiAgICAgICAgdGhpcy5mb3JtYXQgPSBmb3JtYXQ7XG4gICAgICAgIHRoaXMuZm9ybWF0TmFtZSA9IGZvcm1hdE5hbWU7XG4gICAgfVxuICAgIFFyY29kZVJlc3VsdEZvcm1hdC5wcm90b3R5cGUudG9TdHJpbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmZvcm1hdE5hbWU7XG4gICAgfTtcbiAgICBRcmNvZGVSZXN1bHRGb3JtYXQuY3JlYXRlID0gZnVuY3Rpb24gKGZvcm1hdCkge1xuICAgICAgICBpZiAoIWh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1RleHRNYXAuaGFzKGZvcm1hdCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiXCIuY29uY2F0KGZvcm1hdCwgXCIgbm90IGluIGh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0c1RleHRNYXBcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG5ldyBRcmNvZGVSZXN1bHRGb3JtYXQoZm9ybWF0LCBodG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHNUZXh0TWFwLmdldChmb3JtYXQpKTtcbiAgICB9O1xuICAgIHJldHVybiBRcmNvZGVSZXN1bHRGb3JtYXQ7XG59KCkpO1xuZXhwb3J0IHsgUXJjb2RlUmVzdWx0Rm9ybWF0IH07XG52YXIgSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkoKSB7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeS5jcmVhdGVGcm9tVGV4dCA9IGZ1bmN0aW9uIChkZWNvZGVkVGV4dCkge1xuICAgICAgICB2YXIgcXJjb2RlUmVzdWx0ID0ge1xuICAgICAgICAgICAgdGV4dDogZGVjb2RlZFRleHRcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRlY29kZWRUZXh0OiBkZWNvZGVkVGV4dCxcbiAgICAgICAgICAgIHJlc3VsdDogcXJjb2RlUmVzdWx0XG4gICAgICAgIH07XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkuY3JlYXRlRnJvbVFyY29kZVJlc3VsdCA9IGZ1bmN0aW9uIChxcmNvZGVSZXN1bHQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIGRlY29kZWRUZXh0OiBxcmNvZGVSZXN1bHQudGV4dCxcbiAgICAgICAgICAgIHJlc3VsdDogcXJjb2RlUmVzdWx0XG4gICAgICAgIH07XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVSZXN1bHRGYWN0b3J5O1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeSB9O1xuZXhwb3J0IHZhciBIdG1sNVFyY29kZUVycm9yVHlwZXM7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlRXJyb3JUeXBlcykge1xuICAgIEh0bWw1UXJjb2RlRXJyb3JUeXBlc1tIdG1sNVFyY29kZUVycm9yVHlwZXNbXCJVTktXT1dOX0VSUk9SXCJdID0gMF0gPSBcIlVOS1dPV05fRVJST1JcIjtcbiAgICBIdG1sNVFyY29kZUVycm9yVHlwZXNbSHRtbDVRcmNvZGVFcnJvclR5cGVzW1wiSU1QTEVNRU5UQVRJT05fRVJST1JcIl0gPSAxXSA9IFwiSU1QTEVNRU5UQVRJT05fRVJST1JcIjtcbiAgICBIdG1sNVFyY29kZUVycm9yVHlwZXNbSHRtbDVRcmNvZGVFcnJvclR5cGVzW1wiTk9fQ09ERV9GT1VORF9FUlJPUlwiXSA9IDJdID0gXCJOT19DT0RFX0ZPVU5EX0VSUk9SXCI7XG59KShIdG1sNVFyY29kZUVycm9yVHlwZXMgfHwgKEh0bWw1UXJjb2RlRXJyb3JUeXBlcyA9IHt9KSk7XG52YXIgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5KCkge1xuICAgIH1cbiAgICBIdG1sNVFyY29kZUVycm9yRmFjdG9yeS5jcmVhdGVGcm9tID0gZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBlcnJvck1lc3NhZ2U6IGVycm9yLFxuICAgICAgICAgICAgdHlwZTogSHRtbDVRcmNvZGVFcnJvclR5cGVzLlVOS1dPV05fRVJST1JcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHJldHVybiBIdG1sNVFyY29kZUVycm9yRmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZUVycm9yRmFjdG9yeSB9O1xudmFyIEJhc2VMb2dnZ2VyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXNlTG9nZ2dlcih2ZXJib3NlKSB7XG4gICAgICAgIHRoaXMudmVyYm9zZSA9IHZlcmJvc2U7XG4gICAgfVxuICAgIEJhc2VMb2dnZ2VyLnByb3RvdHlwZS5sb2cgPSBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhtZXNzYWdlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgQmFzZUxvZ2dnZXIucHJvdG90eXBlLndhcm4gPSBmdW5jdGlvbiAobWVzc2FnZSkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlKSB7XG4gICAgICAgICAgICBjb25zb2xlLndhcm4obWVzc2FnZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEJhc2VMb2dnZ2VyLnByb3RvdHlwZS5sb2dFcnJvciA9IGZ1bmN0aW9uIChtZXNzYWdlLCBpc0V4cGVyaW1lbnRhbCkge1xuICAgICAgICBpZiAodGhpcy52ZXJib3NlIHx8IGlzRXhwZXJpbWVudGFsID09PSB0cnVlKSB7XG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKG1lc3NhZ2UpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBCYXNlTG9nZ2dlci5wcm90b3R5cGUubG9nRXJyb3JzID0gZnVuY3Rpb24gKGVycm9ycykge1xuICAgICAgICBpZiAoZXJyb3JzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgXCJMb2dnZXIjbG9nRXJyb3IgY2FsbGVkIHdpdGhvdXQgYXJndW1lbnRzXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnJvcnMpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gQmFzZUxvZ2dnZXI7XG59KCkpO1xuZXhwb3J0IHsgQmFzZUxvZ2dnZXIgfTtcbmV4cG9ydCBmdW5jdGlvbiBpc051bGxPclVuZGVmaW5lZChvYmopIHtcbiAgICByZXR1cm4gKHR5cGVvZiBvYmogPT09IFwidW5kZWZpbmVkXCIpIHx8IG9iaiA9PT0gbnVsbDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjbGlwKHZhbHVlLCBtaW5WYWx1ZSwgbWF4VmFsdWUpIHtcbiAgICBpZiAodmFsdWUgPiBtYXhWYWx1ZSkge1xuICAgICAgICByZXR1cm4gbWF4VmFsdWU7XG4gICAgfVxuICAgIGlmICh2YWx1ZSA8IG1pblZhbHVlKSB7XG4gICAgICAgIHJldHVybiBtaW5WYWx1ZTtcbiAgICB9XG4gICAgcmV0dXJuIHZhbHVlO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29yZS5qcy5tYXAiLCJ2YXIgSHRtbDVRcmNvZGVTdHJpbmdzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBIdG1sNVFyY29kZVN0cmluZ3MoKSB7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5jb2RlUGFyc2VFcnJvciA9IGZ1bmN0aW9uIChleGNlcHRpb24pIHtcbiAgICAgICAgcmV0dXJuIFwiUVIgY29kZSBwYXJzZSBlcnJvciwgZXJyb3IgPSBcIi5jb25jYXQoZXhjZXB0aW9uKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5lcnJvckdldHRpbmdVc2VyTWVkaWEgPSBmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgcmV0dXJuIFwiRXJyb3IgZ2V0dGluZyB1c2VyTWVkaWEsIGVycm9yID0gXCIuY29uY2F0KGVycm9yKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU3RyaW5ncy5vbmx5RGV2aWNlU3VwcG9ydGVkRXJyb3IgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlRoZSBkZXZpY2UgZG9lc24ndCBzdXBwb3J0IG5hdmlnYXRvci5tZWRpYURldmljZXMgLCBvbmx5IFwiXG4gICAgICAgICAgICArIFwic3VwcG9ydGVkIGNhbWVyYUlkT3JDb25maWcgaW4gdGhpcyBjYXNlIGlzIGRldmljZUlkIHBhcmFtZXRlciBcIlxuICAgICAgICAgICAgKyBcIihzdHJpbmcpLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLmNhbWVyYVN0cmVhbWluZ05vdFN1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQ2FtZXJhIHN0cmVhbWluZyBub3Qgc3VwcG9ydGVkIGJ5IHRoZSBicm93c2VyLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLnVuYWJsZVRvUXVlcnlTdXBwb3J0ZWREZXZpY2VzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJVbmFibGUgdG8gcXVlcnkgc3VwcG9ydGVkIGRldmljZXMsIHVua25vd24gZXJyb3IuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVN0cmluZ3MuaW5zZWN1cmVDb250ZXh0Q2FtZXJhUXVlcnlFcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiQ2FtZXJhIGFjY2VzcyBpcyBvbmx5IHN1cHBvcnRlZCBpbiBzZWN1cmUgY29udGV4dCBsaWtlIGh0dHBzIFwiXG4gICAgICAgICAgICArIFwib3IgbG9jYWxob3N0LlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTdHJpbmdzLnNjYW5uZXJQYXVzZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNjYW5uZXIgcGF1c2VkXCI7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTdHJpbmdzO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU3RyaW5ncyB9O1xudmFyIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MoKSB7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2Nhbm5pbmdTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNjYW5uaW5nXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmlkbGVTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIklkbGVcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZXJyb3JTdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkVycm9yXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnBlcm1pc3Npb25TdGF0dXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlBlcm1pc3Npb25cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Mubm9DYW1lcmFGb3VuZEVycm9yU3RhdHVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJObyBDYW1lcmFzXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmxhc3RNYXRjaCA9IGZ1bmN0aW9uIChkZWNvZGVkVGV4dCkge1xuICAgICAgICByZXR1cm4gXCJMYXN0IE1hdGNoOiBcIi5jb25jYXQoZGVjb2RlZFRleHQpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jb2RlU2Nhbm5lclRpdGxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJDb2RlIFNjYW5uZXJcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY2FtZXJhUGVybWlzc2lvblRpdGxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJSZXF1ZXN0IENhbWVyYSBQZXJtaXNzaW9uc1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFQZXJtaXNzaW9uUmVxdWVzdGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiUmVxdWVzdGluZyBjYW1lcmEgcGVybWlzc2lvbnMuLi5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Mubm9DYW1lcmFGb3VuZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiTm8gY2FtZXJhIGZvdW5kXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TdG9wU2Nhbm5pbmdUZXh0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTdG9wIFNjYW5uaW5nXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TdGFydFNjYW5uaW5nVGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU3RhcnQgU2Nhbm5pbmdcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPbkJ1dHRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiU3dpdGNoIE9uIFRvcmNoXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT2ZmQnV0dG9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTd2l0Y2ggT2ZmIFRvcmNoXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT25GYWlsZWRNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJGYWlsZWQgdG8gdHVybiBvbiB0b3JjaFwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9mZkZhaWxlZE1lc3NhZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkZhaWxlZCB0byB0dXJuIG9mZiB0b3JjaFwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FuQnV0dG9uU2Nhbm5pbmdTdGFydGluZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiTGF1bmNoaW5nIENhbWVyYS4uLlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50ZXh0SWZDYW1lcmFTY2FuU2VsZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNjYW4gYW4gSW1hZ2UgRmlsZVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50ZXh0SWZGaWxlU2NhblNlbGVjdGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJTY2FuIHVzaW5nIGNhbWVyYSBkaXJlY3RseVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zZWxlY3RDYW1lcmEgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlNlbGVjdCBDYW1lcmFcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbkNob29zZUltYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJDaG9vc2UgSW1hZ2VcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNlbGVjdGlvbkNob29zZUFub3RoZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkNob29zZSBBbm90aGVyXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTZWxlY3Rpb25Ob0ltYWdlU2VsZWN0ZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIk5vIGltYWdlIGNob29zZW5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuYW5vbnltb3VzQ2FtZXJhUHJlZml4ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJBbm9ueW1vdXMgQ2FtZXJhXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmRyYWdBbmREcm9wTWVzc2FnZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiT3IgZHJvcCBhbiBpbWFnZSB0byBzY2FuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmRyYWdBbmREcm9wTWVzc2FnZU9ubHlJbWFnZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIk9yIGRyb3AgYW4gaW1hZ2UgdG8gc2NhbiAob3RoZXIgZmlsZXMgbm90IHN1cHBvcnRlZClcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muem9vbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiem9vbVwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5sb2FkaW5nSW1hZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkxvYWRpbmcgaW1hZ2UuLi5cIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuY2FtZXJhU2NhbkFsdFRleHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIkNhbWVyYSBiYXNlZCBzY2FuXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTY2FuQWx0VGV4dCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiRnVsZSBiYXNlZCBzY2FuXCI7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncztcbn0oKSk7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH07XG52YXIgTGlicmFyeUluZm9TdHJpbmdzID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBMaWJyYXJ5SW5mb1N0cmluZ3MoKSB7XG4gICAgfVxuICAgIExpYnJhcnlJbmZvU3RyaW5ncy5wb3dlcmVkQnkgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlBvd2VyZWQgYnkgXCI7XG4gICAgfTtcbiAgICBMaWJyYXJ5SW5mb1N0cmluZ3MucmVwb3J0SXNzdWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJSZXBvcnQgaXNzdWVzXCI7XG4gICAgfTtcbiAgICByZXR1cm4gTGlicmFyeUluZm9TdHJpbmdzO1xufSgpKTtcbmV4cG9ydCB7IExpYnJhcnlJbmZvU3RyaW5ncyB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3RyaW5ncy5qcy5tYXAiLCJ2YXIgVmlkZW9Db25zdHJhaW50c1V0aWwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFZpZGVvQ29uc3RyYWludHNVdGlsKCkge1xuICAgIH1cbiAgICBWaWRlb0NvbnN0cmFpbnRzVXRpbC5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCA9IGZ1bmN0aW9uICh2aWRlb0NvbnN0cmFpbnRzLCBsb2dnZXIpIHtcbiAgICAgICAgaWYgKHR5cGVvZiB2aWRlb0NvbnN0cmFpbnRzICE9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICB2YXIgdHlwZW9mVmlkZW9Db25zdHJhaW50cyA9IHR5cGVvZiB2aWRlb0NvbnN0cmFpbnRzO1xuICAgICAgICAgICAgbG9nZ2VyLmxvZ0Vycm9yKFwidmlkZW9Db25zdHJhaW50cyBzaG91bGQgYmUgb2YgdHlwZSBvYmplY3QsIHRoZSBcIlxuICAgICAgICAgICAgICAgICsgXCJvYmplY3QgcGFzc2VkIGlzIG9mIHR5cGUgXCIuY29uY2F0KHR5cGVvZlZpZGVvQ29uc3RyYWludHMsIFwiLlwiKSwgdHJ1ZSk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGJhbm5lZEtleXMgPSBbXG4gICAgICAgICAgICBcImF1dG9HYWluQ29udHJvbFwiLFxuICAgICAgICAgICAgXCJjaGFubmVsQ291bnRcIixcbiAgICAgICAgICAgIFwiZWNob0NhbmNlbGxhdGlvblwiLFxuICAgICAgICAgICAgXCJsYXRlbmN5XCIsXG4gICAgICAgICAgICBcIm5vaXNlU3VwcHJlc3Npb25cIixcbiAgICAgICAgICAgIFwic2FtcGxlUmF0ZVwiLFxuICAgICAgICAgICAgXCJzYW1wbGVTaXplXCIsXG4gICAgICAgICAgICBcInZvbHVtZVwiXG4gICAgICAgIF07XG4gICAgICAgIHZhciBiYW5uZWRrZXlzU2V0ID0gbmV3IFNldChiYW5uZWRLZXlzKTtcbiAgICAgICAgdmFyIGtleXNJblZpZGVvQ29uc3RyYWludHMgPSBPYmplY3Qua2V5cyh2aWRlb0NvbnN0cmFpbnRzKTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzXzEgPSBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzOyBfaSA8IGtleXNJblZpZGVvQ29uc3RyYWludHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBrZXkgPSBrZXlzSW5WaWRlb0NvbnN0cmFpbnRzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKGJhbm5lZGtleXNTZXQuaGFzKGtleSkpIHtcbiAgICAgICAgICAgICAgICBsb2dnZXIubG9nRXJyb3IoXCJcIi5jb25jYXQoa2V5LCBcIiBpcyBub3Qgc3VwcG9ydGVkIHZpZGVvQ29uc3RhaW50cy5cIiksIHRydWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9O1xuICAgIHJldHVybiBWaWRlb0NvbnN0cmFpbnRzVXRpbDtcbn0oKSk7XG5leHBvcnQgeyBWaWRlb0NvbnN0cmFpbnRzVXRpbCB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dXRpbHMuanMubWFwIiwiaW1wb3J0ICogYXMgWlhpbmcgZnJvbSBcIi4uL3RoaXJkX3BhcnR5L3p4aW5nLWpzLnVtZFwiO1xuaW1wb3J0IHsgUXJjb2RlUmVzdWx0Rm9ybWF0LCBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMgfSBmcm9tIFwiLi9jb3JlXCI7XG52YXIgWlhpbmdIdG1sNVFyY29kZURlY29kZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFpYaW5nSHRtbDVRcmNvZGVEZWNvZGVyKHJlcXVlc3RlZEZvcm1hdHMsIHZlcmJvc2UsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLmZvcm1hdE1hcCA9IG5ldyBNYXAoW1xuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5RUl9DT0RFLCBaWGluZy5CYXJjb2RlRm9ybWF0LlFSX0NPREVdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5BWlRFQywgWlhpbmcuQmFyY29kZUZvcm1hdC5BWlRFQ10sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREFCQVIsIFpYaW5nLkJhcmNvZGVGb3JtYXQuQ09EQUJBUl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMzksIFpYaW5nLkJhcmNvZGVGb3JtYXQuQ09ERV8zOV0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsIFpYaW5nLkJhcmNvZGVGb3JtYXQuQ09ERV85M10sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfMTI4LFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuQ09ERV8xMjhcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkRBVEFfTUFUUklYLFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuREFUQV9NQVRSSVhcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBbXG4gICAgICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLk1BWElDT0RFLFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuTUFYSUNPREVcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLklURiwgWlhpbmcuQmFyY29kZUZvcm1hdC5JVEZdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsIFpYaW5nLkJhcmNvZGVGb3JtYXQuRUFOXzEzXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuRUFOXzgsIFpYaW5nLkJhcmNvZGVGb3JtYXQuRUFOXzhdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5QREZfNDE3LCBaWGluZy5CYXJjb2RlRm9ybWF0LlBERl80MTddLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfMTQsIFpYaW5nLkJhcmNvZGVGb3JtYXQuUlNTXzE0XSxcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUlNTX0VYUEFOREVELFxuICAgICAgICAgICAgICAgIFpYaW5nLkJhcmNvZGVGb3JtYXQuUlNTX0VYUEFOREVEXG4gICAgICAgICAgICBdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfQSwgWlhpbmcuQmFyY29kZUZvcm1hdC5VUENfQV0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19FLCBaWGluZy5CYXJjb2RlRm9ybWF0LlVQQ19FXSxcbiAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0VBTl9FWFRFTlNJT04sXG4gICAgICAgICAgICAgICAgWlhpbmcuQmFyY29kZUZvcm1hdC5VUENfRUFOX0VYVEVOU0lPTlxuICAgICAgICAgICAgXVxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5yZXZlcnNlRm9ybWF0TWFwID0gdGhpcy5jcmVhdGVSZXZlcnNlRm9ybWF0TWFwKCk7XG4gICAgICAgIGlmICghWlhpbmcpIHtcbiAgICAgICAgICAgIHRocm93IFwiVXNlIGh0bWw1cXJjb2RlLm1pbi5qcyB3aXRob3V0IGVkaXQsIFpYaW5nIG5vdCBmb3VuZC5cIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdmFyIGZvcm1hdHMgPSB0aGlzLmNyZWF0ZVpYaW5nRm9ybWF0cyhyZXF1ZXN0ZWRGb3JtYXRzKTtcbiAgICAgICAgdmFyIGhpbnRzID0gbmV3IE1hcCgpO1xuICAgICAgICBoaW50cy5zZXQoWlhpbmcuRGVjb2RlSGludFR5cGUuUE9TU0lCTEVfRk9STUFUUywgZm9ybWF0cyk7XG4gICAgICAgIGhpbnRzLnNldChaWGluZy5EZWNvZGVIaW50VHlwZS5UUllfSEFSREVSLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuaGludHMgPSBoaW50cztcbiAgICB9XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmRlY29kZUFzeW5jID0gZnVuY3Rpb24gKGNhbnZhcykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXNvbHZlKF90aGlzLmRlY29kZShjYW52YXMpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmRlY29kZSA9IGZ1bmN0aW9uIChjYW52YXMpIHtcbiAgICAgICAgdmFyIHp4aW5nRGVjb2RlciA9IG5ldyBaWGluZy5NdWx0aUZvcm1hdFJlYWRlcih0aGlzLnZlcmJvc2UsIHRoaXMuaGludHMpO1xuICAgICAgICB2YXIgbHVtaW5hbmNlU291cmNlID0gbmV3IFpYaW5nLkhUTUxDYW52YXNFbGVtZW50THVtaW5hbmNlU291cmNlKGNhbnZhcyk7XG4gICAgICAgIHZhciBiaW5hcnlCaXRtYXAgPSBuZXcgWlhpbmcuQmluYXJ5Qml0bWFwKG5ldyBaWGluZy5IeWJyaWRCaW5hcml6ZXIobHVtaW5hbmNlU291cmNlKSk7XG4gICAgICAgIHZhciByZXN1bHQgPSB6eGluZ0RlY29kZXIuZGVjb2RlKGJpbmFyeUJpdG1hcCk7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB0ZXh0OiByZXN1bHQudGV4dCxcbiAgICAgICAgICAgIGZvcm1hdDogUXJjb2RlUmVzdWx0Rm9ybWF0LmNyZWF0ZSh0aGlzLnRvSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKHJlc3VsdC5mb3JtYXQpKSxcbiAgICAgICAgICAgIGRlYnVnRGF0YTogdGhpcy5jcmVhdGVEZWJ1Z0RhdGEoKVxuICAgICAgICB9O1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLmNyZWF0ZVJldmVyc2VGb3JtYXRNYXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciByZXN1bHQgPSBuZXcgTWFwKCk7XG4gICAgICAgIHRoaXMuZm9ybWF0TWFwLmZvckVhY2goZnVuY3Rpb24gKHZhbHVlLCBrZXksIF8pIHtcbiAgICAgICAgICAgIHJlc3VsdC5zZXQodmFsdWUsIGtleSk7XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH07XG4gICAgWlhpbmdIdG1sNVFyY29kZURlY29kZXIucHJvdG90eXBlLnRvSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzID0gZnVuY3Rpb24gKHp4aW5nRm9ybWF0KSB7XG4gICAgICAgIGlmICghdGhpcy5yZXZlcnNlRm9ybWF0TWFwLmhhcyh6eGluZ0Zvcm1hdCkpIHtcbiAgICAgICAgICAgIHRocm93IFwicmV2ZXJzZUZvcm1hdE1hcCBkb2Vzbid0IGhhdmUgXCIuY29uY2F0KHp4aW5nRm9ybWF0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5yZXZlcnNlRm9ybWF0TWFwLmdldCh6eGluZ0Zvcm1hdCk7XG4gICAgfTtcbiAgICBaWGluZ0h0bWw1UXJjb2RlRGVjb2Rlci5wcm90b3R5cGUuY3JlYXRlWlhpbmdGb3JtYXRzID0gZnVuY3Rpb24gKHJlcXVlc3RlZEZvcm1hdHMpIHtcbiAgICAgICAgdmFyIHp4aW5nRm9ybWF0cyA9IFtdO1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIHJlcXVlc3RlZEZvcm1hdHNfMSA9IHJlcXVlc3RlZEZvcm1hdHM7IF9pIDwgcmVxdWVzdGVkRm9ybWF0c18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIHJlcXVlc3RlZEZvcm1hdCA9IHJlcXVlc3RlZEZvcm1hdHNfMVtfaV07XG4gICAgICAgICAgICBpZiAodGhpcy5mb3JtYXRNYXAuaGFzKHJlcXVlc3RlZEZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICB6eGluZ0Zvcm1hdHMucHVzaCh0aGlzLmZvcm1hdE1hcC5nZXQocmVxdWVzdGVkRm9ybWF0KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmxvZ2dlci5sb2dFcnJvcihcIlwiLmNvbmNhdChyZXF1ZXN0ZWRGb3JtYXQsIFwiIGlzIG5vdCBzdXBwb3J0ZWQgYnlcIilcbiAgICAgICAgICAgICAgICAgICAgKyBcIlpYaW5nSHRtbDVRcmNvZGVTaGltXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB6eGluZ0Zvcm1hdHM7XG4gICAgfTtcbiAgICBaWGluZ0h0bWw1UXJjb2RlRGVjb2Rlci5wcm90b3R5cGUuY3JlYXRlRGVidWdEYXRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4geyBkZWNvZGVyTmFtZTogXCJ6eGluZy1qc1wiIH07XG4gICAgfTtcbiAgICByZXR1cm4gWlhpbmdIdG1sNVFyY29kZURlY29kZXI7XG59KCkpO1xuZXhwb3J0IHsgWlhpbmdIdG1sNVFyY29kZURlY29kZXIgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXp4aW5nLWh0bWw1LXFyY29kZS1kZWNvZGVyLmpzLm1hcCIsInZhciBfX2F3YWl0ZXIgPSAodGhpcyAmJiB0aGlzLl9fYXdhaXRlcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIF9hcmd1bWVudHMsIFAsIGdlbmVyYXRvcikge1xuICAgIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICAgIHJldHVybiBuZXcgKFAgfHwgKFAgPSBQcm9taXNlKSkoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICBmdW5jdGlvbiBmdWxmaWxsZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3IubmV4dCh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiBzdGVwKHJlc3VsdCkgeyByZXN1bHQuZG9uZSA/IHJlc29sdmUocmVzdWx0LnZhbHVlKSA6IGFkb3B0KHJlc3VsdC52YWx1ZSkudGhlbihmdWxmaWxsZWQsIHJlamVjdGVkKTsgfVxuICAgICAgICBzdGVwKChnZW5lcmF0b3IgPSBnZW5lcmF0b3IuYXBwbHkodGhpc0FyZywgX2FyZ3VtZW50cyB8fCBbXSkpLm5leHQoKSk7XG4gICAgfSk7XG59O1xudmFyIF9fZ2VuZXJhdG9yID0gKHRoaXMgJiYgdGhpcy5fX2dlbmVyYXRvcikgfHwgZnVuY3Rpb24gKHRoaXNBcmcsIGJvZHkpIHtcbiAgICB2YXIgXyA9IHsgbGFiZWw6IDAsIHNlbnQ6IGZ1bmN0aW9uKCkgeyBpZiAodFswXSAmIDEpIHRocm93IHRbMV07IHJldHVybiB0WzFdOyB9LCB0cnlzOiBbXSwgb3BzOiBbXSB9LCBmLCB5LCB0LCBnO1xuICAgIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICAgIGZ1bmN0aW9uIHZlcmIobikgeyByZXR1cm4gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHN0ZXAoW24sIHZdKTsgfTsgfVxuICAgIGZ1bmN0aW9uIHN0ZXAob3ApIHtcbiAgICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgICB3aGlsZSAoZyAmJiAoZyA9IDAsIG9wWzBdICYmIChfID0gMCkpLCBfKSB0cnkge1xuICAgICAgICAgICAgaWYgKGYgPSAxLCB5ICYmICh0ID0gb3BbMF0gJiAyID8geVtcInJldHVyblwiXSA6IG9wWzBdID8geVtcInRocm93XCJdIHx8ICgodCA9IHlbXCJyZXR1cm5cIl0pICYmIHQuY2FsbCh5KSwgMCkgOiB5Lm5leHQpICYmICEodCA9IHQuY2FsbCh5LCBvcFsxXSkpLmRvbmUpIHJldHVybiB0O1xuICAgICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgICAgc3dpdGNoIChvcFswXSkge1xuICAgICAgICAgICAgICAgIGNhc2UgMDogY2FzZSAxOiB0ID0gb3A7IGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgICAgY2FzZSA1OiBfLmxhYmVsKys7IHkgPSBvcFsxXTsgb3AgPSBbMF07IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGNhc2UgNzogb3AgPSBfLm9wcy5wb3AoKTsgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoISh0ID0gXy50cnlzLCB0ID0gdC5sZW5ndGggPiAwICYmIHRbdC5sZW5ndGggLSAxXSkgJiYgKG9wWzBdID09PSA2IHx8IG9wWzBdID09PSAyKSkgeyBfID0gMDsgY29udGludWU7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSAzICYmICghdCB8fCAob3BbMV0gPiB0WzBdICYmIG9wWzFdIDwgdFszXSkpKSB7IF8ubGFiZWwgPSBvcFsxXTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0ICYmIF8ubGFiZWwgPCB0WzJdKSB7IF8ubGFiZWwgPSB0WzJdOyBfLm9wcy5wdXNoKG9wKTsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRbMl0pIF8ub3BzLnBvcCgpO1xuICAgICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgb3AgPSBib2R5LmNhbGwodGhpc0FyZywgXyk7XG4gICAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgICAgaWYgKG9wWzBdICYgNSkgdGhyb3cgb3BbMV07IHJldHVybiB7IHZhbHVlOiBvcFswXSA/IG9wWzFdIDogdm9pZCAwLCBkb25lOiB0cnVlIH07XG4gICAgfVxufTtcbmltcG9ydCB7IFFyY29kZVJlc3VsdEZvcm1hdCwgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcIi4vY29yZVwiO1xudmFyIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZShyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpIHtcbiAgICAgICAgdGhpcy5mb3JtYXRNYXAgPSBuZXcgTWFwKFtcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUVJfQ09ERSwgXCJxcl9jb2RlXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5BWlRFQywgXCJhenRlY1wiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09EQUJBUiwgXCJjb2RhYmFyXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LCBcImNvZGVfMzlcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsIFwiY29kZV85M1wiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09ERV8xMjgsIFwiY29kZV8xMjhcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkRBVEFfTUFUUklYLCBcImRhdGFfbWF0cml4XCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5JVEYsIFwiaXRmXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fMTMsIFwiZWFuXzEzXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fOCwgXCJlYW5fOFwiXSxcbiAgICAgICAgICAgIFtIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuUERGXzQxNywgXCJwZGY0MTdcIl0sXG4gICAgICAgICAgICBbSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlVQQ19BLCBcInVwY19hXCJdLFxuICAgICAgICAgICAgW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5VUENfRSwgXCJ1cGNfZVwiXVxuICAgICAgICBdKTtcbiAgICAgICAgdGhpcy5yZXZlcnNlRm9ybWF0TWFwID0gdGhpcy5jcmVhdGVSZXZlcnNlRm9ybWF0TWFwKCk7XG4gICAgICAgIGlmICghQmFyY29kZURldGVjdG9yRGVsZWdhdGUuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJVc2UgaHRtbDVxcmNvZGUubWluLmpzIHdpdGhvdXQgZWRpdCwgVXNlIFwiXG4gICAgICAgICAgICAgICAgKyBcIkJhcmNvZGVEZXRlY3RvckRlbGVnYXRlIG9ubHkgaWYgaXQgaXNTdXBwb3J0ZWQoKTtcIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdmFyIGZvcm1hdHMgPSB0aGlzLmNyZWF0ZUJhcmNvZGVEZXRlY3RvckZvcm1hdHMocmVxdWVzdGVkRm9ybWF0cyk7XG4gICAgICAgIHRoaXMuZGV0ZWN0b3IgPSBuZXcgQmFyY29kZURldGVjdG9yKGZvcm1hdHMpO1xuICAgICAgICBpZiAoIXRoaXMuZGV0ZWN0b3IpIHtcbiAgICAgICAgICAgIHRocm93IFwiQmFyY29kZURldGVjdG9yIGRldGVjdG9yIG5vdCBzdXBwb3J0ZWRcIjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5pc1N1cHBvcnRlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCEoXCJCYXJjb2RlRGV0ZWN0b3JcIiBpbiB3aW5kb3cpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGR1bW15RGV0ZWN0b3IgPSBuZXcgQmFyY29kZURldGVjdG9yKHsgZm9ybWF0czogW1wicXJfY29kZVwiXSB9KTtcbiAgICAgICAgcmV0dXJuIHR5cGVvZiBkdW1teURldGVjdG9yICE9PSBcInVuZGVmaW5lZFwiO1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLmRlY29kZUFzeW5jID0gZnVuY3Rpb24gKGNhbnZhcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgYmFyY29kZXMsIGxhcmdlc3RCYXJjb2RlO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gWzQsIHRoaXMuZGV0ZWN0b3IuZGV0ZWN0KGNhbnZhcyldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBiYXJjb2RlcyA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghYmFyY29kZXMgfHwgYmFyY29kZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJObyBiYXJjb2RlIG9yIFFSIGNvZGUgZGV0ZWN0ZWQuXCI7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBsYXJnZXN0QmFyY29kZSA9IHRoaXMuc2VsZWN0TGFyZ2VzdEJhcmNvZGUoYmFyY29kZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRleHQ6IGxhcmdlc3RCYXJjb2RlLnJhd1ZhbHVlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXQ6IFFyY29kZVJlc3VsdEZvcm1hdC5jcmVhdGUodGhpcy50b0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cyhsYXJnZXN0QmFyY29kZS5mb3JtYXQpKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVidWdEYXRhOiB0aGlzLmNyZWF0ZURlYnVnRGF0YSgpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQmFyY29kZURldGVjdG9yRGVsZWdhdGUucHJvdG90eXBlLnNlbGVjdExhcmdlc3RCYXJjb2RlID0gZnVuY3Rpb24gKGJhcmNvZGVzKSB7XG4gICAgICAgIHZhciBsYXJnZXN0QmFyY29kZSA9IG51bGw7XG4gICAgICAgIHZhciBtYXhBcmVhID0gMDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBiYXJjb2Rlc18xID0gYmFyY29kZXM7IF9pIDwgYmFyY29kZXNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBiYXJjb2RlID0gYmFyY29kZXNfMVtfaV07XG4gICAgICAgICAgICB2YXIgYXJlYSA9IGJhcmNvZGUuYm91bmRpbmdCb3gud2lkdGggKiBiYXJjb2RlLmJvdW5kaW5nQm94LmhlaWdodDtcbiAgICAgICAgICAgIGlmIChhcmVhID4gbWF4QXJlYSkge1xuICAgICAgICAgICAgICAgIG1heEFyZWEgPSBhcmVhO1xuICAgICAgICAgICAgICAgIGxhcmdlc3RCYXJjb2RlID0gYmFyY29kZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoIWxhcmdlc3RCYXJjb2RlKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk5vIGxhcmdlc3QgYmFyY29kZSBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBsYXJnZXN0QmFyY29kZTtcbiAgICB9O1xuICAgIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLnByb3RvdHlwZS5jcmVhdGVCYXJjb2RlRGV0ZWN0b3JGb3JtYXRzID0gZnVuY3Rpb24gKHJlcXVlc3RlZEZvcm1hdHMpIHtcbiAgICAgICAgdmFyIGZvcm1hdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCByZXF1ZXN0ZWRGb3JtYXRzXzEgPSByZXF1ZXN0ZWRGb3JtYXRzOyBfaSA8IHJlcXVlc3RlZEZvcm1hdHNfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciByZXF1ZXN0ZWRGb3JtYXQgPSByZXF1ZXN0ZWRGb3JtYXRzXzFbX2ldO1xuICAgICAgICAgICAgaWYgKHRoaXMuZm9ybWF0TWFwLmhhcyhyZXF1ZXN0ZWRGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgZm9ybWF0cy5wdXNoKHRoaXMuZm9ybWF0TWFwLmdldChyZXF1ZXN0ZWRGb3JtYXQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJcIi5jb25jYXQocmVxdWVzdGVkRm9ybWF0LCBcIiBpcyBub3Qgc3VwcG9ydGVkIGJ5XCIpXG4gICAgICAgICAgICAgICAgICAgICsgXCJCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZVwiKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4geyBmb3JtYXRzOiBmb3JtYXRzIH07XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUudG9IdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMgPSBmdW5jdGlvbiAoYmFyY29kZURldGVjdG9yRm9ybWF0KSB7XG4gICAgICAgIGlmICghdGhpcy5yZXZlcnNlRm9ybWF0TWFwLmhhcyhiYXJjb2RlRGV0ZWN0b3JGb3JtYXQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcInJldmVyc2VGb3JtYXRNYXAgZG9lc24ndCBoYXZlIFwiLmNvbmNhdChiYXJjb2RlRGV0ZWN0b3JGb3JtYXQpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJldmVyc2VGb3JtYXRNYXAuZ2V0KGJhcmNvZGVEZXRlY3RvckZvcm1hdCk7XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUuY3JlYXRlUmV2ZXJzZUZvcm1hdE1hcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5mb3JtYXRNYXAuZm9yRWFjaChmdW5jdGlvbiAodmFsdWUsIGtleSwgXykge1xuICAgICAgICAgICAgcmVzdWx0LnNldCh2YWx1ZSwga2V5KTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfTtcbiAgICBCYXJjb2RlRGV0ZWN0b3JEZWxlZ2F0ZS5wcm90b3R5cGUuY3JlYXRlRGVidWdEYXRhID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4geyBkZWNvZGVyTmFtZTogXCJCYXJjb2RlRGV0ZWN0b3JcIiB9O1xuICAgIH07XG4gICAgcmV0dXJuIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlO1xufSgpKTtcbmV4cG9ydCB7IEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1uYXRpdmUtYmFyLWNvZGUtZGV0ZWN0b3IuanMubWFwIiwidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgWlhpbmdIdG1sNVFyY29kZURlY29kZXIgfSBmcm9tIFwiLi96eGluZy1odG1sNS1xcmNvZGUtZGVjb2RlclwiO1xuaW1wb3J0IHsgQmFyY29kZURldGVjdG9yRGVsZWdhdGUgfSBmcm9tIFwiLi9uYXRpdmUtYmFyLWNvZGUtZGV0ZWN0b3JcIjtcbnZhciBIdG1sNVFyY29kZVNoaW0gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlU2hpbShyZXF1ZXN0ZWRGb3JtYXRzLCB1c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCwgdmVyYm9zZSwgbG9nZ2VyKSB7XG4gICAgICAgIHRoaXMuRVhFQ1VUSU9OU19UT19SRVBPUlRfUEVSRk9STUFOQ0UgPSAxMDA7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9ucyA9IDA7XG4gICAgICAgIHRoaXMuZXhlY3V0aW9uUmVzdWx0cyA9IFtdO1xuICAgICAgICB0aGlzLndhc1ByaW1hcnlEZWNvZGVyVXNlZEluTGFzdERlY29kZSA9IGZhbHNlO1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSB2ZXJib3NlO1xuICAgICAgICBpZiAodXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWRcbiAgICAgICAgICAgICYmIEJhcmNvZGVEZXRlY3RvckRlbGVnYXRlLmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMucHJpbWFyeURlY29kZXIgPSBuZXcgQmFyY29kZURldGVjdG9yRGVsZWdhdGUocmVxdWVzdGVkRm9ybWF0cywgdmVyYm9zZSwgbG9nZ2VyKTtcbiAgICAgICAgICAgIHRoaXMuc2Vjb25kYXJ5RGVjb2RlciA9IG5ldyBaWGluZ0h0bWw1UXJjb2RlRGVjb2RlcihyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5wcmltYXJ5RGVjb2RlciA9IG5ldyBaWGluZ0h0bWw1UXJjb2RlRGVjb2RlcihyZXF1ZXN0ZWRGb3JtYXRzLCB2ZXJib3NlLCBsb2dnZXIpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU2hpbS5wcm90b3R5cGUuZGVjb2RlQXN5bmMgPSBmdW5jdGlvbiAoY2FudmFzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzdGFydFRpbWU7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2EudHJ5cy5wdXNoKFsxLCAsIDMsIDRdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgdGhpcy5nZXREZWNvZGVyKCkuZGVjb2RlQXN5bmMoY2FudmFzKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjogcmV0dXJuIFsyLCBfYS5zZW50KCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnBvc3NpYmx5TG9nUGVyZm9ybWFuY2Uoc3RhcnRUaW1lKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbN107XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgNDogcmV0dXJuIFsyXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNoaW0ucHJvdG90eXBlLmRlY29kZVJvYnVzdGx5QXN5bmMgPSBmdW5jdGlvbiAoY2FudmFzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBzdGFydFRpbWUsIGVycm9yXzE7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBzdGFydFRpbWUgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICAgICAgX2EudHJ5cy5wdXNoKFsxLCAzLCA0LCA1XSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzQsIHRoaXMucHJpbWFyeURlY29kZXIuZGVjb2RlQXN5bmMoY2FudmFzKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMjogcmV0dXJuIFsyLCBfYS5zZW50KCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcl8xID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2Vjb25kYXJ5RGVjb2Rlcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgdGhpcy5zZWNvbmRhcnlEZWNvZGVyLmRlY29kZUFzeW5jKGNhbnZhcyldO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgZXJyb3JfMTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wb3NzaWJseUxvZ1BlcmZvcm1hbmNlKHN0YXJ0VGltZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzddO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDU6IHJldHVybiBbMl07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTaGltLnByb3RvdHlwZS5nZXREZWNvZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuc2Vjb25kYXJ5RGVjb2Rlcikge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeURlY29kZXI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHRoaXMud2FzUHJpbWFyeURlY29kZXJVc2VkSW5MYXN0RGVjb2RlID09PSBmYWxzZSkge1xuICAgICAgICAgICAgdGhpcy53YXNQcmltYXJ5RGVjb2RlclVzZWRJbkxhc3REZWNvZGUgPSB0cnVlO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMucHJpbWFyeURlY29kZXI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy53YXNQcmltYXJ5RGVjb2RlclVzZWRJbkxhc3REZWNvZGUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2Vjb25kYXJ5RGVjb2RlcjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2hpbS5wcm90b3R5cGUucG9zc2libHlMb2dQZXJmb3JtYW5jZSA9IGZ1bmN0aW9uIChzdGFydFRpbWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhlY3V0aW9uVGltZSA9IHBlcmZvcm1hbmNlLm5vdygpIC0gc3RhcnRUaW1lO1xuICAgICAgICB0aGlzLmV4ZWN1dGlvblJlc3VsdHMucHVzaChleGVjdXRpb25UaW1lKTtcbiAgICAgICAgdGhpcy5leGVjdXRpb25zKys7XG4gICAgICAgIHRoaXMucG9zc2libHlGbHVzaFBlcmZvcm1hbmNlUmVwb3J0KCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNoaW0ucHJvdG90eXBlLnBvc3NpYmx5Rmx1c2hQZXJmb3JtYW5jZVJlcG9ydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuZXhlY3V0aW9ucyA8IHRoaXMuRVhFQ1VUSU9OU19UT19SRVBPUlRfUEVSRk9STUFOQ0UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgc3VtID0gMDtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IHRoaXMuZXhlY3V0aW9uUmVzdWx0czsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBleGVjdXRpb25UaW1lID0gX2FbX2ldO1xuICAgICAgICAgICAgc3VtICs9IGV4ZWN1dGlvblRpbWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1lYW4gPSBzdW0gLyB0aGlzLmV4ZWN1dGlvblJlc3VsdHMubGVuZ3RoO1xuICAgICAgICBjb25zb2xlLmxvZyhcIlwiLmNvbmNhdChtZWFuLCBcIiBtcyBmb3IgXCIpLmNvbmNhdCh0aGlzLmV4ZWN1dGlvblJlc3VsdHMubGVuZ3RoLCBcIiBsYXN0IHJ1bnMuXCIpKTtcbiAgICAgICAgdGhpcy5leGVjdXRpb25zID0gMDtcbiAgICAgICAgdGhpcy5leGVjdXRpb25SZXN1bHRzID0gW107XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTaGltO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2hpbSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9Y29kZS1kZWNvZGVyLmpzLm1hcCIsInZhciBfX2V4dGVuZHMgPSAodGhpcyAmJiB0aGlzLl9fZXh0ZW5kcykgfHwgKGZ1bmN0aW9uICgpIHtcbiAgICB2YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MgPSBPYmplY3Quc2V0UHJvdG90eXBlT2YgfHxcbiAgICAgICAgICAgICh7IF9fcHJvdG9fXzogW10gfSBpbnN0YW5jZW9mIEFycmF5ICYmIGZ1bmN0aW9uIChkLCBiKSB7IGQuX19wcm90b19fID0gYjsgfSkgfHxcbiAgICAgICAgICAgIGZ1bmN0aW9uIChkLCBiKSB7IGZvciAodmFyIHAgaW4gYikgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChiLCBwKSkgZFtwXSA9IGJbcF07IH07XG4gICAgICAgIHJldHVybiBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgIH07XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChkLCBiKSB7XG4gICAgICAgIGlmICh0eXBlb2YgYiAhPT0gXCJmdW5jdGlvblwiICYmIGIgIT09IG51bGwpXG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2xhc3MgZXh0ZW5kcyB2YWx1ZSBcIiArIFN0cmluZyhiKSArIFwiIGlzIG5vdCBhIGNvbnN0cnVjdG9yIG9yIG51bGxcIik7XG4gICAgICAgIGV4dGVuZFN0YXRpY3MoZCwgYik7XG4gICAgICAgIGZ1bmN0aW9uIF9fKCkgeyB0aGlzLmNvbnN0cnVjdG9yID0gZDsgfVxuICAgICAgICBkLnByb3RvdHlwZSA9IGIgPT09IG51bGwgPyBPYmplY3QuY3JlYXRlKGIpIDogKF9fLnByb3RvdHlwZSA9IGIucHJvdG90eXBlLCBuZXcgX18oKSk7XG4gICAgfTtcbn0pKCk7XG52YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG52YXIgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5ID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkobmFtZSwgdHJhY2spIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy50cmFjayA9IHRyYWNrO1xuICAgIH1cbiAgICBBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLmlzU3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMudHJhY2suZ2V0Q2FwYWJpbGl0aWVzKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRoaXMubmFtZSBpbiB0aGlzLnRyYWNrLmdldENhcGFiaWxpdGllcygpO1xuICAgIH07XG4gICAgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5hcHBseSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICB2YXIgY29uc3RyYWludCA9IHt9O1xuICAgICAgICBjb25zdHJhaW50W3RoaXMubmFtZV0gPSB2YWx1ZTtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnRzID0geyBhZHZhbmNlZDogW2NvbnN0cmFpbnRdIH07XG4gICAgICAgIHJldHVybiB0aGlzLnRyYWNrLmFwcGx5Q29uc3RyYWludHMoY29uc3RyYWludHMpO1xuICAgIH07XG4gICAgQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS52YWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHNldHRpbmdzID0gdGhpcy50cmFjay5nZXRTZXR0aW5ncygpO1xuICAgICAgICBpZiAodGhpcy5uYW1lIGluIHNldHRpbmdzKSB7XG4gICAgICAgICAgICB2YXIgc2V0dGluZ1ZhbHVlID0gc2V0dGluZ3NbdGhpcy5uYW1lXTtcbiAgICAgICAgICAgIHJldHVybiBzZXR0aW5nVmFsdWU7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfTtcbiAgICByZXR1cm4gQWJzdHJhY3RDYW1lcmFDYXBhYmlsaXR5O1xufSgpKTtcbnZhciBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eSA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5KG5hbWUsIHRyYWNrKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBuYW1lLCB0cmFjaykgfHwgdGhpcztcbiAgICB9XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLm1pbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2FwYWJpbGl0aWVzKCkubWluO1xuICAgIH07XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLm1heCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0Q2FwYWJpbGl0aWVzKCkubWF4O1xuICAgIH07XG4gICAgQWJzdHJhY3RSYW5nZUNhbWVyYUNhcGFiaWxpdHkucHJvdG90eXBlLnN0ZXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldENhcGFiaWxpdGllcygpLnN0ZXA7XG4gICAgfTtcbiAgICBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUuYXBwbHkgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgdmFyIGNvbnN0cmFpbnQgPSB7fTtcbiAgICAgICAgY29uc3RyYWludFt0aGlzLm5hbWVdID0gdmFsdWU7XG4gICAgICAgIHZhciBjb25zdHJhaW50cyA9IHsgYWR2YW5jZWQ6IFtjb25zdHJhaW50XSB9O1xuICAgICAgICByZXR1cm4gdGhpcy50cmFjay5hcHBseUNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzKTtcbiAgICB9O1xuICAgIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5LnByb3RvdHlwZS5nZXRDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmFpbElmTm90U3VwcG9ydGVkKCk7XG4gICAgICAgIHZhciBjYXBhYmlsaXRpZXMgPSB0aGlzLnRyYWNrLmdldENhcGFiaWxpdGllcygpO1xuICAgICAgICB2YXIgY2FwYWJpbGl0eSA9IGNhcGFiaWxpdGllc1t0aGlzLm5hbWVdO1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbWluOiBjYXBhYmlsaXR5Lm1pbixcbiAgICAgICAgICAgIG1heDogY2FwYWJpbGl0eS5tYXgsXG4gICAgICAgICAgICBzdGVwOiBjYXBhYmlsaXR5LnN0ZXAsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBBYnN0cmFjdFJhbmdlQ2FtZXJhQ2FwYWJpbGl0eS5wcm90b3R5cGUuZmFpbElmTm90U3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMuaXNTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiXCIuY29uY2F0KHRoaXMubmFtZSwgXCIgY2FwYWJpbGl0eSBub3Qgc3VwcG9ydGVkXCIpKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5O1xufShBYnN0cmFjdENhbWVyYUNhcGFiaWxpdHkpKTtcbnZhciBab29tRmVhdHVyZUltcGwgPSAoZnVuY3Rpb24gKF9zdXBlcikge1xuICAgIF9fZXh0ZW5kcyhab29tRmVhdHVyZUltcGwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gWm9vbUZlYXR1cmVJbXBsKHRyYWNrKSB7XG4gICAgICAgIHJldHVybiBfc3VwZXIuY2FsbCh0aGlzLCBcInpvb21cIiwgdHJhY2spIHx8IHRoaXM7XG4gICAgfVxuICAgIHJldHVybiBab29tRmVhdHVyZUltcGw7XG59KEFic3RyYWN0UmFuZ2VDYW1lcmFDYXBhYmlsaXR5KSk7XG52YXIgVG9yY2hGZWF0dXJlSW1wbCA9IChmdW5jdGlvbiAoX3N1cGVyKSB7XG4gICAgX19leHRlbmRzKFRvcmNoRmVhdHVyZUltcGwsIF9zdXBlcik7XG4gICAgZnVuY3Rpb24gVG9yY2hGZWF0dXJlSW1wbCh0cmFjaykge1xuICAgICAgICByZXR1cm4gX3N1cGVyLmNhbGwodGhpcywgXCJ0b3JjaFwiLCB0cmFjaykgfHwgdGhpcztcbiAgICB9XG4gICAgcmV0dXJuIFRvcmNoRmVhdHVyZUltcGw7XG59KEFic3RyYWN0Q2FtZXJhQ2FwYWJpbGl0eSkpO1xudmFyIENhbWVyYUNhcGFiaWxpdGllc0ltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUNhcGFiaWxpdGllc0ltcGwodHJhY2spIHtcbiAgICAgICAgdGhpcy50cmFjayA9IHRyYWNrO1xuICAgIH1cbiAgICBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsLnByb3RvdHlwZS56b29tRmVhdHVyZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBab29tRmVhdHVyZUltcGwodGhpcy50cmFjayk7XG4gICAgfTtcbiAgICBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsLnByb3RvdHlwZS50b3JjaEZlYXR1cmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBuZXcgVG9yY2hGZWF0dXJlSW1wbCh0aGlzLnRyYWNrKTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsO1xufSgpKTtcbnZhciBSZW5kZXJlZENhbWVyYUltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFJlbmRlcmVkQ2FtZXJhSW1wbChwYXJlbnRFbGVtZW50LCBtZWRpYVN0cmVhbSwgY2FsbGJhY2tzKSB7XG4gICAgICAgIHRoaXMuaXNDbG9zZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5wYXJlbnRFbGVtZW50ID0gcGFyZW50RWxlbWVudDtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgICAgICB0aGlzLmNhbGxiYWNrcyA9IGNhbGxiYWNrcztcbiAgICAgICAgdGhpcy5zdXJmYWNlID0gdGhpcy5jcmVhdGVWaWRlb0VsZW1lbnQodGhpcy5wYXJlbnRFbGVtZW50LmNsaWVudFdpZHRoKTtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmQodGhpcy5zdXJmYWNlKTtcbiAgICB9XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5jcmVhdGVWaWRlb0VsZW1lbnQgPSBmdW5jdGlvbiAod2lkdGgpIHtcbiAgICAgICAgdmFyIHZpZGVvRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJ2aWRlb1wiKTtcbiAgICAgICAgdmlkZW9FbGVtZW50LnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQod2lkdGgsIFwicHhcIik7XG4gICAgICAgIHZpZGVvRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgICB2aWRlb0VsZW1lbnQubXV0ZWQgPSB0cnVlO1xuICAgICAgICB2aWRlb0VsZW1lbnQuc2V0QXR0cmlidXRlKFwibXV0ZWRcIiwgXCJ0cnVlXCIpO1xuICAgICAgICB2aWRlb0VsZW1lbnQucGxheXNJbmxpbmUgPSB0cnVlO1xuICAgICAgICByZXR1cm4gdmlkZW9FbGVtZW50O1xuICAgIH07XG4gICAgUmVuZGVyZWRDYW1lcmFJbXBsLnByb3RvdHlwZS5zZXR1cFN1cmZhY2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHRoaXMuc3VyZmFjZS5vbmFib3J0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgXCJSZW5kZXJlZENhbWVyYUltcGwgdmlkZW8gc3VyZmFjZSBvbmFib3J0KCkgY2FsbGVkXCI7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc3VyZmFjZS5vbmVycm9yID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdGhyb3cgXCJSZW5kZXJlZENhbWVyYUltcGwgdmlkZW8gc3VyZmFjZSBvbmVycm9yKCkgY2FsbGVkXCI7XG4gICAgICAgIH07XG4gICAgICAgIHZhciBvblZpZGVvU3RhcnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgdmlkZW9XaWR0aCA9IF90aGlzLnN1cmZhY2UuY2xpZW50V2lkdGg7XG4gICAgICAgICAgICB2YXIgdmlkZW9IZWlnaHQgPSBfdGhpcy5zdXJmYWNlLmNsaWVudEhlaWdodDtcbiAgICAgICAgICAgIF90aGlzLmNhbGxiYWNrcy5vblJlbmRlclN1cmZhY2VSZWFkeSh2aWRlb1dpZHRoLCB2aWRlb0hlaWdodCk7XG4gICAgICAgICAgICBfdGhpcy5zdXJmYWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJwbGF5aW5nXCIsIG9uVmlkZW9TdGFydCk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc3VyZmFjZS5hZGRFdmVudExpc3RlbmVyKFwicGxheWluZ1wiLCBvblZpZGVvU3RhcnQpO1xuICAgICAgICB0aGlzLnN1cmZhY2Uuc3JjT2JqZWN0ID0gdGhpcy5tZWRpYVN0cmVhbTtcbiAgICAgICAgdGhpcy5zdXJmYWNlLnBsYXkoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgbWVkaWFTdHJlYW0sIG9wdGlvbnMsIGNhbGxiYWNrcykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgcmVuZGVyZWRDYW1lcmEsIGFzcGVjdFJhdGlvQ29uc3RyYWludDtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlbmRlcmVkQ2FtZXJhID0gbmV3IFJlbmRlcmVkQ2FtZXJhSW1wbChwYXJlbnRFbGVtZW50LCBtZWRpYVN0cmVhbSwgY2FsbGJhY2tzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghb3B0aW9ucy5hc3BlY3RSYXRpbykgcmV0dXJuIFszLCAyXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzcGVjdFJhdGlvQ29uc3RyYWludCA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3BlY3RSYXRpbzogb3B0aW9ucy5hc3BlY3RSYXRpb1xuICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgcmVuZGVyZWRDYW1lcmEuZ2V0Rmlyc3RUcmFja09yRmFpbCgpLmFwcGx5Q29uc3RyYWludHMoYXNwZWN0UmF0aW9Db25zdHJhaW50KV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLmxhYmVsID0gMjtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVuZGVyZWRDYW1lcmEuc2V0dXBTdXJmYWNlKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIHJlbmRlcmVkQ2FtZXJhXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmZhaWxJZkNsb3NlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNDbG9zZWQpIHtcbiAgICAgICAgICAgIHRocm93IFwiVGhlIFJlbmRlcmVkQ2FtZXJhIGhhcyBhbHJlYWR5IGJlZW4gY2xvc2VkLlwiO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldEZpcnN0VHJhY2tPckZhaWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmFpbElmQ2xvc2VkKCk7XG4gICAgICAgIGlmICh0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk5vIHZpZGVvIHRyYWNrcyBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKClbMF07XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLnBhdXNlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZhaWxJZkNsb3NlZCgpO1xuICAgICAgICB0aGlzLnN1cmZhY2UucGF1c2UoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUucmVzdW1lID0gZnVuY3Rpb24gKG9uUmVzdW1lQ2FsbGJhY2spIHtcbiAgICAgICAgdGhpcy5mYWlsSWZDbG9zZWQoKTtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdmFyIG9uVmlkZW9SZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KG9uUmVzdW1lQ2FsbGJhY2ssIDIwMCk7XG4gICAgICAgICAgICAkdGhpcy5zdXJmYWNlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJwbGF5aW5nXCIsIG9uVmlkZW9SZXN1bWUpO1xuICAgICAgICB9O1xuICAgICAgICB0aGlzLnN1cmZhY2UuYWRkRXZlbnRMaXN0ZW5lcihcInBsYXlpbmdcIiwgb25WaWRlb1Jlc3VtZSk7XG4gICAgICAgIHRoaXMuc3VyZmFjZS5wbGF5KCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmlzUGF1c2VkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZhaWxJZkNsb3NlZCgpO1xuICAgICAgICByZXR1cm4gdGhpcy5zdXJmYWNlLnBhdXNlZDtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuZ2V0U3VyZmFjZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5mYWlsSWZDbG9zZWQoKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3VyZmFjZTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuZ2V0UnVubmluZ1RyYWNrQ2FwYWJpbGl0aWVzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdFRyYWNrT3JGYWlsKCkuZ2V0Q2FwYWJpbGl0aWVzKCk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja1NldHRpbmdzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRGaXJzdFRyYWNrT3JGYWlsKCkuZ2V0U2V0dGluZ3MoKTtcbiAgICB9O1xuICAgIFJlbmRlcmVkQ2FtZXJhSW1wbC5wcm90b3R5cGUuYXBwbHlWaWRlb0NvbnN0cmFpbnRzID0gZnVuY3Rpb24gKGNvbnN0cmFpbnRzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBpZiAoXCJhc3BlY3RSYXRpb1wiIGluIGNvbnN0cmFpbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiQ2hhbmdpbmcgJ2FzcGVjdFJhdGlvJyBpbiBydW4tdGltZSBpcyBub3QgeWV0IHN1cHBvcnRlZC5cIjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIFsyLCB0aGlzLmdldEZpcnN0VHJhY2tPckZhaWwoKS5hcHBseUNvbnN0cmFpbnRzKGNvbnN0cmFpbnRzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmNsb3NlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc0Nsb3NlZCkge1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgXykge1xuICAgICAgICAgICAgdmFyIHRyYWNrcyA9ICR0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gICAgICAgICAgICB2YXIgdHJhY2tzVG9DbG9zZSA9IHRyYWNrcy5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgdHJhY2tzQ2xvc2VkID0gMDtcbiAgICAgICAgICAgICR0aGlzLm1lZGlhU3RyZWFtLmdldFZpZGVvVHJhY2tzKCkuZm9yRWFjaChmdW5jdGlvbiAodmlkZW9UcmFjaykge1xuICAgICAgICAgICAgICAgICR0aGlzLm1lZGlhU3RyZWFtLnJlbW92ZVRyYWNrKHZpZGVvVHJhY2spO1xuICAgICAgICAgICAgICAgIHZpZGVvVHJhY2suc3RvcCgpO1xuICAgICAgICAgICAgICAgICsrdHJhY2tzQ2xvc2VkO1xuICAgICAgICAgICAgICAgIGlmICh0cmFja3NDbG9zZWQgPj0gdHJhY2tzVG9DbG9zZSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5pc0Nsb3NlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLnBhcmVudEVsZW1lbnQucmVtb3ZlQ2hpbGQoJHRoaXMuc3VyZmFjZSk7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBSZW5kZXJlZENhbWVyYUltcGwucHJvdG90eXBlLmdldENhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBDYW1lcmFDYXBhYmlsaXRpZXNJbXBsKHRoaXMuZ2V0Rmlyc3RUcmFja09yRmFpbCgpKTtcbiAgICB9O1xuICAgIHJldHVybiBSZW5kZXJlZENhbWVyYUltcGw7XG59KCkpO1xudmFyIENhbWVyYUltcGwgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUltcGwobWVkaWFTdHJlYW0pIHtcbiAgICAgICAgdGhpcy5tZWRpYVN0cmVhbSA9IG1lZGlhU3RyZWFtO1xuICAgIH1cbiAgICBDYW1lcmFJbXBsLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgb3B0aW9ucywgY2FsbGJhY2tzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gWzIsIFJlbmRlcmVkQ2FtZXJhSW1wbC5jcmVhdGUocGFyZW50RWxlbWVudCwgdGhpcy5tZWRpYVN0cmVhbSwgb3B0aW9ucywgY2FsbGJhY2tzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYW1lcmFJbXBsLmNyZWF0ZSA9IGZ1bmN0aW9uICh2aWRlb0NvbnN0cmFpbnRzKSB7XG4gICAgICAgIHJldHVybiBfX2F3YWl0ZXIodGhpcywgdm9pZCAwLCB2b2lkIDAsIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjb25zdHJhaW50cywgbWVkaWFTdHJlYW07XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChfYS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW5hdmlnYXRvci5tZWRpYURldmljZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBcIm5hdmlnYXRvci5tZWRpYURldmljZXMgbm90IHN1cHBvcnRlZFwiO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3RyYWludHMgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYXVkaW86IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZGVvOiB2aWRlb0NvbnN0cmFpbnRzXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYShjb25zdHJhaW50cyldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgbmV3IENhbWVyYUltcGwobWVkaWFTdHJlYW0pXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhSW1wbDtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFJbXBsIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jb3JlLWltcGwuanMubWFwIiwidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgQ2FtZXJhSW1wbCB9IGZyb20gXCIuL2NvcmUtaW1wbFwiO1xudmFyIENhbWVyYUZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYUZhY3RvcnkoKSB7XG4gICAgfVxuICAgIENhbWVyYUZhY3RvcnkuZmFpbElmTm90U3VwcG9ydGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFuYXZpZ2F0b3IubWVkaWFEZXZpY2VzKSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwibmF2aWdhdG9yLm1lZGlhRGV2aWNlcyBub3Qgc3VwcG9ydGVkXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybiBbMiwgbmV3IENhbWVyYUZhY3RvcnkoKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBDYW1lcmFGYWN0b3J5LnByb3RvdHlwZS5jcmVhdGUgPSBmdW5jdGlvbiAodmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICByZXR1cm4gX19hd2FpdGVyKHRoaXMsIHZvaWQgMCwgdm9pZCAwLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICByZXR1cm4gX19nZW5lcmF0b3IodGhpcywgZnVuY3Rpb24gKF9hKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIFsyLCBDYW1lcmFJbXBsLmNyZWF0ZSh2aWRlb0NvbnN0cmFpbnRzKV07XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhRmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFGYWN0b3J5IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1mYWN0b3JpZXMuanMubWFwIiwidmFyIF9fYXdhaXRlciA9ICh0aGlzICYmIHRoaXMuX19hd2FpdGVyKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gICAgZnVuY3Rpb24gYWRvcHQodmFsdWUpIHsgcmV0dXJuIHZhbHVlIGluc3RhbmNlb2YgUCA/IHZhbHVlIDogbmV3IFAoZnVuY3Rpb24gKHJlc29sdmUpIHsgcmVzb2x2ZSh2YWx1ZSk7IH0pOyB9XG4gICAgcmV0dXJuIG5ldyAoUCB8fCAoUCA9IFByb21pc2UpKShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gcmVqZWN0ZWQodmFsdWUpIHsgdHJ5IHsgc3RlcChnZW5lcmF0b3JbXCJ0aHJvd1wiXSh2YWx1ZSkpOyB9IGNhdGNoIChlKSB7IHJlamVjdChlKTsgfSB9XG4gICAgICAgIGZ1bmN0aW9uIHN0ZXAocmVzdWx0KSB7IHJlc3VsdC5kb25lID8gcmVzb2x2ZShyZXN1bHQudmFsdWUpIDogYWRvcHQocmVzdWx0LnZhbHVlKS50aGVuKGZ1bGZpbGxlZCwgcmVqZWN0ZWQpOyB9XG4gICAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgICB9KTtcbn07XG52YXIgX19nZW5lcmF0b3IgPSAodGhpcyAmJiB0aGlzLl9fZ2VuZXJhdG9yKSB8fCBmdW5jdGlvbiAodGhpc0FyZywgYm9keSkge1xuICAgIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gICAgcmV0dXJuIGcgPSB7IG5leHQ6IHZlcmIoMCksIFwidGhyb3dcIjogdmVyYigxKSwgXCJyZXR1cm5cIjogdmVyYigyKSB9LCB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgKGdbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uKCkgeyByZXR1cm4gdGhpczsgfSksIGc7XG4gICAgZnVuY3Rpb24gdmVyYihuKSB7IHJldHVybiBmdW5jdGlvbiAodikgeyByZXR1cm4gc3RlcChbbiwgdl0pOyB9OyB9XG4gICAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgICBpZiAoZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkdlbmVyYXRvciBpcyBhbHJlYWR5IGV4ZWN1dGluZy5cIik7XG4gICAgICAgIHdoaWxlIChnICYmIChnID0gMCwgb3BbMF0gJiYgKF8gPSAwKSksIF8pIHRyeSB7XG4gICAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgICBpZiAoeSA9IDAsIHQpIG9wID0gW29wWzBdICYgMiwgdC52YWx1ZV07XG4gICAgICAgICAgICBzd2l0Y2ggKG9wWzBdKSB7XG4gICAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OiBfLmxhYmVsKys7IHJldHVybiB7IHZhbHVlOiBvcFsxXSwgZG9uZTogZmFsc2UgfTtcbiAgICAgICAgICAgICAgICBjYXNlIDU6IF8ubGFiZWwrKzsgeSA9IG9wWzFdOyBvcCA9IFswXTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIGlmICghKHQgPSBfLnRyeXMsIHQgPSB0Lmxlbmd0aCA+IDAgJiYgdFt0Lmxlbmd0aCAtIDFdKSAmJiAob3BbMF0gPT09IDYgfHwgb3BbMF0gPT09IDIpKSB7IF8gPSAwOyBjb250aW51ZTsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDYgJiYgXy5sYWJlbCA8IHRbMV0pIHsgXy5sYWJlbCA9IHRbMV07IHQgPSBvcDsgYnJlYWs7IH1cbiAgICAgICAgICAgICAgICAgICAgaWYgKHQgJiYgXy5sYWJlbCA8IHRbMl0pIHsgXy5sYWJlbCA9IHRbMl07IF8ub3BzLnB1c2gob3ApOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICAgIF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgICAgfSBjYXRjaCAoZSkgeyBvcCA9IFs2LCBlXTsgeSA9IDA7IH0gZmluYWxseSB7IGYgPSB0ID0gMDsgfVxuICAgICAgICBpZiAob3BbMF0gJiA1KSB0aHJvdyBvcFsxXTsgcmV0dXJuIHsgdmFsdWU6IG9wWzBdID8gb3BbMV0gOiB2b2lkIDAsIGRvbmU6IHRydWUgfTtcbiAgICB9XG59O1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTdHJpbmdzIH0gZnJvbSBcIi4uL3N0cmluZ3NcIjtcbnZhciBDYW1lcmFSZXRyaWV2ZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVJldHJpZXZlcigpIHtcbiAgICB9XG4gICAgQ2FtZXJhUmV0cmlldmVyLnJldHJpZXZlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAobmF2aWdhdG9yLm1lZGlhRGV2aWNlcykge1xuICAgICAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhRGV2aWNlcygpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBtc3QgPSBNZWRpYVN0cmVhbVRyYWNrO1xuICAgICAgICBpZiAoTWVkaWFTdHJlYW1UcmFjayAmJiBtc3QuZ2V0U291cmNlcykge1xuICAgICAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhU3RyZWFtVHJhY2soKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gQ2FtZXJhUmV0cmlldmVyLnJlamVjdFdpdGhFcnJvcigpO1xuICAgIH07XG4gICAgQ2FtZXJhUmV0cmlldmVyLnJlamVjdFdpdGhFcnJvciA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGVycm9yTWVzc2FnZSA9IEh0bWw1UXJjb2RlU3RyaW5ncy51bmFibGVUb1F1ZXJ5U3VwcG9ydGVkRGV2aWNlcygpO1xuICAgICAgICBpZiAoIUNhbWVyYVJldHJpZXZlci5pc0h0dHBzT3JMb2NhbGhvc3QoKSkge1xuICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gSHRtbDVRcmNvZGVTdHJpbmdzLmluc2VjdXJlQ29udGV4dENhbWVyYVF1ZXJ5RXJyb3IoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZWplY3QoZXJyb3JNZXNzYWdlKTtcbiAgICB9O1xuICAgIENhbWVyYVJldHJpZXZlci5pc0h0dHBzT3JMb2NhbGhvc3QgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmIChsb2NhdGlvbi5wcm90b2NvbCA9PT0gXCJodHRwczpcIikge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIGhvc3QgPSBsb2NhdGlvbi5ob3N0LnNwbGl0KFwiOlwiKVswXTtcbiAgICAgICAgcmV0dXJuIGhvc3QgPT09IFwiMTI3LjAuMC4xXCIgfHwgaG9zdCA9PT0gXCJsb2NhbGhvc3RcIjtcbiAgICB9O1xuICAgIENhbWVyYVJldHJpZXZlci5nZXRDYW1lcmFzRnJvbU1lZGlhRGV2aWNlcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGNsb3NlQWN0aXZlU3RyZWFtcywgbWVkaWFTdHJlYW0sIGRldmljZXMsIHJlc3VsdHMsIF9pLCBkZXZpY2VzXzEsIGRldmljZTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICAgICAgICAgIGNsb3NlQWN0aXZlU3RyZWFtcyA9IGZ1bmN0aW9uIChzdHJlYW0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgdHJhY2tzID0gc3RyZWFtLmdldFZpZGVvVHJhY2tzKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yICh2YXIgX2kgPSAwLCB0cmFja3NfMSA9IHRyYWNrczsgX2kgPCB0cmFja3NfMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHRyYWNrID0gdHJhY2tzXzFbX2ldO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cmFjay5lbmFibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRyYWNrLnN0b3AoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyZWFtLnJlbW92ZVRyYWNrKHRyYWNrKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmdldFVzZXJNZWRpYSh7IGF1ZGlvOiBmYWxzZSwgdmlkZW86IHRydWUgfSldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBtZWRpYVN0cmVhbSA9IF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbNCwgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VzID0gX2Euc2VudCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChfaSA9IDAsIGRldmljZXNfMSA9IGRldmljZXM7IF9pIDwgZGV2aWNlc18xLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZSA9IGRldmljZXNfMVtfaV07XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRldmljZS5raW5kID09PSBcInZpZGVvaW5wdXRcIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHRzLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IGRldmljZS5kZXZpY2VJZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxhYmVsOiBkZXZpY2UubGFiZWxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgY2xvc2VBY3RpdmVTdHJlYW1zKG1lZGlhU3RyZWFtKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgcmVzdWx0c107XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgQ2FtZXJhUmV0cmlldmVyLmdldENhbWVyYXNGcm9tTWVkaWFTdHJlYW1UcmFjayA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCBfKSB7XG4gICAgICAgICAgICB2YXIgY2FsbGJhY2sgPSBmdW5jdGlvbiAoc291cmNlSW5mb3MpIHtcbiAgICAgICAgICAgICAgICB2YXIgcmVzdWx0cyA9IFtdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIF9pID0gMCwgc291cmNlSW5mb3NfMSA9IHNvdXJjZUluZm9zOyBfaSA8IHNvdXJjZUluZm9zXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzb3VyY2VJbmZvID0gc291cmNlSW5mb3NfMVtfaV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChzb3VyY2VJbmZvLmtpbmQgPT09IFwidmlkZW9cIikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0cy5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZDogc291cmNlSW5mby5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYWJlbDogc291cmNlSW5mby5sYWJlbFxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmVzb2x2ZShyZXN1bHRzKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIgbXN0ID0gTWVkaWFTdHJlYW1UcmFjaztcbiAgICAgICAgICAgIG1zdC5nZXRTb3VyY2VzKGNhbGxiYWNrKTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICByZXR1cm4gQ2FtZXJhUmV0cmlldmVyO1xufSgpKTtcbmV4cG9ydCB7IENhbWVyYVJldHJpZXZlciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cmV0cmlldmVyLmpzLm1hcCIsImV4cG9ydCB2YXIgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGU7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlKSB7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbXCJVTktOT1dOXCJdID0gMF0gPSBcIlVOS05PV05cIjtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZVtIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZVtcIk5PVF9TVEFSVEVEXCJdID0gMV0gPSBcIk5PVF9TVEFSVEVEXCI7XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGVbXCJTQ0FOTklOR1wiXSA9IDJdID0gXCJTQ0FOTklOR1wiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW0h0bWw1UXJjb2RlU2Nhbm5lclN0YXRlW1wiUEFVU0VEXCJdID0gM10gPSBcIlBBVVNFRFwiO1xufSkoSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUgfHwgKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlID0ge30pKTtcbnZhciBTdGF0ZU1hbmFnZXJJbXBsID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBTdGF0ZU1hbmFnZXJJbXBsKCkge1xuICAgICAgICB0aGlzLnN0YXRlID0gSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuTk9UX1NUQVJURUQ7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOO1xuICAgIH1cbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5kaXJlY3RUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHRoaXMuZmFpbElmVHJhbnNpdGlvbk9uZ29pbmcoKTtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVRyYW5zaXRpb24obmV3U3RhdGUpO1xuICAgICAgICB0aGlzLnN0YXRlID0gbmV3U3RhdGU7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5zdGFydFRyYW5zaXRpb24gPSBmdW5jdGlvbiAobmV3U3RhdGUpIHtcbiAgICAgICAgdGhpcy5mYWlsSWZUcmFuc2l0aW9uT25nb2luZygpO1xuICAgICAgICB0aGlzLnZhbGlkYXRlVHJhbnNpdGlvbihuZXdTdGF0ZSk7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBuZXdTdGF0ZTtcbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5leGVjdXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5vbkdvaW5nVHJhbnNhY3Rpb25OZXdTdGF0ZVxuICAgICAgICAgICAgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlVOS05PV04pIHtcbiAgICAgICAgICAgIHRocm93IFwiVHJhbnNhY3Rpb24gaXMgYWxyZWFkeSBjYW5jZWxsZWQsIGNhbm5vdCBleGVjdXRlKCkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHRlbXBOZXdTdGF0ZSA9IHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGU7XG4gICAgICAgIHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGUgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOO1xuICAgICAgICB0aGlzLmRpcmVjdFRyYW5zaXRpb24odGVtcE5ld1N0YXRlKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlckltcGwucHJvdG90eXBlLmNhbmNlbCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGVcbiAgICAgICAgICAgID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlRyYW5zYWN0aW9uIGlzIGFscmVhZHkgY2FuY2VsbGVkLCBjYW5ub3QgY2FuY2VsKCkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vbkdvaW5nVHJhbnNhY3Rpb25OZXdTdGF0ZSA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlVOS05PV047XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGU7XG4gICAgfTtcbiAgICBTdGF0ZU1hbmFnZXJJbXBsLnByb3RvdHlwZS5mYWlsSWZUcmFuc2l0aW9uT25nb2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1RyYW5zYWN0aW9uTmV3U3RhdGVcbiAgICAgICAgICAgICE9PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCB0cmFuc2l0aW9uIHRvIGEgbmV3IHN0YXRlLCBhbHJlYWR5IHVuZGVyIHRyYW5zaXRpb25cIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VySW1wbC5wcm90b3R5cGUudmFsaWRhdGVUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHN3aXRjaCAodGhpcy5zdGF0ZSkge1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5VTktOT1dOOlxuICAgICAgICAgICAgICAgIHRocm93IFwiVHJhbnNpdGlvbiBmcm9tIHVua25vd24gaXMgbm90IGFsbG93ZWRcIjtcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuTk9UX1NUQVJURUQ6XG4gICAgICAgICAgICAgICAgdGhpcy5mYWlsSWZOZXdTdGF0ZUlzKG5ld1N0YXRlLCBbSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEXSk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HOlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5QQVVTRUQ6XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlckltcGwucHJvdG90eXBlLmZhaWxJZk5ld1N0YXRlSXMgPSBmdW5jdGlvbiAobmV3U3RhdGUsIGRpc2FsbG93ZWRTdGF0ZXNUb1RyYW5zaXRpb24pIHtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uXzEgPSBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uOyBfaSA8IGRpc2FsbG93ZWRTdGF0ZXNUb1RyYW5zaXRpb25fMS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBkaXNhbGxvd2VkU3RhdGUgPSBkaXNhbGxvd2VkU3RhdGVzVG9UcmFuc2l0aW9uXzFbX2ldO1xuICAgICAgICAgICAgaWYgKG5ld1N0YXRlID09PSBkaXNhbGxvd2VkU3RhdGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCB0cmFuc2l0aW9uIGZyb20gXCIuY29uY2F0KHRoaXMuc3RhdGUsIFwiIHRvIFwiKS5jb25jYXQobmV3U3RhdGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfTtcbiAgICByZXR1cm4gU3RhdGVNYW5hZ2VySW1wbDtcbn0oKSk7XG52YXIgU3RhdGVNYW5hZ2VyUHJveHkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFN0YXRlTWFuYWdlclByb3h5KHN0YXRlTWFuYWdlcikge1xuICAgICAgICB0aGlzLnN0YXRlTWFuYWdlciA9IHN0YXRlTWFuYWdlcjtcbiAgICB9XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLnN0YXJ0VHJhbnNpdGlvbiA9IGZ1bmN0aW9uIChuZXdTdGF0ZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZU1hbmFnZXIuc3RhcnRUcmFuc2l0aW9uKG5ld1N0YXRlKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5kaXJlY3RUcmFuc2l0aW9uID0gZnVuY3Rpb24gKG5ld1N0YXRlKSB7XG4gICAgICAgIHRoaXMuc3RhdGVNYW5hZ2VyLmRpcmVjdFRyYW5zaXRpb24obmV3U3RhdGUpO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLmdldFN0YXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zdGF0ZU1hbmFnZXIuZ2V0U3RhdGUoKTtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5jYW5TY2FuRmlsZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLmdldFN0YXRlKCkgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLk5PVF9TVEFSVEVEO1xuICAgIH07XG4gICAgU3RhdGVNYW5hZ2VyUHJveHkucHJvdG90eXBlLmlzU2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5nZXRTdGF0ZSgpICE9PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5OT1RfU1RBUlRFRDtcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5pc1N0cmljdGx5U2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN0YXRlTWFuYWdlci5nZXRTdGF0ZSgpID09PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5TQ0FOTklORztcbiAgICB9O1xuICAgIFN0YXRlTWFuYWdlclByb3h5LnByb3RvdHlwZS5pc1BhdXNlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyLmdldFN0YXRlKCkgPT09IEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlBBVVNFRDtcbiAgICB9O1xuICAgIHJldHVybiBTdGF0ZU1hbmFnZXJQcm94eTtcbn0oKSk7XG5leHBvcnQgeyBTdGF0ZU1hbmFnZXJQcm94eSB9O1xudmFyIFN0YXRlTWFuYWdlckZhY3RvcnkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFN0YXRlTWFuYWdlckZhY3RvcnkoKSB7XG4gICAgfVxuICAgIFN0YXRlTWFuYWdlckZhY3RvcnkuY3JlYXRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gbmV3IFN0YXRlTWFuYWdlclByb3h5KG5ldyBTdGF0ZU1hbmFnZXJJbXBsKCkpO1xuICAgIH07XG4gICAgcmV0dXJuIFN0YXRlTWFuYWdlckZhY3Rvcnk7XG59KCkpO1xuZXhwb3J0IHsgU3RhdGVNYW5hZ2VyRmFjdG9yeSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3RhdGUtbWFuYWdlci5qcy5tYXAiLCJ2YXIgX19leHRlbmRzID0gKHRoaXMgJiYgdGhpcy5fX2V4dGVuZHMpIHx8IChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGV4dGVuZFN0YXRpY3MgPSBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBleHRlbmRTdGF0aWNzID0gT2JqZWN0LnNldFByb3RvdHlwZU9mIHx8XG4gICAgICAgICAgICAoeyBfX3Byb3RvX186IFtdIH0gaW5zdGFuY2VvZiBBcnJheSAmJiBmdW5jdGlvbiAoZCwgYikgeyBkLl9fcHJvdG9fXyA9IGI7IH0pIHx8XG4gICAgICAgICAgICBmdW5jdGlvbiAoZCwgYikgeyBmb3IgKHZhciBwIGluIGIpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoYiwgcCkpIGRbcF0gPSBiW3BdOyB9O1xuICAgICAgICByZXR1cm4gZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgICB9O1xuICAgIHJldHVybiBmdW5jdGlvbiAoZCwgYikge1xuICAgICAgICBpZiAodHlwZW9mIGIgIT09IFwiZnVuY3Rpb25cIiAmJiBiICE9PSBudWxsKVxuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNsYXNzIGV4dGVuZHMgdmFsdWUgXCIgKyBTdHJpbmcoYikgKyBcIiBpcyBub3QgYSBjb25zdHJ1Y3RvciBvciBudWxsXCIpO1xuICAgICAgICBleHRlbmRTdGF0aWNzKGQsIGIpO1xuICAgICAgICBmdW5jdGlvbiBfXygpIHsgdGhpcy5jb25zdHJ1Y3RvciA9IGQ7IH1cbiAgICAgICAgZC5wcm90b3R5cGUgPSBiID09PSBudWxsID8gT2JqZWN0LmNyZWF0ZShiKSA6IChfXy5wcm90b3R5cGUgPSBiLnByb3RvdHlwZSwgbmV3IF9fKCkpO1xuICAgIH07XG59KSgpO1xuaW1wb3J0IHsgQmFzZUxvZ2dnZXIsIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeSwgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnksIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cywgaXNWYWxpZEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cywgSHRtbDVRcmNvZGVDb25zdGFudHMsIGlzTnVsbE9yVW5kZWZpbmVkIH0gZnJvbSBcIi4vY29yZVwiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTdHJpbmdzIH0gZnJvbSBcIi4vc3RyaW5nc1wiO1xuaW1wb3J0IHsgVmlkZW9Db25zdHJhaW50c1V0aWwgfSBmcm9tIFwiLi91dGlsc1wiO1xuaW1wb3J0IHsgSHRtbDVRcmNvZGVTaGltIH0gZnJvbSBcIi4vY29kZS1kZWNvZGVyXCI7XG5pbXBvcnQgeyBDYW1lcmFGYWN0b3J5IH0gZnJvbSBcIi4vY2FtZXJhL2ZhY3Rvcmllc1wiO1xuaW1wb3J0IHsgQ2FtZXJhUmV0cmlldmVyIH0gZnJvbSBcIi4vY2FtZXJhL3JldHJpZXZlclwiO1xuaW1wb3J0IHsgU3RhdGVNYW5hZ2VyRmFjdG9yeSwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUgfSBmcm9tIFwiLi9zdGF0ZS1tYW5hZ2VyXCI7XG52YXIgQ29uc3RhbnRzID0gKGZ1bmN0aW9uIChfc3VwZXIpIHtcbiAgICBfX2V4dGVuZHMoQ29uc3RhbnRzLCBfc3VwZXIpO1xuICAgIGZ1bmN0aW9uIENvbnN0YW50cygpIHtcbiAgICAgICAgcmV0dXJuIF9zdXBlciAhPT0gbnVsbCAmJiBfc3VwZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKSB8fCB0aGlzO1xuICAgIH1cbiAgICBDb25zdGFudHMuREVGQVVMVF9XSURUSCA9IDMwMDtcbiAgICBDb25zdGFudHMuREVGQVVMVF9XSURUSF9PRkZTRVQgPSAyO1xuICAgIENvbnN0YW50cy5GSUxFX1NDQU5fTUlOX0hFSUdIVCA9IDMwMDtcbiAgICBDb25zdGFudHMuRklMRV9TQ0FOX0hJRERFTl9DQU5WQVNfUEFERElORyA9IDEwMDtcbiAgICBDb25zdGFudHMuTUlOX1FSX0JPWF9TSVpFID0gNTA7XG4gICAgQ29uc3RhbnRzLlNIQURFRF9MRUZUID0gMTtcbiAgICBDb25zdGFudHMuU0hBREVEX1JJR0hUID0gMjtcbiAgICBDb25zdGFudHMuU0hBREVEX1RPUCA9IDM7XG4gICAgQ29uc3RhbnRzLlNIQURFRF9CT1RUT00gPSA0O1xuICAgIENvbnN0YW50cy5TSEFERURfUkVHSU9OX0VMRU1FTlRfSUQgPSBcInFyLXNoYWRlZC1yZWdpb25cIjtcbiAgICBDb25zdGFudHMuVkVSQk9TRSA9IGZhbHNlO1xuICAgIENvbnN0YW50cy5CT1JERVJfU0hBREVSX0RFRkFVTFRfQ09MT1IgPSBcIiNmZmZmZmZcIjtcbiAgICBDb25zdGFudHMuQk9SREVSX1NIQURFUl9NQVRDSF9DT0xPUiA9IFwicmdiKDkwLCAxOTMsIDU2KVwiO1xuICAgIHJldHVybiBDb25zdGFudHM7XG59KEh0bWw1UXJjb2RlQ29uc3RhbnRzKSk7XG52YXIgSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyhjb25maWcsIGxvZ2dlcikge1xuICAgICAgICB0aGlzLmxvZ2dlciA9IGxvZ2dlcjtcbiAgICAgICAgdGhpcy5mcHMgPSBDb25zdGFudHMuU0NBTl9ERUZBVUxUX0ZQUztcbiAgICAgICAgaWYgKCFjb25maWcpIHtcbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZUZsaXAgPSBDb25zdGFudHMuREVGQVVMVF9ESVNBQkxFX0ZMSVA7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnLmZwcykge1xuICAgICAgICAgICAgICAgIHRoaXMuZnBzID0gY29uZmlnLmZwcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoaXMuZGlzYWJsZUZsaXAgPSBjb25maWcuZGlzYWJsZUZsaXAgPT09IHRydWU7XG4gICAgICAgICAgICB0aGlzLnFyYm94ID0gY29uZmlnLnFyYm94O1xuICAgICAgICAgICAgdGhpcy5hc3BlY3RSYXRpbyA9IGNvbmZpZy5hc3BlY3RSYXRpbztcbiAgICAgICAgICAgIHRoaXMudmlkZW9Db25zdHJhaW50cyA9IGNvbmZpZy52aWRlb0NvbnN0cmFpbnRzO1xuICAgICAgICB9XG4gICAgfVxuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcucHJvdG90eXBlLmlzTWVkaWFTdHJlYW1Db25zdHJhaW50c1ZhbGlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAoIXRoaXMudmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJFbXB0eSB2aWRlb0NvbnN0cmFpbnRzXCIsIHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBWaWRlb0NvbnN0cmFpbnRzVXRpbC5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCh0aGlzLnZpZGVvQ29uc3RyYWludHMsIHRoaXMubG9nZ2VyKTtcbiAgICB9O1xuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcucHJvdG90eXBlLmlzU2hhZGVkQm94RW5hYmxlZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuICFpc051bGxPclVuZGVmaW5lZCh0aGlzLnFyYm94KTtcbiAgICB9O1xuICAgIEludGVybmFsSHRtbDVRcmNvZGVDb25maWcuY3JlYXRlID0gZnVuY3Rpb24gKGNvbmZpZywgbG9nZ2VyKSB7XG4gICAgICAgIHJldHVybiBuZXcgSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZyhjb25maWcsIGxvZ2dlcik7XG4gICAgfTtcbiAgICByZXR1cm4gSW50ZXJuYWxIdG1sNVFyY29kZUNvbmZpZztcbn0oKSk7XG52YXIgSHRtbDVRcmNvZGUgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIEh0bWw1UXJjb2RlKGVsZW1lbnRJZCwgY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuY2FudmFzRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudCA9IG51bGw7XG4gICAgICAgIHRoaXMuaGFzQm9yZGVyU2hhZGVycyA9IG51bGw7XG4gICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycyA9IG51bGw7XG4gICAgICAgIHRoaXMucXJNYXRjaCA9IG51bGw7XG4gICAgICAgIHRoaXMucmVuZGVyZWRDYW1lcmEgPSBudWxsO1xuICAgICAgICB0aGlzLnFyUmVnaW9uID0gbnVsbDtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gbnVsbDtcbiAgICAgICAgdGhpcy5sYXN0U2NhbkltYWdlRmlsZSA9IG51bGw7XG4gICAgICAgIHRoaXMuaXNTY2FubmluZyA9IGZhbHNlO1xuICAgICAgICBpZiAoIWRvY3VtZW50LmdldEVsZW1lbnRCeUlkKGVsZW1lbnRJZCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiSFRNTCBFbGVtZW50IHdpdGggaWQ9XCIuY29uY2F0KGVsZW1lbnRJZCwgXCIgbm90IGZvdW5kXCIpO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZWxlbWVudElkID0gZWxlbWVudElkO1xuICAgICAgICB0aGlzLnZlcmJvc2UgPSBmYWxzZTtcbiAgICAgICAgdmFyIGV4cGVyaW1lbnRhbEZlYXR1cmVDb25maWc7XG4gICAgICAgIHZhciBjb25maWdPYmplY3Q7XG4gICAgICAgIGlmICh0eXBlb2YgY29uZmlnT3JWZXJib3NpdHlGbGFnID09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgPSBjb25maWdPclZlcmJvc2l0eUZsYWcgPT09IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSBpZiAoY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgICAgICBjb25maWdPYmplY3QgPSBjb25maWdPclZlcmJvc2l0eUZsYWc7XG4gICAgICAgICAgICB0aGlzLnZlcmJvc2UgPSBjb25maWdPYmplY3QudmVyYm9zZSA9PT0gdHJ1ZTtcbiAgICAgICAgICAgIGV4cGVyaW1lbnRhbEZlYXR1cmVDb25maWcgPSBjb25maWdPYmplY3QuZXhwZXJpbWVudGFsRmVhdHVyZXM7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5sb2dnZXIgPSBuZXcgQmFzZUxvZ2dnZXIodGhpcy52ZXJib3NlKTtcbiAgICAgICAgdGhpcy5xcmNvZGUgPSBuZXcgSHRtbDVRcmNvZGVTaGltKHRoaXMuZ2V0U3VwcG9ydGVkRm9ybWF0cyhjb25maWdPclZlcmJvc2l0eUZsYWcpLCB0aGlzLmdldFVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkKGNvbmZpZ09iamVjdCksIHRoaXMudmVyYm9zZSwgdGhpcy5sb2dnZXIpO1xuICAgICAgICB0aGlzLmZvcmV2ZXJTY2FuVGltZW91dDtcbiAgICAgICAgdGhpcy5zaG91bGRTY2FuID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5zdGF0ZU1hbmFnZXJQcm94eSA9IFN0YXRlTWFuYWdlckZhY3RvcnkuY3JlYXRlKCk7XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zdGFydCA9IGZ1bmN0aW9uIChjYW1lcmFJZE9yQ29uZmlnLCBjb25maWd1cmF0aW9uLCBxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCFjYW1lcmFJZE9yQ29uZmlnKSB7XG4gICAgICAgICAgICB0aHJvdyBcImNhbWVyYUlkT3JDb25maWcgaXMgcmVxdWlyZWRcIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXFyQ29kZVN1Y2Nlc3NDYWxsYmFja1xuICAgICAgICAgICAgfHwgdHlwZW9mIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjayAhPSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHRocm93IFwicXJDb2RlU3VjY2Vzc0NhbGxiYWNrIGlzIHJlcXVpcmVkIGFuZCBzaG91bGQgYmUgYSBmdW5jdGlvbi5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsO1xuICAgICAgICBpZiAocXJDb2RlRXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsID0gcXJDb2RlRXJyb3JDYWxsYmFjaztcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHFyQ29kZUVycm9yQ2FsbGJhY2tJbnRlcm5hbFxuICAgICAgICAgICAgICAgID0gdGhpcy52ZXJib3NlID8gdGhpcy5sb2dnZXIubG9nIDogZnVuY3Rpb24gKCkgeyB9O1xuICAgICAgICB9XG4gICAgICAgIHZhciBpbnRlcm5hbENvbmZpZyA9IEludGVybmFsSHRtbDVRcmNvZGVDb25maWcuY3JlYXRlKGNvbmZpZ3VyYXRpb24sIHRoaXMubG9nZ2VyKTtcbiAgICAgICAgdGhpcy5jbGVhckVsZW1lbnQoKTtcbiAgICAgICAgdmFyIHZpZGVvQ29uc3RyYWludHNBdmFpbGFibGVBbmRWYWxpZCA9IGZhbHNlO1xuICAgICAgICBpZiAoaW50ZXJuYWxDb25maWcudmlkZW9Db25zdHJhaW50cykge1xuICAgICAgICAgICAgaWYgKCFpbnRlcm5hbENvbmZpZy5pc01lZGlhU3RyZWFtQ29uc3RyYWludHNWYWxpZCgpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5sb2dnZXIubG9nRXJyb3IoXCIndmlkZW9Db25zdHJhaW50cycgaXMgbm90IHZhbGlkICdNZWRpYVN0cmVhbUNvbnN0cmFpbnRzLCBcIlxuICAgICAgICAgICAgICAgICAgICArIFwiaXQgd2lsbCBiZSBpZ25vcmVkLidcIiwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB2aWRlb0NvbnN0cmFpbnRzQXZhaWxhYmxlQW5kVmFsaWQgPSB0cnVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHZhciBhcmVWaWRlb0NvbnN0cmFpbnRzRW5hYmxlZCA9IHZpZGVvQ29uc3RyYWludHNBdmFpbGFibGVBbmRWYWxpZDtcbiAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmVsZW1lbnRJZCk7XG4gICAgICAgIHZhciByb290RWxlbWVudFdpZHRoID0gZWxlbWVudC5jbGllbnRXaWR0aFxuICAgICAgICAgICAgPyBlbGVtZW50LmNsaWVudFdpZHRoIDogQ29uc3RhbnRzLkRFRkFVTFRfV0lEVEg7XG4gICAgICAgIGVsZW1lbnQuc3R5bGUucG9zaXRpb24gPSBcInJlbGF0aXZlXCI7XG4gICAgICAgIHRoaXMuc2hvdWxkU2NhbiA9IHRydWU7XG4gICAgICAgIHRoaXMuZWxlbWVudCA9IGVsZW1lbnQ7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbiA9IHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuc3RhcnRUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HKTtcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgIHZhciB2aWRlb0NvbnN0cmFpbnRzID0gYXJlVmlkZW9Db25zdHJhaW50c0VuYWJsZWRcbiAgICAgICAgICAgICAgICA/IGludGVybmFsQ29uZmlnLnZpZGVvQ29uc3RyYWludHNcbiAgICAgICAgICAgICAgICA6ICR0aGlzLmNyZWF0ZVZpZGVvQ29uc3RyYWludHMoY2FtZXJhSWRPckNvbmZpZyk7XG4gICAgICAgICAgICBpZiAoIXZpZGVvQ29uc3RyYWludHMpIHtcbiAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICByZWplY3QoXCJ2aWRlb0NvbnN0cmFpbnRzIHNob3VsZCBiZSBkZWZpbmVkXCIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBjYW1lcmFSZW5kZXJpbmdPcHRpb25zID0ge307XG4gICAgICAgICAgICBpZiAoIWFyZVZpZGVvQ29uc3RyYWludHNFbmFibGVkIHx8IGludGVybmFsQ29uZmlnLmFzcGVjdFJhdGlvKSB7XG4gICAgICAgICAgICAgICAgY2FtZXJhUmVuZGVyaW5nT3B0aW9ucy5hc3BlY3RSYXRpbyA9IGludGVybmFsQ29uZmlnLmFzcGVjdFJhdGlvO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIHJlbmRlcmluZ0NhbGxiYWNrcyA9IHtcbiAgICAgICAgICAgICAgICBvblJlbmRlclN1cmZhY2VSZWFkeTogZnVuY3Rpb24gKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5zZXR1cFVpKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgaW50ZXJuYWxDb25maWcpO1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5pc1NjYW5uaW5nID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMuZm9yZXZlclNjYW4oaW50ZXJuYWxDb25maWcsIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgcXJDb2RlRXJyb3JDYWxsYmFja0ludGVybmFsKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgQ2FtZXJhRmFjdG9yeS5mYWlsSWZOb3RTdXBwb3J0ZWQoKS50aGVuKGZ1bmN0aW9uIChmYWN0b3J5KSB7XG4gICAgICAgICAgICAgICAgZmFjdG9yeS5jcmVhdGUodmlkZW9Db25zdHJhaW50cykudGhlbihmdW5jdGlvbiAoY2FtZXJhKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBjYW1lcmEucmVuZGVyKF90aGlzLmVsZW1lbnQsIGNhbWVyYVJlbmRlcmluZ09wdGlvbnMsIHJlbmRlcmluZ0NhbGxiYWNrcylcbiAgICAgICAgICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChyZW5kZXJlZENhbWVyYSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgJHRoaXMucmVuZGVyZWRDYW1lcmEgPSByZW5kZXJlZENhbWVyYTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRvU2Nhbm5pbmdTdGF0ZUNoYW5nZVRyYW5zYWN0aW9uLmV4ZWN1dGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUobnVsbCk7XG4gICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICB0b1NjYW5uaW5nU3RhdGVDaGFuZ2VUcmFuc2FjdGlvbi5jYW5jZWwoKTtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KEh0bWw1UXJjb2RlU3RyaW5ncy5lcnJvckdldHRpbmdVc2VyTWVkaWEoZXJyb3IpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgdG9TY2FubmluZ1N0YXRlQ2hhbmdlVHJhbnNhY3Rpb24uY2FuY2VsKCk7XG4gICAgICAgICAgICAgICAgcmVqZWN0KEh0bWw1UXJjb2RlU3RyaW5ncy5jYW1lcmFTdHJlYW1pbmdOb3RTdXBwb3J0ZWQoKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUucGF1c2UgPSBmdW5jdGlvbiAoc2hvdWxkUGF1c2VWaWRlbykge1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuaXNTdHJpY3RseVNjYW5uaW5nKCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiQ2Fubm90IHBhdXNlLCBzY2FubmVyIGlzIG5vdCBzY2FubmluZy5cIjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlTWFuYWdlclByb3h5LmRpcmVjdFRyYW5zaXRpb24oSHRtbDVRcmNvZGVTY2FubmVyU3RhdGUuUEFVU0VEKTtcbiAgICAgICAgdGhpcy5zaG93UGF1c2VkU3RhdGUoKTtcbiAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKHNob3VsZFBhdXNlVmlkZW8pIHx8IHNob3VsZFBhdXNlVmlkZW8gIT09IHRydWUpIHtcbiAgICAgICAgICAgIHNob3VsZFBhdXNlVmlkZW8gPSBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoc2hvdWxkUGF1c2VWaWRlbyAmJiB0aGlzLnJlbmRlcmVkQ2FtZXJhKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVkQ2FtZXJhLnBhdXNlKCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5yZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5pc1BhdXNlZCgpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCByZXN1bHQsIHNjYW5uZXIgaXMgbm90IHBhdXNlZC5cIjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEpIHtcbiAgICAgICAgICAgIHRocm93IFwicmVuZGVyZWRDYW1lcmEgZG9lc24ndCBleGlzdCB3aGlsZSB0cnlpbmcgcmVzdW1lKClcIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgdHJhbnNpdGlvblRvU2Nhbm5pbmcgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICAkdGhpcy5zdGF0ZU1hbmFnZXJQcm94eS5kaXJlY3RUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLlNDQU5OSU5HKTtcbiAgICAgICAgICAgICR0aGlzLmhpZGVQYXVzZWRTdGF0ZSgpO1xuICAgICAgICB9O1xuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEuaXNQYXVzZWQoKSkge1xuICAgICAgICAgICAgdHJhbnNpdGlvblRvU2Nhbm5pbmcoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbmRlcmVkQ2FtZXJhLnJlc3VtZShmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB0cmFuc2l0aW9uVG9TY2FubmluZygpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuZ2V0U3RhdGUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zdG9wID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIXRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuaXNTY2FubmluZygpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkNhbm5vdCBzdG9wLCBzY2FubmVyIGlzIG5vdCBydW5uaW5nIG9yIHBhdXNlZC5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdG9TdG9wcGVkU3RhdGVUcmFuc2FjdGlvbiA9IHRoaXMuc3RhdGVNYW5hZ2VyUHJveHkuc3RhcnRUcmFuc2l0aW9uKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXRlLk5PVF9TVEFSVEVEKTtcbiAgICAgICAgdGhpcy5zaG91bGRTY2FuID0gZmFsc2U7XG4gICAgICAgIGlmICh0aGlzLmZvcmV2ZXJTY2FuVGltZW91dCkge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRoaXMuZm9yZXZlclNjYW5UaW1lb3V0KTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVtb3ZlUXJSZWdpb24gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBpZiAoIV90aGlzLmVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIgY2hpbGRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoQ29uc3RhbnRzLlNIQURFRF9SRUdJT05fRUxFTUVOVF9JRCk7XG4gICAgICAgICAgICBpZiAoY2hpbGRFbGVtZW50KSB7XG4gICAgICAgICAgICAgICAgX3RoaXMuZWxlbWVudC5yZW1vdmVDaGlsZChjaGlsZEVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICByZXR1cm4gdGhpcy5yZW5kZXJlZENhbWVyYS5jbG9zZSgpLnRoZW4oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgJHRoaXMucmVuZGVyZWRDYW1lcmEgPSBudWxsO1xuICAgICAgICAgICAgaWYgKCR0aGlzLmVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5lbGVtZW50LnJlbW92ZUNoaWxkKCR0aGlzLmNhbnZhc0VsZW1lbnQpO1xuICAgICAgICAgICAgICAgICR0aGlzLmNhbnZhc0VsZW1lbnQgPSBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmVtb3ZlUXJSZWdpb24oKTtcbiAgICAgICAgICAgIGlmICgkdGhpcy5xclJlZ2lvbikge1xuICAgICAgICAgICAgICAgICR0aGlzLnFyUmVnaW9uID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICgkdGhpcy5jb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuY29udGV4dCA9IG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0b1N0b3BwZWRTdGF0ZVRyYW5zYWN0aW9uLmV4ZWN1dGUoKTtcbiAgICAgICAgICAgICR0aGlzLmhpZGVQYXVzZWRTdGF0ZSgpO1xuICAgICAgICAgICAgJHRoaXMuaXNTY2FubmluZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5zY2FuRmlsZSA9IGZ1bmN0aW9uIChpbWFnZUZpbGUsIHNob3dJbWFnZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5zY2FuRmlsZVYyKGltYWdlRmlsZSwgc2hvd0ltYWdlKVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGh0bWw1cXJjb2RlUmVzdWx0KSB7IHJldHVybiBodG1sNXFyY29kZVJlc3VsdC5kZWNvZGVkVGV4dDsgfSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2NhbkZpbGVWMiA9IGZ1bmN0aW9uIChpbWFnZUZpbGUsIHNob3dJbWFnZSkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICBpZiAoIWltYWdlRmlsZSB8fCAhKGltYWdlRmlsZSBpbnN0YW5jZW9mIEZpbGUpKSB7XG4gICAgICAgICAgICB0aHJvdyBcImltYWdlRmlsZSBhcmd1bWVudCBpcyBtYW5kYXRvcnkgYW5kIHNob3VsZCBiZSBpbnN0YW5jZSBcIlxuICAgICAgICAgICAgICAgICsgXCJvZiBGaWxlLiBVc2UgJ2V2ZW50LnRhcmdldC5maWxlc1swXScuXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGlzTnVsbE9yVW5kZWZpbmVkKHNob3dJbWFnZSkpIHtcbiAgICAgICAgICAgIHNob3dJbWFnZSA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLnN0YXRlTWFuYWdlclByb3h5LmNhblNjYW5GaWxlKCkpIHtcbiAgICAgICAgICAgIHRocm93IFwiQ2Fubm90IHN0YXJ0IGZpbGUgc2NhbiAtIG9uZ29pbmcgY2FtZXJhIHNjYW5cIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlDbG9zZUxhc3RTY2FuSW1hZ2VGaWxlKCk7XG4gICAgICAgICAgICBfdGhpcy5jbGVhckVsZW1lbnQoKTtcbiAgICAgICAgICAgIF90aGlzLmxhc3RTY2FuSW1hZ2VGaWxlID0gVVJMLmNyZWF0ZU9iamVjdFVSTChpbWFnZUZpbGUpO1xuICAgICAgICAgICAgdmFyIGlucHV0SW1hZ2UgPSBuZXcgSW1hZ2U7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB2YXIgaW1hZ2VXaWR0aCA9IGlucHV0SW1hZ2Uud2lkdGg7XG4gICAgICAgICAgICAgICAgdmFyIGltYWdlSGVpZ2h0ID0gaW5wdXRJbWFnZS5oZWlnaHQ7XG4gICAgICAgICAgICAgICAgdmFyIGVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChfdGhpcy5lbGVtZW50SWQpO1xuICAgICAgICAgICAgICAgIHZhciBjb250YWluZXJXaWR0aCA9IGVsZW1lbnQuY2xpZW50V2lkdGhcbiAgICAgICAgICAgICAgICAgICAgPyBlbGVtZW50LmNsaWVudFdpZHRoIDogQ29uc3RhbnRzLkRFRkFVTFRfV0lEVEg7XG4gICAgICAgICAgICAgICAgdmFyIGNvbnRhaW5lckhlaWdodCA9IE1hdGgubWF4KGVsZW1lbnQuY2xpZW50SGVpZ2h0ID8gZWxlbWVudC5jbGllbnRIZWlnaHQgOiBpbWFnZUhlaWdodCwgQ29uc3RhbnRzLkZJTEVfU0NBTl9NSU5fSEVJR0hUKTtcbiAgICAgICAgICAgICAgICB2YXIgY29uZmlnID0gX3RoaXMuY29tcHV0ZUNhbnZhc0RyYXdDb25maWcoaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQsIGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQpO1xuICAgICAgICAgICAgICAgIGlmIChzaG93SW1hZ2UpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHZpc2libGVDYW52YXMgPSBfdGhpcy5jcmVhdGVDYW52YXNFbGVtZW50KGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQsIFwicXItY2FudmFzLXZpc2libGVcIik7XG4gICAgICAgICAgICAgICAgICAgIHZpc2libGVDYW52YXMuc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQodmlzaWJsZUNhbnZhcyk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBjb250ZXh0XzEgPSB2aXNpYmxlQ2FudmFzLmdldENvbnRleHQoXCIyZFwiKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFjb250ZXh0XzEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiVW5hYmxlIHRvIGdldCAyZCBjb250ZXh0IGZyb20gY2FudmFzXCI7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29udGV4dF8xLmNhbnZhcy53aWR0aCA9IGNvbnRhaW5lcldpZHRoO1xuICAgICAgICAgICAgICAgICAgICBjb250ZXh0XzEuY2FudmFzLmhlaWdodCA9IGNvbnRhaW5lckhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgY29udGV4dF8xLmRyYXdJbWFnZShpbnB1dEltYWdlLCAwLCAwLCBpbWFnZVdpZHRoLCBpbWFnZUhlaWdodCwgY29uZmlnLngsIGNvbmZpZy55LCBjb25maWcud2lkdGgsIGNvbmZpZy5oZWlnaHQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgcGFkZGluZyA9IENvbnN0YW50cy5GSUxFX1NDQU5fSElEREVOX0NBTlZBU19QQURESU5HO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5JbWFnZVdpZHRoID0gTWF0aC5tYXgoaW5wdXRJbWFnZS53aWR0aCwgY29uZmlnLndpZHRoKTtcbiAgICAgICAgICAgICAgICB2YXIgaGlkZGVuSW1hZ2VIZWlnaHQgPSBNYXRoLm1heChpbnB1dEltYWdlLmhlaWdodCwgY29uZmlnLmhlaWdodCk7XG4gICAgICAgICAgICAgICAgdmFyIGhpZGRlbkNhbnZhc1dpZHRoID0gaGlkZGVuSW1hZ2VXaWR0aCArIDIgKiBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5DYW52YXNIZWlnaHQgPSBoaWRkZW5JbWFnZUhlaWdodCArIDIgKiBwYWRkaW5nO1xuICAgICAgICAgICAgICAgIHZhciBoaWRkZW5DYW52YXMgPSBfdGhpcy5jcmVhdGVDYW52YXNFbGVtZW50KGhpZGRlbkNhbnZhc1dpZHRoLCBoaWRkZW5DYW52YXNIZWlnaHQpO1xuICAgICAgICAgICAgICAgIGVsZW1lbnQuYXBwZW5kQ2hpbGQoaGlkZGVuQ2FudmFzKTtcbiAgICAgICAgICAgICAgICB2YXIgY29udGV4dCA9IGhpZGRlbkNhbnZhcy5nZXRDb250ZXh0KFwiMmRcIik7XG4gICAgICAgICAgICAgICAgaWYgKCFjb250ZXh0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiVW5hYmxlIHRvIGdldCAyZCBjb250ZXh0IGZyb20gY2FudmFzXCI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnRleHQuY2FudmFzLndpZHRoID0gaGlkZGVuQ2FudmFzV2lkdGg7XG4gICAgICAgICAgICAgICAgY29udGV4dC5jYW52YXMuaGVpZ2h0ID0gaGlkZGVuQ2FudmFzSGVpZ2h0O1xuICAgICAgICAgICAgICAgIGNvbnRleHQuZHJhd0ltYWdlKGlucHV0SW1hZ2UsIDAsIDAsIGltYWdlV2lkdGgsIGltYWdlSGVpZ2h0LCBwYWRkaW5nLCBwYWRkaW5nLCBoaWRkZW5JbWFnZVdpZHRoLCBoaWRkZW5JbWFnZUhlaWdodCk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgX3RoaXMucXJjb2RlLmRlY29kZVJvYnVzdGx5QXN5bmMoaGlkZGVuQ2FudmFzKVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKHJlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZShIdG1sNVFyY29kZVJlc3VsdEZhY3RvcnkuY3JlYXRlRnJvbVFyY29kZVJlc3VsdChyZXN1bHQpKTtcbiAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaChyZWplY3QpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXhjZXB0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChcIlFSIGNvZGUgcGFyc2UgZXJyb3IsIGVycm9yID0gXCIuY29uY2F0KGV4Y2VwdGlvbikpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uZXJyb3IgPSByZWplY3Q7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uYWJvcnQgPSByZWplY3Q7XG4gICAgICAgICAgICBpbnB1dEltYWdlLm9uc3RhbGxlZCA9IHJlamVjdDtcbiAgICAgICAgICAgIGlucHV0SW1hZ2Uub25zdXNwZW5kID0gcmVqZWN0O1xuICAgICAgICAgICAgaW5wdXRJbWFnZS5zcmMgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGltYWdlRmlsZSk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmNsZWFyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmNsZWFyRWxlbWVudCgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUuZ2V0Q2FtZXJhcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIENhbWVyYVJldHJpZXZlci5yZXRyaWV2ZSgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja0NhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRSdW5uaW5nVHJhY2tDYXBhYmlsaXRpZXMoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRSdW5uaW5nVHJhY2tTZXR0aW5ncygpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja0NhbWVyYUNhcGFiaWxpdGllcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0UmVuZGVyZWRDYW1lcmFPckZhaWwoKS5nZXRDYXBhYmlsaXRpZXMoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5hcHBseVZpZGVvQ29uc3RyYWludHMgPSBmdW5jdGlvbiAodmlkZW9Db25zdGFpbnRzKSB7XG4gICAgICAgIGlmICghdmlkZW9Db25zdGFpbnRzKSB7XG4gICAgICAgICAgICB0aHJvdyBcInZpZGVvQ29uc3RhaW50cyBpcyByZXF1aXJlZCBhcmd1bWVudC5cIjtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIGlmICghVmlkZW9Db25zdHJhaW50c1V0aWwuaXNNZWRpYVN0cmVhbUNvbnN0cmFpbnRzVmFsaWQodmlkZW9Db25zdGFpbnRzLCB0aGlzLmxvZ2dlcikpIHtcbiAgICAgICAgICAgIHRocm93IFwiaW52YWxpZCB2aWRlb0NvbnN0YWludHMgcGFzc2VkLCBjaGVjayBsb2dzIGZvciBtb3JlIGRldGFpbHNcIjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcy5nZXRSZW5kZXJlZENhbWVyYU9yRmFpbCgpLmFwcGx5VmlkZW9Db25zdHJhaW50cyh2aWRlb0NvbnN0YWludHMpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFJlbmRlcmVkQ2FtZXJhT3JGYWlsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5yZW5kZXJlZENhbWVyYSA9PSBudWxsKSB7XG4gICAgICAgICAgICB0aHJvdyBcIlNjYW5uaW5nIGlzIG5vdCBpbiBydW5uaW5nIHN0YXRlLCBjYWxsIHRoaXMgQVBJIG9ubHkgd2hlblwiXG4gICAgICAgICAgICAgICAgKyBcIiBRUiBjb2RlIHNjYW5uaW5nIHVzaW5nIGNhbWVyYSBpcyBpbiBydW5uaW5nIHN0YXRlLlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnJlbmRlcmVkQ2FtZXJhO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFN1cHBvcnRlZEZvcm1hdHMgPSBmdW5jdGlvbiAoY29uZmlnT3JWZXJib3NpdHlGbGFnKSB7XG4gICAgICAgIHZhciBhbGxGb3JtYXRzID0gW1xuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlFSX0NPREUsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQVpURUMsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09EQUJBUixcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5DT0RFXzM5LFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkNPREVfOTMsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuQ09ERV8xMjgsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuREFUQV9NQVRSSVgsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuTUFYSUNPREUsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuSVRGLFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLkVBTl8xMyxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5FQU5fOCxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5QREZfNDE3LFxuICAgICAgICAgICAgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzLlJTU18xNCxcbiAgICAgICAgICAgIEh0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5SU1NfRVhQQU5ERUQsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0EsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0UsXG4gICAgICAgICAgICBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMuVVBDX0VBTl9FWFRFTlNJT04sXG4gICAgICAgIF07XG4gICAgICAgIGlmICghY29uZmlnT3JWZXJib3NpdHlGbGFnXG4gICAgICAgICAgICB8fCB0eXBlb2YgY29uZmlnT3JWZXJib3NpdHlGbGFnID09IFwiYm9vbGVhblwiKSB7XG4gICAgICAgICAgICByZXR1cm4gYWxsRm9ybWF0cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0KSB7XG4gICAgICAgICAgICByZXR1cm4gYWxsRm9ybWF0cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoY29uZmlnT3JWZXJib3NpdHlGbGFnLmZvcm1hdHNUb1N1cHBvcnQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcImNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0IHNob3VsZCBiZSB1bmRlZmluZWQgXCJcbiAgICAgICAgICAgICAgICArIFwib3IgYW4gYXJyYXkuXCI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdGhyb3cgXCJBdGxlYXN0IDEgZm9ybWF0c1RvU3VwcG9ydCBpcyBuZWVkZWQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHN1cHBvcnRlZEZvcm1hdHMgPSBbXTtcbiAgICAgICAgZm9yICh2YXIgX2kgPSAwLCBfYSA9IGNvbmZpZ09yVmVyYm9zaXR5RmxhZy5mb3JtYXRzVG9TdXBwb3J0OyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIGZvcm1hdCA9IF9hW19pXTtcbiAgICAgICAgICAgIGlmIChpc1ZhbGlkSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzKGZvcm1hdCkpIHtcbiAgICAgICAgICAgICAgICBzdXBwb3J0ZWRGb3JtYXRzLnB1c2goZm9ybWF0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMubG9nZ2VyLndhcm4oXCJJbnZhbGlkIGZvcm1hdDogXCIuY29uY2F0KGZvcm1hdCwgXCIgcGFzc2VkIGluIGNvbmZpZywgaWdub3JpbmcuXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoc3VwcG9ydGVkRm9ybWF0cy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIHRocm93IFwiTm9uZSBvZiBmb3JtYXRzVG9TdXBwb3J0IG1hdGNoIHN1cHBvcnRlZCB2YWx1ZXMuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHN1cHBvcnRlZEZvcm1hdHM7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuZ2V0VXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChjb25maWcpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKGNvbmZpZy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCkpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25maWcudXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQgIT09IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChjb25maWcuZXhwZXJpbWVudGFsRmVhdHVyZXMpKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZXhwZXJpbWVudGFsRmVhdHVyZXMgPSBjb25maWcuZXhwZXJpbWVudGFsRmVhdHVyZXM7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChleHBlcmltZW50YWxGZWF0dXJlcy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBleHBlcmltZW50YWxGZWF0dXJlcy51c2VCYXJDb2RlRGV0ZWN0b3JJZlN1cHBvcnRlZCAhPT0gZmFsc2U7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUudmFsaWRhdGVRcmJveFNpemUgPSBmdW5jdGlvbiAodmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBpbnRlcm5hbENvbmZpZykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcXJib3hTaXplID0gaW50ZXJuYWxDb25maWcucXJib3g7XG4gICAgICAgIHRoaXMudmFsaWRhdGVRcmJveENvbmZpZyhxcmJveFNpemUpO1xuICAgICAgICB2YXIgcXJEaW1lbnNpb25zID0gdGhpcy50b1FyZGltZW5zaW9ucyh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIHFyYm94U2l6ZSk7XG4gICAgICAgIHZhciB2YWxpZGF0ZU1pblNpemUgPSBmdW5jdGlvbiAoc2l6ZSkge1xuICAgICAgICAgICAgaWYgKHNpemUgPCBDb25zdGFudHMuTUlOX1FSX0JPWF9TSVpFKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJtaW5pbXVtIHNpemUgb2YgJ2NvbmZpZy5xcmJveCcgZGltZW5zaW9uIHZhbHVlIGlzXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcIiBcIi5jb25jYXQoQ29uc3RhbnRzLk1JTl9RUl9CT1hfU0laRSwgXCJweC5cIik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH07XG4gICAgICAgIHZhciBjb3JyZWN0V2lkdGhCYXNlZE9uUm9vdEVsZW1lbnRTaXplID0gZnVuY3Rpb24gKGNvbmZpZ1dpZHRoKSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnV2lkdGggPiB2aWV3ZmluZGVyV2lkdGgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5sb2dnZXIud2FybihcImBxcmJveC53aWR0aGAgb3IgYHFyYm94YCBpcyBsYXJnZXIgdGhhbiB0aGVcIlxuICAgICAgICAgICAgICAgICAgICArIFwiIHdpZHRoIG9mIHRoZSByb290IGVsZW1lbnQuIFRoZSB3aWR0aCB3aWxsIGJlIHRydW5jYXRlZFwiXG4gICAgICAgICAgICAgICAgICAgICsgXCIgdG8gdGhlIHdpZHRoIG9mIHJvb3QgZWxlbWVudC5cIik7XG4gICAgICAgICAgICAgICAgY29uZmlnV2lkdGggPSB2aWV3ZmluZGVyV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29uZmlnV2lkdGg7XG4gICAgICAgIH07XG4gICAgICAgIHZhbGlkYXRlTWluU2l6ZShxckRpbWVuc2lvbnMud2lkdGgpO1xuICAgICAgICB2YWxpZGF0ZU1pblNpemUocXJEaW1lbnNpb25zLmhlaWdodCk7XG4gICAgICAgIHFyRGltZW5zaW9ucy53aWR0aCA9IGNvcnJlY3RXaWR0aEJhc2VkT25Sb290RWxlbWVudFNpemUocXJEaW1lbnNpb25zLndpZHRoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS52YWxpZGF0ZVFyYm94Q29uZmlnID0gZnVuY3Rpb24gKHFyYm94U2l6ZSkge1xuICAgICAgICBpZiAodHlwZW9mIHFyYm94U2l6ZSA9PT0gXCJudW1iZXJcIikge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGlmICh0eXBlb2YgcXJib3hTaXplID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAocXJib3hTaXplLndpZHRoID09PSB1bmRlZmluZWQgfHwgcXJib3hTaXplLmhlaWdodCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkludmFsaWQgaW5zdGFuY2Ugb2YgUXJEaW1lbnNpb25zIHBhc3NlZCBmb3IgXCJcbiAgICAgICAgICAgICAgICArIFwiJ2NvbmZpZy5xcmJveCcuIEJvdGggJ3dpZHRoJyBhbmQgJ2hlaWdodCcgc2hvdWxkIGJlIHNldC5cIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnRvUXJkaW1lbnNpb25zID0gZnVuY3Rpb24gKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgcXJib3hTaXplKSB7XG4gICAgICAgIGlmICh0eXBlb2YgcXJib3hTaXplID09PSBcIm51bWJlclwiKSB7XG4gICAgICAgICAgICByZXR1cm4geyB3aWR0aDogcXJib3hTaXplLCBoZWlnaHQ6IHFyYm94U2l6ZSB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBxcmJveFNpemUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcXJib3hTaXplKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJxcmJveCBjb25maWcgd2FzIHBhc3NlZCBhcyBhIGZ1bmN0aW9uIGJ1dCBpdCBmYWlsZWQgd2l0aCBcIlxuICAgICAgICAgICAgICAgICAgICArIFwidW5rbm93biBlcnJvclwiICsgZXJyb3IpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBxcmJveFNpemU7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2V0dXBVaSA9IGZ1bmN0aW9uICh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIGludGVybmFsQ29uZmlnKSB7XG4gICAgICAgIGlmIChpbnRlcm5hbENvbmZpZy5pc1NoYWRlZEJveEVuYWJsZWQoKSkge1xuICAgICAgICAgICAgdGhpcy52YWxpZGF0ZVFyYm94U2l6ZSh2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIGludGVybmFsQ29uZmlnKTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgcXJib3hTaXplID0gaXNOdWxsT3JVbmRlZmluZWQoaW50ZXJuYWxDb25maWcucXJib3gpID9cbiAgICAgICAgICAgIHsgd2lkdGg6IHZpZXdmaW5kZXJXaWR0aCwgaGVpZ2h0OiB2aWV3ZmluZGVySGVpZ2h0IH0gOiBpbnRlcm5hbENvbmZpZy5xcmJveDtcbiAgICAgICAgdGhpcy52YWxpZGF0ZVFyYm94Q29uZmlnKHFyYm94U2l6ZSk7XG4gICAgICAgIHZhciBxckRpbWVuc2lvbnMgPSB0aGlzLnRvUXJkaW1lbnNpb25zKHZpZXdmaW5kZXJXaWR0aCwgdmlld2ZpbmRlckhlaWdodCwgcXJib3hTaXplKTtcbiAgICAgICAgaWYgKHFyRGltZW5zaW9ucy5oZWlnaHQgPiB2aWV3ZmluZGVySGVpZ2h0KSB7XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci53YXJuKFwiW0h0bWw1UXJjb2RlXSBjb25maWcucXJib3ggaGFzIGhlaWdodCB0aGF0IGlzXCJcbiAgICAgICAgICAgICAgICArIFwiZ3JlYXRlciB0aGFuIHRoZSBoZWlnaHQgb2YgdGhlIHZpZGVvIHN0cmVhbS4gU2hhZGluZyB3aWxsIGJlXCJcbiAgICAgICAgICAgICAgICArIFwiIGlnbm9yZWRcIik7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHNob3VsZFNoYWRpbmdCZUFwcGxpZWQgPSBpbnRlcm5hbENvbmZpZy5pc1NoYWRlZEJveEVuYWJsZWQoKVxuICAgICAgICAgICAgJiYgcXJEaW1lbnNpb25zLmhlaWdodCA8PSB2aWV3ZmluZGVySGVpZ2h0O1xuICAgICAgICB2YXIgZGVmYXVsdFFyUmVnaW9uID0ge1xuICAgICAgICAgICAgeDogMCxcbiAgICAgICAgICAgIHk6IDAsXG4gICAgICAgICAgICB3aWR0aDogdmlld2ZpbmRlcldpZHRoLFxuICAgICAgICAgICAgaGVpZ2h0OiB2aWV3ZmluZGVySGVpZ2h0XG4gICAgICAgIH07XG4gICAgICAgIHZhciBxclJlZ2lvbiA9IHNob3VsZFNoYWRpbmdCZUFwcGxpZWRcbiAgICAgICAgICAgID8gdGhpcy5nZXRTaGFkZWRSZWdpb25Cb3VuZHModmlld2ZpbmRlcldpZHRoLCB2aWV3ZmluZGVySGVpZ2h0LCBxckRpbWVuc2lvbnMpXG4gICAgICAgICAgICA6IGRlZmF1bHRRclJlZ2lvbjtcbiAgICAgICAgdmFyIGNhbnZhc0VsZW1lbnQgPSB0aGlzLmNyZWF0ZUNhbnZhc0VsZW1lbnQocXJSZWdpb24ud2lkdGgsIHFyUmVnaW9uLmhlaWdodCk7XG4gICAgICAgIHZhciBjb250ZXh0QXR0cmlidXRlcyA9IHsgd2lsbFJlYWRGcmVxdWVudGx5OiB0cnVlIH07XG4gICAgICAgIHZhciBjb250ZXh0ID0gY2FudmFzRWxlbWVudC5nZXRDb250ZXh0KFwiMmRcIiwgY29udGV4dEF0dHJpYnV0ZXMpO1xuICAgICAgICBjb250ZXh0LmNhbnZhcy53aWR0aCA9IHFyUmVnaW9uLndpZHRoO1xuICAgICAgICBjb250ZXh0LmNhbnZhcy5oZWlnaHQgPSBxclJlZ2lvbi5oZWlnaHQ7XG4gICAgICAgIHRoaXMuZWxlbWVudC5hcHBlbmQoY2FudmFzRWxlbWVudCk7XG4gICAgICAgIGlmIChzaG91bGRTaGFkaW5nQmVBcHBsaWVkKSB7XG4gICAgICAgICAgICB0aGlzLnBvc3NpYmx5SW5zZXJ0U2hhZGluZ0VsZW1lbnQodGhpcy5lbGVtZW50LCB2aWV3ZmluZGVyV2lkdGgsIHZpZXdmaW5kZXJIZWlnaHQsIHFyRGltZW5zaW9ucyk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5jcmVhdGVTY2FubmVyUGF1c2VkVWlFbGVtZW50KHRoaXMuZWxlbWVudCk7XG4gICAgICAgIHRoaXMucXJSZWdpb24gPSBxclJlZ2lvbjtcbiAgICAgICAgdGhpcy5jb250ZXh0ID0gY29udGV4dDtcbiAgICAgICAgdGhpcy5jYW52YXNFbGVtZW50ID0gY2FudmFzRWxlbWVudDtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5jcmVhdGVTY2FubmVyUGF1c2VkVWlFbGVtZW50ID0gZnVuY3Rpb24gKHJvb3RFbGVtZW50KSB7XG4gICAgICAgIHZhciBzY2FubmVyUGF1c2VkVWlFbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5pbm5lclRleHQgPSBIdG1sNVFyY29kZVN0cmluZ3Muc2Nhbm5lclBhdXNlZCgpO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS50b3AgPSBcIjBweFwiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLnpJbmRleCA9IFwiMVwiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLmJhY2tncm91bmQgPSBcInJnYmEoOSwgOSwgOSwgMC40NilcIjtcbiAgICAgICAgc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5jb2xvciA9IFwiI0ZGRUNFQ1wiO1xuICAgICAgICBzY2FubmVyUGF1c2VkVWlFbGVtZW50LnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQuc3R5bGUud2lkdGggPSBcIjEwMCVcIjtcbiAgICAgICAgcm9vdEVsZW1lbnQuYXBwZW5kQ2hpbGQoc2Nhbm5lclBhdXNlZFVpRWxlbWVudCk7XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudCA9IHNjYW5uZXJQYXVzZWRVaUVsZW1lbnQ7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuc2NhbkNvbnRleHQgPSBmdW5jdGlvbiAocXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlTWFuYWdlclByb3h5LmlzUGF1c2VkKCkpIHtcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoZmFsc2UpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLnFyY29kZS5kZWNvZGVBc3luYyh0aGlzLmNhbnZhc0VsZW1lbnQpXG4gICAgICAgICAgICAudGhlbihmdW5jdGlvbiAocmVzdWx0KSB7XG4gICAgICAgICAgICBxckNvZGVTdWNjZXNzQ2FsbGJhY2socmVzdWx0LnRleHQsIEh0bWw1UXJjb2RlUmVzdWx0RmFjdG9yeS5jcmVhdGVGcm9tUXJjb2RlUmVzdWx0KHJlc3VsdCkpO1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlVcGRhdGVTaGFkZXJzKHRydWUpO1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgX3RoaXMucG9zc2libHlVcGRhdGVTaGFkZXJzKGZhbHNlKTtcbiAgICAgICAgICAgIHZhciBlcnJvck1lc3NhZ2UgPSBIdG1sNVFyY29kZVN0cmluZ3MuY29kZVBhcnNlRXJyb3IoZXJyb3IpO1xuICAgICAgICAgICAgcXJDb2RlRXJyb3JDYWxsYmFjayhlcnJvck1lc3NhZ2UsIEh0bWw1UXJjb2RlRXJyb3JGYWN0b3J5LmNyZWF0ZUZyb20oZXJyb3JNZXNzYWdlKSk7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmZvcmV2ZXJTY2FuID0gZnVuY3Rpb24gKGludGVybmFsQ29uZmlnLCBxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgaWYgKCF0aGlzLnNob3VsZFNjYW4pIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAoIXRoaXMucmVuZGVyZWRDYW1lcmEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgdmlkZW9FbGVtZW50ID0gdGhpcy5yZW5kZXJlZENhbWVyYS5nZXRTdXJmYWNlKCk7XG4gICAgICAgIHZhciB3aWR0aFJhdGlvID0gdmlkZW9FbGVtZW50LnZpZGVvV2lkdGggLyB2aWRlb0VsZW1lbnQuY2xpZW50V2lkdGg7XG4gICAgICAgIHZhciBoZWlnaHRSYXRpbyA9IHZpZGVvRWxlbWVudC52aWRlb0hlaWdodCAvIHZpZGVvRWxlbWVudC5jbGllbnRIZWlnaHQ7XG4gICAgICAgIGlmICghdGhpcy5xclJlZ2lvbikge1xuICAgICAgICAgICAgdGhyb3cgXCJxclJlZ2lvbiB1bmRlZmluZWQgd2hlbiBsb2NhbE1lZGlhU3RyZWFtIGlzIHJlYWR5LlwiO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzV2lkdGhPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLndpZHRoICogd2lkdGhSYXRpbztcbiAgICAgICAgdmFyIHNIZWlnaHRPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLmhlaWdodCAqIGhlaWdodFJhdGlvO1xuICAgICAgICB2YXIgc3hPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLnggKiB3aWR0aFJhdGlvO1xuICAgICAgICB2YXIgc3lPZmZzZXQgPSB0aGlzLnFyUmVnaW9uLnkgKiBoZWlnaHRSYXRpbztcbiAgICAgICAgdGhpcy5jb250ZXh0LmRyYXdJbWFnZSh2aWRlb0VsZW1lbnQsIHN4T2Zmc2V0LCBzeU9mZnNldCwgc1dpZHRoT2Zmc2V0LCBzSGVpZ2h0T2Zmc2V0LCAwLCAwLCB0aGlzLnFyUmVnaW9uLndpZHRoLCB0aGlzLnFyUmVnaW9uLmhlaWdodCk7XG4gICAgICAgIHZhciB0cmlnZ2VyTmV4dFNjYW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICBfdGhpcy5mb3JldmVyU2NhblRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICBfdGhpcy5mb3JldmVyU2NhbihpbnRlcm5hbENvbmZpZywgcXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0sIF90aGlzLmdldFRpbWVvdXRGcHMoaW50ZXJuYWxDb25maWcuZnBzKSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuc2NhbkNvbnRleHQocXJDb2RlU3VjY2Vzc0NhbGxiYWNrLCBxckNvZGVFcnJvckNhbGxiYWNrKVxuICAgICAgICAgICAgLnRoZW4oZnVuY3Rpb24gKGlzU3VjY2Vzc2Z1bGwpIHtcbiAgICAgICAgICAgIGlmICghaXNTdWNjZXNzZnVsbCAmJiBpbnRlcm5hbENvbmZpZy5kaXNhYmxlRmxpcCAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIF90aGlzLmNvbnRleHQudHJhbnNsYXRlKF90aGlzLmNvbnRleHQuY2FudmFzLndpZHRoLCAwKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5jb250ZXh0LnNjYWxlKC0xLCAxKTtcbiAgICAgICAgICAgICAgICBfdGhpcy5zY2FuQ29udGV4dChxckNvZGVTdWNjZXNzQ2FsbGJhY2ssIHFyQ29kZUVycm9yQ2FsbGJhY2spXG4gICAgICAgICAgICAgICAgICAgIC5maW5hbGx5KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlck5leHRTY2FuKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICB0cmlnZ2VyTmV4dFNjYW4oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICBfdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJFcnJvciBoYXBwZW5kIHdoaWxlIHNjYW5uaW5nIGNvbnRleHRcIiwgZXJyb3IpO1xuICAgICAgICAgICAgdHJpZ2dlck5leHRTY2FuKCk7XG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmNyZWF0ZVZpZGVvQ29uc3RyYWludHMgPSBmdW5jdGlvbiAoY2FtZXJhSWRPckNvbmZpZykge1xuICAgICAgICBpZiAodHlwZW9mIGNhbWVyYUlkT3JDb25maWcgPT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcmV0dXJuIHsgZGV2aWNlSWQ6IHsgZXhhY3Q6IGNhbWVyYUlkT3JDb25maWcgfSB9O1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKHR5cGVvZiBjYW1lcmFJZE9yQ29uZmlnID09IFwib2JqZWN0XCIpIHtcbiAgICAgICAgICAgIHZhciBmYWNpbmdNb2RlS2V5ID0gXCJmYWNpbmdNb2RlXCI7XG4gICAgICAgICAgICB2YXIgZGV2aWNlSWRLZXkgPSBcImRldmljZUlkXCI7XG4gICAgICAgICAgICB2YXIgYWxsb3dlZEZhY2luZ01vZGVWYWx1ZXNfMSA9IHsgXCJ1c2VyXCI6IHRydWUsIFwiZW52aXJvbm1lbnRcIjogdHJ1ZSB9O1xuICAgICAgICAgICAgdmFyIGV4YWN0S2V5ID0gXCJleGFjdFwiO1xuICAgICAgICAgICAgdmFyIGlzVmFsaWRGYWNpbmdNb2RlVmFsdWUgPSBmdW5jdGlvbiAodmFsdWUpIHtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUgaW4gYWxsb3dlZEZhY2luZ01vZGVWYWx1ZXNfMSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiY29uZmlnIGhhcyBpbnZhbGlkICdmYWNpbmdNb2RlJyB2YWx1ZSA9IFwiXG4gICAgICAgICAgICAgICAgICAgICAgICArIFwiJ1wiLmNvbmNhdCh2YWx1ZSwgXCInXCIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB2YXIga2V5cyA9IE9iamVjdC5rZXlzKGNhbWVyYUlkT3JDb25maWcpO1xuICAgICAgICAgICAgaWYgKGtleXMubGVuZ3RoICE9PSAxKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCInY2FtZXJhSWRPckNvbmZpZycgb2JqZWN0IHNob3VsZCBoYXZlIGV4YWN0bHkgMSBrZXksXCJcbiAgICAgICAgICAgICAgICAgICAgKyBcIiBpZiBwYXNzZWQgYXMgYW4gb2JqZWN0LCBmb3VuZCBcIi5jb25jYXQoa2V5cy5sZW5ndGgsIFwiIGtleXNcIik7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB2YXIga2V5ID0gT2JqZWN0LmtleXMoY2FtZXJhSWRPckNvbmZpZylbMF07XG4gICAgICAgICAgICBpZiAoa2V5ICE9PSBmYWNpbmdNb2RlS2V5ICYmIGtleSAhPT0gZGV2aWNlSWRLZXkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIk9ubHkgJ1wiLmNvbmNhdChmYWNpbmdNb2RlS2V5LCBcIicgYW5kICdcIikuY29uY2F0KGRldmljZUlkS2V5LCBcIicgXCIpXG4gICAgICAgICAgICAgICAgICAgICsgXCIgYXJlIHN1cHBvcnRlZCBmb3IgJ2NhbWVyYUlkT3JDb25maWcnXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoa2V5ID09PSBmYWNpbmdNb2RlS2V5KSB7XG4gICAgICAgICAgICAgICAgdmFyIGZhY2luZ01vZGUgPSBjYW1lcmFJZE9yQ29uZmlnLmZhY2luZ01vZGU7XG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiBmYWNpbmdNb2RlID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzVmFsaWRGYWNpbmdNb2RlVmFsdWUoZmFjaW5nTW9kZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB7IGZhY2luZ01vZGU6IGZhY2luZ01vZGUgfTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmICh0eXBlb2YgZmFjaW5nTW9kZSA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGFjdEtleSBpbiBmYWNpbmdNb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaXNWYWxpZEZhY2luZ01vZGVWYWx1ZShmYWNpbmdNb2RlW1wiXCIuY29uY2F0KGV4YWN0S2V5KV0pKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmFjaW5nTW9kZToge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhhY3Q6IGZhY2luZ01vZGVbXCJcIi5jb25jYXQoZXhhY3RLZXkpXVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IFwiJ2ZhY2luZ01vZGUnIHNob3VsZCBiZSBzdHJpbmcgb3Igb2JqZWN0IHdpdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgXCIgXCIuY29uY2F0KGV4YWN0S2V5LCBcIiBhcyBrZXkuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZV8xID0gKHR5cGVvZiBmYWNpbmdNb2RlKTtcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJJbnZhbGlkIHR5cGUgb2YgJ2ZhY2luZ01vZGUnID0gXCIuY29uY2F0KHR5cGVfMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGRldmljZUlkID0gY2FtZXJhSWRPckNvbmZpZy5kZXZpY2VJZDtcbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIGRldmljZUlkID09IFwic3RyaW5nXCIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHsgZGV2aWNlSWQ6IGRldmljZUlkIH07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2UgaWYgKHR5cGVvZiBkZXZpY2VJZCA9PSBcIm9iamVjdFwiKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGFjdEtleSBpbiBkZXZpY2VJZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZXZpY2VJZDogeyBleGFjdDogZGV2aWNlSWRbXCJcIi5jb25jYXQoZXhhY3RLZXkpXSB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCInZGV2aWNlSWQnIHNob3VsZCBiZSBzdHJpbmcgb3Igb2JqZWN0IHdpdGhcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICsgXCIgXCIuY29uY2F0KGV4YWN0S2V5LCBcIiBhcyBrZXkuXCIpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdHlwZV8yID0gKHR5cGVvZiBkZXZpY2VJZCk7XG4gICAgICAgICAgICAgICAgICAgIHRocm93IFwiSW52YWxpZCB0eXBlIG9mICdkZXZpY2VJZCcgPSBcIi5jb25jYXQodHlwZV8yKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHR5cGUgPSAodHlwZW9mIGNhbWVyYUlkT3JDb25maWcpO1xuICAgICAgICB0aHJvdyBcIkludmFsaWQgdHlwZSBvZiAnY2FtZXJhSWRPckNvbmZpZycgPSBcIi5jb25jYXQodHlwZSk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuY29tcHV0ZUNhbnZhc0RyYXdDb25maWcgPSBmdW5jdGlvbiAoaW1hZ2VXaWR0aCwgaW1hZ2VIZWlnaHQsIGNvbnRhaW5lcldpZHRoLCBjb250YWluZXJIZWlnaHQpIHtcbiAgICAgICAgaWYgKGltYWdlV2lkdGggPD0gY29udGFpbmVyV2lkdGhcbiAgICAgICAgICAgICYmIGltYWdlSGVpZ2h0IDw9IGNvbnRhaW5lckhlaWdodCkge1xuICAgICAgICAgICAgdmFyIHhvZmZzZXQgPSAoY29udGFpbmVyV2lkdGggLSBpbWFnZVdpZHRoKSAvIDI7XG4gICAgICAgICAgICB2YXIgeW9mZnNldCA9IChjb250YWluZXJIZWlnaHQgLSBpbWFnZUhlaWdodCkgLyAyO1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICB4OiB4b2Zmc2V0LFxuICAgICAgICAgICAgICAgIHk6IHlvZmZzZXQsXG4gICAgICAgICAgICAgICAgd2lkdGg6IGltYWdlV2lkdGgsXG4gICAgICAgICAgICAgICAgaGVpZ2h0OiBpbWFnZUhlaWdodFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhciBmb3JtZXJJbWFnZVdpZHRoID0gaW1hZ2VXaWR0aDtcbiAgICAgICAgICAgIHZhciBmb3JtZXJJbWFnZUhlaWdodCA9IGltYWdlSGVpZ2h0O1xuICAgICAgICAgICAgaWYgKGltYWdlV2lkdGggPiBjb250YWluZXJXaWR0aCkge1xuICAgICAgICAgICAgICAgIGltYWdlSGVpZ2h0ID0gKGNvbnRhaW5lcldpZHRoIC8gaW1hZ2VXaWR0aCkgKiBpbWFnZUhlaWdodDtcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gY29udGFpbmVyV2lkdGg7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaW1hZ2VIZWlnaHQgPiBjb250YWluZXJIZWlnaHQpIHtcbiAgICAgICAgICAgICAgICBpbWFnZVdpZHRoID0gKGNvbnRhaW5lckhlaWdodCAvIGltYWdlSGVpZ2h0KSAqIGltYWdlV2lkdGg7XG4gICAgICAgICAgICAgICAgaW1hZ2VIZWlnaHQgPSBjb250YWluZXJIZWlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLmxvZ2dlci5sb2coXCJJbWFnZSBkb3duc2FtcGxlZCBmcm9tIFwiXG4gICAgICAgICAgICAgICAgKyBcIlwiLmNvbmNhdChmb3JtZXJJbWFnZVdpZHRoLCBcIlhcIikuY29uY2F0KGZvcm1lckltYWdlSGVpZ2h0KVxuICAgICAgICAgICAgICAgICsgXCIgdG8gXCIuY29uY2F0KGltYWdlV2lkdGgsIFwiWFwiKS5jb25jYXQoaW1hZ2VIZWlnaHQsIFwiLlwiKSk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb21wdXRlQ2FudmFzRHJhd0NvbmZpZyhpbWFnZVdpZHRoLCBpbWFnZUhlaWdodCwgY29udGFpbmVyV2lkdGgsIGNvbnRhaW5lckhlaWdodCk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5jbGVhckVsZW1lbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLnN0YXRlTWFuYWdlclByb3h5LmlzU2Nhbm5pbmcoKSkge1xuICAgICAgICAgICAgdGhyb3cgXCJDYW5ub3QgY2xlYXIgd2hpbGUgc2NhbiBpcyBvbmdvaW5nLCBjbG9zZSBpdCBmaXJzdC5cIjtcbiAgICAgICAgfVxuICAgICAgICB2YXIgZWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZWxlbWVudElkKTtcbiAgICAgICAgaWYgKGVsZW1lbnQpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnBvc3NpYmx5VXBkYXRlU2hhZGVycyA9IGZ1bmN0aW9uIChxck1hdGNoKSB7XG4gICAgICAgIGlmICh0aGlzLnFyTWF0Y2ggPT09IHFyTWF0Y2gpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGhpcy5oYXNCb3JkZXJTaGFkZXJzXG4gICAgICAgICAgICAmJiB0aGlzLmJvcmRlclNoYWRlcnNcbiAgICAgICAgICAgICYmIHRoaXMuYm9yZGVyU2hhZGVycy5sZW5ndGgpIHtcbiAgICAgICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycy5mb3JFYWNoKGZ1bmN0aW9uIChzaGFkZXIpIHtcbiAgICAgICAgICAgICAgICBzaGFkZXIuc3R5bGUuYmFja2dyb3VuZENvbG9yID0gcXJNYXRjaFxuICAgICAgICAgICAgICAgICAgICA/IENvbnN0YW50cy5CT1JERVJfU0hBREVSX01BVENIX0NPTE9SXG4gICAgICAgICAgICAgICAgICAgIDogQ29uc3RhbnRzLkJPUkRFUl9TSEFERVJfREVGQVVMVF9DT0xPUjtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucXJNYXRjaCA9IHFyTWF0Y2g7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUucG9zc2libHlDbG9zZUxhc3RTY2FuSW1hZ2VGaWxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5sYXN0U2NhbkltYWdlRmlsZSkge1xuICAgICAgICAgICAgVVJMLnJldm9rZU9iamVjdFVSTCh0aGlzLmxhc3RTY2FuSW1hZ2VGaWxlKTtcbiAgICAgICAgICAgIHRoaXMubGFzdFNjYW5JbWFnZUZpbGUgPSBudWxsO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuY3JlYXRlQ2FudmFzRWxlbWVudCA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0LCBjdXN0b21JZCkge1xuICAgICAgICB2YXIgY2FudmFzV2lkdGggPSB3aWR0aDtcbiAgICAgICAgdmFyIGNhbnZhc0hlaWdodCA9IGhlaWdodDtcbiAgICAgICAgdmFyIGNhbnZhc0VsZW1lbnQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiY2FudmFzXCIpO1xuICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQoY2FudmFzV2lkdGgsIFwicHhcIik7XG4gICAgICAgIGNhbnZhc0VsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gXCJcIi5jb25jYXQoY2FudmFzSGVpZ2h0LCBcInB4XCIpO1xuICAgICAgICBjYW52YXNFbGVtZW50LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgY2FudmFzRWxlbWVudC5pZCA9IGlzTnVsbE9yVW5kZWZpbmVkKGN1c3RvbUlkKVxuICAgICAgICAgICAgPyBcInFyLWNhbnZhc1wiIDogY3VzdG9tSWQ7XG4gICAgICAgIHJldHVybiBjYW52YXNFbGVtZW50O1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmdldFNoYWRlZFJlZ2lvbkJvdW5kcyA9IGZ1bmN0aW9uICh3aWR0aCwgaGVpZ2h0LCBxcmJveFNpemUpIHtcbiAgICAgICAgaWYgKHFyYm94U2l6ZS53aWR0aCA+IHdpZHRoIHx8IHFyYm94U2l6ZS5oZWlnaHQgPiBoZWlnaHQpIHtcbiAgICAgICAgICAgIHRocm93IFwiJ2NvbmZpZy5xcmJveCcgZGltZW5zaW9ucyBzaG91bGQgbm90IGJlIGdyZWF0ZXIgdGhhbiB0aGUgXCJcbiAgICAgICAgICAgICAgICArIFwiZGltZW5zaW9ucyBvZiB0aGUgcm9vdCBIVE1MIGVsZW1lbnQuXCI7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHg6ICh3aWR0aCAtIHFyYm94U2l6ZS53aWR0aCkgLyAyLFxuICAgICAgICAgICAgeTogKGhlaWdodCAtIHFyYm94U2l6ZS5oZWlnaHQpIC8gMixcbiAgICAgICAgICAgIHdpZHRoOiBxcmJveFNpemUud2lkdGgsXG4gICAgICAgICAgICBoZWlnaHQ6IHFyYm94U2l6ZS5oZWlnaHRcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlLnByb3RvdHlwZS5wb3NzaWJseUluc2VydFNoYWRpbmdFbGVtZW50ID0gZnVuY3Rpb24gKGVsZW1lbnQsIHdpZHRoLCBoZWlnaHQsIHFyYm94U2l6ZSkge1xuICAgICAgICBpZiAoKHdpZHRoIC0gcXJib3hTaXplLndpZHRoKSA8IDEgfHwgKGhlaWdodCAtIHFyYm94U2l6ZS5oZWlnaHQpIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzaGFkaW5nRWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB2YXIgcmlnaHRMZWZ0Qm9yZGVyU2l6ZSA9ICh3aWR0aCAtIHFyYm94U2l6ZS53aWR0aCkgLyAyO1xuICAgICAgICB2YXIgdG9wQm90dG9tQm9yZGVyU2l6ZSA9IChoZWlnaHQgLSBxcmJveFNpemUuaGVpZ2h0KSAvIDI7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlckxlZnRcbiAgICAgICAgICAgID0gXCJcIi5jb25jYXQocmlnaHRMZWZ0Qm9yZGVyU2l6ZSwgXCJweCBzb2xpZCByZ2JhKDAsIDAsIDAsIDAuNDgpXCIpO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3JkZXJSaWdodFxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdChyaWdodExlZnRCb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlclRvcFxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdCh0b3BCb3R0b21Cb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJvcmRlckJvdHRvbVxuICAgICAgICAgICAgPSBcIlwiLmNvbmNhdCh0b3BCb3R0b21Cb3JkZXJTaXplLCBcInB4IHNvbGlkIHJnYmEoMCwgMCwgMCwgMC40OClcIik7XG4gICAgICAgIHNoYWRpbmdFbGVtZW50LnN0eWxlLmJveFNpemluZyA9IFwiYm9yZGVyLWJveFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS50b3AgPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5ib3R0b20gPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5zdHlsZS5sZWZ0ID0gXCIwcHhcIjtcbiAgICAgICAgc2hhZGluZ0VsZW1lbnQuc3R5bGUucmlnaHQgPSBcIjBweFwiO1xuICAgICAgICBzaGFkaW5nRWxlbWVudC5pZCA9IFwiXCIuY29uY2F0KENvbnN0YW50cy5TSEFERURfUkVHSU9OX0VMRU1FTlRfSUQpO1xuICAgICAgICBpZiAoKHdpZHRoIC0gcXJib3hTaXplLndpZHRoKSA8IDExXG4gICAgICAgICAgICB8fCAoaGVpZ2h0IC0gcXJib3hTaXplLmhlaWdodCkgPCAxMSkge1xuICAgICAgICAgICAgdGhpcy5oYXNCb3JkZXJTaGFkZXJzID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB2YXIgc21hbGxTaXplID0gNTtcbiAgICAgICAgICAgIHZhciBsYXJnZVNpemUgPSA0MDtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgbGFyZ2VTaXplLCBzbWFsbFNpemUsIC1zbWFsbFNpemUsIG51bGwsIDAsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBsYXJnZVNpemUsIHNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgbnVsbCwgMCwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBsYXJnZVNpemUsIHNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgMCwgdHJ1ZSk7XG4gICAgICAgICAgICB0aGlzLmluc2VydFNoYWRlckJvcmRlcnMoc2hhZGluZ0VsZW1lbnQsIGxhcmdlU2l6ZSwgc21hbGxTaXplLCBudWxsLCAtc21hbGxTaXplLCAwLCBmYWxzZSk7XG4gICAgICAgICAgICB0aGlzLmluc2VydFNoYWRlckJvcmRlcnMoc2hhZGluZ0VsZW1lbnQsIHNtYWxsU2l6ZSwgbGFyZ2VTaXplICsgc21hbGxTaXplLCAtc21hbGxTaXplLCBudWxsLCAtc21hbGxTaXplLCB0cnVlKTtcbiAgICAgICAgICAgIHRoaXMuaW5zZXJ0U2hhZGVyQm9yZGVycyhzaGFkaW5nRWxlbWVudCwgc21hbGxTaXplLCBsYXJnZVNpemUgKyBzbWFsbFNpemUsIG51bGwsIC1zbWFsbFNpemUsIC1zbWFsbFNpemUsIHRydWUpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBzbWFsbFNpemUsIGxhcmdlU2l6ZSArIHNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRTaGFkZXJCb3JkZXJzKHNoYWRpbmdFbGVtZW50LCBzbWFsbFNpemUsIGxhcmdlU2l6ZSArIHNtYWxsU2l6ZSwgbnVsbCwgLXNtYWxsU2l6ZSwgLXNtYWxsU2l6ZSwgZmFsc2UpO1xuICAgICAgICAgICAgdGhpcy5oYXNCb3JkZXJTaGFkZXJzID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbGVtZW50LmFwcGVuZChzaGFkaW5nRWxlbWVudCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuaW5zZXJ0U2hhZGVyQm9yZGVycyA9IGZ1bmN0aW9uIChzaGFkZXJFbGVtLCB3aWR0aCwgaGVpZ2h0LCB0b3AsIGJvdHRvbSwgc2lkZSwgaXNMZWZ0KSB7XG4gICAgICAgIHZhciBlbGVtID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZWxlbS5zdHlsZS5wb3NpdGlvbiA9IFwiYWJzb2x1dGVcIjtcbiAgICAgICAgZWxlbS5zdHlsZS5iYWNrZ3JvdW5kQ29sb3IgPSBDb25zdGFudHMuQk9SREVSX1NIQURFUl9ERUZBVUxUX0NPTE9SO1xuICAgICAgICBlbGVtLnN0eWxlLndpZHRoID0gXCJcIi5jb25jYXQod2lkdGgsIFwicHhcIik7XG4gICAgICAgIGVsZW0uc3R5bGUuaGVpZ2h0ID0gXCJcIi5jb25jYXQoaGVpZ2h0LCBcInB4XCIpO1xuICAgICAgICBpZiAodG9wICE9PSBudWxsKSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLnRvcCA9IFwiXCIuY29uY2F0KHRvcCwgXCJweFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYm90dG9tICE9PSBudWxsKSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLmJvdHRvbSA9IFwiXCIuY29uY2F0KGJvdHRvbSwgXCJweFwiKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoaXNMZWZ0KSB7XG4gICAgICAgICAgICBlbGVtLnN0eWxlLmxlZnQgPSBcIlwiLmNvbmNhdChzaWRlLCBcInB4XCIpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZWxlbS5zdHlsZS5yaWdodCA9IFwiXCIuY29uY2F0KHNpZGUsIFwicHhcIik7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCF0aGlzLmJvcmRlclNoYWRlcnMpIHtcbiAgICAgICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycyA9IFtdO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuYm9yZGVyU2hhZGVycy5wdXNoKGVsZW0pO1xuICAgICAgICBzaGFkZXJFbGVtLmFwcGVuZENoaWxkKGVsZW0pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLnNob3dQYXVzZWRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRocm93IFwiW2ludGVybmFsIGVycm9yXSBzY2FubmVyIHBhdXNlZCBVSSBlbGVtZW50IG5vdCBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGUucHJvdG90eXBlLmhpZGVQYXVzZWRTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgaWYgKCF0aGlzLnNjYW5uZXJQYXVzZWRVaUVsZW1lbnQpIHtcbiAgICAgICAgICAgIHRocm93IFwiW2ludGVybmFsIGVycm9yXSBzY2FubmVyIHBhdXNlZCBVSSBlbGVtZW50IG5vdCBmb3VuZFwiO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuc2Nhbm5lclBhdXNlZFVpRWxlbWVudC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZS5wcm90b3R5cGUuZ2V0VGltZW91dEZwcyA9IGZ1bmN0aW9uIChmcHMpIHtcbiAgICAgICAgcmV0dXJuIDEwMDAgLyBmcHM7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGU7XG59KCkpO1xuZXhwb3J0IHsgSHRtbDVRcmNvZGUgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWh0bWw1LXFyY29kZS5qcy5tYXAiLCJ2YXIgU1ZHX1hNTF9QUkVGSVggPSBcImRhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsXCI7XG5leHBvcnQgdmFyIEFTU0VUX0NBTUVSQV9TQ0FOID0gU1ZHX1hNTF9QUkVGSVggKyBcIlBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSFpwWlhkQ2IzZzlJakFnTUNBek56RXVOalF6SURNM01TNDJORE1pSUhOMGVXeGxQU0psYm1GaWJHVXRZbUZqYTJkeWIzVnVaRHB1WlhjZ01DQXdJRE0zTVM0Mk5ETWdNemN4TGpZME15SWdlRzFzT25Od1lXTmxQU0p3Y21WelpYSjJaU0krUEhCaGRHZ2daRDBpVFRFd05TNHdPRFFnTXpndU1qY3hhREUyTXk0M05qaDJNakJJTVRBMUxqQTROSG9pTHo0OGNHRjBhQ0JrUFNKTk16RXhMalU1TmlBeE9UQXVNVGc1WXkwM0xqUTBNUzA1TGpNME55MHhPQzQwTURNdE1UWXVNakEyTFRNeUxqYzBNeTB5TUM0MU1qSldNekJqTUMweE5pNDFOREl0TVRNdU5EVTRMVE13TFRNd0xUTXdTREV5TlM0d09EUmpMVEUyTGpVME1pQXdMVE13SURFekxqUTFPQzB6TUNBek1IWXhNakF1TVRRemFDMDRMakk1Tm1NdE1UWXVOVFF5SURBdE16QWdNVE11TkRVNExUTXdJRE13ZGpFdU16TXpZVEk1TGpnd05DQXlPUzQ0TURRZ01DQXdJREFnTkM0Mk1ETWdNVFV1T1RNNVl5MDNMak0wSURVdU5EYzBMVEV5TGpFd015QXhOQzR5TWpFdE1USXVNVEF6SURJMExqQTJNWFl4TGpNek0yTXdJRGt1T0RRZ05DNDNOak1nTVRndU5UZzNJREV5TGpFd015QXlOQzR3TmpKaE1qa3VPREVnTWprdU9ERWdNQ0F3SURBdE5DNDJNRE1nTVRVdU9UTTRkakV1TXpNell6QWdNVFl1TlRReUlERXpMalExT0NBek1DQXpNQ0F6TUdnNExqTXlOR011TkRJM0lERXhMall6TVNBM0xqVXdNeUF5TVM0MU9EY2dNVGN1TlRNMElESTJMakUzTnk0NU16RWdNVEF1TlRBeklEUXVNRGcwSURNd0xqRTROeUF4TkM0M05qZ2dORFV1TlRNM1lUa3VPVGc0SURrdU9UZzRJREFnTUNBd0lEZ3VNakUySURRdU1qZzRJRGt1T1RVNElEa3VPVFU0SURBZ01DQXdJRFV1TnpBMExURXVOemt6WXpRdU5UTXpMVE11TVRVMUlEVXVOalV0T1M0ek9EZ2dNaTQwT1RVdE1UTXVPVEl4TFRZdU56azRMVGt1TnpZM0xUa3VOakF5TFRJeUxqWXdPQzB4TUM0M05pMHpNUzQwYURneUxqWTROV011TWpjeUxqUXhOQzQxTkRVdU9ERTRMamd4TlNBeExqSXhJRE11TVRReUlEUXVOVFF4SURrdU16Y3lJRFV1TmpjNUlERXpMamt4TXlBeUxqVXpOQ0EwTGpVME1pMHpMakUwTWlBMUxqWTNOeTA1TGpNM01TQXlMalV6TlMweE15NDVNVE10TVRFdU9URTVMVEUzTGpJeU9TMDRMamM0Tnkwek5TNDRPRFFnT1M0MU9ERXROVGN1TURFeUlETXVNRFkzTFRJdU5qVXlJREV5TGpNd055MHhNUzQzTXpJZ01URXVNakUzTFRJMExqQXpNeTB1T0RJNExUa3VNelF6TFRjdU1UQTVMVEUzTGpFNU5DMHhPQzQyTmprdE1qTXVNek0zWVRrdU9EVTNJRGt1T0RVM0lEQWdNQ0F3TFRFdU1EWXhMUzQwT0RaakxTNDBOall0TGpFNE1pMHhNUzQwTURNdE5DNDFOemt0T1M0M05ERXRNVFV1TnpBMklERXVNREEzTFRZdU56TTNJREUwTGpjMk9DMDRMakkzTXlBeU15NDNOall0Tnk0Mk5qWWdNak11TVRVMklERXVOVFk1SURNNUxqWTVPQ0EzTGpnd015QTBOeTQ0TXpZZ01UZ3VNREkySURVdU56VXlJRGN1TWpJMUlEY3VOakEzSURFMkxqWXlNeUExTGpZM015QXlPQzQzTXpNdExqUXhNeUF5TGpVNE5TMHVPREkwSURVdU1qUXhMVEV1TWpRMUlEY3VPVFU1TFRVdU56VTJJRE0zTGpFNU5DMHhNaTQ1TVRrZ09ETXVORGd6TFRRNUxqZzNJREV4TkM0Mk5qRXROQzR5TWpFZ015NDFOakV0TkM0M05UWWdPUzQ0TnkweExqRTVOQ0F4TkM0d09USmhPUzQ1T0NBNUxqazRJREFnTUNBd0lEY3VOalE0SURNdU5UVXhJRGt1T1RVMUlEa3VPVFUxSURBZ01DQXdJRFl1TkRRMExUSXVNelU0WXpReUxqWTNNaTB6Tmk0d01EVWdOVEF1T0RBeUxUZzRMalV6TXlBMU5pNDNNemN0TVRJMkxqZzRPQzQwTVRVdE1pNDJPRFF1T0RJeExUVXVNekE1SURFdU1qSTVMVGN1T0RZeklESXVPRE0wTFRFM0xqY3lNUzB1TkRVMUxUTXlMalkwTVMwNUxqYzNNaTAwTkM0ek5EVjZiUzB5TXpJdU16QTRJRFF5TGpZeVl5MDFMalV4TkNBd0xURXdMVFF1TkRnMkxURXdMVEV3ZGkweExqTXpNMk13TFRVdU5URTBJRFF1TkRnMkxURXdJREV3TFRFd2FERTFkakl4TGpNek0yZ3RNVFY2YlMweUxqVXROVEl1TmpZMll6QXROUzQxTVRRZ05DNDBPRFl0TVRBZ01UQXRNVEJvTnk0MWRqSXhMak16TTJndE55NDFZeTAxTGpVeE5DQXdMVEV3TFRRdU5EZzJMVEV3TFRFd2RpMHhMak16TTNwdE1UY3VOU0E1TXk0NU9UbG9MVGN1TldNdE5TNDFNVFFnTUMweE1DMDBMalE0TmkweE1DMHhNSFl0TVM0ek16TmpNQzAxTGpVeE5DQTBMalE0TmkweE1DQXhNQzB4TUdnM0xqVjJNakV1TXpNemVtMHpNQzQzT1RZZ01qZ3VPRGczWXkwMUxqVXhOQ0F3TFRFd0xUUXVORGcyTFRFd0xURXdkaTA0TGpJM01XZzVNUzQwTlRkakxTNDROVEVnTmk0Mk5qZ3RMalF6TnlBeE1pNDNPRGN1TnpNeElERTRMakkzTVdndE9ESXVNVGc0ZW0wM09TNDBPREl0TVRFekxqWTVPR010TXk0eE1qUWdNakF1T1RBMklERXlMalF5TnlBek15NHhPRFFnTWpFdU5qSTFJRE0zTGpBMElEVXVORFF4SURJdU9UWTRJRGN1TlRVeElEVXVOalEzSURjdU56QXhJRGN1TVRnNExqSXhJREl1TVRVdE1pNDFOVE1nTlM0Mk9EUXROQzQwTnpjZ055NHlOVEV0TGpRNE1pNHpOemd0TGpreU9TNDRMVEV1TXpNMUlERXVNall4TFRZdU9UZzNJRGN1T1RNMkxURXhMams0TWlBeE5TNDFNaTB4TlM0ME16SWdNakl1TmpnNGFDMDVOeTQxTmpSV016QmpNQzAxTGpVeE5DQTBMalE0TmkweE1DQXhNQzB4TUdneE1qTXVOelk1WXpVdU5URTBJREFnTVRBZ05DNDBPRFlnTVRBZ01UQjJNVE0xTGpVM09XTXRNeTR3TXpJdExqTTRNUzAyTGpFMUxTNDJPVFF0T1M0ek9Ea3RMamt4TkMweU5TNHhOVGt0TVM0Mk9UUXROREl1TXpjZ055NDNORGd0TkRRdU9EazRJREkwTGpZMk5ub2lMejQ4Y0dGMGFDQmtQU0pOTVRjNUxqRXlPU0E0TXk0eE5qZG9MVEkwTGpBMllUVWdOU0F3SURBZ01DMDFJRFYyTWpRdU1EWXhZVFVnTlNBd0lEQWdNQ0ExSURWb01qUXVNRFpoTlNBMUlEQWdNQ0F3SURVdE5WWTRPQzR4TmpkaE5TQTFJREFnTUNBd0xUVXROWHBOTVRjeUxqWXlPU0F4TkRJdU9EWm9MVEV5TGpVMlZqRXpNQzQ0WVRVZ05TQXdJREVnTUMweE1DQXdkakUzTGpBMk1XRTFJRFVnTUNBd0lEQWdOU0ExYURFM0xqVTJZVFVnTlNBd0lERWdNQ0F3TFRFd0xqQXdNWHBOTWpFMkxqVTJPQ0E0TXk0eE5qZG9MVEkwTGpBMllUVWdOU0F3SURBZ01DMDFJRFYyTWpRdU1EWXhZVFVnTlNBd0lEQWdNQ0ExSURWb01qUXVNRFpoTlNBMUlEQWdNQ0F3SURVdE5WWTRPQzR4TmpkaE5TQTFJREFnTUNBd0xUVXROWHB0TFRVZ01qUXVNRFl4YUMweE5DNHdObFk1TXk0eE5qZG9NVFF1TURaMk1UUXVNRFl4ZWsweU1URXVOalk1SURFeU5TNDVNelpJTVRrM0xqUXhZVFVnTlNBd0lEQWdNQzAxSURWMk1UUXVNalUzWVRVZ05TQXdJREFnTUNBMUlEVm9NVFF1TWpVNVlUVWdOU0F3SURBZ01DQTFMVFYyTFRFMExqSTFOMkUxSURVZ01DQXdJREF0TlMwMWVpSXZQand2YzNablBnPT1cIjtcbmV4cG9ydCB2YXIgQVNTRVRfRklMRV9TQ0FOID0gU1ZHX1hNTF9QUkVGSVggKyBcIlBITjJaeUI0Yld4dWN6MGlhSFIwY0RvdkwzZDNkeTUzTXk1dmNtY3ZNakF3TUM5emRtY2lJSFpwWlhkQ2IzZzlJakFnTUNBMU9TNHdNVGdnTlRrdU1ERTRJaUJ6ZEhsc1pUMGlaVzVoWW14bExXSmhZMnRuY205MWJtUTZibVYzSURBZ01DQTFPUzR3TVRnZ05Ua3VNREU0SWlCNGJXdzZjM0JoWTJVOUluQnlaWE5sY25abElqNDhjR0YwYUNCa1BTSnROVGd1TnpReElEVTBMamd3T1MwMUxqazJPUzAyTGpJME5HRXhNQzQzTkNBeE1DNDNOQ0F3SURBZ01DQXlMamd5TFRjdU1qVmpNQzAxTGprMU15MDBMamcwTXkweE1DNDNPVFl0TVRBdU56azJMVEV3TGpjNU5sTXpOQ0F6TlM0ek5qRWdNelFnTkRFdU16RTBJRE00TGpnME15QTFNaTR4TVNBME5DNDNPVFlnTlRJdU1URmpNaTQwTkRFZ01DQTBMalk0T0MwdU9ESTBJRFl1TkRrNUxUSXVNVGsyYkRZdU1EQXhJRFl1TWpjM1lTNDVPVGd1T1RrNElEQWdNQ0F3SURFdU5ERTBMakF6TWlBeElERWdNQ0F3SURBZ0xqQXpNUzB4TGpReE5IcE5NellnTkRFdU16RTBZekF0TkM0NE5TQXpMamswTmkwNExqYzVOaUE0TGpjNU5pMDRMamM1Tm5NNExqYzVOaUF6TGprME5pQTRMamM1TmlBNExqYzVOaTB6TGprME5pQTRMamM1TmkwNExqYzVOaUE0TGpjNU5sTXpOaUEwTmk0eE5qUWdNellnTkRFdU16RTBlazB4TUM0ME16RWdNVFl1TURnNFl6QWdNeTR3TnlBeUxqUTVPQ0ExTGpVMk9DQTFMalUyT1NBMUxqVTJPSE0xTGpVMk9TMHlMalE1T0NBMUxqVTJPUzAxTGpVMk9HTXdMVE11TURjeExUSXVORGs0TFRVdU5UWTVMVFV1TlRZNUxUVXVOVFk1Y3kwMUxqVTJPU0F5TGpRNU9DMDFMalUyT1NBMUxqVTJPWHB0T1M0eE16Z2dNR013SURFdU9UWTRMVEV1TmpBeUlETXVOVFk0TFRNdU5UWTVJRE11TlRZNGN5MHpMalUyT1MweExqWXdNUzB6TGpVMk9TMHpMalUyT0NBeExqWXdNaTB6TGpVMk9TQXpMalUyT1MwekxqVTJPU0F6TGpVMk9TQXhMall3TVNBekxqVTJPU0F6TGpVMk9Yb2lMejQ4Y0dGMGFDQmtQU0p0TXpBdU9EZ3lJREk0TGprNE55QTVMakU0TFRFd0xqQTFOQ0F4TVM0eU5qSWdNVEF1TXpJellURWdNU0F3SURBZ01DQXhMak0xTVMweExqUTNOV3d0TVRJdE1URmhNU0F4SURBZ01DQXdMVEV1TkRFMExqQTJNMnd0T1M0M09UUWdNVEF1TnpJM0xUUXVOelF6TFRRdU56UXpZVEV1TURBeklERXVNREF6SURBZ01DQXdMVEV1TXpZNExTNHdORFJNTmk0ek16a2dNemN1TnpZNFlURWdNU0F3SURFZ01DQXhMak15TWlBeExqVXdNV3d4Tmk0ek1UTXRNVFF1TXpZeUlEY3VNekU1SURjdU16RTRZUzQ1T1RrdU9UazVJREFnTVNBd0lERXVOREUwTFRFdU5ERTBiQzB4TGpneU5TMHhMamd5TkhvaUx6NDhjR0YwYUNCa1BTSk5NekFnTkRZdU5URTRTREoyTFRReWFEVTBkakk0WVRFZ01TQXdJREVnTUNBeUlEQjJMVEk1WVRFZ01TQXdJREFnTUMweExURklNV0V4SURFZ01DQXdJREF0TVNBeGRqUTBZVEVnTVNBd0lEQWdNQ0F4SURGb01qbGhNU0F4SURBZ01TQXdJREF0TW5vaUx6NDhMM04yWno0PVwiO1xuZXhwb3J0IHZhciBBU1NFVF9JTkZPX0lDT05fMTZQWCA9IFNWR19YTUxfUFJFRklYICsgXCJQSE4yWnlCNGJXeHVjejBpYUhSMGNEb3ZMM2QzZHk1M015NXZjbWN2TWpBd01DOXpkbWNpSUhacFpYZENiM2c5SWpBZ01DQTBOakFnTkRZd0lpQnpkSGxzWlQwaVpXNWhZbXhsTFdKaFkydG5jbTkxYm1RNmJtVjNJREFnTUNBME5qQWdORFl3SWlCNGJXdzZjM0JoWTJVOUluQnlaWE5sY25abElqNDhjR0YwYUNCa1BTSk5Nak13SURCRE1UQXlMamszTlNBd0lEQWdNVEF5TGprM05TQXdJREl6TUhNeE1ESXVPVGMxSURJek1DQXlNekFnTWpNd0lESXpNQzB4TURJdU9UYzBJREl6TUMweU16QlRNelUzTGpBeU5TQXdJREl6TUNBd2VtMHpPQzR6TXpNZ016YzNMak0yWXpBZ09DNDJOell0Tnk0d016UWdNVFV1TnpFdE1UVXVOekVnTVRVdU56Rm9MVFF6TGpFd01XTXRPQzQyTnpZZ01DMHhOUzQzTVMwM0xqQXpOQzB4TlM0M01TMHhOUzQzTVZZeU1ESXVORGMzWXpBdE9DNDJOellnTnk0d016TXRNVFV1TnpFZ01UVXVOekV0TVRVdU56Rm9ORE11TVRBeFl6Z3VOamMySURBZ01UVXVOekVnTnk0d016TWdNVFV1TnpFZ01UVXVOekZXTXpjM0xqTTJlazB5TXpBZ01UVTNZeTB5TVM0MU16a2dNQzB6T1MweE55NDBOakV0TXprdE16bHpNVGN1TkRZeExUTTVJRE01TFRNNUlETTVJREUzTGpRMk1TQXpPU0F6T1MweE55NDBOakVnTXprdE16a2dNemw2SWk4K1BDOXpkbWMrXCI7XG5leHBvcnQgdmFyIEFTU0VUX0NMT1NFX0lDT05fMTZQWCA9IFwiZGF0YTppbWFnZS9wbmc7YmFzZTY0LGlWQk9SdzBLR2dvQUFBQU5TVWhFVWdBQUFCQUFBQUFRQ0FZQUFBQWY4LzloQUFBQUJITkNTVlFJQ0FnSWZBaGtpQUFBQUFsd1NGbHpBQUFBUWdBQUFFSUJhcnFRUkFBQUFCbDBSVmgwVTI5bWRIZGhjbVVBZDNkM0xtbHVhM05qWVhCbExtOXlaNXZ1UEJvQUFBRTFTVVJCVkRpTmZkSTdTME5CRUFYZ0x5YTFvdEZncGJZU2JJU0FncFhZaTZDbWlIOUtDQWlDaGFWZ2E2T2lXUGdmUkRRKzBpdGFHVk5vc1h0bHVXd2N1TXplUGZNNE0zc3E4bGJIQnVid2cxZGM0bTFFL0ovTjRnaERQT0lzZmsvNHhpRWFvNUtYME1jRmxqTjRDOWQ0UVRQWHVZOTlqUDNEc0lvRFBHTTZCWTVpNXlJNVI3TzRxK0ltRmtKWTJEQ2gzY0FIMmtseUIrOUoxeFVNTUFHN2VDaDFhK01yK2s0OGI1ZGlYckZWd3dMdVMrQko5TWZSNytHMEZIT0hoVEhoblhOV1M4N1ZERjRwY25mUUs0RXA3WFNjTkxtUFRaZ1VSTktLWUVOWVdEcHpXMUJoc2NTMVdIUzhDRGdVUkZKUXJXY29GM2MxM0tLYmdnMUJZUWZ5OHhaV0V6VFR3MVFaYkFvS3U4RnFKbmt0ZHU1aGNWU0htY2hpSUx6enVhRFF2akJ6VjJtOHlvaENFMWpIZlB4L3hoVSt5NEcvRDc1RUxsUkpzU1lBQUFBQVNVVk9SSzVDWUlJPVwiO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aW1hZ2UtYXNzZXRzLmpzLm1hcCIsInZhciBQZXJzaXN0ZWREYXRhRmFjdG9yeSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUGVyc2lzdGVkRGF0YUZhY3RvcnkoKSB7XG4gICAgfVxuICAgIFBlcnNpc3RlZERhdGFGYWN0b3J5LmNyZWF0ZURlZmF1bHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBoYXNQZXJtaXNzaW9uOiBmYWxzZSxcbiAgICAgICAgICAgIGxhc3RVc2VkQ2FtZXJhSWQ6IG51bGxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIHJldHVybiBQZXJzaXN0ZWREYXRhRmFjdG9yeTtcbn0oKSk7XG52YXIgUGVyc2lzdGVkRGF0YU1hbmFnZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFBlcnNpc3RlZERhdGFNYW5hZ2VyKCkge1xuICAgICAgICB0aGlzLmRhdGEgPSBQZXJzaXN0ZWREYXRhRmFjdG9yeS5jcmVhdGVEZWZhdWx0KCk7XG4gICAgICAgIHZhciBkYXRhID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oUGVyc2lzdGVkRGF0YU1hbmFnZXIuTE9DQUxfU1RPUkFHRV9LRVkpO1xuICAgICAgICBpZiAoIWRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMucmVzZXQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuZGF0YSA9IEpTT04ucGFyc2UoZGF0YSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLmhhc0NhbWVyYVBlcm1pc3Npb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kYXRhLmhhc1Blcm1pc3Npb247XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUuZ2V0TGFzdFVzZWRDYW1lcmFJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZGF0YS5sYXN0VXNlZENhbWVyYUlkO1xuICAgIH07XG4gICAgUGVyc2lzdGVkRGF0YU1hbmFnZXIucHJvdG90eXBlLnNldEhhc1Blcm1pc3Npb24gPSBmdW5jdGlvbiAoaGFzUGVybWlzc2lvbikge1xuICAgICAgICB0aGlzLmRhdGEuaGFzUGVybWlzc2lvbiA9IGhhc1Blcm1pc3Npb247XG4gICAgICAgIHRoaXMuZmx1c2goKTtcbiAgICB9O1xuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLnByb3RvdHlwZS5zZXRMYXN0VXNlZENhbWVyYUlkID0gZnVuY3Rpb24gKGxhc3RVc2VkQ2FtZXJhSWQpIHtcbiAgICAgICAgdGhpcy5kYXRhLmxhc3RVc2VkQ2FtZXJhSWQgPSBsYXN0VXNlZENhbWVyYUlkO1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUucmVzZXRMYXN0VXNlZENhbWVyYUlkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmRhdGEubGFzdFVzZWRDYW1lcmFJZCA9IG51bGw7XG4gICAgICAgIHRoaXMuZmx1c2goKTtcbiAgICB9O1xuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLnByb3RvdHlwZS5yZXNldCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy5kYXRhID0gUGVyc2lzdGVkRGF0YUZhY3RvcnkuY3JlYXRlRGVmYXVsdCgpO1xuICAgICAgICB0aGlzLmZsdXNoKCk7XG4gICAgfTtcbiAgICBQZXJzaXN0ZWREYXRhTWFuYWdlci5wcm90b3R5cGUuZmx1c2ggPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKFBlcnNpc3RlZERhdGFNYW5hZ2VyLkxPQ0FMX1NUT1JBR0VfS0VZLCBKU09OLnN0cmluZ2lmeSh0aGlzLmRhdGEpKTtcbiAgICB9O1xuICAgIFBlcnNpc3RlZERhdGFNYW5hZ2VyLkxPQ0FMX1NUT1JBR0VfS0VZID0gXCJIVE1MNV9RUkNPREVfREFUQVwiO1xuICAgIHJldHVybiBQZXJzaXN0ZWREYXRhTWFuYWdlcjtcbn0oKSk7XG5leHBvcnQgeyBQZXJzaXN0ZWREYXRhTWFuYWdlciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c3RvcmFnZS5qcy5tYXAiLCJpbXBvcnQgeyBBU1NFVF9DTE9TRV9JQ09OXzE2UFgsIEFTU0VUX0lORk9fSUNPTl8xNlBYIH0gZnJvbSBcIi4vaW1hZ2UtYXNzZXRzXCI7XG5pbXBvcnQgeyBMaWJyYXJ5SW5mb1N0cmluZ3MgfSBmcm9tIFwiLi9zdHJpbmdzXCI7XG52YXIgTGlicmFyeUluZm9EaXYgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExpYnJhcnlJbmZvRGl2KCkge1xuICAgICAgICB0aGlzLmluZm9EaXYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgIH1cbiAgICBMaWJyYXJ5SW5mb0Rpdi5wcm90b3R5cGUucmVuZGVySW50byA9IGZ1bmN0aW9uIChwYXJlbnQpIHtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLnBvc2l0aW9uID0gXCJhYnNvbHV0ZVwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUudG9wID0gXCIxMHB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5yaWdodCA9IFwiMTBweFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuekluZGV4ID0gXCIyXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5wYWRkaW5nID0gXCI1cHRcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmJvcmRlciA9IFwiMXB4IHNvbGlkICMxNzE3MTdcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmZvbnRTaXplID0gXCIxMHB0XCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5iYWNrZ3JvdW5kID0gXCJyZ2IoMCAwIDAgLyA2OSUpXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5zdHlsZS5ib3JkZXJSYWRpdXMgPSBcIjVweFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LnN0eWxlLmZvbnRXZWlnaHQgPSBcIjQwMFwiO1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuY29sb3IgPSBcIndoaXRlXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5pbm5lclRleHQgPSBMaWJyYXJ5SW5mb1N0cmluZ3MucG93ZXJlZEJ5KCk7XG4gICAgICAgIHZhciBwcm9qZWN0TGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xuICAgICAgICBwcm9qZWN0TGluay5pbm5lclRleHQgPSBcIlNjYW5BcHBcIjtcbiAgICAgICAgcHJvamVjdExpbmsuaHJlZiA9IFwiaHR0cHM6Ly9zY2FuYXBwLm9yZ1wiO1xuICAgICAgICBwcm9qZWN0TGluay50YXJnZXQgPSBcIm5ld1wiO1xuICAgICAgICBwcm9qZWN0TGluay5zdHlsZS5jb2xvciA9IFwid2hpdGVcIjtcbiAgICAgICAgdGhpcy5pbmZvRGl2LmFwcGVuZENoaWxkKHByb2plY3RMaW5rKTtcbiAgICAgICAgdmFyIGJyZWFrRWxlbUZpcnN0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJyXCIpO1xuICAgICAgICB2YXIgYnJlYWtFbGVtU2Vjb25kID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImJyXCIpO1xuICAgICAgICB0aGlzLmluZm9EaXYuYXBwZW5kQ2hpbGQoYnJlYWtFbGVtRmlyc3QpO1xuICAgICAgICB0aGlzLmluZm9EaXYuYXBwZW5kQ2hpbGQoYnJlYWtFbGVtU2Vjb25kKTtcbiAgICAgICAgdmFyIHJlcG9ydElzc3VlTGluayA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJhXCIpO1xuICAgICAgICByZXBvcnRJc3N1ZUxpbmsuaW5uZXJUZXh0ID0gTGlicmFyeUluZm9TdHJpbmdzLnJlcG9ydElzc3VlcygpO1xuICAgICAgICByZXBvcnRJc3N1ZUxpbmsuaHJlZiA9IFwiaHR0cHM6Ly9naXRodWIuY29tL21lYmphcy9odG1sNS1xcmNvZGUvaXNzdWVzXCI7XG4gICAgICAgIHJlcG9ydElzc3VlTGluay50YXJnZXQgPSBcIm5ld1wiO1xuICAgICAgICByZXBvcnRJc3N1ZUxpbmsuc3R5bGUuY29sb3IgPSBcIndoaXRlXCI7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5hcHBlbmRDaGlsZChyZXBvcnRJc3N1ZUxpbmspO1xuICAgICAgICBwYXJlbnQuYXBwZW5kQ2hpbGQodGhpcy5pbmZvRGl2KTtcbiAgICB9O1xuICAgIExpYnJhcnlJbmZvRGl2LnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICB9O1xuICAgIExpYnJhcnlJbmZvRGl2LnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmluZm9EaXYuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgIH07XG4gICAgcmV0dXJuIExpYnJhcnlJbmZvRGl2O1xufSgpKTtcbnZhciBMaWJyYXJ5SW5mb0ljb24gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExpYnJhcnlJbmZvSWNvbihvblRhcEluLCBvblRhcE91dCkge1xuICAgICAgICB0aGlzLmlzU2hvd2luZ0luZm9JY29uID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5vblRhcEluID0gb25UYXBJbjtcbiAgICAgICAgdGhpcy5vblRhcE91dCA9IG9uVGFwT3V0O1xuICAgICAgICB0aGlzLmluZm9JY29uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImltZ1wiKTtcbiAgICB9XG4gICAgTGlicmFyeUluZm9JY29uLnByb3RvdHlwZS5yZW5kZXJJbnRvID0gZnVuY3Rpb24gKHBhcmVudCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmluZm9JY29uLmFsdCA9IFwiSW5mbyBpY29uXCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3JjID0gQVNTRVRfSU5GT19JQ09OXzE2UFg7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUucG9zaXRpb24gPSBcImFic29sdXRlXCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUudG9wID0gXCI0cHhcIjtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5yaWdodCA9IFwiNHB4XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUub3BhY2l0eSA9IFwiMC42XCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUuY3Vyc29yID0gXCJwb2ludGVyXCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUuekluZGV4ID0gXCIyXCI7XG4gICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUud2lkdGggPSBcIjE2cHhcIjtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5oZWlnaHQgPSBcIjE2cHhcIjtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5vbm1vdXNlb3ZlciA9IGZ1bmN0aW9uIChfKSB7IHJldHVybiBfdGhpcy5vbkhvdmVySW4oKTsgfTtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5vbm1vdXNlb3V0ID0gZnVuY3Rpb24gKF8pIHsgcmV0dXJuIF90aGlzLm9uSG92ZXJPdXQoKTsgfTtcbiAgICAgICAgdGhpcy5pbmZvSWNvbi5vbmNsaWNrID0gZnVuY3Rpb24gKF8pIHsgcmV0dXJuIF90aGlzLm9uQ2xpY2soKTsgfTtcbiAgICAgICAgcGFyZW50LmFwcGVuZENoaWxkKHRoaXMuaW5mb0ljb24pO1xuICAgIH07XG4gICAgTGlicmFyeUluZm9JY29uLnByb3RvdHlwZS5vbkhvdmVySW4gPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICh0aGlzLmlzU2hvd2luZ0luZm9JY29uKSB7XG4gICAgICAgICAgICB0aGlzLmluZm9JY29uLnN0eWxlLm9wYWNpdHkgPSBcIjFcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTGlicmFyeUluZm9JY29uLnByb3RvdHlwZS5vbkhvdmVyT3V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1Nob3dpbmdJbmZvSWNvbikge1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5vcGFjaXR5ID0gXCIwLjZcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgTGlicmFyeUluZm9JY29uLnByb3RvdHlwZS5vbkNsaWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICBpZiAodGhpcy5pc1Nob3dpbmdJbmZvSWNvbikge1xuICAgICAgICAgICAgdGhpcy5pc1Nob3dpbmdJbmZvSWNvbiA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5vblRhcEluKCk7XG4gICAgICAgICAgICB0aGlzLmluZm9JY29uLnNyYyA9IEFTU0VUX0NMT1NFX0lDT05fMTZQWDtcbiAgICAgICAgICAgIHRoaXMuaW5mb0ljb24uc3R5bGUub3BhY2l0eSA9IFwiMVwiO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pc1Nob3dpbmdJbmZvSWNvbiA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLm9uVGFwT3V0KCk7XG4gICAgICAgICAgICB0aGlzLmluZm9JY29uLnNyYyA9IEFTU0VUX0lORk9fSUNPTl8xNlBYO1xuICAgICAgICAgICAgdGhpcy5pbmZvSWNvbi5zdHlsZS5vcGFjaXR5ID0gXCIwLjZcIjtcbiAgICAgICAgfVxuICAgIH07XG4gICAgcmV0dXJuIExpYnJhcnlJbmZvSWNvbjtcbn0oKSk7XG52YXIgTGlicmFyeUluZm9Db250YWluZXIgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIExpYnJhcnlJbmZvQ29udGFpbmVyKCkge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmluZm9EaXYgPSBuZXcgTGlicmFyeUluZm9EaXYoKTtcbiAgICAgICAgdGhpcy5pbmZvSWNvbiA9IG5ldyBMaWJyYXJ5SW5mb0ljb24oZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgX3RoaXMuaW5mb0Rpdi5zaG93KCk7XG4gICAgICAgIH0sIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIF90aGlzLmluZm9EaXYuaGlkZSgpO1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgTGlicmFyeUluZm9Db250YWluZXIucHJvdG90eXBlLnJlbmRlckludG8gPSBmdW5jdGlvbiAocGFyZW50KSB7XG4gICAgICAgIHRoaXMuaW5mb0Rpdi5yZW5kZXJJbnRvKHBhcmVudCk7XG4gICAgICAgIHRoaXMuaW5mb0ljb24ucmVuZGVySW50byhwYXJlbnQpO1xuICAgIH07XG4gICAgcmV0dXJuIExpYnJhcnlJbmZvQ29udGFpbmVyO1xufSgpKTtcbmV4cG9ydCB7IExpYnJhcnlJbmZvQ29udGFpbmVyIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD11aS5qcy5tYXAiLCJ2YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG52YXIgQ2FtZXJhUGVybWlzc2lvbnMgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVBlcm1pc3Npb25zKCkge1xuICAgIH1cbiAgICBDYW1lcmFQZXJtaXNzaW9ucy5oYXNQZXJtaXNzaW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGRldmljZXMsIF9pLCBkZXZpY2VzXzEsIGRldmljZTtcbiAgICAgICAgICAgIHJldHVybiBfX2dlbmVyYXRvcih0aGlzLCBmdW5jdGlvbiAoX2EpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKF9hLmxhYmVsKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMDogcmV0dXJuIFs0LCBuYXZpZ2F0b3IubWVkaWFEZXZpY2VzLmVudW1lcmF0ZURldmljZXMoKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIGRldmljZXMgPSBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKF9pID0gMCwgZGV2aWNlc18xID0gZGV2aWNlczsgX2kgPCBkZXZpY2VzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGV2aWNlID0gZGV2aWNlc18xW19pXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZGV2aWNlLmtpbmQgPT09IFwidmlkZW9pbnB1dFwiICYmIGRldmljZS5sYWJlbCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gWzIsIHRydWVdO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMiwgZmFsc2VdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFQZXJtaXNzaW9ucztcbn0oKSk7XG5leHBvcnQgeyBDYW1lcmFQZXJtaXNzaW9ucyB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9cGVybWlzc2lvbnMuanMubWFwIiwiaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FuVHlwZSwgSHRtbDVRcmNvZGVDb25zdGFudHMgfSBmcm9tIFwiLi4vLi4vY29yZVwiO1xudmFyIFNjYW5UeXBlU2VsZWN0b3IgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFNjYW5UeXBlU2VsZWN0b3Ioc3VwcG9ydGVkU2NhblR5cGVzKSB7XG4gICAgICAgIHRoaXMuc3VwcG9ydGVkU2NhblR5cGVzID0gdGhpcy52YWxpZGF0ZUFuZFJldHVyblNjYW5UeXBlcyhzdXBwb3J0ZWRTY2FuVHlwZXMpO1xuICAgIH1cbiAgICBTY2FuVHlwZVNlbGVjdG9yLnByb3RvdHlwZS5nZXREZWZhdWx0U2NhblR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1cHBvcnRlZFNjYW5UeXBlc1swXTtcbiAgICB9O1xuICAgIFNjYW5UeXBlU2VsZWN0b3IucHJvdG90eXBlLmhhc01vcmVUaGFuT25lU2NhblR5cGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnN1cHBvcnRlZFNjYW5UeXBlcy5sZW5ndGggPiAxO1xuICAgIH07XG4gICAgU2NhblR5cGVTZWxlY3Rvci5wcm90b3R5cGUuaXNDYW1lcmFTY2FuUmVxdWlyZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLnN1cHBvcnRlZFNjYW5UeXBlczsgX2kgPCBfYS5sZW5ndGg7IF9pKyspIHtcbiAgICAgICAgICAgIHZhciBzY2FuVHlwZSA9IF9hW19pXTtcbiAgICAgICAgICAgIGlmIChTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUoc2NhblR5cGUpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlID0gZnVuY3Rpb24gKHNjYW5UeXBlKSB7XG4gICAgICAgIHJldHVybiBzY2FuVHlwZSA9PT0gSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfQ0FNRVJBO1xuICAgIH07XG4gICAgU2NhblR5cGVTZWxlY3Rvci5pc0ZpbGVTY2FuVHlwZSA9IGZ1bmN0aW9uIChzY2FuVHlwZSkge1xuICAgICAgICByZXR1cm4gc2NhblR5cGUgPT09IEh0bWw1UXJjb2RlU2NhblR5cGUuU0NBTl9UWVBFX0ZJTEU7XG4gICAgfTtcbiAgICBTY2FuVHlwZVNlbGVjdG9yLnByb3RvdHlwZS52YWxpZGF0ZUFuZFJldHVyblNjYW5UeXBlcyA9IGZ1bmN0aW9uIChzdXBwb3J0ZWRTY2FuVHlwZXMpIHtcbiAgICAgICAgaWYgKCFzdXBwb3J0ZWRTY2FuVHlwZXMgfHwgc3VwcG9ydGVkU2NhblR5cGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgbWF4RXhwZWN0ZWRWYWx1ZXMgPSBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEUubGVuZ3RoO1xuICAgICAgICBpZiAoc3VwcG9ydGVkU2NhblR5cGVzLmxlbmd0aCA+IG1heEV4cGVjdGVkVmFsdWVzKSB7XG4gICAgICAgICAgICB0aHJvdyBcIk1heCBcIi5jb25jYXQobWF4RXhwZWN0ZWRWYWx1ZXMsIFwiIHZhbHVlcyBleHBlY3RlZCBmb3IgXCIpXG4gICAgICAgICAgICAgICAgKyBcInN1cHBvcnRlZFNjYW5UeXBlc1wiO1xuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgc3VwcG9ydGVkU2NhblR5cGVzXzEgPSBzdXBwb3J0ZWRTY2FuVHlwZXM7IF9pIDwgc3VwcG9ydGVkU2NhblR5cGVzXzEubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgc2NhblR5cGUgPSBzdXBwb3J0ZWRTY2FuVHlwZXNfMVtfaV07XG4gICAgICAgICAgICBpZiAoIUh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRVxuICAgICAgICAgICAgICAgIC5pbmNsdWRlcyhzY2FuVHlwZSkpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcIlVuc3VwcG9ydGVkIHNjYW4gdHlwZSBcIi5jb25jYXQoc2NhblR5cGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzdXBwb3J0ZWRTY2FuVHlwZXM7XG4gICAgfTtcbiAgICByZXR1cm4gU2NhblR5cGVTZWxlY3Rvcjtcbn0oKSk7XG5leHBvcnQgeyBTY2FuVHlwZVNlbGVjdG9yIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1zY2FuLXR5cGUtc2VsZWN0b3IuanMubWFwIiwidmFyIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcyA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzKCkge1xuICAgIH1cbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQUxMX0VMRU1FTlRfQ0xBU1MgPSBcImh0bWw1LXFyY29kZS1lbGVtZW50XCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9QRVJNSVNTSU9OX0JVVFRPTl9JRCA9IFwiaHRtbDUtcXJjb2RlLWJ1dHRvbi1jYW1lcmEtcGVybWlzc2lvblwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU1RBUlRfQlVUVE9OX0lEID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLWNhbWVyYS1zdGFydFwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU1RPUF9CVVRUT05fSUQgPSBcImh0bWw1LXFyY29kZS1idXR0b24tY2FtZXJhLXN0b3BcIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0lEID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLXRvcmNoXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TRUxFQ1RJT05fU0VMRUNUX0lEID0gXCJodG1sNS1xcmNvZGUtc2VsZWN0LWNhbWVyYVwiO1xuICAgIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5GSUxFX1NFTEVDVElPTl9CVVRUT05fSUQgPSBcImh0bWw1LXFyY29kZS1idXR0b24tZmlsZS1zZWxlY3Rpb25cIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuWk9PTV9TTElERVJfSUQgPSBcImh0bWw1LXFyY29kZS1pbnB1dC1yYW5nZS16b29tXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlNDQU5fVFlQRV9DSEFOR0VfQU5DSE9SX0lEID0gXCJodG1sNS1xcmNvZGUtYW5jaG9yLXNjYW4tdHlwZS1jaGFuZ2VcIjtcbiAgICBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuVE9SQ0hfQlVUVE9OX0NMQVNTX1RPUkNIX09OID0gXCJodG1sNS1xcmNvZGUtYnV0dG9uLXRvcmNoLW9uXCI7XG4gICAgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PRkYgPSBcImh0bWw1LXFyY29kZS1idXR0b24tdG9yY2gtb2ZmXCI7XG4gICAgcmV0dXJuIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcztcbn0oKSk7XG5leHBvcnQgeyBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfTtcbnZhciBCYXNlVWlFbGVtZW50RmFjdG9yeSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQmFzZVVpRWxlbWVudEZhY3RvcnkoKSB7XG4gICAgfVxuICAgIEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQgPSBmdW5jdGlvbiAoZWxlbWVudFR5cGUsIGVsZW1lbnRJZCkge1xuICAgICAgICB2YXIgZWxlbWVudCA9IChkb2N1bWVudC5jcmVhdGVFbGVtZW50KGVsZW1lbnRUeXBlKSk7XG4gICAgICAgIGVsZW1lbnQuaWQgPSBlbGVtZW50SWQ7XG4gICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZChQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQUxMX0VMRU1FTlRfQ0xBU1MpO1xuICAgICAgICBpZiAoZWxlbWVudFR5cGUgPT09IFwiYnV0dG9uXCIpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc2V0QXR0cmlidXRlKFwidHlwZVwiLCBcImJ1dHRvblwiKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gZWxlbWVudDtcbiAgICB9O1xuICAgIHJldHVybiBCYXNlVWlFbGVtZW50RmFjdG9yeTtcbn0oKSk7XG5leHBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9YmFzZS5qcy5tYXAiLCJ2YXIgX19hd2FpdGVyID0gKHRoaXMgJiYgdGhpcy5fX2F3YWl0ZXIpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBfYXJndW1lbnRzLCBQLCBnZW5lcmF0b3IpIHtcbiAgICBmdW5jdGlvbiBhZG9wdCh2YWx1ZSkgeyByZXR1cm4gdmFsdWUgaW5zdGFuY2VvZiBQID8gdmFsdWUgOiBuZXcgUChmdW5jdGlvbiAocmVzb2x2ZSkgeyByZXNvbHZlKHZhbHVlKTsgfSk7IH1cbiAgICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgZnVuY3Rpb24gZnVsZmlsbGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yLm5leHQodmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgICBmdW5jdGlvbiByZWplY3RlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvcltcInRocm93XCJdKHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgICAgc3RlcCgoZ2VuZXJhdG9yID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pKS5uZXh0KCkpO1xuICAgIH0pO1xufTtcbnZhciBfX2dlbmVyYXRvciA9ICh0aGlzICYmIHRoaXMuX19nZW5lcmF0b3IpIHx8IGZ1bmN0aW9uICh0aGlzQXJnLCBib2R5KSB7XG4gICAgdmFyIF8gPSB7IGxhYmVsOiAwLCBzZW50OiBmdW5jdGlvbigpIHsgaWYgKHRbMF0gJiAxKSB0aHJvdyB0WzFdOyByZXR1cm4gdFsxXTsgfSwgdHJ5czogW10sIG9wczogW10gfSwgZiwgeSwgdCwgZztcbiAgICByZXR1cm4gZyA9IHsgbmV4dDogdmVyYigwKSwgXCJ0aHJvd1wiOiB2ZXJiKDEpLCBcInJldHVyblwiOiB2ZXJiKDIpIH0sIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiAoZ1tTeW1ib2wuaXRlcmF0b3JdID0gZnVuY3Rpb24oKSB7IHJldHVybiB0aGlzOyB9KSwgZztcbiAgICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgICBmdW5jdGlvbiBzdGVwKG9wKSB7XG4gICAgICAgIGlmIChmKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgZXhlY3V0aW5nLlwiKTtcbiAgICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICAgIGlmIChmID0gMSwgeSAmJiAodCA9IG9wWzBdICYgMiA/IHlbXCJyZXR1cm5cIl0gOiBvcFswXSA/IHlbXCJ0aHJvd1wiXSB8fCAoKHQgPSB5W1wicmV0dXJuXCJdKSAmJiB0LmNhbGwoeSksIDApIDogeS5uZXh0KSAmJiAhKHQgPSB0LmNhbGwoeSwgb3BbMV0pKS5kb25lKSByZXR1cm4gdDtcbiAgICAgICAgICAgIGlmICh5ID0gMCwgdCkgb3AgPSBbb3BbMF0gJiAyLCB0LnZhbHVlXTtcbiAgICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6IGNhc2UgMTogdCA9IG9wOyBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6IF8ubGFiZWwrKzsgcmV0dXJuIHsgdmFsdWU6IG9wWzFdLCBkb25lOiBmYWxzZSB9O1xuICAgICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgICBjYXNlIDc6IG9wID0gXy5vcHMucG9wKCk7IF8udHJ5cy5wb3AoKTsgY29udGludWU7XG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gMyAmJiAoIXQgfHwgKG9wWzFdID4gdFswXSAmJiBvcFsxXSA8IHRbM10pKSkgeyBfLmxhYmVsID0gb3BbMV07IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChvcFswXSA9PT0gNiAmJiBfLmxhYmVsIDwgdFsxXSkgeyBfLmxhYmVsID0gdFsxXTsgdCA9IG9wOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICAgIGlmICh0WzJdKSBfLm9wcy5wb3AoKTtcbiAgICAgICAgICAgICAgICAgICAgXy50cnlzLnBvcCgpOyBjb250aW51ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG9wID0gYm9keS5jYWxsKHRoaXNBcmcsIF8pO1xuICAgICAgICB9IGNhdGNoIChlKSB7IG9wID0gWzYsIGVdOyB5ID0gMDsgfSBmaW5hbGx5IHsgZiA9IHQgPSAwOyB9XG4gICAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICAgIH1cbn07XG5pbXBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH0gZnJvbSBcIi4uLy4uL3N0cmluZ3NcIjtcbmltcG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5LCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfSBmcm9tIFwiLi9iYXNlXCI7XG52YXIgVG9yY2hDb250cm9sbGVyID0gKGZ1bmN0aW9uICgpIHtcbiAgICBmdW5jdGlvbiBUb3JjaENvbnRyb2xsZXIodG9yY2hDYXBhYmlsaXR5LCBidXR0b25Db250cm9sbGVyLCBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHRoaXMuaXNUb3JjaE9uID0gZmFsc2U7XG4gICAgICAgIHRoaXMudG9yY2hDYXBhYmlsaXR5ID0gdG9yY2hDYXBhYmlsaXR5O1xuICAgICAgICB0aGlzLmJ1dHRvbkNvbnRyb2xsZXIgPSBidXR0b25Db250cm9sbGVyO1xuICAgICAgICB0aGlzLm9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2sgPSBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrO1xuICAgIH1cbiAgICBUb3JjaENvbnRyb2xsZXIucHJvdG90eXBlLmlzVG9yY2hFbmFibGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc1RvcmNoT247XG4gICAgfTtcbiAgICBUb3JjaENvbnRyb2xsZXIucHJvdG90eXBlLmZsaXBTdGF0ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIF9fYXdhaXRlcih0aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGlzVG9yY2hPbkV4cGVjdGVkLCBlcnJvcl8xO1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyLmRpc2FibGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzVG9yY2hPbkV4cGVjdGVkID0gIXRoaXMuaXNUb3JjaE9uO1xuICAgICAgICAgICAgICAgICAgICAgICAgX2EubGFiZWwgPSAxO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS50cnlzLnB1c2goWzEsIDMsICwgNF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFs0LCB0aGlzLnRvcmNoQ2FwYWJpbGl0eS5hcHBseShpc1RvcmNoT25FeHBlY3RlZCldO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgICAgICBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVVpQmFzZWRPbkxhdGVzdFNldHRpbmdzKHRoaXMudG9yY2hDYXBhYmlsaXR5LnZhbHVlKCksIGlzVG9yY2hPbkV4cGVjdGVkKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiBbMywgNF07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yXzEgPSBfYS5zZW50KCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnByb3BhZ2F0ZUZhaWx1cmUoaXNUb3JjaE9uRXhwZWN0ZWQsIGVycm9yXzEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyLmVuYWJsZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFszLCA0XTtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSA0OiByZXR1cm4gWzJdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIFRvcmNoQ29udHJvbGxlci5wcm90b3R5cGUudXBkYXRlVWlCYXNlZE9uTGF0ZXN0U2V0dGluZ3MgPSBmdW5jdGlvbiAoaXNUb3JjaE9uLCBpc1RvcmNoT25FeHBlY3RlZCkge1xuICAgICAgICBpZiAoaXNUb3JjaE9uID09PSBpc1RvcmNoT25FeHBlY3RlZCkge1xuICAgICAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyLnNldFRleHQoaXNUb3JjaE9uRXhwZWN0ZWRcbiAgICAgICAgICAgICAgICA/IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPZmZCdXR0b24oKVxuICAgICAgICAgICAgICAgIDogSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9uQnV0dG9uKCkpO1xuICAgICAgICAgICAgdGhpcy5pc1RvcmNoT24gPSBpc1RvcmNoT25FeHBlY3RlZDtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMucHJvcGFnYXRlRmFpbHVyZShpc1RvcmNoT25FeHBlY3RlZCk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5idXR0b25Db250cm9sbGVyLmVuYWJsZSgpO1xuICAgIH07XG4gICAgVG9yY2hDb250cm9sbGVyLnByb3RvdHlwZS5wcm9wYWdhdGVGYWlsdXJlID0gZnVuY3Rpb24gKGlzVG9yY2hPbkV4cGVjdGVkLCBlcnJvcikge1xuICAgICAgICB2YXIgZXJyb3JNZXNzYWdlID0gaXNUb3JjaE9uRXhwZWN0ZWRcbiAgICAgICAgICAgID8gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50b3JjaE9uRmFpbGVkTWVzc2FnZSgpXG4gICAgICAgICAgICA6IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPZmZGYWlsZWRNZXNzYWdlKCk7XG4gICAgICAgIGlmIChlcnJvcikge1xuICAgICAgICAgICAgZXJyb3JNZXNzYWdlICs9IFwiOyBFcnJvciA9IFwiICsgZXJyb3I7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5vblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKGVycm9yTWVzc2FnZSk7XG4gICAgfTtcbiAgICBUb3JjaENvbnRyb2xsZXIucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmlzVG9yY2hPbiA9IGZhbHNlO1xuICAgIH07XG4gICAgcmV0dXJuIFRvcmNoQ29udHJvbGxlcjtcbn0oKSk7XG52YXIgVG9yY2hCdXR0b24gPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIFRvcmNoQnV0dG9uKHRvcmNoQ2FwYWJpbGl0eSwgb25Ub3JjaEFjdGlvbkZhaWx1cmVDYWxsYmFjaykge1xuICAgICAgICB0aGlzLm9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2sgPSBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrO1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uXG4gICAgICAgICAgICA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9JRCk7XG4gICAgICAgIHRoaXMudG9yY2hDb250cm9sbGVyID0gbmV3IFRvcmNoQ29udHJvbGxlcih0b3JjaENhcGFiaWxpdHksIHRoaXMsIG9uVG9yY2hBY3Rpb25GYWlsdXJlQ2FsbGJhY2spO1xuICAgIH1cbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIHRvcmNoQnV0dG9uT3B0aW9ucykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnRvcmNoT25CdXR0b24oKTtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gdG9yY2hCdXR0b25PcHRpb25zLmRpc3BsYXk7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uc3R5bGUubWFyZ2luTGVmdCA9IHRvcmNoQnV0dG9uT3B0aW9ucy5tYXJnaW5MZWZ0O1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmFkZEV2ZW50TGlzdGVuZXIoXCJjbGlja1wiLCBmdW5jdGlvbiAoXykgeyByZXR1cm4gX19hd2FpdGVyKF90aGlzLCB2b2lkIDAsIHZvaWQgMCwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmV0dXJuIF9fZ2VuZXJhdG9yKHRoaXMsIGZ1bmN0aW9uIChfYSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAoX2EubGFiZWwpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSAwOiByZXR1cm4gWzQsICR0aGlzLnRvcmNoQ29udHJvbGxlci5mbGlwU3RhdGUoKV07XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgICAgIF9hLnNlbnQoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgkdGhpcy50b3JjaENvbnRyb2xsZXIuaXNUb3JjaEVuYWJsZWQoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLnRvcmNoQnV0dG9uLmNsYXNzTGlzdC5yZW1vdmUoUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PRkYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLnRvcmNoQnV0dG9uLmNsYXNzTGlzdC5hZGQoUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PTik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAkdGhpcy50b3JjaEJ1dHRvbi5jbGFzc0xpc3QucmVtb3ZlKFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5UT1JDSF9CVVRUT05fQ0xBU1NfVE9SQ0hfT04pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICR0aGlzLnRvcmNoQnV0dG9uLmNsYXNzTGlzdC5hZGQoUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlRPUkNIX0JVVFRPTl9DTEFTU19UT1JDSF9PRkYpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFsyXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7IH0pO1xuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMudG9yY2hCdXR0b24pO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLnVwZGF0ZVRvcmNoQ2FwYWJpbGl0eSA9IGZ1bmN0aW9uICh0b3JjaENhcGFiaWxpdHkpIHtcbiAgICAgICAgdGhpcy50b3JjaENvbnRyb2xsZXIgPSBuZXcgVG9yY2hDb250cm9sbGVyKHRvcmNoQ2FwYWJpbGl0eSwgdGhpcywgdGhpcy5vblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKTtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5nZXRUb3JjaEJ1dHRvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMudG9yY2hCdXR0b247XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBUb3JjaEJ1dHRvbi5wcm90b3R5cGUuc2hvdyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5lbmFibGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMudG9yY2hCdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICB9O1xuICAgIFRvcmNoQnV0dG9uLnByb3RvdHlwZS5zZXRUZXh0ID0gZnVuY3Rpb24gKHRleHQpIHtcbiAgICAgICAgdGhpcy50b3JjaEJ1dHRvbi5pbm5lclRleHQgPSB0ZXh0O1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24ucHJvdG90eXBlLnJlc2V0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnRvcmNoQnV0dG9uLmlubmVyVGV4dCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MudG9yY2hPbkJ1dHRvbigpO1xuICAgICAgICB0aGlzLnRvcmNoQ29udHJvbGxlci5yZXNldCgpO1xuICAgIH07XG4gICAgVG9yY2hCdXR0b24uY3JlYXRlID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIHRvcmNoQ2FwYWJpbGl0eSwgdG9yY2hCdXR0b25PcHRpb25zLCBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKSB7XG4gICAgICAgIHZhciBidXR0b24gPSBuZXcgVG9yY2hCdXR0b24odG9yY2hDYXBhYmlsaXR5LCBvblRvcmNoQWN0aW9uRmFpbHVyZUNhbGxiYWNrKTtcbiAgICAgICAgYnV0dG9uLnJlbmRlcihwYXJlbnRFbGVtZW50LCB0b3JjaEJ1dHRvbk9wdGlvbnMpO1xuICAgICAgICByZXR1cm4gYnV0dG9uO1xuICAgIH07XG4gICAgcmV0dXJuIFRvcmNoQnV0dG9uO1xufSgpKTtcbmV4cG9ydCB7IFRvcmNoQnV0dG9uIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD10b3JjaC1idXR0b24uanMubWFwIiwiaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncyB9IGZyb20gXCIuLi8uLi9zdHJpbmdzXCI7XG5pbXBvcnQgeyBCYXNlVWlFbGVtZW50RmFjdG9yeSwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzIH0gZnJvbSBcIi4vYmFzZVwiO1xudmFyIEZpbGVTZWxlY3Rpb25VaSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gRmlsZVNlbGVjdGlvblVpKHBhcmVudEVsZW1lbnQsIHNob3dPblJlbmRlciwgb25GaWxlU2VsZWN0ZWQpIHtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uID0gdGhpcy5jcmVhdGVGaWxlQmFzZWRTY2FuUmVnaW9uKCk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5kaXNwbGF5XG4gICAgICAgICAgICA9IHNob3dPblJlbmRlciA/IFwiYmxvY2tcIiA6IFwibm9uZVwiO1xuICAgICAgICBwYXJlbnRFbGVtZW50LmFwcGVuZENoaWxkKHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbik7XG4gICAgICAgIHZhciBmaWxlU2NhbkxhYmVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImxhYmVsXCIpO1xuICAgICAgICBmaWxlU2NhbkxhYmVsLnNldEF0dHJpYnV0ZShcImZvclwiLCB0aGlzLmdldEZpbGVTY2FuSW5wdXRJZCgpKTtcbiAgICAgICAgZmlsZVNjYW5MYWJlbC5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFwcGVuZENoaWxkKGZpbGVTY2FuTGFiZWwpO1xuICAgICAgICB0aGlzLmZpbGVTZWxlY3Rpb25CdXR0b25cbiAgICAgICAgICAgID0gQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudChcImJ1dHRvblwiLCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuRklMRV9TRUxFQ1RJT05fQlVUVE9OX0lEKTtcbiAgICAgICAgdGhpcy5zZXRJbml0aWFsVmFsdWVUb0J1dHRvbigpO1xuICAgICAgICB0aGlzLmZpbGVTZWxlY3Rpb25CdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICBmaWxlU2NhbkxhYmVsLmNsaWNrKCk7XG4gICAgICAgIH0pO1xuICAgICAgICBmaWxlU2NhbkxhYmVsLmFwcGVuZCh0aGlzLmZpbGVTZWxlY3Rpb25CdXR0b24pO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXRcbiAgICAgICAgICAgID0gQmFzZVVpRWxlbWVudEZhY3RvcnkuY3JlYXRlRWxlbWVudChcImlucHV0XCIsIHRoaXMuZ2V0RmlsZVNjYW5JbnB1dElkKCkpO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQudHlwZSA9IFwiZmlsZVwiO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQuYWNjZXB0ID0gXCJpbWFnZS8qXCI7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbnB1dC5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgIGZpbGVTY2FuTGFiZWwuYXBwZW5kQ2hpbGQodGhpcy5maWxlU2NhbklucHV0KTtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LmFkZEV2ZW50TGlzdGVuZXIoXCJjaGFuZ2VcIiwgZnVuY3Rpb24gKGUpIHtcbiAgICAgICAgICAgIGlmIChlID09IG51bGwgfHwgZS50YXJnZXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciB0YXJnZXQgPSBlLnRhcmdldDtcbiAgICAgICAgICAgIGlmICh0YXJnZXQuZmlsZXMgJiYgdGFyZ2V0LmZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHZhciBmaWxlTGlzdCA9IHRhcmdldC5maWxlcztcbiAgICAgICAgICAgIHZhciBmaWxlID0gZmlsZUxpc3RbMF07XG4gICAgICAgICAgICB2YXIgZmlsZU5hbWUgPSBmaWxlLm5hbWU7XG4gICAgICAgICAgICAkdGhpcy5zZXRJbWFnZU5hbWVUb0J1dHRvbihmaWxlTmFtZSk7XG4gICAgICAgICAgICBvbkZpbGVTZWxlY3RlZChmaWxlKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHZhciBkcmFnQW5kRHJvcE1lc3NhZ2UgPSB0aGlzLmNyZWF0ZURyYWdBbmREcm9wTWVzc2FnZSgpO1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uYXBwZW5kQ2hpbGQoZHJhZ0FuZERyb3BNZXNzYWdlKTtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJkcmFnZW50ZXJcIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAkdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmJvcmRlclxuICAgICAgICAgICAgICAgID0gJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbkFjdGl2ZUJvcmRlcigpO1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJkcmFnbGVhdmVcIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAkdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmJvcmRlclxuICAgICAgICAgICAgICAgID0gJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbkRlZmF1bHRCb3JkZXIoKTtcbiAgICAgICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5hZGRFdmVudExpc3RlbmVyKFwiZHJhZ292ZXJcIiwgZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAgICAgICAkdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmJvcmRlclxuICAgICAgICAgICAgICAgID0gJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbkFjdGl2ZUJvcmRlcigpO1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICB9KTtcbiAgICAgICAgdGhpcy5maWxlQmFzZWRTY2FuUmVnaW9uLmFkZEV2ZW50TGlzdGVuZXIoXCJkcm9wXCIsIGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgICAgICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgJHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5ib3JkZXJcbiAgICAgICAgICAgICAgICA9ICR0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25EZWZhdWx0Qm9yZGVyKCk7XG4gICAgICAgICAgICB2YXIgZGF0YVRyYW5zZmVyID0gZXZlbnQuZGF0YVRyYW5zZmVyO1xuICAgICAgICAgICAgaWYgKGRhdGFUcmFuc2Zlcikge1xuICAgICAgICAgICAgICAgIHZhciBmaWxlcyA9IGRhdGFUcmFuc2Zlci5maWxlcztcbiAgICAgICAgICAgICAgICBpZiAoIWZpbGVzIHx8IGZpbGVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHZhciBpc0FueUZpbGVJbWFnZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgZmlsZXMubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZpbGUgPSBmaWxlcy5pdGVtKGkpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoIWZpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIHZhciBpbWFnZVR5cGUgPSAvaW1hZ2UuKi87XG4gICAgICAgICAgICAgICAgICAgIGlmICghZmlsZS50eXBlLm1hdGNoKGltYWdlVHlwZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlzQW55RmlsZUltYWdlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGZpbGVOYW1lID0gZmlsZS5uYW1lO1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5zZXRJbWFnZU5hbWVUb0J1dHRvbihmaWxlTmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIG9uRmlsZVNlbGVjdGVkKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICBkcmFnQW5kRHJvcE1lc3NhZ2UuaW5uZXJUZXh0XG4gICAgICAgICAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZHJhZ0FuZERyb3BNZXNzYWdlKCk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoIWlzQW55RmlsZUltYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgIGRyYWdBbmREcm9wTWVzc2FnZS5pbm5lclRleHRcbiAgICAgICAgICAgICAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5nc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kcmFnQW5kRHJvcE1lc3NhZ2VPbmx5SW1hZ2VzKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5oaWRlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICB0aGlzLmZpbGVTY2FuSW5wdXQuZGlzYWJsZWQgPSB0cnVlO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5zaG93ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICAgICAgdGhpcy5maWxlU2NhbklucHV0LmRpc2FibGVkID0gZmFsc2U7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLmlzU2hvd2luZyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmlsZUJhc2VkU2NhblJlZ2lvbi5zdHlsZS5kaXNwbGF5ID09PSBcImJsb2NrXCI7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLnJlc2V0VmFsdWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbnB1dC52YWx1ZSA9IFwiXCI7XG4gICAgICAgIHRoaXMuc2V0SW5pdGlhbFZhbHVlVG9CdXR0b24oKTtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuY3JlYXRlRmlsZUJhc2VkU2NhblJlZ2lvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIGZpbGVCYXNlZFNjYW5SZWdpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIGZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUubWFyZ2luID0gXCJhdXRvXCI7XG4gICAgICAgIGZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUud2lkdGggPSBcIjgwJVwiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLm1heFdpZHRoID0gXCI2MDBweFwiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLmJvcmRlclxuICAgICAgICAgICAgPSB0aGlzLmZpbGVCYXNlZFNjYW5SZWdpb25EZWZhdWx0Qm9yZGVyKCk7XG4gICAgICAgIGZpbGVCYXNlZFNjYW5SZWdpb24uc3R5bGUucGFkZGluZyA9IFwiMTBweFwiO1xuICAgICAgICBmaWxlQmFzZWRTY2FuUmVnaW9uLnN0eWxlLm1hcmdpbkJvdHRvbSA9IFwiMTBweFwiO1xuICAgICAgICByZXR1cm4gZmlsZUJhc2VkU2NhblJlZ2lvbjtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuZmlsZUJhc2VkU2NhblJlZ2lvbkRlZmF1bHRCb3JkZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIjZweCBkYXNoZWQgI2ViZWJlYlwiO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLnByb3RvdHlwZS5maWxlQmFzZWRTY2FuUmVnaW9uQWN0aXZlQm9yZGVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCI2cHggZGFzaGVkIHJnYigxNTMgMTUxIDE1MSlcIjtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuY3JlYXRlRHJhZ0FuZERyb3BNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgZHJhZ0FuZERyb3BNZXNzYWdlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgZHJhZ0FuZERyb3BNZXNzYWdlLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmRyYWdBbmREcm9wTWVzc2FnZSgpO1xuICAgICAgICBkcmFnQW5kRHJvcE1lc3NhZ2Uuc3R5bGUuZm9udFdlaWdodCA9IFwiNDAwXCI7XG4gICAgICAgIHJldHVybiBkcmFnQW5kRHJvcE1lc3NhZ2U7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLnNldEltYWdlTmFtZVRvQnV0dG9uID0gZnVuY3Rpb24gKGltYWdlRmlsZU5hbWUpIHtcbiAgICAgICAgdmFyIE1BWF9DSEFSUyA9IDIwO1xuICAgICAgICBpZiAoaW1hZ2VGaWxlTmFtZS5sZW5ndGggPiBNQVhfQ0hBUlMpIHtcbiAgICAgICAgICAgIHZhciBzdGFydDhDaGFycyA9IGltYWdlRmlsZU5hbWUuc3Vic3RyaW5nKDAsIDgpO1xuICAgICAgICAgICAgdmFyIGxlbmd0aF8xID0gaW1hZ2VGaWxlTmFtZS5sZW5ndGg7XG4gICAgICAgICAgICB2YXIgbGFzdDhDaGFycyA9IGltYWdlRmlsZU5hbWUuc3Vic3RyaW5nKGxlbmd0aF8xIC0gOCwgbGVuZ3RoXzEpO1xuICAgICAgICAgICAgaW1hZ2VGaWxlTmFtZSA9IFwiXCIuY29uY2F0KHN0YXJ0OENoYXJzLCBcIi4uLi5cIikuY29uY2F0KGxhc3Q4Q2hhcnMpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBuZXdUZXh0ID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uQ2hvb3NlQW5vdGhlcigpXG4gICAgICAgICAgICArIFwiIC0gXCJcbiAgICAgICAgICAgICsgaW1hZ2VGaWxlTmFtZTtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uQnV0dG9uLmlubmVyVGV4dCA9IG5ld1RleHQ7XG4gICAgfTtcbiAgICBGaWxlU2VsZWN0aW9uVWkucHJvdG90eXBlLnNldEluaXRpYWxWYWx1ZVRvQnV0dG9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgaW5pdGlhbFRleHQgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmZpbGVTZWxlY3Rpb25DaG9vc2VJbWFnZSgpXG4gICAgICAgICAgICArIFwiIC0gXCJcbiAgICAgICAgICAgICsgSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5maWxlU2VsZWN0aW9uTm9JbWFnZVNlbGVjdGVkKCk7XG4gICAgICAgIHRoaXMuZmlsZVNlbGVjdGlvbkJ1dHRvbi5pbm5lclRleHQgPSBpbml0aWFsVGV4dDtcbiAgICB9O1xuICAgIEZpbGVTZWxlY3Rpb25VaS5wcm90b3R5cGUuZ2V0RmlsZVNjYW5JbnB1dElkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJodG1sNS1xcmNvZGUtcHJpdmF0ZS1maWxlc2Nhbi1pbnB1dFwiO1xuICAgIH07XG4gICAgRmlsZVNlbGVjdGlvblVpLmNyZWF0ZSA9IGZ1bmN0aW9uIChwYXJlbnRFbGVtZW50LCBzaG93T25SZW5kZXIsIG9uRmlsZVNlbGVjdGVkKSB7XG4gICAgICAgIHZhciBidXR0b24gPSBuZXcgRmlsZVNlbGVjdGlvblVpKHBhcmVudEVsZW1lbnQsIHNob3dPblJlbmRlciwgb25GaWxlU2VsZWN0ZWQpO1xuICAgICAgICByZXR1cm4gYnV0dG9uO1xuICAgIH07XG4gICAgcmV0dXJuIEZpbGVTZWxlY3Rpb25VaTtcbn0oKSk7XG5leHBvcnQgeyBGaWxlU2VsZWN0aW9uVWkgfTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWZpbGUtc2VsZWN0aW9uLXVpLmpzLm1hcCIsImltcG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5LCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfSBmcm9tIFwiLi9iYXNlXCI7XG5pbXBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH0gZnJvbSBcIi4uLy4uL3N0cmluZ3NcIjtcbnZhciBDYW1lcmFTZWxlY3Rpb25VaSA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gQ2FtZXJhU2VsZWN0aW9uVWkoY2FtZXJhcykge1xuICAgICAgICB0aGlzLnNlbGVjdEVsZW1lbnQgPSBCYXNlVWlFbGVtZW50RmFjdG9yeVxuICAgICAgICAgICAgLmNyZWF0ZUVsZW1lbnQoXCJzZWxlY3RcIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TRUxFQ1RJT05fU0VMRUNUX0lEKTtcbiAgICAgICAgdGhpcy5jYW1lcmFzID0gY2FtZXJhcztcbiAgICAgICAgdGhpcy5vcHRpb25zID0gW107XG4gICAgfVxuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5yZW5kZXIgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCkge1xuICAgICAgICB2YXIgY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIGNhbWVyYVNlbGVjdGlvbkNvbnRhaW5lci5zdHlsZS5tYXJnaW5SaWdodCA9IFwiMTBweFwiO1xuICAgICAgICB2YXIgbnVtQ2FtZXJhcyA9IHRoaXMuY2FtZXJhcy5sZW5ndGg7XG4gICAgICAgIGlmIChudW1DYW1lcmFzID09PSAwKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJObyBjYW1lcmFzIGZvdW5kXCIpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChudW1DYW1lcmFzID09PSAxKSB7XG4gICAgICAgICAgICBjYW1lcmFTZWxlY3Rpb25Db250YWluZXIuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdmFyIHNlbGVjdENhbWVyYVN0cmluZyA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2VsZWN0Q2FtZXJhKCk7XG4gICAgICAgICAgICBjYW1lcmFTZWxlY3Rpb25Db250YWluZXIuaW5uZXJUZXh0XG4gICAgICAgICAgICAgICAgPSBcIlwiLmNvbmNhdChzZWxlY3RDYW1lcmFTdHJpbmcsIFwiIChcIikuY29uY2F0KHRoaXMuY2FtZXJhcy5sZW5ndGgsIFwiKSAgXCIpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBhbm9ueW1vdXNDYW1lcmFJZCA9IDE7XG4gICAgICAgIGZvciAodmFyIF9pID0gMCwgX2EgPSB0aGlzLmNhbWVyYXM7IF9pIDwgX2EubGVuZ3RoOyBfaSsrKSB7XG4gICAgICAgICAgICB2YXIgY2FtZXJhID0gX2FbX2ldO1xuICAgICAgICAgICAgdmFyIHZhbHVlID0gY2FtZXJhLmlkO1xuICAgICAgICAgICAgdmFyIG5hbWVfMSA9IGNhbWVyYS5sYWJlbCA9PSBudWxsID8gdmFsdWUgOiBjYW1lcmEubGFiZWw7XG4gICAgICAgICAgICBpZiAoIW5hbWVfMSB8fCBuYW1lXzEgPT09IFwiXCIpIHtcbiAgICAgICAgICAgICAgICBuYW1lXzEgPSBbXG4gICAgICAgICAgICAgICAgICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuYW5vbnltb3VzQ2FtZXJhUHJlZml4KCksXG4gICAgICAgICAgICAgICAgICAgIGFub255bW91c0NhbWVyYUlkKytcbiAgICAgICAgICAgICAgICBdLmpvaW4oXCIgXCIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdmFyIG9wdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJvcHRpb25cIik7XG4gICAgICAgICAgICBvcHRpb24udmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgICAgIG9wdGlvbi5pbm5lclRleHQgPSBuYW1lXzE7XG4gICAgICAgICAgICB0aGlzLm9wdGlvbnMucHVzaChvcHRpb24pO1xuICAgICAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50LmFwcGVuZENoaWxkKG9wdGlvbik7XG4gICAgICAgIH1cbiAgICAgICAgY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyLmFwcGVuZENoaWxkKHRoaXMuc2VsZWN0RWxlbWVudCk7XG4gICAgICAgIHBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoY2FtZXJhU2VsZWN0aW9uQ29udGFpbmVyKTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5kaXNhYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNlbGVjdEVsZW1lbnQuZGlzYWJsZWQgPSB0cnVlO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLmlzRGlzYWJsZWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLnNlbGVjdEVsZW1lbnQuZGlzYWJsZWQgPT09IHRydWU7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuZW5hYmxlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLnNlbGVjdEVsZW1lbnQuZGlzYWJsZWQgPSBmYWxzZTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5nZXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0RWxlbWVudC52YWx1ZTtcbiAgICB9O1xuICAgIENhbWVyYVNlbGVjdGlvblVpLnByb3RvdHlwZS5oYXNWYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkge1xuICAgICAgICBmb3IgKHZhciBfaSA9IDAsIF9hID0gdGhpcy5vcHRpb25zOyBfaSA8IF9hLmxlbmd0aDsgX2krKykge1xuICAgICAgICAgICAgdmFyIG9wdGlvbiA9IF9hW19pXTtcbiAgICAgICAgICAgIGlmIChvcHRpb24udmFsdWUgPT09IHZhbHVlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH07XG4gICAgQ2FtZXJhU2VsZWN0aW9uVWkucHJvdG90eXBlLnNldFZhbHVlID0gZnVuY3Rpb24gKHZhbHVlKSB7XG4gICAgICAgIGlmICghdGhpcy5oYXNWYWx1ZSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIlwiLmNvbmNhdCh2YWx1ZSwgXCIgaXMgbm90IHByZXNlbnQgaW4gdGhlIGNhbWVyYSBsaXN0LlwiKSk7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zZWxlY3RFbGVtZW50LnZhbHVlID0gdmFsdWU7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUuaGFzU2luZ2xlSXRlbSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FtZXJhcy5sZW5ndGggPT09IDE7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5wcm90b3R5cGUubnVtQ2FtZXJhcyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY2FtZXJhcy5sZW5ndGg7XG4gICAgfTtcbiAgICBDYW1lcmFTZWxlY3Rpb25VaS5jcmVhdGUgPSBmdW5jdGlvbiAocGFyZW50RWxlbWVudCwgY2FtZXJhcykge1xuICAgICAgICB2YXIgY2FtZXJhU2VsZWN0VWkgPSBuZXcgQ2FtZXJhU2VsZWN0aW9uVWkoY2FtZXJhcyk7XG4gICAgICAgIGNhbWVyYVNlbGVjdFVpLnJlbmRlcihwYXJlbnRFbGVtZW50KTtcbiAgICAgICAgcmV0dXJuIGNhbWVyYVNlbGVjdFVpO1xuICAgIH07XG4gICAgcmV0dXJuIENhbWVyYVNlbGVjdGlvblVpO1xufSgpKTtcbmV4cG9ydCB7IENhbWVyYVNlbGVjdGlvblVpIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jYW1lcmEtc2VsZWN0aW9uLXVpLmpzLm1hcCIsImltcG9ydCB7IEJhc2VVaUVsZW1lbnRGYWN0b3J5LCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMgfSBmcm9tIFwiLi9iYXNlXCI7XG5pbXBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzIH0gZnJvbSBcIi4uLy4uL3N0cmluZ3NcIjtcbnZhciBDYW1lcmFab29tVWkgPSAoZnVuY3Rpb24gKCkge1xuICAgIGZ1bmN0aW9uIENhbWVyYVpvb21VaSgpIHtcbiAgICAgICAgdGhpcy5vbkNoYW5nZUNhbGxiYWNrID0gbnVsbDtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dCA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJpbnB1dFwiLCBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuWk9PTV9TTElERVJfSUQpO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQudHlwZSA9IFwicmFuZ2VcIjtcbiAgICAgICAgdGhpcy5yYW5nZVRleHQgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwic3BhblwiKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0Lm1pbiA9IFwiMVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQubWF4ID0gXCI1XCI7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC52YWx1ZSA9IFwiMVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3RlcCA9IFwiMC4xXCI7XG4gICAgfVxuICAgIENhbWVyYVpvb21VaS5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHBhcmVudEVsZW1lbnQsIHJlbmRlck9uQ3JlYXRlKSB7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUuZGlzcGxheVxuICAgICAgICAgICAgPSByZW5kZXJPbkNyZWF0ZSA/IFwiYmxvY2tcIiA6IFwibm9uZVwiO1xuICAgICAgICB0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyLnN0eWxlLnBhZGRpbmcgPSBcIjVweCAxMHB4XCI7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgcGFyZW50RWxlbWVudC5hcHBlbmRDaGlsZCh0aGlzLnpvb21FbGVtZW50Q29udGFpbmVyKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3R5bGUud2lkdGggPSBcIjUwJVwiO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuc3R5bGUuaGVpZ2h0ID0gXCI1cHhcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLmJhY2tncm91bmQgPSBcIiNkM2QzZDNcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLm91dGxpbmUgPSBcIm5vbmVcIjtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0LnN0eWxlLm9wYWNpdHkgPSBcIjAuN1wiO1xuICAgICAgICB2YXIgem9vbVN0cmluZyA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muem9vbSgpO1xuICAgICAgICB0aGlzLnJhbmdlVGV4dC5pbm5lclRleHQgPSBcIlwiLmNvbmNhdCh0aGlzLnJhbmdlSW5wdXQudmFsdWUsIFwieCBcIikuY29uY2F0KHpvb21TdHJpbmcpO1xuICAgICAgICB0aGlzLnJhbmdlVGV4dC5zdHlsZS5tYXJnaW5SaWdodCA9IFwiMTBweFwiO1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQuYWRkRXZlbnRMaXN0ZW5lcihcImlucHV0XCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuICR0aGlzLm9uVmFsdWVDaGFuZ2UoKTsgfSk7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5hZGRFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIGZ1bmN0aW9uICgpIHsgcmV0dXJuICR0aGlzLm9uVmFsdWVDaGFuZ2UoKTsgfSk7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuYXBwZW5kQ2hpbGQodGhpcy5yYW5nZUlucHV0KTtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lci5hcHBlbmRDaGlsZCh0aGlzLnJhbmdlVGV4dCk7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLm9uVmFsdWVDaGFuZ2UgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciB6b29tU3RyaW5nID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy56b29tKCk7XG4gICAgICAgIHRoaXMucmFuZ2VUZXh0LmlubmVyVGV4dCA9IFwiXCIuY29uY2F0KHRoaXMucmFuZ2VJbnB1dC52YWx1ZSwgXCJ4IFwiKS5jb25jYXQoem9vbVN0cmluZyk7XG4gICAgICAgIGlmICh0aGlzLm9uQ2hhbmdlQ2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMub25DaGFuZ2VDYWxsYmFjayhwYXJzZUZsb2F0KHRoaXMucmFuZ2VJbnB1dC52YWx1ZSkpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNldFZhbHVlcyA9IGZ1bmN0aW9uIChtaW5WYWx1ZSwgbWF4VmFsdWUsIGRlZmF1bHRWYWx1ZSwgc3RlcCkge1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQubWluID0gbWluVmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5yYW5nZUlucHV0Lm1heCA9IG1heFZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIHRoaXMucmFuZ2VJbnB1dC5zdGVwID0gc3RlcC50b1N0cmluZygpO1xuICAgICAgICB0aGlzLnJhbmdlSW5wdXQudmFsdWUgPSBkZWZhdWx0VmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgdGhpcy5vblZhbHVlQ2hhbmdlKCk7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNob3cgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuem9vbUVsZW1lbnRDb250YWluZXIuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcbiAgICB9O1xuICAgIENhbWVyYVpvb21VaS5wcm90b3R5cGUuaGlkZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdGhpcy56b29tRWxlbWVudENvbnRhaW5lci5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBDYW1lcmFab29tVWkucHJvdG90eXBlLnNldE9uQ2FtZXJhWm9vbVZhbHVlQ2hhbmdlQ2FsbGJhY2sgPSBmdW5jdGlvbiAob25DaGFuZ2VDYWxsYmFjaykge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sgPSBvbkNoYW5nZUNhbGxiYWNrO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLnByb3RvdHlwZS5yZW1vdmVPbkNhbWVyYVpvb21WYWx1ZUNoYW5nZUNhbGxiYWNrID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB0aGlzLm9uQ2hhbmdlQ2FsbGJhY2sgPSBudWxsO1xuICAgIH07XG4gICAgQ2FtZXJhWm9vbVVpLmNyZWF0ZSA9IGZ1bmN0aW9uIChwYXJlbnRFbGVtZW50LCByZW5kZXJPbkNyZWF0ZSkge1xuICAgICAgICB2YXIgY2FtZXJhWm9vbVVpID0gbmV3IENhbWVyYVpvb21VaSgpO1xuICAgICAgICBjYW1lcmFab29tVWkucmVuZGVyKHBhcmVudEVsZW1lbnQsIHJlbmRlck9uQ3JlYXRlKTtcbiAgICAgICAgcmV0dXJuIGNhbWVyYVpvb21VaTtcbiAgICB9O1xuICAgIHJldHVybiBDYW1lcmFab29tVWk7XG59KCkpO1xuZXhwb3J0IHsgQ2FtZXJhWm9vbVVpIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jYW1lcmEtem9vbS11aS5qcy5tYXAiLCJpbXBvcnQgeyBIdG1sNVFyY29kZUNvbnN0YW50cywgSHRtbDVRcmNvZGVTY2FuVHlwZSwgSHRtbDVRcmNvZGVFcnJvckZhY3RvcnksIEJhc2VMb2dnZ2VyLCBpc051bGxPclVuZGVmaW5lZCwgY2xpcCwgfSBmcm9tIFwiLi9jb3JlXCI7XG5pbXBvcnQgeyBIdG1sNVFyY29kZSwgfSBmcm9tIFwiLi9odG1sNS1xcmNvZGVcIjtcbmltcG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MsIH0gZnJvbSBcIi4vc3RyaW5nc1wiO1xuaW1wb3J0IHsgQVNTRVRfRklMRV9TQ0FOLCBBU1NFVF9DQU1FUkFfU0NBTiwgfSBmcm9tIFwiLi9pbWFnZS1hc3NldHNcIjtcbmltcG9ydCB7IFBlcnNpc3RlZERhdGFNYW5hZ2VyIH0gZnJvbSBcIi4vc3RvcmFnZVwiO1xuaW1wb3J0IHsgTGlicmFyeUluZm9Db250YWluZXIgfSBmcm9tIFwiLi91aVwiO1xuaW1wb3J0IHsgQ2FtZXJhUGVybWlzc2lvbnMgfSBmcm9tIFwiLi9jYW1lcmEvcGVybWlzc2lvbnNcIjtcbmltcG9ydCB7IFNjYW5UeXBlU2VsZWN0b3IgfSBmcm9tIFwiLi91aS9zY2FubmVyL3NjYW4tdHlwZS1zZWxlY3RvclwiO1xuaW1wb3J0IHsgVG9yY2hCdXR0b24gfSBmcm9tIFwiLi91aS9zY2FubmVyL3RvcmNoLWJ1dHRvblwiO1xuaW1wb3J0IHsgRmlsZVNlbGVjdGlvblVpIH0gZnJvbSBcIi4vdWkvc2Nhbm5lci9maWxlLXNlbGVjdGlvbi11aVwiO1xuaW1wb3J0IHsgQmFzZVVpRWxlbWVudEZhY3RvcnksIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3NlcyB9IGZyb20gXCIuL3VpL3NjYW5uZXIvYmFzZVwiO1xuaW1wb3J0IHsgQ2FtZXJhU2VsZWN0aW9uVWkgfSBmcm9tIFwiLi91aS9zY2FubmVyL2NhbWVyYS1zZWxlY3Rpb24tdWlcIjtcbmltcG9ydCB7IENhbWVyYVpvb21VaSB9IGZyb20gXCIuL3VpL3NjYW5uZXIvY2FtZXJhLXpvb20tdWlcIjtcbnZhciBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXM7XG4oZnVuY3Rpb24gKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cykge1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbXCJTVEFUVVNfREVGQVVMVFwiXSA9IDBdID0gXCJTVEFUVVNfREVGQVVMVFwiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbXCJTVEFUVVNfU1VDQ0VTU1wiXSA9IDFdID0gXCJTVEFUVVNfU1VDQ0VTU1wiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbXCJTVEFUVVNfV0FSTklOR1wiXSA9IDJdID0gXCJTVEFUVVNfV0FSTklOR1wiO1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1c1tIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXNbXCJTVEFUVVNfUkVRVUVTVElOR19QRVJNSVNTSU9OXCJdID0gM10gPSBcIlNUQVRVU19SRVFVRVNUSU5HX1BFUk1JU1NJT05cIjtcbn0pKEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cyB8fCAoSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzID0ge30pKTtcbmZ1bmN0aW9uIHRvSHRtbDVRcmNvZGVDYW1lcmFTY2FuQ29uZmlnKGNvbmZpZykge1xuICAgIHJldHVybiB7XG4gICAgICAgIGZwczogY29uZmlnLmZwcyxcbiAgICAgICAgcXJib3g6IGNvbmZpZy5xcmJveCxcbiAgICAgICAgYXNwZWN0UmF0aW86IGNvbmZpZy5hc3BlY3RSYXRpbyxcbiAgICAgICAgZGlzYWJsZUZsaXA6IGNvbmZpZy5kaXNhYmxlRmxpcCxcbiAgICAgICAgdmlkZW9Db25zdHJhaW50czogY29uZmlnLnZpZGVvQ29uc3RyYWludHNcbiAgICB9O1xufVxuZnVuY3Rpb24gdG9IdG1sNVFyY29kZUZ1bGxDb25maWcoY29uZmlnLCB2ZXJib3NlKSB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgZm9ybWF0c1RvU3VwcG9ydDogY29uZmlnLmZvcm1hdHNUb1N1cHBvcnQsXG4gICAgICAgIHVzZUJhckNvZGVEZXRlY3RvcklmU3VwcG9ydGVkOiBjb25maWcudXNlQmFyQ29kZURldGVjdG9ySWZTdXBwb3J0ZWQsXG4gICAgICAgIGV4cGVyaW1lbnRhbEZlYXR1cmVzOiBjb25maWcuZXhwZXJpbWVudGFsRmVhdHVyZXMsXG4gICAgICAgIHZlcmJvc2U6IHZlcmJvc2VcbiAgICB9O1xufVxudmFyIEh0bWw1UXJjb2RlU2Nhbm5lciA9IChmdW5jdGlvbiAoKSB7XG4gICAgZnVuY3Rpb24gSHRtbDVRcmNvZGVTY2FubmVyKGVsZW1lbnRJZCwgY29uZmlnLCB2ZXJib3NlKSB7XG4gICAgICAgIHRoaXMubGFzdE1hdGNoRm91bmQgPSBudWxsO1xuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZSA9IG51bGw7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZSA9IG51bGw7XG4gICAgICAgIHRoaXMuZmlsZVNlbGVjdGlvblVpID0gbnVsbDtcbiAgICAgICAgdGhpcy5lbGVtZW50SWQgPSBlbGVtZW50SWQ7XG4gICAgICAgIHRoaXMuY29uZmlnID0gdGhpcy5jcmVhdGVDb25maWcoY29uZmlnKTtcbiAgICAgICAgdGhpcy52ZXJib3NlID0gdmVyYm9zZSA9PT0gdHJ1ZTtcbiAgICAgICAgaWYgKCFkb2N1bWVudC5nZXRFbGVtZW50QnlJZChlbGVtZW50SWQpKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkhUTUwgRWxlbWVudCB3aXRoIGlkPVwiLmNvbmNhdChlbGVtZW50SWQsIFwiIG5vdCBmb3VuZFwiKTtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnNjYW5UeXBlU2VsZWN0b3IgPSBuZXcgU2NhblR5cGVTZWxlY3Rvcih0aGlzLmNvbmZpZy5zdXBwb3J0ZWRTY2FuVHlwZXMpO1xuICAgICAgICB0aGlzLmN1cnJlbnRTY2FuVHlwZSA9IHRoaXMuc2NhblR5cGVTZWxlY3Rvci5nZXREZWZhdWx0U2NhblR5cGUoKTtcbiAgICAgICAgdGhpcy5zZWN0aW9uU3dhcEFsbG93ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLmxvZ2dlciA9IG5ldyBCYXNlTG9nZ2dlcih0aGlzLnZlcmJvc2UpO1xuICAgICAgICB0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyID0gbmV3IFBlcnNpc3RlZERhdGFNYW5hZ2VyKCk7XG4gICAgICAgIGlmIChjb25maWcucmVtZW1iZXJMYXN0VXNlZENhbWVyYSAhPT0gdHJ1ZSkge1xuICAgICAgICAgICAgdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5yZXNldCgpO1xuICAgICAgICB9XG4gICAgfVxuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVuZGVyID0gZnVuY3Rpb24gKHFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgcXJDb2RlRXJyb3JDYWxsYmFjaykge1xuICAgICAgICB2YXIgX3RoaXMgPSB0aGlzO1xuICAgICAgICB0aGlzLmxhc3RNYXRjaEZvdW5kID0gbnVsbDtcbiAgICAgICAgdGhpcy5xckNvZGVTdWNjZXNzQ2FsbGJhY2tcbiAgICAgICAgICAgID0gZnVuY3Rpb24gKGRlY29kZWRUZXh0LCByZXN1bHQpIHtcbiAgICAgICAgICAgICAgICBpZiAocXJDb2RlU3VjY2Vzc0NhbGxiYWNrKSB7XG4gICAgICAgICAgICAgICAgICAgIHFyQ29kZVN1Y2Nlc3NDYWxsYmFjayhkZWNvZGVkVGV4dCwgcmVzdWx0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfdGhpcy5sYXN0TWF0Y2hGb3VuZCA9PT0gZGVjb2RlZFRleHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBfdGhpcy5sYXN0TWF0Y2hGb3VuZCA9IGRlY29kZWRUZXh0O1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5zZXRIZWFkZXJNZXNzYWdlKEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MubGFzdE1hdGNoKGRlY29kZWRUZXh0KSwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19TVUNDRVNTKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB0aGlzLnFyQ29kZUVycm9yQ2FsbGJhY2sgPVxuICAgICAgICAgICAgZnVuY3Rpb24gKGVycm9yTWVzc2FnZSwgZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBpZiAocXJDb2RlRXJyb3JDYWxsYmFjaykge1xuICAgICAgICAgICAgICAgICAgICBxckNvZGVFcnJvckNhbGxiYWNrKGVycm9yTWVzc2FnZSwgZXJyb3IpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH07XG4gICAgICAgIHZhciBjb250YWluZXIgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmVsZW1lbnRJZCk7XG4gICAgICAgIGlmICghY29udGFpbmVyKSB7XG4gICAgICAgICAgICB0aHJvdyBcIkhUTUwgRWxlbWVudCB3aXRoIGlkPVwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCIgbm90IGZvdW5kXCIpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRhaW5lci5pbm5lckhUTUwgPSBcIlwiO1xuICAgICAgICB0aGlzLmNyZWF0ZUJhc2ljTGF5b3V0KGNvbnRhaW5lcik7XG4gICAgICAgIHRoaXMuaHRtbDVRcmNvZGUgPSBuZXcgSHRtbDVRcmNvZGUodGhpcy5nZXRTY2FuUmVnaW9uSWQoKSwgdG9IdG1sNVFyY29kZUZ1bGxDb25maWcodGhpcy5jb25maWcsIHRoaXMudmVyYm9zZSkpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5wYXVzZSA9IGZ1bmN0aW9uIChzaG91bGRQYXVzZVZpZGVvKSB7XG4gICAgICAgIGlmIChpc051bGxPclVuZGVmaW5lZChzaG91bGRQYXVzZVZpZGVvKSB8fCBzaG91bGRQYXVzZVZpZGVvICE9PSB0cnVlKSB7XG4gICAgICAgICAgICBzaG91bGRQYXVzZVZpZGVvID0gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5nZXRIdG1sNVFyY29kZU9yRmFpbCgpLnBhdXNlKHNob3VsZFBhdXNlVmlkZW8pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5yZXN1bWUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHRoaXMuZ2V0SHRtbDVRcmNvZGVPckZhaWwoKS5yZXN1bWUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0U3RhdGUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEh0bWw1UXJjb2RlT3JGYWlsKCkuZ2V0U3RhdGUoKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY2xlYXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBlbXB0eUh0bWxDb250YWluZXIgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbWFpbkNvbnRhaW5lciA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKF90aGlzLmVsZW1lbnRJZCk7XG4gICAgICAgICAgICBpZiAobWFpbkNvbnRhaW5lcikge1xuICAgICAgICAgICAgICAgIG1haW5Db250YWluZXIuaW5uZXJIVE1MID0gXCJcIjtcbiAgICAgICAgICAgICAgICBfdGhpcy5yZXNldEJhc2ljTGF5b3V0KG1haW5Db250YWluZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9O1xuICAgICAgICBpZiAodGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgICAgICAgICAgICBpZiAoIV90aGlzLmh0bWw1UXJjb2RlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuaHRtbDVRcmNvZGUuaXNTY2FubmluZykge1xuICAgICAgICAgICAgICAgICAgICBfdGhpcy5odG1sNVFyY29kZS5zdG9wKCkudGhlbihmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFfdGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5odG1sNVFyY29kZS5jbGVhcigpO1xuICAgICAgICAgICAgICAgICAgICAgICAgZW1wdHlIdG1sQ29udGFpbmVyKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF90aGlzLnZlcmJvc2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJVbmFibGUgdG8gc3RvcCBxcmNvZGUgc2Nhbm5lclwiLCBlcnJvcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZXJyb3IpO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF90aGlzLmh0bWw1UXJjb2RlLmNsZWFyKCk7XG4gICAgICAgICAgICAgICAgICAgIGVtcHR5SHRtbENvbnRhaW5lcigpO1xuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRSdW5uaW5nVHJhY2tDYXBhYmlsaXRpZXMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldEh0bWw1UXJjb2RlT3JGYWlsKCkuZ2V0UnVubmluZ1RyYWNrQ2FwYWJpbGl0aWVzKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldFJ1bm5pbmdUcmFja1NldHRpbmdzID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXRIdG1sNVFyY29kZU9yRmFpbCgpLmdldFJ1bm5pbmdUcmFja1NldHRpbmdzKCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmFwcGx5VmlkZW9Db25zdHJhaW50cyA9IGZ1bmN0aW9uICh2aWRlb0NvbnN0YWludHMpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0SHRtbDVRcmNvZGVPckZhaWwoKS5hcHBseVZpZGVvQ29uc3RyYWludHModmlkZW9Db25zdGFpbnRzKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuZ2V0SHRtbDVRcmNvZGVPckZhaWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIGlmICghdGhpcy5odG1sNVFyY29kZSkge1xuICAgICAgICAgICAgdGhyb3cgXCJDb2RlIHNjYW5uZXIgbm90IGluaXRpYWxpemVkLlwiO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLmh0bWw1UXJjb2RlO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVDb25maWcgPSBmdW5jdGlvbiAoY29uZmlnKSB7XG4gICAgICAgIGlmIChjb25maWcpIHtcbiAgICAgICAgICAgIGlmICghY29uZmlnLmZwcykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5mcHMgPSBIdG1sNVFyY29kZUNvbnN0YW50cy5TQ0FOX0RFRkFVTFRfRlBTO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGNvbmZpZy5yZW1lbWJlckxhc3RVc2VkQ2FtZXJhICE9PSAoIUh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfUkVNRU1CRVJfTEFTVF9DQU1FUkFfVVNFRCkpIHtcbiAgICAgICAgICAgICAgICBjb25maWcucmVtZW1iZXJMYXN0VXNlZENhbWVyYVxuICAgICAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfUkVNRU1CRVJfTEFTVF9DQU1FUkFfVVNFRDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghY29uZmlnLnN1cHBvcnRlZFNjYW5UeXBlcykge1xuICAgICAgICAgICAgICAgIGNvbmZpZy5zdXBwb3J0ZWRTY2FuVHlwZXNcbiAgICAgICAgICAgICAgICAgICAgPSBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1NVUFBPUlRFRF9TQ0FOX1RZUEU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm4gY29uZmlnO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBmcHM6IEh0bWw1UXJjb2RlQ29uc3RhbnRzLlNDQU5fREVGQVVMVF9GUFMsXG4gICAgICAgICAgICByZW1lbWJlckxhc3RVc2VkQ2FtZXJhOiBIdG1sNVFyY29kZUNvbnN0YW50cy5ERUZBVUxUX1JFTUVNQkVSX0xBU1RfQ0FNRVJBX1VTRUQsXG4gICAgICAgICAgICBzdXBwb3J0ZWRTY2FuVHlwZXM6IEh0bWw1UXJjb2RlQ29uc3RhbnRzLkRFRkFVTFRfU1VQUE9SVEVEX1NDQU5fVFlQRVxuICAgICAgICB9O1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVCYXNpY0xheW91dCA9IGZ1bmN0aW9uIChwYXJlbnQpIHtcbiAgICAgICAgcGFyZW50LnN0eWxlLnBvc2l0aW9uID0gXCJyZWxhdGl2ZVwiO1xuICAgICAgICBwYXJlbnQuc3R5bGUucGFkZGluZyA9IFwiMHB4XCI7XG4gICAgICAgIHBhcmVudC5zdHlsZS5ib3JkZXIgPSBcIjFweCBzb2xpZCBzaWx2ZXJcIjtcbiAgICAgICAgdGhpcy5jcmVhdGVIZWFkZXIocGFyZW50KTtcbiAgICAgICAgdmFyIHFyQ29kZVNjYW5SZWdpb24gPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICB2YXIgc2NhblJlZ2lvbklkID0gdGhpcy5nZXRTY2FuUmVnaW9uSWQoKTtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5pZCA9IHNjYW5SZWdpb25JZDtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5zdHlsZS53aWR0aCA9IFwiMTAwJVwiO1xuICAgICAgICBxckNvZGVTY2FuUmVnaW9uLnN0eWxlLm1pbkhlaWdodCA9IFwiMTAwcHhcIjtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICBwYXJlbnQuYXBwZW5kQ2hpbGQocXJDb2RlU2NhblJlZ2lvbik7XG4gICAgICAgIGlmIChTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUodGhpcy5jdXJyZW50U2NhblR5cGUpKSB7XG4gICAgICAgICAgICB0aGlzLmluc2VydENhbWVyYVNjYW5JbWFnZVRvU2NhblJlZ2lvbigpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pbnNlcnRGaWxlU2NhbkltYWdlVG9TY2FuUmVnaW9uKCk7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHFyQ29kZURhc2hib2FyZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHZhciBkYXNoYm9hcmRJZCA9IHRoaXMuZ2V0RGFzaGJvYXJkSWQoKTtcbiAgICAgICAgcXJDb2RlRGFzaGJvYXJkLmlkID0gZGFzaGJvYXJkSWQ7XG4gICAgICAgIHFyQ29kZURhc2hib2FyZC5zdHlsZS53aWR0aCA9IFwiMTAwJVwiO1xuICAgICAgICBwYXJlbnQuYXBwZW5kQ2hpbGQocXJDb2RlRGFzaGJvYXJkKTtcbiAgICAgICAgdGhpcy5zZXR1cEluaXRpYWxEYXNoYm9hcmQocXJDb2RlRGFzaGJvYXJkKTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVzZXRCYXNpY0xheW91dCA9IGZ1bmN0aW9uIChtYWluQ29udGFpbmVyKSB7XG4gICAgICAgIG1haW5Db250YWluZXIuc3R5bGUuYm9yZGVyID0gXCJub25lXCI7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnNldHVwSW5pdGlhbERhc2hib2FyZCA9IGZ1bmN0aW9uIChkYXNoYm9hcmQpIHtcbiAgICAgICAgdGhpcy5jcmVhdGVTZWN0aW9uKGRhc2hib2FyZCk7XG4gICAgICAgIHRoaXMuY3JlYXRlU2VjdGlvbkNvbnRyb2xQYW5lbCgpO1xuICAgICAgICBpZiAodGhpcy5zY2FuVHlwZVNlbGVjdG9yLmhhc01vcmVUaGFuT25lU2NhblR5cGUoKSkge1xuICAgICAgICAgICAgdGhpcy5jcmVhdGVTZWN0aW9uU3dhcCgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZUhlYWRlciA9IGZ1bmN0aW9uIChkYXNoYm9hcmQpIHtcbiAgICAgICAgdmFyIGhlYWRlciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIGhlYWRlci5zdHlsZS50ZXh0QWxpZ24gPSBcImxlZnRcIjtcbiAgICAgICAgaGVhZGVyLnN0eWxlLm1hcmdpbiA9IFwiMHB4XCI7XG4gICAgICAgIGRhc2hib2FyZC5hcHBlbmRDaGlsZChoZWFkZXIpO1xuICAgICAgICB2YXIgbGlicmFyeUluZm8gPSBuZXcgTGlicmFyeUluZm9Db250YWluZXIoKTtcbiAgICAgICAgbGlicmFyeUluZm8ucmVuZGVySW50byhoZWFkZXIpO1xuICAgICAgICB2YXIgaGVhZGVyTWVzc2FnZUNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuaWQgPSB0aGlzLmdldEhlYWRlck1lc3NhZ2VDb250YWluZXJJZCgpO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5zdHlsZS50ZXh0QWxpZ24gPSBcImNlbnRlclwiO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLmZvbnRTaXplID0gXCIxNHB4XCI7XG4gICAgICAgIGhlYWRlck1lc3NhZ2VDb250YWluZXIuc3R5bGUucGFkZGluZyA9IFwiMnB4IDEwcHhcIjtcbiAgICAgICAgaGVhZGVyTWVzc2FnZUNvbnRhaW5lci5zdHlsZS5tYXJnaW4gPSBcIjRweFwiO1xuICAgICAgICBoZWFkZXJNZXNzYWdlQ29udGFpbmVyLnN0eWxlLmJvcmRlclRvcCA9IFwiMXB4IHNvbGlkICNmNmY2ZjZcIjtcbiAgICAgICAgaGVhZGVyLmFwcGVuZENoaWxkKGhlYWRlck1lc3NhZ2VDb250YWluZXIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVTZWN0aW9uID0gZnVuY3Rpb24gKGRhc2hib2FyZCkge1xuICAgICAgICB2YXIgc2VjdGlvbiA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNlY3Rpb24uaWQgPSB0aGlzLmdldERhc2hib2FyZFNlY3Rpb25JZCgpO1xuICAgICAgICBzZWN0aW9uLnN0eWxlLndpZHRoID0gXCIxMDAlXCI7XG4gICAgICAgIHNlY3Rpb24uc3R5bGUucGFkZGluZyA9IFwiMTBweCAwcHggMTBweCAwcHhcIjtcbiAgICAgICAgc2VjdGlvbi5zdHlsZS50ZXh0QWxpZ24gPSBcImxlZnRcIjtcbiAgICAgICAgZGFzaGJvYXJkLmFwcGVuZENoaWxkKHNlY3Rpb24pO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVDYW1lcmFMaXN0VWkgPSBmdW5jdGlvbiAoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIsIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uKSB7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayhmYWxzZSk7XG4gICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFQZXJtaXNzaW9uUmVxdWVzdGluZygpKTtcbiAgICAgICAgdmFyIGNyZWF0ZVBlcm1pc3Npb25CdXR0b25JZk5vdEV4aXN0cyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICghcmVxdWVzdFBlcm1pc3Npb25CdXR0b24pIHtcbiAgICAgICAgICAgICAgICAkdGhpcy5jcmVhdGVQZXJtaXNzaW9uQnV0dG9uKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgSHRtbDVRcmNvZGUuZ2V0Q2FtZXJhcygpLnRoZW4oZnVuY3Rpb24gKGNhbWVyYXMpIHtcbiAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldEhhc1Blcm1pc3Npb24odHJ1ZSk7XG4gICAgICAgICAgICAkdGhpcy5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsodHJ1ZSk7XG4gICAgICAgICAgICAkdGhpcy5yZXNldEhlYWRlck1lc3NhZ2UoKTtcbiAgICAgICAgICAgIGlmIChjYW1lcmFzICYmIGNhbWVyYXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHNjcENhbWVyYVNjYW5SZWdpb24ucmVtb3ZlQ2hpbGQocmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICAgICAgICAgICR0aGlzLnJlbmRlckNhbWVyYVNlbGVjdGlvbihjYW1lcmFzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5ub0NhbWVyYUZvdW5kKCksIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORyk7XG4gICAgICAgICAgICAgICAgY3JlYXRlUGVybWlzc2lvbkJ1dHRvbklmTm90RXhpc3RzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbihmYWxzZSk7XG4gICAgICAgICAgICBpZiAocmVxdWVzdFBlcm1pc3Npb25CdXR0b24pIHtcbiAgICAgICAgICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY3JlYXRlUGVybWlzc2lvbkJ1dHRvbklmTm90RXhpc3RzKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKGVycm9yLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkcpO1xuICAgICAgICAgICAgJHRoaXMuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rKHRydWUpO1xuICAgICAgICB9KTtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlUGVybWlzc2lvbkJ1dHRvbiA9IGZ1bmN0aW9uIChzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcikge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24gPSBCYXNlVWlFbGVtZW50RmFjdG9yeVxuICAgICAgICAgICAgLmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgdGhpcy5nZXRDYW1lcmFQZXJtaXNzaW9uQnV0dG9uSWQoKSk7XG4gICAgICAgIHJlcXVlc3RQZXJtaXNzaW9uQnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLmNhbWVyYVBlcm1pc3Npb25UaXRsZSgpO1xuICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgcmVxdWVzdFBlcm1pc3Npb25CdXR0b24uZGlzYWJsZWQgPSB0cnVlO1xuICAgICAgICAgICAgJHRoaXMuY3JlYXRlQ2FtZXJhTGlzdFVpKHNjcENhbWVyYVNjYW5SZWdpb24sIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyLCByZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbik7XG4gICAgICAgIH0pO1xuICAgICAgICByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lci5hcHBlbmRDaGlsZChyZXF1ZXN0UGVybWlzc2lvbkJ1dHRvbik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNyZWF0ZVBlcm1pc3Npb25zVWkgPSBmdW5jdGlvbiAoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpIHtcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgaWYgKFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSh0aGlzLmN1cnJlbnRTY2FuVHlwZSlcbiAgICAgICAgICAgICYmIHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuaGFzQ2FtZXJhUGVybWlzc2lvbnMoKSkge1xuICAgICAgICAgICAgQ2FtZXJhUGVybWlzc2lvbnMuaGFzUGVybWlzc2lvbnMoKS50aGVuKGZ1bmN0aW9uIChoYXNQZXJtaXNzaW9ucykge1xuICAgICAgICAgICAgICAgIGlmIChoYXNQZXJtaXNzaW9ucykge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5jcmVhdGVDYW1lcmFMaXN0VWkoc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLmNyZWF0ZVBlcm1pc3Npb25CdXR0b24oc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pLmNhdGNoKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuc2V0SGFzUGVybWlzc2lvbihmYWxzZSk7XG4gICAgICAgICAgICAgICAgJHRoaXMuY3JlYXRlUGVybWlzc2lvbkJ1dHRvbihzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNyZWF0ZVBlcm1pc3Npb25CdXR0b24oc2NwQ2FtZXJhU2NhblJlZ2lvbiwgcmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5jcmVhdGVTZWN0aW9uQ29udHJvbFBhbmVsID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgc2VjdGlvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvbklkKCkpO1xuICAgICAgICB2YXIgc2VjdGlvbkNvbnRyb2xQYW5lbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHNlY3Rpb24uYXBwZW5kQ2hpbGQoc2VjdGlvbkNvbnRyb2xQYW5lbCk7XG4gICAgICAgIHZhciBzY3BDYW1lcmFTY2FuUmVnaW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcImRpdlwiKTtcbiAgICAgICAgc2NwQ2FtZXJhU2NhblJlZ2lvbi5pZCA9IHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvbkNhbWVyYVNjYW5SZWdpb25JZCgpO1xuICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLnN0eWxlLmRpc3BsYXlcbiAgICAgICAgICAgID0gU2NhblR5cGVTZWxlY3Rvci5pc0NhbWVyYVNjYW5UeXBlKHRoaXMuY3VycmVudFNjYW5UeXBlKVxuICAgICAgICAgICAgICAgID8gXCJibG9ja1wiIDogXCJub25lXCI7XG4gICAgICAgIHNlY3Rpb25Db250cm9sUGFuZWwuYXBwZW5kQ2hpbGQoc2NwQ2FtZXJhU2NhblJlZ2lvbik7XG4gICAgICAgIHZhciByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lciA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJkaXZcIik7XG4gICAgICAgIHJlcXVlc3RQZXJtaXNzaW9uQ29udGFpbmVyLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHNjcENhbWVyYVNjYW5SZWdpb24uYXBwZW5kQ2hpbGQocmVxdWVzdFBlcm1pc3Npb25Db250YWluZXIpO1xuICAgICAgICBpZiAodGhpcy5zY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblJlcXVpcmVkKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY3JlYXRlUGVybWlzc2lvbnNVaShzY3BDYW1lcmFTY2FuUmVnaW9uLCByZXF1ZXN0UGVybWlzc2lvbkNvbnRhaW5lcik7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5yZW5kZXJGaWxlU2NhblVpKHNlY3Rpb25Db250cm9sUGFuZWwpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5yZW5kZXJGaWxlU2NhblVpID0gZnVuY3Rpb24gKHBhcmVudCkge1xuICAgICAgICB2YXIgc2hvd09uUmVuZGVyID0gU2NhblR5cGVTZWxlY3Rvci5pc0ZpbGVTY2FuVHlwZSh0aGlzLmN1cnJlbnRTY2FuVHlwZSk7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBvbkZpbGVTZWxlY3RlZCA9IGZ1bmN0aW9uIChmaWxlKSB7XG4gICAgICAgICAgICBpZiAoISR0aGlzLmh0bWw1UXJjb2RlKSB7XG4gICAgICAgICAgICAgICAgdGhyb3cgXCJodG1sNVFyY29kZSBub3QgZGVmaW5lZFwiO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFTY2FuVHlwZVNlbGVjdG9yLmlzRmlsZVNjYW5UeXBlKCR0aGlzLmN1cnJlbnRTY2FuVHlwZSkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MubG9hZGluZ0ltYWdlKCkpO1xuICAgICAgICAgICAgJHRoaXMuaHRtbDVRcmNvZGUuc2NhbkZpbGVWMihmaWxlLCB0cnVlKVxuICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChodG1sNXFyY29kZVJlc3VsdCkge1xuICAgICAgICAgICAgICAgICR0aGlzLnJlc2V0SGVhZGVyTWVzc2FnZSgpO1xuICAgICAgICAgICAgICAgICR0aGlzLnFyQ29kZVN1Y2Nlc3NDYWxsYmFjayhodG1sNXFyY29kZVJlc3VsdC5kZWNvZGVkVGV4dCwgaHRtbDVxcmNvZGVSZXN1bHQpO1xuICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAuY2F0Y2goZnVuY3Rpb24gKGVycm9yKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShlcnJvciwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgICAgICAkdGhpcy5xckNvZGVFcnJvckNhbGxiYWNrKGVycm9yLCBIdG1sNVFyY29kZUVycm9yRmFjdG9yeS5jcmVhdGVGcm9tKGVycm9yKSk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5maWxlU2VsZWN0aW9uVWkgPSBGaWxlU2VsZWN0aW9uVWkuY3JlYXRlKHBhcmVudCwgc2hvd09uUmVuZGVyLCBvbkZpbGVTZWxlY3RlZCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnJlbmRlckNhbWVyYVNlbGVjdGlvbiA9IGZ1bmN0aW9uIChjYW1lcmFzKSB7XG4gICAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBzY3BDYW1lcmFTY2FuUmVnaW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uQ2FtZXJhU2NhblJlZ2lvbklkKCkpO1xuICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLnN0eWxlLnRleHRBbGlnbiA9IFwiY2VudGVyXCI7XG4gICAgICAgIHZhciBjYW1lcmFab29tVWkgPSBDYW1lcmFab29tVWkuY3JlYXRlKHNjcENhbWVyYVNjYW5SZWdpb24sIGZhbHNlKTtcbiAgICAgICAgdmFyIHJlbmRlckNhbWVyYVpvb21VaUlmU3VwcG9ydGVkID0gZnVuY3Rpb24gKGNhbWVyYUNhcGFiaWxpdGllcykge1xuICAgICAgICAgICAgdmFyIHpvb21DYXBhYmlsaXR5ID0gY2FtZXJhQ2FwYWJpbGl0aWVzLnpvb21GZWF0dXJlKCk7XG4gICAgICAgICAgICBpZiAoIXpvb21DYXBhYmlsaXR5LmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYW1lcmFab29tVWkuc2V0T25DYW1lcmFab29tVmFsdWVDaGFuZ2VDYWxsYmFjayhmdW5jdGlvbiAoem9vbVZhbHVlKSB7XG4gICAgICAgICAgICAgICAgem9vbUNhcGFiaWxpdHkuYXBwbHkoem9vbVZhbHVlKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdmFyIGRlZmF1bHRab29tID0gMTtcbiAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuZGVmYXVsdFpvb21WYWx1ZUlmU3VwcG9ydGVkKSB7XG4gICAgICAgICAgICAgICAgZGVmYXVsdFpvb20gPSBfdGhpcy5jb25maWcuZGVmYXVsdFpvb21WYWx1ZUlmU3VwcG9ydGVkO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZGVmYXVsdFpvb20gPSBjbGlwKGRlZmF1bHRab29tLCB6b29tQ2FwYWJpbGl0eS5taW4oKSwgem9vbUNhcGFiaWxpdHkubWF4KCkpO1xuICAgICAgICAgICAgY2FtZXJhWm9vbVVpLnNldFZhbHVlcyh6b29tQ2FwYWJpbGl0eS5taW4oKSwgem9vbUNhcGFiaWxpdHkubWF4KCksIGRlZmF1bHRab29tLCB6b29tQ2FwYWJpbGl0eS5zdGVwKCkpO1xuICAgICAgICAgICAgY2FtZXJhWm9vbVVpLnNob3coKTtcbiAgICAgICAgfTtcbiAgICAgICAgdmFyIGNhbWVyYVNlbGVjdFVpID0gQ2FtZXJhU2VsZWN0aW9uVWkuY3JlYXRlKHNjcENhbWVyYVNjYW5SZWdpb24sIGNhbWVyYXMpO1xuICAgICAgICB2YXIgY2FtZXJhQWN0aW9uQ29udGFpbmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcInNwYW5cIik7XG4gICAgICAgIHZhciBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbiA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJidXR0b25cIiwgUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLkNBTUVSQV9TVEFSVF9CVVRUT05fSUQpO1xuICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5pbm5lclRleHRcbiAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5zY2FuQnV0dG9uU3RhcnRTY2FubmluZ1RleHQoKTtcbiAgICAgICAgY2FtZXJhQWN0aW9uQ29udGFpbmVyLmFwcGVuZENoaWxkKGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uKTtcbiAgICAgICAgdmFyIGNhbWVyYUFjdGlvblN0b3BCdXR0b24gPSBCYXNlVWlFbGVtZW50RmFjdG9yeS5jcmVhdGVFbGVtZW50KFwiYnV0dG9uXCIsIFB1YmxpY1VpRWxlbWVudElkQW5kQ2xhc3Nlcy5DQU1FUkFfU1RPUF9CVVRUT05fSUQpO1xuICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBIdG1sNVFyY29kZVNjYW5uZXJTdHJpbmdzLnNjYW5CdXR0b25TdG9wU2Nhbm5pbmdUZXh0KCk7XG4gICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgY2FtZXJhQWN0aW9uQ29udGFpbmVyLmFwcGVuZENoaWxkKGNhbWVyYUFjdGlvblN0b3BCdXR0b24pO1xuICAgICAgICB2YXIgdG9yY2hCdXR0b247XG4gICAgICAgIHZhciBjcmVhdGVBbmRTaG93VG9yY2hCdXR0b25JZlN1cHBvcnRlZCA9IGZ1bmN0aW9uIChjYW1lcmFDYXBhYmlsaXRpZXMpIHtcbiAgICAgICAgICAgIGlmICghY2FtZXJhQ2FwYWJpbGl0aWVzLnRvcmNoRmVhdHVyZSgpLmlzU3VwcG9ydGVkKCkpIHtcbiAgICAgICAgICAgICAgICBpZiAodG9yY2hCdXR0b24pIHtcbiAgICAgICAgICAgICAgICAgICAgdG9yY2hCdXR0b24uaGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIXRvcmNoQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgdG9yY2hCdXR0b24gPSBUb3JjaEJ1dHRvbi5jcmVhdGUoY2FtZXJhQWN0aW9uQ29udGFpbmVyLCBjYW1lcmFDYXBhYmlsaXRpZXMudG9yY2hGZWF0dXJlKCksIHsgZGlzcGxheTogXCJub25lXCIsIG1hcmdpbkxlZnQ6IFwiNXB4XCIgfSwgZnVuY3Rpb24gKGVycm9yTWVzc2FnZSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5zZXRIZWFkZXJNZXNzYWdlKGVycm9yTWVzc2FnZSwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIHRvcmNoQnV0dG9uLnVwZGF0ZVRvcmNoQ2FwYWJpbGl0eShjYW1lcmFDYXBhYmlsaXRpZXMudG9yY2hGZWF0dXJlKCkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgdG9yY2hCdXR0b24uc2hvdygpO1xuICAgICAgICB9O1xuICAgICAgICBzY3BDYW1lcmFTY2FuUmVnaW9uLmFwcGVuZENoaWxkKGNhbWVyYUFjdGlvbkNvbnRhaW5lcik7XG4gICAgICAgIHZhciByZXNldENhbWVyYUFjdGlvblN0YXJ0QnV0dG9uID0gZnVuY3Rpb24gKHNob3VsZFNob3cpIHtcbiAgICAgICAgICAgIGlmICghc2hvdWxkU2hvdykge1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmlubmVyVGV4dFxuICAgICAgICAgICAgICAgID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5nc1xuICAgICAgICAgICAgICAgICAgICAuc2NhbkJ1dHRvblN0YXJ0U2Nhbm5pbmdUZXh0KCk7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5zdHlsZS5vcGFjaXR5ID0gXCIxXCI7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5kaXNhYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKHNob3VsZFNob3cpIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uYWRkRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5pbm5lclRleHRcbiAgICAgICAgICAgICAgICA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3Muc2NhbkJ1dHRvblNjYW5uaW5nU3RhcnRpbmcoKTtcbiAgICAgICAgICAgIGNhbWVyYVNlbGVjdFVpLmRpc2FibGUoKTtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLnN0eWxlLm9wYWNpdHkgPSBcIjAuNVwiO1xuICAgICAgICAgICAgaWYgKF90aGlzLnNjYW5UeXBlU2VsZWN0b3IuaGFzTW9yZVRoYW5PbmVTY2FuVHlwZSgpKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2hvd0hpZGVTY2FuVHlwZVN3YXBMaW5rKGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR0aGlzLnJlc2V0SGVhZGVyTWVzc2FnZSgpO1xuICAgICAgICAgICAgdmFyIGNhbWVyYUlkID0gY2FtZXJhU2VsZWN0VWkuZ2V0VmFsdWUoKTtcbiAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldExhc3RVc2VkQ2FtZXJhSWQoY2FtZXJhSWQpO1xuICAgICAgICAgICAgJHRoaXMuaHRtbDVRcmNvZGUuc3RhcnQoY2FtZXJhSWQsIHRvSHRtbDVRcmNvZGVDYW1lcmFTY2FuQ29uZmlnKCR0aGlzLmNvbmZpZyksICR0aGlzLnFyQ29kZVN1Y2Nlc3NDYWxsYmFjaywgJHRoaXMucXJDb2RlRXJyb3JDYWxsYmFjaylcbiAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0b3BCdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICAgICAgICAgIHJlc2V0Q2FtZXJhQWN0aW9uU3RhcnRCdXR0b24oZmFsc2UpO1xuICAgICAgICAgICAgICAgIHZhciBjYW1lcmFDYXBhYmlsaXRpZXMgPSAkdGhpcy5odG1sNVFyY29kZS5nZXRSdW5uaW5nVHJhY2tDYW1lcmFDYXBhYmlsaXRpZXMoKTtcbiAgICAgICAgICAgICAgICBpZiAoX3RoaXMuY29uZmlnLnNob3dUb3JjaEJ1dHRvbklmU3VwcG9ydGVkID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIGNyZWF0ZUFuZFNob3dUb3JjaEJ1dHRvbklmU3VwcG9ydGVkKGNhbWVyYUNhcGFiaWxpdGllcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChfdGhpcy5jb25maWcuc2hvd1pvb21TbGlkZXJJZlN1cHBvcnRlZCA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICByZW5kZXJDYW1lcmFab29tVWlJZlN1cHBvcnRlZChjYW1lcmFDYXBhYmlsaXRpZXMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKGZ1bmN0aW9uIChlcnJvcikge1xuICAgICAgICAgICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayh0cnVlKTtcbiAgICAgICAgICAgICAgICBjYW1lcmFTZWxlY3RVaS5lbmFibGUoKTtcbiAgICAgICAgICAgICAgICByZXNldENhbWVyYUFjdGlvblN0YXJ0QnV0dG9uKHRydWUpO1xuICAgICAgICAgICAgICAgICR0aGlzLnNldEhlYWRlck1lc3NhZ2UoZXJyb3IsIEh0bWw1UXJjb2RlU2Nhbm5lclN0YXR1cy5TVEFUVVNfV0FSTklORyk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGlmIChjYW1lcmFTZWxlY3RVaS5oYXNTaW5nbGVJdGVtKCkpIHtcbiAgICAgICAgICAgIGNhbWVyYUFjdGlvblN0YXJ0QnV0dG9uLmNsaWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgY2FtZXJhQWN0aW9uU3RvcEJ1dHRvbi5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgIGlmICghJHRoaXMuaHRtbDVRcmNvZGUpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyBcImh0bWw1UXJjb2RlIG5vdCBkZWZpbmVkXCI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICR0aGlzLmh0bWw1UXJjb2RlLnN0b3AoKVxuICAgICAgICAgICAgICAgIC50aGVuKGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICAgICAgaWYgKF90aGlzLnNjYW5UeXBlU2VsZWN0b3IuaGFzTW9yZVRoYW5PbmVTY2FuVHlwZSgpKSB7XG4gICAgICAgICAgICAgICAgICAgICR0aGlzLnNob3dIaWRlU2NhblR5cGVTd2FwTGluayh0cnVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgY2FtZXJhU2VsZWN0VWkuZW5hYmxlKCk7XG4gICAgICAgICAgICAgICAgY2FtZXJhQWN0aW9uU3RhcnRCdXR0b24uZGlzYWJsZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgICAgICAgICBpZiAodG9yY2hCdXR0b24pIHtcbiAgICAgICAgICAgICAgICAgICAgdG9yY2hCdXR0b24ucmVzZXQoKTtcbiAgICAgICAgICAgICAgICAgICAgdG9yY2hCdXR0b24uaGlkZSgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYW1lcmFab29tVWkucmVtb3ZlT25DYW1lcmFab29tVmFsdWVDaGFuZ2VDYWxsYmFjaygpO1xuICAgICAgICAgICAgICAgIGNhbWVyYVpvb21VaS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgJHRoaXMuaW5zZXJ0Q2FtZXJhU2NhbkltYWdlVG9TY2FuUmVnaW9uKCk7XG4gICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdG9wQnV0dG9uLmRpc2FibGVkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgJHRoaXMuc2V0SGVhZGVyTWVzc2FnZShlcnJvciwgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19XQVJOSU5HKTtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICAgICAgaWYgKCR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLmdldExhc3RVc2VkQ2FtZXJhSWQoKSkge1xuICAgICAgICAgICAgdmFyIGNhbWVyYUlkID0gJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuZ2V0TGFzdFVzZWRDYW1lcmFJZCgpO1xuICAgICAgICAgICAgaWYgKGNhbWVyYVNlbGVjdFVpLmhhc1ZhbHVlKGNhbWVyYUlkKSkge1xuICAgICAgICAgICAgICAgIGNhbWVyYVNlbGVjdFVpLnNldFZhbHVlKGNhbWVyYUlkKTtcbiAgICAgICAgICAgICAgICBjYW1lcmFBY3Rpb25TdGFydEJ1dHRvbi5jbGljaygpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgJHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIucmVzZXRMYXN0VXNlZENhbWVyYUlkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuY3JlYXRlU2VjdGlvblN3YXAgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHZhciAkdGhpcyA9IHRoaXM7XG4gICAgICAgIHZhciBURVhUX0lGX0NBTUVSQV9TQ0FOX1NFTEVDVEVEID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50ZXh0SWZDYW1lcmFTY2FuU2VsZWN0ZWQoKTtcbiAgICAgICAgdmFyIFRFWFRfSUZfRklMRV9TQ0FOX1NFTEVDVEVEID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy50ZXh0SWZGaWxlU2NhblNlbGVjdGVkKCk7XG4gICAgICAgIHZhciBzZWN0aW9uID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uSWQoKSk7XG4gICAgICAgIHZhciBzd2l0Y2hDb250YWluZXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KFwiZGl2XCIpO1xuICAgICAgICBzd2l0Y2hDb250YWluZXIuc3R5bGUudGV4dEFsaWduID0gXCJjZW50ZXJcIjtcbiAgICAgICAgdmFyIHN3aXRjaFNjYW5UeXBlTGluayA9IEJhc2VVaUVsZW1lbnRGYWN0b3J5LmNyZWF0ZUVsZW1lbnQoXCJzcGFuXCIsIHRoaXMuZ2V0RGFzaGJvYXJkU2VjdGlvblN3YXBMaW5rSWQoKSk7XG4gICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5zdHlsZS50ZXh0RGVjb3JhdGlvbiA9IFwidW5kZXJsaW5lXCI7XG4gICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5zdHlsZS5jdXJzb3IgPSBcInBvaW50ZXJcIjtcbiAgICAgICAgc3dpdGNoU2NhblR5cGVMaW5rLmlubmVyVGV4dFxuICAgICAgICAgICAgPSBTY2FuVHlwZVNlbGVjdG9yLmlzQ2FtZXJhU2NhblR5cGUodGhpcy5jdXJyZW50U2NhblR5cGUpXG4gICAgICAgICAgICAgICAgPyBURVhUX0lGX0NBTUVSQV9TQ0FOX1NFTEVDVEVEIDogVEVYVF9JRl9GSUxFX1NDQU5fU0VMRUNURUQ7XG4gICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5hZGRFdmVudExpc3RlbmVyKFwiY2xpY2tcIiwgZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKCEkdGhpcy5zZWN0aW9uU3dhcEFsbG93ZWQpIHtcbiAgICAgICAgICAgICAgICBpZiAoJHRoaXMudmVyYm9zZSkge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJTZWN0aW9uIHN3YXAgY2FsbGVkIHdoZW4gbm90IGFsbG93ZWRcIik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICR0aGlzLnJlc2V0SGVhZGVyTWVzc2FnZSgpO1xuICAgICAgICAgICAgJHRoaXMuZmlsZVNlbGVjdGlvblVpLnJlc2V0VmFsdWUoKTtcbiAgICAgICAgICAgICR0aGlzLnNlY3Rpb25Td2FwQWxsb3dlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKFNjYW5UeXBlU2VsZWN0b3IuaXNDYW1lcmFTY2FuVHlwZSgkdGhpcy5jdXJyZW50U2NhblR5cGUpKSB7XG4gICAgICAgICAgICAgICAgJHRoaXMuY2xlYXJTY2FuUmVnaW9uKCk7XG4gICAgICAgICAgICAgICAgJHRoaXMuZ2V0Q2FtZXJhU2NhblJlZ2lvbigpLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICAgICAgICAgICAgICAkdGhpcy5maWxlU2VsZWN0aW9uVWkuc2hvdygpO1xuICAgICAgICAgICAgICAgIHN3aXRjaFNjYW5UeXBlTGluay5pbm5lclRleHQgPSBURVhUX0lGX0ZJTEVfU0NBTl9TRUxFQ1RFRDtcbiAgICAgICAgICAgICAgICAkdGhpcy5jdXJyZW50U2NhblR5cGUgPSBIdG1sNVFyY29kZVNjYW5UeXBlLlNDQU5fVFlQRV9GSUxFO1xuICAgICAgICAgICAgICAgICR0aGlzLmluc2VydEZpbGVTY2FuSW1hZ2VUb1NjYW5SZWdpb24oKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICR0aGlzLmNsZWFyU2NhblJlZ2lvbigpO1xuICAgICAgICAgICAgICAgICR0aGlzLmdldENhbWVyYVNjYW5SZWdpb24oKS5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgICAgICAgICAgICR0aGlzLmZpbGVTZWxlY3Rpb25VaS5oaWRlKCk7XG4gICAgICAgICAgICAgICAgc3dpdGNoU2NhblR5cGVMaW5rLmlubmVyVGV4dCA9IFRFWFRfSUZfQ0FNRVJBX1NDQU5fU0VMRUNURUQ7XG4gICAgICAgICAgICAgICAgJHRoaXMuY3VycmVudFNjYW5UeXBlID0gSHRtbDVRcmNvZGVTY2FuVHlwZS5TQ0FOX1RZUEVfQ0FNRVJBO1xuICAgICAgICAgICAgICAgICR0aGlzLmluc2VydENhbWVyYVNjYW5JbWFnZVRvU2NhblJlZ2lvbigpO1xuICAgICAgICAgICAgICAgICR0aGlzLnN0YXJ0Q2FtZXJhU2NhbklmUGVybWlzc2lvbkV4aXN0c09uU3dhcCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgJHRoaXMuc2VjdGlvblN3YXBBbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgfSk7XG4gICAgICAgIHN3aXRjaENvbnRhaW5lci5hcHBlbmRDaGlsZChzd2l0Y2hTY2FuVHlwZUxpbmspO1xuICAgICAgICBzZWN0aW9uLmFwcGVuZENoaWxkKHN3aXRjaENvbnRhaW5lcik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLnN0YXJ0Q2FtZXJhU2NhbklmUGVybWlzc2lvbkV4aXN0c09uU3dhcCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIF90aGlzID0gdGhpcztcbiAgICAgICAgdmFyICR0aGlzID0gdGhpcztcbiAgICAgICAgaWYgKHRoaXMucGVyc2lzdGVkRGF0YU1hbmFnZXIuaGFzQ2FtZXJhUGVybWlzc2lvbnMoKSkge1xuICAgICAgICAgICAgQ2FtZXJhUGVybWlzc2lvbnMuaGFzUGVybWlzc2lvbnMoKS50aGVuKGZ1bmN0aW9uIChoYXNQZXJtaXNzaW9ucykge1xuICAgICAgICAgICAgICAgIGlmIChoYXNQZXJtaXNzaW9ucykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgcGVybWlzc2lvbkJ1dHRvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCR0aGlzLmdldENhbWVyYVBlcm1pc3Npb25CdXR0b25JZCgpKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFwZXJtaXNzaW9uQnV0dG9uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdGhpcy5sb2dnZXIubG9nRXJyb3IoXCJQZXJtaXNzaW9uIGJ1dHRvbiBub3QgZm91bmQsIGZhaWw7XCIpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgXCJQZXJtaXNzaW9uIGJ1dHRvbiBub3QgZm91bmRcIjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBwZXJtaXNzaW9uQnV0dG9uLmNsaWNrKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkdGhpcy5wZXJzaXN0ZWREYXRhTWFuYWdlci5zZXRIYXNQZXJtaXNzaW9uKGZhbHNlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KS5jYXRjaChmdW5jdGlvbiAoXykge1xuICAgICAgICAgICAgICAgICR0aGlzLnBlcnNpc3RlZERhdGFNYW5hZ2VyLnNldEhhc1Blcm1pc3Npb24oZmFsc2UpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUucmVzZXRIZWFkZXJNZXNzYWdlID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgbWVzc2FnZURpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0SGVhZGVyTWVzc2FnZUNvbnRhaW5lcklkKCkpO1xuICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuc2V0SGVhZGVyTWVzc2FnZSA9IGZ1bmN0aW9uIChtZXNzYWdlVGV4dCwgc2Nhbm5lclN0YXR1cykge1xuICAgICAgICBpZiAoIXNjYW5uZXJTdGF0dXMpIHtcbiAgICAgICAgICAgIHNjYW5uZXJTdGF0dXMgPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX0RFRkFVTFQ7XG4gICAgICAgIH1cbiAgICAgICAgdmFyIG1lc3NhZ2VEaXYgPSB0aGlzLmdldEhlYWRlck1lc3NhZ2VEaXYoKTtcbiAgICAgICAgbWVzc2FnZURpdi5pbm5lclRleHQgPSBtZXNzYWdlVGV4dDtcbiAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuICAgICAgICBzd2l0Y2ggKHNjYW5uZXJTdGF0dXMpIHtcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19TVUNDRVNTOlxuICAgICAgICAgICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuYmFja2dyb3VuZCA9IFwicmdiYSgxMDYsIDE3NSwgODAsIDAuMjYpXCI7XG4gICAgICAgICAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5jb2xvciA9IFwiIzQ3NzczNVwiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0dXMuU1RBVFVTX1dBUk5JTkc6XG4gICAgICAgICAgICAgICAgbWVzc2FnZURpdi5zdHlsZS5iYWNrZ3JvdW5kID0gXCJyZ2JhKDIwMywgMzYsIDQ5LCAwLjE0KVwiO1xuICAgICAgICAgICAgICAgIG1lc3NhZ2VEaXYuc3R5bGUuY29sb3IgPSBcIiNjYjI0MzFcIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgSHRtbDVRcmNvZGVTY2FubmVyU3RhdHVzLlNUQVRVU19ERUZBVUxUOlxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmJhY2tncm91bmQgPSBcInJnYmEoMCwgMCwgMCwgMClcIjtcbiAgICAgICAgICAgICAgICBtZXNzYWdlRGl2LnN0eWxlLmNvbG9yID0gXCJyZ2IoMTcsIDE3LCAxNylcIjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5zaG93SGlkZVNjYW5UeXBlU3dhcExpbmsgPSBmdW5jdGlvbiAoc2hvdWxkRGlzcGxheSkge1xuICAgICAgICBpZiAodGhpcy5zY2FuVHlwZVNlbGVjdG9yLmhhc01vcmVUaGFuT25lU2NhblR5cGUoKSkge1xuICAgICAgICAgICAgaWYgKHNob3VsZERpc3BsYXkgIT09IHRydWUpIHtcbiAgICAgICAgICAgICAgICBzaG91bGREaXNwbGF5ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICB0aGlzLnNlY3Rpb25Td2FwQWxsb3dlZCA9IHNob3VsZERpc3BsYXk7XG4gICAgICAgICAgICB0aGlzLmdldERhc2hib2FyZFNlY3Rpb25Td2FwTGluaygpLnN0eWxlLmRpc3BsYXlcbiAgICAgICAgICAgICAgICA9IHNob3VsZERpc3BsYXkgPyBcImlubGluZS1ibG9ja1wiIDogXCJub25lXCI7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIEh0bWw1UXJjb2RlU2Nhbm5lci5wcm90b3R5cGUuaW5zZXJ0Q2FtZXJhU2NhbkltYWdlVG9TY2FuUmVnaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcXJDb2RlU2NhblJlZ2lvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0U2NhblJlZ2lvbklkKCkpO1xuICAgICAgICBpZiAodGhpcy5jYW1lcmFTY2FuSW1hZ2UpIHtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uaW5uZXJIVE1MID0gXCI8YnI+XCI7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmFwcGVuZENoaWxkKHRoaXMuY2FtZXJhU2NhbkltYWdlKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZSA9IG5ldyBJbWFnZTtcbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2Uub25sb2FkID0gZnVuY3Rpb24gKF8pIHtcbiAgICAgICAgICAgIHFyQ29kZVNjYW5SZWdpb24uaW5uZXJIVE1MID0gXCI8YnI+XCI7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmFwcGVuZENoaWxkKCR0aGlzLmNhbWVyYVNjYW5JbWFnZSk7XG4gICAgICAgIH07XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlLndpZHRoID0gNjQ7XG4gICAgICAgIHRoaXMuY2FtZXJhU2NhbkltYWdlLnN0eWxlLm9wYWNpdHkgPSBcIjAuOFwiO1xuICAgICAgICB0aGlzLmNhbWVyYVNjYW5JbWFnZS5zcmMgPSBBU1NFVF9DQU1FUkFfU0NBTjtcbiAgICAgICAgdGhpcy5jYW1lcmFTY2FuSW1hZ2UuYWx0ID0gSHRtbDVRcmNvZGVTY2FubmVyU3RyaW5ncy5jYW1lcmFTY2FuQWx0VGV4dCgpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5pbnNlcnRGaWxlU2NhbkltYWdlVG9TY2FuUmVnaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICB2YXIgJHRoaXMgPSB0aGlzO1xuICAgICAgICB2YXIgcXJDb2RlU2NhblJlZ2lvbiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKHRoaXMuZ2V0U2NhblJlZ2lvbklkKCkpO1xuICAgICAgICBpZiAodGhpcy5maWxlU2NhbkltYWdlKSB7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmlubmVySFRNTCA9IFwiPGJyPlwiO1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5hcHBlbmRDaGlsZCh0aGlzLmZpbGVTY2FuSW1hZ2UpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZSA9IG5ldyBJbWFnZTtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLm9ubG9hZCA9IGZ1bmN0aW9uIChfKSB7XG4gICAgICAgICAgICBxckNvZGVTY2FuUmVnaW9uLmlubmVySFRNTCA9IFwiPGJyPlwiO1xuICAgICAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5hcHBlbmRDaGlsZCgkdGhpcy5maWxlU2NhbkltYWdlKTtcbiAgICAgICAgfTtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLndpZHRoID0gNjQ7XG4gICAgICAgIHRoaXMuZmlsZVNjYW5JbWFnZS5zdHlsZS5vcGFjaXR5ID0gXCIwLjhcIjtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLnNyYyA9IEFTU0VUX0ZJTEVfU0NBTjtcbiAgICAgICAgdGhpcy5maWxlU2NhbkltYWdlLmFsdCA9IEh0bWw1UXJjb2RlU2Nhbm5lclN0cmluZ3MuZmlsZVNjYW5BbHRUZXh0KCk7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmNsZWFyU2NhblJlZ2lvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHFyQ29kZVNjYW5SZWdpb24gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldFNjYW5SZWdpb25JZCgpKTtcbiAgICAgICAgcXJDb2RlU2NhblJlZ2lvbi5pbm5lckhUTUwgPSBcIlwiO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRTZWN0aW9uSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCJfX2Rhc2hib2FyZF9zZWN0aW9uXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRTZWN0aW9uQ2FtZXJhU2NhblJlZ2lvbklkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gXCJcIi5jb25jYXQodGhpcy5lbGVtZW50SWQsIFwiX19kYXNoYm9hcmRfc2VjdGlvbl9jc3JcIik7XG4gICAgfTtcbiAgICBIdG1sNVFyY29kZVNjYW5uZXIucHJvdG90eXBlLmdldERhc2hib2FyZFNlY3Rpb25Td2FwTGlua0lkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gUHVibGljVWlFbGVtZW50SWRBbmRDbGFzc2VzLlNDQU5fVFlQRV9DSEFOR0VfQU5DSE9SX0lEO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRTY2FuUmVnaW9uSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCJfX3NjYW5fcmVnaW9uXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRJZCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgcmV0dXJuIFwiXCIuY29uY2F0KHRoaXMuZWxlbWVudElkLCBcIl9fZGFzaGJvYXJkXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRIZWFkZXJNZXNzYWdlQ29udGFpbmVySWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBcIlwiLmNvbmNhdCh0aGlzLmVsZW1lbnRJZCwgXCJfX2hlYWRlcl9tZXNzYWdlXCIpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRDYW1lcmFQZXJtaXNzaW9uQnV0dG9uSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBQdWJsaWNVaUVsZW1lbnRJZEFuZENsYXNzZXMuQ0FNRVJBX1BFUk1JU1NJT05fQlVUVE9OX0lEO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRDYW1lcmFTY2FuUmVnaW9uID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXREYXNoYm9hcmRTZWN0aW9uQ2FtZXJhU2NhblJlZ2lvbklkKCkpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXREYXNoYm9hcmRTZWN0aW9uU3dhcExpbmsgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIHJldHVybiBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLmdldERhc2hib2FyZFNlY3Rpb25Td2FwTGlua0lkKCkpO1xuICAgIH07XG4gICAgSHRtbDVRcmNvZGVTY2FubmVyLnByb3RvdHlwZS5nZXRIZWFkZXJNZXNzYWdlRGl2ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICByZXR1cm4gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQodGhpcy5nZXRIZWFkZXJNZXNzYWdlQ29udGFpbmVySWQoKSk7XG4gICAgfTtcbiAgICByZXR1cm4gSHRtbDVRcmNvZGVTY2FubmVyO1xufSgpKTtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lciB9O1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9aHRtbDUtcXJjb2RlLXNjYW5uZXIuanMubWFwIiwiZXhwb3J0IHsgSHRtbDVRcmNvZGUgfSBmcm9tIFwiLi9odG1sNS1xcmNvZGVcIjtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2Nhbm5lciB9IGZyb20gXCIuL2h0bWw1LXFyY29kZS1zY2FubmVyXCI7XG5leHBvcnQgeyBIdG1sNVFyY29kZVN1cHBvcnRlZEZvcm1hdHMgfSBmcm9tIFwiLi9jb3JlXCI7XG5leHBvcnQgeyBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZSB9IGZyb20gXCIuL3N0YXRlLW1hbmFnZXJcIjtcbmV4cG9ydCB7IEh0bWw1UXJjb2RlU2NhblR5cGUgfSBmcm9tIFwiLi9jb3JlXCI7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5qcy5tYXAiLCJleHBvcnQgZnVuY3Rpb24gbnVtYmVyKG4pIHtcbiAgICBpZiAoIU51bWJlci5pc1NhZmVJbnRlZ2VyKG4pIHx8IG4gPCAwKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFdyb25nIHBvc2l0aXZlIGludGVnZXI6ICR7bn1gKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBib29sKGIpIHtcbiAgICBpZiAodHlwZW9mIGIgIT09ICdib29sZWFuJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCBib29sZWFuLCBub3QgJHtifWApO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVzKGIsIC4uLmxlbmd0aHMpIHtcbiAgICBpZiAoIShiIGluc3RhbmNlb2YgVWludDhBcnJheSkpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0V4cGVjdGVkIFVpbnQ4QXJyYXknKTtcbiAgICBpZiAobGVuZ3Rocy5sZW5ndGggPiAwICYmICFsZW5ndGhzLmluY2x1ZGVzKGIubGVuZ3RoKSlcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgRXhwZWN0ZWQgVWludDhBcnJheSBvZiBsZW5ndGggJHtsZW5ndGhzfSwgbm90IG9mIGxlbmd0aD0ke2IubGVuZ3RofWApO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGhhc2goaGFzaCkge1xuICAgIGlmICh0eXBlb2YgaGFzaCAhPT0gJ2Z1bmN0aW9uJyB8fCB0eXBlb2YgaGFzaC5jcmVhdGUgIT09ICdmdW5jdGlvbicpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSGFzaCBzaG91bGQgYmUgd3JhcHBlZCBieSB1dGlscy53cmFwQ29uc3RydWN0b3InKTtcbiAgICBudW1iZXIoaGFzaC5vdXRwdXRMZW4pO1xuICAgIG51bWJlcihoYXNoLmJsb2NrTGVuKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBleGlzdHMoaW5zdGFuY2UsIGNoZWNrRmluaXNoZWQgPSB0cnVlKSB7XG4gICAgaWYgKGluc3RhbmNlLmRlc3Ryb3llZClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdIYXNoIGluc3RhbmNlIGhhcyBiZWVuIGRlc3Ryb3llZCcpO1xuICAgIGlmIChjaGVja0ZpbmlzaGVkICYmIGluc3RhbmNlLmZpbmlzaGVkKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0hhc2gjZGlnZXN0KCkgaGFzIGFscmVhZHkgYmVlbiBjYWxsZWQnKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBvdXRwdXQob3V0LCBpbnN0YW5jZSkge1xuICAgIGJ5dGVzKG91dCk7XG4gICAgY29uc3QgbWluID0gaW5zdGFuY2Uub3V0cHV0TGVuO1xuICAgIGlmIChvdXQubGVuZ3RoIDwgbWluKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgZGlnZXN0SW50bygpIGV4cGVjdHMgb3V0cHV0IGJ1ZmZlciBvZiBsZW5ndGggYXQgbGVhc3QgJHttaW59YCk7XG4gICAgfVxufVxuY29uc3QgYXNzZXJ0ID0ge1xuICAgIG51bWJlcixcbiAgICBib29sLFxuICAgIGJ5dGVzLFxuICAgIGhhc2gsXG4gICAgZXhpc3RzLFxuICAgIG91dHB1dCxcbn07XG5leHBvcnQgZGVmYXVsdCBhc3NlcnQ7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1fYXNzZXJ0LmpzLm1hcCIsImNvbnN0IFUzMl9NQVNLNjQgPSBCaWdJbnQoMiAqKiAzMiAtIDEpO1xuY29uc3QgXzMybiA9IEJpZ0ludCgzMik7XG4vLyBXZSBhcmUgbm90IHVzaW5nIEJpZ1VpbnQ2NEFycmF5LCBiZWNhdXNlIHRoZXkgYXJlIGV4dHJlbWVseSBzbG93IGFzIHBlciAyMDIyXG5leHBvcnQgZnVuY3Rpb24gZnJvbUJpZyhuLCBsZSA9IGZhbHNlKSB7XG4gICAgaWYgKGxlKVxuICAgICAgICByZXR1cm4geyBoOiBOdW1iZXIobiAmIFUzMl9NQVNLNjQpLCBsOiBOdW1iZXIoKG4gPj4gXzMybikgJiBVMzJfTUFTSzY0KSB9O1xuICAgIHJldHVybiB7IGg6IE51bWJlcigobiA+PiBfMzJuKSAmIFUzMl9NQVNLNjQpIHwgMCwgbDogTnVtYmVyKG4gJiBVMzJfTUFTSzY0KSB8IDAgfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBzcGxpdChsc3QsIGxlID0gZmFsc2UpIHtcbiAgICBsZXQgQWggPSBuZXcgVWludDMyQXJyYXkobHN0Lmxlbmd0aCk7XG4gICAgbGV0IEFsID0gbmV3IFVpbnQzMkFycmF5KGxzdC5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbHN0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IHsgaCwgbCB9ID0gZnJvbUJpZyhsc3RbaV0sIGxlKTtcbiAgICAgICAgW0FoW2ldLCBBbFtpXV0gPSBbaCwgbF07XG4gICAgfVxuICAgIHJldHVybiBbQWgsIEFsXTtcbn1cbmV4cG9ydCBjb25zdCB0b0JpZyA9IChoLCBsKSA9PiAoQmlnSW50KGggPj4+IDApIDw8IF8zMm4pIHwgQmlnSW50KGwgPj4+IDApO1xuLy8gZm9yIFNoaWZ0IGluIFswLCAzMilcbmNvbnN0IHNoclNIID0gKGgsIGwsIHMpID0+IGggPj4+IHM7XG5jb25zdCBzaHJTTCA9IChoLCBsLCBzKSA9PiAoaCA8PCAoMzIgLSBzKSkgfCAobCA+Pj4gcyk7XG4vLyBSaWdodCByb3RhdGUgZm9yIFNoaWZ0IGluIFsxLCAzMilcbmNvbnN0IHJvdHJTSCA9IChoLCBsLCBzKSA9PiAoaCA+Pj4gcykgfCAobCA8PCAoMzIgLSBzKSk7XG5jb25zdCByb3RyU0wgPSAoaCwgbCwgcykgPT4gKGggPDwgKDMyIC0gcykpIHwgKGwgPj4+IHMpO1xuLy8gUmlnaHQgcm90YXRlIGZvciBTaGlmdCBpbiAoMzIsIDY0KSwgTk9URTogMzIgaXMgc3BlY2lhbCBjYXNlLlxuY29uc3Qgcm90ckJIID0gKGgsIGwsIHMpID0+IChoIDw8ICg2NCAtIHMpKSB8IChsID4+PiAocyAtIDMyKSk7XG5jb25zdCByb3RyQkwgPSAoaCwgbCwgcykgPT4gKGggPj4+IChzIC0gMzIpKSB8IChsIDw8ICg2NCAtIHMpKTtcbi8vIFJpZ2h0IHJvdGF0ZSBmb3Igc2hpZnQ9PT0zMiAoanVzdCBzd2FwcyBsJmgpXG5jb25zdCByb3RyMzJIID0gKGgsIGwpID0+IGw7XG5jb25zdCByb3RyMzJMID0gKGgsIGwpID0+IGg7XG4vLyBMZWZ0IHJvdGF0ZSBmb3IgU2hpZnQgaW4gWzEsIDMyKVxuY29uc3Qgcm90bFNIID0gKGgsIGwsIHMpID0+IChoIDw8IHMpIHwgKGwgPj4+ICgzMiAtIHMpKTtcbmNvbnN0IHJvdGxTTCA9IChoLCBsLCBzKSA9PiAobCA8PCBzKSB8IChoID4+PiAoMzIgLSBzKSk7XG4vLyBMZWZ0IHJvdGF0ZSBmb3IgU2hpZnQgaW4gKDMyLCA2NCksIE5PVEU6IDMyIGlzIHNwZWNpYWwgY2FzZS5cbmNvbnN0IHJvdGxCSCA9IChoLCBsLCBzKSA9PiAobCA8PCAocyAtIDMyKSkgfCAoaCA+Pj4gKDY0IC0gcykpO1xuY29uc3Qgcm90bEJMID0gKGgsIGwsIHMpID0+IChoIDw8IChzIC0gMzIpKSB8IChsID4+PiAoNjQgLSBzKSk7XG4vLyBKUyB1c2VzIDMyLWJpdCBzaWduZWQgaW50ZWdlcnMgZm9yIGJpdHdpc2Ugb3BlcmF0aW9ucyB3aGljaCBtZWFucyB3ZSBjYW5ub3Rcbi8vIHNpbXBsZSB0YWtlIGNhcnJ5IG91dCBvZiBsb3cgYml0IHN1bSBieSBzaGlmdCwgd2UgbmVlZCB0byB1c2UgZGl2aXNpb24uXG4vLyBSZW1vdmluZyBcImV4cG9ydFwiIGhhcyA1JSBwZXJmIHBlbmFsdHkgLV8tXG5leHBvcnQgZnVuY3Rpb24gYWRkKEFoLCBBbCwgQmgsIEJsKSB7XG4gICAgY29uc3QgbCA9IChBbCA+Pj4gMCkgKyAoQmwgPj4+IDApO1xuICAgIHJldHVybiB7IGg6IChBaCArIEJoICsgKChsIC8gMiAqKiAzMikgfCAwKSkgfCAwLCBsOiBsIHwgMCB9O1xufVxuLy8gQWRkaXRpb24gd2l0aCBtb3JlIHRoYW4gMiBlbGVtZW50c1xuY29uc3QgYWRkM0wgPSAoQWwsIEJsLCBDbCkgPT4gKEFsID4+PiAwKSArIChCbCA+Pj4gMCkgKyAoQ2wgPj4+IDApO1xuY29uc3QgYWRkM0ggPSAobG93LCBBaCwgQmgsIENoKSA9PiAoQWggKyBCaCArIENoICsgKChsb3cgLyAyICoqIDMyKSB8IDApKSB8IDA7XG5jb25zdCBhZGQ0TCA9IChBbCwgQmwsIENsLCBEbCkgPT4gKEFsID4+PiAwKSArIChCbCA+Pj4gMCkgKyAoQ2wgPj4+IDApICsgKERsID4+PiAwKTtcbmNvbnN0IGFkZDRIID0gKGxvdywgQWgsIEJoLCBDaCwgRGgpID0+IChBaCArIEJoICsgQ2ggKyBEaCArICgobG93IC8gMiAqKiAzMikgfCAwKSkgfCAwO1xuY29uc3QgYWRkNUwgPSAoQWwsIEJsLCBDbCwgRGwsIEVsKSA9PiAoQWwgPj4+IDApICsgKEJsID4+PiAwKSArIChDbCA+Pj4gMCkgKyAoRGwgPj4+IDApICsgKEVsID4+PiAwKTtcbmNvbnN0IGFkZDVIID0gKGxvdywgQWgsIEJoLCBDaCwgRGgsIEVoKSA9PiAoQWggKyBCaCArIENoICsgRGggKyBFaCArICgobG93IC8gMiAqKiAzMikgfCAwKSkgfCAwO1xuLy8gcHJldHRpZXItaWdub3JlXG5jb25zdCB1NjQgPSB7XG4gICAgZnJvbUJpZywgc3BsaXQsIHRvQmlnLFxuICAgIHNoclNILCBzaHJTTCxcbiAgICByb3RyU0gsIHJvdHJTTCwgcm90ckJILCByb3RyQkwsXG4gICAgcm90cjMySCwgcm90cjMyTCxcbiAgICByb3RsU0gsIHJvdGxTTCwgcm90bEJILCByb3RsQkwsXG4gICAgYWRkLCBhZGQzTCwgYWRkM0gsIGFkZDRMLCBhZGQ0SCwgYWRkNUgsIGFkZDVMLFxufTtcbmV4cG9ydCBkZWZhdWx0IHU2NDtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPV91NjQuanMubWFwIiwiZXhwb3J0IGNvbnN0IGNyeXB0byA9IHR5cGVvZiBnbG9iYWxUaGlzID09PSAnb2JqZWN0JyAmJiAnY3J5cHRvJyBpbiBnbG9iYWxUaGlzID8gZ2xvYmFsVGhpcy5jcnlwdG8gOiB1bmRlZmluZWQ7XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jcnlwdG8uanMubWFwIiwiLyohIG5vYmxlLWhhc2hlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuLy8gV2UgdXNlIGBnbG9iYWxUaGlzLmNyeXB0b2AsIGJ1dCBub2RlLmpzIHZlcnNpb25zIGVhcmxpZXIgdGhhbiB2MTkgZG9uJ3Rcbi8vIGRlY2xhcmUgaXQgaW4gZ2xvYmFsIHNjb3BlLiBGb3Igbm9kZS5qcywgcGFja2FnZS5qc29uI2V4cG9ydHMgZmllbGQgbWFwcGluZ1xuLy8gcmV3cml0ZXMgaW1wb3J0IGZyb20gYGNyeXB0b2AgdG8gYGNyeXB0b05vZGVgLCB3aGljaCBpbXBvcnRzIG5hdGl2ZSBtb2R1bGUuXG4vLyBNYWtlcyB0aGUgdXRpbHMgdW4taW1wb3J0YWJsZSBpbiBicm93c2VycyB3aXRob3V0IGEgYnVuZGxlci5cbi8vIE9uY2Ugbm9kZS5qcyAxOCBpcyBkZXByZWNhdGVkLCB3ZSBjYW4ganVzdCBkcm9wIHRoZSBpbXBvcnQuXG5pbXBvcnQgeyBjcnlwdG8gfSBmcm9tICdAbm9ibGUvaGFzaGVzL2NyeXB0byc7XG4vLyBDYXN0IGFycmF5IHRvIGRpZmZlcmVudCB0eXBlXG5leHBvcnQgY29uc3QgdTggPSAoYXJyKSA9PiBuZXcgVWludDhBcnJheShhcnIuYnVmZmVyLCBhcnIuYnl0ZU9mZnNldCwgYXJyLmJ5dGVMZW5ndGgpO1xuZXhwb3J0IGNvbnN0IHUzMiA9IChhcnIpID0+IG5ldyBVaW50MzJBcnJheShhcnIuYnVmZmVyLCBhcnIuYnl0ZU9mZnNldCwgTWF0aC5mbG9vcihhcnIuYnl0ZUxlbmd0aCAvIDQpKTtcbi8vIENhc3QgYXJyYXkgdG8gdmlld1xuZXhwb3J0IGNvbnN0IGNyZWF0ZVZpZXcgPSAoYXJyKSA9PiBuZXcgRGF0YVZpZXcoYXJyLmJ1ZmZlciwgYXJyLmJ5dGVPZmZzZXQsIGFyci5ieXRlTGVuZ3RoKTtcbi8vIFRoZSByb3RhdGUgcmlnaHQgKGNpcmN1bGFyIHJpZ2h0IHNoaWZ0KSBvcGVyYXRpb24gZm9yIHVpbnQzMlxuZXhwb3J0IGNvbnN0IHJvdHIgPSAod29yZCwgc2hpZnQpID0+ICh3b3JkIDw8ICgzMiAtIHNoaWZ0KSkgfCAod29yZCA+Pj4gc2hpZnQpO1xuLy8gYmlnLWVuZGlhbiBoYXJkd2FyZSBpcyByYXJlLiBKdXN0IGluIGNhc2Ugc29tZW9uZSBzdGlsbCBkZWNpZGVzIHRvIHJ1biBoYXNoZXM6XG4vLyBlYXJseS10aHJvdyBhbiBlcnJvciBiZWNhdXNlIHdlIGRvbid0IHN1cHBvcnQgQkUgeWV0LlxuZXhwb3J0IGNvbnN0IGlzTEUgPSBuZXcgVWludDhBcnJheShuZXcgVWludDMyQXJyYXkoWzB4MTEyMjMzNDRdKS5idWZmZXIpWzBdID09PSAweDQ0O1xuaWYgKCFpc0xFKVxuICAgIHRocm93IG5ldyBFcnJvcignTm9uIGxpdHRsZS1lbmRpYW4gaGFyZHdhcmUgaXMgbm90IHN1cHBvcnRlZCcpO1xuY29uc3QgaGV4ZXMgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiAyNTYgfSwgKHYsIGkpID0+IGkudG9TdHJpbmcoMTYpLnBhZFN0YXJ0KDIsICcwJykpO1xuLyoqXG4gKiBAZXhhbXBsZSBieXRlc1RvSGV4KFVpbnQ4QXJyYXkuZnJvbShbMHhkZSwgMHhhZCwgMHhiZSwgMHhlZl0pKSAvLyAnZGVhZGJlZWYnXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBieXRlc1RvSGV4KHVpbnQ4YSkge1xuICAgIC8vIHByZS1jYWNoaW5nIGltcHJvdmVzIHRoZSBzcGVlZCA2eFxuICAgIGlmICghKHVpbnQ4YSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgZXhwZWN0ZWQnKTtcbiAgICBsZXQgaGV4ID0gJyc7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB1aW50OGEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaGV4ICs9IGhleGVzW3VpbnQ4YVtpXV07XG4gICAgfVxuICAgIHJldHVybiBoZXg7XG59XG4vKipcbiAqIEBleGFtcGxlIGhleFRvQnl0ZXMoJ2RlYWRiZWVmJykgLy8gVWludDhBcnJheS5mcm9tKFsweGRlLCAweGFkLCAweGJlLCAweGVmXSlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhleFRvQnl0ZXMoaGV4KSB7XG4gICAgaWYgKHR5cGVvZiBoZXggIT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ2hleFRvQnl0ZXM6IGV4cGVjdGVkIHN0cmluZywgZ290ICcgKyB0eXBlb2YgaGV4KTtcbiAgICB9XG4gICAgaWYgKGhleC5sZW5ndGggJSAyKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2hleFRvQnl0ZXM6IHJlY2VpdmVkIGludmFsaWQgdW5wYWRkZWQgaGV4Jyk7XG4gICAgY29uc3QgYXJyYXkgPSBuZXcgVWludDhBcnJheShoZXgubGVuZ3RoIC8gMik7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBqID0gaSAqIDI7XG4gICAgICAgIGNvbnN0IGhleEJ5dGUgPSBoZXguc2xpY2UoaiwgaiArIDIpO1xuICAgICAgICBjb25zdCBieXRlID0gTnVtYmVyLnBhcnNlSW50KGhleEJ5dGUsIDE2KTtcbiAgICAgICAgaWYgKE51bWJlci5pc05hTihieXRlKSB8fCBieXRlIDwgMClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCBieXRlIHNlcXVlbmNlJyk7XG4gICAgICAgIGFycmF5W2ldID0gYnl0ZTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xufVxuLy8gVGhlcmUgaXMgbm8gc2V0SW1tZWRpYXRlIGluIGJyb3dzZXIgYW5kIHNldFRpbWVvdXQgaXMgc2xvdy5cbi8vIGNhbGwgb2YgYXN5bmMgZm4gd2lsbCByZXR1cm4gUHJvbWlzZSwgd2hpY2ggd2lsbCBiZSBmdWxsZmlsZWQgb25seSBvblxuLy8gbmV4dCBzY2hlZHVsZXIgcXVldWUgcHJvY2Vzc2luZyBzdGVwIGFuZCB0aGlzIGlzIGV4YWN0bHkgd2hhdCB3ZSBuZWVkLlxuZXhwb3J0IGNvbnN0IG5leHRUaWNrID0gYXN5bmMgKCkgPT4geyB9O1xuLy8gUmV0dXJucyBjb250cm9sIHRvIHRocmVhZCBlYWNoICd0aWNrJyBtcyB0byBhdm9pZCBibG9ja2luZ1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGFzeW5jTG9vcChpdGVycywgdGljaywgY2IpIHtcbiAgICBsZXQgdHMgPSBEYXRlLm5vdygpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaXRlcnM7IGkrKykge1xuICAgICAgICBjYihpKTtcbiAgICAgICAgLy8gRGF0ZS5ub3coKSBpcyBub3QgbW9ub3RvbmljLCBzbyBpbiBjYXNlIGlmIGNsb2NrIGdvZXMgYmFja3dhcmRzIHdlIHJldHVybiByZXR1cm4gY29udHJvbCB0b29cbiAgICAgICAgY29uc3QgZGlmZiA9IERhdGUubm93KCkgLSB0cztcbiAgICAgICAgaWYgKGRpZmYgPj0gMCAmJiBkaWZmIDwgdGljaylcbiAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICBhd2FpdCBuZXh0VGljaygpO1xuICAgICAgICB0cyArPSBkaWZmO1xuICAgIH1cbn1cbmV4cG9ydCBmdW5jdGlvbiB1dGY4VG9CeXRlcyhzdHIpIHtcbiAgICBpZiAodHlwZW9mIHN0ciAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgdXRmOFRvQnl0ZXMgZXhwZWN0ZWQgc3RyaW5nLCBnb3QgJHt0eXBlb2Ygc3RyfWApO1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFRleHRFbmNvZGVyKCkuZW5jb2RlKHN0cik7XG59XG5leHBvcnQgZnVuY3Rpb24gdG9CeXRlcyhkYXRhKSB7XG4gICAgaWYgKHR5cGVvZiBkYXRhID09PSAnc3RyaW5nJylcbiAgICAgICAgZGF0YSA9IHV0ZjhUb0J5dGVzKGRhdGEpO1xuICAgIGlmICghKGRhdGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KSlcbiAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihgRXhwZWN0ZWQgaW5wdXQgdHlwZSBpcyBVaW50OEFycmF5IChnb3QgJHt0eXBlb2YgZGF0YX0pYCk7XG4gICAgcmV0dXJuIGRhdGE7XG59XG4vKipcbiAqIENvbmNhdHMgVWludDhBcnJheS1zIGludG8gb25lOyBsaWtlIGBCdWZmZXIuY29uY2F0KFtidWYxLCBidWYyXSlgXG4gKiBAZXhhbXBsZSBjb25jYXRCeXRlcyhidWYxLCBidWYyKVxuICovXG5leHBvcnQgZnVuY3Rpb24gY29uY2F0Qnl0ZXMoLi4uYXJyYXlzKSB7XG4gICAgaWYgKCFhcnJheXMuZXZlcnkoKGEpID0+IGEgaW5zdGFuY2VvZiBVaW50OEFycmF5KSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGxpc3QgZXhwZWN0ZWQnKTtcbiAgICBpZiAoYXJyYXlzLmxlbmd0aCA9PT0gMSlcbiAgICAgICAgcmV0dXJuIGFycmF5c1swXTtcbiAgICBjb25zdCBsZW5ndGggPSBhcnJheXMucmVkdWNlKChhLCBhcnIpID0+IGEgKyBhcnIubGVuZ3RoLCAwKTtcbiAgICBjb25zdCByZXN1bHQgPSBuZXcgVWludDhBcnJheShsZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwLCBwYWQgPSAwOyBpIDwgYXJyYXlzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGFyciA9IGFycmF5c1tpXTtcbiAgICAgICAgcmVzdWx0LnNldChhcnIsIHBhZCk7XG4gICAgICAgIHBhZCArPSBhcnIubGVuZ3RoO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xufVxuLy8gRm9yIHJ1bnRpbWUgY2hlY2sgaWYgY2xhc3MgaW1wbGVtZW50cyBpbnRlcmZhY2VcbmV4cG9ydCBjbGFzcyBIYXNoIHtcbiAgICAvLyBTYWZlIHZlcnNpb24gdGhhdCBjbG9uZXMgaW50ZXJuYWwgc3RhdGVcbiAgICBjbG9uZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2Nsb25lSW50bygpO1xuICAgIH1cbn1cbi8vIENoZWNrIGlmIG9iamVjdCBkb2Vucyd0IGhhdmUgY3VzdG9tIGNvbnN0cnVjdG9yIChsaWtlIFVpbnQ4QXJyYXkvQXJyYXkpXG5jb25zdCBpc1BsYWluT2JqZWN0ID0gKG9iaikgPT4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKG9iaikgPT09ICdbb2JqZWN0IE9iamVjdF0nICYmIG9iai5jb25zdHJ1Y3RvciA9PT0gT2JqZWN0O1xuZXhwb3J0IGZ1bmN0aW9uIGNoZWNrT3B0cyhkZWZhdWx0cywgb3B0cykge1xuICAgIGlmIChvcHRzICE9PSB1bmRlZmluZWQgJiYgKHR5cGVvZiBvcHRzICE9PSAnb2JqZWN0JyB8fCAhaXNQbGFpbk9iamVjdChvcHRzKSkpXG4gICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ09wdGlvbnMgc2hvdWxkIGJlIG9iamVjdCBvciB1bmRlZmluZWQnKTtcbiAgICBjb25zdCBtZXJnZWQgPSBPYmplY3QuYXNzaWduKGRlZmF1bHRzLCBvcHRzKTtcbiAgICByZXR1cm4gbWVyZ2VkO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHdyYXBDb25zdHJ1Y3RvcihoYXNoQ29uc3RydWN0b3IpIHtcbiAgICBjb25zdCBoYXNoQyA9IChtZXNzYWdlKSA9PiBoYXNoQ29uc3RydWN0b3IoKS51cGRhdGUodG9CeXRlcyhtZXNzYWdlKSkuZGlnZXN0KCk7XG4gICAgY29uc3QgdG1wID0gaGFzaENvbnN0cnVjdG9yKCk7XG4gICAgaGFzaEMub3V0cHV0TGVuID0gdG1wLm91dHB1dExlbjtcbiAgICBoYXNoQy5ibG9ja0xlbiA9IHRtcC5ibG9ja0xlbjtcbiAgICBoYXNoQy5jcmVhdGUgPSAoKSA9PiBoYXNoQ29uc3RydWN0b3IoKTtcbiAgICByZXR1cm4gaGFzaEM7XG59XG5leHBvcnQgZnVuY3Rpb24gd3JhcENvbnN0cnVjdG9yV2l0aE9wdHMoaGFzaENvbnMpIHtcbiAgICBjb25zdCBoYXNoQyA9IChtc2csIG9wdHMpID0+IGhhc2hDb25zKG9wdHMpLnVwZGF0ZSh0b0J5dGVzKG1zZykpLmRpZ2VzdCgpO1xuICAgIGNvbnN0IHRtcCA9IGhhc2hDb25zKHt9KTtcbiAgICBoYXNoQy5vdXRwdXRMZW4gPSB0bXAub3V0cHV0TGVuO1xuICAgIGhhc2hDLmJsb2NrTGVuID0gdG1wLmJsb2NrTGVuO1xuICAgIGhhc2hDLmNyZWF0ZSA9IChvcHRzKSA9PiBoYXNoQ29ucyhvcHRzKTtcbiAgICByZXR1cm4gaGFzaEM7XG59XG4vKipcbiAqIFNlY3VyZSBQUk5HLiBVc2VzIGBnbG9iYWxUaGlzLmNyeXB0b2Agb3Igbm9kZS5qcyBjcnlwdG8gbW9kdWxlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmFuZG9tQnl0ZXMoYnl0ZXNMZW5ndGggPSAzMikge1xuICAgIGlmIChjcnlwdG8gJiYgdHlwZW9mIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgcmV0dXJuIGNyeXB0by5nZXRSYW5kb21WYWx1ZXMobmV3IFVpbnQ4QXJyYXkoYnl0ZXNMZW5ndGgpKTtcbiAgICB9XG4gICAgdGhyb3cgbmV3IEVycm9yKCdjcnlwdG8uZ2V0UmFuZG9tVmFsdWVzIG11c3QgYmUgZGVmaW5lZCcpO1xufVxuLy8jIHNvdXJjZU1hcHBpbmdVUkw9dXRpbHMuanMubWFwIiwiaW1wb3J0IGFzc2VydCBmcm9tICcuL19hc3NlcnQuanMnO1xuaW1wb3J0IHU2NCBmcm9tICcuL191NjQuanMnO1xuaW1wb3J0IHsgSGFzaCwgdTMyLCB0b0J5dGVzLCB3cmFwQ29uc3RydWN0b3IsIHdyYXBDb25zdHJ1Y3RvcldpdGhPcHRzLCB9IGZyb20gJy4vdXRpbHMuanMnO1xuLy8gVmFyaW91cyBwZXIgcm91bmQgY29uc3RhbnRzIGNhbGN1bGF0aW9uc1xuY29uc3QgW1NIQTNfUEksIFNIQTNfUk9UTCwgX1NIQTNfSU9UQV0gPSBbW10sIFtdLCBbXV07XG5jb25zdCBfMG4gPSBCaWdJbnQoMCk7XG5jb25zdCBfMW4gPSBCaWdJbnQoMSk7XG5jb25zdCBfMm4gPSBCaWdJbnQoMik7XG5jb25zdCBfN24gPSBCaWdJbnQoNyk7XG5jb25zdCBfMjU2biA9IEJpZ0ludCgyNTYpO1xuY29uc3QgXzB4NzFuID0gQmlnSW50KDB4NzEpO1xuZm9yIChsZXQgcm91bmQgPSAwLCBSID0gXzFuLCB4ID0gMSwgeSA9IDA7IHJvdW5kIDwgMjQ7IHJvdW5kKyspIHtcbiAgICAvLyBQaVxuICAgIFt4LCB5XSA9IFt5LCAoMiAqIHggKyAzICogeSkgJSA1XTtcbiAgICBTSEEzX1BJLnB1c2goMiAqICg1ICogeSArIHgpKTtcbiAgICAvLyBSb3RhdGlvbmFsXG4gICAgU0hBM19ST1RMLnB1c2goKCgocm91bmQgKyAxKSAqIChyb3VuZCArIDIpKSAvIDIpICUgNjQpO1xuICAgIC8vIElvdGFcbiAgICBsZXQgdCA9IF8wbjtcbiAgICBmb3IgKGxldCBqID0gMDsgaiA8IDc7IGorKykge1xuICAgICAgICBSID0gKChSIDw8IF8xbikgXiAoKFIgPj4gXzduKSAqIF8weDcxbikpICUgXzI1Nm47XG4gICAgICAgIGlmIChSICYgXzJuKVxuICAgICAgICAgICAgdCBePSBfMW4gPDwgKChfMW4gPDwgQmlnSW50KGopKSAtIF8xbik7XG4gICAgfVxuICAgIF9TSEEzX0lPVEEucHVzaCh0KTtcbn1cbmNvbnN0IFtTSEEzX0lPVEFfSCwgU0hBM19JT1RBX0xdID0gdTY0LnNwbGl0KF9TSEEzX0lPVEEsIHRydWUpO1xuLy8gTGVmdCByb3RhdGlvbiAod2l0aG91dCAwLCAzMiwgNjQpXG5jb25zdCByb3RsSCA9IChoLCBsLCBzKSA9PiBzID4gMzIgPyB1NjQucm90bEJIKGgsIGwsIHMpIDogdTY0LnJvdGxTSChoLCBsLCBzKTtcbmNvbnN0IHJvdGxMID0gKGgsIGwsIHMpID0+IHMgPiAzMiA/IHU2NC5yb3RsQkwoaCwgbCwgcykgOiB1NjQucm90bFNMKGgsIGwsIHMpO1xuLy8gU2FtZSBhcyBrZWNjYWtmMTYwMCwgYnV0IGFsbG93cyB0byBza2lwIHNvbWUgcm91bmRzXG5leHBvcnQgZnVuY3Rpb24ga2VjY2FrUChzLCByb3VuZHMgPSAyNCkge1xuICAgIGNvbnN0IEIgPSBuZXcgVWludDMyQXJyYXkoNSAqIDIpO1xuICAgIC8vIE5PVEU6IGFsbCBpbmRpY2VzIGFyZSB4MiBzaW5jZSB3ZSBzdG9yZSBzdGF0ZSBhcyB1MzIgaW5zdGVhZCBvZiB1NjQgKGJpZ2ludHMgdG8gc2xvdyBpbiBqcylcbiAgICBmb3IgKGxldCByb3VuZCA9IDI0IC0gcm91bmRzOyByb3VuZCA8IDI0OyByb3VuZCsrKSB7XG4gICAgICAgIC8vIFRoZXRhIM64XG4gICAgICAgIGZvciAobGV0IHggPSAwOyB4IDwgMTA7IHgrKylcbiAgICAgICAgICAgIEJbeF0gPSBzW3hdIF4gc1t4ICsgMTBdIF4gc1t4ICsgMjBdIF4gc1t4ICsgMzBdIF4gc1t4ICsgNDBdO1xuICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDEwOyB4ICs9IDIpIHtcbiAgICAgICAgICAgIGNvbnN0IGlkeDEgPSAoeCArIDgpICUgMTA7XG4gICAgICAgICAgICBjb25zdCBpZHgwID0gKHggKyAyKSAlIDEwO1xuICAgICAgICAgICAgY29uc3QgQjAgPSBCW2lkeDBdO1xuICAgICAgICAgICAgY29uc3QgQjEgPSBCW2lkeDAgKyAxXTtcbiAgICAgICAgICAgIGNvbnN0IFRoID0gcm90bEgoQjAsIEIxLCAxKSBeIEJbaWR4MV07XG4gICAgICAgICAgICBjb25zdCBUbCA9IHJvdGxMKEIwLCBCMSwgMSkgXiBCW2lkeDEgKyAxXTtcbiAgICAgICAgICAgIGZvciAobGV0IHkgPSAwOyB5IDwgNTA7IHkgKz0gMTApIHtcbiAgICAgICAgICAgICAgICBzW3ggKyB5XSBePSBUaDtcbiAgICAgICAgICAgICAgICBzW3ggKyB5ICsgMV0gXj0gVGw7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gUmhvICjPgSkgYW5kIFBpICjPgClcbiAgICAgICAgbGV0IGN1ckggPSBzWzJdO1xuICAgICAgICBsZXQgY3VyTCA9IHNbM107XG4gICAgICAgIGZvciAobGV0IHQgPSAwOyB0IDwgMjQ7IHQrKykge1xuICAgICAgICAgICAgY29uc3Qgc2hpZnQgPSBTSEEzX1JPVExbdF07XG4gICAgICAgICAgICBjb25zdCBUaCA9IHJvdGxIKGN1ckgsIGN1ckwsIHNoaWZ0KTtcbiAgICAgICAgICAgIGNvbnN0IFRsID0gcm90bEwoY3VySCwgY3VyTCwgc2hpZnQpO1xuICAgICAgICAgICAgY29uc3QgUEkgPSBTSEEzX1BJW3RdO1xuICAgICAgICAgICAgY3VySCA9IHNbUEldO1xuICAgICAgICAgICAgY3VyTCA9IHNbUEkgKyAxXTtcbiAgICAgICAgICAgIHNbUEldID0gVGg7XG4gICAgICAgICAgICBzW1BJICsgMV0gPSBUbDtcbiAgICAgICAgfVxuICAgICAgICAvLyBDaGkgKM+HKVxuICAgICAgICBmb3IgKGxldCB5ID0gMDsgeSA8IDUwOyB5ICs9IDEwKSB7XG4gICAgICAgICAgICBmb3IgKGxldCB4ID0gMDsgeCA8IDEwOyB4KyspXG4gICAgICAgICAgICAgICAgQlt4XSA9IHNbeSArIHhdO1xuICAgICAgICAgICAgZm9yIChsZXQgeCA9IDA7IHggPCAxMDsgeCsrKVxuICAgICAgICAgICAgICAgIHNbeSArIHhdIF49IH5CWyh4ICsgMikgJSAxMF0gJiBCWyh4ICsgNCkgJSAxMF07XG4gICAgICAgIH1cbiAgICAgICAgLy8gSW90YSAozrkpXG4gICAgICAgIHNbMF0gXj0gU0hBM19JT1RBX0hbcm91bmRdO1xuICAgICAgICBzWzFdIF49IFNIQTNfSU9UQV9MW3JvdW5kXTtcbiAgICB9XG4gICAgQi5maWxsKDApO1xufVxuZXhwb3J0IGNsYXNzIEtlY2NhayBleHRlbmRzIEhhc2gge1xuICAgIC8vIE5PVEU6IHdlIGFjY2VwdCBhcmd1bWVudHMgaW4gYnl0ZXMgaW5zdGVhZCBvZiBiaXRzIGhlcmUuXG4gICAgY29uc3RydWN0b3IoYmxvY2tMZW4sIHN1ZmZpeCwgb3V0cHV0TGVuLCBlbmFibGVYT0YgPSBmYWxzZSwgcm91bmRzID0gMjQpIHtcbiAgICAgICAgc3VwZXIoKTtcbiAgICAgICAgdGhpcy5ibG9ja0xlbiA9IGJsb2NrTGVuO1xuICAgICAgICB0aGlzLnN1ZmZpeCA9IHN1ZmZpeDtcbiAgICAgICAgdGhpcy5vdXRwdXRMZW4gPSBvdXRwdXRMZW47XG4gICAgICAgIHRoaXMuZW5hYmxlWE9GID0gZW5hYmxlWE9GO1xuICAgICAgICB0aGlzLnJvdW5kcyA9IHJvdW5kcztcbiAgICAgICAgdGhpcy5wb3MgPSAwO1xuICAgICAgICB0aGlzLnBvc091dCA9IDA7XG4gICAgICAgIHRoaXMuZmluaXNoZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5kZXN0cm95ZWQgPSBmYWxzZTtcbiAgICAgICAgLy8gQ2FuIGJlIHBhc3NlZCBmcm9tIHVzZXIgYXMgZGtMZW5cbiAgICAgICAgYXNzZXJ0Lm51bWJlcihvdXRwdXRMZW4pO1xuICAgICAgICAvLyAxNjAwID0gNXg1IG1hdHJpeCBvZiA2NGJpdC4gIDE2MDAgYml0cyA9PT0gMjAwIGJ5dGVzXG4gICAgICAgIGlmICgwID49IHRoaXMuYmxvY2tMZW4gfHwgdGhpcy5ibG9ja0xlbiA+PSAyMDApXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1NoYTMgc3VwcG9ydHMgb25seSBrZWNjYWstZjE2MDAgZnVuY3Rpb24nKTtcbiAgICAgICAgdGhpcy5zdGF0ZSA9IG5ldyBVaW50OEFycmF5KDIwMCk7XG4gICAgICAgIHRoaXMuc3RhdGUzMiA9IHUzMih0aGlzLnN0YXRlKTtcbiAgICB9XG4gICAga2VjY2FrKCkge1xuICAgICAgICBrZWNjYWtQKHRoaXMuc3RhdGUzMiwgdGhpcy5yb3VuZHMpO1xuICAgICAgICB0aGlzLnBvc091dCA9IDA7XG4gICAgICAgIHRoaXMucG9zID0gMDtcbiAgICB9XG4gICAgdXBkYXRlKGRhdGEpIHtcbiAgICAgICAgYXNzZXJ0LmV4aXN0cyh0aGlzKTtcbiAgICAgICAgY29uc3QgeyBibG9ja0xlbiwgc3RhdGUgfSA9IHRoaXM7XG4gICAgICAgIGRhdGEgPSB0b0J5dGVzKGRhdGEpO1xuICAgICAgICBjb25zdCBsZW4gPSBkYXRhLmxlbmd0aDtcbiAgICAgICAgZm9yIChsZXQgcG9zID0gMDsgcG9zIDwgbGVuOykge1xuICAgICAgICAgICAgY29uc3QgdGFrZSA9IE1hdGgubWluKGJsb2NrTGVuIC0gdGhpcy5wb3MsIGxlbiAtIHBvcyk7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRha2U7IGkrKylcbiAgICAgICAgICAgICAgICBzdGF0ZVt0aGlzLnBvcysrXSBePSBkYXRhW3BvcysrXTtcbiAgICAgICAgICAgIGlmICh0aGlzLnBvcyA9PT0gYmxvY2tMZW4pXG4gICAgICAgICAgICAgICAgdGhpcy5rZWNjYWsoKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG4gICAgZmluaXNoKCkge1xuICAgICAgICBpZiAodGhpcy5maW5pc2hlZClcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgdGhpcy5maW5pc2hlZCA9IHRydWU7XG4gICAgICAgIGNvbnN0IHsgc3RhdGUsIHN1ZmZpeCwgcG9zLCBibG9ja0xlbiB9ID0gdGhpcztcbiAgICAgICAgLy8gRG8gdGhlIHBhZGRpbmdcbiAgICAgICAgc3RhdGVbcG9zXSBePSBzdWZmaXg7XG4gICAgICAgIGlmICgoc3VmZml4ICYgMHg4MCkgIT09IDAgJiYgcG9zID09PSBibG9ja0xlbiAtIDEpXG4gICAgICAgICAgICB0aGlzLmtlY2NhaygpO1xuICAgICAgICBzdGF0ZVtibG9ja0xlbiAtIDFdIF49IDB4ODA7XG4gICAgICAgIHRoaXMua2VjY2FrKCk7XG4gICAgfVxuICAgIHdyaXRlSW50byhvdXQpIHtcbiAgICAgICAgYXNzZXJ0LmV4aXN0cyh0aGlzLCBmYWxzZSk7XG4gICAgICAgIGFzc2VydC5ieXRlcyhvdXQpO1xuICAgICAgICB0aGlzLmZpbmlzaCgpO1xuICAgICAgICBjb25zdCBidWZmZXJPdXQgPSB0aGlzLnN0YXRlO1xuICAgICAgICBjb25zdCB7IGJsb2NrTGVuIH0gPSB0aGlzO1xuICAgICAgICBmb3IgKGxldCBwb3MgPSAwLCBsZW4gPSBvdXQubGVuZ3RoOyBwb3MgPCBsZW47KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5wb3NPdXQgPj0gYmxvY2tMZW4pXG4gICAgICAgICAgICAgICAgdGhpcy5rZWNjYWsoKTtcbiAgICAgICAgICAgIGNvbnN0IHRha2UgPSBNYXRoLm1pbihibG9ja0xlbiAtIHRoaXMucG9zT3V0LCBsZW4gLSBwb3MpO1xuICAgICAgICAgICAgb3V0LnNldChidWZmZXJPdXQuc3ViYXJyYXkodGhpcy5wb3NPdXQsIHRoaXMucG9zT3V0ICsgdGFrZSksIHBvcyk7XG4gICAgICAgICAgICB0aGlzLnBvc091dCArPSB0YWtlO1xuICAgICAgICAgICAgcG9zICs9IHRha2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG91dDtcbiAgICB9XG4gICAgeG9mSW50byhvdXQpIHtcbiAgICAgICAgLy8gU2hhMy9LZWNjYWsgdXNhZ2Ugd2l0aCBYT0YgaXMgcHJvYmFibHkgbWlzdGFrZSwgb25seSBTSEFLRSBpbnN0YW5jZXMgY2FuIGRvIFhPRlxuICAgICAgICBpZiAoIXRoaXMuZW5hYmxlWE9GKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdYT0YgaXMgbm90IHBvc3NpYmxlIGZvciB0aGlzIGluc3RhbmNlJyk7XG4gICAgICAgIHJldHVybiB0aGlzLndyaXRlSW50byhvdXQpO1xuICAgIH1cbiAgICB4b2YoYnl0ZXMpIHtcbiAgICAgICAgYXNzZXJ0Lm51bWJlcihieXRlcyk7XG4gICAgICAgIHJldHVybiB0aGlzLnhvZkludG8obmV3IFVpbnQ4QXJyYXkoYnl0ZXMpKTtcbiAgICB9XG4gICAgZGlnZXN0SW50byhvdXQpIHtcbiAgICAgICAgYXNzZXJ0Lm91dHB1dChvdXQsIHRoaXMpO1xuICAgICAgICBpZiAodGhpcy5maW5pc2hlZClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZGlnZXN0KCkgd2FzIGFscmVhZHkgY2FsbGVkJyk7XG4gICAgICAgIHRoaXMud3JpdGVJbnRvKG91dCk7XG4gICAgICAgIHRoaXMuZGVzdHJveSgpO1xuICAgICAgICByZXR1cm4gb3V0O1xuICAgIH1cbiAgICBkaWdlc3QoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRpZ2VzdEludG8obmV3IFVpbnQ4QXJyYXkodGhpcy5vdXRwdXRMZW4pKTtcbiAgICB9XG4gICAgZGVzdHJveSgpIHtcbiAgICAgICAgdGhpcy5kZXN0cm95ZWQgPSB0cnVlO1xuICAgICAgICB0aGlzLnN0YXRlLmZpbGwoMCk7XG4gICAgfVxuICAgIF9jbG9uZUludG8odG8pIHtcbiAgICAgICAgY29uc3QgeyBibG9ja0xlbiwgc3VmZml4LCBvdXRwdXRMZW4sIHJvdW5kcywgZW5hYmxlWE9GIH0gPSB0aGlzO1xuICAgICAgICB0byB8fCAodG8gPSBuZXcgS2VjY2FrKGJsb2NrTGVuLCBzdWZmaXgsIG91dHB1dExlbiwgZW5hYmxlWE9GLCByb3VuZHMpKTtcbiAgICAgICAgdG8uc3RhdGUzMi5zZXQodGhpcy5zdGF0ZTMyKTtcbiAgICAgICAgdG8ucG9zID0gdGhpcy5wb3M7XG4gICAgICAgIHRvLnBvc091dCA9IHRoaXMucG9zT3V0O1xuICAgICAgICB0by5maW5pc2hlZCA9IHRoaXMuZmluaXNoZWQ7XG4gICAgICAgIHRvLnJvdW5kcyA9IHJvdW5kcztcbiAgICAgICAgLy8gU3VmZml4IGNhbiBjaGFuZ2UgaW4gY1NIQUtFXG4gICAgICAgIHRvLnN1ZmZpeCA9IHN1ZmZpeDtcbiAgICAgICAgdG8ub3V0cHV0TGVuID0gb3V0cHV0TGVuO1xuICAgICAgICB0by5lbmFibGVYT0YgPSBlbmFibGVYT0Y7XG4gICAgICAgIHRvLmRlc3Ryb3llZCA9IHRoaXMuZGVzdHJveWVkO1xuICAgICAgICByZXR1cm4gdG87XG4gICAgfVxufVxuY29uc3QgZ2VuID0gKHN1ZmZpeCwgYmxvY2tMZW4sIG91dHB1dExlbikgPT4gd3JhcENvbnN0cnVjdG9yKCgpID0+IG5ldyBLZWNjYWsoYmxvY2tMZW4sIHN1ZmZpeCwgb3V0cHV0TGVuKSk7XG5leHBvcnQgY29uc3Qgc2hhM18yMjQgPSBnZW4oMHgwNiwgMTQ0LCAyMjQgLyA4KTtcbi8qKlxuICogU0hBMy0yNTYgaGFzaCBmdW5jdGlvblxuICogQHBhcmFtIG1lc3NhZ2UgLSB0aGF0IHdvdWxkIGJlIGhhc2hlZFxuICovXG5leHBvcnQgY29uc3Qgc2hhM18yNTYgPSBnZW4oMHgwNiwgMTM2LCAyNTYgLyA4KTtcbmV4cG9ydCBjb25zdCBzaGEzXzM4NCA9IGdlbigweDA2LCAxMDQsIDM4NCAvIDgpO1xuZXhwb3J0IGNvbnN0IHNoYTNfNTEyID0gZ2VuKDB4MDYsIDcyLCA1MTIgLyA4KTtcbmV4cG9ydCBjb25zdCBrZWNjYWtfMjI0ID0gZ2VuKDB4MDEsIDE0NCwgMjI0IC8gOCk7XG4vKipcbiAqIGtlY2Nhay0yNTYgaGFzaCBmdW5jdGlvbi4gRGlmZmVyZW50IGZyb20gU0hBMy0yNTYuXG4gKiBAcGFyYW0gbWVzc2FnZSAtIHRoYXQgd291bGQgYmUgaGFzaGVkXG4gKi9cbmV4cG9ydCBjb25zdCBrZWNjYWtfMjU2ID0gZ2VuKDB4MDEsIDEzNiwgMjU2IC8gOCk7XG5leHBvcnQgY29uc3Qga2VjY2FrXzM4NCA9IGdlbigweDAxLCAxMDQsIDM4NCAvIDgpO1xuZXhwb3J0IGNvbnN0IGtlY2Nha181MTIgPSBnZW4oMHgwMSwgNzIsIDUxMiAvIDgpO1xuY29uc3QgZ2VuU2hha2UgPSAoc3VmZml4LCBibG9ja0xlbiwgb3V0cHV0TGVuKSA9PiB3cmFwQ29uc3RydWN0b3JXaXRoT3B0cygob3B0cyA9IHt9KSA9PiBuZXcgS2VjY2FrKGJsb2NrTGVuLCBzdWZmaXgsIG9wdHMuZGtMZW4gPT09IHVuZGVmaW5lZCA/IG91dHB1dExlbiA6IG9wdHMuZGtMZW4sIHRydWUpKTtcbmV4cG9ydCBjb25zdCBzaGFrZTEyOCA9IGdlblNoYWtlKDB4MWYsIDE2OCwgMTI4IC8gOCk7XG5leHBvcnQgY29uc3Qgc2hha2UyNTYgPSBnZW5TaGFrZSgweDFmLCAxMzYsIDI1NiAvIDgpO1xuLy8jIHNvdXJjZU1hcHBpbmdVUkw9c2hhMy5qcy5tYXAiLCIvKiEgbm9ibGUtY3VydmVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG5jb25zdCBfMG4gPSBCaWdJbnQoMCk7XG5jb25zdCBfMW4gPSBCaWdJbnQoMSk7XG5jb25zdCBfMm4gPSBCaWdJbnQoMik7XG5jb25zdCB1OGEgPSAoYSkgPT4gYSBpbnN0YW5jZW9mIFVpbnQ4QXJyYXk7XG5jb25zdCBoZXhlcyA9IEFycmF5LmZyb20oeyBsZW5ndGg6IDI1NiB9LCAodiwgaSkgPT4gaS50b1N0cmluZygxNikucGFkU3RhcnQoMiwgJzAnKSk7XG5leHBvcnQgZnVuY3Rpb24gYnl0ZXNUb0hleChieXRlcykge1xuICAgIGlmICghdThhKGJ5dGVzKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGV4cGVjdGVkJyk7XG4gICAgLy8gcHJlLWNhY2hpbmcgaW1wcm92ZXMgdGhlIHNwZWVkIDZ4XG4gICAgbGV0IGhleCA9ICcnO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnl0ZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaGV4ICs9IGhleGVzW2J5dGVzW2ldXTtcbiAgICB9XG4gICAgcmV0dXJuIGhleDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBudW1iZXJUb0hleFVucGFkZGVkKG51bSkge1xuICAgIGNvbnN0IGhleCA9IG51bS50b1N0cmluZygxNik7XG4gICAgcmV0dXJuIGhleC5sZW5ndGggJiAxID8gYDAke2hleH1gIDogaGV4O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGhleFRvTnVtYmVyKGhleCkge1xuICAgIGlmICh0eXBlb2YgaGV4ICE9PSAnc3RyaW5nJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdoZXggc3RyaW5nIGV4cGVjdGVkLCBnb3QgJyArIHR5cGVvZiBoZXgpO1xuICAgIC8vIEJpZyBFbmRpYW5cbiAgICByZXR1cm4gQmlnSW50KGhleCA9PT0gJycgPyAnMCcgOiBgMHgke2hleH1gKTtcbn1cbi8vIENhY2hpbmcgc2xvd3MgaXQgZG93biAyLTN4XG5leHBvcnQgZnVuY3Rpb24gaGV4VG9CeXRlcyhoZXgpIHtcbiAgICBpZiAodHlwZW9mIGhleCAhPT0gJ3N0cmluZycpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGV4IHN0cmluZyBleHBlY3RlZCwgZ290ICcgKyB0eXBlb2YgaGV4KTtcbiAgICBpZiAoaGV4Lmxlbmd0aCAlIDIpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignaGV4IHN0cmluZyBpcyBpbnZhbGlkOiB1bnBhZGRlZCAnICsgaGV4Lmxlbmd0aCk7XG4gICAgY29uc3QgYXJyYXkgPSBuZXcgVWludDhBcnJheShoZXgubGVuZ3RoIC8gMik7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBhcnJheS5sZW5ndGg7IGkrKykge1xuICAgICAgICBjb25zdCBqID0gaSAqIDI7XG4gICAgICAgIGNvbnN0IGhleEJ5dGUgPSBoZXguc2xpY2UoaiwgaiArIDIpO1xuICAgICAgICBjb25zdCBieXRlID0gTnVtYmVyLnBhcnNlSW50KGhleEJ5dGUsIDE2KTtcbiAgICAgICAgaWYgKE51bWJlci5pc05hTihieXRlKSB8fCBieXRlIDwgMClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBieXRlIHNlcXVlbmNlJyk7XG4gICAgICAgIGFycmF5W2ldID0gYnl0ZTtcbiAgICB9XG4gICAgcmV0dXJuIGFycmF5O1xufVxuLy8gQmlnIEVuZGlhblxuZXhwb3J0IGZ1bmN0aW9uIGJ5dGVzVG9OdW1iZXJCRShieXRlcykge1xuICAgIHJldHVybiBoZXhUb051bWJlcihieXRlc1RvSGV4KGJ5dGVzKSk7XG59XG5leHBvcnQgZnVuY3Rpb24gYnl0ZXNUb051bWJlckxFKGJ5dGVzKSB7XG4gICAgaWYgKCF1OGEoYnl0ZXMpKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgZXhwZWN0ZWQnKTtcbiAgICByZXR1cm4gaGV4VG9OdW1iZXIoYnl0ZXNUb0hleChVaW50OEFycmF5LmZyb20oYnl0ZXMpLnJldmVyc2UoKSkpO1xufVxuZXhwb3J0IGNvbnN0IG51bWJlclRvQnl0ZXNCRSA9IChuLCBsZW4pID0+IGhleFRvQnl0ZXMobi50b1N0cmluZygxNikucGFkU3RhcnQobGVuICogMiwgJzAnKSk7XG5leHBvcnQgY29uc3QgbnVtYmVyVG9CeXRlc0xFID0gKG4sIGxlbikgPT4gbnVtYmVyVG9CeXRlc0JFKG4sIGxlbikucmV2ZXJzZSgpO1xuLy8gUmV0dXJucyB2YXJpYWJsZSBudW1iZXIgYnl0ZXMgKG1pbmltYWwgYmlnaW50IGVuY29kaW5nPylcbmV4cG9ydCBjb25zdCBudW1iZXJUb1ZhckJ5dGVzQkUgPSAobikgPT4gaGV4VG9CeXRlcyhudW1iZXJUb0hleFVucGFkZGVkKG4pKTtcbmV4cG9ydCBmdW5jdGlvbiBlbnN1cmVCeXRlcyh0aXRsZSwgaGV4LCBleHBlY3RlZExlbmd0aCkge1xuICAgIGxldCByZXM7XG4gICAgaWYgKHR5cGVvZiBoZXggPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICByZXMgPSBoZXhUb0J5dGVzKGhleCk7XG4gICAgICAgIH1cbiAgICAgICAgY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHt0aXRsZX0gbXVzdCBiZSB2YWxpZCBoZXggc3RyaW5nLCBnb3QgXCIke2hleH1cIi4gQ2F1c2U6ICR7ZX1gKTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBlbHNlIGlmICh1OGEoaGV4KSkge1xuICAgICAgICAvLyBVaW50OEFycmF5LmZyb20oKSBpbnN0ZWFkIG9mIGhhc2guc2xpY2UoKSBiZWNhdXNlIG5vZGUuanMgQnVmZmVyXG4gICAgICAgIC8vIGlzIGluc3RhbmNlIG9mIFVpbnQ4QXJyYXksIGFuZCBpdHMgc2xpY2UoKSBjcmVhdGVzICoqbXV0YWJsZSoqIGNvcHlcbiAgICAgICAgcmVzID0gVWludDhBcnJheS5mcm9tKGhleCk7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7dGl0bGV9IG11c3QgYmUgaGV4IHN0cmluZyBvciBVaW50OEFycmF5YCk7XG4gICAgfVxuICAgIGNvbnN0IGxlbiA9IHJlcy5sZW5ndGg7XG4gICAgaWYgKHR5cGVvZiBleHBlY3RlZExlbmd0aCA9PT0gJ251bWJlcicgJiYgbGVuICE9PSBleHBlY3RlZExlbmd0aClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke3RpdGxlfSBleHBlY3RlZCAke2V4cGVjdGVkTGVuZ3RofSBieXRlcywgZ290ICR7bGVufWApO1xuICAgIHJldHVybiByZXM7XG59XG4vLyBDb3BpZXMgc2V2ZXJhbCBVaW50OEFycmF5cyBpbnRvIG9uZS5cbmV4cG9ydCBmdW5jdGlvbiBjb25jYXRCeXRlcyguLi5hcnJzKSB7XG4gICAgY29uc3QgciA9IG5ldyBVaW50OEFycmF5KGFycnMucmVkdWNlKChzdW0sIGEpID0+IHN1bSArIGEubGVuZ3RoLCAwKSk7XG4gICAgbGV0IHBhZCA9IDA7IC8vIHdhbGsgdGhyb3VnaCBlYWNoIGl0ZW0sIGVuc3VyZSB0aGV5IGhhdmUgcHJvcGVyIHR5cGVcbiAgICBhcnJzLmZvckVhY2goKGEpID0+IHtcbiAgICAgICAgaWYgKCF1OGEoYSkpXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1VpbnQ4QXJyYXkgZXhwZWN0ZWQnKTtcbiAgICAgICAgci5zZXQoYSwgcGFkKTtcbiAgICAgICAgcGFkICs9IGEubGVuZ3RoO1xuICAgIH0pO1xuICAgIHJldHVybiByO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGVxdWFsQnl0ZXMoYjEsIGIyKSB7XG4gICAgLy8gV2UgZG9uJ3QgY2FyZSBhYm91dCB0aW1pbmcgYXR0YWNrcyBoZXJlXG4gICAgaWYgKGIxLmxlbmd0aCAhPT0gYjIubGVuZ3RoKVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBiMS5sZW5ndGg7IGkrKylcbiAgICAgICAgaWYgKGIxW2ldICE9PSBiMltpXSlcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gdHJ1ZTtcbn1cbmV4cG9ydCBmdW5jdGlvbiB1dGY4VG9CeXRlcyhzdHIpIHtcbiAgICBpZiAodHlwZW9mIHN0ciAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGB1dGY4VG9CeXRlcyBleHBlY3RlZCBzdHJpbmcsIGdvdCAke3R5cGVvZiBzdHJ9YCk7XG4gICAgfVxuICAgIHJldHVybiBuZXcgVGV4dEVuY29kZXIoKS5lbmNvZGUoc3RyKTtcbn1cbi8vIEJpdCBvcGVyYXRpb25zXG4vLyBBbW91bnQgb2YgYml0cyBpbnNpZGUgYmlnaW50IChTYW1lIGFzIG4udG9TdHJpbmcoMikubGVuZ3RoKVxuZXhwb3J0IGZ1bmN0aW9uIGJpdExlbihuKSB7XG4gICAgbGV0IGxlbjtcbiAgICBmb3IgKGxlbiA9IDA7IG4gPiBfMG47IG4gPj49IF8xbiwgbGVuICs9IDEpXG4gICAgICAgIDtcbiAgICByZXR1cm4gbGVuO1xufVxuLy8gR2V0cyBzaW5nbGUgYml0IGF0IHBvc2l0aW9uLiBOT1RFOiBmaXJzdCBiaXQgcG9zaXRpb24gaXMgMCAoc2FtZSBhcyBhcnJheXMpXG4vLyBTYW1lIGFzICEhK0FycmF5LmZyb20obi50b1N0cmluZygyKSkucmV2ZXJzZSgpW3Bvc11cbmV4cG9ydCBjb25zdCBiaXRHZXQgPSAobiwgcG9zKSA9PiAobiA+PiBCaWdJbnQocG9zKSkgJiBfMW47XG4vLyBTZXRzIHNpbmdsZSBiaXQgYXQgcG9zaXRpb25cbmV4cG9ydCBjb25zdCBiaXRTZXQgPSAobiwgcG9zLCB2YWx1ZSkgPT4gbiB8ICgodmFsdWUgPyBfMW4gOiBfMG4pIDw8IEJpZ0ludChwb3MpKTtcbi8vIFJldHVybiBtYXNrIGZvciBOIGJpdHMgKFNhbWUgYXMgQmlnSW50KGAwYiR7QXJyYXkoaSkuZmlsbCgnMScpLmpvaW4oJycpfWApKVxuLy8gTm90IHVzaW5nICoqIG9wZXJhdG9yIHdpdGggYmlnaW50cyBmb3Igb2xkIGVuZ2luZXMuXG5leHBvcnQgY29uc3QgYml0TWFzayA9IChuKSA9PiAoXzJuIDw8IEJpZ0ludChuIC0gMSkpIC0gXzFuO1xuLy8gRFJCR1xuY29uc3QgdThuID0gKGRhdGEpID0+IG5ldyBVaW50OEFycmF5KGRhdGEpOyAvLyBjcmVhdGVzIFVpbnQ4QXJyYXlcbmNvbnN0IHU4ZnIgPSAoYXJyKSA9PiBVaW50OEFycmF5LmZyb20oYXJyKTsgLy8gYW5vdGhlciBzaG9ydGN1dFxuLyoqXG4gKiBNaW5pbWFsIEhNQUMtRFJCRyBmcm9tIE5JU1QgODAwLTkwIGZvciBSRkM2OTc5IHNpZ3MuXG4gKiBAcmV0dXJucyBmdW5jdGlvbiB0aGF0IHdpbGwgY2FsbCBEUkJHIHVudGlsIDJuZCBhcmcgcmV0dXJucyBzb21ldGhpbmcgbWVhbmluZ2Z1bFxuICogQGV4YW1wbGVcbiAqICAgY29uc3QgZHJiZyA9IGNyZWF0ZUhtYWNEUkJHPEtleT4oMzIsIDMyLCBobWFjKTtcbiAqICAgZHJiZyhzZWVkLCBieXRlc1RvS2V5KTsgLy8gYnl0ZXNUb0tleSBtdXN0IHJldHVybiBLZXkgb3IgdW5kZWZpbmVkXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVIbWFjRHJiZyhoYXNoTGVuLCBxQnl0ZUxlbiwgaG1hY0ZuKSB7XG4gICAgaWYgKHR5cGVvZiBoYXNoTGVuICE9PSAnbnVtYmVyJyB8fCBoYXNoTGVuIDwgMilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdoYXNoTGVuIG11c3QgYmUgYSBudW1iZXInKTtcbiAgICBpZiAodHlwZW9mIHFCeXRlTGVuICE9PSAnbnVtYmVyJyB8fCBxQnl0ZUxlbiA8IDIpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcigncUJ5dGVMZW4gbXVzdCBiZSBhIG51bWJlcicpO1xuICAgIGlmICh0eXBlb2YgaG1hY0ZuICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2htYWNGbiBtdXN0IGJlIGEgZnVuY3Rpb24nKTtcbiAgICAvLyBTdGVwIEIsIFN0ZXAgQzogc2V0IGhhc2hMZW4gdG8gOCpjZWlsKGhsZW4vOClcbiAgICBsZXQgdiA9IHU4bihoYXNoTGVuKTsgLy8gTWluaW1hbCBub24tZnVsbC1zcGVjIEhNQUMtRFJCRyBmcm9tIE5JU1QgODAwLTkwIGZvciBSRkM2OTc5IHNpZ3MuXG4gICAgbGV0IGsgPSB1OG4oaGFzaExlbik7IC8vIFN0ZXBzIEIgYW5kIEMgb2YgUkZDNjk3OSAzLjI6IHNldCBoYXNoTGVuLCBpbiBvdXIgY2FzZSBhbHdheXMgc2FtZVxuICAgIGxldCBpID0gMDsgLy8gSXRlcmF0aW9ucyBjb3VudGVyLCB3aWxsIHRocm93IHdoZW4gb3ZlciAxMDAwXG4gICAgY29uc3QgcmVzZXQgPSAoKSA9PiB7XG4gICAgICAgIHYuZmlsbCgxKTtcbiAgICAgICAgay5maWxsKDApO1xuICAgICAgICBpID0gMDtcbiAgICB9O1xuICAgIGNvbnN0IGggPSAoLi4uYikgPT4gaG1hY0ZuKGssIHYsIC4uLmIpOyAvLyBobWFjKGspKHYsIC4uLnZhbHVlcylcbiAgICBjb25zdCByZXNlZWQgPSAoc2VlZCA9IHU4bigpKSA9PiB7XG4gICAgICAgIC8vIEhNQUMtRFJCRyByZXNlZWQoKSBmdW5jdGlvbi4gU3RlcHMgRC1HXG4gICAgICAgIGsgPSBoKHU4ZnIoWzB4MDBdKSwgc2VlZCk7IC8vIGsgPSBobWFjKGsgfHwgdiB8fCAweDAwIHx8IHNlZWQpXG4gICAgICAgIHYgPSBoKCk7IC8vIHYgPSBobWFjKGsgfHwgdilcbiAgICAgICAgaWYgKHNlZWQubGVuZ3RoID09PSAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBrID0gaCh1OGZyKFsweDAxXSksIHNlZWQpOyAvLyBrID0gaG1hYyhrIHx8IHYgfHwgMHgwMSB8fCBzZWVkKVxuICAgICAgICB2ID0gaCgpOyAvLyB2ID0gaG1hYyhrIHx8IHYpXG4gICAgfTtcbiAgICBjb25zdCBnZW4gPSAoKSA9PiB7XG4gICAgICAgIC8vIEhNQUMtRFJCRyBnZW5lcmF0ZSgpIGZ1bmN0aW9uXG4gICAgICAgIGlmIChpKysgPj0gMTAwMClcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignZHJiZzogdHJpZWQgMTAwMCB2YWx1ZXMnKTtcbiAgICAgICAgbGV0IGxlbiA9IDA7XG4gICAgICAgIGNvbnN0IG91dCA9IFtdO1xuICAgICAgICB3aGlsZSAobGVuIDwgcUJ5dGVMZW4pIHtcbiAgICAgICAgICAgIHYgPSBoKCk7XG4gICAgICAgICAgICBjb25zdCBzbCA9IHYuc2xpY2UoKTtcbiAgICAgICAgICAgIG91dC5wdXNoKHNsKTtcbiAgICAgICAgICAgIGxlbiArPSB2Lmxlbmd0aDtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29uY2F0Qnl0ZXMoLi4ub3V0KTtcbiAgICB9O1xuICAgIGNvbnN0IGdlblVudGlsID0gKHNlZWQsIHByZWQpID0+IHtcbiAgICAgICAgcmVzZXQoKTtcbiAgICAgICAgcmVzZWVkKHNlZWQpOyAvLyBTdGVwcyBELUdcbiAgICAgICAgbGV0IHJlcyA9IHVuZGVmaW5lZDsgLy8gU3RlcCBIOiBncmluZCB1bnRpbCBrIGlzIGluIFsxLi5uLTFdXG4gICAgICAgIHdoaWxlICghKHJlcyA9IHByZWQoZ2VuKCkpKSlcbiAgICAgICAgICAgIHJlc2VlZCgpO1xuICAgICAgICByZXNldCgpO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgIH07XG4gICAgcmV0dXJuIGdlblVudGlsO1xufVxuLy8gVmFsaWRhdGluZyBjdXJ2ZXMgYW5kIGZpZWxkc1xuY29uc3QgdmFsaWRhdG9yRm5zID0ge1xuICAgIGJpZ2ludDogKHZhbCkgPT4gdHlwZW9mIHZhbCA9PT0gJ2JpZ2ludCcsXG4gICAgZnVuY3Rpb246ICh2YWwpID0+IHR5cGVvZiB2YWwgPT09ICdmdW5jdGlvbicsXG4gICAgYm9vbGVhbjogKHZhbCkgPT4gdHlwZW9mIHZhbCA9PT0gJ2Jvb2xlYW4nLFxuICAgIHN0cmluZzogKHZhbCkgPT4gdHlwZW9mIHZhbCA9PT0gJ3N0cmluZycsXG4gICAgaXNTYWZlSW50ZWdlcjogKHZhbCkgPT4gTnVtYmVyLmlzU2FmZUludGVnZXIodmFsKSxcbiAgICBhcnJheTogKHZhbCkgPT4gQXJyYXkuaXNBcnJheSh2YWwpLFxuICAgIGZpZWxkOiAodmFsLCBvYmplY3QpID0+IG9iamVjdC5GcC5pc1ZhbGlkKHZhbCksXG4gICAgaGFzaDogKHZhbCkgPT4gdHlwZW9mIHZhbCA9PT0gJ2Z1bmN0aW9uJyAmJiBOdW1iZXIuaXNTYWZlSW50ZWdlcih2YWwub3V0cHV0TGVuKSxcbn07XG4vLyB0eXBlIFJlY29yZDxLIGV4dGVuZHMgc3RyaW5nIHwgbnVtYmVyIHwgc3ltYm9sLCBUPiA9IHsgW1AgaW4gS106IFQ7IH1cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZU9iamVjdChvYmplY3QsIHZhbGlkYXRvcnMsIG9wdFZhbGlkYXRvcnMgPSB7fSkge1xuICAgIGNvbnN0IGNoZWNrRmllbGQgPSAoZmllbGROYW1lLCB0eXBlLCBpc09wdGlvbmFsKSA9PiB7XG4gICAgICAgIGNvbnN0IGNoZWNrVmFsID0gdmFsaWRhdG9yRm5zW3R5cGVdO1xuICAgICAgICBpZiAodHlwZW9mIGNoZWNrVmFsICE9PSAnZnVuY3Rpb24nKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHZhbGlkYXRvciBcIiR7dHlwZX1cIiwgZXhwZWN0ZWQgZnVuY3Rpb25gKTtcbiAgICAgICAgY29uc3QgdmFsID0gb2JqZWN0W2ZpZWxkTmFtZV07XG4gICAgICAgIGlmIChpc09wdGlvbmFsICYmIHZhbCA9PT0gdW5kZWZpbmVkKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBpZiAoIWNoZWNrVmFsKHZhbCwgb2JqZWN0KSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBJbnZhbGlkIHBhcmFtICR7U3RyaW5nKGZpZWxkTmFtZSl9PSR7dmFsfSAoJHt0eXBlb2YgdmFsfSksIGV4cGVjdGVkICR7dHlwZX1gKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgZm9yIChjb25zdCBbZmllbGROYW1lLCB0eXBlXSBvZiBPYmplY3QuZW50cmllcyh2YWxpZGF0b3JzKSlcbiAgICAgICAgY2hlY2tGaWVsZChmaWVsZE5hbWUsIHR5cGUsIGZhbHNlKTtcbiAgICBmb3IgKGNvbnN0IFtmaWVsZE5hbWUsIHR5cGVdIG9mIE9iamVjdC5lbnRyaWVzKG9wdFZhbGlkYXRvcnMpKVxuICAgICAgICBjaGVja0ZpZWxkKGZpZWxkTmFtZSwgdHlwZSwgdHJ1ZSk7XG4gICAgcmV0dXJuIG9iamVjdDtcbn1cbi8vIHZhbGlkYXRlIHR5cGUgdGVzdHNcbi8vIGNvbnN0IG86IHsgYTogbnVtYmVyOyBiOiBudW1iZXI7IGM6IG51bWJlciB9ID0geyBhOiAxLCBiOiA1LCBjOiA2IH07XG4vLyBjb25zdCB6MCA9IHZhbGlkYXRlT2JqZWN0KG8sIHsgYTogJ2lzU2FmZUludGVnZXInIH0sIHsgYzogJ2JpZ2ludCcgfSk7IC8vIE9rIVxuLy8gLy8gU2hvdWxkIGZhaWwgdHlwZS1jaGVja1xuLy8gY29uc3QgejEgPSB2YWxpZGF0ZU9iamVjdChvLCB7IGE6ICd0bXAnIH0sIHsgYzogJ3p6JyB9KTtcbi8vIGNvbnN0IHoyID0gdmFsaWRhdGVPYmplY3QobywgeyBhOiAnaXNTYWZlSW50ZWdlcicgfSwgeyBjOiAnenonIH0pO1xuLy8gY29uc3QgejMgPSB2YWxpZGF0ZU9iamVjdChvLCB7IHRlc3Q6ICdib29sZWFuJywgejogJ2J1ZycgfSk7XG4vLyBjb25zdCB6NCA9IHZhbGlkYXRlT2JqZWN0KG8sIHsgYTogJ2Jvb2xlYW4nLCB6OiAnYnVnJyB9KTtcbi8vIyBzb3VyY2VNYXBwaW5nVVJMPXV0aWxzLmpzLm1hcCIsIi8qISBub2JsZS1jdXJ2ZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbi8vIFV0aWxpdGllcyBmb3IgbW9kdWxhciBhcml0aG1ldGljcyBhbmQgZmluaXRlIGZpZWxkc1xuaW1wb3J0IHsgYml0TWFzaywgbnVtYmVyVG9CeXRlc0JFLCBudW1iZXJUb0J5dGVzTEUsIGJ5dGVzVG9OdW1iZXJCRSwgYnl0ZXNUb051bWJlckxFLCBlbnN1cmVCeXRlcywgdmFsaWRhdGVPYmplY3QsIH0gZnJvbSAnLi91dGlscy5qcyc7XG4vLyBwcmV0dGllci1pZ25vcmVcbmNvbnN0IF8wbiA9IEJpZ0ludCgwKSwgXzFuID0gQmlnSW50KDEpLCBfMm4gPSBCaWdJbnQoMiksIF8zbiA9IEJpZ0ludCgzKTtcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgXzRuID0gQmlnSW50KDQpLCBfNW4gPSBCaWdJbnQoNSksIF84biA9IEJpZ0ludCg4KTtcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgXzluID0gQmlnSW50KDkpLCBfMTZuID0gQmlnSW50KDE2KTtcbi8vIENhbGN1bGF0ZXMgYSBtb2R1bG8gYlxuZXhwb3J0IGZ1bmN0aW9uIG1vZChhLCBiKSB7XG4gICAgY29uc3QgcmVzdWx0ID0gYSAlIGI7XG4gICAgcmV0dXJuIHJlc3VsdCA+PSBfMG4gPyByZXN1bHQgOiBiICsgcmVzdWx0O1xufVxuLyoqXG4gKiBFZmZpY2llbnRseSBleHBvbmVudGlhdGUgbnVtIHRvIHBvd2VyIGFuZCBkbyBtb2R1bGFyIGRpdmlzaW9uLlxuICogVW5zYWZlIGluIHNvbWUgY29udGV4dHM6IHVzZXMgbGFkZGVyLCBzbyBjYW4gZXhwb3NlIGJpZ2ludCBiaXRzLlxuICogQGV4YW1wbGVcbiAqIHBvd01vZCgybiwgNm4sIDExbikgLy8gNjRuICUgMTFuID09IDluXG4gKi9cbi8vIFRPRE86IHVzZSBmaWVsZCB2ZXJzaW9uICYmIHJlbW92ZVxuZXhwb3J0IGZ1bmN0aW9uIHBvdyhudW0sIHBvd2VyLCBtb2R1bG8pIHtcbiAgICBpZiAobW9kdWxvIDw9IF8wbiB8fCBwb3dlciA8IF8wbilcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdFeHBlY3RlZCBwb3dlci9tb2R1bG8gPiAwJyk7XG4gICAgaWYgKG1vZHVsbyA9PT0gXzFuKVxuICAgICAgICByZXR1cm4gXzBuO1xuICAgIGxldCByZXMgPSBfMW47XG4gICAgd2hpbGUgKHBvd2VyID4gXzBuKSB7XG4gICAgICAgIGlmIChwb3dlciAmIF8xbilcbiAgICAgICAgICAgIHJlcyA9IChyZXMgKiBudW0pICUgbW9kdWxvO1xuICAgICAgICBudW0gPSAobnVtICogbnVtKSAlIG1vZHVsbztcbiAgICAgICAgcG93ZXIgPj49IF8xbjtcbiAgICB9XG4gICAgcmV0dXJuIHJlcztcbn1cbi8vIERvZXMgeCBeICgyIF4gcG93ZXIpIG1vZCBwLiBwb3cyKDMwLCA0KSA9PSAzMCBeICgyIF4gNClcbmV4cG9ydCBmdW5jdGlvbiBwb3cyKHgsIHBvd2VyLCBtb2R1bG8pIHtcbiAgICBsZXQgcmVzID0geDtcbiAgICB3aGlsZSAocG93ZXItLSA+IF8wbikge1xuICAgICAgICByZXMgKj0gcmVzO1xuICAgICAgICByZXMgJT0gbW9kdWxvO1xuICAgIH1cbiAgICByZXR1cm4gcmVzO1xufVxuLy8gSW52ZXJzZXMgbnVtYmVyIG92ZXIgbW9kdWxvXG5leHBvcnQgZnVuY3Rpb24gaW52ZXJ0KG51bWJlciwgbW9kdWxvKSB7XG4gICAgaWYgKG51bWJlciA9PT0gXzBuIHx8IG1vZHVsbyA8PSBfMG4pIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBpbnZlcnQ6IGV4cGVjdGVkIHBvc2l0aXZlIGludGVnZXJzLCBnb3Qgbj0ke251bWJlcn0gbW9kPSR7bW9kdWxvfWApO1xuICAgIH1cbiAgICAvLyBFdWNsZWRpYW4gR0NEIGh0dHBzOi8vYnJpbGxpYW50Lm9yZy93aWtpL2V4dGVuZGVkLWV1Y2xpZGVhbi1hbGdvcml0aG0vXG4gICAgLy8gRmVybWF0J3MgbGl0dGxlIHRoZW9yZW0gXCJDVC1saWtlXCIgdmVyc2lvbiBpbnYobikgPSBuXihtLTIpIG1vZCBtIGlzIDMweCBzbG93ZXIuXG4gICAgbGV0IGEgPSBtb2QobnVtYmVyLCBtb2R1bG8pO1xuICAgIGxldCBiID0gbW9kdWxvO1xuICAgIC8vIHByZXR0aWVyLWlnbm9yZVxuICAgIGxldCB4ID0gXzBuLCB5ID0gXzFuLCB1ID0gXzFuLCB2ID0gXzBuO1xuICAgIHdoaWxlIChhICE9PSBfMG4pIHtcbiAgICAgICAgLy8gSklUIGFwcGxpZXMgb3B0aW1pemF0aW9uIGlmIHRob3NlIHR3byBsaW5lcyBmb2xsb3cgZWFjaCBvdGhlclxuICAgICAgICBjb25zdCBxID0gYiAvIGE7XG4gICAgICAgIGNvbnN0IHIgPSBiICUgYTtcbiAgICAgICAgY29uc3QgbSA9IHggLSB1ICogcTtcbiAgICAgICAgY29uc3QgbiA9IHkgLSB2ICogcTtcbiAgICAgICAgLy8gcHJldHRpZXItaWdub3JlXG4gICAgICAgIGIgPSBhLCBhID0gciwgeCA9IHUsIHkgPSB2LCB1ID0gbSwgdiA9IG47XG4gICAgfVxuICAgIGNvbnN0IGdjZCA9IGI7XG4gICAgaWYgKGdjZCAhPT0gXzFuKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludmVydDogZG9lcyBub3QgZXhpc3QnKTtcbiAgICByZXR1cm4gbW9kKHgsIG1vZHVsbyk7XG59XG4vLyBUb25lbGxpLVNoYW5rcyBhbGdvcml0aG1cbi8vIFBhcGVyIDE6IGh0dHBzOi8vZXByaW50LmlhY3Iub3JnLzIwMTIvNjg1LnBkZiAocGFnZSAxMilcbi8vIFBhcGVyIDI6IFNxdWFyZSBSb290cyBmcm9tIDE7IDI0LCA1MSwgMTAgdG8gRGFuIFNoYW5rc1xuZXhwb3J0IGZ1bmN0aW9uIHRvbmVsbGlTaGFua3MoUCkge1xuICAgIC8vIExlZ2VuZHJlIGNvbnN0YW50OiB1c2VkIHRvIGNhbGN1bGF0ZSBMZWdlbmRyZSBzeW1ib2wgKGEgfCBwKSxcbiAgICAvLyB3aGljaCBkZW5vdGVzIHRoZSB2YWx1ZSBvZiBhXigocC0xKS8yKSAobW9kIHApLlxuICAgIC8vIChhIHwgcCkg4omhIDEgICAgaWYgYSBpcyBhIHNxdWFyZSAobW9kIHApXG4gICAgLy8gKGEgfCBwKSDiiaEgLTEgICBpZiBhIGlzIG5vdCBhIHNxdWFyZSAobW9kIHApXG4gICAgLy8gKGEgfCBwKSDiiaEgMCAgICBpZiBhIOKJoSAwIChtb2QgcClcbiAgICBjb25zdCBsZWdlbmRyZUMgPSAoUCAtIF8xbikgLyBfMm47XG4gICAgbGV0IFEsIFMsIFo7XG4gICAgLy8gU3RlcCAxOiBCeSBmYWN0b3Jpbmcgb3V0IHBvd2VycyBvZiAyIGZyb20gcCAtIDEsXG4gICAgLy8gZmluZCBxIGFuZCBzIHN1Y2ggdGhhdCBwIC0gMSA9IHEqKDJecykgd2l0aCBxIG9kZFxuICAgIGZvciAoUSA9IFAgLSBfMW4sIFMgPSAwOyBRICUgXzJuID09PSBfMG47IFEgLz0gXzJuLCBTKyspXG4gICAgICAgIDtcbiAgICAvLyBTdGVwIDI6IFNlbGVjdCBhIG5vbi1zcXVhcmUgeiBzdWNoIHRoYXQgKHogfCBwKSDiiaEgLTEgYW5kIHNldCBjIOKJoSB6cVxuICAgIGZvciAoWiA9IF8ybjsgWiA8IFAgJiYgcG93KFosIGxlZ2VuZHJlQywgUCkgIT09IFAgLSBfMW47IForKylcbiAgICAgICAgO1xuICAgIC8vIEZhc3QtcGF0aFxuICAgIGlmIChTID09PSAxKSB7XG4gICAgICAgIGNvbnN0IHAxZGl2NCA9IChQICsgXzFuKSAvIF80bjtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIHRvbmVsbGlGYXN0KEZwLCBuKSB7XG4gICAgICAgICAgICBjb25zdCByb290ID0gRnAucG93KG4sIHAxZGl2NCk7XG4gICAgICAgICAgICBpZiAoIUZwLmVxbChGcC5zcXIocm9vdCksIG4pKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgc3F1YXJlIHJvb3QnKTtcbiAgICAgICAgICAgIHJldHVybiByb290O1xuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBTbG93LXBhdGhcbiAgICBjb25zdCBRMWRpdjIgPSAoUSArIF8xbikgLyBfMm47XG4gICAgcmV0dXJuIGZ1bmN0aW9uIHRvbmVsbGlTbG93KEZwLCBuKSB7XG4gICAgICAgIC8vIFN0ZXAgMDogQ2hlY2sgdGhhdCBuIGlzIGluZGVlZCBhIHNxdWFyZTogKG4gfCBwKSBzaG91bGQgbm90IGJlIOKJoSAtMVxuICAgICAgICBpZiAoRnAucG93KG4sIGxlZ2VuZHJlQykgPT09IEZwLm5lZyhGcC5PTkUpKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBzcXVhcmUgcm9vdCcpO1xuICAgICAgICBsZXQgciA9IFM7XG4gICAgICAgIC8vIFRPRE86IHdpbGwgZmFpbCBhdCBGcDIvZXRjXG4gICAgICAgIGxldCBnID0gRnAucG93KEZwLm11bChGcC5PTkUsIFopLCBRKTsgLy8gd2lsbCB1cGRhdGUgYm90aCB4IGFuZCBiXG4gICAgICAgIGxldCB4ID0gRnAucG93KG4sIFExZGl2Mik7IC8vIGZpcnN0IGd1ZXNzIGF0IHRoZSBzcXVhcmUgcm9vdFxuICAgICAgICBsZXQgYiA9IEZwLnBvdyhuLCBRKTsgLy8gZmlyc3QgZ3Vlc3MgYXQgdGhlIGZ1ZGdlIGZhY3RvclxuICAgICAgICB3aGlsZSAoIUZwLmVxbChiLCBGcC5PTkUpKSB7XG4gICAgICAgICAgICBpZiAoRnAuZXFsKGIsIEZwLlpFUk8pKVxuICAgICAgICAgICAgICAgIHJldHVybiBGcC5aRVJPOyAvLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ub25lbGxpJUUyJTgwJTkzU2hhbmtzX2FsZ29yaXRobSAoNC4gSWYgdCA9IDAsIHJldHVybiByID0gMClcbiAgICAgICAgICAgIC8vIEZpbmQgbSBzdWNoIGJeKDJebSk9PTFcbiAgICAgICAgICAgIGxldCBtID0gMTtcbiAgICAgICAgICAgIGZvciAobGV0IHQyID0gRnAuc3FyKGIpOyBtIDwgcjsgbSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKEZwLmVxbCh0MiwgRnAuT05FKSlcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgdDIgPSBGcC5zcXIodDIpOyAvLyB0MiAqPSB0MlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gTk9URTogci1tLTEgY2FuIGJlIGJpZ2dlciB0aGFuIDMyLCBuZWVkIHRvIGNvbnZlcnQgdG8gYmlnaW50IGJlZm9yZSBzaGlmdCwgb3RoZXJ3aXNlIHRoZXJlIHdpbGwgYmUgb3ZlcmZsb3dcbiAgICAgICAgICAgIGNvbnN0IGdlID0gRnAucG93KGcsIF8xbiA8PCBCaWdJbnQociAtIG0gLSAxKSk7IC8vIGdlID0gMl4oci1tLTEpXG4gICAgICAgICAgICBnID0gRnAuc3FyKGdlKTsgLy8gZyA9IGdlICogZ2VcbiAgICAgICAgICAgIHggPSBGcC5tdWwoeCwgZ2UpOyAvLyB4ICo9IGdlXG4gICAgICAgICAgICBiID0gRnAubXVsKGIsIGcpOyAvLyBiICo9IGdcbiAgICAgICAgICAgIHIgPSBtO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB4O1xuICAgIH07XG59XG5leHBvcnQgZnVuY3Rpb24gRnBTcXJ0KFApIHtcbiAgICAvLyBOT1RFOiBkaWZmZXJlbnQgYWxnb3JpdGhtcyBjYW4gZ2l2ZSBkaWZmZXJlbnQgcm9vdHMsIGl0IGlzIHVwIHRvIHVzZXIgdG8gZGVjaWRlIHdoaWNoIG9uZSB0aGV5IHdhbnQuXG4gICAgLy8gRm9yIGV4YW1wbGUgdGhlcmUgaXMgRnBTcXJ0T2RkL0ZwU3FydEV2ZW4gdG8gY2hvaWNlIHJvb3QgYmFzZWQgb24gb2RkbmVzcyAodXNlZCBmb3IgaGFzaC10by1jdXJ2ZSkuXG4gICAgLy8gUCDiiaEgMyAobW9kIDQpXG4gICAgLy8g4oiabiA9IG5eKChQKzEpLzQpXG4gICAgaWYgKFAgJSBfNG4gPT09IF8zbikge1xuICAgICAgICAvLyBOb3QgYWxsIHJvb3RzIHBvc3NpYmxlIVxuICAgICAgICAvLyBjb25zdCBPUkRFUiA9XG4gICAgICAgIC8vICAgMHgxYTAxMTFlYTM5N2ZlNjlhNGIxYmE3YjY0MzRiYWNkNzY0Nzc0Yjg0ZjM4NTEyYmY2NzMwZDJhMGY2YjBmNjI0MWVhYmZmZmViMTUzZmZmZmI5ZmVmZmZmZmZmZmFhYWJuO1xuICAgICAgICAvLyBjb25zdCBOVU0gPSA3MjA1NzU5NDAzNzkyNzgxNm47XG4gICAgICAgIGNvbnN0IHAxZGl2NCA9IChQICsgXzFuKSAvIF80bjtcbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uIHNxcnQzbW9kNChGcCwgbikge1xuICAgICAgICAgICAgY29uc3Qgcm9vdCA9IEZwLnBvdyhuLCBwMWRpdjQpO1xuICAgICAgICAgICAgLy8gVGhyb3cgaWYgcm9vdCoqMiAhPSBuXG4gICAgICAgICAgICBpZiAoIUZwLmVxbChGcC5zcXIocm9vdCksIG4pKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ2Fubm90IGZpbmQgc3F1YXJlIHJvb3QnKTtcbiAgICAgICAgICAgIHJldHVybiByb290O1xuICAgICAgICB9O1xuICAgIH1cbiAgICAvLyBBdGtpbiBhbGdvcml0aG0gZm9yIHEg4omhIDUgKG1vZCA4KSwgaHR0cHM6Ly9lcHJpbnQuaWFjci5vcmcvMjAxMi82ODUucGRmIChwYWdlIDEwKVxuICAgIGlmIChQICUgXzhuID09PSBfNW4pIHtcbiAgICAgICAgY29uc3QgYzEgPSAoUCAtIF81bikgLyBfOG47XG4gICAgICAgIHJldHVybiBmdW5jdGlvbiBzcXJ0NW1vZDgoRnAsIG4pIHtcbiAgICAgICAgICAgIGNvbnN0IG4yID0gRnAubXVsKG4sIF8ybik7XG4gICAgICAgICAgICBjb25zdCB2ID0gRnAucG93KG4yLCBjMSk7XG4gICAgICAgICAgICBjb25zdCBudiA9IEZwLm11bChuLCB2KTtcbiAgICAgICAgICAgIGNvbnN0IGkgPSBGcC5tdWwoRnAubXVsKG52LCBfMm4pLCB2KTtcbiAgICAgICAgICAgIGNvbnN0IHJvb3QgPSBGcC5tdWwobnYsIEZwLnN1YihpLCBGcC5PTkUpKTtcbiAgICAgICAgICAgIGlmICghRnAuZXFsKEZwLnNxcihyb290KSwgbikpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdDYW5ub3QgZmluZCBzcXVhcmUgcm9vdCcpO1xuICAgICAgICAgICAgcmV0dXJuIHJvb3Q7XG4gICAgICAgIH07XG4gICAgfVxuICAgIC8vIFAg4omhIDkgKG1vZCAxNilcbiAgICBpZiAoUCAlIF8xNm4gPT09IF85bikge1xuICAgICAgICAvLyBOT1RFOiB0b25lbGxpIGlzIHRvbyBzbG93IGZvciBibHMtRnAyIGNhbGN1bGF0aW9ucyBldmVuIG9uIHN0YXJ0XG4gICAgICAgIC8vIE1lYW5zIHdlIGNhbm5vdCB1c2Ugc3FydCBmb3IgY29uc3RhbnRzIGF0IGFsbCFcbiAgICAgICAgLy9cbiAgICAgICAgLy8gY29uc3QgYzEgPSBGcC5zcXJ0KEZwLm5lZ2F0ZShGcC5PTkUpKTsgLy8gIDEuIGMxID0gc3FydCgtMSkgaW4gRiwgaS5lLiwgKGMxXjIpID09IC0xIGluIEZcbiAgICAgICAgLy8gY29uc3QgYzIgPSBGcC5zcXJ0KGMxKTsgICAgICAgICAgICAgICAgLy8gIDIuIGMyID0gc3FydChjMSkgaW4gRiwgaS5lLiwgKGMyXjIpID09IGMxIGluIEZcbiAgICAgICAgLy8gY29uc3QgYzMgPSBGcC5zcXJ0KEZwLm5lZ2F0ZShjMSkpOyAgICAgLy8gIDMuIGMzID0gc3FydCgtYzEpIGluIEYsIGkuZS4sIChjM14yKSA9PSAtYzEgaW4gRlxuICAgICAgICAvLyBjb25zdCBjNCA9IChQICsgXzduKSAvIF8xNm47ICAgICAgICAgICAvLyAgNC4gYzQgPSAocSArIDcpIC8gMTYgICAgICAgICMgSW50ZWdlciBhcml0aG1ldGljXG4gICAgICAgIC8vIHNxcnQgPSAoeCkgPT4ge1xuICAgICAgICAvLyAgIGxldCB0djEgPSBGcC5wb3coeCwgYzQpOyAgICAgICAgICAgICAvLyAgMS4gdHYxID0geF5jNFxuICAgICAgICAvLyAgIGxldCB0djIgPSBGcC5tdWwoYzEsIHR2MSk7ICAgICAgICAgICAvLyAgMi4gdHYyID0gYzEgKiB0djFcbiAgICAgICAgLy8gICBjb25zdCB0djMgPSBGcC5tdWwoYzIsIHR2MSk7ICAgICAgICAgLy8gIDMuIHR2MyA9IGMyICogdHYxXG4gICAgICAgIC8vICAgbGV0IHR2NCA9IEZwLm11bChjMywgdHYxKTsgICAgICAgICAgIC8vICA0LiB0djQgPSBjMyAqIHR2MVxuICAgICAgICAvLyAgIGNvbnN0IGUxID0gRnAuZXF1YWxzKEZwLnNxdWFyZSh0djIpLCB4KTsgLy8gIDUuICBlMSA9ICh0djJeMikgPT0geFxuICAgICAgICAvLyAgIGNvbnN0IGUyID0gRnAuZXF1YWxzKEZwLnNxdWFyZSh0djMpLCB4KTsgLy8gIDYuICBlMiA9ICh0djNeMikgPT0geFxuICAgICAgICAvLyAgIHR2MSA9IEZwLmNtb3YodHYxLCB0djIsIGUxKTsgLy8gIDcuIHR2MSA9IENNT1YodHYxLCB0djIsIGUxKSAgIyBTZWxlY3QgdHYyIGlmICh0djJeMikgPT0geFxuICAgICAgICAvLyAgIHR2MiA9IEZwLmNtb3YodHY0LCB0djMsIGUyKTsgLy8gIDguIHR2MiA9IENNT1YodHY0LCB0djMsIGUyKSAgIyBTZWxlY3QgdHYzIGlmICh0djNeMikgPT0geFxuICAgICAgICAvLyAgIGNvbnN0IGUzID0gRnAuZXF1YWxzKEZwLnNxdWFyZSh0djIpLCB4KTsgLy8gIDkuICBlMyA9ICh0djJeMikgPT0geFxuICAgICAgICAvLyAgIHJldHVybiBGcC5jbW92KHR2MSwgdHYyLCBlMyk7IC8vICAxMC4gIHogPSBDTU9WKHR2MSwgdHYyLCBlMykgICMgU2VsZWN0IHRoZSBzcXJ0IGZyb20gdHYxIGFuZCB0djJcbiAgICAgICAgLy8gfVxuICAgIH1cbiAgICAvLyBPdGhlciBjYXNlczogVG9uZWxsaS1TaGFua3MgYWxnb3JpdGhtXG4gICAgcmV0dXJuIHRvbmVsbGlTaGFua3MoUCk7XG59XG4vLyBMaXR0bGUtZW5kaWFuIGNoZWNrIGZvciBmaXJzdCBMRSBiaXQgKGxhc3QgQkUgYml0KTtcbmV4cG9ydCBjb25zdCBpc05lZ2F0aXZlTEUgPSAobnVtLCBtb2R1bG8pID0+IChtb2QobnVtLCBtb2R1bG8pICYgXzFuKSA9PT0gXzFuO1xuLy8gcHJldHRpZXItaWdub3JlXG5jb25zdCBGSUVMRF9GSUVMRFMgPSBbXG4gICAgJ2NyZWF0ZScsICdpc1ZhbGlkJywgJ2lzMCcsICduZWcnLCAnaW52JywgJ3NxcnQnLCAnc3FyJyxcbiAgICAnZXFsJywgJ2FkZCcsICdzdWInLCAnbXVsJywgJ3BvdycsICdkaXYnLFxuICAgICdhZGROJywgJ3N1Yk4nLCAnbXVsTicsICdzcXJOJ1xuXTtcbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZUZpZWxkKGZpZWxkKSB7XG4gICAgY29uc3QgaW5pdGlhbCA9IHtcbiAgICAgICAgT1JERVI6ICdiaWdpbnQnLFxuICAgICAgICBNQVNLOiAnYmlnaW50JyxcbiAgICAgICAgQllURVM6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICAgICAgQklUUzogJ2lzU2FmZUludGVnZXInLFxuICAgIH07XG4gICAgY29uc3Qgb3B0cyA9IEZJRUxEX0ZJRUxEUy5yZWR1Y2UoKG1hcCwgdmFsKSA9PiB7XG4gICAgICAgIG1hcFt2YWxdID0gJ2Z1bmN0aW9uJztcbiAgICAgICAgcmV0dXJuIG1hcDtcbiAgICB9LCBpbml0aWFsKTtcbiAgICByZXR1cm4gdmFsaWRhdGVPYmplY3QoZmllbGQsIG9wdHMpO1xufVxuLy8gR2VuZXJpYyBmaWVsZCBmdW5jdGlvbnNcbmV4cG9ydCBmdW5jdGlvbiBGcFBvdyhmLCBudW0sIHBvd2VyKSB7XG4gICAgLy8gU2hvdWxkIGhhdmUgc2FtZSBzcGVlZCBhcyBwb3cgZm9yIGJpZ2ludHNcbiAgICAvLyBUT0RPOiBiZW5jaG1hcmshXG4gICAgaWYgKHBvd2VyIDwgXzBuKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ0V4cGVjdGVkIHBvd2VyID4gMCcpO1xuICAgIGlmIChwb3dlciA9PT0gXzBuKVxuICAgICAgICByZXR1cm4gZi5PTkU7XG4gICAgaWYgKHBvd2VyID09PSBfMW4pXG4gICAgICAgIHJldHVybiBudW07XG4gICAgbGV0IHAgPSBmLk9ORTtcbiAgICBsZXQgZCA9IG51bTtcbiAgICB3aGlsZSAocG93ZXIgPiBfMG4pIHtcbiAgICAgICAgaWYgKHBvd2VyICYgXzFuKVxuICAgICAgICAgICAgcCA9IGYubXVsKHAsIGQpO1xuICAgICAgICBkID0gZi5zcXIoZCk7XG4gICAgICAgIHBvd2VyID4+PSBfMW47XG4gICAgfVxuICAgIHJldHVybiBwO1xufVxuLy8gMCBpcyBub24taW52ZXJ0aWJsZTogbm9uLWJhdGNoZWQgdmVyc2lvbiB3aWxsIHRocm93IG9uIDBcbmV4cG9ydCBmdW5jdGlvbiBGcEludmVydEJhdGNoKGYsIG51bXMpIHtcbiAgICBjb25zdCB0bXAgPSBuZXcgQXJyYXkobnVtcy5sZW5ndGgpO1xuICAgIC8vIFdhbGsgZnJvbSBmaXJzdCB0byBsYXN0LCBtdWx0aXBseSB0aGVtIGJ5IGVhY2ggb3RoZXIgTU9EIHBcbiAgICBjb25zdCBsYXN0TXVsdGlwbGllZCA9IG51bXMucmVkdWNlKChhY2MsIG51bSwgaSkgPT4ge1xuICAgICAgICBpZiAoZi5pczAobnVtKSlcbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgIHRtcFtpXSA9IGFjYztcbiAgICAgICAgcmV0dXJuIGYubXVsKGFjYywgbnVtKTtcbiAgICB9LCBmLk9ORSk7XG4gICAgLy8gSW52ZXJ0IGxhc3QgZWxlbWVudFxuICAgIGNvbnN0IGludmVydGVkID0gZi5pbnYobGFzdE11bHRpcGxpZWQpO1xuICAgIC8vIFdhbGsgZnJvbSBsYXN0IHRvIGZpcnN0LCBtdWx0aXBseSB0aGVtIGJ5IGludmVydGVkIGVhY2ggb3RoZXIgTU9EIHBcbiAgICBudW1zLnJlZHVjZVJpZ2h0KChhY2MsIG51bSwgaSkgPT4ge1xuICAgICAgICBpZiAoZi5pczAobnVtKSlcbiAgICAgICAgICAgIHJldHVybiBhY2M7XG4gICAgICAgIHRtcFtpXSA9IGYubXVsKGFjYywgdG1wW2ldKTtcbiAgICAgICAgcmV0dXJuIGYubXVsKGFjYywgbnVtKTtcbiAgICB9LCBpbnZlcnRlZCk7XG4gICAgcmV0dXJuIHRtcDtcbn1cbmV4cG9ydCBmdW5jdGlvbiBGcERpdihmLCBsaHMsIHJocykge1xuICAgIHJldHVybiBmLm11bChsaHMsIHR5cGVvZiByaHMgPT09ICdiaWdpbnQnID8gaW52ZXJ0KHJocywgZi5PUkRFUikgOiBmLmludihyaHMpKTtcbn1cbi8vIFRoaXMgZnVuY3Rpb24gcmV0dXJucyBUcnVlIHdoZW5ldmVyIHRoZSB2YWx1ZSB4IGlzIGEgc3F1YXJlIGluIHRoZSBmaWVsZCBGLlxuZXhwb3J0IGZ1bmN0aW9uIEZwSXNTcXVhcmUoZikge1xuICAgIGNvbnN0IGxlZ2VuZHJlQ29uc3QgPSAoZi5PUkRFUiAtIF8xbikgLyBfMm47IC8vIEludGVnZXIgYXJpdGhtZXRpY1xuICAgIHJldHVybiAoeCkgPT4ge1xuICAgICAgICBjb25zdCBwID0gZi5wb3coeCwgbGVnZW5kcmVDb25zdCk7XG4gICAgICAgIHJldHVybiBmLmVxbChwLCBmLlpFUk8pIHx8IGYuZXFsKHAsIGYuT05FKTtcbiAgICB9O1xufVxuLy8gQ1VSVkUubiBsZW5ndGhzXG5leHBvcnQgZnVuY3Rpb24gbkxlbmd0aChuLCBuQml0TGVuZ3RoKSB7XG4gICAgLy8gQml0IHNpemUsIGJ5dGUgc2l6ZSBvZiBDVVJWRS5uXG4gICAgY29uc3QgX25CaXRMZW5ndGggPSBuQml0TGVuZ3RoICE9PSB1bmRlZmluZWQgPyBuQml0TGVuZ3RoIDogbi50b1N0cmluZygyKS5sZW5ndGg7XG4gICAgY29uc3QgbkJ5dGVMZW5ndGggPSBNYXRoLmNlaWwoX25CaXRMZW5ndGggLyA4KTtcbiAgICByZXR1cm4geyBuQml0TGVuZ3RoOiBfbkJpdExlbmd0aCwgbkJ5dGVMZW5ndGggfTtcbn1cbi8qKlxuICogSW5pdGlhbGl6ZXMgYSBnYWxvaXMgZmllbGQgb3ZlciBwcmltZS4gTm9uLXByaW1lcyBhcmUgbm90IHN1cHBvcnRlZCBmb3Igbm93LlxuICogRG8gbm90IGluaXQgaW4gbG9vcDogc2xvdy4gVmVyeSBmcmFnaWxlOiBhbHdheXMgcnVuIGEgYmVuY2htYXJrIG9uIGNoYW5nZS5cbiAqIE1ham9yIHBlcmZvcm1hbmNlIGdhaW5zOlxuICogYSkgbm9uLW5vcm1hbGl6ZWQgb3BlcmF0aW9ucyBsaWtlIG11bE4gaW5zdGVhZCBvZiBtdWxcbiAqIGIpIGBPYmplY3QuZnJlZXplYFxuICogYykgU2FtZSBvYmplY3Qgc2hhcGU6IG5ldmVyIGFkZCBvciByZW1vdmUga2V5c1xuICogQHBhcmFtIE9SREVSIHByaW1lIHBvc2l0aXZlIGJpZ2ludFxuICogQHBhcmFtIGJpdExlbiBob3cgbWFueSBiaXRzIHRoZSBmaWVsZCBjb25zdW1lc1xuICogQHBhcmFtIGlzTEUgKGRlZjogZmFsc2UpIGlmIGVuY29kaW5nIC8gZGVjb2Rpbmcgc2hvdWxkIGJlIGluIGxpdHRsZS1lbmRpYW5cbiAqIEBwYXJhbSByZWRlZiBvcHRpb25hbCBmYXN0ZXIgcmVkZWZpbml0aW9ucyBvZiBzcXJ0IGFuZCBvdGhlciBtZXRob2RzXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBGaWVsZChPUkRFUiwgYml0TGVuLCBpc0xFID0gZmFsc2UsIHJlZGVmID0ge30pIHtcbiAgICBpZiAoT1JERVIgPD0gXzBuKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkIEZwIE9SREVSID4gMCwgZ290ICR7T1JERVJ9YCk7XG4gICAgY29uc3QgeyBuQml0TGVuZ3RoOiBCSVRTLCBuQnl0ZUxlbmd0aDogQllURVMgfSA9IG5MZW5ndGgoT1JERVIsIGJpdExlbik7XG4gICAgaWYgKEJZVEVTID4gMjA0OClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdGaWVsZCBsZW5ndGhzIG92ZXIgMjA0OCBieXRlcyBhcmUgbm90IHN1cHBvcnRlZCcpO1xuICAgIGNvbnN0IHNxcnRQID0gRnBTcXJ0KE9SREVSKTtcbiAgICBjb25zdCBmID0gT2JqZWN0LmZyZWV6ZSh7XG4gICAgICAgIE9SREVSLFxuICAgICAgICBCSVRTLFxuICAgICAgICBCWVRFUyxcbiAgICAgICAgTUFTSzogYml0TWFzayhCSVRTKSxcbiAgICAgICAgWkVSTzogXzBuLFxuICAgICAgICBPTkU6IF8xbixcbiAgICAgICAgY3JlYXRlOiAobnVtKSA9PiBtb2QobnVtLCBPUkRFUiksXG4gICAgICAgIGlzVmFsaWQ6IChudW0pID0+IHtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgbnVtICE9PSAnYmlnaW50JylcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgZmllbGQgZWxlbWVudDogZXhwZWN0ZWQgYmlnaW50LCBnb3QgJHt0eXBlb2YgbnVtfWApO1xuICAgICAgICAgICAgcmV0dXJuIF8wbiA8PSBudW0gJiYgbnVtIDwgT1JERVI7IC8vIDAgaXMgdmFsaWQgZWxlbWVudCwgYnV0IGl0J3Mgbm90IGludmVydGlibGVcbiAgICAgICAgfSxcbiAgICAgICAgaXMwOiAobnVtKSA9PiBudW0gPT09IF8wbixcbiAgICAgICAgaXNPZGQ6IChudW0pID0+IChudW0gJiBfMW4pID09PSBfMW4sXG4gICAgICAgIG5lZzogKG51bSkgPT4gbW9kKC1udW0sIE9SREVSKSxcbiAgICAgICAgZXFsOiAobGhzLCByaHMpID0+IGxocyA9PT0gcmhzLFxuICAgICAgICBzcXI6IChudW0pID0+IG1vZChudW0gKiBudW0sIE9SREVSKSxcbiAgICAgICAgYWRkOiAobGhzLCByaHMpID0+IG1vZChsaHMgKyByaHMsIE9SREVSKSxcbiAgICAgICAgc3ViOiAobGhzLCByaHMpID0+IG1vZChsaHMgLSByaHMsIE9SREVSKSxcbiAgICAgICAgbXVsOiAobGhzLCByaHMpID0+IG1vZChsaHMgKiByaHMsIE9SREVSKSxcbiAgICAgICAgcG93OiAobnVtLCBwb3dlcikgPT4gRnBQb3coZiwgbnVtLCBwb3dlciksXG4gICAgICAgIGRpdjogKGxocywgcmhzKSA9PiBtb2QobGhzICogaW52ZXJ0KHJocywgT1JERVIpLCBPUkRFUiksXG4gICAgICAgIC8vIFNhbWUgYXMgYWJvdmUsIGJ1dCBkb2Vzbid0IG5vcm1hbGl6ZVxuICAgICAgICBzcXJOOiAobnVtKSA9PiBudW0gKiBudW0sXG4gICAgICAgIGFkZE46IChsaHMsIHJocykgPT4gbGhzICsgcmhzLFxuICAgICAgICBzdWJOOiAobGhzLCByaHMpID0+IGxocyAtIHJocyxcbiAgICAgICAgbXVsTjogKGxocywgcmhzKSA9PiBsaHMgKiByaHMsXG4gICAgICAgIGludjogKG51bSkgPT4gaW52ZXJ0KG51bSwgT1JERVIpLFxuICAgICAgICBzcXJ0OiByZWRlZi5zcXJ0IHx8ICgobikgPT4gc3FydFAoZiwgbikpLFxuICAgICAgICBpbnZlcnRCYXRjaDogKGxzdCkgPT4gRnBJbnZlcnRCYXRjaChmLCBsc3QpLFxuICAgICAgICAvLyBUT0RPOiBkbyB3ZSByZWFsbHkgbmVlZCBjb25zdGFudCBjbW92P1xuICAgICAgICAvLyBXZSBkb24ndCBoYXZlIGNvbnN0LXRpbWUgYmlnaW50cyBhbnl3YXksIHNvIHByb2JhYmx5IHdpbGwgYmUgbm90IHZlcnkgdXNlZnVsXG4gICAgICAgIGNtb3Y6IChhLCBiLCBjKSA9PiAoYyA/IGIgOiBhKSxcbiAgICAgICAgdG9CeXRlczogKG51bSkgPT4gKGlzTEUgPyBudW1iZXJUb0J5dGVzTEUobnVtLCBCWVRFUykgOiBudW1iZXJUb0J5dGVzQkUobnVtLCBCWVRFUykpLFxuICAgICAgICBmcm9tQnl0ZXM6IChieXRlcykgPT4ge1xuICAgICAgICAgICAgaWYgKGJ5dGVzLmxlbmd0aCAhPT0gQllURVMpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGcC5mcm9tQnl0ZXM6IGV4cGVjdGVkICR7QllURVN9LCBnb3QgJHtieXRlcy5sZW5ndGh9YCk7XG4gICAgICAgICAgICByZXR1cm4gaXNMRSA/IGJ5dGVzVG9OdW1iZXJMRShieXRlcykgOiBieXRlc1RvTnVtYmVyQkUoYnl0ZXMpO1xuICAgICAgICB9LFxuICAgIH0pO1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKGYpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIEZwU3FydE9kZChGcCwgZWxtKSB7XG4gICAgaWYgKCFGcC5pc09kZClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGaWVsZCBkb2Vzbid0IGhhdmUgaXNPZGRgKTtcbiAgICBjb25zdCByb290ID0gRnAuc3FydChlbG0pO1xuICAgIHJldHVybiBGcC5pc09kZChyb290KSA/IHJvb3QgOiBGcC5uZWcocm9vdCk7XG59XG5leHBvcnQgZnVuY3Rpb24gRnBTcXJ0RXZlbihGcCwgZWxtKSB7XG4gICAgaWYgKCFGcC5pc09kZClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBGaWVsZCBkb2Vzbid0IGhhdmUgaXNPZGRgKTtcbiAgICBjb25zdCByb290ID0gRnAuc3FydChlbG0pO1xuICAgIHJldHVybiBGcC5pc09kZChyb290KSA/IEZwLm5lZyhyb290KSA6IHJvb3Q7XG59XG4vKipcbiAqIEZJUFMgMTg2IEIuNC4xLWNvbXBsaWFudCBcImNvbnN0YW50LXRpbWVcIiBwcml2YXRlIGtleSBnZW5lcmF0aW9uIHV0aWxpdHkuXG4gKiBDYW4gdGFrZSAobis4KSBvciBtb3JlIGJ5dGVzIG9mIHVuaWZvcm0gaW5wdXQgZS5nLiBmcm9tIENTUFJORyBvciBLREZcbiAqIGFuZCBjb252ZXJ0IHRoZW0gaW50byBwcml2YXRlIHNjYWxhciwgd2l0aCB0aGUgbW9kdWxvIGJpYXMgYmVpbmcgbmVnbGlibGUuXG4gKiBOZWVkcyBhdCBsZWFzdCA0MCBieXRlcyBvZiBpbnB1dCBmb3IgMzItYnl0ZSBwcml2YXRlIGtleS5cbiAqIGh0dHBzOi8vcmVzZWFyY2gua3VkZWxza2lzZWN1cml0eS5jb20vMjAyMC8wNy8yOC90aGUtZGVmaW5pdGl2ZS1ndWlkZS10by1tb2R1bG8tYmlhcy1hbmQtaG93LXRvLWF2b2lkLWl0L1xuICogQHBhcmFtIGhhc2ggaGFzaCBvdXRwdXQgZnJvbSBTSEEzIG9yIGEgc2ltaWxhciBmdW5jdGlvblxuICogQHJldHVybnMgdmFsaWQgcHJpdmF0ZSBzY2FsYXJcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGhhc2hUb1ByaXZhdGVTY2FsYXIoaGFzaCwgZ3JvdXBPcmRlciwgaXNMRSA9IGZhbHNlKSB7XG4gICAgaGFzaCA9IGVuc3VyZUJ5dGVzKCdwcml2YXRlSGFzaCcsIGhhc2gpO1xuICAgIGNvbnN0IGhhc2hMZW4gPSBoYXNoLmxlbmd0aDtcbiAgICBjb25zdCBtaW5MZW4gPSBuTGVuZ3RoKGdyb3VwT3JkZXIpLm5CeXRlTGVuZ3RoICsgODtcbiAgICBpZiAobWluTGVuIDwgMjQgfHwgaGFzaExlbiA8IG1pbkxlbiB8fCBoYXNoTGVuID4gMTAyNClcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBoYXNoVG9Qcml2YXRlU2NhbGFyOiBleHBlY3RlZCAke21pbkxlbn0tMTAyNCBieXRlcyBvZiBpbnB1dCwgZ290ICR7aGFzaExlbn1gKTtcbiAgICBjb25zdCBudW0gPSBpc0xFID8gYnl0ZXNUb051bWJlckxFKGhhc2gpIDogYnl0ZXNUb051bWJlckJFKGhhc2gpO1xuICAgIHJldHVybiBtb2QobnVtLCBncm91cE9yZGVyIC0gXzFuKSArIF8xbjtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPW1vZHVsYXIuanMubWFwIiwiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuLy8gQWJlbGlhbiBncm91cCB1dGlsaXRpZXNcbmltcG9ydCB7IHZhbGlkYXRlRmllbGQsIG5MZW5ndGggfSBmcm9tICcuL21vZHVsYXIuanMnO1xuaW1wb3J0IHsgdmFsaWRhdGVPYmplY3QgfSBmcm9tICcuL3V0aWxzLmpzJztcbmNvbnN0IF8wbiA9IEJpZ0ludCgwKTtcbmNvbnN0IF8xbiA9IEJpZ0ludCgxKTtcbi8vIEVsbGlwdGljIGN1cnZlIG11bHRpcGxpY2F0aW9uIG9mIFBvaW50IGJ5IHNjYWxhci4gRnJhZ2lsZS5cbi8vIFNjYWxhcnMgc2hvdWxkIGFsd2F5cyBiZSBsZXNzIHRoYW4gY3VydmUgb3JkZXI6IHRoaXMgc2hvdWxkIGJlIGNoZWNrZWQgaW5zaWRlIG9mIGEgY3VydmUgaXRzZWxmLlxuLy8gQ3JlYXRlcyBwcmVjb21wdXRhdGlvbiB0YWJsZXMgZm9yIGZhc3QgbXVsdGlwbGljYXRpb246XG4vLyAtIHByaXZhdGUgc2NhbGFyIGlzIHNwbGl0IGJ5IGZpeGVkIHNpemUgd2luZG93cyBvZiBXIGJpdHNcbi8vIC0gZXZlcnkgd2luZG93IHBvaW50IGlzIGNvbGxlY3RlZCBmcm9tIHdpbmRvdydzIHRhYmxlICYgYWRkZWQgdG8gYWNjdW11bGF0b3Jcbi8vIC0gc2luY2Ugd2luZG93cyBhcmUgZGlmZmVyZW50LCBzYW1lIHBvaW50IGluc2lkZSB0YWJsZXMgd29uJ3QgYmUgYWNjZXNzZWQgbW9yZSB0aGFuIG9uY2UgcGVyIGNhbGNcbi8vIC0gZWFjaCBtdWx0aXBsaWNhdGlvbiBpcyAnTWF0aC5jZWlsKENVUlZFX09SREVSIC8g8J2RiikgKyAxJyBwb2ludCBhZGRpdGlvbnMgKGZpeGVkIGZvciBhbnkgc2NhbGFyKVxuLy8gLSArMSB3aW5kb3cgaXMgbmVjY2Vzc2FyeSBmb3Igd05BRlxuLy8gLSB3TkFGIHJlZHVjZXMgdGFibGUgc2l6ZTogMnggbGVzcyBtZW1vcnkgKyAyeCBmYXN0ZXIgZ2VuZXJhdGlvbiwgYnV0IDEwJSBzbG93ZXIgbXVsdGlwbGljYXRpb25cbi8vIFRPRE86IFJlc2VhcmNoIHJldHVybmluZyAyZCBKUyBhcnJheSBvZiB3aW5kb3dzLCBpbnN0ZWFkIG9mIGEgc2luZ2xlIHdpbmRvdy4gVGhpcyB3b3VsZCBhbGxvd1xuLy8gd2luZG93cyB0byBiZSBpbiBkaWZmZXJlbnQgbWVtb3J5IGxvY2F0aW9uc1xuZXhwb3J0IGZ1bmN0aW9uIHdOQUYoYywgYml0cykge1xuICAgIGNvbnN0IGNvbnN0VGltZU5lZ2F0ZSA9IChjb25kaXRpb24sIGl0ZW0pID0+IHtcbiAgICAgICAgY29uc3QgbmVnID0gaXRlbS5uZWdhdGUoKTtcbiAgICAgICAgcmV0dXJuIGNvbmRpdGlvbiA/IG5lZyA6IGl0ZW07XG4gICAgfTtcbiAgICBjb25zdCBvcHRzID0gKFcpID0+IHtcbiAgICAgICAgY29uc3Qgd2luZG93cyA9IE1hdGguY2VpbChiaXRzIC8gVykgKyAxOyAvLyArMSwgYmVjYXVzZVxuICAgICAgICBjb25zdCB3aW5kb3dTaXplID0gMiAqKiAoVyAtIDEpOyAvLyAtMSBiZWNhdXNlIHdlIHNraXAgemVyb1xuICAgICAgICByZXR1cm4geyB3aW5kb3dzLCB3aW5kb3dTaXplIH07XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgICBjb25zdFRpbWVOZWdhdGUsXG4gICAgICAgIC8vIG5vbi1jb25zdCB0aW1lIG11bHRpcGxpY2F0aW9uIGxhZGRlclxuICAgICAgICB1bnNhZmVMYWRkZXIoZWxtLCBuKSB7XG4gICAgICAgICAgICBsZXQgcCA9IGMuWkVSTztcbiAgICAgICAgICAgIGxldCBkID0gZWxtO1xuICAgICAgICAgICAgd2hpbGUgKG4gPiBfMG4pIHtcbiAgICAgICAgICAgICAgICBpZiAobiAmIF8xbilcbiAgICAgICAgICAgICAgICAgICAgcCA9IHAuYWRkKGQpO1xuICAgICAgICAgICAgICAgIGQgPSBkLmRvdWJsZSgpO1xuICAgICAgICAgICAgICAgIG4gPj49IF8xbjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBwO1xuICAgICAgICB9LFxuICAgICAgICAvKipcbiAgICAgICAgICogQ3JlYXRlcyBhIHdOQUYgcHJlY29tcHV0YXRpb24gd2luZG93LiBVc2VkIGZvciBjYWNoaW5nLlxuICAgICAgICAgKiBEZWZhdWx0IHdpbmRvdyBzaXplIGlzIHNldCBieSBgdXRpbHMucHJlY29tcHV0ZSgpYCBhbmQgaXMgZXF1YWwgdG8gOC5cbiAgICAgICAgICogTnVtYmVyIG9mIHByZWNvbXB1dGVkIHBvaW50cyBkZXBlbmRzIG9uIHRoZSBjdXJ2ZSBzaXplOlxuICAgICAgICAgKiAyXijwnZGK4oiSMSkgKiAoTWF0aC5jZWlsKPCdkZsgLyDwnZGKKSArIDEpLCB3aGVyZTpcbiAgICAgICAgICogLSDwnZGKIGlzIHRoZSB3aW5kb3cgc2l6ZVxuICAgICAgICAgKiAtIPCdkZsgaXMgdGhlIGJpdGxlbmd0aCBvZiB0aGUgY3VydmUgb3JkZXIuXG4gICAgICAgICAqIEZvciBhIDI1Ni1iaXQgY3VydmUgYW5kIHdpbmRvdyBzaXplIDgsIHRoZSBudW1iZXIgb2YgcHJlY29tcHV0ZWQgcG9pbnRzIGlzIDEyOCAqIDMzID0gNDIyNC5cbiAgICAgICAgICogQHJldHVybnMgcHJlY29tcHV0ZWQgcG9pbnQgdGFibGVzIGZsYXR0ZW5lZCB0byBhIHNpbmdsZSBhcnJheVxuICAgICAgICAgKi9cbiAgICAgICAgcHJlY29tcHV0ZVdpbmRvdyhlbG0sIFcpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgd2luZG93cywgd2luZG93U2l6ZSB9ID0gb3B0cyhXKTtcbiAgICAgICAgICAgIGNvbnN0IHBvaW50cyA9IFtdO1xuICAgICAgICAgICAgbGV0IHAgPSBlbG07XG4gICAgICAgICAgICBsZXQgYmFzZSA9IHA7XG4gICAgICAgICAgICBmb3IgKGxldCB3aW5kb3cgPSAwOyB3aW5kb3cgPCB3aW5kb3dzOyB3aW5kb3crKykge1xuICAgICAgICAgICAgICAgIGJhc2UgPSBwO1xuICAgICAgICAgICAgICAgIHBvaW50cy5wdXNoKGJhc2UpO1xuICAgICAgICAgICAgICAgIC8vID0xLCBiZWNhdXNlIHdlIHNraXAgemVyb1xuICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgd2luZG93U2l6ZTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGJhc2UgPSBiYXNlLmFkZChwKTtcbiAgICAgICAgICAgICAgICAgICAgcG9pbnRzLnB1c2goYmFzZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHAgPSBiYXNlLmRvdWJsZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHBvaW50cztcbiAgICAgICAgfSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEltcGxlbWVudHMgZWMgbXVsdGlwbGljYXRpb24gdXNpbmcgcHJlY29tcHV0ZWQgdGFibGVzIGFuZCB3LWFyeSBub24tYWRqYWNlbnQgZm9ybS5cbiAgICAgICAgICogQHBhcmFtIFcgd2luZG93IHNpemVcbiAgICAgICAgICogQHBhcmFtIHByZWNvbXB1dGVzIHByZWNvbXB1dGVkIHRhYmxlc1xuICAgICAgICAgKiBAcGFyYW0gbiBzY2FsYXIgKHdlIGRvbid0IGNoZWNrIGhlcmUsIGJ1dCBzaG91bGQgYmUgbGVzcyB0aGFuIGN1cnZlIG9yZGVyKVxuICAgICAgICAgKiBAcmV0dXJucyByZWFsIGFuZCBmYWtlIChmb3IgY29uc3QtdGltZSkgcG9pbnRzXG4gICAgICAgICAqL1xuICAgICAgICB3TkFGKFcsIHByZWNvbXB1dGVzLCBuKSB7XG4gICAgICAgICAgICAvLyBUT0RPOiBtYXliZSBjaGVjayB0aGF0IHNjYWxhciBpcyBsZXNzIHRoYW4gZ3JvdXAgb3JkZXI/IHdOQUYgYmVoYXZpb3VzIGlzIHVuZGVmaW5lZCBvdGhlcndpc2VcbiAgICAgICAgICAgIC8vIEJ1dCBuZWVkIHRvIGNhcmVmdWxseSByZW1vdmUgb3RoZXIgY2hlY2tzIGJlZm9yZSB3TkFGLiBPUkRFUiA9PSBiaXRzIGhlcmVcbiAgICAgICAgICAgIGNvbnN0IHsgd2luZG93cywgd2luZG93U2l6ZSB9ID0gb3B0cyhXKTtcbiAgICAgICAgICAgIGxldCBwID0gYy5aRVJPO1xuICAgICAgICAgICAgbGV0IGYgPSBjLkJBU0U7XG4gICAgICAgICAgICBjb25zdCBtYXNrID0gQmlnSW50KDIgKiogVyAtIDEpOyAvLyBDcmVhdGUgbWFzayB3aXRoIFcgb25lczogMGIxMTExIGZvciBXPTQgZXRjLlxuICAgICAgICAgICAgY29uc3QgbWF4TnVtYmVyID0gMiAqKiBXO1xuICAgICAgICAgICAgY29uc3Qgc2hpZnRCeSA9IEJpZ0ludChXKTtcbiAgICAgICAgICAgIGZvciAobGV0IHdpbmRvdyA9IDA7IHdpbmRvdyA8IHdpbmRvd3M7IHdpbmRvdysrKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gd2luZG93ICogd2luZG93U2l6ZTtcbiAgICAgICAgICAgICAgICAvLyBFeHRyYWN0IFcgYml0cy5cbiAgICAgICAgICAgICAgICBsZXQgd2JpdHMgPSBOdW1iZXIobiAmIG1hc2spO1xuICAgICAgICAgICAgICAgIC8vIFNoaWZ0IG51bWJlciBieSBXIGJpdHMuXG4gICAgICAgICAgICAgICAgbiA+Pj0gc2hpZnRCeTtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgYml0cyBhcmUgYmlnZ2VyIHRoYW4gbWF4IHNpemUsIHdlJ2xsIHNwbGl0IHRob3NlLlxuICAgICAgICAgICAgICAgIC8vICsyMjQgPT4gMjU2IC0gMzJcbiAgICAgICAgICAgICAgICBpZiAod2JpdHMgPiB3aW5kb3dTaXplKSB7XG4gICAgICAgICAgICAgICAgICAgIHdiaXRzIC09IG1heE51bWJlcjtcbiAgICAgICAgICAgICAgICAgICAgbiArPSBfMW47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIFRoaXMgY29kZSB3YXMgZmlyc3Qgd3JpdHRlbiB3aXRoIGFzc3VtcHRpb24gdGhhdCAnZicgYW5kICdwJyB3aWxsIG5ldmVyIGJlIGluZmluaXR5IHBvaW50OlxuICAgICAgICAgICAgICAgIC8vIHNpbmNlIGVhY2ggYWRkaXRpb24gaXMgbXVsdGlwbGllZCBieSAyICoqIFcsIGl0IGNhbm5vdCBjYW5jZWwgZWFjaCBvdGhlci4gSG93ZXZlcixcbiAgICAgICAgICAgICAgICAvLyB0aGVyZSBpcyBuZWdhdGUgbm93OiBpdCBpcyBwb3NzaWJsZSB0aGF0IG5lZ2F0ZWQgZWxlbWVudCBmcm9tIGxvdyB2YWx1ZVxuICAgICAgICAgICAgICAgIC8vIHdvdWxkIGJlIHRoZSBzYW1lIGFzIGhpZ2ggZWxlbWVudCwgd2hpY2ggd2lsbCBjcmVhdGUgY2FycnkgaW50byBuZXh0IHdpbmRvdy5cbiAgICAgICAgICAgICAgICAvLyBJdCdzIG5vdCBvYnZpb3VzIGhvdyB0aGlzIGNhbiBmYWlsLCBidXQgc3RpbGwgd29ydGggaW52ZXN0aWdhdGluZyBsYXRlci5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB3ZSdyZSBvbnRvIFplcm8gcG9pbnQuXG4gICAgICAgICAgICAgICAgLy8gQWRkIHJhbmRvbSBwb2ludCBpbnNpZGUgY3VycmVudCB3aW5kb3cgdG8gZi5cbiAgICAgICAgICAgICAgICBjb25zdCBvZmZzZXQxID0gb2Zmc2V0O1xuICAgICAgICAgICAgICAgIGNvbnN0IG9mZnNldDIgPSBvZmZzZXQgKyBNYXRoLmFicyh3Yml0cykgLSAxOyAvLyAtMSBiZWNhdXNlIHdlIHNraXAgemVyb1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbmQxID0gd2luZG93ICUgMiAhPT0gMDtcbiAgICAgICAgICAgICAgICBjb25zdCBjb25kMiA9IHdiaXRzIDwgMDtcbiAgICAgICAgICAgICAgICBpZiAod2JpdHMgPT09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIG1vc3QgaW1wb3J0YW50IHBhcnQgZm9yIGNvbnN0LXRpbWUgZ2V0UHVibGljS2V5XG4gICAgICAgICAgICAgICAgICAgIGYgPSBmLmFkZChjb25zdFRpbWVOZWdhdGUoY29uZDEsIHByZWNvbXB1dGVzW29mZnNldDFdKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwID0gcC5hZGQoY29uc3RUaW1lTmVnYXRlKGNvbmQyLCBwcmVjb21wdXRlc1tvZmZzZXQyXSkpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIEpJVC1jb21waWxlciBzaG91bGQgbm90IGVsaW1pbmF0ZSBmIGhlcmUsIHNpbmNlIGl0IHdpbGwgbGF0ZXIgYmUgdXNlZCBpbiBub3JtYWxpemVaKClcbiAgICAgICAgICAgIC8vIEV2ZW4gaWYgdGhlIHZhcmlhYmxlIGlzIHN0aWxsIHVudXNlZCwgdGhlcmUgYXJlIHNvbWUgY2hlY2tzIHdoaWNoIHdpbGxcbiAgICAgICAgICAgIC8vIHRocm93IGFuIGV4Y2VwdGlvbiwgc28gY29tcGlsZXIgbmVlZHMgdG8gcHJvdmUgdGhleSB3b24ndCBoYXBwZW4sIHdoaWNoIGlzIGhhcmQuXG4gICAgICAgICAgICAvLyBBdCB0aGlzIHBvaW50IHRoZXJlIGlzIGEgd2F5IHRvIEYgYmUgaW5maW5pdHktcG9pbnQgZXZlbiBpZiBwIGlzIG5vdCxcbiAgICAgICAgICAgIC8vIHdoaWNoIG1ha2VzIGl0IGxlc3MgY29uc3QtdGltZTogYXJvdW5kIDEgYmlnaW50IG11bHRpcGx5LlxuICAgICAgICAgICAgcmV0dXJuIHsgcCwgZiB9O1xuICAgICAgICB9LFxuICAgICAgICB3TkFGQ2FjaGVkKFAsIHByZWNvbXB1dGVzTWFwLCBuLCB0cmFuc2Zvcm0pIHtcbiAgICAgICAgICAgIC8vIEB0cy1pZ25vcmVcbiAgICAgICAgICAgIGNvbnN0IFcgPSBQLl9XSU5ET1dfU0laRSB8fCAxO1xuICAgICAgICAgICAgLy8gQ2FsY3VsYXRlIHByZWNvbXB1dGVzIG9uIGEgZmlyc3QgcnVuLCByZXVzZSB0aGVtIGFmdGVyXG4gICAgICAgICAgICBsZXQgY29tcCA9IHByZWNvbXB1dGVzTWFwLmdldChQKTtcbiAgICAgICAgICAgIGlmICghY29tcCkge1xuICAgICAgICAgICAgICAgIGNvbXAgPSB0aGlzLnByZWNvbXB1dGVXaW5kb3coUCwgVyk7XG4gICAgICAgICAgICAgICAgaWYgKFcgIT09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgcHJlY29tcHV0ZXNNYXAuc2V0KFAsIHRyYW5zZm9ybShjb21wKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRoaXMud05BRihXLCBjb21wLCBuKTtcbiAgICAgICAgfSxcbiAgICB9O1xufVxuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlQmFzaWMoY3VydmUpIHtcbiAgICB2YWxpZGF0ZUZpZWxkKGN1cnZlLkZwKTtcbiAgICB2YWxpZGF0ZU9iamVjdChjdXJ2ZSwge1xuICAgICAgICBuOiAnYmlnaW50JyxcbiAgICAgICAgaDogJ2JpZ2ludCcsXG4gICAgICAgIEd4OiAnZmllbGQnLFxuICAgICAgICBHeTogJ2ZpZWxkJyxcbiAgICB9LCB7XG4gICAgICAgIG5CaXRMZW5ndGg6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICAgICAgbkJ5dGVMZW5ndGg6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICB9KTtcbiAgICAvLyBTZXQgZGVmYXVsdHNcbiAgICByZXR1cm4gT2JqZWN0LmZyZWV6ZSh7XG4gICAgICAgIC4uLm5MZW5ndGgoY3VydmUubiwgY3VydmUubkJpdExlbmd0aCksXG4gICAgICAgIC4uLmN1cnZlLFxuICAgICAgICAuLi57IHA6IGN1cnZlLkZwLk9SREVSIH0sXG4gICAgfSk7XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1jdXJ2ZS5qcy5tYXAiLCIvKiEgbm9ibGUtY3VydmVzIC0gTUlUIExpY2Vuc2UgKGMpIDIwMjIgUGF1bCBNaWxsZXIgKHBhdWxtaWxsci5jb20pICovXG4vLyBUd2lzdGVkIEVkd2FyZHMgY3VydmUuIFRoZSBmb3JtdWxhIGlzOiBheMKyICsgecKyID0gMSArIGR4wrJ5wrJcbmltcG9ydCB7IG1vZCB9IGZyb20gJy4vbW9kdWxhci5qcyc7XG5pbXBvcnQgKiBhcyB1dCBmcm9tICcuL3V0aWxzLmpzJztcbmltcG9ydCB7IGVuc3VyZUJ5dGVzIH0gZnJvbSAnLi91dGlscy5qcyc7XG5pbXBvcnQgeyB3TkFGLCB2YWxpZGF0ZUJhc2ljIH0gZnJvbSAnLi9jdXJ2ZS5qcyc7XG4vLyBCZSBmcmllbmRseSB0byBiYWQgRUNNQVNjcmlwdCBwYXJzZXJzIGJ5IG5vdCB1c2luZyBiaWdpbnQgbGl0ZXJhbHNcbi8vIHByZXR0aWVyLWlnbm9yZVxuY29uc3QgXzBuID0gQmlnSW50KDApLCBfMW4gPSBCaWdJbnQoMSksIF8ybiA9IEJpZ0ludCgyKSwgXzhuID0gQmlnSW50KDgpO1xuLy8gdmVyaWZpY2F0aW9uIHJ1bGUgaXMgZWl0aGVyIHppcDIxNSBvciByZmM4MDMyIC8gbmlzdDE4Ni01LiBDb25zdWx0IGZyb21IZXg6XG5jb25zdCBWRVJJRllfREVGQVVMVCA9IHsgemlwMjE1OiB0cnVlIH07XG5mdW5jdGlvbiB2YWxpZGF0ZU9wdHMoY3VydmUpIHtcbiAgICBjb25zdCBvcHRzID0gdmFsaWRhdGVCYXNpYyhjdXJ2ZSk7XG4gICAgdXQudmFsaWRhdGVPYmplY3QoY3VydmUsIHtcbiAgICAgICAgaGFzaDogJ2Z1bmN0aW9uJyxcbiAgICAgICAgYTogJ2JpZ2ludCcsXG4gICAgICAgIGQ6ICdiaWdpbnQnLFxuICAgICAgICByYW5kb21CeXRlczogJ2Z1bmN0aW9uJyxcbiAgICB9LCB7XG4gICAgICAgIGFkanVzdFNjYWxhckJ5dGVzOiAnZnVuY3Rpb24nLFxuICAgICAgICBkb21haW46ICdmdW5jdGlvbicsXG4gICAgICAgIHV2UmF0aW86ICdmdW5jdGlvbicsXG4gICAgICAgIG1hcFRvQ3VydmU6ICdmdW5jdGlvbicsXG4gICAgfSk7XG4gICAgLy8gU2V0IGRlZmF1bHRzXG4gICAgcmV0dXJuIE9iamVjdC5mcmVlemUoeyAuLi5vcHRzIH0pO1xufVxuLy8gSXQgaXMgbm90IGdlbmVyaWMgdHdpc3RlZCBjdXJ2ZSBmb3Igbm93LCBidXQgZWQyNTUxOS9lZDQ0OCBnZW5lcmljIGltcGxlbWVudGF0aW9uXG5leHBvcnQgZnVuY3Rpb24gdHdpc3RlZEVkd2FyZHMoY3VydmVEZWYpIHtcbiAgICBjb25zdCBDVVJWRSA9IHZhbGlkYXRlT3B0cyhjdXJ2ZURlZik7XG4gICAgY29uc3QgeyBGcCwgbjogQ1VSVkVfT1JERVIsIHByZWhhc2g6IHByZWhhc2gsIGhhc2g6IGNIYXNoLCByYW5kb21CeXRlcywgbkJ5dGVMZW5ndGgsIGg6IGNvZmFjdG9yLCB9ID0gQ1VSVkU7XG4gICAgY29uc3QgTUFTSyA9IF8ybiAqKiBCaWdJbnQobkJ5dGVMZW5ndGggKiA4KTtcbiAgICBjb25zdCBtb2RQID0gRnAuY3JlYXRlOyAvLyBGdW5jdGlvbiBvdmVycmlkZXNcbiAgICAvLyBzcXJ0KHUvdilcbiAgICBjb25zdCB1dlJhdGlvID0gQ1VSVkUudXZSYXRpbyB8fFxuICAgICAgICAoKHUsIHYpID0+IHtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogdHJ1ZSwgdmFsdWU6IEZwLnNxcnQodSAqIEZwLmludih2KSkgfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogZmFsc2UsIHZhbHVlOiBfMG4gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgY29uc3QgYWRqdXN0U2NhbGFyQnl0ZXMgPSBDVVJWRS5hZGp1c3RTY2FsYXJCeXRlcyB8fCAoKGJ5dGVzKSA9PiBieXRlcyk7IC8vIE5PT1BcbiAgICBjb25zdCBkb21haW4gPSBDVVJWRS5kb21haW4gfHxcbiAgICAgICAgKChkYXRhLCBjdHgsIHBoZmxhZykgPT4ge1xuICAgICAgICAgICAgaWYgKGN0eC5sZW5ndGggfHwgcGhmbGFnKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignQ29udGV4dHMvcHJlLWhhc2ggYXJlIG5vdCBzdXBwb3J0ZWQnKTtcbiAgICAgICAgICAgIHJldHVybiBkYXRhO1xuICAgICAgICB9KTsgLy8gTk9PUFxuICAgIGNvbnN0IGluQmlnID0gKG4pID0+IHR5cGVvZiBuID09PSAnYmlnaW50JyAmJiBfMG4gPCBuOyAvLyBuIGluIFsxLi5dXG4gICAgY29uc3QgaW5SYW5nZSA9IChuLCBtYXgpID0+IGluQmlnKG4pICYmIGluQmlnKG1heCkgJiYgbiA8IG1heDsgLy8gbiBpbiBbMS4ubWF4LTFdXG4gICAgY29uc3QgaW4wTWFza1JhbmdlID0gKG4pID0+IG4gPT09IF8wbiB8fCBpblJhbmdlKG4sIE1BU0spOyAvLyBuIGluIFswLi5NQVNLLTFdXG4gICAgZnVuY3Rpb24gYXNzZXJ0SW5SYW5nZShuLCBtYXgpIHtcbiAgICAgICAgLy8gbiBpbiBbMS4ubWF4LTFdXG4gICAgICAgIGlmIChpblJhbmdlKG4sIG1heCkpXG4gICAgICAgICAgICByZXR1cm4gbjtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBFeHBlY3RlZCB2YWxpZCBzY2FsYXIgPCAke21heH0sIGdvdCAke3R5cGVvZiBufSAke259YCk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGFzc2VydEdFMChuKSB7XG4gICAgICAgIC8vIG4gaW4gWzAuLkNVUlZFX09SREVSLTFdXG4gICAgICAgIHJldHVybiBuID09PSBfMG4gPyBuIDogYXNzZXJ0SW5SYW5nZShuLCBDVVJWRV9PUkRFUik7IC8vIEdFID0gcHJpbWUgc3ViZ3JvdXAsIG5vdCBmdWxsIGdyb3VwXG4gICAgfVxuICAgIGNvbnN0IHBvaW50UHJlY29tcHV0ZXMgPSBuZXcgTWFwKCk7XG4gICAgZnVuY3Rpb24gaXNQb2ludChvdGhlcikge1xuICAgICAgICBpZiAoIShvdGhlciBpbnN0YW5jZW9mIFBvaW50KSlcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignRXh0ZW5kZWRQb2ludCBleHBlY3RlZCcpO1xuICAgIH1cbiAgICAvLyBFeHRlbmRlZCBQb2ludCB3b3JrcyBpbiBleHRlbmRlZCBjb29yZGluYXRlczogKHgsIHksIHosIHQpIOKIiyAoeD14L3osIHk9eS96LCB0PXh5KS5cbiAgICAvLyBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Ud2lzdGVkX0Vkd2FyZHNfY3VydmUjRXh0ZW5kZWRfY29vcmRpbmF0ZXNcbiAgICBjbGFzcyBQb2ludCB7XG4gICAgICAgIGNvbnN0cnVjdG9yKGV4LCBleSwgZXosIGV0KSB7XG4gICAgICAgICAgICB0aGlzLmV4ID0gZXg7XG4gICAgICAgICAgICB0aGlzLmV5ID0gZXk7XG4gICAgICAgICAgICB0aGlzLmV6ID0gZXo7XG4gICAgICAgICAgICB0aGlzLmV0ID0gZXQ7XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZShleCkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd4IHJlcXVpcmVkJyk7XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZShleSkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd5IHJlcXVpcmVkJyk7XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZShleikpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd6IHJlcXVpcmVkJyk7XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZShldCkpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0IHJlcXVpcmVkJyk7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0IHgoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b0FmZmluZSgpLng7XG4gICAgICAgIH1cbiAgICAgICAgZ2V0IHkoKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50b0FmZmluZSgpLnk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIGZyb21BZmZpbmUocCkge1xuICAgICAgICAgICAgaWYgKHAgaW5zdGFuY2VvZiBQb2ludClcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4dGVuZGVkIHBvaW50IG5vdCBhbGxvd2VkJyk7XG4gICAgICAgICAgICBjb25zdCB7IHgsIHkgfSA9IHAgfHwge307XG4gICAgICAgICAgICBpZiAoIWluME1hc2tSYW5nZSh4KSB8fCAhaW4wTWFza1JhbmdlKHkpKVxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignaW52YWxpZCBhZmZpbmUgcG9pbnQnKTtcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoeCwgeSwgXzFuLCBtb2RQKHggKiB5KSk7XG4gICAgICAgIH1cbiAgICAgICAgc3RhdGljIG5vcm1hbGl6ZVoocG9pbnRzKSB7XG4gICAgICAgICAgICBjb25zdCB0b0ludiA9IEZwLmludmVydEJhdGNoKHBvaW50cy5tYXAoKHApID0+IHAuZXopKTtcbiAgICAgICAgICAgIHJldHVybiBwb2ludHMubWFwKChwLCBpKSA9PiBwLnRvQWZmaW5lKHRvSW52W2ldKSkubWFwKFBvaW50LmZyb21BZmZpbmUpO1xuICAgICAgICB9XG4gICAgICAgIC8vIFwiUHJpdmF0ZSBtZXRob2RcIiwgZG9uJ3QgdXNlIGl0IGRpcmVjdGx5XG4gICAgICAgIF9zZXRXaW5kb3dTaXplKHdpbmRvd1NpemUpIHtcbiAgICAgICAgICAgIHRoaXMuX1dJTkRPV19TSVpFID0gd2luZG93U2l6ZTtcbiAgICAgICAgICAgIHBvaW50UHJlY29tcHV0ZXMuZGVsZXRlKHRoaXMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIE5vdCByZXF1aXJlZCBmb3IgZnJvbUhleCgpLCB3aGljaCBhbHdheXMgY3JlYXRlcyB2YWxpZCBwb2ludHMuXG4gICAgICAgIC8vIENvdWxkIGJlIHVzZWZ1bCBmb3IgZnJvbUFmZmluZSgpLlxuICAgICAgICBhc3NlcnRWYWxpZGl0eSgpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgYSwgZCB9ID0gQ1VSVkU7XG4gICAgICAgICAgICBpZiAodGhpcy5pczAoKSlcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JhZCBwb2ludDogWkVSTycpOyAvLyBUT0RPOiBvcHRpbWl6ZSwgd2l0aCB2YXJzIGJlbG93P1xuICAgICAgICAgICAgLy8gRXF1YXRpb24gaW4gYWZmaW5lIGNvb3JkaW5hdGVzOiBheMKyICsgecKyID0gMSArIGR4wrJ5wrJcbiAgICAgICAgICAgIC8vIEVxdWF0aW9uIGluIHByb2plY3RpdmUgY29vcmRpbmF0ZXMgKFgvWiwgWS9aLCBaKTogIChhWMKyICsgWcKyKVrCsiA9IFrigbQgKyBkWMKyWcKyXG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYLCBleTogWSwgZXo6IFosIGV0OiBUIH0gPSB0aGlzO1xuICAgICAgICAgICAgY29uc3QgWDIgPSBtb2RQKFggKiBYKTsgLy8gWMKyXG4gICAgICAgICAgICBjb25zdCBZMiA9IG1vZFAoWSAqIFkpOyAvLyBZwrJcbiAgICAgICAgICAgIGNvbnN0IFoyID0gbW9kUChaICogWik7IC8vIFrCslxuICAgICAgICAgICAgY29uc3QgWjQgPSBtb2RQKFoyICogWjIpOyAvLyBa4oG0XG4gICAgICAgICAgICBjb25zdCBhWDIgPSBtb2RQKFgyICogYSk7IC8vIGFYwrJcbiAgICAgICAgICAgIGNvbnN0IGxlZnQgPSBtb2RQKFoyICogbW9kUChhWDIgKyBZMikpOyAvLyAoYVjCsiArIFnCsilawrJcbiAgICAgICAgICAgIGNvbnN0IHJpZ2h0ID0gbW9kUChaNCArIG1vZFAoZCAqIG1vZFAoWDIgKiBZMikpKTsgLy8gWuKBtCArIGRYwrJZwrJcbiAgICAgICAgICAgIGlmIChsZWZ0ICE9PSByaWdodClcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2JhZCBwb2ludDogZXF1YXRpb24gbGVmdCAhPSByaWdodCAoMSknKTtcbiAgICAgICAgICAgIC8vIEluIEV4dGVuZGVkIGNvb3JkaW5hdGVzIHdlIGFsc28gaGF2ZSBULCB3aGljaCBpcyB4Knk9VC9aOiBjaGVjayBYKlkgPT0gWipUXG4gICAgICAgICAgICBjb25zdCBYWSA9IG1vZFAoWCAqIFkpO1xuICAgICAgICAgICAgY29uc3QgWlQgPSBtb2RQKFogKiBUKTtcbiAgICAgICAgICAgIGlmIChYWSAhPT0gWlQpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdiYWQgcG9pbnQ6IGVxdWF0aW9uIGxlZnQgIT0gcmlnaHQgKDIpJyk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ29tcGFyZSBvbmUgcG9pbnQgdG8gYW5vdGhlci5cbiAgICAgICAgZXF1YWxzKG90aGVyKSB7XG4gICAgICAgICAgICBpc1BvaW50KG90aGVyKTtcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IFgxLCBleTogWTEsIGV6OiBaMSB9ID0gdGhpcztcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IFgyLCBleTogWTIsIGV6OiBaMiB9ID0gb3RoZXI7XG4gICAgICAgICAgICBjb25zdCBYMVoyID0gbW9kUChYMSAqIFoyKTtcbiAgICAgICAgICAgIGNvbnN0IFgyWjEgPSBtb2RQKFgyICogWjEpO1xuICAgICAgICAgICAgY29uc3QgWTFaMiA9IG1vZFAoWTEgKiBaMik7XG4gICAgICAgICAgICBjb25zdCBZMloxID0gbW9kUChZMiAqIFoxKTtcbiAgICAgICAgICAgIHJldHVybiBYMVoyID09PSBYMloxICYmIFkxWjIgPT09IFkyWjE7XG4gICAgICAgIH1cbiAgICAgICAgaXMwKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuZXF1YWxzKFBvaW50LlpFUk8pO1xuICAgICAgICB9XG4gICAgICAgIG5lZ2F0ZSgpIHtcbiAgICAgICAgICAgIC8vIEZsaXBzIHBvaW50IHNpZ24gdG8gYSBuZWdhdGl2ZSBvbmUgKC14LCB5IGluIGFmZmluZSBjb29yZHMpXG4gICAgICAgICAgICByZXR1cm4gbmV3IFBvaW50KG1vZFAoLXRoaXMuZXgpLCB0aGlzLmV5LCB0aGlzLmV6LCBtb2RQKC10aGlzLmV0KSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gRmFzdCBhbGdvIGZvciBkb3VibGluZyBFeHRlbmRlZCBQb2ludC5cbiAgICAgICAgLy8gaHR0cHM6Ly9oeXBlcmVsbGlwdGljLm9yZy9FRkQvZzFwL2F1dG8tdHdpc3RlZC1leHRlbmRlZC5odG1sI2RvdWJsaW5nLWRibC0yMDA4LWh3Y2RcbiAgICAgICAgLy8gQ29zdDogNE0gKyA0UyArIDEqYSArIDZhZGQgKyAxKjIuXG4gICAgICAgIGRvdWJsZSgpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgYSB9ID0gQ1VSVkU7XG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYMSwgZXk6IFkxLCBlejogWjEgfSA9IHRoaXM7XG4gICAgICAgICAgICBjb25zdCBBID0gbW9kUChYMSAqIFgxKTsgLy8gQSA9IFgxMlxuICAgICAgICAgICAgY29uc3QgQiA9IG1vZFAoWTEgKiBZMSk7IC8vIEIgPSBZMTJcbiAgICAgICAgICAgIGNvbnN0IEMgPSBtb2RQKF8ybiAqIG1vZFAoWjEgKiBaMSkpOyAvLyBDID0gMipaMTJcbiAgICAgICAgICAgIGNvbnN0IEQgPSBtb2RQKGEgKiBBKTsgLy8gRCA9IGEqQVxuICAgICAgICAgICAgY29uc3QgeDF5MSA9IFgxICsgWTE7XG4gICAgICAgICAgICBjb25zdCBFID0gbW9kUChtb2RQKHgxeTEgKiB4MXkxKSAtIEEgLSBCKTsgLy8gRSA9IChYMStZMSkyLUEtQlxuICAgICAgICAgICAgY29uc3QgRyA9IEQgKyBCOyAvLyBHID0gRCtCXG4gICAgICAgICAgICBjb25zdCBGID0gRyAtIEM7IC8vIEYgPSBHLUNcbiAgICAgICAgICAgIGNvbnN0IEggPSBEIC0gQjsgLy8gSCA9IEQtQlxuICAgICAgICAgICAgY29uc3QgWDMgPSBtb2RQKEUgKiBGKTsgLy8gWDMgPSBFKkZcbiAgICAgICAgICAgIGNvbnN0IFkzID0gbW9kUChHICogSCk7IC8vIFkzID0gRypIXG4gICAgICAgICAgICBjb25zdCBUMyA9IG1vZFAoRSAqIEgpOyAvLyBUMyA9IEUqSFxuICAgICAgICAgICAgY29uc3QgWjMgPSBtb2RQKEYgKiBHKTsgLy8gWjMgPSBGKkdcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoWDMsIFkzLCBaMywgVDMpO1xuICAgICAgICB9XG4gICAgICAgIC8vIEZhc3QgYWxnbyBmb3IgYWRkaW5nIDIgRXh0ZW5kZWQgUG9pbnRzLlxuICAgICAgICAvLyBodHRwczovL2h5cGVyZWxsaXB0aWMub3JnL0VGRC9nMXAvYXV0by10d2lzdGVkLWV4dGVuZGVkLmh0bWwjYWRkaXRpb24tYWRkLTIwMDgtaHdjZFxuICAgICAgICAvLyBDb3N0OiA5TSArIDEqYSArIDEqZCArIDdhZGQuXG4gICAgICAgIGFkZChvdGhlcikge1xuICAgICAgICAgICAgaXNQb2ludChvdGhlcik7XG4gICAgICAgICAgICBjb25zdCB7IGEsIGQgfSA9IENVUlZFO1xuICAgICAgICAgICAgY29uc3QgeyBleDogWDEsIGV5OiBZMSwgZXo6IFoxLCBldDogVDEgfSA9IHRoaXM7XG4gICAgICAgICAgICBjb25zdCB7IGV4OiBYMiwgZXk6IFkyLCBlejogWjIsIGV0OiBUMiB9ID0gb3RoZXI7XG4gICAgICAgICAgICAvLyBGYXN0ZXIgYWxnbyBmb3IgYWRkaW5nIDIgRXh0ZW5kZWQgUG9pbnRzIHdoZW4gY3VydmUncyBhPS0xLlxuICAgICAgICAgICAgLy8gaHR0cDovL2h5cGVyZWxsaXB0aWMub3JnL0VGRC9nMXAvYXV0by10d2lzdGVkLWV4dGVuZGVkLTEuaHRtbCNhZGRpdGlvbi1hZGQtMjAwOC1od2NkLTRcbiAgICAgICAgICAgIC8vIENvc3Q6IDhNICsgOGFkZCArIDIqMi5cbiAgICAgICAgICAgIC8vIE5vdGU6IEl0IGRvZXMgbm90IGNoZWNrIHdoZXRoZXIgdGhlIGBvdGhlcmAgcG9pbnQgaXMgdmFsaWQuXG4gICAgICAgICAgICBpZiAoYSA9PT0gQmlnSW50KC0xKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IEEgPSBtb2RQKChZMSAtIFgxKSAqIChZMiArIFgyKSk7XG4gICAgICAgICAgICAgICAgY29uc3QgQiA9IG1vZFAoKFkxICsgWDEpICogKFkyIC0gWDIpKTtcbiAgICAgICAgICAgICAgICBjb25zdCBGID0gbW9kUChCIC0gQSk7XG4gICAgICAgICAgICAgICAgaWYgKEYgPT09IF8wbilcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRoaXMuZG91YmxlKCk7IC8vIFNhbWUgcG9pbnQuIFRlc3RzIHNheSBpdCBkb2Vzbid0IGFmZmVjdCB0aW1pbmdcbiAgICAgICAgICAgICAgICBjb25zdCBDID0gbW9kUChaMSAqIF8ybiAqIFQyKTtcbiAgICAgICAgICAgICAgICBjb25zdCBEID0gbW9kUChUMSAqIF8ybiAqIFoyKTtcbiAgICAgICAgICAgICAgICBjb25zdCBFID0gRCArIEM7XG4gICAgICAgICAgICAgICAgY29uc3QgRyA9IEIgKyBBO1xuICAgICAgICAgICAgICAgIGNvbnN0IEggPSBEIC0gQztcbiAgICAgICAgICAgICAgICBjb25zdCBYMyA9IG1vZFAoRSAqIEYpO1xuICAgICAgICAgICAgICAgIGNvbnN0IFkzID0gbW9kUChHICogSCk7XG4gICAgICAgICAgICAgICAgY29uc3QgVDMgPSBtb2RQKEUgKiBIKTtcbiAgICAgICAgICAgICAgICBjb25zdCBaMyA9IG1vZFAoRiAqIEcpO1xuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoWDMsIFkzLCBaMywgVDMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgQSA9IG1vZFAoWDEgKiBYMik7IC8vIEEgPSBYMSpYMlxuICAgICAgICAgICAgY29uc3QgQiA9IG1vZFAoWTEgKiBZMik7IC8vIEIgPSBZMSpZMlxuICAgICAgICAgICAgY29uc3QgQyA9IG1vZFAoVDEgKiBkICogVDIpOyAvLyBDID0gVDEqZCpUMlxuICAgICAgICAgICAgY29uc3QgRCA9IG1vZFAoWjEgKiBaMik7IC8vIEQgPSBaMSpaMlxuICAgICAgICAgICAgY29uc3QgRSA9IG1vZFAoKFgxICsgWTEpICogKFgyICsgWTIpIC0gQSAtIEIpOyAvLyBFID0gKFgxK1kxKSooWDIrWTIpLUEtQlxuICAgICAgICAgICAgY29uc3QgRiA9IEQgLSBDOyAvLyBGID0gRC1DXG4gICAgICAgICAgICBjb25zdCBHID0gRCArIEM7IC8vIEcgPSBEK0NcbiAgICAgICAgICAgIGNvbnN0IEggPSBtb2RQKEIgLSBhICogQSk7IC8vIEggPSBCLWEqQVxuICAgICAgICAgICAgY29uc3QgWDMgPSBtb2RQKEUgKiBGKTsgLy8gWDMgPSBFKkZcbiAgICAgICAgICAgIGNvbnN0IFkzID0gbW9kUChHICogSCk7IC8vIFkzID0gRypIXG4gICAgICAgICAgICBjb25zdCBUMyA9IG1vZFAoRSAqIEgpOyAvLyBUMyA9IEUqSFxuICAgICAgICAgICAgY29uc3QgWjMgPSBtb2RQKEYgKiBHKTsgLy8gWjMgPSBGKkdcbiAgICAgICAgICAgIHJldHVybiBuZXcgUG9pbnQoWDMsIFkzLCBaMywgVDMpO1xuICAgICAgICB9XG4gICAgICAgIHN1YnRyYWN0KG90aGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5hZGQob3RoZXIubmVnYXRlKCkpO1xuICAgICAgICB9XG4gICAgICAgIHdOQUYobikge1xuICAgICAgICAgICAgcmV0dXJuIHduYWYud05BRkNhY2hlZCh0aGlzLCBwb2ludFByZWNvbXB1dGVzLCBuLCBQb2ludC5ub3JtYWxpemVaKTtcbiAgICAgICAgfVxuICAgICAgICAvLyBDb25zdGFudC10aW1lIG11bHRpcGxpY2F0aW9uLlxuICAgICAgICBtdWx0aXBseShzY2FsYXIpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgcCwgZiB9ID0gdGhpcy53TkFGKGFzc2VydEluUmFuZ2Uoc2NhbGFyLCBDVVJWRV9PUkRFUikpO1xuICAgICAgICAgICAgcmV0dXJuIFBvaW50Lm5vcm1hbGl6ZVooW3AsIGZdKVswXTtcbiAgICAgICAgfVxuICAgICAgICAvLyBOb24tY29uc3RhbnQtdGltZSBtdWx0aXBsaWNhdGlvbi4gVXNlcyBkb3VibGUtYW5kLWFkZCBhbGdvcml0aG0uXG4gICAgICAgIC8vIEl0J3MgZmFzdGVyLCBidXQgc2hvdWxkIG9ubHkgYmUgdXNlZCB3aGVuIHlvdSBkb24ndCBjYXJlIGFib3V0XG4gICAgICAgIC8vIGFuIGV4cG9zZWQgcHJpdmF0ZSBrZXkgZS5nLiBzaWcgdmVyaWZpY2F0aW9uLlxuICAgICAgICAvLyBEb2VzIE5PVCBhbGxvdyBzY2FsYXJzIGhpZ2hlciB0aGFuIENVUlZFLm4uXG4gICAgICAgIG11bHRpcGx5VW5zYWZlKHNjYWxhcikge1xuICAgICAgICAgICAgbGV0IG4gPSBhc3NlcnRHRTAoc2NhbGFyKTsgLy8gMCA8PSBzY2FsYXIgPCBDVVJWRS5uXG4gICAgICAgICAgICBpZiAobiA9PT0gXzBuKVxuICAgICAgICAgICAgICAgIHJldHVybiBJO1xuICAgICAgICAgICAgaWYgKHRoaXMuZXF1YWxzKEkpIHx8IG4gPT09IF8xbilcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIGlmICh0aGlzLmVxdWFscyhHKSlcbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcy53TkFGKG4pLnA7XG4gICAgICAgICAgICByZXR1cm4gd25hZi51bnNhZmVMYWRkZXIodGhpcywgbik7XG4gICAgICAgIH1cbiAgICAgICAgLy8gQ2hlY2tzIGlmIHBvaW50IGlzIG9mIHNtYWxsIG9yZGVyLlxuICAgICAgICAvLyBJZiB5b3UgYWRkIHNvbWV0aGluZyB0byBzbWFsbCBvcmRlciBwb2ludCwgeW91IHdpbGwgaGF2ZSBcImRpcnR5XCJcbiAgICAgICAgLy8gcG9pbnQgd2l0aCB0b3JzaW9uIGNvbXBvbmVudC5cbiAgICAgICAgLy8gTXVsdGlwbGllcyBwb2ludCBieSBjb2ZhY3RvciBhbmQgY2hlY2tzIGlmIHRoZSByZXN1bHQgaXMgMC5cbiAgICAgICAgaXNTbWFsbE9yZGVyKCkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubXVsdGlwbHlVbnNhZmUoY29mYWN0b3IpLmlzMCgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIE11bHRpcGxpZXMgcG9pbnQgYnkgY3VydmUgb3JkZXIgYW5kIGNoZWNrcyBpZiB0aGUgcmVzdWx0IGlzIDAuXG4gICAgICAgIC8vIFJldHVybnMgYGZhbHNlYCBpcyB0aGUgcG9pbnQgaXMgZGlydHkuXG4gICAgICAgIGlzVG9yc2lvbkZyZWUoKSB7XG4gICAgICAgICAgICByZXR1cm4gd25hZi51bnNhZmVMYWRkZXIodGhpcywgQ1VSVkVfT1JERVIpLmlzMCgpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENvbnZlcnRzIEV4dGVuZGVkIHBvaW50IHRvIGRlZmF1bHQgKHgsIHkpIGNvb3JkaW5hdGVzLlxuICAgICAgICAvLyBDYW4gYWNjZXB0IHByZWNvbXB1dGVkIFpeLTEgLSBmb3IgZXhhbXBsZSwgZnJvbSBpbnZlcnRCYXRjaC5cbiAgICAgICAgdG9BZmZpbmUoaXopIHtcbiAgICAgICAgICAgIGNvbnN0IHsgZXg6IHgsIGV5OiB5LCBlejogeiB9ID0gdGhpcztcbiAgICAgICAgICAgIGNvbnN0IGlzMCA9IHRoaXMuaXMwKCk7XG4gICAgICAgICAgICBpZiAoaXogPT0gbnVsbClcbiAgICAgICAgICAgICAgICBpeiA9IGlzMCA/IF84biA6IEZwLmludih6KTsgLy8gOCB3YXMgY2hvc2VuIGFyYml0cmFyaWx5XG4gICAgICAgICAgICBjb25zdCBheCA9IG1vZFAoeCAqIGl6KTtcbiAgICAgICAgICAgIGNvbnN0IGF5ID0gbW9kUCh5ICogaXopO1xuICAgICAgICAgICAgY29uc3QgenogPSBtb2RQKHogKiBpeik7XG4gICAgICAgICAgICBpZiAoaXMwKVxuICAgICAgICAgICAgICAgIHJldHVybiB7IHg6IF8wbiwgeTogXzFuIH07XG4gICAgICAgICAgICBpZiAoenogIT09IF8xbilcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2ludlogd2FzIGludmFsaWQnKTtcbiAgICAgICAgICAgIHJldHVybiB7IHg6IGF4LCB5OiBheSB9O1xuICAgICAgICB9XG4gICAgICAgIGNsZWFyQ29mYWN0b3IoKSB7XG4gICAgICAgICAgICBjb25zdCB7IGg6IGNvZmFjdG9yIH0gPSBDVVJWRTtcbiAgICAgICAgICAgIGlmIChjb2ZhY3RvciA9PT0gXzFuKVxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMubXVsdGlwbHlVbnNhZmUoY29mYWN0b3IpO1xuICAgICAgICB9XG4gICAgICAgIC8vIENvbnZlcnRzIGhhc2ggc3RyaW5nIG9yIFVpbnQ4QXJyYXkgdG8gUG9pbnQuXG4gICAgICAgIC8vIFVzZXMgYWxnbyBmcm9tIFJGQzgwMzIgNS4xLjMuXG4gICAgICAgIHN0YXRpYyBmcm9tSGV4KGhleCwgemlwMjE1ID0gZmFsc2UpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgZCwgYSB9ID0gQ1VSVkU7XG4gICAgICAgICAgICBjb25zdCBsZW4gPSBGcC5CWVRFUztcbiAgICAgICAgICAgIGhleCA9IGVuc3VyZUJ5dGVzKCdwb2ludEhleCcsIGhleCwgbGVuKTsgLy8gY29weSBoZXggdG8gYSBuZXcgYXJyYXlcbiAgICAgICAgICAgIGNvbnN0IG5vcm1lZCA9IGhleC5zbGljZSgpOyAvLyBjb3B5IGFnYWluLCB3ZSdsbCBtYW5pcHVsYXRlIGl0XG4gICAgICAgICAgICBjb25zdCBsYXN0Qnl0ZSA9IGhleFtsZW4gLSAxXTsgLy8gc2VsZWN0IGxhc3QgYnl0ZVxuICAgICAgICAgICAgbm9ybWVkW2xlbiAtIDFdID0gbGFzdEJ5dGUgJiB+MHg4MDsgLy8gY2xlYXIgbGFzdCBiaXRcbiAgICAgICAgICAgIGNvbnN0IHkgPSB1dC5ieXRlc1RvTnVtYmVyTEUobm9ybWVkKTtcbiAgICAgICAgICAgIGlmICh5ID09PSBfMG4pIHtcbiAgICAgICAgICAgICAgICAvLyB5PTAgaXMgYWxsb3dlZFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gUkZDODAzMiBwcm9oaWJpdHMgPj0gcCwgYnV0IFpJUDIxNSBkb2Vzbid0XG4gICAgICAgICAgICAgICAgaWYgKHppcDIxNSlcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0SW5SYW5nZSh5LCBNQVNLKTsgLy8gemlwMjE1PXRydWUgWzEuLlAtMV0gKDJeMjU1LTE5LTEgZm9yIGVkMjU1MTkpXG4gICAgICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgICAgICBhc3NlcnRJblJhbmdlKHksIEZwLk9SREVSKTsgLy8gemlwMjE1PWZhbHNlIFsxLi5NQVNLLTFdICgyXjI1Ni0xIGZvciBlZDI1NTE5KVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gRWQyNTUxOTogeMKyID0gKHnCsi0xKS8oZHnCsisxKSBtb2QgcC4gRWQ0NDg6IHjCsiA9ICh5wrItMSkvKGR5wrItMSkgbW9kIHAuIEdlbmVyaWMgY2FzZTpcbiAgICAgICAgICAgIC8vIGF4wrIrecKyPTErZHjCsnnCsiA9PiB5wrItMT1keMKyecKyLWF4wrIgPT4gecKyLTE9eMKyKGR5wrItYSkgPT4geMKyPSh5wrItMSkvKGR5wrItYSlcbiAgICAgICAgICAgIGNvbnN0IHkyID0gbW9kUCh5ICogeSk7IC8vIGRlbm9taW5hdG9yIGlzIGFsd2F5cyBub24tMCBtb2QgcC5cbiAgICAgICAgICAgIGNvbnN0IHUgPSBtb2RQKHkyIC0gXzFuKTsgLy8gdSA9IHnCsiAtIDFcbiAgICAgICAgICAgIGNvbnN0IHYgPSBtb2RQKGQgKiB5MiAtIGEpOyAvLyB2ID0gZCB5wrIgKyAxLlxuICAgICAgICAgICAgbGV0IHsgaXNWYWxpZCwgdmFsdWU6IHggfSA9IHV2UmF0aW8odSwgdik7IC8vIOKImih1L3YpXG4gICAgICAgICAgICBpZiAoIWlzVmFsaWQpXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdQb2ludC5mcm9tSGV4OiBpbnZhbGlkIHkgY29vcmRpbmF0ZScpO1xuICAgICAgICAgICAgY29uc3QgaXNYT2RkID0gKHggJiBfMW4pID09PSBfMW47IC8vIFRoZXJlIGFyZSAyIHNxdWFyZSByb290cy4gVXNlIHhfMCBiaXQgdG8gc2VsZWN0IHByb3BlclxuICAgICAgICAgICAgY29uc3QgaXNMYXN0Qnl0ZU9kZCA9IChsYXN0Qnl0ZSAmIDB4ODApICE9PSAwOyAvLyBpZiB4PTAgYW5kIHhfMCA9IDEsIGZhaWxcbiAgICAgICAgICAgIGlmIChpc0xhc3RCeXRlT2RkICE9PSBpc1hPZGQpXG4gICAgICAgICAgICAgICAgeCA9IG1vZFAoLXgpOyAvLyBpZiB4XzAgIT0geCBtb2QgMiwgc2V0IHggPSBwLXhcbiAgICAgICAgICAgIHJldHVybiBQb2ludC5mcm9tQWZmaW5lKHsgeCwgeSB9KTtcbiAgICAgICAgfVxuICAgICAgICBzdGF0aWMgZnJvbVByaXZhdGVLZXkocHJpdktleSkge1xuICAgICAgICAgICAgcmV0dXJuIGdldEV4dGVuZGVkUHVibGljS2V5KHByaXZLZXkpLnBvaW50O1xuICAgICAgICB9XG4gICAgICAgIHRvUmF3Qnl0ZXMoKSB7XG4gICAgICAgICAgICBjb25zdCB7IHgsIHkgfSA9IHRoaXMudG9BZmZpbmUoKTtcbiAgICAgICAgICAgIGNvbnN0IGJ5dGVzID0gdXQubnVtYmVyVG9CeXRlc0xFKHksIEZwLkJZVEVTKTsgLy8gZWFjaCB5IGhhcyAyIHggdmFsdWVzICh4LCAteSlcbiAgICAgICAgICAgIGJ5dGVzW2J5dGVzLmxlbmd0aCAtIDFdIHw9IHggJiBfMW4gPyAweDgwIDogMDsgLy8gd2hlbiBjb21wcmVzc2luZywgaXQncyBlbm91Z2ggdG8gc3RvcmUgeVxuICAgICAgICAgICAgcmV0dXJuIGJ5dGVzOyAvLyBhbmQgdXNlIHRoZSBsYXN0IGJ5dGUgdG8gZW5jb2RlIHNpZ24gb2YgeFxuICAgICAgICB9XG4gICAgICAgIHRvSGV4KCkge1xuICAgICAgICAgICAgcmV0dXJuIHV0LmJ5dGVzVG9IZXgodGhpcy50b1Jhd0J5dGVzKCkpOyAvLyBTYW1lIGFzIHRvUmF3Qnl0ZXMsIGJ1dCByZXR1cm5zIHN0cmluZy5cbiAgICAgICAgfVxuICAgIH1cbiAgICBQb2ludC5CQVNFID0gbmV3IFBvaW50KENVUlZFLkd4LCBDVVJWRS5HeSwgXzFuLCBtb2RQKENVUlZFLkd4ICogQ1VSVkUuR3kpKTtcbiAgICBQb2ludC5aRVJPID0gbmV3IFBvaW50KF8wbiwgXzFuLCBfMW4sIF8wbik7IC8vIDAsIDEsIDEsIDBcbiAgICBjb25zdCB7IEJBU0U6IEcsIFpFUk86IEkgfSA9IFBvaW50O1xuICAgIGNvbnN0IHduYWYgPSB3TkFGKFBvaW50LCBuQnl0ZUxlbmd0aCAqIDgpO1xuICAgIGZ1bmN0aW9uIG1vZE4oYSkge1xuICAgICAgICByZXR1cm4gbW9kKGEsIENVUlZFX09SREVSKTtcbiAgICB9XG4gICAgLy8gTGl0dGxlLWVuZGlhbiBTSEE1MTIgd2l0aCBtb2R1bG8gblxuICAgIGZ1bmN0aW9uIG1vZE5fTEUoaGFzaCkge1xuICAgICAgICByZXR1cm4gbW9kTih1dC5ieXRlc1RvTnVtYmVyTEUoaGFzaCkpO1xuICAgIH1cbiAgICAvKiogQ29udmVuaWVuY2UgbWV0aG9kIHRoYXQgY3JlYXRlcyBwdWJsaWMga2V5IGFuZCBvdGhlciBzdHVmZi4gUkZDODAzMiA1LjEuNSAqL1xuICAgIGZ1bmN0aW9uIGdldEV4dGVuZGVkUHVibGljS2V5KGtleSkge1xuICAgICAgICBjb25zdCBsZW4gPSBuQnl0ZUxlbmd0aDtcbiAgICAgICAga2V5ID0gZW5zdXJlQnl0ZXMoJ3ByaXZhdGUga2V5Jywga2V5LCBsZW4pO1xuICAgICAgICAvLyBIYXNoIHByaXZhdGUga2V5IHdpdGggY3VydmUncyBoYXNoIGZ1bmN0aW9uIHRvIHByb2R1Y2UgdW5pZm9ybWluZ2x5IHJhbmRvbSBpbnB1dFxuICAgICAgICAvLyBDaGVjayBieXRlIGxlbmd0aHM6IGVuc3VyZSg2NCwgaChlbnN1cmUoMzIsIGtleSkpKVxuICAgICAgICBjb25zdCBoYXNoZWQgPSBlbnN1cmVCeXRlcygnaGFzaGVkIHByaXZhdGUga2V5JywgY0hhc2goa2V5KSwgMiAqIGxlbik7XG4gICAgICAgIGNvbnN0IGhlYWQgPSBhZGp1c3RTY2FsYXJCeXRlcyhoYXNoZWQuc2xpY2UoMCwgbGVuKSk7IC8vIGNsZWFyIGZpcnN0IGhhbGYgYml0cywgcHJvZHVjZSBGRVxuICAgICAgICBjb25zdCBwcmVmaXggPSBoYXNoZWQuc2xpY2UobGVuLCAyICogbGVuKTsgLy8gc2Vjb25kIGhhbGYgaXMgY2FsbGVkIGtleSBwcmVmaXggKDUuMS42KVxuICAgICAgICBjb25zdCBzY2FsYXIgPSBtb2ROX0xFKGhlYWQpOyAvLyBUaGUgYWN0dWFsIHByaXZhdGUgc2NhbGFyXG4gICAgICAgIGNvbnN0IHBvaW50ID0gRy5tdWx0aXBseShzY2FsYXIpOyAvLyBQb2ludCBvbiBFZHdhcmRzIGN1cnZlIGFrYSBwdWJsaWMga2V5XG4gICAgICAgIGNvbnN0IHBvaW50Qnl0ZXMgPSBwb2ludC50b1Jhd0J5dGVzKCk7IC8vIFVpbnQ4QXJyYXkgcmVwcmVzZW50YXRpb25cbiAgICAgICAgcmV0dXJuIHsgaGVhZCwgcHJlZml4LCBzY2FsYXIsIHBvaW50LCBwb2ludEJ5dGVzIH07XG4gICAgfVxuICAgIC8vIENhbGN1bGF0ZXMgRWREU0EgcHViIGtleS4gUkZDODAzMiA1LjEuNS4gUHJpdmtleSBpcyBoYXNoZWQuIFVzZSBmaXJzdCBoYWxmIHdpdGggMyBiaXRzIGNsZWFyZWRcbiAgICBmdW5jdGlvbiBnZXRQdWJsaWNLZXkocHJpdktleSkge1xuICAgICAgICByZXR1cm4gZ2V0RXh0ZW5kZWRQdWJsaWNLZXkocHJpdktleSkucG9pbnRCeXRlcztcbiAgICB9XG4gICAgLy8gaW50KCdMRScsIFNIQTUxMihkb20yKEYsIEMpIHx8IG1zZ3MpKSBtb2QgTlxuICAgIGZ1bmN0aW9uIGhhc2hEb21haW5Ub1NjYWxhcihjb250ZXh0ID0gbmV3IFVpbnQ4QXJyYXkoKSwgLi4ubXNncykge1xuICAgICAgICBjb25zdCBtc2cgPSB1dC5jb25jYXRCeXRlcyguLi5tc2dzKTtcbiAgICAgICAgcmV0dXJuIG1vZE5fTEUoY0hhc2goZG9tYWluKG1zZywgZW5zdXJlQnl0ZXMoJ2NvbnRleHQnLCBjb250ZXh0KSwgISFwcmVoYXNoKSkpO1xuICAgIH1cbiAgICAvKiogU2lnbnMgbWVzc2FnZSB3aXRoIHByaXZhdGVLZXkuIFJGQzgwMzIgNS4xLjYgKi9cbiAgICBmdW5jdGlvbiBzaWduKG1zZywgcHJpdktleSwgb3B0aW9ucyA9IHt9KSB7XG4gICAgICAgIG1zZyA9IGVuc3VyZUJ5dGVzKCdtZXNzYWdlJywgbXNnKTtcbiAgICAgICAgaWYgKHByZWhhc2gpXG4gICAgICAgICAgICBtc2cgPSBwcmVoYXNoKG1zZyk7IC8vIGZvciBlZDI1NTE5cGggZXRjLlxuICAgICAgICBjb25zdCB7IHByZWZpeCwgc2NhbGFyLCBwb2ludEJ5dGVzIH0gPSBnZXRFeHRlbmRlZFB1YmxpY0tleShwcml2S2V5KTtcbiAgICAgICAgY29uc3QgciA9IGhhc2hEb21haW5Ub1NjYWxhcihvcHRpb25zLmNvbnRleHQsIHByZWZpeCwgbXNnKTsgLy8gciA9IGRvbTIoRiwgQykgfHwgcHJlZml4IHx8IFBIKE0pXG4gICAgICAgIGNvbnN0IFIgPSBHLm11bHRpcGx5KHIpLnRvUmF3Qnl0ZXMoKTsgLy8gUiA9IHJHXG4gICAgICAgIGNvbnN0IGsgPSBoYXNoRG9tYWluVG9TY2FsYXIob3B0aW9ucy5jb250ZXh0LCBSLCBwb2ludEJ5dGVzLCBtc2cpOyAvLyBSIHx8IEEgfHwgUEgoTSlcbiAgICAgICAgY29uc3QgcyA9IG1vZE4ociArIGsgKiBzY2FsYXIpOyAvLyBTID0gKHIgKyBrICogcykgbW9kIExcbiAgICAgICAgYXNzZXJ0R0UwKHMpOyAvLyAwIDw9IHMgPCBsXG4gICAgICAgIGNvbnN0IHJlcyA9IHV0LmNvbmNhdEJ5dGVzKFIsIHV0Lm51bWJlclRvQnl0ZXNMRShzLCBGcC5CWVRFUykpO1xuICAgICAgICByZXR1cm4gZW5zdXJlQnl0ZXMoJ3Jlc3VsdCcsIHJlcywgbkJ5dGVMZW5ndGggKiAyKTsgLy8gNjQtYnl0ZSBzaWduYXR1cmVcbiAgICB9XG4gICAgY29uc3QgdmVyaWZ5T3B0cyA9IFZFUklGWV9ERUZBVUxUO1xuICAgIGZ1bmN0aW9uIHZlcmlmeShzaWcsIG1zZywgcHVibGljS2V5LCBvcHRpb25zID0gdmVyaWZ5T3B0cykge1xuICAgICAgICBjb25zdCB7IGNvbnRleHQsIHppcDIxNSB9ID0gb3B0aW9ucztcbiAgICAgICAgY29uc3QgbGVuID0gRnAuQllURVM7IC8vIFZlcmlmaWVzIEVkRFNBIHNpZ25hdHVyZSBhZ2FpbnN0IG1lc3NhZ2UgYW5kIHB1YmxpYyBrZXkuIFJGQzgwMzIgNS4xLjcuXG4gICAgICAgIHNpZyA9IGVuc3VyZUJ5dGVzKCdzaWduYXR1cmUnLCBzaWcsIDIgKiBsZW4pOyAvLyBBbiBleHRlbmRlZCBncm91cCBlcXVhdGlvbiBpcyBjaGVja2VkLlxuICAgICAgICBtc2cgPSBlbnN1cmVCeXRlcygnbWVzc2FnZScsIG1zZyk7XG4gICAgICAgIGlmIChwcmVoYXNoKVxuICAgICAgICAgICAgbXNnID0gcHJlaGFzaChtc2cpOyAvLyBmb3IgZWQyNTUxOXBoLCBldGNcbiAgICAgICAgY29uc3QgcyA9IHV0LmJ5dGVzVG9OdW1iZXJMRShzaWcuc2xpY2UobGVuLCAyICogbGVuKSk7XG4gICAgICAgIC8vIHppcDIxNTogdHJ1ZSBpcyBnb29kIGZvciBjb25zZW5zdXMtY3JpdGljYWwgYXBwcyBhbmQgYWxsb3dzIHBvaW50cyA8IDJeMjU2XG4gICAgICAgIC8vIHppcDIxNTogZmFsc2UgZm9sbG93cyBSRkM4MDMyIC8gTklTVDE4Ni01IGFuZCByZXN0cmljdHMgcG9pbnRzIHRvIENVUlZFLnBcbiAgICAgICAgbGV0IEEsIFIsIFNCO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgQSA9IFBvaW50LmZyb21IZXgocHVibGljS2V5LCB6aXAyMTUpO1xuICAgICAgICAgICAgUiA9IFBvaW50LmZyb21IZXgoc2lnLnNsaWNlKDAsIGxlbiksIHppcDIxNSk7XG4gICAgICAgICAgICBTQiA9IEcubXVsdGlwbHlVbnNhZmUocyk7IC8vIDAgPD0gcyA8IGwgaXMgZG9uZSBpbnNpZGVcbiAgICAgICAgfVxuICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBrID0gaGFzaERvbWFpblRvU2NhbGFyKGNvbnRleHQsIFIudG9SYXdCeXRlcygpLCBBLnRvUmF3Qnl0ZXMoKSwgbXNnKTtcbiAgICAgICAgY29uc3QgUmtBID0gUi5hZGQoQS5tdWx0aXBseVVuc2FmZShrKSk7XG4gICAgICAgIC8vIFs4XVtTXUIgPSBbOF1SICsgWzhdW2tdQSdcbiAgICAgICAgcmV0dXJuIFJrQS5zdWJ0cmFjdChTQikuY2xlYXJDb2ZhY3RvcigpLmVxdWFscyhQb2ludC5aRVJPKTtcbiAgICB9XG4gICAgRy5fc2V0V2luZG93U2l6ZSg4KTsgLy8gRW5hYmxlIHByZWNvbXB1dGVzLiBTbG93cyBkb3duIGZpcnN0IHB1YmxpY0tleSBjb21wdXRhdGlvbiBieSAyMG1zLlxuICAgIGNvbnN0IHV0aWxzID0ge1xuICAgICAgICBnZXRFeHRlbmRlZFB1YmxpY0tleSxcbiAgICAgICAgLy8gZWQyNTUxOSBwcml2YXRlIGtleXMgYXJlIHVuaWZvcm0gMzJiLiBObyBuZWVkIHRvIGNoZWNrIGZvciBtb2R1bG8gYmlhcywgbGlrZSBpbiBzZWNwMjU2azEuXG4gICAgICAgIHJhbmRvbVByaXZhdGVLZXk6ICgpID0+IHJhbmRvbUJ5dGVzKEZwLkJZVEVTKSxcbiAgICAgICAgLyoqXG4gICAgICAgICAqIFdlJ3JlIGRvaW5nIHNjYWxhciBtdWx0aXBsaWNhdGlvbiAodXNlZCBpbiBnZXRQdWJsaWNLZXkgZXRjKSB3aXRoIHByZWNvbXB1dGVkIEJBU0VfUE9JTlRcbiAgICAgICAgICogdmFsdWVzLiBUaGlzIHNsb3dzIGRvd24gZmlyc3QgZ2V0UHVibGljS2V5KCkgYnkgbWlsbGlzZWNvbmRzIChzZWUgU3BlZWQgc2VjdGlvbiksXG4gICAgICAgICAqIGJ1dCBhbGxvd3MgdG8gc3BlZWQtdXAgc3Vic2VxdWVudCBnZXRQdWJsaWNLZXkoKSBjYWxscyB1cCB0byAyMHguXG4gICAgICAgICAqIEBwYXJhbSB3aW5kb3dTaXplIDIsIDQsIDgsIDE2XG4gICAgICAgICAqL1xuICAgICAgICBwcmVjb21wdXRlKHdpbmRvd1NpemUgPSA4LCBwb2ludCA9IFBvaW50LkJBU0UpIHtcbiAgICAgICAgICAgIHBvaW50Ll9zZXRXaW5kb3dTaXplKHdpbmRvd1NpemUpO1xuICAgICAgICAgICAgcG9pbnQubXVsdGlwbHkoQmlnSW50KDMpKTtcbiAgICAgICAgICAgIHJldHVybiBwb2ludDtcbiAgICAgICAgfSxcbiAgICB9O1xuICAgIHJldHVybiB7XG4gICAgICAgIENVUlZFLFxuICAgICAgICBnZXRQdWJsaWNLZXksXG4gICAgICAgIHNpZ24sXG4gICAgICAgIHZlcmlmeSxcbiAgICAgICAgRXh0ZW5kZWRQb2ludDogUG9pbnQsXG4gICAgICAgIHV0aWxzLFxuICAgIH07XG59XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lZHdhcmRzLmpzLm1hcCIsIi8qISBub2JsZS1jdXJ2ZXMgLSBNSVQgTGljZW5zZSAoYykgMjAyMiBQYXVsIE1pbGxlciAocGF1bG1pbGxyLmNvbSkgKi9cbmltcG9ydCB7IG1vZCwgcG93IH0gZnJvbSAnLi9tb2R1bGFyLmpzJztcbmltcG9ydCB7IGJ5dGVzVG9OdW1iZXJMRSwgZW5zdXJlQnl0ZXMsIG51bWJlclRvQnl0ZXNMRSwgdmFsaWRhdGVPYmplY3QgfSBmcm9tICcuL3V0aWxzLmpzJztcbmNvbnN0IF8wbiA9IEJpZ0ludCgwKTtcbmNvbnN0IF8xbiA9IEJpZ0ludCgxKTtcbmZ1bmN0aW9uIHZhbGlkYXRlT3B0cyhjdXJ2ZSkge1xuICAgIHZhbGlkYXRlT2JqZWN0KGN1cnZlLCB7XG4gICAgICAgIGE6ICdiaWdpbnQnLFxuICAgIH0sIHtcbiAgICAgICAgbW9udGdvbWVyeUJpdHM6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICAgICAgbkJ5dGVMZW5ndGg6ICdpc1NhZmVJbnRlZ2VyJyxcbiAgICAgICAgYWRqdXN0U2NhbGFyQnl0ZXM6ICdmdW5jdGlvbicsXG4gICAgICAgIGRvbWFpbjogJ2Z1bmN0aW9uJyxcbiAgICAgICAgcG93UG1pbnVzMjogJ2Z1bmN0aW9uJyxcbiAgICAgICAgR3U6ICdiaWdpbnQnLFxuICAgIH0pO1xuICAgIC8vIFNldCBkZWZhdWx0c1xuICAgIHJldHVybiBPYmplY3QuZnJlZXplKHsgLi4uY3VydmUgfSk7XG59XG4vLyBOT1RFOiBub3QgcmVhbGx5IG1vbnRnb21lcnkgY3VydmUsIGp1c3QgYnVuY2ggb2YgdmVyeSBzcGVjaWZpYyBtZXRob2RzIGZvciBYMjU1MTkvWDQ0OCAoUkZDIDc3NDgsIGh0dHBzOi8vd3d3LnJmYy1lZGl0b3Iub3JnL3JmYy9yZmM3NzQ4KVxuLy8gVXNlcyBvbmx5IG9uZSBjb29yZGluYXRlIGluc3RlYWQgb2YgdHdvXG5leHBvcnQgZnVuY3Rpb24gbW9udGdvbWVyeShjdXJ2ZURlZikge1xuICAgIGNvbnN0IENVUlZFID0gdmFsaWRhdGVPcHRzKGN1cnZlRGVmKTtcbiAgICBjb25zdCB7IFAgfSA9IENVUlZFO1xuICAgIGNvbnN0IG1vZFAgPSAobikgPT4gbW9kKG4sIFApO1xuICAgIGNvbnN0IG1vbnRnb21lcnlCaXRzID0gQ1VSVkUubW9udGdvbWVyeUJpdHM7XG4gICAgY29uc3QgbW9udGdvbWVyeUJ5dGVzID0gTWF0aC5jZWlsKG1vbnRnb21lcnlCaXRzIC8gOCk7XG4gICAgY29uc3QgZmllbGRMZW4gPSBDVVJWRS5uQnl0ZUxlbmd0aDtcbiAgICBjb25zdCBhZGp1c3RTY2FsYXJCeXRlcyA9IENVUlZFLmFkanVzdFNjYWxhckJ5dGVzIHx8ICgoYnl0ZXMpID0+IGJ5dGVzKTtcbiAgICBjb25zdCBwb3dQbWludXMyID0gQ1VSVkUucG93UG1pbnVzMiB8fCAoKHgpID0+IHBvdyh4LCBQIC0gQmlnSW50KDIpLCBQKSk7XG4gICAgLy8gY3N3YXAgZnJvbSBSRkM3NzQ4LiBCdXQgaXQgaXMgbm90IGZyb20gUkZDNzc0OCFcbiAgICAvKlxuICAgICAgY3N3YXAoc3dhcCwgeF8yLCB4XzMpOlxuICAgICAgICAgICBkdW1teSA9IG1hc2soc3dhcCkgQU5EICh4XzIgWE9SIHhfMylcbiAgICAgICAgICAgeF8yID0geF8yIFhPUiBkdW1teVxuICAgICAgICAgICB4XzMgPSB4XzMgWE9SIGR1bW15XG4gICAgICAgICAgIFJldHVybiAoeF8yLCB4XzMpXG4gICAgV2hlcmUgbWFzayhzd2FwKSBpcyB0aGUgYWxsLTEgb3IgYWxsLTAgd29yZCBvZiB0aGUgc2FtZSBsZW5ndGggYXMgeF8yXG4gICAgIGFuZCB4XzMsIGNvbXB1dGVkLCBlLmcuLCBhcyBtYXNrKHN3YXApID0gMCAtIHN3YXAuXG4gICAgKi9cbiAgICBmdW5jdGlvbiBjc3dhcChzd2FwLCB4XzIsIHhfMykge1xuICAgICAgICBjb25zdCBkdW1teSA9IG1vZFAoc3dhcCAqICh4XzIgLSB4XzMpKTtcbiAgICAgICAgeF8yID0gbW9kUCh4XzIgLSBkdW1teSk7XG4gICAgICAgIHhfMyA9IG1vZFAoeF8zICsgZHVtbXkpO1xuICAgICAgICByZXR1cm4gW3hfMiwgeF8zXTtcbiAgICB9XG4gICAgLy8gQWNjZXB0cyAwIGFzIHdlbGxcbiAgICBmdW5jdGlvbiBhc3NlcnRGaWVsZEVsZW1lbnQobikge1xuICAgICAgICBpZiAodHlwZW9mIG4gPT09ICdiaWdpbnQnICYmIF8wbiA8PSBuICYmIG4gPCBQKVxuICAgICAgICAgICAgcmV0dXJuIG47XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignRXhwZWN0ZWQgdmFsaWQgc2NhbGFyIDAgPCBzY2FsYXIgPCBDVVJWRS5QJyk7XG4gICAgfVxuICAgIC8vIHgyNTUxOSBmcm9tIDRcbiAgICAvLyBUaGUgY29uc3RhbnQgYTI0IGlzICg0ODY2NjIgLSAyKSAvIDQgPSAxMjE2NjUgZm9yIGN1cnZlMjU1MTkvWDI1NTE5XG4gICAgY29uc3QgYTI0ID0gKENVUlZFLmEgLSBCaWdJbnQoMikpIC8gQmlnSW50KDQpO1xuICAgIC8qKlxuICAgICAqXG4gICAgICogQHBhcmFtIHBvaW50VSB1IGNvb3JkaW5hdGUgKHgpIG9uIE1vbnRnb21lcnkgQ3VydmUgMjU1MTlcbiAgICAgKiBAcGFyYW0gc2NhbGFyIGJ5IHdoaWNoIHRoZSBwb2ludCB3b3VsZCBiZSBtdWx0aXBsaWVkXG4gICAgICogQHJldHVybnMgbmV3IFBvaW50IG9uIE1vbnRnb21lcnkgY3VydmVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtb250Z29tZXJ5TGFkZGVyKHBvaW50VSwgc2NhbGFyKSB7XG4gICAgICAgIGNvbnN0IHUgPSBhc3NlcnRGaWVsZEVsZW1lbnQocG9pbnRVKTtcbiAgICAgICAgLy8gU2VjdGlvbiA1OiBJbXBsZW1lbnRhdGlvbnMgTVVTVCBhY2NlcHQgbm9uLWNhbm9uaWNhbCB2YWx1ZXMgYW5kIHByb2Nlc3MgdGhlbSBhc1xuICAgICAgICAvLyBpZiB0aGV5IGhhZCBiZWVuIHJlZHVjZWQgbW9kdWxvIHRoZSBmaWVsZCBwcmltZS5cbiAgICAgICAgY29uc3QgayA9IGFzc2VydEZpZWxkRWxlbWVudChzY2FsYXIpO1xuICAgICAgICBjb25zdCB4XzEgPSB1O1xuICAgICAgICBsZXQgeF8yID0gXzFuO1xuICAgICAgICBsZXQgel8yID0gXzBuO1xuICAgICAgICBsZXQgeF8zID0gdTtcbiAgICAgICAgbGV0IHpfMyA9IF8xbjtcbiAgICAgICAgbGV0IHN3YXAgPSBfMG47XG4gICAgICAgIGxldCBzdztcbiAgICAgICAgZm9yIChsZXQgdCA9IEJpZ0ludChtb250Z29tZXJ5Qml0cyAtIDEpOyB0ID49IF8wbjsgdC0tKSB7XG4gICAgICAgICAgICBjb25zdCBrX3QgPSAoayA+PiB0KSAmIF8xbjtcbiAgICAgICAgICAgIHN3YXAgXj0ga190O1xuICAgICAgICAgICAgc3cgPSBjc3dhcChzd2FwLCB4XzIsIHhfMyk7XG4gICAgICAgICAgICB4XzIgPSBzd1swXTtcbiAgICAgICAgICAgIHhfMyA9IHN3WzFdO1xuICAgICAgICAgICAgc3cgPSBjc3dhcChzd2FwLCB6XzIsIHpfMyk7XG4gICAgICAgICAgICB6XzIgPSBzd1swXTtcbiAgICAgICAgICAgIHpfMyA9IHN3WzFdO1xuICAgICAgICAgICAgc3dhcCA9IGtfdDtcbiAgICAgICAgICAgIGNvbnN0IEEgPSB4XzIgKyB6XzI7XG4gICAgICAgICAgICBjb25zdCBBQSA9IG1vZFAoQSAqIEEpO1xuICAgICAgICAgICAgY29uc3QgQiA9IHhfMiAtIHpfMjtcbiAgICAgICAgICAgIGNvbnN0IEJCID0gbW9kUChCICogQik7XG4gICAgICAgICAgICBjb25zdCBFID0gQUEgLSBCQjtcbiAgICAgICAgICAgIGNvbnN0IEMgPSB4XzMgKyB6XzM7XG4gICAgICAgICAgICBjb25zdCBEID0geF8zIC0gel8zO1xuICAgICAgICAgICAgY29uc3QgREEgPSBtb2RQKEQgKiBBKTtcbiAgICAgICAgICAgIGNvbnN0IENCID0gbW9kUChDICogQik7XG4gICAgICAgICAgICBjb25zdCBkYWNiID0gREEgKyBDQjtcbiAgICAgICAgICAgIGNvbnN0IGRhX2NiID0gREEgLSBDQjtcbiAgICAgICAgICAgIHhfMyA9IG1vZFAoZGFjYiAqIGRhY2IpO1xuICAgICAgICAgICAgel8zID0gbW9kUCh4XzEgKiBtb2RQKGRhX2NiICogZGFfY2IpKTtcbiAgICAgICAgICAgIHhfMiA9IG1vZFAoQUEgKiBCQik7XG4gICAgICAgICAgICB6XzIgPSBtb2RQKEUgKiAoQUEgKyBtb2RQKGEyNCAqIEUpKSk7XG4gICAgICAgIH1cbiAgICAgICAgLy8gKHhfMiwgeF8zKSA9IGNzd2FwKHN3YXAsIHhfMiwgeF8zKVxuICAgICAgICBzdyA9IGNzd2FwKHN3YXAsIHhfMiwgeF8zKTtcbiAgICAgICAgeF8yID0gc3dbMF07XG4gICAgICAgIHhfMyA9IHN3WzFdO1xuICAgICAgICAvLyAoel8yLCB6XzMpID0gY3N3YXAoc3dhcCwgel8yLCB6XzMpXG4gICAgICAgIHN3ID0gY3N3YXAoc3dhcCwgel8yLCB6XzMpO1xuICAgICAgICB6XzIgPSBzd1swXTtcbiAgICAgICAgel8zID0gc3dbMV07XG4gICAgICAgIC8vIHpfMl4ocCAtIDIpXG4gICAgICAgIGNvbnN0IHoyID0gcG93UG1pbnVzMih6XzIpO1xuICAgICAgICAvLyBSZXR1cm4geF8yICogKHpfMl4ocCAtIDIpKVxuICAgICAgICByZXR1cm4gbW9kUCh4XzIgKiB6Mik7XG4gICAgfVxuICAgIGZ1bmN0aW9uIGVuY29kZVVDb29yZGluYXRlKHUpIHtcbiAgICAgICAgcmV0dXJuIG51bWJlclRvQnl0ZXNMRShtb2RQKHUpLCBtb250Z29tZXJ5Qnl0ZXMpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkZWNvZGVVQ29vcmRpbmF0ZSh1RW5jKSB7XG4gICAgICAgIC8vIFNlY3Rpb24gNTogV2hlbiByZWNlaXZpbmcgc3VjaCBhbiBhcnJheSwgaW1wbGVtZW50YXRpb25zIG9mIFgyNTUxOVxuICAgICAgICAvLyBNVVNUIG1hc2sgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgYml0IGluIHRoZSBmaW5hbCBieXRlLlxuICAgICAgICAvLyBUaGlzIGlzIHZlcnkgdWdseSB3YXksIGJ1dCBpdCB3b3JrcyBiZWNhdXNlIGZpZWxkTGVuLTEgaXMgb3V0c2lkZSBvZiBib3VuZHMgZm9yIFg0NDgsIHNvIHRoaXMgYmVjb21lcyBOT09QXG4gICAgICAgIC8vIGZpZWxkTGVuIC0gc2NhbGFyeUJ5dGVzID0gMSBmb3IgWDQ0OCBhbmQgPSAwIGZvciBYMjU1MTlcbiAgICAgICAgY29uc3QgdSA9IGVuc3VyZUJ5dGVzKCd1IGNvb3JkaW5hdGUnLCB1RW5jLCBtb250Z29tZXJ5Qnl0ZXMpO1xuICAgICAgICAvLyB1W2ZpZWxkTGVuLTFdIGNyYXNoZXMgUXVpY2tKUyAoVHlwZUVycm9yOiBvdXQtb2YtYm91bmQgbnVtZXJpYyBpbmRleClcbiAgICAgICAgaWYgKGZpZWxkTGVuID09PSBtb250Z29tZXJ5Qnl0ZXMpXG4gICAgICAgICAgICB1W2ZpZWxkTGVuIC0gMV0gJj0gMTI3OyAvLyAwYjAxMTFfMTExMVxuICAgICAgICByZXR1cm4gYnl0ZXNUb051bWJlckxFKHUpO1xuICAgIH1cbiAgICBmdW5jdGlvbiBkZWNvZGVTY2FsYXIobikge1xuICAgICAgICBjb25zdCBieXRlcyA9IGVuc3VyZUJ5dGVzKCdzY2FsYXInLCBuKTtcbiAgICAgICAgaWYgKGJ5dGVzLmxlbmd0aCAhPT0gbW9udGdvbWVyeUJ5dGVzICYmIGJ5dGVzLmxlbmd0aCAhPT0gZmllbGRMZW4pXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEV4cGVjdGVkICR7bW9udGdvbWVyeUJ5dGVzfSBvciAke2ZpZWxkTGVufSBieXRlcywgZ290ICR7Ynl0ZXMubGVuZ3RofWApO1xuICAgICAgICByZXR1cm4gYnl0ZXNUb051bWJlckxFKGFkanVzdFNjYWxhckJ5dGVzKGJ5dGVzKSk7XG4gICAgfVxuICAgIGZ1bmN0aW9uIHNjYWxhck11bHQoc2NhbGFyLCB1KSB7XG4gICAgICAgIGNvbnN0IHBvaW50VSA9IGRlY29kZVVDb29yZGluYXRlKHUpO1xuICAgICAgICBjb25zdCBfc2NhbGFyID0gZGVjb2RlU2NhbGFyKHNjYWxhcik7XG4gICAgICAgIGNvbnN0IHB1ID0gbW9udGdvbWVyeUxhZGRlcihwb2ludFUsIF9zY2FsYXIpO1xuICAgICAgICAvLyBUaGUgcmVzdWx0IHdhcyBub3QgY29udHJpYnV0b3J5XG4gICAgICAgIC8vIGh0dHBzOi8vY3IueXAudG8vZWNkaC5odG1sI3ZhbGlkYXRlXG4gICAgICAgIGlmIChwdSA9PT0gXzBuKVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbnZhbGlkIHByaXZhdGUgb3IgcHVibGljIGtleSByZWNlaXZlZCcpO1xuICAgICAgICByZXR1cm4gZW5jb2RlVUNvb3JkaW5hdGUocHUpO1xuICAgIH1cbiAgICAvLyBDb21wdXRlcyBwdWJsaWMga2V5IGZyb20gcHJpdmF0ZS4gQnkgZG9pbmcgc2NhbGFyIG11bHRpcGxpY2F0aW9uIG9mIGJhc2UgcG9pbnQuXG4gICAgY29uc3QgR3VCeXRlcyA9IGVuY29kZVVDb29yZGluYXRlKENVUlZFLkd1KTtcbiAgICBmdW5jdGlvbiBzY2FsYXJNdWx0QmFzZShzY2FsYXIpIHtcbiAgICAgICAgcmV0dXJuIHNjYWxhck11bHQoc2NhbGFyLCBHdUJ5dGVzKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc2NhbGFyTXVsdCxcbiAgICAgICAgc2NhbGFyTXVsdEJhc2UsXG4gICAgICAgIGdldFNoYXJlZFNlY3JldDogKHByaXZhdGVLZXksIHB1YmxpY0tleSkgPT4gc2NhbGFyTXVsdChwcml2YXRlS2V5LCBwdWJsaWNLZXkpLFxuICAgICAgICBnZXRQdWJsaWNLZXk6IChwcml2YXRlS2V5KSA9PiBzY2FsYXJNdWx0QmFzZShwcml2YXRlS2V5KSxcbiAgICAgICAgdXRpbHM6IHsgcmFuZG9tUHJpdmF0ZUtleTogKCkgPT4gQ1VSVkUucmFuZG9tQnl0ZXMoQ1VSVkUubkJ5dGVMZW5ndGgpIH0sXG4gICAgICAgIEd1Qnl0ZXM6IEd1Qnl0ZXMsXG4gICAgfTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPW1vbnRnb21lcnkuanMubWFwIiwiaW1wb3J0IHsgbW9kIH0gZnJvbSAnLi9tb2R1bGFyLmpzJztcbmltcG9ydCB7IGJ5dGVzVG9OdW1iZXJCRSwgY29uY2F0Qnl0ZXMsIHV0ZjhUb0J5dGVzLCB2YWxpZGF0ZU9iamVjdCB9IGZyb20gJy4vdXRpbHMuanMnO1xuZnVuY3Rpb24gdmFsaWRhdGVEU1QoZHN0KSB7XG4gICAgaWYgKGRzdCBpbnN0YW5jZW9mIFVpbnQ4QXJyYXkpXG4gICAgICAgIHJldHVybiBkc3Q7XG4gICAgaWYgKHR5cGVvZiBkc3QgPT09ICdzdHJpbmcnKVxuICAgICAgICByZXR1cm4gdXRmOFRvQnl0ZXMoZHN0KTtcbiAgICB0aHJvdyBuZXcgRXJyb3IoJ0RTVCBtdXN0IGJlIFVpbnQ4QXJyYXkgb3Igc3RyaW5nJyk7XG59XG4vLyBPY3RldCBTdHJlYW0gdG8gSW50ZWdlci4gXCJzcGVjXCIgaW1wbGVtZW50YXRpb24gb2Ygb3MyaXAgaXMgMi41eCBzbG93ZXIgdnMgYnl0ZXNUb051bWJlckJFLlxuY29uc3Qgb3MyaXAgPSBieXRlc1RvTnVtYmVyQkU7XG4vLyBJbnRlZ2VyIHRvIE9jdGV0IFN0cmVhbSAobnVtYmVyVG9CeXRlc0JFKVxuZnVuY3Rpb24gaTJvc3AodmFsdWUsIGxlbmd0aCkge1xuICAgIGlmICh2YWx1ZSA8IDAgfHwgdmFsdWUgPj0gMSA8PCAoOCAqIGxlbmd0aCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBiYWQgSTJPU1AgY2FsbDogdmFsdWU9JHt2YWx1ZX0gbGVuZ3RoPSR7bGVuZ3RofWApO1xuICAgIH1cbiAgICBjb25zdCByZXMgPSBBcnJheS5mcm9tKHsgbGVuZ3RoIH0pLmZpbGwoMCk7XG4gICAgZm9yIChsZXQgaSA9IGxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XG4gICAgICAgIHJlc1tpXSA9IHZhbHVlICYgMHhmZjtcbiAgICAgICAgdmFsdWUgPj4+PSA4O1xuICAgIH1cbiAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkocmVzKTtcbn1cbmZ1bmN0aW9uIHN0cnhvcihhLCBiKSB7XG4gICAgY29uc3QgYXJyID0gbmV3IFVpbnQ4QXJyYXkoYS5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYS5sZW5ndGg7IGkrKykge1xuICAgICAgICBhcnJbaV0gPSBhW2ldIF4gYltpXTtcbiAgICB9XG4gICAgcmV0dXJuIGFycjtcbn1cbmZ1bmN0aW9uIGlzQnl0ZXMoaXRlbSkge1xuICAgIGlmICghKGl0ZW0gaW5zdGFuY2VvZiBVaW50OEFycmF5KSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdVaW50OEFycmF5IGV4cGVjdGVkJyk7XG59XG5mdW5jdGlvbiBpc051bShpdGVtKSB7XG4gICAgaWYgKCFOdW1iZXIuaXNTYWZlSW50ZWdlcihpdGVtKSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdudW1iZXIgZXhwZWN0ZWQnKTtcbn1cbi8vIFByb2R1Y2VzIGEgdW5pZm9ybWx5IHJhbmRvbSBieXRlIHN0cmluZyB1c2luZyBhIGNyeXB0b2dyYXBoaWMgaGFzaCBmdW5jdGlvbiBIIHRoYXQgb3V0cHV0cyBiIGJpdHNcbi8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvZHJhZnQtaXJ0Zi1jZnJnLWhhc2gtdG8tY3VydmUtMTEjc2VjdGlvbi01LjQuMVxuZXhwb3J0IGZ1bmN0aW9uIGV4cGFuZF9tZXNzYWdlX3htZChtc2csIERTVCwgbGVuSW5CeXRlcywgSCkge1xuICAgIGlzQnl0ZXMobXNnKTtcbiAgICBpc0J5dGVzKERTVCk7XG4gICAgaXNOdW0obGVuSW5CeXRlcyk7XG4gICAgLy8gaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9kcmFmdC1pcnRmLWNmcmctaGFzaC10by1jdXJ2ZS0xNiNzZWN0aW9uLTUuMy4zXG4gICAgaWYgKERTVC5sZW5ndGggPiAyNTUpXG4gICAgICAgIERTVCA9IEgoY29uY2F0Qnl0ZXModXRmOFRvQnl0ZXMoJ0gyQy1PVkVSU0laRS1EU1QtJyksIERTVCkpO1xuICAgIGNvbnN0IHsgb3V0cHV0TGVuOiBiX2luX2J5dGVzLCBibG9ja0xlbjogcl9pbl9ieXRlcyB9ID0gSDtcbiAgICBjb25zdCBlbGwgPSBNYXRoLmNlaWwobGVuSW5CeXRlcyAvIGJfaW5fYnl0ZXMpO1xuICAgIGlmIChlbGwgPiAyNTUpXG4gICAgICAgIHRocm93IG5ldyBFcnJvcignSW52YWxpZCB4bWQgbGVuZ3RoJyk7XG4gICAgY29uc3QgRFNUX3ByaW1lID0gY29uY2F0Qnl0ZXMoRFNULCBpMm9zcChEU1QubGVuZ3RoLCAxKSk7XG4gICAgY29uc3QgWl9wYWQgPSBpMm9zcCgwLCByX2luX2J5dGVzKTtcbiAgICBjb25zdCBsX2lfYl9zdHIgPSBpMm9zcChsZW5JbkJ5dGVzLCAyKTsgLy8gbGVuX2luX2J5dGVzX3N0clxuICAgIGNvbnN0IGIgPSBuZXcgQXJyYXkoZWxsKTtcbiAgICBjb25zdCBiXzAgPSBIKGNvbmNhdEJ5dGVzKFpfcGFkLCBtc2csIGxfaV9iX3N0ciwgaTJvc3AoMCwgMSksIERTVF9wcmltZSkpO1xuICAgIGJbMF0gPSBIKGNvbmNhdEJ5dGVzKGJfMCwgaTJvc3AoMSwgMSksIERTVF9wcmltZSkpO1xuICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IGVsbDsgaSsrKSB7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBbc3RyeG9yKGJfMCwgYltpIC0gMV0pLCBpMm9zcChpICsgMSwgMSksIERTVF9wcmltZV07XG4gICAgICAgIGJbaV0gPSBIKGNvbmNhdEJ5dGVzKC4uLmFyZ3MpKTtcbiAgICB9XG4gICAgY29uc3QgcHNldWRvX3JhbmRvbV9ieXRlcyA9IGNvbmNhdEJ5dGVzKC4uLmIpO1xuICAgIHJldHVybiBwc2V1ZG9fcmFuZG9tX2J5dGVzLnNsaWNlKDAsIGxlbkluQnl0ZXMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGV4cGFuZF9tZXNzYWdlX3hvZihtc2csIERTVCwgbGVuSW5CeXRlcywgaywgSCkge1xuICAgIGlzQnl0ZXMobXNnKTtcbiAgICBpc0J5dGVzKERTVCk7XG4gICAgaXNOdW0obGVuSW5CeXRlcyk7XG4gICAgLy8gaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9kcmFmdC1pcnRmLWNmcmctaGFzaC10by1jdXJ2ZS0xNiNzZWN0aW9uLTUuMy4zXG4gICAgLy8gRFNUID0gSCgnSDJDLU9WRVJTSVpFLURTVC0nIHx8IGFfdmVyeV9sb25nX0RTVCwgTWF0aC5jZWlsKChsZW5JbkJ5dGVzICogaykgLyA4KSk7XG4gICAgaWYgKERTVC5sZW5ndGggPiAyNTUpIHtcbiAgICAgICAgY29uc3QgZGtMZW4gPSBNYXRoLmNlaWwoKDIgKiBrKSAvIDgpO1xuICAgICAgICBEU1QgPSBILmNyZWF0ZSh7IGRrTGVuIH0pLnVwZGF0ZSh1dGY4VG9CeXRlcygnSDJDLU9WRVJTSVpFLURTVC0nKSkudXBkYXRlKERTVCkuZGlnZXN0KCk7XG4gICAgfVxuICAgIGlmIChsZW5JbkJ5dGVzID4gNjU1MzUgfHwgRFNULmxlbmd0aCA+IDI1NSlcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdleHBhbmRfbWVzc2FnZV94b2Y6IGludmFsaWQgbGVuSW5CeXRlcycpO1xuICAgIHJldHVybiAoSC5jcmVhdGUoeyBka0xlbjogbGVuSW5CeXRlcyB9KVxuICAgICAgICAudXBkYXRlKG1zZylcbiAgICAgICAgLnVwZGF0ZShpMm9zcChsZW5JbkJ5dGVzLCAyKSlcbiAgICAgICAgLy8gMi4gRFNUX3ByaW1lID0gRFNUIHx8IEkyT1NQKGxlbihEU1QpLCAxKVxuICAgICAgICAudXBkYXRlKERTVClcbiAgICAgICAgLnVwZGF0ZShpMm9zcChEU1QubGVuZ3RoLCAxKSlcbiAgICAgICAgLmRpZ2VzdCgpKTtcbn1cbi8qKlxuICogSGFzaGVzIGFyYml0cmFyeS1sZW5ndGggYnl0ZSBzdHJpbmdzIHRvIGEgbGlzdCBvZiBvbmUgb3IgbW9yZSBlbGVtZW50cyBvZiBhIGZpbml0ZSBmaWVsZCBGXG4gKiBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTExI3NlY3Rpb24tNS4zXG4gKiBAcGFyYW0gbXNnIGEgYnl0ZSBzdHJpbmcgY29udGFpbmluZyB0aGUgbWVzc2FnZSB0byBoYXNoXG4gKiBAcGFyYW0gY291bnQgdGhlIG51bWJlciBvZiBlbGVtZW50cyBvZiBGIHRvIG91dHB1dFxuICogQHBhcmFtIG9wdGlvbnMgYHtEU1Q6IHN0cmluZywgcDogYmlnaW50LCBtOiBudW1iZXIsIGs6IG51bWJlciwgZXhwYW5kOiAneG1kJyB8ICd4b2YnLCBoYXNoOiBIfWAsIHNlZSBhYm92ZVxuICogQHJldHVybnMgW3VfMCwgLi4uLCB1Xyhjb3VudCAtIDEpXSwgYSBsaXN0IG9mIGZpZWxkIGVsZW1lbnRzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gaGFzaF90b19maWVsZChtc2csIGNvdW50LCBvcHRpb25zKSB7XG4gICAgdmFsaWRhdGVPYmplY3Qob3B0aW9ucywge1xuICAgICAgICBEU1Q6ICdzdHJpbmcnLFxuICAgICAgICBwOiAnYmlnaW50JyxcbiAgICAgICAgbTogJ2lzU2FmZUludGVnZXInLFxuICAgICAgICBrOiAnaXNTYWZlSW50ZWdlcicsXG4gICAgICAgIGhhc2g6ICdoYXNoJyxcbiAgICB9KTtcbiAgICBjb25zdCB7IHAsIGssIG0sIGhhc2gsIGV4cGFuZCwgRFNUOiBfRFNUIH0gPSBvcHRpb25zO1xuICAgIGlzQnl0ZXMobXNnKTtcbiAgICBpc051bShjb3VudCk7XG4gICAgY29uc3QgRFNUID0gdmFsaWRhdGVEU1QoX0RTVCk7XG4gICAgY29uc3QgbG9nMnAgPSBwLnRvU3RyaW5nKDIpLmxlbmd0aDtcbiAgICBjb25zdCBMID0gTWF0aC5jZWlsKChsb2cycCArIGspIC8gOCk7IC8vIHNlY3Rpb24gNS4xIG9mIGlldGYgZHJhZnQgbGluayBhYm92ZVxuICAgIGNvbnN0IGxlbl9pbl9ieXRlcyA9IGNvdW50ICogbSAqIEw7XG4gICAgbGV0IHByYjsgLy8gcHNldWRvX3JhbmRvbV9ieXRlc1xuICAgIGlmIChleHBhbmQgPT09ICd4bWQnKSB7XG4gICAgICAgIHByYiA9IGV4cGFuZF9tZXNzYWdlX3htZChtc2csIERTVCwgbGVuX2luX2J5dGVzLCBoYXNoKTtcbiAgICB9XG4gICAgZWxzZSBpZiAoZXhwYW5kID09PSAneG9mJykge1xuICAgICAgICBwcmIgPSBleHBhbmRfbWVzc2FnZV94b2YobXNnLCBEU1QsIGxlbl9pbl9ieXRlcywgaywgaGFzaCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGV4cGFuZCA9PT0gJ19pbnRlcm5hbF9wYXNzJykge1xuICAgICAgICAvLyBmb3IgaW50ZXJuYWwgdGVzdHMgb25seVxuICAgICAgICBwcmIgPSBtc2c7XG4gICAgfVxuICAgIGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2V4cGFuZCBtdXN0IGJlIFwieG1kXCIgb3IgXCJ4b2ZcIicpO1xuICAgIH1cbiAgICBjb25zdCB1ID0gbmV3IEFycmF5KGNvdW50KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvdW50OyBpKyspIHtcbiAgICAgICAgY29uc3QgZSA9IG5ldyBBcnJheShtKTtcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBtOyBqKyspIHtcbiAgICAgICAgICAgIGNvbnN0IGVsbV9vZmZzZXQgPSBMICogKGogKyBpICogbSk7XG4gICAgICAgICAgICBjb25zdCB0diA9IHByYi5zdWJhcnJheShlbG1fb2Zmc2V0LCBlbG1fb2Zmc2V0ICsgTCk7XG4gICAgICAgICAgICBlW2pdID0gbW9kKG9zMmlwKHR2KSwgcCk7XG4gICAgICAgIH1cbiAgICAgICAgdVtpXSA9IGU7XG4gICAgfVxuICAgIHJldHVybiB1O1xufVxuZXhwb3J0IGZ1bmN0aW9uIGlzb2dlbnlNYXAoZmllbGQsIG1hcCkge1xuICAgIC8vIE1ha2Ugc2FtZSBvcmRlciBhcyBpbiBzcGVjXG4gICAgY29uc3QgQ09FRkYgPSBtYXAubWFwKChpKSA9PiBBcnJheS5mcm9tKGkpLnJldmVyc2UoKSk7XG4gICAgcmV0dXJuICh4LCB5KSA9PiB7XG4gICAgICAgIGNvbnN0IFt4TnVtLCB4RGVuLCB5TnVtLCB5RGVuXSA9IENPRUZGLm1hcCgodmFsKSA9PiB2YWwucmVkdWNlKChhY2MsIGkpID0+IGZpZWxkLmFkZChmaWVsZC5tdWwoYWNjLCB4KSwgaSkpKTtcbiAgICAgICAgeCA9IGZpZWxkLmRpdih4TnVtLCB4RGVuKTsgLy8geE51bSAvIHhEZW5cbiAgICAgICAgeSA9IGZpZWxkLm11bCh5LCBmaWVsZC5kaXYoeU51bSwgeURlbikpOyAvLyB5ICogKHlOdW0gLyB5RGV2KVxuICAgICAgICByZXR1cm4geyB4LCB5IH07XG4gICAgfTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVIYXNoZXIoUG9pbnQsIG1hcFRvQ3VydmUsIGRlZikge1xuICAgIGlmICh0eXBlb2YgbWFwVG9DdXJ2ZSAhPT0gJ2Z1bmN0aW9uJylcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdtYXBUb0N1cnZlKCkgbXVzdCBiZSBkZWZpbmVkJyk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLy8gRW5jb2RlcyBieXRlIHN0cmluZyB0byBlbGxpcHRpYyBjdXJ2ZVxuICAgICAgICAvLyBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTE2I3NlY3Rpb24tM1xuICAgICAgICBoYXNoVG9DdXJ2ZShtc2csIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IHUgPSBoYXNoX3RvX2ZpZWxkKG1zZywgMiwgeyAuLi5kZWYsIERTVDogZGVmLkRTVCwgLi4ub3B0aW9ucyB9KTtcbiAgICAgICAgICAgIGNvbnN0IHUwID0gUG9pbnQuZnJvbUFmZmluZShtYXBUb0N1cnZlKHVbMF0pKTtcbiAgICAgICAgICAgIGNvbnN0IHUxID0gUG9pbnQuZnJvbUFmZmluZShtYXBUb0N1cnZlKHVbMV0pKTtcbiAgICAgICAgICAgIGNvbnN0IFAgPSB1MC5hZGQodTEpLmNsZWFyQ29mYWN0b3IoKTtcbiAgICAgICAgICAgIFAuYXNzZXJ0VmFsaWRpdHkoKTtcbiAgICAgICAgICAgIHJldHVybiBQO1xuICAgICAgICB9LFxuICAgICAgICAvLyBodHRwczovL2RhdGF0cmFja2VyLmlldGYub3JnL2RvYy9odG1sL2RyYWZ0LWlydGYtY2ZyZy1oYXNoLXRvLWN1cnZlLTE2I3NlY3Rpb24tM1xuICAgICAgICBlbmNvZGVUb0N1cnZlKG1zZywgb3B0aW9ucykge1xuICAgICAgICAgICAgY29uc3QgdSA9IGhhc2hfdG9fZmllbGQobXNnLCAxLCB7IC4uLmRlZiwgRFNUOiBkZWYuZW5jb2RlRFNULCAuLi5vcHRpb25zIH0pO1xuICAgICAgICAgICAgY29uc3QgUCA9IFBvaW50LmZyb21BZmZpbmUobWFwVG9DdXJ2ZSh1WzBdKSkuY2xlYXJDb2ZhY3RvcigpO1xuICAgICAgICAgICAgUC5hc3NlcnRWYWxpZGl0eSgpO1xuICAgICAgICAgICAgcmV0dXJuIFA7XG4gICAgICAgIH0sXG4gICAgfTtcbn1cbi8vIyBzb3VyY2VNYXBwaW5nVVJMPWhhc2gtdG8tY3VydmUuanMubWFwIiwiLyohIG5vYmxlLWN1cnZlcyAtIE1JVCBMaWNlbnNlIChjKSAyMDIyIFBhdWwgTWlsbGVyIChwYXVsbWlsbHIuY29tKSAqL1xuaW1wb3J0IHsgc2hha2UyNTYgfSBmcm9tICdAbm9ibGUvaGFzaGVzL3NoYTMnO1xuaW1wb3J0IHsgY29uY2F0Qnl0ZXMsIHJhbmRvbUJ5dGVzLCB1dGY4VG9CeXRlcywgd3JhcENvbnN0cnVjdG9yIH0gZnJvbSAnQG5vYmxlL2hhc2hlcy91dGlscyc7XG5pbXBvcnQgeyB0d2lzdGVkRWR3YXJkcyB9IGZyb20gJy4vYWJzdHJhY3QvZWR3YXJkcy5qcyc7XG5pbXBvcnQgeyBtb2QsIHBvdzIsIEZpZWxkIH0gZnJvbSAnLi9hYnN0cmFjdC9tb2R1bGFyLmpzJztcbmltcG9ydCB7IG1vbnRnb21lcnkgfSBmcm9tICcuL2Fic3RyYWN0L21vbnRnb21lcnkuanMnO1xuaW1wb3J0ICogYXMgaHRmIGZyb20gJy4vYWJzdHJhY3QvaGFzaC10by1jdXJ2ZS5qcyc7XG4vKipcbiAqIEVkd2FyZHM0NDggKG5vdCBFZDQ0OC1Hb2xkaWxvY2tzKSBjdXJ2ZSB3aXRoIGZvbGxvd2luZyBhZGRvbnM6XG4gKiAqIFg0NDggRUNESFxuICogQ29uZm9ybXMgdG8gUkZDIDgwMzIgaHR0cHM6Ly93d3cucmZjLWVkaXRvci5vcmcvcmZjL3JmYzgwMzIuaHRtbCNzZWN0aW9uLTUuMlxuICovXG5jb25zdCBzaGFrZTI1Nl8xMTQgPSB3cmFwQ29uc3RydWN0b3IoKCkgPT4gc2hha2UyNTYuY3JlYXRlKHsgZGtMZW46IDExNCB9KSk7XG5jb25zdCBzaGFrZTI1Nl82NCA9IHdyYXBDb25zdHJ1Y3RvcigoKSA9PiBzaGFrZTI1Ni5jcmVhdGUoeyBka0xlbjogNjQgfSkpO1xuY29uc3QgZWQ0NDhQID0gQmlnSW50KCc3MjY4Mzg3MjQyOTU2MDY4OTA1NDkzMjM4MDc4ODgwMDQ1MzQzNTM2NDEzNjA2ODczMTgwNjAyODE0OTAxOTkxODA2MTIzMjgxNjY3MzA3NzI2ODYzOTYzODM2OTg2NzY1NDU5MzAwODg4ODQ0NjE4NDM2MzczNjEwNTM0OTgwMTgzNjU0MzknKTtcbi8vIHBvd1BtaW51czNkaXY0IGNhbGN1bGF0ZXMgeiA9IHheayBtb2QgcCwgd2hlcmUgayA9IChwLTMpLzQuXG4vLyBVc2VkIGZvciBlZmZpY2llbnQgc3F1YXJlIHJvb3QgY2FsY3VsYXRpb24uXG4vLyAoKFAtMykvNCkudG9TdHJpbmcoMikgd291bGQgcHJvZHVjZSBiaXRzIFsyMjN4IDEsIDAsIDIyMnggMV1cbmZ1bmN0aW9uIGVkNDQ4X3Bvd19QbWludXMzZGl2NCh4KSB7XG4gICAgY29uc3QgUCA9IGVkNDQ4UDtcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBjb25zdCBfMW4gPSBCaWdJbnQoMSksIF8ybiA9IEJpZ0ludCgyKSwgXzNuID0gQmlnSW50KDMpLCBfMTFuID0gQmlnSW50KDExKTtcbiAgICAvLyBwcmV0dGllci1pZ25vcmVcbiAgICBjb25zdCBfMjJuID0gQmlnSW50KDIyKSwgXzQ0biA9IEJpZ0ludCg0NCksIF84OG4gPSBCaWdJbnQoODgpLCBfMjIzbiA9IEJpZ0ludCgyMjMpO1xuICAgIGNvbnN0IGIyID0gKHggKiB4ICogeCkgJSBQO1xuICAgIGNvbnN0IGIzID0gKGIyICogYjIgKiB4KSAlIFA7XG4gICAgY29uc3QgYjYgPSAocG93MihiMywgXzNuLCBQKSAqIGIzKSAlIFA7XG4gICAgY29uc3QgYjkgPSAocG93MihiNiwgXzNuLCBQKSAqIGIzKSAlIFA7XG4gICAgY29uc3QgYjExID0gKHBvdzIoYjksIF8ybiwgUCkgKiBiMikgJSBQO1xuICAgIGNvbnN0IGIyMiA9IChwb3cyKGIxMSwgXzExbiwgUCkgKiBiMTEpICUgUDtcbiAgICBjb25zdCBiNDQgPSAocG93MihiMjIsIF8yMm4sIFApICogYjIyKSAlIFA7XG4gICAgY29uc3QgYjg4ID0gKHBvdzIoYjQ0LCBfNDRuLCBQKSAqIGI0NCkgJSBQO1xuICAgIGNvbnN0IGIxNzYgPSAocG93MihiODgsIF84OG4sIFApICogYjg4KSAlIFA7XG4gICAgY29uc3QgYjIyMCA9IChwb3cyKGIxNzYsIF80NG4sIFApICogYjQ0KSAlIFA7XG4gICAgY29uc3QgYjIyMiA9IChwb3cyKGIyMjAsIF8ybiwgUCkgKiBiMikgJSBQO1xuICAgIGNvbnN0IGIyMjMgPSAocG93MihiMjIyLCBfMW4sIFApICogeCkgJSBQO1xuICAgIHJldHVybiAocG93MihiMjIzLCBfMjIzbiwgUCkgKiBiMjIyKSAlIFA7XG59XG5mdW5jdGlvbiBhZGp1c3RTY2FsYXJCeXRlcyhieXRlcykge1xuICAgIC8vIFNlY3Rpb24gNTogTGlrZXdpc2UsIGZvciBYNDQ4LCBzZXQgdGhlIHR3byBsZWFzdCBzaWduaWZpY2FudCBiaXRzIG9mIHRoZSBmaXJzdCBieXRlIHRvIDAsIGFuZCB0aGUgbW9zdFxuICAgIC8vIHNpZ25pZmljYW50IGJpdCBvZiB0aGUgbGFzdCBieXRlIHRvIDEuXG4gICAgYnl0ZXNbMF0gJj0gMjUyOyAvLyAwYjExMTExMTAwXG4gICAgLy8gYW5kIHRoZSBtb3N0IHNpZ25pZmljYW50IGJpdCBvZiB0aGUgbGFzdCBieXRlIHRvIDEuXG4gICAgYnl0ZXNbNTVdIHw9IDEyODsgLy8gMGIxMDAwMDAwMFxuICAgIC8vIE5PVEU6IGlzIGlzIE5PT1AgZm9yIDU2IGJ5dGVzIHNjYWxhcnMgKFgyNTUxOS9YNDQ4KVxuICAgIGJ5dGVzWzU2XSA9IDA7IC8vIEJ5dGUgb3V0c2lkZSBvZiBncm91cCAoNDU2IGJ1dHMgdnMgNDQ4IGJpdHMpXG4gICAgcmV0dXJuIGJ5dGVzO1xufVxuY29uc3QgRnAgPSBGaWVsZChlZDQ0OFAsIDQ1NiwgdHJ1ZSk7XG5jb25zdCBfNG4gPSBCaWdJbnQoNCk7XG5jb25zdCBFRDQ0OF9ERUYgPSB7XG4gICAgLy8gUGFyYW06IGFcbiAgICBhOiBCaWdJbnQoMSksXG4gICAgLy8gLTM5MDgxLiBOZWdhdGl2ZSBudW1iZXIgaXMgUCAtIG51bWJlclxuICAgIGQ6IEJpZ0ludCgnNzI2ODM4NzI0Mjk1NjA2ODkwNTQ5MzIzODA3ODg4MDA0NTM0MzUzNjQxMzYwNjg3MzE4MDYwMjgxNDkwMTk5MTgwNjEyMzI4MTY2NzMwNzcyNjg2Mzk2MzgzNjk4Njc2NTQ1OTMwMDg4ODg0NDYxODQzNjM3MzYxMDUzNDk4MDE4MzI2MzU4JyksXG4gICAgLy8gRmluaXRlIGZpZWxkIPCdlL1wIG92ZXIgd2hpY2ggd2UnbGwgZG8gY2FsY3VsYXRpb25zOyAybiAqKiA0NDhuIC0gMm4gKiogMjI0biAtIDFuXG4gICAgRnAsXG4gICAgLy8gU3ViZ3JvdXAgb3JkZXI6IGhvdyBtYW55IHBvaW50cyBjdXJ2ZSBoYXM7XG4gICAgLy8gMm4qKjQ0Nm4gLSAxMzgxODA2NjgwOTg5NTExNTM1MjAwNzM4Njc0ODUxNTQyNjg4MDMzNjY5MjQ3NDg4MjE3ODYwOTg5NDU0NzUwMzg4NW5cbiAgICBuOiBCaWdJbnQoJzE4MTcwOTY4MTA3MzkwMTcyMjYzNzMzMDk1MTk3MjAwMTEzMzU4ODQxMDM0MDE3MTgyOTUxNTA3MDM3MjU0OTc5NTE0NjAwMzk2MTUzOTU4NTcxNjE5NTc1NTI5MTY5MjM3NTk2MzMxMDI5MzcwOTA5MTY2MjMwNDc3Mzc1NTg1OTY0OTc3OScpLFxuICAgIG5CaXRMZW5ndGg6IDQ1NixcbiAgICAvLyBDb2ZhY3RvclxuICAgIGg6IEJpZ0ludCg0KSxcbiAgICAvLyBCYXNlIHBvaW50ICh4LCB5KSBha2EgZ2VuZXJhdG9yIHBvaW50XG4gICAgR3g6IEJpZ0ludCgnMjI0NTgwMDQwMjk1OTI0MzAwMTg3NjA0MzM0MDk5ODk2MDM2MjQ2Nzg5NjQxNjMyNTY0MTM0MjQ2MTI1NDYxNjg2OTUwNDE1NDY3NDA2MDMyOTA5MDI5MTkyODY5MzU3OTUzMjgyNTc4MDMyMDc1MTQ2NDQ2MTczNjc0NjAyNjM1MjQ3NzEwJyksXG4gICAgR3k6IEJpZ0ludCgnMjk4ODE5MjEwMDc4NDgxNDkyNjc2MDE3OTMwNDQzOTMwNjczNDM3NTQ0MDQwMTU0MDgwMjQyMDk1OTI4MjQxMzcyMzMxNTA2MTg5ODM1ODc2MDAzNTM2ODc4NjU1NDE4Nzg0NzMzOTgyMzAzMjMzNTAzNDYyNTAwNTMxNTQ1MDYyODMyNjYwJyksXG4gICAgLy8gU0hBS0UyNTYoZG9tNChwaGZsYWcsY29udGV4dCl8fHgsIDExNClcbiAgICBoYXNoOiBzaGFrZTI1Nl8xMTQsXG4gICAgcmFuZG9tQnl0ZXMsXG4gICAgYWRqdXN0U2NhbGFyQnl0ZXMsXG4gICAgLy8gZG9tNFxuICAgIGRvbWFpbjogKGRhdGEsIGN0eCwgcGhmbGFnKSA9PiB7XG4gICAgICAgIGlmIChjdHgubGVuZ3RoID4gMjU1KVxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDb250ZXh0IGlzIHRvbyBiaWc6ICR7Y3R4Lmxlbmd0aH1gKTtcbiAgICAgICAgcmV0dXJuIGNvbmNhdEJ5dGVzKHV0ZjhUb0J5dGVzKCdTaWdFZDQ0OCcpLCBuZXcgVWludDhBcnJheShbcGhmbGFnID8gMSA6IDAsIGN0eC5sZW5ndGhdKSwgY3R4LCBkYXRhKTtcbiAgICB9LFxuICAgIC8vIENvbnN0YW50LXRpbWUgcmF0aW8gb2YgdSB0byB2LiBBbGxvd3MgdG8gY29tYmluZSBpbnZlcnNpb24gYW5kIHNxdWFyZSByb290IHUv4oiadi5cbiAgICAvLyBVc2VzIGFsZ28gZnJvbSBSRkM4MDMyIDUuMS4zLlxuICAgIHV2UmF0aW86ICh1LCB2KSA9PiB7XG4gICAgICAgIGNvbnN0IFAgPSBlZDQ0OFA7XG4gICAgICAgIC8vIGh0dHBzOi8vZGF0YXRyYWNrZXIuaWV0Zi5vcmcvZG9jL2h0bWwvcmZjODAzMiNzZWN0aW9uLTUuMi4zXG4gICAgICAgIC8vIFRvIGNvbXB1dGUgdGhlIHNxdWFyZSByb290IG9mICh1L3YpLCB0aGUgZmlyc3Qgc3RlcCBpcyB0byBjb21wdXRlIHRoZVxuICAgICAgICAvLyAgIGNhbmRpZGF0ZSByb290IHggPSAodS92KV4oKHArMSkvNCkuICBUaGlzIGNhbiBiZSBkb25lIHVzaW5nIHRoZVxuICAgICAgICAvLyBmb2xsb3dpbmcgdHJpY2ssIHRvIHVzZSBhIHNpbmdsZSBtb2R1bGFyIHBvd2VyaW5nIGZvciBib3RoIHRoZVxuICAgICAgICAvLyBpbnZlcnNpb24gb2YgdiBhbmQgdGhlIHNxdWFyZSByb290OlxuICAgICAgICAvLyB4ID0gKHUvdileKChwKzEpLzQpICAgPSB1wrN2KHXigbV2wrMpXigocC0zKS80KSAgIChtb2QgcClcbiAgICAgICAgY29uc3QgdTJ2ID0gbW9kKHUgKiB1ICogdiwgUCk7IC8vIHXCsnZcbiAgICAgICAgY29uc3QgdTN2ID0gbW9kKHUydiAqIHUsIFApOyAvLyB1wrN2XG4gICAgICAgIGNvbnN0IHU1djMgPSBtb2QodTN2ICogdTJ2ICogdiwgUCk7IC8vIHXigbV2wrNcbiAgICAgICAgY29uc3Qgcm9vdCA9IGVkNDQ4X3Bvd19QbWludXMzZGl2NCh1NXYzKTtcbiAgICAgICAgY29uc3QgeCA9IG1vZCh1M3YgKiByb290LCBQKTtcbiAgICAgICAgLy8gVmVyaWZ5IHRoYXQgcm9vdCBpcyBleGlzdHNcbiAgICAgICAgY29uc3QgeDIgPSBtb2QoeCAqIHgsIFApOyAvLyB4wrJcbiAgICAgICAgLy8gSWYgdnjCsiA9IHUsIHRoZSByZWNvdmVyZWQgeC1jb29yZGluYXRlIGlzIHguICBPdGhlcndpc2UsIG5vXG4gICAgICAgIC8vIHNxdWFyZSByb290IGV4aXN0cywgYW5kIHRoZSBkZWNvZGluZyBmYWlscy5cbiAgICAgICAgcmV0dXJuIHsgaXNWYWxpZDogbW9kKHgyICogdiwgUCkgPT09IHUsIHZhbHVlOiB4IH07XG4gICAgfSxcbn07XG5leHBvcnQgY29uc3QgZWQ0NDggPSB0d2lzdGVkRWR3YXJkcyhFRDQ0OF9ERUYpO1xuLy8gTk9URTogdGhlcmUgaXMgbm8gZWQ0NDhjdHgsIHNpbmNlIGVkNDQ4IHN1cHBvcnRzIGN0eCBieSBkZWZhdWx0XG5leHBvcnQgY29uc3QgZWQ0NDhwaCA9IHR3aXN0ZWRFZHdhcmRzKHsgLi4uRUQ0NDhfREVGLCBwcmVoYXNoOiBzaGFrZTI1Nl82NCB9KTtcbmV4cG9ydCBjb25zdCB4NDQ4ID0gbW9udGdvbWVyeSh7XG4gICAgYTogQmlnSW50KDE1NjMyNiksXG4gICAgbW9udGdvbWVyeUJpdHM6IDQ0OCxcbiAgICBuQnl0ZUxlbmd0aDogNTcsXG4gICAgUDogZWQ0NDhQLFxuICAgIEd1OiBCaWdJbnQoNSksXG4gICAgcG93UG1pbnVzMjogKHgpID0+IHtcbiAgICAgICAgY29uc3QgUCA9IGVkNDQ4UDtcbiAgICAgICAgY29uc3QgUG1pbnVzM2RpdjQgPSBlZDQ0OF9wb3dfUG1pbnVzM2RpdjQoeCk7XG4gICAgICAgIGNvbnN0IFBtaW51czMgPSBwb3cyKFBtaW51czNkaXY0LCBCaWdJbnQoMiksIFApO1xuICAgICAgICByZXR1cm4gbW9kKFBtaW51czMgKiB4LCBQKTsgLy8gUG1pbnVzMyAqIHggPSBQbWludXMyXG4gICAgfSxcbiAgICBhZGp1c3RTY2FsYXJCeXRlcyxcbiAgICByYW5kb21CeXRlcyxcbn0pO1xuLyoqXG4gKiBDb252ZXJ0cyBlZHdhcmRzNDQ4IHB1YmxpYyBrZXkgdG8geDQ0OCBwdWJsaWMga2V5LiBVc2VzIGZvcm11bGE6XG4gKiAqIGAodSwgdikgPSAoKHktMSkvKHkrMSksIHNxcnQoMTU2MzI0KSp1L3gpYFxuICogKiBgKHgsIHkpID0gKHNxcnQoMTU2MzI0KSp1L3YsICgxK3UpLygxLXUpKWBcbiAqIEBleGFtcGxlXG4gKiAgIGNvbnN0IGFQdWIgPSBlZDQ0OC5nZXRQdWJsaWNLZXkodXRpbHMucmFuZG9tUHJpdmF0ZUtleSgpKTtcbiAqICAgeDQ0OC5nZXRTaGFyZWRTZWNyZXQoZWR3YXJkc1RvTW9udGdvbWVyeShhUHViKSwgZWR3YXJkc1RvTW9udGdvbWVyeShzb21lb25lc1B1YikpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlZHdhcmRzVG9Nb250Z29tZXJ5KGVkd2FyZHNQdWIpIHtcbiAgICBjb25zdCB7IHkgfSA9IGVkNDQ4LkV4dGVuZGVkUG9pbnQuZnJvbUhleChlZHdhcmRzUHViKTtcbiAgICBjb25zdCBfMW4gPSBCaWdJbnQoMSk7XG4gICAgcmV0dXJuIEZwLnRvQnl0ZXMoRnAuY3JlYXRlKCh5IC0gXzFuKSAqIEZwLmludih5ICsgXzFuKSkpO1xufVxuLy8gSGFzaCBUbyBDdXJ2ZSBFbGxpZ2F0b3IyIE1hcFxuY29uc3QgRUxMMl9DMSA9IChGcC5PUkRFUiAtIEJpZ0ludCgzKSkgLyBCaWdJbnQoNCk7IC8vIDEuIGMxID0gKHEgLSAzKSAvIDQgICAgICAgICAjIEludGVnZXIgYXJpdGhtZXRpY1xuY29uc3QgRUxMMl9KID0gQmlnSW50KDE1NjMyNik7XG5mdW5jdGlvbiBtYXBfdG9fY3VydmVfZWxsaWdhdG9yMl9jdXJ2ZTQ0OCh1KSB7XG4gICAgbGV0IHR2MSA9IEZwLnNxcih1KTsgLy8gMS4gIHR2MSA9IHVeMlxuICAgIGxldCBlMSA9IEZwLmVxbCh0djEsIEZwLk9ORSk7IC8vIDIuICAgZTEgPSB0djEgPT0gMVxuICAgIHR2MSA9IEZwLmNtb3YodHYxLCBGcC5aRVJPLCBlMSk7IC8vIDMuICB0djEgPSBDTU9WKHR2MSwgMCwgZTEpICAjIElmIFogKiB1XjIgPT0gLTEsIHNldCB0djEgPSAwXG4gICAgbGV0IHhkID0gRnAuc3ViKEZwLk9ORSwgdHYxKTsgLy8gNC4gICB4ZCA9IDEgLSB0djFcbiAgICBsZXQgeDFuID0gRnAubmVnKEVMTDJfSik7IC8vIDUuICB4MW4gPSAtSlxuICAgIGxldCB0djIgPSBGcC5zcXIoeGQpOyAvLyA2LiAgdHYyID0geGReMlxuICAgIGxldCBneGQgPSBGcC5tdWwodHYyLCB4ZCk7IC8vIDcuICBneGQgPSB0djIgKiB4ZCAgICAgICAgICAjIGd4ZCA9IHhkXjNcbiAgICBsZXQgZ3gxID0gRnAubXVsKHR2MSwgRnAubmVnKEVMTDJfSikpOyAvLyA4LiAgZ3gxID0gLUogKiB0djEgICAgICAgICAgIyB4MW4gKyBKICogeGRcbiAgICBneDEgPSBGcC5tdWwoZ3gxLCB4MW4pOyAvLyA5LiAgZ3gxID0gZ3gxICogeDFuICAgICAgICAgIyB4MW5eMiArIEogKiB4MW4gKiB4ZFxuICAgIGd4MSA9IEZwLmFkZChneDEsIHR2Mik7IC8vIDEwLiBneDEgPSBneDEgKyB0djIgICAgICAgICAjIHgxbl4yICsgSiAqIHgxbiAqIHhkICsgeGReMlxuICAgIGd4MSA9IEZwLm11bChneDEsIHgxbik7IC8vIDExLiBneDEgPSBneDEgKiB4MW4gICAgICAgICAjIHgxbl4zICsgSiAqIHgxbl4yICogeGQgKyB4MW4gKiB4ZF4yXG4gICAgbGV0IHR2MyA9IEZwLnNxcihneGQpOyAvLyAxMi4gdHYzID0gZ3hkXjJcbiAgICB0djIgPSBGcC5tdWwoZ3gxLCBneGQpOyAvLyAxMy4gdHYyID0gZ3gxICogZ3hkICAgICAgICAgIyBneDEgKiBneGRcbiAgICB0djMgPSBGcC5tdWwodHYzLCB0djIpOyAvLyAxNC4gdHYzID0gdHYzICogdHYyICAgICAgICAgIyBneDEgKiBneGReM1xuICAgIGxldCB5MSA9IEZwLnBvdyh0djMsIEVMTDJfQzEpOyAvLyAxNS4gIHkxID0gdHYzXmMxICAgICAgICAgICAgIyAoZ3gxICogZ3hkXjMpXigocCAtIDMpIC8gNClcbiAgICB5MSA9IEZwLm11bCh5MSwgdHYyKTsgLy8gMTYuICB5MSA9IHkxICogdHYyICAgICAgICAgICMgZ3gxICogZ3hkICogKGd4MSAqIGd4ZF4zKV4oKHAgLSAzKSAvIDQpXG4gICAgbGV0IHgybiA9IEZwLm11bCh4MW4sIEZwLm5lZyh0djEpKTsgLy8gMTcuIHgybiA9IC10djEgKiB4MW4gICAgICAgICMgeDIgPSB4Mm4gLyB4ZCA9IC0xICogdV4yICogeDFuIC8geGRcbiAgICBsZXQgeTIgPSBGcC5tdWwoeTEsIHUpOyAvLyAxOC4gIHkyID0geTEgKiB1XG4gICAgeTIgPSBGcC5jbW92KHkyLCBGcC5aRVJPLCBlMSk7IC8vIDE5LiAgeTIgPSBDTU9WKHkyLCAwLCBlMSlcbiAgICB0djIgPSBGcC5zcXIoeTEpOyAvLyAyMC4gdHYyID0geTFeMlxuICAgIHR2MiA9IEZwLm11bCh0djIsIGd4ZCk7IC8vIDIxLiB0djIgPSB0djIgKiBneGRcbiAgICBsZXQgZTIgPSBGcC5lcWwodHYyLCBneDEpOyAvLyAyMi4gIGUyID0gdHYyID09IGd4MVxuICAgIGxldCB4biA9IEZwLmNtb3YoeDJuLCB4MW4sIGUyKTsgLy8gMjMuICB4biA9IENNT1YoeDJuLCB4MW4sIGUyKSAgIyBJZiBlMiwgeCA9IHgxLCBlbHNlIHggPSB4MlxuICAgIGxldCB5ID0gRnAuY21vdih5MiwgeTEsIGUyKTsgLy8gMjQuICAgeSA9IENNT1YoeTIsIHkxLCBlMikgICAgIyBJZiBlMiwgeSA9IHkxLCBlbHNlIHkgPSB5MlxuICAgIGxldCBlMyA9IEZwLmlzT2RkKHkpOyAvLyAyNS4gIGUzID0gc2duMCh5KSA9PSAxICAgICAgICAjIEZpeCBzaWduIG9mIHlcbiAgICB5ID0gRnAuY21vdih5LCBGcC5uZWcoeSksIGUyICE9PSBlMyk7IC8vIDI2LiAgIHkgPSBDTU9WKHksIC15LCBlMiBYT1IgZTMpXG4gICAgcmV0dXJuIHsgeG4sIHhkLCB5bjogeSwgeWQ6IEZwLk9ORSB9OyAvLyAyNy4gcmV0dXJuICh4biwgeGQsIHksIDEpXG59XG5mdW5jdGlvbiBtYXBfdG9fY3VydmVfZWxsaWdhdG9yMl9lZHdhcmRzNDQ4KHUpIHtcbiAgICBsZXQgeyB4biwgeGQsIHluLCB5ZCB9ID0gbWFwX3RvX2N1cnZlX2VsbGlnYXRvcjJfY3VydmU0NDgodSk7IC8vIDEuICh4biwgeGQsIHluLCB5ZCkgPSBtYXBfdG9fY3VydmVfZWxsaWdhdG9yMl9jdXJ2ZTQ0OCh1KVxuICAgIGxldCB4bjIgPSBGcC5zcXIoeG4pOyAvLyAyLiAgeG4yID0geG5eMlxuICAgIGxldCB4ZDIgPSBGcC5zcXIoeGQpOyAvLyAzLiAgeGQyID0geGReMlxuICAgIGxldCB4ZDQgPSBGcC5zcXIoeGQyKTsgLy8gNC4gIHhkNCA9IHhkMl4yXG4gICAgbGV0IHluMiA9IEZwLnNxcih5bik7IC8vIDUuICB5bjIgPSB5bl4yXG4gICAgbGV0IHlkMiA9IEZwLnNxcih5ZCk7IC8vIDYuICB5ZDIgPSB5ZF4yXG4gICAgbGV0IHhFbiA9IEZwLnN1Yih4bjIsIHhkMik7IC8vIDcuICB4RW4gPSB4bjIgLSB4ZDJcbiAgICBsZXQgdHYyID0gRnAuc3ViKHhFbiwgeGQyKTsgLy8gOC4gIHR2MiA9IHhFbiAtIHhkMlxuICAgIHhFbiA9IEZwLm11bCh4RW4sIHhkMik7IC8vIDkuICB4RW4gPSB4RW4gKiB4ZDJcbiAgICB4RW4gPSBGcC5tdWwoeEVuLCB5ZCk7IC8vIDEwLiB4RW4gPSB4RW4gKiB5ZFxuICAgIHhFbiA9IEZwLm11bCh4RW4sIHluKTsgLy8gMTEuIHhFbiA9IHhFbiAqIHluXG4gICAgeEVuID0gRnAubXVsKHhFbiwgXzRuKTsgLy8gMTIuIHhFbiA9IHhFbiAqIDRcbiAgICB0djIgPSBGcC5tdWwodHYyLCB4bjIpOyAvLyAxMy4gdHYyID0gdHYyICogeG4yXG4gICAgdHYyID0gRnAubXVsKHR2MiwgeWQyKTsgLy8gMTQuIHR2MiA9IHR2MiAqIHlkMlxuICAgIGxldCB0djMgPSBGcC5tdWwoeW4yLCBfNG4pOyAvLyAxNS4gdHYzID0gNCAqIHluMlxuICAgIGxldCB0djEgPSBGcC5hZGQodHYzLCB5ZDIpOyAvLyAxNi4gdHYxID0gdHYzICsgeWQyXG4gICAgdHYxID0gRnAubXVsKHR2MSwgeGQ0KTsgLy8gMTcuIHR2MSA9IHR2MSAqIHhkNFxuICAgIGxldCB4RWQgPSBGcC5hZGQodHYxLCB0djIpOyAvLyAxOC4geEVkID0gdHYxICsgdHYyXG4gICAgdHYyID0gRnAubXVsKHR2MiwgeG4pOyAvLyAxOS4gdHYyID0gdHYyICogeG5cbiAgICBsZXQgdHY0ID0gRnAubXVsKHhuLCB4ZDQpOyAvLyAyMC4gdHY0ID0geG4gKiB4ZDRcbiAgICBsZXQgeUVuID0gRnAuc3ViKHR2MywgeWQyKTsgLy8gMjEuIHlFbiA9IHR2MyAtIHlkMlxuICAgIHlFbiA9IEZwLm11bCh5RW4sIHR2NCk7IC8vIDIyLiB5RW4gPSB5RW4gKiB0djRcbiAgICB5RW4gPSBGcC5zdWIoeUVuLCB0djIpOyAvLyAyMy4geUVuID0geUVuIC0gdHYyXG4gICAgdHYxID0gRnAuYWRkKHhuMiwgeGQyKTsgLy8gMjQuIHR2MSA9IHhuMiArIHhkMlxuICAgIHR2MSA9IEZwLm11bCh0djEsIHhkMik7IC8vIDI1LiB0djEgPSB0djEgKiB4ZDJcbiAgICB0djEgPSBGcC5tdWwodHYxLCB4ZCk7IC8vIDI2LiB0djEgPSB0djEgKiB4ZFxuICAgIHR2MSA9IEZwLm11bCh0djEsIHluMik7IC8vIDI3LiB0djEgPSB0djEgKiB5bjJcbiAgICB0djEgPSBGcC5tdWwodHYxLCBCaWdJbnQoLTIpKTsgLy8gMjguIHR2MSA9IC0yICogdHYxXG4gICAgbGV0IHlFZCA9IEZwLmFkZCh0djIsIHR2MSk7IC8vIDI5LiB5RWQgPSB0djIgKyB0djFcbiAgICB0djQgPSBGcC5tdWwodHY0LCB5ZDIpOyAvLyAzMC4gdHY0ID0gdHY0ICogeWQyXG4gICAgeUVkID0gRnAuYWRkKHlFZCwgdHY0KTsgLy8gMzEuIHlFZCA9IHlFZCArIHR2NFxuICAgIHR2MSA9IEZwLm11bCh4RWQsIHlFZCk7IC8vIDMyLiB0djEgPSB4RWQgKiB5RWRcbiAgICBsZXQgZSA9IEZwLmVxbCh0djEsIEZwLlpFUk8pOyAvLyAzMy4gICBlID0gdHYxID09IDBcbiAgICB4RW4gPSBGcC5jbW92KHhFbiwgRnAuWkVSTywgZSk7IC8vIDM0LiB4RW4gPSBDTU9WKHhFbiwgMCwgZSlcbiAgICB4RWQgPSBGcC5jbW92KHhFZCwgRnAuT05FLCBlKTsgLy8gMzUuIHhFZCA9IENNT1YoeEVkLCAxLCBlKVxuICAgIHlFbiA9IEZwLmNtb3YoeUVuLCBGcC5PTkUsIGUpOyAvLyAzNi4geUVuID0gQ01PVih5RW4sIDEsIGUpXG4gICAgeUVkID0gRnAuY21vdih5RWQsIEZwLk9ORSwgZSk7IC8vIDM3LiB5RWQgPSBDTU9WKHlFZCwgMSwgZSlcbiAgICBjb25zdCBpbnYgPSBGcC5pbnZlcnRCYXRjaChbeEVkLCB5RWRdKTsgLy8gYmF0Y2ggZGl2aXNpb25cbiAgICByZXR1cm4geyB4OiBGcC5tdWwoeEVuLCBpbnZbMF0pLCB5OiBGcC5tdWwoeUVuLCBpbnZbMV0pIH07IC8vIDM4LiByZXR1cm4gKHhFbiwgeEVkLCB5RW4sIHlFZClcbn1cbmNvbnN0IHsgaGFzaFRvQ3VydmUsIGVuY29kZVRvQ3VydmUgfSA9IGh0Zi5jcmVhdGVIYXNoZXIoZWQ0NDguRXh0ZW5kZWRQb2ludCwgKHNjYWxhcnMpID0+IG1hcF90b19jdXJ2ZV9lbGxpZ2F0b3IyX2Vkd2FyZHM0NDgoc2NhbGFyc1swXSksIHtcbiAgICBEU1Q6ICdlZHdhcmRzNDQ4X1hPRjpTSEFLRTI1Nl9FTEwyX1JPXycsXG4gICAgZW5jb2RlRFNUOiAnZWR3YXJkczQ0OF9YT0Y6U0hBS0UyNTZfRUxMMl9OVV8nLFxuICAgIHA6IEZwLk9SREVSLFxuICAgIG06IDEsXG4gICAgazogMjI0LFxuICAgIGV4cGFuZDogJ3hvZicsXG4gICAgaGFzaDogc2hha2UyNTYsXG59KTtcbmV4cG9ydCB7IGhhc2hUb0N1cnZlLCBlbmNvZGVUb0N1cnZlIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1lZDQ0OC5qcy5tYXAiLCJmdW5jdGlvbiBfdHlwZW9mKG9iaikgeyBcIkBiYWJlbC9oZWxwZXJzIC0gdHlwZW9mXCI7IHJldHVybiBfdHlwZW9mID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgJiYgXCJzeW1ib2xcIiA9PSB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID8gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gdHlwZW9mIG9iajsgfSA6IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iaiAmJiBcImZ1bmN0aW9uXCIgPT0gdHlwZW9mIFN5bWJvbCAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajsgfSwgX3R5cGVvZihvYmopOyB9XG5mdW5jdGlvbiBfc2xpY2VkVG9BcnJheShhcnIsIGkpIHsgcmV0dXJuIF9hcnJheVdpdGhIb2xlcyhhcnIpIHx8IF9pdGVyYWJsZVRvQXJyYXlMaW1pdChhcnIsIGkpIHx8IF91bnN1cHBvcnRlZEl0ZXJhYmxlVG9BcnJheShhcnIsIGkpIHx8IF9ub25JdGVyYWJsZVJlc3QoKTsgfVxuZnVuY3Rpb24gX25vbkl0ZXJhYmxlUmVzdCgpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkludmFsaWQgYXR0ZW1wdCB0byBkZXN0cnVjdHVyZSBub24taXRlcmFibGUgaW5zdGFuY2UuXFxuSW4gb3JkZXIgdG8gYmUgaXRlcmFibGUsIG5vbi1hcnJheSBvYmplY3RzIG11c3QgaGF2ZSBhIFtTeW1ib2wuaXRlcmF0b3JdKCkgbWV0aG9kLlwiKTsgfVxuZnVuY3Rpb24gX3Vuc3VwcG9ydGVkSXRlcmFibGVUb0FycmF5KG8sIG1pbkxlbikgeyBpZiAoIW8pIHJldHVybjsgaWYgKHR5cGVvZiBvID09PSBcInN0cmluZ1wiKSByZXR1cm4gX2FycmF5TGlrZVRvQXJyYXkobywgbWluTGVuKTsgdmFyIG4gPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwobykuc2xpY2UoOCwgLTEpOyBpZiAobiA9PT0gXCJPYmplY3RcIiAmJiBvLmNvbnN0cnVjdG9yKSBuID0gby5jb25zdHJ1Y3Rvci5uYW1lOyBpZiAobiA9PT0gXCJNYXBcIiB8fCBuID09PSBcIlNldFwiKSByZXR1cm4gQXJyYXkuZnJvbShvKTsgaWYgKG4gPT09IFwiQXJndW1lbnRzXCIgfHwgL14oPzpVaXxJKW50KD86OHwxNnwzMikoPzpDbGFtcGVkKT9BcnJheSQvLnRlc3QobikpIHJldHVybiBfYXJyYXlMaWtlVG9BcnJheShvLCBtaW5MZW4pOyB9XG5mdW5jdGlvbiBfYXJyYXlMaWtlVG9BcnJheShhcnIsIGxlbikgeyBpZiAobGVuID09IG51bGwgfHwgbGVuID4gYXJyLmxlbmd0aCkgbGVuID0gYXJyLmxlbmd0aDsgZm9yICh2YXIgaSA9IDAsIGFycjIgPSBuZXcgQXJyYXkobGVuKTsgaSA8IGxlbjsgaSsrKSBhcnIyW2ldID0gYXJyW2ldOyByZXR1cm4gYXJyMjsgfVxuZnVuY3Rpb24gX2l0ZXJhYmxlVG9BcnJheUxpbWl0KGFyciwgaSkgeyB2YXIgX2kgPSBudWxsID09IGFyciA/IG51bGwgOiBcInVuZGVmaW5lZFwiICE9IHR5cGVvZiBTeW1ib2wgJiYgYXJyW1N5bWJvbC5pdGVyYXRvcl0gfHwgYXJyW1wiQEBpdGVyYXRvclwiXTsgaWYgKG51bGwgIT0gX2kpIHsgdmFyIF9zLCBfZSwgX3gsIF9yLCBfYXJyID0gW10sIF9uID0gITAsIF9kID0gITE7IHRyeSB7IGlmIChfeCA9IChfaSA9IF9pLmNhbGwoYXJyKSkubmV4dCwgMCA9PT0gaSkgeyBpZiAoT2JqZWN0KF9pKSAhPT0gX2kpIHJldHVybjsgX24gPSAhMTsgfSBlbHNlIGZvciAoOyAhKF9uID0gKF9zID0gX3guY2FsbChfaSkpLmRvbmUpICYmIChfYXJyLnB1c2goX3MudmFsdWUpLCBfYXJyLmxlbmd0aCAhPT0gaSk7IF9uID0gITApOyB9IGNhdGNoIChlcnIpIHsgX2QgPSAhMCwgX2UgPSBlcnI7IH0gZmluYWxseSB7IHRyeSB7IGlmICghX24gJiYgbnVsbCAhPSBfaVtcInJldHVyblwiXSAmJiAoX3IgPSBfaVtcInJldHVyblwiXSgpLCBPYmplY3QoX3IpICE9PSBfcikpIHJldHVybjsgfSBmaW5hbGx5IHsgaWYgKF9kKSB0aHJvdyBfZTsgfSB9IHJldHVybiBfYXJyOyB9IH1cbmZ1bmN0aW9uIF9hcnJheVdpdGhIb2xlcyhhcnIpIHsgaWYgKEFycmF5LmlzQXJyYXkoYXJyKSkgcmV0dXJuIGFycjsgfVxuZnVuY3Rpb24gX3JlZ2VuZXJhdG9yUnVudGltZSgpIHsgXCJ1c2Ugc3RyaWN0XCI7IC8qISByZWdlbmVyYXRvci1ydW50aW1lIC0tIENvcHlyaWdodCAoYykgMjAxNC1wcmVzZW50LCBGYWNlYm9vaywgSW5jLiAtLSBsaWNlbnNlIChNSVQpOiBodHRwczovL2dpdGh1Yi5jb20vZmFjZWJvb2svcmVnZW5lcmF0b3IvYmxvYi9tYWluL0xJQ0VOU0UgKi8gX3JlZ2VuZXJhdG9yUnVudGltZSA9IGZ1bmN0aW9uIF9yZWdlbmVyYXRvclJ1bnRpbWUoKSB7IHJldHVybiBleHBvcnRzOyB9OyB2YXIgZXhwb3J0cyA9IHt9LCBPcCA9IE9iamVjdC5wcm90b3R5cGUsIGhhc093biA9IE9wLmhhc093blByb3BlcnR5LCBkZWZpbmVQcm9wZXJ0eSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSB8fCBmdW5jdGlvbiAob2JqLCBrZXksIGRlc2MpIHsgb2JqW2tleV0gPSBkZXNjLnZhbHVlOyB9LCAkU3ltYm9sID0gXCJmdW5jdGlvblwiID09IHR5cGVvZiBTeW1ib2wgPyBTeW1ib2wgOiB7fSwgaXRlcmF0b3JTeW1ib2wgPSAkU3ltYm9sLml0ZXJhdG9yIHx8IFwiQEBpdGVyYXRvclwiLCBhc3luY0l0ZXJhdG9yU3ltYm9sID0gJFN5bWJvbC5hc3luY0l0ZXJhdG9yIHx8IFwiQEBhc3luY0l0ZXJhdG9yXCIsIHRvU3RyaW5nVGFnU3ltYm9sID0gJFN5bWJvbC50b1N0cmluZ1RhZyB8fCBcIkBAdG9TdHJpbmdUYWdcIjsgZnVuY3Rpb24gZGVmaW5lKG9iaiwga2V5LCB2YWx1ZSkgeyByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KG9iaiwga2V5LCB7IHZhbHVlOiB2YWx1ZSwgZW51bWVyYWJsZTogITAsIGNvbmZpZ3VyYWJsZTogITAsIHdyaXRhYmxlOiAhMCB9KSwgb2JqW2tleV07IH0gdHJ5IHsgZGVmaW5lKHt9LCBcIlwiKTsgfSBjYXRjaCAoZXJyKSB7IGRlZmluZSA9IGZ1bmN0aW9uIGRlZmluZShvYmosIGtleSwgdmFsdWUpIHsgcmV0dXJuIG9ialtrZXldID0gdmFsdWU7IH07IH0gZnVuY3Rpb24gd3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCkgeyB2YXIgcHJvdG9HZW5lcmF0b3IgPSBvdXRlckZuICYmIG91dGVyRm4ucHJvdG90eXBlIGluc3RhbmNlb2YgR2VuZXJhdG9yID8gb3V0ZXJGbiA6IEdlbmVyYXRvciwgZ2VuZXJhdG9yID0gT2JqZWN0LmNyZWF0ZShwcm90b0dlbmVyYXRvci5wcm90b3R5cGUpLCBjb250ZXh0ID0gbmV3IENvbnRleHQodHJ5TG9jc0xpc3QgfHwgW10pOyByZXR1cm4gZGVmaW5lUHJvcGVydHkoZ2VuZXJhdG9yLCBcIl9pbnZva2VcIiwgeyB2YWx1ZTogbWFrZUludm9rZU1ldGhvZChpbm5lckZuLCBzZWxmLCBjb250ZXh0KSB9KSwgZ2VuZXJhdG9yOyB9IGZ1bmN0aW9uIHRyeUNhdGNoKGZuLCBvYmosIGFyZykgeyB0cnkgeyByZXR1cm4geyB0eXBlOiBcIm5vcm1hbFwiLCBhcmc6IGZuLmNhbGwob2JqLCBhcmcpIH07IH0gY2F0Y2ggKGVycikgeyByZXR1cm4geyB0eXBlOiBcInRocm93XCIsIGFyZzogZXJyIH07IH0gfSBleHBvcnRzLndyYXAgPSB3cmFwOyB2YXIgQ29udGludWVTZW50aW5lbCA9IHt9OyBmdW5jdGlvbiBHZW5lcmF0b3IoKSB7fSBmdW5jdGlvbiBHZW5lcmF0b3JGdW5jdGlvbigpIHt9IGZ1bmN0aW9uIEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlKCkge30gdmFyIEl0ZXJhdG9yUHJvdG90eXBlID0ge307IGRlZmluZShJdGVyYXRvclByb3RvdHlwZSwgaXRlcmF0b3JTeW1ib2wsIGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0pOyB2YXIgZ2V0UHJvdG8gPSBPYmplY3QuZ2V0UHJvdG90eXBlT2YsIE5hdGl2ZUl0ZXJhdG9yUHJvdG90eXBlID0gZ2V0UHJvdG8gJiYgZ2V0UHJvdG8oZ2V0UHJvdG8odmFsdWVzKFtdKSkpOyBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSAmJiBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSAhPT0gT3AgJiYgaGFzT3duLmNhbGwoTmF0aXZlSXRlcmF0b3JQcm90b3R5cGUsIGl0ZXJhdG9yU3ltYm9sKSAmJiAoSXRlcmF0b3JQcm90b3R5cGUgPSBOYXRpdmVJdGVyYXRvclByb3RvdHlwZSk7IHZhciBHcCA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLnByb3RvdHlwZSA9IEdlbmVyYXRvci5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKEl0ZXJhdG9yUHJvdG90eXBlKTsgZnVuY3Rpb24gZGVmaW5lSXRlcmF0b3JNZXRob2RzKHByb3RvdHlwZSkgeyBbXCJuZXh0XCIsIFwidGhyb3dcIiwgXCJyZXR1cm5cIl0uZm9yRWFjaChmdW5jdGlvbiAobWV0aG9kKSB7IGRlZmluZShwcm90b3R5cGUsIG1ldGhvZCwgZnVuY3Rpb24gKGFyZykgeyByZXR1cm4gdGhpcy5faW52b2tlKG1ldGhvZCwgYXJnKTsgfSk7IH0pOyB9IGZ1bmN0aW9uIEFzeW5jSXRlcmF0b3IoZ2VuZXJhdG9yLCBQcm9taXNlSW1wbCkgeyBmdW5jdGlvbiBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCkgeyB2YXIgcmVjb3JkID0gdHJ5Q2F0Y2goZ2VuZXJhdG9yW21ldGhvZF0sIGdlbmVyYXRvciwgYXJnKTsgaWYgKFwidGhyb3dcIiAhPT0gcmVjb3JkLnR5cGUpIHsgdmFyIHJlc3VsdCA9IHJlY29yZC5hcmcsIHZhbHVlID0gcmVzdWx0LnZhbHVlOyByZXR1cm4gdmFsdWUgJiYgXCJvYmplY3RcIiA9PSBfdHlwZW9mKHZhbHVlKSAmJiBoYXNPd24uY2FsbCh2YWx1ZSwgXCJfX2F3YWl0XCIpID8gUHJvbWlzZUltcGwucmVzb2x2ZSh2YWx1ZS5fX2F3YWl0KS50aGVuKGZ1bmN0aW9uICh2YWx1ZSkgeyBpbnZva2UoXCJuZXh0XCIsIHZhbHVlLCByZXNvbHZlLCByZWplY3QpOyB9LCBmdW5jdGlvbiAoZXJyKSB7IGludm9rZShcInRocm93XCIsIGVyciwgcmVzb2x2ZSwgcmVqZWN0KTsgfSkgOiBQcm9taXNlSW1wbC5yZXNvbHZlKHZhbHVlKS50aGVuKGZ1bmN0aW9uICh1bndyYXBwZWQpIHsgcmVzdWx0LnZhbHVlID0gdW53cmFwcGVkLCByZXNvbHZlKHJlc3VsdCk7IH0sIGZ1bmN0aW9uIChlcnJvcikgeyByZXR1cm4gaW52b2tlKFwidGhyb3dcIiwgZXJyb3IsIHJlc29sdmUsIHJlamVjdCk7IH0pOyB9IHJlamVjdChyZWNvcmQuYXJnKTsgfSB2YXIgcHJldmlvdXNQcm9taXNlOyBkZWZpbmVQcm9wZXJ0eSh0aGlzLCBcIl9pbnZva2VcIiwgeyB2YWx1ZTogZnVuY3Rpb24gdmFsdWUobWV0aG9kLCBhcmcpIHsgZnVuY3Rpb24gY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcoKSB7IHJldHVybiBuZXcgUHJvbWlzZUltcGwoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkgeyBpbnZva2UobWV0aG9kLCBhcmcsIHJlc29sdmUsIHJlamVjdCk7IH0pOyB9IHJldHVybiBwcmV2aW91c1Byb21pc2UgPSBwcmV2aW91c1Byb21pc2UgPyBwcmV2aW91c1Byb21pc2UudGhlbihjYWxsSW52b2tlV2l0aE1ldGhvZEFuZEFyZywgY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcpIDogY2FsbEludm9rZVdpdGhNZXRob2RBbmRBcmcoKTsgfSB9KTsgfSBmdW5jdGlvbiBtYWtlSW52b2tlTWV0aG9kKGlubmVyRm4sIHNlbGYsIGNvbnRleHQpIHsgdmFyIHN0YXRlID0gXCJzdXNwZW5kZWRTdGFydFwiOyByZXR1cm4gZnVuY3Rpb24gKG1ldGhvZCwgYXJnKSB7IGlmIChcImV4ZWN1dGluZ1wiID09PSBzdGF0ZSkgdGhyb3cgbmV3IEVycm9yKFwiR2VuZXJhdG9yIGlzIGFscmVhZHkgcnVubmluZ1wiKTsgaWYgKFwiY29tcGxldGVkXCIgPT09IHN0YXRlKSB7IGlmIChcInRocm93XCIgPT09IG1ldGhvZCkgdGhyb3cgYXJnOyByZXR1cm4gZG9uZVJlc3VsdCgpOyB9IGZvciAoY29udGV4dC5tZXRob2QgPSBtZXRob2QsIGNvbnRleHQuYXJnID0gYXJnOzspIHsgdmFyIGRlbGVnYXRlID0gY29udGV4dC5kZWxlZ2F0ZTsgaWYgKGRlbGVnYXRlKSB7IHZhciBkZWxlZ2F0ZVJlc3VsdCA9IG1heWJlSW52b2tlRGVsZWdhdGUoZGVsZWdhdGUsIGNvbnRleHQpOyBpZiAoZGVsZWdhdGVSZXN1bHQpIHsgaWYgKGRlbGVnYXRlUmVzdWx0ID09PSBDb250aW51ZVNlbnRpbmVsKSBjb250aW51ZTsgcmV0dXJuIGRlbGVnYXRlUmVzdWx0OyB9IH0gaWYgKFwibmV4dFwiID09PSBjb250ZXh0Lm1ldGhvZCkgY29udGV4dC5zZW50ID0gY29udGV4dC5fc2VudCA9IGNvbnRleHQuYXJnO2Vsc2UgaWYgKFwidGhyb3dcIiA9PT0gY29udGV4dC5tZXRob2QpIHsgaWYgKFwic3VzcGVuZGVkU3RhcnRcIiA9PT0gc3RhdGUpIHRocm93IHN0YXRlID0gXCJjb21wbGV0ZWRcIiwgY29udGV4dC5hcmc7IGNvbnRleHQuZGlzcGF0Y2hFeGNlcHRpb24oY29udGV4dC5hcmcpOyB9IGVsc2UgXCJyZXR1cm5cIiA9PT0gY29udGV4dC5tZXRob2QgJiYgY29udGV4dC5hYnJ1cHQoXCJyZXR1cm5cIiwgY29udGV4dC5hcmcpOyBzdGF0ZSA9IFwiZXhlY3V0aW5nXCI7IHZhciByZWNvcmQgPSB0cnlDYXRjaChpbm5lckZuLCBzZWxmLCBjb250ZXh0KTsgaWYgKFwibm9ybWFsXCIgPT09IHJlY29yZC50eXBlKSB7IGlmIChzdGF0ZSA9IGNvbnRleHQuZG9uZSA/IFwiY29tcGxldGVkXCIgOiBcInN1c3BlbmRlZFlpZWxkXCIsIHJlY29yZC5hcmcgPT09IENvbnRpbnVlU2VudGluZWwpIGNvbnRpbnVlOyByZXR1cm4geyB2YWx1ZTogcmVjb3JkLmFyZywgZG9uZTogY29udGV4dC5kb25lIH07IH0gXCJ0aHJvd1wiID09PSByZWNvcmQudHlwZSAmJiAoc3RhdGUgPSBcImNvbXBsZXRlZFwiLCBjb250ZXh0Lm1ldGhvZCA9IFwidGhyb3dcIiwgY29udGV4dC5hcmcgPSByZWNvcmQuYXJnKTsgfSB9OyB9IGZ1bmN0aW9uIG1heWJlSW52b2tlRGVsZWdhdGUoZGVsZWdhdGUsIGNvbnRleHQpIHsgdmFyIG1ldGhvZE5hbWUgPSBjb250ZXh0Lm1ldGhvZCwgbWV0aG9kID0gZGVsZWdhdGUuaXRlcmF0b3JbbWV0aG9kTmFtZV07IGlmICh1bmRlZmluZWQgPT09IG1ldGhvZCkgcmV0dXJuIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsLCBcInRocm93XCIgPT09IG1ldGhvZE5hbWUgJiYgZGVsZWdhdGUuaXRlcmF0b3JbXCJyZXR1cm5cIl0gJiYgKGNvbnRleHQubWV0aG9kID0gXCJyZXR1cm5cIiwgY29udGV4dC5hcmcgPSB1bmRlZmluZWQsIG1heWJlSW52b2tlRGVsZWdhdGUoZGVsZWdhdGUsIGNvbnRleHQpLCBcInRocm93XCIgPT09IGNvbnRleHQubWV0aG9kKSB8fCBcInJldHVyblwiICE9PSBtZXRob2ROYW1lICYmIChjb250ZXh0Lm1ldGhvZCA9IFwidGhyb3dcIiwgY29udGV4dC5hcmcgPSBuZXcgVHlwZUVycm9yKFwiVGhlIGl0ZXJhdG9yIGRvZXMgbm90IHByb3ZpZGUgYSAnXCIgKyBtZXRob2ROYW1lICsgXCInIG1ldGhvZFwiKSksIENvbnRpbnVlU2VudGluZWw7IHZhciByZWNvcmQgPSB0cnlDYXRjaChtZXRob2QsIGRlbGVnYXRlLml0ZXJhdG9yLCBjb250ZXh0LmFyZyk7IGlmIChcInRocm93XCIgPT09IHJlY29yZC50eXBlKSByZXR1cm4gY29udGV4dC5tZXRob2QgPSBcInRocm93XCIsIGNvbnRleHQuYXJnID0gcmVjb3JkLmFyZywgY29udGV4dC5kZWxlZ2F0ZSA9IG51bGwsIENvbnRpbnVlU2VudGluZWw7IHZhciBpbmZvID0gcmVjb3JkLmFyZzsgcmV0dXJuIGluZm8gPyBpbmZvLmRvbmUgPyAoY29udGV4dFtkZWxlZ2F0ZS5yZXN1bHROYW1lXSA9IGluZm8udmFsdWUsIGNvbnRleHQubmV4dCA9IGRlbGVnYXRlLm5leHRMb2MsIFwicmV0dXJuXCIgIT09IGNvbnRleHQubWV0aG9kICYmIChjb250ZXh0Lm1ldGhvZCA9IFwibmV4dFwiLCBjb250ZXh0LmFyZyA9IHVuZGVmaW5lZCksIGNvbnRleHQuZGVsZWdhdGUgPSBudWxsLCBDb250aW51ZVNlbnRpbmVsKSA6IGluZm8gOiAoY29udGV4dC5tZXRob2QgPSBcInRocm93XCIsIGNvbnRleHQuYXJnID0gbmV3IFR5cGVFcnJvcihcIml0ZXJhdG9yIHJlc3VsdCBpcyBub3QgYW4gb2JqZWN0XCIpLCBjb250ZXh0LmRlbGVnYXRlID0gbnVsbCwgQ29udGludWVTZW50aW5lbCk7IH0gZnVuY3Rpb24gcHVzaFRyeUVudHJ5KGxvY3MpIHsgdmFyIGVudHJ5ID0geyB0cnlMb2M6IGxvY3NbMF0gfTsgMSBpbiBsb2NzICYmIChlbnRyeS5jYXRjaExvYyA9IGxvY3NbMV0pLCAyIGluIGxvY3MgJiYgKGVudHJ5LmZpbmFsbHlMb2MgPSBsb2NzWzJdLCBlbnRyeS5hZnRlckxvYyA9IGxvY3NbM10pLCB0aGlzLnRyeUVudHJpZXMucHVzaChlbnRyeSk7IH0gZnVuY3Rpb24gcmVzZXRUcnlFbnRyeShlbnRyeSkgeyB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbiB8fCB7fTsgcmVjb3JkLnR5cGUgPSBcIm5vcm1hbFwiLCBkZWxldGUgcmVjb3JkLmFyZywgZW50cnkuY29tcGxldGlvbiA9IHJlY29yZDsgfSBmdW5jdGlvbiBDb250ZXh0KHRyeUxvY3NMaXN0KSB7IHRoaXMudHJ5RW50cmllcyA9IFt7IHRyeUxvYzogXCJyb290XCIgfV0sIHRyeUxvY3NMaXN0LmZvckVhY2gocHVzaFRyeUVudHJ5LCB0aGlzKSwgdGhpcy5yZXNldCghMCk7IH0gZnVuY3Rpb24gdmFsdWVzKGl0ZXJhYmxlKSB7IGlmIChpdGVyYWJsZSkgeyB2YXIgaXRlcmF0b3JNZXRob2QgPSBpdGVyYWJsZVtpdGVyYXRvclN5bWJvbF07IGlmIChpdGVyYXRvck1ldGhvZCkgcmV0dXJuIGl0ZXJhdG9yTWV0aG9kLmNhbGwoaXRlcmFibGUpOyBpZiAoXCJmdW5jdGlvblwiID09IHR5cGVvZiBpdGVyYWJsZS5uZXh0KSByZXR1cm4gaXRlcmFibGU7IGlmICghaXNOYU4oaXRlcmFibGUubGVuZ3RoKSkgeyB2YXIgaSA9IC0xLCBuZXh0ID0gZnVuY3Rpb24gbmV4dCgpIHsgZm9yICg7ICsraSA8IGl0ZXJhYmxlLmxlbmd0aDspIGlmIChoYXNPd24uY2FsbChpdGVyYWJsZSwgaSkpIHJldHVybiBuZXh0LnZhbHVlID0gaXRlcmFibGVbaV0sIG5leHQuZG9uZSA9ICExLCBuZXh0OyByZXR1cm4gbmV4dC52YWx1ZSA9IHVuZGVmaW5lZCwgbmV4dC5kb25lID0gITAsIG5leHQ7IH07IHJldHVybiBuZXh0Lm5leHQgPSBuZXh0OyB9IH0gcmV0dXJuIHsgbmV4dDogZG9uZVJlc3VsdCB9OyB9IGZ1bmN0aW9uIGRvbmVSZXN1bHQoKSB7IHJldHVybiB7IHZhbHVlOiB1bmRlZmluZWQsIGRvbmU6ICEwIH07IH0gcmV0dXJuIEdlbmVyYXRvckZ1bmN0aW9uLnByb3RvdHlwZSA9IEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLCBkZWZpbmVQcm9wZXJ0eShHcCwgXCJjb25zdHJ1Y3RvclwiLCB7IHZhbHVlOiBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgY29uZmlndXJhYmxlOiAhMCB9KSwgZGVmaW5lUHJvcGVydHkoR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUsIFwiY29uc3RydWN0b3JcIiwgeyB2YWx1ZTogR2VuZXJhdG9yRnVuY3Rpb24sIGNvbmZpZ3VyYWJsZTogITAgfSksIEdlbmVyYXRvckZ1bmN0aW9uLmRpc3BsYXlOYW1lID0gZGVmaW5lKEdlbmVyYXRvckZ1bmN0aW9uUHJvdG90eXBlLCB0b1N0cmluZ1RhZ1N5bWJvbCwgXCJHZW5lcmF0b3JGdW5jdGlvblwiKSwgZXhwb3J0cy5pc0dlbmVyYXRvckZ1bmN0aW9uID0gZnVuY3Rpb24gKGdlbkZ1bikgeyB2YXIgY3RvciA9IFwiZnVuY3Rpb25cIiA9PSB0eXBlb2YgZ2VuRnVuICYmIGdlbkZ1bi5jb25zdHJ1Y3RvcjsgcmV0dXJuICEhY3RvciAmJiAoY3RvciA9PT0gR2VuZXJhdG9yRnVuY3Rpb24gfHwgXCJHZW5lcmF0b3JGdW5jdGlvblwiID09PSAoY3Rvci5kaXNwbGF5TmFtZSB8fCBjdG9yLm5hbWUpKTsgfSwgZXhwb3J0cy5tYXJrID0gZnVuY3Rpb24gKGdlbkZ1bikgeyByZXR1cm4gT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKGdlbkZ1biwgR2VuZXJhdG9yRnVuY3Rpb25Qcm90b3R5cGUpIDogKGdlbkZ1bi5fX3Byb3RvX18gPSBHZW5lcmF0b3JGdW5jdGlvblByb3RvdHlwZSwgZGVmaW5lKGdlbkZ1biwgdG9TdHJpbmdUYWdTeW1ib2wsIFwiR2VuZXJhdG9yRnVuY3Rpb25cIikpLCBnZW5GdW4ucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZShHcCksIGdlbkZ1bjsgfSwgZXhwb3J0cy5hd3JhcCA9IGZ1bmN0aW9uIChhcmcpIHsgcmV0dXJuIHsgX19hd2FpdDogYXJnIH07IH0sIGRlZmluZUl0ZXJhdG9yTWV0aG9kcyhBc3luY0l0ZXJhdG9yLnByb3RvdHlwZSksIGRlZmluZShBc3luY0l0ZXJhdG9yLnByb3RvdHlwZSwgYXN5bmNJdGVyYXRvclN5bWJvbCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSksIGV4cG9ydHMuQXN5bmNJdGVyYXRvciA9IEFzeW5jSXRlcmF0b3IsIGV4cG9ydHMuYXN5bmMgPSBmdW5jdGlvbiAoaW5uZXJGbiwgb3V0ZXJGbiwgc2VsZiwgdHJ5TG9jc0xpc3QsIFByb21pc2VJbXBsKSB7IHZvaWQgMCA9PT0gUHJvbWlzZUltcGwgJiYgKFByb21pc2VJbXBsID0gUHJvbWlzZSk7IHZhciBpdGVyID0gbmV3IEFzeW5jSXRlcmF0b3Iod3JhcChpbm5lckZuLCBvdXRlckZuLCBzZWxmLCB0cnlMb2NzTGlzdCksIFByb21pc2VJbXBsKTsgcmV0dXJuIGV4cG9ydHMuaXNHZW5lcmF0b3JGdW5jdGlvbihvdXRlckZuKSA/IGl0ZXIgOiBpdGVyLm5leHQoKS50aGVuKGZ1bmN0aW9uIChyZXN1bHQpIHsgcmV0dXJuIHJlc3VsdC5kb25lID8gcmVzdWx0LnZhbHVlIDogaXRlci5uZXh0KCk7IH0pOyB9LCBkZWZpbmVJdGVyYXRvck1ldGhvZHMoR3ApLCBkZWZpbmUoR3AsIHRvU3RyaW5nVGFnU3ltYm9sLCBcIkdlbmVyYXRvclwiKSwgZGVmaW5lKEdwLCBpdGVyYXRvclN5bWJvbCwgZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSksIGRlZmluZShHcCwgXCJ0b1N0cmluZ1wiLCBmdW5jdGlvbiAoKSB7IHJldHVybiBcIltvYmplY3QgR2VuZXJhdG9yXVwiOyB9KSwgZXhwb3J0cy5rZXlzID0gZnVuY3Rpb24gKHZhbCkgeyB2YXIgb2JqZWN0ID0gT2JqZWN0KHZhbCksIGtleXMgPSBbXTsgZm9yICh2YXIga2V5IGluIG9iamVjdCkga2V5cy5wdXNoKGtleSk7IHJldHVybiBrZXlzLnJldmVyc2UoKSwgZnVuY3Rpb24gbmV4dCgpIHsgZm9yICg7IGtleXMubGVuZ3RoOykgeyB2YXIga2V5ID0ga2V5cy5wb3AoKTsgaWYgKGtleSBpbiBvYmplY3QpIHJldHVybiBuZXh0LnZhbHVlID0ga2V5LCBuZXh0LmRvbmUgPSAhMSwgbmV4dDsgfSByZXR1cm4gbmV4dC5kb25lID0gITAsIG5leHQ7IH07IH0sIGV4cG9ydHMudmFsdWVzID0gdmFsdWVzLCBDb250ZXh0LnByb3RvdHlwZSA9IHsgY29uc3RydWN0b3I6IENvbnRleHQsIHJlc2V0OiBmdW5jdGlvbiByZXNldChza2lwVGVtcFJlc2V0KSB7IGlmICh0aGlzLnByZXYgPSAwLCB0aGlzLm5leHQgPSAwLCB0aGlzLnNlbnQgPSB0aGlzLl9zZW50ID0gdW5kZWZpbmVkLCB0aGlzLmRvbmUgPSAhMSwgdGhpcy5kZWxlZ2F0ZSA9IG51bGwsIHRoaXMubWV0aG9kID0gXCJuZXh0XCIsIHRoaXMuYXJnID0gdW5kZWZpbmVkLCB0aGlzLnRyeUVudHJpZXMuZm9yRWFjaChyZXNldFRyeUVudHJ5KSwgIXNraXBUZW1wUmVzZXQpIGZvciAodmFyIG5hbWUgaW4gdGhpcykgXCJ0XCIgPT09IG5hbWUuY2hhckF0KDApICYmIGhhc093bi5jYWxsKHRoaXMsIG5hbWUpICYmICFpc05hTigrbmFtZS5zbGljZSgxKSkgJiYgKHRoaXNbbmFtZV0gPSB1bmRlZmluZWQpOyB9LCBzdG9wOiBmdW5jdGlvbiBzdG9wKCkgeyB0aGlzLmRvbmUgPSAhMDsgdmFyIHJvb3RSZWNvcmQgPSB0aGlzLnRyeUVudHJpZXNbMF0uY29tcGxldGlvbjsgaWYgKFwidGhyb3dcIiA9PT0gcm9vdFJlY29yZC50eXBlKSB0aHJvdyByb290UmVjb3JkLmFyZzsgcmV0dXJuIHRoaXMucnZhbDsgfSwgZGlzcGF0Y2hFeGNlcHRpb246IGZ1bmN0aW9uIGRpc3BhdGNoRXhjZXB0aW9uKGV4Y2VwdGlvbikgeyBpZiAodGhpcy5kb25lKSB0aHJvdyBleGNlcHRpb247IHZhciBjb250ZXh0ID0gdGhpczsgZnVuY3Rpb24gaGFuZGxlKGxvYywgY2F1Z2h0KSB7IHJldHVybiByZWNvcmQudHlwZSA9IFwidGhyb3dcIiwgcmVjb3JkLmFyZyA9IGV4Y2VwdGlvbiwgY29udGV4dC5uZXh0ID0gbG9jLCBjYXVnaHQgJiYgKGNvbnRleHQubWV0aG9kID0gXCJuZXh0XCIsIGNvbnRleHQuYXJnID0gdW5kZWZpbmVkKSwgISFjYXVnaHQ7IH0gZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgeyB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV0sIHJlY29yZCA9IGVudHJ5LmNvbXBsZXRpb247IGlmIChcInJvb3RcIiA9PT0gZW50cnkudHJ5TG9jKSByZXR1cm4gaGFuZGxlKFwiZW5kXCIpOyBpZiAoZW50cnkudHJ5TG9jIDw9IHRoaXMucHJldikgeyB2YXIgaGFzQ2F0Y2ggPSBoYXNPd24uY2FsbChlbnRyeSwgXCJjYXRjaExvY1wiKSwgaGFzRmluYWxseSA9IGhhc093bi5jYWxsKGVudHJ5LCBcImZpbmFsbHlMb2NcIik7IGlmIChoYXNDYXRjaCAmJiBoYXNGaW5hbGx5KSB7IGlmICh0aGlzLnByZXYgPCBlbnRyeS5jYXRjaExvYykgcmV0dXJuIGhhbmRsZShlbnRyeS5jYXRjaExvYywgITApOyBpZiAodGhpcy5wcmV2IDwgZW50cnkuZmluYWxseUxvYykgcmV0dXJuIGhhbmRsZShlbnRyeS5maW5hbGx5TG9jKTsgfSBlbHNlIGlmIChoYXNDYXRjaCkgeyBpZiAodGhpcy5wcmV2IDwgZW50cnkuY2F0Y2hMb2MpIHJldHVybiBoYW5kbGUoZW50cnkuY2F0Y2hMb2MsICEwKTsgfSBlbHNlIHsgaWYgKCFoYXNGaW5hbGx5KSB0aHJvdyBuZXcgRXJyb3IoXCJ0cnkgc3RhdGVtZW50IHdpdGhvdXQgY2F0Y2ggb3IgZmluYWxseVwiKTsgaWYgKHRoaXMucHJldiA8IGVudHJ5LmZpbmFsbHlMb2MpIHJldHVybiBoYW5kbGUoZW50cnkuZmluYWxseUxvYyk7IH0gfSB9IH0sIGFicnVwdDogZnVuY3Rpb24gYWJydXB0KHR5cGUsIGFyZykgeyBmb3IgKHZhciBpID0gdGhpcy50cnlFbnRyaWVzLmxlbmd0aCAtIDE7IGkgPj0gMDsgLS1pKSB7IHZhciBlbnRyeSA9IHRoaXMudHJ5RW50cmllc1tpXTsgaWYgKGVudHJ5LnRyeUxvYyA8PSB0aGlzLnByZXYgJiYgaGFzT3duLmNhbGwoZW50cnksIFwiZmluYWxseUxvY1wiKSAmJiB0aGlzLnByZXYgPCBlbnRyeS5maW5hbGx5TG9jKSB7IHZhciBmaW5hbGx5RW50cnkgPSBlbnRyeTsgYnJlYWs7IH0gfSBmaW5hbGx5RW50cnkgJiYgKFwiYnJlYWtcIiA9PT0gdHlwZSB8fCBcImNvbnRpbnVlXCIgPT09IHR5cGUpICYmIGZpbmFsbHlFbnRyeS50cnlMb2MgPD0gYXJnICYmIGFyZyA8PSBmaW5hbGx5RW50cnkuZmluYWxseUxvYyAmJiAoZmluYWxseUVudHJ5ID0gbnVsbCk7IHZhciByZWNvcmQgPSBmaW5hbGx5RW50cnkgPyBmaW5hbGx5RW50cnkuY29tcGxldGlvbiA6IHt9OyByZXR1cm4gcmVjb3JkLnR5cGUgPSB0eXBlLCByZWNvcmQuYXJnID0gYXJnLCBmaW5hbGx5RW50cnkgPyAodGhpcy5tZXRob2QgPSBcIm5leHRcIiwgdGhpcy5uZXh0ID0gZmluYWxseUVudHJ5LmZpbmFsbHlMb2MsIENvbnRpbnVlU2VudGluZWwpIDogdGhpcy5jb21wbGV0ZShyZWNvcmQpOyB9LCBjb21wbGV0ZTogZnVuY3Rpb24gY29tcGxldGUocmVjb3JkLCBhZnRlckxvYykgeyBpZiAoXCJ0aHJvd1wiID09PSByZWNvcmQudHlwZSkgdGhyb3cgcmVjb3JkLmFyZzsgcmV0dXJuIFwiYnJlYWtcIiA9PT0gcmVjb3JkLnR5cGUgfHwgXCJjb250aW51ZVwiID09PSByZWNvcmQudHlwZSA/IHRoaXMubmV4dCA9IHJlY29yZC5hcmcgOiBcInJldHVyblwiID09PSByZWNvcmQudHlwZSA/ICh0aGlzLnJ2YWwgPSB0aGlzLmFyZyA9IHJlY29yZC5hcmcsIHRoaXMubWV0aG9kID0gXCJyZXR1cm5cIiwgdGhpcy5uZXh0ID0gXCJlbmRcIikgOiBcIm5vcm1hbFwiID09PSByZWNvcmQudHlwZSAmJiBhZnRlckxvYyAmJiAodGhpcy5uZXh0ID0gYWZ0ZXJMb2MpLCBDb250aW51ZVNlbnRpbmVsOyB9LCBmaW5pc2g6IGZ1bmN0aW9uIGZpbmlzaChmaW5hbGx5TG9jKSB7IGZvciAodmFyIGkgPSB0aGlzLnRyeUVudHJpZXMubGVuZ3RoIC0gMTsgaSA+PSAwOyAtLWkpIHsgdmFyIGVudHJ5ID0gdGhpcy50cnlFbnRyaWVzW2ldOyBpZiAoZW50cnkuZmluYWxseUxvYyA9PT0gZmluYWxseUxvYykgcmV0dXJuIHRoaXMuY29tcGxldGUoZW50cnkuY29tcGxldGlvbiwgZW50cnkuYWZ0ZXJMb2MpLCByZXNldFRyeUVudHJ5KGVudHJ5KSwgQ29udGludWVTZW50aW5lbDsgfSB9LCBcImNhdGNoXCI6IGZ1bmN0aW9uIF9jYXRjaCh0cnlMb2MpIHsgZm9yICh2YXIgaSA9IHRoaXMudHJ5RW50cmllcy5sZW5ndGggLSAxOyBpID49IDA7IC0taSkgeyB2YXIgZW50cnkgPSB0aGlzLnRyeUVudHJpZXNbaV07IGlmIChlbnRyeS50cnlMb2MgPT09IHRyeUxvYykgeyB2YXIgcmVjb3JkID0gZW50cnkuY29tcGxldGlvbjsgaWYgKFwidGhyb3dcIiA9PT0gcmVjb3JkLnR5cGUpIHsgdmFyIHRocm93biA9IHJlY29yZC5hcmc7IHJlc2V0VHJ5RW50cnkoZW50cnkpOyB9IHJldHVybiB0aHJvd247IH0gfSB0aHJvdyBuZXcgRXJyb3IoXCJpbGxlZ2FsIGNhdGNoIGF0dGVtcHRcIik7IH0sIGRlbGVnYXRlWWllbGQ6IGZ1bmN0aW9uIGRlbGVnYXRlWWllbGQoaXRlcmFibGUsIHJlc3VsdE5hbWUsIG5leHRMb2MpIHsgcmV0dXJuIHRoaXMuZGVsZWdhdGUgPSB7IGl0ZXJhdG9yOiB2YWx1ZXMoaXRlcmFibGUpLCByZXN1bHROYW1lOiByZXN1bHROYW1lLCBuZXh0TG9jOiBuZXh0TG9jIH0sIFwibmV4dFwiID09PSB0aGlzLm1ldGhvZCAmJiAodGhpcy5hcmcgPSB1bmRlZmluZWQpLCBDb250aW51ZVNlbnRpbmVsOyB9IH0sIGV4cG9ydHM7IH1cbmZ1bmN0aW9uIGFzeW5jR2VuZXJhdG9yU3RlcChnZW4sIHJlc29sdmUsIHJlamVjdCwgX25leHQsIF90aHJvdywga2V5LCBhcmcpIHsgdHJ5IHsgdmFyIGluZm8gPSBnZW5ba2V5XShhcmcpOyB2YXIgdmFsdWUgPSBpbmZvLnZhbHVlOyB9IGNhdGNoIChlcnJvcikgeyByZWplY3QoZXJyb3IpOyByZXR1cm47IH0gaWYgKGluZm8uZG9uZSkgeyByZXNvbHZlKHZhbHVlKTsgfSBlbHNlIHsgUHJvbWlzZS5yZXNvbHZlKHZhbHVlKS50aGVuKF9uZXh0LCBfdGhyb3cpOyB9IH1cbmZ1bmN0aW9uIF9hc3luY1RvR2VuZXJhdG9yKGZuKSB7IHJldHVybiBmdW5jdGlvbiAoKSB7IHZhciBzZWxmID0gdGhpcywgYXJncyA9IGFyZ3VtZW50czsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdmFyIGdlbiA9IGZuLmFwcGx5KHNlbGYsIGFyZ3MpOyBmdW5jdGlvbiBfbmV4dCh2YWx1ZSkgeyBhc3luY0dlbmVyYXRvclN0ZXAoZ2VuLCByZXNvbHZlLCByZWplY3QsIF9uZXh0LCBfdGhyb3csIFwibmV4dFwiLCB2YWx1ZSk7IH0gZnVuY3Rpb24gX3Rocm93KGVycikgeyBhc3luY0dlbmVyYXRvclN0ZXAoZ2VuLCByZXNvbHZlLCByZWplY3QsIF9uZXh0LCBfdGhyb3csIFwidGhyb3dcIiwgZXJyKTsgfSBfbmV4dCh1bmRlZmluZWQpOyB9KTsgfTsgfVxuaW1wb3J0IHsgSHRtbDVRcmNvZGVTY2FubmVyLCBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZSwgSHRtbDVRcmNvZGVTdXBwb3J0ZWRGb3JtYXRzIH0gZnJvbSBcImh0bWw1LXFyY29kZVwiO1xuaW1wb3J0IHsgZWQ0NDggfSBmcm9tIFwiQG5vYmxlL2N1cnZlcy9lZDQ0OFwiO1xuaW1wb3J0IHsgQnVmZmVyIH0gZnJvbSBcImJ1ZmZlclwiO1xudmFyIGN1cnJlbnRseUFkZGluZ0l0ZW1CeVRhZyA9IG5ldyBNYXAoKTtcbnZhciByZWNlaXZlZF9pdGVtcyA9IHt9O1xudmFyIGNvbmZpZztcbnZhciBzY2FubmVyID0gbmV3IEh0bWw1UXJjb2RlU2Nhbm5lcihcInJlYWRlclwiLCB7XG4gIGZwczogMTAsXG4gIHFyYm94OiB7XG4gICAgd2lkdGg6IDI1MCxcbiAgICBoZWlnaHQ6IDI1MFxuICB9LFxuICBzaG93VG9yY2hCdXR0b25JZlN1cHBvcnRlZDogdHJ1ZSxcbiAgZm9ybWF0c1RvU3VwcG9ydDogW0h0bWw1UXJjb2RlU3VwcG9ydGVkRm9ybWF0cy5RUl9DT0RFXSxcbiAgLy90aGVyZSBhcmUgbWFueSBvdGhlciB0eXBlcyBvZiBjb2RlcyBvbiB0aGUgbGFiZWxzIHdlIGRvIG5vdCB3YW50XG4gIHJlbWVtYmVyTGFzdFVzZWRDYW1lcmE6IHRydWVcbn0pO1xudmFyIHNjYW5uZXJfYXVkaW8gPSBuZXcgQXVkaW8oXCIvYmVlcC53YXZcIik7XG5zY2FubmVyX2F1ZGlvLmxvYWQoKTtcbnZhciB0b2FzdERpdiA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwiYm90dG9tVG9hc3RcIik7XG5cbi8qXG4gKiBIZWxwZXIgZnVuY3Rpb25zXG4gKi9cbmZ1bmN0aW9uIGh0b2EoaCkge1xuICByZXR1cm4gVWludDhBcnJheS5mcm9tKEJ1ZmZlci5mcm9tKGgsIFwiaGV4XCIpKTtcbn1cbmZ1bmN0aW9uIHRvYXN0KHRpdGxlLCBtZXNzYWdlKSB7XG4gIHRvYXN0RGl2LmNoaWxkcmVuWzBdLmNoaWxkcmVuWzBdLmlubmVySFRNTCA9IHRpdGxlO1xuICB0b2FzdERpdi5jaGlsZHJlblsxXS5pbm5lckhUTUwgPSBtZXNzYWdlO1xuICB0b2FzdERpdi5jbGFzc0xpc3QucmVtb3ZlKFwiaGlkZVwiKTtcbiAgdG9hc3REaXYuY2xhc3NMaXN0LmFkZChcInNob3dcIik7XG4gIHRvYXN0RGl2LmNsYXNzTGlzdC5hZGQoXCJzaG93aW5nXCIpO1xuICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICB0b2FzdERpdi5jbGFzc0xpc3QucmVtb3ZlKFwic2hvd1wiKTtcbiAgICB0b2FzdERpdi5jbGFzc0xpc3QucmVtb3ZlKFwic2hvd2luZ1wiKTtcbiAgICB0b2FzdERpdi5jbGFzc0xpc3QuYWRkKFwiaGlkZVwiKTtcbiAgfSwgMzAwMCk7XG59XG5mdW5jdGlvbiBmZXRjaFdpdGhBdXRoKF94LCBfeDIpIHtcbiAgcmV0dXJuIF9mZXRjaFdpdGhBdXRoLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfZmV0Y2hXaXRoQXV0aCgpIHtcbiAgX2ZldGNoV2l0aEF1dGggPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUoaW5wdXQsIGluaXQpIHtcbiAgICB2YXIgcmVzcG9uc2U7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUkKF9jb250ZXh0KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dC5wcmV2ID0gX2NvbnRleHQubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKGluaXQgPT0gdW5kZWZpbmVkIHx8IGluaXQgPT0gbnVsbCkge1xuICAgICAgICAgICAgaW5pdCA9IHt9O1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoaW5pdFtcImhlYWRlcnNcIl0gPT0gbnVsbCkge1xuICAgICAgICAgICAgaW5pdFtcImhlYWRlcnNcIl0gPSB7fTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5nZXRJdGVtKFwiYWNjZXNzX3Rva2VuXCIpKSB7XG4gICAgICAgICAgICBfY29udGV4dC5uZXh0ID0gNTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dC5uZXh0ID0gNTtcbiAgICAgICAgICByZXR1cm4gbG9naW4oKTtcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgIGluaXRbXCJoZWFkZXJzXCJdW1wiQXV0aG9yaXphdGlvblwiXSA9IFwiQmVhcmVyIFwiICsgd2luZG93LnNlc3Npb25TdG9yYWdlLmdldEl0ZW0oXCJhY2Nlc3NfdG9rZW5cIik7XG4gICAgICAgICAgX2NvbnRleHQubmV4dCA9IDg7XG4gICAgICAgICAgcmV0dXJuIGZldGNoKGlucHV0LCBpbml0KTtcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQuc2VudDtcbiAgICAgICAgY2FzZSA5OlxuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyA9PSA0MDEpKSB7XG4gICAgICAgICAgICBfY29udGV4dC5uZXh0ID0gMTk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJGZXRjaCB3aXRoIGF1dGggZmFpbGVkIGZvclwiLCBpbnB1dCk7XG4gICAgICAgICAgX2NvbnRleHQubmV4dCA9IDEzO1xuICAgICAgICAgIHJldHVybiBsb2dpbigpO1xuICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgIGluaXRbXCJoZWFkZXJzXCJdW1wiQXV0aG9yaXphdGlvblwiXSA9IFwiQmVhcmVyIFwiICsgd2luZG93LnNlc3Npb25TdG9yYWdlLmdldEl0ZW0oXCJhY2Nlc3NfdG9rZW5cIik7XG4gICAgICAgICAgX2NvbnRleHQubmV4dCA9IDE2O1xuICAgICAgICAgIHJldHVybiBmZXRjaChpbnB1dCwgaW5pdCk7XG4gICAgICAgIGNhc2UgMTY6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dC5zZW50O1xuICAgICAgICAgIF9jb250ZXh0Lm5leHQgPSA5O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDE5OlxuICAgICAgICAgIHJldHVybiBfY29udGV4dC5hYnJ1cHQoXCJyZXR1cm5cIiwgcmVzcG9uc2UpO1xuICAgICAgICBjYXNlIDIwOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlKTtcbiAgfSkpO1xuICByZXR1cm4gX2ZldGNoV2l0aEF1dGguYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihfeDMsIF94NCkge1xuICByZXR1cm4gX2NoZWNrUmVzcG9uc2VGb3JFcnJvci5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2NoZWNrUmVzcG9uc2VGb3JFcnJvcigpIHtcbiAgX2NoZWNrUmVzcG9uc2VGb3JFcnJvciA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTIocmVzcG9uc2UsIG1lc3NhZ2UpIHtcbiAgICB2YXIgY29udGVudDtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTIkKF9jb250ZXh0Mikge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQyLnByZXYgPSBfY29udGV4dDIubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEocmVzcG9uc2Uuc3RhdHVzICE9PSAyMDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDIubmV4dCA9IDc7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQyLm5leHQgPSAzO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBjb250ZW50ID0gX2NvbnRleHQyLnNlbnQ7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJHb3QgUmVzcG9uc2UgRXJyb3I6XCIsIG1lc3NhZ2UsIHJlc3BvbnNlKTtcbiAgICAgICAgICBhbGVydChtZXNzYWdlICsgXCI7IFN0YXR1czogXCIgKyByZXNwb25zZS5zdGF0dXMgKyBcIjsgQ29udGVudDogXCIgKyBjb250ZW50KTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQyLmFicnVwdChcInJldHVyblwiLCBmYWxzZSk7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQyLmFicnVwdChcInJldHVyblwiLCB0cnVlKTtcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Mi5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTIpO1xuICB9KSk7XG4gIHJldHVybiBfY2hlY2tSZXNwb25zZUZvckVycm9yLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBnZXRDb25maWcoKSB7XG4gIHJldHVybiBfZ2V0Q29uZmlnLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfZ2V0Q29uZmlnKCkge1xuICBfZ2V0Q29uZmlnID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMygpIHtcbiAgICB2YXIgY29uZmlnX3JlcXVlc3Q7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUzJChfY29udGV4dDMpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0My5wcmV2ID0gX2NvbnRleHQzLm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGlmICghKGNvbmZpZyA9PSB1bmRlZmluZWQpKSB7XG4gICAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDEyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0My5uZXh0ID0gMztcbiAgICAgICAgICByZXR1cm4gZmV0Y2goXCJjb25maWcuanNvblwiKTtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGNvbmZpZ19yZXF1ZXN0ID0gX2NvbnRleHQzLnNlbnQ7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJMb2FkaW5nIGNvbmZpZ1wiKTtcbiAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDc7XG4gICAgICAgICAgcmV0dXJuIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihjb25maWdfcmVxdWVzdCwgXCJDb3VsZCBub3QgbG9hZCBjb25maWdcIik7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICBpZiAoIV9jb250ZXh0My5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDMubmV4dCA9IDEyO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0My5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIGNvbmZpZ19yZXF1ZXN0Lmpzb24oKTtcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICBjb25maWcgPSBfY29udGV4dDMuc2VudDtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkxvYWRlZCBjb25maWdcIik7XG4gICAgICAgIGNhc2UgMTI6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQzLnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMyk7XG4gIH0pKTtcbiAgcmV0dXJuIF9nZXRDb25maWcuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIGxvZ2luKF94NSkge1xuICByZXR1cm4gX2xvZ2luLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfbG9naW4oKSB7XG4gIF9sb2dpbiA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTQocGFzc3dvcmRUb1RyeSkge1xuICAgIHZhciBsb2dpblN1Y2Nlc3MsIHBhc3N3b3JkLCBmb3JtLCByZXNwb25zZSwgcmVzdWx0O1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlNCQoX2NvbnRleHQ0KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDQucHJldiA9IF9jb250ZXh0NC5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlBlcmZvcm1pbmcgbG9naW5cIik7XG4gICAgICAgICAgbG9naW5TdWNjZXNzID0gZmFsc2U7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgICBpZiAocGFzc3dvcmRUb1RyeSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlVzaW5nIHBhc3N3b3JkIHRvIHRyeSBmcm9tIHBhcmFtZXRlclwiKTtcbiAgICAgICAgICAgIHBhc3N3b3JkID0gcGFzc3dvcmRUb1RyeTtcbiAgICAgICAgICAgIHBhc3N3b3JkVG9UcnkgPSB1bmRlZmluZWQ7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiUHJvbXB0aW5nIHVzZXIgZm9yIHNoYXJlZCBzZWNyZXQuXCIpO1xuICAgICAgICAgICAgcGFzc3dvcmQgPSBwcm9tcHQoXCJwcm92aWRlIHRoZSBzaGFyZWQgc2VjcmV0XCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgZm9ybS5hcHBlbmQoXCJncmFudF90eXBlXCIsIFwicGFzc3dvcmRcIik7XG4gICAgICAgICAgZm9ybS5hcHBlbmQoXCJ1c2VybmFtZVwiLCBcIndvcmtlclwiKTtcbiAgICAgICAgICBmb3JtLmFwcGVuZChcInBhc3N3b3JkXCIsIHBhc3N3b3JkKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlJlcXVlc3RpbmcgdG9rZW4uXCIpO1xuICAgICAgICAgIF9jb250ZXh0NC5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIGZldGNoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL3Rva2VuXCIsIHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgICAgICBib2R5OiBmb3JtXG4gICAgICAgICAgfSk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDQuc2VudDtcbiAgICAgICAgICBfY29udGV4dDQubmV4dCA9IDEzO1xuICAgICAgICAgIHJldHVybiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiTG9naW4gZmFpbGVkXCIpO1xuICAgICAgICBjYXNlIDEzOlxuICAgICAgICAgIGlmICghX2NvbnRleHQ0LnNlbnQpIHtcbiAgICAgICAgICAgIF9jb250ZXh0NC5uZXh0ID0gMjA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQ0Lm5leHQgPSAxNjtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDE2OlxuICAgICAgICAgIHJlc3VsdCA9IF9jb250ZXh0NC5zZW50O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiR290IHRva2VuXCIpO1xuICAgICAgICAgIHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5zZXRJdGVtKFwiYWNjZXNzX3Rva2VuXCIsIHJlc3VsdC5hY2Nlc3NfdG9rZW4pO1xuICAgICAgICAgIGxvZ2luU3VjY2VzcyA9IHRydWU7XG4gICAgICAgIGNhc2UgMjA6XG4gICAgICAgICAgaWYgKCFsb2dpblN1Y2Nlc3MpIHtcbiAgICAgICAgICAgIF9jb250ZXh0NC5uZXh0ID0gMjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAyMTpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDQuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWU0KTtcbiAgfSkpO1xuICByZXR1cm4gX2xvZ2luLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiB1cGRhdGVJdGVtc1ZpZXcoKSB7XG4gIGNvbnNvbGUubG9nKFwiVXBkYXRpbmcgaXRlbXMgdmlld1wiKTtcbiAgdmFyIGl0ZW1zID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihcIiNpdGVtc1wiKTtcbiAgaXRlbXMuaW5uZXJIVE1MID0gXCJcIjtcbiAgZm9yICh2YXIgaXRlbSBpbiByZWNlaXZlZF9pdGVtcykge1xuICAgIHZhciBsaSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJsaVwiKTtcbiAgICBjb25zb2xlLmxvZyhpdGVtKTtcbiAgICBjb25zb2xlLmxvZyhyZWNlaXZlZF9pdGVtc1tpdGVtXSk7XG4gICAgbGkuaW5uZXJIVE1MID0gXCI8ZGl2IGlkPVxcXCJpdGVtX1wiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS51dWlkICsgXCJcXFwiIGNsYXNzPVxcXCJhbGVydCBhbGVydC1zdWNjZXNzXFxcIiByb2xlPVxcXCJhbGVydFxcXCI+XCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnRhZyArIFwiIChcIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0uYWRkcmVzc2VlICsgXCIsIFwiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS50ZWFtICsgXCIpXCIgKyBcIiZlbXNwOzxzcGFuIGNsYXNzPVxcXCJiYWRnZSBiYWRnZS1saWdodFxcXCI+XCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5udW0gKyBcIjwvc3Bhbj5cIiArIFwiJmVtc3A7PGJ1dHRvbiBjbGFzcz1cXFwiYnRuIGJ0bi1wcmltYXJ5XFxcIiBvbmNsaWNrPVxcXCJsaWIuaW5jcmVhc2VJdGVtQ291bnQoJ1wiICsgcmVjZWl2ZWRfaXRlbXNbaXRlbV0uaXRlbS51dWlkICsgXCInKVxcXCI+KzwvYnV0dG9uPlwiICsgXCImZW1zcDs8YnV0dG9uIGNsYXNzPVxcXCJidG4gYnRuLXByaW1hcnlcXFwiIG9uY2xpY2s9XFxcImxpYi5kZWNyZWFzZUl0ZW1Db3VudCgnXCIgKyByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnV1aWQgKyBcIicpXFxcIj4tPC9idXR0b24+PC9kaXY+XCI7XG4gICAgaXRlbXMuYXBwZW5kQ2hpbGQobGkpO1xuICB9XG59XG5cbi8qXG4gKiB2YXJpb3VzIGFkZCBJdGVtcyBmdW5jdGlvbnNcbiAqL1xuXG5leHBvcnQgZnVuY3Rpb24gb25UYWdUZXh0VXBkYXRlKF94Nikge1xuICByZXR1cm4gX29uVGFnVGV4dFVwZGF0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX29uVGFnVGV4dFVwZGF0ZSgpIHtcbiAgX29uVGFnVGV4dFVwZGF0ZSA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTUoZWxlbWVudCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlNSQoX2NvbnRleHQ1KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDUucHJldiA9IF9jb250ZXh0NS5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBpZiAoIShlbGVtZW50LnZhbHVlLmxlbmd0aCA9PSAwKSkge1xuICAgICAgICAgICAgX2NvbnRleHQ1Lm5leHQgPSA1O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIGVsZW1lbnQuc2V0Q3VzdG9tVmFsaWRpdHkoXCJcIik7XG4gICAgICAgICAgZWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKFwiaXMtaW52YWxpZFwiKTtcbiAgICAgICAgICBfY29udGV4dDUubmV4dCA9IDEyO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDU6XG4gICAgICAgICAgaWYgKCEoZWxlbWVudC52YWx1ZS5sZW5ndGggIT0gNikpIHtcbiAgICAgICAgICAgIF9jb250ZXh0NS5uZXh0ID0gMTE7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgZWxlbWVudC5zZXRDdXN0b21WYWxpZGl0eShcIkNvZGUgbXVzdCBiZSA2IGNoYXJzIGxvbmcuXCIpO1xuICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LmFkZChcImlzLWludmFsaWRcIik7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0NS5hYnJ1cHQoXCJyZXR1cm5cIik7XG4gICAgICAgIGNhc2UgMTE6XG4gICAgICAgICAgdGFnRW50ZXJlZChlbGVtZW50KTtcbiAgICAgICAgY2FzZSAxMjpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDUuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWU1KTtcbiAgfSkpO1xuICByZXR1cm4gX29uVGFnVGV4dFVwZGF0ZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIG9uVGFnSW5wdXRDaGFuZ2VkKF94Nykge1xuICByZXR1cm4gX29uVGFnSW5wdXRDaGFuZ2VkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfb25UYWdJbnB1dENoYW5nZWQoKSB7XG4gIF9vblRhZ0lucHV0Q2hhbmdlZCA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTYoZWxlbWVudCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlNiQoX2NvbnRleHQ2KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDYucHJldiA9IF9jb250ZXh0Ni5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAvLyBFbGVtZW50IGxvc3QgZm9jdXMgb3IgdXNlciBwcmVzc2VkIGVudGVyXG4gICAgICAgICAgaWYgKGVsZW1lbnQudmFsdWUubGVuZ3RoID09IDYpIHtcbiAgICAgICAgICAgIHRhZ0VudGVyZWQoZWxlbWVudCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVsZW1lbnQucmVwb3J0VmFsaWRpdHkoKTtcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDYuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWU2KTtcbiAgfSkpO1xuICByZXR1cm4gX29uVGFnSW5wdXRDaGFuZ2VkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiB0YWdFbnRlcmVkKF94OCkge1xuICByZXR1cm4gX3RhZ0VudGVyZWQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF90YWdFbnRlcmVkKCkge1xuICBfdGFnRW50ZXJlZCA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTcoZWxlbWVudCkge1xuICAgIHZhciB0YWcsIHN1Y2M7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWU3JChfY29udGV4dDcpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0Ny5wcmV2ID0gX2NvbnRleHQ3Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIHRhZyA9IGVsZW1lbnQudmFsdWU7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJUYWcgRW50ZXJlZFwiLCB0YWcpO1xuICAgICAgICAgIGlmICghY3VycmVudGx5QWRkaW5nSXRlbUJ5VGFnLmhhcyh0YWcpKSB7XG4gICAgICAgICAgICBfY29udGV4dDcubmV4dCA9IDQ7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0Ny5hYnJ1cHQoXCJyZXR1cm5cIik7XG4gICAgICAgIGNhc2UgNDpcbiAgICAgICAgICBjdXJyZW50bHlBZGRpbmdJdGVtQnlUYWcuc2V0KHRhZywgXCJcIik7XG4gICAgICAgICAgX2NvbnRleHQ3Lm5leHQgPSA3O1xuICAgICAgICAgIHJldHVybiBhZGRJdGVtQnlUYWcoZWxlbWVudC52YWx1ZSk7XG4gICAgICAgIGNhc2UgNzpcbiAgICAgICAgICBzdWNjID0gX2NvbnRleHQ3LnNlbnQ7XG4gICAgICAgICAgaWYgKHN1Y2MpIHtcbiAgICAgICAgICAgIGVsZW1lbnQuY2xhc3NMaXN0LnJlbW92ZShcImlzLWludmFsaWRcIik7XG4gICAgICAgICAgICBlbGVtZW50LnZhbHVlID0gXCJcIjtcbiAgICAgICAgICAgIGVsZW1lbnQuc2V0Q3VzdG9tVmFsaWRpdHkoXCJcIik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGVsZW1lbnQuc2V0Q3VzdG9tVmFsaWRpdHkoXCJVbmtub3duIGl0ZW1cIik7XG4gICAgICAgICAgICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoXCJpcy1pbnZhbGlkXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBlbGVtZW50LnJlcG9ydFZhbGlkaXR5KCk7XG4gICAgICAgICAgY3VycmVudGx5QWRkaW5nSXRlbUJ5VGFnW1wiZGVsZXRlXCJdKHRhZyk7XG4gICAgICAgIGNhc2UgMTE6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ3LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlNyk7XG4gIH0pKTtcbiAgcmV0dXJuIF90YWdFbnRlcmVkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gYWRkSXRlbUJ5VGFnKF94OSkge1xuICByZXR1cm4gX2FkZEl0ZW1CeVRhZy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2FkZEl0ZW1CeVRhZygpIHtcbiAgX2FkZEl0ZW1CeVRhZyA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTgodGFnKSB7XG4gICAgdmFyIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlOCQoX2NvbnRleHQ4KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDgucHJldiA9IF9jb250ZXh0OC5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBpZiAoISh0YWcubGVuZ3RoICE9IDYpKSB7XG4gICAgICAgICAgICBfY29udGV4dDgubmV4dCA9IDI7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgdGhyb3cgXCJJbnRlcm5hbCBFcnJvcjogVGFnIG5vdCBsZW5ndGggNi5cIjtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHRhZyA9IHRhZy50b0xvd2VyQ2FzZSgpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiVHJ5aW5nIHRvIGFkZCBpdGVtIGJ5IHRhZzpcIiwgdGFnKTtcbiAgICAgICAgICBfY29udGV4dDgubmV4dCA9IDY7XG4gICAgICAgICAgcmV0dXJuIGZldGNoV2l0aEF1dGgoY29uZmlnLmJhY2tlbmRfdXJsICsgXCIvdGFnL1wiICsgdGFnKTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQ4LnNlbnQ7XG4gICAgICAgICAgaWYgKCEocmVzcG9uc2Uuc3RhdHVzID09IDIwMCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0OC5uZXh0ID0gMTg7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQ4Lm5leHQgPSAxMDtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDEwOlxuICAgICAgICAgIHRyYWNraW5nX2l0ZW0gPSBfY29udGV4dDguc2VudDtcbiAgICAgICAgICBpZiAodHJhY2tpbmdfaXRlbS51dWlkIGluIHJlY2VpdmVkX2l0ZW1zKSB7XG4gICAgICAgICAgICByZWNlaXZlZF9pdGVtc1t0cmFja2luZ19pdGVtLnV1aWRdLm51bSArPSAxO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZWNlaXZlZF9pdGVtc1t0cmFja2luZ19pdGVtLnV1aWRdID0ge1xuICAgICAgICAgICAgICBcIm51bVwiOiAxLFxuICAgICAgICAgICAgICBcIml0ZW1cIjogdHJhY2tpbmdfaXRlbVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICB9XG4gICAgICAgICAgdXBkYXRlSXRlbXNWaWV3KCk7XG4gICAgICAgICAgc2Nhbm5lcl9hdWRpby5wbGF5KCk7XG4gICAgICAgICAgY29uc29sZS5sb2coXCJBZGRlZCBpdGVtIGJ5IHRhZ1wiKTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ4LmFicnVwdChcInJldHVyblwiLCB0cnVlKTtcbiAgICAgICAgY2FzZSAxODpcbiAgICAgICAgICBpZiAoIShyZXNwb25zZS5zdGF0dXMgPT0gNDA0KSkge1xuICAgICAgICAgICAgX2NvbnRleHQ4Lm5leHQgPSAyMztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkl0ZW0gbm90IGZvdW5kXCIpO1xuICAgICAgICAgIHJldHVybiBfY29udGV4dDguYWJydXB0KFwicmV0dXJuXCIsIGZhbHNlKTtcbiAgICAgICAgY2FzZSAyMzpcbiAgICAgICAgICBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIGdldCBpdGVtIGZyb20gYmFja2VuZFwiKTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ4LmFicnVwdChcInJldHVyblwiLCBmYWxzZSk7XG4gICAgICAgIGNhc2UgMjU6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQ4LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlOCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9hZGRJdGVtQnlUYWcuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIGhhbmRsZVFyRXJyb3IoX3gxMCwgX3gxMSkge1xuICByZXR1cm4gX2hhbmRsZVFyRXJyb3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9oYW5kbGVRckVycm9yKCkge1xuICBfaGFuZGxlUXJFcnJvciA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTkobXNnLCBlcnIpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTkkKF9jb250ZXh0OSkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQ5LnByZXYgPSBfY29udGV4dDkubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0OS5hYnJ1cHQoXCJyZXR1cm5cIik7XG4gICAgICAgIGNhc2UgMTpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDkuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWU5KTtcbiAgfSkpO1xuICByZXR1cm4gX2hhbmRsZVFyRXJyb3IuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIGRlYm91bmNlU2Nhbm5lcigpIHtcbiAgaWYgKHNjYW5uZXIuZ2V0U3RhdGUoKSAhPSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5TQ0FOTklORykge1xuICAgIHJldHVybjtcbiAgfVxuICBzY2FubmVyLnBhdXNlKGZhbHNlKTtcbiAgc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgaWYgKHNjYW5uZXIuZ2V0U3RhdGUoKSA9PSBIdG1sNVFyY29kZVNjYW5uZXJTdGF0ZS5QQVVTRUQpIHtcbiAgICAgIHNjYW5uZXIucmVzdW1lKCk7XG4gICAgfVxuICB9LCAxMDAwKTtcbn1cbmZ1bmN0aW9uIGhhbmRsZUl0ZW1TY2FuUmVzdWx0KF94MTIpIHtcbiAgcmV0dXJuIF9oYW5kbGVJdGVtU2NhblJlc3VsdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2hhbmRsZUl0ZW1TY2FuUmVzdWx0KCkge1xuICBfaGFuZGxlSXRlbVNjYW5SZXN1bHQgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxMChpdGVtX3V1aWQpIHtcbiAgICB2YXIgcmVzcG9uc2UsIHRyYWNraW5nX2l0ZW07XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxMCQoX2NvbnRleHQxMCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxMC5wcmV2ID0gX2NvbnRleHQxMC5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBkZWJvdW5jZVNjYW5uZXIoKTtcbiAgICAgICAgICBpZiAoIShpdGVtX3V1aWQubGVuZ3RoID09IDM2KSkge1xuICAgICAgICAgICAgX2NvbnRleHQxMC5uZXh0ID0gMjc7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJUcnlpbmcgdG8gYWRkIGl0ZW0gYnkgdXVpZCAoc2Nhbm5lZClcIik7XG4gICAgICAgICAgaWYgKCEoaXRlbV91dWlkIGluIHJlY2VpdmVkX2l0ZW1zKSkge1xuICAgICAgICAgICAgX2NvbnRleHQxMC5uZXh0ID0gMTA7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbaXRlbV91dWlkXS5udW0gKz0gMTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkluY3JlYXNlZCBjb3VudCBvZiBleGlzdGluZyBpdGVtIHV1aWRcIik7XG4gICAgICAgICAgdXBkYXRlSXRlbXNWaWV3KCk7XG4gICAgICAgICAgc2Nhbm5lcl9hdWRpby5wbGF5KCk7XG4gICAgICAgICAgX2NvbnRleHQxMC5uZXh0ID0gMjU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbaXRlbV91dWlkXSA9IHtcbiAgICAgICAgICAgIFwibnVtXCI6IDEsXG4gICAgICAgICAgICBcIml0ZW1cIjogbnVsbFxuICAgICAgICAgIH07XG4gICAgICAgICAgX2NvbnRleHQxMC5uZXh0ID0gMTM7XG4gICAgICAgICAgcmV0dXJuIGZldGNoV2l0aEF1dGgoY29uZmlnLmJhY2tlbmRfdXJsICsgXCIvaXRlbS9cIiArIGl0ZW1fdXVpZCk7XG4gICAgICAgIGNhc2UgMTM6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDEwLnNlbnQ7XG4gICAgICAgICAgaWYgKCEocmVzcG9uc2Uuc3RhdHVzID09IDIwMCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDI0O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MTAubmV4dCA9IDE3O1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgMTc6XG4gICAgICAgICAgdHJhY2tpbmdfaXRlbSA9IF9jb250ZXh0MTAuc2VudDtcbiAgICAgICAgICByZWNlaXZlZF9pdGVtc1tpdGVtX3V1aWRdID0ge1xuICAgICAgICAgICAgXCJudW1cIjogMSxcbiAgICAgICAgICAgIFwiaXRlbVwiOiB0cmFja2luZ19pdGVtXG4gICAgICAgICAgfTtcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgICBzY2FubmVyX2F1ZGlvLnBsYXkoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkFkZGVkIGl0ZW0gYnkgdXVpZC5cIik7XG4gICAgICAgICAgX2NvbnRleHQxMC5uZXh0ID0gMjU7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjQ6XG4gICAgICAgICAgaWYgKHJlc3BvbnNlLnN0YXR1cyA9PSA0MDQpIHtcbiAgICAgICAgICAgIGFsZXJ0KFwiSXRlbSBub3QgZm91bmRcIik7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIkl0ZW0gbm90IGZvdW5kXCIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIGdldCBpdGVtIGZyb20gYmFja2VuZFwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMjU6XG4gICAgICAgICAgX2NvbnRleHQxMC5uZXh0ID0gMjg7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgMjc6XG4gICAgICAgICAgYWxlcnQoXCJRUiBDb2RlIGlzIG5vdCBhIGJncCBjaGVja2luIGNvZGUuXCIpO1xuICAgICAgICBjYXNlIDI4OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTAuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxMCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9oYW5kbGVJdGVtU2NhblJlc3VsdC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGFkZEl0ZW1TY2FuKCkge1xuICByZXR1cm4gX2FkZEl0ZW1TY2FuLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfYWRkSXRlbVNjYW4oKSB7XG4gIF9hZGRJdGVtU2NhbiA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTExKCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTEkKF9jb250ZXh0MTEpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTEucHJldiA9IF9jb250ZXh0MTEubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJTdGFydGluZyBzY2FubmVyXCIpO1xuICAgICAgICAgIHNjYW5uZXIucmVuZGVyKGhhbmRsZUl0ZW1TY2FuUmVzdWx0LCBoYW5kbGVRckVycm9yKTtcbiAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChcInN0YXJ0U2NhblwiKS5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG4gICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoXCJzdG9wU2NhblwiKS5zdHlsZS5kaXNwbGF5ID0gXCJpbmxpbmUtYmxvY2tcIjtcbiAgICAgICAgY2FzZSA0OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTEuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxMSk7XG4gIH0pKTtcbiAgcmV0dXJuIF9hZGRJdGVtU2Nhbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHN0b3BTY2FubmluZ0l0ZW0oKSB7XG4gIHJldHVybiBfc3RvcFNjYW5uaW5nSXRlbS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX3N0b3BTY2FubmluZ0l0ZW0oKSB7XG4gIF9zdG9wU2Nhbm5pbmdJdGVtID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTIoKSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxMiQoX2NvbnRleHQxMikge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxMi5wcmV2ID0gX2NvbnRleHQxMi5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlN0b3BwaW5nIHNjYW5uZXJcIik7XG4gICAgICAgICAgc2Nhbm5lci5jbGVhcigpO1xuICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic3RhcnRTY2FuXCIpLnN0eWxlLmRpc3BsYXkgPSBcImlubGluZS1ibG9ja1wiO1xuICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKFwic3RvcFNjYW5cIikuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuICAgICAgICBjYXNlIDQ6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxMi5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTEyKTtcbiAgfSkpO1xuICByZXR1cm4gX3N0b3BTY2FubmluZ0l0ZW0uYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBhZGRJdGVtSW1hZ2UoX3gxMykge1xuICByZXR1cm4gX2FkZEl0ZW1JbWFnZS5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2FkZEl0ZW1JbWFnZSgpIHtcbiAgX2FkZEl0ZW1JbWFnZSA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTEzKGUpIHtcbiAgICB2YXIgZm9ybSwgcmVzcG9uc2UsIHRyYWNraW5nX2l0ZW07XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxMyQoX2NvbnRleHQxMykge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxMy5wcmV2ID0gX2NvbnRleHQxMy5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkFkZGluZyBpdGVtICBieSBpbWFnZVwiKTtcbiAgICAgICAgICBmb3JtID0gbmV3IEZvcm1EYXRhKCk7XG4gICAgICAgICAgZm9ybS5hcHBlbmQoXCJpbWFnZVwiLCBlLmZpbGVzWzBdKTtcbiAgICAgICAgICBfY29udGV4dDEzLm5leHQgPSA1O1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL2l0ZW0vcmVnaXN0ZXJcIiwge1xuICAgICAgICAgICAgbWV0aG9kOiBcIlBPU1RcIixcbiAgICAgICAgICAgIGJvZHk6IGZvcm1cbiAgICAgICAgICB9KTtcbiAgICAgICAgY2FzZSA1OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQxMy5zZW50O1xuICAgICAgICAgIF9jb250ZXh0MTMubmV4dCA9IDg7XG4gICAgICAgICAgcmV0dXJuIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihyZXNwb25zZSwgXCJGYWlsZWQgdG8gc2F2ZSBpdGVtXCIpO1xuICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgaWYgKCFfY29udGV4dDEzLnNlbnQpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTMubmV4dCA9IDE2O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MTMubmV4dCA9IDExO1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgMTE6XG4gICAgICAgICAgdHJhY2tpbmdfaXRlbSA9IF9jb250ZXh0MTMuc2VudDtcbiAgICAgICAgICByZWNlaXZlZF9pdGVtc1t0cmFja2luZ19pdGVtLnV1aWRdID0ge1xuICAgICAgICAgICAgXCJudW1cIjogMSxcbiAgICAgICAgICAgIFwiaXRlbVwiOiB0cmFja2luZ19pdGVtXG4gICAgICAgICAgfTtcbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgICBzY2FubmVyX2F1ZGlvLnBsYXkoKTtcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkFkZGVkIGl0ZW0gYnkgaW1hZ2UuXCIpO1xuICAgICAgICBjYXNlIDE2OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTMuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxMyk7XG4gIH0pKTtcbiAgcmV0dXJuIF9hZGRJdGVtSW1hZ2UuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmV4cG9ydCBmdW5jdGlvbiBkZWNyZWFzZUl0ZW1Db3VudChfeDE0KSB7XG4gIHJldHVybiBfZGVjcmVhc2VJdGVtQ291bnQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9kZWNyZWFzZUl0ZW1Db3VudCgpIHtcbiAgX2RlY3JlYXNlSXRlbUNvdW50ID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTQodXVpZCkge1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTQkKF9jb250ZXh0MTQpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTQucHJldiA9IF9jb250ZXh0MTQubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgaWYgKCEocmVjZWl2ZWRfaXRlbXNbdXVpZF0gPT0gbnVsbCkpIHtcbiAgICAgICAgICAgIF9jb250ZXh0MTQubmV4dCA9IDM7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgY29uc29sZS5sb2coXCJUcnlpbmcgdG8gZGVjcmVhc2UgaXRlbSBjb3VudCBvZiB1bmtub3duIGl0ZW1cIiwgdXVpZCk7XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTQuYWJydXB0KFwicmV0dXJuXCIpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgY29uc29sZS5sb2coXCJEZWNyZWFzaW5nIGl0ZW0gY291bnQgb2ZcIiwgdXVpZCk7XG4gICAgICAgICAgcmVjZWl2ZWRfaXRlbXNbdXVpZF1bXCJudW1cIl0tLTtcbiAgICAgICAgICBpZiAocmVjZWl2ZWRfaXRlbXNbdXVpZF1bXCJudW1cIl0gPD0gMCkge1xuICAgICAgICAgICAgZGVsZXRlIHJlY2VpdmVkX2l0ZW1zW3V1aWRdO1xuICAgICAgICAgIH1cbiAgICAgICAgICB1cGRhdGVJdGVtc1ZpZXcoKTtcbiAgICAgICAgY2FzZSA3OlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTQuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxNCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9kZWNyZWFzZUl0ZW1Db3VudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIGluY3JlYXNlSXRlbUNvdW50KF94MTUpIHtcbiAgcmV0dXJuIF9pbmNyZWFzZUl0ZW1Db3VudC5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuXG4vKlxuICogQ2hlY2tpbiB0aGUgc2VsZWN0ZWQgaXRlbXNcbiAqL1xuZnVuY3Rpb24gX2luY3JlYXNlSXRlbUNvdW50KCkge1xuICBfaW5jcmVhc2VJdGVtQ291bnQgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxNSh1dWlkKSB7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUxNSQoX2NvbnRleHQxNSkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQxNS5wcmV2ID0gX2NvbnRleHQxNS5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBpZiAoIShyZWNlaXZlZF9pdGVtc1t1dWlkXSA9PSBudWxsKSkge1xuICAgICAgICAgICAgX2NvbnRleHQxNS5uZXh0ID0gMztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zb2xlLmxvZyhcIlRyeWluZyB0byBpbmNyZWFzZSBpdGVtIGNvdW50IG9mIHVua25vd24gaXRlbVwiLCB1dWlkKTtcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxNS5hYnJ1cHQoXCJyZXR1cm5cIik7XG4gICAgICAgIGNhc2UgMzpcbiAgICAgICAgICBjb25zb2xlLmxvZyhcIkluY3JlYXNpbmcgaXRlbSBjb3VudCBvZlwiLCB1dWlkKTtcbiAgICAgICAgICByZWNlaXZlZF9pdGVtc1t1dWlkXVtcIm51bVwiXSsrO1xuICAgICAgICAgIHVwZGF0ZUl0ZW1zVmlldygpO1xuICAgICAgICBjYXNlIDY6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxNS5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTE1KTtcbiAgfSkpO1xuICByZXR1cm4gX2luY3JlYXNlSXRlbUNvdW50LmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gY2hlY2tpbkl0ZW1zKCkge1xuICByZXR1cm4gX2NoZWNraW5JdGVtcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZnVuY3Rpb24gX2NoZWNraW5JdGVtcygpIHtcbiAgX2NoZWNraW5JdGVtcyA9IF9hc3luY1RvR2VuZXJhdG9yKCAvKiNfX1BVUkVfXyovX3JlZ2VuZXJhdG9yUnVudGltZSgpLm1hcmsoZnVuY3Rpb24gX2NhbGxlZTE2KCkge1xuICAgIHZhciBzdWNjZXNzZnVsbENvdW50LCBpdGVtLCByZXNwb25zZSwgdHJhY2tpbmdfaXRlbTtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE2JChfY29udGV4dDE2KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE2LnByZXYgPSBfY29udGV4dDE2Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiQ2hlY2tpbmcgaW4gaXRlbXNcIik7XG4gICAgICAgICAgc3VjY2Vzc2Z1bGxDb3VudCA9IDA7XG4gICAgICAgICAgX2NvbnRleHQxNi50MCA9IF9yZWdlbmVyYXRvclJ1bnRpbWUoKS5rZXlzKHJlY2VpdmVkX2l0ZW1zKTtcbiAgICAgICAgY2FzZSAzOlxuICAgICAgICAgIGlmICgoX2NvbnRleHQxNi50MSA9IF9jb250ZXh0MTYudDAoKSkuZG9uZSkge1xuICAgICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gMTg7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgaXRlbSA9IF9jb250ZXh0MTYudDEudmFsdWU7XG4gICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gNztcbiAgICAgICAgICByZXR1cm4gZmV0Y2hXaXRoQXV0aChjb25maWcuYmFja2VuZF91cmwgKyBcIi9jaGVja2luXCIsIHtcbiAgICAgICAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgIFwiQ29udGVudC1UeXBlXCI6IFwiYXBwbGljYXRpb24vanNvblwiXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgYm9keTogSlNPTi5zdHJpbmdpZnkoe1xuICAgICAgICAgICAgICBcIml0ZW1fdXVpZFwiOiByZWNlaXZlZF9pdGVtc1tpdGVtXS5pdGVtLnV1aWQsXG4gICAgICAgICAgICAgIFwic3RvcmFnZV9uYW1lXCI6IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjc3RvcmFnZV9zZWxlY3RcIikudmFsdWUsXG4gICAgICAgICAgICAgIFwiYW1vdW50XCI6IHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLm51bVxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9KTtcbiAgICAgICAgY2FzZSA3OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQxNi5zZW50O1xuICAgICAgICAgIF9jb250ZXh0MTYubmV4dCA9IDEwO1xuICAgICAgICAgIHJldHVybiBjaGVja1Jlc3BvbnNlRm9yRXJyb3IocmVzcG9uc2UsIFwiRmFpbGVkIHRvIGNoZWNraW4gaXRlbSBcIiArIHJlY2VpdmVkX2l0ZW1zW2l0ZW1dLml0ZW0udGFnKTtcbiAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICBpZiAoIV9jb250ZXh0MTYuc2VudCkge1xuICAgICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gMTY7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICB9XG4gICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gMTM7XG4gICAgICAgICAgcmV0dXJuIHJlc3BvbnNlLmpzb24oKTtcbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICB0cmFja2luZ19pdGVtID0gX2NvbnRleHQxNi5zZW50O1xuICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLWxpbmUgbm8tdW51c2VkLXZhcnNcbiAgICAgICAgICBkZWxldGUgcmVjZWl2ZWRfaXRlbXNbdHJhY2tpbmdfaXRlbS51dWlkXTtcbiAgICAgICAgICBzdWNjZXNzZnVsbENvdW50Kys7XG4gICAgICAgIGNhc2UgMTY6XG4gICAgICAgICAgX2NvbnRleHQxNi5uZXh0ID0gMztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxODpcbiAgICAgICAgICB0b2FzdChcIkNoZWNrLUluIHN1Y2Nlc3NmdWxsLlwiLCBcIlRoZSBjaGVjay1pbiBvZiBcIiArIHN1Y2Nlc3NmdWxsQ291bnQgKyBcIiBpdGVtcyBjb21wbGV0ZWQgc3VjY2VzZnVsbHkuXCIpO1xuICAgICAgICAgIHVwZGF0ZUl0ZW1zVmlldygpO1xuICAgICAgICBjYXNlIDIwOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MTYuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUxNik7XG4gIH0pKTtcbiAgcmV0dXJuIF9jaGVja2luSXRlbXMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIG9uUmVjZXZpZXJTY2FuU3VjY2VzcyhfeDE2KSB7XG4gIHJldHVybiBfb25SZWNldmllclNjYW5TdWNjZXNzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfb25SZWNldmllclNjYW5TdWNjZXNzKCkge1xuICBfb25SZWNldmllclNjYW5TdWNjZXNzID0gX2FzeW5jVG9HZW5lcmF0b3IoIC8qI19fUFVSRV9fKi9fcmVnZW5lcmF0b3JSdW50aW1lKCkubWFyayhmdW5jdGlvbiBfY2FsbGVlMTcoc2Nhbm5lZENvZGUpIHtcbiAgICB2YXIgX3NjYW5uZWRDb2RlJHNwbGl0LCBfc2Nhbm5lZENvZGUkc3BsaXQyLCB1dWlkLCBzaWduYXR1cmUsIHJlc3BvbnNlLCB0cmFja2luZ19pdGVtO1xuICAgIHJldHVybiBfcmVnZW5lcmF0b3JSdW50aW1lKCkud3JhcChmdW5jdGlvbiBfY2FsbGVlMTckKF9jb250ZXh0MTcpIHtcbiAgICAgIHdoaWxlICgxKSBzd2l0Y2ggKF9jb250ZXh0MTcucHJldiA9IF9jb250ZXh0MTcubmV4dCkge1xuICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgZGVib3VuY2VTY2FubmVyKCk7XG4gICAgICAgICAgX3NjYW5uZWRDb2RlJHNwbGl0ID0gc2Nhbm5lZENvZGUuc3BsaXQoXCIvXCIpLCBfc2Nhbm5lZENvZGUkc3BsaXQyID0gX3NsaWNlZFRvQXJyYXkoX3NjYW5uZWRDb2RlJHNwbGl0LCAyKSwgdXVpZCA9IF9zY2FubmVkQ29kZSRzcGxpdDJbMF0sIHNpZ25hdHVyZSA9IF9zY2FubmVkQ29kZSRzcGxpdDJbMV07XG4gICAgICAgICAgY29uc29sZS5sb2coXCJSZWNlaXZlciBzY2FuIHN1Y2Nlc3NcIik7XG4gICAgICAgICAgc2Nhbm5lcl9hdWRpby5wbGF5KCk7XG4gICAgICAgICAgX2NvbnRleHQxNy5uZXh0ID0gNjtcbiAgICAgICAgICByZXR1cm4gZ2V0Q29uZmlnKCk7XG4gICAgICAgIGNhc2UgNjpcbiAgICAgICAgICBfY29udGV4dDE3Lm5leHQgPSA4O1xuICAgICAgICAgIHJldHVybiBmZXRjaChjb25maWcuYmFja2VuZF91cmwgKyBcIi9pdGVtL1wiICsgdXVpZCwge1xuICAgICAgICAgICAgaGVhZGVyczoge31cbiAgICAgICAgICB9KTtcbiAgICAgICAgY2FzZSA4OlxuICAgICAgICAgIHJlc3BvbnNlID0gX2NvbnRleHQxNy5zZW50O1xuICAgICAgICAgIGlmICghKHJlc3BvbnNlLnN0YXR1cyA9PSAyMDApKSB7XG4gICAgICAgICAgICBfY29udGV4dDE3Lm5leHQgPSAxNjtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDE3Lm5leHQgPSAxMjtcbiAgICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgICAgICBjYXNlIDEyOlxuICAgICAgICAgIHRyYWNraW5nX2l0ZW0gPSBfY29udGV4dDE3LnNlbnQ7XG4gICAgICAgICAgaWYgKGVkNDQ4LnZlcmlmeShodG9hKHNpZ25hdHVyZSksIG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZSh0cmFja2luZ19pdGVtLnV1aWQpLCBodG9hKHRyYWNraW5nX2l0ZW0udmVyaWZpY2F0aW9uKSkpIHtcbiAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjdXVpZFwiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLnV1aWQ7XG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3RhZ1wiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLnRhZztcbiAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjc3RvcmFnZVwiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLnN0b3JhZ2U7XG4gICAgICAgICAgICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI2FkZHJlc3NlZVwiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLmFkZHJlc3NlZTtcbiAgICAgICAgICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoXCIjdGVhbVwiKS5pbm5lckhUTUwgPSB0cmFja2luZ19pdGVtLnRlYW07XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcIlJlY2VpdmVyIHZlcmlmeSBzdWNjZXNzXCIpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBhbGVydChcIkNvdWxkIG5vdCB2ZXJpZnkgc2lnbmF0dXJlLlwiKTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiQ291bGQgbm90IHZlcmlmeSBzaWduYXR1cmUuXCIpO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDE3Lm5leHQgPSAxNztcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAxNjpcbiAgICAgICAgICBpZiAocmVzcG9uc2Uuc3RhdHVzID09IDQwNCkge1xuICAgICAgICAgICAgYWxlcnQoXCJJdGVtIG5vdCBmb3VuZC5cIik7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGNoZWNrUmVzcG9uc2VGb3JFcnJvcihyZXNwb25zZSwgXCJGYWlsZWQgdG8gZ2V0IGl0ZW0gZnJvbSBiYWNrZW5kLlwiKTtcbiAgICAgICAgICB9XG4gICAgICAgIGNhc2UgMTc6XG4gICAgICAgIGNhc2UgXCJlbmRcIjpcbiAgICAgICAgICByZXR1cm4gX2NvbnRleHQxNy5zdG9wKCk7XG4gICAgICB9XG4gICAgfSwgX2NhbGxlZTE3KTtcbiAgfSkpO1xuICByZXR1cm4gX29uUmVjZXZpZXJTY2FuU3VjY2Vzcy5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xufVxuZXhwb3J0IGZ1bmN0aW9uIHNjYW5SZWNlaXZlcigpIHtcbiAgcmV0dXJuIF9zY2FuUmVjZWl2ZXIuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9zY2FuUmVjZWl2ZXIoKSB7XG4gIF9zY2FuUmVjZWl2ZXIgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxOCgpIHtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE4JChfY29udGV4dDE4KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE4LnByZXYgPSBfY29udGV4dDE4Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiU2Nhbm5pbmcgcmVjZWl2ZXIuXCIpO1xuICAgICAgICAgIHNjYW5uZXIucmVuZGVyKG9uUmVjZXZpZXJTY2FuU3VjY2VzcywgaGFuZGxlUXJFcnJvcik7XG4gICAgICAgIGNhc2UgMjpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE4LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTgpO1xuICB9KSk7XG4gIHJldHVybiBfc2NhblJlY2VpdmVyLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gbG9hZFN0b3JhZ2VzKF94MTcpIHtcbiAgcmV0dXJuIF9sb2FkU3RvcmFnZXMuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbn1cbmZ1bmN0aW9uIF9sb2FkU3RvcmFnZXMoKSB7XG4gIF9sb2FkU3RvcmFnZXMgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUxOShzZWxlY3RlZFN0b3JhZ2UpIHtcbiAgICB2YXIgcmVzcG9uc2UsIHN0b3JhZ2VzLCBzZWxlY3QsIGksIG9wdGlvbjtcbiAgICByZXR1cm4gX3JlZ2VuZXJhdG9yUnVudGltZSgpLndyYXAoZnVuY3Rpb24gX2NhbGxlZTE5JChfY29udGV4dDE5KSB7XG4gICAgICB3aGlsZSAoMSkgc3dpdGNoIChfY29udGV4dDE5LnByZXYgPSBfY29udGV4dDE5Lm5leHQpIHtcbiAgICAgICAgY2FzZSAwOlxuICAgICAgICAgIGNvbnNvbGUubG9nKFwiUmV0cmlldmluZyBzdG9yYWdlc1wiKTtcbiAgICAgICAgICBfY29udGV4dDE5Lm5leHQgPSAzO1xuICAgICAgICAgIHJldHVybiBmZXRjaFdpdGhBdXRoKGNvbmZpZy5iYWNrZW5kX3VybCArIFwiL3N0b3JhZ2VzXCIpO1xuICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgcmVzcG9uc2UgPSBfY29udGV4dDE5LnNlbnQ7XG4gICAgICAgICAgX2NvbnRleHQxOS5uZXh0ID0gNjtcbiAgICAgICAgICByZXR1cm4gY2hlY2tSZXNwb25zZUZvckVycm9yKHJlc3BvbnNlLCBcIkZhaWxlZCB0byBsb2FkIHN0b3JhZ2VzLlwiKTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgIGlmICghX2NvbnRleHQxOS5zZW50KSB7XG4gICAgICAgICAgICBfY29udGV4dDE5Lm5leHQgPSAxMztcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBfY29udGV4dDE5Lm5leHQgPSA5O1xuICAgICAgICAgIHJldHVybiByZXNwb25zZS5qc29uKCk7XG4gICAgICAgIGNhc2UgOTpcbiAgICAgICAgICBzdG9yYWdlcyA9IF9jb250ZXh0MTkuc2VudDtcbiAgICAgICAgICBzZWxlY3QgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFwiI3N0b3JhZ2Vfc2VsZWN0XCIpO1xuICAgICAgICAgIGNvbnNvbGUubG9nKFwiR290IHN0b3JhZ2VzXCIpO1xuICAgICAgICAgIGZvciAoaSBpbiBzdG9yYWdlcykge1xuICAgICAgICAgICAgb3B0aW9uID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudChcIm9wdGlvblwiKTtcbiAgICAgICAgICAgIG9wdGlvbi50ZXh0Q29udGVudCA9IHN0b3JhZ2VzW2ldLm5hbWU7XG4gICAgICAgICAgICBvcHRpb24udmFsdWUgPSBzdG9yYWdlc1tpXS5uYW1lO1xuICAgICAgICAgICAgc2VsZWN0LmFwcGVuZENoaWxkKG9wdGlvbik7XG4gICAgICAgICAgICBpZiAoc2VsZWN0ZWRTdG9yYWdlID09IHN0b3JhZ2VzW2ldLm5hbWUpIHtcbiAgICAgICAgICAgICAgc2VsZWN0LnZhbHVlID0gc2VsZWN0ZWRTdG9yYWdlO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgY2FzZSBcImVuZFwiOlxuICAgICAgICAgIHJldHVybiBfY29udGV4dDE5LnN0b3AoKTtcbiAgICAgIH1cbiAgICB9LCBfY2FsbGVlMTkpO1xuICB9KSk7XG4gIHJldHVybiBfbG9hZFN0b3JhZ2VzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5leHBvcnQgZnVuY3Rpb24gb25QYWdlTG9hZCgpIHtcbiAgcmV0dXJuIF9vblBhZ2VMb2FkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5mdW5jdGlvbiBfb25QYWdlTG9hZCgpIHtcbiAgX29uUGFnZUxvYWQgPSBfYXN5bmNUb0dlbmVyYXRvciggLyojX19QVVJFX18qL19yZWdlbmVyYXRvclJ1bnRpbWUoKS5tYXJrKGZ1bmN0aW9uIF9jYWxsZWUyMCgpIHtcbiAgICB2YXIgcHc7XG4gICAgcmV0dXJuIF9yZWdlbmVyYXRvclJ1bnRpbWUoKS53cmFwKGZ1bmN0aW9uIF9jYWxsZWUyMCQoX2NvbnRleHQyMCkge1xuICAgICAgd2hpbGUgKDEpIHN3aXRjaCAoX2NvbnRleHQyMC5wcmV2ID0gX2NvbnRleHQyMC5uZXh0KSB7XG4gICAgICAgIGNhc2UgMDpcbiAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSAyO1xuICAgICAgICAgIHJldHVybiBnZXRDb25maWcoKTtcbiAgICAgICAgY2FzZSAyOlxuICAgICAgICAgIHB3ID0gd2luZG93LmxvY2F0aW9uLmhhc2guc3Vic3RyaW5nKDEpO1xuICAgICAgICAgIGlmICghKHB3Lmxlbmd0aCA+IDEpKSB7XG4gICAgICAgICAgICBfY29udGV4dDIwLm5leHQgPSA4O1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgfVxuICAgICAgICAgIF9jb250ZXh0MjAubmV4dCA9IDY7XG4gICAgICAgICAgcmV0dXJuIGxvZ2luKHB3KTtcbiAgICAgICAgY2FzZSA2OlxuICAgICAgICAgIF9jb250ZXh0MjAubmV4dCA9IDEwO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlIDg6XG4gICAgICAgICAgX2NvbnRleHQyMC5uZXh0ID0gMTA7XG4gICAgICAgICAgcmV0dXJuIGxvZ2luKCk7XG4gICAgICAgIGNhc2UgMTA6XG4gICAgICAgICAgbG9hZFN0b3JhZ2VzKGRvY3VtZW50LmxvY2F0aW9uLnNlYXJjaC5zdWJzdHJpbmcoMSkpO1xuICAgICAgICBjYXNlIDExOlxuICAgICAgICBjYXNlIFwiZW5kXCI6XG4gICAgICAgICAgcmV0dXJuIF9jb250ZXh0MjAuc3RvcCgpO1xuICAgICAgfVxuICAgIH0sIF9jYWxsZWUyMCk7XG4gIH0pKTtcbiAgcmV0dXJuIF9vblBhZ2VMb2FkLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59Il0sIm5hbWVzIjpbXSwic291cmNlUm9vdCI6IiJ9\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
diff --git a/src/js/main.js b/src/js/main.js
index 29f1395..90452ee 100644
--- a/src/js/main.js
+++ b/src/js/main.js
@@ -129,6 +129,8 @@ function updateItemsView() {
   items.innerHTML = "";
   for (var item in received_items) {
     var li = document.createElement("li");
+    console.log(item);
+    console.log(received_items[item]);
     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>"+
@@ -248,7 +250,7 @@ async function handleItemScanResult(item_uuid) {
       scanner_audio.play();
     } else {
       received_items[item_uuid] = { "num":1, "item": null };
-      var response = await fetch(config.backend_url + "/item/"+item_uuid);
+      var response = await fetchWithAuth(config.backend_url + "/item/"+item_uuid);
       if (response.status == 200) {
         var tracking_item = await response.json();
         received_items[item_uuid] = { "num":1, "item": tracking_item };
@@ -355,7 +357,10 @@ async function onRecevierScanSuccess(scannedCode) {
   console.log("Receiver scan success");
   scanner_audio.play();
   await getConfig();
-  var response = await fetch(config.backend_url + "/item/"+uuid);
+  var response = await fetch(config.backend_url + "/item/"+uuid, {
+    headers: {
+    }
+  });
   if (response.status == 200) {
     var tracking_item = await response.json();
     if (ed448.verify(htoa(signature),new TextEncoder().encode(tracking_item.uuid),htoa(tracking_item.verification))) {
-- 
GitLab