webpackJsonp([2],{"++K3":function(module,exports){eval("/**\n * Copyright 2004-present Facebook. All Rights Reserved.\n *\n * @providesModule UserAgent_DEPRECATED\n */\n\n/**\n * Provides entirely client-side User Agent and OS detection. You should prefer\n * the non-deprecated UserAgent module when possible, which exposes our\n * authoritative server-side PHP-based detection to the client.\n *\n * Usage is straightforward:\n *\n * if (UserAgent_DEPRECATED.ie()) {\n * // IE\n * }\n *\n * You can also do version checks:\n *\n * if (UserAgent_DEPRECATED.ie() >= 7) {\n * // IE7 or better\n * }\n *\n * The browser functions will return NaN if the browser does not match, so\n * you can also do version compares the other way:\n *\n * if (UserAgent_DEPRECATED.ie() < 7) {\n * // IE6 or worse\n * }\n *\n * Note that the version is a float and may include a minor version number,\n * so you should always use range operators to perform comparisons, not\n * strict equality.\n *\n * **Note:** You should **strongly** prefer capability detection to browser\n * version detection where it's reasonable:\n *\n * http://www.quirksmode.org/js/support.html\n *\n * Further, we have a large number of mature wrapper functions and classes\n * which abstract away many browser irregularities. Check the documentation,\n * grep for things, or ask on javascript@lists.facebook.com before writing yet\n * another copy of \"event || window.event\".\n *\n */\n\nvar _populated = false;\n\n// Browsers\nvar _ie, _firefox, _opera, _webkit, _chrome;\n\n// Actual IE browser for compatibility mode\nvar _ie_real_version;\n\n// Platforms\nvar _osx, _windows, _linux, _android;\n\n// Architectures\nvar _win64;\n\n// Devices\nvar _iphone, _ipad, _native;\n\nvar _mobile;\n\nfunction _populate() {\n if (_populated) {\n return;\n }\n\n _populated = true;\n\n // To work around buggy JS libraries that can't handle multi-digit\n // version numbers, Opera 10's user agent string claims it's Opera\n // 9, then later includes a Version/X.Y field:\n //\n // Opera/9.80 (foo) Presto/2.2.15 Version/10.10\n var uas = navigator.userAgent;\n var agent = /(?:MSIE.(\\d+\\.\\d+))|(?:(?:Firefox|GranParadiso|Iceweasel).(\\d+\\.\\d+))|(?:Opera(?:.+Version.|.)(\\d+\\.\\d+))|(?:AppleWebKit.(\\d+(?:\\.\\d+)?))|(?:Trident\\/\\d+\\.\\d+.*rv:(\\d+\\.\\d+))/.exec(uas);\n var os = /(Mac OS X)|(Windows)|(Linux)/.exec(uas);\n\n _iphone = /\\b(iPhone|iP[ao]d)/.exec(uas);\n _ipad = /\\b(iP[ao]d)/.exec(uas);\n _android = /Android/i.exec(uas);\n _native = /FBAN\\/\\w+;/i.exec(uas);\n _mobile = /Mobile/i.exec(uas);\n\n // Note that the IE team blog would have you believe you should be checking\n // for 'Win64; x64'. But MSDN then reveals that you can actually be coming\n // from either x64 or ia64; so ultimately, you should just check for Win64\n // as in indicator of whether you're in 64-bit IE. 32-bit IE on 64-bit\n // Windows will send 'WOW64' instead.\n _win64 = !!(/Win64/.exec(uas));\n\n if (agent) {\n _ie = agent[1] ? parseFloat(agent[1]) : (\n agent[5] ? parseFloat(agent[5]) : NaN);\n // IE compatibility mode\n if (_ie && document && document.documentMode) {\n _ie = document.documentMode;\n }\n // grab the \"true\" ie version from the trident token if available\n var trident = /(?:Trident\\/(\\d+.\\d+))/.exec(uas);\n _ie_real_version = trident ? parseFloat(trident[1]) + 4 : _ie;\n\n _firefox = agent[2] ? parseFloat(agent[2]) : NaN;\n _opera = agent[3] ? parseFloat(agent[3]) : NaN;\n _webkit = agent[4] ? parseFloat(agent[4]) : NaN;\n if (_webkit) {\n // We do not add the regexp to the above test, because it will always\n // match 'safari' only since 'AppleWebKit' appears before 'Chrome' in\n // the userAgent string.\n agent = /(?:Chrome\\/(\\d+\\.\\d+))/.exec(uas);\n _chrome = agent && agent[1] ? parseFloat(agent[1]) : NaN;\n } else {\n _chrome = NaN;\n }\n } else {\n _ie = _firefox = _opera = _chrome = _webkit = NaN;\n }\n\n if (os) {\n if (os[1]) {\n // Detect OS X version. If no version number matches, set _osx to true.\n // Version examples: 10, 10_6_1, 10.7\n // Parses version number as a float, taking only first two sets of\n // digits. If only one set of digits is found, returns just the major\n // version number.\n var ver = /(?:Mac OS X (\\d+(?:[._]\\d+)?))/.exec(uas);\n\n _osx = ver ? parseFloat(ver[1].replace('_', '.')) : true;\n } else {\n _osx = false;\n }\n _windows = !!os[2];\n _linux = !!os[3];\n } else {\n _osx = _windows = _linux = false;\n }\n}\n\nvar UserAgent_DEPRECATED = {\n\n /**\n * Check if the UA is Internet Explorer.\n *\n *\n * @return float|NaN Version number (if match) or NaN.\n */\n ie: function() {\n return _populate() || _ie;\n },\n\n /**\n * Check if we're in Internet Explorer compatibility mode.\n *\n * @return bool true if in compatibility mode, false if\n * not compatibility mode or not ie\n */\n ieCompatibilityMode: function() {\n return _populate() || (_ie_real_version > _ie);\n },\n\n\n /**\n * Whether the browser is 64-bit IE. Really, this is kind of weak sauce; we\n * only need this because Skype can't handle 64-bit IE yet. We need to remove\n * this when we don't need it -- tracked by #601957.\n */\n ie64: function() {\n return UserAgent_DEPRECATED.ie() && _win64;\n },\n\n /**\n * Check if the UA is Firefox.\n *\n *\n * @return float|NaN Version number (if match) or NaN.\n */\n firefox: function() {\n return _populate() || _firefox;\n },\n\n\n /**\n * Check if the UA is Opera.\n *\n *\n * @return float|NaN Version number (if match) or NaN.\n */\n opera: function() {\n return _populate() || _opera;\n },\n\n\n /**\n * Check if the UA is WebKit.\n *\n *\n * @return float|NaN Version number (if match) or NaN.\n */\n webkit: function() {\n return _populate() || _webkit;\n },\n\n /**\n * For Push\n * WILL BE REMOVED VERY SOON. Use UserAgent_DEPRECATED.webkit\n */\n safari: function() {\n return UserAgent_DEPRECATED.webkit();\n },\n\n /**\n * Check if the UA is a Chrome browser.\n *\n *\n * @return float|NaN Version number (if match) or NaN.\n */\n chrome : function() {\n return _populate() || _chrome;\n },\n\n\n /**\n * Check if the user is running Windows.\n *\n * @return bool `true' if the user's OS is Windows.\n */\n windows: function() {\n return _populate() || _windows;\n },\n\n\n /**\n * Check if the user is running Mac OS X.\n *\n * @return float|bool Returns a float if a version number is detected,\n * otherwise true/false.\n */\n osx: function() {\n return _populate() || _osx;\n },\n\n /**\n * Check if the user is running Linux.\n *\n * @return bool `true' if the user's OS is some flavor of Linux.\n */\n linux: function() {\n return _populate() || _linux;\n },\n\n /**\n * Check if the user is running on an iPhone or iPod platform.\n *\n * @return bool `true' if the user is running some flavor of the\n * iPhone OS.\n */\n iphone: function() {\n return _populate() || _iphone;\n },\n\n mobile: function() {\n return _populate() || (_iphone || _ipad || _android || _mobile);\n },\n\n nativeApp: function() {\n // webviews inside of the native apps\n return _populate() || _native;\n },\n\n android: function() {\n return _populate() || _android;\n },\n\n ipad: function() {\n return _populate() || _ipad;\n }\n};\n\nmodule.exports = UserAgent_DEPRECATED;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiKytLMy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ub3JtYWxpemUtd2hlZWwvc3JjL1VzZXJBZ2VudF9ERVBSRUNBVEVELmpzP2ZiZTIiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgMjAwNC1wcmVzZW50IEZhY2Vib29rLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIEBwcm92aWRlc01vZHVsZSBVc2VyQWdlbnRfREVQUkVDQVRFRFxuICovXG5cbi8qKlxuICogIFByb3ZpZGVzIGVudGlyZWx5IGNsaWVudC1zaWRlIFVzZXIgQWdlbnQgYW5kIE9TIGRldGVjdGlvbi4gWW91IHNob3VsZCBwcmVmZXJcbiAqICB0aGUgbm9uLWRlcHJlY2F0ZWQgVXNlckFnZW50IG1vZHVsZSB3aGVuIHBvc3NpYmxlLCB3aGljaCBleHBvc2VzIG91clxuICogIGF1dGhvcml0YXRpdmUgc2VydmVyLXNpZGUgUEhQLWJhc2VkIGRldGVjdGlvbiB0byB0aGUgY2xpZW50LlxuICpcbiAqICBVc2FnZSBpcyBzdHJhaWdodGZvcndhcmQ6XG4gKlxuICogICAgaWYgKFVzZXJBZ2VudF9ERVBSRUNBVEVELmllKCkpIHtcbiAqICAgICAgLy8gIElFXG4gKiAgICB9XG4gKlxuICogIFlvdSBjYW4gYWxzbyBkbyB2ZXJzaW9uIGNoZWNrczpcbiAqXG4gKiAgICBpZiAoVXNlckFnZW50X0RFUFJFQ0FURUQuaWUoKSA+PSA3KSB7XG4gKiAgICAgIC8vICBJRTcgb3IgYmV0dGVyXG4gKiAgICB9XG4gKlxuICogIFRoZSBicm93c2VyIGZ1bmN0aW9ucyB3aWxsIHJldHVybiBOYU4gaWYgdGhlIGJyb3dzZXIgZG9lcyBub3QgbWF0Y2gsIHNvXG4gKiAgeW91IGNhbiBhbHNvIGRvIHZlcnNpb24gY29tcGFyZXMgdGhlIG90aGVyIHdheTpcbiAqXG4gKiAgICBpZiAoVXNlckFnZW50X0RFUFJFQ0FURUQuaWUoKSA8IDcpIHtcbiAqICAgICAgLy8gIElFNiBvciB3b3JzZVxuICogICAgfVxuICpcbiAqICBOb3RlIHRoYXQgdGhlIHZlcnNpb24gaXMgYSBmbG9hdCBhbmQgbWF5IGluY2x1ZGUgYSBtaW5vciB2ZXJzaW9uIG51bWJlcixcbiAqICBzbyB5b3Ugc2hvdWxkIGFsd2F5cyB1c2UgcmFuZ2Ugb3BlcmF0b3JzIHRvIHBlcmZvcm0gY29tcGFyaXNvbnMsIG5vdFxuICogIHN0cmljdCBlcXVhbGl0eS5cbiAqXG4gKiAgKipOb3RlOioqIFlvdSBzaG91bGQgKipzdHJvbmdseSoqIHByZWZlciBjYXBhYmlsaXR5IGRldGVjdGlvbiB0byBicm93c2VyXG4gKiAgdmVyc2lvbiBkZXRlY3Rpb24gd2hlcmUgaXQncyByZWFzb25hYmxlOlxuICpcbiAqICAgIGh0dHA6Ly93d3cucXVpcmtzbW9kZS5vcmcvanMvc3VwcG9ydC5odG1sXG4gKlxuICogIEZ1cnRoZXIsIHdlIGhhdmUgYSBsYXJnZSBudW1iZXIgb2YgbWF0dXJlIHdyYXBwZXIgZnVuY3Rpb25zIGFuZCBjbGFzc2VzXG4gKiAgd2hpY2ggYWJzdHJhY3QgYXdheSBtYW55IGJyb3dzZXIgaXJyZWd1bGFyaXRpZXMuIENoZWNrIHRoZSBkb2N1bWVudGF0aW9uLFxuICogIGdyZXAgZm9yIHRoaW5ncywgb3IgYXNrIG9uIGphdmFzY3JpcHRAbGlzdHMuZmFjZWJvb2suY29tIGJlZm9yZSB3cml0aW5nIHlldFxuICogIGFub3RoZXIgY29weSBvZiBcImV2ZW50IHx8IHdpbmRvdy5ldmVudFwiLlxuICpcbiAqL1xuXG52YXIgX3BvcHVsYXRlZCA9IGZhbHNlO1xuXG4vLyBCcm93c2Vyc1xudmFyIF9pZSwgX2ZpcmVmb3gsIF9vcGVyYSwgX3dlYmtpdCwgX2Nocm9tZTtcblxuLy8gQWN0dWFsIElFIGJyb3dzZXIgZm9yIGNvbXBhdGliaWxpdHkgbW9kZVxudmFyIF9pZV9yZWFsX3ZlcnNpb247XG5cbi8vIFBsYXRmb3Jtc1xudmFyIF9vc3gsIF93aW5kb3dzLCBfbGludXgsIF9hbmRyb2lkO1xuXG4vLyBBcmNoaXRlY3R1cmVzXG52YXIgX3dpbjY0O1xuXG4vLyBEZXZpY2VzXG52YXIgX2lwaG9uZSwgX2lwYWQsIF9uYXRpdmU7XG5cbnZhciBfbW9iaWxlO1xuXG5mdW5jdGlvbiBfcG9wdWxhdGUoKSB7XG4gIGlmIChfcG9wdWxhdGVkKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgX3BvcHVsYXRlZCA9IHRydWU7XG5cbiAgLy8gVG8gd29yayBhcm91bmQgYnVnZ3kgSlMgbGlicmFyaWVzIHRoYXQgY2FuJ3QgaGFuZGxlIG11bHRpLWRpZ2l0XG4gIC8vIHZlcnNpb24gbnVtYmVycywgT3BlcmEgMTAncyB1c2VyIGFnZW50IHN0cmluZyBjbGFpbXMgaXQncyBPcGVyYVxuICAvLyA5LCB0aGVuIGxhdGVyIGluY2x1ZGVzIGEgVmVyc2lvbi9YLlkgZmllbGQ6XG4gIC8vXG4gIC8vIE9wZXJhLzkuODAgKGZvbykgUHJlc3RvLzIuMi4xNSBWZXJzaW9uLzEwLjEwXG4gIHZhciB1YXMgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuICB2YXIgYWdlbnQgPSAvKD86TVNJRS4oXFxkK1xcLlxcZCspKXwoPzooPzpGaXJlZm94fEdyYW5QYXJhZGlzb3xJY2V3ZWFzZWwpLihcXGQrXFwuXFxkKykpfCg/Ok9wZXJhKD86LitWZXJzaW9uLnwuKShcXGQrXFwuXFxkKykpfCg/OkFwcGxlV2ViS2l0LihcXGQrKD86XFwuXFxkKyk/KSl8KD86VHJpZGVudFxcL1xcZCtcXC5cXGQrLipydjooXFxkK1xcLlxcZCspKS8uZXhlYyh1YXMpO1xuICB2YXIgb3MgICAgPSAvKE1hYyBPUyBYKXwoV2luZG93cyl8KExpbnV4KS8uZXhlYyh1YXMpO1xuXG4gIF9pcGhvbmUgPSAvXFxiKGlQaG9uZXxpUFthb11kKS8uZXhlYyh1YXMpO1xuICBfaXBhZCA9IC9cXGIoaVBbYW9dZCkvLmV4ZWModWFzKTtcbiAgX2FuZHJvaWQgPSAvQW5kcm9pZC9pLmV4ZWModWFzKTtcbiAgX25hdGl2ZSA9IC9GQkFOXFwvXFx3KzsvaS5leGVjKHVhcyk7XG4gIF9tb2JpbGUgPSAvTW9iaWxlL2kuZXhlYyh1YXMpO1xuXG4gIC8vIE5vdGUgdGhhdCB0aGUgSUUgdGVhbSBibG9nIHdvdWxkIGhhdmUgeW91IGJlbGlldmUgeW91IHNob3VsZCBiZSBjaGVja2luZ1xuICAvLyBmb3IgJ1dpbjY0OyB4NjQnLiAgQnV0IE1TRE4gdGhlbiByZXZlYWxzIHRoYXQgeW91IGNhbiBhY3R1YWxseSBiZSBjb21pbmdcbiAgLy8gZnJvbSBlaXRoZXIgeDY0IG9yIGlhNjQ7ICBzbyB1bHRpbWF0ZWx5LCB5b3Ugc2hvdWxkIGp1c3QgY2hlY2sgZm9yIFdpbjY0XG4gIC8vIGFzIGluIGluZGljYXRvciBvZiB3aGV0aGVyIHlvdSdyZSBpbiA2NC1iaXQgSUUuICAzMi1iaXQgSUUgb24gNjQtYml0XG4gIC8vIFdpbmRvd3Mgd2lsbCBzZW5kICdXT1c2NCcgaW5zdGVhZC5cbiAgX3dpbjY0ID0gISEoL1dpbjY0Ly5leGVjKHVhcykpO1xuXG4gIGlmIChhZ2VudCkge1xuICAgIF9pZSA9IGFnZW50WzFdID8gcGFyc2VGbG9hdChhZ2VudFsxXSkgOiAoXG4gICAgICAgICAgYWdlbnRbNV0gPyBwYXJzZUZsb2F0KGFnZW50WzVdKSA6IE5hTik7XG4gICAgLy8gSUUgY29tcGF0aWJpbGl0eSBtb2RlXG4gICAgaWYgKF9pZSAmJiBkb2N1bWVudCAmJiBkb2N1bWVudC5kb2N1bWVudE1vZGUpIHtcbiAgICAgIF9pZSA9IGRvY3VtZW50LmRvY3VtZW50TW9kZTtcbiAgICB9XG4gICAgLy8gZ3JhYiB0aGUgXCJ0cnVlXCIgaWUgdmVyc2lvbiBmcm9tIHRoZSB0cmlkZW50IHRva2VuIGlmIGF2YWlsYWJsZVxuICAgIHZhciB0cmlkZW50ID0gLyg/OlRyaWRlbnRcXC8oXFxkKy5cXGQrKSkvLmV4ZWModWFzKTtcbiAgICBfaWVfcmVhbF92ZXJzaW9uID0gdHJpZGVudCA/IHBhcnNlRmxvYXQodHJpZGVudFsxXSkgKyA0IDogX2llO1xuXG4gICAgX2ZpcmVmb3ggPSBhZ2VudFsyXSA/IHBhcnNlRmxvYXQoYWdlbnRbMl0pIDogTmFOO1xuICAgIF9vcGVyYSAgID0gYWdlbnRbM10gPyBwYXJzZUZsb2F0KGFnZW50WzNdKSA6IE5hTjtcbiAgICBfd2Via2l0ICA9IGFnZW50WzRdID8gcGFyc2VGbG9hdChhZ2VudFs0XSkgOiBOYU47XG4gICAgaWYgKF93ZWJraXQpIHtcbiAgICAgIC8vIFdlIGRvIG5vdCBhZGQgdGhlIHJlZ2V4cCB0byB0aGUgYWJvdmUgdGVzdCwgYmVjYXVzZSBpdCB3aWxsIGFsd2F5c1xuICAgICAgLy8gbWF0Y2ggJ3NhZmFyaScgb25seSBzaW5jZSAnQXBwbGVXZWJLaXQnIGFwcGVhcnMgYmVmb3JlICdDaHJvbWUnIGluXG4gICAgICAvLyB0aGUgdXNlckFnZW50IHN0cmluZy5cbiAgICAgIGFnZW50ID0gLyg/OkNocm9tZVxcLyhcXGQrXFwuXFxkKykpLy5leGVjKHVhcyk7XG4gICAgICBfY2hyb21lID0gYWdlbnQgJiYgYWdlbnRbMV0gPyBwYXJzZUZsb2F0KGFnZW50WzFdKSA6IE5hTjtcbiAgICB9IGVsc2Uge1xuICAgICAgX2Nocm9tZSA9IE5hTjtcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgX2llID0gX2ZpcmVmb3ggPSBfb3BlcmEgPSBfY2hyb21lID0gX3dlYmtpdCA9IE5hTjtcbiAgfVxuXG4gIGlmIChvcykge1xuICAgIGlmIChvc1sxXSkge1xuICAgICAgLy8gRGV0ZWN0IE9TIFggdmVyc2lvbi4gIElmIG5vIHZlcnNpb24gbnVtYmVyIG1hdGNoZXMsIHNldCBfb3N4IHRvIHRydWUuXG4gICAgICAvLyBWZXJzaW9uIGV4YW1wbGVzOiAgMTAsIDEwXzZfMSwgMTAuN1xuICAgICAgLy8gUGFyc2VzIHZlcnNpb24gbnVtYmVyIGFzIGEgZmxvYXQsIHRha2luZyBvbmx5IGZpcnN0IHR3byBzZXRzIG9mXG4gICAgICAvLyBkaWdpdHMuICBJZiBvbmx5IG9uZSBzZXQgb2YgZGlnaXRzIGlzIGZvdW5kLCByZXR1cm5zIGp1c3QgdGhlIG1ham9yXG4gICAgICAvLyB2ZXJzaW9uIG51bWJlci5cbiAgICAgIHZhciB2ZXIgPSAvKD86TWFjIE9TIFggKFxcZCsoPzpbLl9dXFxkKyk/KSkvLmV4ZWModWFzKTtcblxuICAgICAgX29zeCA9IHZlciA/IHBhcnNlRmxvYXQodmVyWzFdLnJlcGxhY2UoJ18nLCAnLicpKSA6IHRydWU7XG4gICAgfSBlbHNlIHtcbiAgICAgIF9vc3ggPSBmYWxzZTtcbiAgICB9XG4gICAgX3dpbmRvd3MgPSAhIW9zWzJdO1xuICAgIF9saW51eCAgID0gISFvc1szXTtcbiAgfSBlbHNlIHtcbiAgICBfb3N4ID0gX3dpbmRvd3MgPSBfbGludXggPSBmYWxzZTtcbiAgfVxufVxuXG52YXIgVXNlckFnZW50X0RFUFJFQ0FURUQgPSB7XG5cbiAgLyoqXG4gICAqICBDaGVjayBpZiB0aGUgVUEgaXMgSW50ZXJuZXQgRXhwbG9yZXIuXG4gICAqXG4gICAqXG4gICAqICBAcmV0dXJuIGZsb2F0fE5hTiBWZXJzaW9uIG51bWJlciAoaWYgbWF0Y2gpIG9yIE5hTi5cbiAgICovXG4gIGllOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gX3BvcHVsYXRlKCkgfHwgX2llO1xuICB9LFxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB3ZSdyZSBpbiBJbnRlcm5ldCBFeHBsb3JlciBjb21wYXRpYmlsaXR5IG1vZGUuXG4gICAqXG4gICAqIEByZXR1cm4gYm9vbCB0cnVlIGlmIGluIGNvbXBhdGliaWxpdHkgbW9kZSwgZmFsc2UgaWZcbiAgICogbm90IGNvbXBhdGliaWxpdHkgbW9kZSBvciBub3QgaWVcbiAgICovXG4gIGllQ29tcGF0aWJpbGl0eU1vZGU6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfcG9wdWxhdGUoKSB8fCAoX2llX3JlYWxfdmVyc2lvbiA+IF9pZSk7XG4gIH0sXG5cblxuICAvKipcbiAgICogV2hldGhlciB0aGUgYnJvd3NlciBpcyA2NC1iaXQgSUUuICBSZWFsbHksIHRoaXMgaXMga2luZCBvZiB3ZWFrIHNhdWNlOyAgd2VcbiAgICogb25seSBuZWVkIHRoaXMgYmVjYXVzZSBTa3lwZSBjYW4ndCBoYW5kbGUgNjQtYml0IElFIHlldC4gIFdlIG5lZWQgdG8gcmVtb3ZlXG4gICAqIHRoaXMgd2hlbiB3ZSBkb24ndCBuZWVkIGl0IC0tIHRyYWNrZWQgYnkgIzYwMTk1Ny5cbiAgICovXG4gIGllNjQ6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBVc2VyQWdlbnRfREVQUkVDQVRFRC5pZSgpICYmIF93aW42NDtcbiAgfSxcblxuICAvKipcbiAgICogIENoZWNrIGlmIHRoZSBVQSBpcyBGaXJlZm94LlxuICAgKlxuICAgKlxuICAgKiAgQHJldHVybiBmbG9hdHxOYU4gVmVyc2lvbiBudW1iZXIgKGlmIG1hdGNoKSBvciBOYU4uXG4gICAqL1xuICBmaXJlZm94OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gX3BvcHVsYXRlKCkgfHwgX2ZpcmVmb3g7XG4gIH0sXG5cblxuICAvKipcbiAgICogIENoZWNrIGlmIHRoZSBVQSBpcyBPcGVyYS5cbiAgICpcbiAgICpcbiAgICogIEByZXR1cm4gZmxvYXR8TmFOIFZlcnNpb24gbnVtYmVyIChpZiBtYXRjaCkgb3IgTmFOLlxuICAgKi9cbiAgb3BlcmE6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfcG9wdWxhdGUoKSB8fCBfb3BlcmE7XG4gIH0sXG5cblxuICAvKipcbiAgICogIENoZWNrIGlmIHRoZSBVQSBpcyBXZWJLaXQuXG4gICAqXG4gICAqXG4gICAqICBAcmV0dXJuIGZsb2F0fE5hTiBWZXJzaW9uIG51bWJlciAoaWYgbWF0Y2gpIG9yIE5hTi5cbiAgICovXG4gIHdlYmtpdDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF9wb3B1bGF0ZSgpIHx8IF93ZWJraXQ7XG4gIH0sXG5cbiAgLyoqXG4gICAqICBGb3IgUHVzaFxuICAgKiAgV0lMTCBCRSBSRU1PVkVEIFZFUlkgU09PTi4gVXNlIFVzZXJBZ2VudF9ERVBSRUNBVEVELndlYmtpdFxuICAgKi9cbiAgc2FmYXJpOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gVXNlckFnZW50X0RFUFJFQ0FURUQud2Via2l0KCk7XG4gIH0sXG5cbiAgLyoqXG4gICAqICBDaGVjayBpZiB0aGUgVUEgaXMgYSBDaHJvbWUgYnJvd3Nlci5cbiAgICpcbiAgICpcbiAgICogIEByZXR1cm4gZmxvYXR8TmFOIFZlcnNpb24gbnVtYmVyIChpZiBtYXRjaCkgb3IgTmFOLlxuICAgKi9cbiAgY2hyb21lIDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF9wb3B1bGF0ZSgpIHx8IF9jaHJvbWU7XG4gIH0sXG5cblxuICAvKipcbiAgICogIENoZWNrIGlmIHRoZSB1c2VyIGlzIHJ1bm5pbmcgV2luZG93cy5cbiAgICpcbiAgICogIEByZXR1cm4gYm9vbCBgdHJ1ZScgaWYgdGhlIHVzZXIncyBPUyBpcyBXaW5kb3dzLlxuICAgKi9cbiAgd2luZG93czogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF9wb3B1bGF0ZSgpIHx8IF93aW5kb3dzO1xuICB9LFxuXG5cbiAgLyoqXG4gICAqICBDaGVjayBpZiB0aGUgdXNlciBpcyBydW5uaW5nIE1hYyBPUyBYLlxuICAgKlxuICAgKiAgQHJldHVybiBmbG9hdHxib29sICAgUmV0dXJucyBhIGZsb2F0IGlmIGEgdmVyc2lvbiBudW1iZXIgaXMgZGV0ZWN0ZWQsXG4gICAqICAgICAgICAgICAgICAgICAgICAgICBvdGhlcndpc2UgdHJ1ZS9mYWxzZS5cbiAgICovXG4gIG9zeDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF9wb3B1bGF0ZSgpIHx8IF9vc3g7XG4gIH0sXG5cbiAgLyoqXG4gICAqIENoZWNrIGlmIHRoZSB1c2VyIGlzIHJ1bm5pbmcgTGludXguXG4gICAqXG4gICAqIEByZXR1cm4gYm9vbCBgdHJ1ZScgaWYgdGhlIHVzZXIncyBPUyBpcyBzb21lIGZsYXZvciBvZiBMaW51eC5cbiAgICovXG4gIGxpbnV4OiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gX3BvcHVsYXRlKCkgfHwgX2xpbnV4O1xuICB9LFxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0aGUgdXNlciBpcyBydW5uaW5nIG9uIGFuIGlQaG9uZSBvciBpUG9kIHBsYXRmb3JtLlxuICAgKlxuICAgKiBAcmV0dXJuIGJvb2wgYHRydWUnIGlmIHRoZSB1c2VyIGlzIHJ1bm5pbmcgc29tZSBmbGF2b3Igb2YgdGhlXG4gICAqICAgIGlQaG9uZSBPUy5cbiAgICovXG4gIGlwaG9uZTogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF9wb3B1bGF0ZSgpIHx8IF9pcGhvbmU7XG4gIH0sXG5cbiAgbW9iaWxlOiBmdW5jdGlvbigpIHtcbiAgICByZXR1cm4gX3BvcHVsYXRlKCkgfHwgKF9pcGhvbmUgfHwgX2lwYWQgfHwgX2FuZHJvaWQgfHwgX21vYmlsZSk7XG4gIH0sXG5cbiAgbmF0aXZlQXBwOiBmdW5jdGlvbigpIHtcbiAgICAvLyB3ZWJ2aWV3cyBpbnNpZGUgb2YgdGhlIG5hdGl2ZSBhcHBzXG4gICAgcmV0dXJuIF9wb3B1bGF0ZSgpIHx8IF9uYXRpdmU7XG4gIH0sXG5cbiAgYW5kcm9pZDogZnVuY3Rpb24oKSB7XG4gICAgcmV0dXJuIF9wb3B1bGF0ZSgpIHx8IF9hbmRyb2lkO1xuICB9LFxuXG4gIGlwYWQ6IGZ1bmN0aW9uKCkge1xuICAgIHJldHVybiBfcG9wdWxhdGUoKSB8fCBfaXBhZDtcbiAgfVxufTtcblxubW9kdWxlLmV4cG9ydHMgPSBVc2VyQWdlbnRfREVQUkVDQVRFRDtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL25vcm1hbGl6ZS13aGVlbC9zcmMvVXNlckFnZW50X0RFUFJFQ0FURUQuanNcbi8vIG1vZHVsZSBpZCA9ICsrSzNcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///++K3\n")},"+E39":function(module,exports,__webpack_require__){eval("// Thank's IE8 for his funny defineProperty\nmodule.exports = !__webpack_require__(\"S82l\")(function () {\n return Object.defineProperty({}, 'a', { get: function () { return 7; } }).a != 7;\n});\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiK0UzOS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZGVzY3JpcHRvcnMuanM/Zjg0ZCJdLCJzb3VyY2VzQ29udGVudCI6WyIvLyBUaGFuaydzIElFOCBmb3IgaGlzIGZ1bm55IGRlZmluZVByb3BlcnR5XG5tb2R1bGUuZXhwb3J0cyA9ICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgJ2EnLCB7IGdldDogZnVuY3Rpb24gKCkgeyByZXR1cm4gNzsgfSB9KS5hICE9IDc7XG59KTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19kZXNjcmlwdG9ycy5qc1xuLy8gbW9kdWxlIGlkID0gK0UzOVxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///+E39\n")},"+ZMJ":function(module,exports,__webpack_require__){eval('// optional / simple context binding\nvar aFunction = __webpack_require__("lOnJ");\nmodule.exports = function (fn, that, length) {\n aFunction(fn);\n if (that === undefined) return fn;\n switch (length) {\n case 1: return function (a) {\n return fn.call(that, a);\n };\n case 2: return function (a, b) {\n return fn.call(that, a, b);\n };\n case 3: return function (a, b, c) {\n return fn.call(that, a, b, c);\n };\n }\n return function (/* ...args */) {\n return fn.apply(that, arguments);\n };\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiK1pNSi5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fY3R4LmpzP2Y5OTMiXSwic291cmNlc0NvbnRlbnQiOlsiLy8gb3B0aW9uYWwgLyBzaW1wbGUgY29udGV4dCBiaW5kaW5nXG52YXIgYUZ1bmN0aW9uID0gcmVxdWlyZSgnLi9fYS1mdW5jdGlvbicpO1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoZm4sIHRoYXQsIGxlbmd0aCkge1xuICBhRnVuY3Rpb24oZm4pO1xuICBpZiAodGhhdCA9PT0gdW5kZWZpbmVkKSByZXR1cm4gZm47XG4gIHN3aXRjaCAobGVuZ3RoKSB7XG4gICAgY2FzZSAxOiByZXR1cm4gZnVuY3Rpb24gKGEpIHtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEpO1xuICAgIH07XG4gICAgY2FzZSAyOiByZXR1cm4gZnVuY3Rpb24gKGEsIGIpIHtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIpO1xuICAgIH07XG4gICAgY2FzZSAzOiByZXR1cm4gZnVuY3Rpb24gKGEsIGIsIGMpIHtcbiAgICAgIHJldHVybiBmbi5jYWxsKHRoYXQsIGEsIGIsIGMpO1xuICAgIH07XG4gIH1cbiAgcmV0dXJuIGZ1bmN0aW9uICgvKiAuLi5hcmdzICovKSB7XG4gICAgcmV0dXJuIGZuLmFwcGx5KHRoYXQsIGFyZ3VtZW50cyk7XG4gIH07XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2N0eC5qc1xuLy8gbW9kdWxlIGlkID0gK1pNSlxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///+ZMJ\n')},"+tPU":function(module,exports,__webpack_require__){eval("__webpack_require__(\"xGkn\");\nvar global = __webpack_require__(\"7KvD\");\nvar hide = __webpack_require__(\"hJx8\");\nvar Iterators = __webpack_require__(\"/bQp\");\nvar TO_STRING_TAG = __webpack_require__(\"dSzd\")('toStringTag');\n\nvar DOMIterables = ('CSSRuleList,CSSStyleDeclaration,CSSValueList,ClientRectList,DOMRectList,DOMStringList,' +\n 'DOMTokenList,DataTransferItemList,FileList,HTMLAllCollection,HTMLCollection,HTMLFormElement,HTMLSelectElement,' +\n 'MediaList,MimeTypeArray,NamedNodeMap,NodeList,PaintRequestList,Plugin,PluginArray,SVGLengthList,SVGNumberList,' +\n 'SVGPathSegList,SVGPointList,SVGStringList,SVGTransformList,SourceBufferList,StyleSheetList,TextTrackCueList,' +\n 'TextTrackList,TouchList').split(',');\n\nfor (var i = 0; i < DOMIterables.length; i++) {\n var NAME = DOMIterables[i];\n var Collection = global[NAME];\n var proto = Collection && Collection.prototype;\n if (proto && !proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);\n Iterators[NAME] = Iterators.Array;\n}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiK3RQVS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy93ZWIuZG9tLml0ZXJhYmxlLmpzP2ZhZDMiXSwic291cmNlc0NvbnRlbnQiOlsicmVxdWlyZSgnLi9lczYuYXJyYXkuaXRlcmF0b3InKTtcbnZhciBnbG9iYWwgPSByZXF1aXJlKCcuL19nbG9iYWwnKTtcbnZhciBoaWRlID0gcmVxdWlyZSgnLi9faGlkZScpO1xudmFyIEl0ZXJhdG9ycyA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpO1xudmFyIFRPX1NUUklOR19UQUcgPSByZXF1aXJlKCcuL193a3MnKSgndG9TdHJpbmdUYWcnKTtcblxudmFyIERPTUl0ZXJhYmxlcyA9ICgnQ1NTUnVsZUxpc3QsQ1NTU3R5bGVEZWNsYXJhdGlvbixDU1NWYWx1ZUxpc3QsQ2xpZW50UmVjdExpc3QsRE9NUmVjdExpc3QsRE9NU3RyaW5nTGlzdCwnICtcbiAgJ0RPTVRva2VuTGlzdCxEYXRhVHJhbnNmZXJJdGVtTGlzdCxGaWxlTGlzdCxIVE1MQWxsQ29sbGVjdGlvbixIVE1MQ29sbGVjdGlvbixIVE1MRm9ybUVsZW1lbnQsSFRNTFNlbGVjdEVsZW1lbnQsJyArXG4gICdNZWRpYUxpc3QsTWltZVR5cGVBcnJheSxOYW1lZE5vZGVNYXAsTm9kZUxpc3QsUGFpbnRSZXF1ZXN0TGlzdCxQbHVnaW4sUGx1Z2luQXJyYXksU1ZHTGVuZ3RoTGlzdCxTVkdOdW1iZXJMaXN0LCcgK1xuICAnU1ZHUGF0aFNlZ0xpc3QsU1ZHUG9pbnRMaXN0LFNWR1N0cmluZ0xpc3QsU1ZHVHJhbnNmb3JtTGlzdCxTb3VyY2VCdWZmZXJMaXN0LFN0eWxlU2hlZXRMaXN0LFRleHRUcmFja0N1ZUxpc3QsJyArXG4gICdUZXh0VHJhY2tMaXN0LFRvdWNoTGlzdCcpLnNwbGl0KCcsJyk7XG5cbmZvciAodmFyIGkgPSAwOyBpIDwgRE9NSXRlcmFibGVzLmxlbmd0aDsgaSsrKSB7XG4gIHZhciBOQU1FID0gRE9NSXRlcmFibGVzW2ldO1xuICB2YXIgQ29sbGVjdGlvbiA9IGdsb2JhbFtOQU1FXTtcbiAgdmFyIHByb3RvID0gQ29sbGVjdGlvbiAmJiBDb2xsZWN0aW9uLnByb3RvdHlwZTtcbiAgaWYgKHByb3RvICYmICFwcm90b1tUT19TVFJJTkdfVEFHXSkgaGlkZShwcm90bywgVE9fU1RSSU5HX1RBRywgTkFNRSk7XG4gIEl0ZXJhdG9yc1tOQU1FXSA9IEl0ZXJhdG9ycy5BcnJheTtcbn1cblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUuanNcbi8vIG1vZHVsZSBpZCA9ICt0UFVcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///+tPU\n")},"//Fk":function(module,exports,__webpack_require__){eval('module.exports = { "default": __webpack_require__("U5ju"), __esModule: true };//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLy9Gay5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvcHJvbWlzZS5qcz9mZmYxIl0sInNvdXJjZXNDb250ZW50IjpbIm1vZHVsZS5leHBvcnRzID0geyBcImRlZmF1bHRcIjogcmVxdWlyZShcImNvcmUtanMvbGlicmFyeS9mbi9wcm9taXNlXCIpLCBfX2VzTW9kdWxlOiB0cnVlIH07XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYmFiZWwtcnVudGltZS9jb3JlLWpzL3Byb21pc2UuanNcbi8vIG1vZHVsZSBpZCA9IC8vRmtcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal://///Fk\n')},"/MY8":function(module,exports,__webpack_require__){eval('/*\n *\tMP3 huffman table selecting and bit counting\n *\n *\tCopyright (c) 1999-2005 Takehiro TOMINAGA\n *\tCopyright (c) 2002-2005 Gabriel Bouvigne\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\t See the GNU\n * Library General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n * Boston, MA 02111-1307, USA.\n */\n\n/* $Id: Takehiro.java,v 1.26 2011/05/24 20:48:06 kenchis Exp $ */\n\n//package mp3;\n\n//import java.util.Arrays;\nvar common = __webpack_require__("Dkd2");\nvar System = common.System;\nvar VbrMode = common.VbrMode;\nvar Float = common.Float;\nvar ShortBlock = common.ShortBlock;\nvar Util = common.Util;\nvar Arrays = common.Arrays;\nvar new_array_n = common.new_array_n;\nvar new_byte = common.new_byte;\nvar new_double = common.new_double;\nvar new_float = common.new_float;\nvar new_float_n = common.new_float_n;\nvar new_int = common.new_int;\nvar new_int_n = common.new_int_n;\nvar assert = common.assert;\n\nvar Encoder = __webpack_require__("E2dQ");\nvar Tables = __webpack_require__("Nk+c");\nvar GrInfo = __webpack_require__("PrPO");\nvar QuantizePVT = __webpack_require__("GZKO");\n\n\nfunction Takehiro() {\n\n var qupvt = null;\n this.qupvt = null;\n\n this.setModules = function (_qupvt) {\n this.qupvt = _qupvt;\n qupvt = _qupvt;\n }\n\n function Bits(b) {\n this.bits = 0 | b;\n }\n\n var subdv_table = [[0, 0], /* 0 bands */\n [0, 0], /* 1 bands */\n [0, 0], /* 2 bands */\n [0, 0], /* 3 bands */\n [0, 0], /* 4 bands */\n [0, 1], /* 5 bands */\n [1, 1], /* 6 bands */\n [1, 1], /* 7 bands */\n [1, 2], /* 8 bands */\n [2, 2], /* 9 bands */\n [2, 3], /* 10 bands */\n [2, 3], /* 11 bands */\n [3, 4], /* 12 bands */\n [3, 4], /* 13 bands */\n [3, 4], /* 14 bands */\n [4, 5], /* 15 bands */\n [4, 5], /* 16 bands */\n [4, 6], /* 17 bands */\n [5, 6], /* 18 bands */\n [5, 6], /* 19 bands */\n [5, 7], /* 20 bands */\n [6, 7], /* 21 bands */\n [6, 7], /* 22 bands */\n ];\n\n /**\n * nonlinear quantization of xr More accurate formula than the ISO formula.\n * Takes into account the fact that we are quantizing xr . ix, but we want\n * ix^4/3 to be as close as possible to x^4/3. (taking the nearest int would\n * mean ix is as close as possible to xr, which is different.)\n *\n * From Segher Boessenkool 11/1999\n *\n * 09/2000: ASM code removed in favor of IEEE754 hack by Takehiro Tominaga.\n * If you need the ASM code, check CVS circa Aug 2000.\n *\n * 01/2004: Optimizations by Gabriel Bouvigne\n */\n function quantize_lines_xrpow_01(l, istep, xr, xrPos, ix, ixPos) {\n var compareval0 = (1.0 - 0.4054) / istep;\n\n assert(l > 0);\n l = l >> 1;\n while ((l--) != 0) {\n ix[ixPos++] = (compareval0 > xr[xrPos++]) ? 0 : 1;\n ix[ixPos++] = (compareval0 > xr[xrPos++]) ? 0 : 1;\n }\n }\n\n /**\n * XRPOW_FTOI is a macro to convert floats to ints.
\n * if XRPOW_FTOI(x) = nearest_int(x), then QUANTFAC(x)=adj43asm[x]
\n * ROUNDFAC= -0.0946
\n *\n * if XRPOW_FTOI(x) = floor(x), then QUANTFAC(x)=asj43[x]
\n * ROUNDFAC=0.4054
\n *\n * Note: using floor() or 0| is extremely slow. On machines where the\n * TAKEHIRO_IEEE754_HACK code above does not work, it is worthwile to write\n * some ASM for XRPOW_FTOI().\n */\n function quantize_lines_xrpow(l, istep, xr, xrPos, ix, ixPos) {\n assert(l > 0);\n\n l = l >> 1;\n var remaining = l % 2;\n l = l >> 1;\n while (l-- != 0) {\n var x0, x1, x2, x3;\n var rx0, rx1, rx2, rx3;\n\n x0 = xr[xrPos++] * istep;\n x1 = xr[xrPos++] * istep;\n rx0 = 0 | x0;\n x2 = xr[xrPos++] * istep;\n rx1 = 0 | x1;\n x3 = xr[xrPos++] * istep;\n rx2 = 0 | x2;\n x0 += qupvt.adj43[rx0];\n rx3 = 0 | x3;\n x1 += qupvt.adj43[rx1];\n ix[ixPos++] = 0 | x0;\n x2 += qupvt.adj43[rx2];\n ix[ixPos++] = 0 | x1;\n x3 += qupvt.adj43[rx3];\n ix[ixPos++] = 0 | x2;\n ix[ixPos++] = 0 | x3;\n }\n if (remaining != 0) {\n var x0, x1;\n var rx0, rx1;\n\n x0 = xr[xrPos++] * istep;\n x1 = xr[xrPos++] * istep;\n rx0 = 0 | x0;\n rx1 = 0 | x1;\n x0 += qupvt.adj43[rx0];\n x1 += qupvt.adj43[rx1];\n ix[ixPos++] = 0 | x0;\n ix[ixPos++] = 0 | x1;\n }\n }\n\n /**\n * Quantization function This function will select which lines to quantize\n * and call the proper quantization function\n */\n function quantize_xrpow(xp, pi, istep, codInfo, prevNoise) {\n /* quantize on xr^(3/4) instead of xr */\n var sfb;\n var sfbmax;\n var j = 0;\n var prev_data_use;\n var accumulate = 0;\n var accumulate01 = 0;\n var xpPos = 0;\n var iData = pi;\n var iDataPos = 0;\n var acc_iData = iData;\n var acc_iDataPos = 0;\n var acc_xp = xp;\n var acc_xpPos = 0;\n\n /*\n * Reusing previously computed data does not seems to work if global\n * gain is changed. Finding why it behaves this way would allow to use a\n * cache of previously computed values (let\'s 10 cached values per sfb)\n * that would probably provide a noticeable speedup\n */\n prev_data_use = (prevNoise != null && (codInfo.global_gain == prevNoise.global_gain));\n\n if (codInfo.block_type == Encoder.SHORT_TYPE)\n sfbmax = 38;\n else\n sfbmax = 21;\n\n for (sfb = 0; sfb <= sfbmax; sfb++) {\n var step = -1;\n\n if (prev_data_use || codInfo.block_type == Encoder.NORM_TYPE) {\n step = codInfo.global_gain\n - ((codInfo.scalefac[sfb] + (codInfo.preflag != 0 ? qupvt.pretab[sfb]\n : 0)) << (codInfo.scalefac_scale + 1))\n - codInfo.subblock_gain[codInfo.window[sfb]] * 8;\n }\n assert(codInfo.width[sfb] >= 0);\n if (prev_data_use && (prevNoise.step[sfb] == step)) {\n /*\n * do not recompute this part, but compute accumulated lines\n */\n if (accumulate != 0) {\n quantize_lines_xrpow(accumulate, istep, acc_xp, acc_xpPos,\n acc_iData, acc_iDataPos);\n accumulate = 0;\n }\n if (accumulate01 != 0) {\n quantize_lines_xrpow_01(accumulate01, istep, acc_xp,\n acc_xpPos, acc_iData, acc_iDataPos);\n accumulate01 = 0;\n }\n } else { /* should compute this part */\n var l = codInfo.width[sfb];\n\n if ((j + codInfo.width[sfb]) > codInfo.max_nonzero_coeff) {\n /* do not compute upper zero part */\n var usefullsize;\n usefullsize = codInfo.max_nonzero_coeff - j + 1;\n Arrays.fill(pi, codInfo.max_nonzero_coeff, 576, 0);\n l = usefullsize;\n\n if (l < 0) {\n l = 0;\n }\n\n /* no need to compute higher sfb values */\n sfb = sfbmax + 1;\n }\n\n /* accumulate lines to quantize */\n if (0 == accumulate && 0 == accumulate01) {\n acc_iData = iData;\n acc_iDataPos = iDataPos;\n acc_xp = xp;\n acc_xpPos = xpPos;\n }\n if (prevNoise != null && prevNoise.sfb_count1 > 0\n && sfb >= prevNoise.sfb_count1\n && prevNoise.step[sfb] > 0\n && step >= prevNoise.step[sfb]) {\n\n if (accumulate != 0) {\n quantize_lines_xrpow(accumulate, istep, acc_xp,\n acc_xpPos, acc_iData, acc_iDataPos);\n accumulate = 0;\n acc_iData = iData;\n acc_iDataPos = iDataPos;\n acc_xp = xp;\n acc_xpPos = xpPos;\n }\n accumulate01 += l;\n } else {\n if (accumulate01 != 0) {\n quantize_lines_xrpow_01(accumulate01, istep, acc_xp,\n acc_xpPos, acc_iData, acc_iDataPos);\n accumulate01 = 0;\n acc_iData = iData;\n acc_iDataPos = iDataPos;\n acc_xp = xp;\n acc_xpPos = xpPos;\n }\n accumulate += l;\n }\n\n if (l <= 0) {\n /*\n * rh: 20040215 may happen due to "prev_data_use"\n * optimization\n */\n if (accumulate01 != 0) {\n quantize_lines_xrpow_01(accumulate01, istep, acc_xp,\n acc_xpPos, acc_iData, acc_iDataPos);\n accumulate01 = 0;\n }\n if (accumulate != 0) {\n quantize_lines_xrpow(accumulate, istep, acc_xp,\n acc_xpPos, acc_iData, acc_iDataPos);\n accumulate = 0;\n }\n\n break;\n /* ends for-loop */\n }\n }\n if (sfb <= sfbmax) {\n iDataPos += codInfo.width[sfb];\n xpPos += codInfo.width[sfb];\n j += codInfo.width[sfb];\n }\n }\n if (accumulate != 0) { /* last data part */\n quantize_lines_xrpow(accumulate, istep, acc_xp, acc_xpPos,\n acc_iData, acc_iDataPos);\n accumulate = 0;\n }\n if (accumulate01 != 0) { /* last data part */\n quantize_lines_xrpow_01(accumulate01, istep, acc_xp, acc_xpPos,\n acc_iData, acc_iDataPos);\n accumulate01 = 0;\n }\n\n }\n\n /**\n * ix_max\n */\n function ix_max(ix, ixPos, endPos) {\n var max1 = 0, max2 = 0;\n\n do {\n var x1 = ix[ixPos++];\n var x2 = ix[ixPos++];\n if (max1 < x1)\n max1 = x1;\n\n if (max2 < x2)\n max2 = x2;\n } while (ixPos < endPos);\n if (max1 < max2)\n max1 = max2;\n return max1;\n }\n\n function count_bit_ESC(ix, ixPos, end, t1, t2, s) {\n /* ESC-table is used */\n var linbits = Tables.ht[t1].xlen * 65536 + Tables.ht[t2].xlen;\n var sum = 0, sum2;\n\n do {\n var x = ix[ixPos++];\n var y = ix[ixPos++];\n\n if (x != 0) {\n if (x > 14) {\n x = 15;\n sum += linbits;\n }\n x *= 16;\n }\n\n if (y != 0) {\n if (y > 14) {\n y = 15;\n sum += linbits;\n }\n x += y;\n }\n\n sum += Tables.largetbl[x];\n } while (ixPos < end);\n\n sum2 = sum & 0xffff;\n sum >>= 16;\n\n if (sum > sum2) {\n sum = sum2;\n t1 = t2;\n }\n\n s.bits += sum;\n return t1;\n }\n\n function count_bit_noESC(ix, ixPos, end, s) {\n /* No ESC-words */\n var sum1 = 0;\n var hlen1 = Tables.ht[1].hlen;\n\n do {\n var x = ix[ixPos + 0] * 2 + ix[ixPos + 1];\n ixPos += 2;\n sum1 += hlen1[x];\n } while (ixPos < end);\n\n s.bits += sum1;\n return 1;\n }\n\n function count_bit_noESC_from2(ix, ixPos, end, t1, s) {\n /* No ESC-words */\n var sum = 0, sum2;\n var xlen = Tables.ht[t1].xlen;\n var hlen;\n if (t1 == 2)\n hlen = Tables.table23;\n else\n hlen = Tables.table56;\n\n do {\n var x = ix[ixPos + 0] * xlen + ix[ixPos + 1];\n ixPos += 2;\n sum += hlen[x];\n } while (ixPos < end);\n\n sum2 = sum & 0xffff;\n sum >>= 16;\n\n if (sum > sum2) {\n sum = sum2;\n t1++;\n }\n\n s.bits += sum;\n return t1;\n }\n\n function count_bit_noESC_from3(ix, ixPos, end, t1, s) {\n /* No ESC-words */\n var sum1 = 0;\n var sum2 = 0;\n var sum3 = 0;\n var xlen = Tables.ht[t1].xlen;\n var hlen1 = Tables.ht[t1].hlen;\n var hlen2 = Tables.ht[t1 + 1].hlen;\n var hlen3 = Tables.ht[t1 + 2].hlen;\n\n do {\n var x = ix[ixPos + 0] * xlen + ix[ixPos + 1];\n ixPos += 2;\n sum1 += hlen1[x];\n sum2 += hlen2[x];\n sum3 += hlen3[x];\n } while (ixPos < end);\n var t = t1;\n if (sum1 > sum2) {\n sum1 = sum2;\n t++;\n }\n if (sum1 > sum3) {\n sum1 = sum3;\n t = t1 + 2;\n }\n s.bits += sum1;\n\n return t;\n }\n\n /*************************************************************************/\n /* choose table */\n /*************************************************************************/\n\n var huf_tbl_noESC = [1, 2, 5, 7, 7, 10, 10, 13, 13,\n 13, 13, 13, 13, 13, 13];\n\n /**\n * Choose the Huffman table that will encode ix[begin..end] with the fewest\n * bits.\n *\n * Note: This code contains knowledge about the sizes and characteristics of\n * the Huffman tables as defined in the IS (Table B.7), and will not work\n * with any arbitrary tables.\n */\n function choose_table(ix, ixPos, endPos, s) {\n var max = ix_max(ix, ixPos, endPos);\n\n switch (max) {\n case 0:\n return max;\n\n case 1:\n return count_bit_noESC(ix, ixPos, endPos, s);\n\n case 2:\n case 3:\n return count_bit_noESC_from2(ix, ixPos, endPos,\n huf_tbl_noESC[max - 1], s);\n\n case 4:\n case 5:\n case 6:\n case 7:\n case 8:\n case 9:\n case 10:\n case 11:\n case 12:\n case 13:\n case 14:\n case 15:\n return count_bit_noESC_from3(ix, ixPos, endPos,\n huf_tbl_noESC[max - 1], s);\n\n default:\n /* try tables with linbits */\n if (max > QuantizePVT.IXMAX_VAL) {\n s.bits = QuantizePVT.LARGE_BITS;\n return -1;\n }\n max -= 15;\n var choice2;\n for (choice2 = 24; choice2 < 32; choice2++) {\n if (Tables.ht[choice2].linmax >= max) {\n break;\n }\n }\n var choice;\n for (choice = choice2 - 8; choice < 24; choice++) {\n if (Tables.ht[choice].linmax >= max) {\n break;\n }\n }\n return count_bit_ESC(ix, ixPos, endPos, choice, choice2, s);\n }\n }\n\n /**\n * count_bit\n */\n this.noquant_count_bits = function (gfc, gi, prev_noise) {\n var ix = gi.l3_enc;\n var i = Math.min(576, ((gi.max_nonzero_coeff + 2) >> 1) << 1);\n\n if (prev_noise != null)\n prev_noise.sfb_count1 = 0;\n\n /* Determine count1 region */\n for (; i > 1; i -= 2)\n if ((ix[i - 1] | ix[i - 2]) != 0)\n break;\n gi.count1 = i;\n\n /* Determines the number of bits to encode the quadruples. */\n var a1 = 0;\n var a2 = 0;\n for (; i > 3; i -= 4) {\n var p;\n /* hack to check if all values <= 1 */\n //throw "TODO: HACK if ((((long) ix[i - 1] | (long) ix[i - 2] | (long) ix[i - 3] | (long) ix[i - 4]) & 0xffffffffL) > 1L "\n //if (true) {\n if (((ix[i - 1] | ix[i - 2] | ix[i - 3] | ix[i - 4]) & 0x7fffffff) > 1) {\n break;\n }\n p = ((ix[i - 4] * 2 + ix[i - 3]) * 2 + ix[i - 2]) * 2 + ix[i - 1];\n a1 += Tables.t32l[p];\n a2 += Tables.t33l[p];\n }\n var bits = a1;\n gi.count1table_select = 0;\n if (a1 > a2) {\n bits = a2;\n gi.count1table_select = 1;\n }\n\n gi.count1bits = bits;\n gi.big_values = i;\n if (i == 0)\n return bits;\n\n if (gi.block_type == Encoder.SHORT_TYPE) {\n a1 = 3 * gfc.scalefac_band.s[3];\n if (a1 > gi.big_values)\n a1 = gi.big_values;\n a2 = gi.big_values;\n\n } else if (gi.block_type == Encoder.NORM_TYPE) {\n assert(i <= 576);\n /* bv_scf has 576 entries (0..575) */\n a1 = gi.region0_count = gfc.bv_scf[i - 2];\n a2 = gi.region1_count = gfc.bv_scf[i - 1];\n\n assert(a1 + a2 + 2 < Encoder.SBPSY_l);\n a2 = gfc.scalefac_band.l[a1 + a2 + 2];\n a1 = gfc.scalefac_band.l[a1 + 1];\n if (a2 < i) {\n var bi = new Bits(bits);\n gi.table_select[2] = choose_table(ix, a2, i, bi);\n bits = bi.bits;\n }\n } else {\n gi.region0_count = 7;\n /* gi.region1_count = SBPSY_l - 7 - 1; */\n gi.region1_count = Encoder.SBMAX_l - 1 - 7 - 1;\n a1 = gfc.scalefac_band.l[7 + 1];\n a2 = i;\n if (a1 > a2) {\n a1 = a2;\n }\n }\n\n /* have to allow for the case when bigvalues < region0 < region1 */\n /* (and region0, region1 are ignored) */\n a1 = Math.min(a1, i);\n a2 = Math.min(a2, i);\n\n assert(a1 >= 0);\n assert(a2 >= 0);\n\n /* Count the number of bits necessary to code the bigvalues region. */\n if (0 < a1) {\n var bi = new Bits(bits);\n gi.table_select[0] = choose_table(ix, 0, a1, bi);\n bits = bi.bits;\n }\n if (a1 < a2) {\n var bi = new Bits(bits);\n gi.table_select[1] = choose_table(ix, a1, a2, bi);\n bits = bi.bits;\n }\n if (gfc.use_best_huffman == 2) {\n gi.part2_3_length = bits;\n best_huffman_divide(gfc, gi);\n bits = gi.part2_3_length;\n }\n\n if (prev_noise != null) {\n if (gi.block_type == Encoder.NORM_TYPE) {\n var sfb = 0;\n while (gfc.scalefac_band.l[sfb] < gi.big_values) {\n sfb++;\n }\n prev_noise.sfb_count1 = sfb;\n }\n }\n\n return bits;\n }\n\n this.count_bits = function (gfc, xr, gi, prev_noise) {\n var ix = gi.l3_enc;\n\n /* since quantize_xrpow uses table lookup, we need to check this first: */\n var w = (QuantizePVT.IXMAX_VAL) / qupvt.IPOW20(gi.global_gain);\n\n if (gi.xrpow_max > w)\n return QuantizePVT.LARGE_BITS;\n\n quantize_xrpow(xr, ix, qupvt.IPOW20(gi.global_gain), gi, prev_noise);\n\n if ((gfc.substep_shaping & 2) != 0) {\n var j = 0;\n /* 0.634521682242439 = 0.5946*2**(.5*0.1875) */\n var gain = gi.global_gain + gi.scalefac_scale;\n var roundfac = 0.634521682242439 / qupvt.IPOW20(gain);\n for (var sfb = 0; sfb < gi.sfbmax; sfb++) {\n var width = gi.width[sfb];\n assert(width >= 0);\n if (0 == gfc.pseudohalf[sfb]) {\n j += width;\n } else {\n var k;\n for (k = j, j += width; k < j; ++k) {\n ix[k] = (xr[k] >= roundfac) ? ix[k] : 0;\n }\n }\n }\n }\n return this.noquant_count_bits(gfc, gi, prev_noise);\n }\n\n /**\n * re-calculate the best scalefac_compress using scfsi the saved bits are\n * kept in the bit reservoir.\n */\n function recalc_divide_init(gfc, cod_info, ix, r01_bits, r01_div, r0_tbl, r1_tbl) {\n var bigv = cod_info.big_values;\n\n for (var r0 = 0; r0 <= 7 + 15; r0++) {\n r01_bits[r0] = QuantizePVT.LARGE_BITS;\n }\n\n for (var r0 = 0; r0 < 16; r0++) {\n var a1 = gfc.scalefac_band.l[r0 + 1];\n if (a1 >= bigv)\n break;\n var r0bits = 0;\n var bi = new Bits(r0bits);\n var r0t = choose_table(ix, 0, a1, bi);\n r0bits = bi.bits;\n\n for (var r1 = 0; r1 < 8; r1++) {\n var a2 = gfc.scalefac_band.l[r0 + r1 + 2];\n if (a2 >= bigv)\n break;\n var bits = r0bits;\n bi = new Bits(bits);\n var r1t = choose_table(ix, a1, a2, bi);\n bits = bi.bits;\n if (r01_bits[r0 + r1] > bits) {\n r01_bits[r0 + r1] = bits;\n r01_div[r0 + r1] = r0;\n r0_tbl[r0 + r1] = r0t;\n r1_tbl[r0 + r1] = r1t;\n }\n }\n }\n }\n\n function recalc_divide_sub(gfc, cod_info2, gi, ix, r01_bits, r01_div, r0_tbl, r1_tbl) {\n var bigv = cod_info2.big_values;\n\n for (var r2 = 2; r2 < Encoder.SBMAX_l + 1; r2++) {\n var a2 = gfc.scalefac_band.l[r2];\n if (a2 >= bigv)\n break;\n var bits = r01_bits[r2 - 2] + cod_info2.count1bits;\n if (gi.part2_3_length <= bits)\n break;\n\n var bi = new Bits(bits);\n var r2t = choose_table(ix, a2, bigv, bi);\n bits = bi.bits;\n if (gi.part2_3_length <= bits)\n continue;\n\n gi.assign(cod_info2);\n gi.part2_3_length = bits;\n gi.region0_count = r01_div[r2 - 2];\n gi.region1_count = r2 - 2 - r01_div[r2 - 2];\n gi.table_select[0] = r0_tbl[r2 - 2];\n gi.table_select[1] = r1_tbl[r2 - 2];\n gi.table_select[2] = r2t;\n }\n }\n\n this.best_huffman_divide = function (gfc, gi) {\n var cod_info2 = new GrInfo();\n var ix = gi.l3_enc;\n var r01_bits = new_int(7 + 15 + 1);\n var r01_div = new_int(7 + 15 + 1);\n var r0_tbl = new_int(7 + 15 + 1);\n var r1_tbl = new_int(7 + 15 + 1);\n\n /* SHORT BLOCK stuff fails for MPEG2 */\n if (gi.block_type == Encoder.SHORT_TYPE && gfc.mode_gr == 1)\n return;\n\n cod_info2.assign(gi);\n if (gi.block_type == Encoder.NORM_TYPE) {\n recalc_divide_init(gfc, gi, ix, r01_bits, r01_div, r0_tbl, r1_tbl);\n recalc_divide_sub(gfc, cod_info2, gi, ix, r01_bits, r01_div,\n r0_tbl, r1_tbl);\n }\n var i = cod_info2.big_values;\n if (i == 0 || (ix[i - 2] | ix[i - 1]) > 1)\n return;\n\n i = gi.count1 + 2;\n if (i > 576)\n return;\n\n /* Determines the number of bits to encode the quadruples. */\n cod_info2.assign(gi);\n cod_info2.count1 = i;\n var a1 = 0;\n var a2 = 0;\n\n assert(i <= 576);\n\n for (; i > cod_info2.big_values; i -= 4) {\n var p = ((ix[i - 4] * 2 + ix[i - 3]) * 2 + ix[i - 2]) * 2\n + ix[i - 1];\n a1 += Tables.t32l[p];\n a2 += Tables.t33l[p];\n }\n cod_info2.big_values = i;\n\n cod_info2.count1table_select = 0;\n if (a1 > a2) {\n a1 = a2;\n cod_info2.count1table_select = 1;\n }\n\n cod_info2.count1bits = a1;\n\n if (cod_info2.block_type == Encoder.NORM_TYPE)\n recalc_divide_sub(gfc, cod_info2, gi, ix, r01_bits, r01_div,\n r0_tbl, r1_tbl);\n else {\n /* Count the number of bits necessary to code the bigvalues region. */\n cod_info2.part2_3_length = a1;\n a1 = gfc.scalefac_band.l[7 + 1];\n if (a1 > i) {\n a1 = i;\n }\n if (a1 > 0) {\n var bi = new Bits(cod_info2.part2_3_length);\n cod_info2.table_select[0] = choose_table(ix, 0, a1, bi);\n cod_info2.part2_3_length = bi.bits;\n }\n if (i > a1) {\n var bi = new Bits(cod_info2.part2_3_length);\n cod_info2.table_select[1] = choose_table(ix, a1, i, bi);\n cod_info2.part2_3_length = bi.bits;\n }\n if (gi.part2_3_length > cod_info2.part2_3_length)\n gi.assign(cod_info2);\n }\n }\n\n var slen1_n = [1, 1, 1, 1, 8, 2, 2, 2, 4, 4, 4, 8, 8, 8, 16, 16];\n var slen2_n = [1, 2, 4, 8, 1, 2, 4, 8, 2, 4, 8, 2, 4, 8, 4, 8];\n var slen1_tab = [0, 0, 0, 0, 3, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4];\n var slen2_tab = [0, 1, 2, 3, 0, 1, 2, 3, 1, 2, 3, 1, 2, 3, 2, 3];\n Takehiro.slen1_tab = slen1_tab;\n Takehiro.slen2_tab = slen2_tab;\n\n function scfsi_calc(ch, l3_side) {\n var sfb;\n var gi = l3_side.tt[1][ch];\n var g0 = l3_side.tt[0][ch];\n\n for (var i = 0; i < Tables.scfsi_band.length - 1; i++) {\n for (sfb = Tables.scfsi_band[i]; sfb < Tables.scfsi_band[i + 1]; sfb++) {\n if (g0.scalefac[sfb] != gi.scalefac[sfb]\n && gi.scalefac[sfb] >= 0)\n break;\n }\n if (sfb == Tables.scfsi_band[i + 1]) {\n for (sfb = Tables.scfsi_band[i]; sfb < Tables.scfsi_band[i + 1]; sfb++) {\n gi.scalefac[sfb] = -1;\n }\n l3_side.scfsi[ch][i] = 1;\n }\n }\n var s1 = 0;\n var c1 = 0;\n for (sfb = 0; sfb < 11; sfb++) {\n if (gi.scalefac[sfb] == -1)\n continue;\n c1++;\n if (s1 < gi.scalefac[sfb])\n s1 = gi.scalefac[sfb];\n }\n var s2 = 0;\n var c2 = 0;\n for (; sfb < Encoder.SBPSY_l; sfb++) {\n if (gi.scalefac[sfb] == -1)\n continue;\n c2++;\n if (s2 < gi.scalefac[sfb])\n s2 = gi.scalefac[sfb];\n }\n\n for (var i = 0; i < 16; i++) {\n if (s1 < slen1_n[i] && s2 < slen2_n[i]) {\n var c = slen1_tab[i] * c1 + slen2_tab[i] * c2;\n if (gi.part2_length > c) {\n gi.part2_length = c;\n gi.scalefac_compress = i;\n }\n }\n }\n }\n\n /**\n * Find the optimal way to store the scalefactors. Only call this routine\n * after final scalefactors have been chosen and the channel/granule will\n * not be re-encoded.\n */\n this.best_scalefac_store = function (gfc, gr, ch, l3_side) {\n /* use scalefac_scale if we can */\n var gi = l3_side.tt[gr][ch];\n var sfb, i, j, l;\n var recalc = 0;\n\n /*\n * remove scalefacs from bands with ix=0. This idea comes from the AAC\n * ISO docs. added mt 3/00\n */\n /* check if l3_enc=0 */\n j = 0;\n for (sfb = 0; sfb < gi.sfbmax; sfb++) {\n var width = gi.width[sfb];\n assert(width >= 0);\n j += width;\n for (l = -width; l < 0; l++) {\n if (gi.l3_enc[l + j] != 0)\n break;\n }\n if (l == 0)\n gi.scalefac[sfb] = recalc = -2;\n /* anything goes. */\n /*\n * only best_scalefac_store and calc_scfsi know--and only they\n * should know--about the magic number -2.\n */\n }\n\n if (0 == gi.scalefac_scale && 0 == gi.preflag) {\n var s = 0;\n for (sfb = 0; sfb < gi.sfbmax; sfb++)\n if (gi.scalefac[sfb] > 0)\n s |= gi.scalefac[sfb];\n\n if (0 == (s & 1) && s != 0) {\n for (sfb = 0; sfb < gi.sfbmax; sfb++)\n if (gi.scalefac[sfb] > 0)\n gi.scalefac[sfb] >>= 1;\n\n gi.scalefac_scale = recalc = 1;\n }\n }\n\n if (0 == gi.preflag && gi.block_type != Encoder.SHORT_TYPE\n && gfc.mode_gr == 2) {\n for (sfb = 11; sfb < Encoder.SBPSY_l; sfb++)\n if (gi.scalefac[sfb] < qupvt.pretab[sfb]\n && gi.scalefac[sfb] != -2)\n break;\n if (sfb == Encoder.SBPSY_l) {\n for (sfb = 11; sfb < Encoder.SBPSY_l; sfb++)\n if (gi.scalefac[sfb] > 0)\n gi.scalefac[sfb] -= qupvt.pretab[sfb];\n\n gi.preflag = recalc = 1;\n }\n }\n\n for (i = 0; i < 4; i++)\n l3_side.scfsi[ch][i] = 0;\n\n if (gfc.mode_gr == 2 && gr == 1\n && l3_side.tt[0][ch].block_type != Encoder.SHORT_TYPE\n && l3_side.tt[1][ch].block_type != Encoder.SHORT_TYPE) {\n scfsi_calc(ch, l3_side);\n recalc = 0;\n }\n for (sfb = 0; sfb < gi.sfbmax; sfb++) {\n if (gi.scalefac[sfb] == -2) {\n gi.scalefac[sfb] = 0;\n /* if anything goes, then 0 is a good choice */\n }\n }\n if (recalc != 0) {\n if (gfc.mode_gr == 2) {\n this.scale_bitcount(gi);\n } else {\n this.scale_bitcount_lsf(gfc, gi);\n }\n }\n }\n\n function all_scalefactors_not_negative(scalefac, n) {\n for (var i = 0; i < n; ++i) {\n if (scalefac[i] < 0)\n return false;\n }\n return true;\n }\n\n /**\n * number of bits used to encode scalefacs.\n *\n * 18*slen1_tab[i] + 18*slen2_tab[i]\n */\n var scale_short = [0, 18, 36, 54, 54, 36, 54, 72,\n 54, 72, 90, 72, 90, 108, 108, 126];\n\n /**\n * number of bits used to encode scalefacs.\n *\n * 17*slen1_tab[i] + 18*slen2_tab[i]\n */\n var scale_mixed = [0, 18, 36, 54, 51, 35, 53, 71,\n 52, 70, 88, 69, 87, 105, 104, 122];\n\n /**\n * number of bits used to encode scalefacs.\n *\n * 11*slen1_tab[i] + 10*slen2_tab[i]\n */\n var scale_long = [0, 10, 20, 30, 33, 21, 31, 41, 32, 42,\n 52, 43, 53, 63, 64, 74];\n\n /**\n * Also calculates the number of bits necessary to code the scalefactors.\n */\n this.scale_bitcount = function (cod_info) {\n var k, sfb, max_slen1 = 0, max_slen2 = 0;\n\n /* maximum values */\n var tab;\n var scalefac = cod_info.scalefac;\n\n assert(all_scalefactors_not_negative(scalefac, cod_info.sfbmax));\n\n if (cod_info.block_type == Encoder.SHORT_TYPE) {\n tab = scale_short;\n if (cod_info.mixed_block_flag != 0)\n tab = scale_mixed;\n } else { /* block_type == 1,2,or 3 */\n tab = scale_long;\n if (0 == cod_info.preflag) {\n for (sfb = 11; sfb < Encoder.SBPSY_l; sfb++)\n if (scalefac[sfb] < qupvt.pretab[sfb])\n break;\n\n if (sfb == Encoder.SBPSY_l) {\n cod_info.preflag = 1;\n for (sfb = 11; sfb < Encoder.SBPSY_l; sfb++)\n scalefac[sfb] -= qupvt.pretab[sfb];\n }\n }\n }\n\n for (sfb = 0; sfb < cod_info.sfbdivide; sfb++)\n if (max_slen1 < scalefac[sfb])\n max_slen1 = scalefac[sfb];\n\n for (; sfb < cod_info.sfbmax; sfb++)\n if (max_slen2 < scalefac[sfb])\n max_slen2 = scalefac[sfb];\n\n /*\n * from Takehiro TOMINAGA 10/99 loop over *all*\n * posible values of scalefac_compress to find the one which uses the\n * smallest number of bits. ISO would stop at first valid index\n */\n cod_info.part2_length = QuantizePVT.LARGE_BITS;\n for (k = 0; k < 16; k++) {\n if (max_slen1 < slen1_n[k] && max_slen2 < slen2_n[k]\n && cod_info.part2_length > tab[k]) {\n cod_info.part2_length = tab[k];\n cod_info.scalefac_compress = k;\n }\n }\n return cod_info.part2_length == QuantizePVT.LARGE_BITS;\n }\n\n /**\n * table of largest scalefactor values for MPEG2\n */\n var max_range_sfac_tab = [[15, 15, 7, 7],\n [15, 15, 7, 0], [7, 3, 0, 0], [15, 31, 31, 0],\n [7, 7, 7, 0], [3, 3, 0, 0]];\n\n /**\n * Also counts the number of bits to encode the scalefacs but for MPEG 2\n * Lower sampling frequencies (24, 22.05 and 16 kHz.)\n *\n * This is reverse-engineered from section 2.4.3.2 of the MPEG2 IS,\n * "Audio Decoding Layer III"\n */\n this.scale_bitcount_lsf = function (gfc, cod_info) {\n var table_number, row_in_table, partition, nr_sfb, window;\n var over;\n var i, sfb;\n var max_sfac = new_int(4);\n//var partition_table;\n var scalefac = cod_info.scalefac;\n\n /*\n * Set partition table. Note that should try to use table one, but do\n * not yet...\n */\n if (cod_info.preflag != 0)\n table_number = 2;\n else\n table_number = 0;\n\n for (i = 0; i < 4; i++)\n max_sfac[i] = 0;\n\n if (cod_info.block_type == Encoder.SHORT_TYPE) {\n row_in_table = 1;\n var partition_table = qupvt.nr_of_sfb_block[table_number][row_in_table];\n for (sfb = 0, partition = 0; partition < 4; partition++) {\n nr_sfb = partition_table[partition] / 3;\n for (i = 0; i < nr_sfb; i++, sfb++)\n for (window = 0; window < 3; window++)\n if (scalefac[sfb * 3 + window] > max_sfac[partition])\n max_sfac[partition] = scalefac[sfb * 3 + window];\n }\n } else {\n row_in_table = 0;\n var partition_table = qupvt.nr_of_sfb_block[table_number][row_in_table];\n for (sfb = 0, partition = 0; partition < 4; partition++) {\n nr_sfb = partition_table[partition];\n for (i = 0; i < nr_sfb; i++, sfb++)\n if (scalefac[sfb] > max_sfac[partition])\n max_sfac[partition] = scalefac[sfb];\n }\n }\n\n for (over = false, partition = 0; partition < 4; partition++) {\n if (max_sfac[partition] > max_range_sfac_tab[table_number][partition])\n over = true;\n }\n if (!over) {\n var slen1, slen2, slen3, slen4;\n\n cod_info.sfb_partition_table = qupvt.nr_of_sfb_block[table_number][row_in_table];\n for (partition = 0; partition < 4; partition++)\n cod_info.slen[partition] = log2tab[max_sfac[partition]];\n\n /* set scalefac_compress */\n slen1 = cod_info.slen[0];\n slen2 = cod_info.slen[1];\n slen3 = cod_info.slen[2];\n slen4 = cod_info.slen[3];\n\n switch (table_number) {\n case 0:\n cod_info.scalefac_compress = (((slen1 * 5) + slen2) << 4)\n + (slen3 << 2) + slen4;\n break;\n\n case 1:\n cod_info.scalefac_compress = 400 + (((slen1 * 5) + slen2) << 2)\n + slen3;\n break;\n\n case 2:\n cod_info.scalefac_compress = 500 + (slen1 * 3) + slen2;\n break;\n\n default:\n System.err.printf("intensity stereo not implemented yet\\n");\n break;\n }\n }\n if (!over) {\n assert(cod_info.sfb_partition_table != null);\n cod_info.part2_length = 0;\n for (partition = 0; partition < 4; partition++)\n cod_info.part2_length += cod_info.slen[partition]\n * cod_info.sfb_partition_table[partition];\n }\n return over;\n }\n\n /*\n * Since no bands have been over-amplified, we can set scalefac_compress and\n * slen[] for the formatter\n */\n var log2tab = [0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4,\n 4, 4, 4, 4];\n\n this.huffman_init = function (gfc) {\n for (var i = 2; i <= 576; i += 2) {\n var scfb_anz = 0, bv_index;\n while (gfc.scalefac_band.l[++scfb_anz] < i)\n ;\n\n bv_index = subdv_table[scfb_anz][0]; // .region0_count\n while (gfc.scalefac_band.l[bv_index + 1] > i)\n bv_index--;\n\n if (bv_index < 0) {\n /*\n * this is an indication that everything is going to be encoded\n * as region0: bigvalues < region0 < region1 so lets set\n * region0, region1 to some value larger than bigvalues\n */\n bv_index = subdv_table[scfb_anz][0]; // .region0_count\n }\n\n gfc.bv_scf[i - 2] = bv_index;\n\n bv_index = subdv_table[scfb_anz][1]; // .region1_count\n while (gfc.scalefac_band.l[bv_index + gfc.bv_scf[i - 2] + 2] > i)\n bv_index--;\n\n if (bv_index < 0) {\n bv_index = subdv_table[scfb_anz][1]; // .region1_count\n }\n\n gfc.bv_scf[i - 1] = bv_index;\n }\n }\n}\n\nmodule.exports = Takehiro;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL01ZOC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvVGFrZWhpcm8uanM/ZmNjNiJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICpcdE1QMyBodWZmbWFuIHRhYmxlIHNlbGVjdGluZyBhbmQgYml0IGNvdW50aW5nXG4gKlxuICpcdENvcHlyaWdodCAoYykgMTk5OS0yMDA1IFRha2VoaXJvIFRPTUlOQUdBXG4gKlx0Q29weXJpZ2h0IChjKSAyMDAyLTIwMDUgR2FicmllbCBCb3V2aWduZVxuICpcbiAqIFRoaXMgbGlicmFyeSBpcyBmcmVlIHNvZnR3YXJlOyB5b3UgY2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3JcbiAqIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbiAqIExpY2Vuc2UgYXMgcHVibGlzaGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlclxuICogdmVyc2lvbiAyIG9mIHRoZSBMaWNlbnNlLCBvciAoYXQgeW91ciBvcHRpb24pIGFueSBsYXRlciB2ZXJzaW9uLlxuICpcbiAqIFRoaXMgbGlicmFyeSBpcyBkaXN0cmlidXRlZCBpbiB0aGUgaG9wZSB0aGF0IGl0IHdpbGwgYmUgdXNlZnVsLFxuICogYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqIE1FUkNIQU5UQUJJTElUWSBvciBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRS5cdCBTZWUgdGhlIEdOVVxuICogTGlicmFyeSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGVcbiAqIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlIC0gU3VpdGUgMzMwLFxuICogQm9zdG9uLCBNQSAwMjExMS0xMzA3LCBVU0EuXG4gKi9cblxuLyogJElkOiBUYWtlaGlyby5qYXZhLHYgMS4yNiAyMDExLzA1LzI0IDIwOjQ4OjA2IGtlbmNoaXMgRXhwICQgKi9cblxuLy9wYWNrYWdlIG1wMztcblxuLy9pbXBvcnQgamF2YS51dGlsLkFycmF5cztcbnZhciBjb21tb24gPSByZXF1aXJlKCcuL2NvbW1vbi5qcycpO1xudmFyIFN5c3RlbSA9IGNvbW1vbi5TeXN0ZW07XG52YXIgVmJyTW9kZSA9IGNvbW1vbi5WYnJNb2RlO1xudmFyIEZsb2F0ID0gY29tbW9uLkZsb2F0O1xudmFyIFNob3J0QmxvY2sgPSBjb21tb24uU2hvcnRCbG9jaztcbnZhciBVdGlsID0gY29tbW9uLlV0aWw7XG52YXIgQXJyYXlzID0gY29tbW9uLkFycmF5cztcbnZhciBuZXdfYXJyYXlfbiA9IGNvbW1vbi5uZXdfYXJyYXlfbjtcbnZhciBuZXdfYnl0ZSA9IGNvbW1vbi5uZXdfYnl0ZTtcbnZhciBuZXdfZG91YmxlID0gY29tbW9uLm5ld19kb3VibGU7XG52YXIgbmV3X2Zsb2F0ID0gY29tbW9uLm5ld19mbG9hdDtcbnZhciBuZXdfZmxvYXRfbiA9IGNvbW1vbi5uZXdfZmxvYXRfbjtcbnZhciBuZXdfaW50ID0gY29tbW9uLm5ld19pbnQ7XG52YXIgbmV3X2ludF9uID0gY29tbW9uLm5ld19pbnRfbjtcbnZhciBhc3NlcnQgPSBjb21tb24uYXNzZXJ0O1xuXG52YXIgRW5jb2RlciA9IHJlcXVpcmUoJy4vRW5jb2Rlci5qcycpO1xudmFyIFRhYmxlcyA9IHJlcXVpcmUoJy4vVGFibGVzLmpzJyk7XG52YXIgR3JJbmZvID0gcmVxdWlyZSgnLi9HckluZm8uanMnKTtcbnZhciBRdWFudGl6ZVBWVCA9IHJlcXVpcmUoJy4vUXVhbnRpemVQVlQuanMnKTtcblxuXG5mdW5jdGlvbiBUYWtlaGlybygpIHtcblxuICAgIHZhciBxdXB2dCA9IG51bGw7XG4gICAgdGhpcy5xdXB2dCA9IG51bGw7XG5cbiAgICB0aGlzLnNldE1vZHVsZXMgPSBmdW5jdGlvbiAoX3F1cHZ0KSB7XG4gICAgICAgIHRoaXMucXVwdnQgPSBfcXVwdnQ7XG4gICAgICAgIHF1cHZ0ID0gX3F1cHZ0O1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIEJpdHMoYikge1xuICAgICAgICB0aGlzLmJpdHMgPSAwIHwgYjtcbiAgICB9XG5cbiAgICB2YXIgc3ViZHZfdGFibGUgPSBbWzAsIDBdLCAvKiAwIGJhbmRzICovXG4gICAgICAgIFswLCAwXSwgLyogMSBiYW5kcyAqL1xuICAgICAgICBbMCwgMF0sIC8qIDIgYmFuZHMgKi9cbiAgICAgICAgWzAsIDBdLCAvKiAzIGJhbmRzICovXG4gICAgICAgIFswLCAwXSwgLyogNCBiYW5kcyAqL1xuICAgICAgICBbMCwgMV0sIC8qIDUgYmFuZHMgKi9cbiAgICAgICAgWzEsIDFdLCAvKiA2IGJhbmRzICovXG4gICAgICAgIFsxLCAxXSwgLyogNyBiYW5kcyAqL1xuICAgICAgICBbMSwgMl0sIC8qIDggYmFuZHMgKi9cbiAgICAgICAgWzIsIDJdLCAvKiA5IGJhbmRzICovXG4gICAgICAgIFsyLCAzXSwgLyogMTAgYmFuZHMgKi9cbiAgICAgICAgWzIsIDNdLCAvKiAxMSBiYW5kcyAqL1xuICAgICAgICBbMywgNF0sIC8qIDEyIGJhbmRzICovXG4gICAgICAgIFszLCA0XSwgLyogMTMgYmFuZHMgKi9cbiAgICAgICAgWzMsIDRdLCAvKiAxNCBiYW5kcyAqL1xuICAgICAgICBbNCwgNV0sIC8qIDE1IGJhbmRzICovXG4gICAgICAgIFs0LCA1XSwgLyogMTYgYmFuZHMgKi9cbiAgICAgICAgWzQsIDZdLCAvKiAxNyBiYW5kcyAqL1xuICAgICAgICBbNSwgNl0sIC8qIDE4IGJhbmRzICovXG4gICAgICAgIFs1LCA2XSwgLyogMTkgYmFuZHMgKi9cbiAgICAgICAgWzUsIDddLCAvKiAyMCBiYW5kcyAqL1xuICAgICAgICBbNiwgN10sIC8qIDIxIGJhbmRzICovXG4gICAgICAgIFs2LCA3XSwgLyogMjIgYmFuZHMgKi9cbiAgICBdO1xuXG4gICAgLyoqXG4gICAgICogbm9ubGluZWFyIHF1YW50aXphdGlvbiBvZiB4ciBNb3JlIGFjY3VyYXRlIGZvcm11bGEgdGhhbiB0aGUgSVNPIGZvcm11bGEuXG4gICAgICogVGFrZXMgaW50byBhY2NvdW50IHRoZSBmYWN0IHRoYXQgd2UgYXJlIHF1YW50aXppbmcgeHIgLiBpeCwgYnV0IHdlIHdhbnRcbiAgICAgKiBpeF40LzMgdG8gYmUgYXMgY2xvc2UgYXMgcG9zc2libGUgdG8geF40LzMuICh0YWtpbmcgdGhlIG5lYXJlc3QgaW50IHdvdWxkXG4gICAgICogbWVhbiBpeCBpcyBhcyBjbG9zZSBhcyBwb3NzaWJsZSB0byB4ciwgd2hpY2ggaXMgZGlmZmVyZW50LilcbiAgICAgKlxuICAgICAqIEZyb20gU2VnaGVyIEJvZXNzZW5rb29sIDxzZWdoZXJAZWFzdHNpdGUubmw+IDExLzE5OTlcbiAgICAgKlxuICAgICAqIDA5LzIwMDA6IEFTTSBjb2RlIHJlbW92ZWQgaW4gZmF2b3Igb2YgSUVFRTc1NCBoYWNrIGJ5IFRha2VoaXJvIFRvbWluYWdhLlxuICAgICAqIElmIHlvdSBuZWVkIHRoZSBBU00gY29kZSwgY2hlY2sgQ1ZTIGNpcmNhIEF1ZyAyMDAwLlxuICAgICAqXG4gICAgICogMDEvMjAwNDogT3B0aW1pemF0aW9ucyBieSBHYWJyaWVsIEJvdXZpZ25lXG4gICAgICovXG4gICAgZnVuY3Rpb24gcXVhbnRpemVfbGluZXNfeHJwb3dfMDEobCwgaXN0ZXAsIHhyLCB4clBvcywgaXgsIGl4UG9zKSB7XG4gICAgICAgIHZhciBjb21wYXJldmFsMCA9ICgxLjAgLSAwLjQwNTQpIC8gaXN0ZXA7XG5cbiAgICAgICAgYXNzZXJ0KGwgPiAwKTtcbiAgICAgICAgbCA9IGwgPj4gMTtcbiAgICAgICAgd2hpbGUgKChsLS0pICE9IDApIHtcbiAgICAgICAgICAgIGl4W2l4UG9zKytdID0gKGNvbXBhcmV2YWwwID4geHJbeHJQb3MrK10pID8gMCA6IDE7XG4gICAgICAgICAgICBpeFtpeFBvcysrXSA9IChjb21wYXJldmFsMCA+IHhyW3hyUG9zKytdKSA/IDAgOiAxO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogWFJQT1dfRlRPSSBpcyBhIG1hY3JvIHRvIGNvbnZlcnQgZmxvYXRzIHRvIGludHMuPEJSPlxuICAgICAqIGlmIFhSUE9XX0ZUT0koeCkgPSBuZWFyZXN0X2ludCh4KSwgdGhlbiBRVUFOVEZBQyh4KT1hZGo0M2FzbVt4XTxCUj5cbiAgICAgKiBST1VOREZBQz0gLTAuMDk0NjxCUj5cbiAgICAgKlxuICAgICAqIGlmIFhSUE9XX0ZUT0koeCkgPSBmbG9vcih4KSwgdGhlbiBRVUFOVEZBQyh4KT1hc2o0M1t4XTxCUj5cbiAgICAgKiBST1VOREZBQz0wLjQwNTQ8QlI+XG4gICAgICpcbiAgICAgKiBOb3RlOiB1c2luZyBmbG9vcigpIG9yIDB8IGlzIGV4dHJlbWVseSBzbG93LiBPbiBtYWNoaW5lcyB3aGVyZSB0aGVcbiAgICAgKiBUQUtFSElST19JRUVFNzU0X0hBQ0sgY29kZSBhYm92ZSBkb2VzIG5vdCB3b3JrLCBpdCBpcyB3b3J0aHdpbGUgdG8gd3JpdGVcbiAgICAgKiBzb21lIEFTTSBmb3IgWFJQT1dfRlRPSSgpLlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHF1YW50aXplX2xpbmVzX3hycG93KGwsIGlzdGVwLCB4ciwgeHJQb3MsIGl4LCBpeFBvcykge1xuICAgICAgICBhc3NlcnQobCA+IDApO1xuXG4gICAgICAgIGwgPSBsID4+IDE7XG4gICAgICAgIHZhciByZW1haW5pbmcgPSBsICUgMjtcbiAgICAgICAgbCA9IGwgPj4gMTtcbiAgICAgICAgd2hpbGUgKGwtLSAhPSAwKSB7XG4gICAgICAgICAgICB2YXIgeDAsIHgxLCB4MiwgeDM7XG4gICAgICAgICAgICB2YXIgcngwLCByeDEsIHJ4MiwgcngzO1xuXG4gICAgICAgICAgICB4MCA9IHhyW3hyUG9zKytdICogaXN0ZXA7XG4gICAgICAgICAgICB4MSA9IHhyW3hyUG9zKytdICogaXN0ZXA7XG4gICAgICAgICAgICByeDAgPSAwIHwgeDA7XG4gICAgICAgICAgICB4MiA9IHhyW3hyUG9zKytdICogaXN0ZXA7XG4gICAgICAgICAgICByeDEgPSAwIHwgeDE7XG4gICAgICAgICAgICB4MyA9IHhyW3hyUG9zKytdICogaXN0ZXA7XG4gICAgICAgICAgICByeDIgPSAwIHwgeDI7XG4gICAgICAgICAgICB4MCArPSBxdXB2dC5hZGo0M1tyeDBdO1xuICAgICAgICAgICAgcngzID0gMCB8IHgzO1xuICAgICAgICAgICAgeDEgKz0gcXVwdnQuYWRqNDNbcngxXTtcbiAgICAgICAgICAgIGl4W2l4UG9zKytdID0gMCB8IHgwO1xuICAgICAgICAgICAgeDIgKz0gcXVwdnQuYWRqNDNbcngyXTtcbiAgICAgICAgICAgIGl4W2l4UG9zKytdID0gMCB8IHgxO1xuICAgICAgICAgICAgeDMgKz0gcXVwdnQuYWRqNDNbcngzXTtcbiAgICAgICAgICAgIGl4W2l4UG9zKytdID0gMCB8IHgyO1xuICAgICAgICAgICAgaXhbaXhQb3MrK10gPSAwIHwgeDM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJlbWFpbmluZyAhPSAwKSB7XG4gICAgICAgICAgICB2YXIgeDAsIHgxO1xuICAgICAgICAgICAgdmFyIHJ4MCwgcngxO1xuXG4gICAgICAgICAgICB4MCA9IHhyW3hyUG9zKytdICogaXN0ZXA7XG4gICAgICAgICAgICB4MSA9IHhyW3hyUG9zKytdICogaXN0ZXA7XG4gICAgICAgICAgICByeDAgPSAwIHwgeDA7XG4gICAgICAgICAgICByeDEgPSAwIHwgeDE7XG4gICAgICAgICAgICB4MCArPSBxdXB2dC5hZGo0M1tyeDBdO1xuICAgICAgICAgICAgeDEgKz0gcXVwdnQuYWRqNDNbcngxXTtcbiAgICAgICAgICAgIGl4W2l4UG9zKytdID0gMCB8IHgwO1xuICAgICAgICAgICAgaXhbaXhQb3MrK10gPSAwIHwgeDE7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBRdWFudGl6YXRpb24gZnVuY3Rpb24gVGhpcyBmdW5jdGlvbiB3aWxsIHNlbGVjdCB3aGljaCBsaW5lcyB0byBxdWFudGl6ZVxuICAgICAqIGFuZCBjYWxsIHRoZSBwcm9wZXIgcXVhbnRpemF0aW9uIGZ1bmN0aW9uXG4gICAgICovXG4gICAgZnVuY3Rpb24gcXVhbnRpemVfeHJwb3coeHAsIHBpLCBpc3RlcCwgY29kSW5mbywgcHJldk5vaXNlKSB7XG4gICAgICAgIC8qIHF1YW50aXplIG9uIHhyXigzLzQpIGluc3RlYWQgb2YgeHIgKi9cbiAgICAgICAgdmFyIHNmYjtcbiAgICAgICAgdmFyIHNmYm1heDtcbiAgICAgICAgdmFyIGogPSAwO1xuICAgICAgICB2YXIgcHJldl9kYXRhX3VzZTtcbiAgICAgICAgdmFyIGFjY3VtdWxhdGUgPSAwO1xuICAgICAgICB2YXIgYWNjdW11bGF0ZTAxID0gMDtcbiAgICAgICAgdmFyIHhwUG9zID0gMDtcbiAgICAgICAgdmFyIGlEYXRhID0gcGk7XG4gICAgICAgIHZhciBpRGF0YVBvcyA9IDA7XG4gICAgICAgIHZhciBhY2NfaURhdGEgPSBpRGF0YTtcbiAgICAgICAgdmFyIGFjY19pRGF0YVBvcyA9IDA7XG4gICAgICAgIHZhciBhY2NfeHAgPSB4cDtcbiAgICAgICAgdmFyIGFjY194cFBvcyA9IDA7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogUmV1c2luZyBwcmV2aW91c2x5IGNvbXB1dGVkIGRhdGEgZG9lcyBub3Qgc2VlbXMgdG8gd29yayBpZiBnbG9iYWxcbiAgICAgICAgICogZ2FpbiBpcyBjaGFuZ2VkLiBGaW5kaW5nIHdoeSBpdCBiZWhhdmVzIHRoaXMgd2F5IHdvdWxkIGFsbG93IHRvIHVzZSBhXG4gICAgICAgICAqIGNhY2hlIG9mIHByZXZpb3VzbHkgY29tcHV0ZWQgdmFsdWVzIChsZXQncyAxMCBjYWNoZWQgdmFsdWVzIHBlciBzZmIpXG4gICAgICAgICAqIHRoYXQgd291bGQgcHJvYmFibHkgcHJvdmlkZSBhIG5vdGljZWFibGUgc3BlZWR1cFxuICAgICAgICAgKi9cbiAgICAgICAgcHJldl9kYXRhX3VzZSA9IChwcmV2Tm9pc2UgIT0gbnVsbCAmJiAoY29kSW5mby5nbG9iYWxfZ2FpbiA9PSBwcmV2Tm9pc2UuZ2xvYmFsX2dhaW4pKTtcblxuICAgICAgICBpZiAoY29kSW5mby5ibG9ja190eXBlID09IEVuY29kZXIuU0hPUlRfVFlQRSlcbiAgICAgICAgICAgIHNmYm1heCA9IDM4O1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBzZmJtYXggPSAyMTtcblxuICAgICAgICBmb3IgKHNmYiA9IDA7IHNmYiA8PSBzZmJtYXg7IHNmYisrKSB7XG4gICAgICAgICAgICB2YXIgc3RlcCA9IC0xO1xuXG4gICAgICAgICAgICBpZiAocHJldl9kYXRhX3VzZSB8fCBjb2RJbmZvLmJsb2NrX3R5cGUgPT0gRW5jb2Rlci5OT1JNX1RZUEUpIHtcbiAgICAgICAgICAgICAgICBzdGVwID0gY29kSW5mby5nbG9iYWxfZ2FpblxuICAgICAgICAgICAgICAgICAgICAtICgoY29kSW5mby5zY2FsZWZhY1tzZmJdICsgKGNvZEluZm8ucHJlZmxhZyAhPSAwID8gcXVwdnQucHJldGFiW3NmYl1cbiAgICAgICAgICAgICAgICAgICAgICAgIDogMCkpIDw8IChjb2RJbmZvLnNjYWxlZmFjX3NjYWxlICsgMSkpXG4gICAgICAgICAgICAgICAgICAgIC0gY29kSW5mby5zdWJibG9ja19nYWluW2NvZEluZm8ud2luZG93W3NmYl1dICogODtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzc2VydChjb2RJbmZvLndpZHRoW3NmYl0gPj0gMCk7XG4gICAgICAgICAgICBpZiAocHJldl9kYXRhX3VzZSAmJiAocHJldk5vaXNlLnN0ZXBbc2ZiXSA9PSBzdGVwKSkge1xuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICogZG8gbm90IHJlY29tcHV0ZSB0aGlzIHBhcnQsIGJ1dCBjb21wdXRlIGFjY3VtdWxhdGVkIGxpbmVzXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgaWYgKGFjY3VtdWxhdGUgIT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBxdWFudGl6ZV9saW5lc194cnBvdyhhY2N1bXVsYXRlLCBpc3RlcCwgYWNjX3hwLCBhY2NfeHBQb3MsXG4gICAgICAgICAgICAgICAgICAgICAgICBhY2NfaURhdGEsIGFjY19pRGF0YVBvcyk7XG4gICAgICAgICAgICAgICAgICAgIGFjY3VtdWxhdGUgPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoYWNjdW11bGF0ZTAxICE9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgcXVhbnRpemVfbGluZXNfeHJwb3dfMDEoYWNjdW11bGF0ZTAxLCBpc3RlcCwgYWNjX3hwLFxuICAgICAgICAgICAgICAgICAgICAgICAgYWNjX3hwUG9zLCBhY2NfaURhdGEsIGFjY19pRGF0YVBvcyk7XG4gICAgICAgICAgICAgICAgICAgIGFjY3VtdWxhdGUwMSA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHsgLyogc2hvdWxkIGNvbXB1dGUgdGhpcyBwYXJ0ICovXG4gICAgICAgICAgICAgICAgdmFyIGwgPSBjb2RJbmZvLndpZHRoW3NmYl07XG5cbiAgICAgICAgICAgICAgICBpZiAoKGogKyBjb2RJbmZvLndpZHRoW3NmYl0pID4gY29kSW5mby5tYXhfbm9uemVyb19jb2VmZikge1xuICAgICAgICAgICAgICAgICAgICAvKiBkbyBub3QgY29tcHV0ZSB1cHBlciB6ZXJvIHBhcnQgKi9cbiAgICAgICAgICAgICAgICAgICAgdmFyIHVzZWZ1bGxzaXplO1xuICAgICAgICAgICAgICAgICAgICB1c2VmdWxsc2l6ZSA9IGNvZEluZm8ubWF4X25vbnplcm9fY29lZmYgLSBqICsgMTtcbiAgICAgICAgICAgICAgICAgICAgQXJyYXlzLmZpbGwocGksIGNvZEluZm8ubWF4X25vbnplcm9fY29lZmYsIDU3NiwgMCk7XG4gICAgICAgICAgICAgICAgICAgIGwgPSB1c2VmdWxsc2l6ZTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobCA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGwgPSAwO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLyogbm8gbmVlZCB0byBjb21wdXRlIGhpZ2hlciBzZmIgdmFsdWVzICovXG4gICAgICAgICAgICAgICAgICAgIHNmYiA9IHNmYm1heCArIDE7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLyogYWNjdW11bGF0ZSBsaW5lcyB0byBxdWFudGl6ZSAqL1xuICAgICAgICAgICAgICAgIGlmICgwID09IGFjY3VtdWxhdGUgJiYgMCA9PSBhY2N1bXVsYXRlMDEpIHtcbiAgICAgICAgICAgICAgICAgICAgYWNjX2lEYXRhID0gaURhdGE7XG4gICAgICAgICAgICAgICAgICAgIGFjY19pRGF0YVBvcyA9IGlEYXRhUG9zO1xuICAgICAgICAgICAgICAgICAgICBhY2NfeHAgPSB4cDtcbiAgICAgICAgICAgICAgICAgICAgYWNjX3hwUG9zID0geHBQb3M7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChwcmV2Tm9pc2UgIT0gbnVsbCAmJiBwcmV2Tm9pc2Uuc2ZiX2NvdW50MSA+IDBcbiAgICAgICAgICAgICAgICAgICAgJiYgc2ZiID49IHByZXZOb2lzZS5zZmJfY291bnQxXG4gICAgICAgICAgICAgICAgICAgICYmIHByZXZOb2lzZS5zdGVwW3NmYl0gPiAwXG4gICAgICAgICAgICAgICAgICAgICYmIHN0ZXAgPj0gcHJldk5vaXNlLnN0ZXBbc2ZiXSkge1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChhY2N1bXVsYXRlICE9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHF1YW50aXplX2xpbmVzX3hycG93KGFjY3VtdWxhdGUsIGlzdGVwLCBhY2NfeHAsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYWNjX3hwUG9zLCBhY2NfaURhdGEsIGFjY19pRGF0YVBvcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY2N1bXVsYXRlID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjY19pRGF0YSA9IGlEYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWNjX2lEYXRhUG9zID0gaURhdGFQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY2NfeHAgPSB4cDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjY194cFBvcyA9IHhwUG9zO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGFjY3VtdWxhdGUwMSArPSBsO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChhY2N1bXVsYXRlMDEgIT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcXVhbnRpemVfbGluZXNfeHJwb3dfMDEoYWNjdW11bGF0ZTAxLCBpc3RlcCwgYWNjX3hwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjY194cFBvcywgYWNjX2lEYXRhLCBhY2NfaURhdGFQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWNjdW11bGF0ZTAxID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjY19pRGF0YSA9IGlEYXRhO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWNjX2lEYXRhUG9zID0gaURhdGFQb3M7XG4gICAgICAgICAgICAgICAgICAgICAgICBhY2NfeHAgPSB4cDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFjY194cFBvcyA9IHhwUG9zO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGFjY3VtdWxhdGUgKz0gbDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobCA8PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICAgICAqIHJoOiAyMDA0MDIxNSBtYXkgaGFwcGVuIGR1ZSB0byBcInByZXZfZGF0YV91c2VcIlxuICAgICAgICAgICAgICAgICAgICAgKiBvcHRpbWl6YXRpb25cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIGlmIChhY2N1bXVsYXRlMDEgIT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgcXVhbnRpemVfbGluZXNfeHJwb3dfMDEoYWNjdW11bGF0ZTAxLCBpc3RlcCwgYWNjX3hwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjY194cFBvcywgYWNjX2lEYXRhLCBhY2NfaURhdGFQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWNjdW11bGF0ZTAxID0gMDtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoYWNjdW11bGF0ZSAhPSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBxdWFudGl6ZV9saW5lc194cnBvdyhhY2N1bXVsYXRlLCBpc3RlcCwgYWNjX3hwLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFjY194cFBvcywgYWNjX2lEYXRhLCBhY2NfaURhdGFQb3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgYWNjdW11bGF0ZSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgLyogZW5kcyBmb3ItbG9vcCAqL1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChzZmIgPD0gc2ZibWF4KSB7XG4gICAgICAgICAgICAgICAgaURhdGFQb3MgKz0gY29kSW5mby53aWR0aFtzZmJdO1xuICAgICAgICAgICAgICAgIHhwUG9zICs9IGNvZEluZm8ud2lkdGhbc2ZiXTtcbiAgICAgICAgICAgICAgICBqICs9IGNvZEluZm8ud2lkdGhbc2ZiXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAoYWNjdW11bGF0ZSAhPSAwKSB7IC8qIGxhc3QgZGF0YSBwYXJ0ICovXG4gICAgICAgICAgICBxdWFudGl6ZV9saW5lc194cnBvdyhhY2N1bXVsYXRlLCBpc3RlcCwgYWNjX3hwLCBhY2NfeHBQb3MsXG4gICAgICAgICAgICAgICAgYWNjX2lEYXRhLCBhY2NfaURhdGFQb3MpO1xuICAgICAgICAgICAgYWNjdW11bGF0ZSA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGFjY3VtdWxhdGUwMSAhPSAwKSB7IC8qIGxhc3QgZGF0YSBwYXJ0ICovXG4gICAgICAgICAgICBxdWFudGl6ZV9saW5lc194cnBvd18wMShhY2N1bXVsYXRlMDEsIGlzdGVwLCBhY2NfeHAsIGFjY194cFBvcyxcbiAgICAgICAgICAgICAgICBhY2NfaURhdGEsIGFjY19pRGF0YVBvcyk7XG4gICAgICAgICAgICBhY2N1bXVsYXRlMDEgPSAwO1xuICAgICAgICB9XG5cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBpeF9tYXhcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpeF9tYXgoaXgsIGl4UG9zLCBlbmRQb3MpIHtcbiAgICAgICAgdmFyIG1heDEgPSAwLCBtYXgyID0gMDtcblxuICAgICAgICBkbyB7XG4gICAgICAgICAgICB2YXIgeDEgPSBpeFtpeFBvcysrXTtcbiAgICAgICAgICAgIHZhciB4MiA9IGl4W2l4UG9zKytdO1xuICAgICAgICAgICAgaWYgKG1heDEgPCB4MSlcbiAgICAgICAgICAgICAgICBtYXgxID0geDE7XG5cbiAgICAgICAgICAgIGlmIChtYXgyIDwgeDIpXG4gICAgICAgICAgICAgICAgbWF4MiA9IHgyO1xuICAgICAgICB9IHdoaWxlIChpeFBvcyA8IGVuZFBvcyk7XG4gICAgICAgIGlmIChtYXgxIDwgbWF4MilcbiAgICAgICAgICAgIG1heDEgPSBtYXgyO1xuICAgICAgICByZXR1cm4gbWF4MTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb3VudF9iaXRfRVNDKGl4LCBpeFBvcywgZW5kLCB0MSwgdDIsIHMpIHtcbiAgICAgICAgLyogRVNDLXRhYmxlIGlzIHVzZWQgKi9cbiAgICAgICAgdmFyIGxpbmJpdHMgPSBUYWJsZXMuaHRbdDFdLnhsZW4gKiA2NTUzNiArIFRhYmxlcy5odFt0Ml0ueGxlbjtcbiAgICAgICAgdmFyIHN1bSA9IDAsIHN1bTI7XG5cbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgdmFyIHggPSBpeFtpeFBvcysrXTtcbiAgICAgICAgICAgIHZhciB5ID0gaXhbaXhQb3MrK107XG5cbiAgICAgICAgICAgIGlmICh4ICE9IDApIHtcbiAgICAgICAgICAgICAgICBpZiAoeCA+IDE0KSB7XG4gICAgICAgICAgICAgICAgICAgIHggPSAxNTtcbiAgICAgICAgICAgICAgICAgICAgc3VtICs9IGxpbmJpdHM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHggKj0gMTY7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh5ICE9IDApIHtcbiAgICAgICAgICAgICAgICBpZiAoeSA+IDE0KSB7XG4gICAgICAgICAgICAgICAgICAgIHkgPSAxNTtcbiAgICAgICAgICAgICAgICAgICAgc3VtICs9IGxpbmJpdHM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIHggKz0geTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgc3VtICs9IFRhYmxlcy5sYXJnZXRibFt4XTtcbiAgICAgICAgfSB3aGlsZSAoaXhQb3MgPCBlbmQpO1xuXG4gICAgICAgIHN1bTIgPSBzdW0gJiAweGZmZmY7XG4gICAgICAgIHN1bSA+Pj0gMTY7XG5cbiAgICAgICAgaWYgKHN1bSA+IHN1bTIpIHtcbiAgICAgICAgICAgIHN1bSA9IHN1bTI7XG4gICAgICAgICAgICB0MSA9IHQyO1xuICAgICAgICB9XG5cbiAgICAgICAgcy5iaXRzICs9IHN1bTtcbiAgICAgICAgcmV0dXJuIHQxO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvdW50X2JpdF9ub0VTQyhpeCwgaXhQb3MsIGVuZCwgcykge1xuICAgICAgICAvKiBObyBFU0Mtd29yZHMgKi9cbiAgICAgICAgdmFyIHN1bTEgPSAwO1xuICAgICAgICB2YXIgaGxlbjEgPSBUYWJsZXMuaHRbMV0uaGxlbjtcblxuICAgICAgICBkbyB7XG4gICAgICAgICAgICB2YXIgeCA9IGl4W2l4UG9zICsgMF0gKiAyICsgaXhbaXhQb3MgKyAxXTtcbiAgICAgICAgICAgIGl4UG9zICs9IDI7XG4gICAgICAgICAgICBzdW0xICs9IGhsZW4xW3hdO1xuICAgICAgICB9IHdoaWxlIChpeFBvcyA8IGVuZCk7XG5cbiAgICAgICAgcy5iaXRzICs9IHN1bTE7XG4gICAgICAgIHJldHVybiAxO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvdW50X2JpdF9ub0VTQ19mcm9tMihpeCwgaXhQb3MsIGVuZCwgdDEsIHMpIHtcbiAgICAgICAgLyogTm8gRVNDLXdvcmRzICovXG4gICAgICAgIHZhciBzdW0gPSAwLCBzdW0yO1xuICAgICAgICB2YXIgeGxlbiA9IFRhYmxlcy5odFt0MV0ueGxlbjtcbiAgICAgICAgdmFyIGhsZW47XG4gICAgICAgIGlmICh0MSA9PSAyKVxuICAgICAgICAgICAgaGxlbiA9IFRhYmxlcy50YWJsZTIzO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBobGVuID0gVGFibGVzLnRhYmxlNTY7XG5cbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgdmFyIHggPSBpeFtpeFBvcyArIDBdICogeGxlbiArIGl4W2l4UG9zICsgMV07XG4gICAgICAgICAgICBpeFBvcyArPSAyO1xuICAgICAgICAgICAgc3VtICs9IGhsZW5beF07XG4gICAgICAgIH0gd2hpbGUgKGl4UG9zIDwgZW5kKTtcblxuICAgICAgICBzdW0yID0gc3VtICYgMHhmZmZmO1xuICAgICAgICBzdW0gPj49IDE2O1xuXG4gICAgICAgIGlmIChzdW0gPiBzdW0yKSB7XG4gICAgICAgICAgICBzdW0gPSBzdW0yO1xuICAgICAgICAgICAgdDErKztcbiAgICAgICAgfVxuXG4gICAgICAgIHMuYml0cyArPSBzdW07XG4gICAgICAgIHJldHVybiB0MTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjb3VudF9iaXRfbm9FU0NfZnJvbTMoaXgsIGl4UG9zLCBlbmQsIHQxLCBzKSB7XG4gICAgICAgIC8qIE5vIEVTQy13b3JkcyAqL1xuICAgICAgICB2YXIgc3VtMSA9IDA7XG4gICAgICAgIHZhciBzdW0yID0gMDtcbiAgICAgICAgdmFyIHN1bTMgPSAwO1xuICAgICAgICB2YXIgeGxlbiA9IFRhYmxlcy5odFt0MV0ueGxlbjtcbiAgICAgICAgdmFyIGhsZW4xID0gVGFibGVzLmh0W3QxXS5obGVuO1xuICAgICAgICB2YXIgaGxlbjIgPSBUYWJsZXMuaHRbdDEgKyAxXS5obGVuO1xuICAgICAgICB2YXIgaGxlbjMgPSBUYWJsZXMuaHRbdDEgKyAyXS5obGVuO1xuXG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIHZhciB4ID0gaXhbaXhQb3MgKyAwXSAqIHhsZW4gKyBpeFtpeFBvcyArIDFdO1xuICAgICAgICAgICAgaXhQb3MgKz0gMjtcbiAgICAgICAgICAgIHN1bTEgKz0gaGxlbjFbeF07XG4gICAgICAgICAgICBzdW0yICs9IGhsZW4yW3hdO1xuICAgICAgICAgICAgc3VtMyArPSBobGVuM1t4XTtcbiAgICAgICAgfSB3aGlsZSAoaXhQb3MgPCBlbmQpO1xuICAgICAgICB2YXIgdCA9IHQxO1xuICAgICAgICBpZiAoc3VtMSA+IHN1bTIpIHtcbiAgICAgICAgICAgIHN1bTEgPSBzdW0yO1xuICAgICAgICAgICAgdCsrO1xuICAgICAgICB9XG4gICAgICAgIGlmIChzdW0xID4gc3VtMykge1xuICAgICAgICAgICAgc3VtMSA9IHN1bTM7XG4gICAgICAgICAgICB0ID0gdDEgKyAyO1xuICAgICAgICB9XG4gICAgICAgIHMuYml0cyArPSBzdW0xO1xuXG4gICAgICAgIHJldHVybiB0O1xuICAgIH1cblxuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuICAgIC8qIGNob29zZSB0YWJsZSAqL1xuICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuXG4gICAgdmFyIGh1Zl90Ymxfbm9FU0MgPSBbMSwgMiwgNSwgNywgNywgMTAsIDEwLCAxMywgMTMsXG4gICAgICAgIDEzLCAxMywgMTMsIDEzLCAxMywgMTNdO1xuXG4gICAgLyoqXG4gICAgICogQ2hvb3NlIHRoZSBIdWZmbWFuIHRhYmxlIHRoYXQgd2lsbCBlbmNvZGUgaXhbYmVnaW4uLmVuZF0gd2l0aCB0aGUgZmV3ZXN0XG4gICAgICogYml0cy5cbiAgICAgKlxuICAgICAqIE5vdGU6IFRoaXMgY29kZSBjb250YWlucyBrbm93bGVkZ2UgYWJvdXQgdGhlIHNpemVzIGFuZCBjaGFyYWN0ZXJpc3RpY3Mgb2ZcbiAgICAgKiB0aGUgSHVmZm1hbiB0YWJsZXMgYXMgZGVmaW5lZCBpbiB0aGUgSVMgKFRhYmxlIEIuNyksIGFuZCB3aWxsIG5vdCB3b3JrXG4gICAgICogd2l0aCBhbnkgYXJiaXRyYXJ5IHRhYmxlcy5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjaG9vc2VfdGFibGUoaXgsIGl4UG9zLCBlbmRQb3MsIHMpIHtcbiAgICAgICAgdmFyIG1heCA9IGl4X21heChpeCwgaXhQb3MsIGVuZFBvcyk7XG5cbiAgICAgICAgc3dpdGNoIChtYXgpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICByZXR1cm4gbWF4O1xuXG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvdW50X2JpdF9ub0VTQyhpeCwgaXhQb3MsIGVuZFBvcywgcyk7XG5cbiAgICAgICAgICAgIGNhc2UgMjpcbiAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICByZXR1cm4gY291bnRfYml0X25vRVNDX2Zyb20yKGl4LCBpeFBvcywgZW5kUG9zLFxuICAgICAgICAgICAgICAgICAgICBodWZfdGJsX25vRVNDW21heCAtIDFdLCBzKTtcblxuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgY2FzZSA2OlxuICAgICAgICAgICAgY2FzZSA3OlxuICAgICAgICAgICAgY2FzZSA4OlxuICAgICAgICAgICAgY2FzZSA5OlxuICAgICAgICAgICAgY2FzZSAxMDpcbiAgICAgICAgICAgIGNhc2UgMTE6XG4gICAgICAgICAgICBjYXNlIDEyOlxuICAgICAgICAgICAgY2FzZSAxMzpcbiAgICAgICAgICAgIGNhc2UgMTQ6XG4gICAgICAgICAgICBjYXNlIDE1OlxuICAgICAgICAgICAgICAgIHJldHVybiBjb3VudF9iaXRfbm9FU0NfZnJvbTMoaXgsIGl4UG9zLCBlbmRQb3MsXG4gICAgICAgICAgICAgICAgICAgIGh1Zl90Ymxfbm9FU0NbbWF4IC0gMV0sIHMpO1xuXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIC8qIHRyeSB0YWJsZXMgd2l0aCBsaW5iaXRzICovXG4gICAgICAgICAgICAgICAgaWYgKG1heCA+IFF1YW50aXplUFZULklYTUFYX1ZBTCkge1xuICAgICAgICAgICAgICAgICAgICBzLmJpdHMgPSBRdWFudGl6ZVBWVC5MQVJHRV9CSVRTO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gLTE7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIG1heCAtPSAxNTtcbiAgICAgICAgICAgICAgICB2YXIgY2hvaWNlMjtcbiAgICAgICAgICAgICAgICBmb3IgKGNob2ljZTIgPSAyNDsgY2hvaWNlMiA8IDMyOyBjaG9pY2UyKyspIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKFRhYmxlcy5odFtjaG9pY2UyXS5saW5tYXggPj0gbWF4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB2YXIgY2hvaWNlO1xuICAgICAgICAgICAgICAgIGZvciAoY2hvaWNlID0gY2hvaWNlMiAtIDg7IGNob2ljZSA8IDI0OyBjaG9pY2UrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoVGFibGVzLmh0W2Nob2ljZV0ubGlubWF4ID49IG1heCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvdW50X2JpdF9FU0MoaXgsIGl4UG9zLCBlbmRQb3MsIGNob2ljZSwgY2hvaWNlMiwgcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBjb3VudF9iaXRcbiAgICAgKi9cbiAgICB0aGlzLm5vcXVhbnRfY291bnRfYml0cyA9IGZ1bmN0aW9uIChnZmMsIGdpLCBwcmV2X25vaXNlKSB7XG4gICAgICAgIHZhciBpeCA9IGdpLmwzX2VuYztcbiAgICAgICAgdmFyIGkgPSBNYXRoLm1pbig1NzYsICgoZ2kubWF4X25vbnplcm9fY29lZmYgKyAyKSA+PiAxKSA8PCAxKTtcblxuICAgICAgICBpZiAocHJldl9ub2lzZSAhPSBudWxsKVxuICAgICAgICAgICAgcHJldl9ub2lzZS5zZmJfY291bnQxID0gMDtcblxuICAgICAgICAvKiBEZXRlcm1pbmUgY291bnQxIHJlZ2lvbiAqL1xuICAgICAgICBmb3IgKDsgaSA+IDE7IGkgLT0gMilcbiAgICAgICAgICAgIGlmICgoaXhbaSAtIDFdIHwgaXhbaSAtIDJdKSAhPSAwKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBnaS5jb3VudDEgPSBpO1xuXG4gICAgICAgIC8qIERldGVybWluZXMgdGhlIG51bWJlciBvZiBiaXRzIHRvIGVuY29kZSB0aGUgcXVhZHJ1cGxlcy4gKi9cbiAgICAgICAgdmFyIGExID0gMDtcbiAgICAgICAgdmFyIGEyID0gMDtcbiAgICAgICAgZm9yICg7IGkgPiAzOyBpIC09IDQpIHtcbiAgICAgICAgICAgIHZhciBwO1xuICAgICAgICAgICAgLyogaGFjayB0byBjaGVjayBpZiBhbGwgdmFsdWVzIDw9IDEgKi9cbiAgICAgICAgICAgIC8vdGhyb3cgXCJUT0RPOiBIQUNLICAgICAgICAgaWYgKCgoKGxvbmcpIGl4W2kgLSAxXSB8IChsb25nKSBpeFtpIC0gMl0gfCAobG9uZykgaXhbaSAtIDNdIHwgKGxvbmcpIGl4W2kgLSA0XSkgJiAweGZmZmZmZmZmTCkgPiAxTCAgICAgICAgXCJcbiAgICAgICAgICAgIC8vaWYgKHRydWUpIHtcbiAgICAgICAgICAgIGlmICgoKGl4W2kgLSAxXSB8IGl4W2kgLSAyXSB8IGl4W2kgLSAzXSB8IGl4W2kgLSA0XSkgJiAweDdmZmZmZmZmKSA+IDEpIHtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHAgPSAoKGl4W2kgLSA0XSAqIDIgKyBpeFtpIC0gM10pICogMiArIGl4W2kgLSAyXSkgKiAyICsgaXhbaSAtIDFdO1xuICAgICAgICAgICAgYTEgKz0gVGFibGVzLnQzMmxbcF07XG4gICAgICAgICAgICBhMiArPSBUYWJsZXMudDMzbFtwXTtcbiAgICAgICAgfVxuICAgICAgICB2YXIgYml0cyA9IGExO1xuICAgICAgICBnaS5jb3VudDF0YWJsZV9zZWxlY3QgPSAwO1xuICAgICAgICBpZiAoYTEgPiBhMikge1xuICAgICAgICAgICAgYml0cyA9IGEyO1xuICAgICAgICAgICAgZ2kuY291bnQxdGFibGVfc2VsZWN0ID0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdpLmNvdW50MWJpdHMgPSBiaXRzO1xuICAgICAgICBnaS5iaWdfdmFsdWVzID0gaTtcbiAgICAgICAgaWYgKGkgPT0gMClcbiAgICAgICAgICAgIHJldHVybiBiaXRzO1xuXG4gICAgICAgIGlmIChnaS5ibG9ja190eXBlID09IEVuY29kZXIuU0hPUlRfVFlQRSkge1xuICAgICAgICAgICAgYTEgPSAzICogZ2ZjLnNjYWxlZmFjX2JhbmQuc1szXTtcbiAgICAgICAgICAgIGlmIChhMSA+IGdpLmJpZ192YWx1ZXMpXG4gICAgICAgICAgICAgICAgYTEgPSBnaS5iaWdfdmFsdWVzO1xuICAgICAgICAgICAgYTIgPSBnaS5iaWdfdmFsdWVzO1xuXG4gICAgICAgIH0gZWxzZSBpZiAoZ2kuYmxvY2tfdHlwZSA9PSBFbmNvZGVyLk5PUk1fVFlQRSkge1xuICAgICAgICAgICAgYXNzZXJ0KGkgPD0gNTc2KTtcbiAgICAgICAgICAgIC8qIGJ2X3NjZiBoYXMgNTc2IGVudHJpZXMgKDAuLjU3NSkgKi9cbiAgICAgICAgICAgIGExID0gZ2kucmVnaW9uMF9jb3VudCA9IGdmYy5idl9zY2ZbaSAtIDJdO1xuICAgICAgICAgICAgYTIgPSBnaS5yZWdpb24xX2NvdW50ID0gZ2ZjLmJ2X3NjZltpIC0gMV07XG5cbiAgICAgICAgICAgIGFzc2VydChhMSArIGEyICsgMiA8IEVuY29kZXIuU0JQU1lfbCk7XG4gICAgICAgICAgICBhMiA9IGdmYy5zY2FsZWZhY19iYW5kLmxbYTEgKyBhMiArIDJdO1xuICAgICAgICAgICAgYTEgPSBnZmMuc2NhbGVmYWNfYmFuZC5sW2ExICsgMV07XG4gICAgICAgICAgICBpZiAoYTIgPCBpKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJpID0gbmV3IEJpdHMoYml0cyk7XG4gICAgICAgICAgICAgICAgZ2kudGFibGVfc2VsZWN0WzJdID0gY2hvb3NlX3RhYmxlKGl4LCBhMiwgaSwgYmkpO1xuICAgICAgICAgICAgICAgIGJpdHMgPSBiaS5iaXRzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZ2kucmVnaW9uMF9jb3VudCA9IDc7XG4gICAgICAgICAgICAvKiBnaS5yZWdpb24xX2NvdW50ID0gU0JQU1lfbCAtIDcgLSAxOyAqL1xuICAgICAgICAgICAgZ2kucmVnaW9uMV9jb3VudCA9IEVuY29kZXIuU0JNQVhfbCAtIDEgLSA3IC0gMTtcbiAgICAgICAgICAgIGExID0gZ2ZjLnNjYWxlZmFjX2JhbmQubFs3ICsgMV07XG4gICAgICAgICAgICBhMiA9IGk7XG4gICAgICAgICAgICBpZiAoYTEgPiBhMikge1xuICAgICAgICAgICAgICAgIGExID0gYTI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKiBoYXZlIHRvIGFsbG93IGZvciB0aGUgY2FzZSB3aGVuIGJpZ3ZhbHVlcyA8IHJlZ2lvbjAgPCByZWdpb24xICovXG4gICAgICAgIC8qIChhbmQgcmVnaW9uMCwgcmVnaW9uMSBhcmUgaWdub3JlZCkgKi9cbiAgICAgICAgYTEgPSBNYXRoLm1pbihhMSwgaSk7XG4gICAgICAgIGEyID0gTWF0aC5taW4oYTIsIGkpO1xuXG4gICAgICAgIGFzc2VydChhMSA+PSAwKTtcbiAgICAgICAgYXNzZXJ0KGEyID49IDApO1xuXG4gICAgICAgIC8qIENvdW50IHRoZSBudW1iZXIgb2YgYml0cyBuZWNlc3NhcnkgdG8gY29kZSB0aGUgYmlndmFsdWVzIHJlZ2lvbi4gKi9cbiAgICAgICAgaWYgKDAgPCBhMSkge1xuICAgICAgICAgICAgdmFyIGJpID0gbmV3IEJpdHMoYml0cyk7XG4gICAgICAgICAgICBnaS50YWJsZV9zZWxlY3RbMF0gPSBjaG9vc2VfdGFibGUoaXgsIDAsIGExLCBiaSk7XG4gICAgICAgICAgICBiaXRzID0gYmkuYml0cztcbiAgICAgICAgfVxuICAgICAgICBpZiAoYTEgPCBhMikge1xuICAgICAgICAgICAgdmFyIGJpID0gbmV3IEJpdHMoYml0cyk7XG4gICAgICAgICAgICBnaS50YWJsZV9zZWxlY3RbMV0gPSBjaG9vc2VfdGFibGUoaXgsIGExLCBhMiwgYmkpO1xuICAgICAgICAgICAgYml0cyA9IGJpLmJpdHM7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGdmYy51c2VfYmVzdF9odWZmbWFuID09IDIpIHtcbiAgICAgICAgICAgIGdpLnBhcnQyXzNfbGVuZ3RoID0gYml0cztcbiAgICAgICAgICAgIGJlc3RfaHVmZm1hbl9kaXZpZGUoZ2ZjLCBnaSk7XG4gICAgICAgICAgICBiaXRzID0gZ2kucGFydDJfM19sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocHJldl9ub2lzZSAhPSBudWxsKSB7XG4gICAgICAgICAgICBpZiAoZ2kuYmxvY2tfdHlwZSA9PSBFbmNvZGVyLk5PUk1fVFlQRSkge1xuICAgICAgICAgICAgICAgIHZhciBzZmIgPSAwO1xuICAgICAgICAgICAgICAgIHdoaWxlIChnZmMuc2NhbGVmYWNfYmFuZC5sW3NmYl0gPCBnaS5iaWdfdmFsdWVzKSB7XG4gICAgICAgICAgICAgICAgICAgIHNmYisrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBwcmV2X25vaXNlLnNmYl9jb3VudDEgPSBzZmI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYml0cztcbiAgICB9XG5cbiAgICB0aGlzLmNvdW50X2JpdHMgPSBmdW5jdGlvbiAoZ2ZjLCB4ciwgZ2ksIHByZXZfbm9pc2UpIHtcbiAgICAgICAgdmFyIGl4ID0gZ2kubDNfZW5jO1xuXG4gICAgICAgIC8qIHNpbmNlIHF1YW50aXplX3hycG93IHVzZXMgdGFibGUgbG9va3VwLCB3ZSBuZWVkIHRvIGNoZWNrIHRoaXMgZmlyc3Q6ICovXG4gICAgICAgIHZhciB3ID0gKFF1YW50aXplUFZULklYTUFYX1ZBTCkgLyBxdXB2dC5JUE9XMjAoZ2kuZ2xvYmFsX2dhaW4pO1xuXG4gICAgICAgIGlmIChnaS54cnBvd19tYXggPiB3KVxuICAgICAgICAgICAgcmV0dXJuIFF1YW50aXplUFZULkxBUkdFX0JJVFM7XG5cbiAgICAgICAgcXVhbnRpemVfeHJwb3coeHIsIGl4LCBxdXB2dC5JUE9XMjAoZ2kuZ2xvYmFsX2dhaW4pLCBnaSwgcHJldl9ub2lzZSk7XG5cbiAgICAgICAgaWYgKChnZmMuc3Vic3RlcF9zaGFwaW5nICYgMikgIT0gMCkge1xuICAgICAgICAgICAgdmFyIGogPSAwO1xuICAgICAgICAgICAgLyogMC42MzQ1MjE2ODIyNDI0MzkgPSAwLjU5NDYqMioqKC41KjAuMTg3NSkgKi9cbiAgICAgICAgICAgIHZhciBnYWluID0gZ2kuZ2xvYmFsX2dhaW4gKyBnaS5zY2FsZWZhY19zY2FsZTtcbiAgICAgICAgICAgIHZhciByb3VuZGZhYyA9IDAuNjM0NTIxNjgyMjQyNDM5IC8gcXVwdnQuSVBPVzIwKGdhaW4pO1xuICAgICAgICAgICAgZm9yICh2YXIgc2ZiID0gMDsgc2ZiIDwgZ2kuc2ZibWF4OyBzZmIrKykge1xuICAgICAgICAgICAgICAgIHZhciB3aWR0aCA9IGdpLndpZHRoW3NmYl07XG4gICAgICAgICAgICAgICAgYXNzZXJ0KHdpZHRoID49IDApO1xuICAgICAgICAgICAgICAgIGlmICgwID09IGdmYy5wc2V1ZG9oYWxmW3NmYl0pIHtcbiAgICAgICAgICAgICAgICAgICAgaiArPSB3aWR0aDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgaztcbiAgICAgICAgICAgICAgICAgICAgZm9yIChrID0gaiwgaiArPSB3aWR0aDsgayA8IGo7ICsraykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXhba10gPSAoeHJba10gPj0gcm91bmRmYWMpID8gaXhba10gOiAwO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0aGlzLm5vcXVhbnRfY291bnRfYml0cyhnZmMsIGdpLCBwcmV2X25vaXNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiByZS1jYWxjdWxhdGUgdGhlIGJlc3Qgc2NhbGVmYWNfY29tcHJlc3MgdXNpbmcgc2Nmc2kgdGhlIHNhdmVkIGJpdHMgYXJlXG4gICAgICoga2VwdCBpbiB0aGUgYml0IHJlc2Vydm9pci5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiByZWNhbGNfZGl2aWRlX2luaXQoZ2ZjLCBjb2RfaW5mbywgaXgsIHIwMV9iaXRzLCByMDFfZGl2LCByMF90YmwsIHIxX3RibCkge1xuICAgICAgICB2YXIgYmlndiA9IGNvZF9pbmZvLmJpZ192YWx1ZXM7XG5cbiAgICAgICAgZm9yICh2YXIgcjAgPSAwOyByMCA8PSA3ICsgMTU7IHIwKyspIHtcbiAgICAgICAgICAgIHIwMV9iaXRzW3IwXSA9IFF1YW50aXplUFZULkxBUkdFX0JJVFM7XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKHZhciByMCA9IDA7IHIwIDwgMTY7IHIwKyspIHtcbiAgICAgICAgICAgIHZhciBhMSA9IGdmYy5zY2FsZWZhY19iYW5kLmxbcjAgKyAxXTtcbiAgICAgICAgICAgIGlmIChhMSA+PSBiaWd2KVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgdmFyIHIwYml0cyA9IDA7XG4gICAgICAgICAgICB2YXIgYmkgPSBuZXcgQml0cyhyMGJpdHMpO1xuICAgICAgICAgICAgdmFyIHIwdCA9IGNob29zZV90YWJsZShpeCwgMCwgYTEsIGJpKTtcbiAgICAgICAgICAgIHIwYml0cyA9IGJpLmJpdHM7XG5cbiAgICAgICAgICAgIGZvciAodmFyIHIxID0gMDsgcjEgPCA4OyByMSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGEyID0gZ2ZjLnNjYWxlZmFjX2JhbmQubFtyMCArIHIxICsgMl07XG4gICAgICAgICAgICAgICAgaWYgKGEyID49IGJpZ3YpXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIHZhciBiaXRzID0gcjBiaXRzO1xuICAgICAgICAgICAgICAgIGJpID0gbmV3IEJpdHMoYml0cyk7XG4gICAgICAgICAgICAgICAgdmFyIHIxdCA9IGNob29zZV90YWJsZShpeCwgYTEsIGEyLCBiaSk7XG4gICAgICAgICAgICAgICAgYml0cyA9IGJpLmJpdHM7XG4gICAgICAgICAgICAgICAgaWYgKHIwMV9iaXRzW3IwICsgcjFdID4gYml0cykge1xuICAgICAgICAgICAgICAgICAgICByMDFfYml0c1tyMCArIHIxXSA9IGJpdHM7XG4gICAgICAgICAgICAgICAgICAgIHIwMV9kaXZbcjAgKyByMV0gPSByMDtcbiAgICAgICAgICAgICAgICAgICAgcjBfdGJsW3IwICsgcjFdID0gcjB0O1xuICAgICAgICAgICAgICAgICAgICByMV90YmxbcjAgKyByMV0gPSByMXQ7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVjYWxjX2RpdmlkZV9zdWIoZ2ZjLCBjb2RfaW5mbzIsIGdpLCBpeCwgcjAxX2JpdHMsIHIwMV9kaXYsIHIwX3RibCwgcjFfdGJsKSB7XG4gICAgICAgIHZhciBiaWd2ID0gY29kX2luZm8yLmJpZ192YWx1ZXM7XG5cbiAgICAgICAgZm9yICh2YXIgcjIgPSAyOyByMiA8IEVuY29kZXIuU0JNQVhfbCArIDE7IHIyKyspIHtcbiAgICAgICAgICAgIHZhciBhMiA9IGdmYy5zY2FsZWZhY19iYW5kLmxbcjJdO1xuICAgICAgICAgICAgaWYgKGEyID49IGJpZ3YpXG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB2YXIgYml0cyA9IHIwMV9iaXRzW3IyIC0gMl0gKyBjb2RfaW5mbzIuY291bnQxYml0cztcbiAgICAgICAgICAgIGlmIChnaS5wYXJ0Ml8zX2xlbmd0aCA8PSBiaXRzKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICB2YXIgYmkgPSBuZXcgQml0cyhiaXRzKTtcbiAgICAgICAgICAgIHZhciByMnQgPSBjaG9vc2VfdGFibGUoaXgsIGEyLCBiaWd2LCBiaSk7XG4gICAgICAgICAgICBiaXRzID0gYmkuYml0cztcbiAgICAgICAgICAgIGlmIChnaS5wYXJ0Ml8zX2xlbmd0aCA8PSBiaXRzKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuXG4gICAgICAgICAgICBnaS5hc3NpZ24oY29kX2luZm8yKTtcbiAgICAgICAgICAgIGdpLnBhcnQyXzNfbGVuZ3RoID0gYml0cztcbiAgICAgICAgICAgIGdpLnJlZ2lvbjBfY291bnQgPSByMDFfZGl2W3IyIC0gMl07XG4gICAgICAgICAgICBnaS5yZWdpb24xX2NvdW50ID0gcjIgLSAyIC0gcjAxX2RpdltyMiAtIDJdO1xuICAgICAgICAgICAgZ2kudGFibGVfc2VsZWN0WzBdID0gcjBfdGJsW3IyIC0gMl07XG4gICAgICAgICAgICBnaS50YWJsZV9zZWxlY3RbMV0gPSByMV90YmxbcjIgLSAyXTtcbiAgICAgICAgICAgIGdpLnRhYmxlX3NlbGVjdFsyXSA9IHIydDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuYmVzdF9odWZmbWFuX2RpdmlkZSA9IGZ1bmN0aW9uIChnZmMsIGdpKSB7XG4gICAgICAgIHZhciBjb2RfaW5mbzIgPSBuZXcgR3JJbmZvKCk7XG4gICAgICAgIHZhciBpeCA9IGdpLmwzX2VuYztcbiAgICAgICAgdmFyIHIwMV9iaXRzID0gbmV3X2ludCg3ICsgMTUgKyAxKTtcbiAgICAgICAgdmFyIHIwMV9kaXYgPSBuZXdfaW50KDcgKyAxNSArIDEpO1xuICAgICAgICB2YXIgcjBfdGJsID0gbmV3X2ludCg3ICsgMTUgKyAxKTtcbiAgICAgICAgdmFyIHIxX3RibCA9IG5ld19pbnQoNyArIDE1ICsgMSk7XG5cbiAgICAgICAgLyogU0hPUlQgQkxPQ0sgc3R1ZmYgZmFpbHMgZm9yIE1QRUcyICovXG4gICAgICAgIGlmIChnaS5ibG9ja190eXBlID09IEVuY29kZXIuU0hPUlRfVFlQRSAmJiBnZmMubW9kZV9nciA9PSAxKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvZF9pbmZvMi5hc3NpZ24oZ2kpO1xuICAgICAgICBpZiAoZ2kuYmxvY2tfdHlwZSA9PSBFbmNvZGVyLk5PUk1fVFlQRSkge1xuICAgICAgICAgICAgcmVjYWxjX2RpdmlkZV9pbml0KGdmYywgZ2ksIGl4LCByMDFfYml0cywgcjAxX2RpdiwgcjBfdGJsLCByMV90YmwpO1xuICAgICAgICAgICAgcmVjYWxjX2RpdmlkZV9zdWIoZ2ZjLCBjb2RfaW5mbzIsIGdpLCBpeCwgcjAxX2JpdHMsIHIwMV9kaXYsXG4gICAgICAgICAgICAgICAgcjBfdGJsLCByMV90YmwpO1xuICAgICAgICB9XG4gICAgICAgIHZhciBpID0gY29kX2luZm8yLmJpZ192YWx1ZXM7XG4gICAgICAgIGlmIChpID09IDAgfHwgKGl4W2kgLSAyXSB8IGl4W2kgLSAxXSkgPiAxKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGkgPSBnaS5jb3VudDEgKyAyO1xuICAgICAgICBpZiAoaSA+IDU3NilcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICAvKiBEZXRlcm1pbmVzIHRoZSBudW1iZXIgb2YgYml0cyB0byBlbmNvZGUgdGhlIHF1YWRydXBsZXMuICovXG4gICAgICAgIGNvZF9pbmZvMi5hc3NpZ24oZ2kpO1xuICAgICAgICBjb2RfaW5mbzIuY291bnQxID0gaTtcbiAgICAgICAgdmFyIGExID0gMDtcbiAgICAgICAgdmFyIGEyID0gMDtcblxuICAgICAgICBhc3NlcnQoaSA8PSA1NzYpO1xuXG4gICAgICAgIGZvciAoOyBpID4gY29kX2luZm8yLmJpZ192YWx1ZXM7IGkgLT0gNCkge1xuICAgICAgICAgICAgdmFyIHAgPSAoKGl4W2kgLSA0XSAqIDIgKyBpeFtpIC0gM10pICogMiArIGl4W2kgLSAyXSkgKiAyXG4gICAgICAgICAgICAgICAgKyBpeFtpIC0gMV07XG4gICAgICAgICAgICBhMSArPSBUYWJsZXMudDMybFtwXTtcbiAgICAgICAgICAgIGEyICs9IFRhYmxlcy50MzNsW3BdO1xuICAgICAgICB9XG4gICAgICAgIGNvZF9pbmZvMi5iaWdfdmFsdWVzID0gaTtcblxuICAgICAgICBjb2RfaW5mbzIuY291bnQxdGFibGVfc2VsZWN0ID0gMDtcbiAgICAgICAgaWYgKGExID4gYTIpIHtcbiAgICAgICAgICAgIGExID0gYTI7XG4gICAgICAgICAgICBjb2RfaW5mbzIuY291bnQxdGFibGVfc2VsZWN0ID0gMTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvZF9pbmZvMi5jb3VudDFiaXRzID0gYTE7XG5cbiAgICAgICAgaWYgKGNvZF9pbmZvMi5ibG9ja190eXBlID09IEVuY29kZXIuTk9STV9UWVBFKVxuICAgICAgICAgICAgcmVjYWxjX2RpdmlkZV9zdWIoZ2ZjLCBjb2RfaW5mbzIsIGdpLCBpeCwgcjAxX2JpdHMsIHIwMV9kaXYsXG4gICAgICAgICAgICAgICAgcjBfdGJsLCByMV90YmwpO1xuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIC8qIENvdW50IHRoZSBudW1iZXIgb2YgYml0cyBuZWNlc3NhcnkgdG8gY29kZSB0aGUgYmlndmFsdWVzIHJlZ2lvbi4gKi9cbiAgICAgICAgICAgIGNvZF9pbmZvMi5wYXJ0Ml8zX2xlbmd0aCA9IGExO1xuICAgICAgICAgICAgYTEgPSBnZmMuc2NhbGVmYWNfYmFuZC5sWzcgKyAxXTtcbiAgICAgICAgICAgIGlmIChhMSA+IGkpIHtcbiAgICAgICAgICAgICAgICBhMSA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYTEgPiAwKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJpID0gbmV3IEJpdHMoY29kX2luZm8yLnBhcnQyXzNfbGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBjb2RfaW5mbzIudGFibGVfc2VsZWN0WzBdID0gY2hvb3NlX3RhYmxlKGl4LCAwLCBhMSwgYmkpO1xuICAgICAgICAgICAgICAgIGNvZF9pbmZvMi5wYXJ0Ml8zX2xlbmd0aCA9IGJpLmJpdHM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaSA+IGExKSB7XG4gICAgICAgICAgICAgICAgdmFyIGJpID0gbmV3IEJpdHMoY29kX2luZm8yLnBhcnQyXzNfbGVuZ3RoKTtcbiAgICAgICAgICAgICAgICBjb2RfaW5mbzIudGFibGVfc2VsZWN0WzFdID0gY2hvb3NlX3RhYmxlKGl4LCBhMSwgaSwgYmkpO1xuICAgICAgICAgICAgICAgIGNvZF9pbmZvMi5wYXJ0Ml8zX2xlbmd0aCA9IGJpLmJpdHM7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZ2kucGFydDJfM19sZW5ndGggPiBjb2RfaW5mbzIucGFydDJfM19sZW5ndGgpXG4gICAgICAgICAgICAgICAgZ2kuYXNzaWduKGNvZF9pbmZvMik7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICB2YXIgc2xlbjFfbiA9IFsxLCAxLCAxLCAxLCA4LCAyLCAyLCAyLCA0LCA0LCA0LCA4LCA4LCA4LCAxNiwgMTZdO1xuICAgIHZhciBzbGVuMl9uID0gWzEsIDIsIDQsIDgsIDEsIDIsIDQsIDgsIDIsIDQsIDgsIDIsIDQsIDgsIDQsIDhdO1xuICAgIHZhciBzbGVuMV90YWIgPSBbMCwgMCwgMCwgMCwgMywgMSwgMSwgMSwgMiwgMiwgMiwgMywgMywgMywgNCwgNF07XG4gICAgdmFyIHNsZW4yX3RhYiA9IFswLCAxLCAyLCAzLCAwLCAxLCAyLCAzLCAxLCAyLCAzLCAxLCAyLCAzLCAyLCAzXTtcbiAgICBUYWtlaGlyby5zbGVuMV90YWIgPSBzbGVuMV90YWI7XG4gICAgVGFrZWhpcm8uc2xlbjJfdGFiID0gc2xlbjJfdGFiO1xuXG4gICAgZnVuY3Rpb24gc2Nmc2lfY2FsYyhjaCwgbDNfc2lkZSkge1xuICAgICAgICB2YXIgc2ZiO1xuICAgICAgICB2YXIgZ2kgPSBsM19zaWRlLnR0WzFdW2NoXTtcbiAgICAgICAgdmFyIGcwID0gbDNfc2lkZS50dFswXVtjaF07XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBUYWJsZXMuc2Nmc2lfYmFuZC5sZW5ndGggLSAxOyBpKyspIHtcbiAgICAgICAgICAgIGZvciAoc2ZiID0gVGFibGVzLnNjZnNpX2JhbmRbaV07IHNmYiA8IFRhYmxlcy5zY2ZzaV9iYW5kW2kgKyAxXTsgc2ZiKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoZzAuc2NhbGVmYWNbc2ZiXSAhPSBnaS5zY2FsZWZhY1tzZmJdXG4gICAgICAgICAgICAgICAgICAgICYmIGdpLnNjYWxlZmFjW3NmYl0gPj0gMClcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2ZiID09IFRhYmxlcy5zY2ZzaV9iYW5kW2kgKyAxXSkge1xuICAgICAgICAgICAgICAgIGZvciAoc2ZiID0gVGFibGVzLnNjZnNpX2JhbmRbaV07IHNmYiA8IFRhYmxlcy5zY2ZzaV9iYW5kW2kgKyAxXTsgc2ZiKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZ2kuc2NhbGVmYWNbc2ZiXSA9IC0xO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBsM19zaWRlLnNjZnNpW2NoXVtpXSA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdmFyIHMxID0gMDtcbiAgICAgICAgdmFyIGMxID0gMDtcbiAgICAgICAgZm9yIChzZmIgPSAwOyBzZmIgPCAxMTsgc2ZiKyspIHtcbiAgICAgICAgICAgIGlmIChnaS5zY2FsZWZhY1tzZmJdID09IC0xKVxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgYzErKztcbiAgICAgICAgICAgIGlmIChzMSA8IGdpLnNjYWxlZmFjW3NmYl0pXG4gICAgICAgICAgICAgICAgczEgPSBnaS5zY2FsZWZhY1tzZmJdO1xuICAgICAgICB9XG4gICAgICAgIHZhciBzMiA9IDA7XG4gICAgICAgIHZhciBjMiA9IDA7XG4gICAgICAgIGZvciAoOyBzZmIgPCBFbmNvZGVyLlNCUFNZX2w7IHNmYisrKSB7XG4gICAgICAgICAgICBpZiAoZ2kuc2NhbGVmYWNbc2ZiXSA9PSAtMSlcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgIGMyKys7XG4gICAgICAgICAgICBpZiAoczIgPCBnaS5zY2FsZWZhY1tzZmJdKVxuICAgICAgICAgICAgICAgIHMyID0gZ2kuc2NhbGVmYWNbc2ZiXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMTY7IGkrKykge1xuICAgICAgICAgICAgaWYgKHMxIDwgc2xlbjFfbltpXSAmJiBzMiA8IHNsZW4yX25baV0pIHtcbiAgICAgICAgICAgICAgICB2YXIgYyA9IHNsZW4xX3RhYltpXSAqIGMxICsgc2xlbjJfdGFiW2ldICogYzI7XG4gICAgICAgICAgICAgICAgaWYgKGdpLnBhcnQyX2xlbmd0aCA+IGMpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2kucGFydDJfbGVuZ3RoID0gYztcbiAgICAgICAgICAgICAgICAgICAgZ2kuc2NhbGVmYWNfY29tcHJlc3MgPSBpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZpbmQgdGhlIG9wdGltYWwgd2F5IHRvIHN0b3JlIHRoZSBzY2FsZWZhY3RvcnMuIE9ubHkgY2FsbCB0aGlzIHJvdXRpbmVcbiAgICAgKiBhZnRlciBmaW5hbCBzY2FsZWZhY3RvcnMgaGF2ZSBiZWVuIGNob3NlbiBhbmQgdGhlIGNoYW5uZWwvZ3JhbnVsZSB3aWxsXG4gICAgICogbm90IGJlIHJlLWVuY29kZWQuXG4gICAgICovXG4gICAgdGhpcy5iZXN0X3NjYWxlZmFjX3N0b3JlID0gZnVuY3Rpb24gKGdmYywgZ3IsIGNoLCBsM19zaWRlKSB7XG4gICAgICAgIC8qIHVzZSBzY2FsZWZhY19zY2FsZSBpZiB3ZSBjYW4gKi9cbiAgICAgICAgdmFyIGdpID0gbDNfc2lkZS50dFtncl1bY2hdO1xuICAgICAgICB2YXIgc2ZiLCBpLCBqLCBsO1xuICAgICAgICB2YXIgcmVjYWxjID0gMDtcblxuICAgICAgICAvKlxuICAgICAgICAgKiByZW1vdmUgc2NhbGVmYWNzIGZyb20gYmFuZHMgd2l0aCBpeD0wLiBUaGlzIGlkZWEgY29tZXMgZnJvbSB0aGUgQUFDXG4gICAgICAgICAqIElTTyBkb2NzLiBhZGRlZCBtdCAzLzAwXG4gICAgICAgICAqL1xuICAgICAgICAvKiBjaGVjayBpZiBsM19lbmM9MCAqL1xuICAgICAgICBqID0gMDtcbiAgICAgICAgZm9yIChzZmIgPSAwOyBzZmIgPCBnaS5zZmJtYXg7IHNmYisrKSB7XG4gICAgICAgICAgICB2YXIgd2lkdGggPSBnaS53aWR0aFtzZmJdO1xuICAgICAgICAgICAgYXNzZXJ0KHdpZHRoID49IDApO1xuICAgICAgICAgICAgaiArPSB3aWR0aDtcbiAgICAgICAgICAgIGZvciAobCA9IC13aWR0aDsgbCA8IDA7IGwrKykge1xuICAgICAgICAgICAgICAgIGlmIChnaS5sM19lbmNbbCArIGpdICE9IDApXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGwgPT0gMClcbiAgICAgICAgICAgICAgICBnaS5zY2FsZWZhY1tzZmJdID0gcmVjYWxjID0gLTI7XG4gICAgICAgICAgICAvKiBhbnl0aGluZyBnb2VzLiAqL1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIG9ubHkgYmVzdF9zY2FsZWZhY19zdG9yZSBhbmQgY2FsY19zY2ZzaSBrbm93LS1hbmQgb25seSB0aGV5XG4gICAgICAgICAgICAgKiBzaG91bGQga25vdy0tYWJvdXQgdGhlIG1hZ2ljIG51bWJlciAtMi5cbiAgICAgICAgICAgICAqL1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKDAgPT0gZ2kuc2NhbGVmYWNfc2NhbGUgJiYgMCA9PSBnaS5wcmVmbGFnKSB7XG4gICAgICAgICAgICB2YXIgcyA9IDA7XG4gICAgICAgICAgICBmb3IgKHNmYiA9IDA7IHNmYiA8IGdpLnNmYm1heDsgc2ZiKyspXG4gICAgICAgICAgICAgICAgaWYgKGdpLnNjYWxlZmFjW3NmYl0gPiAwKVxuICAgICAgICAgICAgICAgICAgICBzIHw9IGdpLnNjYWxlZmFjW3NmYl07XG5cbiAgICAgICAgICAgIGlmICgwID09IChzICYgMSkgJiYgcyAhPSAwKSB7XG4gICAgICAgICAgICAgICAgZm9yIChzZmIgPSAwOyBzZmIgPCBnaS5zZmJtYXg7IHNmYisrKVxuICAgICAgICAgICAgICAgICAgICBpZiAoZ2kuc2NhbGVmYWNbc2ZiXSA+IDApXG4gICAgICAgICAgICAgICAgICAgICAgICBnaS5zY2FsZWZhY1tzZmJdID4+PSAxO1xuXG4gICAgICAgICAgICAgICAgZ2kuc2NhbGVmYWNfc2NhbGUgPSByZWNhbGMgPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKDAgPT0gZ2kucHJlZmxhZyAmJiBnaS5ibG9ja190eXBlICE9IEVuY29kZXIuU0hPUlRfVFlQRVxuICAgICAgICAgICAgJiYgZ2ZjLm1vZGVfZ3IgPT0gMikge1xuICAgICAgICAgICAgZm9yIChzZmIgPSAxMTsgc2ZiIDwgRW5jb2Rlci5TQlBTWV9sOyBzZmIrKylcbiAgICAgICAgICAgICAgICBpZiAoZ2kuc2NhbGVmYWNbc2ZiXSA8IHF1cHZ0LnByZXRhYltzZmJdXG4gICAgICAgICAgICAgICAgICAgICYmIGdpLnNjYWxlZmFjW3NmYl0gIT0gLTIpXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgaWYgKHNmYiA9PSBFbmNvZGVyLlNCUFNZX2wpIHtcbiAgICAgICAgICAgICAgICBmb3IgKHNmYiA9IDExOyBzZmIgPCBFbmNvZGVyLlNCUFNZX2w7IHNmYisrKVxuICAgICAgICAgICAgICAgICAgICBpZiAoZ2kuc2NhbGVmYWNbc2ZiXSA+IDApXG4gICAgICAgICAgICAgICAgICAgICAgICBnaS5zY2FsZWZhY1tzZmJdIC09IHF1cHZ0LnByZXRhYltzZmJdO1xuXG4gICAgICAgICAgICAgICAgZ2kucHJlZmxhZyA9IHJlY2FsYyA9IDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNDsgaSsrKVxuICAgICAgICAgICAgbDNfc2lkZS5zY2ZzaVtjaF1baV0gPSAwO1xuXG4gICAgICAgIGlmIChnZmMubW9kZV9nciA9PSAyICYmIGdyID09IDFcbiAgICAgICAgICAgICYmIGwzX3NpZGUudHRbMF1bY2hdLmJsb2NrX3R5cGUgIT0gRW5jb2Rlci5TSE9SVF9UWVBFXG4gICAgICAgICAgICAmJiBsM19zaWRlLnR0WzFdW2NoXS5ibG9ja190eXBlICE9IEVuY29kZXIuU0hPUlRfVFlQRSkge1xuICAgICAgICAgICAgc2Nmc2lfY2FsYyhjaCwgbDNfc2lkZSk7XG4gICAgICAgICAgICByZWNhbGMgPSAwO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoc2ZiID0gMDsgc2ZiIDwgZ2kuc2ZibWF4OyBzZmIrKykge1xuICAgICAgICAgICAgaWYgKGdpLnNjYWxlZmFjW3NmYl0gPT0gLTIpIHtcbiAgICAgICAgICAgICAgICBnaS5zY2FsZWZhY1tzZmJdID0gMDtcbiAgICAgICAgICAgICAgICAvKiBpZiBhbnl0aGluZyBnb2VzLCB0aGVuIDAgaXMgYSBnb29kIGNob2ljZSAqL1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGlmIChyZWNhbGMgIT0gMCkge1xuICAgICAgICAgICAgaWYgKGdmYy5tb2RlX2dyID09IDIpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNjYWxlX2JpdGNvdW50KGdpKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zY2FsZV9iaXRjb3VudF9sc2YoZ2ZjLCBnaSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiBhbGxfc2NhbGVmYWN0b3JzX25vdF9uZWdhdGl2ZShzY2FsZWZhYywgbikge1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG47ICsraSkge1xuICAgICAgICAgICAgaWYgKHNjYWxlZmFjW2ldIDwgMClcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogbnVtYmVyIG9mIGJpdHMgdXNlZCB0byBlbmNvZGUgc2NhbGVmYWNzLlxuICAgICAqXG4gICAgICogMTgqc2xlbjFfdGFiW2ldICsgMTgqc2xlbjJfdGFiW2ldXG4gICAgICovXG4gICAgdmFyIHNjYWxlX3Nob3J0ID0gWzAsIDE4LCAzNiwgNTQsIDU0LCAzNiwgNTQsIDcyLFxuICAgICAgICA1NCwgNzIsIDkwLCA3MiwgOTAsIDEwOCwgMTA4LCAxMjZdO1xuXG4gICAgLyoqXG4gICAgICogbnVtYmVyIG9mIGJpdHMgdXNlZCB0byBlbmNvZGUgc2NhbGVmYWNzLlxuICAgICAqXG4gICAgICogMTcqc2xlbjFfdGFiW2ldICsgMTgqc2xlbjJfdGFiW2ldXG4gICAgICovXG4gICAgdmFyIHNjYWxlX21peGVkID0gWzAsIDE4LCAzNiwgNTQsIDUxLCAzNSwgNTMsIDcxLFxuICAgICAgICA1MiwgNzAsIDg4LCA2OSwgODcsIDEwNSwgMTA0LCAxMjJdO1xuXG4gICAgLyoqXG4gICAgICogbnVtYmVyIG9mIGJpdHMgdXNlZCB0byBlbmNvZGUgc2NhbGVmYWNzLlxuICAgICAqXG4gICAgICogMTEqc2xlbjFfdGFiW2ldICsgMTAqc2xlbjJfdGFiW2ldXG4gICAgICovXG4gICAgdmFyIHNjYWxlX2xvbmcgPSBbMCwgMTAsIDIwLCAzMCwgMzMsIDIxLCAzMSwgNDEsIDMyLCA0MixcbiAgICAgICAgNTIsIDQzLCA1MywgNjMsIDY0LCA3NF07XG5cbiAgICAvKipcbiAgICAgKiBBbHNvIGNhbGN1bGF0ZXMgdGhlIG51bWJlciBvZiBiaXRzIG5lY2Vzc2FyeSB0byBjb2RlIHRoZSBzY2FsZWZhY3RvcnMuXG4gICAgICovXG4gICAgdGhpcy5zY2FsZV9iaXRjb3VudCA9IGZ1bmN0aW9uIChjb2RfaW5mbykge1xuICAgICAgICB2YXIgaywgc2ZiLCBtYXhfc2xlbjEgPSAwLCBtYXhfc2xlbjIgPSAwO1xuXG4gICAgICAgIC8qIG1heGltdW0gdmFsdWVzICovXG4gICAgICAgIHZhciB0YWI7XG4gICAgICAgIHZhciBzY2FsZWZhYyA9IGNvZF9pbmZvLnNjYWxlZmFjO1xuXG4gICAgICAgIGFzc2VydChhbGxfc2NhbGVmYWN0b3JzX25vdF9uZWdhdGl2ZShzY2FsZWZhYywgY29kX2luZm8uc2ZibWF4KSk7XG5cbiAgICAgICAgaWYgKGNvZF9pbmZvLmJsb2NrX3R5cGUgPT0gRW5jb2Rlci5TSE9SVF9UWVBFKSB7XG4gICAgICAgICAgICB0YWIgPSBzY2FsZV9zaG9ydDtcbiAgICAgICAgICAgIGlmIChjb2RfaW5mby5taXhlZF9ibG9ja19mbGFnICE9IDApXG4gICAgICAgICAgICAgICAgdGFiID0gc2NhbGVfbWl4ZWQ7XG4gICAgICAgIH0gZWxzZSB7IC8qIGJsb2NrX3R5cGUgPT0gMSwyLG9yIDMgKi9cbiAgICAgICAgICAgIHRhYiA9IHNjYWxlX2xvbmc7XG4gICAgICAgICAgICBpZiAoMCA9PSBjb2RfaW5mby5wcmVmbGFnKSB7XG4gICAgICAgICAgICAgICAgZm9yIChzZmIgPSAxMTsgc2ZiIDwgRW5jb2Rlci5TQlBTWV9sOyBzZmIrKylcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNjYWxlZmFjW3NmYl0gPCBxdXB2dC5wcmV0YWJbc2ZiXSlcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICAgICAgaWYgKHNmYiA9PSBFbmNvZGVyLlNCUFNZX2wpIHtcbiAgICAgICAgICAgICAgICAgICAgY29kX2luZm8ucHJlZmxhZyA9IDE7XG4gICAgICAgICAgICAgICAgICAgIGZvciAoc2ZiID0gMTE7IHNmYiA8IEVuY29kZXIuU0JQU1lfbDsgc2ZiKyspXG4gICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWZhY1tzZmJdIC09IHF1cHZ0LnByZXRhYltzZmJdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoc2ZiID0gMDsgc2ZiIDwgY29kX2luZm8uc2ZiZGl2aWRlOyBzZmIrKylcbiAgICAgICAgICAgIGlmIChtYXhfc2xlbjEgPCBzY2FsZWZhY1tzZmJdKVxuICAgICAgICAgICAgICAgIG1heF9zbGVuMSA9IHNjYWxlZmFjW3NmYl07XG5cbiAgICAgICAgZm9yICg7IHNmYiA8IGNvZF9pbmZvLnNmYm1heDsgc2ZiKyspXG4gICAgICAgICAgICBpZiAobWF4X3NsZW4yIDwgc2NhbGVmYWNbc2ZiXSlcbiAgICAgICAgICAgICAgICBtYXhfc2xlbjIgPSBzY2FsZWZhY1tzZmJdO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIGZyb20gVGFrZWhpcm8gVE9NSU5BR0EgPHRvbWluYWdhQGlzb3Rlcm5ldC5vcmc+IDEwLzk5IGxvb3Agb3ZlciAqYWxsKlxuICAgICAgICAgKiBwb3NpYmxlIHZhbHVlcyBvZiBzY2FsZWZhY19jb21wcmVzcyB0byBmaW5kIHRoZSBvbmUgd2hpY2ggdXNlcyB0aGVcbiAgICAgICAgICogc21hbGxlc3QgbnVtYmVyIG9mIGJpdHMuIElTTyB3b3VsZCBzdG9wIGF0IGZpcnN0IHZhbGlkIGluZGV4XG4gICAgICAgICAqL1xuICAgICAgICBjb2RfaW5mby5wYXJ0Ml9sZW5ndGggPSBRdWFudGl6ZVBWVC5MQVJHRV9CSVRTO1xuICAgICAgICBmb3IgKGsgPSAwOyBrIDwgMTY7IGsrKykge1xuICAgICAgICAgICAgaWYgKG1heF9zbGVuMSA8IHNsZW4xX25ba10gJiYgbWF4X3NsZW4yIDwgc2xlbjJfbltrXVxuICAgICAgICAgICAgICAgICYmIGNvZF9pbmZvLnBhcnQyX2xlbmd0aCA+IHRhYltrXSkge1xuICAgICAgICAgICAgICAgIGNvZF9pbmZvLnBhcnQyX2xlbmd0aCA9IHRhYltrXTtcbiAgICAgICAgICAgICAgICBjb2RfaW5mby5zY2FsZWZhY19jb21wcmVzcyA9IGs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGNvZF9pbmZvLnBhcnQyX2xlbmd0aCA9PSBRdWFudGl6ZVBWVC5MQVJHRV9CSVRTO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHRhYmxlIG9mIGxhcmdlc3Qgc2NhbGVmYWN0b3IgdmFsdWVzIGZvciBNUEVHMlxuICAgICAqL1xuICAgIHZhciBtYXhfcmFuZ2Vfc2ZhY190YWIgPSBbWzE1LCAxNSwgNywgN10sXG4gICAgICAgIFsxNSwgMTUsIDcsIDBdLCBbNywgMywgMCwgMF0sIFsxNSwgMzEsIDMxLCAwXSxcbiAgICAgICAgWzcsIDcsIDcsIDBdLCBbMywgMywgMCwgMF1dO1xuXG4gICAgLyoqXG4gICAgICogQWxzbyBjb3VudHMgdGhlIG51bWJlciBvZiBiaXRzIHRvIGVuY29kZSB0aGUgc2NhbGVmYWNzIGJ1dCBmb3IgTVBFRyAyXG4gICAgICogTG93ZXIgc2FtcGxpbmcgZnJlcXVlbmNpZXMgKDI0LCAyMi4wNSBhbmQgMTYga0h6LilcbiAgICAgKlxuICAgICAqIFRoaXMgaXMgcmV2ZXJzZS1lbmdpbmVlcmVkIGZyb20gc2VjdGlvbiAyLjQuMy4yIG9mIHRoZSBNUEVHMiBJUyxcbiAgICAgKiBcIkF1ZGlvIERlY29kaW5nIExheWVyIElJSVwiXG4gICAgICovXG4gICAgdGhpcy5zY2FsZV9iaXRjb3VudF9sc2YgPSBmdW5jdGlvbiAoZ2ZjLCBjb2RfaW5mbykge1xuICAgICAgICB2YXIgdGFibGVfbnVtYmVyLCByb3dfaW5fdGFibGUsIHBhcnRpdGlvbiwgbnJfc2ZiLCB3aW5kb3c7XG4gICAgICAgIHZhciBvdmVyO1xuICAgICAgICB2YXIgaSwgc2ZiO1xuICAgICAgICB2YXIgbWF4X3NmYWMgPSBuZXdfaW50KDQpO1xuLy92YXIgcGFydGl0aW9uX3RhYmxlO1xuICAgICAgICB2YXIgc2NhbGVmYWMgPSBjb2RfaW5mby5zY2FsZWZhYztcblxuICAgICAgICAvKlxuICAgICAgICAgKiBTZXQgcGFydGl0aW9uIHRhYmxlLiBOb3RlIHRoYXQgc2hvdWxkIHRyeSB0byB1c2UgdGFibGUgb25lLCBidXQgZG9cbiAgICAgICAgICogbm90IHlldC4uLlxuICAgICAgICAgKi9cbiAgICAgICAgaWYgKGNvZF9pbmZvLnByZWZsYWcgIT0gMClcbiAgICAgICAgICAgIHRhYmxlX251bWJlciA9IDI7XG4gICAgICAgIGVsc2VcbiAgICAgICAgICAgIHRhYmxlX251bWJlciA9IDA7XG5cbiAgICAgICAgZm9yIChpID0gMDsgaSA8IDQ7IGkrKylcbiAgICAgICAgICAgIG1heF9zZmFjW2ldID0gMDtcblxuICAgICAgICBpZiAoY29kX2luZm8uYmxvY2tfdHlwZSA9PSBFbmNvZGVyLlNIT1JUX1RZUEUpIHtcbiAgICAgICAgICAgIHJvd19pbl90YWJsZSA9IDE7XG4gICAgICAgICAgICB2YXIgcGFydGl0aW9uX3RhYmxlID0gcXVwdnQubnJfb2Zfc2ZiX2Jsb2NrW3RhYmxlX251bWJlcl1bcm93X2luX3RhYmxlXTtcbiAgICAgICAgICAgIGZvciAoc2ZiID0gMCwgcGFydGl0aW9uID0gMDsgcGFydGl0aW9uIDwgNDsgcGFydGl0aW9uKyspIHtcbiAgICAgICAgICAgICAgICBucl9zZmIgPSBwYXJ0aXRpb25fdGFibGVbcGFydGl0aW9uXSAvIDM7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IG5yX3NmYjsgaSsrLCBzZmIrKylcbiAgICAgICAgICAgICAgICAgICAgZm9yICh3aW5kb3cgPSAwOyB3aW5kb3cgPCAzOyB3aW5kb3crKylcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChzY2FsZWZhY1tzZmIgKiAzICsgd2luZG93XSA+IG1heF9zZmFjW3BhcnRpdGlvbl0pXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4X3NmYWNbcGFydGl0aW9uXSA9IHNjYWxlZmFjW3NmYiAqIDMgKyB3aW5kb3ddO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcm93X2luX3RhYmxlID0gMDtcbiAgICAgICAgICAgIHZhciBwYXJ0aXRpb25fdGFibGUgPSBxdXB2dC5ucl9vZl9zZmJfYmxvY2tbdGFibGVfbnVtYmVyXVtyb3dfaW5fdGFibGVdO1xuICAgICAgICAgICAgZm9yIChzZmIgPSAwLCBwYXJ0aXRpb24gPSAwOyBwYXJ0aXRpb24gPCA0OyBwYXJ0aXRpb24rKykge1xuICAgICAgICAgICAgICAgIG5yX3NmYiA9IHBhcnRpdGlvbl90YWJsZVtwYXJ0aXRpb25dO1xuICAgICAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBucl9zZmI7IGkrKywgc2ZiKyspXG4gICAgICAgICAgICAgICAgICAgIGlmIChzY2FsZWZhY1tzZmJdID4gbWF4X3NmYWNbcGFydGl0aW9uXSlcbiAgICAgICAgICAgICAgICAgICAgICAgIG1heF9zZmFjW3BhcnRpdGlvbl0gPSBzY2FsZWZhY1tzZmJdO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChvdmVyID0gZmFsc2UsIHBhcnRpdGlvbiA9IDA7IHBhcnRpdGlvbiA8IDQ7IHBhcnRpdGlvbisrKSB7XG4gICAgICAgICAgICBpZiAobWF4X3NmYWNbcGFydGl0aW9uXSA+IG1heF9yYW5nZV9zZmFjX3RhYlt0YWJsZV9udW1iZXJdW3BhcnRpdGlvbl0pXG4gICAgICAgICAgICAgICAgb3ZlciA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFvdmVyKSB7XG4gICAgICAgICAgICB2YXIgc2xlbjEsIHNsZW4yLCBzbGVuMywgc2xlbjQ7XG5cbiAgICAgICAgICAgIGNvZF9pbmZvLnNmYl9wYXJ0aXRpb25fdGFibGUgPSBxdXB2dC5ucl9vZl9zZmJfYmxvY2tbdGFibGVfbnVtYmVyXVtyb3dfaW5fdGFibGVdO1xuICAgICAgICAgICAgZm9yIChwYXJ0aXRpb24gPSAwOyBwYXJ0aXRpb24gPCA0OyBwYXJ0aXRpb24rKylcbiAgICAgICAgICAgICAgICBjb2RfaW5mby5zbGVuW3BhcnRpdGlvbl0gPSBsb2cydGFiW21heF9zZmFjW3BhcnRpdGlvbl1dO1xuXG4gICAgICAgICAgICAvKiBzZXQgc2NhbGVmYWNfY29tcHJlc3MgKi9cbiAgICAgICAgICAgIHNsZW4xID0gY29kX2luZm8uc2xlblswXTtcbiAgICAgICAgICAgIHNsZW4yID0gY29kX2luZm8uc2xlblsxXTtcbiAgICAgICAgICAgIHNsZW4zID0gY29kX2luZm8uc2xlblsyXTtcbiAgICAgICAgICAgIHNsZW40ID0gY29kX2luZm8uc2xlblszXTtcblxuICAgICAgICAgICAgc3dpdGNoICh0YWJsZV9udW1iZXIpIHtcbiAgICAgICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgICAgIGNvZF9pbmZvLnNjYWxlZmFjX2NvbXByZXNzID0gKCgoc2xlbjEgKiA1KSArIHNsZW4yKSA8PCA0KVxuICAgICAgICAgICAgICAgICAgICAgICAgKyAoc2xlbjMgPDwgMikgKyBzbGVuNDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgICAgIGNvZF9pbmZvLnNjYWxlZmFjX2NvbXByZXNzID0gNDAwICsgKCgoc2xlbjEgKiA1KSArIHNsZW4yKSA8PCAyKVxuICAgICAgICAgICAgICAgICAgICAgICAgKyBzbGVuMztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgICAgIGNvZF9pbmZvLnNjYWxlZmFjX2NvbXByZXNzID0gNTAwICsgKHNsZW4xICogMykgKyBzbGVuMjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG5cbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgICBTeXN0ZW0uZXJyLnByaW50ZihcImludGVuc2l0eSBzdGVyZW8gbm90IGltcGxlbWVudGVkIHlldFxcblwiKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFvdmVyKSB7XG4gICAgICAgICAgICBhc3NlcnQoY29kX2luZm8uc2ZiX3BhcnRpdGlvbl90YWJsZSAhPSBudWxsKTtcbiAgICAgICAgICAgIGNvZF9pbmZvLnBhcnQyX2xlbmd0aCA9IDA7XG4gICAgICAgICAgICBmb3IgKHBhcnRpdGlvbiA9IDA7IHBhcnRpdGlvbiA8IDQ7IHBhcnRpdGlvbisrKVxuICAgICAgICAgICAgICAgIGNvZF9pbmZvLnBhcnQyX2xlbmd0aCArPSBjb2RfaW5mby5zbGVuW3BhcnRpdGlvbl1cbiAgICAgICAgICAgICAgICAgICAgKiBjb2RfaW5mby5zZmJfcGFydGl0aW9uX3RhYmxlW3BhcnRpdGlvbl07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG92ZXI7XG4gICAgfVxuXG4gICAgLypcbiAgICAgKiBTaW5jZSBubyBiYW5kcyBoYXZlIGJlZW4gb3Zlci1hbXBsaWZpZWQsIHdlIGNhbiBzZXQgc2NhbGVmYWNfY29tcHJlc3MgYW5kXG4gICAgICogc2xlbltdIGZvciB0aGUgZm9ybWF0dGVyXG4gICAgICovXG4gICAgdmFyIGxvZzJ0YWIgPSBbMCwgMSwgMiwgMiwgMywgMywgMywgMywgNCwgNCwgNCwgNCxcbiAgICAgICAgNCwgNCwgNCwgNF07XG5cbiAgICB0aGlzLmh1ZmZtYW5faW5pdCA9IGZ1bmN0aW9uIChnZmMpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDI7IGkgPD0gNTc2OyBpICs9IDIpIHtcbiAgICAgICAgICAgIHZhciBzY2ZiX2FueiA9IDAsIGJ2X2luZGV4O1xuICAgICAgICAgICAgd2hpbGUgKGdmYy5zY2FsZWZhY19iYW5kLmxbKytzY2ZiX2Fuel0gPCBpKVxuICAgICAgICAgICAgICAgIDtcblxuICAgICAgICAgICAgYnZfaW5kZXggPSBzdWJkdl90YWJsZVtzY2ZiX2Fuel1bMF07IC8vIC5yZWdpb24wX2NvdW50XG4gICAgICAgICAgICB3aGlsZSAoZ2ZjLnNjYWxlZmFjX2JhbmQubFtidl9pbmRleCArIDFdID4gaSlcbiAgICAgICAgICAgICAgICBidl9pbmRleC0tO1xuXG4gICAgICAgICAgICBpZiAoYnZfaW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgKiB0aGlzIGlzIGFuIGluZGljYXRpb24gdGhhdCBldmVyeXRoaW5nIGlzIGdvaW5nIHRvIGJlIGVuY29kZWRcbiAgICAgICAgICAgICAgICAgKiBhcyByZWdpb24wOiBiaWd2YWx1ZXMgPCByZWdpb24wIDwgcmVnaW9uMSBzbyBsZXRzIHNldFxuICAgICAgICAgICAgICAgICAqIHJlZ2lvbjAsIHJlZ2lvbjEgdG8gc29tZSB2YWx1ZSBsYXJnZXIgdGhhbiBiaWd2YWx1ZXNcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBidl9pbmRleCA9IHN1YmR2X3RhYmxlW3NjZmJfYW56XVswXTsgLy8gLnJlZ2lvbjBfY291bnRcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2ZjLmJ2X3NjZltpIC0gMl0gPSBidl9pbmRleDtcblxuICAgICAgICAgICAgYnZfaW5kZXggPSBzdWJkdl90YWJsZVtzY2ZiX2Fuel1bMV07IC8vIC5yZWdpb24xX2NvdW50XG4gICAgICAgICAgICB3aGlsZSAoZ2ZjLnNjYWxlZmFjX2JhbmQubFtidl9pbmRleCArIGdmYy5idl9zY2ZbaSAtIDJdICsgMl0gPiBpKVxuICAgICAgICAgICAgICAgIGJ2X2luZGV4LS07XG5cbiAgICAgICAgICAgIGlmIChidl9pbmRleCA8IDApIHtcbiAgICAgICAgICAgICAgICBidl9pbmRleCA9IHN1YmR2X3RhYmxlW3NjZmJfYW56XVsxXTsgLy8gLnJlZ2lvbjFfY291bnRcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2ZjLmJ2X3NjZltpIC0gMV0gPSBidl9pbmRleDtcbiAgICAgICAgfVxuICAgIH1cbn1cblxubW9kdWxlLmV4cG9ydHMgPSBUYWtlaGlybztcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL19sYW1lanNAMS4yLjFAbGFtZWpzL3NyYy9qcy9UYWtlaGlyby5qc1xuLy8gbW9kdWxlIGlkID0gL01ZOFxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:////MY8\n')},"/N9a":function(module,exports,__webpack_require__){eval('/*\n * ReplayGainAnalysis - analyzes input samples and give the recommended dB change\n * Copyright (C) 2001 David Robinson and Glen Sawyer\n * Improvements and optimizations added by Frank Klemm, and by Marcel Muller \n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2.1 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Lesser General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the Free Software\n * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n *\n * concept and filter values by David Robinson (David@Robinson.org)\n * -- blame him if you think the idea is flawed\n * original coding by Glen Sawyer (mp3gain@hotmail.com)\n * -- blame him if you think this runs too slowly, or the coding is otherwise flawed\n *\n * lots of code improvements by Frank Klemm ( http://www.uni-jena.de/~pfk/mpp/ )\n * -- credit him for all the _good_ programming ;)\n *\n *\n * For an explanation of the concepts and the basic algorithms involved, go to:\n * http://www.replaygain.org/\n */\n\n/*\n * Here\'s the deal. Call\n *\n * InitGainAnalysis ( long samplefreq );\n *\n * to initialize everything. Call\n *\n * AnalyzeSamples ( var Float_t* left_samples,\n * var Float_t* right_samples,\n * size_t num_samples,\n * int num_channels );\n *\n * as many times as you want, with as many or as few samples as you want.\n * If mono, pass the sample buffer in through left_samples, leave\n * right_samples NULL, and make sure num_channels = 1.\n *\n * GetTitleGain()\n *\n * will return the recommended dB level change for all samples analyzed\n * SINCE THE LAST TIME you called GetTitleGain() OR InitGainAnalysis().\n *\n * GetAlbumGain()\n *\n * will return the recommended dB level change for all samples analyzed\n * since InitGainAnalysis() was called and finalized with GetTitleGain().\n *\n * Pseudo-code to process an album:\n *\n * Float_t l_samples [4096];\n * Float_t r_samples [4096];\n * size_t num_samples;\n * unsigned int num_songs;\n * unsigned int i;\n *\n * InitGainAnalysis ( 44100 );\n * for ( i = 1; i <= num_songs; i++ ) {\n * while ( ( num_samples = getSongSamples ( song[i], left_samples, right_samples ) ) > 0 )\n * AnalyzeSamples ( left_samples, right_samples, num_samples, 2 );\n * fprintf ("Recommended dB change for song %2d: %+6.2 dB\\n", i, GetTitleGain() );\n * }\n * fprintf ("Recommended dB change for whole album: %+6.2 dB\\n", GetAlbumGain() );\n */\n\n/*\n * So here\'s the main source of potential code confusion:\n *\n * The filters applied to the incoming samples are IIR filters,\n * meaning they rely on up to number of previous samples\n * AND up to number of previous filtered samples.\n *\n * I set up the AnalyzeSamples routine to minimize memory usage and interface\n * complexity. The speed isn\'t compromised too much (I don\'t think), but the\n * internal complexity is higher than it should be for such a relatively\n * simple routine.\n *\n * Optimization/clarity suggestions are welcome.\n */\nvar common = __webpack_require__("Dkd2");\nvar System = common.System;\nvar VbrMode = common.VbrMode;\nvar Float = common.Float;\nvar ShortBlock = common.ShortBlock;\nvar Util = common.Util;\nvar Arrays = common.Arrays;\nvar new_array_n = common.new_array_n;\nvar new_byte = common.new_byte;\nvar new_double = common.new_double;\nvar new_float = common.new_float;\nvar new_float_n = common.new_float_n;\nvar new_int = common.new_int;\nvar new_int_n = common.new_int_n;\nvar assert = common.assert;\n\n/**\n * Table entries per dB\n */\nGainAnalysis.STEPS_per_dB = 100.;\n/**\n * Table entries for 0...MAX_dB (normal max. values are 70...80 dB)\n */\nGainAnalysis.MAX_dB = 120.;\nGainAnalysis.GAIN_NOT_ENOUGH_SAMPLES = -24601;\nGainAnalysis.GAIN_ANALYSIS_ERROR = 0;\nGainAnalysis.GAIN_ANALYSIS_OK = 1;\nGainAnalysis.INIT_GAIN_ANALYSIS_ERROR = 0;\nGainAnalysis.INIT_GAIN_ANALYSIS_OK = 1;\n\nGainAnalysis.YULE_ORDER = 10;\nGainAnalysis.MAX_ORDER = GainAnalysis.YULE_ORDER;\n\nGainAnalysis.MAX_SAMP_FREQ = 48000;\nGainAnalysis.RMS_WINDOW_TIME_NUMERATOR = 1;\nGainAnalysis.RMS_WINDOW_TIME_DENOMINATOR = 20;\nGainAnalysis.MAX_SAMPLES_PER_WINDOW = ((GainAnalysis.MAX_SAMP_FREQ * GainAnalysis.RMS_WINDOW_TIME_NUMERATOR) / GainAnalysis.RMS_WINDOW_TIME_DENOMINATOR + 1);\n\nfunction GainAnalysis() {\n /**\n * calibration value for 89dB\n */\n var PINK_REF = 64.82;\n\n var YULE_ORDER = GainAnalysis.YULE_ORDER;\n /**\n * percentile which is louder than the proposed level\n */\n var RMS_PERCENTILE = 0.95;\n /**\n * maximum allowed sample frequency [Hz]\n */\n var MAX_SAMP_FREQ = GainAnalysis.MAX_SAMP_FREQ;\n var RMS_WINDOW_TIME_NUMERATOR = GainAnalysis.RMS_WINDOW_TIME_NUMERATOR;\n /**\n * numerator / denominator = time slice size [s]\n */\n var RMS_WINDOW_TIME_DENOMINATOR = GainAnalysis.RMS_WINDOW_TIME_DENOMINATOR;\n /**\n * max. Samples per Time slice\n */\n var MAX_SAMPLES_PER_WINDOW = GainAnalysis.MAX_SAMPLES_PER_WINDOW;\n\n\n var ABYule = [\n [0.03857599435200, -3.84664617118067, -0.02160367184185,\n 7.81501653005538, -0.00123395316851, -11.34170355132042,\n -0.00009291677959, 13.05504219327545, -0.01655260341619,\n -12.28759895145294, 0.02161526843274, 9.48293806319790,\n -0.02074045215285, -5.87257861775999, 0.00594298065125,\n 2.75465861874613, 0.00306428023191, -0.86984376593551,\n 0.00012025322027, 0.13919314567432, 0.00288463683916],\n [0.05418656406430, -3.47845948550071, -0.02911007808948,\n 6.36317777566148, -0.00848709379851, -8.54751527471874,\n -0.00851165645469, 9.47693607801280, -0.00834990904936,\n -8.81498681370155, 0.02245293253339, 6.85401540936998,\n -0.02596338512915, -4.39470996079559, 0.01624864962975,\n 2.19611684890774, -0.00240879051584, -0.75104302451432,\n 0.00674613682247, 0.13149317958808, -0.00187763777362],\n [0.15457299681924, -2.37898834973084, -0.09331049056315,\n 2.84868151156327, -0.06247880153653, -2.64577170229825,\n 0.02163541888798, 2.23697657451713, -0.05588393329856,\n -1.67148153367602, 0.04781476674921, 1.00595954808547,\n 0.00222312597743, -0.45953458054983, 0.03174092540049,\n 0.16378164858596, -0.01390589421898, -0.05032077717131,\n 0.00651420667831, 0.02347897407020, -0.00881362733839],\n [0.30296907319327, -1.61273165137247, -0.22613988682123,\n 1.07977492259970, -0.08587323730772, -0.25656257754070,\n 0.03282930172664, -0.16276719120440, -0.00915702933434,\n -0.22638893773906, -0.02364141202522, 0.39120800788284,\n -0.00584456039913, -0.22138138954925, 0.06276101321749,\n 0.04500235387352, -0.00000828086748, 0.02005851806501,\n 0.00205861885564, 0.00302439095741, -0.02950134983287],\n [0.33642304856132, -1.49858979367799, -0.25572241425570,\n 0.87350271418188, -0.11828570177555, 0.12205022308084,\n 0.11921148675203, -0.80774944671438, -0.07834489609479,\n 0.47854794562326, -0.00469977914380, -0.12453458140019,\n -0.00589500224440, -0.04067510197014, 0.05724228140351,\n 0.08333755284107, 0.00832043980773, -0.04237348025746,\n -0.01635381384540, 0.02977207319925, -0.01760176568150],\n [0.44915256608450, -0.62820619233671, -0.14351757464547,\n 0.29661783706366, -0.22784394429749, -0.37256372942400,\n -0.01419140100551, 0.00213767857124, 0.04078262797139,\n -0.42029820170918, -0.12398163381748, 0.22199650564824,\n 0.04097565135648, 0.00613424350682, 0.10478503600251,\n 0.06747620744683, -0.01863887810927, 0.05784820375801,\n -0.03193428438915, 0.03222754072173, 0.00541907748707],\n [0.56619470757641, -1.04800335126349, -0.75464456939302,\n 0.29156311971249, 0.16242137742230, -0.26806001042947,\n 0.16744243493672, 0.00819999645858, -0.18901604199609,\n 0.45054734505008, 0.30931782841830, -0.33032403314006,\n -0.27562961986224, 0.06739368333110, 0.00647310677246,\n -0.04784254229033, 0.08647503780351, 0.01639907836189,\n -0.03788984554840, 0.01807364323573, -0.00588215443421],\n [0.58100494960553, -0.51035327095184, -0.53174909058578,\n -0.31863563325245, -0.14289799034253, -0.20256413484477,\n 0.17520704835522, 0.14728154134330, 0.02377945217615,\n 0.38952639978999, 0.15558449135573, -0.23313271880868,\n -0.25344790059353, -0.05246019024463, 0.01628462406333,\n -0.02505961724053, 0.06920467763959, 0.02442357316099,\n -0.03721611395801, 0.01818801111503, -0.00749618797172],\n [0.53648789255105, -0.25049871956020, -0.42163034350696,\n -0.43193942311114, -0.00275953611929, -0.03424681017675,\n 0.04267842219415, -0.04678328784242, -0.10214864179676,\n 0.26408300200955, 0.14590772289388, 0.15113130533216,\n -0.02459864859345, -0.17556493366449, -0.11202315195388,\n -0.18823009262115, -0.04060034127000, 0.05477720428674,\n 0.04788665548180, 0.04704409688120, -0.02217936801134]];\n\n var ABButter = [\n [0.98621192462708, -1.97223372919527, -1.97242384925416,\n 0.97261396931306, 0.98621192462708],\n [0.98500175787242, -1.96977855582618, -1.97000351574484,\n 0.97022847566350, 0.98500175787242],\n [0.97938932735214, -1.95835380975398, -1.95877865470428,\n 0.95920349965459, 0.97938932735214],\n [0.97531843204928, -1.95002759149878, -1.95063686409857,\n 0.95124613669835, 0.97531843204928],\n [0.97316523498161, -1.94561023566527, -1.94633046996323,\n 0.94705070426118, 0.97316523498161],\n [0.96454515552826, -1.92783286977036, -1.92909031105652,\n 0.93034775234268, 0.96454515552826],\n [0.96009142950541, -1.91858953033784, -1.92018285901082,\n 0.92177618768381, 0.96009142950541],\n [0.95856916599601, -1.91542108074780, -1.91713833199203,\n 0.91885558323625, 0.95856916599601],\n [0.94597685600279, -1.88903307939452, -1.89195371200558,\n 0.89487434461664, 0.94597685600279]];\n\n\n /**\n * When calling this procedure, make sure that ip[-order] and op[-order]\n * point to real data\n */\n //private void filterYule(final float[] input, int inputPos, float[] output,\n //int outputPos, int nSamples, final float[] kernel) {\n function filterYule(input, inputPos, output, outputPos, nSamples, kernel) {\n\n while ((nSamples--) != 0) {\n /* 1e-10 is a hack to avoid slowdown because of denormals */\n output[outputPos] = 1e-10 + input[inputPos + 0] * kernel[0]\n - output[outputPos - 1] * kernel[1] + input[inputPos - 1]\n * kernel[2] - output[outputPos - 2] * kernel[3]\n + input[inputPos - 2] * kernel[4] - output[outputPos - 3]\n * kernel[5] + input[inputPos - 3] * kernel[6]\n - output[outputPos - 4] * kernel[7] + input[inputPos - 4]\n * kernel[8] - output[outputPos - 5] * kernel[9]\n + input[inputPos - 5] * kernel[10] - output[outputPos - 6]\n * kernel[11] + input[inputPos - 6] * kernel[12]\n - output[outputPos - 7] * kernel[13] + input[inputPos - 7]\n * kernel[14] - output[outputPos - 8] * kernel[15]\n + input[inputPos - 8] * kernel[16] - output[outputPos - 9]\n * kernel[17] + input[inputPos - 9] * kernel[18]\n - output[outputPos - 10] * kernel[19]\n + input[inputPos - 10] * kernel[20];\n ++outputPos;\n ++inputPos;\n }\n }\n\n//private void filterButter(final float[] input, int inputPos,\n// float[] output, int outputPos, int nSamples, final float[] kernel) {\n function filterButter(input, inputPos, output, outputPos, nSamples, kernel) {\n\n while ((nSamples--) != 0) {\n output[outputPos] = input[inputPos + 0] * kernel[0]\n - output[outputPos - 1] * kernel[1] + input[inputPos - 1]\n * kernel[2] - output[outputPos - 2] * kernel[3]\n + input[inputPos - 2] * kernel[4];\n ++outputPos;\n ++inputPos;\n }\n }\n\n /**\n * @return INIT_GAIN_ANALYSIS_OK if successful, INIT_GAIN_ANALYSIS_ERROR if\n * not\n */\n function ResetSampleFrequency(rgData, samplefreq) {\n /* zero out initial values */\n for (var i = 0; i < MAX_ORDER; i++)\n rgData.linprebuf[i] = rgData.lstepbuf[i] = rgData.loutbuf[i] = rgData.rinprebuf[i] = rgData.rstepbuf[i] = rgData.routbuf[i] = 0.;\n\n switch (0 | (samplefreq)) {\n case 48000:\n rgData.reqindex = 0;\n break;\n case 44100:\n rgData.reqindex = 1;\n break;\n case 32000:\n rgData.reqindex = 2;\n break;\n case 24000:\n rgData.reqindex = 3;\n break;\n case 22050:\n rgData.reqindex = 4;\n break;\n case 16000:\n rgData.reqindex = 5;\n break;\n case 12000:\n rgData.reqindex = 6;\n break;\n case 11025:\n rgData.reqindex = 7;\n break;\n case 8000:\n rgData.reqindex = 8;\n break;\n default:\n return INIT_GAIN_ANALYSIS_ERROR;\n }\n\n rgData.sampleWindow = 0 | ((samplefreq * RMS_WINDOW_TIME_NUMERATOR\n + RMS_WINDOW_TIME_DENOMINATOR - 1) / RMS_WINDOW_TIME_DENOMINATOR);\n\n rgData.lsum = 0.;\n rgData.rsum = 0.;\n rgData.totsamp = 0;\n\n Arrays.ill(rgData.A, 0);\n\n return INIT_GAIN_ANALYSIS_OK;\n }\n\n this.InitGainAnalysis = function (rgData, samplefreq) {\n if (ResetSampleFrequency(rgData, samplefreq) != INIT_GAIN_ANALYSIS_OK) {\n return INIT_GAIN_ANALYSIS_ERROR;\n }\n\n rgData.linpre = MAX_ORDER;\n rgData.rinpre = MAX_ORDER;\n rgData.lstep = MAX_ORDER;\n rgData.rstep = MAX_ORDER;\n rgData.lout = MAX_ORDER;\n rgData.rout = MAX_ORDER;\n\n Arrays.fill(rgData.B, 0);\n\n return INIT_GAIN_ANALYSIS_OK;\n };\n\n /**\n * square\n */\n function fsqr(d) {\n return d * d;\n }\n\n this.AnalyzeSamples = function (rgData, left_samples, left_samplesPos, right_samples, right_samplesPos, num_samples,\n num_channels) {\n var curleft;\n var curleftBase;\n var curright;\n var currightBase;\n var batchsamples;\n var cursamples;\n var cursamplepos;\n\n if (num_samples == 0)\n return GAIN_ANALYSIS_OK;\n\n cursamplepos = 0;\n batchsamples = num_samples;\n\n switch (num_channels) {\n case 1:\n right_samples = left_samples;\n right_samplesPos = left_samplesPos;\n break;\n case 2:\n break;\n default:\n return GAIN_ANALYSIS_ERROR;\n }\n\n if (num_samples < MAX_ORDER) {\n System.arraycopy(left_samples, left_samplesPos, rgData.linprebuf,\n MAX_ORDER, num_samples);\n System.arraycopy(right_samples, right_samplesPos, rgData.rinprebuf,\n MAX_ORDER, num_samples);\n } else {\n System.arraycopy(left_samples, left_samplesPos, rgData.linprebuf,\n MAX_ORDER, MAX_ORDER);\n System.arraycopy(right_samples, right_samplesPos, rgData.rinprebuf,\n MAX_ORDER, MAX_ORDER);\n }\n\n while (batchsamples > 0) {\n cursamples = batchsamples > rgData.sampleWindow - rgData.totsamp ? rgData.sampleWindow\n - rgData.totsamp\n : batchsamples;\n if (cursamplepos < MAX_ORDER) {\n curleft = rgData.linpre + cursamplepos;\n curleftBase = rgData.linprebuf;\n curright = rgData.rinpre + cursamplepos;\n currightBase = rgData.rinprebuf;\n if (cursamples > MAX_ORDER - cursamplepos)\n cursamples = MAX_ORDER - cursamplepos;\n } else {\n curleft = left_samplesPos + cursamplepos;\n curleftBase = left_samples;\n curright = right_samplesPos + cursamplepos;\n currightBase = right_samples;\n }\n\n filterYule(curleftBase, curleft, rgData.lstepbuf, rgData.lstep\n + rgData.totsamp, cursamples, ABYule[rgData.reqindex]);\n filterYule(currightBase, curright, rgData.rstepbuf, rgData.rstep\n + rgData.totsamp, cursamples, ABYule[rgData.reqindex]);\n\n filterButter(rgData.lstepbuf, rgData.lstep + rgData.totsamp,\n rgData.loutbuf, rgData.lout + rgData.totsamp, cursamples,\n ABButter[rgData.reqindex]);\n filterButter(rgData.rstepbuf, rgData.rstep + rgData.totsamp,\n rgData.routbuf, rgData.rout + rgData.totsamp, cursamples,\n ABButter[rgData.reqindex]);\n\n curleft = rgData.lout + rgData.totsamp;\n /* Get the squared values */\n curleftBase = rgData.loutbuf;\n curright = rgData.rout + rgData.totsamp;\n currightBase = rgData.routbuf;\n\n var i = cursamples % 8;\n while ((i--) != 0) {\n rgData.lsum += fsqr(curleftBase[curleft++]);\n rgData.rsum += fsqr(currightBase[curright++]);\n }\n i = cursamples / 8;\n while ((i--) != 0) {\n rgData.lsum += fsqr(curleftBase[curleft + 0])\n + fsqr(curleftBase[curleft + 1])\n + fsqr(curleftBase[curleft + 2])\n + fsqr(curleftBase[curleft + 3])\n + fsqr(curleftBase[curleft + 4])\n + fsqr(curleftBase[curleft + 5])\n + fsqr(curleftBase[curleft + 6])\n + fsqr(curleftBase[curleft + 7]);\n curleft += 8;\n rgData.rsum += fsqr(currightBase[curright + 0])\n + fsqr(currightBase[curright + 1])\n + fsqr(currightBase[curright + 2])\n + fsqr(currightBase[curright + 3])\n + fsqr(currightBase[curright + 4])\n + fsqr(currightBase[curright + 5])\n + fsqr(currightBase[curright + 6])\n + fsqr(currightBase[curright + 7]);\n curright += 8;\n }\n\n batchsamples -= cursamples;\n cursamplepos += cursamples;\n rgData.totsamp += cursamples;\n if (rgData.totsamp == rgData.sampleWindow) {\n /* Get the Root Mean Square (RMS) for this set of samples */\n var val = GainAnalysis.STEPS_per_dB\n * 10.\n * Math.log10((rgData.lsum + rgData.rsum)\n / rgData.totsamp * 0.5 + 1.e-37);\n var ival = (val <= 0) ? 0 : 0 | val;\n if (ival >= rgData.A.length)\n ival = rgData.A.length - 1;\n rgData.A[ival]++;\n rgData.lsum = rgData.rsum = 0.;\n\n System.arraycopy(rgData.loutbuf, rgData.totsamp,\n rgData.loutbuf, 0, MAX_ORDER);\n System.arraycopy(rgData.routbuf, rgData.totsamp,\n rgData.routbuf, 0, MAX_ORDER);\n System.arraycopy(rgData.lstepbuf, rgData.totsamp,\n rgData.lstepbuf, 0, MAX_ORDER);\n System.arraycopy(rgData.rstepbuf, rgData.totsamp,\n rgData.rstepbuf, 0, MAX_ORDER);\n rgData.totsamp = 0;\n }\n if (rgData.totsamp > rgData.sampleWindow) {\n /*\n * somehow I really screwed up: Error in programming! Contact\n * author about totsamp > sampleWindow\n */\n return GAIN_ANALYSIS_ERROR;\n }\n }\n if (num_samples < MAX_ORDER) {\n System.arraycopy(rgData.linprebuf, num_samples, rgData.linprebuf,\n 0, MAX_ORDER - num_samples);\n System.arraycopy(rgData.rinprebuf, num_samples, rgData.rinprebuf,\n 0, MAX_ORDER - num_samples);\n System.arraycopy(left_samples, left_samplesPos, rgData.linprebuf,\n MAX_ORDER - num_samples, num_samples);\n System.arraycopy(right_samples, right_samplesPos, rgData.rinprebuf,\n MAX_ORDER - num_samples, num_samples);\n } else {\n System.arraycopy(left_samples, left_samplesPos + num_samples\n - MAX_ORDER, rgData.linprebuf, 0, MAX_ORDER);\n System.arraycopy(right_samples, right_samplesPos + num_samples\n - MAX_ORDER, rgData.rinprebuf, 0, MAX_ORDER);\n }\n\n return GAIN_ANALYSIS_OK;\n };\n\n function analyzeResult(Array, len) {\n var i;\n\n var elems = 0;\n for (i = 0; i < len; i++)\n elems += Array[i];\n if (elems == 0)\n return GAIN_NOT_ENOUGH_SAMPLES;\n\n var upper = 0 | Math.ceil(elems * (1. - RMS_PERCENTILE));\n for (i = len; i-- > 0;) {\n if ((upper -= Array[i]) <= 0)\n break;\n }\n\n //return (float) ((float) PINK_REF - (float) i / (float) STEPS_per_dB);\n return (PINK_REF - i / GainAnalysis.STEPS_per_dB);\n }\n\n this.GetTitleGain = function (rgData) {\n var retval = analyzeResult(rgData.A, rgData.A.length);\n\n for (var i = 0; i < rgData.A.length; i++) {\n rgData.B[i] += rgData.A[i];\n rgData.A[i] = 0;\n }\n\n for (var i = 0; i < MAX_ORDER; i++)\n rgData.linprebuf[i] = rgData.lstepbuf[i] = rgData.loutbuf[i] = rgData.rinprebuf[i] = rgData.rstepbuf[i] = rgData.routbuf[i] = 0.;\n\n rgData.totsamp = 0;\n rgData.lsum = rgData.rsum = 0.;\n return retval;\n }\n\n}\n\nmodule.exports = GainAnalysis;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL045YS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvR2FpbkFuYWx5c2lzLmpzP2ZjZGYiXSwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqICBSZXBsYXlHYWluQW5hbHlzaXMgLSBhbmFseXplcyBpbnB1dCBzYW1wbGVzIGFuZCBnaXZlIHRoZSByZWNvbW1lbmRlZCBkQiBjaGFuZ2VcbiAqICBDb3B5cmlnaHQgKEMpIDIwMDEgRGF2aWQgUm9iaW5zb24gYW5kIEdsZW4gU2F3eWVyXG4gKiAgSW1wcm92ZW1lbnRzIGFuZCBvcHRpbWl6YXRpb25zIGFkZGVkIGJ5IEZyYW5rIEtsZW1tLCBhbmQgYnkgTWFyY2VsIE11bGxlciBcbiAqXG4gKiAgVGhpcyBsaWJyYXJ5IGlzIGZyZWUgc29mdHdhcmU7IHlvdSBjYW4gcmVkaXN0cmlidXRlIGl0IGFuZC9vclxuICogIG1vZGlmeSBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbiAqICBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbiAqICB2ZXJzaW9uIDIuMSBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiAgVGhpcyBsaWJyYXJ5IGlzIGRpc3RyaWJ1dGVkIGluIHRoZSBob3BlIHRoYXQgaXQgd2lsbCBiZSB1c2VmdWwsXG4gKiAgYnV0IFdJVEhPVVQgQU5ZIFdBUlJBTlRZOyB3aXRob3V0IGV2ZW4gdGhlIGltcGxpZWQgd2FycmFudHkgb2ZcbiAqICBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuICogIExlc3NlciBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogIFlvdSBzaG91bGQgaGF2ZSByZWNlaXZlZCBhIGNvcHkgb2YgdGhlIEdOVSBMZXNzZXIgR2VuZXJhbCBQdWJsaWNcbiAqICBMaWNlbnNlIGFsb25nIHdpdGggdGhpcyBsaWJyYXJ5OyBpZiBub3QsIHdyaXRlIHRvIHRoZSBGcmVlIFNvZnR3YXJlXG4gKiAgRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlLCBTdWl0ZSAzMzAsIEJvc3RvbiwgTUEgIDAyMTExLTEzMDcgIFVTQVxuICpcbiAqICBjb25jZXB0IGFuZCBmaWx0ZXIgdmFsdWVzIGJ5IERhdmlkIFJvYmluc29uIChEYXZpZEBSb2JpbnNvbi5vcmcpXG4gKiAgICAtLSBibGFtZSBoaW0gaWYgeW91IHRoaW5rIHRoZSBpZGVhIGlzIGZsYXdlZFxuICogIG9yaWdpbmFsIGNvZGluZyBieSBHbGVuIFNhd3llciAobXAzZ2FpbkBob3RtYWlsLmNvbSlcbiAqICAgIC0tIGJsYW1lIGhpbSBpZiB5b3UgdGhpbmsgdGhpcyBydW5zIHRvbyBzbG93bHksIG9yIHRoZSBjb2RpbmcgaXMgb3RoZXJ3aXNlIGZsYXdlZFxuICpcbiAqICBsb3RzIG9mIGNvZGUgaW1wcm92ZW1lbnRzIGJ5IEZyYW5rIEtsZW1tICggaHR0cDovL3d3dy51bmktamVuYS5kZS9+cGZrL21wcC8gKVxuICogICAgLS0gY3JlZGl0IGhpbSBmb3IgYWxsIHRoZSBfZ29vZF8gcHJvZ3JhbW1pbmcgOylcbiAqXG4gKlxuICogIEZvciBhbiBleHBsYW5hdGlvbiBvZiB0aGUgY29uY2VwdHMgYW5kIHRoZSBiYXNpYyBhbGdvcml0aG1zIGludm9sdmVkLCBnbyB0bzpcbiAqICAgIGh0dHA6Ly93d3cucmVwbGF5Z2Fpbi5vcmcvXG4gKi9cblxuLypcbiAqICBIZXJlJ3MgdGhlIGRlYWwuIENhbGxcbiAqXG4gKiAgICBJbml0R2FpbkFuYWx5c2lzICggbG9uZyBzYW1wbGVmcmVxICk7XG4gKlxuICogIHRvIGluaXRpYWxpemUgZXZlcnl0aGluZy4gQ2FsbFxuICpcbiAqICAgIEFuYWx5emVTYW1wbGVzICggdmFyIEZsb2F0X3QqICBsZWZ0X3NhbXBsZXMsXG4gKiAgICAgICAgICAgICAgICAgICAgIHZhciBGbG9hdF90KiAgcmlnaHRfc2FtcGxlcyxcbiAqICAgICAgICAgICAgICAgICAgICAgc2l6ZV90ICAgICAgICAgIG51bV9zYW1wbGVzLFxuICogICAgICAgICAgICAgICAgICAgICBpbnQgICAgICAgICAgICAgbnVtX2NoYW5uZWxzICk7XG4gKlxuICogIGFzIG1hbnkgdGltZXMgYXMgeW91IHdhbnQsIHdpdGggYXMgbWFueSBvciBhcyBmZXcgc2FtcGxlcyBhcyB5b3Ugd2FudC5cbiAqICBJZiBtb25vLCBwYXNzIHRoZSBzYW1wbGUgYnVmZmVyIGluIHRocm91Z2ggbGVmdF9zYW1wbGVzLCBsZWF2ZVxuICogIHJpZ2h0X3NhbXBsZXMgTlVMTCwgYW5kIG1ha2Ugc3VyZSBudW1fY2hhbm5lbHMgPSAxLlxuICpcbiAqICAgIEdldFRpdGxlR2FpbigpXG4gKlxuICogIHdpbGwgcmV0dXJuIHRoZSByZWNvbW1lbmRlZCBkQiBsZXZlbCBjaGFuZ2UgZm9yIGFsbCBzYW1wbGVzIGFuYWx5emVkXG4gKiAgU0lOQ0UgVEhFIExBU1QgVElNRSB5b3UgY2FsbGVkIEdldFRpdGxlR2FpbigpIE9SIEluaXRHYWluQW5hbHlzaXMoKS5cbiAqXG4gKiAgICBHZXRBbGJ1bUdhaW4oKVxuICpcbiAqICB3aWxsIHJldHVybiB0aGUgcmVjb21tZW5kZWQgZEIgbGV2ZWwgY2hhbmdlIGZvciBhbGwgc2FtcGxlcyBhbmFseXplZFxuICogIHNpbmNlIEluaXRHYWluQW5hbHlzaXMoKSB3YXMgY2FsbGVkIGFuZCBmaW5hbGl6ZWQgd2l0aCBHZXRUaXRsZUdhaW4oKS5cbiAqXG4gKiAgUHNldWRvLWNvZGUgdG8gcHJvY2VzcyBhbiBhbGJ1bTpcbiAqXG4gKiAgICBGbG9hdF90ICAgICAgIGxfc2FtcGxlcyBbNDA5Nl07XG4gKiAgICBGbG9hdF90ICAgICAgIHJfc2FtcGxlcyBbNDA5Nl07XG4gKiAgICBzaXplX3QgICAgICAgIG51bV9zYW1wbGVzO1xuICogICAgdW5zaWduZWQgaW50ICBudW1fc29uZ3M7XG4gKiAgICB1bnNpZ25lZCBpbnQgIGk7XG4gKlxuICogICAgSW5pdEdhaW5BbmFseXNpcyAoIDQ0MTAwICk7XG4gKiAgICBmb3IgKCBpID0gMTsgaSA8PSBudW1fc29uZ3M7IGkrKyApIHtcbiAqICAgICAgICB3aGlsZSAoICggbnVtX3NhbXBsZXMgPSBnZXRTb25nU2FtcGxlcyAoIHNvbmdbaV0sIGxlZnRfc2FtcGxlcywgcmlnaHRfc2FtcGxlcyApICkgPiAwIClcbiAqICAgICAgICAgICAgQW5hbHl6ZVNhbXBsZXMgKCBsZWZ0X3NhbXBsZXMsIHJpZ2h0X3NhbXBsZXMsIG51bV9zYW1wbGVzLCAyICk7XG4gKiAgICAgICAgZnByaW50ZiAoXCJSZWNvbW1lbmRlZCBkQiBjaGFuZ2UgZm9yIHNvbmcgJTJkOiAlKzYuMiBkQlxcblwiLCBpLCBHZXRUaXRsZUdhaW4oKSApO1xuICogICAgfVxuICogICAgZnByaW50ZiAoXCJSZWNvbW1lbmRlZCBkQiBjaGFuZ2UgZm9yIHdob2xlIGFsYnVtOiAlKzYuMiBkQlxcblwiLCBHZXRBbGJ1bUdhaW4oKSApO1xuICovXG5cbi8qXG4gKiAgU28gaGVyZSdzIHRoZSBtYWluIHNvdXJjZSBvZiBwb3RlbnRpYWwgY29kZSBjb25mdXNpb246XG4gKlxuICogIFRoZSBmaWx0ZXJzIGFwcGxpZWQgdG8gdGhlIGluY29taW5nIHNhbXBsZXMgYXJlIElJUiBmaWx0ZXJzLFxuICogIG1lYW5pbmcgdGhleSByZWx5IG9uIHVwIHRvIDxmaWx0ZXIgb3JkZXI+IG51bWJlciBvZiBwcmV2aW91cyBzYW1wbGVzXG4gKiAgQU5EIHVwIHRvIDxmaWx0ZXIgb3JkZXI+IG51bWJlciBvZiBwcmV2aW91cyBmaWx0ZXJlZCBzYW1wbGVzLlxuICpcbiAqICBJIHNldCB1cCB0aGUgQW5hbHl6ZVNhbXBsZXMgcm91dGluZSB0byBtaW5pbWl6ZSBtZW1vcnkgdXNhZ2UgYW5kIGludGVyZmFjZVxuICogIGNvbXBsZXhpdHkuIFRoZSBzcGVlZCBpc24ndCBjb21wcm9taXNlZCB0b28gbXVjaCAoSSBkb24ndCB0aGluayksIGJ1dCB0aGVcbiAqICBpbnRlcm5hbCBjb21wbGV4aXR5IGlzIGhpZ2hlciB0aGFuIGl0IHNob3VsZCBiZSBmb3Igc3VjaCBhIHJlbGF0aXZlbHlcbiAqICBzaW1wbGUgcm91dGluZS5cbiAqXG4gKiAgT3B0aW1pemF0aW9uL2NsYXJpdHkgc3VnZ2VzdGlvbnMgYXJlIHdlbGNvbWUuXG4gKi9cbnZhciBjb21tb24gPSByZXF1aXJlKCcuL2NvbW1vbi5qcycpO1xudmFyIFN5c3RlbSA9IGNvbW1vbi5TeXN0ZW07XG52YXIgVmJyTW9kZSA9IGNvbW1vbi5WYnJNb2RlO1xudmFyIEZsb2F0ID0gY29tbW9uLkZsb2F0O1xudmFyIFNob3J0QmxvY2sgPSBjb21tb24uU2hvcnRCbG9jaztcbnZhciBVdGlsID0gY29tbW9uLlV0aWw7XG52YXIgQXJyYXlzID0gY29tbW9uLkFycmF5cztcbnZhciBuZXdfYXJyYXlfbiA9IGNvbW1vbi5uZXdfYXJyYXlfbjtcbnZhciBuZXdfYnl0ZSA9IGNvbW1vbi5uZXdfYnl0ZTtcbnZhciBuZXdfZG91YmxlID0gY29tbW9uLm5ld19kb3VibGU7XG52YXIgbmV3X2Zsb2F0ID0gY29tbW9uLm5ld19mbG9hdDtcbnZhciBuZXdfZmxvYXRfbiA9IGNvbW1vbi5uZXdfZmxvYXRfbjtcbnZhciBuZXdfaW50ID0gY29tbW9uLm5ld19pbnQ7XG52YXIgbmV3X2ludF9uID0gY29tbW9uLm5ld19pbnRfbjtcbnZhciBhc3NlcnQgPSBjb21tb24uYXNzZXJ0O1xuXG4vKipcbiAqIFRhYmxlIGVudHJpZXMgcGVyIGRCXG4gKi9cbkdhaW5BbmFseXNpcy5TVEVQU19wZXJfZEIgPSAxMDAuO1xuLyoqXG4gKiBUYWJsZSBlbnRyaWVzIGZvciAwLi4uTUFYX2RCIChub3JtYWwgbWF4LiB2YWx1ZXMgYXJlIDcwLi4uODAgZEIpXG4gKi9cbkdhaW5BbmFseXNpcy5NQVhfZEIgPSAxMjAuO1xuR2FpbkFuYWx5c2lzLkdBSU5fTk9UX0VOT1VHSF9TQU1QTEVTID0gLTI0NjAxO1xuR2FpbkFuYWx5c2lzLkdBSU5fQU5BTFlTSVNfRVJST1IgPSAwO1xuR2FpbkFuYWx5c2lzLkdBSU5fQU5BTFlTSVNfT0sgPSAxO1xuR2FpbkFuYWx5c2lzLklOSVRfR0FJTl9BTkFMWVNJU19FUlJPUiA9IDA7XG5HYWluQW5hbHlzaXMuSU5JVF9HQUlOX0FOQUxZU0lTX09LID0gMTtcblxuR2FpbkFuYWx5c2lzLllVTEVfT1JERVIgPSAxMDtcbkdhaW5BbmFseXNpcy5NQVhfT1JERVIgPSBHYWluQW5hbHlzaXMuWVVMRV9PUkRFUjtcblxuR2FpbkFuYWx5c2lzLk1BWF9TQU1QX0ZSRVEgPSA0ODAwMDtcbkdhaW5BbmFseXNpcy5STVNfV0lORE9XX1RJTUVfTlVNRVJBVE9SID0gMTtcbkdhaW5BbmFseXNpcy5STVNfV0lORE9XX1RJTUVfREVOT01JTkFUT1IgPSAyMDtcbkdhaW5BbmFseXNpcy5NQVhfU0FNUExFU19QRVJfV0lORE9XID0gKChHYWluQW5hbHlzaXMuTUFYX1NBTVBfRlJFUSAqIEdhaW5BbmFseXNpcy5STVNfV0lORE9XX1RJTUVfTlVNRVJBVE9SKSAvIEdhaW5BbmFseXNpcy5STVNfV0lORE9XX1RJTUVfREVOT01JTkFUT1IgKyAxKTtcblxuZnVuY3Rpb24gR2FpbkFuYWx5c2lzKCkge1xuICAgIC8qKlxuICAgICAqIGNhbGlicmF0aW9uIHZhbHVlIGZvciA4OWRCXG4gICAgICovXG4gICAgdmFyIFBJTktfUkVGID0gNjQuODI7XG5cbiAgICB2YXIgWVVMRV9PUkRFUiA9IEdhaW5BbmFseXNpcy5ZVUxFX09SREVSO1xuICAgIC8qKlxuICAgICAqIHBlcmNlbnRpbGUgd2hpY2ggaXMgbG91ZGVyIHRoYW4gdGhlIHByb3Bvc2VkIGxldmVsXG4gICAgICovXG4gICAgdmFyIFJNU19QRVJDRU5USUxFID0gMC45NTtcbiAgICAvKipcbiAgICAgKiBtYXhpbXVtIGFsbG93ZWQgc2FtcGxlIGZyZXF1ZW5jeSBbSHpdXG4gICAgICovXG4gICAgdmFyIE1BWF9TQU1QX0ZSRVEgPSBHYWluQW5hbHlzaXMuTUFYX1NBTVBfRlJFUTtcbiAgICB2YXIgUk1TX1dJTkRPV19USU1FX05VTUVSQVRPUiA9IEdhaW5BbmFseXNpcy5STVNfV0lORE9XX1RJTUVfTlVNRVJBVE9SO1xuICAgIC8qKlxuICAgICAqIG51bWVyYXRvciAvIGRlbm9taW5hdG9yID0gdGltZSBzbGljZSBzaXplIFtzXVxuICAgICAqL1xuICAgIHZhciBSTVNfV0lORE9XX1RJTUVfREVOT01JTkFUT1IgPSBHYWluQW5hbHlzaXMuUk1TX1dJTkRPV19USU1FX0RFTk9NSU5BVE9SO1xuICAgIC8qKlxuICAgICAqIG1heC4gU2FtcGxlcyBwZXIgVGltZSBzbGljZVxuICAgICAqL1xuICAgIHZhciBNQVhfU0FNUExFU19QRVJfV0lORE9XID0gR2FpbkFuYWx5c2lzLk1BWF9TQU1QTEVTX1BFUl9XSU5ET1c7XG5cblxuICAgIHZhciBBQll1bGUgPSBbXG4gICAgICAgIFswLjAzODU3NTk5NDM1MjAwLCAtMy44NDY2NDYxNzExODA2NywgLTAuMDIxNjAzNjcxODQxODUsXG4gICAgICAgICAgICA3LjgxNTAxNjUzMDA1NTM4LCAtMC4wMDEyMzM5NTMxNjg1MSwgLTExLjM0MTcwMzU1MTMyMDQyLFxuICAgICAgICAgICAgLTAuMDAwMDkyOTE2Nzc5NTksIDEzLjA1NTA0MjE5MzI3NTQ1LCAtMC4wMTY1NTI2MDM0MTYxOSxcbiAgICAgICAgICAgIC0xMi4yODc1OTg5NTE0NTI5NCwgMC4wMjE2MTUyNjg0MzI3NCwgOS40ODI5MzgwNjMxOTc5MCxcbiAgICAgICAgICAgIC0wLjAyMDc0MDQ1MjE1Mjg1LCAtNS44NzI1Nzg2MTc3NTk5OSwgMC4wMDU5NDI5ODA2NTEyNSxcbiAgICAgICAgICAgIDIuNzU0NjU4NjE4NzQ2MTMsIDAuMDAzMDY0MjgwMjMxOTEsIC0wLjg2OTg0Mzc2NTkzNTUxLFxuICAgICAgICAgICAgMC4wMDAxMjAyNTMyMjAyNywgMC4xMzkxOTMxNDU2NzQzMiwgMC4wMDI4ODQ2MzY4MzkxNl0sXG4gICAgICAgIFswLjA1NDE4NjU2NDA2NDMwLCAtMy40Nzg0NTk0ODU1MDA3MSwgLTAuMDI5MTEwMDc4MDg5NDgsXG4gICAgICAgICAgICA2LjM2MzE3Nzc3NTY2MTQ4LCAtMC4wMDg0ODcwOTM3OTg1MSwgLTguNTQ3NTE1Mjc0NzE4NzQsXG4gICAgICAgICAgICAtMC4wMDg1MTE2NTY0NTQ2OSwgOS40NzY5MzYwNzgwMTI4MCwgLTAuMDA4MzQ5OTA5MDQ5MzYsXG4gICAgICAgICAgICAtOC44MTQ5ODY4MTM3MDE1NSwgMC4wMjI0NTI5MzI1MzMzOSwgNi44NTQwMTU0MDkzNjk5OCxcbiAgICAgICAgICAgIC0wLjAyNTk2MzM4NTEyOTE1LCAtNC4zOTQ3MDk5NjA3OTU1OSwgMC4wMTYyNDg2NDk2Mjk3NSxcbiAgICAgICAgICAgIDIuMTk2MTE2ODQ4OTA3NzQsIC0wLjAwMjQwODc5MDUxNTg0LCAtMC43NTEwNDMwMjQ1MTQzMixcbiAgICAgICAgICAgIDAuMDA2NzQ2MTM2ODIyNDcsIDAuMTMxNDkzMTc5NTg4MDgsIC0wLjAwMTg3NzYzNzc3MzYyXSxcbiAgICAgICAgWzAuMTU0NTcyOTk2ODE5MjQsIC0yLjM3ODk4ODM0OTczMDg0LCAtMC4wOTMzMTA0OTA1NjMxNSxcbiAgICAgICAgICAgIDIuODQ4NjgxNTExNTYzMjcsIC0wLjA2MjQ3ODgwMTUzNjUzLCAtMi42NDU3NzE3MDIyOTgyNSxcbiAgICAgICAgICAgIDAuMDIxNjM1NDE4ODg3OTgsIDIuMjM2OTc2NTc0NTE3MTMsIC0wLjA1NTg4MzkzMzI5ODU2LFxuICAgICAgICAgICAgLTEuNjcxNDgxNTMzNjc2MDIsIDAuMDQ3ODE0NzY2NzQ5MjEsIDEuMDA1OTU5NTQ4MDg1NDcsXG4gICAgICAgICAgICAwLjAwMjIyMzEyNTk3NzQzLCAtMC40NTk1MzQ1ODA1NDk4MywgMC4wMzE3NDA5MjU0MDA0OSxcbiAgICAgICAgICAgIDAuMTYzNzgxNjQ4NTg1OTYsIC0wLjAxMzkwNTg5NDIxODk4LCAtMC4wNTAzMjA3NzcxNzEzMSxcbiAgICAgICAgICAgIDAuMDA2NTE0MjA2Njc4MzEsIDAuMDIzNDc4OTc0MDcwMjAsIC0wLjAwODgxMzYyNzMzODM5XSxcbiAgICAgICAgWzAuMzAyOTY5MDczMTkzMjcsIC0xLjYxMjczMTY1MTM3MjQ3LCAtMC4yMjYxMzk4ODY4MjEyMyxcbiAgICAgICAgICAgIDEuMDc5Nzc0OTIyNTk5NzAsIC0wLjA4NTg3MzIzNzMwNzcyLCAtMC4yNTY1NjI1Nzc1NDA3MCxcbiAgICAgICAgICAgIDAuMDMyODI5MzAxNzI2NjQsIC0wLjE2Mjc2NzE5MTIwNDQwLCAtMC4wMDkxNTcwMjkzMzQzNCxcbiAgICAgICAgICAgIC0wLjIyNjM4ODkzNzczOTA2LCAtMC4wMjM2NDE0MTIwMjUyMiwgMC4zOTEyMDgwMDc4ODI4NCxcbiAgICAgICAgICAgIC0wLjAwNTg0NDU2MDM5OTEzLCAtMC4yMjEzODEzODk1NDkyNSwgMC4wNjI3NjEwMTMyMTc0OSxcbiAgICAgICAgICAgIDAuMDQ1MDAyMzUzODczNTIsIC0wLjAwMDAwODI4MDg2NzQ4LCAwLjAyMDA1ODUxODA2NTAxLFxuICAgICAgICAgICAgMC4wMDIwNTg2MTg4NTU2NCwgMC4wMDMwMjQzOTA5NTc0MSwgLTAuMDI5NTAxMzQ5ODMyODddLFxuICAgICAgICBbMC4zMzY0MjMwNDg1NjEzMiwgLTEuNDk4NTg5NzkzNjc3OTksIC0wLjI1NTcyMjQxNDI1NTcwLFxuICAgICAgICAgICAgMC44NzM1MDI3MTQxODE4OCwgLTAuMTE4Mjg1NzAxNzc1NTUsIDAuMTIyMDUwMjIzMDgwODQsXG4gICAgICAgICAgICAwLjExOTIxMTQ4Njc1MjAzLCAtMC44MDc3NDk0NDY3MTQzOCwgLTAuMDc4MzQ0ODk2MDk0NzksXG4gICAgICAgICAgICAwLjQ3ODU0Nzk0NTYyMzI2LCAtMC4wMDQ2OTk3NzkxNDM4MCwgLTAuMTI0NTM0NTgxNDAwMTksXG4gICAgICAgICAgICAtMC4wMDU4OTUwMDIyNDQ0MCwgLTAuMDQwNjc1MTAxOTcwMTQsIDAuMDU3MjQyMjgxNDAzNTEsXG4gICAgICAgICAgICAwLjA4MzMzNzU1Mjg0MTA3LCAwLjAwODMyMDQzOTgwNzczLCAtMC4wNDIzNzM0ODAyNTc0NixcbiAgICAgICAgICAgIC0wLjAxNjM1MzgxMzg0NTQwLCAwLjAyOTc3MjA3MzE5OTI1LCAtMC4wMTc2MDE3NjU2ODE1MF0sXG4gICAgICAgIFswLjQ0OTE1MjU2NjA4NDUwLCAtMC42MjgyMDYxOTIzMzY3MSwgLTAuMTQzNTE3NTc0NjQ1NDcsXG4gICAgICAgICAgICAwLjI5NjYxNzgzNzA2MzY2LCAtMC4yMjc4NDM5NDQyOTc0OSwgLTAuMzcyNTYzNzI5NDI0MDAsXG4gICAgICAgICAgICAtMC4wMTQxOTE0MDEwMDU1MSwgMC4wMDIxMzc2Nzg1NzEyNCwgMC4wNDA3ODI2Mjc5NzEzOSxcbiAgICAgICAgICAgIC0wLjQyMDI5ODIwMTcwOTE4LCAtMC4xMjM5ODE2MzM4MTc0OCwgMC4yMjE5OTY1MDU2NDgyNCxcbiAgICAgICAgICAgIDAuMDQwOTc1NjUxMzU2NDgsIDAuMDA2MTM0MjQzNTA2ODIsIDAuMTA0Nzg1MDM2MDAyNTEsXG4gICAgICAgICAgICAwLjA2NzQ3NjIwNzQ0NjgzLCAtMC4wMTg2Mzg4NzgxMDkyNywgMC4wNTc4NDgyMDM3NTgwMSxcbiAgICAgICAgICAgIC0wLjAzMTkzNDI4NDM4OTE1LCAwLjAzMjIyNzU0MDcyMTczLCAwLjAwNTQxOTA3NzQ4NzA3XSxcbiAgICAgICAgWzAuNTY2MTk0NzA3NTc2NDEsIC0xLjA0ODAwMzM1MTI2MzQ5LCAtMC43NTQ2NDQ1NjkzOTMwMixcbiAgICAgICAgICAgIDAuMjkxNTYzMTE5NzEyNDksIDAuMTYyNDIxMzc3NDIyMzAsIC0wLjI2ODA2MDAxMDQyOTQ3LFxuICAgICAgICAgICAgMC4xNjc0NDI0MzQ5MzY3MiwgMC4wMDgxOTk5OTY0NTg1OCwgLTAuMTg5MDE2MDQxOTk2MDksXG4gICAgICAgICAgICAwLjQ1MDU0NzM0NTA1MDA4LCAwLjMwOTMxNzgyODQxODMwLCAtMC4zMzAzMjQwMzMxNDAwNixcbiAgICAgICAgICAgIC0wLjI3NTYyOTYxOTg2MjI0LCAwLjA2NzM5MzY4MzMzMTEwLCAwLjAwNjQ3MzEwNjc3MjQ2LFxuICAgICAgICAgICAgLTAuMDQ3ODQyNTQyMjkwMzMsIDAuMDg2NDc1MDM3ODAzNTEsIDAuMDE2Mzk5MDc4MzYxODksXG4gICAgICAgICAgICAtMC4wMzc4ODk4NDU1NDg0MCwgMC4wMTgwNzM2NDMyMzU3MywgLTAuMDA1ODgyMTU0NDM0MjFdLFxuICAgICAgICBbMC41ODEwMDQ5NDk2MDU1MywgLTAuNTEwMzUzMjcwOTUxODQsIC0wLjUzMTc0OTA5MDU4NTc4LFxuICAgICAgICAgICAgLTAuMzE4NjM1NjMzMjUyNDUsIC0wLjE0Mjg5Nzk5MDM0MjUzLCAtMC4yMDI1NjQxMzQ4NDQ3NyxcbiAgICAgICAgICAgIDAuMTc1MjA3MDQ4MzU1MjIsIDAuMTQ3MjgxNTQxMzQzMzAsIDAuMDIzNzc5NDUyMTc2MTUsXG4gICAgICAgICAgICAwLjM4OTUyNjM5OTc4OTk5LCAwLjE1NTU4NDQ5MTM1NTczLCAtMC4yMzMxMzI3MTg4MDg2OCxcbiAgICAgICAgICAgIC0wLjI1MzQ0NzkwMDU5MzUzLCAtMC4wNTI0NjAxOTAyNDQ2MywgMC4wMTYyODQ2MjQwNjMzMyxcbiAgICAgICAgICAgIC0wLjAyNTA1OTYxNzI0MDUzLCAwLjA2OTIwNDY3NzYzOTU5LCAwLjAyNDQyMzU3MzE2MDk5LFxuICAgICAgICAgICAgLTAuMDM3MjE2MTEzOTU4MDEsIDAuMDE4MTg4MDExMTE1MDMsIC0wLjAwNzQ5NjE4Nzk3MTcyXSxcbiAgICAgICAgWzAuNTM2NDg3ODkyNTUxMDUsIC0wLjI1MDQ5ODcxOTU2MDIwLCAtMC40MjE2MzAzNDM1MDY5NixcbiAgICAgICAgICAgIC0wLjQzMTkzOTQyMzExMTE0LCAtMC4wMDI3NTk1MzYxMTkyOSwgLTAuMDM0MjQ2ODEwMTc2NzUsXG4gICAgICAgICAgICAwLjA0MjY3ODQyMjE5NDE1LCAtMC4wNDY3ODMyODc4NDI0MiwgLTAuMTAyMTQ4NjQxNzk2NzYsXG4gICAgICAgICAgICAwLjI2NDA4MzAwMjAwOTU1LCAwLjE0NTkwNzcyMjg5Mzg4LCAwLjE1MTEzMTMwNTMzMjE2LFxuICAgICAgICAgICAgLTAuMDI0NTk4NjQ4NTkzNDUsIC0wLjE3NTU2NDkzMzY2NDQ5LCAtMC4xMTIwMjMxNTE5NTM4OCxcbiAgICAgICAgICAgIC0wLjE4ODIzMDA5MjYyMTE1LCAtMC4wNDA2MDAzNDEyNzAwMCwgMC4wNTQ3NzcyMDQyODY3NCxcbiAgICAgICAgICAgIDAuMDQ3ODg2NjU1NDgxODAsIDAuMDQ3MDQ0MDk2ODgxMjAsIC0wLjAyMjE3OTM2ODAxMTM0XV07XG5cbiAgICB2YXIgQUJCdXR0ZXIgPSBbXG4gICAgICAgIFswLjk4NjIxMTkyNDYyNzA4LCAtMS45NzIyMzM3MjkxOTUyNywgLTEuOTcyNDIzODQ5MjU0MTYsXG4gICAgICAgICAgICAwLjk3MjYxMzk2OTMxMzA2LCAwLjk4NjIxMTkyNDYyNzA4XSxcbiAgICAgICAgWzAuOTg1MDAxNzU3ODcyNDIsIC0xLjk2OTc3ODU1NTgyNjE4LCAtMS45NzAwMDM1MTU3NDQ4NCxcbiAgICAgICAgICAgIDAuOTcwMjI4NDc1NjYzNTAsIDAuOTg1MDAxNzU3ODcyNDJdLFxuICAgICAgICBbMC45NzkzODkzMjczNTIxNCwgLTEuOTU4MzUzODA5NzUzOTgsIC0xLjk1ODc3ODY1NDcwNDI4LFxuICAgICAgICAgICAgMC45NTkyMDM0OTk2NTQ1OSwgMC45NzkzODkzMjczNTIxNF0sXG4gICAgICAgIFswLjk3NTMxODQzMjA0OTI4LCAtMS45NTAwMjc1OTE0OTg3OCwgLTEuOTUwNjM2ODY0MDk4NTcsXG4gICAgICAgICAgICAwLjk1MTI0NjEzNjY5ODM1LCAwLjk3NTMxODQzMjA0OTI4XSxcbiAgICAgICAgWzAuOTczMTY1MjM0OTgxNjEsIC0xLjk0NTYxMDIzNTY2NTI3LCAtMS45NDYzMzA0Njk5NjMyMyxcbiAgICAgICAgICAgIDAuOTQ3MDUwNzA0MjYxMTgsIDAuOTczMTY1MjM0OTgxNjFdLFxuICAgICAgICBbMC45NjQ1NDUxNTU1MjgyNiwgLTEuOTI3ODMyODY5NzcwMzYsIC0xLjkyOTA5MDMxMTA1NjUyLFxuICAgICAgICAgICAgMC45MzAzNDc3NTIzNDI2OCwgMC45NjQ1NDUxNTU1MjgyNl0sXG4gICAgICAgIFswLjk2MDA5MTQyOTUwNTQxLCAtMS45MTg1ODk1MzAzMzc4NCwgLTEuOTIwMTgyODU5MDEwODIsXG4gICAgICAgICAgICAwLjkyMTc3NjE4NzY4MzgxLCAwLjk2MDA5MTQyOTUwNTQxXSxcbiAgICAgICAgWzAuOTU4NTY5MTY1OTk2MDEsIC0xLjkxNTQyMTA4MDc0NzgwLCAtMS45MTcxMzgzMzE5OTIwMyxcbiAgICAgICAgICAgIDAuOTE4ODU1NTgzMjM2MjUsIDAuOTU4NTY5MTY1OTk2MDFdLFxuICAgICAgICBbMC45NDU5NzY4NTYwMDI3OSwgLTEuODg5MDMzMDc5Mzk0NTIsIC0xLjg5MTk1MzcxMjAwNTU4LFxuICAgICAgICAgICAgMC44OTQ4NzQzNDQ2MTY2NCwgMC45NDU5NzY4NTYwMDI3OV1dO1xuXG5cbiAgICAvKipcbiAgICAgKiBXaGVuIGNhbGxpbmcgdGhpcyBwcm9jZWR1cmUsIG1ha2Ugc3VyZSB0aGF0IGlwWy1vcmRlcl0gYW5kIG9wWy1vcmRlcl1cbiAgICAgKiBwb2ludCB0byByZWFsIGRhdGFcbiAgICAgKi9cbiAgICAvL3ByaXZhdGUgdm9pZCBmaWx0ZXJZdWxlKGZpbmFsIGZsb2F0W10gaW5wdXQsIGludCBpbnB1dFBvcywgZmxvYXRbXSBvdXRwdXQsXG4gICAgLy9pbnQgb3V0cHV0UG9zLCBpbnQgblNhbXBsZXMsIGZpbmFsIGZsb2F0W10ga2VybmVsKSB7XG4gICAgZnVuY3Rpb24gZmlsdGVyWXVsZShpbnB1dCwgaW5wdXRQb3MsIG91dHB1dCwgb3V0cHV0UG9zLCBuU2FtcGxlcywga2VybmVsKSB7XG5cbiAgICAgICAgd2hpbGUgKChuU2FtcGxlcy0tKSAhPSAwKSB7XG4gICAgICAgICAgICAvKiAxZS0xMCBpcyBhIGhhY2sgdG8gYXZvaWQgc2xvd2Rvd24gYmVjYXVzZSBvZiBkZW5vcm1hbHMgKi9cbiAgICAgICAgICAgIG91dHB1dFtvdXRwdXRQb3NdID0gMWUtMTAgKyBpbnB1dFtpbnB1dFBvcyArIDBdICoga2VybmVsWzBdXG4gICAgICAgICAgICAgICAgLSBvdXRwdXRbb3V0cHV0UG9zIC0gMV0gKiBrZXJuZWxbMV0gKyBpbnB1dFtpbnB1dFBvcyAtIDFdXG4gICAgICAgICAgICAgICAgKiBrZXJuZWxbMl0gLSBvdXRwdXRbb3V0cHV0UG9zIC0gMl0gKiBrZXJuZWxbM11cbiAgICAgICAgICAgICAgICArIGlucHV0W2lucHV0UG9zIC0gMl0gKiBrZXJuZWxbNF0gLSBvdXRwdXRbb3V0cHV0UG9zIC0gM11cbiAgICAgICAgICAgICAgICAqIGtlcm5lbFs1XSArIGlucHV0W2lucHV0UG9zIC0gM10gKiBrZXJuZWxbNl1cbiAgICAgICAgICAgICAgICAtIG91dHB1dFtvdXRwdXRQb3MgLSA0XSAqIGtlcm5lbFs3XSArIGlucHV0W2lucHV0UG9zIC0gNF1cbiAgICAgICAgICAgICAgICAqIGtlcm5lbFs4XSAtIG91dHB1dFtvdXRwdXRQb3MgLSA1XSAqIGtlcm5lbFs5XVxuICAgICAgICAgICAgICAgICsgaW5wdXRbaW5wdXRQb3MgLSA1XSAqIGtlcm5lbFsxMF0gLSBvdXRwdXRbb3V0cHV0UG9zIC0gNl1cbiAgICAgICAgICAgICAgICAqIGtlcm5lbFsxMV0gKyBpbnB1dFtpbnB1dFBvcyAtIDZdICoga2VybmVsWzEyXVxuICAgICAgICAgICAgICAgIC0gb3V0cHV0W291dHB1dFBvcyAtIDddICoga2VybmVsWzEzXSArIGlucHV0W2lucHV0UG9zIC0gN11cbiAgICAgICAgICAgICAgICAqIGtlcm5lbFsxNF0gLSBvdXRwdXRbb3V0cHV0UG9zIC0gOF0gKiBrZXJuZWxbMTVdXG4gICAgICAgICAgICAgICAgKyBpbnB1dFtpbnB1dFBvcyAtIDhdICoga2VybmVsWzE2XSAtIG91dHB1dFtvdXRwdXRQb3MgLSA5XVxuICAgICAgICAgICAgICAgICoga2VybmVsWzE3XSArIGlucHV0W2lucHV0UG9zIC0gOV0gKiBrZXJuZWxbMThdXG4gICAgICAgICAgICAgICAgLSBvdXRwdXRbb3V0cHV0UG9zIC0gMTBdICoga2VybmVsWzE5XVxuICAgICAgICAgICAgICAgICsgaW5wdXRbaW5wdXRQb3MgLSAxMF0gKiBrZXJuZWxbMjBdO1xuICAgICAgICAgICAgKytvdXRwdXRQb3M7XG4gICAgICAgICAgICArK2lucHV0UG9zO1xuICAgICAgICB9XG4gICAgfVxuXG4vL3ByaXZhdGUgdm9pZCBmaWx0ZXJCdXR0ZXIoZmluYWwgZmxvYXRbXSBpbnB1dCwgaW50IGlucHV0UG9zLFxuLy8gICAgZmxvYXRbXSBvdXRwdXQsIGludCBvdXRwdXRQb3MsIGludCBuU2FtcGxlcywgZmluYWwgZmxvYXRbXSBrZXJuZWwpIHtcbiAgICBmdW5jdGlvbiBmaWx0ZXJCdXR0ZXIoaW5wdXQsIGlucHV0UG9zLCBvdXRwdXQsIG91dHB1dFBvcywgblNhbXBsZXMsIGtlcm5lbCkge1xuXG4gICAgICAgIHdoaWxlICgoblNhbXBsZXMtLSkgIT0gMCkge1xuICAgICAgICAgICAgb3V0cHV0W291dHB1dFBvc10gPSBpbnB1dFtpbnB1dFBvcyArIDBdICoga2VybmVsWzBdXG4gICAgICAgICAgICAgICAgLSBvdXRwdXRbb3V0cHV0UG9zIC0gMV0gKiBrZXJuZWxbMV0gKyBpbnB1dFtpbnB1dFBvcyAtIDFdXG4gICAgICAgICAgICAgICAgKiBrZXJuZWxbMl0gLSBvdXRwdXRbb3V0cHV0UG9zIC0gMl0gKiBrZXJuZWxbM11cbiAgICAgICAgICAgICAgICArIGlucHV0W2lucHV0UG9zIC0gMl0gKiBrZXJuZWxbNF07XG4gICAgICAgICAgICArK291dHB1dFBvcztcbiAgICAgICAgICAgICsraW5wdXRQb3M7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBAcmV0dXJuIElOSVRfR0FJTl9BTkFMWVNJU19PSyBpZiBzdWNjZXNzZnVsLCBJTklUX0dBSU5fQU5BTFlTSVNfRVJST1IgaWZcbiAgICAgKiAgICAgICAgIG5vdFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIFJlc2V0U2FtcGxlRnJlcXVlbmN5KHJnRGF0YSwgc2FtcGxlZnJlcSkge1xuICAgICAgICAvKiB6ZXJvIG91dCBpbml0aWFsIHZhbHVlcyAqL1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IE1BWF9PUkRFUjsgaSsrKVxuICAgICAgICAgICAgcmdEYXRhLmxpbnByZWJ1ZltpXSA9IHJnRGF0YS5sc3RlcGJ1ZltpXSA9IHJnRGF0YS5sb3V0YnVmW2ldID0gcmdEYXRhLnJpbnByZWJ1ZltpXSA9IHJnRGF0YS5yc3RlcGJ1ZltpXSA9IHJnRGF0YS5yb3V0YnVmW2ldID0gMC47XG5cbiAgICAgICAgc3dpdGNoICgwIHwgKHNhbXBsZWZyZXEpKSB7XG4gICAgICAgICAgICBjYXNlIDQ4MDAwOlxuICAgICAgICAgICAgICAgIHJnRGF0YS5yZXFpbmRleCA9IDA7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDQ0MTAwOlxuICAgICAgICAgICAgICAgIHJnRGF0YS5yZXFpbmRleCA9IDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDMyMDAwOlxuICAgICAgICAgICAgICAgIHJnRGF0YS5yZXFpbmRleCA9IDI7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDI0MDAwOlxuICAgICAgICAgICAgICAgIHJnRGF0YS5yZXFpbmRleCA9IDM7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDIyMDUwOlxuICAgICAgICAgICAgICAgIHJnRGF0YS5yZXFpbmRleCA9IDQ7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDE2MDAwOlxuICAgICAgICAgICAgICAgIHJnRGF0YS5yZXFpbmRleCA9IDU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDEyMDAwOlxuICAgICAgICAgICAgICAgIHJnRGF0YS5yZXFpbmRleCA9IDY7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDExMDI1OlxuICAgICAgICAgICAgICAgIHJnRGF0YS5yZXFpbmRleCA9IDc7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDgwMDA6XG4gICAgICAgICAgICAgICAgcmdEYXRhLnJlcWluZGV4ID0gODtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmV0dXJuIElOSVRfR0FJTl9BTkFMWVNJU19FUlJPUjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJnRGF0YS5zYW1wbGVXaW5kb3cgPSAwIHwgKChzYW1wbGVmcmVxICogUk1TX1dJTkRPV19USU1FX05VTUVSQVRPUlxuICAgICAgICAgICAgKyBSTVNfV0lORE9XX1RJTUVfREVOT01JTkFUT1IgLSAxKSAvIFJNU19XSU5ET1dfVElNRV9ERU5PTUlOQVRPUik7XG5cbiAgICAgICAgcmdEYXRhLmxzdW0gPSAwLjtcbiAgICAgICAgcmdEYXRhLnJzdW0gPSAwLjtcbiAgICAgICAgcmdEYXRhLnRvdHNhbXAgPSAwO1xuXG4gICAgICAgIEFycmF5cy5pbGwocmdEYXRhLkEsIDApO1xuXG4gICAgICAgIHJldHVybiBJTklUX0dBSU5fQU5BTFlTSVNfT0s7XG4gICAgfVxuXG4gICAgdGhpcy5Jbml0R2FpbkFuYWx5c2lzID0gZnVuY3Rpb24gKHJnRGF0YSwgc2FtcGxlZnJlcSkge1xuICAgICAgICBpZiAoUmVzZXRTYW1wbGVGcmVxdWVuY3kocmdEYXRhLCBzYW1wbGVmcmVxKSAhPSBJTklUX0dBSU5fQU5BTFlTSVNfT0spIHtcbiAgICAgICAgICAgIHJldHVybiBJTklUX0dBSU5fQU5BTFlTSVNfRVJST1I7XG4gICAgICAgIH1cblxuICAgICAgICByZ0RhdGEubGlucHJlID0gTUFYX09SREVSO1xuICAgICAgICByZ0RhdGEucmlucHJlID0gTUFYX09SREVSO1xuICAgICAgICByZ0RhdGEubHN0ZXAgPSBNQVhfT1JERVI7XG4gICAgICAgIHJnRGF0YS5yc3RlcCA9IE1BWF9PUkRFUjtcbiAgICAgICAgcmdEYXRhLmxvdXQgPSBNQVhfT1JERVI7XG4gICAgICAgIHJnRGF0YS5yb3V0ID0gTUFYX09SREVSO1xuXG4gICAgICAgIEFycmF5cy5maWxsKHJnRGF0YS5CLCAwKTtcblxuICAgICAgICByZXR1cm4gSU5JVF9HQUlOX0FOQUxZU0lTX09LO1xuICAgIH07XG5cbiAgICAvKipcbiAgICAgKiBzcXVhcmVcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmc3FyKGQpIHtcbiAgICAgICAgcmV0dXJuIGQgKiBkO1xuICAgIH1cblxuICAgIHRoaXMuQW5hbHl6ZVNhbXBsZXMgPSBmdW5jdGlvbiAocmdEYXRhLCBsZWZ0X3NhbXBsZXMsIGxlZnRfc2FtcGxlc1BvcywgcmlnaHRfc2FtcGxlcywgcmlnaHRfc2FtcGxlc1BvcywgbnVtX3NhbXBsZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBudW1fY2hhbm5lbHMpIHtcbiAgICAgICAgdmFyIGN1cmxlZnQ7XG4gICAgICAgIHZhciBjdXJsZWZ0QmFzZTtcbiAgICAgICAgdmFyIGN1cnJpZ2h0O1xuICAgICAgICB2YXIgY3VycmlnaHRCYXNlO1xuICAgICAgICB2YXIgYmF0Y2hzYW1wbGVzO1xuICAgICAgICB2YXIgY3Vyc2FtcGxlcztcbiAgICAgICAgdmFyIGN1cnNhbXBsZXBvcztcblxuICAgICAgICBpZiAobnVtX3NhbXBsZXMgPT0gMClcbiAgICAgICAgICAgIHJldHVybiBHQUlOX0FOQUxZU0lTX09LO1xuXG4gICAgICAgIGN1cnNhbXBsZXBvcyA9IDA7XG4gICAgICAgIGJhdGNoc2FtcGxlcyA9IG51bV9zYW1wbGVzO1xuXG4gICAgICAgIHN3aXRjaCAobnVtX2NoYW5uZWxzKSB7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgcmlnaHRfc2FtcGxlcyA9IGxlZnRfc2FtcGxlcztcbiAgICAgICAgICAgICAgICByaWdodF9zYW1wbGVzUG9zID0gbGVmdF9zYW1wbGVzUG9zO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICByZXR1cm4gR0FJTl9BTkFMWVNJU19FUlJPUjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChudW1fc2FtcGxlcyA8IE1BWF9PUkRFUikge1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShsZWZ0X3NhbXBsZXMsIGxlZnRfc2FtcGxlc1BvcywgcmdEYXRhLmxpbnByZWJ1ZixcbiAgICAgICAgICAgICAgICBNQVhfT1JERVIsIG51bV9zYW1wbGVzKTtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkocmlnaHRfc2FtcGxlcywgcmlnaHRfc2FtcGxlc1BvcywgcmdEYXRhLnJpbnByZWJ1ZixcbiAgICAgICAgICAgICAgICBNQVhfT1JERVIsIG51bV9zYW1wbGVzKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkobGVmdF9zYW1wbGVzLCBsZWZ0X3NhbXBsZXNQb3MsIHJnRGF0YS5saW5wcmVidWYsXG4gICAgICAgICAgICAgICAgTUFYX09SREVSLCBNQVhfT1JERVIpO1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShyaWdodF9zYW1wbGVzLCByaWdodF9zYW1wbGVzUG9zLCByZ0RhdGEucmlucHJlYnVmLFxuICAgICAgICAgICAgICAgIE1BWF9PUkRFUiwgTUFYX09SREVSKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHdoaWxlIChiYXRjaHNhbXBsZXMgPiAwKSB7XG4gICAgICAgICAgICBjdXJzYW1wbGVzID0gYmF0Y2hzYW1wbGVzID4gcmdEYXRhLnNhbXBsZVdpbmRvdyAtIHJnRGF0YS50b3RzYW1wID8gcmdEYXRhLnNhbXBsZVdpbmRvd1xuICAgICAgICAgICAgLSByZ0RhdGEudG90c2FtcFxuICAgICAgICAgICAgICAgIDogYmF0Y2hzYW1wbGVzO1xuICAgICAgICAgICAgaWYgKGN1cnNhbXBsZXBvcyA8IE1BWF9PUkRFUikge1xuICAgICAgICAgICAgICAgIGN1cmxlZnQgPSByZ0RhdGEubGlucHJlICsgY3Vyc2FtcGxlcG9zO1xuICAgICAgICAgICAgICAgIGN1cmxlZnRCYXNlID0gcmdEYXRhLmxpbnByZWJ1ZjtcbiAgICAgICAgICAgICAgICBjdXJyaWdodCA9IHJnRGF0YS5yaW5wcmUgKyBjdXJzYW1wbGVwb3M7XG4gICAgICAgICAgICAgICAgY3VycmlnaHRCYXNlID0gcmdEYXRhLnJpbnByZWJ1ZjtcbiAgICAgICAgICAgICAgICBpZiAoY3Vyc2FtcGxlcyA+IE1BWF9PUkRFUiAtIGN1cnNhbXBsZXBvcylcbiAgICAgICAgICAgICAgICAgICAgY3Vyc2FtcGxlcyA9IE1BWF9PUkRFUiAtIGN1cnNhbXBsZXBvcztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY3VybGVmdCA9IGxlZnRfc2FtcGxlc1BvcyArIGN1cnNhbXBsZXBvcztcbiAgICAgICAgICAgICAgICBjdXJsZWZ0QmFzZSA9IGxlZnRfc2FtcGxlcztcbiAgICAgICAgICAgICAgICBjdXJyaWdodCA9IHJpZ2h0X3NhbXBsZXNQb3MgKyBjdXJzYW1wbGVwb3M7XG4gICAgICAgICAgICAgICAgY3VycmlnaHRCYXNlID0gcmlnaHRfc2FtcGxlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZmlsdGVyWXVsZShjdXJsZWZ0QmFzZSwgY3VybGVmdCwgcmdEYXRhLmxzdGVwYnVmLCByZ0RhdGEubHN0ZXBcbiAgICAgICAgICAgICAgICArIHJnRGF0YS50b3RzYW1wLCBjdXJzYW1wbGVzLCBBQll1bGVbcmdEYXRhLnJlcWluZGV4XSk7XG4gICAgICAgICAgICBmaWx0ZXJZdWxlKGN1cnJpZ2h0QmFzZSwgY3VycmlnaHQsIHJnRGF0YS5yc3RlcGJ1ZiwgcmdEYXRhLnJzdGVwXG4gICAgICAgICAgICAgICAgKyByZ0RhdGEudG90c2FtcCwgY3Vyc2FtcGxlcywgQUJZdWxlW3JnRGF0YS5yZXFpbmRleF0pO1xuXG4gICAgICAgICAgICBmaWx0ZXJCdXR0ZXIocmdEYXRhLmxzdGVwYnVmLCByZ0RhdGEubHN0ZXAgKyByZ0RhdGEudG90c2FtcCxcbiAgICAgICAgICAgICAgICByZ0RhdGEubG91dGJ1ZiwgcmdEYXRhLmxvdXQgKyByZ0RhdGEudG90c2FtcCwgY3Vyc2FtcGxlcyxcbiAgICAgICAgICAgICAgICBBQkJ1dHRlcltyZ0RhdGEucmVxaW5kZXhdKTtcbiAgICAgICAgICAgIGZpbHRlckJ1dHRlcihyZ0RhdGEucnN0ZXBidWYsIHJnRGF0YS5yc3RlcCArIHJnRGF0YS50b3RzYW1wLFxuICAgICAgICAgICAgICAgIHJnRGF0YS5yb3V0YnVmLCByZ0RhdGEucm91dCArIHJnRGF0YS50b3RzYW1wLCBjdXJzYW1wbGVzLFxuICAgICAgICAgICAgICAgIEFCQnV0dGVyW3JnRGF0YS5yZXFpbmRleF0pO1xuXG4gICAgICAgICAgICBjdXJsZWZ0ID0gcmdEYXRhLmxvdXQgKyByZ0RhdGEudG90c2FtcDtcbiAgICAgICAgICAgIC8qIEdldCB0aGUgc3F1YXJlZCB2YWx1ZXMgKi9cbiAgICAgICAgICAgIGN1cmxlZnRCYXNlID0gcmdEYXRhLmxvdXRidWY7XG4gICAgICAgICAgICBjdXJyaWdodCA9IHJnRGF0YS5yb3V0ICsgcmdEYXRhLnRvdHNhbXA7XG4gICAgICAgICAgICBjdXJyaWdodEJhc2UgPSByZ0RhdGEucm91dGJ1ZjtcblxuICAgICAgICAgICAgdmFyIGkgPSBjdXJzYW1wbGVzICUgODtcbiAgICAgICAgICAgIHdoaWxlICgoaS0tKSAhPSAwKSB7XG4gICAgICAgICAgICAgICAgcmdEYXRhLmxzdW0gKz0gZnNxcihjdXJsZWZ0QmFzZVtjdXJsZWZ0KytdKTtcbiAgICAgICAgICAgICAgICByZ0RhdGEucnN1bSArPSBmc3FyKGN1cnJpZ2h0QmFzZVtjdXJyaWdodCsrXSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpID0gY3Vyc2FtcGxlcyAvIDg7XG4gICAgICAgICAgICB3aGlsZSAoKGktLSkgIT0gMCkge1xuICAgICAgICAgICAgICAgIHJnRGF0YS5sc3VtICs9IGZzcXIoY3VybGVmdEJhc2VbY3VybGVmdCArIDBdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VybGVmdEJhc2VbY3VybGVmdCArIDFdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VybGVmdEJhc2VbY3VybGVmdCArIDJdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VybGVmdEJhc2VbY3VybGVmdCArIDNdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VybGVmdEJhc2VbY3VybGVmdCArIDRdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VybGVmdEJhc2VbY3VybGVmdCArIDVdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VybGVmdEJhc2VbY3VybGVmdCArIDZdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VybGVmdEJhc2VbY3VybGVmdCArIDddKTtcbiAgICAgICAgICAgICAgICBjdXJsZWZ0ICs9IDg7XG4gICAgICAgICAgICAgICAgcmdEYXRhLnJzdW0gKz0gZnNxcihjdXJyaWdodEJhc2VbY3VycmlnaHQgKyAwXSlcbiAgICAgICAgICAgICAgICAgICAgKyBmc3FyKGN1cnJpZ2h0QmFzZVtjdXJyaWdodCArIDFdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VycmlnaHRCYXNlW2N1cnJpZ2h0ICsgMl0pXG4gICAgICAgICAgICAgICAgICAgICsgZnNxcihjdXJyaWdodEJhc2VbY3VycmlnaHQgKyAzXSlcbiAgICAgICAgICAgICAgICAgICAgKyBmc3FyKGN1cnJpZ2h0QmFzZVtjdXJyaWdodCArIDRdKVxuICAgICAgICAgICAgICAgICAgICArIGZzcXIoY3VycmlnaHRCYXNlW2N1cnJpZ2h0ICsgNV0pXG4gICAgICAgICAgICAgICAgICAgICsgZnNxcihjdXJyaWdodEJhc2VbY3VycmlnaHQgKyA2XSlcbiAgICAgICAgICAgICAgICAgICAgKyBmc3FyKGN1cnJpZ2h0QmFzZVtjdXJyaWdodCArIDddKTtcbiAgICAgICAgICAgICAgICBjdXJyaWdodCArPSA4O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBiYXRjaHNhbXBsZXMgLT0gY3Vyc2FtcGxlcztcbiAgICAgICAgICAgIGN1cnNhbXBsZXBvcyArPSBjdXJzYW1wbGVzO1xuICAgICAgICAgICAgcmdEYXRhLnRvdHNhbXAgKz0gY3Vyc2FtcGxlcztcbiAgICAgICAgICAgIGlmIChyZ0RhdGEudG90c2FtcCA9PSByZ0RhdGEuc2FtcGxlV2luZG93KSB7XG4gICAgICAgICAgICAgICAgLyogR2V0IHRoZSBSb290IE1lYW4gU3F1YXJlIChSTVMpIGZvciB0aGlzIHNldCBvZiBzYW1wbGVzICovXG4gICAgICAgICAgICAgICAgdmFyIHZhbCA9IEdhaW5BbmFseXNpcy5TVEVQU19wZXJfZEJcbiAgICAgICAgICAgICAgICAgICAgKiAxMC5cbiAgICAgICAgICAgICAgICAgICAgKiBNYXRoLmxvZzEwKChyZ0RhdGEubHN1bSArIHJnRGF0YS5yc3VtKVxuICAgICAgICAgICAgICAgICAgICAgICAgLyByZ0RhdGEudG90c2FtcCAqIDAuNSArIDEuZS0zNyk7XG4gICAgICAgICAgICAgICAgdmFyIGl2YWwgPSAodmFsIDw9IDApID8gMCA6IDAgfCB2YWw7XG4gICAgICAgICAgICAgICAgaWYgKGl2YWwgPj0gcmdEYXRhLkEubGVuZ3RoKVxuICAgICAgICAgICAgICAgICAgICBpdmFsID0gcmdEYXRhLkEubGVuZ3RoIC0gMTtcbiAgICAgICAgICAgICAgICByZ0RhdGEuQVtpdmFsXSsrO1xuICAgICAgICAgICAgICAgIHJnRGF0YS5sc3VtID0gcmdEYXRhLnJzdW0gPSAwLjtcblxuICAgICAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkocmdEYXRhLmxvdXRidWYsIHJnRGF0YS50b3RzYW1wLFxuICAgICAgICAgICAgICAgICAgICByZ0RhdGEubG91dGJ1ZiwgMCwgTUFYX09SREVSKTtcbiAgICAgICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHJnRGF0YS5yb3V0YnVmLCByZ0RhdGEudG90c2FtcCxcbiAgICAgICAgICAgICAgICAgICAgcmdEYXRhLnJvdXRidWYsIDAsIE1BWF9PUkRFUik7XG4gICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShyZ0RhdGEubHN0ZXBidWYsIHJnRGF0YS50b3RzYW1wLFxuICAgICAgICAgICAgICAgICAgICByZ0RhdGEubHN0ZXBidWYsIDAsIE1BWF9PUkRFUik7XG4gICAgICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShyZ0RhdGEucnN0ZXBidWYsIHJnRGF0YS50b3RzYW1wLFxuICAgICAgICAgICAgICAgICAgICByZ0RhdGEucnN0ZXBidWYsIDAsIE1BWF9PUkRFUik7XG4gICAgICAgICAgICAgICAgcmdEYXRhLnRvdHNhbXAgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHJnRGF0YS50b3RzYW1wID4gcmdEYXRhLnNhbXBsZVdpbmRvdykge1xuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICogc29tZWhvdyBJIHJlYWxseSBzY3Jld2VkIHVwOiBFcnJvciBpbiBwcm9ncmFtbWluZyEgQ29udGFjdFxuICAgICAgICAgICAgICAgICAqIGF1dGhvciBhYm91dCB0b3RzYW1wID4gc2FtcGxlV2luZG93XG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgcmV0dXJuIEdBSU5fQU5BTFlTSVNfRVJST1I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG51bV9zYW1wbGVzIDwgTUFYX09SREVSKSB7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KHJnRGF0YS5saW5wcmVidWYsIG51bV9zYW1wbGVzLCByZ0RhdGEubGlucHJlYnVmLFxuICAgICAgICAgICAgICAgIDAsIE1BWF9PUkRFUiAtIG51bV9zYW1wbGVzKTtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkocmdEYXRhLnJpbnByZWJ1ZiwgbnVtX3NhbXBsZXMsIHJnRGF0YS5yaW5wcmVidWYsXG4gICAgICAgICAgICAgICAgMCwgTUFYX09SREVSIC0gbnVtX3NhbXBsZXMpO1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShsZWZ0X3NhbXBsZXMsIGxlZnRfc2FtcGxlc1BvcywgcmdEYXRhLmxpbnByZWJ1ZixcbiAgICAgICAgICAgICAgICBNQVhfT1JERVIgLSBudW1fc2FtcGxlcywgbnVtX3NhbXBsZXMpO1xuICAgICAgICAgICAgU3lzdGVtLmFycmF5Y29weShyaWdodF9zYW1wbGVzLCByaWdodF9zYW1wbGVzUG9zLCByZ0RhdGEucmlucHJlYnVmLFxuICAgICAgICAgICAgICAgIE1BWF9PUkRFUiAtIG51bV9zYW1wbGVzLCBudW1fc2FtcGxlcyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBTeXN0ZW0uYXJyYXljb3B5KGxlZnRfc2FtcGxlcywgbGVmdF9zYW1wbGVzUG9zICsgbnVtX3NhbXBsZXNcbiAgICAgICAgICAgICAgICAtIE1BWF9PUkRFUiwgcmdEYXRhLmxpbnByZWJ1ZiwgMCwgTUFYX09SREVSKTtcbiAgICAgICAgICAgIFN5c3RlbS5hcnJheWNvcHkocmlnaHRfc2FtcGxlcywgcmlnaHRfc2FtcGxlc1BvcyArIG51bV9zYW1wbGVzXG4gICAgICAgICAgICAgICAgLSBNQVhfT1JERVIsIHJnRGF0YS5yaW5wcmVidWYsIDAsIE1BWF9PUkRFUik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gR0FJTl9BTkFMWVNJU19PSztcbiAgICB9O1xuXG4gICAgZnVuY3Rpb24gYW5hbHl6ZVJlc3VsdChBcnJheSwgbGVuKSB7XG4gICAgICAgIHZhciBpO1xuXG4gICAgICAgIHZhciBlbGVtcyA9IDA7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBsZW47IGkrKylcbiAgICAgICAgICAgIGVsZW1zICs9IEFycmF5W2ldO1xuICAgICAgICBpZiAoZWxlbXMgPT0gMClcbiAgICAgICAgICAgIHJldHVybiBHQUlOX05PVF9FTk9VR0hfU0FNUExFUztcblxuICAgICAgICB2YXIgdXBwZXIgPSAwIHwgTWF0aC5jZWlsKGVsZW1zICogKDEuIC0gUk1TX1BFUkNFTlRJTEUpKTtcbiAgICAgICAgZm9yIChpID0gbGVuOyBpLS0gPiAwOykge1xuICAgICAgICAgICAgaWYgKCh1cHBlciAtPSBBcnJheVtpXSkgPD0gMClcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vcmV0dXJuIChmbG9hdCkgKChmbG9hdCkgUElOS19SRUYgLSAoZmxvYXQpIGkgLyAoZmxvYXQpIFNURVBTX3Blcl9kQik7XG4gICAgICAgIHJldHVybiAoUElOS19SRUYgLSBpIC8gR2FpbkFuYWx5c2lzLlNURVBTX3Blcl9kQik7XG4gICAgfVxuXG4gICAgdGhpcy5HZXRUaXRsZUdhaW4gPSBmdW5jdGlvbiAocmdEYXRhKSB7XG4gICAgICAgIHZhciByZXR2YWwgPSBhbmFseXplUmVzdWx0KHJnRGF0YS5BLCByZ0RhdGEuQS5sZW5ndGgpO1xuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgcmdEYXRhLkEubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIHJnRGF0YS5CW2ldICs9IHJnRGF0YS5BW2ldO1xuICAgICAgICAgICAgcmdEYXRhLkFbaV0gPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBNQVhfT1JERVI7IGkrKylcbiAgICAgICAgICAgIHJnRGF0YS5saW5wcmVidWZbaV0gPSByZ0RhdGEubHN0ZXBidWZbaV0gPSByZ0RhdGEubG91dGJ1ZltpXSA9IHJnRGF0YS5yaW5wcmVidWZbaV0gPSByZ0RhdGEucnN0ZXBidWZbaV0gPSByZ0RhdGEucm91dGJ1ZltpXSA9IDAuO1xuXG4gICAgICAgIHJnRGF0YS50b3RzYW1wID0gMDtcbiAgICAgICAgcmdEYXRhLmxzdW0gPSByZ0RhdGEucnN1bSA9IDAuO1xuICAgICAgICByZXR1cm4gcmV0dmFsO1xuICAgIH1cblxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IEdhaW5BbmFseXNpcztcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL19sYW1lanNAMS4yLjFAbGFtZWpzL3NyYy9qcy9HYWluQW5hbHlzaXMuanNcbi8vIG1vZHVsZSBpZCA9IC9OOWFcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:////N9a\n')},"/bQp":function(module,exports){eval("module.exports = {};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL2JRcC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9faXRlcmF0b3JzLmpzP2ZkYjQiXSwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSB7fTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19pdGVyYXRvcnMuanNcbi8vIG1vZHVsZSBpZCA9IC9iUXBcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:////bQp\n")},"/dO2":function(module,__webpack_exports__,__webpack_require__){"use strict";eval("Object.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"MultiDrag\", function() { return MultiDragPlugin; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Sortable\", function() { return Sortable; });\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, \"Swap\", function() { return SwapPlugin; });\n/**!\n * Sortable 1.10.2\n * @author\tRubaXa \n * @author\towenm \n * @license MIT\n */\nfunction _typeof(obj) {\n if (typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\") {\n _typeof = function (obj) {\n return typeof obj;\n };\n } else {\n _typeof = function (obj) {\n return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj;\n };\n }\n\n return _typeof(obj);\n}\n\nfunction _defineProperty(obj, key, value) {\n if (key in obj) {\n Object.defineProperty(obj, key, {\n value: value,\n enumerable: true,\n configurable: true,\n writable: true\n });\n } else {\n obj[key] = value;\n }\n\n return obj;\n}\n\nfunction _extends() {\n _extends = Object.assign || function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n\n return target;\n };\n\n return _extends.apply(this, arguments);\n}\n\nfunction _objectSpread(target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i] != null ? arguments[i] : {};\n var ownKeys = Object.keys(source);\n\n if (typeof Object.getOwnPropertySymbols === 'function') {\n ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) {\n return Object.getOwnPropertyDescriptor(source, sym).enumerable;\n }));\n }\n\n ownKeys.forEach(function (key) {\n _defineProperty(target, key, source[key]);\n });\n }\n\n return target;\n}\n\nfunction _objectWithoutPropertiesLoose(source, excluded) {\n if (source == null) return {};\n var target = {};\n var sourceKeys = Object.keys(source);\n var key, i;\n\n for (i = 0; i < sourceKeys.length; i++) {\n key = sourceKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n target[key] = source[key];\n }\n\n return target;\n}\n\nfunction _objectWithoutProperties(source, excluded) {\n if (source == null) return {};\n\n var target = _objectWithoutPropertiesLoose(source, excluded);\n\n var key, i;\n\n if (Object.getOwnPropertySymbols) {\n var sourceSymbolKeys = Object.getOwnPropertySymbols(source);\n\n for (i = 0; i < sourceSymbolKeys.length; i++) {\n key = sourceSymbolKeys[i];\n if (excluded.indexOf(key) >= 0) continue;\n if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;\n target[key] = source[key];\n }\n }\n\n return target;\n}\n\nfunction _toConsumableArray(arr) {\n return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();\n}\n\nfunction _arrayWithoutHoles(arr) {\n if (Array.isArray(arr)) {\n for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];\n\n return arr2;\n }\n}\n\nfunction _iterableToArray(iter) {\n if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === \"[object Arguments]\") return Array.from(iter);\n}\n\nfunction _nonIterableSpread() {\n throw new TypeError(\"Invalid attempt to spread non-iterable instance\");\n}\n\nvar version = \"1.10.2\";\n\nfunction userAgent(pattern) {\n if (typeof window !== 'undefined' && window.navigator) {\n return !!\n /*@__PURE__*/\n navigator.userAgent.match(pattern);\n }\n}\n\nvar IE11OrLess = userAgent(/(?:Trident.*rv[ :]?11\\.|msie|iemobile|Windows Phone)/i);\nvar Edge = userAgent(/Edge/i);\nvar FireFox = userAgent(/firefox/i);\nvar Safari = userAgent(/safari/i) && !userAgent(/chrome/i) && !userAgent(/android/i);\nvar IOS = userAgent(/iP(ad|od|hone)/i);\nvar ChromeForAndroid = userAgent(/chrome/i) && userAgent(/android/i);\n\nvar captureMode = {\n capture: false,\n passive: false\n};\n\nfunction on(el, event, fn) {\n el.addEventListener(event, fn, !IE11OrLess && captureMode);\n}\n\nfunction off(el, event, fn) {\n el.removeEventListener(event, fn, !IE11OrLess && captureMode);\n}\n\nfunction matches(\n/**HTMLElement*/\nel,\n/**String*/\nselector) {\n if (!selector) return;\n selector[0] === '>' && (selector = selector.substring(1));\n\n if (el) {\n try {\n if (el.matches) {\n return el.matches(selector);\n } else if (el.msMatchesSelector) {\n return el.msMatchesSelector(selector);\n } else if (el.webkitMatchesSelector) {\n return el.webkitMatchesSelector(selector);\n }\n } catch (_) {\n return false;\n }\n }\n\n return false;\n}\n\nfunction getParentOrHost(el) {\n return el.host && el !== document && el.host.nodeType ? el.host : el.parentNode;\n}\n\nfunction closest(\n/**HTMLElement*/\nel,\n/**String*/\nselector,\n/**HTMLElement*/\nctx, includeCTX) {\n if (el) {\n ctx = ctx || document;\n\n do {\n if (selector != null && (selector[0] === '>' ? el.parentNode === ctx && matches(el, selector) : matches(el, selector)) || includeCTX && el === ctx) {\n return el;\n }\n\n if (el === ctx) break;\n /* jshint boss:true */\n } while (el = getParentOrHost(el));\n }\n\n return null;\n}\n\nvar R_SPACE = /\\s+/g;\n\nfunction toggleClass(el, name, state) {\n if (el && name) {\n if (el.classList) {\n el.classList[state ? 'add' : 'remove'](name);\n } else {\n var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');\n el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');\n }\n }\n}\n\nfunction css(el, prop, val) {\n var style = el && el.style;\n\n if (style) {\n if (val === void 0) {\n if (document.defaultView && document.defaultView.getComputedStyle) {\n val = document.defaultView.getComputedStyle(el, '');\n } else if (el.currentStyle) {\n val = el.currentStyle;\n }\n\n return prop === void 0 ? val : val[prop];\n } else {\n if (!(prop in style) && prop.indexOf('webkit') === -1) {\n prop = '-webkit-' + prop;\n }\n\n style[prop] = val + (typeof val === 'string' ? '' : 'px');\n }\n }\n}\n\nfunction matrix(el, selfOnly) {\n var appliedTransforms = '';\n\n if (typeof el === 'string') {\n appliedTransforms = el;\n } else {\n do {\n var transform = css(el, 'transform');\n\n if (transform && transform !== 'none') {\n appliedTransforms = transform + ' ' + appliedTransforms;\n }\n /* jshint boss:true */\n\n } while (!selfOnly && (el = el.parentNode));\n }\n\n var matrixFn = window.DOMMatrix || window.WebKitCSSMatrix || window.CSSMatrix || window.MSCSSMatrix;\n /*jshint -W056 */\n\n return matrixFn && new matrixFn(appliedTransforms);\n}\n\nfunction find(ctx, tagName, iterator) {\n if (ctx) {\n var list = ctx.getElementsByTagName(tagName),\n i = 0,\n n = list.length;\n\n if (iterator) {\n for (; i < n; i++) {\n iterator(list[i], i);\n }\n }\n\n return list;\n }\n\n return [];\n}\n\nfunction getWindowScrollingElement() {\n var scrollingElement = document.scrollingElement;\n\n if (scrollingElement) {\n return scrollingElement;\n } else {\n return document.documentElement;\n }\n}\n/**\r\n * Returns the \"bounding client rect\" of given element\r\n * @param {HTMLElement} el The element whose boundingClientRect is wanted\r\n * @param {[Boolean]} relativeToContainingBlock Whether the rect should be relative to the containing block of (including) the container\r\n * @param {[Boolean]} relativeToNonStaticParent Whether the rect should be relative to the relative parent of (including) the contaienr\r\n * @param {[Boolean]} undoScale Whether the container's scale() should be undone\r\n * @param {[HTMLElement]} container The parent the element will be placed in\r\n * @return {Object} The boundingClientRect of el, with specified adjustments\r\n */\n\n\nfunction getRect(el, relativeToContainingBlock, relativeToNonStaticParent, undoScale, container) {\n if (!el.getBoundingClientRect && el !== window) return;\n var elRect, top, left, bottom, right, height, width;\n\n if (el !== window && el !== getWindowScrollingElement()) {\n elRect = el.getBoundingClientRect();\n top = elRect.top;\n left = elRect.left;\n bottom = elRect.bottom;\n right = elRect.right;\n height = elRect.height;\n width = elRect.width;\n } else {\n top = 0;\n left = 0;\n bottom = window.innerHeight;\n right = window.innerWidth;\n height = window.innerHeight;\n width = window.innerWidth;\n }\n\n if ((relativeToContainingBlock || relativeToNonStaticParent) && el !== window) {\n // Adjust for translate()\n container = container || el.parentNode; // solves #1123 (see: https://stackoverflow.com/a/37953806/6088312)\n // Not needed on <= IE11\n\n if (!IE11OrLess) {\n do {\n if (container && container.getBoundingClientRect && (css(container, 'transform') !== 'none' || relativeToNonStaticParent && css(container, 'position') !== 'static')) {\n var containerRect = container.getBoundingClientRect(); // Set relative to edges of padding box of container\n\n top -= containerRect.top + parseInt(css(container, 'border-top-width'));\n left -= containerRect.left + parseInt(css(container, 'border-left-width'));\n bottom = top + elRect.height;\n right = left + elRect.width;\n break;\n }\n /* jshint boss:true */\n\n } while (container = container.parentNode);\n }\n }\n\n if (undoScale && el !== window) {\n // Adjust for scale()\n var elMatrix = matrix(container || el),\n scaleX = elMatrix && elMatrix.a,\n scaleY = elMatrix && elMatrix.d;\n\n if (elMatrix) {\n top /= scaleY;\n left /= scaleX;\n width /= scaleX;\n height /= scaleY;\n bottom = top + height;\n right = left + width;\n }\n }\n\n return {\n top: top,\n left: left,\n bottom: bottom,\n right: right,\n width: width,\n height: height\n };\n}\n/**\r\n * Checks if a side of an element is scrolled past a side of its parents\r\n * @param {HTMLElement} el The element who's side being scrolled out of view is in question\r\n * @param {String} elSide Side of the element in question ('top', 'left', 'right', 'bottom')\r\n * @param {String} parentSide Side of the parent in question ('top', 'left', 'right', 'bottom')\r\n * @return {HTMLElement} The parent scroll element that the el's side is scrolled past, or null if there is no such element\r\n */\n\n\nfunction isScrolledPast(el, elSide, parentSide) {\n var parent = getParentAutoScrollElement(el, true),\n elSideVal = getRect(el)[elSide];\n /* jshint boss:true */\n\n while (parent) {\n var parentSideVal = getRect(parent)[parentSide],\n visible = void 0;\n\n if (parentSide === 'top' || parentSide === 'left') {\n visible = elSideVal >= parentSideVal;\n } else {\n visible = elSideVal <= parentSideVal;\n }\n\n if (!visible) return parent;\n if (parent === getWindowScrollingElement()) break;\n parent = getParentAutoScrollElement(parent, false);\n }\n\n return false;\n}\n/**\r\n * Gets nth child of el, ignoring hidden children, sortable's elements (does not ignore clone if it's visible)\r\n * and non-draggable elements\r\n * @param {HTMLElement} el The parent element\r\n * @param {Number} childNum The index of the child\r\n * @param {Object} options Parent Sortable's options\r\n * @return {HTMLElement} The child at index childNum, or null if not found\r\n */\n\n\nfunction getChild(el, childNum, options) {\n var currentChild = 0,\n i = 0,\n children = el.children;\n\n while (i < children.length) {\n if (children[i].style.display !== 'none' && children[i] !== Sortable.ghost && children[i] !== Sortable.dragged && closest(children[i], options.draggable, el, false)) {\n if (currentChild === childNum) {\n return children[i];\n }\n\n currentChild++;\n }\n\n i++;\n }\n\n return null;\n}\n/**\r\n * Gets the last child in the el, ignoring ghostEl or invisible elements (clones)\r\n * @param {HTMLElement} el Parent element\r\n * @param {selector} selector Any other elements that should be ignored\r\n * @return {HTMLElement} The last child, ignoring ghostEl\r\n */\n\n\nfunction lastChild(el, selector) {\n var last = el.lastElementChild;\n\n while (last && (last === Sortable.ghost || css(last, 'display') === 'none' || selector && !matches(last, selector))) {\n last = last.previousElementSibling;\n }\n\n return last || null;\n}\n/**\r\n * Returns the index of an element within its parent for a selected set of\r\n * elements\r\n * @param {HTMLElement} el\r\n * @param {selector} selector\r\n * @return {number}\r\n */\n\n\nfunction index(el, selector) {\n var index = 0;\n\n if (!el || !el.parentNode) {\n return -1;\n }\n /* jshint boss:true */\n\n\n while (el = el.previousElementSibling) {\n if (el.nodeName.toUpperCase() !== 'TEMPLATE' && el !== Sortable.clone && (!selector || matches(el, selector))) {\n index++;\n }\n }\n\n return index;\n}\n/**\r\n * Returns the scroll offset of the given element, added with all the scroll offsets of parent elements.\r\n * The value is returned in real pixels.\r\n * @param {HTMLElement} el\r\n * @return {Array} Offsets in the format of [left, top]\r\n */\n\n\nfunction getRelativeScrollOffset(el) {\n var offsetLeft = 0,\n offsetTop = 0,\n winScroller = getWindowScrollingElement();\n\n if (el) {\n do {\n var elMatrix = matrix(el),\n scaleX = elMatrix.a,\n scaleY = elMatrix.d;\n offsetLeft += el.scrollLeft * scaleX;\n offsetTop += el.scrollTop * scaleY;\n } while (el !== winScroller && (el = el.parentNode));\n }\n\n return [offsetLeft, offsetTop];\n}\n/**\r\n * Returns the index of the object within the given array\r\n * @param {Array} arr Array that may or may not hold the object\r\n * @param {Object} obj An object that has a key-value pair unique to and identical to a key-value pair in the object you want to find\r\n * @return {Number} The index of the object in the array, or -1\r\n */\n\n\nfunction indexOfObject(arr, obj) {\n for (var i in arr) {\n if (!arr.hasOwnProperty(i)) continue;\n\n for (var key in obj) {\n if (obj.hasOwnProperty(key) && obj[key] === arr[i][key]) return Number(i);\n }\n }\n\n return -1;\n}\n\nfunction getParentAutoScrollElement(el, includeSelf) {\n // skip to window\n if (!el || !el.getBoundingClientRect) return getWindowScrollingElement();\n var elem = el;\n var gotSelf = false;\n\n do {\n // we don't need to get elem css if it isn't even overflowing in the first place (performance)\n if (elem.clientWidth < elem.scrollWidth || elem.clientHeight < elem.scrollHeight) {\n var elemCSS = css(elem);\n\n if (elem.clientWidth < elem.scrollWidth && (elemCSS.overflowX == 'auto' || elemCSS.overflowX == 'scroll') || elem.clientHeight < elem.scrollHeight && (elemCSS.overflowY == 'auto' || elemCSS.overflowY == 'scroll')) {\n if (!elem.getBoundingClientRect || elem === document.body) return getWindowScrollingElement();\n if (gotSelf || includeSelf) return elem;\n gotSelf = true;\n }\n }\n /* jshint boss:true */\n\n } while (elem = elem.parentNode);\n\n return getWindowScrollingElement();\n}\n\nfunction extend(dst, src) {\n if (dst && src) {\n for (var key in src) {\n if (src.hasOwnProperty(key)) {\n dst[key] = src[key];\n }\n }\n }\n\n return dst;\n}\n\nfunction isRectEqual(rect1, rect2) {\n return Math.round(rect1.top) === Math.round(rect2.top) && Math.round(rect1.left) === Math.round(rect2.left) && Math.round(rect1.height) === Math.round(rect2.height) && Math.round(rect1.width) === Math.round(rect2.width);\n}\n\nvar _throttleTimeout;\n\nfunction throttle(callback, ms) {\n return function () {\n if (!_throttleTimeout) {\n var args = arguments,\n _this = this;\n\n if (args.length === 1) {\n callback.call(_this, args[0]);\n } else {\n callback.apply(_this, args);\n }\n\n _throttleTimeout = setTimeout(function () {\n _throttleTimeout = void 0;\n }, ms);\n }\n };\n}\n\nfunction cancelThrottle() {\n clearTimeout(_throttleTimeout);\n _throttleTimeout = void 0;\n}\n\nfunction scrollBy(el, x, y) {\n el.scrollLeft += x;\n el.scrollTop += y;\n}\n\nfunction clone(el) {\n var Polymer = window.Polymer;\n var $ = window.jQuery || window.Zepto;\n\n if (Polymer && Polymer.dom) {\n return Polymer.dom(el).cloneNode(true);\n } else if ($) {\n return $(el).clone(true)[0];\n } else {\n return el.cloneNode(true);\n }\n}\n\nfunction setRect(el, rect) {\n css(el, 'position', 'absolute');\n css(el, 'top', rect.top);\n css(el, 'left', rect.left);\n css(el, 'width', rect.width);\n css(el, 'height', rect.height);\n}\n\nfunction unsetRect(el) {\n css(el, 'position', '');\n css(el, 'top', '');\n css(el, 'left', '');\n css(el, 'width', '');\n css(el, 'height', '');\n}\n\nvar expando = 'Sortable' + new Date().getTime();\n\nfunction AnimationStateManager() {\n var animationStates = [],\n animationCallbackId;\n return {\n captureAnimationState: function captureAnimationState() {\n animationStates = [];\n if (!this.options.animation) return;\n var children = [].slice.call(this.el.children);\n children.forEach(function (child) {\n if (css(child, 'display') === 'none' || child === Sortable.ghost) return;\n animationStates.push({\n target: child,\n rect: getRect(child)\n });\n\n var fromRect = _objectSpread({}, animationStates[animationStates.length - 1].rect); // If animating: compensate for current animation\n\n\n if (child.thisAnimationDuration) {\n var childMatrix = matrix(child, true);\n\n if (childMatrix) {\n fromRect.top -= childMatrix.f;\n fromRect.left -= childMatrix.e;\n }\n }\n\n child.fromRect = fromRect;\n });\n },\n addAnimationState: function addAnimationState(state) {\n animationStates.push(state);\n },\n removeAnimationState: function removeAnimationState(target) {\n animationStates.splice(indexOfObject(animationStates, {\n target: target\n }), 1);\n },\n animateAll: function animateAll(callback) {\n var _this = this;\n\n if (!this.options.animation) {\n clearTimeout(animationCallbackId);\n if (typeof callback === 'function') callback();\n return;\n }\n\n var animating = false,\n animationTime = 0;\n animationStates.forEach(function (state) {\n var time = 0,\n target = state.target,\n fromRect = target.fromRect,\n toRect = getRect(target),\n prevFromRect = target.prevFromRect,\n prevToRect = target.prevToRect,\n animatingRect = state.rect,\n targetMatrix = matrix(target, true);\n\n if (targetMatrix) {\n // Compensate for current animation\n toRect.top -= targetMatrix.f;\n toRect.left -= targetMatrix.e;\n }\n\n target.toRect = toRect;\n\n if (target.thisAnimationDuration) {\n // Could also check if animatingRect is between fromRect and toRect\n if (isRectEqual(prevFromRect, toRect) && !isRectEqual(fromRect, toRect) && // Make sure animatingRect is on line between toRect & fromRect\n (animatingRect.top - toRect.top) / (animatingRect.left - toRect.left) === (fromRect.top - toRect.top) / (fromRect.left - toRect.left)) {\n // If returning to same place as started from animation and on same axis\n time = calculateRealTime(animatingRect, prevFromRect, prevToRect, _this.options);\n }\n } // if fromRect != toRect: animate\n\n\n if (!isRectEqual(toRect, fromRect)) {\n target.prevFromRect = fromRect;\n target.prevToRect = toRect;\n\n if (!time) {\n time = _this.options.animation;\n }\n\n _this.animate(target, animatingRect, toRect, time);\n }\n\n if (time) {\n animating = true;\n animationTime = Math.max(animationTime, time);\n clearTimeout(target.animationResetTimer);\n target.animationResetTimer = setTimeout(function () {\n target.animationTime = 0;\n target.prevFromRect = null;\n target.fromRect = null;\n target.prevToRect = null;\n target.thisAnimationDuration = null;\n }, time);\n target.thisAnimationDuration = time;\n }\n });\n clearTimeout(animationCallbackId);\n\n if (!animating) {\n if (typeof callback === 'function') callback();\n } else {\n animationCallbackId = setTimeout(function () {\n if (typeof callback === 'function') callback();\n }, animationTime);\n }\n\n animationStates = [];\n },\n animate: function animate(target, currentRect, toRect, duration) {\n if (duration) {\n css(target, 'transition', '');\n css(target, 'transform', '');\n var elMatrix = matrix(this.el),\n scaleX = elMatrix && elMatrix.a,\n scaleY = elMatrix && elMatrix.d,\n translateX = (currentRect.left - toRect.left) / (scaleX || 1),\n translateY = (currentRect.top - toRect.top) / (scaleY || 1);\n target.animatingX = !!translateX;\n target.animatingY = !!translateY;\n css(target, 'transform', 'translate3d(' + translateX + 'px,' + translateY + 'px,0)');\n repaint(target); // repaint\n\n css(target, 'transition', 'transform ' + duration + 'ms' + (this.options.easing ? ' ' + this.options.easing : ''));\n css(target, 'transform', 'translate3d(0,0,0)');\n typeof target.animated === 'number' && clearTimeout(target.animated);\n target.animated = setTimeout(function () {\n css(target, 'transition', '');\n css(target, 'transform', '');\n target.animated = false;\n target.animatingX = false;\n target.animatingY = false;\n }, duration);\n }\n }\n };\n}\n\nfunction repaint(target) {\n return target.offsetWidth;\n}\n\nfunction calculateRealTime(animatingRect, fromRect, toRect, options) {\n return Math.sqrt(Math.pow(fromRect.top - animatingRect.top, 2) + Math.pow(fromRect.left - animatingRect.left, 2)) / Math.sqrt(Math.pow(fromRect.top - toRect.top, 2) + Math.pow(fromRect.left - toRect.left, 2)) * options.animation;\n}\n\nvar plugins = [];\nvar defaults = {\n initializeByDefault: true\n};\nvar PluginManager = {\n mount: function mount(plugin) {\n // Set default static properties\n for (var option in defaults) {\n if (defaults.hasOwnProperty(option) && !(option in plugin)) {\n plugin[option] = defaults[option];\n }\n }\n\n plugins.push(plugin);\n },\n pluginEvent: function pluginEvent(eventName, sortable, evt) {\n var _this = this;\n\n this.eventCanceled = false;\n\n evt.cancel = function () {\n _this.eventCanceled = true;\n };\n\n var eventNameGlobal = eventName + 'Global';\n plugins.forEach(function (plugin) {\n if (!sortable[plugin.pluginName]) return; // Fire global events if it exists in this sortable\n\n if (sortable[plugin.pluginName][eventNameGlobal]) {\n sortable[plugin.pluginName][eventNameGlobal](_objectSpread({\n sortable: sortable\n }, evt));\n } // Only fire plugin event if plugin is enabled in this sortable,\n // and plugin has event defined\n\n\n if (sortable.options[plugin.pluginName] && sortable[plugin.pluginName][eventName]) {\n sortable[plugin.pluginName][eventName](_objectSpread({\n sortable: sortable\n }, evt));\n }\n });\n },\n initializePlugins: function initializePlugins(sortable, el, defaults, options) {\n plugins.forEach(function (plugin) {\n var pluginName = plugin.pluginName;\n if (!sortable.options[pluginName] && !plugin.initializeByDefault) return;\n var initialized = new plugin(sortable, el, sortable.options);\n initialized.sortable = sortable;\n initialized.options = sortable.options;\n sortable[pluginName] = initialized; // Add default options from plugin\n\n _extends(defaults, initialized.defaults);\n });\n\n for (var option in sortable.options) {\n if (!sortable.options.hasOwnProperty(option)) continue;\n var modified = this.modifyOption(sortable, option, sortable.options[option]);\n\n if (typeof modified !== 'undefined') {\n sortable.options[option] = modified;\n }\n }\n },\n getEventProperties: function getEventProperties(name, sortable) {\n var eventProperties = {};\n plugins.forEach(function (plugin) {\n if (typeof plugin.eventProperties !== 'function') return;\n\n _extends(eventProperties, plugin.eventProperties.call(sortable[plugin.pluginName], name));\n });\n return eventProperties;\n },\n modifyOption: function modifyOption(sortable, name, value) {\n var modifiedValue;\n plugins.forEach(function (plugin) {\n // Plugin must exist on the Sortable\n if (!sortable[plugin.pluginName]) return; // If static option listener exists for this option, call in the context of the Sortable's instance of this plugin\n\n if (plugin.optionListeners && typeof plugin.optionListeners[name] === 'function') {\n modifiedValue = plugin.optionListeners[name].call(sortable[plugin.pluginName], value);\n }\n });\n return modifiedValue;\n }\n};\n\nfunction dispatchEvent(_ref) {\n var sortable = _ref.sortable,\n rootEl = _ref.rootEl,\n name = _ref.name,\n targetEl = _ref.targetEl,\n cloneEl = _ref.cloneEl,\n toEl = _ref.toEl,\n fromEl = _ref.fromEl,\n oldIndex = _ref.oldIndex,\n newIndex = _ref.newIndex,\n oldDraggableIndex = _ref.oldDraggableIndex,\n newDraggableIndex = _ref.newDraggableIndex,\n originalEvent = _ref.originalEvent,\n putSortable = _ref.putSortable,\n extraEventProperties = _ref.extraEventProperties;\n sortable = sortable || rootEl && rootEl[expando];\n if (!sortable) return;\n var evt,\n options = sortable.options,\n onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1); // Support for new CustomEvent feature\n\n if (window.CustomEvent && !IE11OrLess && !Edge) {\n evt = new CustomEvent(name, {\n bubbles: true,\n cancelable: true\n });\n } else {\n evt = document.createEvent('Event');\n evt.initEvent(name, true, true);\n }\n\n evt.to = toEl || rootEl;\n evt.from = fromEl || rootEl;\n evt.item = targetEl || rootEl;\n evt.clone = cloneEl;\n evt.oldIndex = oldIndex;\n evt.newIndex = newIndex;\n evt.oldDraggableIndex = oldDraggableIndex;\n evt.newDraggableIndex = newDraggableIndex;\n evt.originalEvent = originalEvent;\n evt.pullMode = putSortable ? putSortable.lastPutMode : undefined;\n\n var allEventProperties = _objectSpread({}, extraEventProperties, PluginManager.getEventProperties(name, sortable));\n\n for (var option in allEventProperties) {\n evt[option] = allEventProperties[option];\n }\n\n if (rootEl) {\n rootEl.dispatchEvent(evt);\n }\n\n if (options[onName]) {\n options[onName].call(sortable, evt);\n }\n}\n\nvar pluginEvent = function pluginEvent(eventName, sortable) {\n var _ref = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},\n originalEvent = _ref.evt,\n data = _objectWithoutProperties(_ref, [\"evt\"]);\n\n PluginManager.pluginEvent.bind(Sortable)(eventName, sortable, _objectSpread({\n dragEl: dragEl,\n parentEl: parentEl,\n ghostEl: ghostEl,\n rootEl: rootEl,\n nextEl: nextEl,\n lastDownEl: lastDownEl,\n cloneEl: cloneEl,\n cloneHidden: cloneHidden,\n dragStarted: moved,\n putSortable: putSortable,\n activeSortable: Sortable.active,\n originalEvent: originalEvent,\n oldIndex: oldIndex,\n oldDraggableIndex: oldDraggableIndex,\n newIndex: newIndex,\n newDraggableIndex: newDraggableIndex,\n hideGhostForTarget: _hideGhostForTarget,\n unhideGhostForTarget: _unhideGhostForTarget,\n cloneNowHidden: function cloneNowHidden() {\n cloneHidden = true;\n },\n cloneNowShown: function cloneNowShown() {\n cloneHidden = false;\n },\n dispatchSortableEvent: function dispatchSortableEvent(name) {\n _dispatchEvent({\n sortable: sortable,\n name: name,\n originalEvent: originalEvent\n });\n }\n }, data));\n};\n\nfunction _dispatchEvent(info) {\n dispatchEvent(_objectSpread({\n putSortable: putSortable,\n cloneEl: cloneEl,\n targetEl: dragEl,\n rootEl: rootEl,\n oldIndex: oldIndex,\n oldDraggableIndex: oldDraggableIndex,\n newIndex: newIndex,\n newDraggableIndex: newDraggableIndex\n }, info));\n}\n\nvar dragEl,\n parentEl,\n ghostEl,\n rootEl,\n nextEl,\n lastDownEl,\n cloneEl,\n cloneHidden,\n oldIndex,\n newIndex,\n oldDraggableIndex,\n newDraggableIndex,\n activeGroup,\n putSortable,\n awaitingDragStarted = false,\n ignoreNextClick = false,\n sortables = [],\n tapEvt,\n touchEvt,\n lastDx,\n lastDy,\n tapDistanceLeft,\n tapDistanceTop,\n moved,\n lastTarget,\n lastDirection,\n pastFirstInvertThresh = false,\n isCircumstantialInvert = false,\n targetMoveDistance,\n // For positioning ghost absolutely\nghostRelativeParent,\n ghostRelativeParentInitialScroll = [],\n // (left, top)\n_silent = false,\n savedInputChecked = [];\n/** @const */\n\nvar documentExists = typeof document !== 'undefined',\n PositionGhostAbsolutely = IOS,\n CSSFloatProperty = Edge || IE11OrLess ? 'cssFloat' : 'float',\n // This will not pass for IE9, because IE9 DnD only works on anchors\nsupportDraggable = documentExists && !ChromeForAndroid && !IOS && 'draggable' in document.createElement('div'),\n supportCssPointerEvents = function () {\n if (!documentExists) return; // false when <= IE11\n\n if (IE11OrLess) {\n return false;\n }\n\n var el = document.createElement('x');\n el.style.cssText = 'pointer-events:auto';\n return el.style.pointerEvents === 'auto';\n}(),\n _detectDirection = function _detectDirection(el, options) {\n var elCSS = css(el),\n elWidth = parseInt(elCSS.width) - parseInt(elCSS.paddingLeft) - parseInt(elCSS.paddingRight) - parseInt(elCSS.borderLeftWidth) - parseInt(elCSS.borderRightWidth),\n child1 = getChild(el, 0, options),\n child2 = getChild(el, 1, options),\n firstChildCSS = child1 && css(child1),\n secondChildCSS = child2 && css(child2),\n firstChildWidth = firstChildCSS && parseInt(firstChildCSS.marginLeft) + parseInt(firstChildCSS.marginRight) + getRect(child1).width,\n secondChildWidth = secondChildCSS && parseInt(secondChildCSS.marginLeft) + parseInt(secondChildCSS.marginRight) + getRect(child2).width;\n\n if (elCSS.display === 'flex') {\n return elCSS.flexDirection === 'column' || elCSS.flexDirection === 'column-reverse' ? 'vertical' : 'horizontal';\n }\n\n if (elCSS.display === 'grid') {\n return elCSS.gridTemplateColumns.split(' ').length <= 1 ? 'vertical' : 'horizontal';\n }\n\n if (child1 && firstChildCSS[\"float\"] && firstChildCSS[\"float\"] !== 'none') {\n var touchingSideChild2 = firstChildCSS[\"float\"] === 'left' ? 'left' : 'right';\n return child2 && (secondChildCSS.clear === 'both' || secondChildCSS.clear === touchingSideChild2) ? 'vertical' : 'horizontal';\n }\n\n return child1 && (firstChildCSS.display === 'block' || firstChildCSS.display === 'flex' || firstChildCSS.display === 'table' || firstChildCSS.display === 'grid' || firstChildWidth >= elWidth && elCSS[CSSFloatProperty] === 'none' || child2 && elCSS[CSSFloatProperty] === 'none' && firstChildWidth + secondChildWidth > elWidth) ? 'vertical' : 'horizontal';\n},\n _dragElInRowColumn = function _dragElInRowColumn(dragRect, targetRect, vertical) {\n var dragElS1Opp = vertical ? dragRect.left : dragRect.top,\n dragElS2Opp = vertical ? dragRect.right : dragRect.bottom,\n dragElOppLength = vertical ? dragRect.width : dragRect.height,\n targetS1Opp = vertical ? targetRect.left : targetRect.top,\n targetS2Opp = vertical ? targetRect.right : targetRect.bottom,\n targetOppLength = vertical ? targetRect.width : targetRect.height;\n return dragElS1Opp === targetS1Opp || dragElS2Opp === targetS2Opp || dragElS1Opp + dragElOppLength / 2 === targetS1Opp + targetOppLength / 2;\n},\n\n/**\n * Detects first nearest empty sortable to X and Y position using emptyInsertThreshold.\n * @param {Number} x X position\n * @param {Number} y Y position\n * @return {HTMLElement} Element of the first found nearest Sortable\n */\n_detectNearestEmptySortable = function _detectNearestEmptySortable(x, y) {\n var ret;\n sortables.some(function (sortable) {\n if (lastChild(sortable)) return;\n var rect = getRect(sortable),\n threshold = sortable[expando].options.emptyInsertThreshold,\n insideHorizontally = x >= rect.left - threshold && x <= rect.right + threshold,\n insideVertically = y >= rect.top - threshold && y <= rect.bottom + threshold;\n\n if (threshold && insideHorizontally && insideVertically) {\n return ret = sortable;\n }\n });\n return ret;\n},\n _prepareGroup = function _prepareGroup(options) {\n function toFn(value, pull) {\n return function (to, from, dragEl, evt) {\n var sameGroup = to.options.group.name && from.options.group.name && to.options.group.name === from.options.group.name;\n\n if (value == null && (pull || sameGroup)) {\n // Default pull value\n // Default pull and put value if same group\n return true;\n } else if (value == null || value === false) {\n return false;\n } else if (pull && value === 'clone') {\n return value;\n } else if (typeof value === 'function') {\n return toFn(value(to, from, dragEl, evt), pull)(to, from, dragEl, evt);\n } else {\n var otherGroup = (pull ? to : from).options.group.name;\n return value === true || typeof value === 'string' && value === otherGroup || value.join && value.indexOf(otherGroup) > -1;\n }\n };\n }\n\n var group = {};\n var originalGroup = options.group;\n\n if (!originalGroup || _typeof(originalGroup) != 'object') {\n originalGroup = {\n name: originalGroup\n };\n }\n\n group.name = originalGroup.name;\n group.checkPull = toFn(originalGroup.pull, true);\n group.checkPut = toFn(originalGroup.put);\n group.revertClone = originalGroup.revertClone;\n options.group = group;\n},\n _hideGhostForTarget = function _hideGhostForTarget() {\n if (!supportCssPointerEvents && ghostEl) {\n css(ghostEl, 'display', 'none');\n }\n},\n _unhideGhostForTarget = function _unhideGhostForTarget() {\n if (!supportCssPointerEvents && ghostEl) {\n css(ghostEl, 'display', '');\n }\n}; // #1184 fix - Prevent click event on fallback if dragged but item not changed position\n\n\nif (documentExists) {\n document.addEventListener('click', function (evt) {\n if (ignoreNextClick) {\n evt.preventDefault();\n evt.stopPropagation && evt.stopPropagation();\n evt.stopImmediatePropagation && evt.stopImmediatePropagation();\n ignoreNextClick = false;\n return false;\n }\n }, true);\n}\n\nvar nearestEmptyInsertDetectEvent = function nearestEmptyInsertDetectEvent(evt) {\n if (dragEl) {\n evt = evt.touches ? evt.touches[0] : evt;\n\n var nearest = _detectNearestEmptySortable(evt.clientX, evt.clientY);\n\n if (nearest) {\n // Create imitation event\n var event = {};\n\n for (var i in evt) {\n if (evt.hasOwnProperty(i)) {\n event[i] = evt[i];\n }\n }\n\n event.target = event.rootEl = nearest;\n event.preventDefault = void 0;\n event.stopPropagation = void 0;\n\n nearest[expando]._onDragOver(event);\n }\n }\n};\n\nvar _checkOutsideTargetEl = function _checkOutsideTargetEl(evt) {\n if (dragEl) {\n dragEl.parentNode[expando]._isOutsideThisEl(evt.target);\n }\n};\n/**\n * @class Sortable\n * @param {HTMLElement} el\n * @param {Object} [options]\n */\n\n\nfunction Sortable(el, options) {\n if (!(el && el.nodeType && el.nodeType === 1)) {\n throw \"Sortable: `el` must be an HTMLElement, not \".concat({}.toString.call(el));\n }\n\n this.el = el; // root element\n\n this.options = options = _extends({}, options); // Export instance\n\n el[expando] = this;\n var defaults = {\n group: null,\n sort: true,\n disabled: false,\n store: null,\n handle: null,\n draggable: /^[uo]l$/i.test(el.nodeName) ? '>li' : '>*',\n swapThreshold: 1,\n // percentage; 0 <= x <= 1\n invertSwap: false,\n // invert always\n invertedSwapThreshold: null,\n // will be set to same as swapThreshold if default\n removeCloneOnHide: true,\n direction: function direction() {\n return _detectDirection(el, this.options);\n },\n ghostClass: 'sortable-ghost',\n chosenClass: 'sortable-chosen',\n dragClass: 'sortable-drag',\n ignore: 'a, img',\n filter: null,\n preventOnFilter: true,\n animation: 0,\n easing: null,\n setData: function setData(dataTransfer, dragEl) {\n dataTransfer.setData('Text', dragEl.textContent);\n },\n dropBubble: false,\n dragoverBubble: false,\n dataIdAttr: 'data-id',\n delay: 0,\n delayOnTouchOnly: false,\n touchStartThreshold: (Number.parseInt ? Number : window).parseInt(window.devicePixelRatio, 10) || 1,\n forceFallback: false,\n fallbackClass: 'sortable-fallback',\n fallbackOnBody: false,\n fallbackTolerance: 0,\n fallbackOffset: {\n x: 0,\n y: 0\n },\n supportPointer: Sortable.supportPointer !== false && 'PointerEvent' in window,\n emptyInsertThreshold: 5\n };\n PluginManager.initializePlugins(this, el, defaults); // Set default options\n\n for (var name in defaults) {\n !(name in options) && (options[name] = defaults[name]);\n }\n\n _prepareGroup(options); // Bind all private methods\n\n\n for (var fn in this) {\n if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {\n this[fn] = this[fn].bind(this);\n }\n } // Setup drag mode\n\n\n this.nativeDraggable = options.forceFallback ? false : supportDraggable;\n\n if (this.nativeDraggable) {\n // Touch start threshold cannot be greater than the native dragstart threshold\n this.options.touchStartThreshold = 1;\n } // Bind events\n\n\n if (options.supportPointer) {\n on(el, 'pointerdown', this._onTapStart);\n } else {\n on(el, 'mousedown', this._onTapStart);\n on(el, 'touchstart', this._onTapStart);\n }\n\n if (this.nativeDraggable) {\n on(el, 'dragover', this);\n on(el, 'dragenter', this);\n }\n\n sortables.push(this.el); // Restore sorting\n\n options.store && options.store.get && this.sort(options.store.get(this) || []); // Add animation state manager\n\n _extends(this, AnimationStateManager());\n}\n\nSortable.prototype =\n/** @lends Sortable.prototype */\n{\n constructor: Sortable,\n _isOutsideThisEl: function _isOutsideThisEl(target) {\n if (!this.el.contains(target) && target !== this.el) {\n lastTarget = null;\n }\n },\n _getDirection: function _getDirection(evt, target) {\n return typeof this.options.direction === 'function' ? this.options.direction.call(this, evt, target, dragEl) : this.options.direction;\n },\n _onTapStart: function _onTapStart(\n /** Event|TouchEvent */\n evt) {\n if (!evt.cancelable) return;\n\n var _this = this,\n el = this.el,\n options = this.options,\n preventOnFilter = options.preventOnFilter,\n type = evt.type,\n touch = evt.touches && evt.touches[0] || evt.pointerType && evt.pointerType === 'touch' && evt,\n target = (touch || evt).target,\n originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0] || evt.composedPath && evt.composedPath()[0]) || target,\n filter = options.filter;\n\n _saveInputCheckedState(el); // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.\n\n\n if (dragEl) {\n return;\n }\n\n if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {\n return; // only left button and enabled\n } // cancel dnd if original target is content editable\n\n\n if (originalTarget.isContentEditable) {\n return;\n }\n\n target = closest(target, options.draggable, el, false);\n\n if (target && target.animated) {\n return;\n }\n\n if (lastDownEl === target) {\n // Ignoring duplicate `down`\n return;\n } // Get the index of the dragged element within its parent\n\n\n oldIndex = index(target);\n oldDraggableIndex = index(target, options.draggable); // Check filter\n\n if (typeof filter === 'function') {\n if (filter.call(this, evt, target, this)) {\n _dispatchEvent({\n sortable: _this,\n rootEl: originalTarget,\n name: 'filter',\n targetEl: target,\n toEl: el,\n fromEl: el\n });\n\n pluginEvent('filter', _this, {\n evt: evt\n });\n preventOnFilter && evt.cancelable && evt.preventDefault();\n return; // cancel dnd\n }\n } else if (filter) {\n filter = filter.split(',').some(function (criteria) {\n criteria = closest(originalTarget, criteria.trim(), el, false);\n\n if (criteria) {\n _dispatchEvent({\n sortable: _this,\n rootEl: criteria,\n name: 'filter',\n targetEl: target,\n fromEl: el,\n toEl: el\n });\n\n pluginEvent('filter', _this, {\n evt: evt\n });\n return true;\n }\n });\n\n if (filter) {\n preventOnFilter && evt.cancelable && evt.preventDefault();\n return; // cancel dnd\n }\n }\n\n if (options.handle && !closest(originalTarget, options.handle, el, false)) {\n return;\n } // Prepare `dragstart`\n\n\n this._prepareDragStart(evt, touch, target);\n },\n _prepareDragStart: function _prepareDragStart(\n /** Event */\n evt,\n /** Touch */\n touch,\n /** HTMLElement */\n target) {\n var _this = this,\n el = _this.el,\n options = _this.options,\n ownerDocument = el.ownerDocument,\n dragStartFn;\n\n if (target && !dragEl && target.parentNode === el) {\n var dragRect = getRect(target);\n rootEl = el;\n dragEl = target;\n parentEl = dragEl.parentNode;\n nextEl = dragEl.nextSibling;\n lastDownEl = target;\n activeGroup = options.group;\n Sortable.dragged = dragEl;\n tapEvt = {\n target: dragEl,\n clientX: (touch || evt).clientX,\n clientY: (touch || evt).clientY\n };\n tapDistanceLeft = tapEvt.clientX - dragRect.left;\n tapDistanceTop = tapEvt.clientY - dragRect.top;\n this._lastX = (touch || evt).clientX;\n this._lastY = (touch || evt).clientY;\n dragEl.style['will-change'] = 'all';\n\n dragStartFn = function dragStartFn() {\n pluginEvent('delayEnded', _this, {\n evt: evt\n });\n\n if (Sortable.eventCanceled) {\n _this._onDrop();\n\n return;\n } // Delayed drag has been triggered\n // we can re-enable the events: touchmove/mousemove\n\n\n _this._disableDelayedDragEvents();\n\n if (!FireFox && _this.nativeDraggable) {\n dragEl.draggable = true;\n } // Bind the events: dragstart/dragend\n\n\n _this._triggerDragStart(evt, touch); // Drag start event\n\n\n _dispatchEvent({\n sortable: _this,\n name: 'choose',\n originalEvent: evt\n }); // Chosen item\n\n\n toggleClass(dragEl, options.chosenClass, true);\n }; // Disable \"draggable\"\n\n\n options.ignore.split(',').forEach(function (criteria) {\n find(dragEl, criteria.trim(), _disableDraggable);\n });\n on(ownerDocument, 'dragover', nearestEmptyInsertDetectEvent);\n on(ownerDocument, 'mousemove', nearestEmptyInsertDetectEvent);\n on(ownerDocument, 'touchmove', nearestEmptyInsertDetectEvent);\n on(ownerDocument, 'mouseup', _this._onDrop);\n on(ownerDocument, 'touchend', _this._onDrop);\n on(ownerDocument, 'touchcancel', _this._onDrop); // Make dragEl draggable (must be before delay for FireFox)\n\n if (FireFox && this.nativeDraggable) {\n this.options.touchStartThreshold = 4;\n dragEl.draggable = true;\n }\n\n pluginEvent('delayStart', this, {\n evt: evt\n }); // Delay is impossible for native DnD in Edge or IE\n\n if (options.delay && (!options.delayOnTouchOnly || touch) && (!this.nativeDraggable || !(Edge || IE11OrLess))) {\n if (Sortable.eventCanceled) {\n this._onDrop();\n\n return;\n } // If the user moves the pointer or let go the click or touch\n // before the delay has been reached:\n // disable the delayed drag\n\n\n on(ownerDocument, 'mouseup', _this._disableDelayedDrag);\n on(ownerDocument, 'touchend', _this._disableDelayedDrag);\n on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);\n on(ownerDocument, 'mousemove', _this._delayedDragTouchMoveHandler);\n on(ownerDocument, 'touchmove', _this._delayedDragTouchMoveHandler);\n options.supportPointer && on(ownerDocument, 'pointermove', _this._delayedDragTouchMoveHandler);\n _this._dragStartTimer = setTimeout(dragStartFn, options.delay);\n } else {\n dragStartFn();\n }\n }\n },\n _delayedDragTouchMoveHandler: function _delayedDragTouchMoveHandler(\n /** TouchEvent|PointerEvent **/\n e) {\n var touch = e.touches ? e.touches[0] : e;\n\n if (Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) >= Math.floor(this.options.touchStartThreshold / (this.nativeDraggable && window.devicePixelRatio || 1))) {\n this._disableDelayedDrag();\n }\n },\n _disableDelayedDrag: function _disableDelayedDrag() {\n dragEl && _disableDraggable(dragEl);\n clearTimeout(this._dragStartTimer);\n\n this._disableDelayedDragEvents();\n },\n _disableDelayedDragEvents: function _disableDelayedDragEvents() {\n var ownerDocument = this.el.ownerDocument;\n off(ownerDocument, 'mouseup', this._disableDelayedDrag);\n off(ownerDocument, 'touchend', this._disableDelayedDrag);\n off(ownerDocument, 'touchcancel', this._disableDelayedDrag);\n off(ownerDocument, 'mousemove', this._delayedDragTouchMoveHandler);\n off(ownerDocument, 'touchmove', this._delayedDragTouchMoveHandler);\n off(ownerDocument, 'pointermove', this._delayedDragTouchMoveHandler);\n },\n _triggerDragStart: function _triggerDragStart(\n /** Event */\n evt,\n /** Touch */\n touch) {\n touch = touch || evt.pointerType == 'touch' && evt;\n\n if (!this.nativeDraggable || touch) {\n if (this.options.supportPointer) {\n on(document, 'pointermove', this._onTouchMove);\n } else if (touch) {\n on(document, 'touchmove', this._onTouchMove);\n } else {\n on(document, 'mousemove', this._onTouchMove);\n }\n } else {\n on(dragEl, 'dragend', this);\n on(rootEl, 'dragstart', this._onDragStart);\n }\n\n try {\n if (document.selection) {\n // Timeout neccessary for IE9\n _nextTick(function () {\n document.selection.empty();\n });\n } else {\n window.getSelection().removeAllRanges();\n }\n } catch (err) {}\n },\n _dragStarted: function _dragStarted(fallback, evt) {\n\n awaitingDragStarted = false;\n\n if (rootEl && dragEl) {\n pluginEvent('dragStarted', this, {\n evt: evt\n });\n\n if (this.nativeDraggable) {\n on(document, 'dragover', _checkOutsideTargetEl);\n }\n\n var options = this.options; // Apply effect\n\n !fallback && toggleClass(dragEl, options.dragClass, false);\n toggleClass(dragEl, options.ghostClass, true);\n Sortable.active = this;\n fallback && this._appendGhost(); // Drag start event\n\n _dispatchEvent({\n sortable: this,\n name: 'start',\n originalEvent: evt\n });\n } else {\n this._nulling();\n }\n },\n _emulateDragOver: function _emulateDragOver() {\n if (touchEvt) {\n this._lastX = touchEvt.clientX;\n this._lastY = touchEvt.clientY;\n\n _hideGhostForTarget();\n\n var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);\n var parent = target;\n\n while (target && target.shadowRoot) {\n target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);\n if (target === parent) break;\n parent = target;\n }\n\n dragEl.parentNode[expando]._isOutsideThisEl(target);\n\n if (parent) {\n do {\n if (parent[expando]) {\n var inserted = void 0;\n inserted = parent[expando]._onDragOver({\n clientX: touchEvt.clientX,\n clientY: touchEvt.clientY,\n target: target,\n rootEl: parent\n });\n\n if (inserted && !this.options.dragoverBubble) {\n break;\n }\n }\n\n target = parent; // store last element\n }\n /* jshint boss:true */\n while (parent = parent.parentNode);\n }\n\n _unhideGhostForTarget();\n }\n },\n _onTouchMove: function _onTouchMove(\n /**TouchEvent*/\n evt) {\n if (tapEvt) {\n var options = this.options,\n fallbackTolerance = options.fallbackTolerance,\n fallbackOffset = options.fallbackOffset,\n touch = evt.touches ? evt.touches[0] : evt,\n ghostMatrix = ghostEl && matrix(ghostEl, true),\n scaleX = ghostEl && ghostMatrix && ghostMatrix.a,\n scaleY = ghostEl && ghostMatrix && ghostMatrix.d,\n relativeScrollOffset = PositionGhostAbsolutely && ghostRelativeParent && getRelativeScrollOffset(ghostRelativeParent),\n dx = (touch.clientX - tapEvt.clientX + fallbackOffset.x) / (scaleX || 1) + (relativeScrollOffset ? relativeScrollOffset[0] - ghostRelativeParentInitialScroll[0] : 0) / (scaleX || 1),\n dy = (touch.clientY - tapEvt.clientY + fallbackOffset.y) / (scaleY || 1) + (relativeScrollOffset ? relativeScrollOffset[1] - ghostRelativeParentInitialScroll[1] : 0) / (scaleY || 1); // only set the status to dragging, when we are actually dragging\n\n if (!Sortable.active && !awaitingDragStarted) {\n if (fallbackTolerance && Math.max(Math.abs(touch.clientX - this._lastX), Math.abs(touch.clientY - this._lastY)) < fallbackTolerance) {\n return;\n }\n\n this._onDragStart(evt, true);\n }\n\n if (ghostEl) {\n if (ghostMatrix) {\n ghostMatrix.e += dx - (lastDx || 0);\n ghostMatrix.f += dy - (lastDy || 0);\n } else {\n ghostMatrix = {\n a: 1,\n b: 0,\n c: 0,\n d: 1,\n e: dx,\n f: dy\n };\n }\n\n var cssMatrix = \"matrix(\".concat(ghostMatrix.a, \",\").concat(ghostMatrix.b, \",\").concat(ghostMatrix.c, \",\").concat(ghostMatrix.d, \",\").concat(ghostMatrix.e, \",\").concat(ghostMatrix.f, \")\");\n css(ghostEl, 'webkitTransform', cssMatrix);\n css(ghostEl, 'mozTransform', cssMatrix);\n css(ghostEl, 'msTransform', cssMatrix);\n css(ghostEl, 'transform', cssMatrix);\n lastDx = dx;\n lastDy = dy;\n touchEvt = touch;\n }\n\n evt.cancelable && evt.preventDefault();\n }\n },\n _appendGhost: function _appendGhost() {\n // Bug if using scale(): https://stackoverflow.com/questions/2637058\n // Not being adjusted for\n if (!ghostEl) {\n var container = this.options.fallbackOnBody ? document.body : rootEl,\n rect = getRect(dragEl, true, PositionGhostAbsolutely, true, container),\n options = this.options; // Position absolutely\n\n if (PositionGhostAbsolutely) {\n // Get relatively positioned parent\n ghostRelativeParent = container;\n\n while (css(ghostRelativeParent, 'position') === 'static' && css(ghostRelativeParent, 'transform') === 'none' && ghostRelativeParent !== document) {\n ghostRelativeParent = ghostRelativeParent.parentNode;\n }\n\n if (ghostRelativeParent !== document.body && ghostRelativeParent !== document.documentElement) {\n if (ghostRelativeParent === document) ghostRelativeParent = getWindowScrollingElement();\n rect.top += ghostRelativeParent.scrollTop;\n rect.left += ghostRelativeParent.scrollLeft;\n } else {\n ghostRelativeParent = getWindowScrollingElement();\n }\n\n ghostRelativeParentInitialScroll = getRelativeScrollOffset(ghostRelativeParent);\n }\n\n ghostEl = dragEl.cloneNode(true);\n toggleClass(ghostEl, options.ghostClass, false);\n toggleClass(ghostEl, options.fallbackClass, true);\n toggleClass(ghostEl, options.dragClass, true);\n css(ghostEl, 'transition', '');\n css(ghostEl, 'transform', '');\n css(ghostEl, 'box-sizing', 'border-box');\n css(ghostEl, 'margin', 0);\n css(ghostEl, 'top', rect.top);\n css(ghostEl, 'left', rect.left);\n css(ghostEl, 'width', rect.width);\n css(ghostEl, 'height', rect.height);\n css(ghostEl, 'opacity', '0.8');\n css(ghostEl, 'position', PositionGhostAbsolutely ? 'absolute' : 'fixed');\n css(ghostEl, 'zIndex', '100000');\n css(ghostEl, 'pointerEvents', 'none');\n Sortable.ghost = ghostEl;\n container.appendChild(ghostEl); // Set transform-origin\n\n css(ghostEl, 'transform-origin', tapDistanceLeft / parseInt(ghostEl.style.width) * 100 + '% ' + tapDistanceTop / parseInt(ghostEl.style.height) * 100 + '%');\n }\n },\n _onDragStart: function _onDragStart(\n /**Event*/\n evt,\n /**boolean*/\n fallback) {\n var _this = this;\n\n var dataTransfer = evt.dataTransfer;\n var options = _this.options;\n pluginEvent('dragStart', this, {\n evt: evt\n });\n\n if (Sortable.eventCanceled) {\n this._onDrop();\n\n return;\n }\n\n pluginEvent('setupClone', this);\n\n if (!Sortable.eventCanceled) {\n cloneEl = clone(dragEl);\n cloneEl.draggable = false;\n cloneEl.style['will-change'] = '';\n\n this._hideClone();\n\n toggleClass(cloneEl, this.options.chosenClass, false);\n Sortable.clone = cloneEl;\n } // #1143: IFrame support workaround\n\n\n _this.cloneId = _nextTick(function () {\n pluginEvent('clone', _this);\n if (Sortable.eventCanceled) return;\n\n if (!_this.options.removeCloneOnHide) {\n rootEl.insertBefore(cloneEl, dragEl);\n }\n\n _this._hideClone();\n\n _dispatchEvent({\n sortable: _this,\n name: 'clone'\n });\n });\n !fallback && toggleClass(dragEl, options.dragClass, true); // Set proper drop events\n\n if (fallback) {\n ignoreNextClick = true;\n _this._loopId = setInterval(_this._emulateDragOver, 50);\n } else {\n // Undo what was set in _prepareDragStart before drag started\n off(document, 'mouseup', _this._onDrop);\n off(document, 'touchend', _this._onDrop);\n off(document, 'touchcancel', _this._onDrop);\n\n if (dataTransfer) {\n dataTransfer.effectAllowed = 'move';\n options.setData && options.setData.call(_this, dataTransfer, dragEl);\n }\n\n on(document, 'drop', _this); // #1276 fix:\n\n css(dragEl, 'transform', 'translateZ(0)');\n }\n\n awaitingDragStarted = true;\n _this._dragStartId = _nextTick(_this._dragStarted.bind(_this, fallback, evt));\n on(document, 'selectstart', _this);\n moved = true;\n\n if (Safari) {\n css(document.body, 'user-select', 'none');\n }\n },\n // Returns true - if no further action is needed (either inserted or another condition)\n _onDragOver: function _onDragOver(\n /**Event*/\n evt) {\n var el = this.el,\n target = evt.target,\n dragRect,\n targetRect,\n revert,\n options = this.options,\n group = options.group,\n activeSortable = Sortable.active,\n isOwner = activeGroup === group,\n canSort = options.sort,\n fromSortable = putSortable || activeSortable,\n vertical,\n _this = this,\n completedFired = false;\n\n if (_silent) return;\n\n function dragOverEvent(name, extra) {\n pluginEvent(name, _this, _objectSpread({\n evt: evt,\n isOwner: isOwner,\n axis: vertical ? 'vertical' : 'horizontal',\n revert: revert,\n dragRect: dragRect,\n targetRect: targetRect,\n canSort: canSort,\n fromSortable: fromSortable,\n target: target,\n completed: completed,\n onMove: function onMove(target, after) {\n return _onMove(rootEl, el, dragEl, dragRect, target, getRect(target), evt, after);\n },\n changed: changed\n }, extra));\n } // Capture animation state\n\n\n function capture() {\n dragOverEvent('dragOverAnimationCapture');\n\n _this.captureAnimationState();\n\n if (_this !== fromSortable) {\n fromSortable.captureAnimationState();\n }\n } // Return invocation when dragEl is inserted (or completed)\n\n\n function completed(insertion) {\n dragOverEvent('dragOverCompleted', {\n insertion: insertion\n });\n\n if (insertion) {\n // Clones must be hidden before folding animation to capture dragRectAbsolute properly\n if (isOwner) {\n activeSortable._hideClone();\n } else {\n activeSortable._showClone(_this);\n }\n\n if (_this !== fromSortable) {\n // Set ghost class to new sortable's ghost class\n toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : activeSortable.options.ghostClass, false);\n toggleClass(dragEl, options.ghostClass, true);\n }\n\n if (putSortable !== _this && _this !== Sortable.active) {\n putSortable = _this;\n } else if (_this === Sortable.active && putSortable) {\n putSortable = null;\n } // Animation\n\n\n if (fromSortable === _this) {\n _this._ignoreWhileAnimating = target;\n }\n\n _this.animateAll(function () {\n dragOverEvent('dragOverAnimationComplete');\n _this._ignoreWhileAnimating = null;\n });\n\n if (_this !== fromSortable) {\n fromSortable.animateAll();\n fromSortable._ignoreWhileAnimating = null;\n }\n } // Null lastTarget if it is not inside a previously swapped element\n\n\n if (target === dragEl && !dragEl.animated || target === el && !target.animated) {\n lastTarget = null;\n } // no bubbling and not fallback\n\n\n if (!options.dragoverBubble && !evt.rootEl && target !== document) {\n dragEl.parentNode[expando]._isOutsideThisEl(evt.target); // Do not detect for empty insert if already inserted\n\n\n !insertion && nearestEmptyInsertDetectEvent(evt);\n }\n\n !options.dragoverBubble && evt.stopPropagation && evt.stopPropagation();\n return completedFired = true;\n } // Call when dragEl has been inserted\n\n\n function changed() {\n newIndex = index(dragEl);\n newDraggableIndex = index(dragEl, options.draggable);\n\n _dispatchEvent({\n sortable: _this,\n name: 'change',\n toEl: el,\n newIndex: newIndex,\n newDraggableIndex: newDraggableIndex,\n originalEvent: evt\n });\n }\n\n if (evt.preventDefault !== void 0) {\n evt.cancelable && evt.preventDefault();\n }\n\n target = closest(target, options.draggable, el, true);\n dragOverEvent('dragOver');\n if (Sortable.eventCanceled) return completedFired;\n\n if (dragEl.contains(evt.target) || target.animated && target.animatingX && target.animatingY || _this._ignoreWhileAnimating === target) {\n return completed(false);\n }\n\n ignoreNextClick = false;\n\n if (activeSortable && !options.disabled && (isOwner ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list\n : putSortable === this || (this.lastPutMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) && group.checkPut(this, activeSortable, dragEl, evt))) {\n vertical = this._getDirection(evt, target) === 'vertical';\n dragRect = getRect(dragEl);\n dragOverEvent('dragOverValid');\n if (Sortable.eventCanceled) return completedFired;\n\n if (revert) {\n parentEl = rootEl; // actualization\n\n capture();\n\n this._hideClone();\n\n dragOverEvent('revert');\n\n if (!Sortable.eventCanceled) {\n if (nextEl) {\n rootEl.insertBefore(dragEl, nextEl);\n } else {\n rootEl.appendChild(dragEl);\n }\n }\n\n return completed(true);\n }\n\n var elLastChild = lastChild(el, options.draggable);\n\n if (!elLastChild || _ghostIsLast(evt, vertical, this) && !elLastChild.animated) {\n // If already at end of list: Do not insert\n if (elLastChild === dragEl) {\n return completed(false);\n } // assign target only if condition is true\n\n\n if (elLastChild && el === evt.target) {\n target = elLastChild;\n }\n\n if (target) {\n targetRect = getRect(target);\n }\n\n if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, !!target) !== false) {\n capture();\n el.appendChild(dragEl);\n parentEl = el; // actualization\n\n changed();\n return completed(true);\n }\n } else if (target.parentNode === el) {\n targetRect = getRect(target);\n var direction = 0,\n targetBeforeFirstSwap,\n differentLevel = dragEl.parentNode !== el,\n differentRowCol = !_dragElInRowColumn(dragEl.animated && dragEl.toRect || dragRect, target.animated && target.toRect || targetRect, vertical),\n side1 = vertical ? 'top' : 'left',\n scrolledPastTop = isScrolledPast(target, 'top', 'top') || isScrolledPast(dragEl, 'top', 'top'),\n scrollBefore = scrolledPastTop ? scrolledPastTop.scrollTop : void 0;\n\n if (lastTarget !== target) {\n targetBeforeFirstSwap = targetRect[side1];\n pastFirstInvertThresh = false;\n isCircumstantialInvert = !differentRowCol && options.invertSwap || differentLevel;\n }\n\n direction = _getSwapDirection(evt, target, targetRect, vertical, differentRowCol ? 1 : options.swapThreshold, options.invertedSwapThreshold == null ? options.swapThreshold : options.invertedSwapThreshold, isCircumstantialInvert, lastTarget === target);\n var sibling;\n\n if (direction !== 0) {\n // Check if target is beside dragEl in respective direction (ignoring hidden elements)\n var dragIndex = index(dragEl);\n\n do {\n dragIndex -= direction;\n sibling = parentEl.children[dragIndex];\n } while (sibling && (css(sibling, 'display') === 'none' || sibling === ghostEl));\n } // If dragEl is already beside target: Do not insert\n\n\n if (direction === 0 || sibling === target) {\n return completed(false);\n }\n\n lastTarget = target;\n lastDirection = direction;\n var nextSibling = target.nextElementSibling,\n after = false;\n after = direction === 1;\n\n var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);\n\n if (moveVector !== false) {\n if (moveVector === 1 || moveVector === -1) {\n after = moveVector === 1;\n }\n\n _silent = true;\n setTimeout(_unsilent, 30);\n capture();\n\n if (after && !nextSibling) {\n el.appendChild(dragEl);\n } else {\n target.parentNode.insertBefore(dragEl, after ? nextSibling : target);\n } // Undo chrome's scroll adjustment (has no effect on other browsers)\n\n\n if (scrolledPastTop) {\n scrollBy(scrolledPastTop, 0, scrollBefore - scrolledPastTop.scrollTop);\n }\n\n parentEl = dragEl.parentNode; // actualization\n // must be done before animation\n\n if (targetBeforeFirstSwap !== undefined && !isCircumstantialInvert) {\n targetMoveDistance = Math.abs(targetBeforeFirstSwap - getRect(target)[side1]);\n }\n\n changed();\n return completed(true);\n }\n }\n\n if (el.contains(dragEl)) {\n return completed(false);\n }\n }\n\n return false;\n },\n _ignoreWhileAnimating: null,\n _offMoveEvents: function _offMoveEvents() {\n off(document, 'mousemove', this._onTouchMove);\n off(document, 'touchmove', this._onTouchMove);\n off(document, 'pointermove', this._onTouchMove);\n off(document, 'dragover', nearestEmptyInsertDetectEvent);\n off(document, 'mousemove', nearestEmptyInsertDetectEvent);\n off(document, 'touchmove', nearestEmptyInsertDetectEvent);\n },\n _offUpEvents: function _offUpEvents() {\n var ownerDocument = this.el.ownerDocument;\n off(ownerDocument, 'mouseup', this._onDrop);\n off(ownerDocument, 'touchend', this._onDrop);\n off(ownerDocument, 'pointerup', this._onDrop);\n off(ownerDocument, 'touchcancel', this._onDrop);\n off(document, 'selectstart', this);\n },\n _onDrop: function _onDrop(\n /**Event*/\n evt) {\n var el = this.el,\n options = this.options; // Get the index of the dragged element within its parent\n\n newIndex = index(dragEl);\n newDraggableIndex = index(dragEl, options.draggable);\n pluginEvent('drop', this, {\n evt: evt\n });\n parentEl = dragEl && dragEl.parentNode; // Get again after plugin event\n\n newIndex = index(dragEl);\n newDraggableIndex = index(dragEl, options.draggable);\n\n if (Sortable.eventCanceled) {\n this._nulling();\n\n return;\n }\n\n awaitingDragStarted = false;\n isCircumstantialInvert = false;\n pastFirstInvertThresh = false;\n clearInterval(this._loopId);\n clearTimeout(this._dragStartTimer);\n\n _cancelNextTick(this.cloneId);\n\n _cancelNextTick(this._dragStartId); // Unbind events\n\n\n if (this.nativeDraggable) {\n off(document, 'drop', this);\n off(el, 'dragstart', this._onDragStart);\n }\n\n this._offMoveEvents();\n\n this._offUpEvents();\n\n if (Safari) {\n css(document.body, 'user-select', '');\n }\n\n css(dragEl, 'transform', '');\n\n if (evt) {\n if (moved) {\n evt.cancelable && evt.preventDefault();\n !options.dropBubble && evt.stopPropagation();\n }\n\n ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);\n\n if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {\n // Remove clone(s)\n cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);\n }\n\n if (dragEl) {\n if (this.nativeDraggable) {\n off(dragEl, 'dragend', this);\n }\n\n _disableDraggable(dragEl);\n\n dragEl.style['will-change'] = ''; // Remove classes\n // ghostClass is added in dragStarted\n\n if (moved && !awaitingDragStarted) {\n toggleClass(dragEl, putSortable ? putSortable.options.ghostClass : this.options.ghostClass, false);\n }\n\n toggleClass(dragEl, this.options.chosenClass, false); // Drag stop event\n\n _dispatchEvent({\n sortable: this,\n name: 'unchoose',\n toEl: parentEl,\n newIndex: null,\n newDraggableIndex: null,\n originalEvent: evt\n });\n\n if (rootEl !== parentEl) {\n if (newIndex >= 0) {\n // Add event\n _dispatchEvent({\n rootEl: parentEl,\n name: 'add',\n toEl: parentEl,\n fromEl: rootEl,\n originalEvent: evt\n }); // Remove event\n\n\n _dispatchEvent({\n sortable: this,\n name: 'remove',\n toEl: parentEl,\n originalEvent: evt\n }); // drag from one list and drop into another\n\n\n _dispatchEvent({\n rootEl: parentEl,\n name: 'sort',\n toEl: parentEl,\n fromEl: rootEl,\n originalEvent: evt\n });\n\n _dispatchEvent({\n sortable: this,\n name: 'sort',\n toEl: parentEl,\n originalEvent: evt\n });\n }\n\n putSortable && putSortable.save();\n } else {\n if (newIndex !== oldIndex) {\n if (newIndex >= 0) {\n // drag & drop within the same list\n _dispatchEvent({\n sortable: this,\n name: 'update',\n toEl: parentEl,\n originalEvent: evt\n });\n\n _dispatchEvent({\n sortable: this,\n name: 'sort',\n toEl: parentEl,\n originalEvent: evt\n });\n }\n }\n }\n\n if (Sortable.active) {\n /* jshint eqnull:true */\n if (newIndex == null || newIndex === -1) {\n newIndex = oldIndex;\n newDraggableIndex = oldDraggableIndex;\n }\n\n _dispatchEvent({\n sortable: this,\n name: 'end',\n toEl: parentEl,\n originalEvent: evt\n }); // Save sorting\n\n\n this.save();\n }\n }\n }\n\n this._nulling();\n },\n _nulling: function _nulling() {\n pluginEvent('nulling', this);\n rootEl = dragEl = parentEl = ghostEl = nextEl = cloneEl = lastDownEl = cloneHidden = tapEvt = touchEvt = moved = newIndex = newDraggableIndex = oldIndex = oldDraggableIndex = lastTarget = lastDirection = putSortable = activeGroup = Sortable.dragged = Sortable.ghost = Sortable.clone = Sortable.active = null;\n savedInputChecked.forEach(function (el) {\n el.checked = true;\n });\n savedInputChecked.length = lastDx = lastDy = 0;\n },\n handleEvent: function handleEvent(\n /**Event*/\n evt) {\n switch (evt.type) {\n case 'drop':\n case 'dragend':\n this._onDrop(evt);\n\n break;\n\n case 'dragenter':\n case 'dragover':\n if (dragEl) {\n this._onDragOver(evt);\n\n _globalDragOver(evt);\n }\n\n break;\n\n case 'selectstart':\n evt.preventDefault();\n break;\n }\n },\n\n /**\n * Serializes the item into an array of string.\n * @returns {String[]}\n */\n toArray: function toArray() {\n var order = [],\n el,\n children = this.el.children,\n i = 0,\n n = children.length,\n options = this.options;\n\n for (; i < n; i++) {\n el = children[i];\n\n if (closest(el, options.draggable, this.el, false)) {\n order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));\n }\n }\n\n return order;\n },\n\n /**\n * Sorts the elements according to the array.\n * @param {String[]} order order of the items\n */\n sort: function sort(order) {\n var items = {},\n rootEl = this.el;\n this.toArray().forEach(function (id, i) {\n var el = rootEl.children[i];\n\n if (closest(el, this.options.draggable, rootEl, false)) {\n items[id] = el;\n }\n }, this);\n order.forEach(function (id) {\n if (items[id]) {\n rootEl.removeChild(items[id]);\n rootEl.appendChild(items[id]);\n }\n });\n },\n\n /**\n * Save the current sorting\n */\n save: function save() {\n var store = this.options.store;\n store && store.set && store.set(this);\n },\n\n /**\n * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.\n * @param {HTMLElement} el\n * @param {String} [selector] default: `options.draggable`\n * @returns {HTMLElement|null}\n */\n closest: function closest$1(el, selector) {\n return closest(el, selector || this.options.draggable, this.el, false);\n },\n\n /**\n * Set/get option\n * @param {string} name\n * @param {*} [value]\n * @returns {*}\n */\n option: function option(name, value) {\n var options = this.options;\n\n if (value === void 0) {\n return options[name];\n } else {\n var modifiedValue = PluginManager.modifyOption(this, name, value);\n\n if (typeof modifiedValue !== 'undefined') {\n options[name] = modifiedValue;\n } else {\n options[name] = value;\n }\n\n if (name === 'group') {\n _prepareGroup(options);\n }\n }\n },\n\n /**\n * Destroy\n */\n destroy: function destroy() {\n pluginEvent('destroy', this);\n var el = this.el;\n el[expando] = null;\n off(el, 'mousedown', this._onTapStart);\n off(el, 'touchstart', this._onTapStart);\n off(el, 'pointerdown', this._onTapStart);\n\n if (this.nativeDraggable) {\n off(el, 'dragover', this);\n off(el, 'dragenter', this);\n } // Remove draggable attributes\n\n\n Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {\n el.removeAttribute('draggable');\n });\n\n this._onDrop();\n\n this._disableDelayedDragEvents();\n\n sortables.splice(sortables.indexOf(this.el), 1);\n this.el = el = null;\n },\n _hideClone: function _hideClone() {\n if (!cloneHidden) {\n pluginEvent('hideClone', this);\n if (Sortable.eventCanceled) return;\n css(cloneEl, 'display', 'none');\n\n if (this.options.removeCloneOnHide && cloneEl.parentNode) {\n cloneEl.parentNode.removeChild(cloneEl);\n }\n\n cloneHidden = true;\n }\n },\n _showClone: function _showClone(putSortable) {\n if (putSortable.lastPutMode !== 'clone') {\n this._hideClone();\n\n return;\n }\n\n if (cloneHidden) {\n pluginEvent('showClone', this);\n if (Sortable.eventCanceled) return; // show clone at dragEl or original position\n\n if (rootEl.contains(dragEl) && !this.options.group.revertClone) {\n rootEl.insertBefore(cloneEl, dragEl);\n } else if (nextEl) {\n rootEl.insertBefore(cloneEl, nextEl);\n } else {\n rootEl.appendChild(cloneEl);\n }\n\n if (this.options.group.revertClone) {\n this.animate(dragEl, cloneEl);\n }\n\n css(cloneEl, 'display', '');\n cloneHidden = false;\n }\n }\n};\n\nfunction _globalDragOver(\n/**Event*/\nevt) {\n if (evt.dataTransfer) {\n evt.dataTransfer.dropEffect = 'move';\n }\n\n evt.cancelable && evt.preventDefault();\n}\n\nfunction _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvent, willInsertAfter) {\n var evt,\n sortable = fromEl[expando],\n onMoveFn = sortable.options.onMove,\n retVal; // Support for new CustomEvent feature\n\n if (window.CustomEvent && !IE11OrLess && !Edge) {\n evt = new CustomEvent('move', {\n bubbles: true,\n cancelable: true\n });\n } else {\n evt = document.createEvent('Event');\n evt.initEvent('move', true, true);\n }\n\n evt.to = toEl;\n evt.from = fromEl;\n evt.dragged = dragEl;\n evt.draggedRect = dragRect;\n evt.related = targetEl || toEl;\n evt.relatedRect = targetRect || getRect(toEl);\n evt.willInsertAfter = willInsertAfter;\n evt.originalEvent = originalEvent;\n fromEl.dispatchEvent(evt);\n\n if (onMoveFn) {\n retVal = onMoveFn.call(sortable, evt, originalEvent);\n }\n\n return retVal;\n}\n\nfunction _disableDraggable(el) {\n el.draggable = false;\n}\n\nfunction _unsilent() {\n _silent = false;\n}\n\nfunction _ghostIsLast(evt, vertical, sortable) {\n var rect = getRect(lastChild(sortable.el, sortable.options.draggable));\n var spacer = 10;\n return vertical ? evt.clientX > rect.right + spacer || evt.clientX <= rect.right && evt.clientY > rect.bottom && evt.clientX >= rect.left : evt.clientX > rect.right && evt.clientY > rect.top || evt.clientX <= rect.right && evt.clientY > rect.bottom + spacer;\n}\n\nfunction _getSwapDirection(evt, target, targetRect, vertical, swapThreshold, invertedSwapThreshold, invertSwap, isLastTarget) {\n var mouseOnAxis = vertical ? evt.clientY : evt.clientX,\n targetLength = vertical ? targetRect.height : targetRect.width,\n targetS1 = vertical ? targetRect.top : targetRect.left,\n targetS2 = vertical ? targetRect.bottom : targetRect.right,\n invert = false;\n\n if (!invertSwap) {\n // Never invert or create dragEl shadow when target movemenet causes mouse to move past the end of regular swapThreshold\n if (isLastTarget && targetMoveDistance < targetLength * swapThreshold) {\n // multiplied only by swapThreshold because mouse will already be inside target by (1 - threshold) * targetLength / 2\n // check if past first invert threshold on side opposite of lastDirection\n if (!pastFirstInvertThresh && (lastDirection === 1 ? mouseOnAxis > targetS1 + targetLength * invertedSwapThreshold / 2 : mouseOnAxis < targetS2 - targetLength * invertedSwapThreshold / 2)) {\n // past first invert threshold, do not restrict inverted threshold to dragEl shadow\n pastFirstInvertThresh = true;\n }\n\n if (!pastFirstInvertThresh) {\n // dragEl shadow (target move distance shadow)\n if (lastDirection === 1 ? mouseOnAxis < targetS1 + targetMoveDistance // over dragEl shadow\n : mouseOnAxis > targetS2 - targetMoveDistance) {\n return -lastDirection;\n }\n } else {\n invert = true;\n }\n } else {\n // Regular\n if (mouseOnAxis > targetS1 + targetLength * (1 - swapThreshold) / 2 && mouseOnAxis < targetS2 - targetLength * (1 - swapThreshold) / 2) {\n return _getInsertDirection(target);\n }\n }\n }\n\n invert = invert || invertSwap;\n\n if (invert) {\n // Invert of regular\n if (mouseOnAxis < targetS1 + targetLength * invertedSwapThreshold / 2 || mouseOnAxis > targetS2 - targetLength * invertedSwapThreshold / 2) {\n return mouseOnAxis > targetS1 + targetLength / 2 ? 1 : -1;\n }\n }\n\n return 0;\n}\n/**\n * Gets the direction dragEl must be swapped relative to target in order to make it\n * seem that dragEl has been \"inserted\" into that element's position\n * @param {HTMLElement} target The target whose position dragEl is being inserted at\n * @return {Number} Direction dragEl must be swapped\n */\n\n\nfunction _getInsertDirection(target) {\n if (index(dragEl) < index(target)) {\n return 1;\n } else {\n return -1;\n }\n}\n/**\n * Generate id\n * @param {HTMLElement} el\n * @returns {String}\n * @private\n */\n\n\nfunction _generateId(el) {\n var str = el.tagName + el.className + el.src + el.href + el.textContent,\n i = str.length,\n sum = 0;\n\n while (i--) {\n sum += str.charCodeAt(i);\n }\n\n return sum.toString(36);\n}\n\nfunction _saveInputCheckedState(root) {\n savedInputChecked.length = 0;\n var inputs = root.getElementsByTagName('input');\n var idx = inputs.length;\n\n while (idx--) {\n var el = inputs[idx];\n el.checked && savedInputChecked.push(el);\n }\n}\n\nfunction _nextTick(fn) {\n return setTimeout(fn, 0);\n}\n\nfunction _cancelNextTick(id) {\n return clearTimeout(id);\n} // Fixed #973:\n\n\nif (documentExists) {\n on(document, 'touchmove', function (evt) {\n if ((Sortable.active || awaitingDragStarted) && evt.cancelable) {\n evt.preventDefault();\n }\n });\n} // Export utils\n\n\nSortable.utils = {\n on: on,\n off: off,\n css: css,\n find: find,\n is: function is(el, selector) {\n return !!closest(el, selector, el, false);\n },\n extend: extend,\n throttle: throttle,\n closest: closest,\n toggleClass: toggleClass,\n clone: clone,\n index: index,\n nextTick: _nextTick,\n cancelNextTick: _cancelNextTick,\n detectDirection: _detectDirection,\n getChild: getChild\n};\n/**\n * Get the Sortable instance of an element\n * @param {HTMLElement} element The element\n * @return {Sortable|undefined} The instance of Sortable\n */\n\nSortable.get = function (element) {\n return element[expando];\n};\n/**\n * Mount a plugin to Sortable\n * @param {...SortablePlugin|SortablePlugin[]} plugins Plugins being mounted\n */\n\n\nSortable.mount = function () {\n for (var _len = arguments.length, plugins = new Array(_len), _key = 0; _key < _len; _key++) {\n plugins[_key] = arguments[_key];\n }\n\n if (plugins[0].constructor === Array) plugins = plugins[0];\n plugins.forEach(function (plugin) {\n if (!plugin.prototype || !plugin.prototype.constructor) {\n throw \"Sortable: Mounted plugin must be a constructor function, not \".concat({}.toString.call(plugin));\n }\n\n if (plugin.utils) Sortable.utils = _objectSpread({}, Sortable.utils, plugin.utils);\n PluginManager.mount(plugin);\n });\n};\n/**\n * Create sortable instance\n * @param {HTMLElement} el\n * @param {Object} [options]\n */\n\n\nSortable.create = function (el, options) {\n return new Sortable(el, options);\n}; // Export\n\n\nSortable.version = version;\n\nvar autoScrolls = [],\n scrollEl,\n scrollRootEl,\n scrolling = false,\n lastAutoScrollX,\n lastAutoScrollY,\n touchEvt$1,\n pointerElemChangedInterval;\n\nfunction AutoScrollPlugin() {\n function AutoScroll() {\n this.defaults = {\n scroll: true,\n scrollSensitivity: 30,\n scrollSpeed: 10,\n bubbleScroll: true\n }; // Bind all private methods\n\n for (var fn in this) {\n if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {\n this[fn] = this[fn].bind(this);\n }\n }\n }\n\n AutoScroll.prototype = {\n dragStarted: function dragStarted(_ref) {\n var originalEvent = _ref.originalEvent;\n\n if (this.sortable.nativeDraggable) {\n on(document, 'dragover', this._handleAutoScroll);\n } else {\n if (this.options.supportPointer) {\n on(document, 'pointermove', this._handleFallbackAutoScroll);\n } else if (originalEvent.touches) {\n on(document, 'touchmove', this._handleFallbackAutoScroll);\n } else {\n on(document, 'mousemove', this._handleFallbackAutoScroll);\n }\n }\n },\n dragOverCompleted: function dragOverCompleted(_ref2) {\n var originalEvent = _ref2.originalEvent;\n\n // For when bubbling is canceled and using fallback (fallback 'touchmove' always reached)\n if (!this.options.dragOverBubble && !originalEvent.rootEl) {\n this._handleAutoScroll(originalEvent);\n }\n },\n drop: function drop() {\n if (this.sortable.nativeDraggable) {\n off(document, 'dragover', this._handleAutoScroll);\n } else {\n off(document, 'pointermove', this._handleFallbackAutoScroll);\n off(document, 'touchmove', this._handleFallbackAutoScroll);\n off(document, 'mousemove', this._handleFallbackAutoScroll);\n }\n\n clearPointerElemChangedInterval();\n clearAutoScrolls();\n cancelThrottle();\n },\n nulling: function nulling() {\n touchEvt$1 = scrollRootEl = scrollEl = scrolling = pointerElemChangedInterval = lastAutoScrollX = lastAutoScrollY = null;\n autoScrolls.length = 0;\n },\n _handleFallbackAutoScroll: function _handleFallbackAutoScroll(evt) {\n this._handleAutoScroll(evt, true);\n },\n _handleAutoScroll: function _handleAutoScroll(evt, fallback) {\n var _this = this;\n\n var x = (evt.touches ? evt.touches[0] : evt).clientX,\n y = (evt.touches ? evt.touches[0] : evt).clientY,\n elem = document.elementFromPoint(x, y);\n touchEvt$1 = evt; // IE does not seem to have native autoscroll,\n // Edge's autoscroll seems too conditional,\n // MACOS Safari does not have autoscroll,\n // Firefox and Chrome are good\n\n if (fallback || Edge || IE11OrLess || Safari) {\n autoScroll(evt, this.options, elem, fallback); // Listener for pointer element change\n\n var ogElemScroller = getParentAutoScrollElement(elem, true);\n\n if (scrolling && (!pointerElemChangedInterval || x !== lastAutoScrollX || y !== lastAutoScrollY)) {\n pointerElemChangedInterval && clearPointerElemChangedInterval(); // Detect for pointer elem change, emulating native DnD behaviour\n\n pointerElemChangedInterval = setInterval(function () {\n var newElem = getParentAutoScrollElement(document.elementFromPoint(x, y), true);\n\n if (newElem !== ogElemScroller) {\n ogElemScroller = newElem;\n clearAutoScrolls();\n }\n\n autoScroll(evt, _this.options, newElem, fallback);\n }, 10);\n lastAutoScrollX = x;\n lastAutoScrollY = y;\n }\n } else {\n // if DnD is enabled (and browser has good autoscrolling), first autoscroll will already scroll, so get parent autoscroll of first autoscroll\n if (!this.options.bubbleScroll || getParentAutoScrollElement(elem, true) === getWindowScrollingElement()) {\n clearAutoScrolls();\n return;\n }\n\n autoScroll(evt, this.options, getParentAutoScrollElement(elem, false), false);\n }\n }\n };\n return _extends(AutoScroll, {\n pluginName: 'scroll',\n initializeByDefault: true\n });\n}\n\nfunction clearAutoScrolls() {\n autoScrolls.forEach(function (autoScroll) {\n clearInterval(autoScroll.pid);\n });\n autoScrolls = [];\n}\n\nfunction clearPointerElemChangedInterval() {\n clearInterval(pointerElemChangedInterval);\n}\n\nvar autoScroll = throttle(function (evt, options, rootEl, isFallback) {\n // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521\n if (!options.scroll) return;\n var x = (evt.touches ? evt.touches[0] : evt).clientX,\n y = (evt.touches ? evt.touches[0] : evt).clientY,\n sens = options.scrollSensitivity,\n speed = options.scrollSpeed,\n winScroller = getWindowScrollingElement();\n var scrollThisInstance = false,\n scrollCustomFn; // New scroll root, set scrollEl\n\n if (scrollRootEl !== rootEl) {\n scrollRootEl = rootEl;\n clearAutoScrolls();\n scrollEl = options.scroll;\n scrollCustomFn = options.scrollFn;\n\n if (scrollEl === true) {\n scrollEl = getParentAutoScrollElement(rootEl, true);\n }\n }\n\n var layersOut = 0;\n var currentParent = scrollEl;\n\n do {\n var el = currentParent,\n rect = getRect(el),\n top = rect.top,\n bottom = rect.bottom,\n left = rect.left,\n right = rect.right,\n width = rect.width,\n height = rect.height,\n canScrollX = void 0,\n canScrollY = void 0,\n scrollWidth = el.scrollWidth,\n scrollHeight = el.scrollHeight,\n elCSS = css(el),\n scrollPosX = el.scrollLeft,\n scrollPosY = el.scrollTop;\n\n if (el === winScroller) {\n canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll' || elCSS.overflowX === 'visible');\n canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll' || elCSS.overflowY === 'visible');\n } else {\n canScrollX = width < scrollWidth && (elCSS.overflowX === 'auto' || elCSS.overflowX === 'scroll');\n canScrollY = height < scrollHeight && (elCSS.overflowY === 'auto' || elCSS.overflowY === 'scroll');\n }\n\n var vx = canScrollX && (Math.abs(right - x) <= sens && scrollPosX + width < scrollWidth) - (Math.abs(left - x) <= sens && !!scrollPosX);\n var vy = canScrollY && (Math.abs(bottom - y) <= sens && scrollPosY + height < scrollHeight) - (Math.abs(top - y) <= sens && !!scrollPosY);\n\n if (!autoScrolls[layersOut]) {\n for (var i = 0; i <= layersOut; i++) {\n if (!autoScrolls[i]) {\n autoScrolls[i] = {};\n }\n }\n }\n\n if (autoScrolls[layersOut].vx != vx || autoScrolls[layersOut].vy != vy || autoScrolls[layersOut].el !== el) {\n autoScrolls[layersOut].el = el;\n autoScrolls[layersOut].vx = vx;\n autoScrolls[layersOut].vy = vy;\n clearInterval(autoScrolls[layersOut].pid);\n\n if (vx != 0 || vy != 0) {\n scrollThisInstance = true;\n /* jshint loopfunc:true */\n\n autoScrolls[layersOut].pid = setInterval(function () {\n // emulate drag over during autoscroll (fallback), emulating native DnD behaviour\n if (isFallback && this.layer === 0) {\n Sortable.active._onTouchMove(touchEvt$1); // To move ghost if it is positioned absolutely\n\n }\n\n var scrollOffsetY = autoScrolls[this.layer].vy ? autoScrolls[this.layer].vy * speed : 0;\n var scrollOffsetX = autoScrolls[this.layer].vx ? autoScrolls[this.layer].vx * speed : 0;\n\n if (typeof scrollCustomFn === 'function') {\n if (scrollCustomFn.call(Sortable.dragged.parentNode[expando], scrollOffsetX, scrollOffsetY, evt, touchEvt$1, autoScrolls[this.layer].el) !== 'continue') {\n return;\n }\n }\n\n scrollBy(autoScrolls[this.layer].el, scrollOffsetX, scrollOffsetY);\n }.bind({\n layer: layersOut\n }), 24);\n }\n }\n\n layersOut++;\n } while (options.bubbleScroll && currentParent !== winScroller && (currentParent = getParentAutoScrollElement(currentParent, false)));\n\n scrolling = scrollThisInstance; // in case another function catches scrolling as false in between when it is not\n}, 30);\n\nvar drop = function drop(_ref) {\n var originalEvent = _ref.originalEvent,\n putSortable = _ref.putSortable,\n dragEl = _ref.dragEl,\n activeSortable = _ref.activeSortable,\n dispatchSortableEvent = _ref.dispatchSortableEvent,\n hideGhostForTarget = _ref.hideGhostForTarget,\n unhideGhostForTarget = _ref.unhideGhostForTarget;\n if (!originalEvent) return;\n var toSortable = putSortable || activeSortable;\n hideGhostForTarget();\n var touch = originalEvent.changedTouches && originalEvent.changedTouches.length ? originalEvent.changedTouches[0] : originalEvent;\n var target = document.elementFromPoint(touch.clientX, touch.clientY);\n unhideGhostForTarget();\n\n if (toSortable && !toSortable.el.contains(target)) {\n dispatchSortableEvent('spill');\n this.onSpill({\n dragEl: dragEl,\n putSortable: putSortable\n });\n }\n};\n\nfunction Revert() {}\n\nRevert.prototype = {\n startIndex: null,\n dragStart: function dragStart(_ref2) {\n var oldDraggableIndex = _ref2.oldDraggableIndex;\n this.startIndex = oldDraggableIndex;\n },\n onSpill: function onSpill(_ref3) {\n var dragEl = _ref3.dragEl,\n putSortable = _ref3.putSortable;\n this.sortable.captureAnimationState();\n\n if (putSortable) {\n putSortable.captureAnimationState();\n }\n\n var nextSibling = getChild(this.sortable.el, this.startIndex, this.options);\n\n if (nextSibling) {\n this.sortable.el.insertBefore(dragEl, nextSibling);\n } else {\n this.sortable.el.appendChild(dragEl);\n }\n\n this.sortable.animateAll();\n\n if (putSortable) {\n putSortable.animateAll();\n }\n },\n drop: drop\n};\n\n_extends(Revert, {\n pluginName: 'revertOnSpill'\n});\n\nfunction Remove() {}\n\nRemove.prototype = {\n onSpill: function onSpill(_ref4) {\n var dragEl = _ref4.dragEl,\n putSortable = _ref4.putSortable;\n var parentSortable = putSortable || this.sortable;\n parentSortable.captureAnimationState();\n dragEl.parentNode && dragEl.parentNode.removeChild(dragEl);\n parentSortable.animateAll();\n },\n drop: drop\n};\n\n_extends(Remove, {\n pluginName: 'removeOnSpill'\n});\n\nvar lastSwapEl;\n\nfunction SwapPlugin() {\n function Swap() {\n this.defaults = {\n swapClass: 'sortable-swap-highlight'\n };\n }\n\n Swap.prototype = {\n dragStart: function dragStart(_ref) {\n var dragEl = _ref.dragEl;\n lastSwapEl = dragEl;\n },\n dragOverValid: function dragOverValid(_ref2) {\n var completed = _ref2.completed,\n target = _ref2.target,\n onMove = _ref2.onMove,\n activeSortable = _ref2.activeSortable,\n changed = _ref2.changed,\n cancel = _ref2.cancel;\n if (!activeSortable.options.swap) return;\n var el = this.sortable.el,\n options = this.options;\n\n if (target && target !== el) {\n var prevSwapEl = lastSwapEl;\n\n if (onMove(target) !== false) {\n toggleClass(target, options.swapClass, true);\n lastSwapEl = target;\n } else {\n lastSwapEl = null;\n }\n\n if (prevSwapEl && prevSwapEl !== lastSwapEl) {\n toggleClass(prevSwapEl, options.swapClass, false);\n }\n }\n\n changed();\n completed(true);\n cancel();\n },\n drop: function drop(_ref3) {\n var activeSortable = _ref3.activeSortable,\n putSortable = _ref3.putSortable,\n dragEl = _ref3.dragEl;\n var toSortable = putSortable || this.sortable;\n var options = this.options;\n lastSwapEl && toggleClass(lastSwapEl, options.swapClass, false);\n\n if (lastSwapEl && (options.swap || putSortable && putSortable.options.swap)) {\n if (dragEl !== lastSwapEl) {\n toSortable.captureAnimationState();\n if (toSortable !== activeSortable) activeSortable.captureAnimationState();\n swapNodes(dragEl, lastSwapEl);\n toSortable.animateAll();\n if (toSortable !== activeSortable) activeSortable.animateAll();\n }\n }\n },\n nulling: function nulling() {\n lastSwapEl = null;\n }\n };\n return _extends(Swap, {\n pluginName: 'swap',\n eventProperties: function eventProperties() {\n return {\n swapItem: lastSwapEl\n };\n }\n });\n}\n\nfunction swapNodes(n1, n2) {\n var p1 = n1.parentNode,\n p2 = n2.parentNode,\n i1,\n i2;\n if (!p1 || !p2 || p1.isEqualNode(n2) || p2.isEqualNode(n1)) return;\n i1 = index(n1);\n i2 = index(n2);\n\n if (p1.isEqualNode(p2) && i1 < i2) {\n i2++;\n }\n\n p1.insertBefore(n2, p1.children[i1]);\n p2.insertBefore(n1, p2.children[i2]);\n}\n\nvar multiDragElements = [],\n multiDragClones = [],\n lastMultiDragSelect,\n // for selection with modifier key down (SHIFT)\nmultiDragSortable,\n initialFolding = false,\n // Initial multi-drag fold when drag started\nfolding = false,\n // Folding any other time\ndragStarted = false,\n dragEl$1,\n clonesFromRect,\n clonesHidden;\n\nfunction MultiDragPlugin() {\n function MultiDrag(sortable) {\n // Bind all private methods\n for (var fn in this) {\n if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {\n this[fn] = this[fn].bind(this);\n }\n }\n\n if (sortable.options.supportPointer) {\n on(document, 'pointerup', this._deselectMultiDrag);\n } else {\n on(document, 'mouseup', this._deselectMultiDrag);\n on(document, 'touchend', this._deselectMultiDrag);\n }\n\n on(document, 'keydown', this._checkKeyDown);\n on(document, 'keyup', this._checkKeyUp);\n this.defaults = {\n selectedClass: 'sortable-selected',\n multiDragKey: null,\n setData: function setData(dataTransfer, dragEl) {\n var data = '';\n\n if (multiDragElements.length && multiDragSortable === sortable) {\n multiDragElements.forEach(function (multiDragElement, i) {\n data += (!i ? '' : ', ') + multiDragElement.textContent;\n });\n } else {\n data = dragEl.textContent;\n }\n\n dataTransfer.setData('Text', data);\n }\n };\n }\n\n MultiDrag.prototype = {\n multiDragKeyDown: false,\n isMultiDrag: false,\n delayStartGlobal: function delayStartGlobal(_ref) {\n var dragged = _ref.dragEl;\n dragEl$1 = dragged;\n },\n delayEnded: function delayEnded() {\n this.isMultiDrag = ~multiDragElements.indexOf(dragEl$1);\n },\n setupClone: function setupClone(_ref2) {\n var sortable = _ref2.sortable,\n cancel = _ref2.cancel;\n if (!this.isMultiDrag) return;\n\n for (var i = 0; i < multiDragElements.length; i++) {\n multiDragClones.push(clone(multiDragElements[i]));\n multiDragClones[i].sortableIndex = multiDragElements[i].sortableIndex;\n multiDragClones[i].draggable = false;\n multiDragClones[i].style['will-change'] = '';\n toggleClass(multiDragClones[i], this.options.selectedClass, false);\n multiDragElements[i] === dragEl$1 && toggleClass(multiDragClones[i], this.options.chosenClass, false);\n }\n\n sortable._hideClone();\n\n cancel();\n },\n clone: function clone(_ref3) {\n var sortable = _ref3.sortable,\n rootEl = _ref3.rootEl,\n dispatchSortableEvent = _ref3.dispatchSortableEvent,\n cancel = _ref3.cancel;\n if (!this.isMultiDrag) return;\n\n if (!this.options.removeCloneOnHide) {\n if (multiDragElements.length && multiDragSortable === sortable) {\n insertMultiDragClones(true, rootEl);\n dispatchSortableEvent('clone');\n cancel();\n }\n }\n },\n showClone: function showClone(_ref4) {\n var cloneNowShown = _ref4.cloneNowShown,\n rootEl = _ref4.rootEl,\n cancel = _ref4.cancel;\n if (!this.isMultiDrag) return;\n insertMultiDragClones(false, rootEl);\n multiDragClones.forEach(function (clone) {\n css(clone, 'display', '');\n });\n cloneNowShown();\n clonesHidden = false;\n cancel();\n },\n hideClone: function hideClone(_ref5) {\n var _this = this;\n\n var sortable = _ref5.sortable,\n cloneNowHidden = _ref5.cloneNowHidden,\n cancel = _ref5.cancel;\n if (!this.isMultiDrag) return;\n multiDragClones.forEach(function (clone) {\n css(clone, 'display', 'none');\n\n if (_this.options.removeCloneOnHide && clone.parentNode) {\n clone.parentNode.removeChild(clone);\n }\n });\n cloneNowHidden();\n clonesHidden = true;\n cancel();\n },\n dragStartGlobal: function dragStartGlobal(_ref6) {\n var sortable = _ref6.sortable;\n\n if (!this.isMultiDrag && multiDragSortable) {\n multiDragSortable.multiDrag._deselectMultiDrag();\n }\n\n multiDragElements.forEach(function (multiDragElement) {\n multiDragElement.sortableIndex = index(multiDragElement);\n }); // Sort multi-drag elements\n\n multiDragElements = multiDragElements.sort(function (a, b) {\n return a.sortableIndex - b.sortableIndex;\n });\n dragStarted = true;\n },\n dragStarted: function dragStarted(_ref7) {\n var _this2 = this;\n\n var sortable = _ref7.sortable;\n if (!this.isMultiDrag) return;\n\n if (this.options.sort) {\n // Capture rects,\n // hide multi drag elements (by positioning them absolute),\n // set multi drag elements rects to dragRect,\n // show multi drag elements,\n // animate to rects,\n // unset rects & remove from DOM\n sortable.captureAnimationState();\n\n if (this.options.animation) {\n multiDragElements.forEach(function (multiDragElement) {\n if (multiDragElement === dragEl$1) return;\n css(multiDragElement, 'position', 'absolute');\n });\n var dragRect = getRect(dragEl$1, false, true, true);\n multiDragElements.forEach(function (multiDragElement) {\n if (multiDragElement === dragEl$1) return;\n setRect(multiDragElement, dragRect);\n });\n folding = true;\n initialFolding = true;\n }\n }\n\n sortable.animateAll(function () {\n folding = false;\n initialFolding = false;\n\n if (_this2.options.animation) {\n multiDragElements.forEach(function (multiDragElement) {\n unsetRect(multiDragElement);\n });\n } // Remove all auxiliary multidrag items from el, if sorting enabled\n\n\n if (_this2.options.sort) {\n removeMultiDragElements();\n }\n });\n },\n dragOver: function dragOver(_ref8) {\n var target = _ref8.target,\n completed = _ref8.completed,\n cancel = _ref8.cancel;\n\n if (folding && ~multiDragElements.indexOf(target)) {\n completed(false);\n cancel();\n }\n },\n revert: function revert(_ref9) {\n var fromSortable = _ref9.fromSortable,\n rootEl = _ref9.rootEl,\n sortable = _ref9.sortable,\n dragRect = _ref9.dragRect;\n\n if (multiDragElements.length > 1) {\n // Setup unfold animation\n multiDragElements.forEach(function (multiDragElement) {\n sortable.addAnimationState({\n target: multiDragElement,\n rect: folding ? getRect(multiDragElement) : dragRect\n });\n unsetRect(multiDragElement);\n multiDragElement.fromRect = dragRect;\n fromSortable.removeAnimationState(multiDragElement);\n });\n folding = false;\n insertMultiDragElements(!this.options.removeCloneOnHide, rootEl);\n }\n },\n dragOverCompleted: function dragOverCompleted(_ref10) {\n var sortable = _ref10.sortable,\n isOwner = _ref10.isOwner,\n insertion = _ref10.insertion,\n activeSortable = _ref10.activeSortable,\n parentEl = _ref10.parentEl,\n putSortable = _ref10.putSortable;\n var options = this.options;\n\n if (insertion) {\n // Clones must be hidden before folding animation to capture dragRectAbsolute properly\n if (isOwner) {\n activeSortable._hideClone();\n }\n\n initialFolding = false; // If leaving sort:false root, or already folding - Fold to new location\n\n if (options.animation && multiDragElements.length > 1 && (folding || !isOwner && !activeSortable.options.sort && !putSortable)) {\n // Fold: Set all multi drag elements's rects to dragEl's rect when multi-drag elements are invisible\n var dragRectAbsolute = getRect(dragEl$1, false, true, true);\n multiDragElements.forEach(function (multiDragElement) {\n if (multiDragElement === dragEl$1) return;\n setRect(multiDragElement, dragRectAbsolute); // Move element(s) to end of parentEl so that it does not interfere with multi-drag clones insertion if they are inserted\n // while folding, and so that we can capture them again because old sortable will no longer be fromSortable\n\n parentEl.appendChild(multiDragElement);\n });\n folding = true;\n } // Clones must be shown (and check to remove multi drags) after folding when interfering multiDragElements are moved out\n\n\n if (!isOwner) {\n // Only remove if not folding (folding will remove them anyways)\n if (!folding) {\n removeMultiDragElements();\n }\n\n if (multiDragElements.length > 1) {\n var clonesHiddenBefore = clonesHidden;\n\n activeSortable._showClone(sortable); // Unfold animation for clones if showing from hidden\n\n\n if (activeSortable.options.animation && !clonesHidden && clonesHiddenBefore) {\n multiDragClones.forEach(function (clone) {\n activeSortable.addAnimationState({\n target: clone,\n rect: clonesFromRect\n });\n clone.fromRect = clonesFromRect;\n clone.thisAnimationDuration = null;\n });\n }\n } else {\n activeSortable._showClone(sortable);\n }\n }\n }\n },\n dragOverAnimationCapture: function dragOverAnimationCapture(_ref11) {\n var dragRect = _ref11.dragRect,\n isOwner = _ref11.isOwner,\n activeSortable = _ref11.activeSortable;\n multiDragElements.forEach(function (multiDragElement) {\n multiDragElement.thisAnimationDuration = null;\n });\n\n if (activeSortable.options.animation && !isOwner && activeSortable.multiDrag.isMultiDrag) {\n clonesFromRect = _extends({}, dragRect);\n var dragMatrix = matrix(dragEl$1, true);\n clonesFromRect.top -= dragMatrix.f;\n clonesFromRect.left -= dragMatrix.e;\n }\n },\n dragOverAnimationComplete: function dragOverAnimationComplete() {\n if (folding) {\n folding = false;\n removeMultiDragElements();\n }\n },\n drop: function drop(_ref12) {\n var evt = _ref12.originalEvent,\n rootEl = _ref12.rootEl,\n parentEl = _ref12.parentEl,\n sortable = _ref12.sortable,\n dispatchSortableEvent = _ref12.dispatchSortableEvent,\n oldIndex = _ref12.oldIndex,\n putSortable = _ref12.putSortable;\n var toSortable = putSortable || this.sortable;\n if (!evt) return;\n var options = this.options,\n children = parentEl.children; // Multi-drag selection\n\n if (!dragStarted) {\n if (options.multiDragKey && !this.multiDragKeyDown) {\n this._deselectMultiDrag();\n }\n\n toggleClass(dragEl$1, options.selectedClass, !~multiDragElements.indexOf(dragEl$1));\n\n if (!~multiDragElements.indexOf(dragEl$1)) {\n multiDragElements.push(dragEl$1);\n dispatchEvent({\n sortable: sortable,\n rootEl: rootEl,\n name: 'select',\n targetEl: dragEl$1,\n originalEvt: evt\n }); // Modifier activated, select from last to dragEl\n\n if (evt.shiftKey && lastMultiDragSelect && sortable.el.contains(lastMultiDragSelect)) {\n var lastIndex = index(lastMultiDragSelect),\n currentIndex = index(dragEl$1);\n\n if (~lastIndex && ~currentIndex && lastIndex !== currentIndex) {\n // Must include lastMultiDragSelect (select it), in case modified selection from no selection\n // (but previous selection existed)\n var n, i;\n\n if (currentIndex > lastIndex) {\n i = lastIndex;\n n = currentIndex;\n } else {\n i = currentIndex;\n n = lastIndex + 1;\n }\n\n for (; i < n; i++) {\n if (~multiDragElements.indexOf(children[i])) continue;\n toggleClass(children[i], options.selectedClass, true);\n multiDragElements.push(children[i]);\n dispatchEvent({\n sortable: sortable,\n rootEl: rootEl,\n name: 'select',\n targetEl: children[i],\n originalEvt: evt\n });\n }\n }\n } else {\n lastMultiDragSelect = dragEl$1;\n }\n\n multiDragSortable = toSortable;\n } else {\n multiDragElements.splice(multiDragElements.indexOf(dragEl$1), 1);\n lastMultiDragSelect = null;\n dispatchEvent({\n sortable: sortable,\n rootEl: rootEl,\n name: 'deselect',\n targetEl: dragEl$1,\n originalEvt: evt\n });\n }\n } // Multi-drag drop\n\n\n if (dragStarted && this.isMultiDrag) {\n // Do not \"unfold\" after around dragEl if reverted\n if ((parentEl[expando].options.sort || parentEl !== rootEl) && multiDragElements.length > 1) {\n var dragRect = getRect(dragEl$1),\n multiDragIndex = index(dragEl$1, ':not(.' + this.options.selectedClass + ')');\n if (!initialFolding && options.animation) dragEl$1.thisAnimationDuration = null;\n toSortable.captureAnimationState();\n\n if (!initialFolding) {\n if (options.animation) {\n dragEl$1.fromRect = dragRect;\n multiDragElements.forEach(function (multiDragElement) {\n multiDragElement.thisAnimationDuration = null;\n\n if (multiDragElement !== dragEl$1) {\n var rect = folding ? getRect(multiDragElement) : dragRect;\n multiDragElement.fromRect = rect; // Prepare unfold animation\n\n toSortable.addAnimationState({\n target: multiDragElement,\n rect: rect\n });\n }\n });\n } // Multi drag elements are not necessarily removed from the DOM on drop, so to reinsert\n // properly they must all be removed\n\n\n removeMultiDragElements();\n multiDragElements.forEach(function (multiDragElement) {\n if (children[multiDragIndex]) {\n parentEl.insertBefore(multiDragElement, children[multiDragIndex]);\n } else {\n parentEl.appendChild(multiDragElement);\n }\n\n multiDragIndex++;\n }); // If initial folding is done, the elements may have changed position because they are now\n // unfolding around dragEl, even though dragEl may not have his index changed, so update event\n // must be fired here as Sortable will not.\n\n if (oldIndex === index(dragEl$1)) {\n var update = false;\n multiDragElements.forEach(function (multiDragElement) {\n if (multiDragElement.sortableIndex !== index(multiDragElement)) {\n update = true;\n return;\n }\n });\n\n if (update) {\n dispatchSortableEvent('update');\n }\n }\n } // Must be done after capturing individual rects (scroll bar)\n\n\n multiDragElements.forEach(function (multiDragElement) {\n unsetRect(multiDragElement);\n });\n toSortable.animateAll();\n }\n\n multiDragSortable = toSortable;\n } // Remove clones if necessary\n\n\n if (rootEl === parentEl || putSortable && putSortable.lastPutMode !== 'clone') {\n multiDragClones.forEach(function (clone) {\n clone.parentNode && clone.parentNode.removeChild(clone);\n });\n }\n },\n nullingGlobal: function nullingGlobal() {\n this.isMultiDrag = dragStarted = false;\n multiDragClones.length = 0;\n },\n destroyGlobal: function destroyGlobal() {\n this._deselectMultiDrag();\n\n off(document, 'pointerup', this._deselectMultiDrag);\n off(document, 'mouseup', this._deselectMultiDrag);\n off(document, 'touchend', this._deselectMultiDrag);\n off(document, 'keydown', this._checkKeyDown);\n off(document, 'keyup', this._checkKeyUp);\n },\n _deselectMultiDrag: function _deselectMultiDrag(evt) {\n if (typeof dragStarted !== \"undefined\" && dragStarted) return; // Only deselect if selection is in this sortable\n\n if (multiDragSortable !== this.sortable) return; // Only deselect if target is not item in this sortable\n\n if (evt && closest(evt.target, this.options.draggable, this.sortable.el, false)) return; // Only deselect if left click\n\n if (evt && evt.button !== 0) return;\n\n while (multiDragElements.length) {\n var el = multiDragElements[0];\n toggleClass(el, this.options.selectedClass, false);\n multiDragElements.shift();\n dispatchEvent({\n sortable: this.sortable,\n rootEl: this.sortable.el,\n name: 'deselect',\n targetEl: el,\n originalEvt: evt\n });\n }\n },\n _checkKeyDown: function _checkKeyDown(evt) {\n if (evt.key === this.options.multiDragKey) {\n this.multiDragKeyDown = true;\n }\n },\n _checkKeyUp: function _checkKeyUp(evt) {\n if (evt.key === this.options.multiDragKey) {\n this.multiDragKeyDown = false;\n }\n }\n };\n return _extends(MultiDrag, {\n // Static methods & properties\n pluginName: 'multiDrag',\n utils: {\n /**\r\n * Selects the provided multi-drag item\r\n * @param {HTMLElement} el The element to be selected\r\n */\n select: function select(el) {\n var sortable = el.parentNode[expando];\n if (!sortable || !sortable.options.multiDrag || ~multiDragElements.indexOf(el)) return;\n\n if (multiDragSortable && multiDragSortable !== sortable) {\n multiDragSortable.multiDrag._deselectMultiDrag();\n\n multiDragSortable = sortable;\n }\n\n toggleClass(el, sortable.options.selectedClass, true);\n multiDragElements.push(el);\n },\n\n /**\r\n * Deselects the provided multi-drag item\r\n * @param {HTMLElement} el The element to be deselected\r\n */\n deselect: function deselect(el) {\n var sortable = el.parentNode[expando],\n index = multiDragElements.indexOf(el);\n if (!sortable || !sortable.options.multiDrag || !~index) return;\n toggleClass(el, sortable.options.selectedClass, false);\n multiDragElements.splice(index, 1);\n }\n },\n eventProperties: function eventProperties() {\n var _this3 = this;\n\n var oldIndicies = [],\n newIndicies = [];\n multiDragElements.forEach(function (multiDragElement) {\n oldIndicies.push({\n multiDragElement: multiDragElement,\n index: multiDragElement.sortableIndex\n }); // multiDragElements will already be sorted if folding\n\n var newIndex;\n\n if (folding && multiDragElement !== dragEl$1) {\n newIndex = -1;\n } else if (folding) {\n newIndex = index(multiDragElement, ':not(.' + _this3.options.selectedClass + ')');\n } else {\n newIndex = index(multiDragElement);\n }\n\n newIndicies.push({\n multiDragElement: multiDragElement,\n index: newIndex\n });\n });\n return {\n items: _toConsumableArray(multiDragElements),\n clones: [].concat(multiDragClones),\n oldIndicies: oldIndicies,\n newIndicies: newIndicies\n };\n },\n optionListeners: {\n multiDragKey: function multiDragKey(key) {\n key = key.toLowerCase();\n\n if (key === 'ctrl') {\n key = 'Control';\n } else if (key.length > 1) {\n key = key.charAt(0).toUpperCase() + key.substr(1);\n }\n\n return key;\n }\n }\n });\n}\n\nfunction insertMultiDragElements(clonesInserted, rootEl) {\n multiDragElements.forEach(function (multiDragElement, i) {\n var target = rootEl.children[multiDragElement.sortableIndex + (clonesInserted ? Number(i) : 0)];\n\n if (target) {\n rootEl.insertBefore(multiDragElement, target);\n } else {\n rootEl.appendChild(multiDragElement);\n }\n });\n}\n/**\r\n * Insert multi-drag clones\r\n * @param {[Boolean]} elementsInserted Whether the multi-drag elements are inserted\r\n * @param {HTMLElement} rootEl\r\n */\n\n\nfunction insertMultiDragClones(elementsInserted, rootEl) {\n multiDragClones.forEach(function (clone, i) {\n var target = rootEl.children[clone.sortableIndex + (elementsInserted ? Number(i) : 0)];\n\n if (target) {\n rootEl.insertBefore(clone, target);\n } else {\n rootEl.appendChild(clone);\n }\n });\n}\n\nfunction removeMultiDragElements() {\n multiDragElements.forEach(function (multiDragElement) {\n if (multiDragElement === dragEl$1) return;\n multiDragElement.parentNode && multiDragElement.parentNode.removeChild(multiDragElement);\n });\n}\n\nSortable.mount(new AutoScrollPlugin());\nSortable.mount(Remove, Revert);\n\n/* harmony default export */ __webpack_exports__[\"default\"] = (Sortable);\n\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL2RPMi5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9zb3J0YWJsZWpzL21vZHVsYXIvc29ydGFibGUuZXNtLmpzP2ZkZDMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqIVxuICogU29ydGFibGUgMS4xMC4yXG4gKiBAYXV0aG9yXHRSdWJhWGEgICA8dHJhc2hAcnViYXhhLm9yZz5cbiAqIEBhdXRob3JcdG93ZW5tICAgIDxvd2VuMjMzNTVAZ21haWwuY29tPlxuICogQGxpY2Vuc2UgTUlUXG4gKi9cbmZ1bmN0aW9uIF90eXBlb2Yob2JqKSB7XG4gIGlmICh0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgdHlwZW9mIFN5bWJvbC5pdGVyYXRvciA9PT0gXCJzeW1ib2xcIikge1xuICAgIF90eXBlb2YgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICByZXR1cm4gdHlwZW9mIG9iajtcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIF90eXBlb2YgPSBmdW5jdGlvbiAob2JqKSB7XG4gICAgICByZXR1cm4gb2JqICYmIHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiBvYmouY29uc3RydWN0b3IgPT09IFN5bWJvbCAmJiBvYmogIT09IFN5bWJvbC5wcm90b3R5cGUgPyBcInN5bWJvbFwiIDogdHlwZW9mIG9iajtcbiAgICB9O1xuICB9XG5cbiAgcmV0dXJuIF90eXBlb2Yob2JqKTtcbn1cblxuZnVuY3Rpb24gX2RlZmluZVByb3BlcnR5KG9iaiwga2V5LCB2YWx1ZSkge1xuICBpZiAoa2V5IGluIG9iaikge1xuICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvYmosIGtleSwge1xuICAgICAgdmFsdWU6IHZhbHVlLFxuICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSxcbiAgICAgIHdyaXRhYmxlOiB0cnVlXG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgb2JqW2tleV0gPSB2YWx1ZTtcbiAgfVxuXG4gIHJldHVybiBvYmo7XG59XG5cbmZ1bmN0aW9uIF9leHRlbmRzKCkge1xuICBfZXh0ZW5kcyA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gKHRhcmdldCkge1xuICAgIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgc291cmNlID0gYXJndW1lbnRzW2ldO1xuXG4gICAgICBmb3IgKHZhciBrZXkgaW4gc291cmNlKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoc291cmNlLCBrZXkpKSB7XG4gICAgICAgICAgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB0YXJnZXQ7XG4gIH07XG5cbiAgcmV0dXJuIF9leHRlbmRzLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5cbmZ1bmN0aW9uIF9vYmplY3RTcHJlYWQodGFyZ2V0KSB7XG4gIGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHNvdXJjZSA9IGFyZ3VtZW50c1tpXSAhPSBudWxsID8gYXJndW1lbnRzW2ldIDoge307XG4gICAgdmFyIG93bktleXMgPSBPYmplY3Qua2V5cyhzb3VyY2UpO1xuXG4gICAgaWYgKHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBvd25LZXlzID0gb3duS2V5cy5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzb3VyY2UpLmZpbHRlcihmdW5jdGlvbiAoc3ltKSB7XG4gICAgICAgIHJldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHNvdXJjZSwgc3ltKS5lbnVtZXJhYmxlO1xuICAgICAgfSkpO1xuICAgIH1cblxuICAgIG93bktleXMuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICBfZGVmaW5lUHJvcGVydHkodGFyZ2V0LCBrZXksIHNvdXJjZVtrZXldKTtcbiAgICB9KTtcbiAgfVxuXG4gIHJldHVybiB0YXJnZXQ7XG59XG5cbmZ1bmN0aW9uIF9vYmplY3RXaXRob3V0UHJvcGVydGllc0xvb3NlKHNvdXJjZSwgZXhjbHVkZWQpIHtcbiAgaWYgKHNvdXJjZSA9PSBudWxsKSByZXR1cm4ge307XG4gIHZhciB0YXJnZXQgPSB7fTtcbiAgdmFyIHNvdXJjZUtleXMgPSBPYmplY3Qua2V5cyhzb3VyY2UpO1xuICB2YXIga2V5LCBpO1xuXG4gIGZvciAoaSA9IDA7IGkgPCBzb3VyY2VLZXlzLmxlbmd0aDsgaSsrKSB7XG4gICAga2V5ID0gc291cmNlS2V5c1tpXTtcbiAgICBpZiAoZXhjbHVkZWQuaW5kZXhPZihrZXkpID49IDApIGNvbnRpbnVlO1xuICAgIHRhcmdldFtrZXldID0gc291cmNlW2tleV07XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufVxuXG5mdW5jdGlvbiBfb2JqZWN0V2l0aG91dFByb3BlcnRpZXMoc291cmNlLCBleGNsdWRlZCkge1xuICBpZiAoc291cmNlID09IG51bGwpIHJldHVybiB7fTtcblxuICB2YXIgdGFyZ2V0ID0gX29iamVjdFdpdGhvdXRQcm9wZXJ0aWVzTG9vc2Uoc291cmNlLCBleGNsdWRlZCk7XG5cbiAgdmFyIGtleSwgaTtcblxuICBpZiAoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scykge1xuICAgIHZhciBzb3VyY2VTeW1ib2xLZXlzID0gT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhzb3VyY2UpO1xuXG4gICAgZm9yIChpID0gMDsgaSA8IHNvdXJjZVN5bWJvbEtleXMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGtleSA9IHNvdXJjZVN5bWJvbEtleXNbaV07XG4gICAgICBpZiAoZXhjbHVkZWQuaW5kZXhPZihrZXkpID49IDApIGNvbnRpbnVlO1xuICAgICAgaWYgKCFPYmplY3QucHJvdG90eXBlLnByb3BlcnR5SXNFbnVtZXJhYmxlLmNhbGwoc291cmNlLCBrZXkpKSBjb250aW51ZTtcbiAgICAgIHRhcmdldFtrZXldID0gc291cmNlW2tleV07XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRhcmdldDtcbn1cblxuZnVuY3Rpb24gX3RvQ29uc3VtYWJsZUFycmF5KGFycikge1xuICByZXR1cm4gX2FycmF5V2l0aG91dEhvbGVzKGFycikgfHwgX2l0ZXJhYmxlVG9BcnJheShhcnIpIHx8IF9ub25JdGVyYWJsZVNwcmVhZCgpO1xufVxuXG5mdW5jdGlvbiBfYXJyYXlXaXRob3V0SG9sZXMoYXJyKSB7XG4gIGlmIChBcnJheS5pc0FycmF5KGFycikpIHtcbiAgICBmb3IgKHZhciBpID0gMCwgYXJyMiA9IG5ldyBBcnJheShhcnIubGVuZ3RoKTsgaSA8IGFyci5sZW5ndGg7IGkrKykgYXJyMltpXSA9IGFycltpXTtcblxuICAgIHJldHVybiBhcnIyO1xuICB9XG59XG5cbmZ1bmN0aW9uIF9pdGVyYWJsZVRvQXJyYXkoaXRlcikge1xuICBpZiAoU3ltYm9sLml0ZXJhdG9yIGluIE9iamVjdChpdGVyKSB8fCBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoaXRlcikgPT09IFwiW29iamVjdCBBcmd1bWVudHNdXCIpIHJldHVybiBBcnJheS5mcm9tKGl0ZXIpO1xufVxuXG5mdW5jdGlvbiBfbm9uSXRlcmFibGVTcHJlYWQoKSB7XG4gIHRocm93IG5ldyBUeXBlRXJyb3IoXCJJbnZhbGlkIGF0dGVtcHQgdG8gc3ByZWFkIG5vbi1pdGVyYWJsZSBpbnN0YW5jZVwiKTtcbn1cblxudmFyIHZlcnNpb24gPSBcIjEuMTAuMlwiO1xuXG5mdW5jdGlvbiB1c2VyQWdlbnQocGF0dGVybikge1xuICBpZiAodHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcgJiYgd2luZG93Lm5hdmlnYXRvcikge1xuICAgIHJldHVybiAhIVxuICAgIC8qQF9fUFVSRV9fKi9cbiAgICBuYXZpZ2F0b3IudXNlckFnZW50Lm1hdGNoKHBhdHRlcm4pO1xuICB9XG59XG5cbnZhciBJRTExT3JMZXNzID0gdXNlckFnZW50KC8oPzpUcmlkZW50LipydlsgOl0/MTFcXC58bXNpZXxpZW1vYmlsZXxXaW5kb3dzIFBob25lKS9pKTtcbnZhciBFZGdlID0gdXNlckFnZW50KC9FZGdlL2kpO1xudmFyIEZpcmVGb3ggPSB1c2VyQWdlbnQoL2ZpcmVmb3gvaSk7XG52YXIgU2FmYXJpID0gdXNlckFnZW50KC9zYWZhcmkvaSkgJiYgIXVzZXJBZ2VudCgvY2hyb21lL2kpICYmICF1c2VyQWdlbnQoL2FuZHJvaWQvaSk7XG52YXIgSU9TID0gdXNlckFnZW50KC9pUChhZHxvZHxob25lKS9pKTtcbnZhciBDaHJvbWVGb3JBbmRyb2lkID0gdXNlckFnZW50KC9jaHJvbWUvaSkgJiYgdXNlckFnZW50KC9hbmRyb2lkL2kpO1xuXG52YXIgY2FwdHVyZU1vZGUgPSB7XG4gIGNhcHR1cmU6IGZhbHNlLFxuICBwYXNzaXZlOiBmYWxzZVxufTtcblxuZnVuY3Rpb24gb24oZWwsIGV2ZW50LCBmbikge1xuICBlbC5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBmbiwgIUlFMTFPckxlc3MgJiYgY2FwdHVyZU1vZGUpO1xufVxuXG5mdW5jdGlvbiBvZmYoZWwsIGV2ZW50LCBmbikge1xuICBlbC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBmbiwgIUlFMTFPckxlc3MgJiYgY2FwdHVyZU1vZGUpO1xufVxuXG5mdW5jdGlvbiBtYXRjaGVzKFxuLyoqSFRNTEVsZW1lbnQqL1xuZWwsXG4vKipTdHJpbmcqL1xuc2VsZWN0b3IpIHtcbiAgaWYgKCFzZWxlY3RvcikgcmV0dXJuO1xuICBzZWxlY3RvclswXSA9PT0gJz4nICYmIChzZWxlY3RvciA9IHNlbGVjdG9yLnN1YnN0cmluZygxKSk7XG5cbiAgaWYgKGVsKSB7XG4gICAgdHJ5IHtcbiAgICAgIGlmIChlbC5tYXRjaGVzKSB7XG4gICAgICAgIHJldHVybiBlbC5tYXRjaGVzKHNlbGVjdG9yKTtcbiAgICAgIH0gZWxzZSBpZiAoZWwubXNNYXRjaGVzU2VsZWN0b3IpIHtcbiAgICAgICAgcmV0dXJuIGVsLm1zTWF0Y2hlc1NlbGVjdG9yKHNlbGVjdG9yKTtcbiAgICAgIH0gZWxzZSBpZiAoZWwud2Via2l0TWF0Y2hlc1NlbGVjdG9yKSB7XG4gICAgICAgIHJldHVybiBlbC53ZWJraXRNYXRjaGVzU2VsZWN0b3Ioc2VsZWN0b3IpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGdldFBhcmVudE9ySG9zdChlbCkge1xuICByZXR1cm4gZWwuaG9zdCAmJiBlbCAhPT0gZG9jdW1lbnQgJiYgZWwuaG9zdC5ub2RlVHlwZSA/IGVsLmhvc3QgOiBlbC5wYXJlbnROb2RlO1xufVxuXG5mdW5jdGlvbiBjbG9zZXN0KFxuLyoqSFRNTEVsZW1lbnQqL1xuZWwsXG4vKipTdHJpbmcqL1xuc2VsZWN0b3IsXG4vKipIVE1MRWxlbWVudCovXG5jdHgsIGluY2x1ZGVDVFgpIHtcbiAgaWYgKGVsKSB7XG4gICAgY3R4ID0gY3R4IHx8IGRvY3VtZW50O1xuXG4gICAgZG8ge1xuICAgICAgaWYgKHNlbGVjdG9yICE9IG51bGwgJiYgKHNlbGVjdG9yWzBdID09PSAnPicgPyBlbC5wYXJlbnROb2RlID09PSBjdHggJiYgbWF0Y2hlcyhlbCwgc2VsZWN0b3IpIDogbWF0Y2hlcyhlbCwgc2VsZWN0b3IpKSB8fCBpbmNsdWRlQ1RYICYmIGVsID09PSBjdHgpIHtcbiAgICAgICAgcmV0dXJuIGVsO1xuICAgICAgfVxuXG4gICAgICBpZiAoZWwgPT09IGN0eCkgYnJlYWs7XG4gICAgICAvKiBqc2hpbnQgYm9zczp0cnVlICovXG4gICAgfSB3aGlsZSAoZWwgPSBnZXRQYXJlbnRPckhvc3QoZWwpKTtcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuXG52YXIgUl9TUEFDRSA9IC9cXHMrL2c7XG5cbmZ1bmN0aW9uIHRvZ2dsZUNsYXNzKGVsLCBuYW1lLCBzdGF0ZSkge1xuICBpZiAoZWwgJiYgbmFtZSkge1xuICAgIGlmIChlbC5jbGFzc0xpc3QpIHtcbiAgICAgIGVsLmNsYXNzTGlzdFtzdGF0ZSA/ICdhZGQnIDogJ3JlbW92ZSddKG5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB2YXIgY2xhc3NOYW1lID0gKCcgJyArIGVsLmNsYXNzTmFtZSArICcgJykucmVwbGFjZShSX1NQQUNFLCAnICcpLnJlcGxhY2UoJyAnICsgbmFtZSArICcgJywgJyAnKTtcbiAgICAgIGVsLmNsYXNzTmFtZSA9IChjbGFzc05hbWUgKyAoc3RhdGUgPyAnICcgKyBuYW1lIDogJycpKS5yZXBsYWNlKFJfU1BBQ0UsICcgJyk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGNzcyhlbCwgcHJvcCwgdmFsKSB7XG4gIHZhciBzdHlsZSA9IGVsICYmIGVsLnN0eWxlO1xuXG4gIGlmIChzdHlsZSkge1xuICAgIGlmICh2YWwgPT09IHZvaWQgMCkge1xuICAgICAgaWYgKGRvY3VtZW50LmRlZmF1bHRWaWV3ICYmIGRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUpIHtcbiAgICAgICAgdmFsID0gZG9jdW1lbnQuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShlbCwgJycpO1xuICAgICAgfSBlbHNlIGlmIChlbC5jdXJyZW50U3R5bGUpIHtcbiAgICAgICAgdmFsID0gZWwuY3VycmVudFN0eWxlO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4gcHJvcCA9PT0gdm9pZCAwID8gdmFsIDogdmFsW3Byb3BdO1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAoIShwcm9wIGluIHN0eWxlKSAmJiBwcm9wLmluZGV4T2YoJ3dlYmtpdCcpID09PSAtMSkge1xuICAgICAgICBwcm9wID0gJy13ZWJraXQtJyArIHByb3A7XG4gICAgICB9XG5cbiAgICAgIHN0eWxlW3Byb3BdID0gdmFsICsgKHR5cGVvZiB2YWwgPT09ICdzdHJpbmcnID8gJycgOiAncHgnKTtcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gbWF0cml4KGVsLCBzZWxmT25seSkge1xuICB2YXIgYXBwbGllZFRyYW5zZm9ybXMgPSAnJztcblxuICBpZiAodHlwZW9mIGVsID09PSAnc3RyaW5nJykge1xuICAgIGFwcGxpZWRUcmFuc2Zvcm1zID0gZWw7XG4gIH0gZWxzZSB7XG4gICAgZG8ge1xuICAgICAgdmFyIHRyYW5zZm9ybSA9IGNzcyhlbCwgJ3RyYW5zZm9ybScpO1xuXG4gICAgICBpZiAodHJhbnNmb3JtICYmIHRyYW5zZm9ybSAhPT0gJ25vbmUnKSB7XG4gICAgICAgIGFwcGxpZWRUcmFuc2Zvcm1zID0gdHJhbnNmb3JtICsgJyAnICsgYXBwbGllZFRyYW5zZm9ybXM7XG4gICAgICB9XG4gICAgICAvKiBqc2hpbnQgYm9zczp0cnVlICovXG5cbiAgICB9IHdoaWxlICghc2VsZk9ubHkgJiYgKGVsID0gZWwucGFyZW50Tm9kZSkpO1xuICB9XG5cbiAgdmFyIG1hdHJpeEZuID0gd2luZG93LkRPTU1hdHJpeCB8fCB3aW5kb3cuV2ViS2l0Q1NTTWF0cml4IHx8IHdpbmRvdy5DU1NNYXRyaXggfHwgd2luZG93Lk1TQ1NTTWF0cml4O1xuICAvKmpzaGludCAtVzA1NiAqL1xuXG4gIHJldHVybiBtYXRyaXhGbiAmJiBuZXcgbWF0cml4Rm4oYXBwbGllZFRyYW5zZm9ybXMpO1xufVxuXG5mdW5jdGlvbiBmaW5kKGN0eCwgdGFnTmFtZSwgaXRlcmF0b3IpIHtcbiAgaWYgKGN0eCkge1xuICAgIHZhciBsaXN0ID0gY3R4LmdldEVsZW1lbnRzQnlUYWdOYW1lKHRhZ05hbWUpLFxuICAgICAgICBpID0gMCxcbiAgICAgICAgbiA9IGxpc3QubGVuZ3RoO1xuXG4gICAgaWYgKGl0ZXJhdG9yKSB7XG4gICAgICBmb3IgKDsgaSA8IG47IGkrKykge1xuICAgICAgICBpdGVyYXRvcihsaXN0W2ldLCBpKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbGlzdDtcbiAgfVxuXG4gIHJldHVybiBbXTtcbn1cblxuZnVuY3Rpb24gZ2V0V2luZG93U2Nyb2xsaW5nRWxlbWVudCgpIHtcbiAgdmFyIHNjcm9sbGluZ0VsZW1lbnQgPSBkb2N1bWVudC5zY3JvbGxpbmdFbGVtZW50O1xuXG4gIGlmIChzY3JvbGxpbmdFbGVtZW50KSB7XG4gICAgcmV0dXJuIHNjcm9sbGluZ0VsZW1lbnQ7XG4gIH0gZWxzZSB7XG4gICAgcmV0dXJuIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgfVxufVxuLyoqXHJcbiAqIFJldHVybnMgdGhlIFwiYm91bmRpbmcgY2xpZW50IHJlY3RcIiBvZiBnaXZlbiBlbGVtZW50XHJcbiAqIEBwYXJhbSAge0hUTUxFbGVtZW50fSBlbCAgICAgICAgICAgICAgICAgICAgICAgVGhlIGVsZW1lbnQgd2hvc2UgYm91bmRpbmdDbGllbnRSZWN0IGlzIHdhbnRlZFxyXG4gKiBAcGFyYW0gIHtbQm9vbGVhbl19IHJlbGF0aXZlVG9Db250YWluaW5nQmxvY2sgIFdoZXRoZXIgdGhlIHJlY3Qgc2hvdWxkIGJlIHJlbGF0aXZlIHRvIHRoZSBjb250YWluaW5nIGJsb2NrIG9mIChpbmNsdWRpbmcpIHRoZSBjb250YWluZXJcclxuICogQHBhcmFtICB7W0Jvb2xlYW5dfSByZWxhdGl2ZVRvTm9uU3RhdGljUGFyZW50ICBXaGV0aGVyIHRoZSByZWN0IHNob3VsZCBiZSByZWxhdGl2ZSB0byB0aGUgcmVsYXRpdmUgcGFyZW50IG9mIChpbmNsdWRpbmcpIHRoZSBjb250YWllbnJcclxuICogQHBhcmFtICB7W0Jvb2xlYW5dfSB1bmRvU2NhbGUgICAgICAgICAgICAgICAgICBXaGV0aGVyIHRoZSBjb250YWluZXIncyBzY2FsZSgpIHNob3VsZCBiZSB1bmRvbmVcclxuICogQHBhcmFtICB7W0hUTUxFbGVtZW50XX0gY29udGFpbmVyICAgICAgICAgICAgICBUaGUgcGFyZW50IHRoZSBlbGVtZW50IHdpbGwgYmUgcGxhY2VkIGluXHJcbiAqIEByZXR1cm4ge09iamVjdH0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGhlIGJvdW5kaW5nQ2xpZW50UmVjdCBvZiBlbCwgd2l0aCBzcGVjaWZpZWQgYWRqdXN0bWVudHNcclxuICovXG5cblxuZnVuY3Rpb24gZ2V0UmVjdChlbCwgcmVsYXRpdmVUb0NvbnRhaW5pbmdCbG9jaywgcmVsYXRpdmVUb05vblN0YXRpY1BhcmVudCwgdW5kb1NjYWxlLCBjb250YWluZXIpIHtcbiAgaWYgKCFlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QgJiYgZWwgIT09IHdpbmRvdykgcmV0dXJuO1xuICB2YXIgZWxSZWN0LCB0b3AsIGxlZnQsIGJvdHRvbSwgcmlnaHQsIGhlaWdodCwgd2lkdGg7XG5cbiAgaWYgKGVsICE9PSB3aW5kb3cgJiYgZWwgIT09IGdldFdpbmRvd1Njcm9sbGluZ0VsZW1lbnQoKSkge1xuICAgIGVsUmVjdCA9IGVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHRvcCA9IGVsUmVjdC50b3A7XG4gICAgbGVmdCA9IGVsUmVjdC5sZWZ0O1xuICAgIGJvdHRvbSA9IGVsUmVjdC5ib3R0b207XG4gICAgcmlnaHQgPSBlbFJlY3QucmlnaHQ7XG4gICAgaGVpZ2h0ID0gZWxSZWN0LmhlaWdodDtcbiAgICB3aWR0aCA9IGVsUmVjdC53aWR0aDtcbiAgfSBlbHNlIHtcbiAgICB0b3AgPSAwO1xuICAgIGxlZnQgPSAwO1xuICAgIGJvdHRvbSA9IHdpbmRvdy5pbm5lckhlaWdodDtcbiAgICByaWdodCA9IHdpbmRvdy5pbm5lcldpZHRoO1xuICAgIGhlaWdodCA9IHdpbmRvdy5pbm5lckhlaWdodDtcbiAgICB3aWR0aCA9IHdpbmRvdy5pbm5lcldpZHRoO1xuICB9XG5cbiAgaWYgKChyZWxhdGl2ZVRvQ29udGFpbmluZ0Jsb2NrIHx8IHJlbGF0aXZlVG9Ob25TdGF0aWNQYXJlbnQpICYmIGVsICE9PSB3aW5kb3cpIHtcbiAgICAvLyBBZGp1c3QgZm9yIHRyYW5zbGF0ZSgpXG4gICAgY29udGFpbmVyID0gY29udGFpbmVyIHx8IGVsLnBhcmVudE5vZGU7IC8vIHNvbHZlcyAjMTEyMyAoc2VlOiBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzc5NTM4MDYvNjA4ODMxMilcbiAgICAvLyBOb3QgbmVlZGVkIG9uIDw9IElFMTFcblxuICAgIGlmICghSUUxMU9yTGVzcykge1xuICAgICAgZG8ge1xuICAgICAgICBpZiAoY29udGFpbmVyICYmIGNvbnRhaW5lci5nZXRCb3VuZGluZ0NsaWVudFJlY3QgJiYgKGNzcyhjb250YWluZXIsICd0cmFuc2Zvcm0nKSAhPT0gJ25vbmUnIHx8IHJlbGF0aXZlVG9Ob25TdGF0aWNQYXJlbnQgJiYgY3NzKGNvbnRhaW5lciwgJ3Bvc2l0aW9uJykgIT09ICdzdGF0aWMnKSkge1xuICAgICAgICAgIHZhciBjb250YWluZXJSZWN0ID0gY29udGFpbmVyLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpOyAvLyBTZXQgcmVsYXRpdmUgdG8gZWRnZXMgb2YgcGFkZGluZyBib3ggb2YgY29udGFpbmVyXG5cbiAgICAgICAgICB0b3AgLT0gY29udGFpbmVyUmVjdC50b3AgKyBwYXJzZUludChjc3MoY29udGFpbmVyLCAnYm9yZGVyLXRvcC13aWR0aCcpKTtcbiAgICAgICAgICBsZWZ0IC09IGNvbnRhaW5lclJlY3QubGVmdCArIHBhcnNlSW50KGNzcyhjb250YWluZXIsICdib3JkZXItbGVmdC13aWR0aCcpKTtcbiAgICAgICAgICBib3R0b20gPSB0b3AgKyBlbFJlY3QuaGVpZ2h0O1xuICAgICAgICAgIHJpZ2h0ID0gbGVmdCArIGVsUmVjdC53aWR0aDtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICAvKiBqc2hpbnQgYm9zczp0cnVlICovXG5cbiAgICAgIH0gd2hpbGUgKGNvbnRhaW5lciA9IGNvbnRhaW5lci5wYXJlbnROb2RlKTtcbiAgICB9XG4gIH1cblxuICBpZiAodW5kb1NjYWxlICYmIGVsICE9PSB3aW5kb3cpIHtcbiAgICAvLyBBZGp1c3QgZm9yIHNjYWxlKClcbiAgICB2YXIgZWxNYXRyaXggPSBtYXRyaXgoY29udGFpbmVyIHx8IGVsKSxcbiAgICAgICAgc2NhbGVYID0gZWxNYXRyaXggJiYgZWxNYXRyaXguYSxcbiAgICAgICAgc2NhbGVZID0gZWxNYXRyaXggJiYgZWxNYXRyaXguZDtcblxuICAgIGlmIChlbE1hdHJpeCkge1xuICAgICAgdG9wIC89IHNjYWxlWTtcbiAgICAgIGxlZnQgLz0gc2NhbGVYO1xuICAgICAgd2lkdGggLz0gc2NhbGVYO1xuICAgICAgaGVpZ2h0IC89IHNjYWxlWTtcbiAgICAgIGJvdHRvbSA9IHRvcCArIGhlaWdodDtcbiAgICAgIHJpZ2h0ID0gbGVmdCArIHdpZHRoO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgdG9wOiB0b3AsXG4gICAgbGVmdDogbGVmdCxcbiAgICBib3R0b206IGJvdHRvbSxcbiAgICByaWdodDogcmlnaHQsXG4gICAgd2lkdGg6IHdpZHRoLFxuICAgIGhlaWdodDogaGVpZ2h0XG4gIH07XG59XG4vKipcclxuICogQ2hlY2tzIGlmIGEgc2lkZSBvZiBhbiBlbGVtZW50IGlzIHNjcm9sbGVkIHBhc3QgYSBzaWRlIG9mIGl0cyBwYXJlbnRzXHJcbiAqIEBwYXJhbSAge0hUTUxFbGVtZW50fSAgZWwgICAgICAgICAgIFRoZSBlbGVtZW50IHdobydzIHNpZGUgYmVpbmcgc2Nyb2xsZWQgb3V0IG9mIHZpZXcgaXMgaW4gcXVlc3Rpb25cclxuICogQHBhcmFtICB7U3RyaW5nfSAgICAgICBlbFNpZGUgICAgICAgU2lkZSBvZiB0aGUgZWxlbWVudCBpbiBxdWVzdGlvbiAoJ3RvcCcsICdsZWZ0JywgJ3JpZ2h0JywgJ2JvdHRvbScpXHJcbiAqIEBwYXJhbSAge1N0cmluZ30gICAgICAgcGFyZW50U2lkZSAgIFNpZGUgb2YgdGhlIHBhcmVudCBpbiBxdWVzdGlvbiAoJ3RvcCcsICdsZWZ0JywgJ3JpZ2h0JywgJ2JvdHRvbScpXHJcbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50fSAgICAgICAgICAgICAgIFRoZSBwYXJlbnQgc2Nyb2xsIGVsZW1lbnQgdGhhdCB0aGUgZWwncyBzaWRlIGlzIHNjcm9sbGVkIHBhc3QsIG9yIG51bGwgaWYgdGhlcmUgaXMgbm8gc3VjaCBlbGVtZW50XHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGlzU2Nyb2xsZWRQYXN0KGVsLCBlbFNpZGUsIHBhcmVudFNpZGUpIHtcbiAgdmFyIHBhcmVudCA9IGdldFBhcmVudEF1dG9TY3JvbGxFbGVtZW50KGVsLCB0cnVlKSxcbiAgICAgIGVsU2lkZVZhbCA9IGdldFJlY3QoZWwpW2VsU2lkZV07XG4gIC8qIGpzaGludCBib3NzOnRydWUgKi9cblxuICB3aGlsZSAocGFyZW50KSB7XG4gICAgdmFyIHBhcmVudFNpZGVWYWwgPSBnZXRSZWN0KHBhcmVudClbcGFyZW50U2lkZV0sXG4gICAgICAgIHZpc2libGUgPSB2b2lkIDA7XG5cbiAgICBpZiAocGFyZW50U2lkZSA9PT0gJ3RvcCcgfHwgcGFyZW50U2lkZSA9PT0gJ2xlZnQnKSB7XG4gICAgICB2aXNpYmxlID0gZWxTaWRlVmFsID49IHBhcmVudFNpZGVWYWw7XG4gICAgfSBlbHNlIHtcbiAgICAgIHZpc2libGUgPSBlbFNpZGVWYWwgPD0gcGFyZW50U2lkZVZhbDtcbiAgICB9XG5cbiAgICBpZiAoIXZpc2libGUpIHJldHVybiBwYXJlbnQ7XG4gICAgaWYgKHBhcmVudCA9PT0gZ2V0V2luZG93U2Nyb2xsaW5nRWxlbWVudCgpKSBicmVhaztcbiAgICBwYXJlbnQgPSBnZXRQYXJlbnRBdXRvU2Nyb2xsRWxlbWVudChwYXJlbnQsIGZhbHNlKTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cbi8qKlxyXG4gKiBHZXRzIG50aCBjaGlsZCBvZiBlbCwgaWdub3JpbmcgaGlkZGVuIGNoaWxkcmVuLCBzb3J0YWJsZSdzIGVsZW1lbnRzIChkb2VzIG5vdCBpZ25vcmUgY2xvbmUgaWYgaXQncyB2aXNpYmxlKVxyXG4gKiBhbmQgbm9uLWRyYWdnYWJsZSBlbGVtZW50c1xyXG4gKiBAcGFyYW0gIHtIVE1MRWxlbWVudH0gZWwgICAgICAgVGhlIHBhcmVudCBlbGVtZW50XHJcbiAqIEBwYXJhbSAge051bWJlcn0gY2hpbGROdW0gICAgICBUaGUgaW5kZXggb2YgdGhlIGNoaWxkXHJcbiAqIEBwYXJhbSAge09iamVjdH0gb3B0aW9ucyAgICAgICBQYXJlbnQgU29ydGFibGUncyBvcHRpb25zXHJcbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50fSAgICAgICAgICBUaGUgY2hpbGQgYXQgaW5kZXggY2hpbGROdW0sIG9yIG51bGwgaWYgbm90IGZvdW5kXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGdldENoaWxkKGVsLCBjaGlsZE51bSwgb3B0aW9ucykge1xuICB2YXIgY3VycmVudENoaWxkID0gMCxcbiAgICAgIGkgPSAwLFxuICAgICAgY2hpbGRyZW4gPSBlbC5jaGlsZHJlbjtcblxuICB3aGlsZSAoaSA8IGNoaWxkcmVuLmxlbmd0aCkge1xuICAgIGlmIChjaGlsZHJlbltpXS5zdHlsZS5kaXNwbGF5ICE9PSAnbm9uZScgJiYgY2hpbGRyZW5baV0gIT09IFNvcnRhYmxlLmdob3N0ICYmIGNoaWxkcmVuW2ldICE9PSBTb3J0YWJsZS5kcmFnZ2VkICYmIGNsb3Nlc3QoY2hpbGRyZW5baV0sIG9wdGlvbnMuZHJhZ2dhYmxlLCBlbCwgZmFsc2UpKSB7XG4gICAgICBpZiAoY3VycmVudENoaWxkID09PSBjaGlsZE51bSkge1xuICAgICAgICByZXR1cm4gY2hpbGRyZW5baV07XG4gICAgICB9XG5cbiAgICAgIGN1cnJlbnRDaGlsZCsrO1xuICAgIH1cblxuICAgIGkrKztcbiAgfVxuXG4gIHJldHVybiBudWxsO1xufVxuLyoqXHJcbiAqIEdldHMgdGhlIGxhc3QgY2hpbGQgaW4gdGhlIGVsLCBpZ25vcmluZyBnaG9zdEVsIG9yIGludmlzaWJsZSBlbGVtZW50cyAoY2xvbmVzKVxyXG4gKiBAcGFyYW0gIHtIVE1MRWxlbWVudH0gZWwgICAgICAgUGFyZW50IGVsZW1lbnRcclxuICogQHBhcmFtICB7c2VsZWN0b3J9IHNlbGVjdG9yICAgIEFueSBvdGhlciBlbGVtZW50cyB0aGF0IHNob3VsZCBiZSBpZ25vcmVkXHJcbiAqIEByZXR1cm4ge0hUTUxFbGVtZW50fSAgICAgICAgICBUaGUgbGFzdCBjaGlsZCwgaWdub3JpbmcgZ2hvc3RFbFxyXG4gKi9cblxuXG5mdW5jdGlvbiBsYXN0Q2hpbGQoZWwsIHNlbGVjdG9yKSB7XG4gIHZhciBsYXN0ID0gZWwubGFzdEVsZW1lbnRDaGlsZDtcblxuICB3aGlsZSAobGFzdCAmJiAobGFzdCA9PT0gU29ydGFibGUuZ2hvc3QgfHwgY3NzKGxhc3QsICdkaXNwbGF5JykgPT09ICdub25lJyB8fCBzZWxlY3RvciAmJiAhbWF0Y2hlcyhsYXN0LCBzZWxlY3RvcikpKSB7XG4gICAgbGFzdCA9IGxhc3QucHJldmlvdXNFbGVtZW50U2libGluZztcbiAgfVxuXG4gIHJldHVybiBsYXN0IHx8IG51bGw7XG59XG4vKipcclxuICogUmV0dXJucyB0aGUgaW5kZXggb2YgYW4gZWxlbWVudCB3aXRoaW4gaXRzIHBhcmVudCBmb3IgYSBzZWxlY3RlZCBzZXQgb2ZcclxuICogZWxlbWVudHNcclxuICogQHBhcmFtICB7SFRNTEVsZW1lbnR9IGVsXHJcbiAqIEBwYXJhbSAge3NlbGVjdG9yfSBzZWxlY3RvclxyXG4gKiBAcmV0dXJuIHtudW1iZXJ9XHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGluZGV4KGVsLCBzZWxlY3Rvcikge1xuICB2YXIgaW5kZXggPSAwO1xuXG4gIGlmICghZWwgfHwgIWVsLnBhcmVudE5vZGUpIHtcbiAgICByZXR1cm4gLTE7XG4gIH1cbiAgLyoganNoaW50IGJvc3M6dHJ1ZSAqL1xuXG5cbiAgd2hpbGUgKGVsID0gZWwucHJldmlvdXNFbGVtZW50U2libGluZykge1xuICAgIGlmIChlbC5ub2RlTmFtZS50b1VwcGVyQ2FzZSgpICE9PSAnVEVNUExBVEUnICYmIGVsICE9PSBTb3J0YWJsZS5jbG9uZSAmJiAoIXNlbGVjdG9yIHx8IG1hdGNoZXMoZWwsIHNlbGVjdG9yKSkpIHtcbiAgICAgIGluZGV4Kys7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGluZGV4O1xufVxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHNjcm9sbCBvZmZzZXQgb2YgdGhlIGdpdmVuIGVsZW1lbnQsIGFkZGVkIHdpdGggYWxsIHRoZSBzY3JvbGwgb2Zmc2V0cyBvZiBwYXJlbnQgZWxlbWVudHMuXHJcbiAqIFRoZSB2YWx1ZSBpcyByZXR1cm5lZCBpbiByZWFsIHBpeGVscy5cclxuICogQHBhcmFtICB7SFRNTEVsZW1lbnR9IGVsXHJcbiAqIEByZXR1cm4ge0FycmF5fSAgICAgICAgICAgICBPZmZzZXRzIGluIHRoZSBmb3JtYXQgb2YgW2xlZnQsIHRvcF1cclxuICovXG5cblxuZnVuY3Rpb24gZ2V0UmVsYXRpdmVTY3JvbGxPZmZzZXQoZWwpIHtcbiAgdmFyIG9mZnNldExlZnQgPSAwLFxuICAgICAgb2Zmc2V0VG9wID0gMCxcbiAgICAgIHdpblNjcm9sbGVyID0gZ2V0V2luZG93U2Nyb2xsaW5nRWxlbWVudCgpO1xuXG4gIGlmIChlbCkge1xuICAgIGRvIHtcbiAgICAgIHZhciBlbE1hdHJpeCA9IG1hdHJpeChlbCksXG4gICAgICAgICAgc2NhbGVYID0gZWxNYXRyaXguYSxcbiAgICAgICAgICBzY2FsZVkgPSBlbE1hdHJpeC5kO1xuICAgICAgb2Zmc2V0TGVmdCArPSBlbC5zY3JvbGxMZWZ0ICogc2NhbGVYO1xuICAgICAgb2Zmc2V0VG9wICs9IGVsLnNjcm9sbFRvcCAqIHNjYWxlWTtcbiAgICB9IHdoaWxlIChlbCAhPT0gd2luU2Nyb2xsZXIgJiYgKGVsID0gZWwucGFyZW50Tm9kZSkpO1xuICB9XG5cbiAgcmV0dXJuIFtvZmZzZXRMZWZ0LCBvZmZzZXRUb3BdO1xufVxuLyoqXHJcbiAqIFJldHVybnMgdGhlIGluZGV4IG9mIHRoZSBvYmplY3Qgd2l0aGluIHRoZSBnaXZlbiBhcnJheVxyXG4gKiBAcGFyYW0gIHtBcnJheX0gYXJyICAgQXJyYXkgdGhhdCBtYXkgb3IgbWF5IG5vdCBob2xkIHRoZSBvYmplY3RcclxuICogQHBhcmFtICB7T2JqZWN0fSBvYmogIEFuIG9iamVjdCB0aGF0IGhhcyBhIGtleS12YWx1ZSBwYWlyIHVuaXF1ZSB0byBhbmQgaWRlbnRpY2FsIHRvIGEga2V5LXZhbHVlIHBhaXIgaW4gdGhlIG9iamVjdCB5b3Ugd2FudCB0byBmaW5kXHJcbiAqIEByZXR1cm4ge051bWJlcn0gICAgICBUaGUgaW5kZXggb2YgdGhlIG9iamVjdCBpbiB0aGUgYXJyYXksIG9yIC0xXHJcbiAqL1xuXG5cbmZ1bmN0aW9uIGluZGV4T2ZPYmplY3QoYXJyLCBvYmopIHtcbiAgZm9yICh2YXIgaSBpbiBhcnIpIHtcbiAgICBpZiAoIWFyci5oYXNPd25Qcm9wZXJ0eShpKSkgY29udGludWU7XG5cbiAgICBmb3IgKHZhciBrZXkgaW4gb2JqKSB7XG4gICAgICBpZiAob2JqLmhhc093blByb3BlcnR5KGtleSkgJiYgb2JqW2tleV0gPT09IGFycltpXVtrZXldKSByZXR1cm4gTnVtYmVyKGkpO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiAtMTtcbn1cblxuZnVuY3Rpb24gZ2V0UGFyZW50QXV0b1Njcm9sbEVsZW1lbnQoZWwsIGluY2x1ZGVTZWxmKSB7XG4gIC8vIHNraXAgdG8gd2luZG93XG4gIGlmICghZWwgfHwgIWVsLmdldEJvdW5kaW5nQ2xpZW50UmVjdCkgcmV0dXJuIGdldFdpbmRvd1Njcm9sbGluZ0VsZW1lbnQoKTtcbiAgdmFyIGVsZW0gPSBlbDtcbiAgdmFyIGdvdFNlbGYgPSBmYWxzZTtcblxuICBkbyB7XG4gICAgLy8gd2UgZG9uJ3QgbmVlZCB0byBnZXQgZWxlbSBjc3MgaWYgaXQgaXNuJ3QgZXZlbiBvdmVyZmxvd2luZyBpbiB0aGUgZmlyc3QgcGxhY2UgKHBlcmZvcm1hbmNlKVxuICAgIGlmIChlbGVtLmNsaWVudFdpZHRoIDwgZWxlbS5zY3JvbGxXaWR0aCB8fCBlbGVtLmNsaWVudEhlaWdodCA8IGVsZW0uc2Nyb2xsSGVpZ2h0KSB7XG4gICAgICB2YXIgZWxlbUNTUyA9IGNzcyhlbGVtKTtcblxuICAgICAgaWYgKGVsZW0uY2xpZW50V2lkdGggPCBlbGVtLnNjcm9sbFdpZHRoICYmIChlbGVtQ1NTLm92ZXJmbG93WCA9PSAnYXV0bycgfHwgZWxlbUNTUy5vdmVyZmxvd1ggPT0gJ3Njcm9sbCcpIHx8IGVsZW0uY2xpZW50SGVpZ2h0IDwgZWxlbS5zY3JvbGxIZWlnaHQgJiYgKGVsZW1DU1Mub3ZlcmZsb3dZID09ICdhdXRvJyB8fCBlbGVtQ1NTLm92ZXJmbG93WSA9PSAnc2Nyb2xsJykpIHtcbiAgICAgICAgaWYgKCFlbGVtLmdldEJvdW5kaW5nQ2xpZW50UmVjdCB8fCBlbGVtID09PSBkb2N1bWVudC5ib2R5KSByZXR1cm4gZ2V0V2luZG93U2Nyb2xsaW5nRWxlbWVudCgpO1xuICAgICAgICBpZiAoZ290U2VsZiB8fCBpbmNsdWRlU2VsZikgcmV0dXJuIGVsZW07XG4gICAgICAgIGdvdFNlbGYgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cbiAgICAvKiBqc2hpbnQgYm9zczp0cnVlICovXG5cbiAgfSB3aGlsZSAoZWxlbSA9IGVsZW0ucGFyZW50Tm9kZSk7XG5cbiAgcmV0dXJuIGdldFdpbmRvd1Njcm9sbGluZ0VsZW1lbnQoKTtcbn1cblxuZnVuY3Rpb24gZXh0ZW5kKGRzdCwgc3JjKSB7XG4gIGlmIChkc3QgJiYgc3JjKSB7XG4gICAgZm9yICh2YXIga2V5IGluIHNyYykge1xuICAgICAgaWYgKHNyYy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgIGRzdFtrZXldID0gc3JjW2tleV07XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIGRzdDtcbn1cblxuZnVuY3Rpb24gaXNSZWN0RXF1YWwocmVjdDEsIHJlY3QyKSB7XG4gIHJldHVybiBNYXRoLnJvdW5kKHJlY3QxLnRvcCkgPT09IE1hdGgucm91bmQocmVjdDIudG9wKSAmJiBNYXRoLnJvdW5kKHJlY3QxLmxlZnQpID09PSBNYXRoLnJvdW5kKHJlY3QyLmxlZnQpICYmIE1hdGgucm91bmQocmVjdDEuaGVpZ2h0KSA9PT0gTWF0aC5yb3VuZChyZWN0Mi5oZWlnaHQpICYmIE1hdGgucm91bmQocmVjdDEud2lkdGgpID09PSBNYXRoLnJvdW5kKHJlY3QyLndpZHRoKTtcbn1cblxudmFyIF90aHJvdHRsZVRpbWVvdXQ7XG5cbmZ1bmN0aW9uIHRocm90dGxlKGNhbGxiYWNrLCBtcykge1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIGlmICghX3Rocm90dGxlVGltZW91dCkge1xuICAgICAgdmFyIGFyZ3MgPSBhcmd1bWVudHMsXG4gICAgICAgICAgX3RoaXMgPSB0aGlzO1xuXG4gICAgICBpZiAoYXJncy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgY2FsbGJhY2suY2FsbChfdGhpcywgYXJnc1swXSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjYWxsYmFjay5hcHBseShfdGhpcywgYXJncyk7XG4gICAgICB9XG5cbiAgICAgIF90aHJvdHRsZVRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3Rocm90dGxlVGltZW91dCA9IHZvaWQgMDtcbiAgICAgIH0sIG1zKTtcbiAgICB9XG4gIH07XG59XG5cbmZ1bmN0aW9uIGNhbmNlbFRocm90dGxlKCkge1xuICBjbGVhclRpbWVvdXQoX3Rocm90dGxlVGltZW91dCk7XG4gIF90aHJvdHRsZVRpbWVvdXQgPSB2b2lkIDA7XG59XG5cbmZ1bmN0aW9uIHNjcm9sbEJ5KGVsLCB4LCB5KSB7XG4gIGVsLnNjcm9sbExlZnQgKz0geDtcbiAgZWwuc2Nyb2xsVG9wICs9IHk7XG59XG5cbmZ1bmN0aW9uIGNsb25lKGVsKSB7XG4gIHZhciBQb2x5bWVyID0gd2luZG93LlBvbHltZXI7XG4gIHZhciAkID0gd2luZG93LmpRdWVyeSB8fCB3aW5kb3cuWmVwdG87XG5cbiAgaWYgKFBvbHltZXIgJiYgUG9seW1lci5kb20pIHtcbiAgICByZXR1cm4gUG9seW1lci5kb20oZWwpLmNsb25lTm9kZSh0cnVlKTtcbiAgfSBlbHNlIGlmICgkKSB7XG4gICAgcmV0dXJuICQoZWwpLmNsb25lKHRydWUpWzBdO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBlbC5jbG9uZU5vZGUodHJ1ZSk7XG4gIH1cbn1cblxuZnVuY3Rpb24gc2V0UmVjdChlbCwgcmVjdCkge1xuICBjc3MoZWwsICdwb3NpdGlvbicsICdhYnNvbHV0ZScpO1xuICBjc3MoZWwsICd0b3AnLCByZWN0LnRvcCk7XG4gIGNzcyhlbCwgJ2xlZnQnLCByZWN0LmxlZnQpO1xuICBjc3MoZWwsICd3aWR0aCcsIHJlY3Qud2lkdGgpO1xuICBjc3MoZWwsICdoZWlnaHQnLCByZWN0LmhlaWdodCk7XG59XG5cbmZ1bmN0aW9uIHVuc2V0UmVjdChlbCkge1xuICBjc3MoZWwsICdwb3NpdGlvbicsICcnKTtcbiAgY3NzKGVsLCAndG9wJywgJycpO1xuICBjc3MoZWwsICdsZWZ0JywgJycpO1xuICBjc3MoZWwsICd3aWR0aCcsICcnKTtcbiAgY3NzKGVsLCAnaGVpZ2h0JywgJycpO1xufVxuXG52YXIgZXhwYW5kbyA9ICdTb3J0YWJsZScgKyBuZXcgRGF0ZSgpLmdldFRpbWUoKTtcblxuZnVuY3Rpb24gQW5pbWF0aW9uU3RhdGVNYW5hZ2VyKCkge1xuICB2YXIgYW5pbWF0aW9uU3RhdGVzID0gW10sXG4gICAgICBhbmltYXRpb25DYWxsYmFja0lkO1xuICByZXR1cm4ge1xuICAgIGNhcHR1cmVBbmltYXRpb25TdGF0ZTogZnVuY3Rpb24gY2FwdHVyZUFuaW1hdGlvblN0YXRlKCkge1xuICAgICAgYW5pbWF0aW9uU3RhdGVzID0gW107XG4gICAgICBpZiAoIXRoaXMub3B0aW9ucy5hbmltYXRpb24pIHJldHVybjtcbiAgICAgIHZhciBjaGlsZHJlbiA9IFtdLnNsaWNlLmNhbGwodGhpcy5lbC5jaGlsZHJlbik7XG4gICAgICBjaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xuICAgICAgICBpZiAoY3NzKGNoaWxkLCAnZGlzcGxheScpID09PSAnbm9uZScgfHwgY2hpbGQgPT09IFNvcnRhYmxlLmdob3N0KSByZXR1cm47XG4gICAgICAgIGFuaW1hdGlvblN0YXRlcy5wdXNoKHtcbiAgICAgICAgICB0YXJnZXQ6IGNoaWxkLFxuICAgICAgICAgIHJlY3Q6IGdldFJlY3QoY2hpbGQpXG4gICAgICAgIH0pO1xuXG4gICAgICAgIHZhciBmcm9tUmVjdCA9IF9vYmplY3RTcHJlYWQoe30sIGFuaW1hdGlvblN0YXRlc1thbmltYXRpb25TdGF0ZXMubGVuZ3RoIC0gMV0ucmVjdCk7IC8vIElmIGFuaW1hdGluZzogY29tcGVuc2F0ZSBmb3IgY3VycmVudCBhbmltYXRpb25cblxuXG4gICAgICAgIGlmIChjaGlsZC50aGlzQW5pbWF0aW9uRHVyYXRpb24pIHtcbiAgICAgICAgICB2YXIgY2hpbGRNYXRyaXggPSBtYXRyaXgoY2hpbGQsIHRydWUpO1xuXG4gICAgICAgICAgaWYgKGNoaWxkTWF0cml4KSB7XG4gICAgICAgICAgICBmcm9tUmVjdC50b3AgLT0gY2hpbGRNYXRyaXguZjtcbiAgICAgICAgICAgIGZyb21SZWN0LmxlZnQgLT0gY2hpbGRNYXRyaXguZTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBjaGlsZC5mcm9tUmVjdCA9IGZyb21SZWN0O1xuICAgICAgfSk7XG4gICAgfSxcbiAgICBhZGRBbmltYXRpb25TdGF0ZTogZnVuY3Rpb24gYWRkQW5pbWF0aW9uU3RhdGUoc3RhdGUpIHtcbiAgICAgIGFuaW1hdGlvblN0YXRlcy5wdXNoKHN0YXRlKTtcbiAgICB9LFxuICAgIHJlbW92ZUFuaW1hdGlvblN0YXRlOiBmdW5jdGlvbiByZW1vdmVBbmltYXRpb25TdGF0ZSh0YXJnZXQpIHtcbiAgICAgIGFuaW1hdGlvblN0YXRlcy5zcGxpY2UoaW5kZXhPZk9iamVjdChhbmltYXRpb25TdGF0ZXMsIHtcbiAgICAgICAgdGFyZ2V0OiB0YXJnZXRcbiAgICAgIH0pLCAxKTtcbiAgICB9LFxuICAgIGFuaW1hdGVBbGw6IGZ1bmN0aW9uIGFuaW1hdGVBbGwoY2FsbGJhY2spIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIGlmICghdGhpcy5vcHRpb25zLmFuaW1hdGlvbikge1xuICAgICAgICBjbGVhclRpbWVvdXQoYW5pbWF0aW9uQ2FsbGJhY2tJZCk7XG4gICAgICAgIGlmICh0eXBlb2YgY2FsbGJhY2sgPT09ICdmdW5jdGlvbicpIGNhbGxiYWNrKCk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdmFyIGFuaW1hdGluZyA9IGZhbHNlLFxuICAgICAgICAgIGFuaW1hdGlvblRpbWUgPSAwO1xuICAgICAgYW5pbWF0aW9uU3RhdGVzLmZvckVhY2goZnVuY3Rpb24gKHN0YXRlKSB7XG4gICAgICAgIHZhciB0aW1lID0gMCxcbiAgICAgICAgICAgIHRhcmdldCA9IHN0YXRlLnRhcmdldCxcbiAgICAgICAgICAgIGZyb21SZWN0ID0gdGFyZ2V0LmZyb21SZWN0LFxuICAgICAgICAgICAgdG9SZWN0ID0gZ2V0UmVjdCh0YXJnZXQpLFxuICAgICAgICAgICAgcHJldkZyb21SZWN0ID0gdGFyZ2V0LnByZXZGcm9tUmVjdCxcbiAgICAgICAgICAgIHByZXZUb1JlY3QgPSB0YXJnZXQucHJldlRvUmVjdCxcbiAgICAgICAgICAgIGFuaW1hdGluZ1JlY3QgPSBzdGF0ZS5yZWN0LFxuICAgICAgICAgICAgdGFyZ2V0TWF0cml4ID0gbWF0cml4KHRhcmdldCwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKHRhcmdldE1hdHJpeCkge1xuICAgICAgICAgIC8vIENvbXBlbnNhdGUgZm9yIGN1cnJlbnQgYW5pbWF0aW9uXG4gICAgICAgICAgdG9SZWN0LnRvcCAtPSB0YXJnZXRNYXRyaXguZjtcbiAgICAgICAgICB0b1JlY3QubGVmdCAtPSB0YXJnZXRNYXRyaXguZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRhcmdldC50b1JlY3QgPSB0b1JlY3Q7XG5cbiAgICAgICAgaWYgKHRhcmdldC50aGlzQW5pbWF0aW9uRHVyYXRpb24pIHtcbiAgICAgICAgICAvLyBDb3VsZCBhbHNvIGNoZWNrIGlmIGFuaW1hdGluZ1JlY3QgaXMgYmV0d2VlbiBmcm9tUmVjdCBhbmQgdG9SZWN0XG4gICAgICAgICAgaWYgKGlzUmVjdEVxdWFsKHByZXZGcm9tUmVjdCwgdG9SZWN0KSAmJiAhaXNSZWN0RXF1YWwoZnJvbVJlY3QsIHRvUmVjdCkgJiYgLy8gTWFrZSBzdXJlIGFuaW1hdGluZ1JlY3QgaXMgb24gbGluZSBiZXR3ZWVuIHRvUmVjdCAmIGZyb21SZWN0XG4gICAgICAgICAgKGFuaW1hdGluZ1JlY3QudG9wIC0gdG9SZWN0LnRvcCkgLyAoYW5pbWF0aW5nUmVjdC5sZWZ0IC0gdG9SZWN0LmxlZnQpID09PSAoZnJvbVJlY3QudG9wIC0gdG9SZWN0LnRvcCkgLyAoZnJvbVJlY3QubGVmdCAtIHRvUmVjdC5sZWZ0KSkge1xuICAgICAgICAgICAgLy8gSWYgcmV0dXJuaW5nIHRvIHNhbWUgcGxhY2UgYXMgc3RhcnRlZCBmcm9tIGFuaW1hdGlvbiBhbmQgb24gc2FtZSBheGlzXG4gICAgICAgICAgICB0aW1lID0gY2FsY3VsYXRlUmVhbFRpbWUoYW5pbWF0aW5nUmVjdCwgcHJldkZyb21SZWN0LCBwcmV2VG9SZWN0LCBfdGhpcy5vcHRpb25zKTtcbiAgICAgICAgICB9XG4gICAgICAgIH0gLy8gaWYgZnJvbVJlY3QgIT0gdG9SZWN0OiBhbmltYXRlXG5cblxuICAgICAgICBpZiAoIWlzUmVjdEVxdWFsKHRvUmVjdCwgZnJvbVJlY3QpKSB7XG4gICAgICAgICAgdGFyZ2V0LnByZXZGcm9tUmVjdCA9IGZyb21SZWN0O1xuICAgICAgICAgIHRhcmdldC5wcmV2VG9SZWN0ID0gdG9SZWN0O1xuXG4gICAgICAgICAgaWYgKCF0aW1lKSB7XG4gICAgICAgICAgICB0aW1lID0gX3RoaXMub3B0aW9ucy5hbmltYXRpb247XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgX3RoaXMuYW5pbWF0ZSh0YXJnZXQsIGFuaW1hdGluZ1JlY3QsIHRvUmVjdCwgdGltZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGltZSkge1xuICAgICAgICAgIGFuaW1hdGluZyA9IHRydWU7XG4gICAgICAgICAgYW5pbWF0aW9uVGltZSA9IE1hdGgubWF4KGFuaW1hdGlvblRpbWUsIHRpbWUpO1xuICAgICAgICAgIGNsZWFyVGltZW91dCh0YXJnZXQuYW5pbWF0aW9uUmVzZXRUaW1lcik7XG4gICAgICAgICAgdGFyZ2V0LmFuaW1hdGlvblJlc2V0VGltZXIgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRhcmdldC5hbmltYXRpb25UaW1lID0gMDtcbiAgICAgICAgICAgIHRhcmdldC5wcmV2RnJvbVJlY3QgPSBudWxsO1xuICAgICAgICAgICAgdGFyZ2V0LmZyb21SZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIHRhcmdldC5wcmV2VG9SZWN0ID0gbnVsbDtcbiAgICAgICAgICAgIHRhcmdldC50aGlzQW5pbWF0aW9uRHVyYXRpb24gPSBudWxsO1xuICAgICAgICAgIH0sIHRpbWUpO1xuICAgICAgICAgIHRhcmdldC50aGlzQW5pbWF0aW9uRHVyYXRpb24gPSB0aW1lO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGNsZWFyVGltZW91dChhbmltYXRpb25DYWxsYmFja0lkKTtcblxuICAgICAgaWYgKCFhbmltYXRpbmcpIHtcbiAgICAgICAgaWYgKHR5cGVvZiBjYWxsYmFjayA9PT0gJ2Z1bmN0aW9uJykgY2FsbGJhY2soKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGFuaW1hdGlvbkNhbGxiYWNrSWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGNhbGxiYWNrID09PSAnZnVuY3Rpb24nKSBjYWxsYmFjaygpO1xuICAgICAgICB9LCBhbmltYXRpb25UaW1lKTtcbiAgICAgIH1cblxuICAgICAgYW5pbWF0aW9uU3RhdGVzID0gW107XG4gICAgfSxcbiAgICBhbmltYXRlOiBmdW5jdGlvbiBhbmltYXRlKHRhcmdldCwgY3VycmVudFJlY3QsIHRvUmVjdCwgZHVyYXRpb24pIHtcbiAgICAgIGlmIChkdXJhdGlvbikge1xuICAgICAgICBjc3ModGFyZ2V0LCAndHJhbnNpdGlvbicsICcnKTtcbiAgICAgICAgY3NzKHRhcmdldCwgJ3RyYW5zZm9ybScsICcnKTtcbiAgICAgICAgdmFyIGVsTWF0cml4ID0gbWF0cml4KHRoaXMuZWwpLFxuICAgICAgICAgICAgc2NhbGVYID0gZWxNYXRyaXggJiYgZWxNYXRyaXguYSxcbiAgICAgICAgICAgIHNjYWxlWSA9IGVsTWF0cml4ICYmIGVsTWF0cml4LmQsXG4gICAgICAgICAgICB0cmFuc2xhdGVYID0gKGN1cnJlbnRSZWN0LmxlZnQgLSB0b1JlY3QubGVmdCkgLyAoc2NhbGVYIHx8IDEpLFxuICAgICAgICAgICAgdHJhbnNsYXRlWSA9IChjdXJyZW50UmVjdC50b3AgLSB0b1JlY3QudG9wKSAvIChzY2FsZVkgfHwgMSk7XG4gICAgICAgIHRhcmdldC5hbmltYXRpbmdYID0gISF0cmFuc2xhdGVYO1xuICAgICAgICB0YXJnZXQuYW5pbWF0aW5nWSA9ICEhdHJhbnNsYXRlWTtcbiAgICAgICAgY3NzKHRhcmdldCwgJ3RyYW5zZm9ybScsICd0cmFuc2xhdGUzZCgnICsgdHJhbnNsYXRlWCArICdweCwnICsgdHJhbnNsYXRlWSArICdweCwwKScpO1xuICAgICAgICByZXBhaW50KHRhcmdldCk7IC8vIHJlcGFpbnRcblxuICAgICAgICBjc3ModGFyZ2V0LCAndHJhbnNpdGlvbicsICd0cmFuc2Zvcm0gJyArIGR1cmF0aW9uICsgJ21zJyArICh0aGlzLm9wdGlvbnMuZWFzaW5nID8gJyAnICsgdGhpcy5vcHRpb25zLmVhc2luZyA6ICcnKSk7XG4gICAgICAgIGNzcyh0YXJnZXQsICd0cmFuc2Zvcm0nLCAndHJhbnNsYXRlM2QoMCwwLDApJyk7XG4gICAgICAgIHR5cGVvZiB0YXJnZXQuYW5pbWF0ZWQgPT09ICdudW1iZXInICYmIGNsZWFyVGltZW91dCh0YXJnZXQuYW5pbWF0ZWQpO1xuICAgICAgICB0YXJnZXQuYW5pbWF0ZWQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBjc3ModGFyZ2V0LCAndHJhbnNpdGlvbicsICcnKTtcbiAgICAgICAgICBjc3ModGFyZ2V0LCAndHJhbnNmb3JtJywgJycpO1xuICAgICAgICAgIHRhcmdldC5hbmltYXRlZCA9IGZhbHNlO1xuICAgICAgICAgIHRhcmdldC5hbmltYXRpbmdYID0gZmFsc2U7XG4gICAgICAgICAgdGFyZ2V0LmFuaW1hdGluZ1kgPSBmYWxzZTtcbiAgICAgICAgfSwgZHVyYXRpb24pO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbn1cblxuZnVuY3Rpb24gcmVwYWludCh0YXJnZXQpIHtcbiAgcmV0dXJuIHRhcmdldC5vZmZzZXRXaWR0aDtcbn1cblxuZnVuY3Rpb24gY2FsY3VsYXRlUmVhbFRpbWUoYW5pbWF0aW5nUmVjdCwgZnJvbVJlY3QsIHRvUmVjdCwgb3B0aW9ucykge1xuICByZXR1cm4gTWF0aC5zcXJ0KE1hdGgucG93KGZyb21SZWN0LnRvcCAtIGFuaW1hdGluZ1JlY3QudG9wLCAyKSArIE1hdGgucG93KGZyb21SZWN0LmxlZnQgLSBhbmltYXRpbmdSZWN0LmxlZnQsIDIpKSAvIE1hdGguc3FydChNYXRoLnBvdyhmcm9tUmVjdC50b3AgLSB0b1JlY3QudG9wLCAyKSArIE1hdGgucG93KGZyb21SZWN0LmxlZnQgLSB0b1JlY3QubGVmdCwgMikpICogb3B0aW9ucy5hbmltYXRpb247XG59XG5cbnZhciBwbHVnaW5zID0gW107XG52YXIgZGVmYXVsdHMgPSB7XG4gIGluaXRpYWxpemVCeURlZmF1bHQ6IHRydWVcbn07XG52YXIgUGx1Z2luTWFuYWdlciA9IHtcbiAgbW91bnQ6IGZ1bmN0aW9uIG1vdW50KHBsdWdpbikge1xuICAgIC8vIFNldCBkZWZhdWx0IHN0YXRpYyBwcm9wZXJ0aWVzXG4gICAgZm9yICh2YXIgb3B0aW9uIGluIGRlZmF1bHRzKSB7XG4gICAgICBpZiAoZGVmYXVsdHMuaGFzT3duUHJvcGVydHkob3B0aW9uKSAmJiAhKG9wdGlvbiBpbiBwbHVnaW4pKSB7XG4gICAgICAgIHBsdWdpbltvcHRpb25dID0gZGVmYXVsdHNbb3B0aW9uXTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwbHVnaW5zLnB1c2gocGx1Z2luKTtcbiAgfSxcbiAgcGx1Z2luRXZlbnQ6IGZ1bmN0aW9uIHBsdWdpbkV2ZW50KGV2ZW50TmFtZSwgc29ydGFibGUsIGV2dCkge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB0aGlzLmV2ZW50Q2FuY2VsZWQgPSBmYWxzZTtcblxuICAgIGV2dC5jYW5jZWwgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBfdGhpcy5ldmVudENhbmNlbGVkID0gdHJ1ZTtcbiAgICB9O1xuXG4gICAgdmFyIGV2ZW50TmFtZUdsb2JhbCA9IGV2ZW50TmFtZSArICdHbG9iYWwnO1xuICAgIHBsdWdpbnMuZm9yRWFjaChmdW5jdGlvbiAocGx1Z2luKSB7XG4gICAgICBpZiAoIXNvcnRhYmxlW3BsdWdpbi5wbHVnaW5OYW1lXSkgcmV0dXJuOyAvLyBGaXJlIGdsb2JhbCBldmVudHMgaWYgaXQgZXhpc3RzIGluIHRoaXMgc29ydGFibGVcblxuICAgICAgaWYgKHNvcnRhYmxlW3BsdWdpbi5wbHVnaW5OYW1lXVtldmVudE5hbWVHbG9iYWxdKSB7XG4gICAgICAgIHNvcnRhYmxlW3BsdWdpbi5wbHVnaW5OYW1lXVtldmVudE5hbWVHbG9iYWxdKF9vYmplY3RTcHJlYWQoe1xuICAgICAgICAgIHNvcnRhYmxlOiBzb3J0YWJsZVxuICAgICAgICB9LCBldnQpKTtcbiAgICAgIH0gLy8gT25seSBmaXJlIHBsdWdpbiBldmVudCBpZiBwbHVnaW4gaXMgZW5hYmxlZCBpbiB0aGlzIHNvcnRhYmxlLFxuICAgICAgLy8gYW5kIHBsdWdpbiBoYXMgZXZlbnQgZGVmaW5lZFxuXG5cbiAgICAgIGlmIChzb3J0YWJsZS5vcHRpb25zW3BsdWdpbi5wbHVnaW5OYW1lXSAmJiBzb3J0YWJsZVtwbHVnaW4ucGx1Z2luTmFtZV1bZXZlbnROYW1lXSkge1xuICAgICAgICBzb3J0YWJsZVtwbHVnaW4ucGx1Z2luTmFtZV1bZXZlbnROYW1lXShfb2JqZWN0U3ByZWFkKHtcbiAgICAgICAgICBzb3J0YWJsZTogc29ydGFibGVcbiAgICAgICAgfSwgZXZ0KSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH0sXG4gIGluaXRpYWxpemVQbHVnaW5zOiBmdW5jdGlvbiBpbml0aWFsaXplUGx1Z2lucyhzb3J0YWJsZSwgZWwsIGRlZmF1bHRzLCBvcHRpb25zKSB7XG4gICAgcGx1Z2lucy5mb3JFYWNoKGZ1bmN0aW9uIChwbHVnaW4pIHtcbiAgICAgIHZhciBwbHVnaW5OYW1lID0gcGx1Z2luLnBsdWdpbk5hbWU7XG4gICAgICBpZiAoIXNvcnRhYmxlLm9wdGlvbnNbcGx1Z2luTmFtZV0gJiYgIXBsdWdpbi5pbml0aWFsaXplQnlEZWZhdWx0KSByZXR1cm47XG4gICAgICB2YXIgaW5pdGlhbGl6ZWQgPSBuZXcgcGx1Z2luKHNvcnRhYmxlLCBlbCwgc29ydGFibGUub3B0aW9ucyk7XG4gICAgICBpbml0aWFsaXplZC5zb3J0YWJsZSA9IHNvcnRhYmxlO1xuICAgICAgaW5pdGlhbGl6ZWQub3B0aW9ucyA9IHNvcnRhYmxlLm9wdGlvbnM7XG4gICAgICBzb3J0YWJsZVtwbHVnaW5OYW1lXSA9IGluaXRpYWxpemVkOyAvLyBBZGQgZGVmYXVsdCBvcHRpb25zIGZyb20gcGx1Z2luXG5cbiAgICAgIF9leHRlbmRzKGRlZmF1bHRzLCBpbml0aWFsaXplZC5kZWZhdWx0cyk7XG4gICAgfSk7XG5cbiAgICBmb3IgKHZhciBvcHRpb24gaW4gc29ydGFibGUub3B0aW9ucykge1xuICAgICAgaWYgKCFzb3J0YWJsZS5vcHRpb25zLmhhc093blByb3BlcnR5KG9wdGlvbikpIGNvbnRpbnVlO1xuICAgICAgdmFyIG1vZGlmaWVkID0gdGhpcy5tb2RpZnlPcHRpb24oc29ydGFibGUsIG9wdGlvbiwgc29ydGFibGUub3B0aW9uc1tvcHRpb25dKTtcblxuICAgICAgaWYgKHR5cGVvZiBtb2RpZmllZCAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgc29ydGFibGUub3B0aW9uc1tvcHRpb25dID0gbW9kaWZpZWQ7XG4gICAgICB9XG4gICAgfVxuICB9LFxuICBnZXRFdmVudFByb3BlcnRpZXM6IGZ1bmN0aW9uIGdldEV2ZW50UHJvcGVydGllcyhuYW1lLCBzb3J0YWJsZSkge1xuICAgIHZhciBldmVudFByb3BlcnRpZXMgPSB7fTtcbiAgICBwbHVnaW5zLmZvckVhY2goZnVuY3Rpb24gKHBsdWdpbikge1xuICAgICAgaWYgKHR5cGVvZiBwbHVnaW4uZXZlbnRQcm9wZXJ0aWVzICE9PSAnZnVuY3Rpb24nKSByZXR1cm47XG5cbiAgICAgIF9leHRlbmRzKGV2ZW50UHJvcGVydGllcywgcGx1Z2luLmV2ZW50UHJvcGVydGllcy5jYWxsKHNvcnRhYmxlW3BsdWdpbi5wbHVnaW5OYW1lXSwgbmFtZSkpO1xuICAgIH0pO1xuICAgIHJldHVybiBldmVudFByb3BlcnRpZXM7XG4gIH0sXG4gIG1vZGlmeU9wdGlvbjogZnVuY3Rpb24gbW9kaWZ5T3B0aW9uKHNvcnRhYmxlLCBuYW1lLCB2YWx1ZSkge1xuICAgIHZhciBtb2RpZmllZFZhbHVlO1xuICAgIHBsdWdpbnMuZm9yRWFjaChmdW5jdGlvbiAocGx1Z2luKSB7XG4gICAgICAvLyBQbHVnaW4gbXVzdCBleGlzdCBvbiB0aGUgU29ydGFibGVcbiAgICAgIGlmICghc29ydGFibGVbcGx1Z2luLnBsdWdpbk5hbWVdKSByZXR1cm47IC8vIElmIHN0YXRpYyBvcHRpb24gbGlzdGVuZXIgZXhpc3RzIGZvciB0aGlzIG9wdGlvbiwgY2FsbCBpbiB0aGUgY29udGV4dCBvZiB0aGUgU29ydGFibGUncyBpbnN0YW5jZSBvZiB0aGlzIHBsdWdpblxuXG4gICAgICBpZiAocGx1Z2luLm9wdGlvbkxpc3RlbmVycyAmJiB0eXBlb2YgcGx1Z2luLm9wdGlvbkxpc3RlbmVyc1tuYW1lXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICBtb2RpZmllZFZhbHVlID0gcGx1Z2luLm9wdGlvbkxpc3RlbmVyc1tuYW1lXS5jYWxsKHNvcnRhYmxlW3BsdWdpbi5wbHVnaW5OYW1lXSwgdmFsdWUpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHJldHVybiBtb2RpZmllZFZhbHVlO1xuICB9XG59O1xuXG5mdW5jdGlvbiBkaXNwYXRjaEV2ZW50KF9yZWYpIHtcbiAgdmFyIHNvcnRhYmxlID0gX3JlZi5zb3J0YWJsZSxcbiAgICAgIHJvb3RFbCA9IF9yZWYucm9vdEVsLFxuICAgICAgbmFtZSA9IF9yZWYubmFtZSxcbiAgICAgIHRhcmdldEVsID0gX3JlZi50YXJnZXRFbCxcbiAgICAgIGNsb25lRWwgPSBfcmVmLmNsb25lRWwsXG4gICAgICB0b0VsID0gX3JlZi50b0VsLFxuICAgICAgZnJvbUVsID0gX3JlZi5mcm9tRWwsXG4gICAgICBvbGRJbmRleCA9IF9yZWYub2xkSW5kZXgsXG4gICAgICBuZXdJbmRleCA9IF9yZWYubmV3SW5kZXgsXG4gICAgICBvbGREcmFnZ2FibGVJbmRleCA9IF9yZWYub2xkRHJhZ2dhYmxlSW5kZXgsXG4gICAgICBuZXdEcmFnZ2FibGVJbmRleCA9IF9yZWYubmV3RHJhZ2dhYmxlSW5kZXgsXG4gICAgICBvcmlnaW5hbEV2ZW50ID0gX3JlZi5vcmlnaW5hbEV2ZW50LFxuICAgICAgcHV0U29ydGFibGUgPSBfcmVmLnB1dFNvcnRhYmxlLFxuICAgICAgZXh0cmFFdmVudFByb3BlcnRpZXMgPSBfcmVmLmV4dHJhRXZlbnRQcm9wZXJ0aWVzO1xuICBzb3J0YWJsZSA9IHNvcnRhYmxlIHx8IHJvb3RFbCAmJiByb290RWxbZXhwYW5kb107XG4gIGlmICghc29ydGFibGUpIHJldHVybjtcbiAgdmFyIGV2dCxcbiAgICAgIG9wdGlvbnMgPSBzb3J0YWJsZS5vcHRpb25zLFxuICAgICAgb25OYW1lID0gJ29uJyArIG5hbWUuY2hhckF0KDApLnRvVXBwZXJDYXNlKCkgKyBuYW1lLnN1YnN0cigxKTsgLy8gU3VwcG9ydCBmb3IgbmV3IEN1c3RvbUV2ZW50IGZlYXR1cmVcblxuICBpZiAod2luZG93LkN1c3RvbUV2ZW50ICYmICFJRTExT3JMZXNzICYmICFFZGdlKSB7XG4gICAgZXZ0ID0gbmV3IEN1c3RvbUV2ZW50KG5hbWUsIHtcbiAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICBjYW5jZWxhYmxlOiB0cnVlXG4gICAgfSk7XG4gIH0gZWxzZSB7XG4gICAgZXZ0ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7XG4gICAgZXZ0LmluaXRFdmVudChuYW1lLCB0cnVlLCB0cnVlKTtcbiAgfVxuXG4gIGV2dC50byA9IHRvRWwgfHwgcm9vdEVsO1xuICBldnQuZnJvbSA9IGZyb21FbCB8fCByb290RWw7XG4gIGV2dC5pdGVtID0gdGFyZ2V0RWwgfHwgcm9vdEVsO1xuICBldnQuY2xvbmUgPSBjbG9uZUVsO1xuICBldnQub2xkSW5kZXggPSBvbGRJbmRleDtcbiAgZXZ0Lm5ld0luZGV4ID0gbmV3SW5kZXg7XG4gIGV2dC5vbGREcmFnZ2FibGVJbmRleCA9IG9sZERyYWdnYWJsZUluZGV4O1xuICBldnQubmV3RHJhZ2dhYmxlSW5kZXggPSBuZXdEcmFnZ2FibGVJbmRleDtcbiAgZXZ0Lm9yaWdpbmFsRXZlbnQgPSBvcmlnaW5hbEV2ZW50O1xuICBldnQucHVsbE1vZGUgPSBwdXRTb3J0YWJsZSA/IHB1dFNvcnRhYmxlLmxhc3RQdXRNb2RlIDogdW5kZWZpbmVkO1xuXG4gIHZhciBhbGxFdmVudFByb3BlcnRpZXMgPSBfb2JqZWN0U3ByZWFkKHt9LCBleHRyYUV2ZW50UHJvcGVydGllcywgUGx1Z2luTWFuYWdlci5nZXRFdmVudFByb3BlcnRpZXMobmFtZSwgc29ydGFibGUpKTtcblxuICBmb3IgKHZhciBvcHRpb24gaW4gYWxsRXZlbnRQcm9wZXJ0aWVzKSB7XG4gICAgZXZ0W29wdGlvbl0gPSBhbGxFdmVudFByb3BlcnRpZXNbb3B0aW9uXTtcbiAgfVxuXG4gIGlmIChyb290RWwpIHtcbiAgICByb290RWwuZGlzcGF0Y2hFdmVudChldnQpO1xuICB9XG5cbiAgaWYgKG9wdGlvbnNbb25OYW1lXSkge1xuICAgIG9wdGlvbnNbb25OYW1lXS5jYWxsKHNvcnRhYmxlLCBldnQpO1xuICB9XG59XG5cbnZhciBwbHVnaW5FdmVudCA9IGZ1bmN0aW9uIHBsdWdpbkV2ZW50KGV2ZW50TmFtZSwgc29ydGFibGUpIHtcbiAgdmFyIF9yZWYgPSBhcmd1bWVudHMubGVuZ3RoID4gMiAmJiBhcmd1bWVudHNbMl0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1syXSA6IHt9LFxuICAgICAgb3JpZ2luYWxFdmVudCA9IF9yZWYuZXZ0LFxuICAgICAgZGF0YSA9IF9vYmplY3RXaXRob3V0UHJvcGVydGllcyhfcmVmLCBbXCJldnRcIl0pO1xuXG4gIFBsdWdpbk1hbmFnZXIucGx1Z2luRXZlbnQuYmluZChTb3J0YWJsZSkoZXZlbnROYW1lLCBzb3J0YWJsZSwgX29iamVjdFNwcmVhZCh7XG4gICAgZHJhZ0VsOiBkcmFnRWwsXG4gICAgcGFyZW50RWw6IHBhcmVudEVsLFxuICAgIGdob3N0RWw6IGdob3N0RWwsXG4gICAgcm9vdEVsOiByb290RWwsXG4gICAgbmV4dEVsOiBuZXh0RWwsXG4gICAgbGFzdERvd25FbDogbGFzdERvd25FbCxcbiAgICBjbG9uZUVsOiBjbG9uZUVsLFxuICAgIGNsb25lSGlkZGVuOiBjbG9uZUhpZGRlbixcbiAgICBkcmFnU3RhcnRlZDogbW92ZWQsXG4gICAgcHV0U29ydGFibGU6IHB1dFNvcnRhYmxlLFxuICAgIGFjdGl2ZVNvcnRhYmxlOiBTb3J0YWJsZS5hY3RpdmUsXG4gICAgb3JpZ2luYWxFdmVudDogb3JpZ2luYWxFdmVudCxcbiAgICBvbGRJbmRleDogb2xkSW5kZXgsXG4gICAgb2xkRHJhZ2dhYmxlSW5kZXg6IG9sZERyYWdnYWJsZUluZGV4LFxuICAgIG5ld0luZGV4OiBuZXdJbmRleCxcbiAgICBuZXdEcmFnZ2FibGVJbmRleDogbmV3RHJhZ2dhYmxlSW5kZXgsXG4gICAgaGlkZUdob3N0Rm9yVGFyZ2V0OiBfaGlkZUdob3N0Rm9yVGFyZ2V0LFxuICAgIHVuaGlkZUdob3N0Rm9yVGFyZ2V0OiBfdW5oaWRlR2hvc3RGb3JUYXJnZXQsXG4gICAgY2xvbmVOb3dIaWRkZW46IGZ1bmN0aW9uIGNsb25lTm93SGlkZGVuKCkge1xuICAgICAgY2xvbmVIaWRkZW4gPSB0cnVlO1xuICAgIH0sXG4gICAgY2xvbmVOb3dTaG93bjogZnVuY3Rpb24gY2xvbmVOb3dTaG93bigpIHtcbiAgICAgIGNsb25lSGlkZGVuID0gZmFsc2U7XG4gICAgfSxcbiAgICBkaXNwYXRjaFNvcnRhYmxlRXZlbnQ6IGZ1bmN0aW9uIGRpc3BhdGNoU29ydGFibGVFdmVudChuYW1lKSB7XG4gICAgICBfZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgIHNvcnRhYmxlOiBzb3J0YWJsZSxcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgb3JpZ2luYWxFdmVudDogb3JpZ2luYWxFdmVudFxuICAgICAgfSk7XG4gICAgfVxuICB9LCBkYXRhKSk7XG59O1xuXG5mdW5jdGlvbiBfZGlzcGF0Y2hFdmVudChpbmZvKSB7XG4gIGRpc3BhdGNoRXZlbnQoX29iamVjdFNwcmVhZCh7XG4gICAgcHV0U29ydGFibGU6IHB1dFNvcnRhYmxlLFxuICAgIGNsb25lRWw6IGNsb25lRWwsXG4gICAgdGFyZ2V0RWw6IGRyYWdFbCxcbiAgICByb290RWw6IHJvb3RFbCxcbiAgICBvbGRJbmRleDogb2xkSW5kZXgsXG4gICAgb2xkRHJhZ2dhYmxlSW5kZXg6IG9sZERyYWdnYWJsZUluZGV4LFxuICAgIG5ld0luZGV4OiBuZXdJbmRleCxcbiAgICBuZXdEcmFnZ2FibGVJbmRleDogbmV3RHJhZ2dhYmxlSW5kZXhcbiAgfSwgaW5mbykpO1xufVxuXG52YXIgZHJhZ0VsLFxuICAgIHBhcmVudEVsLFxuICAgIGdob3N0RWwsXG4gICAgcm9vdEVsLFxuICAgIG5leHRFbCxcbiAgICBsYXN0RG93bkVsLFxuICAgIGNsb25lRWwsXG4gICAgY2xvbmVIaWRkZW4sXG4gICAgb2xkSW5kZXgsXG4gICAgbmV3SW5kZXgsXG4gICAgb2xkRHJhZ2dhYmxlSW5kZXgsXG4gICAgbmV3RHJhZ2dhYmxlSW5kZXgsXG4gICAgYWN0aXZlR3JvdXAsXG4gICAgcHV0U29ydGFibGUsXG4gICAgYXdhaXRpbmdEcmFnU3RhcnRlZCA9IGZhbHNlLFxuICAgIGlnbm9yZU5leHRDbGljayA9IGZhbHNlLFxuICAgIHNvcnRhYmxlcyA9IFtdLFxuICAgIHRhcEV2dCxcbiAgICB0b3VjaEV2dCxcbiAgICBsYXN0RHgsXG4gICAgbGFzdER5LFxuICAgIHRhcERpc3RhbmNlTGVmdCxcbiAgICB0YXBEaXN0YW5jZVRvcCxcbiAgICBtb3ZlZCxcbiAgICBsYXN0VGFyZ2V0LFxuICAgIGxhc3REaXJlY3Rpb24sXG4gICAgcGFzdEZpcnN0SW52ZXJ0VGhyZXNoID0gZmFsc2UsXG4gICAgaXNDaXJjdW1zdGFudGlhbEludmVydCA9IGZhbHNlLFxuICAgIHRhcmdldE1vdmVEaXN0YW5jZSxcbiAgICAvLyBGb3IgcG9zaXRpb25pbmcgZ2hvc3QgYWJzb2x1dGVseVxuZ2hvc3RSZWxhdGl2ZVBhcmVudCxcbiAgICBnaG9zdFJlbGF0aXZlUGFyZW50SW5pdGlhbFNjcm9sbCA9IFtdLFxuICAgIC8vIChsZWZ0LCB0b3ApXG5fc2lsZW50ID0gZmFsc2UsXG4gICAgc2F2ZWRJbnB1dENoZWNrZWQgPSBbXTtcbi8qKiBAY29uc3QgKi9cblxudmFyIGRvY3VtZW50RXhpc3RzID0gdHlwZW9mIGRvY3VtZW50ICE9PSAndW5kZWZpbmVkJyxcbiAgICBQb3NpdGlvbkdob3N0QWJzb2x1dGVseSA9IElPUyxcbiAgICBDU1NGbG9hdFByb3BlcnR5ID0gRWRnZSB8fCBJRTExT3JMZXNzID8gJ2Nzc0Zsb2F0JyA6ICdmbG9hdCcsXG4gICAgLy8gVGhpcyB3aWxsIG5vdCBwYXNzIGZvciBJRTksIGJlY2F1c2UgSUU5IERuRCBvbmx5IHdvcmtzIG9uIGFuY2hvcnNcbnN1cHBvcnREcmFnZ2FibGUgPSBkb2N1bWVudEV4aXN0cyAmJiAhQ2hyb21lRm9yQW5kcm9pZCAmJiAhSU9TICYmICdkcmFnZ2FibGUnIGluIGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2RpdicpLFxuICAgIHN1cHBvcnRDc3NQb2ludGVyRXZlbnRzID0gZnVuY3Rpb24gKCkge1xuICBpZiAoIWRvY3VtZW50RXhpc3RzKSByZXR1cm47IC8vIGZhbHNlIHdoZW4gPD0gSUUxMVxuXG4gIGlmIChJRTExT3JMZXNzKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xuICB9XG5cbiAgdmFyIGVsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgneCcpO1xuICBlbC5zdHlsZS5jc3NUZXh0ID0gJ3BvaW50ZXItZXZlbnRzOmF1dG8nO1xuICByZXR1cm4gZWwuc3R5bGUucG9pbnRlckV2ZW50cyA9PT0gJ2F1dG8nO1xufSgpLFxuICAgIF9kZXRlY3REaXJlY3Rpb24gPSBmdW5jdGlvbiBfZGV0ZWN0RGlyZWN0aW9uKGVsLCBvcHRpb25zKSB7XG4gIHZhciBlbENTUyA9IGNzcyhlbCksXG4gICAgICBlbFdpZHRoID0gcGFyc2VJbnQoZWxDU1Mud2lkdGgpIC0gcGFyc2VJbnQoZWxDU1MucGFkZGluZ0xlZnQpIC0gcGFyc2VJbnQoZWxDU1MucGFkZGluZ1JpZ2h0KSAtIHBhcnNlSW50KGVsQ1NTLmJvcmRlckxlZnRXaWR0aCkgLSBwYXJzZUludChlbENTUy5ib3JkZXJSaWdodFdpZHRoKSxcbiAgICAgIGNoaWxkMSA9IGdldENoaWxkKGVsLCAwLCBvcHRpb25zKSxcbiAgICAgIGNoaWxkMiA9IGdldENoaWxkKGVsLCAxLCBvcHRpb25zKSxcbiAgICAgIGZpcnN0Q2hpbGRDU1MgPSBjaGlsZDEgJiYgY3NzKGNoaWxkMSksXG4gICAgICBzZWNvbmRDaGlsZENTUyA9IGNoaWxkMiAmJiBjc3MoY2hpbGQyKSxcbiAgICAgIGZpcnN0Q2hpbGRXaWR0aCA9IGZpcnN0Q2hpbGRDU1MgJiYgcGFyc2VJbnQoZmlyc3RDaGlsZENTUy5tYXJnaW5MZWZ0KSArIHBhcnNlSW50KGZpcnN0Q2hpbGRDU1MubWFyZ2luUmlnaHQpICsgZ2V0UmVjdChjaGlsZDEpLndpZHRoLFxuICAgICAgc2Vjb25kQ2hpbGRXaWR0aCA9IHNlY29uZENoaWxkQ1NTICYmIHBhcnNlSW50KHNlY29uZENoaWxkQ1NTLm1hcmdpbkxlZnQpICsgcGFyc2VJbnQoc2Vjb25kQ2hpbGRDU1MubWFyZ2luUmlnaHQpICsgZ2V0UmVjdChjaGlsZDIpLndpZHRoO1xuXG4gIGlmIChlbENTUy5kaXNwbGF5ID09PSAnZmxleCcpIHtcbiAgICByZXR1cm4gZWxDU1MuZmxleERpcmVjdGlvbiA9PT0gJ2NvbHVtbicgfHwgZWxDU1MuZmxleERpcmVjdGlvbiA9PT0gJ2NvbHVtbi1yZXZlcnNlJyA/ICd2ZXJ0aWNhbCcgOiAnaG9yaXpvbnRhbCc7XG4gIH1cblxuICBpZiAoZWxDU1MuZGlzcGxheSA9PT0gJ2dyaWQnKSB7XG4gICAgcmV0dXJuIGVsQ1NTLmdyaWRUZW1wbGF0ZUNvbHVtbnMuc3BsaXQoJyAnKS5sZW5ndGggPD0gMSA/ICd2ZXJ0aWNhbCcgOiAnaG9yaXpvbnRhbCc7XG4gIH1cblxuICBpZiAoY2hpbGQxICYmIGZpcnN0Q2hpbGRDU1NbXCJmbG9hdFwiXSAmJiBmaXJzdENoaWxkQ1NTW1wiZmxvYXRcIl0gIT09ICdub25lJykge1xuICAgIHZhciB0b3VjaGluZ1NpZGVDaGlsZDIgPSBmaXJzdENoaWxkQ1NTW1wiZmxvYXRcIl0gPT09ICdsZWZ0JyA/ICdsZWZ0JyA6ICdyaWdodCc7XG4gICAgcmV0dXJuIGNoaWxkMiAmJiAoc2Vjb25kQ2hpbGRDU1MuY2xlYXIgPT09ICdib3RoJyB8fCBzZWNvbmRDaGlsZENTUy5jbGVhciA9PT0gdG91Y2hpbmdTaWRlQ2hpbGQyKSA/ICd2ZXJ0aWNhbCcgOiAnaG9yaXpvbnRhbCc7XG4gIH1cblxuICByZXR1cm4gY2hpbGQxICYmIChmaXJzdENoaWxkQ1NTLmRpc3BsYXkgPT09ICdibG9jaycgfHwgZmlyc3RDaGlsZENTUy5kaXNwbGF5ID09PSAnZmxleCcgfHwgZmlyc3RDaGlsZENTUy5kaXNwbGF5ID09PSAndGFibGUnIHx8IGZpcnN0Q2hpbGRDU1MuZGlzcGxheSA9PT0gJ2dyaWQnIHx8IGZpcnN0Q2hpbGRXaWR0aCA+PSBlbFdpZHRoICYmIGVsQ1NTW0NTU0Zsb2F0UHJvcGVydHldID09PSAnbm9uZScgfHwgY2hpbGQyICYmIGVsQ1NTW0NTU0Zsb2F0UHJvcGVydHldID09PSAnbm9uZScgJiYgZmlyc3RDaGlsZFdpZHRoICsgc2Vjb25kQ2hpbGRXaWR0aCA+IGVsV2lkdGgpID8gJ3ZlcnRpY2FsJyA6ICdob3Jpem9udGFsJztcbn0sXG4gICAgX2RyYWdFbEluUm93Q29sdW1uID0gZnVuY3Rpb24gX2RyYWdFbEluUm93Q29sdW1uKGRyYWdSZWN0LCB0YXJnZXRSZWN0LCB2ZXJ0aWNhbCkge1xuICB2YXIgZHJhZ0VsUzFPcHAgPSB2ZXJ0aWNhbCA/IGRyYWdSZWN0LmxlZnQgOiBkcmFnUmVjdC50b3AsXG4gICAgICBkcmFnRWxTMk9wcCA9IHZlcnRpY2FsID8gZHJhZ1JlY3QucmlnaHQgOiBkcmFnUmVjdC5ib3R0b20sXG4gICAgICBkcmFnRWxPcHBMZW5ndGggPSB2ZXJ0aWNhbCA/IGRyYWdSZWN0LndpZHRoIDogZHJhZ1JlY3QuaGVpZ2h0LFxuICAgICAgdGFyZ2V0UzFPcHAgPSB2ZXJ0aWNhbCA/IHRhcmdldFJlY3QubGVmdCA6IHRhcmdldFJlY3QudG9wLFxuICAgICAgdGFyZ2V0UzJPcHAgPSB2ZXJ0aWNhbCA/IHRhcmdldFJlY3QucmlnaHQgOiB0YXJnZXRSZWN0LmJvdHRvbSxcbiAgICAgIHRhcmdldE9wcExlbmd0aCA9IHZlcnRpY2FsID8gdGFyZ2V0UmVjdC53aWR0aCA6IHRhcmdldFJlY3QuaGVpZ2h0O1xuICByZXR1cm4gZHJhZ0VsUzFPcHAgPT09IHRhcmdldFMxT3BwIHx8IGRyYWdFbFMyT3BwID09PSB0YXJnZXRTMk9wcCB8fCBkcmFnRWxTMU9wcCArIGRyYWdFbE9wcExlbmd0aCAvIDIgPT09IHRhcmdldFMxT3BwICsgdGFyZ2V0T3BwTGVuZ3RoIC8gMjtcbn0sXG5cbi8qKlxuICogRGV0ZWN0cyBmaXJzdCBuZWFyZXN0IGVtcHR5IHNvcnRhYmxlIHRvIFggYW5kIFkgcG9zaXRpb24gdXNpbmcgZW1wdHlJbnNlcnRUaHJlc2hvbGQuXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHggICAgICBYIHBvc2l0aW9uXG4gKiBAcGFyYW0gIHtOdW1iZXJ9IHkgICAgICBZIHBvc2l0aW9uXG4gKiBAcmV0dXJuIHtIVE1MRWxlbWVudH0gICBFbGVtZW50IG9mIHRoZSBmaXJzdCBmb3VuZCBuZWFyZXN0IFNvcnRhYmxlXG4gKi9cbl9kZXRlY3ROZWFyZXN0RW1wdHlTb3J0YWJsZSA9IGZ1bmN0aW9uIF9kZXRlY3ROZWFyZXN0RW1wdHlTb3J0YWJsZSh4LCB5KSB7XG4gIHZhciByZXQ7XG4gIHNvcnRhYmxlcy5zb21lKGZ1bmN0aW9uIChzb3J0YWJsZSkge1xuICAgIGlmIChsYXN0Q2hpbGQoc29ydGFibGUpKSByZXR1cm47XG4gICAgdmFyIHJlY3QgPSBnZXRSZWN0KHNvcnRhYmxlKSxcbiAgICAgICAgdGhyZXNob2xkID0gc29ydGFibGVbZXhwYW5kb10ub3B0aW9ucy5lbXB0eUluc2VydFRocmVzaG9sZCxcbiAgICAgICAgaW5zaWRlSG9yaXpvbnRhbGx5ID0geCA+PSByZWN0LmxlZnQgLSB0aHJlc2hvbGQgJiYgeCA8PSByZWN0LnJpZ2h0ICsgdGhyZXNob2xkLFxuICAgICAgICBpbnNpZGVWZXJ0aWNhbGx5ID0geSA+PSByZWN0LnRvcCAtIHRocmVzaG9sZCAmJiB5IDw9IHJlY3QuYm90dG9tICsgdGhyZXNob2xkO1xuXG4gICAgaWYgKHRocmVzaG9sZCAmJiBpbnNpZGVIb3Jpem9udGFsbHkgJiYgaW5zaWRlVmVydGljYWxseSkge1xuICAgICAgcmV0dXJuIHJldCA9IHNvcnRhYmxlO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiByZXQ7XG59LFxuICAgIF9wcmVwYXJlR3JvdXAgPSBmdW5jdGlvbiBfcHJlcGFyZUdyb3VwKG9wdGlvbnMpIHtcbiAgZnVuY3Rpb24gdG9Gbih2YWx1ZSwgcHVsbCkge1xuICAgIHJldHVybiBmdW5jdGlvbiAodG8sIGZyb20sIGRyYWdFbCwgZXZ0KSB7XG4gICAgICB2YXIgc2FtZUdyb3VwID0gdG8ub3B0aW9ucy5ncm91cC5uYW1lICYmIGZyb20ub3B0aW9ucy5ncm91cC5uYW1lICYmIHRvLm9wdGlvbnMuZ3JvdXAubmFtZSA9PT0gZnJvbS5vcHRpb25zLmdyb3VwLm5hbWU7XG5cbiAgICAgIGlmICh2YWx1ZSA9PSBudWxsICYmIChwdWxsIHx8IHNhbWVHcm91cCkpIHtcbiAgICAgICAgLy8gRGVmYXVsdCBwdWxsIHZhbHVlXG4gICAgICAgIC8vIERlZmF1bHQgcHVsbCBhbmQgcHV0IHZhbHVlIGlmIHNhbWUgZ3JvdXBcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICB9IGVsc2UgaWYgKHZhbHVlID09IG51bGwgfHwgdmFsdWUgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH0gZWxzZSBpZiAocHVsbCAmJiB2YWx1ZSA9PT0gJ2Nsb25lJykge1xuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICB9IGVsc2UgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICByZXR1cm4gdG9Gbih2YWx1ZSh0bywgZnJvbSwgZHJhZ0VsLCBldnQpLCBwdWxsKSh0bywgZnJvbSwgZHJhZ0VsLCBldnQpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFyIG90aGVyR3JvdXAgPSAocHVsbCA/IHRvIDogZnJvbSkub3B0aW9ucy5ncm91cC5uYW1lO1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IHRydWUgfHwgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiB2YWx1ZSA9PT0gb3RoZXJHcm91cCB8fCB2YWx1ZS5qb2luICYmIHZhbHVlLmluZGV4T2Yob3RoZXJHcm91cCkgPiAtMTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgdmFyIGdyb3VwID0ge307XG4gIHZhciBvcmlnaW5hbEdyb3VwID0gb3B0aW9ucy5ncm91cDtcblxuICBpZiAoIW9yaWdpbmFsR3JvdXAgfHwgX3R5cGVvZihvcmlnaW5hbEdyb3VwKSAhPSAnb2JqZWN0Jykge1xuICAgIG9yaWdpbmFsR3JvdXAgPSB7XG4gICAgICBuYW1lOiBvcmlnaW5hbEdyb3VwXG4gICAgfTtcbiAgfVxuXG4gIGdyb3VwLm5hbWUgPSBvcmlnaW5hbEdyb3VwLm5hbWU7XG4gIGdyb3VwLmNoZWNrUHVsbCA9IHRvRm4ob3JpZ2luYWxHcm91cC5wdWxsLCB0cnVlKTtcbiAgZ3JvdXAuY2hlY2tQdXQgPSB0b0ZuKG9yaWdpbmFsR3JvdXAucHV0KTtcbiAgZ3JvdXAucmV2ZXJ0Q2xvbmUgPSBvcmlnaW5hbEdyb3VwLnJldmVydENsb25lO1xuICBvcHRpb25zLmdyb3VwID0gZ3JvdXA7XG59LFxuICAgIF9oaWRlR2hvc3RGb3JUYXJnZXQgPSBmdW5jdGlvbiBfaGlkZUdob3N0Rm9yVGFyZ2V0KCkge1xuICBpZiAoIXN1cHBvcnRDc3NQb2ludGVyRXZlbnRzICYmIGdob3N0RWwpIHtcbiAgICBjc3MoZ2hvc3RFbCwgJ2Rpc3BsYXknLCAnbm9uZScpO1xuICB9XG59LFxuICAgIF91bmhpZGVHaG9zdEZvclRhcmdldCA9IGZ1bmN0aW9uIF91bmhpZGVHaG9zdEZvclRhcmdldCgpIHtcbiAgaWYgKCFzdXBwb3J0Q3NzUG9pbnRlckV2ZW50cyAmJiBnaG9zdEVsKSB7XG4gICAgY3NzKGdob3N0RWwsICdkaXNwbGF5JywgJycpO1xuICB9XG59OyAvLyAjMTE4NCBmaXggLSBQcmV2ZW50IGNsaWNrIGV2ZW50IG9uIGZhbGxiYWNrIGlmIGRyYWdnZWQgYnV0IGl0ZW0gbm90IGNoYW5nZWQgcG9zaXRpb25cblxuXG5pZiAoZG9jdW1lbnRFeGlzdHMpIHtcbiAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCBmdW5jdGlvbiAoZXZ0KSB7XG4gICAgaWYgKGlnbm9yZU5leHRDbGljaykge1xuICAgICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBldnQuc3RvcFByb3BhZ2F0aW9uICYmIGV2dC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIGV2dC5zdG9wSW1tZWRpYXRlUHJvcGFnYXRpb24gJiYgZXZ0LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgaWdub3JlTmV4dENsaWNrID0gZmFsc2U7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9LCB0cnVlKTtcbn1cblxudmFyIG5lYXJlc3RFbXB0eUluc2VydERldGVjdEV2ZW50ID0gZnVuY3Rpb24gbmVhcmVzdEVtcHR5SW5zZXJ0RGV0ZWN0RXZlbnQoZXZ0KSB7XG4gIGlmIChkcmFnRWwpIHtcbiAgICBldnQgPSBldnQudG91Y2hlcyA/IGV2dC50b3VjaGVzWzBdIDogZXZ0O1xuXG4gICAgdmFyIG5lYXJlc3QgPSBfZGV0ZWN0TmVhcmVzdEVtcHR5U29ydGFibGUoZXZ0LmNsaWVudFgsIGV2dC5jbGllbnRZKTtcblxuICAgIGlmIChuZWFyZXN0KSB7XG4gICAgICAvLyBDcmVhdGUgaW1pdGF0aW9uIGV2ZW50XG4gICAgICB2YXIgZXZlbnQgPSB7fTtcblxuICAgICAgZm9yICh2YXIgaSBpbiBldnQpIHtcbiAgICAgICAgaWYgKGV2dC5oYXNPd25Qcm9wZXJ0eShpKSkge1xuICAgICAgICAgIGV2ZW50W2ldID0gZXZ0W2ldO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGV2ZW50LnRhcmdldCA9IGV2ZW50LnJvb3RFbCA9IG5lYXJlc3Q7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCA9IHZvaWQgMDtcbiAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbiA9IHZvaWQgMDtcblxuICAgICAgbmVhcmVzdFtleHBhbmRvXS5fb25EcmFnT3ZlcihldmVudCk7XG4gICAgfVxuICB9XG59O1xuXG52YXIgX2NoZWNrT3V0c2lkZVRhcmdldEVsID0gZnVuY3Rpb24gX2NoZWNrT3V0c2lkZVRhcmdldEVsKGV2dCkge1xuICBpZiAoZHJhZ0VsKSB7XG4gICAgZHJhZ0VsLnBhcmVudE5vZGVbZXhwYW5kb10uX2lzT3V0c2lkZVRoaXNFbChldnQudGFyZ2V0KTtcbiAgfVxufTtcbi8qKlxuICogQGNsYXNzICBTb3J0YWJsZVxuICogQHBhcmFtICB7SFRNTEVsZW1lbnR9ICBlbFxuICogQHBhcmFtICB7T2JqZWN0fSAgICAgICBbb3B0aW9uc11cbiAqL1xuXG5cbmZ1bmN0aW9uIFNvcnRhYmxlKGVsLCBvcHRpb25zKSB7XG4gIGlmICghKGVsICYmIGVsLm5vZGVUeXBlICYmIGVsLm5vZGVUeXBlID09PSAxKSkge1xuICAgIHRocm93IFwiU29ydGFibGU6IGBlbGAgbXVzdCBiZSBhbiBIVE1MRWxlbWVudCwgbm90IFwiLmNvbmNhdCh7fS50b1N0cmluZy5jYWxsKGVsKSk7XG4gIH1cblxuICB0aGlzLmVsID0gZWw7IC8vIHJvb3QgZWxlbWVudFxuXG4gIHRoaXMub3B0aW9ucyA9IG9wdGlvbnMgPSBfZXh0ZW5kcyh7fSwgb3B0aW9ucyk7IC8vIEV4cG9ydCBpbnN0YW5jZVxuXG4gIGVsW2V4cGFuZG9dID0gdGhpcztcbiAgdmFyIGRlZmF1bHRzID0ge1xuICAgIGdyb3VwOiBudWxsLFxuICAgIHNvcnQ6IHRydWUsXG4gICAgZGlzYWJsZWQ6IGZhbHNlLFxuICAgIHN0b3JlOiBudWxsLFxuICAgIGhhbmRsZTogbnVsbCxcbiAgICBkcmFnZ2FibGU6IC9eW3VvXWwkL2kudGVzdChlbC5ub2RlTmFtZSkgPyAnPmxpJyA6ICc+KicsXG4gICAgc3dhcFRocmVzaG9sZDogMSxcbiAgICAvLyBwZXJjZW50YWdlOyAwIDw9IHggPD0gMVxuICAgIGludmVydFN3YXA6IGZhbHNlLFxuICAgIC8vIGludmVydCBhbHdheXNcbiAgICBpbnZlcnRlZFN3YXBUaHJlc2hvbGQ6IG51bGwsXG4gICAgLy8gd2lsbCBiZSBzZXQgdG8gc2FtZSBhcyBzd2FwVGhyZXNob2xkIGlmIGRlZmF1bHRcbiAgICByZW1vdmVDbG9uZU9uSGlkZTogdHJ1ZSxcbiAgICBkaXJlY3Rpb246IGZ1bmN0aW9uIGRpcmVjdGlvbigpIHtcbiAgICAgIHJldHVybiBfZGV0ZWN0RGlyZWN0aW9uKGVsLCB0aGlzLm9wdGlvbnMpO1xuICAgIH0sXG4gICAgZ2hvc3RDbGFzczogJ3NvcnRhYmxlLWdob3N0JyxcbiAgICBjaG9zZW5DbGFzczogJ3NvcnRhYmxlLWNob3NlbicsXG4gICAgZHJhZ0NsYXNzOiAnc29ydGFibGUtZHJhZycsXG4gICAgaWdub3JlOiAnYSwgaW1nJyxcbiAgICBmaWx0ZXI6IG51bGwsXG4gICAgcHJldmVudE9uRmlsdGVyOiB0cnVlLFxuICAgIGFuaW1hdGlvbjogMCxcbiAgICBlYXNpbmc6IG51bGwsXG4gICAgc2V0RGF0YTogZnVuY3Rpb24gc2V0RGF0YShkYXRhVHJhbnNmZXIsIGRyYWdFbCkge1xuICAgICAgZGF0YVRyYW5zZmVyLnNldERhdGEoJ1RleHQnLCBkcmFnRWwudGV4dENvbnRlbnQpO1xuICAgIH0sXG4gICAgZHJvcEJ1YmJsZTogZmFsc2UsXG4gICAgZHJhZ292ZXJCdWJibGU6IGZhbHNlLFxuICAgIGRhdGFJZEF0dHI6ICdkYXRhLWlkJyxcbiAgICBkZWxheTogMCxcbiAgICBkZWxheU9uVG91Y2hPbmx5OiBmYWxzZSxcbiAgICB0b3VjaFN0YXJ0VGhyZXNob2xkOiAoTnVtYmVyLnBhcnNlSW50ID8gTnVtYmVyIDogd2luZG93KS5wYXJzZUludCh3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbywgMTApIHx8IDEsXG4gICAgZm9yY2VGYWxsYmFjazogZmFsc2UsXG4gICAgZmFsbGJhY2tDbGFzczogJ3NvcnRhYmxlLWZhbGxiYWNrJyxcbiAgICBmYWxsYmFja09uQm9keTogZmFsc2UsXG4gICAgZmFsbGJhY2tUb2xlcmFuY2U6IDAsXG4gICAgZmFsbGJhY2tPZmZzZXQ6IHtcbiAgICAgIHg6IDAsXG4gICAgICB5OiAwXG4gICAgfSxcbiAgICBzdXBwb3J0UG9pbnRlcjogU29ydGFibGUuc3VwcG9ydFBvaW50ZXIgIT09IGZhbHNlICYmICdQb2ludGVyRXZlbnQnIGluIHdpbmRvdyxcbiAgICBlbXB0eUluc2VydFRocmVzaG9sZDogNVxuICB9O1xuICBQbHVnaW5NYW5hZ2VyLmluaXRpYWxpemVQbHVnaW5zKHRoaXMsIGVsLCBkZWZhdWx0cyk7IC8vIFNldCBkZWZhdWx0IG9wdGlvbnNcblxuICBmb3IgKHZhciBuYW1lIGluIGRlZmF1bHRzKSB7XG4gICAgIShuYW1lIGluIG9wdGlvbnMpICYmIChvcHRpb25zW25hbWVdID0gZGVmYXVsdHNbbmFtZV0pO1xuICB9XG5cbiAgX3ByZXBhcmVHcm91cChvcHRpb25zKTsgLy8gQmluZCBhbGwgcHJpdmF0ZSBtZXRob2RzXG5cblxuICBmb3IgKHZhciBmbiBpbiB0aGlzKSB7XG4gICAgaWYgKGZuLmNoYXJBdCgwKSA9PT0gJ18nICYmIHR5cGVvZiB0aGlzW2ZuXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgdGhpc1tmbl0gPSB0aGlzW2ZuXS5iaW5kKHRoaXMpO1xuICAgIH1cbiAgfSAvLyBTZXR1cCBkcmFnIG1vZGVcblxuXG4gIHRoaXMubmF0aXZlRHJhZ2dhYmxlID0gb3B0aW9ucy5mb3JjZUZhbGxiYWNrID8gZmFsc2UgOiBzdXBwb3J0RHJhZ2dhYmxlO1xuXG4gIGlmICh0aGlzLm5hdGl2ZURyYWdnYWJsZSkge1xuICAgIC8vIFRvdWNoIHN0YXJ0IHRocmVzaG9sZCBjYW5ub3QgYmUgZ3JlYXRlciB0aGFuIHRoZSBuYXRpdmUgZHJhZ3N0YXJ0IHRocmVzaG9sZFxuICAgIHRoaXMub3B0aW9ucy50b3VjaFN0YXJ0VGhyZXNob2xkID0gMTtcbiAgfSAvLyBCaW5kIGV2ZW50c1xuXG5cbiAgaWYgKG9wdGlvbnMuc3VwcG9ydFBvaW50ZXIpIHtcbiAgICBvbihlbCwgJ3BvaW50ZXJkb3duJywgdGhpcy5fb25UYXBTdGFydCk7XG4gIH0gZWxzZSB7XG4gICAgb24oZWwsICdtb3VzZWRvd24nLCB0aGlzLl9vblRhcFN0YXJ0KTtcbiAgICBvbihlbCwgJ3RvdWNoc3RhcnQnLCB0aGlzLl9vblRhcFN0YXJ0KTtcbiAgfVxuXG4gIGlmICh0aGlzLm5hdGl2ZURyYWdnYWJsZSkge1xuICAgIG9uKGVsLCAnZHJhZ292ZXInLCB0aGlzKTtcbiAgICBvbihlbCwgJ2RyYWdlbnRlcicsIHRoaXMpO1xuICB9XG5cbiAgc29ydGFibGVzLnB1c2godGhpcy5lbCk7IC8vIFJlc3RvcmUgc29ydGluZ1xuXG4gIG9wdGlvbnMuc3RvcmUgJiYgb3B0aW9ucy5zdG9yZS5nZXQgJiYgdGhpcy5zb3J0KG9wdGlvbnMuc3RvcmUuZ2V0KHRoaXMpIHx8IFtdKTsgLy8gQWRkIGFuaW1hdGlvbiBzdGF0ZSBtYW5hZ2VyXG5cbiAgX2V4dGVuZHModGhpcywgQW5pbWF0aW9uU3RhdGVNYW5hZ2VyKCkpO1xufVxuXG5Tb3J0YWJsZS5wcm90b3R5cGUgPVxuLyoqIEBsZW5kcyBTb3J0YWJsZS5wcm90b3R5cGUgKi9cbntcbiAgY29uc3RydWN0b3I6IFNvcnRhYmxlLFxuICBfaXNPdXRzaWRlVGhpc0VsOiBmdW5jdGlvbiBfaXNPdXRzaWRlVGhpc0VsKHRhcmdldCkge1xuICAgIGlmICghdGhpcy5lbC5jb250YWlucyh0YXJnZXQpICYmIHRhcmdldCAhPT0gdGhpcy5lbCkge1xuICAgICAgbGFzdFRhcmdldCA9IG51bGw7XG4gICAgfVxuICB9LFxuICBfZ2V0RGlyZWN0aW9uOiBmdW5jdGlvbiBfZ2V0RGlyZWN0aW9uKGV2dCwgdGFyZ2V0KSB7XG4gICAgcmV0dXJuIHR5cGVvZiB0aGlzLm9wdGlvbnMuZGlyZWN0aW9uID09PSAnZnVuY3Rpb24nID8gdGhpcy5vcHRpb25zLmRpcmVjdGlvbi5jYWxsKHRoaXMsIGV2dCwgdGFyZ2V0LCBkcmFnRWwpIDogdGhpcy5vcHRpb25zLmRpcmVjdGlvbjtcbiAgfSxcbiAgX29uVGFwU3RhcnQ6IGZ1bmN0aW9uIF9vblRhcFN0YXJ0KFxuICAvKiogRXZlbnR8VG91Y2hFdmVudCAqL1xuICBldnQpIHtcbiAgICBpZiAoIWV2dC5jYW5jZWxhYmxlKSByZXR1cm47XG5cbiAgICB2YXIgX3RoaXMgPSB0aGlzLFxuICAgICAgICBlbCA9IHRoaXMuZWwsXG4gICAgICAgIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnMsXG4gICAgICAgIHByZXZlbnRPbkZpbHRlciA9IG9wdGlvbnMucHJldmVudE9uRmlsdGVyLFxuICAgICAgICB0eXBlID0gZXZ0LnR5cGUsXG4gICAgICAgIHRvdWNoID0gZXZ0LnRvdWNoZXMgJiYgZXZ0LnRvdWNoZXNbMF0gfHwgZXZ0LnBvaW50ZXJUeXBlICYmIGV2dC5wb2ludGVyVHlwZSA9PT0gJ3RvdWNoJyAmJiBldnQsXG4gICAgICAgIHRhcmdldCA9ICh0b3VjaCB8fCBldnQpLnRhcmdldCxcbiAgICAgICAgb3JpZ2luYWxUYXJnZXQgPSBldnQudGFyZ2V0LnNoYWRvd1Jvb3QgJiYgKGV2dC5wYXRoICYmIGV2dC5wYXRoWzBdIHx8IGV2dC5jb21wb3NlZFBhdGggJiYgZXZ0LmNvbXBvc2VkUGF0aCgpWzBdKSB8fCB0YXJnZXQsXG4gICAgICAgIGZpbHRlciA9IG9wdGlvbnMuZmlsdGVyO1xuXG4gICAgX3NhdmVJbnB1dENoZWNrZWRTdGF0ZShlbCk7IC8vIERvbid0IHRyaWdnZXIgc3RhcnQgZXZlbnQgd2hlbiBhbiBlbGVtZW50IGlzIGJlZW4gZHJhZ2dlZCwgb3RoZXJ3aXNlIHRoZSBldnQub2xkaW5kZXggYWx3YXlzIHdyb25nIHdoZW4gc2V0IG9wdGlvbi5ncm91cC5cblxuXG4gICAgaWYgKGRyYWdFbCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICgvbW91c2Vkb3dufHBvaW50ZXJkb3duLy50ZXN0KHR5cGUpICYmIGV2dC5idXR0b24gIT09IDAgfHwgb3B0aW9ucy5kaXNhYmxlZCkge1xuICAgICAgcmV0dXJuOyAvLyBvbmx5IGxlZnQgYnV0dG9uIGFuZCBlbmFibGVkXG4gICAgfSAvLyBjYW5jZWwgZG5kIGlmIG9yaWdpbmFsIHRhcmdldCBpcyBjb250ZW50IGVkaXRhYmxlXG5cblxuICAgIGlmIChvcmlnaW5hbFRhcmdldC5pc0NvbnRlbnRFZGl0YWJsZSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIHRhcmdldCA9IGNsb3Nlc3QodGFyZ2V0LCBvcHRpb25zLmRyYWdnYWJsZSwgZWwsIGZhbHNlKTtcblxuICAgIGlmICh0YXJnZXQgJiYgdGFyZ2V0LmFuaW1hdGVkKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGxhc3REb3duRWwgPT09IHRhcmdldCkge1xuICAgICAgLy8gSWdub3JpbmcgZHVwbGljYXRlIGBkb3duYFxuICAgICAgcmV0dXJuO1xuICAgIH0gLy8gR2V0IHRoZSBpbmRleCBvZiB0aGUgZHJhZ2dlZCBlbGVtZW50IHdpdGhpbiBpdHMgcGFyZW50XG5cblxuICAgIG9sZEluZGV4ID0gaW5kZXgodGFyZ2V0KTtcbiAgICBvbGREcmFnZ2FibGVJbmRleCA9IGluZGV4KHRhcmdldCwgb3B0aW9ucy5kcmFnZ2FibGUpOyAvLyBDaGVjayBmaWx0ZXJcblxuICAgIGlmICh0eXBlb2YgZmlsdGVyID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICBpZiAoZmlsdGVyLmNhbGwodGhpcywgZXZ0LCB0YXJnZXQsIHRoaXMpKSB7XG4gICAgICAgIF9kaXNwYXRjaEV2ZW50KHtcbiAgICAgICAgICBzb3J0YWJsZTogX3RoaXMsXG4gICAgICAgICAgcm9vdEVsOiBvcmlnaW5hbFRhcmdldCxcbiAgICAgICAgICBuYW1lOiAnZmlsdGVyJyxcbiAgICAgICAgICB0YXJnZXRFbDogdGFyZ2V0LFxuICAgICAgICAgIHRvRWw6IGVsLFxuICAgICAgICAgIGZyb21FbDogZWxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcGx1Z2luRXZlbnQoJ2ZpbHRlcicsIF90aGlzLCB7XG4gICAgICAgICAgZXZ0OiBldnRcbiAgICAgICAgfSk7XG4gICAgICAgIHByZXZlbnRPbkZpbHRlciAmJiBldnQuY2FuY2VsYWJsZSAmJiBldnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgcmV0dXJuOyAvLyBjYW5jZWwgZG5kXG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChmaWx0ZXIpIHtcbiAgICAgIGZpbHRlciA9IGZpbHRlci5zcGxpdCgnLCcpLnNvbWUoZnVuY3Rpb24gKGNyaXRlcmlhKSB7XG4gICAgICAgIGNyaXRlcmlhID0gY2xvc2VzdChvcmlnaW5hbFRhcmdldCwgY3JpdGVyaWEudHJpbSgpLCBlbCwgZmFsc2UpO1xuXG4gICAgICAgIGlmIChjcml0ZXJpYSkge1xuICAgICAgICAgIF9kaXNwYXRjaEV2ZW50KHtcbiAgICAgICAgICAgIHNvcnRhYmxlOiBfdGhpcyxcbiAgICAgICAgICAgIHJvb3RFbDogY3JpdGVyaWEsXG4gICAgICAgICAgICBuYW1lOiAnZmlsdGVyJyxcbiAgICAgICAgICAgIHRhcmdldEVsOiB0YXJnZXQsXG4gICAgICAgICAgICBmcm9tRWw6IGVsLFxuICAgICAgICAgICAgdG9FbDogZWxcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIHBsdWdpbkV2ZW50KCdmaWx0ZXInLCBfdGhpcywge1xuICAgICAgICAgICAgZXZ0OiBldnRcbiAgICAgICAgICB9KTtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGlmIChmaWx0ZXIpIHtcbiAgICAgICAgcHJldmVudE9uRmlsdGVyICYmIGV2dC5jYW5jZWxhYmxlICYmIGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICByZXR1cm47IC8vIGNhbmNlbCBkbmRcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAob3B0aW9ucy5oYW5kbGUgJiYgIWNsb3Nlc3Qob3JpZ2luYWxUYXJnZXQsIG9wdGlvbnMuaGFuZGxlLCBlbCwgZmFsc2UpKSB7XG4gICAgICByZXR1cm47XG4gICAgfSAvLyBQcmVwYXJlIGBkcmFnc3RhcnRgXG5cblxuICAgIHRoaXMuX3ByZXBhcmVEcmFnU3RhcnQoZXZ0LCB0b3VjaCwgdGFyZ2V0KTtcbiAgfSxcbiAgX3ByZXBhcmVEcmFnU3RhcnQ6IGZ1bmN0aW9uIF9wcmVwYXJlRHJhZ1N0YXJ0KFxuICAvKiogRXZlbnQgKi9cbiAgZXZ0LFxuICAvKiogVG91Y2ggKi9cbiAgdG91Y2gsXG4gIC8qKiBIVE1MRWxlbWVudCAqL1xuICB0YXJnZXQpIHtcbiAgICB2YXIgX3RoaXMgPSB0aGlzLFxuICAgICAgICBlbCA9IF90aGlzLmVsLFxuICAgICAgICBvcHRpb25zID0gX3RoaXMub3B0aW9ucyxcbiAgICAgICAgb3duZXJEb2N1bWVudCA9IGVsLm93bmVyRG9jdW1lbnQsXG4gICAgICAgIGRyYWdTdGFydEZuO1xuXG4gICAgaWYgKHRhcmdldCAmJiAhZHJhZ0VsICYmIHRhcmdldC5wYXJlbnROb2RlID09PSBlbCkge1xuICAgICAgdmFyIGRyYWdSZWN0ID0gZ2V0UmVjdCh0YXJnZXQpO1xuICAgICAgcm9vdEVsID0gZWw7XG4gICAgICBkcmFnRWwgPSB0YXJnZXQ7XG4gICAgICBwYXJlbnRFbCA9IGRyYWdFbC5wYXJlbnROb2RlO1xuICAgICAgbmV4dEVsID0gZHJhZ0VsLm5leHRTaWJsaW5nO1xuICAgICAgbGFzdERvd25FbCA9IHRhcmdldDtcbiAgICAgIGFjdGl2ZUdyb3VwID0gb3B0aW9ucy5ncm91cDtcbiAgICAgIFNvcnRhYmxlLmRyYWdnZWQgPSBkcmFnRWw7XG4gICAgICB0YXBFdnQgPSB7XG4gICAgICAgIHRhcmdldDogZHJhZ0VsLFxuICAgICAgICBjbGllbnRYOiAodG91Y2ggfHwgZXZ0KS5jbGllbnRYLFxuICAgICAgICBjbGllbnRZOiAodG91Y2ggfHwgZXZ0KS5jbGllbnRZXG4gICAgICB9O1xuICAgICAgdGFwRGlzdGFuY2VMZWZ0ID0gdGFwRXZ0LmNsaWVudFggLSBkcmFnUmVjdC5sZWZ0O1xuICAgICAgdGFwRGlzdGFuY2VUb3AgPSB0YXBFdnQuY2xpZW50WSAtIGRyYWdSZWN0LnRvcDtcbiAgICAgIHRoaXMuX2xhc3RYID0gKHRvdWNoIHx8IGV2dCkuY2xpZW50WDtcbiAgICAgIHRoaXMuX2xhc3RZID0gKHRvdWNoIHx8IGV2dCkuY2xpZW50WTtcbiAgICAgIGRyYWdFbC5zdHlsZVsnd2lsbC1jaGFuZ2UnXSA9ICdhbGwnO1xuXG4gICAgICBkcmFnU3RhcnRGbiA9IGZ1bmN0aW9uIGRyYWdTdGFydEZuKCkge1xuICAgICAgICBwbHVnaW5FdmVudCgnZGVsYXlFbmRlZCcsIF90aGlzLCB7XG4gICAgICAgICAgZXZ0OiBldnRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKFNvcnRhYmxlLmV2ZW50Q2FuY2VsZWQpIHtcbiAgICAgICAgICBfdGhpcy5fb25Ecm9wKCk7XG5cbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH0gLy8gRGVsYXllZCBkcmFnIGhhcyBiZWVuIHRyaWdnZXJlZFxuICAgICAgICAvLyB3ZSBjYW4gcmUtZW5hYmxlIHRoZSBldmVudHM6IHRvdWNobW92ZS9tb3VzZW1vdmVcblxuXG4gICAgICAgIF90aGlzLl9kaXNhYmxlRGVsYXllZERyYWdFdmVudHMoKTtcblxuICAgICAgICBpZiAoIUZpcmVGb3ggJiYgX3RoaXMubmF0aXZlRHJhZ2dhYmxlKSB7XG4gICAgICAgICAgZHJhZ0VsLmRyYWdnYWJsZSA9IHRydWU7XG4gICAgICAgIH0gLy8gQmluZCB0aGUgZXZlbnRzOiBkcmFnc3RhcnQvZHJhZ2VuZFxuXG5cbiAgICAgICAgX3RoaXMuX3RyaWdnZXJEcmFnU3RhcnQoZXZ0LCB0b3VjaCk7IC8vIERyYWcgc3RhcnQgZXZlbnRcblxuXG4gICAgICAgIF9kaXNwYXRjaEV2ZW50KHtcbiAgICAgICAgICBzb3J0YWJsZTogX3RoaXMsXG4gICAgICAgICAgbmFtZTogJ2Nob29zZScsXG4gICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZ0XG4gICAgICAgIH0pOyAvLyBDaG9zZW4gaXRlbVxuXG5cbiAgICAgICAgdG9nZ2xlQ2xhc3MoZHJhZ0VsLCBvcHRpb25zLmNob3NlbkNsYXNzLCB0cnVlKTtcbiAgICAgIH07IC8vIERpc2FibGUgXCJkcmFnZ2FibGVcIlxuXG5cbiAgICAgIG9wdGlvbnMuaWdub3JlLnNwbGl0KCcsJykuZm9yRWFjaChmdW5jdGlvbiAoY3JpdGVyaWEpIHtcbiAgICAgICAgZmluZChkcmFnRWwsIGNyaXRlcmlhLnRyaW0oKSwgX2Rpc2FibGVEcmFnZ2FibGUpO1xuICAgICAgfSk7XG4gICAgICBvbihvd25lckRvY3VtZW50LCAnZHJhZ292ZXInLCBuZWFyZXN0RW1wdHlJbnNlcnREZXRlY3RFdmVudCk7XG4gICAgICBvbihvd25lckRvY3VtZW50LCAnbW91c2Vtb3ZlJywgbmVhcmVzdEVtcHR5SW5zZXJ0RGV0ZWN0RXZlbnQpO1xuICAgICAgb24ob3duZXJEb2N1bWVudCwgJ3RvdWNobW92ZScsIG5lYXJlc3RFbXB0eUluc2VydERldGVjdEV2ZW50KTtcbiAgICAgIG9uKG93bmVyRG9jdW1lbnQsICdtb3VzZXVwJywgX3RoaXMuX29uRHJvcCk7XG4gICAgICBvbihvd25lckRvY3VtZW50LCAndG91Y2hlbmQnLCBfdGhpcy5fb25Ecm9wKTtcbiAgICAgIG9uKG93bmVyRG9jdW1lbnQsICd0b3VjaGNhbmNlbCcsIF90aGlzLl9vbkRyb3ApOyAvLyBNYWtlIGRyYWdFbCBkcmFnZ2FibGUgKG11c3QgYmUgYmVmb3JlIGRlbGF5IGZvciBGaXJlRm94KVxuXG4gICAgICBpZiAoRmlyZUZveCAmJiB0aGlzLm5hdGl2ZURyYWdnYWJsZSkge1xuICAgICAgICB0aGlzLm9wdGlvbnMudG91Y2hTdGFydFRocmVzaG9sZCA9IDQ7XG4gICAgICAgIGRyYWdFbC5kcmFnZ2FibGUgPSB0cnVlO1xuICAgICAgfVxuXG4gICAgICBwbHVnaW5FdmVudCgnZGVsYXlTdGFydCcsIHRoaXMsIHtcbiAgICAgICAgZXZ0OiBldnRcbiAgICAgIH0pOyAvLyBEZWxheSBpcyBpbXBvc3NpYmxlIGZvciBuYXRpdmUgRG5EIGluIEVkZ2Ugb3IgSUVcblxuICAgICAgaWYgKG9wdGlvbnMuZGVsYXkgJiYgKCFvcHRpb25zLmRlbGF5T25Ub3VjaE9ubHkgfHwgdG91Y2gpICYmICghdGhpcy5uYXRpdmVEcmFnZ2FibGUgfHwgIShFZGdlIHx8IElFMTFPckxlc3MpKSkge1xuICAgICAgICBpZiAoU29ydGFibGUuZXZlbnRDYW5jZWxlZCkge1xuICAgICAgICAgIHRoaXMuX29uRHJvcCgpO1xuXG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9IC8vIElmIHRoZSB1c2VyIG1vdmVzIHRoZSBwb2ludGVyIG9yIGxldCBnbyB0aGUgY2xpY2sgb3IgdG91Y2hcbiAgICAgICAgLy8gYmVmb3JlIHRoZSBkZWxheSBoYXMgYmVlbiByZWFjaGVkOlxuICAgICAgICAvLyBkaXNhYmxlIHRoZSBkZWxheWVkIGRyYWdcblxuXG4gICAgICAgIG9uKG93bmVyRG9jdW1lbnQsICdtb3VzZXVwJywgX3RoaXMuX2Rpc2FibGVEZWxheWVkRHJhZyk7XG4gICAgICAgIG9uKG93bmVyRG9jdW1lbnQsICd0b3VjaGVuZCcsIF90aGlzLl9kaXNhYmxlRGVsYXllZERyYWcpO1xuICAgICAgICBvbihvd25lckRvY3VtZW50LCAndG91Y2hjYW5jZWwnLCBfdGhpcy5fZGlzYWJsZURlbGF5ZWREcmFnKTtcbiAgICAgICAgb24ob3duZXJEb2N1bWVudCwgJ21vdXNlbW92ZScsIF90aGlzLl9kZWxheWVkRHJhZ1RvdWNoTW92ZUhhbmRsZXIpO1xuICAgICAgICBvbihvd25lckRvY3VtZW50LCAndG91Y2htb3ZlJywgX3RoaXMuX2RlbGF5ZWREcmFnVG91Y2hNb3ZlSGFuZGxlcik7XG4gICAgICAgIG9wdGlvbnMuc3VwcG9ydFBvaW50ZXIgJiYgb24ob3duZXJEb2N1bWVudCwgJ3BvaW50ZXJtb3ZlJywgX3RoaXMuX2RlbGF5ZWREcmFnVG91Y2hNb3ZlSGFuZGxlcik7XG4gICAgICAgIF90aGlzLl9kcmFnU3RhcnRUaW1lciA9IHNldFRpbWVvdXQoZHJhZ1N0YXJ0Rm4sIG9wdGlvbnMuZGVsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgZHJhZ1N0YXJ0Rm4oKTtcbiAgICAgIH1cbiAgICB9XG4gIH0sXG4gIF9kZWxheWVkRHJhZ1RvdWNoTW92ZUhhbmRsZXI6IGZ1bmN0aW9uIF9kZWxheWVkRHJhZ1RvdWNoTW92ZUhhbmRsZXIoXG4gIC8qKiBUb3VjaEV2ZW50fFBvaW50ZXJFdmVudCAqKi9cbiAgZSkge1xuICAgIHZhciB0b3VjaCA9IGUudG91Y2hlcyA/IGUudG91Y2hlc1swXSA6IGU7XG5cbiAgICBpZiAoTWF0aC5tYXgoTWF0aC5hYnModG91Y2guY2xpZW50WCAtIHRoaXMuX2xhc3RYKSwgTWF0aC5hYnModG91Y2guY2xpZW50WSAtIHRoaXMuX2xhc3RZKSkgPj0gTWF0aC5mbG9vcih0aGlzLm9wdGlvbnMudG91Y2hTdGFydFRocmVzaG9sZCAvICh0aGlzLm5hdGl2ZURyYWdnYWJsZSAmJiB3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpbyB8fCAxKSkpIHtcbiAgICAgIHRoaXMuX2Rpc2FibGVEZWxheWVkRHJhZygpO1xuICAgIH1cbiAgfSxcbiAgX2Rpc2FibGVEZWxheWVkRHJhZzogZnVuY3Rpb24gX2Rpc2FibGVEZWxheWVkRHJhZygpIHtcbiAgICBkcmFnRWwgJiYgX2Rpc2FibGVEcmFnZ2FibGUoZHJhZ0VsKTtcbiAgICBjbGVhclRpbWVvdXQodGhpcy5fZHJhZ1N0YXJ0VGltZXIpO1xuXG4gICAgdGhpcy5fZGlzYWJsZURlbGF5ZWREcmFnRXZlbnRzKCk7XG4gIH0sXG4gIF9kaXNhYmxlRGVsYXllZERyYWdFdmVudHM6IGZ1bmN0aW9uIF9kaXNhYmxlRGVsYXllZERyYWdFdmVudHMoKSB7XG4gICAgdmFyIG93bmVyRG9jdW1lbnQgPSB0aGlzLmVsLm93bmVyRG9jdW1lbnQ7XG4gICAgb2ZmKG93bmVyRG9jdW1lbnQsICdtb3VzZXVwJywgdGhpcy5fZGlzYWJsZURlbGF5ZWREcmFnKTtcbiAgICBvZmYob3duZXJEb2N1bWVudCwgJ3RvdWNoZW5kJywgdGhpcy5fZGlzYWJsZURlbGF5ZWREcmFnKTtcbiAgICBvZmYob3duZXJEb2N1bWVudCwgJ3RvdWNoY2FuY2VsJywgdGhpcy5fZGlzYWJsZURlbGF5ZWREcmFnKTtcbiAgICBvZmYob3duZXJEb2N1bWVudCwgJ21vdXNlbW92ZScsIHRoaXMuX2RlbGF5ZWREcmFnVG91Y2hNb3ZlSGFuZGxlcik7XG4gICAgb2ZmKG93bmVyRG9jdW1lbnQsICd0b3VjaG1vdmUnLCB0aGlzLl9kZWxheWVkRHJhZ1RvdWNoTW92ZUhhbmRsZXIpO1xuICAgIG9mZihvd25lckRvY3VtZW50LCAncG9pbnRlcm1vdmUnLCB0aGlzLl9kZWxheWVkRHJhZ1RvdWNoTW92ZUhhbmRsZXIpO1xuICB9LFxuICBfdHJpZ2dlckRyYWdTdGFydDogZnVuY3Rpb24gX3RyaWdnZXJEcmFnU3RhcnQoXG4gIC8qKiBFdmVudCAqL1xuICBldnQsXG4gIC8qKiBUb3VjaCAqL1xuICB0b3VjaCkge1xuICAgIHRvdWNoID0gdG91Y2ggfHwgZXZ0LnBvaW50ZXJUeXBlID09ICd0b3VjaCcgJiYgZXZ0O1xuXG4gICAgaWYgKCF0aGlzLm5hdGl2ZURyYWdnYWJsZSB8fCB0b3VjaCkge1xuICAgICAgaWYgKHRoaXMub3B0aW9ucy5zdXBwb3J0UG9pbnRlcikge1xuICAgICAgICBvbihkb2N1bWVudCwgJ3BvaW50ZXJtb3ZlJywgdGhpcy5fb25Ub3VjaE1vdmUpO1xuICAgICAgfSBlbHNlIGlmICh0b3VjaCkge1xuICAgICAgICBvbihkb2N1bWVudCwgJ3RvdWNobW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG9uKGRvY3VtZW50LCAnbW91c2Vtb3ZlJywgdGhpcy5fb25Ub3VjaE1vdmUpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBvbihkcmFnRWwsICdkcmFnZW5kJywgdGhpcyk7XG4gICAgICBvbihyb290RWwsICdkcmFnc3RhcnQnLCB0aGlzLl9vbkRyYWdTdGFydCk7XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIGlmIChkb2N1bWVudC5zZWxlY3Rpb24pIHtcbiAgICAgICAgLy8gVGltZW91dCBuZWNjZXNzYXJ5IGZvciBJRTlcbiAgICAgICAgX25leHRUaWNrKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBkb2N1bWVudC5zZWxlY3Rpb24uZW1wdHkoKTtcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB3aW5kb3cuZ2V0U2VsZWN0aW9uKCkucmVtb3ZlQWxsUmFuZ2VzKCk7XG4gICAgICB9XG4gICAgfSBjYXRjaCAoZXJyKSB7fVxuICB9LFxuICBfZHJhZ1N0YXJ0ZWQ6IGZ1bmN0aW9uIF9kcmFnU3RhcnRlZChmYWxsYmFjaywgZXZ0KSB7XG5cbiAgICBhd2FpdGluZ0RyYWdTdGFydGVkID0gZmFsc2U7XG5cbiAgICBpZiAocm9vdEVsICYmIGRyYWdFbCkge1xuICAgICAgcGx1Z2luRXZlbnQoJ2RyYWdTdGFydGVkJywgdGhpcywge1xuICAgICAgICBldnQ6IGV2dFxuICAgICAgfSk7XG5cbiAgICAgIGlmICh0aGlzLm5hdGl2ZURyYWdnYWJsZSkge1xuICAgICAgICBvbihkb2N1bWVudCwgJ2RyYWdvdmVyJywgX2NoZWNrT3V0c2lkZVRhcmdldEVsKTtcbiAgICAgIH1cblxuICAgICAgdmFyIG9wdGlvbnMgPSB0aGlzLm9wdGlvbnM7IC8vIEFwcGx5IGVmZmVjdFxuXG4gICAgICAhZmFsbGJhY2sgJiYgdG9nZ2xlQ2xhc3MoZHJhZ0VsLCBvcHRpb25zLmRyYWdDbGFzcywgZmFsc2UpO1xuICAgICAgdG9nZ2xlQ2xhc3MoZHJhZ0VsLCBvcHRpb25zLmdob3N0Q2xhc3MsIHRydWUpO1xuICAgICAgU29ydGFibGUuYWN0aXZlID0gdGhpcztcbiAgICAgIGZhbGxiYWNrICYmIHRoaXMuX2FwcGVuZEdob3N0KCk7IC8vIERyYWcgc3RhcnQgZXZlbnRcblxuICAgICAgX2Rpc3BhdGNoRXZlbnQoe1xuICAgICAgICBzb3J0YWJsZTogdGhpcyxcbiAgICAgICAgbmFtZTogJ3N0YXJ0JyxcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZXZ0XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fbnVsbGluZygpO1xuICAgIH1cbiAgfSxcbiAgX2VtdWxhdGVEcmFnT3ZlcjogZnVuY3Rpb24gX2VtdWxhdGVEcmFnT3ZlcigpIHtcbiAgICBpZiAodG91Y2hFdnQpIHtcbiAgICAgIHRoaXMuX2xhc3RYID0gdG91Y2hFdnQuY2xpZW50WDtcbiAgICAgIHRoaXMuX2xhc3RZID0gdG91Y2hFdnQuY2xpZW50WTtcblxuICAgICAgX2hpZGVHaG9zdEZvclRhcmdldCgpO1xuXG4gICAgICB2YXIgdGFyZ2V0ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludCh0b3VjaEV2dC5jbGllbnRYLCB0b3VjaEV2dC5jbGllbnRZKTtcbiAgICAgIHZhciBwYXJlbnQgPSB0YXJnZXQ7XG5cbiAgICAgIHdoaWxlICh0YXJnZXQgJiYgdGFyZ2V0LnNoYWRvd1Jvb3QpIHtcbiAgICAgICAgdGFyZ2V0ID0gdGFyZ2V0LnNoYWRvd1Jvb3QuZWxlbWVudEZyb21Qb2ludCh0b3VjaEV2dC5jbGllbnRYLCB0b3VjaEV2dC5jbGllbnRZKTtcbiAgICAgICAgaWYgKHRhcmdldCA9PT0gcGFyZW50KSBicmVhaztcbiAgICAgICAgcGFyZW50ID0gdGFyZ2V0O1xuICAgICAgfVxuXG4gICAgICBkcmFnRWwucGFyZW50Tm9kZVtleHBhbmRvXS5faXNPdXRzaWRlVGhpc0VsKHRhcmdldCk7XG5cbiAgICAgIGlmIChwYXJlbnQpIHtcbiAgICAgICAgZG8ge1xuICAgICAgICAgIGlmIChwYXJlbnRbZXhwYW5kb10pIHtcbiAgICAgICAgICAgIHZhciBpbnNlcnRlZCA9IHZvaWQgMDtcbiAgICAgICAgICAgIGluc2VydGVkID0gcGFyZW50W2V4cGFuZG9dLl9vbkRyYWdPdmVyKHtcbiAgICAgICAgICAgICAgY2xpZW50WDogdG91Y2hFdnQuY2xpZW50WCxcbiAgICAgICAgICAgICAgY2xpZW50WTogdG91Y2hFdnQuY2xpZW50WSxcbiAgICAgICAgICAgICAgdGFyZ2V0OiB0YXJnZXQsXG4gICAgICAgICAgICAgIHJvb3RFbDogcGFyZW50XG4gICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgaWYgKGluc2VydGVkICYmICF0aGlzLm9wdGlvbnMuZHJhZ292ZXJCdWJibGUpIHtcbiAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgdGFyZ2V0ID0gcGFyZW50OyAvLyBzdG9yZSBsYXN0IGVsZW1lbnRcbiAgICAgICAgfVxuICAgICAgICAvKiBqc2hpbnQgYm9zczp0cnVlICovXG4gICAgICAgIHdoaWxlIChwYXJlbnQgPSBwYXJlbnQucGFyZW50Tm9kZSk7XG4gICAgICB9XG5cbiAgICAgIF91bmhpZGVHaG9zdEZvclRhcmdldCgpO1xuICAgIH1cbiAgfSxcbiAgX29uVG91Y2hNb3ZlOiBmdW5jdGlvbiBfb25Ub3VjaE1vdmUoXG4gIC8qKlRvdWNoRXZlbnQqL1xuICBldnQpIHtcbiAgICBpZiAodGFwRXZ0KSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgICBmYWxsYmFja1RvbGVyYW5jZSA9IG9wdGlvbnMuZmFsbGJhY2tUb2xlcmFuY2UsXG4gICAgICAgICAgZmFsbGJhY2tPZmZzZXQgPSBvcHRpb25zLmZhbGxiYWNrT2Zmc2V0LFxuICAgICAgICAgIHRvdWNoID0gZXZ0LnRvdWNoZXMgPyBldnQudG91Y2hlc1swXSA6IGV2dCxcbiAgICAgICAgICBnaG9zdE1hdHJpeCA9IGdob3N0RWwgJiYgbWF0cml4KGdob3N0RWwsIHRydWUpLFxuICAgICAgICAgIHNjYWxlWCA9IGdob3N0RWwgJiYgZ2hvc3RNYXRyaXggJiYgZ2hvc3RNYXRyaXguYSxcbiAgICAgICAgICBzY2FsZVkgPSBnaG9zdEVsICYmIGdob3N0TWF0cml4ICYmIGdob3N0TWF0cml4LmQsXG4gICAgICAgICAgcmVsYXRpdmVTY3JvbGxPZmZzZXQgPSBQb3NpdGlvbkdob3N0QWJzb2x1dGVseSAmJiBnaG9zdFJlbGF0aXZlUGFyZW50ICYmIGdldFJlbGF0aXZlU2Nyb2xsT2Zmc2V0KGdob3N0UmVsYXRpdmVQYXJlbnQpLFxuICAgICAgICAgIGR4ID0gKHRvdWNoLmNsaWVudFggLSB0YXBFdnQuY2xpZW50WCArIGZhbGxiYWNrT2Zmc2V0LngpIC8gKHNjYWxlWCB8fCAxKSArIChyZWxhdGl2ZVNjcm9sbE9mZnNldCA/IHJlbGF0aXZlU2Nyb2xsT2Zmc2V0WzBdIC0gZ2hvc3RSZWxhdGl2ZVBhcmVudEluaXRpYWxTY3JvbGxbMF0gOiAwKSAvIChzY2FsZVggfHwgMSksXG4gICAgICAgICAgZHkgPSAodG91Y2guY2xpZW50WSAtIHRhcEV2dC5jbGllbnRZICsgZmFsbGJhY2tPZmZzZXQueSkgLyAoc2NhbGVZIHx8IDEpICsgKHJlbGF0aXZlU2Nyb2xsT2Zmc2V0ID8gcmVsYXRpdmVTY3JvbGxPZmZzZXRbMV0gLSBnaG9zdFJlbGF0aXZlUGFyZW50SW5pdGlhbFNjcm9sbFsxXSA6IDApIC8gKHNjYWxlWSB8fCAxKTsgLy8gb25seSBzZXQgdGhlIHN0YXR1cyB0byBkcmFnZ2luZywgd2hlbiB3ZSBhcmUgYWN0dWFsbHkgZHJhZ2dpbmdcblxuICAgICAgaWYgKCFTb3J0YWJsZS5hY3RpdmUgJiYgIWF3YWl0aW5nRHJhZ1N0YXJ0ZWQpIHtcbiAgICAgICAgaWYgKGZhbGxiYWNrVG9sZXJhbmNlICYmIE1hdGgubWF4KE1hdGguYWJzKHRvdWNoLmNsaWVudFggLSB0aGlzLl9sYXN0WCksIE1hdGguYWJzKHRvdWNoLmNsaWVudFkgLSB0aGlzLl9sYXN0WSkpIDwgZmFsbGJhY2tUb2xlcmFuY2UpIHtcbiAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9vbkRyYWdTdGFydChldnQsIHRydWUpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZ2hvc3RFbCkge1xuICAgICAgICBpZiAoZ2hvc3RNYXRyaXgpIHtcbiAgICAgICAgICBnaG9zdE1hdHJpeC5lICs9IGR4IC0gKGxhc3REeCB8fCAwKTtcbiAgICAgICAgICBnaG9zdE1hdHJpeC5mICs9IGR5IC0gKGxhc3REeSB8fCAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBnaG9zdE1hdHJpeCA9IHtcbiAgICAgICAgICAgIGE6IDEsXG4gICAgICAgICAgICBiOiAwLFxuICAgICAgICAgICAgYzogMCxcbiAgICAgICAgICAgIGQ6IDEsXG4gICAgICAgICAgICBlOiBkeCxcbiAgICAgICAgICAgIGY6IGR5XG4gICAgICAgICAgfTtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBjc3NNYXRyaXggPSBcIm1hdHJpeChcIi5jb25jYXQoZ2hvc3RNYXRyaXguYSwgXCIsXCIpLmNvbmNhdChnaG9zdE1hdHJpeC5iLCBcIixcIikuY29uY2F0KGdob3N0TWF0cml4LmMsIFwiLFwiKS5jb25jYXQoZ2hvc3RNYXRyaXguZCwgXCIsXCIpLmNvbmNhdChnaG9zdE1hdHJpeC5lLCBcIixcIikuY29uY2F0KGdob3N0TWF0cml4LmYsIFwiKVwiKTtcbiAgICAgICAgY3NzKGdob3N0RWwsICd3ZWJraXRUcmFuc2Zvcm0nLCBjc3NNYXRyaXgpO1xuICAgICAgICBjc3MoZ2hvc3RFbCwgJ21velRyYW5zZm9ybScsIGNzc01hdHJpeCk7XG4gICAgICAgIGNzcyhnaG9zdEVsLCAnbXNUcmFuc2Zvcm0nLCBjc3NNYXRyaXgpO1xuICAgICAgICBjc3MoZ2hvc3RFbCwgJ3RyYW5zZm9ybScsIGNzc01hdHJpeCk7XG4gICAgICAgIGxhc3REeCA9IGR4O1xuICAgICAgICBsYXN0RHkgPSBkeTtcbiAgICAgICAgdG91Y2hFdnQgPSB0b3VjaDtcbiAgICAgIH1cblxuICAgICAgZXZ0LmNhbmNlbGFibGUgJiYgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICB9LFxuICBfYXBwZW5kR2hvc3Q6IGZ1bmN0aW9uIF9hcHBlbmRHaG9zdCgpIHtcbiAgICAvLyBCdWcgaWYgdXNpbmcgc2NhbGUoKTogaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjYzNzA1OFxuICAgIC8vIE5vdCBiZWluZyBhZGp1c3RlZCBmb3JcbiAgICBpZiAoIWdob3N0RWwpIHtcbiAgICAgIHZhciBjb250YWluZXIgPSB0aGlzLm9wdGlvbnMuZmFsbGJhY2tPbkJvZHkgPyBkb2N1bWVudC5ib2R5IDogcm9vdEVsLFxuICAgICAgICAgIHJlY3QgPSBnZXRSZWN0KGRyYWdFbCwgdHJ1ZSwgUG9zaXRpb25HaG9zdEFic29sdXRlbHksIHRydWUsIGNvbnRhaW5lciksXG4gICAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9uczsgLy8gUG9zaXRpb24gYWJzb2x1dGVseVxuXG4gICAgICBpZiAoUG9zaXRpb25HaG9zdEFic29sdXRlbHkpIHtcbiAgICAgICAgLy8gR2V0IHJlbGF0aXZlbHkgcG9zaXRpb25lZCBwYXJlbnRcbiAgICAgICAgZ2hvc3RSZWxhdGl2ZVBhcmVudCA9IGNvbnRhaW5lcjtcblxuICAgICAgICB3aGlsZSAoY3NzKGdob3N0UmVsYXRpdmVQYXJlbnQsICdwb3NpdGlvbicpID09PSAnc3RhdGljJyAmJiBjc3MoZ2hvc3RSZWxhdGl2ZVBhcmVudCwgJ3RyYW5zZm9ybScpID09PSAnbm9uZScgJiYgZ2hvc3RSZWxhdGl2ZVBhcmVudCAhPT0gZG9jdW1lbnQpIHtcbiAgICAgICAgICBnaG9zdFJlbGF0aXZlUGFyZW50ID0gZ2hvc3RSZWxhdGl2ZVBhcmVudC5wYXJlbnROb2RlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdob3N0UmVsYXRpdmVQYXJlbnQgIT09IGRvY3VtZW50LmJvZHkgJiYgZ2hvc3RSZWxhdGl2ZVBhcmVudCAhPT0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50KSB7XG4gICAgICAgICAgaWYgKGdob3N0UmVsYXRpdmVQYXJlbnQgPT09IGRvY3VtZW50KSBnaG9zdFJlbGF0aXZlUGFyZW50ID0gZ2V0V2luZG93U2Nyb2xsaW5nRWxlbWVudCgpO1xuICAgICAgICAgIHJlY3QudG9wICs9IGdob3N0UmVsYXRpdmVQYXJlbnQuc2Nyb2xsVG9wO1xuICAgICAgICAgIHJlY3QubGVmdCArPSBnaG9zdFJlbGF0aXZlUGFyZW50LnNjcm9sbExlZnQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZ2hvc3RSZWxhdGl2ZVBhcmVudCA9IGdldFdpbmRvd1Njcm9sbGluZ0VsZW1lbnQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGdob3N0UmVsYXRpdmVQYXJlbnRJbml0aWFsU2Nyb2xsID0gZ2V0UmVsYXRpdmVTY3JvbGxPZmZzZXQoZ2hvc3RSZWxhdGl2ZVBhcmVudCk7XG4gICAgICB9XG5cbiAgICAgIGdob3N0RWwgPSBkcmFnRWwuY2xvbmVOb2RlKHRydWUpO1xuICAgICAgdG9nZ2xlQ2xhc3MoZ2hvc3RFbCwgb3B0aW9ucy5naG9zdENsYXNzLCBmYWxzZSk7XG4gICAgICB0b2dnbGVDbGFzcyhnaG9zdEVsLCBvcHRpb25zLmZhbGxiYWNrQ2xhc3MsIHRydWUpO1xuICAgICAgdG9nZ2xlQ2xhc3MoZ2hvc3RFbCwgb3B0aW9ucy5kcmFnQ2xhc3MsIHRydWUpO1xuICAgICAgY3NzKGdob3N0RWwsICd0cmFuc2l0aW9uJywgJycpO1xuICAgICAgY3NzKGdob3N0RWwsICd0cmFuc2Zvcm0nLCAnJyk7XG4gICAgICBjc3MoZ2hvc3RFbCwgJ2JveC1zaXppbmcnLCAnYm9yZGVyLWJveCcpO1xuICAgICAgY3NzKGdob3N0RWwsICdtYXJnaW4nLCAwKTtcbiAgICAgIGNzcyhnaG9zdEVsLCAndG9wJywgcmVjdC50b3ApO1xuICAgICAgY3NzKGdob3N0RWwsICdsZWZ0JywgcmVjdC5sZWZ0KTtcbiAgICAgIGNzcyhnaG9zdEVsLCAnd2lkdGgnLCByZWN0LndpZHRoKTtcbiAgICAgIGNzcyhnaG9zdEVsLCAnaGVpZ2h0JywgcmVjdC5oZWlnaHQpO1xuICAgICAgY3NzKGdob3N0RWwsICdvcGFjaXR5JywgJzAuOCcpO1xuICAgICAgY3NzKGdob3N0RWwsICdwb3NpdGlvbicsIFBvc2l0aW9uR2hvc3RBYnNvbHV0ZWx5ID8gJ2Fic29sdXRlJyA6ICdmaXhlZCcpO1xuICAgICAgY3NzKGdob3N0RWwsICd6SW5kZXgnLCAnMTAwMDAwJyk7XG4gICAgICBjc3MoZ2hvc3RFbCwgJ3BvaW50ZXJFdmVudHMnLCAnbm9uZScpO1xuICAgICAgU29ydGFibGUuZ2hvc3QgPSBnaG9zdEVsO1xuICAgICAgY29udGFpbmVyLmFwcGVuZENoaWxkKGdob3N0RWwpOyAvLyBTZXQgdHJhbnNmb3JtLW9yaWdpblxuXG4gICAgICBjc3MoZ2hvc3RFbCwgJ3RyYW5zZm9ybS1vcmlnaW4nLCB0YXBEaXN0YW5jZUxlZnQgLyBwYXJzZUludChnaG9zdEVsLnN0eWxlLndpZHRoKSAqIDEwMCArICclICcgKyB0YXBEaXN0YW5jZVRvcCAvIHBhcnNlSW50KGdob3N0RWwuc3R5bGUuaGVpZ2h0KSAqIDEwMCArICclJyk7XG4gICAgfVxuICB9LFxuICBfb25EcmFnU3RhcnQ6IGZ1bmN0aW9uIF9vbkRyYWdTdGFydChcbiAgLyoqRXZlbnQqL1xuICBldnQsXG4gIC8qKmJvb2xlYW4qL1xuICBmYWxsYmFjaykge1xuICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICB2YXIgZGF0YVRyYW5zZmVyID0gZXZ0LmRhdGFUcmFuc2ZlcjtcbiAgICB2YXIgb3B0aW9ucyA9IF90aGlzLm9wdGlvbnM7XG4gICAgcGx1Z2luRXZlbnQoJ2RyYWdTdGFydCcsIHRoaXMsIHtcbiAgICAgIGV2dDogZXZ0XG4gICAgfSk7XG5cbiAgICBpZiAoU29ydGFibGUuZXZlbnRDYW5jZWxlZCkge1xuICAgICAgdGhpcy5fb25Ecm9wKCk7XG5cbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBwbHVnaW5FdmVudCgnc2V0dXBDbG9uZScsIHRoaXMpO1xuXG4gICAgaWYgKCFTb3J0YWJsZS5ldmVudENhbmNlbGVkKSB7XG4gICAgICBjbG9uZUVsID0gY2xvbmUoZHJhZ0VsKTtcbiAgICAgIGNsb25lRWwuZHJhZ2dhYmxlID0gZmFsc2U7XG4gICAgICBjbG9uZUVsLnN0eWxlWyd3aWxsLWNoYW5nZSddID0gJyc7XG5cbiAgICAgIHRoaXMuX2hpZGVDbG9uZSgpO1xuXG4gICAgICB0b2dnbGVDbGFzcyhjbG9uZUVsLCB0aGlzLm9wdGlvbnMuY2hvc2VuQ2xhc3MsIGZhbHNlKTtcbiAgICAgIFNvcnRhYmxlLmNsb25lID0gY2xvbmVFbDtcbiAgICB9IC8vICMxMTQzOiBJRnJhbWUgc3VwcG9ydCB3b3JrYXJvdW5kXG5cblxuICAgIF90aGlzLmNsb25lSWQgPSBfbmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgcGx1Z2luRXZlbnQoJ2Nsb25lJywgX3RoaXMpO1xuICAgICAgaWYgKFNvcnRhYmxlLmV2ZW50Q2FuY2VsZWQpIHJldHVybjtcblxuICAgICAgaWYgKCFfdGhpcy5vcHRpb25zLnJlbW92ZUNsb25lT25IaWRlKSB7XG4gICAgICAgIHJvb3RFbC5pbnNlcnRCZWZvcmUoY2xvbmVFbCwgZHJhZ0VsKTtcbiAgICAgIH1cblxuICAgICAgX3RoaXMuX2hpZGVDbG9uZSgpO1xuXG4gICAgICBfZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgIHNvcnRhYmxlOiBfdGhpcyxcbiAgICAgICAgbmFtZTogJ2Nsb25lJ1xuICAgICAgfSk7XG4gICAgfSk7XG4gICAgIWZhbGxiYWNrICYmIHRvZ2dsZUNsYXNzKGRyYWdFbCwgb3B0aW9ucy5kcmFnQ2xhc3MsIHRydWUpOyAvLyBTZXQgcHJvcGVyIGRyb3AgZXZlbnRzXG5cbiAgICBpZiAoZmFsbGJhY2spIHtcbiAgICAgIGlnbm9yZU5leHRDbGljayA9IHRydWU7XG4gICAgICBfdGhpcy5fbG9vcElkID0gc2V0SW50ZXJ2YWwoX3RoaXMuX2VtdWxhdGVEcmFnT3ZlciwgNTApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBVbmRvIHdoYXQgd2FzIHNldCBpbiBfcHJlcGFyZURyYWdTdGFydCBiZWZvcmUgZHJhZyBzdGFydGVkXG4gICAgICBvZmYoZG9jdW1lbnQsICdtb3VzZXVwJywgX3RoaXMuX29uRHJvcCk7XG4gICAgICBvZmYoZG9jdW1lbnQsICd0b3VjaGVuZCcsIF90aGlzLl9vbkRyb3ApO1xuICAgICAgb2ZmKGRvY3VtZW50LCAndG91Y2hjYW5jZWwnLCBfdGhpcy5fb25Ecm9wKTtcblxuICAgICAgaWYgKGRhdGFUcmFuc2Zlcikge1xuICAgICAgICBkYXRhVHJhbnNmZXIuZWZmZWN0QWxsb3dlZCA9ICdtb3ZlJztcbiAgICAgICAgb3B0aW9ucy5zZXREYXRhICYmIG9wdGlvbnMuc2V0RGF0YS5jYWxsKF90aGlzLCBkYXRhVHJhbnNmZXIsIGRyYWdFbCk7XG4gICAgICB9XG5cbiAgICAgIG9uKGRvY3VtZW50LCAnZHJvcCcsIF90aGlzKTsgLy8gIzEyNzYgZml4OlxuXG4gICAgICBjc3MoZHJhZ0VsLCAndHJhbnNmb3JtJywgJ3RyYW5zbGF0ZVooMCknKTtcbiAgICB9XG5cbiAgICBhd2FpdGluZ0RyYWdTdGFydGVkID0gdHJ1ZTtcbiAgICBfdGhpcy5fZHJhZ1N0YXJ0SWQgPSBfbmV4dFRpY2soX3RoaXMuX2RyYWdTdGFydGVkLmJpbmQoX3RoaXMsIGZhbGxiYWNrLCBldnQpKTtcbiAgICBvbihkb2N1bWVudCwgJ3NlbGVjdHN0YXJ0JywgX3RoaXMpO1xuICAgIG1vdmVkID0gdHJ1ZTtcblxuICAgIGlmIChTYWZhcmkpIHtcbiAgICAgIGNzcyhkb2N1bWVudC5ib2R5LCAndXNlci1zZWxlY3QnLCAnbm9uZScpO1xuICAgIH1cbiAgfSxcbiAgLy8gUmV0dXJucyB0cnVlIC0gaWYgbm8gZnVydGhlciBhY3Rpb24gaXMgbmVlZGVkIChlaXRoZXIgaW5zZXJ0ZWQgb3IgYW5vdGhlciBjb25kaXRpb24pXG4gIF9vbkRyYWdPdmVyOiBmdW5jdGlvbiBfb25EcmFnT3ZlcihcbiAgLyoqRXZlbnQqL1xuICBldnQpIHtcbiAgICB2YXIgZWwgPSB0aGlzLmVsLFxuICAgICAgICB0YXJnZXQgPSBldnQudGFyZ2V0LFxuICAgICAgICBkcmFnUmVjdCxcbiAgICAgICAgdGFyZ2V0UmVjdCxcbiAgICAgICAgcmV2ZXJ0LFxuICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zLFxuICAgICAgICBncm91cCA9IG9wdGlvbnMuZ3JvdXAsXG4gICAgICAgIGFjdGl2ZVNvcnRhYmxlID0gU29ydGFibGUuYWN0aXZlLFxuICAgICAgICBpc093bmVyID0gYWN0aXZlR3JvdXAgPT09IGdyb3VwLFxuICAgICAgICBjYW5Tb3J0ID0gb3B0aW9ucy5zb3J0LFxuICAgICAgICBmcm9tU29ydGFibGUgPSBwdXRTb3J0YWJsZSB8fCBhY3RpdmVTb3J0YWJsZSxcbiAgICAgICAgdmVydGljYWwsXG4gICAgICAgIF90aGlzID0gdGhpcyxcbiAgICAgICAgY29tcGxldGVkRmlyZWQgPSBmYWxzZTtcblxuICAgIGlmIChfc2lsZW50KSByZXR1cm47XG5cbiAgICBmdW5jdGlvbiBkcmFnT3ZlckV2ZW50KG5hbWUsIGV4dHJhKSB7XG4gICAgICBwbHVnaW5FdmVudChuYW1lLCBfdGhpcywgX29iamVjdFNwcmVhZCh7XG4gICAgICAgIGV2dDogZXZ0LFxuICAgICAgICBpc093bmVyOiBpc093bmVyLFxuICAgICAgICBheGlzOiB2ZXJ0aWNhbCA/ICd2ZXJ0aWNhbCcgOiAnaG9yaXpvbnRhbCcsXG4gICAgICAgIHJldmVydDogcmV2ZXJ0LFxuICAgICAgICBkcmFnUmVjdDogZHJhZ1JlY3QsXG4gICAgICAgIHRhcmdldFJlY3Q6IHRhcmdldFJlY3QsXG4gICAgICAgIGNhblNvcnQ6IGNhblNvcnQsXG4gICAgICAgIGZyb21Tb3J0YWJsZTogZnJvbVNvcnRhYmxlLFxuICAgICAgICB0YXJnZXQ6IHRhcmdldCxcbiAgICAgICAgY29tcGxldGVkOiBjb21wbGV0ZWQsXG4gICAgICAgIG9uTW92ZTogZnVuY3Rpb24gb25Nb3ZlKHRhcmdldCwgYWZ0ZXIpIHtcbiAgICAgICAgICByZXR1cm4gX29uTW92ZShyb290RWwsIGVsLCBkcmFnRWwsIGRyYWdSZWN0LCB0YXJnZXQsIGdldFJlY3QodGFyZ2V0KSwgZXZ0LCBhZnRlcik7XG4gICAgICAgIH0sXG4gICAgICAgIGNoYW5nZWQ6IGNoYW5nZWRcbiAgICAgIH0sIGV4dHJhKSk7XG4gICAgfSAvLyBDYXB0dXJlIGFuaW1hdGlvbiBzdGF0ZVxuXG5cbiAgICBmdW5jdGlvbiBjYXB0dXJlKCkge1xuICAgICAgZHJhZ092ZXJFdmVudCgnZHJhZ092ZXJBbmltYXRpb25DYXB0dXJlJyk7XG5cbiAgICAgIF90aGlzLmNhcHR1cmVBbmltYXRpb25TdGF0ZSgpO1xuXG4gICAgICBpZiAoX3RoaXMgIT09IGZyb21Tb3J0YWJsZSkge1xuICAgICAgICBmcm9tU29ydGFibGUuY2FwdHVyZUFuaW1hdGlvblN0YXRlKCk7XG4gICAgICB9XG4gICAgfSAvLyBSZXR1cm4gaW52b2NhdGlvbiB3aGVuIGRyYWdFbCBpcyBpbnNlcnRlZCAob3IgY29tcGxldGVkKVxuXG5cbiAgICBmdW5jdGlvbiBjb21wbGV0ZWQoaW5zZXJ0aW9uKSB7XG4gICAgICBkcmFnT3ZlckV2ZW50KCdkcmFnT3ZlckNvbXBsZXRlZCcsIHtcbiAgICAgICAgaW5zZXJ0aW9uOiBpbnNlcnRpb25cbiAgICAgIH0pO1xuXG4gICAgICBpZiAoaW5zZXJ0aW9uKSB7XG4gICAgICAgIC8vIENsb25lcyBtdXN0IGJlIGhpZGRlbiBiZWZvcmUgZm9sZGluZyBhbmltYXRpb24gdG8gY2FwdHVyZSBkcmFnUmVjdEFic29sdXRlIHByb3Blcmx5XG4gICAgICAgIGlmIChpc093bmVyKSB7XG4gICAgICAgICAgYWN0aXZlU29ydGFibGUuX2hpZGVDbG9uZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGFjdGl2ZVNvcnRhYmxlLl9zaG93Q2xvbmUoX3RoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKF90aGlzICE9PSBmcm9tU29ydGFibGUpIHtcbiAgICAgICAgICAvLyBTZXQgZ2hvc3QgY2xhc3MgdG8gbmV3IHNvcnRhYmxlJ3MgZ2hvc3QgY2xhc3NcbiAgICAgICAgICB0b2dnbGVDbGFzcyhkcmFnRWwsIHB1dFNvcnRhYmxlID8gcHV0U29ydGFibGUub3B0aW9ucy5naG9zdENsYXNzIDogYWN0aXZlU29ydGFibGUub3B0aW9ucy5naG9zdENsYXNzLCBmYWxzZSk7XG4gICAgICAgICAgdG9nZ2xlQ2xhc3MoZHJhZ0VsLCBvcHRpb25zLmdob3N0Q2xhc3MsIHRydWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHB1dFNvcnRhYmxlICE9PSBfdGhpcyAmJiBfdGhpcyAhPT0gU29ydGFibGUuYWN0aXZlKSB7XG4gICAgICAgICAgcHV0U29ydGFibGUgPSBfdGhpcztcbiAgICAgICAgfSBlbHNlIGlmIChfdGhpcyA9PT0gU29ydGFibGUuYWN0aXZlICYmIHB1dFNvcnRhYmxlKSB7XG4gICAgICAgICAgcHV0U29ydGFibGUgPSBudWxsO1xuICAgICAgICB9IC8vIEFuaW1hdGlvblxuXG5cbiAgICAgICAgaWYgKGZyb21Tb3J0YWJsZSA9PT0gX3RoaXMpIHtcbiAgICAgICAgICBfdGhpcy5faWdub3JlV2hpbGVBbmltYXRpbmcgPSB0YXJnZXQ7XG4gICAgICAgIH1cblxuICAgICAgICBfdGhpcy5hbmltYXRlQWxsKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBkcmFnT3ZlckV2ZW50KCdkcmFnT3ZlckFuaW1hdGlvbkNvbXBsZXRlJyk7XG4gICAgICAgICAgX3RoaXMuX2lnbm9yZVdoaWxlQW5pbWF0aW5nID0gbnVsbDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKF90aGlzICE9PSBmcm9tU29ydGFibGUpIHtcbiAgICAgICAgICBmcm9tU29ydGFibGUuYW5pbWF0ZUFsbCgpO1xuICAgICAgICAgIGZyb21Tb3J0YWJsZS5faWdub3JlV2hpbGVBbmltYXRpbmcgPSBudWxsO1xuICAgICAgICB9XG4gICAgICB9IC8vIE51bGwgbGFzdFRhcmdldCBpZiBpdCBpcyBub3QgaW5zaWRlIGEgcHJldmlvdXNseSBzd2FwcGVkIGVsZW1lbnRcblxuXG4gICAgICBpZiAodGFyZ2V0ID09PSBkcmFnRWwgJiYgIWRyYWdFbC5hbmltYXRlZCB8fCB0YXJnZXQgPT09IGVsICYmICF0YXJnZXQuYW5pbWF0ZWQpIHtcbiAgICAgICAgbGFzdFRhcmdldCA9IG51bGw7XG4gICAgICB9IC8vIG5vIGJ1YmJsaW5nIGFuZCBub3QgZmFsbGJhY2tcblxuXG4gICAgICBpZiAoIW9wdGlvbnMuZHJhZ292ZXJCdWJibGUgJiYgIWV2dC5yb290RWwgJiYgdGFyZ2V0ICE9PSBkb2N1bWVudCkge1xuICAgICAgICBkcmFnRWwucGFyZW50Tm9kZVtleHBhbmRvXS5faXNPdXRzaWRlVGhpc0VsKGV2dC50YXJnZXQpOyAvLyBEbyBub3QgZGV0ZWN0IGZvciBlbXB0eSBpbnNlcnQgaWYgYWxyZWFkeSBpbnNlcnRlZFxuXG5cbiAgICAgICAgIWluc2VydGlvbiAmJiBuZWFyZXN0RW1wdHlJbnNlcnREZXRlY3RFdmVudChldnQpO1xuICAgICAgfVxuXG4gICAgICAhb3B0aW9ucy5kcmFnb3ZlckJ1YmJsZSAmJiBldnQuc3RvcFByb3BhZ2F0aW9uICYmIGV2dC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIHJldHVybiBjb21wbGV0ZWRGaXJlZCA9IHRydWU7XG4gICAgfSAvLyBDYWxsIHdoZW4gZHJhZ0VsIGhhcyBiZWVuIGluc2VydGVkXG5cblxuICAgIGZ1bmN0aW9uIGNoYW5nZWQoKSB7XG4gICAgICBuZXdJbmRleCA9IGluZGV4KGRyYWdFbCk7XG4gICAgICBuZXdEcmFnZ2FibGVJbmRleCA9IGluZGV4KGRyYWdFbCwgb3B0aW9ucy5kcmFnZ2FibGUpO1xuXG4gICAgICBfZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgIHNvcnRhYmxlOiBfdGhpcyxcbiAgICAgICAgbmFtZTogJ2NoYW5nZScsXG4gICAgICAgIHRvRWw6IGVsLFxuICAgICAgICBuZXdJbmRleDogbmV3SW5kZXgsXG4gICAgICAgIG5ld0RyYWdnYWJsZUluZGV4OiBuZXdEcmFnZ2FibGVJbmRleCxcbiAgICAgICAgb3JpZ2luYWxFdmVudDogZXZ0XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBpZiAoZXZ0LnByZXZlbnREZWZhdWx0ICE9PSB2b2lkIDApIHtcbiAgICAgIGV2dC5jYW5jZWxhYmxlICYmIGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIHRhcmdldCA9IGNsb3Nlc3QodGFyZ2V0LCBvcHRpb25zLmRyYWdnYWJsZSwgZWwsIHRydWUpO1xuICAgIGRyYWdPdmVyRXZlbnQoJ2RyYWdPdmVyJyk7XG4gICAgaWYgKFNvcnRhYmxlLmV2ZW50Q2FuY2VsZWQpIHJldHVybiBjb21wbGV0ZWRGaXJlZDtcblxuICAgIGlmIChkcmFnRWwuY29udGFpbnMoZXZ0LnRhcmdldCkgfHwgdGFyZ2V0LmFuaW1hdGVkICYmIHRhcmdldC5hbmltYXRpbmdYICYmIHRhcmdldC5hbmltYXRpbmdZIHx8IF90aGlzLl9pZ25vcmVXaGlsZUFuaW1hdGluZyA9PT0gdGFyZ2V0KSB7XG4gICAgICByZXR1cm4gY29tcGxldGVkKGZhbHNlKTtcbiAgICB9XG5cbiAgICBpZ25vcmVOZXh0Q2xpY2sgPSBmYWxzZTtcblxuICAgIGlmIChhY3RpdmVTb3J0YWJsZSAmJiAhb3B0aW9ucy5kaXNhYmxlZCAmJiAoaXNPd25lciA/IGNhblNvcnQgfHwgKHJldmVydCA9ICFyb290RWwuY29udGFpbnMoZHJhZ0VsKSkgLy8gUmV2ZXJ0aW5nIGl0ZW0gaW50byB0aGUgb3JpZ2luYWwgbGlzdFxuICAgIDogcHV0U29ydGFibGUgPT09IHRoaXMgfHwgKHRoaXMubGFzdFB1dE1vZGUgPSBhY3RpdmVHcm91cC5jaGVja1B1bGwodGhpcywgYWN0aXZlU29ydGFibGUsIGRyYWdFbCwgZXZ0KSkgJiYgZ3JvdXAuY2hlY2tQdXQodGhpcywgYWN0aXZlU29ydGFibGUsIGRyYWdFbCwgZXZ0KSkpIHtcbiAgICAgIHZlcnRpY2FsID0gdGhpcy5fZ2V0RGlyZWN0aW9uKGV2dCwgdGFyZ2V0KSA9PT0gJ3ZlcnRpY2FsJztcbiAgICAgIGRyYWdSZWN0ID0gZ2V0UmVjdChkcmFnRWwpO1xuICAgICAgZHJhZ092ZXJFdmVudCgnZHJhZ092ZXJWYWxpZCcpO1xuICAgICAgaWYgKFNvcnRhYmxlLmV2ZW50Q2FuY2VsZWQpIHJldHVybiBjb21wbGV0ZWRGaXJlZDtcblxuICAgICAgaWYgKHJldmVydCkge1xuICAgICAgICBwYXJlbnRFbCA9IHJvb3RFbDsgLy8gYWN0dWFsaXphdGlvblxuXG4gICAgICAgIGNhcHR1cmUoKTtcblxuICAgICAgICB0aGlzLl9oaWRlQ2xvbmUoKTtcblxuICAgICAgICBkcmFnT3ZlckV2ZW50KCdyZXZlcnQnKTtcblxuICAgICAgICBpZiAoIVNvcnRhYmxlLmV2ZW50Q2FuY2VsZWQpIHtcbiAgICAgICAgICBpZiAobmV4dEVsKSB7XG4gICAgICAgICAgICByb290RWwuaW5zZXJ0QmVmb3JlKGRyYWdFbCwgbmV4dEVsKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcm9vdEVsLmFwcGVuZENoaWxkKGRyYWdFbCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNvbXBsZXRlZCh0cnVlKTtcbiAgICAgIH1cblxuICAgICAgdmFyIGVsTGFzdENoaWxkID0gbGFzdENoaWxkKGVsLCBvcHRpb25zLmRyYWdnYWJsZSk7XG5cbiAgICAgIGlmICghZWxMYXN0Q2hpbGQgfHwgX2dob3N0SXNMYXN0KGV2dCwgdmVydGljYWwsIHRoaXMpICYmICFlbExhc3RDaGlsZC5hbmltYXRlZCkge1xuICAgICAgICAvLyBJZiBhbHJlYWR5IGF0IGVuZCBvZiBsaXN0OiBEbyBub3QgaW5zZXJ0XG4gICAgICAgIGlmIChlbExhc3RDaGlsZCA9PT0gZHJhZ0VsKSB7XG4gICAgICAgICAgcmV0dXJuIGNvbXBsZXRlZChmYWxzZSk7XG4gICAgICAgIH0gLy8gYXNzaWduIHRhcmdldCBvbmx5IGlmIGNvbmRpdGlvbiBpcyB0cnVlXG5cblxuICAgICAgICBpZiAoZWxMYXN0Q2hpbGQgJiYgZWwgPT09IGV2dC50YXJnZXQpIHtcbiAgICAgICAgICB0YXJnZXQgPSBlbExhc3RDaGlsZDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0YXJnZXQpIHtcbiAgICAgICAgICB0YXJnZXRSZWN0ID0gZ2V0UmVjdCh0YXJnZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKF9vbk1vdmUocm9vdEVsLCBlbCwgZHJhZ0VsLCBkcmFnUmVjdCwgdGFyZ2V0LCB0YXJnZXRSZWN0LCBldnQsICEhdGFyZ2V0KSAhPT0gZmFsc2UpIHtcbiAgICAgICAgICBjYXB0dXJlKCk7XG4gICAgICAgICAgZWwuYXBwZW5kQ2hpbGQoZHJhZ0VsKTtcbiAgICAgICAgICBwYXJlbnRFbCA9IGVsOyAvLyBhY3R1YWxpemF0aW9uXG5cbiAgICAgICAgICBjaGFuZ2VkKCk7XG4gICAgICAgICAgcmV0dXJuIGNvbXBsZXRlZCh0cnVlKTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0YXJnZXQucGFyZW50Tm9kZSA9PT0gZWwpIHtcbiAgICAgICAgdGFyZ2V0UmVjdCA9IGdldFJlY3QodGFyZ2V0KTtcbiAgICAgICAgdmFyIGRpcmVjdGlvbiA9IDAsXG4gICAgICAgICAgICB0YXJnZXRCZWZvcmVGaXJzdFN3YXAsXG4gICAgICAgICAgICBkaWZmZXJlbnRMZXZlbCA9IGRyYWdFbC5wYXJlbnROb2RlICE9PSBlbCxcbiAgICAgICAgICAgIGRpZmZlcmVudFJvd0NvbCA9ICFfZHJhZ0VsSW5Sb3dDb2x1bW4oZHJhZ0VsLmFuaW1hdGVkICYmIGRyYWdFbC50b1JlY3QgfHwgZHJhZ1JlY3QsIHRhcmdldC5hbmltYXRlZCAmJiB0YXJnZXQudG9SZWN0IHx8IHRhcmdldFJlY3QsIHZlcnRpY2FsKSxcbiAgICAgICAgICAgIHNpZGUxID0gdmVydGljYWwgPyAndG9wJyA6ICdsZWZ0JyxcbiAgICAgICAgICAgIHNjcm9sbGVkUGFzdFRvcCA9IGlzU2Nyb2xsZWRQYXN0KHRhcmdldCwgJ3RvcCcsICd0b3AnKSB8fCBpc1Njcm9sbGVkUGFzdChkcmFnRWwsICd0b3AnLCAndG9wJyksXG4gICAgICAgICAgICBzY3JvbGxCZWZvcmUgPSBzY3JvbGxlZFBhc3RUb3AgPyBzY3JvbGxlZFBhc3RUb3Auc2Nyb2xsVG9wIDogdm9pZCAwO1xuXG4gICAgICAgIGlmIChsYXN0VGFyZ2V0ICE9PSB0YXJnZXQpIHtcbiAgICAgICAgICB0YXJnZXRCZWZvcmVGaXJzdFN3YXAgPSB0YXJnZXRSZWN0W3NpZGUxXTtcbiAgICAgICAgICBwYXN0Rmlyc3RJbnZlcnRUaHJlc2ggPSBmYWxzZTtcbiAgICAgICAgICBpc0NpcmN1bXN0YW50aWFsSW52ZXJ0ID0gIWRpZmZlcmVudFJvd0NvbCAmJiBvcHRpb25zLmludmVydFN3YXAgfHwgZGlmZmVyZW50TGV2ZWw7XG4gICAgICAgIH1cblxuICAgICAgICBkaXJlY3Rpb24gPSBfZ2V0U3dhcERpcmVjdGlvbihldnQsIHRhcmdldCwgdGFyZ2V0UmVjdCwgdmVydGljYWwsIGRpZmZlcmVudFJvd0NvbCA/IDEgOiBvcHRpb25zLnN3YXBUaHJlc2hvbGQsIG9wdGlvbnMuaW52ZXJ0ZWRTd2FwVGhyZXNob2xkID09IG51bGwgPyBvcHRpb25zLnN3YXBUaHJlc2hvbGQgOiBvcHRpb25zLmludmVydGVkU3dhcFRocmVzaG9sZCwgaXNDaXJjdW1zdGFudGlhbEludmVydCwgbGFzdFRhcmdldCA9PT0gdGFyZ2V0KTtcbiAgICAgICAgdmFyIHNpYmxpbmc7XG5cbiAgICAgICAgaWYgKGRpcmVjdGlvbiAhPT0gMCkge1xuICAgICAgICAgIC8vIENoZWNrIGlmIHRhcmdldCBpcyBiZXNpZGUgZHJhZ0VsIGluIHJlc3BlY3RpdmUgZGlyZWN0aW9uIChpZ25vcmluZyBoaWRkZW4gZWxlbWVudHMpXG4gICAgICAgICAgdmFyIGRyYWdJbmRleCA9IGluZGV4KGRyYWdFbCk7XG5cbiAgICAgICAgICBkbyB7XG4gICAgICAgICAgICBkcmFnSW5kZXggLT0gZGlyZWN0aW9uO1xuICAgICAgICAgICAgc2libGluZyA9IHBhcmVudEVsLmNoaWxkcmVuW2RyYWdJbmRleF07XG4gICAgICAgICAgfSB3aGlsZSAoc2libGluZyAmJiAoY3NzKHNpYmxpbmcsICdkaXNwbGF5JykgPT09ICdub25lJyB8fCBzaWJsaW5nID09PSBnaG9zdEVsKSk7XG4gICAgICAgIH0gLy8gSWYgZHJhZ0VsIGlzIGFscmVhZHkgYmVzaWRlIHRhcmdldDogRG8gbm90IGluc2VydFxuXG5cbiAgICAgICAgaWYgKGRpcmVjdGlvbiA9PT0gMCB8fCBzaWJsaW5nID09PSB0YXJnZXQpIHtcbiAgICAgICAgICByZXR1cm4gY29tcGxldGVkKGZhbHNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxhc3RUYXJnZXQgPSB0YXJnZXQ7XG4gICAgICAgIGxhc3REaXJlY3Rpb24gPSBkaXJlY3Rpb247XG4gICAgICAgIHZhciBuZXh0U2libGluZyA9IHRhcmdldC5uZXh0RWxlbWVudFNpYmxpbmcsXG4gICAgICAgICAgICBhZnRlciA9IGZhbHNlO1xuICAgICAgICBhZnRlciA9IGRpcmVjdGlvbiA9PT0gMTtcblxuICAgICAgICB2YXIgbW92ZVZlY3RvciA9IF9vbk1vdmUocm9vdEVsLCBlbCwgZHJhZ0VsLCBkcmFnUmVjdCwgdGFyZ2V0LCB0YXJnZXRSZWN0LCBldnQsIGFmdGVyKTtcblxuICAgICAgICBpZiAobW92ZVZlY3RvciAhPT0gZmFsc2UpIHtcbiAgICAgICAgICBpZiAobW92ZVZlY3RvciA9PT0gMSB8fCBtb3ZlVmVjdG9yID09PSAtMSkge1xuICAgICAgICAgICAgYWZ0ZXIgPSBtb3ZlVmVjdG9yID09PSAxO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIF9zaWxlbnQgPSB0cnVlO1xuICAgICAgICAgIHNldFRpbWVvdXQoX3Vuc2lsZW50LCAzMCk7XG4gICAgICAgICAgY2FwdHVyZSgpO1xuXG4gICAgICAgICAgaWYgKGFmdGVyICYmICFuZXh0U2libGluZykge1xuICAgICAgICAgICAgZWwuYXBwZW5kQ2hpbGQoZHJhZ0VsKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGFyZ2V0LnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGRyYWdFbCwgYWZ0ZXIgPyBuZXh0U2libGluZyA6IHRhcmdldCk7XG4gICAgICAgICAgfSAvLyBVbmRvIGNocm9tZSdzIHNjcm9sbCBhZGp1c3RtZW50IChoYXMgbm8gZWZmZWN0IG9uIG90aGVyIGJyb3dzZXJzKVxuXG5cbiAgICAgICAgICBpZiAoc2Nyb2xsZWRQYXN0VG9wKSB7XG4gICAgICAgICAgICBzY3JvbGxCeShzY3JvbGxlZFBhc3RUb3AsIDAsIHNjcm9sbEJlZm9yZSAtIHNjcm9sbGVkUGFzdFRvcC5zY3JvbGxUb3ApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHBhcmVudEVsID0gZHJhZ0VsLnBhcmVudE5vZGU7IC8vIGFjdHVhbGl6YXRpb25cbiAgICAgICAgICAvLyBtdXN0IGJlIGRvbmUgYmVmb3JlIGFuaW1hdGlvblxuXG4gICAgICAgICAgaWYgKHRhcmdldEJlZm9yZUZpcnN0U3dhcCAhPT0gdW5kZWZpbmVkICYmICFpc0NpcmN1bXN0YW50aWFsSW52ZXJ0KSB7XG4gICAgICAgICAgICB0YXJnZXRNb3ZlRGlzdGFuY2UgPSBNYXRoLmFicyh0YXJnZXRCZWZvcmVGaXJzdFN3YXAgLSBnZXRSZWN0KHRhcmdldClbc2lkZTFdKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjaGFuZ2VkKCk7XG4gICAgICAgICAgcmV0dXJuIGNvbXBsZXRlZCh0cnVlKTtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoZWwuY29udGFpbnMoZHJhZ0VsKSkge1xuICAgICAgICByZXR1cm4gY29tcGxldGVkKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gZmFsc2U7XG4gIH0sXG4gIF9pZ25vcmVXaGlsZUFuaW1hdGluZzogbnVsbCxcbiAgX29mZk1vdmVFdmVudHM6IGZ1bmN0aW9uIF9vZmZNb3ZlRXZlbnRzKCkge1xuICAgIG9mZihkb2N1bWVudCwgJ21vdXNlbW92ZScsIHRoaXMuX29uVG91Y2hNb3ZlKTtcbiAgICBvZmYoZG9jdW1lbnQsICd0b3VjaG1vdmUnLCB0aGlzLl9vblRvdWNoTW92ZSk7XG4gICAgb2ZmKGRvY3VtZW50LCAncG9pbnRlcm1vdmUnLCB0aGlzLl9vblRvdWNoTW92ZSk7XG4gICAgb2ZmKGRvY3VtZW50LCAnZHJhZ292ZXInLCBuZWFyZXN0RW1wdHlJbnNlcnREZXRlY3RFdmVudCk7XG4gICAgb2ZmKGRvY3VtZW50LCAnbW91c2Vtb3ZlJywgbmVhcmVzdEVtcHR5SW5zZXJ0RGV0ZWN0RXZlbnQpO1xuICAgIG9mZihkb2N1bWVudCwgJ3RvdWNobW92ZScsIG5lYXJlc3RFbXB0eUluc2VydERldGVjdEV2ZW50KTtcbiAgfSxcbiAgX29mZlVwRXZlbnRzOiBmdW5jdGlvbiBfb2ZmVXBFdmVudHMoKSB7XG4gICAgdmFyIG93bmVyRG9jdW1lbnQgPSB0aGlzLmVsLm93bmVyRG9jdW1lbnQ7XG4gICAgb2ZmKG93bmVyRG9jdW1lbnQsICdtb3VzZXVwJywgdGhpcy5fb25Ecm9wKTtcbiAgICBvZmYob3duZXJEb2N1bWVudCwgJ3RvdWNoZW5kJywgdGhpcy5fb25Ecm9wKTtcbiAgICBvZmYob3duZXJEb2N1bWVudCwgJ3BvaW50ZXJ1cCcsIHRoaXMuX29uRHJvcCk7XG4gICAgb2ZmKG93bmVyRG9jdW1lbnQsICd0b3VjaGNhbmNlbCcsIHRoaXMuX29uRHJvcCk7XG4gICAgb2ZmKGRvY3VtZW50LCAnc2VsZWN0c3RhcnQnLCB0aGlzKTtcbiAgfSxcbiAgX29uRHJvcDogZnVuY3Rpb24gX29uRHJvcChcbiAgLyoqRXZlbnQqL1xuICBldnQpIHtcbiAgICB2YXIgZWwgPSB0aGlzLmVsLFxuICAgICAgICBvcHRpb25zID0gdGhpcy5vcHRpb25zOyAvLyBHZXQgdGhlIGluZGV4IG9mIHRoZSBkcmFnZ2VkIGVsZW1lbnQgd2l0aGluIGl0cyBwYXJlbnRcblxuICAgIG5ld0luZGV4ID0gaW5kZXgoZHJhZ0VsKTtcbiAgICBuZXdEcmFnZ2FibGVJbmRleCA9IGluZGV4KGRyYWdFbCwgb3B0aW9ucy5kcmFnZ2FibGUpO1xuICAgIHBsdWdpbkV2ZW50KCdkcm9wJywgdGhpcywge1xuICAgICAgZXZ0OiBldnRcbiAgICB9KTtcbiAgICBwYXJlbnRFbCA9IGRyYWdFbCAmJiBkcmFnRWwucGFyZW50Tm9kZTsgLy8gR2V0IGFnYWluIGFmdGVyIHBsdWdpbiBldmVudFxuXG4gICAgbmV3SW5kZXggPSBpbmRleChkcmFnRWwpO1xuICAgIG5ld0RyYWdnYWJsZUluZGV4ID0gaW5kZXgoZHJhZ0VsLCBvcHRpb25zLmRyYWdnYWJsZSk7XG5cbiAgICBpZiAoU29ydGFibGUuZXZlbnRDYW5jZWxlZCkge1xuICAgICAgdGhpcy5fbnVsbGluZygpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgYXdhaXRpbmdEcmFnU3RhcnRlZCA9IGZhbHNlO1xuICAgIGlzQ2lyY3Vtc3RhbnRpYWxJbnZlcnQgPSBmYWxzZTtcbiAgICBwYXN0Rmlyc3RJbnZlcnRUaHJlc2ggPSBmYWxzZTtcbiAgICBjbGVhckludGVydmFsKHRoaXMuX2xvb3BJZCk7XG4gICAgY2xlYXJUaW1lb3V0KHRoaXMuX2RyYWdTdGFydFRpbWVyKTtcblxuICAgIF9jYW5jZWxOZXh0VGljayh0aGlzLmNsb25lSWQpO1xuXG4gICAgX2NhbmNlbE5leHRUaWNrKHRoaXMuX2RyYWdTdGFydElkKTsgLy8gVW5iaW5kIGV2ZW50c1xuXG5cbiAgICBpZiAodGhpcy5uYXRpdmVEcmFnZ2FibGUpIHtcbiAgICAgIG9mZihkb2N1bWVudCwgJ2Ryb3AnLCB0aGlzKTtcbiAgICAgIG9mZihlbCwgJ2RyYWdzdGFydCcsIHRoaXMuX29uRHJhZ1N0YXJ0KTtcbiAgICB9XG5cbiAgICB0aGlzLl9vZmZNb3ZlRXZlbnRzKCk7XG5cbiAgICB0aGlzLl9vZmZVcEV2ZW50cygpO1xuXG4gICAgaWYgKFNhZmFyaSkge1xuICAgICAgY3NzKGRvY3VtZW50LmJvZHksICd1c2VyLXNlbGVjdCcsICcnKTtcbiAgICB9XG5cbiAgICBjc3MoZHJhZ0VsLCAndHJhbnNmb3JtJywgJycpO1xuXG4gICAgaWYgKGV2dCkge1xuICAgICAgaWYgKG1vdmVkKSB7XG4gICAgICAgIGV2dC5jYW5jZWxhYmxlICYmIGV2dC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAhb3B0aW9ucy5kcm9wQnViYmxlICYmIGV2dC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgIH1cblxuICAgICAgZ2hvc3RFbCAmJiBnaG9zdEVsLnBhcmVudE5vZGUgJiYgZ2hvc3RFbC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGdob3N0RWwpO1xuXG4gICAgICBpZiAocm9vdEVsID09PSBwYXJlbnRFbCB8fCBwdXRTb3J0YWJsZSAmJiBwdXRTb3J0YWJsZS5sYXN0UHV0TW9kZSAhPT0gJ2Nsb25lJykge1xuICAgICAgICAvLyBSZW1vdmUgY2xvbmUocylcbiAgICAgICAgY2xvbmVFbCAmJiBjbG9uZUVsLnBhcmVudE5vZGUgJiYgY2xvbmVFbC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGNsb25lRWwpO1xuICAgICAgfVxuXG4gICAgICBpZiAoZHJhZ0VsKSB7XG4gICAgICAgIGlmICh0aGlzLm5hdGl2ZURyYWdnYWJsZSkge1xuICAgICAgICAgIG9mZihkcmFnRWwsICdkcmFnZW5kJywgdGhpcyk7XG4gICAgICAgIH1cblxuICAgICAgICBfZGlzYWJsZURyYWdnYWJsZShkcmFnRWwpO1xuXG4gICAgICAgIGRyYWdFbC5zdHlsZVsnd2lsbC1jaGFuZ2UnXSA9ICcnOyAvLyBSZW1vdmUgY2xhc3Nlc1xuICAgICAgICAvLyBnaG9zdENsYXNzIGlzIGFkZGVkIGluIGRyYWdTdGFydGVkXG5cbiAgICAgICAgaWYgKG1vdmVkICYmICFhd2FpdGluZ0RyYWdTdGFydGVkKSB7XG4gICAgICAgICAgdG9nZ2xlQ2xhc3MoZHJhZ0VsLCBwdXRTb3J0YWJsZSA/IHB1dFNvcnRhYmxlLm9wdGlvbnMuZ2hvc3RDbGFzcyA6IHRoaXMub3B0aW9ucy5naG9zdENsYXNzLCBmYWxzZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0b2dnbGVDbGFzcyhkcmFnRWwsIHRoaXMub3B0aW9ucy5jaG9zZW5DbGFzcywgZmFsc2UpOyAvLyBEcmFnIHN0b3AgZXZlbnRcblxuICAgICAgICBfZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgICAgc29ydGFibGU6IHRoaXMsXG4gICAgICAgICAgbmFtZTogJ3VuY2hvb3NlJyxcbiAgICAgICAgICB0b0VsOiBwYXJlbnRFbCxcbiAgICAgICAgICBuZXdJbmRleDogbnVsbCxcbiAgICAgICAgICBuZXdEcmFnZ2FibGVJbmRleDogbnVsbCxcbiAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBldnRcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHJvb3RFbCAhPT0gcGFyZW50RWwpIHtcbiAgICAgICAgICBpZiAobmV3SW5kZXggPj0gMCkge1xuICAgICAgICAgICAgLy8gQWRkIGV2ZW50XG4gICAgICAgICAgICBfZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgICAgICAgIHJvb3RFbDogcGFyZW50RWwsXG4gICAgICAgICAgICAgIG5hbWU6ICdhZGQnLFxuICAgICAgICAgICAgICB0b0VsOiBwYXJlbnRFbCxcbiAgICAgICAgICAgICAgZnJvbUVsOiByb290RWwsXG4gICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2dFxuICAgICAgICAgICAgfSk7IC8vIFJlbW92ZSBldmVudFxuXG5cbiAgICAgICAgICAgIF9kaXNwYXRjaEV2ZW50KHtcbiAgICAgICAgICAgICAgc29ydGFibGU6IHRoaXMsXG4gICAgICAgICAgICAgIG5hbWU6ICdyZW1vdmUnLFxuICAgICAgICAgICAgICB0b0VsOiBwYXJlbnRFbCxcbiAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZ0XG4gICAgICAgICAgICB9KTsgLy8gZHJhZyBmcm9tIG9uZSBsaXN0IGFuZCBkcm9wIGludG8gYW5vdGhlclxuXG5cbiAgICAgICAgICAgIF9kaXNwYXRjaEV2ZW50KHtcbiAgICAgICAgICAgICAgcm9vdEVsOiBwYXJlbnRFbCxcbiAgICAgICAgICAgICAgbmFtZTogJ3NvcnQnLFxuICAgICAgICAgICAgICB0b0VsOiBwYXJlbnRFbCxcbiAgICAgICAgICAgICAgZnJvbUVsOiByb290RWwsXG4gICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2dFxuICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgIF9kaXNwYXRjaEV2ZW50KHtcbiAgICAgICAgICAgICAgc29ydGFibGU6IHRoaXMsXG4gICAgICAgICAgICAgIG5hbWU6ICdzb3J0JyxcbiAgICAgICAgICAgICAgdG9FbDogcGFyZW50RWwsXG4gICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQ6IGV2dFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcHV0U29ydGFibGUgJiYgcHV0U29ydGFibGUuc2F2ZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChuZXdJbmRleCAhPT0gb2xkSW5kZXgpIHtcbiAgICAgICAgICAgIGlmIChuZXdJbmRleCA+PSAwKSB7XG4gICAgICAgICAgICAgIC8vIGRyYWcgJiBkcm9wIHdpdGhpbiB0aGUgc2FtZSBsaXN0XG4gICAgICAgICAgICAgIF9kaXNwYXRjaEV2ZW50KHtcbiAgICAgICAgICAgICAgICBzb3J0YWJsZTogdGhpcyxcbiAgICAgICAgICAgICAgICBuYW1lOiAndXBkYXRlJyxcbiAgICAgICAgICAgICAgICB0b0VsOiBwYXJlbnRFbCxcbiAgICAgICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBldnRcbiAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgX2Rpc3BhdGNoRXZlbnQoe1xuICAgICAgICAgICAgICAgIHNvcnRhYmxlOiB0aGlzLFxuICAgICAgICAgICAgICAgIG5hbWU6ICdzb3J0JyxcbiAgICAgICAgICAgICAgICB0b0VsOiBwYXJlbnRFbCxcbiAgICAgICAgICAgICAgICBvcmlnaW5hbEV2ZW50OiBldnRcbiAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKFNvcnRhYmxlLmFjdGl2ZSkge1xuICAgICAgICAgIC8qIGpzaGludCBlcW51bGw6dHJ1ZSAqL1xuICAgICAgICAgIGlmIChuZXdJbmRleCA9PSBudWxsIHx8IG5ld0luZGV4ID09PSAtMSkge1xuICAgICAgICAgICAgbmV3SW5kZXggPSBvbGRJbmRleDtcbiAgICAgICAgICAgIG5ld0RyYWdnYWJsZUluZGV4ID0gb2xkRHJhZ2dhYmxlSW5kZXg7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgX2Rpc3BhdGNoRXZlbnQoe1xuICAgICAgICAgICAgc29ydGFibGU6IHRoaXMsXG4gICAgICAgICAgICBuYW1lOiAnZW5kJyxcbiAgICAgICAgICAgIHRvRWw6IHBhcmVudEVsLFxuICAgICAgICAgICAgb3JpZ2luYWxFdmVudDogZXZ0XG4gICAgICAgICAgfSk7IC8vIFNhdmUgc29ydGluZ1xuXG5cbiAgICAgICAgICB0aGlzLnNhdmUoKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuX251bGxpbmcoKTtcbiAgfSxcbiAgX251bGxpbmc6IGZ1bmN0aW9uIF9udWxsaW5nKCkge1xuICAgIHBsdWdpbkV2ZW50KCdudWxsaW5nJywgdGhpcyk7XG4gICAgcm9vdEVsID0gZHJhZ0VsID0gcGFyZW50RWwgPSBnaG9zdEVsID0gbmV4dEVsID0gY2xvbmVFbCA9IGxhc3REb3duRWwgPSBjbG9uZUhpZGRlbiA9IHRhcEV2dCA9IHRvdWNoRXZ0ID0gbW92ZWQgPSBuZXdJbmRleCA9IG5ld0RyYWdnYWJsZUluZGV4ID0gb2xkSW5kZXggPSBvbGREcmFnZ2FibGVJbmRleCA9IGxhc3RUYXJnZXQgPSBsYXN0RGlyZWN0aW9uID0gcHV0U29ydGFibGUgPSBhY3RpdmVHcm91cCA9IFNvcnRhYmxlLmRyYWdnZWQgPSBTb3J0YWJsZS5naG9zdCA9IFNvcnRhYmxlLmNsb25lID0gU29ydGFibGUuYWN0aXZlID0gbnVsbDtcbiAgICBzYXZlZElucHV0Q2hlY2tlZC5mb3JFYWNoKGZ1bmN0aW9uIChlbCkge1xuICAgICAgZWwuY2hlY2tlZCA9IHRydWU7XG4gICAgfSk7XG4gICAgc2F2ZWRJbnB1dENoZWNrZWQubGVuZ3RoID0gbGFzdER4ID0gbGFzdER5ID0gMDtcbiAgfSxcbiAgaGFuZGxlRXZlbnQ6IGZ1bmN0aW9uIGhhbmRsZUV2ZW50KFxuICAvKipFdmVudCovXG4gIGV2dCkge1xuICAgIHN3aXRjaCAoZXZ0LnR5cGUpIHtcbiAgICAgIGNhc2UgJ2Ryb3AnOlxuICAgICAgY2FzZSAnZHJhZ2VuZCc6XG4gICAgICAgIHRoaXMuX29uRHJvcChldnQpO1xuXG4gICAgICAgIGJyZWFrO1xuXG4gICAgICBjYXNlICdkcmFnZW50ZXInOlxuICAgICAgY2FzZSAnZHJhZ292ZXInOlxuICAgICAgICBpZiAoZHJhZ0VsKSB7XG4gICAgICAgICAgdGhpcy5fb25EcmFnT3ZlcihldnQpO1xuXG4gICAgICAgICAgX2dsb2JhbERyYWdPdmVyKGV2dCk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcblxuICAgICAgY2FzZSAnc2VsZWN0c3RhcnQnOlxuICAgICAgICBldnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgYnJlYWs7XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBTZXJpYWxpemVzIHRoZSBpdGVtIGludG8gYW4gYXJyYXkgb2Ygc3RyaW5nLlxuICAgKiBAcmV0dXJucyB7U3RyaW5nW119XG4gICAqL1xuICB0b0FycmF5OiBmdW5jdGlvbiB0b0FycmF5KCkge1xuICAgIHZhciBvcmRlciA9IFtdLFxuICAgICAgICBlbCxcbiAgICAgICAgY2hpbGRyZW4gPSB0aGlzLmVsLmNoaWxkcmVuLFxuICAgICAgICBpID0gMCxcbiAgICAgICAgbiA9IGNoaWxkcmVuLmxlbmd0aCxcbiAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcblxuICAgIGZvciAoOyBpIDwgbjsgaSsrKSB7XG4gICAgICBlbCA9IGNoaWxkcmVuW2ldO1xuXG4gICAgICBpZiAoY2xvc2VzdChlbCwgb3B0aW9ucy5kcmFnZ2FibGUsIHRoaXMuZWwsIGZhbHNlKSkge1xuICAgICAgICBvcmRlci5wdXNoKGVsLmdldEF0dHJpYnV0ZShvcHRpb25zLmRhdGFJZEF0dHIpIHx8IF9nZW5lcmF0ZUlkKGVsKSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9yZGVyO1xuICB9LFxuXG4gIC8qKlxuICAgKiBTb3J0cyB0aGUgZWxlbWVudHMgYWNjb3JkaW5nIHRvIHRoZSBhcnJheS5cbiAgICogQHBhcmFtICB7U3RyaW5nW119ICBvcmRlciAgb3JkZXIgb2YgdGhlIGl0ZW1zXG4gICAqL1xuICBzb3J0OiBmdW5jdGlvbiBzb3J0KG9yZGVyKSB7XG4gICAgdmFyIGl0ZW1zID0ge30sXG4gICAgICAgIHJvb3RFbCA9IHRoaXMuZWw7XG4gICAgdGhpcy50b0FycmF5KCkuZm9yRWFjaChmdW5jdGlvbiAoaWQsIGkpIHtcbiAgICAgIHZhciBlbCA9IHJvb3RFbC5jaGlsZHJlbltpXTtcblxuICAgICAgaWYgKGNsb3Nlc3QoZWwsIHRoaXMub3B0aW9ucy5kcmFnZ2FibGUsIHJvb3RFbCwgZmFsc2UpKSB7XG4gICAgICAgIGl0ZW1zW2lkXSA9IGVsO1xuICAgICAgfVxuICAgIH0sIHRoaXMpO1xuICAgIG9yZGVyLmZvckVhY2goZnVuY3Rpb24gKGlkKSB7XG4gICAgICBpZiAoaXRlbXNbaWRdKSB7XG4gICAgICAgIHJvb3RFbC5yZW1vdmVDaGlsZChpdGVtc1tpZF0pO1xuICAgICAgICByb290RWwuYXBwZW5kQ2hpbGQoaXRlbXNbaWRdKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfSxcblxuICAvKipcbiAgICogU2F2ZSB0aGUgY3VycmVudCBzb3J0aW5nXG4gICAqL1xuICBzYXZlOiBmdW5jdGlvbiBzYXZlKCkge1xuICAgIHZhciBzdG9yZSA9IHRoaXMub3B0aW9ucy5zdG9yZTtcbiAgICBzdG9yZSAmJiBzdG9yZS5zZXQgJiYgc3RvcmUuc2V0KHRoaXMpO1xuICB9LFxuXG4gIC8qKlxuICAgKiBGb3IgZWFjaCBlbGVtZW50IGluIHRoZSBzZXQsIGdldCB0aGUgZmlyc3QgZWxlbWVudCB0aGF0IG1hdGNoZXMgdGhlIHNlbGVjdG9yIGJ5IHRlc3RpbmcgdGhlIGVsZW1lbnQgaXRzZWxmIGFuZCB0cmF2ZXJzaW5nIHVwIHRocm91Z2ggaXRzIGFuY2VzdG9ycyBpbiB0aGUgRE9NIHRyZWUuXG4gICAqIEBwYXJhbSAgIHtIVE1MRWxlbWVudH0gIGVsXG4gICAqIEBwYXJhbSAgIHtTdHJpbmd9ICAgICAgIFtzZWxlY3Rvcl0gIGRlZmF1bHQ6IGBvcHRpb25zLmRyYWdnYWJsZWBcbiAgICogQHJldHVybnMge0hUTUxFbGVtZW50fG51bGx9XG4gICAqL1xuICBjbG9zZXN0OiBmdW5jdGlvbiBjbG9zZXN0JDEoZWwsIHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuIGNsb3Nlc3QoZWwsIHNlbGVjdG9yIHx8IHRoaXMub3B0aW9ucy5kcmFnZ2FibGUsIHRoaXMuZWwsIGZhbHNlKTtcbiAgfSxcblxuICAvKipcbiAgICogU2V0L2dldCBvcHRpb25cbiAgICogQHBhcmFtICAge3N0cmluZ30gbmFtZVxuICAgKiBAcGFyYW0gICB7Kn0gICAgICBbdmFsdWVdXG4gICAqIEByZXR1cm5zIHsqfVxuICAgKi9cbiAgb3B0aW9uOiBmdW5jdGlvbiBvcHRpb24obmFtZSwgdmFsdWUpIHtcbiAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcblxuICAgIGlmICh2YWx1ZSA9PT0gdm9pZCAwKSB7XG4gICAgICByZXR1cm4gb3B0aW9uc1tuYW1lXTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIG1vZGlmaWVkVmFsdWUgPSBQbHVnaW5NYW5hZ2VyLm1vZGlmeU9wdGlvbih0aGlzLCBuYW1lLCB2YWx1ZSk7XG5cbiAgICAgIGlmICh0eXBlb2YgbW9kaWZpZWRWYWx1ZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgb3B0aW9uc1tuYW1lXSA9IG1vZGlmaWVkVmFsdWU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBvcHRpb25zW25hbWVdID0gdmFsdWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChuYW1lID09PSAnZ3JvdXAnKSB7XG4gICAgICAgIF9wcmVwYXJlR3JvdXAob3B0aW9ucyk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuXG4gIC8qKlxuICAgKiBEZXN0cm95XG4gICAqL1xuICBkZXN0cm95OiBmdW5jdGlvbiBkZXN0cm95KCkge1xuICAgIHBsdWdpbkV2ZW50KCdkZXN0cm95JywgdGhpcyk7XG4gICAgdmFyIGVsID0gdGhpcy5lbDtcbiAgICBlbFtleHBhbmRvXSA9IG51bGw7XG4gICAgb2ZmKGVsLCAnbW91c2Vkb3duJywgdGhpcy5fb25UYXBTdGFydCk7XG4gICAgb2ZmKGVsLCAndG91Y2hzdGFydCcsIHRoaXMuX29uVGFwU3RhcnQpO1xuICAgIG9mZihlbCwgJ3BvaW50ZXJkb3duJywgdGhpcy5fb25UYXBTdGFydCk7XG5cbiAgICBpZiAodGhpcy5uYXRpdmVEcmFnZ2FibGUpIHtcbiAgICAgIG9mZihlbCwgJ2RyYWdvdmVyJywgdGhpcyk7XG4gICAgICBvZmYoZWwsICdkcmFnZW50ZXInLCB0aGlzKTtcbiAgICB9IC8vIFJlbW92ZSBkcmFnZ2FibGUgYXR0cmlidXRlc1xuXG5cbiAgICBBcnJheS5wcm90b3R5cGUuZm9yRWFjaC5jYWxsKGVsLnF1ZXJ5U2VsZWN0b3JBbGwoJ1tkcmFnZ2FibGVdJyksIGZ1bmN0aW9uIChlbCkge1xuICAgICAgZWwucmVtb3ZlQXR0cmlidXRlKCdkcmFnZ2FibGUnKTtcbiAgICB9KTtcblxuICAgIHRoaXMuX29uRHJvcCgpO1xuXG4gICAgdGhpcy5fZGlzYWJsZURlbGF5ZWREcmFnRXZlbnRzKCk7XG5cbiAgICBzb3J0YWJsZXMuc3BsaWNlKHNvcnRhYmxlcy5pbmRleE9mKHRoaXMuZWwpLCAxKTtcbiAgICB0aGlzLmVsID0gZWwgPSBudWxsO1xuICB9LFxuICBfaGlkZUNsb25lOiBmdW5jdGlvbiBfaGlkZUNsb25lKCkge1xuICAgIGlmICghY2xvbmVIaWRkZW4pIHtcbiAgICAgIHBsdWdpbkV2ZW50KCdoaWRlQ2xvbmUnLCB0aGlzKTtcbiAgICAgIGlmIChTb3J0YWJsZS5ldmVudENhbmNlbGVkKSByZXR1cm47XG4gICAgICBjc3MoY2xvbmVFbCwgJ2Rpc3BsYXknLCAnbm9uZScpO1xuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLnJlbW92ZUNsb25lT25IaWRlICYmIGNsb25lRWwucGFyZW50Tm9kZSkge1xuICAgICAgICBjbG9uZUVsLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY2xvbmVFbCk7XG4gICAgICB9XG5cbiAgICAgIGNsb25lSGlkZGVuID0gdHJ1ZTtcbiAgICB9XG4gIH0sXG4gIF9zaG93Q2xvbmU6IGZ1bmN0aW9uIF9zaG93Q2xvbmUocHV0U29ydGFibGUpIHtcbiAgICBpZiAocHV0U29ydGFibGUubGFzdFB1dE1vZGUgIT09ICdjbG9uZScpIHtcbiAgICAgIHRoaXMuX2hpZGVDbG9uZSgpO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKGNsb25lSGlkZGVuKSB7XG4gICAgICBwbHVnaW5FdmVudCgnc2hvd0Nsb25lJywgdGhpcyk7XG4gICAgICBpZiAoU29ydGFibGUuZXZlbnRDYW5jZWxlZCkgcmV0dXJuOyAvLyBzaG93IGNsb25lIGF0IGRyYWdFbCBvciBvcmlnaW5hbCBwb3NpdGlvblxuXG4gICAgICBpZiAocm9vdEVsLmNvbnRhaW5zKGRyYWdFbCkgJiYgIXRoaXMub3B0aW9ucy5ncm91cC5yZXZlcnRDbG9uZSkge1xuICAgICAgICByb290RWwuaW5zZXJ0QmVmb3JlKGNsb25lRWwsIGRyYWdFbCk7XG4gICAgICB9IGVsc2UgaWYgKG5leHRFbCkge1xuICAgICAgICByb290RWwuaW5zZXJ0QmVmb3JlKGNsb25lRWwsIG5leHRFbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByb290RWwuYXBwZW5kQ2hpbGQoY2xvbmVFbCk7XG4gICAgICB9XG5cbiAgICAgIGlmICh0aGlzLm9wdGlvbnMuZ3JvdXAucmV2ZXJ0Q2xvbmUpIHtcbiAgICAgICAgdGhpcy5hbmltYXRlKGRyYWdFbCwgY2xvbmVFbCk7XG4gICAgICB9XG5cbiAgICAgIGNzcyhjbG9uZUVsLCAnZGlzcGxheScsICcnKTtcbiAgICAgIGNsb25lSGlkZGVuID0gZmFsc2U7XG4gICAgfVxuICB9XG59O1xuXG5mdW5jdGlvbiBfZ2xvYmFsRHJhZ092ZXIoXG4vKipFdmVudCovXG5ldnQpIHtcbiAgaWYgKGV2dC5kYXRhVHJhbnNmZXIpIHtcbiAgICBldnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbW92ZSc7XG4gIH1cblxuICBldnQuY2FuY2VsYWJsZSAmJiBldnQucHJldmVudERlZmF1bHQoKTtcbn1cblxuZnVuY3Rpb24gX29uTW92ZShmcm9tRWwsIHRvRWwsIGRyYWdFbCwgZHJhZ1JlY3QsIHRhcmdldEVsLCB0YXJnZXRSZWN0LCBvcmlnaW5hbEV2ZW50LCB3aWxsSW5zZXJ0QWZ0ZXIpIHtcbiAgdmFyIGV2dCxcbiAgICAgIHNvcnRhYmxlID0gZnJvbUVsW2V4cGFuZG9dLFxuICAgICAgb25Nb3ZlRm4gPSBzb3J0YWJsZS5vcHRpb25zLm9uTW92ZSxcbiAgICAgIHJldFZhbDsgLy8gU3VwcG9ydCBmb3IgbmV3IEN1c3RvbUV2ZW50IGZlYXR1cmVcblxuICBpZiAod2luZG93LkN1c3RvbUV2ZW50ICYmICFJRTExT3JMZXNzICYmICFFZGdlKSB7XG4gICAgZXZ0ID0gbmV3IEN1c3RvbUV2ZW50KCdtb3ZlJywge1xuICAgICAgYnViYmxlczogdHJ1ZSxcbiAgICAgIGNhbmNlbGFibGU6IHRydWVcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBldnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnRXZlbnQnKTtcbiAgICBldnQuaW5pdEV2ZW50KCdtb3ZlJywgdHJ1ZSwgdHJ1ZSk7XG4gIH1cblxuICBldnQudG8gPSB0b0VsO1xuICBldnQuZnJvbSA9IGZyb21FbDtcbiAgZXZ0LmRyYWdnZWQgPSBkcmFnRWw7XG4gIGV2dC5kcmFnZ2VkUmVjdCA9IGRyYWdSZWN0O1xuICBldnQucmVsYXRlZCA9IHRhcmdldEVsIHx8IHRvRWw7XG4gIGV2dC5yZWxhdGVkUmVjdCA9IHRhcmdldFJlY3QgfHwgZ2V0UmVjdCh0b0VsKTtcbiAgZXZ0LndpbGxJbnNlcnRBZnRlciA9IHdpbGxJbnNlcnRBZnRlcjtcbiAgZXZ0Lm9yaWdpbmFsRXZlbnQgPSBvcmlnaW5hbEV2ZW50O1xuICBmcm9tRWwuZGlzcGF0Y2hFdmVudChldnQpO1xuXG4gIGlmIChvbk1vdmVGbikge1xuICAgIHJldFZhbCA9IG9uTW92ZUZuLmNhbGwoc29ydGFibGUsIGV2dCwgb3JpZ2luYWxFdmVudCk7XG4gIH1cblxuICByZXR1cm4gcmV0VmFsO1xufVxuXG5mdW5jdGlvbiBfZGlzYWJsZURyYWdnYWJsZShlbCkge1xuICBlbC5kcmFnZ2FibGUgPSBmYWxzZTtcbn1cblxuZnVuY3Rpb24gX3Vuc2lsZW50KCkge1xuICBfc2lsZW50ID0gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIF9naG9zdElzTGFzdChldnQsIHZlcnRpY2FsLCBzb3J0YWJsZSkge1xuICB2YXIgcmVjdCA9IGdldFJlY3QobGFzdENoaWxkKHNvcnRhYmxlLmVsLCBzb3J0YWJsZS5vcHRpb25zLmRyYWdnYWJsZSkpO1xuICB2YXIgc3BhY2VyID0gMTA7XG4gIHJldHVybiB2ZXJ0aWNhbCA/IGV2dC5jbGllbnRYID4gcmVjdC5yaWdodCArIHNwYWNlciB8fCBldnQuY2xpZW50WCA8PSByZWN0LnJpZ2h0ICYmIGV2dC5jbGllbnRZID4gcmVjdC5ib3R0b20gJiYgZXZ0LmNsaWVudFggPj0gcmVjdC5sZWZ0IDogZXZ0LmNsaWVudFggPiByZWN0LnJpZ2h0ICYmIGV2dC5jbGllbnRZID4gcmVjdC50b3AgfHwgZXZ0LmNsaWVudFggPD0gcmVjdC5yaWdodCAmJiBldnQuY2xpZW50WSA+IHJlY3QuYm90dG9tICsgc3BhY2VyO1xufVxuXG5mdW5jdGlvbiBfZ2V0U3dhcERpcmVjdGlvbihldnQsIHRhcmdldCwgdGFyZ2V0UmVjdCwgdmVydGljYWwsIHN3YXBUaHJlc2hvbGQsIGludmVydGVkU3dhcFRocmVzaG9sZCwgaW52ZXJ0U3dhcCwgaXNMYXN0VGFyZ2V0KSB7XG4gIHZhciBtb3VzZU9uQXhpcyA9IHZlcnRpY2FsID8gZXZ0LmNsaWVudFkgOiBldnQuY2xpZW50WCxcbiAgICAgIHRhcmdldExlbmd0aCA9IHZlcnRpY2FsID8gdGFyZ2V0UmVjdC5oZWlnaHQgOiB0YXJnZXRSZWN0LndpZHRoLFxuICAgICAgdGFyZ2V0UzEgPSB2ZXJ0aWNhbCA/IHRhcmdldFJlY3QudG9wIDogdGFyZ2V0UmVjdC5sZWZ0LFxuICAgICAgdGFyZ2V0UzIgPSB2ZXJ0aWNhbCA/IHRhcmdldFJlY3QuYm90dG9tIDogdGFyZ2V0UmVjdC5yaWdodCxcbiAgICAgIGludmVydCA9IGZhbHNlO1xuXG4gIGlmICghaW52ZXJ0U3dhcCkge1xuICAgIC8vIE5ldmVyIGludmVydCBvciBjcmVhdGUgZHJhZ0VsIHNoYWRvdyB3aGVuIHRhcmdldCBtb3ZlbWVuZXQgY2F1c2VzIG1vdXNlIHRvIG1vdmUgcGFzdCB0aGUgZW5kIG9mIHJlZ3VsYXIgc3dhcFRocmVzaG9sZFxuICAgIGlmIChpc0xhc3RUYXJnZXQgJiYgdGFyZ2V0TW92ZURpc3RhbmNlIDwgdGFyZ2V0TGVuZ3RoICogc3dhcFRocmVzaG9sZCkge1xuICAgICAgLy8gbXVsdGlwbGllZCBvbmx5IGJ5IHN3YXBUaHJlc2hvbGQgYmVjYXVzZSBtb3VzZSB3aWxsIGFscmVhZHkgYmUgaW5zaWRlIHRhcmdldCBieSAoMSAtIHRocmVzaG9sZCkgKiB0YXJnZXRMZW5ndGggLyAyXG4gICAgICAvLyBjaGVjayBpZiBwYXN0IGZpcnN0IGludmVydCB0aHJlc2hvbGQgb24gc2lkZSBvcHBvc2l0ZSBvZiBsYXN0RGlyZWN0aW9uXG4gICAgICBpZiAoIXBhc3RGaXJzdEludmVydFRocmVzaCAmJiAobGFzdERpcmVjdGlvbiA9PT0gMSA/IG1vdXNlT25BeGlzID4gdGFyZ2V0UzEgKyB0YXJnZXRMZW5ndGggKiBpbnZlcnRlZFN3YXBUaHJlc2hvbGQgLyAyIDogbW91c2VPbkF4aXMgPCB0YXJnZXRTMiAtIHRhcmdldExlbmd0aCAqIGludmVydGVkU3dhcFRocmVzaG9sZCAvIDIpKSB7XG4gICAgICAgIC8vIHBhc3QgZmlyc3QgaW52ZXJ0IHRocmVzaG9sZCwgZG8gbm90IHJlc3RyaWN0IGludmVydGVkIHRocmVzaG9sZCB0byBkcmFnRWwgc2hhZG93XG4gICAgICAgIHBhc3RGaXJzdEludmVydFRocmVzaCA9IHRydWU7XG4gICAgICB9XG5cbiAgICAgIGlmICghcGFzdEZpcnN0SW52ZXJ0VGhyZXNoKSB7XG4gICAgICAgIC8vIGRyYWdFbCBzaGFkb3cgKHRhcmdldCBtb3ZlIGRpc3RhbmNlIHNoYWRvdylcbiAgICAgICAgaWYgKGxhc3REaXJlY3Rpb24gPT09IDEgPyBtb3VzZU9uQXhpcyA8IHRhcmdldFMxICsgdGFyZ2V0TW92ZURpc3RhbmNlIC8vIG92ZXIgZHJhZ0VsIHNoYWRvd1xuICAgICAgICA6IG1vdXNlT25BeGlzID4gdGFyZ2V0UzIgLSB0YXJnZXRNb3ZlRGlzdGFuY2UpIHtcbiAgICAgICAgICByZXR1cm4gLWxhc3REaXJlY3Rpb247XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGludmVydCA9IHRydWU7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIFJlZ3VsYXJcbiAgICAgIGlmIChtb3VzZU9uQXhpcyA+IHRhcmdldFMxICsgdGFyZ2V0TGVuZ3RoICogKDEgLSBzd2FwVGhyZXNob2xkKSAvIDIgJiYgbW91c2VPbkF4aXMgPCB0YXJnZXRTMiAtIHRhcmdldExlbmd0aCAqICgxIC0gc3dhcFRocmVzaG9sZCkgLyAyKSB7XG4gICAgICAgIHJldHVybiBfZ2V0SW5zZXJ0RGlyZWN0aW9uKHRhcmdldCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgaW52ZXJ0ID0gaW52ZXJ0IHx8IGludmVydFN3YXA7XG5cbiAgaWYgKGludmVydCkge1xuICAgIC8vIEludmVydCBvZiByZWd1bGFyXG4gICAgaWYgKG1vdXNlT25BeGlzIDwgdGFyZ2V0UzEgKyB0YXJnZXRMZW5ndGggKiBpbnZlcnRlZFN3YXBUaHJlc2hvbGQgLyAyIHx8IG1vdXNlT25BeGlzID4gdGFyZ2V0UzIgLSB0YXJnZXRMZW5ndGggKiBpbnZlcnRlZFN3YXBUaHJlc2hvbGQgLyAyKSB7XG4gICAgICByZXR1cm4gbW91c2VPbkF4aXMgPiB0YXJnZXRTMSArIHRhcmdldExlbmd0aCAvIDIgPyAxIDogLTE7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIDA7XG59XG4vKipcbiAqIEdldHMgdGhlIGRpcmVjdGlvbiBkcmFnRWwgbXVzdCBiZSBzd2FwcGVkIHJlbGF0aXZlIHRvIHRhcmdldCBpbiBvcmRlciB0byBtYWtlIGl0XG4gKiBzZWVtIHRoYXQgZHJhZ0VsIGhhcyBiZWVuIFwiaW5zZXJ0ZWRcIiBpbnRvIHRoYXQgZWxlbWVudCdzIHBvc2l0aW9uXG4gKiBAcGFyYW0gIHtIVE1MRWxlbWVudH0gdGFyZ2V0ICAgICAgIFRoZSB0YXJnZXQgd2hvc2UgcG9zaXRpb24gZHJhZ0VsIGlzIGJlaW5nIGluc2VydGVkIGF0XG4gKiBAcmV0dXJuIHtOdW1iZXJ9ICAgICAgICAgICAgICAgICAgIERpcmVjdGlvbiBkcmFnRWwgbXVzdCBiZSBzd2FwcGVkXG4gKi9cblxuXG5mdW5jdGlvbiBfZ2V0SW5zZXJ0RGlyZWN0aW9uKHRhcmdldCkge1xuICBpZiAoaW5kZXgoZHJhZ0VsKSA8IGluZGV4KHRhcmdldCkpIHtcbiAgICByZXR1cm4gMTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gLTE7XG4gIH1cbn1cbi8qKlxuICogR2VuZXJhdGUgaWRcbiAqIEBwYXJhbSAgIHtIVE1MRWxlbWVudH0gZWxcbiAqIEByZXR1cm5zIHtTdHJpbmd9XG4gKiBAcHJpdmF0ZVxuICovXG5cblxuZnVuY3Rpb24gX2dlbmVyYXRlSWQoZWwpIHtcbiAgdmFyIHN0ciA9IGVsLnRhZ05hbWUgKyBlbC5jbGFzc05hbWUgKyBlbC5zcmMgKyBlbC5ocmVmICsgZWwudGV4dENvbnRlbnQsXG4gICAgICBpID0gc3RyLmxlbmd0aCxcbiAgICAgIHN1bSA9IDA7XG5cbiAgd2hpbGUgKGktLSkge1xuICAgIHN1bSArPSBzdHIuY2hhckNvZGVBdChpKTtcbiAgfVxuXG4gIHJldHVybiBzdW0udG9TdHJpbmcoMzYpO1xufVxuXG5mdW5jdGlvbiBfc2F2ZUlucHV0Q2hlY2tlZFN0YXRlKHJvb3QpIHtcbiAgc2F2ZWRJbnB1dENoZWNrZWQubGVuZ3RoID0gMDtcbiAgdmFyIGlucHV0cyA9IHJvb3QuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2lucHV0Jyk7XG4gIHZhciBpZHggPSBpbnB1dHMubGVuZ3RoO1xuXG4gIHdoaWxlIChpZHgtLSkge1xuICAgIHZhciBlbCA9IGlucHV0c1tpZHhdO1xuICAgIGVsLmNoZWNrZWQgJiYgc2F2ZWRJbnB1dENoZWNrZWQucHVzaChlbCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gX25leHRUaWNrKGZuKSB7XG4gIHJldHVybiBzZXRUaW1lb3V0KGZuLCAwKTtcbn1cblxuZnVuY3Rpb24gX2NhbmNlbE5leHRUaWNrKGlkKSB7XG4gIHJldHVybiBjbGVhclRpbWVvdXQoaWQpO1xufSAvLyBGaXhlZCAjOTczOlxuXG5cbmlmIChkb2N1bWVudEV4aXN0cykge1xuICBvbihkb2N1bWVudCwgJ3RvdWNobW92ZScsIGZ1bmN0aW9uIChldnQpIHtcbiAgICBpZiAoKFNvcnRhYmxlLmFjdGl2ZSB8fCBhd2FpdGluZ0RyYWdTdGFydGVkKSAmJiBldnQuY2FuY2VsYWJsZSkge1xuICAgICAgZXZ0LnByZXZlbnREZWZhdWx0KCk7XG4gICAgfVxuICB9KTtcbn0gLy8gRXhwb3J0IHV0aWxzXG5cblxuU29ydGFibGUudXRpbHMgPSB7XG4gIG9uOiBvbixcbiAgb2ZmOiBvZmYsXG4gIGNzczogY3NzLFxuICBmaW5kOiBmaW5kLFxuICBpczogZnVuY3Rpb24gaXMoZWwsIHNlbGVjdG9yKSB7XG4gICAgcmV0dXJuICEhY2xvc2VzdChlbCwgc2VsZWN0b3IsIGVsLCBmYWxzZSk7XG4gIH0sXG4gIGV4dGVuZDogZXh0ZW5kLFxuICB0aHJvdHRsZTogdGhyb3R0bGUsXG4gIGNsb3Nlc3Q6IGNsb3Nlc3QsXG4gIHRvZ2dsZUNsYXNzOiB0b2dnbGVDbGFzcyxcbiAgY2xvbmU6IGNsb25lLFxuICBpbmRleDogaW5kZXgsXG4gIG5leHRUaWNrOiBfbmV4dFRpY2ssXG4gIGNhbmNlbE5leHRUaWNrOiBfY2FuY2VsTmV4dFRpY2ssXG4gIGRldGVjdERpcmVjdGlvbjogX2RldGVjdERpcmVjdGlvbixcbiAgZ2V0Q2hpbGQ6IGdldENoaWxkXG59O1xuLyoqXG4gKiBHZXQgdGhlIFNvcnRhYmxlIGluc3RhbmNlIG9mIGFuIGVsZW1lbnRcbiAqIEBwYXJhbSAge0hUTUxFbGVtZW50fSBlbGVtZW50IFRoZSBlbGVtZW50XG4gKiBAcmV0dXJuIHtTb3J0YWJsZXx1bmRlZmluZWR9ICAgICAgICAgVGhlIGluc3RhbmNlIG9mIFNvcnRhYmxlXG4gKi9cblxuU29ydGFibGUuZ2V0ID0gZnVuY3Rpb24gKGVsZW1lbnQpIHtcbiAgcmV0dXJuIGVsZW1lbnRbZXhwYW5kb107XG59O1xuLyoqXG4gKiBNb3VudCBhIHBsdWdpbiB0byBTb3J0YWJsZVxuICogQHBhcmFtICB7Li4uU29ydGFibGVQbHVnaW58U29ydGFibGVQbHVnaW5bXX0gcGx1Z2lucyAgICAgICBQbHVnaW5zIGJlaW5nIG1vdW50ZWRcbiAqL1xuXG5cblNvcnRhYmxlLm1vdW50ID0gZnVuY3Rpb24gKCkge1xuICBmb3IgKHZhciBfbGVuID0gYXJndW1lbnRzLmxlbmd0aCwgcGx1Z2lucyA9IG5ldyBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICBwbHVnaW5zW19rZXldID0gYXJndW1lbnRzW19rZXldO1xuICB9XG5cbiAgaWYgKHBsdWdpbnNbMF0uY29uc3RydWN0b3IgPT09IEFycmF5KSBwbHVnaW5zID0gcGx1Z2luc1swXTtcbiAgcGx1Z2lucy5mb3JFYWNoKGZ1bmN0aW9uIChwbHVnaW4pIHtcbiAgICBpZiAoIXBsdWdpbi5wcm90b3R5cGUgfHwgIXBsdWdpbi5wcm90b3R5cGUuY29uc3RydWN0b3IpIHtcbiAgICAgIHRocm93IFwiU29ydGFibGU6IE1vdW50ZWQgcGx1Z2luIG11c3QgYmUgYSBjb25zdHJ1Y3RvciBmdW5jdGlvbiwgbm90IFwiLmNvbmNhdCh7fS50b1N0cmluZy5jYWxsKHBsdWdpbikpO1xuICAgIH1cblxuICAgIGlmIChwbHVnaW4udXRpbHMpIFNvcnRhYmxlLnV0aWxzID0gX29iamVjdFNwcmVhZCh7fSwgU29ydGFibGUudXRpbHMsIHBsdWdpbi51dGlscyk7XG4gICAgUGx1Z2luTWFuYWdlci5tb3VudChwbHVnaW4pO1xuICB9KTtcbn07XG4vKipcbiAqIENyZWF0ZSBzb3J0YWJsZSBpbnN0YW5jZVxuICogQHBhcmFtIHtIVE1MRWxlbWVudH0gIGVsXG4gKiBAcGFyYW0ge09iamVjdH0gICAgICBbb3B0aW9uc11cbiAqL1xuXG5cblNvcnRhYmxlLmNyZWF0ZSA9IGZ1bmN0aW9uIChlbCwgb3B0aW9ucykge1xuICByZXR1cm4gbmV3IFNvcnRhYmxlKGVsLCBvcHRpb25zKTtcbn07IC8vIEV4cG9ydFxuXG5cblNvcnRhYmxlLnZlcnNpb24gPSB2ZXJzaW9uO1xuXG52YXIgYXV0b1Njcm9sbHMgPSBbXSxcbiAgICBzY3JvbGxFbCxcbiAgICBzY3JvbGxSb290RWwsXG4gICAgc2Nyb2xsaW5nID0gZmFsc2UsXG4gICAgbGFzdEF1dG9TY3JvbGxYLFxuICAgIGxhc3RBdXRvU2Nyb2xsWSxcbiAgICB0b3VjaEV2dCQxLFxuICAgIHBvaW50ZXJFbGVtQ2hhbmdlZEludGVydmFsO1xuXG5mdW5jdGlvbiBBdXRvU2Nyb2xsUGx1Z2luKCkge1xuICBmdW5jdGlvbiBBdXRvU2Nyb2xsKCkge1xuICAgIHRoaXMuZGVmYXVsdHMgPSB7XG4gICAgICBzY3JvbGw6IHRydWUsXG4gICAgICBzY3JvbGxTZW5zaXRpdml0eTogMzAsXG4gICAgICBzY3JvbGxTcGVlZDogMTAsXG4gICAgICBidWJibGVTY3JvbGw6IHRydWVcbiAgICB9OyAvLyBCaW5kIGFsbCBwcml2YXRlIG1ldGhvZHNcblxuICAgIGZvciAodmFyIGZuIGluIHRoaXMpIHtcbiAgICAgIGlmIChmbi5jaGFyQXQoMCkgPT09ICdfJyAmJiB0eXBlb2YgdGhpc1tmbl0gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgdGhpc1tmbl0gPSB0aGlzW2ZuXS5iaW5kKHRoaXMpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIEF1dG9TY3JvbGwucHJvdG90eXBlID0ge1xuICAgIGRyYWdTdGFydGVkOiBmdW5jdGlvbiBkcmFnU3RhcnRlZChfcmVmKSB7XG4gICAgICB2YXIgb3JpZ2luYWxFdmVudCA9IF9yZWYub3JpZ2luYWxFdmVudDtcblxuICAgICAgaWYgKHRoaXMuc29ydGFibGUubmF0aXZlRHJhZ2dhYmxlKSB7XG4gICAgICAgIG9uKGRvY3VtZW50LCAnZHJhZ292ZXInLCB0aGlzLl9oYW5kbGVBdXRvU2Nyb2xsKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGlmICh0aGlzLm9wdGlvbnMuc3VwcG9ydFBvaW50ZXIpIHtcbiAgICAgICAgICBvbihkb2N1bWVudCwgJ3BvaW50ZXJtb3ZlJywgdGhpcy5faGFuZGxlRmFsbGJhY2tBdXRvU2Nyb2xsKTtcbiAgICAgICAgfSBlbHNlIGlmIChvcmlnaW5hbEV2ZW50LnRvdWNoZXMpIHtcbiAgICAgICAgICBvbihkb2N1bWVudCwgJ3RvdWNobW92ZScsIHRoaXMuX2hhbmRsZUZhbGxiYWNrQXV0b1Njcm9sbCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb24oZG9jdW1lbnQsICdtb3VzZW1vdmUnLCB0aGlzLl9oYW5kbGVGYWxsYmFja0F1dG9TY3JvbGwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBkcmFnT3ZlckNvbXBsZXRlZDogZnVuY3Rpb24gZHJhZ092ZXJDb21wbGV0ZWQoX3JlZjIpIHtcbiAgICAgIHZhciBvcmlnaW5hbEV2ZW50ID0gX3JlZjIub3JpZ2luYWxFdmVudDtcblxuICAgICAgLy8gRm9yIHdoZW4gYnViYmxpbmcgaXMgY2FuY2VsZWQgYW5kIHVzaW5nIGZhbGxiYWNrIChmYWxsYmFjayAndG91Y2htb3ZlJyBhbHdheXMgcmVhY2hlZClcbiAgICAgIGlmICghdGhpcy5vcHRpb25zLmRyYWdPdmVyQnViYmxlICYmICFvcmlnaW5hbEV2ZW50LnJvb3RFbCkge1xuICAgICAgICB0aGlzLl9oYW5kbGVBdXRvU2Nyb2xsKG9yaWdpbmFsRXZlbnQpO1xuICAgICAgfVxuICAgIH0sXG4gICAgZHJvcDogZnVuY3Rpb24gZHJvcCgpIHtcbiAgICAgIGlmICh0aGlzLnNvcnRhYmxlLm5hdGl2ZURyYWdnYWJsZSkge1xuICAgICAgICBvZmYoZG9jdW1lbnQsICdkcmFnb3ZlcicsIHRoaXMuX2hhbmRsZUF1dG9TY3JvbGwpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb2ZmKGRvY3VtZW50LCAncG9pbnRlcm1vdmUnLCB0aGlzLl9oYW5kbGVGYWxsYmFja0F1dG9TY3JvbGwpO1xuICAgICAgICBvZmYoZG9jdW1lbnQsICd0b3VjaG1vdmUnLCB0aGlzLl9oYW5kbGVGYWxsYmFja0F1dG9TY3JvbGwpO1xuICAgICAgICBvZmYoZG9jdW1lbnQsICdtb3VzZW1vdmUnLCB0aGlzLl9oYW5kbGVGYWxsYmFja0F1dG9TY3JvbGwpO1xuICAgICAgfVxuXG4gICAgICBjbGVhclBvaW50ZXJFbGVtQ2hhbmdlZEludGVydmFsKCk7XG4gICAgICBjbGVhckF1dG9TY3JvbGxzKCk7XG4gICAgICBjYW5jZWxUaHJvdHRsZSgpO1xuICAgIH0sXG4gICAgbnVsbGluZzogZnVuY3Rpb24gbnVsbGluZygpIHtcbiAgICAgIHRvdWNoRXZ0JDEgPSBzY3JvbGxSb290RWwgPSBzY3JvbGxFbCA9IHNjcm9sbGluZyA9IHBvaW50ZXJFbGVtQ2hhbmdlZEludGVydmFsID0gbGFzdEF1dG9TY3JvbGxYID0gbGFzdEF1dG9TY3JvbGxZID0gbnVsbDtcbiAgICAgIGF1dG9TY3JvbGxzLmxlbmd0aCA9IDA7XG4gICAgfSxcbiAgICBfaGFuZGxlRmFsbGJhY2tBdXRvU2Nyb2xsOiBmdW5jdGlvbiBfaGFuZGxlRmFsbGJhY2tBdXRvU2Nyb2xsKGV2dCkge1xuICAgICAgdGhpcy5faGFuZGxlQXV0b1Njcm9sbChldnQsIHRydWUpO1xuICAgIH0sXG4gICAgX2hhbmRsZUF1dG9TY3JvbGw6IGZ1bmN0aW9uIF9oYW5kbGVBdXRvU2Nyb2xsKGV2dCwgZmFsbGJhY2spIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIHZhciB4ID0gKGV2dC50b3VjaGVzID8gZXZ0LnRvdWNoZXNbMF0gOiBldnQpLmNsaWVudFgsXG4gICAgICAgICAgeSA9IChldnQudG91Y2hlcyA/IGV2dC50b3VjaGVzWzBdIDogZXZ0KS5jbGllbnRZLFxuICAgICAgICAgIGVsZW0gPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHgsIHkpO1xuICAgICAgdG91Y2hFdnQkMSA9IGV2dDsgLy8gSUUgZG9lcyBub3Qgc2VlbSB0byBoYXZlIG5hdGl2ZSBhdXRvc2Nyb2xsLFxuICAgICAgLy8gRWRnZSdzIGF1dG9zY3JvbGwgc2VlbXMgdG9vIGNvbmRpdGlvbmFsLFxuICAgICAgLy8gTUFDT1MgU2FmYXJpIGRvZXMgbm90IGhhdmUgYXV0b3Njcm9sbCxcbiAgICAgIC8vIEZpcmVmb3ggYW5kIENocm9tZSBhcmUgZ29vZFxuXG4gICAgICBpZiAoZmFsbGJhY2sgfHwgRWRnZSB8fCBJRTExT3JMZXNzIHx8IFNhZmFyaSkge1xuICAgICAgICBhdXRvU2Nyb2xsKGV2dCwgdGhpcy5vcHRpb25zLCBlbGVtLCBmYWxsYmFjayk7IC8vIExpc3RlbmVyIGZvciBwb2ludGVyIGVsZW1lbnQgY2hhbmdlXG5cbiAgICAgICAgdmFyIG9nRWxlbVNjcm9sbGVyID0gZ2V0UGFyZW50QXV0b1Njcm9sbEVsZW1lbnQoZWxlbSwgdHJ1ZSk7XG5cbiAgICAgICAgaWYgKHNjcm9sbGluZyAmJiAoIXBvaW50ZXJFbGVtQ2hhbmdlZEludGVydmFsIHx8IHggIT09IGxhc3RBdXRvU2Nyb2xsWCB8fCB5ICE9PSBsYXN0QXV0b1Njcm9sbFkpKSB7XG4gICAgICAgICAgcG9pbnRlckVsZW1DaGFuZ2VkSW50ZXJ2YWwgJiYgY2xlYXJQb2ludGVyRWxlbUNoYW5nZWRJbnRlcnZhbCgpOyAvLyBEZXRlY3QgZm9yIHBvaW50ZXIgZWxlbSBjaGFuZ2UsIGVtdWxhdGluZyBuYXRpdmUgRG5EIGJlaGF2aW91clxuXG4gICAgICAgICAgcG9pbnRlckVsZW1DaGFuZ2VkSW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgICB2YXIgbmV3RWxlbSA9IGdldFBhcmVudEF1dG9TY3JvbGxFbGVtZW50KGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoeCwgeSksIHRydWUpO1xuXG4gICAgICAgICAgICBpZiAobmV3RWxlbSAhPT0gb2dFbGVtU2Nyb2xsZXIpIHtcbiAgICAgICAgICAgICAgb2dFbGVtU2Nyb2xsZXIgPSBuZXdFbGVtO1xuICAgICAgICAgICAgICBjbGVhckF1dG9TY3JvbGxzKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGF1dG9TY3JvbGwoZXZ0LCBfdGhpcy5vcHRpb25zLCBuZXdFbGVtLCBmYWxsYmFjayk7XG4gICAgICAgICAgfSwgMTApO1xuICAgICAgICAgIGxhc3RBdXRvU2Nyb2xsWCA9IHg7XG4gICAgICAgICAgbGFzdEF1dG9TY3JvbGxZID0geTtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaWYgRG5EIGlzIGVuYWJsZWQgKGFuZCBicm93c2VyIGhhcyBnb29kIGF1dG9zY3JvbGxpbmcpLCBmaXJzdCBhdXRvc2Nyb2xsIHdpbGwgYWxyZWFkeSBzY3JvbGwsIHNvIGdldCBwYXJlbnQgYXV0b3Njcm9sbCBvZiBmaXJzdCBhdXRvc2Nyb2xsXG4gICAgICAgIGlmICghdGhpcy5vcHRpb25zLmJ1YmJsZVNjcm9sbCB8fCBnZXRQYXJlbnRBdXRvU2Nyb2xsRWxlbWVudChlbGVtLCB0cnVlKSA9PT0gZ2V0V2luZG93U2Nyb2xsaW5nRWxlbWVudCgpKSB7XG4gICAgICAgICAgY2xlYXJBdXRvU2Nyb2xscygpO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGF1dG9TY3JvbGwoZXZ0LCB0aGlzLm9wdGlvbnMsIGdldFBhcmVudEF1dG9TY3JvbGxFbGVtZW50KGVsZW0sIGZhbHNlKSwgZmFsc2UpO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgcmV0dXJuIF9leHRlbmRzKEF1dG9TY3JvbGwsIHtcbiAgICBwbHVnaW5OYW1lOiAnc2Nyb2xsJyxcbiAgICBpbml0aWFsaXplQnlEZWZhdWx0OiB0cnVlXG4gIH0pO1xufVxuXG5mdW5jdGlvbiBjbGVhckF1dG9TY3JvbGxzKCkge1xuICBhdXRvU2Nyb2xscy5mb3JFYWNoKGZ1bmN0aW9uIChhdXRvU2Nyb2xsKSB7XG4gICAgY2xlYXJJbnRlcnZhbChhdXRvU2Nyb2xsLnBpZCk7XG4gIH0pO1xuICBhdXRvU2Nyb2xscyA9IFtdO1xufVxuXG5mdW5jdGlvbiBjbGVhclBvaW50ZXJFbGVtQ2hhbmdlZEludGVydmFsKCkge1xuICBjbGVhckludGVydmFsKHBvaW50ZXJFbGVtQ2hhbmdlZEludGVydmFsKTtcbn1cblxudmFyIGF1dG9TY3JvbGwgPSB0aHJvdHRsZShmdW5jdGlvbiAoZXZ0LCBvcHRpb25zLCByb290RWwsIGlzRmFsbGJhY2spIHtcbiAgLy8gQnVnOiBodHRwczovL2J1Z3ppbGxhLm1vemlsbGEub3JnL3Nob3dfYnVnLmNnaT9pZD01MDU1MjFcbiAgaWYgKCFvcHRpb25zLnNjcm9sbCkgcmV0dXJuO1xuICB2YXIgeCA9IChldnQudG91Y2hlcyA/IGV2dC50b3VjaGVzWzBdIDogZXZ0KS5jbGllbnRYLFxuICAgICAgeSA9IChldnQudG91Y2hlcyA/IGV2dC50b3VjaGVzWzBdIDogZXZ0KS5jbGllbnRZLFxuICAgICAgc2VucyA9IG9wdGlvbnMuc2Nyb2xsU2Vuc2l0aXZpdHksXG4gICAgICBzcGVlZCA9IG9wdGlvbnMuc2Nyb2xsU3BlZWQsXG4gICAgICB3aW5TY3JvbGxlciA9IGdldFdpbmRvd1Njcm9sbGluZ0VsZW1lbnQoKTtcbiAgdmFyIHNjcm9sbFRoaXNJbnN0YW5jZSA9IGZhbHNlLFxuICAgICAgc2Nyb2xsQ3VzdG9tRm47IC8vIE5ldyBzY3JvbGwgcm9vdCwgc2V0IHNjcm9sbEVsXG5cbiAgaWYgKHNjcm9sbFJvb3RFbCAhPT0gcm9vdEVsKSB7XG4gICAgc2Nyb2xsUm9vdEVsID0gcm9vdEVsO1xuICAgIGNsZWFyQXV0b1Njcm9sbHMoKTtcbiAgICBzY3JvbGxFbCA9IG9wdGlvbnMuc2Nyb2xsO1xuICAgIHNjcm9sbEN1c3RvbUZuID0gb3B0aW9ucy5zY3JvbGxGbjtcblxuICAgIGlmIChzY3JvbGxFbCA9PT0gdHJ1ZSkge1xuICAgICAgc2Nyb2xsRWwgPSBnZXRQYXJlbnRBdXRvU2Nyb2xsRWxlbWVudChyb290RWwsIHRydWUpO1xuICAgIH1cbiAgfVxuXG4gIHZhciBsYXllcnNPdXQgPSAwO1xuICB2YXIgY3VycmVudFBhcmVudCA9IHNjcm9sbEVsO1xuXG4gIGRvIHtcbiAgICB2YXIgZWwgPSBjdXJyZW50UGFyZW50LFxuICAgICAgICByZWN0ID0gZ2V0UmVjdChlbCksXG4gICAgICAgIHRvcCA9IHJlY3QudG9wLFxuICAgICAgICBib3R0b20gPSByZWN0LmJvdHRvbSxcbiAgICAgICAgbGVmdCA9IHJlY3QubGVmdCxcbiAgICAgICAgcmlnaHQgPSByZWN0LnJpZ2h0LFxuICAgICAgICB3aWR0aCA9IHJlY3Qud2lkdGgsXG4gICAgICAgIGhlaWdodCA9IHJlY3QuaGVpZ2h0LFxuICAgICAgICBjYW5TY3JvbGxYID0gdm9pZCAwLFxuICAgICAgICBjYW5TY3JvbGxZID0gdm9pZCAwLFxuICAgICAgICBzY3JvbGxXaWR0aCA9IGVsLnNjcm9sbFdpZHRoLFxuICAgICAgICBzY3JvbGxIZWlnaHQgPSBlbC5zY3JvbGxIZWlnaHQsXG4gICAgICAgIGVsQ1NTID0gY3NzKGVsKSxcbiAgICAgICAgc2Nyb2xsUG9zWCA9IGVsLnNjcm9sbExlZnQsXG4gICAgICAgIHNjcm9sbFBvc1kgPSBlbC5zY3JvbGxUb3A7XG5cbiAgICBpZiAoZWwgPT09IHdpblNjcm9sbGVyKSB7XG4gICAgICBjYW5TY3JvbGxYID0gd2lkdGggPCBzY3JvbGxXaWR0aCAmJiAoZWxDU1Mub3ZlcmZsb3dYID09PSAnYXV0bycgfHwgZWxDU1Mub3ZlcmZsb3dYID09PSAnc2Nyb2xsJyB8fCBlbENTUy5vdmVyZmxvd1ggPT09ICd2aXNpYmxlJyk7XG4gICAgICBjYW5TY3JvbGxZID0gaGVpZ2h0IDwgc2Nyb2xsSGVpZ2h0ICYmIChlbENTUy5vdmVyZmxvd1kgPT09ICdhdXRvJyB8fCBlbENTUy5vdmVyZmxvd1kgPT09ICdzY3JvbGwnIHx8IGVsQ1NTLm92ZXJmbG93WSA9PT0gJ3Zpc2libGUnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgY2FuU2Nyb2xsWCA9IHdpZHRoIDwgc2Nyb2xsV2lkdGggJiYgKGVsQ1NTLm92ZXJmbG93WCA9PT0gJ2F1dG8nIHx8IGVsQ1NTLm92ZXJmbG93WCA9PT0gJ3Njcm9sbCcpO1xuICAgICAgY2FuU2Nyb2xsWSA9IGhlaWdodCA8IHNjcm9sbEhlaWdodCAmJiAoZWxDU1Mub3ZlcmZsb3dZID09PSAnYXV0bycgfHwgZWxDU1Mub3ZlcmZsb3dZID09PSAnc2Nyb2xsJyk7XG4gICAgfVxuXG4gICAgdmFyIHZ4ID0gY2FuU2Nyb2xsWCAmJiAoTWF0aC5hYnMocmlnaHQgLSB4KSA8PSBzZW5zICYmIHNjcm9sbFBvc1ggKyB3aWR0aCA8IHNjcm9sbFdpZHRoKSAtIChNYXRoLmFicyhsZWZ0IC0geCkgPD0gc2VucyAmJiAhIXNjcm9sbFBvc1gpO1xuICAgIHZhciB2eSA9IGNhblNjcm9sbFkgJiYgKE1hdGguYWJzKGJvdHRvbSAtIHkpIDw9IHNlbnMgJiYgc2Nyb2xsUG9zWSArIGhlaWdodCA8IHNjcm9sbEhlaWdodCkgLSAoTWF0aC5hYnModG9wIC0geSkgPD0gc2VucyAmJiAhIXNjcm9sbFBvc1kpO1xuXG4gICAgaWYgKCFhdXRvU2Nyb2xsc1tsYXllcnNPdXRdKSB7XG4gICAgICBmb3IgKHZhciBpID0gMDsgaSA8PSBsYXllcnNPdXQ7IGkrKykge1xuICAgICAgICBpZiAoIWF1dG9TY3JvbGxzW2ldKSB7XG4gICAgICAgICAgYXV0b1Njcm9sbHNbaV0gPSB7fTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChhdXRvU2Nyb2xsc1tsYXllcnNPdXRdLnZ4ICE9IHZ4IHx8IGF1dG9TY3JvbGxzW2xheWVyc091dF0udnkgIT0gdnkgfHwgYXV0b1Njcm9sbHNbbGF5ZXJzT3V0XS5lbCAhPT0gZWwpIHtcbiAgICAgIGF1dG9TY3JvbGxzW2xheWVyc091dF0uZWwgPSBlbDtcbiAgICAgIGF1dG9TY3JvbGxzW2xheWVyc091dF0udnggPSB2eDtcbiAgICAgIGF1dG9TY3JvbGxzW2xheWVyc091dF0udnkgPSB2eTtcbiAgICAgIGNsZWFySW50ZXJ2YWwoYXV0b1Njcm9sbHNbbGF5ZXJzT3V0XS5waWQpO1xuXG4gICAgICBpZiAodnggIT0gMCB8fCB2eSAhPSAwKSB7XG4gICAgICAgIHNjcm9sbFRoaXNJbnN0YW5jZSA9IHRydWU7XG4gICAgICAgIC8qIGpzaGludCBsb29wZnVuYzp0cnVlICovXG5cbiAgICAgICAgYXV0b1Njcm9sbHNbbGF5ZXJzT3V0XS5waWQgPSBzZXRJbnRlcnZhbChmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgLy8gZW11bGF0ZSBkcmFnIG92ZXIgZHVyaW5nIGF1dG9zY3JvbGwgKGZhbGxiYWNrKSwgZW11bGF0aW5nIG5hdGl2ZSBEbkQgYmVoYXZpb3VyXG4gICAgICAgICAgaWYgKGlzRmFsbGJhY2sgJiYgdGhpcy5sYXllciA9PT0gMCkge1xuICAgICAgICAgICAgU29ydGFibGUuYWN0aXZlLl9vblRvdWNoTW92ZSh0b3VjaEV2dCQxKTsgLy8gVG8gbW92ZSBnaG9zdCBpZiBpdCBpcyBwb3NpdGlvbmVkIGFic29sdXRlbHlcblxuICAgICAgICAgIH1cblxuICAgICAgICAgIHZhciBzY3JvbGxPZmZzZXRZID0gYXV0b1Njcm9sbHNbdGhpcy5sYXllcl0udnkgPyBhdXRvU2Nyb2xsc1t0aGlzLmxheWVyXS52eSAqIHNwZWVkIDogMDtcbiAgICAgICAgICB2YXIgc2Nyb2xsT2Zmc2V0WCA9IGF1dG9TY3JvbGxzW3RoaXMubGF5ZXJdLnZ4ID8gYXV0b1Njcm9sbHNbdGhpcy5sYXllcl0udnggKiBzcGVlZCA6IDA7XG5cbiAgICAgICAgICBpZiAodHlwZW9mIHNjcm9sbEN1c3RvbUZuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBpZiAoc2Nyb2xsQ3VzdG9tRm4uY2FsbChTb3J0YWJsZS5kcmFnZ2VkLnBhcmVudE5vZGVbZXhwYW5kb10sIHNjcm9sbE9mZnNldFgsIHNjcm9sbE9mZnNldFksIGV2dCwgdG91Y2hFdnQkMSwgYXV0b1Njcm9sbHNbdGhpcy5sYXllcl0uZWwpICE9PSAnY29udGludWUnKSB7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBzY3JvbGxCeShhdXRvU2Nyb2xsc1t0aGlzLmxheWVyXS5lbCwgc2Nyb2xsT2Zmc2V0WCwgc2Nyb2xsT2Zmc2V0WSk7XG4gICAgICAgIH0uYmluZCh7XG4gICAgICAgICAgbGF5ZXI6IGxheWVyc091dFxuICAgICAgICB9KSwgMjQpO1xuICAgICAgfVxuICAgIH1cblxuICAgIGxheWVyc091dCsrO1xuICB9IHdoaWxlIChvcHRpb25zLmJ1YmJsZVNjcm9sbCAmJiBjdXJyZW50UGFyZW50ICE9PSB3aW5TY3JvbGxlciAmJiAoY3VycmVudFBhcmVudCA9IGdldFBhcmVudEF1dG9TY3JvbGxFbGVtZW50KGN1cnJlbnRQYXJlbnQsIGZhbHNlKSkpO1xuXG4gIHNjcm9sbGluZyA9IHNjcm9sbFRoaXNJbnN0YW5jZTsgLy8gaW4gY2FzZSBhbm90aGVyIGZ1bmN0aW9uIGNhdGNoZXMgc2Nyb2xsaW5nIGFzIGZhbHNlIGluIGJldHdlZW4gd2hlbiBpdCBpcyBub3Rcbn0sIDMwKTtcblxudmFyIGRyb3AgPSBmdW5jdGlvbiBkcm9wKF9yZWYpIHtcbiAgdmFyIG9yaWdpbmFsRXZlbnQgPSBfcmVmLm9yaWdpbmFsRXZlbnQsXG4gICAgICBwdXRTb3J0YWJsZSA9IF9yZWYucHV0U29ydGFibGUsXG4gICAgICBkcmFnRWwgPSBfcmVmLmRyYWdFbCxcbiAgICAgIGFjdGl2ZVNvcnRhYmxlID0gX3JlZi5hY3RpdmVTb3J0YWJsZSxcbiAgICAgIGRpc3BhdGNoU29ydGFibGVFdmVudCA9IF9yZWYuZGlzcGF0Y2hTb3J0YWJsZUV2ZW50LFxuICAgICAgaGlkZUdob3N0Rm9yVGFyZ2V0ID0gX3JlZi5oaWRlR2hvc3RGb3JUYXJnZXQsXG4gICAgICB1bmhpZGVHaG9zdEZvclRhcmdldCA9IF9yZWYudW5oaWRlR2hvc3RGb3JUYXJnZXQ7XG4gIGlmICghb3JpZ2luYWxFdmVudCkgcmV0dXJuO1xuICB2YXIgdG9Tb3J0YWJsZSA9IHB1dFNvcnRhYmxlIHx8IGFjdGl2ZVNvcnRhYmxlO1xuICBoaWRlR2hvc3RGb3JUYXJnZXQoKTtcbiAgdmFyIHRvdWNoID0gb3JpZ2luYWxFdmVudC5jaGFuZ2VkVG91Y2hlcyAmJiBvcmlnaW5hbEV2ZW50LmNoYW5nZWRUb3VjaGVzLmxlbmd0aCA/IG9yaWdpbmFsRXZlbnQuY2hhbmdlZFRvdWNoZXNbMF0gOiBvcmlnaW5hbEV2ZW50O1xuICB2YXIgdGFyZ2V0ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludCh0b3VjaC5jbGllbnRYLCB0b3VjaC5jbGllbnRZKTtcbiAgdW5oaWRlR2hvc3RGb3JUYXJnZXQoKTtcblxuICBpZiAodG9Tb3J0YWJsZSAmJiAhdG9Tb3J0YWJsZS5lbC5jb250YWlucyh0YXJnZXQpKSB7XG4gICAgZGlzcGF0Y2hTb3J0YWJsZUV2ZW50KCdzcGlsbCcpO1xuICAgIHRoaXMub25TcGlsbCh7XG4gICAgICBkcmFnRWw6IGRyYWdFbCxcbiAgICAgIHB1dFNvcnRhYmxlOiBwdXRTb3J0YWJsZVxuICAgIH0pO1xuICB9XG59O1xuXG5mdW5jdGlvbiBSZXZlcnQoKSB7fVxuXG5SZXZlcnQucHJvdG90eXBlID0ge1xuICBzdGFydEluZGV4OiBudWxsLFxuICBkcmFnU3RhcnQ6IGZ1bmN0aW9uIGRyYWdTdGFydChfcmVmMikge1xuICAgIHZhciBvbGREcmFnZ2FibGVJbmRleCA9IF9yZWYyLm9sZERyYWdnYWJsZUluZGV4O1xuICAgIHRoaXMuc3RhcnRJbmRleCA9IG9sZERyYWdnYWJsZUluZGV4O1xuICB9LFxuICBvblNwaWxsOiBmdW5jdGlvbiBvblNwaWxsKF9yZWYzKSB7XG4gICAgdmFyIGRyYWdFbCA9IF9yZWYzLmRyYWdFbCxcbiAgICAgICAgcHV0U29ydGFibGUgPSBfcmVmMy5wdXRTb3J0YWJsZTtcbiAgICB0aGlzLnNvcnRhYmxlLmNhcHR1cmVBbmltYXRpb25TdGF0ZSgpO1xuXG4gICAgaWYgKHB1dFNvcnRhYmxlKSB7XG4gICAgICBwdXRTb3J0YWJsZS5jYXB0dXJlQW5pbWF0aW9uU3RhdGUoKTtcbiAgICB9XG5cbiAgICB2YXIgbmV4dFNpYmxpbmcgPSBnZXRDaGlsZCh0aGlzLnNvcnRhYmxlLmVsLCB0aGlzLnN0YXJ0SW5kZXgsIHRoaXMub3B0aW9ucyk7XG5cbiAgICBpZiAobmV4dFNpYmxpbmcpIHtcbiAgICAgIHRoaXMuc29ydGFibGUuZWwuaW5zZXJ0QmVmb3JlKGRyYWdFbCwgbmV4dFNpYmxpbmcpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnNvcnRhYmxlLmVsLmFwcGVuZENoaWxkKGRyYWdFbCk7XG4gICAgfVxuXG4gICAgdGhpcy5zb3J0YWJsZS5hbmltYXRlQWxsKCk7XG5cbiAgICBpZiAocHV0U29ydGFibGUpIHtcbiAgICAgIHB1dFNvcnRhYmxlLmFuaW1hdGVBbGwoKTtcbiAgICB9XG4gIH0sXG4gIGRyb3A6IGRyb3Bcbn07XG5cbl9leHRlbmRzKFJldmVydCwge1xuICBwbHVnaW5OYW1lOiAncmV2ZXJ0T25TcGlsbCdcbn0pO1xuXG5mdW5jdGlvbiBSZW1vdmUoKSB7fVxuXG5SZW1vdmUucHJvdG90eXBlID0ge1xuICBvblNwaWxsOiBmdW5jdGlvbiBvblNwaWxsKF9yZWY0KSB7XG4gICAgdmFyIGRyYWdFbCA9IF9yZWY0LmRyYWdFbCxcbiAgICAgICAgcHV0U29ydGFibGUgPSBfcmVmNC5wdXRTb3J0YWJsZTtcbiAgICB2YXIgcGFyZW50U29ydGFibGUgPSBwdXRTb3J0YWJsZSB8fCB0aGlzLnNvcnRhYmxlO1xuICAgIHBhcmVudFNvcnRhYmxlLmNhcHR1cmVBbmltYXRpb25TdGF0ZSgpO1xuICAgIGRyYWdFbC5wYXJlbnROb2RlICYmIGRyYWdFbC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGRyYWdFbCk7XG4gICAgcGFyZW50U29ydGFibGUuYW5pbWF0ZUFsbCgpO1xuICB9LFxuICBkcm9wOiBkcm9wXG59O1xuXG5fZXh0ZW5kcyhSZW1vdmUsIHtcbiAgcGx1Z2luTmFtZTogJ3JlbW92ZU9uU3BpbGwnXG59KTtcblxudmFyIGxhc3RTd2FwRWw7XG5cbmZ1bmN0aW9uIFN3YXBQbHVnaW4oKSB7XG4gIGZ1bmN0aW9uIFN3YXAoKSB7XG4gICAgdGhpcy5kZWZhdWx0cyA9IHtcbiAgICAgIHN3YXBDbGFzczogJ3NvcnRhYmxlLXN3YXAtaGlnaGxpZ2h0J1xuICAgIH07XG4gIH1cblxuICBTd2FwLnByb3RvdHlwZSA9IHtcbiAgICBkcmFnU3RhcnQ6IGZ1bmN0aW9uIGRyYWdTdGFydChfcmVmKSB7XG4gICAgICB2YXIgZHJhZ0VsID0gX3JlZi5kcmFnRWw7XG4gICAgICBsYXN0U3dhcEVsID0gZHJhZ0VsO1xuICAgIH0sXG4gICAgZHJhZ092ZXJWYWxpZDogZnVuY3Rpb24gZHJhZ092ZXJWYWxpZChfcmVmMikge1xuICAgICAgdmFyIGNvbXBsZXRlZCA9IF9yZWYyLmNvbXBsZXRlZCxcbiAgICAgICAgICB0YXJnZXQgPSBfcmVmMi50YXJnZXQsXG4gICAgICAgICAgb25Nb3ZlID0gX3JlZjIub25Nb3ZlLFxuICAgICAgICAgIGFjdGl2ZVNvcnRhYmxlID0gX3JlZjIuYWN0aXZlU29ydGFibGUsXG4gICAgICAgICAgY2hhbmdlZCA9IF9yZWYyLmNoYW5nZWQsXG4gICAgICAgICAgY2FuY2VsID0gX3JlZjIuY2FuY2VsO1xuICAgICAgaWYgKCFhY3RpdmVTb3J0YWJsZS5vcHRpb25zLnN3YXApIHJldHVybjtcbiAgICAgIHZhciBlbCA9IHRoaXMuc29ydGFibGUuZWwsXG4gICAgICAgICAgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcblxuICAgICAgaWYgKHRhcmdldCAmJiB0YXJnZXQgIT09IGVsKSB7XG4gICAgICAgIHZhciBwcmV2U3dhcEVsID0gbGFzdFN3YXBFbDtcblxuICAgICAgICBpZiAob25Nb3ZlKHRhcmdldCkgIT09IGZhbHNlKSB7XG4gICAgICAgICAgdG9nZ2xlQ2xhc3ModGFyZ2V0LCBvcHRpb25zLnN3YXBDbGFzcywgdHJ1ZSk7XG4gICAgICAgICAgbGFzdFN3YXBFbCA9IHRhcmdldDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsYXN0U3dhcEVsID0gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwcmV2U3dhcEVsICYmIHByZXZTd2FwRWwgIT09IGxhc3RTd2FwRWwpIHtcbiAgICAgICAgICB0b2dnbGVDbGFzcyhwcmV2U3dhcEVsLCBvcHRpb25zLnN3YXBDbGFzcywgZmFsc2UpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNoYW5nZWQoKTtcbiAgICAgIGNvbXBsZXRlZCh0cnVlKTtcbiAgICAgIGNhbmNlbCgpO1xuICAgIH0sXG4gICAgZHJvcDogZnVuY3Rpb24gZHJvcChfcmVmMykge1xuICAgICAgdmFyIGFjdGl2ZVNvcnRhYmxlID0gX3JlZjMuYWN0aXZlU29ydGFibGUsXG4gICAgICAgICAgcHV0U29ydGFibGUgPSBfcmVmMy5wdXRTb3J0YWJsZSxcbiAgICAgICAgICBkcmFnRWwgPSBfcmVmMy5kcmFnRWw7XG4gICAgICB2YXIgdG9Tb3J0YWJsZSA9IHB1dFNvcnRhYmxlIHx8IHRoaXMuc29ydGFibGU7XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucztcbiAgICAgIGxhc3RTd2FwRWwgJiYgdG9nZ2xlQ2xhc3MobGFzdFN3YXBFbCwgb3B0aW9ucy5zd2FwQ2xhc3MsIGZhbHNlKTtcblxuICAgICAgaWYgKGxhc3RTd2FwRWwgJiYgKG9wdGlvbnMuc3dhcCB8fCBwdXRTb3J0YWJsZSAmJiBwdXRTb3J0YWJsZS5vcHRpb25zLnN3YXApKSB7XG4gICAgICAgIGlmIChkcmFnRWwgIT09IGxhc3RTd2FwRWwpIHtcbiAgICAgICAgICB0b1NvcnRhYmxlLmNhcHR1cmVBbmltYXRpb25TdGF0ZSgpO1xuICAgICAgICAgIGlmICh0b1NvcnRhYmxlICE9PSBhY3RpdmVTb3J0YWJsZSkgYWN0aXZlU29ydGFibGUuY2FwdHVyZUFuaW1hdGlvblN0YXRlKCk7XG4gICAgICAgICAgc3dhcE5vZGVzKGRyYWdFbCwgbGFzdFN3YXBFbCk7XG4gICAgICAgICAgdG9Tb3J0YWJsZS5hbmltYXRlQWxsKCk7XG4gICAgICAgICAgaWYgKHRvU29ydGFibGUgIT09IGFjdGl2ZVNvcnRhYmxlKSBhY3RpdmVTb3J0YWJsZS5hbmltYXRlQWxsKCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9LFxuICAgIG51bGxpbmc6IGZ1bmN0aW9uIG51bGxpbmcoKSB7XG4gICAgICBsYXN0U3dhcEVsID0gbnVsbDtcbiAgICB9XG4gIH07XG4gIHJldHVybiBfZXh0ZW5kcyhTd2FwLCB7XG4gICAgcGx1Z2luTmFtZTogJ3N3YXAnLFxuICAgIGV2ZW50UHJvcGVydGllczogZnVuY3Rpb24gZXZlbnRQcm9wZXJ0aWVzKCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgc3dhcEl0ZW06IGxhc3RTd2FwRWxcbiAgICAgIH07XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gc3dhcE5vZGVzKG4xLCBuMikge1xuICB2YXIgcDEgPSBuMS5wYXJlbnROb2RlLFxuICAgICAgcDIgPSBuMi5wYXJlbnROb2RlLFxuICAgICAgaTEsXG4gICAgICBpMjtcbiAgaWYgKCFwMSB8fCAhcDIgfHwgcDEuaXNFcXVhbE5vZGUobjIpIHx8IHAyLmlzRXF1YWxOb2RlKG4xKSkgcmV0dXJuO1xuICBpMSA9IGluZGV4KG4xKTtcbiAgaTIgPSBpbmRleChuMik7XG5cbiAgaWYgKHAxLmlzRXF1YWxOb2RlKHAyKSAmJiBpMSA8IGkyKSB7XG4gICAgaTIrKztcbiAgfVxuXG4gIHAxLmluc2VydEJlZm9yZShuMiwgcDEuY2hpbGRyZW5baTFdKTtcbiAgcDIuaW5zZXJ0QmVmb3JlKG4xLCBwMi5jaGlsZHJlbltpMl0pO1xufVxuXG52YXIgbXVsdGlEcmFnRWxlbWVudHMgPSBbXSxcbiAgICBtdWx0aURyYWdDbG9uZXMgPSBbXSxcbiAgICBsYXN0TXVsdGlEcmFnU2VsZWN0LFxuICAgIC8vIGZvciBzZWxlY3Rpb24gd2l0aCBtb2RpZmllciBrZXkgZG93biAoU0hJRlQpXG5tdWx0aURyYWdTb3J0YWJsZSxcbiAgICBpbml0aWFsRm9sZGluZyA9IGZhbHNlLFxuICAgIC8vIEluaXRpYWwgbXVsdGktZHJhZyBmb2xkIHdoZW4gZHJhZyBzdGFydGVkXG5mb2xkaW5nID0gZmFsc2UsXG4gICAgLy8gRm9sZGluZyBhbnkgb3RoZXIgdGltZVxuZHJhZ1N0YXJ0ZWQgPSBmYWxzZSxcbiAgICBkcmFnRWwkMSxcbiAgICBjbG9uZXNGcm9tUmVjdCxcbiAgICBjbG9uZXNIaWRkZW47XG5cbmZ1bmN0aW9uIE11bHRpRHJhZ1BsdWdpbigpIHtcbiAgZnVuY3Rpb24gTXVsdGlEcmFnKHNvcnRhYmxlKSB7XG4gICAgLy8gQmluZCBhbGwgcHJpdmF0ZSBtZXRob2RzXG4gICAgZm9yICh2YXIgZm4gaW4gdGhpcykge1xuICAgICAgaWYgKGZuLmNoYXJBdCgwKSA9PT0gJ18nICYmIHR5cGVvZiB0aGlzW2ZuXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICB0aGlzW2ZuXSA9IHRoaXNbZm5dLmJpbmQodGhpcyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHNvcnRhYmxlLm9wdGlvbnMuc3VwcG9ydFBvaW50ZXIpIHtcbiAgICAgIG9uKGRvY3VtZW50LCAncG9pbnRlcnVwJywgdGhpcy5fZGVzZWxlY3RNdWx0aURyYWcpO1xuICAgIH0gZWxzZSB7XG4gICAgICBvbihkb2N1bWVudCwgJ21vdXNldXAnLCB0aGlzLl9kZXNlbGVjdE11bHRpRHJhZyk7XG4gICAgICBvbihkb2N1bWVudCwgJ3RvdWNoZW5kJywgdGhpcy5fZGVzZWxlY3RNdWx0aURyYWcpO1xuICAgIH1cblxuICAgIG9uKGRvY3VtZW50LCAna2V5ZG93bicsIHRoaXMuX2NoZWNrS2V5RG93bik7XG4gICAgb24oZG9jdW1lbnQsICdrZXl1cCcsIHRoaXMuX2NoZWNrS2V5VXApO1xuICAgIHRoaXMuZGVmYXVsdHMgPSB7XG4gICAgICBzZWxlY3RlZENsYXNzOiAnc29ydGFibGUtc2VsZWN0ZWQnLFxuICAgICAgbXVsdGlEcmFnS2V5OiBudWxsLFxuICAgICAgc2V0RGF0YTogZnVuY3Rpb24gc2V0RGF0YShkYXRhVHJhbnNmZXIsIGRyYWdFbCkge1xuICAgICAgICB2YXIgZGF0YSA9ICcnO1xuXG4gICAgICAgIGlmIChtdWx0aURyYWdFbGVtZW50cy5sZW5ndGggJiYgbXVsdGlEcmFnU29ydGFibGUgPT09IHNvcnRhYmxlKSB7XG4gICAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAobXVsdGlEcmFnRWxlbWVudCwgaSkge1xuICAgICAgICAgICAgZGF0YSArPSAoIWkgPyAnJyA6ICcsICcpICsgbXVsdGlEcmFnRWxlbWVudC50ZXh0Q29udGVudDtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkYXRhID0gZHJhZ0VsLnRleHRDb250ZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgZGF0YVRyYW5zZmVyLnNldERhdGEoJ1RleHQnLCBkYXRhKTtcbiAgICAgIH1cbiAgICB9O1xuICB9XG5cbiAgTXVsdGlEcmFnLnByb3RvdHlwZSA9IHtcbiAgICBtdWx0aURyYWdLZXlEb3duOiBmYWxzZSxcbiAgICBpc011bHRpRHJhZzogZmFsc2UsXG4gICAgZGVsYXlTdGFydEdsb2JhbDogZnVuY3Rpb24gZGVsYXlTdGFydEdsb2JhbChfcmVmKSB7XG4gICAgICB2YXIgZHJhZ2dlZCA9IF9yZWYuZHJhZ0VsO1xuICAgICAgZHJhZ0VsJDEgPSBkcmFnZ2VkO1xuICAgIH0sXG4gICAgZGVsYXlFbmRlZDogZnVuY3Rpb24gZGVsYXlFbmRlZCgpIHtcbiAgICAgIHRoaXMuaXNNdWx0aURyYWcgPSB+bXVsdGlEcmFnRWxlbWVudHMuaW5kZXhPZihkcmFnRWwkMSk7XG4gICAgfSxcbiAgICBzZXR1cENsb25lOiBmdW5jdGlvbiBzZXR1cENsb25lKF9yZWYyKSB7XG4gICAgICB2YXIgc29ydGFibGUgPSBfcmVmMi5zb3J0YWJsZSxcbiAgICAgICAgICBjYW5jZWwgPSBfcmVmMi5jYW5jZWw7XG4gICAgICBpZiAoIXRoaXMuaXNNdWx0aURyYWcpIHJldHVybjtcblxuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBtdWx0aURyYWdFbGVtZW50cy5sZW5ndGg7IGkrKykge1xuICAgICAgICBtdWx0aURyYWdDbG9uZXMucHVzaChjbG9uZShtdWx0aURyYWdFbGVtZW50c1tpXSkpO1xuICAgICAgICBtdWx0aURyYWdDbG9uZXNbaV0uc29ydGFibGVJbmRleCA9IG11bHRpRHJhZ0VsZW1lbnRzW2ldLnNvcnRhYmxlSW5kZXg7XG4gICAgICAgIG11bHRpRHJhZ0Nsb25lc1tpXS5kcmFnZ2FibGUgPSBmYWxzZTtcbiAgICAgICAgbXVsdGlEcmFnQ2xvbmVzW2ldLnN0eWxlWyd3aWxsLWNoYW5nZSddID0gJyc7XG4gICAgICAgIHRvZ2dsZUNsYXNzKG11bHRpRHJhZ0Nsb25lc1tpXSwgdGhpcy5vcHRpb25zLnNlbGVjdGVkQ2xhc3MsIGZhbHNlKTtcbiAgICAgICAgbXVsdGlEcmFnRWxlbWVudHNbaV0gPT09IGRyYWdFbCQxICYmIHRvZ2dsZUNsYXNzKG11bHRpRHJhZ0Nsb25lc1tpXSwgdGhpcy5vcHRpb25zLmNob3NlbkNsYXNzLCBmYWxzZSk7XG4gICAgICB9XG5cbiAgICAgIHNvcnRhYmxlLl9oaWRlQ2xvbmUoKTtcblxuICAgICAgY2FuY2VsKCk7XG4gICAgfSxcbiAgICBjbG9uZTogZnVuY3Rpb24gY2xvbmUoX3JlZjMpIHtcbiAgICAgIHZhciBzb3J0YWJsZSA9IF9yZWYzLnNvcnRhYmxlLFxuICAgICAgICAgIHJvb3RFbCA9IF9yZWYzLnJvb3RFbCxcbiAgICAgICAgICBkaXNwYXRjaFNvcnRhYmxlRXZlbnQgPSBfcmVmMy5kaXNwYXRjaFNvcnRhYmxlRXZlbnQsXG4gICAgICAgICAgY2FuY2VsID0gX3JlZjMuY2FuY2VsO1xuICAgICAgaWYgKCF0aGlzLmlzTXVsdGlEcmFnKSByZXR1cm47XG5cbiAgICAgIGlmICghdGhpcy5vcHRpb25zLnJlbW92ZUNsb25lT25IaWRlKSB7XG4gICAgICAgIGlmIChtdWx0aURyYWdFbGVtZW50cy5sZW5ndGggJiYgbXVsdGlEcmFnU29ydGFibGUgPT09IHNvcnRhYmxlKSB7XG4gICAgICAgICAgaW5zZXJ0TXVsdGlEcmFnQ2xvbmVzKHRydWUsIHJvb3RFbCk7XG4gICAgICAgICAgZGlzcGF0Y2hTb3J0YWJsZUV2ZW50KCdjbG9uZScpO1xuICAgICAgICAgIGNhbmNlbCgpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBzaG93Q2xvbmU6IGZ1bmN0aW9uIHNob3dDbG9uZShfcmVmNCkge1xuICAgICAgdmFyIGNsb25lTm93U2hvd24gPSBfcmVmNC5jbG9uZU5vd1Nob3duLFxuICAgICAgICAgIHJvb3RFbCA9IF9yZWY0LnJvb3RFbCxcbiAgICAgICAgICBjYW5jZWwgPSBfcmVmNC5jYW5jZWw7XG4gICAgICBpZiAoIXRoaXMuaXNNdWx0aURyYWcpIHJldHVybjtcbiAgICAgIGluc2VydE11bHRpRHJhZ0Nsb25lcyhmYWxzZSwgcm9vdEVsKTtcbiAgICAgIG11bHRpRHJhZ0Nsb25lcy5mb3JFYWNoKGZ1bmN0aW9uIChjbG9uZSkge1xuICAgICAgICBjc3MoY2xvbmUsICdkaXNwbGF5JywgJycpO1xuICAgICAgfSk7XG4gICAgICBjbG9uZU5vd1Nob3duKCk7XG4gICAgICBjbG9uZXNIaWRkZW4gPSBmYWxzZTtcbiAgICAgIGNhbmNlbCgpO1xuICAgIH0sXG4gICAgaGlkZUNsb25lOiBmdW5jdGlvbiBoaWRlQ2xvbmUoX3JlZjUpIHtcbiAgICAgIHZhciBfdGhpcyA9IHRoaXM7XG5cbiAgICAgIHZhciBzb3J0YWJsZSA9IF9yZWY1LnNvcnRhYmxlLFxuICAgICAgICAgIGNsb25lTm93SGlkZGVuID0gX3JlZjUuY2xvbmVOb3dIaWRkZW4sXG4gICAgICAgICAgY2FuY2VsID0gX3JlZjUuY2FuY2VsO1xuICAgICAgaWYgKCF0aGlzLmlzTXVsdGlEcmFnKSByZXR1cm47XG4gICAgICBtdWx0aURyYWdDbG9uZXMuZm9yRWFjaChmdW5jdGlvbiAoY2xvbmUpIHtcbiAgICAgICAgY3NzKGNsb25lLCAnZGlzcGxheScsICdub25lJyk7XG5cbiAgICAgICAgaWYgKF90aGlzLm9wdGlvbnMucmVtb3ZlQ2xvbmVPbkhpZGUgJiYgY2xvbmUucGFyZW50Tm9kZSkge1xuICAgICAgICAgIGNsb25lLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY2xvbmUpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICAgIGNsb25lTm93SGlkZGVuKCk7XG4gICAgICBjbG9uZXNIaWRkZW4gPSB0cnVlO1xuICAgICAgY2FuY2VsKCk7XG4gICAgfSxcbiAgICBkcmFnU3RhcnRHbG9iYWw6IGZ1bmN0aW9uIGRyYWdTdGFydEdsb2JhbChfcmVmNikge1xuICAgICAgdmFyIHNvcnRhYmxlID0gX3JlZjYuc29ydGFibGU7XG5cbiAgICAgIGlmICghdGhpcy5pc011bHRpRHJhZyAmJiBtdWx0aURyYWdTb3J0YWJsZSkge1xuICAgICAgICBtdWx0aURyYWdTb3J0YWJsZS5tdWx0aURyYWcuX2Rlc2VsZWN0TXVsdGlEcmFnKCk7XG4gICAgICB9XG5cbiAgICAgIG11bHRpRHJhZ0VsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKG11bHRpRHJhZ0VsZW1lbnQpIHtcbiAgICAgICAgbXVsdGlEcmFnRWxlbWVudC5zb3J0YWJsZUluZGV4ID0gaW5kZXgobXVsdGlEcmFnRWxlbWVudCk7XG4gICAgICB9KTsgLy8gU29ydCBtdWx0aS1kcmFnIGVsZW1lbnRzXG5cbiAgICAgIG11bHRpRHJhZ0VsZW1lbnRzID0gbXVsdGlEcmFnRWxlbWVudHMuc29ydChmdW5jdGlvbiAoYSwgYikge1xuICAgICAgICByZXR1cm4gYS5zb3J0YWJsZUluZGV4IC0gYi5zb3J0YWJsZUluZGV4O1xuICAgICAgfSk7XG4gICAgICBkcmFnU3RhcnRlZCA9IHRydWU7XG4gICAgfSxcbiAgICBkcmFnU3RhcnRlZDogZnVuY3Rpb24gZHJhZ1N0YXJ0ZWQoX3JlZjcpIHtcbiAgICAgIHZhciBfdGhpczIgPSB0aGlzO1xuXG4gICAgICB2YXIgc29ydGFibGUgPSBfcmVmNy5zb3J0YWJsZTtcbiAgICAgIGlmICghdGhpcy5pc011bHRpRHJhZykgcmV0dXJuO1xuXG4gICAgICBpZiAodGhpcy5vcHRpb25zLnNvcnQpIHtcbiAgICAgICAgLy8gQ2FwdHVyZSByZWN0cyxcbiAgICAgICAgLy8gaGlkZSBtdWx0aSBkcmFnIGVsZW1lbnRzIChieSBwb3NpdGlvbmluZyB0aGVtIGFic29sdXRlKSxcbiAgICAgICAgLy8gc2V0IG11bHRpIGRyYWcgZWxlbWVudHMgcmVjdHMgdG8gZHJhZ1JlY3QsXG4gICAgICAgIC8vIHNob3cgbXVsdGkgZHJhZyBlbGVtZW50cyxcbiAgICAgICAgLy8gYW5pbWF0ZSB0byByZWN0cyxcbiAgICAgICAgLy8gdW5zZXQgcmVjdHMgJiByZW1vdmUgZnJvbSBET01cbiAgICAgICAgc29ydGFibGUuY2FwdHVyZUFuaW1hdGlvblN0YXRlKCk7XG5cbiAgICAgICAgaWYgKHRoaXMub3B0aW9ucy5hbmltYXRpb24pIHtcbiAgICAgICAgICBtdWx0aURyYWdFbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChtdWx0aURyYWdFbGVtZW50KSB7XG4gICAgICAgICAgICBpZiAobXVsdGlEcmFnRWxlbWVudCA9PT0gZHJhZ0VsJDEpIHJldHVybjtcbiAgICAgICAgICAgIGNzcyhtdWx0aURyYWdFbGVtZW50LCAncG9zaXRpb24nLCAnYWJzb2x1dGUnKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB2YXIgZHJhZ1JlY3QgPSBnZXRSZWN0KGRyYWdFbCQxLCBmYWxzZSwgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAobXVsdGlEcmFnRWxlbWVudCkge1xuICAgICAgICAgICAgaWYgKG11bHRpRHJhZ0VsZW1lbnQgPT09IGRyYWdFbCQxKSByZXR1cm47XG4gICAgICAgICAgICBzZXRSZWN0KG11bHRpRHJhZ0VsZW1lbnQsIGRyYWdSZWN0KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBmb2xkaW5nID0gdHJ1ZTtcbiAgICAgICAgICBpbml0aWFsRm9sZGluZyA9IHRydWU7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgc29ydGFibGUuYW5pbWF0ZUFsbChmdW5jdGlvbiAoKSB7XG4gICAgICAgIGZvbGRpbmcgPSBmYWxzZTtcbiAgICAgICAgaW5pdGlhbEZvbGRpbmcgPSBmYWxzZTtcblxuICAgICAgICBpZiAoX3RoaXMyLm9wdGlvbnMuYW5pbWF0aW9uKSB7XG4gICAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAobXVsdGlEcmFnRWxlbWVudCkge1xuICAgICAgICAgICAgdW5zZXRSZWN0KG11bHRpRHJhZ0VsZW1lbnQpO1xuICAgICAgICAgIH0pO1xuICAgICAgICB9IC8vIFJlbW92ZSBhbGwgYXV4aWxpYXJ5IG11bHRpZHJhZyBpdGVtcyBmcm9tIGVsLCBpZiBzb3J0aW5nIGVuYWJsZWRcblxuXG4gICAgICAgIGlmIChfdGhpczIub3B0aW9ucy5zb3J0KSB7XG4gICAgICAgICAgcmVtb3ZlTXVsdGlEcmFnRWxlbWVudHMoKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSxcbiAgICBkcmFnT3ZlcjogZnVuY3Rpb24gZHJhZ092ZXIoX3JlZjgpIHtcbiAgICAgIHZhciB0YXJnZXQgPSBfcmVmOC50YXJnZXQsXG4gICAgICAgICAgY29tcGxldGVkID0gX3JlZjguY29tcGxldGVkLFxuICAgICAgICAgIGNhbmNlbCA9IF9yZWY4LmNhbmNlbDtcblxuICAgICAgaWYgKGZvbGRpbmcgJiYgfm11bHRpRHJhZ0VsZW1lbnRzLmluZGV4T2YodGFyZ2V0KSkge1xuICAgICAgICBjb21wbGV0ZWQoZmFsc2UpO1xuICAgICAgICBjYW5jZWwoKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIHJldmVydDogZnVuY3Rpb24gcmV2ZXJ0KF9yZWY5KSB7XG4gICAgICB2YXIgZnJvbVNvcnRhYmxlID0gX3JlZjkuZnJvbVNvcnRhYmxlLFxuICAgICAgICAgIHJvb3RFbCA9IF9yZWY5LnJvb3RFbCxcbiAgICAgICAgICBzb3J0YWJsZSA9IF9yZWY5LnNvcnRhYmxlLFxuICAgICAgICAgIGRyYWdSZWN0ID0gX3JlZjkuZHJhZ1JlY3Q7XG5cbiAgICAgIGlmIChtdWx0aURyYWdFbGVtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgIC8vIFNldHVwIHVuZm9sZCBhbmltYXRpb25cbiAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAobXVsdGlEcmFnRWxlbWVudCkge1xuICAgICAgICAgIHNvcnRhYmxlLmFkZEFuaW1hdGlvblN0YXRlKHtcbiAgICAgICAgICAgIHRhcmdldDogbXVsdGlEcmFnRWxlbWVudCxcbiAgICAgICAgICAgIHJlY3Q6IGZvbGRpbmcgPyBnZXRSZWN0KG11bHRpRHJhZ0VsZW1lbnQpIDogZHJhZ1JlY3RcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB1bnNldFJlY3QobXVsdGlEcmFnRWxlbWVudCk7XG4gICAgICAgICAgbXVsdGlEcmFnRWxlbWVudC5mcm9tUmVjdCA9IGRyYWdSZWN0O1xuICAgICAgICAgIGZyb21Tb3J0YWJsZS5yZW1vdmVBbmltYXRpb25TdGF0ZShtdWx0aURyYWdFbGVtZW50KTtcbiAgICAgICAgfSk7XG4gICAgICAgIGZvbGRpbmcgPSBmYWxzZTtcbiAgICAgICAgaW5zZXJ0TXVsdGlEcmFnRWxlbWVudHMoIXRoaXMub3B0aW9ucy5yZW1vdmVDbG9uZU9uSGlkZSwgcm9vdEVsKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGRyYWdPdmVyQ29tcGxldGVkOiBmdW5jdGlvbiBkcmFnT3ZlckNvbXBsZXRlZChfcmVmMTApIHtcbiAgICAgIHZhciBzb3J0YWJsZSA9IF9yZWYxMC5zb3J0YWJsZSxcbiAgICAgICAgICBpc093bmVyID0gX3JlZjEwLmlzT3duZXIsXG4gICAgICAgICAgaW5zZXJ0aW9uID0gX3JlZjEwLmluc2VydGlvbixcbiAgICAgICAgICBhY3RpdmVTb3J0YWJsZSA9IF9yZWYxMC5hY3RpdmVTb3J0YWJsZSxcbiAgICAgICAgICBwYXJlbnRFbCA9IF9yZWYxMC5wYXJlbnRFbCxcbiAgICAgICAgICBwdXRTb3J0YWJsZSA9IF9yZWYxMC5wdXRTb3J0YWJsZTtcbiAgICAgIHZhciBvcHRpb25zID0gdGhpcy5vcHRpb25zO1xuXG4gICAgICBpZiAoaW5zZXJ0aW9uKSB7XG4gICAgICAgIC8vIENsb25lcyBtdXN0IGJlIGhpZGRlbiBiZWZvcmUgZm9sZGluZyBhbmltYXRpb24gdG8gY2FwdHVyZSBkcmFnUmVjdEFic29sdXRlIHByb3Blcmx5XG4gICAgICAgIGlmIChpc093bmVyKSB7XG4gICAgICAgICAgYWN0aXZlU29ydGFibGUuX2hpZGVDbG9uZSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgaW5pdGlhbEZvbGRpbmcgPSBmYWxzZTsgLy8gSWYgbGVhdmluZyBzb3J0OmZhbHNlIHJvb3QsIG9yIGFscmVhZHkgZm9sZGluZyAtIEZvbGQgdG8gbmV3IGxvY2F0aW9uXG5cbiAgICAgICAgaWYgKG9wdGlvbnMuYW5pbWF0aW9uICYmIG11bHRpRHJhZ0VsZW1lbnRzLmxlbmd0aCA+IDEgJiYgKGZvbGRpbmcgfHwgIWlzT3duZXIgJiYgIWFjdGl2ZVNvcnRhYmxlLm9wdGlvbnMuc29ydCAmJiAhcHV0U29ydGFibGUpKSB7XG4gICAgICAgICAgLy8gRm9sZDogU2V0IGFsbCBtdWx0aSBkcmFnIGVsZW1lbnRzJ3MgcmVjdHMgdG8gZHJhZ0VsJ3MgcmVjdCB3aGVuIG11bHRpLWRyYWcgZWxlbWVudHMgYXJlIGludmlzaWJsZVxuICAgICAgICAgIHZhciBkcmFnUmVjdEFic29sdXRlID0gZ2V0UmVjdChkcmFnRWwkMSwgZmFsc2UsIHRydWUsIHRydWUpO1xuICAgICAgICAgIG11bHRpRHJhZ0VsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKG11bHRpRHJhZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgIGlmIChtdWx0aURyYWdFbGVtZW50ID09PSBkcmFnRWwkMSkgcmV0dXJuO1xuICAgICAgICAgICAgc2V0UmVjdChtdWx0aURyYWdFbGVtZW50LCBkcmFnUmVjdEFic29sdXRlKTsgLy8gTW92ZSBlbGVtZW50KHMpIHRvIGVuZCBvZiBwYXJlbnRFbCBzbyB0aGF0IGl0IGRvZXMgbm90IGludGVyZmVyZSB3aXRoIG11bHRpLWRyYWcgY2xvbmVzIGluc2VydGlvbiBpZiB0aGV5IGFyZSBpbnNlcnRlZFxuICAgICAgICAgICAgLy8gd2hpbGUgZm9sZGluZywgYW5kIHNvIHRoYXQgd2UgY2FuIGNhcHR1cmUgdGhlbSBhZ2FpbiBiZWNhdXNlIG9sZCBzb3J0YWJsZSB3aWxsIG5vIGxvbmdlciBiZSBmcm9tU29ydGFibGVcblxuICAgICAgICAgICAgcGFyZW50RWwuYXBwZW5kQ2hpbGQobXVsdGlEcmFnRWxlbWVudCk7XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgZm9sZGluZyA9IHRydWU7XG4gICAgICAgIH0gLy8gQ2xvbmVzIG11c3QgYmUgc2hvd24gKGFuZCBjaGVjayB0byByZW1vdmUgbXVsdGkgZHJhZ3MpIGFmdGVyIGZvbGRpbmcgd2hlbiBpbnRlcmZlcmluZyBtdWx0aURyYWdFbGVtZW50cyBhcmUgbW92ZWQgb3V0XG5cblxuICAgICAgICBpZiAoIWlzT3duZXIpIHtcbiAgICAgICAgICAvLyBPbmx5IHJlbW92ZSBpZiBub3QgZm9sZGluZyAoZm9sZGluZyB3aWxsIHJlbW92ZSB0aGVtIGFueXdheXMpXG4gICAgICAgICAgaWYgKCFmb2xkaW5nKSB7XG4gICAgICAgICAgICByZW1vdmVNdWx0aURyYWdFbGVtZW50cygpO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChtdWx0aURyYWdFbGVtZW50cy5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICB2YXIgY2xvbmVzSGlkZGVuQmVmb3JlID0gY2xvbmVzSGlkZGVuO1xuXG4gICAgICAgICAgICBhY3RpdmVTb3J0YWJsZS5fc2hvd0Nsb25lKHNvcnRhYmxlKTsgLy8gVW5mb2xkIGFuaW1hdGlvbiBmb3IgY2xvbmVzIGlmIHNob3dpbmcgZnJvbSBoaWRkZW5cblxuXG4gICAgICAgICAgICBpZiAoYWN0aXZlU29ydGFibGUub3B0aW9ucy5hbmltYXRpb24gJiYgIWNsb25lc0hpZGRlbiAmJiBjbG9uZXNIaWRkZW5CZWZvcmUpIHtcbiAgICAgICAgICAgICAgbXVsdGlEcmFnQ2xvbmVzLmZvckVhY2goZnVuY3Rpb24gKGNsb25lKSB7XG4gICAgICAgICAgICAgICAgYWN0aXZlU29ydGFibGUuYWRkQW5pbWF0aW9uU3RhdGUoe1xuICAgICAgICAgICAgICAgICAgdGFyZ2V0OiBjbG9uZSxcbiAgICAgICAgICAgICAgICAgIHJlY3Q6IGNsb25lc0Zyb21SZWN0XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgY2xvbmUuZnJvbVJlY3QgPSBjbG9uZXNGcm9tUmVjdDtcbiAgICAgICAgICAgICAgICBjbG9uZS50aGlzQW5pbWF0aW9uRHVyYXRpb24gPSBudWxsO1xuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYWN0aXZlU29ydGFibGUuX3Nob3dDbG9uZShzb3J0YWJsZSk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBkcmFnT3ZlckFuaW1hdGlvbkNhcHR1cmU6IGZ1bmN0aW9uIGRyYWdPdmVyQW5pbWF0aW9uQ2FwdHVyZShfcmVmMTEpIHtcbiAgICAgIHZhciBkcmFnUmVjdCA9IF9yZWYxMS5kcmFnUmVjdCxcbiAgICAgICAgICBpc093bmVyID0gX3JlZjExLmlzT3duZXIsXG4gICAgICAgICAgYWN0aXZlU29ydGFibGUgPSBfcmVmMTEuYWN0aXZlU29ydGFibGU7XG4gICAgICBtdWx0aURyYWdFbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChtdWx0aURyYWdFbGVtZW50KSB7XG4gICAgICAgIG11bHRpRHJhZ0VsZW1lbnQudGhpc0FuaW1hdGlvbkR1cmF0aW9uID0gbnVsbDtcbiAgICAgIH0pO1xuXG4gICAgICBpZiAoYWN0aXZlU29ydGFibGUub3B0aW9ucy5hbmltYXRpb24gJiYgIWlzT3duZXIgJiYgYWN0aXZlU29ydGFibGUubXVsdGlEcmFnLmlzTXVsdGlEcmFnKSB7XG4gICAgICAgIGNsb25lc0Zyb21SZWN0ID0gX2V4dGVuZHMoe30sIGRyYWdSZWN0KTtcbiAgICAgICAgdmFyIGRyYWdNYXRyaXggPSBtYXRyaXgoZHJhZ0VsJDEsIHRydWUpO1xuICAgICAgICBjbG9uZXNGcm9tUmVjdC50b3AgLT0gZHJhZ01hdHJpeC5mO1xuICAgICAgICBjbG9uZXNGcm9tUmVjdC5sZWZ0IC09IGRyYWdNYXRyaXguZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGRyYWdPdmVyQW5pbWF0aW9uQ29tcGxldGU6IGZ1bmN0aW9uIGRyYWdPdmVyQW5pbWF0aW9uQ29tcGxldGUoKSB7XG4gICAgICBpZiAoZm9sZGluZykge1xuICAgICAgICBmb2xkaW5nID0gZmFsc2U7XG4gICAgICAgIHJlbW92ZU11bHRpRHJhZ0VsZW1lbnRzKCk7XG4gICAgICB9XG4gICAgfSxcbiAgICBkcm9wOiBmdW5jdGlvbiBkcm9wKF9yZWYxMikge1xuICAgICAgdmFyIGV2dCA9IF9yZWYxMi5vcmlnaW5hbEV2ZW50LFxuICAgICAgICAgIHJvb3RFbCA9IF9yZWYxMi5yb290RWwsXG4gICAgICAgICAgcGFyZW50RWwgPSBfcmVmMTIucGFyZW50RWwsXG4gICAgICAgICAgc29ydGFibGUgPSBfcmVmMTIuc29ydGFibGUsXG4gICAgICAgICAgZGlzcGF0Y2hTb3J0YWJsZUV2ZW50ID0gX3JlZjEyLmRpc3BhdGNoU29ydGFibGVFdmVudCxcbiAgICAgICAgICBvbGRJbmRleCA9IF9yZWYxMi5vbGRJbmRleCxcbiAgICAgICAgICBwdXRTb3J0YWJsZSA9IF9yZWYxMi5wdXRTb3J0YWJsZTtcbiAgICAgIHZhciB0b1NvcnRhYmxlID0gcHV0U29ydGFibGUgfHwgdGhpcy5zb3J0YWJsZTtcbiAgICAgIGlmICghZXZ0KSByZXR1cm47XG4gICAgICB2YXIgb3B0aW9ucyA9IHRoaXMub3B0aW9ucyxcbiAgICAgICAgICBjaGlsZHJlbiA9IHBhcmVudEVsLmNoaWxkcmVuOyAvLyBNdWx0aS1kcmFnIHNlbGVjdGlvblxuXG4gICAgICBpZiAoIWRyYWdTdGFydGVkKSB7XG4gICAgICAgIGlmIChvcHRpb25zLm11bHRpRHJhZ0tleSAmJiAhdGhpcy5tdWx0aURyYWdLZXlEb3duKSB7XG4gICAgICAgICAgdGhpcy5fZGVzZWxlY3RNdWx0aURyYWcoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRvZ2dsZUNsYXNzKGRyYWdFbCQxLCBvcHRpb25zLnNlbGVjdGVkQ2xhc3MsICF+bXVsdGlEcmFnRWxlbWVudHMuaW5kZXhPZihkcmFnRWwkMSkpO1xuXG4gICAgICAgIGlmICghfm11bHRpRHJhZ0VsZW1lbnRzLmluZGV4T2YoZHJhZ0VsJDEpKSB7XG4gICAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMucHVzaChkcmFnRWwkMSk7XG4gICAgICAgICAgZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgICAgICBzb3J0YWJsZTogc29ydGFibGUsXG4gICAgICAgICAgICByb290RWw6IHJvb3RFbCxcbiAgICAgICAgICAgIG5hbWU6ICdzZWxlY3QnLFxuICAgICAgICAgICAgdGFyZ2V0RWw6IGRyYWdFbCQxLFxuICAgICAgICAgICAgb3JpZ2luYWxFdnQ6IGV2dFxuICAgICAgICAgIH0pOyAvLyBNb2RpZmllciBhY3RpdmF0ZWQsIHNlbGVjdCBmcm9tIGxhc3QgdG8gZHJhZ0VsXG5cbiAgICAgICAgICBpZiAoZXZ0LnNoaWZ0S2V5ICYmIGxhc3RNdWx0aURyYWdTZWxlY3QgJiYgc29ydGFibGUuZWwuY29udGFpbnMobGFzdE11bHRpRHJhZ1NlbGVjdCkpIHtcbiAgICAgICAgICAgIHZhciBsYXN0SW5kZXggPSBpbmRleChsYXN0TXVsdGlEcmFnU2VsZWN0KSxcbiAgICAgICAgICAgICAgICBjdXJyZW50SW5kZXggPSBpbmRleChkcmFnRWwkMSk7XG5cbiAgICAgICAgICAgIGlmICh+bGFzdEluZGV4ICYmIH5jdXJyZW50SW5kZXggJiYgbGFzdEluZGV4ICE9PSBjdXJyZW50SW5kZXgpIHtcbiAgICAgICAgICAgICAgLy8gTXVzdCBpbmNsdWRlIGxhc3RNdWx0aURyYWdTZWxlY3QgKHNlbGVjdCBpdCksIGluIGNhc2UgbW9kaWZpZWQgc2VsZWN0aW9uIGZyb20gbm8gc2VsZWN0aW9uXG4gICAgICAgICAgICAgIC8vIChidXQgcHJldmlvdXMgc2VsZWN0aW9uIGV4aXN0ZWQpXG4gICAgICAgICAgICAgIHZhciBuLCBpO1xuXG4gICAgICAgICAgICAgIGlmIChjdXJyZW50SW5kZXggPiBsYXN0SW5kZXgpIHtcbiAgICAgICAgICAgICAgICBpID0gbGFzdEluZGV4O1xuICAgICAgICAgICAgICAgIG4gPSBjdXJyZW50SW5kZXg7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaSA9IGN1cnJlbnRJbmRleDtcbiAgICAgICAgICAgICAgICBuID0gbGFzdEluZGV4ICsgMTtcbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIGZvciAoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKH5tdWx0aURyYWdFbGVtZW50cy5pbmRleE9mKGNoaWxkcmVuW2ldKSkgY29udGludWU7XG4gICAgICAgICAgICAgICAgdG9nZ2xlQ2xhc3MoY2hpbGRyZW5baV0sIG9wdGlvbnMuc2VsZWN0ZWRDbGFzcywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMucHVzaChjaGlsZHJlbltpXSk7XG4gICAgICAgICAgICAgICAgZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgICAgICAgICAgICBzb3J0YWJsZTogc29ydGFibGUsXG4gICAgICAgICAgICAgICAgICByb290RWw6IHJvb3RFbCxcbiAgICAgICAgICAgICAgICAgIG5hbWU6ICdzZWxlY3QnLFxuICAgICAgICAgICAgICAgICAgdGFyZ2V0RWw6IGNoaWxkcmVuW2ldLFxuICAgICAgICAgICAgICAgICAgb3JpZ2luYWxFdnQ6IGV2dFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxhc3RNdWx0aURyYWdTZWxlY3QgPSBkcmFnRWwkMTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBtdWx0aURyYWdTb3J0YWJsZSA9IHRvU29ydGFibGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMuc3BsaWNlKG11bHRpRHJhZ0VsZW1lbnRzLmluZGV4T2YoZHJhZ0VsJDEpLCAxKTtcbiAgICAgICAgICBsYXN0TXVsdGlEcmFnU2VsZWN0ID0gbnVsbDtcbiAgICAgICAgICBkaXNwYXRjaEV2ZW50KHtcbiAgICAgICAgICAgIHNvcnRhYmxlOiBzb3J0YWJsZSxcbiAgICAgICAgICAgIHJvb3RFbDogcm9vdEVsLFxuICAgICAgICAgICAgbmFtZTogJ2Rlc2VsZWN0JyxcbiAgICAgICAgICAgIHRhcmdldEVsOiBkcmFnRWwkMSxcbiAgICAgICAgICAgIG9yaWdpbmFsRXZ0OiBldnRcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfSAvLyBNdWx0aS1kcmFnIGRyb3BcblxuXG4gICAgICBpZiAoZHJhZ1N0YXJ0ZWQgJiYgdGhpcy5pc011bHRpRHJhZykge1xuICAgICAgICAvLyBEbyBub3QgXCJ1bmZvbGRcIiBhZnRlciBhcm91bmQgZHJhZ0VsIGlmIHJldmVydGVkXG4gICAgICAgIGlmICgocGFyZW50RWxbZXhwYW5kb10ub3B0aW9ucy5zb3J0IHx8IHBhcmVudEVsICE9PSByb290RWwpICYmIG11bHRpRHJhZ0VsZW1lbnRzLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICB2YXIgZHJhZ1JlY3QgPSBnZXRSZWN0KGRyYWdFbCQxKSxcbiAgICAgICAgICAgICAgbXVsdGlEcmFnSW5kZXggPSBpbmRleChkcmFnRWwkMSwgJzpub3QoLicgKyB0aGlzLm9wdGlvbnMuc2VsZWN0ZWRDbGFzcyArICcpJyk7XG4gICAgICAgICAgaWYgKCFpbml0aWFsRm9sZGluZyAmJiBvcHRpb25zLmFuaW1hdGlvbikgZHJhZ0VsJDEudGhpc0FuaW1hdGlvbkR1cmF0aW9uID0gbnVsbDtcbiAgICAgICAgICB0b1NvcnRhYmxlLmNhcHR1cmVBbmltYXRpb25TdGF0ZSgpO1xuXG4gICAgICAgICAgaWYgKCFpbml0aWFsRm9sZGluZykge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuYW5pbWF0aW9uKSB7XG4gICAgICAgICAgICAgIGRyYWdFbCQxLmZyb21SZWN0ID0gZHJhZ1JlY3Q7XG4gICAgICAgICAgICAgIG11bHRpRHJhZ0VsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKG11bHRpRHJhZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBtdWx0aURyYWdFbGVtZW50LnRoaXNBbmltYXRpb25EdXJhdGlvbiA9IG51bGw7XG5cbiAgICAgICAgICAgICAgICBpZiAobXVsdGlEcmFnRWxlbWVudCAhPT0gZHJhZ0VsJDEpIHtcbiAgICAgICAgICAgICAgICAgIHZhciByZWN0ID0gZm9sZGluZyA/IGdldFJlY3QobXVsdGlEcmFnRWxlbWVudCkgOiBkcmFnUmVjdDtcbiAgICAgICAgICAgICAgICAgIG11bHRpRHJhZ0VsZW1lbnQuZnJvbVJlY3QgPSByZWN0OyAvLyBQcmVwYXJlIHVuZm9sZCBhbmltYXRpb25cblxuICAgICAgICAgICAgICAgICAgdG9Tb3J0YWJsZS5hZGRBbmltYXRpb25TdGF0ZSh7XG4gICAgICAgICAgICAgICAgICAgIHRhcmdldDogbXVsdGlEcmFnRWxlbWVudCxcbiAgICAgICAgICAgICAgICAgICAgcmVjdDogcmVjdFxuICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gLy8gTXVsdGkgZHJhZyBlbGVtZW50cyBhcmUgbm90IG5lY2Vzc2FyaWx5IHJlbW92ZWQgZnJvbSB0aGUgRE9NIG9uIGRyb3AsIHNvIHRvIHJlaW5zZXJ0XG4gICAgICAgICAgICAvLyBwcm9wZXJseSB0aGV5IG11c3QgYWxsIGJlIHJlbW92ZWRcblxuXG4gICAgICAgICAgICByZW1vdmVNdWx0aURyYWdFbGVtZW50cygpO1xuICAgICAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMuZm9yRWFjaChmdW5jdGlvbiAobXVsdGlEcmFnRWxlbWVudCkge1xuICAgICAgICAgICAgICBpZiAoY2hpbGRyZW5bbXVsdGlEcmFnSW5kZXhdKSB7XG4gICAgICAgICAgICAgICAgcGFyZW50RWwuaW5zZXJ0QmVmb3JlKG11bHRpRHJhZ0VsZW1lbnQsIGNoaWxkcmVuW211bHRpRHJhZ0luZGV4XSk7XG4gICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcGFyZW50RWwuYXBwZW5kQ2hpbGQobXVsdGlEcmFnRWxlbWVudCk7XG4gICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICBtdWx0aURyYWdJbmRleCsrO1xuICAgICAgICAgICAgfSk7IC8vIElmIGluaXRpYWwgZm9sZGluZyBpcyBkb25lLCB0aGUgZWxlbWVudHMgbWF5IGhhdmUgY2hhbmdlZCBwb3NpdGlvbiBiZWNhdXNlIHRoZXkgYXJlIG5vd1xuICAgICAgICAgICAgLy8gdW5mb2xkaW5nIGFyb3VuZCBkcmFnRWwsIGV2ZW4gdGhvdWdoIGRyYWdFbCBtYXkgbm90IGhhdmUgaGlzIGluZGV4IGNoYW5nZWQsIHNvIHVwZGF0ZSBldmVudFxuICAgICAgICAgICAgLy8gbXVzdCBiZSBmaXJlZCBoZXJlIGFzIFNvcnRhYmxlIHdpbGwgbm90LlxuXG4gICAgICAgICAgICBpZiAob2xkSW5kZXggPT09IGluZGV4KGRyYWdFbCQxKSkge1xuICAgICAgICAgICAgICB2YXIgdXBkYXRlID0gZmFsc2U7XG4gICAgICAgICAgICAgIG11bHRpRHJhZ0VsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKG11bHRpRHJhZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBpZiAobXVsdGlEcmFnRWxlbWVudC5zb3J0YWJsZUluZGV4ICE9PSBpbmRleChtdWx0aURyYWdFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgICAgdXBkYXRlID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgIGlmICh1cGRhdGUpIHtcbiAgICAgICAgICAgICAgICBkaXNwYXRjaFNvcnRhYmxlRXZlbnQoJ3VwZGF0ZScpO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSAvLyBNdXN0IGJlIGRvbmUgYWZ0ZXIgY2FwdHVyaW5nIGluZGl2aWR1YWwgcmVjdHMgKHNjcm9sbCBiYXIpXG5cblxuICAgICAgICAgIG11bHRpRHJhZ0VsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKG11bHRpRHJhZ0VsZW1lbnQpIHtcbiAgICAgICAgICAgIHVuc2V0UmVjdChtdWx0aURyYWdFbGVtZW50KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICB0b1NvcnRhYmxlLmFuaW1hdGVBbGwoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIG11bHRpRHJhZ1NvcnRhYmxlID0gdG9Tb3J0YWJsZTtcbiAgICAgIH0gLy8gUmVtb3ZlIGNsb25lcyBpZiBuZWNlc3NhcnlcblxuXG4gICAgICBpZiAocm9vdEVsID09PSBwYXJlbnRFbCB8fCBwdXRTb3J0YWJsZSAmJiBwdXRTb3J0YWJsZS5sYXN0UHV0TW9kZSAhPT0gJ2Nsb25lJykge1xuICAgICAgICBtdWx0aURyYWdDbG9uZXMuZm9yRWFjaChmdW5jdGlvbiAoY2xvbmUpIHtcbiAgICAgICAgICBjbG9uZS5wYXJlbnROb2RlICYmIGNsb25lLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoY2xvbmUpO1xuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9LFxuICAgIG51bGxpbmdHbG9iYWw6IGZ1bmN0aW9uIG51bGxpbmdHbG9iYWwoKSB7XG4gICAgICB0aGlzLmlzTXVsdGlEcmFnID0gZHJhZ1N0YXJ0ZWQgPSBmYWxzZTtcbiAgICAgIG11bHRpRHJhZ0Nsb25lcy5sZW5ndGggPSAwO1xuICAgIH0sXG4gICAgZGVzdHJveUdsb2JhbDogZnVuY3Rpb24gZGVzdHJveUdsb2JhbCgpIHtcbiAgICAgIHRoaXMuX2Rlc2VsZWN0TXVsdGlEcmFnKCk7XG5cbiAgICAgIG9mZihkb2N1bWVudCwgJ3BvaW50ZXJ1cCcsIHRoaXMuX2Rlc2VsZWN0TXVsdGlEcmFnKTtcbiAgICAgIG9mZihkb2N1bWVudCwgJ21vdXNldXAnLCB0aGlzLl9kZXNlbGVjdE11bHRpRHJhZyk7XG4gICAgICBvZmYoZG9jdW1lbnQsICd0b3VjaGVuZCcsIHRoaXMuX2Rlc2VsZWN0TXVsdGlEcmFnKTtcbiAgICAgIG9mZihkb2N1bWVudCwgJ2tleWRvd24nLCB0aGlzLl9jaGVja0tleURvd24pO1xuICAgICAgb2ZmKGRvY3VtZW50LCAna2V5dXAnLCB0aGlzLl9jaGVja0tleVVwKTtcbiAgICB9LFxuICAgIF9kZXNlbGVjdE11bHRpRHJhZzogZnVuY3Rpb24gX2Rlc2VsZWN0TXVsdGlEcmFnKGV2dCkge1xuICAgICAgaWYgKHR5cGVvZiBkcmFnU3RhcnRlZCAhPT0gXCJ1bmRlZmluZWRcIiAmJiBkcmFnU3RhcnRlZCkgcmV0dXJuOyAvLyBPbmx5IGRlc2VsZWN0IGlmIHNlbGVjdGlvbiBpcyBpbiB0aGlzIHNvcnRhYmxlXG5cbiAgICAgIGlmIChtdWx0aURyYWdTb3J0YWJsZSAhPT0gdGhpcy5zb3J0YWJsZSkgcmV0dXJuOyAvLyBPbmx5IGRlc2VsZWN0IGlmIHRhcmdldCBpcyBub3QgaXRlbSBpbiB0aGlzIHNvcnRhYmxlXG5cbiAgICAgIGlmIChldnQgJiYgY2xvc2VzdChldnQudGFyZ2V0LCB0aGlzLm9wdGlvbnMuZHJhZ2dhYmxlLCB0aGlzLnNvcnRhYmxlLmVsLCBmYWxzZSkpIHJldHVybjsgLy8gT25seSBkZXNlbGVjdCBpZiBsZWZ0IGNsaWNrXG5cbiAgICAgIGlmIChldnQgJiYgZXZ0LmJ1dHRvbiAhPT0gMCkgcmV0dXJuO1xuXG4gICAgICB3aGlsZSAobXVsdGlEcmFnRWxlbWVudHMubGVuZ3RoKSB7XG4gICAgICAgIHZhciBlbCA9IG11bHRpRHJhZ0VsZW1lbnRzWzBdO1xuICAgICAgICB0b2dnbGVDbGFzcyhlbCwgdGhpcy5vcHRpb25zLnNlbGVjdGVkQ2xhc3MsIGZhbHNlKTtcbiAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMuc2hpZnQoKTtcbiAgICAgICAgZGlzcGF0Y2hFdmVudCh7XG4gICAgICAgICAgc29ydGFibGU6IHRoaXMuc29ydGFibGUsXG4gICAgICAgICAgcm9vdEVsOiB0aGlzLnNvcnRhYmxlLmVsLFxuICAgICAgICAgIG5hbWU6ICdkZXNlbGVjdCcsXG4gICAgICAgICAgdGFyZ2V0RWw6IGVsLFxuICAgICAgICAgIG9yaWdpbmFsRXZ0OiBldnRcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSxcbiAgICBfY2hlY2tLZXlEb3duOiBmdW5jdGlvbiBfY2hlY2tLZXlEb3duKGV2dCkge1xuICAgICAgaWYgKGV2dC5rZXkgPT09IHRoaXMub3B0aW9ucy5tdWx0aURyYWdLZXkpIHtcbiAgICAgICAgdGhpcy5tdWx0aURyYWdLZXlEb3duID0gdHJ1ZTtcbiAgICAgIH1cbiAgICB9LFxuICAgIF9jaGVja0tleVVwOiBmdW5jdGlvbiBfY2hlY2tLZXlVcChldnQpIHtcbiAgICAgIGlmIChldnQua2V5ID09PSB0aGlzLm9wdGlvbnMubXVsdGlEcmFnS2V5KSB7XG4gICAgICAgIHRoaXMubXVsdGlEcmFnS2V5RG93biA9IGZhbHNlO1xuICAgICAgfVxuICAgIH1cbiAgfTtcbiAgcmV0dXJuIF9leHRlbmRzKE11bHRpRHJhZywge1xuICAgIC8vIFN0YXRpYyBtZXRob2RzICYgcHJvcGVydGllc1xuICAgIHBsdWdpbk5hbWU6ICdtdWx0aURyYWcnLFxuICAgIHV0aWxzOiB7XG4gICAgICAvKipcclxuICAgICAgICogU2VsZWN0cyB0aGUgcHJvdmlkZWQgbXVsdGktZHJhZyBpdGVtXHJcbiAgICAgICAqIEBwYXJhbSAge0hUTUxFbGVtZW50fSBlbCAgICBUaGUgZWxlbWVudCB0byBiZSBzZWxlY3RlZFxyXG4gICAgICAgKi9cbiAgICAgIHNlbGVjdDogZnVuY3Rpb24gc2VsZWN0KGVsKSB7XG4gICAgICAgIHZhciBzb3J0YWJsZSA9IGVsLnBhcmVudE5vZGVbZXhwYW5kb107XG4gICAgICAgIGlmICghc29ydGFibGUgfHwgIXNvcnRhYmxlLm9wdGlvbnMubXVsdGlEcmFnIHx8IH5tdWx0aURyYWdFbGVtZW50cy5pbmRleE9mKGVsKSkgcmV0dXJuO1xuXG4gICAgICAgIGlmIChtdWx0aURyYWdTb3J0YWJsZSAmJiBtdWx0aURyYWdTb3J0YWJsZSAhPT0gc29ydGFibGUpIHtcbiAgICAgICAgICBtdWx0aURyYWdTb3J0YWJsZS5tdWx0aURyYWcuX2Rlc2VsZWN0TXVsdGlEcmFnKCk7XG5cbiAgICAgICAgICBtdWx0aURyYWdTb3J0YWJsZSA9IHNvcnRhYmxlO1xuICAgICAgICB9XG5cbiAgICAgICAgdG9nZ2xlQ2xhc3MoZWwsIHNvcnRhYmxlLm9wdGlvbnMuc2VsZWN0ZWRDbGFzcywgdHJ1ZSk7XG4gICAgICAgIG11bHRpRHJhZ0VsZW1lbnRzLnB1c2goZWwpO1xuICAgICAgfSxcblxuICAgICAgLyoqXHJcbiAgICAgICAqIERlc2VsZWN0cyB0aGUgcHJvdmlkZWQgbXVsdGktZHJhZyBpdGVtXHJcbiAgICAgICAqIEBwYXJhbSAge0hUTUxFbGVtZW50fSBlbCAgICBUaGUgZWxlbWVudCB0byBiZSBkZXNlbGVjdGVkXHJcbiAgICAgICAqL1xuICAgICAgZGVzZWxlY3Q6IGZ1bmN0aW9uIGRlc2VsZWN0KGVsKSB7XG4gICAgICAgIHZhciBzb3J0YWJsZSA9IGVsLnBhcmVudE5vZGVbZXhwYW5kb10sXG4gICAgICAgICAgICBpbmRleCA9IG11bHRpRHJhZ0VsZW1lbnRzLmluZGV4T2YoZWwpO1xuICAgICAgICBpZiAoIXNvcnRhYmxlIHx8ICFzb3J0YWJsZS5vcHRpb25zLm11bHRpRHJhZyB8fCAhfmluZGV4KSByZXR1cm47XG4gICAgICAgIHRvZ2dsZUNsYXNzKGVsLCBzb3J0YWJsZS5vcHRpb25zLnNlbGVjdGVkQ2xhc3MsIGZhbHNlKTtcbiAgICAgICAgbXVsdGlEcmFnRWxlbWVudHMuc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgIH1cbiAgICB9LFxuICAgIGV2ZW50UHJvcGVydGllczogZnVuY3Rpb24gZXZlbnRQcm9wZXJ0aWVzKCkge1xuICAgICAgdmFyIF90aGlzMyA9IHRoaXM7XG5cbiAgICAgIHZhciBvbGRJbmRpY2llcyA9IFtdLFxuICAgICAgICAgIG5ld0luZGljaWVzID0gW107XG4gICAgICBtdWx0aURyYWdFbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChtdWx0aURyYWdFbGVtZW50KSB7XG4gICAgICAgIG9sZEluZGljaWVzLnB1c2goe1xuICAgICAgICAgIG11bHRpRHJhZ0VsZW1lbnQ6IG11bHRpRHJhZ0VsZW1lbnQsXG4gICAgICAgICAgaW5kZXg6IG11bHRpRHJhZ0VsZW1lbnQuc29ydGFibGVJbmRleFxuICAgICAgICB9KTsgLy8gbXVsdGlEcmFnRWxlbWVudHMgd2lsbCBhbHJlYWR5IGJlIHNvcnRlZCBpZiBmb2xkaW5nXG5cbiAgICAgICAgdmFyIG5ld0luZGV4O1xuXG4gICAgICAgIGlmIChmb2xkaW5nICYmIG11bHRpRHJhZ0VsZW1lbnQgIT09IGRyYWdFbCQxKSB7XG4gICAgICAgICAgbmV3SW5kZXggPSAtMTtcbiAgICAgICAgfSBlbHNlIGlmIChmb2xkaW5nKSB7XG4gICAgICAgICAgbmV3SW5kZXggPSBpbmRleChtdWx0aURyYWdFbGVtZW50LCAnOm5vdCguJyArIF90aGlzMy5vcHRpb25zLnNlbGVjdGVkQ2xhc3MgKyAnKScpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG5ld0luZGV4ID0gaW5kZXgobXVsdGlEcmFnRWxlbWVudCk7XG4gICAgICAgIH1cblxuICAgICAgICBuZXdJbmRpY2llcy5wdXNoKHtcbiAgICAgICAgICBtdWx0aURyYWdFbGVtZW50OiBtdWx0aURyYWdFbGVtZW50LFxuICAgICAgICAgIGluZGV4OiBuZXdJbmRleFxuICAgICAgICB9KTtcbiAgICAgIH0pO1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaXRlbXM6IF90b0NvbnN1bWFibGVBcnJheShtdWx0aURyYWdFbGVtZW50cyksXG4gICAgICAgIGNsb25lczogW10uY29uY2F0KG11bHRpRHJhZ0Nsb25lcyksXG4gICAgICAgIG9sZEluZGljaWVzOiBvbGRJbmRpY2llcyxcbiAgICAgICAgbmV3SW5kaWNpZXM6IG5ld0luZGljaWVzXG4gICAgICB9O1xuICAgIH0sXG4gICAgb3B0aW9uTGlzdGVuZXJzOiB7XG4gICAgICBtdWx0aURyYWdLZXk6IGZ1bmN0aW9uIG11bHRpRHJhZ0tleShrZXkpIHtcbiAgICAgICAga2V5ID0ga2V5LnRvTG93ZXJDYXNlKCk7XG5cbiAgICAgICAgaWYgKGtleSA9PT0gJ2N0cmwnKSB7XG4gICAgICAgICAga2V5ID0gJ0NvbnRyb2wnO1xuICAgICAgICB9IGVsc2UgaWYgKGtleS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAga2V5ID0ga2V5LmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsga2V5LnN1YnN0cigxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBrZXk7XG4gICAgICB9XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gaW5zZXJ0TXVsdGlEcmFnRWxlbWVudHMoY2xvbmVzSW5zZXJ0ZWQsIHJvb3RFbCkge1xuICBtdWx0aURyYWdFbGVtZW50cy5mb3JFYWNoKGZ1bmN0aW9uIChtdWx0aURyYWdFbGVtZW50LCBpKSB7XG4gICAgdmFyIHRhcmdldCA9IHJvb3RFbC5jaGlsZHJlblttdWx0aURyYWdFbGVtZW50LnNvcnRhYmxlSW5kZXggKyAoY2xvbmVzSW5zZXJ0ZWQgPyBOdW1iZXIoaSkgOiAwKV07XG5cbiAgICBpZiAodGFyZ2V0KSB7XG4gICAgICByb290RWwuaW5zZXJ0QmVmb3JlKG11bHRpRHJhZ0VsZW1lbnQsIHRhcmdldCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJvb3RFbC5hcHBlbmRDaGlsZChtdWx0aURyYWdFbGVtZW50KTtcbiAgICB9XG4gIH0pO1xufVxuLyoqXHJcbiAqIEluc2VydCBtdWx0aS1kcmFnIGNsb25lc1xyXG4gKiBAcGFyYW0gIHtbQm9vbGVhbl19IGVsZW1lbnRzSW5zZXJ0ZWQgIFdoZXRoZXIgdGhlIG11bHRpLWRyYWcgZWxlbWVudHMgYXJlIGluc2VydGVkXHJcbiAqIEBwYXJhbSAge0hUTUxFbGVtZW50fSByb290RWxcclxuICovXG5cblxuZnVuY3Rpb24gaW5zZXJ0TXVsdGlEcmFnQ2xvbmVzKGVsZW1lbnRzSW5zZXJ0ZWQsIHJvb3RFbCkge1xuICBtdWx0aURyYWdDbG9uZXMuZm9yRWFjaChmdW5jdGlvbiAoY2xvbmUsIGkpIHtcbiAgICB2YXIgdGFyZ2V0ID0gcm9vdEVsLmNoaWxkcmVuW2Nsb25lLnNvcnRhYmxlSW5kZXggKyAoZWxlbWVudHNJbnNlcnRlZCA/IE51bWJlcihpKSA6IDApXTtcblxuICAgIGlmICh0YXJnZXQpIHtcbiAgICAgIHJvb3RFbC5pbnNlcnRCZWZvcmUoY2xvbmUsIHRhcmdldCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJvb3RFbC5hcHBlbmRDaGlsZChjbG9uZSk7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlTXVsdGlEcmFnRWxlbWVudHMoKSB7XG4gIG11bHRpRHJhZ0VsZW1lbnRzLmZvckVhY2goZnVuY3Rpb24gKG11bHRpRHJhZ0VsZW1lbnQpIHtcbiAgICBpZiAobXVsdGlEcmFnRWxlbWVudCA9PT0gZHJhZ0VsJDEpIHJldHVybjtcbiAgICBtdWx0aURyYWdFbGVtZW50LnBhcmVudE5vZGUgJiYgbXVsdGlEcmFnRWxlbWVudC5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG11bHRpRHJhZ0VsZW1lbnQpO1xuICB9KTtcbn1cblxuU29ydGFibGUubW91bnQobmV3IEF1dG9TY3JvbGxQbHVnaW4oKSk7XG5Tb3J0YWJsZS5tb3VudChSZW1vdmUsIFJldmVydCk7XG5cbmV4cG9ydCBkZWZhdWx0IFNvcnRhYmxlO1xuZXhwb3J0IHsgTXVsdGlEcmFnUGx1Z2luIGFzIE11bHRpRHJhZywgU29ydGFibGUsIFN3YXBQbHVnaW4gYXMgU3dhcCB9O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvc29ydGFibGVqcy9tb2R1bGFyL3NvcnRhYmxlLmVzbS5qc1xuLy8gbW9kdWxlIGlkID0gL2RPMlxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:////dO2\n")},"/n6Q":function(module,exports,__webpack_require__){eval('__webpack_require__("zQR9");\n__webpack_require__("+tPU");\nmodule.exports = __webpack_require__("Kh4W").f(\'iterator\');\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL242US5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vc3ltYm9sL2l0ZXJhdG9yLmpzP2ZlN2UiXSwic291cmNlc0NvbnRlbnQiOlsicmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYuc3RyaW5nLml0ZXJhdG9yJyk7XG5yZXF1aXJlKCcuLi8uLi9tb2R1bGVzL3dlYi5kb20uaXRlcmFibGUnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9fd2tzLWV4dCcpLmYoJ2l0ZXJhdG9yJyk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vc3ltYm9sL2l0ZXJhdG9yLmpzXG4vLyBtb2R1bGUgaWQgPSAvbjZRXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:////n6Q\n')},"/ocq":function(module,__webpack_exports__,__webpack_require__){"use strict";eval("/*!\n * vue-router v3.5.1\n * (c) 2021 Evan You\n * @license MIT\n */\n/* */\n\nfunction assert (condition, message) {\n if (!condition) {\n throw new Error((\"[vue-router] \" + message))\n }\n}\n\nfunction warn (condition, message) {\n if (false) {\n typeof console !== 'undefined' && console.warn((\"[vue-router] \" + message));\n }\n}\n\nfunction extend (a, b) {\n for (var key in b) {\n a[key] = b[key];\n }\n return a\n}\n\n/* */\n\nvar encodeReserveRE = /[!'()*]/g;\nvar encodeReserveReplacer = function (c) { return '%' + c.charCodeAt(0).toString(16); };\nvar commaRE = /%2C/g;\n\n// fixed encodeURIComponent which is more conformant to RFC3986:\n// - escapes [!'()*]\n// - preserve commas\nvar encode = function (str) { return encodeURIComponent(str)\n .replace(encodeReserveRE, encodeReserveReplacer)\n .replace(commaRE, ','); };\n\nfunction decode (str) {\n try {\n return decodeURIComponent(str)\n } catch (err) {\n if (false) {\n warn(false, (\"Error decoding \\\"\" + str + \"\\\". Leaving it intact.\"));\n }\n }\n return str\n}\n\nfunction resolveQuery (\n query,\n extraQuery,\n _parseQuery\n) {\n if ( extraQuery === void 0 ) extraQuery = {};\n\n var parse = _parseQuery || parseQuery;\n var parsedQuery;\n try {\n parsedQuery = parse(query || '');\n } catch (e) {\n \"production\" !== 'production' && warn(false, e.message);\n parsedQuery = {};\n }\n for (var key in extraQuery) {\n var value = extraQuery[key];\n parsedQuery[key] = Array.isArray(value)\n ? value.map(castQueryParamValue)\n : castQueryParamValue(value);\n }\n return parsedQuery\n}\n\nvar castQueryParamValue = function (value) { return (value == null || typeof value === 'object' ? value : String(value)); };\n\nfunction parseQuery (query) {\n var res = {};\n\n query = query.trim().replace(/^(\\?|#|&)/, '');\n\n if (!query) {\n return res\n }\n\n query.split('&').forEach(function (param) {\n var parts = param.replace(/\\+/g, ' ').split('=');\n var key = decode(parts.shift());\n var val = parts.length > 0 ? decode(parts.join('=')) : null;\n\n if (res[key] === undefined) {\n res[key] = val;\n } else if (Array.isArray(res[key])) {\n res[key].push(val);\n } else {\n res[key] = [res[key], val];\n }\n });\n\n return res\n}\n\nfunction stringifyQuery (obj) {\n var res = obj\n ? Object.keys(obj)\n .map(function (key) {\n var val = obj[key];\n\n if (val === undefined) {\n return ''\n }\n\n if (val === null) {\n return encode(key)\n }\n\n if (Array.isArray(val)) {\n var result = [];\n val.forEach(function (val2) {\n if (val2 === undefined) {\n return\n }\n if (val2 === null) {\n result.push(encode(key));\n } else {\n result.push(encode(key) + '=' + encode(val2));\n }\n });\n return result.join('&')\n }\n\n return encode(key) + '=' + encode(val)\n })\n .filter(function (x) { return x.length > 0; })\n .join('&')\n : null;\n return res ? (\"?\" + res) : ''\n}\n\n/* */\n\nvar trailingSlashRE = /\\/?$/;\n\nfunction createRoute (\n record,\n location,\n redirectedFrom,\n router\n) {\n var stringifyQuery = router && router.options.stringifyQuery;\n\n var query = location.query || {};\n try {\n query = clone(query);\n } catch (e) {}\n\n var route = {\n name: location.name || (record && record.name),\n meta: (record && record.meta) || {},\n path: location.path || '/',\n hash: location.hash || '',\n query: query,\n params: location.params || {},\n fullPath: getFullPath(location, stringifyQuery),\n matched: record ? formatMatch(record) : []\n };\n if (redirectedFrom) {\n route.redirectedFrom = getFullPath(redirectedFrom, stringifyQuery);\n }\n return Object.freeze(route)\n}\n\nfunction clone (value) {\n if (Array.isArray(value)) {\n return value.map(clone)\n } else if (value && typeof value === 'object') {\n var res = {};\n for (var key in value) {\n res[key] = clone(value[key]);\n }\n return res\n } else {\n return value\n }\n}\n\n// the starting route that represents the initial state\nvar START = createRoute(null, {\n path: '/'\n});\n\nfunction formatMatch (record) {\n var res = [];\n while (record) {\n res.unshift(record);\n record = record.parent;\n }\n return res\n}\n\nfunction getFullPath (\n ref,\n _stringifyQuery\n) {\n var path = ref.path;\n var query = ref.query; if ( query === void 0 ) query = {};\n var hash = ref.hash; if ( hash === void 0 ) hash = '';\n\n var stringify = _stringifyQuery || stringifyQuery;\n return (path || '/') + stringify(query) + hash\n}\n\nfunction isSameRoute (a, b, onlyPath) {\n if (b === START) {\n return a === b\n } else if (!b) {\n return false\n } else if (a.path && b.path) {\n return a.path.replace(trailingSlashRE, '') === b.path.replace(trailingSlashRE, '') && (onlyPath ||\n a.hash === b.hash &&\n isObjectEqual(a.query, b.query))\n } else if (a.name && b.name) {\n return (\n a.name === b.name &&\n (onlyPath || (\n a.hash === b.hash &&\n isObjectEqual(a.query, b.query) &&\n isObjectEqual(a.params, b.params))\n )\n )\n } else {\n return false\n }\n}\n\nfunction isObjectEqual (a, b) {\n if ( a === void 0 ) a = {};\n if ( b === void 0 ) b = {};\n\n // handle null value #1566\n if (!a || !b) { return a === b }\n var aKeys = Object.keys(a).sort();\n var bKeys = Object.keys(b).sort();\n if (aKeys.length !== bKeys.length) {\n return false\n }\n return aKeys.every(function (key, i) {\n var aVal = a[key];\n var bKey = bKeys[i];\n if (bKey !== key) { return false }\n var bVal = b[key];\n // query values can be null and undefined\n if (aVal == null || bVal == null) { return aVal === bVal }\n // check nested equality\n if (typeof aVal === 'object' && typeof bVal === 'object') {\n return isObjectEqual(aVal, bVal)\n }\n return String(aVal) === String(bVal)\n })\n}\n\nfunction isIncludedRoute (current, target) {\n return (\n current.path.replace(trailingSlashRE, '/').indexOf(\n target.path.replace(trailingSlashRE, '/')\n ) === 0 &&\n (!target.hash || current.hash === target.hash) &&\n queryIncludes(current.query, target.query)\n )\n}\n\nfunction queryIncludes (current, target) {\n for (var key in target) {\n if (!(key in current)) {\n return false\n }\n }\n return true\n}\n\nfunction handleRouteEntered (route) {\n for (var i = 0; i < route.matched.length; i++) {\n var record = route.matched[i];\n for (var name in record.instances) {\n var instance = record.instances[name];\n var cbs = record.enteredCbs[name];\n if (!instance || !cbs) { continue }\n delete record.enteredCbs[name];\n for (var i$1 = 0; i$1 < cbs.length; i$1++) {\n if (!instance._isBeingDestroyed) { cbs[i$1](instance); }\n }\n }\n }\n}\n\nvar View = {\n name: 'RouterView',\n functional: true,\n props: {\n name: {\n type: String,\n default: 'default'\n }\n },\n render: function render (_, ref) {\n var props = ref.props;\n var children = ref.children;\n var parent = ref.parent;\n var data = ref.data;\n\n // used by devtools to display a router-view badge\n data.routerView = true;\n\n // directly use parent context's createElement() function\n // so that components rendered by router-view can resolve named slots\n var h = parent.$createElement;\n var name = props.name;\n var route = parent.$route;\n var cache = parent._routerViewCache || (parent._routerViewCache = {});\n\n // determine current view depth, also check to see if the tree\n // has been toggled inactive but kept-alive.\n var depth = 0;\n var inactive = false;\n while (parent && parent._routerRoot !== parent) {\n var vnodeData = parent.$vnode ? parent.$vnode.data : {};\n if (vnodeData.routerView) {\n depth++;\n }\n if (vnodeData.keepAlive && parent._directInactive && parent._inactive) {\n inactive = true;\n }\n parent = parent.$parent;\n }\n data.routerViewDepth = depth;\n\n // render previous view if the tree is inactive and kept-alive\n if (inactive) {\n var cachedData = cache[name];\n var cachedComponent = cachedData && cachedData.component;\n if (cachedComponent) {\n // #2301\n // pass props\n if (cachedData.configProps) {\n fillPropsinData(cachedComponent, data, cachedData.route, cachedData.configProps);\n }\n return h(cachedComponent, data, children)\n } else {\n // render previous empty view\n return h()\n }\n }\n\n var matched = route.matched[depth];\n var component = matched && matched.components[name];\n\n // render empty node if no matched route or no config component\n if (!matched || !component) {\n cache[name] = null;\n return h()\n }\n\n // cache component\n cache[name] = { component: component };\n\n // attach instance registration hook\n // this will be called in the instance's injected lifecycle hooks\n data.registerRouteInstance = function (vm, val) {\n // val could be undefined for unregistration\n var current = matched.instances[name];\n if (\n (val && current !== vm) ||\n (!val && current === vm)\n ) {\n matched.instances[name] = val;\n }\n }\n\n // also register instance in prepatch hook\n // in case the same component instance is reused across different routes\n ;(data.hook || (data.hook = {})).prepatch = function (_, vnode) {\n matched.instances[name] = vnode.componentInstance;\n };\n\n // register instance in init hook\n // in case kept-alive component be actived when routes changed\n data.hook.init = function (vnode) {\n if (vnode.data.keepAlive &&\n vnode.componentInstance &&\n vnode.componentInstance !== matched.instances[name]\n ) {\n matched.instances[name] = vnode.componentInstance;\n }\n\n // if the route transition has already been confirmed then we weren't\n // able to call the cbs during confirmation as the component was not\n // registered yet, so we call it here.\n handleRouteEntered(route);\n };\n\n var configProps = matched.props && matched.props[name];\n // save route and configProps in cache\n if (configProps) {\n extend(cache[name], {\n route: route,\n configProps: configProps\n });\n fillPropsinData(component, data, route, configProps);\n }\n\n return h(component, data, children)\n }\n};\n\nfunction fillPropsinData (component, data, route, configProps) {\n // resolve props\n var propsToPass = data.props = resolveProps(route, configProps);\n if (propsToPass) {\n // clone to prevent mutation\n propsToPass = data.props = extend({}, propsToPass);\n // pass non-declared props as attrs\n var attrs = data.attrs = data.attrs || {};\n for (var key in propsToPass) {\n if (!component.props || !(key in component.props)) {\n attrs[key] = propsToPass[key];\n delete propsToPass[key];\n }\n }\n }\n}\n\nfunction resolveProps (route, config) {\n switch (typeof config) {\n case 'undefined':\n return\n case 'object':\n return config\n case 'function':\n return config(route)\n case 'boolean':\n return config ? route.params : undefined\n default:\n if (false) {\n warn(\n false,\n \"props in \\\"\" + (route.path) + \"\\\" is a \" + (typeof config) + \", \" +\n \"expecting an object, function or boolean.\"\n );\n }\n }\n}\n\n/* */\n\nfunction resolvePath (\n relative,\n base,\n append\n) {\n var firstChar = relative.charAt(0);\n if (firstChar === '/') {\n return relative\n }\n\n if (firstChar === '?' || firstChar === '#') {\n return base + relative\n }\n\n var stack = base.split('/');\n\n // remove trailing segment if:\n // - not appending\n // - appending to trailing slash (last segment is empty)\n if (!append || !stack[stack.length - 1]) {\n stack.pop();\n }\n\n // resolve relative path\n var segments = relative.replace(/^\\//, '').split('/');\n for (var i = 0; i < segments.length; i++) {\n var segment = segments[i];\n if (segment === '..') {\n stack.pop();\n } else if (segment !== '.') {\n stack.push(segment);\n }\n }\n\n // ensure leading slash\n if (stack[0] !== '') {\n stack.unshift('');\n }\n\n return stack.join('/')\n}\n\nfunction parsePath (path) {\n var hash = '';\n var query = '';\n\n var hashIndex = path.indexOf('#');\n if (hashIndex >= 0) {\n hash = path.slice(hashIndex);\n path = path.slice(0, hashIndex);\n }\n\n var queryIndex = path.indexOf('?');\n if (queryIndex >= 0) {\n query = path.slice(queryIndex + 1);\n path = path.slice(0, queryIndex);\n }\n\n return {\n path: path,\n query: query,\n hash: hash\n }\n}\n\nfunction cleanPath (path) {\n return path.replace(/\\/\\//g, '/')\n}\n\nvar isarray = Array.isArray || function (arr) {\n return Object.prototype.toString.call(arr) == '[object Array]';\n};\n\n/**\n * Expose `pathToRegexp`.\n */\nvar pathToRegexp_1 = pathToRegexp;\nvar parse_1 = parse;\nvar compile_1 = compile;\nvar tokensToFunction_1 = tokensToFunction;\nvar tokensToRegExp_1 = tokensToRegExp;\n\n/**\n * The main path matching regexp utility.\n *\n * @type {RegExp}\n */\nvar PATH_REGEXP = new RegExp([\n // Match escaped characters that would otherwise appear in future matches.\n // This allows the user to escape special characters that won't transform.\n '(\\\\\\\\.)',\n // Match Express-style parameters and un-named parameters with a prefix\n // and optional suffixes. Matches appear as:\n //\n // \"/:test(\\\\d+)?\" => [\"/\", \"test\", \"\\d+\", undefined, \"?\", undefined]\n // \"/route(\\\\d+)\" => [undefined, undefined, undefined, \"\\d+\", undefined, undefined]\n // \"/*\" => [\"/\", undefined, undefined, undefined, undefined, \"*\"]\n '([\\\\/.])?(?:(?:\\\\:(\\\\w+)(?:\\\\(((?:\\\\\\\\.|[^\\\\\\\\()])+)\\\\))?|\\\\(((?:\\\\\\\\.|[^\\\\\\\\()])+)\\\\))([+*?])?|(\\\\*))'\n].join('|'), 'g');\n\n/**\n * Parse a string for the raw tokens.\n *\n * @param {string} str\n * @param {Object=} options\n * @return {!Array}\n */\nfunction parse (str, options) {\n var tokens = [];\n var key = 0;\n var index = 0;\n var path = '';\n var defaultDelimiter = options && options.delimiter || '/';\n var res;\n\n while ((res = PATH_REGEXP.exec(str)) != null) {\n var m = res[0];\n var escaped = res[1];\n var offset = res.index;\n path += str.slice(index, offset);\n index = offset + m.length;\n\n // Ignore already escaped sequences.\n if (escaped) {\n path += escaped[1];\n continue\n }\n\n var next = str[index];\n var prefix = res[2];\n var name = res[3];\n var capture = res[4];\n var group = res[5];\n var modifier = res[6];\n var asterisk = res[7];\n\n // Push the current path onto the tokens.\n if (path) {\n tokens.push(path);\n path = '';\n }\n\n var partial = prefix != null && next != null && next !== prefix;\n var repeat = modifier === '+' || modifier === '*';\n var optional = modifier === '?' || modifier === '*';\n var delimiter = res[2] || defaultDelimiter;\n var pattern = capture || group;\n\n tokens.push({\n name: name || key++,\n prefix: prefix || '',\n delimiter: delimiter,\n optional: optional,\n repeat: repeat,\n partial: partial,\n asterisk: !!asterisk,\n pattern: pattern ? escapeGroup(pattern) : (asterisk ? '.*' : '[^' + escapeString(delimiter) + ']+?')\n });\n }\n\n // Match any characters still remaining.\n if (index < str.length) {\n path += str.substr(index);\n }\n\n // If the path exists, push it onto the end.\n if (path) {\n tokens.push(path);\n }\n\n return tokens\n}\n\n/**\n * Compile a string to a template function for the path.\n *\n * @param {string} str\n * @param {Object=} options\n * @return {!function(Object=, Object=)}\n */\nfunction compile (str, options) {\n return tokensToFunction(parse(str, options), options)\n}\n\n/**\n * Prettier encoding of URI path segments.\n *\n * @param {string}\n * @return {string}\n */\nfunction encodeURIComponentPretty (str) {\n return encodeURI(str).replace(/[\\/?#]/g, function (c) {\n return '%' + c.charCodeAt(0).toString(16).toUpperCase()\n })\n}\n\n/**\n * Encode the asterisk parameter. Similar to `pretty`, but allows slashes.\n *\n * @param {string}\n * @return {string}\n */\nfunction encodeAsterisk (str) {\n return encodeURI(str).replace(/[?#]/g, function (c) {\n return '%' + c.charCodeAt(0).toString(16).toUpperCase()\n })\n}\n\n/**\n * Expose a method for transforming tokens into the path function.\n */\nfunction tokensToFunction (tokens, options) {\n // Compile all the tokens into regexps.\n var matches = new Array(tokens.length);\n\n // Compile all the patterns before compilation.\n for (var i = 0; i < tokens.length; i++) {\n if (typeof tokens[i] === 'object') {\n matches[i] = new RegExp('^(?:' + tokens[i].pattern + ')$', flags(options));\n }\n }\n\n return function (obj, opts) {\n var path = '';\n var data = obj || {};\n var options = opts || {};\n var encode = options.pretty ? encodeURIComponentPretty : encodeURIComponent;\n\n for (var i = 0; i < tokens.length; i++) {\n var token = tokens[i];\n\n if (typeof token === 'string') {\n path += token;\n\n continue\n }\n\n var value = data[token.name];\n var segment;\n\n if (value == null) {\n if (token.optional) {\n // Prepend partial segment prefixes.\n if (token.partial) {\n path += token.prefix;\n }\n\n continue\n } else {\n throw new TypeError('Expected \"' + token.name + '\" to be defined')\n }\n }\n\n if (isarray(value)) {\n if (!token.repeat) {\n throw new TypeError('Expected \"' + token.name + '\" to not repeat, but received `' + JSON.stringify(value) + '`')\n }\n\n if (value.length === 0) {\n if (token.optional) {\n continue\n } else {\n throw new TypeError('Expected \"' + token.name + '\" to not be empty')\n }\n }\n\n for (var j = 0; j < value.length; j++) {\n segment = encode(value[j]);\n\n if (!matches[i].test(segment)) {\n throw new TypeError('Expected all \"' + token.name + '\" to match \"' + token.pattern + '\", but received `' + JSON.stringify(segment) + '`')\n }\n\n path += (j === 0 ? token.prefix : token.delimiter) + segment;\n }\n\n continue\n }\n\n segment = token.asterisk ? encodeAsterisk(value) : encode(value);\n\n if (!matches[i].test(segment)) {\n throw new TypeError('Expected \"' + token.name + '\" to match \"' + token.pattern + '\", but received \"' + segment + '\"')\n }\n\n path += token.prefix + segment;\n }\n\n return path\n }\n}\n\n/**\n * Escape a regular expression string.\n *\n * @param {string} str\n * @return {string}\n */\nfunction escapeString (str) {\n return str.replace(/([.+*?=^!:${}()[\\]|\\/\\\\])/g, '\\\\$1')\n}\n\n/**\n * Escape the capturing group by escaping special characters and meaning.\n *\n * @param {string} group\n * @return {string}\n */\nfunction escapeGroup (group) {\n return group.replace(/([=!:$\\/()])/g, '\\\\$1')\n}\n\n/**\n * Attach the keys as a property of the regexp.\n *\n * @param {!RegExp} re\n * @param {Array} keys\n * @return {!RegExp}\n */\nfunction attachKeys (re, keys) {\n re.keys = keys;\n return re\n}\n\n/**\n * Get the flags for a regexp from the options.\n *\n * @param {Object} options\n * @return {string}\n */\nfunction flags (options) {\n return options && options.sensitive ? '' : 'i'\n}\n\n/**\n * Pull out keys from a regexp.\n *\n * @param {!RegExp} path\n * @param {!Array} keys\n * @return {!RegExp}\n */\nfunction regexpToRegexp (path, keys) {\n // Use a negative lookahead to match only capturing groups.\n var groups = path.source.match(/\\((?!\\?)/g);\n\n if (groups) {\n for (var i = 0; i < groups.length; i++) {\n keys.push({\n name: i,\n prefix: null,\n delimiter: null,\n optional: false,\n repeat: false,\n partial: false,\n asterisk: false,\n pattern: null\n });\n }\n }\n\n return attachKeys(path, keys)\n}\n\n/**\n * Transform an array into a regexp.\n *\n * @param {!Array} path\n * @param {Array} keys\n * @param {!Object} options\n * @return {!RegExp}\n */\nfunction arrayToRegexp (path, keys, options) {\n var parts = [];\n\n for (var i = 0; i < path.length; i++) {\n parts.push(pathToRegexp(path[i], keys, options).source);\n }\n\n var regexp = new RegExp('(?:' + parts.join('|') + ')', flags(options));\n\n return attachKeys(regexp, keys)\n}\n\n/**\n * Create a path regexp from string input.\n *\n * @param {string} path\n * @param {!Array} keys\n * @param {!Object} options\n * @return {!RegExp}\n */\nfunction stringToRegexp (path, keys, options) {\n return tokensToRegExp(parse(path, options), keys, options)\n}\n\n/**\n * Expose a function for taking tokens and returning a RegExp.\n *\n * @param {!Array} tokens\n * @param {(Array|Object)=} keys\n * @param {Object=} options\n * @return {!RegExp}\n */\nfunction tokensToRegExp (tokens, keys, options) {\n if (!isarray(keys)) {\n options = /** @type {!Object} */ (keys || options);\n keys = [];\n }\n\n options = options || {};\n\n var strict = options.strict;\n var end = options.end !== false;\n var route = '';\n\n // Iterate over the tokens and create our regexp string.\n for (var i = 0; i < tokens.length; i++) {\n var token = tokens[i];\n\n if (typeof token === 'string') {\n route += escapeString(token);\n } else {\n var prefix = escapeString(token.prefix);\n var capture = '(?:' + token.pattern + ')';\n\n keys.push(token);\n\n if (token.repeat) {\n capture += '(?:' + prefix + capture + ')*';\n }\n\n if (token.optional) {\n if (!token.partial) {\n capture = '(?:' + prefix + '(' + capture + '))?';\n } else {\n capture = prefix + '(' + capture + ')?';\n }\n } else {\n capture = prefix + '(' + capture + ')';\n }\n\n route += capture;\n }\n }\n\n var delimiter = escapeString(options.delimiter || '/');\n var endsWithDelimiter = route.slice(-delimiter.length) === delimiter;\n\n // In non-strict mode we allow a slash at the end of match. If the path to\n // match already ends with a slash, we remove it for consistency. The slash\n // is valid at the end of a path match, not in the middle. This is important\n // in non-ending mode, where \"/test/\" shouldn't match \"/test//route\".\n if (!strict) {\n route = (endsWithDelimiter ? route.slice(0, -delimiter.length) : route) + '(?:' + delimiter + '(?=$))?';\n }\n\n if (end) {\n route += '$';\n } else {\n // In non-ending mode, we need the capturing groups to match as much as\n // possible by using a positive lookahead to the end or next path segment.\n route += strict && endsWithDelimiter ? '' : '(?=' + delimiter + '|$)';\n }\n\n return attachKeys(new RegExp('^' + route, flags(options)), keys)\n}\n\n/**\n * Normalize the given path string, returning a regular expression.\n *\n * An empty array can be passed in for the keys, which will hold the\n * placeholder key descriptions. For example, using `/user/:id`, `keys` will\n * contain `[{ name: 'id', delimiter: '/', optional: false, repeat: false }]`.\n *\n * @param {(string|RegExp|Array)} path\n * @param {(Array|Object)=} keys\n * @param {Object=} options\n * @return {!RegExp}\n */\nfunction pathToRegexp (path, keys, options) {\n if (!isarray(keys)) {\n options = /** @type {!Object} */ (keys || options);\n keys = [];\n }\n\n options = options || {};\n\n if (path instanceof RegExp) {\n return regexpToRegexp(path, /** @type {!Array} */ (keys))\n }\n\n if (isarray(path)) {\n return arrayToRegexp(/** @type {!Array} */ (path), /** @type {!Array} */ (keys), options)\n }\n\n return stringToRegexp(/** @type {string} */ (path), /** @type {!Array} */ (keys), options)\n}\npathToRegexp_1.parse = parse_1;\npathToRegexp_1.compile = compile_1;\npathToRegexp_1.tokensToFunction = tokensToFunction_1;\npathToRegexp_1.tokensToRegExp = tokensToRegExp_1;\n\n/* */\n\n// $flow-disable-line\nvar regexpCompileCache = Object.create(null);\n\nfunction fillParams (\n path,\n params,\n routeMsg\n) {\n params = params || {};\n try {\n var filler =\n regexpCompileCache[path] ||\n (regexpCompileCache[path] = pathToRegexp_1.compile(path));\n\n // Fix #2505 resolving asterisk routes { name: 'not-found', params: { pathMatch: '/not-found' }}\n // and fix #3106 so that you can work with location descriptor object having params.pathMatch equal to empty string\n if (typeof params.pathMatch === 'string') { params[0] = params.pathMatch; }\n\n return filler(params, { pretty: true })\n } catch (e) {\n if (false) {\n // Fix #3072 no warn if `pathMatch` is string\n warn(typeof params.pathMatch === 'string', (\"missing param for \" + routeMsg + \": \" + (e.message)));\n }\n return ''\n } finally {\n // delete the 0 if it was added\n delete params[0];\n }\n}\n\n/* */\n\nfunction normalizeLocation (\n raw,\n current,\n append,\n router\n) {\n var next = typeof raw === 'string' ? { path: raw } : raw;\n // named target\n if (next._normalized) {\n return next\n } else if (next.name) {\n next = extend({}, raw);\n var params = next.params;\n if (params && typeof params === 'object') {\n next.params = extend({}, params);\n }\n return next\n }\n\n // relative params\n if (!next.path && next.params && current) {\n next = extend({}, next);\n next._normalized = true;\n var params$1 = extend(extend({}, current.params), next.params);\n if (current.name) {\n next.name = current.name;\n next.params = params$1;\n } else if (current.matched.length) {\n var rawPath = current.matched[current.matched.length - 1].path;\n next.path = fillParams(rawPath, params$1, (\"path \" + (current.path)));\n } else if (false) {\n warn(false, \"relative params navigation requires a current route.\");\n }\n return next\n }\n\n var parsedPath = parsePath(next.path || '');\n var basePath = (current && current.path) || '/';\n var path = parsedPath.path\n ? resolvePath(parsedPath.path, basePath, append || next.append)\n : basePath;\n\n var query = resolveQuery(\n parsedPath.query,\n next.query,\n router && router.options.parseQuery\n );\n\n var hash = next.hash || parsedPath.hash;\n if (hash && hash.charAt(0) !== '#') {\n hash = \"#\" + hash;\n }\n\n return {\n _normalized: true,\n path: path,\n query: query,\n hash: hash\n }\n}\n\n/* */\n\n// work around weird flow bug\nvar toTypes = [String, Object];\nvar eventTypes = [String, Array];\n\nvar noop = function () {};\n\nvar warnedCustomSlot;\nvar warnedTagProp;\nvar warnedEventProp;\n\nvar Link = {\n name: 'RouterLink',\n props: {\n to: {\n type: toTypes,\n required: true\n },\n tag: {\n type: String,\n default: 'a'\n },\n custom: Boolean,\n exact: Boolean,\n exactPath: Boolean,\n append: Boolean,\n replace: Boolean,\n activeClass: String,\n exactActiveClass: String,\n ariaCurrentValue: {\n type: String,\n default: 'page'\n },\n event: {\n type: eventTypes,\n default: 'click'\n }\n },\n render: function render (h) {\n var this$1 = this;\n\n var router = this.$router;\n var current = this.$route;\n var ref = router.resolve(\n this.to,\n current,\n this.append\n );\n var location = ref.location;\n var route = ref.route;\n var href = ref.href;\n\n var classes = {};\n var globalActiveClass = router.options.linkActiveClass;\n var globalExactActiveClass = router.options.linkExactActiveClass;\n // Support global empty active class\n var activeClassFallback =\n globalActiveClass == null ? 'router-link-active' : globalActiveClass;\n var exactActiveClassFallback =\n globalExactActiveClass == null\n ? 'router-link-exact-active'\n : globalExactActiveClass;\n var activeClass =\n this.activeClass == null ? activeClassFallback : this.activeClass;\n var exactActiveClass =\n this.exactActiveClass == null\n ? exactActiveClassFallback\n : this.exactActiveClass;\n\n var compareTarget = route.redirectedFrom\n ? createRoute(null, normalizeLocation(route.redirectedFrom), null, router)\n : route;\n\n classes[exactActiveClass] = isSameRoute(current, compareTarget, this.exactPath);\n classes[activeClass] = this.exact || this.exactPath\n ? classes[exactActiveClass]\n : isIncludedRoute(current, compareTarget);\n\n var ariaCurrentValue = classes[exactActiveClass] ? this.ariaCurrentValue : null;\n\n var handler = function (e) {\n if (guardEvent(e)) {\n if (this$1.replace) {\n router.replace(location, noop);\n } else {\n router.push(location, noop);\n }\n }\n };\n\n var on = { click: guardEvent };\n if (Array.isArray(this.event)) {\n this.event.forEach(function (e) {\n on[e] = handler;\n });\n } else {\n on[this.event] = handler;\n }\n\n var data = { class: classes };\n\n var scopedSlot =\n !this.$scopedSlots.$hasNormal &&\n this.$scopedSlots.default &&\n this.$scopedSlots.default({\n href: href,\n route: route,\n navigate: handler,\n isActive: classes[activeClass],\n isExactActive: classes[exactActiveClass]\n });\n\n if (scopedSlot) {\n if (false) {\n !warnedCustomSlot && warn(false, 'In Vue Router 4, the v-slot API will by default wrap its content with an element. Use the custom prop to remove this warning:\\n\\n');\n warnedCustomSlot = true;\n }\n if (scopedSlot.length === 1) {\n return scopedSlot[0]\n } else if (scopedSlot.length > 1 || !scopedSlot.length) {\n if (false) {\n warn(\n false,\n (\" with to=\\\"\" + (this.to) + \"\\\" is trying to use a scoped slot but it didn't provide exactly one child. Wrapping the content with a span element.\")\n );\n }\n return scopedSlot.length === 0 ? h() : h('span', {}, scopedSlot)\n }\n }\n\n if (false) {\n if ('tag' in this.$options.propsData && !warnedTagProp) {\n warn(\n false,\n \"'s tag prop is deprecated and has been removed in Vue Router 4. Use the v-slot API to remove this warning: https://next.router.vuejs.org/guide/migration/#removal-of-event-and-tag-props-in-router-link.\"\n );\n warnedTagProp = true;\n }\n if ('event' in this.$options.propsData && !warnedEventProp) {\n warn(\n false,\n \"'s event prop is deprecated and has been removed in Vue Router 4. Use the v-slot API to remove this warning: https://next.router.vuejs.org/guide/migration/#removal-of-event-and-tag-props-in-router-link.\"\n );\n warnedEventProp = true;\n }\n }\n\n if (this.tag === 'a') {\n data.on = on;\n data.attrs = { href: href, 'aria-current': ariaCurrentValue };\n } else {\n // find the first child and apply listener and href\n var a = findAnchor(this.$slots.default);\n if (a) {\n // in case the is a static node\n a.isStatic = false;\n var aData = (a.data = extend({}, a.data));\n aData.on = aData.on || {};\n // transform existing events in both objects into arrays so we can push later\n for (var event in aData.on) {\n var handler$1 = aData.on[event];\n if (event in on) {\n aData.on[event] = Array.isArray(handler$1) ? handler$1 : [handler$1];\n }\n }\n // append new listeners for router-link\n for (var event$1 in on) {\n if (event$1 in aData.on) {\n // on[event] is always a function\n aData.on[event$1].push(on[event$1]);\n } else {\n aData.on[event$1] = handler;\n }\n }\n\n var aAttrs = (a.data.attrs = extend({}, a.data.attrs));\n aAttrs.href = href;\n aAttrs['aria-current'] = ariaCurrentValue;\n } else {\n // doesn't have child, apply listener to self\n data.on = on;\n }\n }\n\n return h(this.tag, data, this.$slots.default)\n }\n};\n\nfunction guardEvent (e) {\n // don't redirect with control keys\n if (e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) { return }\n // don't redirect when preventDefault called\n if (e.defaultPrevented) { return }\n // don't redirect on right click\n if (e.button !== undefined && e.button !== 0) { return }\n // don't redirect if `target=\"_blank\"`\n if (e.currentTarget && e.currentTarget.getAttribute) {\n var target = e.currentTarget.getAttribute('target');\n if (/\\b_blank\\b/i.test(target)) { return }\n }\n // this may be a Weex event which doesn't have this method\n if (e.preventDefault) {\n e.preventDefault();\n }\n return true\n}\n\nfunction findAnchor (children) {\n if (children) {\n var child;\n for (var i = 0; i < children.length; i++) {\n child = children[i];\n if (child.tag === 'a') {\n return child\n }\n if (child.children && (child = findAnchor(child.children))) {\n return child\n }\n }\n }\n}\n\nvar _Vue;\n\nfunction install (Vue) {\n if (install.installed && _Vue === Vue) { return }\n install.installed = true;\n\n _Vue = Vue;\n\n var isDef = function (v) { return v !== undefined; };\n\n var registerInstance = function (vm, callVal) {\n var i = vm.$options._parentVnode;\n if (isDef(i) && isDef(i = i.data) && isDef(i = i.registerRouteInstance)) {\n i(vm, callVal);\n }\n };\n\n Vue.mixin({\n beforeCreate: function beforeCreate () {\n if (isDef(this.$options.router)) {\n this._routerRoot = this;\n this._router = this.$options.router;\n this._router.init(this);\n Vue.util.defineReactive(this, '_route', this._router.history.current);\n } else {\n this._routerRoot = (this.$parent && this.$parent._routerRoot) || this;\n }\n registerInstance(this, this);\n },\n destroyed: function destroyed () {\n registerInstance(this);\n }\n });\n\n Object.defineProperty(Vue.prototype, '$router', {\n get: function get () { return this._routerRoot._router }\n });\n\n Object.defineProperty(Vue.prototype, '$route', {\n get: function get () { return this._routerRoot._route }\n });\n\n Vue.component('RouterView', View);\n Vue.component('RouterLink', Link);\n\n var strats = Vue.config.optionMergeStrategies;\n // use the same hook merging strategy for route hooks\n strats.beforeRouteEnter = strats.beforeRouteLeave = strats.beforeRouteUpdate = strats.created;\n}\n\n/* */\n\nvar inBrowser = typeof window !== 'undefined';\n\n/* */\n\nfunction createRouteMap (\n routes,\n oldPathList,\n oldPathMap,\n oldNameMap,\n parentRoute\n) {\n // the path list is used to control path matching priority\n var pathList = oldPathList || [];\n // $flow-disable-line\n var pathMap = oldPathMap || Object.create(null);\n // $flow-disable-line\n var nameMap = oldNameMap || Object.create(null);\n\n routes.forEach(function (route) {\n addRouteRecord(pathList, pathMap, nameMap, route, parentRoute);\n });\n\n // ensure wildcard routes are always at the end\n for (var i = 0, l = pathList.length; i < l; i++) {\n if (pathList[i] === '*') {\n pathList.push(pathList.splice(i, 1)[0]);\n l--;\n i--;\n }\n }\n\n if (false) {\n // warn if routes do not include leading slashes\n var found = pathList\n // check for missing leading slash\n .filter(function (path) { return path && path.charAt(0) !== '*' && path.charAt(0) !== '/'; });\n\n if (found.length > 0) {\n var pathNames = found.map(function (path) { return (\"- \" + path); }).join('\\n');\n warn(false, (\"Non-nested routes must include a leading slash character. Fix the following routes: \\n\" + pathNames));\n }\n }\n\n return {\n pathList: pathList,\n pathMap: pathMap,\n nameMap: nameMap\n }\n}\n\nfunction addRouteRecord (\n pathList,\n pathMap,\n nameMap,\n route,\n parent,\n matchAs\n) {\n var path = route.path;\n var name = route.name;\n if (false) {\n assert(path != null, \"\\\"path\\\" is required in a route configuration.\");\n assert(\n typeof route.component !== 'string',\n \"route config \\\"component\\\" for path: \" + (String(\n path || name\n )) + \" cannot be a \" + \"string id. Use an actual component instead.\"\n );\n\n warn(\n // eslint-disable-next-line no-control-regex\n !/[^\\u0000-\\u007F]+/.test(path),\n \"Route with path \\\"\" + path + \"\\\" contains unencoded characters, make sure \" +\n \"your path is correctly encoded before passing it to the router. Use \" +\n \"encodeURI to encode static segments of your path.\"\n );\n }\n\n var pathToRegexpOptions =\n route.pathToRegexpOptions || {};\n var normalizedPath = normalizePath(path, parent, pathToRegexpOptions.strict);\n\n if (typeof route.caseSensitive === 'boolean') {\n pathToRegexpOptions.sensitive = route.caseSensitive;\n }\n\n var record = {\n path: normalizedPath,\n regex: compileRouteRegex(normalizedPath, pathToRegexpOptions),\n components: route.components || { default: route.component },\n alias: route.alias\n ? typeof route.alias === 'string'\n ? [route.alias]\n : route.alias\n : [],\n instances: {},\n enteredCbs: {},\n name: name,\n parent: parent,\n matchAs: matchAs,\n redirect: route.redirect,\n beforeEnter: route.beforeEnter,\n meta: route.meta || {},\n props:\n route.props == null\n ? {}\n : route.components\n ? route.props\n : { default: route.props }\n };\n\n if (route.children) {\n // Warn if route is named, does not redirect and has a default child route.\n // If users navigate to this route by name, the default child will\n // not be rendered (GH Issue #629)\n if (false) {\n if (\n route.name &&\n !route.redirect &&\n route.children.some(function (child) { return /^\\/?$/.test(child.path); })\n ) {\n warn(\n false,\n \"Named Route '\" + (route.name) + \"' has a default child route. \" +\n \"When navigating to this named route (:to=\\\"{name: '\" + (route.name) + \"'\\\"), \" +\n \"the default child route will not be rendered. Remove the name from \" +\n \"this route and use the name of the default child route for named \" +\n \"links instead.\"\n );\n }\n }\n route.children.forEach(function (child) {\n var childMatchAs = matchAs\n ? cleanPath((matchAs + \"/\" + (child.path)))\n : undefined;\n addRouteRecord(pathList, pathMap, nameMap, child, record, childMatchAs);\n });\n }\n\n if (!pathMap[record.path]) {\n pathList.push(record.path);\n pathMap[record.path] = record;\n }\n\n if (route.alias !== undefined) {\n var aliases = Array.isArray(route.alias) ? route.alias : [route.alias];\n for (var i = 0; i < aliases.length; ++i) {\n var alias = aliases[i];\n if (false) {\n warn(\n false,\n (\"Found an alias with the same value as the path: \\\"\" + path + \"\\\". You have to remove that alias. It will be ignored in development.\")\n );\n // skip in dev to make it work\n continue\n }\n\n var aliasRoute = {\n path: alias,\n children: route.children\n };\n addRouteRecord(\n pathList,\n pathMap,\n nameMap,\n aliasRoute,\n parent,\n record.path || '/' // matchAs\n );\n }\n }\n\n if (name) {\n if (!nameMap[name]) {\n nameMap[name] = record;\n } else if (false) {\n warn(\n false,\n \"Duplicate named routes definition: \" +\n \"{ name: \\\"\" + name + \"\\\", path: \\\"\" + (record.path) + \"\\\" }\"\n );\n }\n }\n}\n\nfunction compileRouteRegex (\n path,\n pathToRegexpOptions\n) {\n var regex = pathToRegexp_1(path, [], pathToRegexpOptions);\n if (false) {\n var keys = Object.create(null);\n regex.keys.forEach(function (key) {\n warn(\n !keys[key.name],\n (\"Duplicate param keys in route with path: \\\"\" + path + \"\\\"\")\n );\n keys[key.name] = true;\n });\n }\n return regex\n}\n\nfunction normalizePath (\n path,\n parent,\n strict\n) {\n if (!strict) { path = path.replace(/\\/$/, ''); }\n if (path[0] === '/') { return path }\n if (parent == null) { return path }\n return cleanPath(((parent.path) + \"/\" + path))\n}\n\n/* */\n\n\n\nfunction createMatcher (\n routes,\n router\n) {\n var ref = createRouteMap(routes);\n var pathList = ref.pathList;\n var pathMap = ref.pathMap;\n var nameMap = ref.nameMap;\n\n function addRoutes (routes) {\n createRouteMap(routes, pathList, pathMap, nameMap);\n }\n\n function addRoute (parentOrRoute, route) {\n var parent = (typeof parentOrRoute !== 'object') ? nameMap[parentOrRoute] : undefined;\n // $flow-disable-line\n createRouteMap([route || parentOrRoute], pathList, pathMap, nameMap, parent);\n\n // add aliases of parent\n if (parent) {\n createRouteMap(\n // $flow-disable-line route is defined if parent is\n parent.alias.map(function (alias) { return ({ path: alias, children: [route] }); }),\n pathList,\n pathMap,\n nameMap,\n parent\n );\n }\n }\n\n function getRoutes () {\n return pathList.map(function (path) { return pathMap[path]; })\n }\n\n function match (\n raw,\n currentRoute,\n redirectedFrom\n ) {\n var location = normalizeLocation(raw, currentRoute, false, router);\n var name = location.name;\n\n if (name) {\n var record = nameMap[name];\n if (false) {\n warn(record, (\"Route with name '\" + name + \"' does not exist\"));\n }\n if (!record) { return _createRoute(null, location) }\n var paramNames = record.regex.keys\n .filter(function (key) { return !key.optional; })\n .map(function (key) { return key.name; });\n\n if (typeof location.params !== 'object') {\n location.params = {};\n }\n\n if (currentRoute && typeof currentRoute.params === 'object') {\n for (var key in currentRoute.params) {\n if (!(key in location.params) && paramNames.indexOf(key) > -1) {\n location.params[key] = currentRoute.params[key];\n }\n }\n }\n\n location.path = fillParams(record.path, location.params, (\"named route \\\"\" + name + \"\\\"\"));\n return _createRoute(record, location, redirectedFrom)\n } else if (location.path) {\n location.params = {};\n for (var i = 0; i < pathList.length; i++) {\n var path = pathList[i];\n var record$1 = pathMap[path];\n if (matchRoute(record$1.regex, location.path, location.params)) {\n return _createRoute(record$1, location, redirectedFrom)\n }\n }\n }\n // no match\n return _createRoute(null, location)\n }\n\n function redirect (\n record,\n location\n ) {\n var originalRedirect = record.redirect;\n var redirect = typeof originalRedirect === 'function'\n ? originalRedirect(createRoute(record, location, null, router))\n : originalRedirect;\n\n if (typeof redirect === 'string') {\n redirect = { path: redirect };\n }\n\n if (!redirect || typeof redirect !== 'object') {\n if (false) {\n warn(\n false, (\"invalid redirect option: \" + (JSON.stringify(redirect)))\n );\n }\n return _createRoute(null, location)\n }\n\n var re = redirect;\n var name = re.name;\n var path = re.path;\n var query = location.query;\n var hash = location.hash;\n var params = location.params;\n query = re.hasOwnProperty('query') ? re.query : query;\n hash = re.hasOwnProperty('hash') ? re.hash : hash;\n params = re.hasOwnProperty('params') ? re.params : params;\n\n if (name) {\n // resolved named direct\n var targetRecord = nameMap[name];\n if (false) {\n assert(targetRecord, (\"redirect failed: named route \\\"\" + name + \"\\\" not found.\"));\n }\n return match({\n _normalized: true,\n name: name,\n query: query,\n hash: hash,\n params: params\n }, undefined, location)\n } else if (path) {\n // 1. resolve relative redirect\n var rawPath = resolveRecordPath(path, record);\n // 2. resolve params\n var resolvedPath = fillParams(rawPath, params, (\"redirect route with path \\\"\" + rawPath + \"\\\"\"));\n // 3. rematch with existing query and hash\n return match({\n _normalized: true,\n path: resolvedPath,\n query: query,\n hash: hash\n }, undefined, location)\n } else {\n if (false) {\n warn(false, (\"invalid redirect option: \" + (JSON.stringify(redirect))));\n }\n return _createRoute(null, location)\n }\n }\n\n function alias (\n record,\n location,\n matchAs\n ) {\n var aliasedPath = fillParams(matchAs, location.params, (\"aliased route with path \\\"\" + matchAs + \"\\\"\"));\n var aliasedMatch = match({\n _normalized: true,\n path: aliasedPath\n });\n if (aliasedMatch) {\n var matched = aliasedMatch.matched;\n var aliasedRecord = matched[matched.length - 1];\n location.params = aliasedMatch.params;\n return _createRoute(aliasedRecord, location)\n }\n return _createRoute(null, location)\n }\n\n function _createRoute (\n record,\n location,\n redirectedFrom\n ) {\n if (record && record.redirect) {\n return redirect(record, redirectedFrom || location)\n }\n if (record && record.matchAs) {\n return alias(record, location, record.matchAs)\n }\n return createRoute(record, location, redirectedFrom, router)\n }\n\n return {\n match: match,\n addRoute: addRoute,\n getRoutes: getRoutes,\n addRoutes: addRoutes\n }\n}\n\nfunction matchRoute (\n regex,\n path,\n params\n) {\n var m = path.match(regex);\n\n if (!m) {\n return false\n } else if (!params) {\n return true\n }\n\n for (var i = 1, len = m.length; i < len; ++i) {\n var key = regex.keys[i - 1];\n if (key) {\n // Fix #1994: using * with props: true generates a param named 0\n params[key.name || 'pathMatch'] = typeof m[i] === 'string' ? decode(m[i]) : m[i];\n }\n }\n\n return true\n}\n\nfunction resolveRecordPath (path, record) {\n return resolvePath(path, record.parent ? record.parent.path : '/', true)\n}\n\n/* */\n\n// use User Timing api (if present) for more accurate key precision\nvar Time =\n inBrowser && window.performance && window.performance.now\n ? window.performance\n : Date;\n\nfunction genStateKey () {\n return Time.now().toFixed(3)\n}\n\nvar _key = genStateKey();\n\nfunction getStateKey () {\n return _key\n}\n\nfunction setStateKey (key) {\n return (_key = key)\n}\n\n/* */\n\nvar positionStore = Object.create(null);\n\nfunction setupScroll () {\n // Prevent browser scroll behavior on History popstate\n if ('scrollRestoration' in window.history) {\n window.history.scrollRestoration = 'manual';\n }\n // Fix for #1585 for Firefox\n // Fix for #2195 Add optional third attribute to workaround a bug in safari https://bugs.webkit.org/show_bug.cgi?id=182678\n // Fix for #2774 Support for apps loaded from Windows file shares not mapped to network drives: replaced location.origin with\n // window.location.protocol + '//' + window.location.host\n // location.host contains the port and location.hostname doesn't\n var protocolAndPath = window.location.protocol + '//' + window.location.host;\n var absolutePath = window.location.href.replace(protocolAndPath, '');\n // preserve existing history state as it could be overriden by the user\n var stateCopy = extend({}, window.history.state);\n stateCopy.key = getStateKey();\n window.history.replaceState(stateCopy, '', absolutePath);\n window.addEventListener('popstate', handlePopState);\n return function () {\n window.removeEventListener('popstate', handlePopState);\n }\n}\n\nfunction handleScroll (\n router,\n to,\n from,\n isPop\n) {\n if (!router.app) {\n return\n }\n\n var behavior = router.options.scrollBehavior;\n if (!behavior) {\n return\n }\n\n if (false) {\n assert(typeof behavior === 'function', \"scrollBehavior must be a function\");\n }\n\n // wait until re-render finishes before scrolling\n router.app.$nextTick(function () {\n var position = getScrollPosition();\n var shouldScroll = behavior.call(\n router,\n to,\n from,\n isPop ? position : null\n );\n\n if (!shouldScroll) {\n return\n }\n\n if (typeof shouldScroll.then === 'function') {\n shouldScroll\n .then(function (shouldScroll) {\n scrollToPosition((shouldScroll), position);\n })\n .catch(function (err) {\n if (false) {\n assert(false, err.toString());\n }\n });\n } else {\n scrollToPosition(shouldScroll, position);\n }\n });\n}\n\nfunction saveScrollPosition () {\n var key = getStateKey();\n if (key) {\n positionStore[key] = {\n x: window.pageXOffset,\n y: window.pageYOffset\n };\n }\n}\n\nfunction handlePopState (e) {\n saveScrollPosition();\n if (e.state && e.state.key) {\n setStateKey(e.state.key);\n }\n}\n\nfunction getScrollPosition () {\n var key = getStateKey();\n if (key) {\n return positionStore[key]\n }\n}\n\nfunction getElementPosition (el, offset) {\n var docEl = document.documentElement;\n var docRect = docEl.getBoundingClientRect();\n var elRect = el.getBoundingClientRect();\n return {\n x: elRect.left - docRect.left - offset.x,\n y: elRect.top - docRect.top - offset.y\n }\n}\n\nfunction isValidPosition (obj) {\n return isNumber(obj.x) || isNumber(obj.y)\n}\n\nfunction normalizePosition (obj) {\n return {\n x: isNumber(obj.x) ? obj.x : window.pageXOffset,\n y: isNumber(obj.y) ? obj.y : window.pageYOffset\n }\n}\n\nfunction normalizeOffset (obj) {\n return {\n x: isNumber(obj.x) ? obj.x : 0,\n y: isNumber(obj.y) ? obj.y : 0\n }\n}\n\nfunction isNumber (v) {\n return typeof v === 'number'\n}\n\nvar hashStartsWithNumberRE = /^#\\d/;\n\nfunction scrollToPosition (shouldScroll, position) {\n var isObject = typeof shouldScroll === 'object';\n if (isObject && typeof shouldScroll.selector === 'string') {\n // getElementById would still fail if the selector contains a more complicated query like #main[data-attr]\n // but at the same time, it doesn't make much sense to select an element with an id and an extra selector\n var el = hashStartsWithNumberRE.test(shouldScroll.selector) // $flow-disable-line\n ? document.getElementById(shouldScroll.selector.slice(1)) // $flow-disable-line\n : document.querySelector(shouldScroll.selector);\n\n if (el) {\n var offset =\n shouldScroll.offset && typeof shouldScroll.offset === 'object'\n ? shouldScroll.offset\n : {};\n offset = normalizeOffset(offset);\n position = getElementPosition(el, offset);\n } else if (isValidPosition(shouldScroll)) {\n position = normalizePosition(shouldScroll);\n }\n } else if (isObject && isValidPosition(shouldScroll)) {\n position = normalizePosition(shouldScroll);\n }\n\n if (position) {\n // $flow-disable-line\n if ('scrollBehavior' in document.documentElement.style) {\n window.scrollTo({\n left: position.x,\n top: position.y,\n // $flow-disable-line\n behavior: shouldScroll.behavior\n });\n } else {\n window.scrollTo(position.x, position.y);\n }\n }\n}\n\n/* */\n\nvar supportsPushState =\n inBrowser &&\n (function () {\n var ua = window.navigator.userAgent;\n\n if (\n (ua.indexOf('Android 2.') !== -1 || ua.indexOf('Android 4.0') !== -1) &&\n ua.indexOf('Mobile Safari') !== -1 &&\n ua.indexOf('Chrome') === -1 &&\n ua.indexOf('Windows Phone') === -1\n ) {\n return false\n }\n\n return window.history && typeof window.history.pushState === 'function'\n })();\n\nfunction pushState (url, replace) {\n saveScrollPosition();\n // try...catch the pushState call to get around Safari\n // DOM Exception 18 where it limits to 100 pushState calls\n var history = window.history;\n try {\n if (replace) {\n // preserve existing history state as it could be overriden by the user\n var stateCopy = extend({}, history.state);\n stateCopy.key = getStateKey();\n history.replaceState(stateCopy, '', url);\n } else {\n history.pushState({ key: setStateKey(genStateKey()) }, '', url);\n }\n } catch (e) {\n window.location[replace ? 'replace' : 'assign'](url);\n }\n}\n\nfunction replaceState (url) {\n pushState(url, true);\n}\n\n/* */\n\nfunction runQueue (queue, fn, cb) {\n var step = function (index) {\n if (index >= queue.length) {\n cb();\n } else {\n if (queue[index]) {\n fn(queue[index], function () {\n step(index + 1);\n });\n } else {\n step(index + 1);\n }\n }\n };\n step(0);\n}\n\n// When changing thing, also edit router.d.ts\nvar NavigationFailureType = {\n redirected: 2,\n aborted: 4,\n cancelled: 8,\n duplicated: 16\n};\n\nfunction createNavigationRedirectedError (from, to) {\n return createRouterError(\n from,\n to,\n NavigationFailureType.redirected,\n (\"Redirected when going from \\\"\" + (from.fullPath) + \"\\\" to \\\"\" + (stringifyRoute(\n to\n )) + \"\\\" via a navigation guard.\")\n )\n}\n\nfunction createNavigationDuplicatedError (from, to) {\n var error = createRouterError(\n from,\n to,\n NavigationFailureType.duplicated,\n (\"Avoided redundant navigation to current location: \\\"\" + (from.fullPath) + \"\\\".\")\n );\n // backwards compatible with the first introduction of Errors\n error.name = 'NavigationDuplicated';\n return error\n}\n\nfunction createNavigationCancelledError (from, to) {\n return createRouterError(\n from,\n to,\n NavigationFailureType.cancelled,\n (\"Navigation cancelled from \\\"\" + (from.fullPath) + \"\\\" to \\\"\" + (to.fullPath) + \"\\\" with a new navigation.\")\n )\n}\n\nfunction createNavigationAbortedError (from, to) {\n return createRouterError(\n from,\n to,\n NavigationFailureType.aborted,\n (\"Navigation aborted from \\\"\" + (from.fullPath) + \"\\\" to \\\"\" + (to.fullPath) + \"\\\" via a navigation guard.\")\n )\n}\n\nfunction createRouterError (from, to, type, message) {\n var error = new Error(message);\n error._isRouter = true;\n error.from = from;\n error.to = to;\n error.type = type;\n\n return error\n}\n\nvar propertiesToLog = ['params', 'query', 'hash'];\n\nfunction stringifyRoute (to) {\n if (typeof to === 'string') { return to }\n if ('path' in to) { return to.path }\n var location = {};\n propertiesToLog.forEach(function (key) {\n if (key in to) { location[key] = to[key]; }\n });\n return JSON.stringify(location, null, 2)\n}\n\nfunction isError (err) {\n return Object.prototype.toString.call(err).indexOf('Error') > -1\n}\n\nfunction isNavigationFailure (err, errorType) {\n return (\n isError(err) &&\n err._isRouter &&\n (errorType == null || err.type === errorType)\n )\n}\n\n/* */\n\nfunction resolveAsyncComponents (matched) {\n return function (to, from, next) {\n var hasAsync = false;\n var pending = 0;\n var error = null;\n\n flatMapComponents(matched, function (def, _, match, key) {\n // if it's a function and doesn't have cid attached,\n // assume it's an async component resolve function.\n // we are not using Vue's default async resolving mechanism because\n // we want to halt the navigation until the incoming component has been\n // resolved.\n if (typeof def === 'function' && def.cid === undefined) {\n hasAsync = true;\n pending++;\n\n var resolve = once(function (resolvedDef) {\n if (isESModule(resolvedDef)) {\n resolvedDef = resolvedDef.default;\n }\n // save resolved on async factory in case it's used elsewhere\n def.resolved = typeof resolvedDef === 'function'\n ? resolvedDef\n : _Vue.extend(resolvedDef);\n match.components[key] = resolvedDef;\n pending--;\n if (pending <= 0) {\n next();\n }\n });\n\n var reject = once(function (reason) {\n var msg = \"Failed to resolve async component \" + key + \": \" + reason;\n \"production\" !== 'production' && warn(false, msg);\n if (!error) {\n error = isError(reason)\n ? reason\n : new Error(msg);\n next(error);\n }\n });\n\n var res;\n try {\n res = def(resolve, reject);\n } catch (e) {\n reject(e);\n }\n if (res) {\n if (typeof res.then === 'function') {\n res.then(resolve, reject);\n } else {\n // new syntax in Vue 2.3\n var comp = res.component;\n if (comp && typeof comp.then === 'function') {\n comp.then(resolve, reject);\n }\n }\n }\n }\n });\n\n if (!hasAsync) { next(); }\n }\n}\n\nfunction flatMapComponents (\n matched,\n fn\n) {\n return flatten(matched.map(function (m) {\n return Object.keys(m.components).map(function (key) { return fn(\n m.components[key],\n m.instances[key],\n m, key\n ); })\n }))\n}\n\nfunction flatten (arr) {\n return Array.prototype.concat.apply([], arr)\n}\n\nvar hasSymbol =\n typeof Symbol === 'function' &&\n typeof Symbol.toStringTag === 'symbol';\n\nfunction isESModule (obj) {\n return obj.__esModule || (hasSymbol && obj[Symbol.toStringTag] === 'Module')\n}\n\n// in Webpack 2, require.ensure now also returns a Promise\n// so the resolve/reject functions may get called an extra time\n// if the user uses an arrow function shorthand that happens to\n// return that Promise.\nfunction once (fn) {\n var called = false;\n return function () {\n var args = [], len = arguments.length;\n while ( len-- ) args[ len ] = arguments[ len ];\n\n if (called) { return }\n called = true;\n return fn.apply(this, args)\n }\n}\n\n/* */\n\nvar History = function History (router, base) {\n this.router = router;\n this.base = normalizeBase(base);\n // start with a route object that stands for \"nowhere\"\n this.current = START;\n this.pending = null;\n this.ready = false;\n this.readyCbs = [];\n this.readyErrorCbs = [];\n this.errorCbs = [];\n this.listeners = [];\n};\n\nHistory.prototype.listen = function listen (cb) {\n this.cb = cb;\n};\n\nHistory.prototype.onReady = function onReady (cb, errorCb) {\n if (this.ready) {\n cb();\n } else {\n this.readyCbs.push(cb);\n if (errorCb) {\n this.readyErrorCbs.push(errorCb);\n }\n }\n};\n\nHistory.prototype.onError = function onError (errorCb) {\n this.errorCbs.push(errorCb);\n};\n\nHistory.prototype.transitionTo = function transitionTo (\n location,\n onComplete,\n onAbort\n) {\n var this$1 = this;\n\n var route;\n // catch redirect option https://github.com/vuejs/vue-router/issues/3201\n try {\n route = this.router.match(location, this.current);\n } catch (e) {\n this.errorCbs.forEach(function (cb) {\n cb(e);\n });\n // Exception should still be thrown\n throw e\n }\n var prev = this.current;\n this.confirmTransition(\n route,\n function () {\n this$1.updateRoute(route);\n onComplete && onComplete(route);\n this$1.ensureURL();\n this$1.router.afterHooks.forEach(function (hook) {\n hook && hook(route, prev);\n });\n\n // fire ready cbs once\n if (!this$1.ready) {\n this$1.ready = true;\n this$1.readyCbs.forEach(function (cb) {\n cb(route);\n });\n }\n },\n function (err) {\n if (onAbort) {\n onAbort(err);\n }\n if (err && !this$1.ready) {\n // Initial redirection should not mark the history as ready yet\n // because it's triggered by the redirection instead\n // https://github.com/vuejs/vue-router/issues/3225\n // https://github.com/vuejs/vue-router/issues/3331\n if (!isNavigationFailure(err, NavigationFailureType.redirected) || prev !== START) {\n this$1.ready = true;\n this$1.readyErrorCbs.forEach(function (cb) {\n cb(err);\n });\n }\n }\n }\n );\n};\n\nHistory.prototype.confirmTransition = function confirmTransition (route, onComplete, onAbort) {\n var this$1 = this;\n\n var current = this.current;\n this.pending = route;\n var abort = function (err) {\n // changed after adding errors with\n // https://github.com/vuejs/vue-router/pull/3047 before that change,\n // redirect and aborted navigation would produce an err == null\n if (!isNavigationFailure(err) && isError(err)) {\n if (this$1.errorCbs.length) {\n this$1.errorCbs.forEach(function (cb) {\n cb(err);\n });\n } else {\n warn(false, 'uncaught error during route navigation:');\n console.error(err);\n }\n }\n onAbort && onAbort(err);\n };\n var lastRouteIndex = route.matched.length - 1;\n var lastCurrentIndex = current.matched.length - 1;\n if (\n isSameRoute(route, current) &&\n // in the case the route map has been dynamically appended to\n lastRouteIndex === lastCurrentIndex &&\n route.matched[lastRouteIndex] === current.matched[lastCurrentIndex]\n ) {\n this.ensureURL();\n return abort(createNavigationDuplicatedError(current, route))\n }\n\n var ref = resolveQueue(\n this.current.matched,\n route.matched\n );\n var updated = ref.updated;\n var deactivated = ref.deactivated;\n var activated = ref.activated;\n\n var queue = [].concat(\n // in-component leave guards\n extractLeaveGuards(deactivated),\n // global before hooks\n this.router.beforeHooks,\n // in-component update hooks\n extractUpdateHooks(updated),\n // in-config enter guards\n activated.map(function (m) { return m.beforeEnter; }),\n // async components\n resolveAsyncComponents(activated)\n );\n\n var iterator = function (hook, next) {\n if (this$1.pending !== route) {\n return abort(createNavigationCancelledError(current, route))\n }\n try {\n hook(route, current, function (to) {\n if (to === false) {\n // next(false) -> abort navigation, ensure current URL\n this$1.ensureURL(true);\n abort(createNavigationAbortedError(current, route));\n } else if (isError(to)) {\n this$1.ensureURL(true);\n abort(to);\n } else if (\n typeof to === 'string' ||\n (typeof to === 'object' &&\n (typeof to.path === 'string' || typeof to.name === 'string'))\n ) {\n // next('/') or next({ path: '/' }) -> redirect\n abort(createNavigationRedirectedError(current, route));\n if (typeof to === 'object' && to.replace) {\n this$1.replace(to);\n } else {\n this$1.push(to);\n }\n } else {\n // confirm transition and pass on the value\n next(to);\n }\n });\n } catch (e) {\n abort(e);\n }\n };\n\n runQueue(queue, iterator, function () {\n // wait until async components are resolved before\n // extracting in-component enter guards\n var enterGuards = extractEnterGuards(activated);\n var queue = enterGuards.concat(this$1.router.resolveHooks);\n runQueue(queue, iterator, function () {\n if (this$1.pending !== route) {\n return abort(createNavigationCancelledError(current, route))\n }\n this$1.pending = null;\n onComplete(route);\n if (this$1.router.app) {\n this$1.router.app.$nextTick(function () {\n handleRouteEntered(route);\n });\n }\n });\n });\n};\n\nHistory.prototype.updateRoute = function updateRoute (route) {\n this.current = route;\n this.cb && this.cb(route);\n};\n\nHistory.prototype.setupListeners = function setupListeners () {\n // Default implementation is empty\n};\n\nHistory.prototype.teardown = function teardown () {\n // clean up event listeners\n // https://github.com/vuejs/vue-router/issues/2341\n this.listeners.forEach(function (cleanupListener) {\n cleanupListener();\n });\n this.listeners = [];\n\n // reset current history route\n // https://github.com/vuejs/vue-router/issues/3294\n this.current = START;\n this.pending = null;\n};\n\nfunction normalizeBase (base) {\n if (!base) {\n if (inBrowser) {\n // respect tag\n var baseEl = document.querySelector('base');\n base = (baseEl && baseEl.getAttribute('href')) || '/';\n // strip full URL origin\n base = base.replace(/^https?:\\/\\/[^\\/]+/, '');\n } else {\n base = '/';\n }\n }\n // make sure there's the starting slash\n if (base.charAt(0) !== '/') {\n base = '/' + base;\n }\n // remove trailing slash\n return base.replace(/\\/$/, '')\n}\n\nfunction resolveQueue (\n current,\n next\n) {\n var i;\n var max = Math.max(current.length, next.length);\n for (i = 0; i < max; i++) {\n if (current[i] !== next[i]) {\n break\n }\n }\n return {\n updated: next.slice(0, i),\n activated: next.slice(i),\n deactivated: current.slice(i)\n }\n}\n\nfunction extractGuards (\n records,\n name,\n bind,\n reverse\n) {\n var guards = flatMapComponents(records, function (def, instance, match, key) {\n var guard = extractGuard(def, name);\n if (guard) {\n return Array.isArray(guard)\n ? guard.map(function (guard) { return bind(guard, instance, match, key); })\n : bind(guard, instance, match, key)\n }\n });\n return flatten(reverse ? guards.reverse() : guards)\n}\n\nfunction extractGuard (\n def,\n key\n) {\n if (typeof def !== 'function') {\n // extend now so that global mixins are applied.\n def = _Vue.extend(def);\n }\n return def.options[key]\n}\n\nfunction extractLeaveGuards (deactivated) {\n return extractGuards(deactivated, 'beforeRouteLeave', bindGuard, true)\n}\n\nfunction extractUpdateHooks (updated) {\n return extractGuards(updated, 'beforeRouteUpdate', bindGuard)\n}\n\nfunction bindGuard (guard, instance) {\n if (instance) {\n return function boundRouteGuard () {\n return guard.apply(instance, arguments)\n }\n }\n}\n\nfunction extractEnterGuards (\n activated\n) {\n return extractGuards(\n activated,\n 'beforeRouteEnter',\n function (guard, _, match, key) {\n return bindEnterGuard(guard, match, key)\n }\n )\n}\n\nfunction bindEnterGuard (\n guard,\n match,\n key\n) {\n return function routeEnterGuard (to, from, next) {\n return guard(to, from, function (cb) {\n if (typeof cb === 'function') {\n if (!match.enteredCbs[key]) {\n match.enteredCbs[key] = [];\n }\n match.enteredCbs[key].push(cb);\n }\n next(cb);\n })\n }\n}\n\n/* */\n\nvar HTML5History = /*@__PURE__*/(function (History) {\n function HTML5History (router, base) {\n History.call(this, router, base);\n\n this._startLocation = getLocation(this.base);\n }\n\n if ( History ) HTML5History.__proto__ = History;\n HTML5History.prototype = Object.create( History && History.prototype );\n HTML5History.prototype.constructor = HTML5History;\n\n HTML5History.prototype.setupListeners = function setupListeners () {\n var this$1 = this;\n\n if (this.listeners.length > 0) {\n return\n }\n\n var router = this.router;\n var expectScroll = router.options.scrollBehavior;\n var supportsScroll = supportsPushState && expectScroll;\n\n if (supportsScroll) {\n this.listeners.push(setupScroll());\n }\n\n var handleRoutingEvent = function () {\n var current = this$1.current;\n\n // Avoiding first `popstate` event dispatched in some browsers but first\n // history route not updated since async guard at the same time.\n var location = getLocation(this$1.base);\n if (this$1.current === START && location === this$1._startLocation) {\n return\n }\n\n this$1.transitionTo(location, function (route) {\n if (supportsScroll) {\n handleScroll(router, route, current, true);\n }\n });\n };\n window.addEventListener('popstate', handleRoutingEvent);\n this.listeners.push(function () {\n window.removeEventListener('popstate', handleRoutingEvent);\n });\n };\n\n HTML5History.prototype.go = function go (n) {\n window.history.go(n);\n };\n\n HTML5History.prototype.push = function push (location, onComplete, onAbort) {\n var this$1 = this;\n\n var ref = this;\n var fromRoute = ref.current;\n this.transitionTo(location, function (route) {\n pushState(cleanPath(this$1.base + route.fullPath));\n handleScroll(this$1.router, route, fromRoute, false);\n onComplete && onComplete(route);\n }, onAbort);\n };\n\n HTML5History.prototype.replace = function replace (location, onComplete, onAbort) {\n var this$1 = this;\n\n var ref = this;\n var fromRoute = ref.current;\n this.transitionTo(location, function (route) {\n replaceState(cleanPath(this$1.base + route.fullPath));\n handleScroll(this$1.router, route, fromRoute, false);\n onComplete && onComplete(route);\n }, onAbort);\n };\n\n HTML5History.prototype.ensureURL = function ensureURL (push) {\n if (getLocation(this.base) !== this.current.fullPath) {\n var current = cleanPath(this.base + this.current.fullPath);\n push ? pushState(current) : replaceState(current);\n }\n };\n\n HTML5History.prototype.getCurrentLocation = function getCurrentLocation () {\n return getLocation(this.base)\n };\n\n return HTML5History;\n}(History));\n\nfunction getLocation (base) {\n var path = window.location.pathname;\n if (base && path.toLowerCase().indexOf(base.toLowerCase()) === 0) {\n path = path.slice(base.length);\n }\n return (path || '/') + window.location.search + window.location.hash\n}\n\n/* */\n\nvar HashHistory = /*@__PURE__*/(function (History) {\n function HashHistory (router, base, fallback) {\n History.call(this, router, base);\n // check history fallback deeplinking\n if (fallback && checkFallback(this.base)) {\n return\n }\n ensureSlash();\n }\n\n if ( History ) HashHistory.__proto__ = History;\n HashHistory.prototype = Object.create( History && History.prototype );\n HashHistory.prototype.constructor = HashHistory;\n\n // this is delayed until the app mounts\n // to avoid the hashchange listener being fired too early\n HashHistory.prototype.setupListeners = function setupListeners () {\n var this$1 = this;\n\n if (this.listeners.length > 0) {\n return\n }\n\n var router = this.router;\n var expectScroll = router.options.scrollBehavior;\n var supportsScroll = supportsPushState && expectScroll;\n\n if (supportsScroll) {\n this.listeners.push(setupScroll());\n }\n\n var handleRoutingEvent = function () {\n var current = this$1.current;\n if (!ensureSlash()) {\n return\n }\n this$1.transitionTo(getHash(), function (route) {\n if (supportsScroll) {\n handleScroll(this$1.router, route, current, true);\n }\n if (!supportsPushState) {\n replaceHash(route.fullPath);\n }\n });\n };\n var eventType = supportsPushState ? 'popstate' : 'hashchange';\n window.addEventListener(\n eventType,\n handleRoutingEvent\n );\n this.listeners.push(function () {\n window.removeEventListener(eventType, handleRoutingEvent);\n });\n };\n\n HashHistory.prototype.push = function push (location, onComplete, onAbort) {\n var this$1 = this;\n\n var ref = this;\n var fromRoute = ref.current;\n this.transitionTo(\n location,\n function (route) {\n pushHash(route.fullPath);\n handleScroll(this$1.router, route, fromRoute, false);\n onComplete && onComplete(route);\n },\n onAbort\n );\n };\n\n HashHistory.prototype.replace = function replace (location, onComplete, onAbort) {\n var this$1 = this;\n\n var ref = this;\n var fromRoute = ref.current;\n this.transitionTo(\n location,\n function (route) {\n replaceHash(route.fullPath);\n handleScroll(this$1.router, route, fromRoute, false);\n onComplete && onComplete(route);\n },\n onAbort\n );\n };\n\n HashHistory.prototype.go = function go (n) {\n window.history.go(n);\n };\n\n HashHistory.prototype.ensureURL = function ensureURL (push) {\n var current = this.current.fullPath;\n if (getHash() !== current) {\n push ? pushHash(current) : replaceHash(current);\n }\n };\n\n HashHistory.prototype.getCurrentLocation = function getCurrentLocation () {\n return getHash()\n };\n\n return HashHistory;\n}(History));\n\nfunction checkFallback (base) {\n var location = getLocation(base);\n if (!/^\\/#/.test(location)) {\n window.location.replace(cleanPath(base + '/#' + location));\n return true\n }\n}\n\nfunction ensureSlash () {\n var path = getHash();\n if (path.charAt(0) === '/') {\n return true\n }\n replaceHash('/' + path);\n return false\n}\n\nfunction getHash () {\n // We can't use window.location.hash here because it's not\n // consistent across browsers - Firefox will pre-decode it!\n var href = window.location.href;\n var index = href.indexOf('#');\n // empty path\n if (index < 0) { return '' }\n\n href = href.slice(index + 1);\n\n return href\n}\n\nfunction getUrl (path) {\n var href = window.location.href;\n var i = href.indexOf('#');\n var base = i >= 0 ? href.slice(0, i) : href;\n return (base + \"#\" + path)\n}\n\nfunction pushHash (path) {\n if (supportsPushState) {\n pushState(getUrl(path));\n } else {\n window.location.hash = path;\n }\n}\n\nfunction replaceHash (path) {\n if (supportsPushState) {\n replaceState(getUrl(path));\n } else {\n window.location.replace(getUrl(path));\n }\n}\n\n/* */\n\nvar AbstractHistory = /*@__PURE__*/(function (History) {\n function AbstractHistory (router, base) {\n History.call(this, router, base);\n this.stack = [];\n this.index = -1;\n }\n\n if ( History ) AbstractHistory.__proto__ = History;\n AbstractHistory.prototype = Object.create( History && History.prototype );\n AbstractHistory.prototype.constructor = AbstractHistory;\n\n AbstractHistory.prototype.push = function push (location, onComplete, onAbort) {\n var this$1 = this;\n\n this.transitionTo(\n location,\n function (route) {\n this$1.stack = this$1.stack.slice(0, this$1.index + 1).concat(route);\n this$1.index++;\n onComplete && onComplete(route);\n },\n onAbort\n );\n };\n\n AbstractHistory.prototype.replace = function replace (location, onComplete, onAbort) {\n var this$1 = this;\n\n this.transitionTo(\n location,\n function (route) {\n this$1.stack = this$1.stack.slice(0, this$1.index).concat(route);\n onComplete && onComplete(route);\n },\n onAbort\n );\n };\n\n AbstractHistory.prototype.go = function go (n) {\n var this$1 = this;\n\n var targetIndex = this.index + n;\n if (targetIndex < 0 || targetIndex >= this.stack.length) {\n return\n }\n var route = this.stack[targetIndex];\n this.confirmTransition(\n route,\n function () {\n var prev = this$1.current;\n this$1.index = targetIndex;\n this$1.updateRoute(route);\n this$1.router.afterHooks.forEach(function (hook) {\n hook && hook(route, prev);\n });\n },\n function (err) {\n if (isNavigationFailure(err, NavigationFailureType.duplicated)) {\n this$1.index = targetIndex;\n }\n }\n );\n };\n\n AbstractHistory.prototype.getCurrentLocation = function getCurrentLocation () {\n var current = this.stack[this.stack.length - 1];\n return current ? current.fullPath : '/'\n };\n\n AbstractHistory.prototype.ensureURL = function ensureURL () {\n // noop\n };\n\n return AbstractHistory;\n}(History));\n\n/* */\n\nvar VueRouter = function VueRouter (options) {\n if ( options === void 0 ) options = {};\n\n this.app = null;\n this.apps = [];\n this.options = options;\n this.beforeHooks = [];\n this.resolveHooks = [];\n this.afterHooks = [];\n this.matcher = createMatcher(options.routes || [], this);\n\n var mode = options.mode || 'hash';\n this.fallback =\n mode === 'history' && !supportsPushState && options.fallback !== false;\n if (this.fallback) {\n mode = 'hash';\n }\n if (!inBrowser) {\n mode = 'abstract';\n }\n this.mode = mode;\n\n switch (mode) {\n case 'history':\n this.history = new HTML5History(this, options.base);\n break\n case 'hash':\n this.history = new HashHistory(this, options.base, this.fallback);\n break\n case 'abstract':\n this.history = new AbstractHistory(this, options.base);\n break\n default:\n if (false) {\n assert(false, (\"invalid mode: \" + mode));\n }\n }\n};\n\nvar prototypeAccessors = { currentRoute: { configurable: true } };\n\nVueRouter.prototype.match = function match (raw, current, redirectedFrom) {\n return this.matcher.match(raw, current, redirectedFrom)\n};\n\nprototypeAccessors.currentRoute.get = function () {\n return this.history && this.history.current\n};\n\nVueRouter.prototype.init = function init (app /* Vue component instance */) {\n var this$1 = this;\n\n \"production\" !== 'production' &&\n assert(\n install.installed,\n \"not installed. Make sure to call `Vue.use(VueRouter)` \" +\n \"before creating root instance.\"\n );\n\n this.apps.push(app);\n\n // set up app destroyed handler\n // https://github.com/vuejs/vue-router/issues/2639\n app.$once('hook:destroyed', function () {\n // clean out app from this.apps array once destroyed\n var index = this$1.apps.indexOf(app);\n if (index > -1) { this$1.apps.splice(index, 1); }\n // ensure we still have a main app or null if no apps\n // we do not release the router so it can be reused\n if (this$1.app === app) { this$1.app = this$1.apps[0] || null; }\n\n if (!this$1.app) { this$1.history.teardown(); }\n });\n\n // main app previously initialized\n // return as we don't need to set up new history listener\n if (this.app) {\n return\n }\n\n this.app = app;\n\n var history = this.history;\n\n if (history instanceof HTML5History || history instanceof HashHistory) {\n var handleInitialScroll = function (routeOrError) {\n var from = history.current;\n var expectScroll = this$1.options.scrollBehavior;\n var supportsScroll = supportsPushState && expectScroll;\n\n if (supportsScroll && 'fullPath' in routeOrError) {\n handleScroll(this$1, routeOrError, from, false);\n }\n };\n var setupListeners = function (routeOrError) {\n history.setupListeners();\n handleInitialScroll(routeOrError);\n };\n history.transitionTo(\n history.getCurrentLocation(),\n setupListeners,\n setupListeners\n );\n }\n\n history.listen(function (route) {\n this$1.apps.forEach(function (app) {\n app._route = route;\n });\n });\n};\n\nVueRouter.prototype.beforeEach = function beforeEach (fn) {\n return registerHook(this.beforeHooks, fn)\n};\n\nVueRouter.prototype.beforeResolve = function beforeResolve (fn) {\n return registerHook(this.resolveHooks, fn)\n};\n\nVueRouter.prototype.afterEach = function afterEach (fn) {\n return registerHook(this.afterHooks, fn)\n};\n\nVueRouter.prototype.onReady = function onReady (cb, errorCb) {\n this.history.onReady(cb, errorCb);\n};\n\nVueRouter.prototype.onError = function onError (errorCb) {\n this.history.onError(errorCb);\n};\n\nVueRouter.prototype.push = function push (location, onComplete, onAbort) {\n var this$1 = this;\n\n // $flow-disable-line\n if (!onComplete && !onAbort && typeof Promise !== 'undefined') {\n return new Promise(function (resolve, reject) {\n this$1.history.push(location, resolve, reject);\n })\n } else {\n this.history.push(location, onComplete, onAbort);\n }\n};\n\nVueRouter.prototype.replace = function replace (location, onComplete, onAbort) {\n var this$1 = this;\n\n // $flow-disable-line\n if (!onComplete && !onAbort && typeof Promise !== 'undefined') {\n return new Promise(function (resolve, reject) {\n this$1.history.replace(location, resolve, reject);\n })\n } else {\n this.history.replace(location, onComplete, onAbort);\n }\n};\n\nVueRouter.prototype.go = function go (n) {\n this.history.go(n);\n};\n\nVueRouter.prototype.back = function back () {\n this.go(-1);\n};\n\nVueRouter.prototype.forward = function forward () {\n this.go(1);\n};\n\nVueRouter.prototype.getMatchedComponents = function getMatchedComponents (to) {\n var route = to\n ? to.matched\n ? to\n : this.resolve(to).route\n : this.currentRoute;\n if (!route) {\n return []\n }\n return [].concat.apply(\n [],\n route.matched.map(function (m) {\n return Object.keys(m.components).map(function (key) {\n return m.components[key]\n })\n })\n )\n};\n\nVueRouter.prototype.resolve = function resolve (\n to,\n current,\n append\n) {\n current = current || this.history.current;\n var location = normalizeLocation(to, current, append, this);\n var route = this.match(location, current);\n var fullPath = route.redirectedFrom || route.fullPath;\n var base = this.history.base;\n var href = createHref(base, fullPath, this.mode);\n return {\n location: location,\n route: route,\n href: href,\n // for backwards compat\n normalizedTo: location,\n resolved: route\n }\n};\n\nVueRouter.prototype.getRoutes = function getRoutes () {\n return this.matcher.getRoutes()\n};\n\nVueRouter.prototype.addRoute = function addRoute (parentOrRoute, route) {\n this.matcher.addRoute(parentOrRoute, route);\n if (this.history.current !== START) {\n this.history.transitionTo(this.history.getCurrentLocation());\n }\n};\n\nVueRouter.prototype.addRoutes = function addRoutes (routes) {\n if (false) {\n warn(false, 'router.addRoutes() is deprecated and has been removed in Vue Router 4. Use router.addRoute() instead.');\n }\n this.matcher.addRoutes(routes);\n if (this.history.current !== START) {\n this.history.transitionTo(this.history.getCurrentLocation());\n }\n};\n\nObject.defineProperties( VueRouter.prototype, prototypeAccessors );\n\nfunction registerHook (list, fn) {\n list.push(fn);\n return function () {\n var i = list.indexOf(fn);\n if (i > -1) { list.splice(i, 1); }\n }\n}\n\nfunction createHref (base, fullPath, mode) {\n var path = mode === 'hash' ? '#' + fullPath : fullPath;\n return base ? cleanPath(base + '/' + path) : path\n}\n\nVueRouter.install = install;\nVueRouter.version = '3.5.1';\nVueRouter.isNavigationFailure = isNavigationFailure;\nVueRouter.NavigationFailureType = NavigationFailureType;\nVueRouter.START_LOCATION = START;\n\nif (inBrowser && window.Vue) {\n window.Vue.use(VueRouter);\n}\n\n/* harmony default export */ __webpack_exports__[\"a\"] = (VueRouter);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiL29jcS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy92dWUtcm91dGVyL2Rpc3QvdnVlLXJvdXRlci5lc20uanM/ZmU4NyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKiFcbiAgKiB2dWUtcm91dGVyIHYzLjUuMVxuICAqIChjKSAyMDIxIEV2YW4gWW91XG4gICogQGxpY2Vuc2UgTUlUXG4gICovXG4vKiAgKi9cblxuZnVuY3Rpb24gYXNzZXJ0IChjb25kaXRpb24sIG1lc3NhZ2UpIHtcbiAgaWYgKCFjb25kaXRpb24pIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoKFwiW3Z1ZS1yb3V0ZXJdIFwiICsgbWVzc2FnZSkpXG4gIH1cbn1cblxuZnVuY3Rpb24gd2FybiAoY29uZGl0aW9uLCBtZXNzYWdlKSB7XG4gIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nICYmICFjb25kaXRpb24pIHtcbiAgICB0eXBlb2YgY29uc29sZSAhPT0gJ3VuZGVmaW5lZCcgJiYgY29uc29sZS53YXJuKChcIlt2dWUtcm91dGVyXSBcIiArIG1lc3NhZ2UpKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBleHRlbmQgKGEsIGIpIHtcbiAgZm9yICh2YXIga2V5IGluIGIpIHtcbiAgICBhW2tleV0gPSBiW2tleV07XG4gIH1cbiAgcmV0dXJuIGFcbn1cblxuLyogICovXG5cbnZhciBlbmNvZGVSZXNlcnZlUkUgPSAvWyEnKCkqXS9nO1xudmFyIGVuY29kZVJlc2VydmVSZXBsYWNlciA9IGZ1bmN0aW9uIChjKSB7IHJldHVybiAnJScgKyBjLmNoYXJDb2RlQXQoMCkudG9TdHJpbmcoMTYpOyB9O1xudmFyIGNvbW1hUkUgPSAvJTJDL2c7XG5cbi8vIGZpeGVkIGVuY29kZVVSSUNvbXBvbmVudCB3aGljaCBpcyBtb3JlIGNvbmZvcm1hbnQgdG8gUkZDMzk4Njpcbi8vIC0gZXNjYXBlcyBbIScoKSpdXG4vLyAtIHByZXNlcnZlIGNvbW1hc1xudmFyIGVuY29kZSA9IGZ1bmN0aW9uIChzdHIpIHsgcmV0dXJuIGVuY29kZVVSSUNvbXBvbmVudChzdHIpXG4gICAgLnJlcGxhY2UoZW5jb2RlUmVzZXJ2ZVJFLCBlbmNvZGVSZXNlcnZlUmVwbGFjZXIpXG4gICAgLnJlcGxhY2UoY29tbWFSRSwgJywnKTsgfTtcblxuZnVuY3Rpb24gZGVjb2RlIChzdHIpIHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gZGVjb2RlVVJJQ29tcG9uZW50KHN0cilcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgIHdhcm4oZmFsc2UsIChcIkVycm9yIGRlY29kaW5nIFxcXCJcIiArIHN0ciArIFwiXFxcIi4gTGVhdmluZyBpdCBpbnRhY3QuXCIpKTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIHN0clxufVxuXG5mdW5jdGlvbiByZXNvbHZlUXVlcnkgKFxuICBxdWVyeSxcbiAgZXh0cmFRdWVyeSxcbiAgX3BhcnNlUXVlcnlcbikge1xuICBpZiAoIGV4dHJhUXVlcnkgPT09IHZvaWQgMCApIGV4dHJhUXVlcnkgPSB7fTtcblxuICB2YXIgcGFyc2UgPSBfcGFyc2VRdWVyeSB8fCBwYXJzZVF1ZXJ5O1xuICB2YXIgcGFyc2VkUXVlcnk7XG4gIHRyeSB7XG4gICAgcGFyc2VkUXVlcnkgPSBwYXJzZShxdWVyeSB8fCAnJyk7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICBwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nICYmIHdhcm4oZmFsc2UsIGUubWVzc2FnZSk7XG4gICAgcGFyc2VkUXVlcnkgPSB7fTtcbiAgfVxuICBmb3IgKHZhciBrZXkgaW4gZXh0cmFRdWVyeSkge1xuICAgIHZhciB2YWx1ZSA9IGV4dHJhUXVlcnlba2V5XTtcbiAgICBwYXJzZWRRdWVyeVtrZXldID0gQXJyYXkuaXNBcnJheSh2YWx1ZSlcbiAgICAgID8gdmFsdWUubWFwKGNhc3RRdWVyeVBhcmFtVmFsdWUpXG4gICAgICA6IGNhc3RRdWVyeVBhcmFtVmFsdWUodmFsdWUpO1xuICB9XG4gIHJldHVybiBwYXJzZWRRdWVyeVxufVxuXG52YXIgY2FzdFF1ZXJ5UGFyYW1WYWx1ZSA9IGZ1bmN0aW9uICh2YWx1ZSkgeyByZXR1cm4gKHZhbHVlID09IG51bGwgfHwgdHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyA/IHZhbHVlIDogU3RyaW5nKHZhbHVlKSk7IH07XG5cbmZ1bmN0aW9uIHBhcnNlUXVlcnkgKHF1ZXJ5KSB7XG4gIHZhciByZXMgPSB7fTtcblxuICBxdWVyeSA9IHF1ZXJ5LnRyaW0oKS5yZXBsYWNlKC9eKFxcP3wjfCYpLywgJycpO1xuXG4gIGlmICghcXVlcnkpIHtcbiAgICByZXR1cm4gcmVzXG4gIH1cblxuICBxdWVyeS5zcGxpdCgnJicpLmZvckVhY2goZnVuY3Rpb24gKHBhcmFtKSB7XG4gICAgdmFyIHBhcnRzID0gcGFyYW0ucmVwbGFjZSgvXFwrL2csICcgJykuc3BsaXQoJz0nKTtcbiAgICB2YXIga2V5ID0gZGVjb2RlKHBhcnRzLnNoaWZ0KCkpO1xuICAgIHZhciB2YWwgPSBwYXJ0cy5sZW5ndGggPiAwID8gZGVjb2RlKHBhcnRzLmpvaW4oJz0nKSkgOiBudWxsO1xuXG4gICAgaWYgKHJlc1trZXldID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJlc1trZXldID0gdmFsO1xuICAgIH0gZWxzZSBpZiAoQXJyYXkuaXNBcnJheShyZXNba2V5XSkpIHtcbiAgICAgIHJlc1trZXldLnB1c2godmFsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgcmVzW2tleV0gPSBbcmVzW2tleV0sIHZhbF07XG4gICAgfVxuICB9KTtcblxuICByZXR1cm4gcmVzXG59XG5cbmZ1bmN0aW9uIHN0cmluZ2lmeVF1ZXJ5IChvYmopIHtcbiAgdmFyIHJlcyA9IG9ialxuICAgID8gT2JqZWN0LmtleXMob2JqKVxuICAgICAgLm1hcChmdW5jdGlvbiAoa2V5KSB7XG4gICAgICAgIHZhciB2YWwgPSBvYmpba2V5XTtcblxuICAgICAgICBpZiAodmFsID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICByZXR1cm4gJydcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh2YWwgPT09IG51bGwpIHtcbiAgICAgICAgICByZXR1cm4gZW5jb2RlKGtleSlcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBcnJheS5pc0FycmF5KHZhbCkpIHtcbiAgICAgICAgICB2YXIgcmVzdWx0ID0gW107XG4gICAgICAgICAgdmFsLmZvckVhY2goZnVuY3Rpb24gKHZhbDIpIHtcbiAgICAgICAgICAgIGlmICh2YWwyID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgcmV0dXJuXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAodmFsMiA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICByZXN1bHQucHVzaChlbmNvZGUoa2V5KSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICByZXN1bHQucHVzaChlbmNvZGUoa2V5KSArICc9JyArIGVuY29kZSh2YWwyKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSk7XG4gICAgICAgICAgcmV0dXJuIHJlc3VsdC5qb2luKCcmJylcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBlbmNvZGUoa2V5KSArICc9JyArIGVuY29kZSh2YWwpXG4gICAgICB9KVxuICAgICAgLmZpbHRlcihmdW5jdGlvbiAoeCkgeyByZXR1cm4geC5sZW5ndGggPiAwOyB9KVxuICAgICAgLmpvaW4oJyYnKVxuICAgIDogbnVsbDtcbiAgcmV0dXJuIHJlcyA/IChcIj9cIiArIHJlcykgOiAnJ1xufVxuXG4vKiAgKi9cblxudmFyIHRyYWlsaW5nU2xhc2hSRSA9IC9cXC8/JC87XG5cbmZ1bmN0aW9uIGNyZWF0ZVJvdXRlIChcbiAgcmVjb3JkLFxuICBsb2NhdGlvbixcbiAgcmVkaXJlY3RlZEZyb20sXG4gIHJvdXRlclxuKSB7XG4gIHZhciBzdHJpbmdpZnlRdWVyeSA9IHJvdXRlciAmJiByb3V0ZXIub3B0aW9ucy5zdHJpbmdpZnlRdWVyeTtcblxuICB2YXIgcXVlcnkgPSBsb2NhdGlvbi5xdWVyeSB8fCB7fTtcbiAgdHJ5IHtcbiAgICBxdWVyeSA9IGNsb25lKHF1ZXJ5KTtcbiAgfSBjYXRjaCAoZSkge31cblxuICB2YXIgcm91dGUgPSB7XG4gICAgbmFtZTogbG9jYXRpb24ubmFtZSB8fCAocmVjb3JkICYmIHJlY29yZC5uYW1lKSxcbiAgICBtZXRhOiAocmVjb3JkICYmIHJlY29yZC5tZXRhKSB8fCB7fSxcbiAgICBwYXRoOiBsb2NhdGlvbi5wYXRoIHx8ICcvJyxcbiAgICBoYXNoOiBsb2NhdGlvbi5oYXNoIHx8ICcnLFxuICAgIHF1ZXJ5OiBxdWVyeSxcbiAgICBwYXJhbXM6IGxvY2F0aW9uLnBhcmFtcyB8fCB7fSxcbiAgICBmdWxsUGF0aDogZ2V0RnVsbFBhdGgobG9jYXRpb24sIHN0cmluZ2lmeVF1ZXJ5KSxcbiAgICBtYXRjaGVkOiByZWNvcmQgPyBmb3JtYXRNYXRjaChyZWNvcmQpIDogW11cbiAgfTtcbiAgaWYgKHJlZGlyZWN0ZWRGcm9tKSB7XG4gICAgcm91dGUucmVkaXJlY3RlZEZyb20gPSBnZXRGdWxsUGF0aChyZWRpcmVjdGVkRnJvbSwgc3RyaW5naWZ5UXVlcnkpO1xuICB9XG4gIHJldHVybiBPYmplY3QuZnJlZXplKHJvdXRlKVxufVxuXG5mdW5jdGlvbiBjbG9uZSAodmFsdWUpIHtcbiAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpKSB7XG4gICAgcmV0dXJuIHZhbHVlLm1hcChjbG9uZSlcbiAgfSBlbHNlIGlmICh2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XG4gICAgdmFyIHJlcyA9IHt9O1xuICAgIGZvciAodmFyIGtleSBpbiB2YWx1ZSkge1xuICAgICAgcmVzW2tleV0gPSBjbG9uZSh2YWx1ZVtrZXldKTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc1xuICB9IGVsc2Uge1xuICAgIHJldHVybiB2YWx1ZVxuICB9XG59XG5cbi8vIHRoZSBzdGFydGluZyByb3V0ZSB0aGF0IHJlcHJlc2VudHMgdGhlIGluaXRpYWwgc3RhdGVcbnZhciBTVEFSVCA9IGNyZWF0ZVJvdXRlKG51bGwsIHtcbiAgcGF0aDogJy8nXG59KTtcblxuZnVuY3Rpb24gZm9ybWF0TWF0Y2ggKHJlY29yZCkge1xuICB2YXIgcmVzID0gW107XG4gIHdoaWxlIChyZWNvcmQpIHtcbiAgICByZXMudW5zaGlmdChyZWNvcmQpO1xuICAgIHJlY29yZCA9IHJlY29yZC5wYXJlbnQ7XG4gIH1cbiAgcmV0dXJuIHJlc1xufVxuXG5mdW5jdGlvbiBnZXRGdWxsUGF0aCAoXG4gIHJlZixcbiAgX3N0cmluZ2lmeVF1ZXJ5XG4pIHtcbiAgdmFyIHBhdGggPSByZWYucGF0aDtcbiAgdmFyIHF1ZXJ5ID0gcmVmLnF1ZXJ5OyBpZiAoIHF1ZXJ5ID09PSB2b2lkIDAgKSBxdWVyeSA9IHt9O1xuICB2YXIgaGFzaCA9IHJlZi5oYXNoOyBpZiAoIGhhc2ggPT09IHZvaWQgMCApIGhhc2ggPSAnJztcblxuICB2YXIgc3RyaW5naWZ5ID0gX3N0cmluZ2lmeVF1ZXJ5IHx8IHN0cmluZ2lmeVF1ZXJ5O1xuICByZXR1cm4gKHBhdGggfHwgJy8nKSArIHN0cmluZ2lmeShxdWVyeSkgKyBoYXNoXG59XG5cbmZ1bmN0aW9uIGlzU2FtZVJvdXRlIChhLCBiLCBvbmx5UGF0aCkge1xuICBpZiAoYiA9PT0gU1RBUlQpIHtcbiAgICByZXR1cm4gYSA9PT0gYlxuICB9IGVsc2UgaWYgKCFiKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH0gZWxzZSBpZiAoYS5wYXRoICYmIGIucGF0aCkge1xuICAgIHJldHVybiBhLnBhdGgucmVwbGFjZSh0cmFpbGluZ1NsYXNoUkUsICcnKSA9PT0gYi5wYXRoLnJlcGxhY2UodHJhaWxpbmdTbGFzaFJFLCAnJykgJiYgKG9ubHlQYXRoIHx8XG4gICAgICBhLmhhc2ggPT09IGIuaGFzaCAmJlxuICAgICAgaXNPYmplY3RFcXVhbChhLnF1ZXJ5LCBiLnF1ZXJ5KSlcbiAgfSBlbHNlIGlmIChhLm5hbWUgJiYgYi5uYW1lKSB7XG4gICAgcmV0dXJuIChcbiAgICAgIGEubmFtZSA9PT0gYi5uYW1lICYmXG4gICAgICAob25seVBhdGggfHwgKFxuICAgICAgICBhLmhhc2ggPT09IGIuaGFzaCAmJlxuICAgICAgaXNPYmplY3RFcXVhbChhLnF1ZXJ5LCBiLnF1ZXJ5KSAmJlxuICAgICAgaXNPYmplY3RFcXVhbChhLnBhcmFtcywgYi5wYXJhbXMpKVxuICAgICAgKVxuICAgIClcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZmFsc2VcbiAgfVxufVxuXG5mdW5jdGlvbiBpc09iamVjdEVxdWFsIChhLCBiKSB7XG4gIGlmICggYSA9PT0gdm9pZCAwICkgYSA9IHt9O1xuICBpZiAoIGIgPT09IHZvaWQgMCApIGIgPSB7fTtcblxuICAvLyBoYW5kbGUgbnVsbCB2YWx1ZSAjMTU2NlxuICBpZiAoIWEgfHwgIWIpIHsgcmV0dXJuIGEgPT09IGIgfVxuICB2YXIgYUtleXMgPSBPYmplY3Qua2V5cyhhKS5zb3J0KCk7XG4gIHZhciBiS2V5cyA9IE9iamVjdC5rZXlzKGIpLnNvcnQoKTtcbiAgaWYgKGFLZXlzLmxlbmd0aCAhPT0gYktleXMubGVuZ3RoKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH1cbiAgcmV0dXJuIGFLZXlzLmV2ZXJ5KGZ1bmN0aW9uIChrZXksIGkpIHtcbiAgICB2YXIgYVZhbCA9IGFba2V5XTtcbiAgICB2YXIgYktleSA9IGJLZXlzW2ldO1xuICAgIGlmIChiS2V5ICE9PSBrZXkpIHsgcmV0dXJuIGZhbHNlIH1cbiAgICB2YXIgYlZhbCA9IGJba2V5XTtcbiAgICAvLyBxdWVyeSB2YWx1ZXMgY2FuIGJlIG51bGwgYW5kIHVuZGVmaW5lZFxuICAgIGlmIChhVmFsID09IG51bGwgfHwgYlZhbCA9PSBudWxsKSB7IHJldHVybiBhVmFsID09PSBiVmFsIH1cbiAgICAvLyBjaGVjayBuZXN0ZWQgZXF1YWxpdHlcbiAgICBpZiAodHlwZW9mIGFWYWwgPT09ICdvYmplY3QnICYmIHR5cGVvZiBiVmFsID09PSAnb2JqZWN0Jykge1xuICAgICAgcmV0dXJuIGlzT2JqZWN0RXF1YWwoYVZhbCwgYlZhbClcbiAgICB9XG4gICAgcmV0dXJuIFN0cmluZyhhVmFsKSA9PT0gU3RyaW5nKGJWYWwpXG4gIH0pXG59XG5cbmZ1bmN0aW9uIGlzSW5jbHVkZWRSb3V0ZSAoY3VycmVudCwgdGFyZ2V0KSB7XG4gIHJldHVybiAoXG4gICAgY3VycmVudC5wYXRoLnJlcGxhY2UodHJhaWxpbmdTbGFzaFJFLCAnLycpLmluZGV4T2YoXG4gICAgICB0YXJnZXQucGF0aC5yZXBsYWNlKHRyYWlsaW5nU2xhc2hSRSwgJy8nKVxuICAgICkgPT09IDAgJiZcbiAgICAoIXRhcmdldC5oYXNoIHx8IGN1cnJlbnQuaGFzaCA9PT0gdGFyZ2V0Lmhhc2gpICYmXG4gICAgcXVlcnlJbmNsdWRlcyhjdXJyZW50LnF1ZXJ5LCB0YXJnZXQucXVlcnkpXG4gIClcbn1cblxuZnVuY3Rpb24gcXVlcnlJbmNsdWRlcyAoY3VycmVudCwgdGFyZ2V0KSB7XG4gIGZvciAodmFyIGtleSBpbiB0YXJnZXQpIHtcbiAgICBpZiAoIShrZXkgaW4gY3VycmVudCkpIHtcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH1cbiAgfVxuICByZXR1cm4gdHJ1ZVxufVxuXG5mdW5jdGlvbiBoYW5kbGVSb3V0ZUVudGVyZWQgKHJvdXRlKSB7XG4gIGZvciAodmFyIGkgPSAwOyBpIDwgcm91dGUubWF0Y2hlZC5sZW5ndGg7IGkrKykge1xuICAgIHZhciByZWNvcmQgPSByb3V0ZS5tYXRjaGVkW2ldO1xuICAgIGZvciAodmFyIG5hbWUgaW4gcmVjb3JkLmluc3RhbmNlcykge1xuICAgICAgdmFyIGluc3RhbmNlID0gcmVjb3JkLmluc3RhbmNlc1tuYW1lXTtcbiAgICAgIHZhciBjYnMgPSByZWNvcmQuZW50ZXJlZENic1tuYW1lXTtcbiAgICAgIGlmICghaW5zdGFuY2UgfHwgIWNicykgeyBjb250aW51ZSB9XG4gICAgICBkZWxldGUgcmVjb3JkLmVudGVyZWRDYnNbbmFtZV07XG4gICAgICBmb3IgKHZhciBpJDEgPSAwOyBpJDEgPCBjYnMubGVuZ3RoOyBpJDErKykge1xuICAgICAgICBpZiAoIWluc3RhbmNlLl9pc0JlaW5nRGVzdHJveWVkKSB7IGNic1tpJDFdKGluc3RhbmNlKTsgfVxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG52YXIgVmlldyA9IHtcbiAgbmFtZTogJ1JvdXRlclZpZXcnLFxuICBmdW5jdGlvbmFsOiB0cnVlLFxuICBwcm9wczoge1xuICAgIG5hbWU6IHtcbiAgICAgIHR5cGU6IFN0cmluZyxcbiAgICAgIGRlZmF1bHQ6ICdkZWZhdWx0J1xuICAgIH1cbiAgfSxcbiAgcmVuZGVyOiBmdW5jdGlvbiByZW5kZXIgKF8sIHJlZikge1xuICAgIHZhciBwcm9wcyA9IHJlZi5wcm9wcztcbiAgICB2YXIgY2hpbGRyZW4gPSByZWYuY2hpbGRyZW47XG4gICAgdmFyIHBhcmVudCA9IHJlZi5wYXJlbnQ7XG4gICAgdmFyIGRhdGEgPSByZWYuZGF0YTtcblxuICAgIC8vIHVzZWQgYnkgZGV2dG9vbHMgdG8gZGlzcGxheSBhIHJvdXRlci12aWV3IGJhZGdlXG4gICAgZGF0YS5yb3V0ZXJWaWV3ID0gdHJ1ZTtcblxuICAgIC8vIGRpcmVjdGx5IHVzZSBwYXJlbnQgY29udGV4dCdzIGNyZWF0ZUVsZW1lbnQoKSBmdW5jdGlvblxuICAgIC8vIHNvIHRoYXQgY29tcG9uZW50cyByZW5kZXJlZCBieSByb3V0ZXItdmlldyBjYW4gcmVzb2x2ZSBuYW1lZCBzbG90c1xuICAgIHZhciBoID0gcGFyZW50LiRjcmVhdGVFbGVtZW50O1xuICAgIHZhciBuYW1lID0gcHJvcHMubmFtZTtcbiAgICB2YXIgcm91dGUgPSBwYXJlbnQuJHJvdXRlO1xuICAgIHZhciBjYWNoZSA9IHBhcmVudC5fcm91dGVyVmlld0NhY2hlIHx8IChwYXJlbnQuX3JvdXRlclZpZXdDYWNoZSA9IHt9KTtcblxuICAgIC8vIGRldGVybWluZSBjdXJyZW50IHZpZXcgZGVwdGgsIGFsc28gY2hlY2sgdG8gc2VlIGlmIHRoZSB0cmVlXG4gICAgLy8gaGFzIGJlZW4gdG9nZ2xlZCBpbmFjdGl2ZSBidXQga2VwdC1hbGl2ZS5cbiAgICB2YXIgZGVwdGggPSAwO1xuICAgIHZhciBpbmFjdGl2ZSA9IGZhbHNlO1xuICAgIHdoaWxlIChwYXJlbnQgJiYgcGFyZW50Ll9yb3V0ZXJSb290ICE9PSBwYXJlbnQpIHtcbiAgICAgIHZhciB2bm9kZURhdGEgPSBwYXJlbnQuJHZub2RlID8gcGFyZW50LiR2bm9kZS5kYXRhIDoge307XG4gICAgICBpZiAodm5vZGVEYXRhLnJvdXRlclZpZXcpIHtcbiAgICAgICAgZGVwdGgrKztcbiAgICAgIH1cbiAgICAgIGlmICh2bm9kZURhdGEua2VlcEFsaXZlICYmIHBhcmVudC5fZGlyZWN0SW5hY3RpdmUgJiYgcGFyZW50Ll9pbmFjdGl2ZSkge1xuICAgICAgICBpbmFjdGl2ZSA9IHRydWU7XG4gICAgICB9XG4gICAgICBwYXJlbnQgPSBwYXJlbnQuJHBhcmVudDtcbiAgICB9XG4gICAgZGF0YS5yb3V0ZXJWaWV3RGVwdGggPSBkZXB0aDtcblxuICAgIC8vIHJlbmRlciBwcmV2aW91cyB2aWV3IGlmIHRoZSB0cmVlIGlzIGluYWN0aXZlIGFuZCBrZXB0LWFsaXZlXG4gICAgaWYgKGluYWN0aXZlKSB7XG4gICAgICB2YXIgY2FjaGVkRGF0YSA9IGNhY2hlW25hbWVdO1xuICAgICAgdmFyIGNhY2hlZENvbXBvbmVudCA9IGNhY2hlZERhdGEgJiYgY2FjaGVkRGF0YS5jb21wb25lbnQ7XG4gICAgICBpZiAoY2FjaGVkQ29tcG9uZW50KSB7XG4gICAgICAgIC8vICMyMzAxXG4gICAgICAgIC8vIHBhc3MgcHJvcHNcbiAgICAgICAgaWYgKGNhY2hlZERhdGEuY29uZmlnUHJvcHMpIHtcbiAgICAgICAgICBmaWxsUHJvcHNpbkRhdGEoY2FjaGVkQ29tcG9uZW50LCBkYXRhLCBjYWNoZWREYXRhLnJvdXRlLCBjYWNoZWREYXRhLmNvbmZpZ1Byb3BzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaChjYWNoZWRDb21wb25lbnQsIGRhdGEsIGNoaWxkcmVuKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gcmVuZGVyIHByZXZpb3VzIGVtcHR5IHZpZXdcbiAgICAgICAgcmV0dXJuIGgoKVxuICAgICAgfVxuICAgIH1cblxuICAgIHZhciBtYXRjaGVkID0gcm91dGUubWF0Y2hlZFtkZXB0aF07XG4gICAgdmFyIGNvbXBvbmVudCA9IG1hdGNoZWQgJiYgbWF0Y2hlZC5jb21wb25lbnRzW25hbWVdO1xuXG4gICAgLy8gcmVuZGVyIGVtcHR5IG5vZGUgaWYgbm8gbWF0Y2hlZCByb3V0ZSBvciBubyBjb25maWcgY29tcG9uZW50XG4gICAgaWYgKCFtYXRjaGVkIHx8ICFjb21wb25lbnQpIHtcbiAgICAgIGNhY2hlW25hbWVdID0gbnVsbDtcbiAgICAgIHJldHVybiBoKClcbiAgICB9XG5cbiAgICAvLyBjYWNoZSBjb21wb25lbnRcbiAgICBjYWNoZVtuYW1lXSA9IHsgY29tcG9uZW50OiBjb21wb25lbnQgfTtcblxuICAgIC8vIGF0dGFjaCBpbnN0YW5jZSByZWdpc3RyYXRpb24gaG9va1xuICAgIC8vIHRoaXMgd2lsbCBiZSBjYWxsZWQgaW4gdGhlIGluc3RhbmNlJ3MgaW5qZWN0ZWQgbGlmZWN5Y2xlIGhvb2tzXG4gICAgZGF0YS5yZWdpc3RlclJvdXRlSW5zdGFuY2UgPSBmdW5jdGlvbiAodm0sIHZhbCkge1xuICAgICAgLy8gdmFsIGNvdWxkIGJlIHVuZGVmaW5lZCBmb3IgdW5yZWdpc3RyYXRpb25cbiAgICAgIHZhciBjdXJyZW50ID0gbWF0Y2hlZC5pbnN0YW5jZXNbbmFtZV07XG4gICAgICBpZiAoXG4gICAgICAgICh2YWwgJiYgY3VycmVudCAhPT0gdm0pIHx8XG4gICAgICAgICghdmFsICYmIGN1cnJlbnQgPT09IHZtKVxuICAgICAgKSB7XG4gICAgICAgIG1hdGNoZWQuaW5zdGFuY2VzW25hbWVdID0gdmFsO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIGFsc28gcmVnaXN0ZXIgaW5zdGFuY2UgaW4gcHJlcGF0Y2ggaG9va1xuICAgIC8vIGluIGNhc2UgdGhlIHNhbWUgY29tcG9uZW50IGluc3RhbmNlIGlzIHJldXNlZCBhY3Jvc3MgZGlmZmVyZW50IHJvdXRlc1xuICAgIDsoZGF0YS5ob29rIHx8IChkYXRhLmhvb2sgPSB7fSkpLnByZXBhdGNoID0gZnVuY3Rpb24gKF8sIHZub2RlKSB7XG4gICAgICBtYXRjaGVkLmluc3RhbmNlc1tuYW1lXSA9IHZub2RlLmNvbXBvbmVudEluc3RhbmNlO1xuICAgIH07XG5cbiAgICAvLyByZWdpc3RlciBpbnN0YW5jZSBpbiBpbml0IGhvb2tcbiAgICAvLyBpbiBjYXNlIGtlcHQtYWxpdmUgY29tcG9uZW50IGJlIGFjdGl2ZWQgd2hlbiByb3V0ZXMgY2hhbmdlZFxuICAgIGRhdGEuaG9vay5pbml0ID0gZnVuY3Rpb24gKHZub2RlKSB7XG4gICAgICBpZiAodm5vZGUuZGF0YS5rZWVwQWxpdmUgJiZcbiAgICAgICAgdm5vZGUuY29tcG9uZW50SW5zdGFuY2UgJiZcbiAgICAgICAgdm5vZGUuY29tcG9uZW50SW5zdGFuY2UgIT09IG1hdGNoZWQuaW5zdGFuY2VzW25hbWVdXG4gICAgICApIHtcbiAgICAgICAgbWF0Y2hlZC5pbnN0YW5jZXNbbmFtZV0gPSB2bm9kZS5jb21wb25lbnRJbnN0YW5jZTtcbiAgICAgIH1cblxuICAgICAgLy8gaWYgdGhlIHJvdXRlIHRyYW5zaXRpb24gaGFzIGFscmVhZHkgYmVlbiBjb25maXJtZWQgdGhlbiB3ZSB3ZXJlbid0XG4gICAgICAvLyBhYmxlIHRvIGNhbGwgdGhlIGNicyBkdXJpbmcgY29uZmlybWF0aW9uIGFzIHRoZSBjb21wb25lbnQgd2FzIG5vdFxuICAgICAgLy8gcmVnaXN0ZXJlZCB5ZXQsIHNvIHdlIGNhbGwgaXQgaGVyZS5cbiAgICAgIGhhbmRsZVJvdXRlRW50ZXJlZChyb3V0ZSk7XG4gICAgfTtcblxuICAgIHZhciBjb25maWdQcm9wcyA9IG1hdGNoZWQucHJvcHMgJiYgbWF0Y2hlZC5wcm9wc1tuYW1lXTtcbiAgICAvLyBzYXZlIHJvdXRlIGFuZCBjb25maWdQcm9wcyBpbiBjYWNoZVxuICAgIGlmIChjb25maWdQcm9wcykge1xuICAgICAgZXh0ZW5kKGNhY2hlW25hbWVdLCB7XG4gICAgICAgIHJvdXRlOiByb3V0ZSxcbiAgICAgICAgY29uZmlnUHJvcHM6IGNvbmZpZ1Byb3BzXG4gICAgICB9KTtcbiAgICAgIGZpbGxQcm9wc2luRGF0YShjb21wb25lbnQsIGRhdGEsIHJvdXRlLCBjb25maWdQcm9wcyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIGgoY29tcG9uZW50LCBkYXRhLCBjaGlsZHJlbilcbiAgfVxufTtcblxuZnVuY3Rpb24gZmlsbFByb3BzaW5EYXRhIChjb21wb25lbnQsIGRhdGEsIHJvdXRlLCBjb25maWdQcm9wcykge1xuICAvLyByZXNvbHZlIHByb3BzXG4gIHZhciBwcm9wc1RvUGFzcyA9IGRhdGEucHJvcHMgPSByZXNvbHZlUHJvcHMocm91dGUsIGNvbmZpZ1Byb3BzKTtcbiAgaWYgKHByb3BzVG9QYXNzKSB7XG4gICAgLy8gY2xvbmUgdG8gcHJldmVudCBtdXRhdGlvblxuICAgIHByb3BzVG9QYXNzID0gZGF0YS5wcm9wcyA9IGV4dGVuZCh7fSwgcHJvcHNUb1Bhc3MpO1xuICAgIC8vIHBhc3Mgbm9uLWRlY2xhcmVkIHByb3BzIGFzIGF0dHJzXG4gICAgdmFyIGF0dHJzID0gZGF0YS5hdHRycyA9IGRhdGEuYXR0cnMgfHwge307XG4gICAgZm9yICh2YXIga2V5IGluIHByb3BzVG9QYXNzKSB7XG4gICAgICBpZiAoIWNvbXBvbmVudC5wcm9wcyB8fCAhKGtleSBpbiBjb21wb25lbnQucHJvcHMpKSB7XG4gICAgICAgIGF0dHJzW2tleV0gPSBwcm9wc1RvUGFzc1trZXldO1xuICAgICAgICBkZWxldGUgcHJvcHNUb1Bhc3Nba2V5XTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVByb3BzIChyb3V0ZSwgY29uZmlnKSB7XG4gIHN3aXRjaCAodHlwZW9mIGNvbmZpZykge1xuICAgIGNhc2UgJ3VuZGVmaW5lZCc6XG4gICAgICByZXR1cm5cbiAgICBjYXNlICdvYmplY3QnOlxuICAgICAgcmV0dXJuIGNvbmZpZ1xuICAgIGNhc2UgJ2Z1bmN0aW9uJzpcbiAgICAgIHJldHVybiBjb25maWcocm91dGUpXG4gICAgY2FzZSAnYm9vbGVhbic6XG4gICAgICByZXR1cm4gY29uZmlnID8gcm91dGUucGFyYW1zIDogdW5kZWZpbmVkXG4gICAgZGVmYXVsdDpcbiAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICAgIHdhcm4oXG4gICAgICAgICAgZmFsc2UsXG4gICAgICAgICAgXCJwcm9wcyBpbiBcXFwiXCIgKyAocm91dGUucGF0aCkgKyBcIlxcXCIgaXMgYSBcIiArICh0eXBlb2YgY29uZmlnKSArIFwiLCBcIiArXG4gICAgICAgICAgXCJleHBlY3RpbmcgYW4gb2JqZWN0LCBmdW5jdGlvbiBvciBib29sZWFuLlwiXG4gICAgICAgICk7XG4gICAgICB9XG4gIH1cbn1cblxuLyogICovXG5cbmZ1bmN0aW9uIHJlc29sdmVQYXRoIChcbiAgcmVsYXRpdmUsXG4gIGJhc2UsXG4gIGFwcGVuZFxuKSB7XG4gIHZhciBmaXJzdENoYXIgPSByZWxhdGl2ZS5jaGFyQXQoMCk7XG4gIGlmIChmaXJzdENoYXIgPT09ICcvJykge1xuICAgIHJldHVybiByZWxhdGl2ZVxuICB9XG5cbiAgaWYgKGZpcnN0Q2hhciA9PT0gJz8nIHx8IGZpcnN0Q2hhciA9PT0gJyMnKSB7XG4gICAgcmV0dXJuIGJhc2UgKyByZWxhdGl2ZVxuICB9XG5cbiAgdmFyIHN0YWNrID0gYmFzZS5zcGxpdCgnLycpO1xuXG4gIC8vIHJlbW92ZSB0cmFpbGluZyBzZWdtZW50IGlmOlxuICAvLyAtIG5vdCBhcHBlbmRpbmdcbiAgLy8gLSBhcHBlbmRpbmcgdG8gdHJhaWxpbmcgc2xhc2ggKGxhc3Qgc2VnbWVudCBpcyBlbXB0eSlcbiAgaWYgKCFhcHBlbmQgfHwgIXN0YWNrW3N0YWNrLmxlbmd0aCAtIDFdKSB7XG4gICAgc3RhY2sucG9wKCk7XG4gIH1cblxuICAvLyByZXNvbHZlIHJlbGF0aXZlIHBhdGhcbiAgdmFyIHNlZ21lbnRzID0gcmVsYXRpdmUucmVwbGFjZSgvXlxcLy8sICcnKS5zcGxpdCgnLycpO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IHNlZ21lbnRzLmxlbmd0aDsgaSsrKSB7XG4gICAgdmFyIHNlZ21lbnQgPSBzZWdtZW50c1tpXTtcbiAgICBpZiAoc2VnbWVudCA9PT0gJy4uJykge1xuICAgICAgc3RhY2sucG9wKCk7XG4gICAgfSBlbHNlIGlmIChzZWdtZW50ICE9PSAnLicpIHtcbiAgICAgIHN0YWNrLnB1c2goc2VnbWVudCk7XG4gICAgfVxuICB9XG5cbiAgLy8gZW5zdXJlIGxlYWRpbmcgc2xhc2hcbiAgaWYgKHN0YWNrWzBdICE9PSAnJykge1xuICAgIHN0YWNrLnVuc2hpZnQoJycpO1xuICB9XG5cbiAgcmV0dXJuIHN0YWNrLmpvaW4oJy8nKVxufVxuXG5mdW5jdGlvbiBwYXJzZVBhdGggKHBhdGgpIHtcbiAgdmFyIGhhc2ggPSAnJztcbiAgdmFyIHF1ZXJ5ID0gJyc7XG5cbiAgdmFyIGhhc2hJbmRleCA9IHBhdGguaW5kZXhPZignIycpO1xuICBpZiAoaGFzaEluZGV4ID49IDApIHtcbiAgICBoYXNoID0gcGF0aC5zbGljZShoYXNoSW5kZXgpO1xuICAgIHBhdGggPSBwYXRoLnNsaWNlKDAsIGhhc2hJbmRleCk7XG4gIH1cblxuICB2YXIgcXVlcnlJbmRleCA9IHBhdGguaW5kZXhPZignPycpO1xuICBpZiAocXVlcnlJbmRleCA+PSAwKSB7XG4gICAgcXVlcnkgPSBwYXRoLnNsaWNlKHF1ZXJ5SW5kZXggKyAxKTtcbiAgICBwYXRoID0gcGF0aC5zbGljZSgwLCBxdWVyeUluZGV4KTtcbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcGF0aDogcGF0aCxcbiAgICBxdWVyeTogcXVlcnksXG4gICAgaGFzaDogaGFzaFxuICB9XG59XG5cbmZ1bmN0aW9uIGNsZWFuUGF0aCAocGF0aCkge1xuICByZXR1cm4gcGF0aC5yZXBsYWNlKC9cXC9cXC8vZywgJy8nKVxufVxuXG52YXIgaXNhcnJheSA9IEFycmF5LmlzQXJyYXkgfHwgZnVuY3Rpb24gKGFycikge1xuICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGFycikgPT0gJ1tvYmplY3QgQXJyYXldJztcbn07XG5cbi8qKlxuICogRXhwb3NlIGBwYXRoVG9SZWdleHBgLlxuICovXG52YXIgcGF0aFRvUmVnZXhwXzEgPSBwYXRoVG9SZWdleHA7XG52YXIgcGFyc2VfMSA9IHBhcnNlO1xudmFyIGNvbXBpbGVfMSA9IGNvbXBpbGU7XG52YXIgdG9rZW5zVG9GdW5jdGlvbl8xID0gdG9rZW5zVG9GdW5jdGlvbjtcbnZhciB0b2tlbnNUb1JlZ0V4cF8xID0gdG9rZW5zVG9SZWdFeHA7XG5cbi8qKlxuICogVGhlIG1haW4gcGF0aCBtYXRjaGluZyByZWdleHAgdXRpbGl0eS5cbiAqXG4gKiBAdHlwZSB7UmVnRXhwfVxuICovXG52YXIgUEFUSF9SRUdFWFAgPSBuZXcgUmVnRXhwKFtcbiAgLy8gTWF0Y2ggZXNjYXBlZCBjaGFyYWN0ZXJzIHRoYXQgd291bGQgb3RoZXJ3aXNlIGFwcGVhciBpbiBmdXR1cmUgbWF0Y2hlcy5cbiAgLy8gVGhpcyBhbGxvd3MgdGhlIHVzZXIgdG8gZXNjYXBlIHNwZWNpYWwgY2hhcmFjdGVycyB0aGF0IHdvbid0IHRyYW5zZm9ybS5cbiAgJyhcXFxcXFxcXC4pJyxcbiAgLy8gTWF0Y2ggRXhwcmVzcy1zdHlsZSBwYXJhbWV0ZXJzIGFuZCB1bi1uYW1lZCBwYXJhbWV0ZXJzIHdpdGggYSBwcmVmaXhcbiAgLy8gYW5kIG9wdGlvbmFsIHN1ZmZpeGVzLiBNYXRjaGVzIGFwcGVhciBhczpcbiAgLy9cbiAgLy8gXCIvOnRlc3QoXFxcXGQrKT9cIiA9PiBbXCIvXCIsIFwidGVzdFwiLCBcIlxcZCtcIiwgdW5kZWZpbmVkLCBcIj9cIiwgdW5kZWZpbmVkXVxuICAvLyBcIi9yb3V0ZShcXFxcZCspXCIgID0+IFt1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBcIlxcZCtcIiwgdW5kZWZpbmVkLCB1bmRlZmluZWRdXG4gIC8vIFwiLypcIiAgICAgICAgICAgID0+IFtcIi9cIiwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCBcIipcIl1cbiAgJyhbXFxcXC8uXSk/KD86KD86XFxcXDooXFxcXHcrKSg/OlxcXFwoKCg/OlxcXFxcXFxcLnxbXlxcXFxcXFxcKCldKSspXFxcXCkpP3xcXFxcKCgoPzpcXFxcXFxcXC58W15cXFxcXFxcXCgpXSkrKVxcXFwpKShbKyo/XSk/fChcXFxcKikpJ1xuXS5qb2luKCd8JyksICdnJyk7XG5cbi8qKlxuICogUGFyc2UgYSBzdHJpbmcgZm9yIHRoZSByYXcgdG9rZW5zLlxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gIHN0clxuICogQHBhcmFtICB7T2JqZWN0PX0gb3B0aW9uc1xuICogQHJldHVybiB7IUFycmF5fVxuICovXG5mdW5jdGlvbiBwYXJzZSAoc3RyLCBvcHRpb25zKSB7XG4gIHZhciB0b2tlbnMgPSBbXTtcbiAgdmFyIGtleSA9IDA7XG4gIHZhciBpbmRleCA9IDA7XG4gIHZhciBwYXRoID0gJyc7XG4gIHZhciBkZWZhdWx0RGVsaW1pdGVyID0gb3B0aW9ucyAmJiBvcHRpb25zLmRlbGltaXRlciB8fCAnLyc7XG4gIHZhciByZXM7XG5cbiAgd2hpbGUgKChyZXMgPSBQQVRIX1JFR0VYUC5leGVjKHN0cikpICE9IG51bGwpIHtcbiAgICB2YXIgbSA9IHJlc1swXTtcbiAgICB2YXIgZXNjYXBlZCA9IHJlc1sxXTtcbiAgICB2YXIgb2Zmc2V0ID0gcmVzLmluZGV4O1xuICAgIHBhdGggKz0gc3RyLnNsaWNlKGluZGV4LCBvZmZzZXQpO1xuICAgIGluZGV4ID0gb2Zmc2V0ICsgbS5sZW5ndGg7XG5cbiAgICAvLyBJZ25vcmUgYWxyZWFkeSBlc2NhcGVkIHNlcXVlbmNlcy5cbiAgICBpZiAoZXNjYXBlZCkge1xuICAgICAgcGF0aCArPSBlc2NhcGVkWzFdO1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICB2YXIgbmV4dCA9IHN0cltpbmRleF07XG4gICAgdmFyIHByZWZpeCA9IHJlc1syXTtcbiAgICB2YXIgbmFtZSA9IHJlc1szXTtcbiAgICB2YXIgY2FwdHVyZSA9IHJlc1s0XTtcbiAgICB2YXIgZ3JvdXAgPSByZXNbNV07XG4gICAgdmFyIG1vZGlmaWVyID0gcmVzWzZdO1xuICAgIHZhciBhc3RlcmlzayA9IHJlc1s3XTtcblxuICAgIC8vIFB1c2ggdGhlIGN1cnJlbnQgcGF0aCBvbnRvIHRoZSB0b2tlbnMuXG4gICAgaWYgKHBhdGgpIHtcbiAgICAgIHRva2Vucy5wdXNoKHBhdGgpO1xuICAgICAgcGF0aCA9ICcnO1xuICAgIH1cblxuICAgIHZhciBwYXJ0aWFsID0gcHJlZml4ICE9IG51bGwgJiYgbmV4dCAhPSBudWxsICYmIG5leHQgIT09IHByZWZpeDtcbiAgICB2YXIgcmVwZWF0ID0gbW9kaWZpZXIgPT09ICcrJyB8fCBtb2RpZmllciA9PT0gJyonO1xuICAgIHZhciBvcHRpb25hbCA9IG1vZGlmaWVyID09PSAnPycgfHwgbW9kaWZpZXIgPT09ICcqJztcbiAgICB2YXIgZGVsaW1pdGVyID0gcmVzWzJdIHx8IGRlZmF1bHREZWxpbWl0ZXI7XG4gICAgdmFyIHBhdHRlcm4gPSBjYXB0dXJlIHx8IGdyb3VwO1xuXG4gICAgdG9rZW5zLnB1c2goe1xuICAgICAgbmFtZTogbmFtZSB8fCBrZXkrKyxcbiAgICAgIHByZWZpeDogcHJlZml4IHx8ICcnLFxuICAgICAgZGVsaW1pdGVyOiBkZWxpbWl0ZXIsXG4gICAgICBvcHRpb25hbDogb3B0aW9uYWwsXG4gICAgICByZXBlYXQ6IHJlcGVhdCxcbiAgICAgIHBhcnRpYWw6IHBhcnRpYWwsXG4gICAgICBhc3RlcmlzazogISFhc3RlcmlzayxcbiAgICAgIHBhdHRlcm46IHBhdHRlcm4gPyBlc2NhcGVHcm91cChwYXR0ZXJuKSA6IChhc3RlcmlzayA/ICcuKicgOiAnW14nICsgZXNjYXBlU3RyaW5nKGRlbGltaXRlcikgKyAnXSs/JylcbiAgICB9KTtcbiAgfVxuXG4gIC8vIE1hdGNoIGFueSBjaGFyYWN0ZXJzIHN0aWxsIHJlbWFpbmluZy5cbiAgaWYgKGluZGV4IDwgc3RyLmxlbmd0aCkge1xuICAgIHBhdGggKz0gc3RyLnN1YnN0cihpbmRleCk7XG4gIH1cblxuICAvLyBJZiB0aGUgcGF0aCBleGlzdHMsIHB1c2ggaXQgb250byB0aGUgZW5kLlxuICBpZiAocGF0aCkge1xuICAgIHRva2Vucy5wdXNoKHBhdGgpO1xuICB9XG5cbiAgcmV0dXJuIHRva2Vuc1xufVxuXG4vKipcbiAqIENvbXBpbGUgYSBzdHJpbmcgdG8gYSB0ZW1wbGF0ZSBmdW5jdGlvbiBmb3IgdGhlIHBhdGguXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSAgICAgICAgICAgICBzdHJcbiAqIEBwYXJhbSAge09iamVjdD19ICAgICAgICAgICAgb3B0aW9uc1xuICogQHJldHVybiB7IWZ1bmN0aW9uKE9iamVjdD0sIE9iamVjdD0pfVxuICovXG5mdW5jdGlvbiBjb21waWxlIChzdHIsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHRva2Vuc1RvRnVuY3Rpb24ocGFyc2Uoc3RyLCBvcHRpb25zKSwgb3B0aW9ucylcbn1cblxuLyoqXG4gKiBQcmV0dGllciBlbmNvZGluZyBvZiBVUkkgcGF0aCBzZWdtZW50cy5cbiAqXG4gKiBAcGFyYW0gIHtzdHJpbmd9XG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIGVuY29kZVVSSUNvbXBvbmVudFByZXR0eSAoc3RyKSB7XG4gIHJldHVybiBlbmNvZGVVUkkoc3RyKS5yZXBsYWNlKC9bXFwvPyNdL2csIGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuICclJyArIGMuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKVxuICB9KVxufVxuXG4vKipcbiAqIEVuY29kZSB0aGUgYXN0ZXJpc2sgcGFyYW1ldGVyLiBTaW1pbGFyIHRvIGBwcmV0dHlgLCBidXQgYWxsb3dzIHNsYXNoZXMuXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfVxuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiBlbmNvZGVBc3RlcmlzayAoc3RyKSB7XG4gIHJldHVybiBlbmNvZGVVUkkoc3RyKS5yZXBsYWNlKC9bPyNdL2csIGZ1bmN0aW9uIChjKSB7XG4gICAgcmV0dXJuICclJyArIGMuY2hhckNvZGVBdCgwKS50b1N0cmluZygxNikudG9VcHBlckNhc2UoKVxuICB9KVxufVxuXG4vKipcbiAqIEV4cG9zZSBhIG1ldGhvZCBmb3IgdHJhbnNmb3JtaW5nIHRva2VucyBpbnRvIHRoZSBwYXRoIGZ1bmN0aW9uLlxuICovXG5mdW5jdGlvbiB0b2tlbnNUb0Z1bmN0aW9uICh0b2tlbnMsIG9wdGlvbnMpIHtcbiAgLy8gQ29tcGlsZSBhbGwgdGhlIHRva2VucyBpbnRvIHJlZ2V4cHMuXG4gIHZhciBtYXRjaGVzID0gbmV3IEFycmF5KHRva2Vucy5sZW5ndGgpO1xuXG4gIC8vIENvbXBpbGUgYWxsIHRoZSBwYXR0ZXJucyBiZWZvcmUgY29tcGlsYXRpb24uXG4gIGZvciAodmFyIGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgaWYgKHR5cGVvZiB0b2tlbnNbaV0gPT09ICdvYmplY3QnKSB7XG4gICAgICBtYXRjaGVzW2ldID0gbmV3IFJlZ0V4cCgnXig/OicgKyB0b2tlbnNbaV0ucGF0dGVybiArICcpJCcsIGZsYWdzKG9wdGlvbnMpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKG9iaiwgb3B0cykge1xuICAgIHZhciBwYXRoID0gJyc7XG4gICAgdmFyIGRhdGEgPSBvYmogfHwge307XG4gICAgdmFyIG9wdGlvbnMgPSBvcHRzIHx8IHt9O1xuICAgIHZhciBlbmNvZGUgPSBvcHRpb25zLnByZXR0eSA/IGVuY29kZVVSSUNvbXBvbmVudFByZXR0eSA6IGVuY29kZVVSSUNvbXBvbmVudDtcblxuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdG9rZW5zLmxlbmd0aDsgaSsrKSB7XG4gICAgICB2YXIgdG9rZW4gPSB0b2tlbnNbaV07XG5cbiAgICAgIGlmICh0eXBlb2YgdG9rZW4gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIHBhdGggKz0gdG9rZW47XG5cbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgdmFyIHZhbHVlID0gZGF0YVt0b2tlbi5uYW1lXTtcbiAgICAgIHZhciBzZWdtZW50O1xuXG4gICAgICBpZiAodmFsdWUgPT0gbnVsbCkge1xuICAgICAgICBpZiAodG9rZW4ub3B0aW9uYWwpIHtcbiAgICAgICAgICAvLyBQcmVwZW5kIHBhcnRpYWwgc2VnbWVudCBwcmVmaXhlcy5cbiAgICAgICAgICBpZiAodG9rZW4ucGFydGlhbCkge1xuICAgICAgICAgICAgcGF0aCArPSB0b2tlbi5wcmVmaXg7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdFeHBlY3RlZCBcIicgKyB0b2tlbi5uYW1lICsgJ1wiIHRvIGJlIGRlZmluZWQnKVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChpc2FycmF5KHZhbHVlKSkge1xuICAgICAgICBpZiAoIXRva2VuLnJlcGVhdCkge1xuICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoJ0V4cGVjdGVkIFwiJyArIHRva2VuLm5hbWUgKyAnXCIgdG8gbm90IHJlcGVhdCwgYnV0IHJlY2VpdmVkIGAnICsgSlNPTi5zdHJpbmdpZnkodmFsdWUpICsgJ2AnKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgIGlmICh0b2tlbi5vcHRpb25hbCkge1xuICAgICAgICAgICAgY29udGludWVcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcignRXhwZWN0ZWQgXCInICsgdG9rZW4ubmFtZSArICdcIiB0byBub3QgYmUgZW1wdHknKVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgdmFsdWUubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICBzZWdtZW50ID0gZW5jb2RlKHZhbHVlW2pdKTtcblxuICAgICAgICAgIGlmICghbWF0Y2hlc1tpXS50ZXN0KHNlZ21lbnQpKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdFeHBlY3RlZCBhbGwgXCInICsgdG9rZW4ubmFtZSArICdcIiB0byBtYXRjaCBcIicgKyB0b2tlbi5wYXR0ZXJuICsgJ1wiLCBidXQgcmVjZWl2ZWQgYCcgKyBKU09OLnN0cmluZ2lmeShzZWdtZW50KSArICdgJylcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBwYXRoICs9IChqID09PSAwID8gdG9rZW4ucHJlZml4IDogdG9rZW4uZGVsaW1pdGVyKSArIHNlZ21lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb250aW51ZVxuICAgICAgfVxuXG4gICAgICBzZWdtZW50ID0gdG9rZW4uYXN0ZXJpc2sgPyBlbmNvZGVBc3Rlcmlzayh2YWx1ZSkgOiBlbmNvZGUodmFsdWUpO1xuXG4gICAgICBpZiAoIW1hdGNoZXNbaV0udGVzdChzZWdtZW50KSkge1xuICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKCdFeHBlY3RlZCBcIicgKyB0b2tlbi5uYW1lICsgJ1wiIHRvIG1hdGNoIFwiJyArIHRva2VuLnBhdHRlcm4gKyAnXCIsIGJ1dCByZWNlaXZlZCBcIicgKyBzZWdtZW50ICsgJ1wiJylcbiAgICAgIH1cblxuICAgICAgcGF0aCArPSB0b2tlbi5wcmVmaXggKyBzZWdtZW50O1xuICAgIH1cblxuICAgIHJldHVybiBwYXRoXG4gIH1cbn1cblxuLyoqXG4gKiBFc2NhcGUgYSByZWd1bGFyIGV4cHJlc3Npb24gc3RyaW5nLlxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gc3RyXG4gKiBAcmV0dXJuIHtzdHJpbmd9XG4gKi9cbmZ1bmN0aW9uIGVzY2FwZVN0cmluZyAoc3RyKSB7XG4gIHJldHVybiBzdHIucmVwbGFjZSgvKFsuKyo/PV4hOiR7fSgpW1xcXXxcXC9cXFxcXSkvZywgJ1xcXFwkMScpXG59XG5cbi8qKlxuICogRXNjYXBlIHRoZSBjYXB0dXJpbmcgZ3JvdXAgYnkgZXNjYXBpbmcgc3BlY2lhbCBjaGFyYWN0ZXJzIGFuZCBtZWFuaW5nLlxuICpcbiAqIEBwYXJhbSAge3N0cmluZ30gZ3JvdXBcbiAqIEByZXR1cm4ge3N0cmluZ31cbiAqL1xuZnVuY3Rpb24gZXNjYXBlR3JvdXAgKGdyb3VwKSB7XG4gIHJldHVybiBncm91cC5yZXBsYWNlKC8oWz0hOiRcXC8oKV0pL2csICdcXFxcJDEnKVxufVxuXG4vKipcbiAqIEF0dGFjaCB0aGUga2V5cyBhcyBhIHByb3BlcnR5IG9mIHRoZSByZWdleHAuXG4gKlxuICogQHBhcmFtICB7IVJlZ0V4cH0gcmVcbiAqIEBwYXJhbSAge0FycmF5fSAgIGtleXNcbiAqIEByZXR1cm4geyFSZWdFeHB9XG4gKi9cbmZ1bmN0aW9uIGF0dGFjaEtleXMgKHJlLCBrZXlzKSB7XG4gIHJlLmtleXMgPSBrZXlzO1xuICByZXR1cm4gcmVcbn1cblxuLyoqXG4gKiBHZXQgdGhlIGZsYWdzIGZvciBhIHJlZ2V4cCBmcm9tIHRoZSBvcHRpb25zLlxuICpcbiAqIEBwYXJhbSAge09iamVjdH0gb3B0aW9uc1xuICogQHJldHVybiB7c3RyaW5nfVxuICovXG5mdW5jdGlvbiBmbGFncyAob3B0aW9ucykge1xuICByZXR1cm4gb3B0aW9ucyAmJiBvcHRpb25zLnNlbnNpdGl2ZSA/ICcnIDogJ2knXG59XG5cbi8qKlxuICogUHVsbCBvdXQga2V5cyBmcm9tIGEgcmVnZXhwLlxuICpcbiAqIEBwYXJhbSAgeyFSZWdFeHB9IHBhdGhcbiAqIEBwYXJhbSAgeyFBcnJheX0gIGtleXNcbiAqIEByZXR1cm4geyFSZWdFeHB9XG4gKi9cbmZ1bmN0aW9uIHJlZ2V4cFRvUmVnZXhwIChwYXRoLCBrZXlzKSB7XG4gIC8vIFVzZSBhIG5lZ2F0aXZlIGxvb2thaGVhZCB0byBtYXRjaCBvbmx5IGNhcHR1cmluZyBncm91cHMuXG4gIHZhciBncm91cHMgPSBwYXRoLnNvdXJjZS5tYXRjaCgvXFwoKD8hXFw/KS9nKTtcblxuICBpZiAoZ3JvdXBzKSB7XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBncm91cHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGtleXMucHVzaCh7XG4gICAgICAgIG5hbWU6IGksXG4gICAgICAgIHByZWZpeDogbnVsbCxcbiAgICAgICAgZGVsaW1pdGVyOiBudWxsLFxuICAgICAgICBvcHRpb25hbDogZmFsc2UsXG4gICAgICAgIHJlcGVhdDogZmFsc2UsXG4gICAgICAgIHBhcnRpYWw6IGZhbHNlLFxuICAgICAgICBhc3RlcmlzazogZmFsc2UsXG4gICAgICAgIHBhdHRlcm46IG51bGxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBhdHRhY2hLZXlzKHBhdGgsIGtleXMpXG59XG5cbi8qKlxuICogVHJhbnNmb3JtIGFuIGFycmF5IGludG8gYSByZWdleHAuXG4gKlxuICogQHBhcmFtICB7IUFycmF5fSAgcGF0aFxuICogQHBhcmFtICB7QXJyYXl9ICAga2V5c1xuICogQHBhcmFtICB7IU9iamVjdH0gb3B0aW9uc1xuICogQHJldHVybiB7IVJlZ0V4cH1cbiAqL1xuZnVuY3Rpb24gYXJyYXlUb1JlZ2V4cCAocGF0aCwga2V5cywgb3B0aW9ucykge1xuICB2YXIgcGFydHMgPSBbXTtcblxuICBmb3IgKHZhciBpID0gMDsgaSA8IHBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICBwYXJ0cy5wdXNoKHBhdGhUb1JlZ2V4cChwYXRoW2ldLCBrZXlzLCBvcHRpb25zKS5zb3VyY2UpO1xuICB9XG5cbiAgdmFyIHJlZ2V4cCA9IG5ldyBSZWdFeHAoJyg/OicgKyBwYXJ0cy5qb2luKCd8JykgKyAnKScsIGZsYWdzKG9wdGlvbnMpKTtcblxuICByZXR1cm4gYXR0YWNoS2V5cyhyZWdleHAsIGtleXMpXG59XG5cbi8qKlxuICogQ3JlYXRlIGEgcGF0aCByZWdleHAgZnJvbSBzdHJpbmcgaW5wdXQuXG4gKlxuICogQHBhcmFtICB7c3RyaW5nfSAgcGF0aFxuICogQHBhcmFtICB7IUFycmF5fSAga2V5c1xuICogQHBhcmFtICB7IU9iamVjdH0gb3B0aW9uc1xuICogQHJldHVybiB7IVJlZ0V4cH1cbiAqL1xuZnVuY3Rpb24gc3RyaW5nVG9SZWdleHAgKHBhdGgsIGtleXMsIG9wdGlvbnMpIHtcbiAgcmV0dXJuIHRva2Vuc1RvUmVnRXhwKHBhcnNlKHBhdGgsIG9wdGlvbnMpLCBrZXlzLCBvcHRpb25zKVxufVxuXG4vKipcbiAqIEV4cG9zZSBhIGZ1bmN0aW9uIGZvciB0YWtpbmcgdG9rZW5zIGFuZCByZXR1cm5pbmcgYSBSZWdFeHAuXG4gKlxuICogQHBhcmFtICB7IUFycmF5fSAgICAgICAgICB0b2tlbnNcbiAqIEBwYXJhbSAgeyhBcnJheXxPYmplY3QpPX0ga2V5c1xuICogQHBhcmFtICB7T2JqZWN0PX0gICAgICAgICBvcHRpb25zXG4gKiBAcmV0dXJuIHshUmVnRXhwfVxuICovXG5mdW5jdGlvbiB0b2tlbnNUb1JlZ0V4cCAodG9rZW5zLCBrZXlzLCBvcHRpb25zKSB7XG4gIGlmICghaXNhcnJheShrZXlzKSkge1xuICAgIG9wdGlvbnMgPSAvKiogQHR5cGUgeyFPYmplY3R9ICovIChrZXlzIHx8IG9wdGlvbnMpO1xuICAgIGtleXMgPSBbXTtcbiAgfVxuXG4gIG9wdGlvbnMgPSBvcHRpb25zIHx8IHt9O1xuXG4gIHZhciBzdHJpY3QgPSBvcHRpb25zLnN0cmljdDtcbiAgdmFyIGVuZCA9IG9wdGlvbnMuZW5kICE9PSBmYWxzZTtcbiAgdmFyIHJvdXRlID0gJyc7XG5cbiAgLy8gSXRlcmF0ZSBvdmVyIHRoZSB0b2tlbnMgYW5kIGNyZWF0ZSBvdXIgcmVnZXhwIHN0cmluZy5cbiAgZm9yICh2YXIgaSA9IDA7IGkgPCB0b2tlbnMubGVuZ3RoOyBpKyspIHtcbiAgICB2YXIgdG9rZW4gPSB0b2tlbnNbaV07XG5cbiAgICBpZiAodHlwZW9mIHRva2VuID09PSAnc3RyaW5nJykge1xuICAgICAgcm91dGUgKz0gZXNjYXBlU3RyaW5nKHRva2VuKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdmFyIHByZWZpeCA9IGVzY2FwZVN0cmluZyh0b2tlbi5wcmVmaXgpO1xuICAgICAgdmFyIGNhcHR1cmUgPSAnKD86JyArIHRva2VuLnBhdHRlcm4gKyAnKSc7XG5cbiAgICAgIGtleXMucHVzaCh0b2tlbik7XG5cbiAgICAgIGlmICh0b2tlbi5yZXBlYXQpIHtcbiAgICAgICAgY2FwdHVyZSArPSAnKD86JyArIHByZWZpeCArIGNhcHR1cmUgKyAnKSonO1xuICAgICAgfVxuXG4gICAgICBpZiAodG9rZW4ub3B0aW9uYWwpIHtcbiAgICAgICAgaWYgKCF0b2tlbi5wYXJ0aWFsKSB7XG4gICAgICAgICAgY2FwdHVyZSA9ICcoPzonICsgcHJlZml4ICsgJygnICsgY2FwdHVyZSArICcpKT8nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGNhcHR1cmUgPSBwcmVmaXggKyAnKCcgKyBjYXB0dXJlICsgJyk/JztcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY2FwdHVyZSA9IHByZWZpeCArICcoJyArIGNhcHR1cmUgKyAnKSc7XG4gICAgICB9XG5cbiAgICAgIHJvdXRlICs9IGNhcHR1cmU7XG4gICAgfVxuICB9XG5cbiAgdmFyIGRlbGltaXRlciA9IGVzY2FwZVN0cmluZyhvcHRpb25zLmRlbGltaXRlciB8fCAnLycpO1xuICB2YXIgZW5kc1dpdGhEZWxpbWl0ZXIgPSByb3V0ZS5zbGljZSgtZGVsaW1pdGVyLmxlbmd0aCkgPT09IGRlbGltaXRlcjtcblxuICAvLyBJbiBub24tc3RyaWN0IG1vZGUgd2UgYWxsb3cgYSBzbGFzaCBhdCB0aGUgZW5kIG9mIG1hdGNoLiBJZiB0aGUgcGF0aCB0b1xuICAvLyBtYXRjaCBhbHJlYWR5IGVuZHMgd2l0aCBhIHNsYXNoLCB3ZSByZW1vdmUgaXQgZm9yIGNvbnNpc3RlbmN5LiBUaGUgc2xhc2hcbiAgLy8gaXMgdmFsaWQgYXQgdGhlIGVuZCBvZiBhIHBhdGggbWF0Y2gsIG5vdCBpbiB0aGUgbWlkZGxlLiBUaGlzIGlzIGltcG9ydGFudFxuICAvLyBpbiBub24tZW5kaW5nIG1vZGUsIHdoZXJlIFwiL3Rlc3QvXCIgc2hvdWxkbid0IG1hdGNoIFwiL3Rlc3QvL3JvdXRlXCIuXG4gIGlmICghc3RyaWN0KSB7XG4gICAgcm91dGUgPSAoZW5kc1dpdGhEZWxpbWl0ZXIgPyByb3V0ZS5zbGljZSgwLCAtZGVsaW1pdGVyLmxlbmd0aCkgOiByb3V0ZSkgKyAnKD86JyArIGRlbGltaXRlciArICcoPz0kKSk/JztcbiAgfVxuXG4gIGlmIChlbmQpIHtcbiAgICByb3V0ZSArPSAnJCc7XG4gIH0gZWxzZSB7XG4gICAgLy8gSW4gbm9uLWVuZGluZyBtb2RlLCB3ZSBuZWVkIHRoZSBjYXB0dXJpbmcgZ3JvdXBzIHRvIG1hdGNoIGFzIG11Y2ggYXNcbiAgICAvLyBwb3NzaWJsZSBieSB1c2luZyBhIHBvc2l0aXZlIGxvb2thaGVhZCB0byB0aGUgZW5kIG9yIG5leHQgcGF0aCBzZWdtZW50LlxuICAgIHJvdXRlICs9IHN0cmljdCAmJiBlbmRzV2l0aERlbGltaXRlciA/ICcnIDogJyg/PScgKyBkZWxpbWl0ZXIgKyAnfCQpJztcbiAgfVxuXG4gIHJldHVybiBhdHRhY2hLZXlzKG5ldyBSZWdFeHAoJ14nICsgcm91dGUsIGZsYWdzKG9wdGlvbnMpKSwga2V5cylcbn1cblxuLyoqXG4gKiBOb3JtYWxpemUgdGhlIGdpdmVuIHBhdGggc3RyaW5nLCByZXR1cm5pbmcgYSByZWd1bGFyIGV4cHJlc3Npb24uXG4gKlxuICogQW4gZW1wdHkgYXJyYXkgY2FuIGJlIHBhc3NlZCBpbiBmb3IgdGhlIGtleXMsIHdoaWNoIHdpbGwgaG9sZCB0aGVcbiAqIHBsYWNlaG9sZGVyIGtleSBkZXNjcmlwdGlvbnMuIEZvciBleGFtcGxlLCB1c2luZyBgL3VzZXIvOmlkYCwgYGtleXNgIHdpbGxcbiAqIGNvbnRhaW4gYFt7IG5hbWU6ICdpZCcsIGRlbGltaXRlcjogJy8nLCBvcHRpb25hbDogZmFsc2UsIHJlcGVhdDogZmFsc2UgfV1gLlxuICpcbiAqIEBwYXJhbSAgeyhzdHJpbmd8UmVnRXhwfEFycmF5KX0gcGF0aFxuICogQHBhcmFtICB7KEFycmF5fE9iamVjdCk9fSAgICAgICBrZXlzXG4gKiBAcGFyYW0gIHtPYmplY3Q9fSAgICAgICAgICAgICAgIG9wdGlvbnNcbiAqIEByZXR1cm4geyFSZWdFeHB9XG4gKi9cbmZ1bmN0aW9uIHBhdGhUb1JlZ2V4cCAocGF0aCwga2V5cywgb3B0aW9ucykge1xuICBpZiAoIWlzYXJyYXkoa2V5cykpIHtcbiAgICBvcHRpb25zID0gLyoqIEB0eXBlIHshT2JqZWN0fSAqLyAoa2V5cyB8fCBvcHRpb25zKTtcbiAgICBrZXlzID0gW107XG4gIH1cblxuICBvcHRpb25zID0gb3B0aW9ucyB8fCB7fTtcblxuICBpZiAocGF0aCBpbnN0YW5jZW9mIFJlZ0V4cCkge1xuICAgIHJldHVybiByZWdleHBUb1JlZ2V4cChwYXRoLCAvKiogQHR5cGUgeyFBcnJheX0gKi8gKGtleXMpKVxuICB9XG5cbiAgaWYgKGlzYXJyYXkocGF0aCkpIHtcbiAgICByZXR1cm4gYXJyYXlUb1JlZ2V4cCgvKiogQHR5cGUgeyFBcnJheX0gKi8gKHBhdGgpLCAvKiogQHR5cGUgeyFBcnJheX0gKi8gKGtleXMpLCBvcHRpb25zKVxuICB9XG5cbiAgcmV0dXJuIHN0cmluZ1RvUmVnZXhwKC8qKiBAdHlwZSB7c3RyaW5nfSAqLyAocGF0aCksIC8qKiBAdHlwZSB7IUFycmF5fSAqLyAoa2V5cyksIG9wdGlvbnMpXG59XG5wYXRoVG9SZWdleHBfMS5wYXJzZSA9IHBhcnNlXzE7XG5wYXRoVG9SZWdleHBfMS5jb21waWxlID0gY29tcGlsZV8xO1xucGF0aFRvUmVnZXhwXzEudG9rZW5zVG9GdW5jdGlvbiA9IHRva2Vuc1RvRnVuY3Rpb25fMTtcbnBhdGhUb1JlZ2V4cF8xLnRva2Vuc1RvUmVnRXhwID0gdG9rZW5zVG9SZWdFeHBfMTtcblxuLyogICovXG5cbi8vICRmbG93LWRpc2FibGUtbGluZVxudmFyIHJlZ2V4cENvbXBpbGVDYWNoZSA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cbmZ1bmN0aW9uIGZpbGxQYXJhbXMgKFxuICBwYXRoLFxuICBwYXJhbXMsXG4gIHJvdXRlTXNnXG4pIHtcbiAgcGFyYW1zID0gcGFyYW1zIHx8IHt9O1xuICB0cnkge1xuICAgIHZhciBmaWxsZXIgPVxuICAgICAgcmVnZXhwQ29tcGlsZUNhY2hlW3BhdGhdIHx8XG4gICAgICAocmVnZXhwQ29tcGlsZUNhY2hlW3BhdGhdID0gcGF0aFRvUmVnZXhwXzEuY29tcGlsZShwYXRoKSk7XG5cbiAgICAvLyBGaXggIzI1MDUgcmVzb2x2aW5nIGFzdGVyaXNrIHJvdXRlcyB7IG5hbWU6ICdub3QtZm91bmQnLCBwYXJhbXM6IHsgcGF0aE1hdGNoOiAnL25vdC1mb3VuZCcgfX1cbiAgICAvLyBhbmQgZml4ICMzMTA2IHNvIHRoYXQgeW91IGNhbiB3b3JrIHdpdGggbG9jYXRpb24gZGVzY3JpcHRvciBvYmplY3QgaGF2aW5nIHBhcmFtcy5wYXRoTWF0Y2ggZXF1YWwgdG8gZW1wdHkgc3RyaW5nXG4gICAgaWYgKHR5cGVvZiBwYXJhbXMucGF0aE1hdGNoID09PSAnc3RyaW5nJykgeyBwYXJhbXNbMF0gPSBwYXJhbXMucGF0aE1hdGNoOyB9XG5cbiAgICByZXR1cm4gZmlsbGVyKHBhcmFtcywgeyBwcmV0dHk6IHRydWUgfSlcbiAgfSBjYXRjaCAoZSkge1xuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICAvLyBGaXggIzMwNzIgbm8gd2FybiBpZiBgcGF0aE1hdGNoYCBpcyBzdHJpbmdcbiAgICAgIHdhcm4odHlwZW9mIHBhcmFtcy5wYXRoTWF0Y2ggPT09ICdzdHJpbmcnLCAoXCJtaXNzaW5nIHBhcmFtIGZvciBcIiArIHJvdXRlTXNnICsgXCI6IFwiICsgKGUubWVzc2FnZSkpKTtcbiAgICB9XG4gICAgcmV0dXJuICcnXG4gIH0gZmluYWxseSB7XG4gICAgLy8gZGVsZXRlIHRoZSAwIGlmIGl0IHdhcyBhZGRlZFxuICAgIGRlbGV0ZSBwYXJhbXNbMF07XG4gIH1cbn1cblxuLyogICovXG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZUxvY2F0aW9uIChcbiAgcmF3LFxuICBjdXJyZW50LFxuICBhcHBlbmQsXG4gIHJvdXRlclxuKSB7XG4gIHZhciBuZXh0ID0gdHlwZW9mIHJhdyA9PT0gJ3N0cmluZycgPyB7IHBhdGg6IHJhdyB9IDogcmF3O1xuICAvLyBuYW1lZCB0YXJnZXRcbiAgaWYgKG5leHQuX25vcm1hbGl6ZWQpIHtcbiAgICByZXR1cm4gbmV4dFxuICB9IGVsc2UgaWYgKG5leHQubmFtZSkge1xuICAgIG5leHQgPSBleHRlbmQoe30sIHJhdyk7XG4gICAgdmFyIHBhcmFtcyA9IG5leHQucGFyYW1zO1xuICAgIGlmIChwYXJhbXMgJiYgdHlwZW9mIHBhcmFtcyA9PT0gJ29iamVjdCcpIHtcbiAgICAgIG5leHQucGFyYW1zID0gZXh0ZW5kKHt9LCBwYXJhbXMpO1xuICAgIH1cbiAgICByZXR1cm4gbmV4dFxuICB9XG5cbiAgLy8gcmVsYXRpdmUgcGFyYW1zXG4gIGlmICghbmV4dC5wYXRoICYmIG5leHQucGFyYW1zICYmIGN1cnJlbnQpIHtcbiAgICBuZXh0ID0gZXh0ZW5kKHt9LCBuZXh0KTtcbiAgICBuZXh0Ll9ub3JtYWxpemVkID0gdHJ1ZTtcbiAgICB2YXIgcGFyYW1zJDEgPSBleHRlbmQoZXh0ZW5kKHt9LCBjdXJyZW50LnBhcmFtcyksIG5leHQucGFyYW1zKTtcbiAgICBpZiAoY3VycmVudC5uYW1lKSB7XG4gICAgICBuZXh0Lm5hbWUgPSBjdXJyZW50Lm5hbWU7XG4gICAgICBuZXh0LnBhcmFtcyA9IHBhcmFtcyQxO1xuICAgIH0gZWxzZSBpZiAoY3VycmVudC5tYXRjaGVkLmxlbmd0aCkge1xuICAgICAgdmFyIHJhd1BhdGggPSBjdXJyZW50Lm1hdGNoZWRbY3VycmVudC5tYXRjaGVkLmxlbmd0aCAtIDFdLnBhdGg7XG4gICAgICBuZXh0LnBhdGggPSBmaWxsUGFyYW1zKHJhd1BhdGgsIHBhcmFtcyQxLCAoXCJwYXRoIFwiICsgKGN1cnJlbnQucGF0aCkpKTtcbiAgICB9IGVsc2UgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgIHdhcm4oZmFsc2UsIFwicmVsYXRpdmUgcGFyYW1zIG5hdmlnYXRpb24gcmVxdWlyZXMgYSBjdXJyZW50IHJvdXRlLlwiKTtcbiAgICB9XG4gICAgcmV0dXJuIG5leHRcbiAgfVxuXG4gIHZhciBwYXJzZWRQYXRoID0gcGFyc2VQYXRoKG5leHQucGF0aCB8fCAnJyk7XG4gIHZhciBiYXNlUGF0aCA9IChjdXJyZW50ICYmIGN1cnJlbnQucGF0aCkgfHwgJy8nO1xuICB2YXIgcGF0aCA9IHBhcnNlZFBhdGgucGF0aFxuICAgID8gcmVzb2x2ZVBhdGgocGFyc2VkUGF0aC5wYXRoLCBiYXNlUGF0aCwgYXBwZW5kIHx8IG5leHQuYXBwZW5kKVxuICAgIDogYmFzZVBhdGg7XG5cbiAgdmFyIHF1ZXJ5ID0gcmVzb2x2ZVF1ZXJ5KFxuICAgIHBhcnNlZFBhdGgucXVlcnksXG4gICAgbmV4dC5xdWVyeSxcbiAgICByb3V0ZXIgJiYgcm91dGVyLm9wdGlvbnMucGFyc2VRdWVyeVxuICApO1xuXG4gIHZhciBoYXNoID0gbmV4dC5oYXNoIHx8IHBhcnNlZFBhdGguaGFzaDtcbiAgaWYgKGhhc2ggJiYgaGFzaC5jaGFyQXQoMCkgIT09ICcjJykge1xuICAgIGhhc2ggPSBcIiNcIiArIGhhc2g7XG4gIH1cblxuICByZXR1cm4ge1xuICAgIF9ub3JtYWxpemVkOiB0cnVlLFxuICAgIHBhdGg6IHBhdGgsXG4gICAgcXVlcnk6IHF1ZXJ5LFxuICAgIGhhc2g6IGhhc2hcbiAgfVxufVxuXG4vKiAgKi9cblxuLy8gd29yayBhcm91bmQgd2VpcmQgZmxvdyBidWdcbnZhciB0b1R5cGVzID0gW1N0cmluZywgT2JqZWN0XTtcbnZhciBldmVudFR5cGVzID0gW1N0cmluZywgQXJyYXldO1xuXG52YXIgbm9vcCA9IGZ1bmN0aW9uICgpIHt9O1xuXG52YXIgd2FybmVkQ3VzdG9tU2xvdDtcbnZhciB3YXJuZWRUYWdQcm9wO1xudmFyIHdhcm5lZEV2ZW50UHJvcDtcblxudmFyIExpbmsgPSB7XG4gIG5hbWU6ICdSb3V0ZXJMaW5rJyxcbiAgcHJvcHM6IHtcbiAgICB0bzoge1xuICAgICAgdHlwZTogdG9UeXBlcyxcbiAgICAgIHJlcXVpcmVkOiB0cnVlXG4gICAgfSxcbiAgICB0YWc6IHtcbiAgICAgIHR5cGU6IFN0cmluZyxcbiAgICAgIGRlZmF1bHQ6ICdhJ1xuICAgIH0sXG4gICAgY3VzdG9tOiBCb29sZWFuLFxuICAgIGV4YWN0OiBCb29sZWFuLFxuICAgIGV4YWN0UGF0aDogQm9vbGVhbixcbiAgICBhcHBlbmQ6IEJvb2xlYW4sXG4gICAgcmVwbGFjZTogQm9vbGVhbixcbiAgICBhY3RpdmVDbGFzczogU3RyaW5nLFxuICAgIGV4YWN0QWN0aXZlQ2xhc3M6IFN0cmluZyxcbiAgICBhcmlhQ3VycmVudFZhbHVlOiB7XG4gICAgICB0eXBlOiBTdHJpbmcsXG4gICAgICBkZWZhdWx0OiAncGFnZSdcbiAgICB9LFxuICAgIGV2ZW50OiB7XG4gICAgICB0eXBlOiBldmVudFR5cGVzLFxuICAgICAgZGVmYXVsdDogJ2NsaWNrJ1xuICAgIH1cbiAgfSxcbiAgcmVuZGVyOiBmdW5jdGlvbiByZW5kZXIgKGgpIHtcbiAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIHZhciByb3V0ZXIgPSB0aGlzLiRyb3V0ZXI7XG4gICAgdmFyIGN1cnJlbnQgPSB0aGlzLiRyb3V0ZTtcbiAgICB2YXIgcmVmID0gcm91dGVyLnJlc29sdmUoXG4gICAgICB0aGlzLnRvLFxuICAgICAgY3VycmVudCxcbiAgICAgIHRoaXMuYXBwZW5kXG4gICAgKTtcbiAgICB2YXIgbG9jYXRpb24gPSByZWYubG9jYXRpb247XG4gICAgdmFyIHJvdXRlID0gcmVmLnJvdXRlO1xuICAgIHZhciBocmVmID0gcmVmLmhyZWY7XG5cbiAgICB2YXIgY2xhc3NlcyA9IHt9O1xuICAgIHZhciBnbG9iYWxBY3RpdmVDbGFzcyA9IHJvdXRlci5vcHRpb25zLmxpbmtBY3RpdmVDbGFzcztcbiAgICB2YXIgZ2xvYmFsRXhhY3RBY3RpdmVDbGFzcyA9IHJvdXRlci5vcHRpb25zLmxpbmtFeGFjdEFjdGl2ZUNsYXNzO1xuICAgIC8vIFN1cHBvcnQgZ2xvYmFsIGVtcHR5IGFjdGl2ZSBjbGFzc1xuICAgIHZhciBhY3RpdmVDbGFzc0ZhbGxiYWNrID1cbiAgICAgIGdsb2JhbEFjdGl2ZUNsYXNzID09IG51bGwgPyAncm91dGVyLWxpbmstYWN0aXZlJyA6IGdsb2JhbEFjdGl2ZUNsYXNzO1xuICAgIHZhciBleGFjdEFjdGl2ZUNsYXNzRmFsbGJhY2sgPVxuICAgICAgZ2xvYmFsRXhhY3RBY3RpdmVDbGFzcyA9PSBudWxsXG4gICAgICAgID8gJ3JvdXRlci1saW5rLWV4YWN0LWFjdGl2ZSdcbiAgICAgICAgOiBnbG9iYWxFeGFjdEFjdGl2ZUNsYXNzO1xuICAgIHZhciBhY3RpdmVDbGFzcyA9XG4gICAgICB0aGlzLmFjdGl2ZUNsYXNzID09IG51bGwgPyBhY3RpdmVDbGFzc0ZhbGxiYWNrIDogdGhpcy5hY3RpdmVDbGFzcztcbiAgICB2YXIgZXhhY3RBY3RpdmVDbGFzcyA9XG4gICAgICB0aGlzLmV4YWN0QWN0aXZlQ2xhc3MgPT0gbnVsbFxuICAgICAgICA/IGV4YWN0QWN0aXZlQ2xhc3NGYWxsYmFja1xuICAgICAgICA6IHRoaXMuZXhhY3RBY3RpdmVDbGFzcztcblxuICAgIHZhciBjb21wYXJlVGFyZ2V0ID0gcm91dGUucmVkaXJlY3RlZEZyb21cbiAgICAgID8gY3JlYXRlUm91dGUobnVsbCwgbm9ybWFsaXplTG9jYXRpb24ocm91dGUucmVkaXJlY3RlZEZyb20pLCBudWxsLCByb3V0ZXIpXG4gICAgICA6IHJvdXRlO1xuXG4gICAgY2xhc3Nlc1tleGFjdEFjdGl2ZUNsYXNzXSA9IGlzU2FtZVJvdXRlKGN1cnJlbnQsIGNvbXBhcmVUYXJnZXQsIHRoaXMuZXhhY3RQYXRoKTtcbiAgICBjbGFzc2VzW2FjdGl2ZUNsYXNzXSA9IHRoaXMuZXhhY3QgfHwgdGhpcy5leGFjdFBhdGhcbiAgICAgID8gY2xhc3Nlc1tleGFjdEFjdGl2ZUNsYXNzXVxuICAgICAgOiBpc0luY2x1ZGVkUm91dGUoY3VycmVudCwgY29tcGFyZVRhcmdldCk7XG5cbiAgICB2YXIgYXJpYUN1cnJlbnRWYWx1ZSA9IGNsYXNzZXNbZXhhY3RBY3RpdmVDbGFzc10gPyB0aGlzLmFyaWFDdXJyZW50VmFsdWUgOiBudWxsO1xuXG4gICAgdmFyIGhhbmRsZXIgPSBmdW5jdGlvbiAoZSkge1xuICAgICAgaWYgKGd1YXJkRXZlbnQoZSkpIHtcbiAgICAgICAgaWYgKHRoaXMkMS5yZXBsYWNlKSB7XG4gICAgICAgICAgcm91dGVyLnJlcGxhY2UobG9jYXRpb24sIG5vb3ApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHJvdXRlci5wdXNoKGxvY2F0aW9uLCBub29wKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH07XG5cbiAgICB2YXIgb24gPSB7IGNsaWNrOiBndWFyZEV2ZW50IH07XG4gICAgaWYgKEFycmF5LmlzQXJyYXkodGhpcy5ldmVudCkpIHtcbiAgICAgIHRoaXMuZXZlbnQuZm9yRWFjaChmdW5jdGlvbiAoZSkge1xuICAgICAgICBvbltlXSA9IGhhbmRsZXI7XG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgb25bdGhpcy5ldmVudF0gPSBoYW5kbGVyO1xuICAgIH1cblxuICAgIHZhciBkYXRhID0geyBjbGFzczogY2xhc3NlcyB9O1xuXG4gICAgdmFyIHNjb3BlZFNsb3QgPVxuICAgICAgIXRoaXMuJHNjb3BlZFNsb3RzLiRoYXNOb3JtYWwgJiZcbiAgICAgIHRoaXMuJHNjb3BlZFNsb3RzLmRlZmF1bHQgJiZcbiAgICAgIHRoaXMuJHNjb3BlZFNsb3RzLmRlZmF1bHQoe1xuICAgICAgICBocmVmOiBocmVmLFxuICAgICAgICByb3V0ZTogcm91dGUsXG4gICAgICAgIG5hdmlnYXRlOiBoYW5kbGVyLFxuICAgICAgICBpc0FjdGl2ZTogY2xhc3Nlc1thY3RpdmVDbGFzc10sXG4gICAgICAgIGlzRXhhY3RBY3RpdmU6IGNsYXNzZXNbZXhhY3RBY3RpdmVDbGFzc11cbiAgICAgIH0pO1xuXG4gICAgaWYgKHNjb3BlZFNsb3QpIHtcbiAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nICYmICF0aGlzLmN1c3RvbSkge1xuICAgICAgICAhd2FybmVkQ3VzdG9tU2xvdCAmJiB3YXJuKGZhbHNlLCAnSW4gVnVlIFJvdXRlciA0LCB0aGUgdi1zbG90IEFQSSB3aWxsIGJ5IGRlZmF1bHQgd3JhcCBpdHMgY29udGVudCB3aXRoIGFuIDxhPiBlbGVtZW50LiBVc2UgdGhlIGN1c3RvbSBwcm9wIHRvIHJlbW92ZSB0aGlzIHdhcm5pbmc6XFxuPHJvdXRlci1saW5rIHYtc2xvdD1cInsgbmF2aWdhdGUsIGhyZWYgfVwiIGN1c3RvbT48L3JvdXRlci1saW5rPlxcbicpO1xuICAgICAgICB3YXJuZWRDdXN0b21TbG90ID0gdHJ1ZTtcbiAgICAgIH1cbiAgICAgIGlmIChzY29wZWRTbG90Lmxlbmd0aCA9PT0gMSkge1xuICAgICAgICByZXR1cm4gc2NvcGVkU2xvdFswXVxuICAgICAgfSBlbHNlIGlmIChzY29wZWRTbG90Lmxlbmd0aCA+IDEgfHwgIXNjb3BlZFNsb3QubGVuZ3RoKSB7XG4gICAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICAgICAgd2FybihcbiAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgKFwiPHJvdXRlci1saW5rPiB3aXRoIHRvPVxcXCJcIiArICh0aGlzLnRvKSArIFwiXFxcIiBpcyB0cnlpbmcgdG8gdXNlIGEgc2NvcGVkIHNsb3QgYnV0IGl0IGRpZG4ndCBwcm92aWRlIGV4YWN0bHkgb25lIGNoaWxkLiBXcmFwcGluZyB0aGUgY29udGVudCB3aXRoIGEgc3BhbiBlbGVtZW50LlwiKVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNjb3BlZFNsb3QubGVuZ3RoID09PSAwID8gaCgpIDogaCgnc3BhbicsIHt9LCBzY29wZWRTbG90KVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICBpZiAoJ3RhZycgaW4gdGhpcy4kb3B0aW9ucy5wcm9wc0RhdGEgJiYgIXdhcm5lZFRhZ1Byb3ApIHtcbiAgICAgICAgd2FybihcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICBcIjxyb3V0ZXItbGluaz4ncyB0YWcgcHJvcCBpcyBkZXByZWNhdGVkIGFuZCBoYXMgYmVlbiByZW1vdmVkIGluIFZ1ZSBSb3V0ZXIgNC4gVXNlIHRoZSB2LXNsb3QgQVBJIHRvIHJlbW92ZSB0aGlzIHdhcm5pbmc6IGh0dHBzOi8vbmV4dC5yb3V0ZXIudnVlanMub3JnL2d1aWRlL21pZ3JhdGlvbi8jcmVtb3ZhbC1vZi1ldmVudC1hbmQtdGFnLXByb3BzLWluLXJvdXRlci1saW5rLlwiXG4gICAgICAgICk7XG4gICAgICAgIHdhcm5lZFRhZ1Byb3AgPSB0cnVlO1xuICAgICAgfVxuICAgICAgaWYgKCdldmVudCcgaW4gdGhpcy4kb3B0aW9ucy5wcm9wc0RhdGEgJiYgIXdhcm5lZEV2ZW50UHJvcCkge1xuICAgICAgICB3YXJuKFxuICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgIFwiPHJvdXRlci1saW5rPidzIGV2ZW50IHByb3AgaXMgZGVwcmVjYXRlZCBhbmQgaGFzIGJlZW4gcmVtb3ZlZCBpbiBWdWUgUm91dGVyIDQuIFVzZSB0aGUgdi1zbG90IEFQSSB0byByZW1vdmUgdGhpcyB3YXJuaW5nOiBodHRwczovL25leHQucm91dGVyLnZ1ZWpzLm9yZy9ndWlkZS9taWdyYXRpb24vI3JlbW92YWwtb2YtZXZlbnQtYW5kLXRhZy1wcm9wcy1pbi1yb3V0ZXItbGluay5cIlxuICAgICAgICApO1xuICAgICAgICB3YXJuZWRFdmVudFByb3AgPSB0cnVlO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh0aGlzLnRhZyA9PT0gJ2EnKSB7XG4gICAgICBkYXRhLm9uID0gb247XG4gICAgICBkYXRhLmF0dHJzID0geyBocmVmOiBocmVmLCAnYXJpYS1jdXJyZW50JzogYXJpYUN1cnJlbnRWYWx1ZSB9O1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBmaW5kIHRoZSBmaXJzdCA8YT4gY2hpbGQgYW5kIGFwcGx5IGxpc3RlbmVyIGFuZCBocmVmXG4gICAgICB2YXIgYSA9IGZpbmRBbmNob3IodGhpcy4kc2xvdHMuZGVmYXVsdCk7XG4gICAgICBpZiAoYSkge1xuICAgICAgICAvLyBpbiBjYXNlIHRoZSA8YT4gaXMgYSBzdGF0aWMgbm9kZVxuICAgICAgICBhLmlzU3RhdGljID0gZmFsc2U7XG4gICAgICAgIHZhciBhRGF0YSA9IChhLmRhdGEgPSBleHRlbmQoe30sIGEuZGF0YSkpO1xuICAgICAgICBhRGF0YS5vbiA9IGFEYXRhLm9uIHx8IHt9O1xuICAgICAgICAvLyB0cmFuc2Zvcm0gZXhpc3RpbmcgZXZlbnRzIGluIGJvdGggb2JqZWN0cyBpbnRvIGFycmF5cyBzbyB3ZSBjYW4gcHVzaCBsYXRlclxuICAgICAgICBmb3IgKHZhciBldmVudCBpbiBhRGF0YS5vbikge1xuICAgICAgICAgIHZhciBoYW5kbGVyJDEgPSBhRGF0YS5vbltldmVudF07XG4gICAgICAgICAgaWYgKGV2ZW50IGluIG9uKSB7XG4gICAgICAgICAgICBhRGF0YS5vbltldmVudF0gPSBBcnJheS5pc0FycmF5KGhhbmRsZXIkMSkgPyBoYW5kbGVyJDEgOiBbaGFuZGxlciQxXTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLy8gYXBwZW5kIG5ldyBsaXN0ZW5lcnMgZm9yIHJvdXRlci1saW5rXG4gICAgICAgIGZvciAodmFyIGV2ZW50JDEgaW4gb24pIHtcbiAgICAgICAgICBpZiAoZXZlbnQkMSBpbiBhRGF0YS5vbikge1xuICAgICAgICAgICAgLy8gb25bZXZlbnRdIGlzIGFsd2F5cyBhIGZ1bmN0aW9uXG4gICAgICAgICAgICBhRGF0YS5vbltldmVudCQxXS5wdXNoKG9uW2V2ZW50JDFdKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYURhdGEub25bZXZlbnQkMV0gPSBoYW5kbGVyO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhciBhQXR0cnMgPSAoYS5kYXRhLmF0dHJzID0gZXh0ZW5kKHt9LCBhLmRhdGEuYXR0cnMpKTtcbiAgICAgICAgYUF0dHJzLmhyZWYgPSBocmVmO1xuICAgICAgICBhQXR0cnNbJ2FyaWEtY3VycmVudCddID0gYXJpYUN1cnJlbnRWYWx1ZTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIGRvZXNuJ3QgaGF2ZSA8YT4gY2hpbGQsIGFwcGx5IGxpc3RlbmVyIHRvIHNlbGZcbiAgICAgICAgZGF0YS5vbiA9IG9uO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBoKHRoaXMudGFnLCBkYXRhLCB0aGlzLiRzbG90cy5kZWZhdWx0KVxuICB9XG59O1xuXG5mdW5jdGlvbiBndWFyZEV2ZW50IChlKSB7XG4gIC8vIGRvbid0IHJlZGlyZWN0IHdpdGggY29udHJvbCBrZXlzXG4gIGlmIChlLm1ldGFLZXkgfHwgZS5hbHRLZXkgfHwgZS5jdHJsS2V5IHx8IGUuc2hpZnRLZXkpIHsgcmV0dXJuIH1cbiAgLy8gZG9uJ3QgcmVkaXJlY3Qgd2hlbiBwcmV2ZW50RGVmYXVsdCBjYWxsZWRcbiAgaWYgKGUuZGVmYXVsdFByZXZlbnRlZCkgeyByZXR1cm4gfVxuICAvLyBkb24ndCByZWRpcmVjdCBvbiByaWdodCBjbGlja1xuICBpZiAoZS5idXR0b24gIT09IHVuZGVmaW5lZCAmJiBlLmJ1dHRvbiAhPT0gMCkgeyByZXR1cm4gfVxuICAvLyBkb24ndCByZWRpcmVjdCBpZiBgdGFyZ2V0PVwiX2JsYW5rXCJgXG4gIGlmIChlLmN1cnJlbnRUYXJnZXQgJiYgZS5jdXJyZW50VGFyZ2V0LmdldEF0dHJpYnV0ZSkge1xuICAgIHZhciB0YXJnZXQgPSBlLmN1cnJlbnRUYXJnZXQuZ2V0QXR0cmlidXRlKCd0YXJnZXQnKTtcbiAgICBpZiAoL1xcYl9ibGFua1xcYi9pLnRlc3QodGFyZ2V0KSkgeyByZXR1cm4gfVxuICB9XG4gIC8vIHRoaXMgbWF5IGJlIGEgV2VleCBldmVudCB3aGljaCBkb2Vzbid0IGhhdmUgdGhpcyBtZXRob2RcbiAgaWYgKGUucHJldmVudERlZmF1bHQpIHtcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gIH1cbiAgcmV0dXJuIHRydWVcbn1cblxuZnVuY3Rpb24gZmluZEFuY2hvciAoY2hpbGRyZW4pIHtcbiAgaWYgKGNoaWxkcmVuKSB7XG4gICAgdmFyIGNoaWxkO1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNoaWxkID0gY2hpbGRyZW5baV07XG4gICAgICBpZiAoY2hpbGQudGFnID09PSAnYScpIHtcbiAgICAgICAgcmV0dXJuIGNoaWxkXG4gICAgICB9XG4gICAgICBpZiAoY2hpbGQuY2hpbGRyZW4gJiYgKGNoaWxkID0gZmluZEFuY2hvcihjaGlsZC5jaGlsZHJlbikpKSB7XG4gICAgICAgIHJldHVybiBjaGlsZFxuICAgICAgfVxuICAgIH1cbiAgfVxufVxuXG52YXIgX1Z1ZTtcblxuZnVuY3Rpb24gaW5zdGFsbCAoVnVlKSB7XG4gIGlmIChpbnN0YWxsLmluc3RhbGxlZCAmJiBfVnVlID09PSBWdWUpIHsgcmV0dXJuIH1cbiAgaW5zdGFsbC5pbnN0YWxsZWQgPSB0cnVlO1xuXG4gIF9WdWUgPSBWdWU7XG5cbiAgdmFyIGlzRGVmID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIHYgIT09IHVuZGVmaW5lZDsgfTtcblxuICB2YXIgcmVnaXN0ZXJJbnN0YW5jZSA9IGZ1bmN0aW9uICh2bSwgY2FsbFZhbCkge1xuICAgIHZhciBpID0gdm0uJG9wdGlvbnMuX3BhcmVudFZub2RlO1xuICAgIGlmIChpc0RlZihpKSAmJiBpc0RlZihpID0gaS5kYXRhKSAmJiBpc0RlZihpID0gaS5yZWdpc3RlclJvdXRlSW5zdGFuY2UpKSB7XG4gICAgICBpKHZtLCBjYWxsVmFsKTtcbiAgICB9XG4gIH07XG5cbiAgVnVlLm1peGluKHtcbiAgICBiZWZvcmVDcmVhdGU6IGZ1bmN0aW9uIGJlZm9yZUNyZWF0ZSAoKSB7XG4gICAgICBpZiAoaXNEZWYodGhpcy4kb3B0aW9ucy5yb3V0ZXIpKSB7XG4gICAgICAgIHRoaXMuX3JvdXRlclJvb3QgPSB0aGlzO1xuICAgICAgICB0aGlzLl9yb3V0ZXIgPSB0aGlzLiRvcHRpb25zLnJvdXRlcjtcbiAgICAgICAgdGhpcy5fcm91dGVyLmluaXQodGhpcyk7XG4gICAgICAgIFZ1ZS51dGlsLmRlZmluZVJlYWN0aXZlKHRoaXMsICdfcm91dGUnLCB0aGlzLl9yb3V0ZXIuaGlzdG9yeS5jdXJyZW50KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuX3JvdXRlclJvb3QgPSAodGhpcy4kcGFyZW50ICYmIHRoaXMuJHBhcmVudC5fcm91dGVyUm9vdCkgfHwgdGhpcztcbiAgICAgIH1cbiAgICAgIHJlZ2lzdGVySW5zdGFuY2UodGhpcywgdGhpcyk7XG4gICAgfSxcbiAgICBkZXN0cm95ZWQ6IGZ1bmN0aW9uIGRlc3Ryb3llZCAoKSB7XG4gICAgICByZWdpc3Rlckluc3RhbmNlKHRoaXMpO1xuICAgIH1cbiAgfSk7XG5cbiAgT2JqZWN0LmRlZmluZVByb3BlcnR5KFZ1ZS5wcm90b3R5cGUsICckcm91dGVyJywge1xuICAgIGdldDogZnVuY3Rpb24gZ2V0ICgpIHsgcmV0dXJuIHRoaXMuX3JvdXRlclJvb3QuX3JvdXRlciB9XG4gIH0pO1xuXG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShWdWUucHJvdG90eXBlLCAnJHJvdXRlJywge1xuICAgIGdldDogZnVuY3Rpb24gZ2V0ICgpIHsgcmV0dXJuIHRoaXMuX3JvdXRlclJvb3QuX3JvdXRlIH1cbiAgfSk7XG5cbiAgVnVlLmNvbXBvbmVudCgnUm91dGVyVmlldycsIFZpZXcpO1xuICBWdWUuY29tcG9uZW50KCdSb3V0ZXJMaW5rJywgTGluayk7XG5cbiAgdmFyIHN0cmF0cyA9IFZ1ZS5jb25maWcub3B0aW9uTWVyZ2VTdHJhdGVnaWVzO1xuICAvLyB1c2UgdGhlIHNhbWUgaG9vayBtZXJnaW5nIHN0cmF0ZWd5IGZvciByb3V0ZSBob29rc1xuICBzdHJhdHMuYmVmb3JlUm91dGVFbnRlciA9IHN0cmF0cy5iZWZvcmVSb3V0ZUxlYXZlID0gc3RyYXRzLmJlZm9yZVJvdXRlVXBkYXRlID0gc3RyYXRzLmNyZWF0ZWQ7XG59XG5cbi8qICAqL1xuXG52YXIgaW5Ccm93c2VyID0gdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCc7XG5cbi8qICAqL1xuXG5mdW5jdGlvbiBjcmVhdGVSb3V0ZU1hcCAoXG4gIHJvdXRlcyxcbiAgb2xkUGF0aExpc3QsXG4gIG9sZFBhdGhNYXAsXG4gIG9sZE5hbWVNYXAsXG4gIHBhcmVudFJvdXRlXG4pIHtcbiAgLy8gdGhlIHBhdGggbGlzdCBpcyB1c2VkIHRvIGNvbnRyb2wgcGF0aCBtYXRjaGluZyBwcmlvcml0eVxuICB2YXIgcGF0aExpc3QgPSBvbGRQYXRoTGlzdCB8fCBbXTtcbiAgLy8gJGZsb3ctZGlzYWJsZS1saW5lXG4gIHZhciBwYXRoTWFwID0gb2xkUGF0aE1hcCB8fCBPYmplY3QuY3JlYXRlKG51bGwpO1xuICAvLyAkZmxvdy1kaXNhYmxlLWxpbmVcbiAgdmFyIG5hbWVNYXAgPSBvbGROYW1lTWFwIHx8IE9iamVjdC5jcmVhdGUobnVsbCk7XG5cbiAgcm91dGVzLmZvckVhY2goZnVuY3Rpb24gKHJvdXRlKSB7XG4gICAgYWRkUm91dGVSZWNvcmQocGF0aExpc3QsIHBhdGhNYXAsIG5hbWVNYXAsIHJvdXRlLCBwYXJlbnRSb3V0ZSk7XG4gIH0pO1xuXG4gIC8vIGVuc3VyZSB3aWxkY2FyZCByb3V0ZXMgYXJlIGFsd2F5cyBhdCB0aGUgZW5kXG4gIGZvciAodmFyIGkgPSAwLCBsID0gcGF0aExpc3QubGVuZ3RoOyBpIDwgbDsgaSsrKSB7XG4gICAgaWYgKHBhdGhMaXN0W2ldID09PSAnKicpIHtcbiAgICAgIHBhdGhMaXN0LnB1c2gocGF0aExpc3Quc3BsaWNlKGksIDEpWzBdKTtcbiAgICAgIGwtLTtcbiAgICAgIGktLTtcbiAgICB9XG4gIH1cblxuICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdkZXZlbG9wbWVudCcpIHtcbiAgICAvLyB3YXJuIGlmIHJvdXRlcyBkbyBub3QgaW5jbHVkZSBsZWFkaW5nIHNsYXNoZXNcbiAgICB2YXIgZm91bmQgPSBwYXRoTGlzdFxuICAgIC8vIGNoZWNrIGZvciBtaXNzaW5nIGxlYWRpbmcgc2xhc2hcbiAgICAgIC5maWx0ZXIoZnVuY3Rpb24gKHBhdGgpIHsgcmV0dXJuIHBhdGggJiYgcGF0aC5jaGFyQXQoMCkgIT09ICcqJyAmJiBwYXRoLmNoYXJBdCgwKSAhPT0gJy8nOyB9KTtcblxuICAgIGlmIChmb3VuZC5sZW5ndGggPiAwKSB7XG4gICAgICB2YXIgcGF0aE5hbWVzID0gZm91bmQubWFwKGZ1bmN0aW9uIChwYXRoKSB7IHJldHVybiAoXCItIFwiICsgcGF0aCk7IH0pLmpvaW4oJ1xcbicpO1xuICAgICAgd2FybihmYWxzZSwgKFwiTm9uLW5lc3RlZCByb3V0ZXMgbXVzdCBpbmNsdWRlIGEgbGVhZGluZyBzbGFzaCBjaGFyYWN0ZXIuIEZpeCB0aGUgZm9sbG93aW5nIHJvdXRlczogXFxuXCIgKyBwYXRoTmFtZXMpKTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHBhdGhMaXN0OiBwYXRoTGlzdCxcbiAgICBwYXRoTWFwOiBwYXRoTWFwLFxuICAgIG5hbWVNYXA6IG5hbWVNYXBcbiAgfVxufVxuXG5mdW5jdGlvbiBhZGRSb3V0ZVJlY29yZCAoXG4gIHBhdGhMaXN0LFxuICBwYXRoTWFwLFxuICBuYW1lTWFwLFxuICByb3V0ZSxcbiAgcGFyZW50LFxuICBtYXRjaEFzXG4pIHtcbiAgdmFyIHBhdGggPSByb3V0ZS5wYXRoO1xuICB2YXIgbmFtZSA9IHJvdXRlLm5hbWU7XG4gIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgYXNzZXJ0KHBhdGggIT0gbnVsbCwgXCJcXFwicGF0aFxcXCIgaXMgcmVxdWlyZWQgaW4gYSByb3V0ZSBjb25maWd1cmF0aW9uLlwiKTtcbiAgICBhc3NlcnQoXG4gICAgICB0eXBlb2Ygcm91dGUuY29tcG9uZW50ICE9PSAnc3RyaW5nJyxcbiAgICAgIFwicm91dGUgY29uZmlnIFxcXCJjb21wb25lbnRcXFwiIGZvciBwYXRoOiBcIiArIChTdHJpbmcoXG4gICAgICAgIHBhdGggfHwgbmFtZVxuICAgICAgKSkgKyBcIiBjYW5ub3QgYmUgYSBcIiArIFwic3RyaW5nIGlkLiBVc2UgYW4gYWN0dWFsIGNvbXBvbmVudCBpbnN0ZWFkLlwiXG4gICAgKTtcblxuICAgIHdhcm4oXG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgbm8tY29udHJvbC1yZWdleFxuICAgICAgIS9bXlxcdTAwMDAtXFx1MDA3Rl0rLy50ZXN0KHBhdGgpLFxuICAgICAgXCJSb3V0ZSB3aXRoIHBhdGggXFxcIlwiICsgcGF0aCArIFwiXFxcIiBjb250YWlucyB1bmVuY29kZWQgY2hhcmFjdGVycywgbWFrZSBzdXJlIFwiICtcbiAgICAgICAgXCJ5b3VyIHBhdGggaXMgY29ycmVjdGx5IGVuY29kZWQgYmVmb3JlIHBhc3NpbmcgaXQgdG8gdGhlIHJvdXRlci4gVXNlIFwiICtcbiAgICAgICAgXCJlbmNvZGVVUkkgdG8gZW5jb2RlIHN0YXRpYyBzZWdtZW50cyBvZiB5b3VyIHBhdGguXCJcbiAgICApO1xuICB9XG5cbiAgdmFyIHBhdGhUb1JlZ2V4cE9wdGlvbnMgPVxuICAgIHJvdXRlLnBhdGhUb1JlZ2V4cE9wdGlvbnMgfHwge307XG4gIHZhciBub3JtYWxpemVkUGF0aCA9IG5vcm1hbGl6ZVBhdGgocGF0aCwgcGFyZW50LCBwYXRoVG9SZWdleHBPcHRpb25zLnN0cmljdCk7XG5cbiAgaWYgKHR5cGVvZiByb3V0ZS5jYXNlU2Vuc2l0aXZlID09PSAnYm9vbGVhbicpIHtcbiAgICBwYXRoVG9SZWdleHBPcHRpb25zLnNlbnNpdGl2ZSA9IHJvdXRlLmNhc2VTZW5zaXRpdmU7XG4gIH1cblxuICB2YXIgcmVjb3JkID0ge1xuICAgIHBhdGg6IG5vcm1hbGl6ZWRQYXRoLFxuICAgIHJlZ2V4OiBjb21waWxlUm91dGVSZWdleChub3JtYWxpemVkUGF0aCwgcGF0aFRvUmVnZXhwT3B0aW9ucyksXG4gICAgY29tcG9uZW50czogcm91dGUuY29tcG9uZW50cyB8fCB7IGRlZmF1bHQ6IHJvdXRlLmNvbXBvbmVudCB9LFxuICAgIGFsaWFzOiByb3V0ZS5hbGlhc1xuICAgICAgPyB0eXBlb2Ygcm91dGUuYWxpYXMgPT09ICdzdHJpbmcnXG4gICAgICAgID8gW3JvdXRlLmFsaWFzXVxuICAgICAgICA6IHJvdXRlLmFsaWFzXG4gICAgICA6IFtdLFxuICAgIGluc3RhbmNlczoge30sXG4gICAgZW50ZXJlZENiczoge30sXG4gICAgbmFtZTogbmFtZSxcbiAgICBwYXJlbnQ6IHBhcmVudCxcbiAgICBtYXRjaEFzOiBtYXRjaEFzLFxuICAgIHJlZGlyZWN0OiByb3V0ZS5yZWRpcmVjdCxcbiAgICBiZWZvcmVFbnRlcjogcm91dGUuYmVmb3JlRW50ZXIsXG4gICAgbWV0YTogcm91dGUubWV0YSB8fCB7fSxcbiAgICBwcm9wczpcbiAgICAgIHJvdXRlLnByb3BzID09IG51bGxcbiAgICAgICAgPyB7fVxuICAgICAgICA6IHJvdXRlLmNvbXBvbmVudHNcbiAgICAgICAgICA/IHJvdXRlLnByb3BzXG4gICAgICAgICAgOiB7IGRlZmF1bHQ6IHJvdXRlLnByb3BzIH1cbiAgfTtcblxuICBpZiAocm91dGUuY2hpbGRyZW4pIHtcbiAgICAvLyBXYXJuIGlmIHJvdXRlIGlzIG5hbWVkLCBkb2VzIG5vdCByZWRpcmVjdCBhbmQgaGFzIGEgZGVmYXVsdCBjaGlsZCByb3V0ZS5cbiAgICAvLyBJZiB1c2VycyBuYXZpZ2F0ZSB0byB0aGlzIHJvdXRlIGJ5IG5hbWUsIHRoZSBkZWZhdWx0IGNoaWxkIHdpbGxcbiAgICAvLyBub3QgYmUgcmVuZGVyZWQgKEdIIElzc3VlICM2MjkpXG4gICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgIGlmIChcbiAgICAgICAgcm91dGUubmFtZSAmJlxuICAgICAgICAhcm91dGUucmVkaXJlY3QgJiZcbiAgICAgICAgcm91dGUuY2hpbGRyZW4uc29tZShmdW5jdGlvbiAoY2hpbGQpIHsgcmV0dXJuIC9eXFwvPyQvLnRlc3QoY2hpbGQucGF0aCk7IH0pXG4gICAgICApIHtcbiAgICAgICAgd2FybihcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICBcIk5hbWVkIFJvdXRlICdcIiArIChyb3V0ZS5uYW1lKSArIFwiJyBoYXMgYSBkZWZhdWx0IGNoaWxkIHJvdXRlLiBcIiArXG4gICAgICAgICAgICBcIldoZW4gbmF2aWdhdGluZyB0byB0aGlzIG5hbWVkIHJvdXRlICg6dG89XFxcIntuYW1lOiAnXCIgKyAocm91dGUubmFtZSkgKyBcIidcXFwiKSwgXCIgK1xuICAgICAgICAgICAgXCJ0aGUgZGVmYXVsdCBjaGlsZCByb3V0ZSB3aWxsIG5vdCBiZSByZW5kZXJlZC4gUmVtb3ZlIHRoZSBuYW1lIGZyb20gXCIgK1xuICAgICAgICAgICAgXCJ0aGlzIHJvdXRlIGFuZCB1c2UgdGhlIG5hbWUgb2YgdGhlIGRlZmF1bHQgY2hpbGQgcm91dGUgZm9yIG5hbWVkIFwiICtcbiAgICAgICAgICAgIFwibGlua3MgaW5zdGVhZC5cIlxuICAgICAgICApO1xuICAgICAgfVxuICAgIH1cbiAgICByb3V0ZS5jaGlsZHJlbi5mb3JFYWNoKGZ1bmN0aW9uIChjaGlsZCkge1xuICAgICAgdmFyIGNoaWxkTWF0Y2hBcyA9IG1hdGNoQXNcbiAgICAgICAgPyBjbGVhblBhdGgoKG1hdGNoQXMgKyBcIi9cIiArIChjaGlsZC5wYXRoKSkpXG4gICAgICAgIDogdW5kZWZpbmVkO1xuICAgICAgYWRkUm91dGVSZWNvcmQocGF0aExpc3QsIHBhdGhNYXAsIG5hbWVNYXAsIGNoaWxkLCByZWNvcmQsIGNoaWxkTWF0Y2hBcyk7XG4gICAgfSk7XG4gIH1cblxuICBpZiAoIXBhdGhNYXBbcmVjb3JkLnBhdGhdKSB7XG4gICAgcGF0aExpc3QucHVzaChyZWNvcmQucGF0aCk7XG4gICAgcGF0aE1hcFtyZWNvcmQucGF0aF0gPSByZWNvcmQ7XG4gIH1cblxuICBpZiAocm91dGUuYWxpYXMgIT09IHVuZGVmaW5lZCkge1xuICAgIHZhciBhbGlhc2VzID0gQXJyYXkuaXNBcnJheShyb3V0ZS5hbGlhcykgPyByb3V0ZS5hbGlhcyA6IFtyb3V0ZS5hbGlhc107XG4gICAgZm9yICh2YXIgaSA9IDA7IGkgPCBhbGlhc2VzLmxlbmd0aDsgKytpKSB7XG4gICAgICB2YXIgYWxpYXMgPSBhbGlhc2VzW2ldO1xuICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgJiYgYWxpYXMgPT09IHBhdGgpIHtcbiAgICAgICAgd2FybihcbiAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAoXCJGb3VuZCBhbiBhbGlhcyB3aXRoIHRoZSBzYW1lIHZhbHVlIGFzIHRoZSBwYXRoOiBcXFwiXCIgKyBwYXRoICsgXCJcXFwiLiBZb3UgaGF2ZSB0byByZW1vdmUgdGhhdCBhbGlhcy4gSXQgd2lsbCBiZSBpZ25vcmVkIGluIGRldmVsb3BtZW50LlwiKVxuICAgICAgICApO1xuICAgICAgICAvLyBza2lwIGluIGRldiB0byBtYWtlIGl0IHdvcmtcbiAgICAgICAgY29udGludWVcbiAgICAgIH1cblxuICAgICAgdmFyIGFsaWFzUm91dGUgPSB7XG4gICAgICAgIHBhdGg6IGFsaWFzLFxuICAgICAgICBjaGlsZHJlbjogcm91dGUuY2hpbGRyZW5cbiAgICAgIH07XG4gICAgICBhZGRSb3V0ZVJlY29yZChcbiAgICAgICAgcGF0aExpc3QsXG4gICAgICAgIHBhdGhNYXAsXG4gICAgICAgIG5hbWVNYXAsXG4gICAgICAgIGFsaWFzUm91dGUsXG4gICAgICAgIHBhcmVudCxcbiAgICAgICAgcmVjb3JkLnBhdGggfHwgJy8nIC8vIG1hdGNoQXNcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgaWYgKG5hbWUpIHtcbiAgICBpZiAoIW5hbWVNYXBbbmFtZV0pIHtcbiAgICAgIG5hbWVNYXBbbmFtZV0gPSByZWNvcmQ7XG4gICAgfSBlbHNlIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nICYmICFtYXRjaEFzKSB7XG4gICAgICB3YXJuKFxuICAgICAgICBmYWxzZSxcbiAgICAgICAgXCJEdXBsaWNhdGUgbmFtZWQgcm91dGVzIGRlZmluaXRpb246IFwiICtcbiAgICAgICAgICBcInsgbmFtZTogXFxcIlwiICsgbmFtZSArIFwiXFxcIiwgcGF0aDogXFxcIlwiICsgKHJlY29yZC5wYXRoKSArIFwiXFxcIiB9XCJcbiAgICAgICk7XG4gICAgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGNvbXBpbGVSb3V0ZVJlZ2V4IChcbiAgcGF0aCxcbiAgcGF0aFRvUmVnZXhwT3B0aW9uc1xuKSB7XG4gIHZhciByZWdleCA9IHBhdGhUb1JlZ2V4cF8xKHBhdGgsIFtdLCBwYXRoVG9SZWdleHBPcHRpb25zKTtcbiAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICB2YXIga2V5cyA9IE9iamVjdC5jcmVhdGUobnVsbCk7XG4gICAgcmVnZXgua2V5cy5mb3JFYWNoKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgIHdhcm4oXG4gICAgICAgICFrZXlzW2tleS5uYW1lXSxcbiAgICAgICAgKFwiRHVwbGljYXRlIHBhcmFtIGtleXMgaW4gcm91dGUgd2l0aCBwYXRoOiBcXFwiXCIgKyBwYXRoICsgXCJcXFwiXCIpXG4gICAgICApO1xuICAgICAga2V5c1trZXkubmFtZV0gPSB0cnVlO1xuICAgIH0pO1xuICB9XG4gIHJldHVybiByZWdleFxufVxuXG5mdW5jdGlvbiBub3JtYWxpemVQYXRoIChcbiAgcGF0aCxcbiAgcGFyZW50LFxuICBzdHJpY3Rcbikge1xuICBpZiAoIXN0cmljdCkgeyBwYXRoID0gcGF0aC5yZXBsYWNlKC9cXC8kLywgJycpOyB9XG4gIGlmIChwYXRoWzBdID09PSAnLycpIHsgcmV0dXJuIHBhdGggfVxuICBpZiAocGFyZW50ID09IG51bGwpIHsgcmV0dXJuIHBhdGggfVxuICByZXR1cm4gY2xlYW5QYXRoKCgocGFyZW50LnBhdGgpICsgXCIvXCIgKyBwYXRoKSlcbn1cblxuLyogICovXG5cblxuXG5mdW5jdGlvbiBjcmVhdGVNYXRjaGVyIChcbiAgcm91dGVzLFxuICByb3V0ZXJcbikge1xuICB2YXIgcmVmID0gY3JlYXRlUm91dGVNYXAocm91dGVzKTtcbiAgdmFyIHBhdGhMaXN0ID0gcmVmLnBhdGhMaXN0O1xuICB2YXIgcGF0aE1hcCA9IHJlZi5wYXRoTWFwO1xuICB2YXIgbmFtZU1hcCA9IHJlZi5uYW1lTWFwO1xuXG4gIGZ1bmN0aW9uIGFkZFJvdXRlcyAocm91dGVzKSB7XG4gICAgY3JlYXRlUm91dGVNYXAocm91dGVzLCBwYXRoTGlzdCwgcGF0aE1hcCwgbmFtZU1hcCk7XG4gIH1cblxuICBmdW5jdGlvbiBhZGRSb3V0ZSAocGFyZW50T3JSb3V0ZSwgcm91dGUpIHtcbiAgICB2YXIgcGFyZW50ID0gKHR5cGVvZiBwYXJlbnRPclJvdXRlICE9PSAnb2JqZWN0JykgPyBuYW1lTWFwW3BhcmVudE9yUm91dGVdIDogdW5kZWZpbmVkO1xuICAgIC8vICRmbG93LWRpc2FibGUtbGluZVxuICAgIGNyZWF0ZVJvdXRlTWFwKFtyb3V0ZSB8fCBwYXJlbnRPclJvdXRlXSwgcGF0aExpc3QsIHBhdGhNYXAsIG5hbWVNYXAsIHBhcmVudCk7XG5cbiAgICAvLyBhZGQgYWxpYXNlcyBvZiBwYXJlbnRcbiAgICBpZiAocGFyZW50KSB7XG4gICAgICBjcmVhdGVSb3V0ZU1hcChcbiAgICAgICAgLy8gJGZsb3ctZGlzYWJsZS1saW5lIHJvdXRlIGlzIGRlZmluZWQgaWYgcGFyZW50IGlzXG4gICAgICAgIHBhcmVudC5hbGlhcy5tYXAoZnVuY3Rpb24gKGFsaWFzKSB7IHJldHVybiAoeyBwYXRoOiBhbGlhcywgY2hpbGRyZW46IFtyb3V0ZV0gfSk7IH0pLFxuICAgICAgICBwYXRoTGlzdCxcbiAgICAgICAgcGF0aE1hcCxcbiAgICAgICAgbmFtZU1hcCxcbiAgICAgICAgcGFyZW50XG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGZ1bmN0aW9uIGdldFJvdXRlcyAoKSB7XG4gICAgcmV0dXJuIHBhdGhMaXN0Lm1hcChmdW5jdGlvbiAocGF0aCkgeyByZXR1cm4gcGF0aE1hcFtwYXRoXTsgfSlcbiAgfVxuXG4gIGZ1bmN0aW9uIG1hdGNoIChcbiAgICByYXcsXG4gICAgY3VycmVudFJvdXRlLFxuICAgIHJlZGlyZWN0ZWRGcm9tXG4gICkge1xuICAgIHZhciBsb2NhdGlvbiA9IG5vcm1hbGl6ZUxvY2F0aW9uKHJhdywgY3VycmVudFJvdXRlLCBmYWxzZSwgcm91dGVyKTtcbiAgICB2YXIgbmFtZSA9IGxvY2F0aW9uLm5hbWU7XG5cbiAgICBpZiAobmFtZSkge1xuICAgICAgdmFyIHJlY29yZCA9IG5hbWVNYXBbbmFtZV07XG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgICAgICB3YXJuKHJlY29yZCwgKFwiUm91dGUgd2l0aCBuYW1lICdcIiArIG5hbWUgKyBcIicgZG9lcyBub3QgZXhpc3RcIikpO1xuICAgICAgfVxuICAgICAgaWYgKCFyZWNvcmQpIHsgcmV0dXJuIF9jcmVhdGVSb3V0ZShudWxsLCBsb2NhdGlvbikgfVxuICAgICAgdmFyIHBhcmFtTmFtZXMgPSByZWNvcmQucmVnZXgua2V5c1xuICAgICAgICAuZmlsdGVyKGZ1bmN0aW9uIChrZXkpIHsgcmV0dXJuICFrZXkub3B0aW9uYWw7IH0pXG4gICAgICAgIC5tYXAoZnVuY3Rpb24gKGtleSkgeyByZXR1cm4ga2V5Lm5hbWU7IH0pO1xuXG4gICAgICBpZiAodHlwZW9mIGxvY2F0aW9uLnBhcmFtcyAhPT0gJ29iamVjdCcpIHtcbiAgICAgICAgbG9jYXRpb24ucGFyYW1zID0ge307XG4gICAgICB9XG5cbiAgICAgIGlmIChjdXJyZW50Um91dGUgJiYgdHlwZW9mIGN1cnJlbnRSb3V0ZS5wYXJhbXMgPT09ICdvYmplY3QnKSB7XG4gICAgICAgIGZvciAodmFyIGtleSBpbiBjdXJyZW50Um91dGUucGFyYW1zKSB7XG4gICAgICAgICAgaWYgKCEoa2V5IGluIGxvY2F0aW9uLnBhcmFtcykgJiYgcGFyYW1OYW1lcy5pbmRleE9mKGtleSkgPiAtMSkge1xuICAgICAgICAgICAgbG9jYXRpb24ucGFyYW1zW2tleV0gPSBjdXJyZW50Um91dGUucGFyYW1zW2tleV07XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxvY2F0aW9uLnBhdGggPSBmaWxsUGFyYW1zKHJlY29yZC5wYXRoLCBsb2NhdGlvbi5wYXJhbXMsIChcIm5hbWVkIHJvdXRlIFxcXCJcIiArIG5hbWUgKyBcIlxcXCJcIikpO1xuICAgICAgcmV0dXJuIF9jcmVhdGVSb3V0ZShyZWNvcmQsIGxvY2F0aW9uLCByZWRpcmVjdGVkRnJvbSlcbiAgICB9IGVsc2UgaWYgKGxvY2F0aW9uLnBhdGgpIHtcbiAgICAgIGxvY2F0aW9uLnBhcmFtcyA9IHt9O1xuICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBwYXRoTGlzdC5sZW5ndGg7IGkrKykge1xuICAgICAgICB2YXIgcGF0aCA9IHBhdGhMaXN0W2ldO1xuICAgICAgICB2YXIgcmVjb3JkJDEgPSBwYXRoTWFwW3BhdGhdO1xuICAgICAgICBpZiAobWF0Y2hSb3V0ZShyZWNvcmQkMS5yZWdleCwgbG9jYXRpb24ucGF0aCwgbG9jYXRpb24ucGFyYW1zKSkge1xuICAgICAgICAgIHJldHVybiBfY3JlYXRlUm91dGUocmVjb3JkJDEsIGxvY2F0aW9uLCByZWRpcmVjdGVkRnJvbSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgICAvLyBubyBtYXRjaFxuICAgIHJldHVybiBfY3JlYXRlUm91dGUobnVsbCwgbG9jYXRpb24pXG4gIH1cblxuICBmdW5jdGlvbiByZWRpcmVjdCAoXG4gICAgcmVjb3JkLFxuICAgIGxvY2F0aW9uXG4gICkge1xuICAgIHZhciBvcmlnaW5hbFJlZGlyZWN0ID0gcmVjb3JkLnJlZGlyZWN0O1xuICAgIHZhciByZWRpcmVjdCA9IHR5cGVvZiBvcmlnaW5hbFJlZGlyZWN0ID09PSAnZnVuY3Rpb24nXG4gICAgICA/IG9yaWdpbmFsUmVkaXJlY3QoY3JlYXRlUm91dGUocmVjb3JkLCBsb2NhdGlvbiwgbnVsbCwgcm91dGVyKSlcbiAgICAgIDogb3JpZ2luYWxSZWRpcmVjdDtcblxuICAgIGlmICh0eXBlb2YgcmVkaXJlY3QgPT09ICdzdHJpbmcnKSB7XG4gICAgICByZWRpcmVjdCA9IHsgcGF0aDogcmVkaXJlY3QgfTtcbiAgICB9XG5cbiAgICBpZiAoIXJlZGlyZWN0IHx8IHR5cGVvZiByZWRpcmVjdCAhPT0gJ29iamVjdCcpIHtcbiAgICAgIGlmIChwcm9jZXNzLmVudi5OT0RFX0VOViAhPT0gJ3Byb2R1Y3Rpb24nKSB7XG4gICAgICAgIHdhcm4oXG4gICAgICAgICAgZmFsc2UsIChcImludmFsaWQgcmVkaXJlY3Qgb3B0aW9uOiBcIiArIChKU09OLnN0cmluZ2lmeShyZWRpcmVjdCkpKVxuICAgICAgICApO1xuICAgICAgfVxuICAgICAgcmV0dXJuIF9jcmVhdGVSb3V0ZShudWxsLCBsb2NhdGlvbilcbiAgICB9XG5cbiAgICB2YXIgcmUgPSByZWRpcmVjdDtcbiAgICB2YXIgbmFtZSA9IHJlLm5hbWU7XG4gICAgdmFyIHBhdGggPSByZS5wYXRoO1xuICAgIHZhciBxdWVyeSA9IGxvY2F0aW9uLnF1ZXJ5O1xuICAgIHZhciBoYXNoID0gbG9jYXRpb24uaGFzaDtcbiAgICB2YXIgcGFyYW1zID0gbG9jYXRpb24ucGFyYW1zO1xuICAgIHF1ZXJ5ID0gcmUuaGFzT3duUHJvcGVydHkoJ3F1ZXJ5JykgPyByZS5xdWVyeSA6IHF1ZXJ5O1xuICAgIGhhc2ggPSByZS5oYXNPd25Qcm9wZXJ0eSgnaGFzaCcpID8gcmUuaGFzaCA6IGhhc2g7XG4gICAgcGFyYW1zID0gcmUuaGFzT3duUHJvcGVydHkoJ3BhcmFtcycpID8gcmUucGFyYW1zIDogcGFyYW1zO1xuXG4gICAgaWYgKG5hbWUpIHtcbiAgICAgIC8vIHJlc29sdmVkIG5hbWVkIGRpcmVjdFxuICAgICAgdmFyIHRhcmdldFJlY29yZCA9IG5hbWVNYXBbbmFtZV07XG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgICAgICBhc3NlcnQodGFyZ2V0UmVjb3JkLCAoXCJyZWRpcmVjdCBmYWlsZWQ6IG5hbWVkIHJvdXRlIFxcXCJcIiArIG5hbWUgKyBcIlxcXCIgbm90IGZvdW5kLlwiKSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gbWF0Y2goe1xuICAgICAgICBfbm9ybWFsaXplZDogdHJ1ZSxcbiAgICAgICAgbmFtZTogbmFtZSxcbiAgICAgICAgcXVlcnk6IHF1ZXJ5LFxuICAgICAgICBoYXNoOiBoYXNoLFxuICAgICAgICBwYXJhbXM6IHBhcmFtc1xuICAgICAgfSwgdW5kZWZpbmVkLCBsb2NhdGlvbilcbiAgICB9IGVsc2UgaWYgKHBhdGgpIHtcbiAgICAgIC8vIDEuIHJlc29sdmUgcmVsYXRpdmUgcmVkaXJlY3RcbiAgICAgIHZhciByYXdQYXRoID0gcmVzb2x2ZVJlY29yZFBhdGgocGF0aCwgcmVjb3JkKTtcbiAgICAgIC8vIDIuIHJlc29sdmUgcGFyYW1zXG4gICAgICB2YXIgcmVzb2x2ZWRQYXRoID0gZmlsbFBhcmFtcyhyYXdQYXRoLCBwYXJhbXMsIChcInJlZGlyZWN0IHJvdXRlIHdpdGggcGF0aCBcXFwiXCIgKyByYXdQYXRoICsgXCJcXFwiXCIpKTtcbiAgICAgIC8vIDMuIHJlbWF0Y2ggd2l0aCBleGlzdGluZyBxdWVyeSBhbmQgaGFzaFxuICAgICAgcmV0dXJuIG1hdGNoKHtcbiAgICAgICAgX25vcm1hbGl6ZWQ6IHRydWUsXG4gICAgICAgIHBhdGg6IHJlc29sdmVkUGF0aCxcbiAgICAgICAgcXVlcnk6IHF1ZXJ5LFxuICAgICAgICBoYXNoOiBoYXNoXG4gICAgICB9LCB1bmRlZmluZWQsIGxvY2F0aW9uKVxuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgICAgICB3YXJuKGZhbHNlLCAoXCJpbnZhbGlkIHJlZGlyZWN0IG9wdGlvbjogXCIgKyAoSlNPTi5zdHJpbmdpZnkocmVkaXJlY3QpKSkpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIF9jcmVhdGVSb3V0ZShudWxsLCBsb2NhdGlvbilcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBhbGlhcyAoXG4gICAgcmVjb3JkLFxuICAgIGxvY2F0aW9uLFxuICAgIG1hdGNoQXNcbiAgKSB7XG4gICAgdmFyIGFsaWFzZWRQYXRoID0gZmlsbFBhcmFtcyhtYXRjaEFzLCBsb2NhdGlvbi5wYXJhbXMsIChcImFsaWFzZWQgcm91dGUgd2l0aCBwYXRoIFxcXCJcIiArIG1hdGNoQXMgKyBcIlxcXCJcIikpO1xuICAgIHZhciBhbGlhc2VkTWF0Y2ggPSBtYXRjaCh7XG4gICAgICBfbm9ybWFsaXplZDogdHJ1ZSxcbiAgICAgIHBhdGg6IGFsaWFzZWRQYXRoXG4gICAgfSk7XG4gICAgaWYgKGFsaWFzZWRNYXRjaCkge1xuICAgICAgdmFyIG1hdGNoZWQgPSBhbGlhc2VkTWF0Y2gubWF0Y2hlZDtcbiAgICAgIHZhciBhbGlhc2VkUmVjb3JkID0gbWF0Y2hlZFttYXRjaGVkLmxlbmd0aCAtIDFdO1xuICAgICAgbG9jYXRpb24ucGFyYW1zID0gYWxpYXNlZE1hdGNoLnBhcmFtcztcbiAgICAgIHJldHVybiBfY3JlYXRlUm91dGUoYWxpYXNlZFJlY29yZCwgbG9jYXRpb24pXG4gICAgfVxuICAgIHJldHVybiBfY3JlYXRlUm91dGUobnVsbCwgbG9jYXRpb24pXG4gIH1cblxuICBmdW5jdGlvbiBfY3JlYXRlUm91dGUgKFxuICAgIHJlY29yZCxcbiAgICBsb2NhdGlvbixcbiAgICByZWRpcmVjdGVkRnJvbVxuICApIHtcbiAgICBpZiAocmVjb3JkICYmIHJlY29yZC5yZWRpcmVjdCkge1xuICAgICAgcmV0dXJuIHJlZGlyZWN0KHJlY29yZCwgcmVkaXJlY3RlZEZyb20gfHwgbG9jYXRpb24pXG4gICAgfVxuICAgIGlmIChyZWNvcmQgJiYgcmVjb3JkLm1hdGNoQXMpIHtcbiAgICAgIHJldHVybiBhbGlhcyhyZWNvcmQsIGxvY2F0aW9uLCByZWNvcmQubWF0Y2hBcylcbiAgICB9XG4gICAgcmV0dXJuIGNyZWF0ZVJvdXRlKHJlY29yZCwgbG9jYXRpb24sIHJlZGlyZWN0ZWRGcm9tLCByb3V0ZXIpXG4gIH1cblxuICByZXR1cm4ge1xuICAgIG1hdGNoOiBtYXRjaCxcbiAgICBhZGRSb3V0ZTogYWRkUm91dGUsXG4gICAgZ2V0Um91dGVzOiBnZXRSb3V0ZXMsXG4gICAgYWRkUm91dGVzOiBhZGRSb3V0ZXNcbiAgfVxufVxuXG5mdW5jdGlvbiBtYXRjaFJvdXRlIChcbiAgcmVnZXgsXG4gIHBhdGgsXG4gIHBhcmFtc1xuKSB7XG4gIHZhciBtID0gcGF0aC5tYXRjaChyZWdleCk7XG5cbiAgaWYgKCFtKSB7XG4gICAgcmV0dXJuIGZhbHNlXG4gIH0gZWxzZSBpZiAoIXBhcmFtcykge1xuICAgIHJldHVybiB0cnVlXG4gIH1cblxuICBmb3IgKHZhciBpID0gMSwgbGVuID0gbS5sZW5ndGg7IGkgPCBsZW47ICsraSkge1xuICAgIHZhciBrZXkgPSByZWdleC5rZXlzW2kgLSAxXTtcbiAgICBpZiAoa2V5KSB7XG4gICAgICAvLyBGaXggIzE5OTQ6IHVzaW5nICogd2l0aCBwcm9wczogdHJ1ZSBnZW5lcmF0ZXMgYSBwYXJhbSBuYW1lZCAwXG4gICAgICBwYXJhbXNba2V5Lm5hbWUgfHwgJ3BhdGhNYXRjaCddID0gdHlwZW9mIG1baV0gPT09ICdzdHJpbmcnID8gZGVjb2RlKG1baV0pIDogbVtpXTtcbiAgICB9XG4gIH1cblxuICByZXR1cm4gdHJ1ZVxufVxuXG5mdW5jdGlvbiByZXNvbHZlUmVjb3JkUGF0aCAocGF0aCwgcmVjb3JkKSB7XG4gIHJldHVybiByZXNvbHZlUGF0aChwYXRoLCByZWNvcmQucGFyZW50ID8gcmVjb3JkLnBhcmVudC5wYXRoIDogJy8nLCB0cnVlKVxufVxuXG4vKiAgKi9cblxuLy8gdXNlIFVzZXIgVGltaW5nIGFwaSAoaWYgcHJlc2VudCkgZm9yIG1vcmUgYWNjdXJhdGUga2V5IHByZWNpc2lvblxudmFyIFRpbWUgPVxuICBpbkJyb3dzZXIgJiYgd2luZG93LnBlcmZvcm1hbmNlICYmIHdpbmRvdy5wZXJmb3JtYW5jZS5ub3dcbiAgICA/IHdpbmRvdy5wZXJmb3JtYW5jZVxuICAgIDogRGF0ZTtcblxuZnVuY3Rpb24gZ2VuU3RhdGVLZXkgKCkge1xuICByZXR1cm4gVGltZS5ub3coKS50b0ZpeGVkKDMpXG59XG5cbnZhciBfa2V5ID0gZ2VuU3RhdGVLZXkoKTtcblxuZnVuY3Rpb24gZ2V0U3RhdGVLZXkgKCkge1xuICByZXR1cm4gX2tleVxufVxuXG5mdW5jdGlvbiBzZXRTdGF0ZUtleSAoa2V5KSB7XG4gIHJldHVybiAoX2tleSA9IGtleSlcbn1cblxuLyogICovXG5cbnZhciBwb3NpdGlvblN0b3JlID0gT2JqZWN0LmNyZWF0ZShudWxsKTtcblxuZnVuY3Rpb24gc2V0dXBTY3JvbGwgKCkge1xuICAvLyBQcmV2ZW50IGJyb3dzZXIgc2Nyb2xsIGJlaGF2aW9yIG9uIEhpc3RvcnkgcG9wc3RhdGVcbiAgaWYgKCdzY3JvbGxSZXN0b3JhdGlvbicgaW4gd2luZG93Lmhpc3RvcnkpIHtcbiAgICB3aW5kb3cuaGlzdG9yeS5zY3JvbGxSZXN0b3JhdGlvbiA9ICdtYW51YWwnO1xuICB9XG4gIC8vIEZpeCBmb3IgIzE1ODUgZm9yIEZpcmVmb3hcbiAgLy8gRml4IGZvciAjMjE5NSBBZGQgb3B0aW9uYWwgdGhpcmQgYXR0cmlidXRlIHRvIHdvcmthcm91bmQgYSBidWcgaW4gc2FmYXJpIGh0dHBzOi8vYnVncy53ZWJraXQub3JnL3Nob3dfYnVnLmNnaT9pZD0xODI2NzhcbiAgLy8gRml4IGZvciAjMjc3NCBTdXBwb3J0IGZvciBhcHBzIGxvYWRlZCBmcm9tIFdpbmRvd3MgZmlsZSBzaGFyZXMgbm90IG1hcHBlZCB0byBuZXR3b3JrIGRyaXZlczogcmVwbGFjZWQgbG9jYXRpb24ub3JpZ2luIHdpdGhcbiAgLy8gd2luZG93LmxvY2F0aW9uLnByb3RvY29sICsgJy8vJyArIHdpbmRvdy5sb2NhdGlvbi5ob3N0XG4gIC8vIGxvY2F0aW9uLmhvc3QgY29udGFpbnMgdGhlIHBvcnQgYW5kIGxvY2F0aW9uLmhvc3RuYW1lIGRvZXNuJ3RcbiAgdmFyIHByb3RvY29sQW5kUGF0aCA9IHdpbmRvdy5sb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyB3aW5kb3cubG9jYXRpb24uaG9zdDtcbiAgdmFyIGFic29sdXRlUGF0aCA9IHdpbmRvdy5sb2NhdGlvbi5ocmVmLnJlcGxhY2UocHJvdG9jb2xBbmRQYXRoLCAnJyk7XG4gIC8vIHByZXNlcnZlIGV4aXN0aW5nIGhpc3Rvcnkgc3RhdGUgYXMgaXQgY291bGQgYmUgb3ZlcnJpZGVuIGJ5IHRoZSB1c2VyXG4gIHZhciBzdGF0ZUNvcHkgPSBleHRlbmQoe30sIHdpbmRvdy5oaXN0b3J5LnN0YXRlKTtcbiAgc3RhdGVDb3B5LmtleSA9IGdldFN0YXRlS2V5KCk7XG4gIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZShzdGF0ZUNvcHksICcnLCBhYnNvbHV0ZVBhdGgpO1xuICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncG9wc3RhdGUnLCBoYW5kbGVQb3BTdGF0ZSk7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgaGFuZGxlUG9wU3RhdGUpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVNjcm9sbCAoXG4gIHJvdXRlcixcbiAgdG8sXG4gIGZyb20sXG4gIGlzUG9wXG4pIHtcbiAgaWYgKCFyb3V0ZXIuYXBwKSB7XG4gICAgcmV0dXJuXG4gIH1cblxuICB2YXIgYmVoYXZpb3IgPSByb3V0ZXIub3B0aW9ucy5zY3JvbGxCZWhhdmlvcjtcbiAgaWYgKCFiZWhhdmlvcikge1xuICAgIHJldHVyblxuICB9XG5cbiAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICBhc3NlcnQodHlwZW9mIGJlaGF2aW9yID09PSAnZnVuY3Rpb24nLCBcInNjcm9sbEJlaGF2aW9yIG11c3QgYmUgYSBmdW5jdGlvblwiKTtcbiAgfVxuXG4gIC8vIHdhaXQgdW50aWwgcmUtcmVuZGVyIGZpbmlzaGVzIGJlZm9yZSBzY3JvbGxpbmdcbiAgcm91dGVyLmFwcC4kbmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgIHZhciBwb3NpdGlvbiA9IGdldFNjcm9sbFBvc2l0aW9uKCk7XG4gICAgdmFyIHNob3VsZFNjcm9sbCA9IGJlaGF2aW9yLmNhbGwoXG4gICAgICByb3V0ZXIsXG4gICAgICB0byxcbiAgICAgIGZyb20sXG4gICAgICBpc1BvcCA/IHBvc2l0aW9uIDogbnVsbFxuICAgICk7XG5cbiAgICBpZiAoIXNob3VsZFNjcm9sbCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgaWYgKHR5cGVvZiBzaG91bGRTY3JvbGwudGhlbiA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgc2hvdWxkU2Nyb2xsXG4gICAgICAgIC50aGVuKGZ1bmN0aW9uIChzaG91bGRTY3JvbGwpIHtcbiAgICAgICAgICBzY3JvbGxUb1Bvc2l0aW9uKChzaG91bGRTY3JvbGwpLCBwb3NpdGlvbik7XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaChmdW5jdGlvbiAoZXJyKSB7XG4gICAgICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgICAgICAgIGFzc2VydChmYWxzZSwgZXJyLnRvU3RyaW5nKCkpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNjcm9sbFRvUG9zaXRpb24oc2hvdWxkU2Nyb2xsLCBwb3NpdGlvbik7XG4gICAgfVxuICB9KTtcbn1cblxuZnVuY3Rpb24gc2F2ZVNjcm9sbFBvc2l0aW9uICgpIHtcbiAgdmFyIGtleSA9IGdldFN0YXRlS2V5KCk7XG4gIGlmIChrZXkpIHtcbiAgICBwb3NpdGlvblN0b3JlW2tleV0gPSB7XG4gICAgICB4OiB3aW5kb3cucGFnZVhPZmZzZXQsXG4gICAgICB5OiB3aW5kb3cucGFnZVlPZmZzZXRcbiAgICB9O1xuICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVBvcFN0YXRlIChlKSB7XG4gIHNhdmVTY3JvbGxQb3NpdGlvbigpO1xuICBpZiAoZS5zdGF0ZSAmJiBlLnN0YXRlLmtleSkge1xuICAgIHNldFN0YXRlS2V5KGUuc3RhdGUua2V5KTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRTY3JvbGxQb3NpdGlvbiAoKSB7XG4gIHZhciBrZXkgPSBnZXRTdGF0ZUtleSgpO1xuICBpZiAoa2V5KSB7XG4gICAgcmV0dXJuIHBvc2l0aW9uU3RvcmVba2V5XVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldEVsZW1lbnRQb3NpdGlvbiAoZWwsIG9mZnNldCkge1xuICB2YXIgZG9jRWwgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQ7XG4gIHZhciBkb2NSZWN0ID0gZG9jRWwuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gIHZhciBlbFJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgcmV0dXJuIHtcbiAgICB4OiBlbFJlY3QubGVmdCAtIGRvY1JlY3QubGVmdCAtIG9mZnNldC54LFxuICAgIHk6IGVsUmVjdC50b3AgLSBkb2NSZWN0LnRvcCAtIG9mZnNldC55XG4gIH1cbn1cblxuZnVuY3Rpb24gaXNWYWxpZFBvc2l0aW9uIChvYmopIHtcbiAgcmV0dXJuIGlzTnVtYmVyKG9iai54KSB8fCBpc051bWJlcihvYmoueSlcbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplUG9zaXRpb24gKG9iaikge1xuICByZXR1cm4ge1xuICAgIHg6IGlzTnVtYmVyKG9iai54KSA/IG9iai54IDogd2luZG93LnBhZ2VYT2Zmc2V0LFxuICAgIHk6IGlzTnVtYmVyKG9iai55KSA/IG9iai55IDogd2luZG93LnBhZ2VZT2Zmc2V0XG4gIH1cbn1cblxuZnVuY3Rpb24gbm9ybWFsaXplT2Zmc2V0IChvYmopIHtcbiAgcmV0dXJuIHtcbiAgICB4OiBpc051bWJlcihvYmoueCkgPyBvYmoueCA6IDAsXG4gICAgeTogaXNOdW1iZXIob2JqLnkpID8gb2JqLnkgOiAwXG4gIH1cbn1cblxuZnVuY3Rpb24gaXNOdW1iZXIgKHYpIHtcbiAgcmV0dXJuIHR5cGVvZiB2ID09PSAnbnVtYmVyJ1xufVxuXG52YXIgaGFzaFN0YXJ0c1dpdGhOdW1iZXJSRSA9IC9eI1xcZC87XG5cbmZ1bmN0aW9uIHNjcm9sbFRvUG9zaXRpb24gKHNob3VsZFNjcm9sbCwgcG9zaXRpb24pIHtcbiAgdmFyIGlzT2JqZWN0ID0gdHlwZW9mIHNob3VsZFNjcm9sbCA9PT0gJ29iamVjdCc7XG4gIGlmIChpc09iamVjdCAmJiB0eXBlb2Ygc2hvdWxkU2Nyb2xsLnNlbGVjdG9yID09PSAnc3RyaW5nJykge1xuICAgIC8vIGdldEVsZW1lbnRCeUlkIHdvdWxkIHN0aWxsIGZhaWwgaWYgdGhlIHNlbGVjdG9yIGNvbnRhaW5zIGEgbW9yZSBjb21wbGljYXRlZCBxdWVyeSBsaWtlICNtYWluW2RhdGEtYXR0cl1cbiAgICAvLyBidXQgYXQgdGhlIHNhbWUgdGltZSwgaXQgZG9lc24ndCBtYWtlIG11Y2ggc2Vuc2UgdG8gc2VsZWN0IGFuIGVsZW1lbnQgd2l0aCBhbiBpZCBhbmQgYW4gZXh0cmEgc2VsZWN0b3JcbiAgICB2YXIgZWwgPSBoYXNoU3RhcnRzV2l0aE51bWJlclJFLnRlc3Qoc2hvdWxkU2Nyb2xsLnNlbGVjdG9yKSAvLyAkZmxvdy1kaXNhYmxlLWxpbmVcbiAgICAgID8gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoc2hvdWxkU2Nyb2xsLnNlbGVjdG9yLnNsaWNlKDEpKSAvLyAkZmxvdy1kaXNhYmxlLWxpbmVcbiAgICAgIDogZG9jdW1lbnQucXVlcnlTZWxlY3RvcihzaG91bGRTY3JvbGwuc2VsZWN0b3IpO1xuXG4gICAgaWYgKGVsKSB7XG4gICAgICB2YXIgb2Zmc2V0ID1cbiAgICAgICAgc2hvdWxkU2Nyb2xsLm9mZnNldCAmJiB0eXBlb2Ygc2hvdWxkU2Nyb2xsLm9mZnNldCA9PT0gJ29iamVjdCdcbiAgICAgICAgICA/IHNob3VsZFNjcm9sbC5vZmZzZXRcbiAgICAgICAgICA6IHt9O1xuICAgICAgb2Zmc2V0ID0gbm9ybWFsaXplT2Zmc2V0KG9mZnNldCk7XG4gICAgICBwb3NpdGlvbiA9IGdldEVsZW1lbnRQb3NpdGlvbihlbCwgb2Zmc2V0KTtcbiAgICB9IGVsc2UgaWYgKGlzVmFsaWRQb3NpdGlvbihzaG91bGRTY3JvbGwpKSB7XG4gICAgICBwb3NpdGlvbiA9IG5vcm1hbGl6ZVBvc2l0aW9uKHNob3VsZFNjcm9sbCk7XG4gICAgfVxuICB9IGVsc2UgaWYgKGlzT2JqZWN0ICYmIGlzVmFsaWRQb3NpdGlvbihzaG91bGRTY3JvbGwpKSB7XG4gICAgcG9zaXRpb24gPSBub3JtYWxpemVQb3NpdGlvbihzaG91bGRTY3JvbGwpO1xuICB9XG5cbiAgaWYgKHBvc2l0aW9uKSB7XG4gICAgLy8gJGZsb3ctZGlzYWJsZS1saW5lXG4gICAgaWYgKCdzY3JvbGxCZWhhdmlvcicgaW4gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlKSB7XG4gICAgICB3aW5kb3cuc2Nyb2xsVG8oe1xuICAgICAgICBsZWZ0OiBwb3NpdGlvbi54LFxuICAgICAgICB0b3A6IHBvc2l0aW9uLnksXG4gICAgICAgIC8vICRmbG93LWRpc2FibGUtbGluZVxuICAgICAgICBiZWhhdmlvcjogc2hvdWxkU2Nyb2xsLmJlaGF2aW9yXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgd2luZG93LnNjcm9sbFRvKHBvc2l0aW9uLngsIHBvc2l0aW9uLnkpO1xuICAgIH1cbiAgfVxufVxuXG4vKiAgKi9cblxudmFyIHN1cHBvcnRzUHVzaFN0YXRlID1cbiAgaW5Ccm93c2VyICYmXG4gIChmdW5jdGlvbiAoKSB7XG4gICAgdmFyIHVhID0gd2luZG93Lm5hdmlnYXRvci51c2VyQWdlbnQ7XG5cbiAgICBpZiAoXG4gICAgICAodWEuaW5kZXhPZignQW5kcm9pZCAyLicpICE9PSAtMSB8fCB1YS5pbmRleE9mKCdBbmRyb2lkIDQuMCcpICE9PSAtMSkgJiZcbiAgICAgIHVhLmluZGV4T2YoJ01vYmlsZSBTYWZhcmknKSAhPT0gLTEgJiZcbiAgICAgIHVhLmluZGV4T2YoJ0Nocm9tZScpID09PSAtMSAmJlxuICAgICAgdWEuaW5kZXhPZignV2luZG93cyBQaG9uZScpID09PSAtMVxuICAgICkge1xuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuXG4gICAgcmV0dXJuIHdpbmRvdy5oaXN0b3J5ICYmIHR5cGVvZiB3aW5kb3cuaGlzdG9yeS5wdXNoU3RhdGUgPT09ICdmdW5jdGlvbidcbiAgfSkoKTtcblxuZnVuY3Rpb24gcHVzaFN0YXRlICh1cmwsIHJlcGxhY2UpIHtcbiAgc2F2ZVNjcm9sbFBvc2l0aW9uKCk7XG4gIC8vIHRyeS4uLmNhdGNoIHRoZSBwdXNoU3RhdGUgY2FsbCB0byBnZXQgYXJvdW5kIFNhZmFyaVxuICAvLyBET00gRXhjZXB0aW9uIDE4IHdoZXJlIGl0IGxpbWl0cyB0byAxMDAgcHVzaFN0YXRlIGNhbGxzXG4gIHZhciBoaXN0b3J5ID0gd2luZG93Lmhpc3Rvcnk7XG4gIHRyeSB7XG4gICAgaWYgKHJlcGxhY2UpIHtcbiAgICAgIC8vIHByZXNlcnZlIGV4aXN0aW5nIGhpc3Rvcnkgc3RhdGUgYXMgaXQgY291bGQgYmUgb3ZlcnJpZGVuIGJ5IHRoZSB1c2VyXG4gICAgICB2YXIgc3RhdGVDb3B5ID0gZXh0ZW5kKHt9LCBoaXN0b3J5LnN0YXRlKTtcbiAgICAgIHN0YXRlQ29weS5rZXkgPSBnZXRTdGF0ZUtleSgpO1xuICAgICAgaGlzdG9yeS5yZXBsYWNlU3RhdGUoc3RhdGVDb3B5LCAnJywgdXJsKTtcbiAgICB9IGVsc2Uge1xuICAgICAgaGlzdG9yeS5wdXNoU3RhdGUoeyBrZXk6IHNldFN0YXRlS2V5KGdlblN0YXRlS2V5KCkpIH0sICcnLCB1cmwpO1xuICAgIH1cbiAgfSBjYXRjaCAoZSkge1xuICAgIHdpbmRvdy5sb2NhdGlvbltyZXBsYWNlID8gJ3JlcGxhY2UnIDogJ2Fzc2lnbiddKHVybCk7XG4gIH1cbn1cblxuZnVuY3Rpb24gcmVwbGFjZVN0YXRlICh1cmwpIHtcbiAgcHVzaFN0YXRlKHVybCwgdHJ1ZSk7XG59XG5cbi8qICAqL1xuXG5mdW5jdGlvbiBydW5RdWV1ZSAocXVldWUsIGZuLCBjYikge1xuICB2YXIgc3RlcCA9IGZ1bmN0aW9uIChpbmRleCkge1xuICAgIGlmIChpbmRleCA+PSBxdWV1ZS5sZW5ndGgpIHtcbiAgICAgIGNiKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGlmIChxdWV1ZVtpbmRleF0pIHtcbiAgICAgICAgZm4ocXVldWVbaW5kZXhdLCBmdW5jdGlvbiAoKSB7XG4gICAgICAgICAgc3RlcChpbmRleCArIDEpO1xuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHN0ZXAoaW5kZXggKyAxKTtcbiAgICAgIH1cbiAgICB9XG4gIH07XG4gIHN0ZXAoMCk7XG59XG5cbi8vIFdoZW4gY2hhbmdpbmcgdGhpbmcsIGFsc28gZWRpdCByb3V0ZXIuZC50c1xudmFyIE5hdmlnYXRpb25GYWlsdXJlVHlwZSA9IHtcbiAgcmVkaXJlY3RlZDogMixcbiAgYWJvcnRlZDogNCxcbiAgY2FuY2VsbGVkOiA4LFxuICBkdXBsaWNhdGVkOiAxNlxufTtcblxuZnVuY3Rpb24gY3JlYXRlTmF2aWdhdGlvblJlZGlyZWN0ZWRFcnJvciAoZnJvbSwgdG8pIHtcbiAgcmV0dXJuIGNyZWF0ZVJvdXRlckVycm9yKFxuICAgIGZyb20sXG4gICAgdG8sXG4gICAgTmF2aWdhdGlvbkZhaWx1cmVUeXBlLnJlZGlyZWN0ZWQsXG4gICAgKFwiUmVkaXJlY3RlZCB3aGVuIGdvaW5nIGZyb20gXFxcIlwiICsgKGZyb20uZnVsbFBhdGgpICsgXCJcXFwiIHRvIFxcXCJcIiArIChzdHJpbmdpZnlSb3V0ZShcbiAgICAgIHRvXG4gICAgKSkgKyBcIlxcXCIgdmlhIGEgbmF2aWdhdGlvbiBndWFyZC5cIilcbiAgKVxufVxuXG5mdW5jdGlvbiBjcmVhdGVOYXZpZ2F0aW9uRHVwbGljYXRlZEVycm9yIChmcm9tLCB0bykge1xuICB2YXIgZXJyb3IgPSBjcmVhdGVSb3V0ZXJFcnJvcihcbiAgICBmcm9tLFxuICAgIHRvLFxuICAgIE5hdmlnYXRpb25GYWlsdXJlVHlwZS5kdXBsaWNhdGVkLFxuICAgIChcIkF2b2lkZWQgcmVkdW5kYW50IG5hdmlnYXRpb24gdG8gY3VycmVudCBsb2NhdGlvbjogXFxcIlwiICsgKGZyb20uZnVsbFBhdGgpICsgXCJcXFwiLlwiKVxuICApO1xuICAvLyBiYWNrd2FyZHMgY29tcGF0aWJsZSB3aXRoIHRoZSBmaXJzdCBpbnRyb2R1Y3Rpb24gb2YgRXJyb3JzXG4gIGVycm9yLm5hbWUgPSAnTmF2aWdhdGlvbkR1cGxpY2F0ZWQnO1xuICByZXR1cm4gZXJyb3Jcbn1cblxuZnVuY3Rpb24gY3JlYXRlTmF2aWdhdGlvbkNhbmNlbGxlZEVycm9yIChmcm9tLCB0bykge1xuICByZXR1cm4gY3JlYXRlUm91dGVyRXJyb3IoXG4gICAgZnJvbSxcbiAgICB0byxcbiAgICBOYXZpZ2F0aW9uRmFpbHVyZVR5cGUuY2FuY2VsbGVkLFxuICAgIChcIk5hdmlnYXRpb24gY2FuY2VsbGVkIGZyb20gXFxcIlwiICsgKGZyb20uZnVsbFBhdGgpICsgXCJcXFwiIHRvIFxcXCJcIiArICh0by5mdWxsUGF0aCkgKyBcIlxcXCIgd2l0aCBhIG5ldyBuYXZpZ2F0aW9uLlwiKVxuICApXG59XG5cbmZ1bmN0aW9uIGNyZWF0ZU5hdmlnYXRpb25BYm9ydGVkRXJyb3IgKGZyb20sIHRvKSB7XG4gIHJldHVybiBjcmVhdGVSb3V0ZXJFcnJvcihcbiAgICBmcm9tLFxuICAgIHRvLFxuICAgIE5hdmlnYXRpb25GYWlsdXJlVHlwZS5hYm9ydGVkLFxuICAgIChcIk5hdmlnYXRpb24gYWJvcnRlZCBmcm9tIFxcXCJcIiArIChmcm9tLmZ1bGxQYXRoKSArIFwiXFxcIiB0byBcXFwiXCIgKyAodG8uZnVsbFBhdGgpICsgXCJcXFwiIHZpYSBhIG5hdmlnYXRpb24gZ3VhcmQuXCIpXG4gIClcbn1cblxuZnVuY3Rpb24gY3JlYXRlUm91dGVyRXJyb3IgKGZyb20sIHRvLCB0eXBlLCBtZXNzYWdlKSB7XG4gIHZhciBlcnJvciA9IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgZXJyb3IuX2lzUm91dGVyID0gdHJ1ZTtcbiAgZXJyb3IuZnJvbSA9IGZyb207XG4gIGVycm9yLnRvID0gdG87XG4gIGVycm9yLnR5cGUgPSB0eXBlO1xuXG4gIHJldHVybiBlcnJvclxufVxuXG52YXIgcHJvcGVydGllc1RvTG9nID0gWydwYXJhbXMnLCAncXVlcnknLCAnaGFzaCddO1xuXG5mdW5jdGlvbiBzdHJpbmdpZnlSb3V0ZSAodG8pIHtcbiAgaWYgKHR5cGVvZiB0byA9PT0gJ3N0cmluZycpIHsgcmV0dXJuIHRvIH1cbiAgaWYgKCdwYXRoJyBpbiB0bykgeyByZXR1cm4gdG8ucGF0aCB9XG4gIHZhciBsb2NhdGlvbiA9IHt9O1xuICBwcm9wZXJ0aWVzVG9Mb2cuZm9yRWFjaChmdW5jdGlvbiAoa2V5KSB7XG4gICAgaWYgKGtleSBpbiB0bykgeyBsb2NhdGlvbltrZXldID0gdG9ba2V5XTsgfVxuICB9KTtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGxvY2F0aW9uLCBudWxsLCAyKVxufVxuXG5mdW5jdGlvbiBpc0Vycm9yIChlcnIpIHtcbiAgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChlcnIpLmluZGV4T2YoJ0Vycm9yJykgPiAtMVxufVxuXG5mdW5jdGlvbiBpc05hdmlnYXRpb25GYWlsdXJlIChlcnIsIGVycm9yVHlwZSkge1xuICByZXR1cm4gKFxuICAgIGlzRXJyb3IoZXJyKSAmJlxuICAgIGVyci5faXNSb3V0ZXIgJiZcbiAgICAoZXJyb3JUeXBlID09IG51bGwgfHwgZXJyLnR5cGUgPT09IGVycm9yVHlwZSlcbiAgKVxufVxuXG4vKiAgKi9cblxuZnVuY3Rpb24gcmVzb2x2ZUFzeW5jQ29tcG9uZW50cyAobWF0Y2hlZCkge1xuICByZXR1cm4gZnVuY3Rpb24gKHRvLCBmcm9tLCBuZXh0KSB7XG4gICAgdmFyIGhhc0FzeW5jID0gZmFsc2U7XG4gICAgdmFyIHBlbmRpbmcgPSAwO1xuICAgIHZhciBlcnJvciA9IG51bGw7XG5cbiAgICBmbGF0TWFwQ29tcG9uZW50cyhtYXRjaGVkLCBmdW5jdGlvbiAoZGVmLCBfLCBtYXRjaCwga2V5KSB7XG4gICAgICAvLyBpZiBpdCdzIGEgZnVuY3Rpb24gYW5kIGRvZXNuJ3QgaGF2ZSBjaWQgYXR0YWNoZWQsXG4gICAgICAvLyBhc3N1bWUgaXQncyBhbiBhc3luYyBjb21wb25lbnQgcmVzb2x2ZSBmdW5jdGlvbi5cbiAgICAgIC8vIHdlIGFyZSBub3QgdXNpbmcgVnVlJ3MgZGVmYXVsdCBhc3luYyByZXNvbHZpbmcgbWVjaGFuaXNtIGJlY2F1c2VcbiAgICAgIC8vIHdlIHdhbnQgdG8gaGFsdCB0aGUgbmF2aWdhdGlvbiB1bnRpbCB0aGUgaW5jb21pbmcgY29tcG9uZW50IGhhcyBiZWVuXG4gICAgICAvLyByZXNvbHZlZC5cbiAgICAgIGlmICh0eXBlb2YgZGVmID09PSAnZnVuY3Rpb24nICYmIGRlZi5jaWQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBoYXNBc3luYyA9IHRydWU7XG4gICAgICAgIHBlbmRpbmcrKztcblxuICAgICAgICB2YXIgcmVzb2x2ZSA9IG9uY2UoZnVuY3Rpb24gKHJlc29sdmVkRGVmKSB7XG4gICAgICAgICAgaWYgKGlzRVNNb2R1bGUocmVzb2x2ZWREZWYpKSB7XG4gICAgICAgICAgICByZXNvbHZlZERlZiA9IHJlc29sdmVkRGVmLmRlZmF1bHQ7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIHNhdmUgcmVzb2x2ZWQgb24gYXN5bmMgZmFjdG9yeSBpbiBjYXNlIGl0J3MgdXNlZCBlbHNld2hlcmVcbiAgICAgICAgICBkZWYucmVzb2x2ZWQgPSB0eXBlb2YgcmVzb2x2ZWREZWYgPT09ICdmdW5jdGlvbidcbiAgICAgICAgICAgID8gcmVzb2x2ZWREZWZcbiAgICAgICAgICAgIDogX1Z1ZS5leHRlbmQocmVzb2x2ZWREZWYpO1xuICAgICAgICAgIG1hdGNoLmNvbXBvbmVudHNba2V5XSA9IHJlc29sdmVkRGVmO1xuICAgICAgICAgIHBlbmRpbmctLTtcbiAgICAgICAgICBpZiAocGVuZGluZyA8PSAwKSB7XG4gICAgICAgICAgICBuZXh0KCk7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgcmVqZWN0ID0gb25jZShmdW5jdGlvbiAocmVhc29uKSB7XG4gICAgICAgICAgdmFyIG1zZyA9IFwiRmFpbGVkIHRvIHJlc29sdmUgYXN5bmMgY29tcG9uZW50IFwiICsga2V5ICsgXCI6IFwiICsgcmVhc29uO1xuICAgICAgICAgIHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgJiYgd2FybihmYWxzZSwgbXNnKTtcbiAgICAgICAgICBpZiAoIWVycm9yKSB7XG4gICAgICAgICAgICBlcnJvciA9IGlzRXJyb3IocmVhc29uKVxuICAgICAgICAgICAgICA/IHJlYXNvblxuICAgICAgICAgICAgICA6IG5ldyBFcnJvcihtc2cpO1xuICAgICAgICAgICAgbmV4dChlcnJvcik7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICB2YXIgcmVzO1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHJlcyA9IGRlZihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgcmVqZWN0KGUpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChyZXMpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIHJlcy50aGVuID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICByZXMudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBuZXcgc3ludGF4IGluIFZ1ZSAyLjNcbiAgICAgICAgICAgIHZhciBjb21wID0gcmVzLmNvbXBvbmVudDtcbiAgICAgICAgICAgIGlmIChjb21wICYmIHR5cGVvZiBjb21wLnRoZW4gPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgY29tcC50aGVuKHJlc29sdmUsIHJlamVjdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG5cbiAgICBpZiAoIWhhc0FzeW5jKSB7IG5leHQoKTsgfVxuICB9XG59XG5cbmZ1bmN0aW9uIGZsYXRNYXBDb21wb25lbnRzIChcbiAgbWF0Y2hlZCxcbiAgZm5cbikge1xuICByZXR1cm4gZmxhdHRlbihtYXRjaGVkLm1hcChmdW5jdGlvbiAobSkge1xuICAgIHJldHVybiBPYmplY3Qua2V5cyhtLmNvbXBvbmVudHMpLm1hcChmdW5jdGlvbiAoa2V5KSB7IHJldHVybiBmbihcbiAgICAgIG0uY29tcG9uZW50c1trZXldLFxuICAgICAgbS5pbnN0YW5jZXNba2V5XSxcbiAgICAgIG0sIGtleVxuICAgICk7IH0pXG4gIH0pKVxufVxuXG5mdW5jdGlvbiBmbGF0dGVuIChhcnIpIHtcbiAgcmV0dXJuIEFycmF5LnByb3RvdHlwZS5jb25jYXQuYXBwbHkoW10sIGFycilcbn1cblxudmFyIGhhc1N5bWJvbCA9XG4gIHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicgJiZcbiAgdHlwZW9mIFN5bWJvbC50b1N0cmluZ1RhZyA9PT0gJ3N5bWJvbCc7XG5cbmZ1bmN0aW9uIGlzRVNNb2R1bGUgKG9iaikge1xuICByZXR1cm4gb2JqLl9fZXNNb2R1bGUgfHwgKGhhc1N5bWJvbCAmJiBvYmpbU3ltYm9sLnRvU3RyaW5nVGFnXSA9PT0gJ01vZHVsZScpXG59XG5cbi8vIGluIFdlYnBhY2sgMiwgcmVxdWlyZS5lbnN1cmUgbm93IGFsc28gcmV0dXJucyBhIFByb21pc2Vcbi8vIHNvIHRoZSByZXNvbHZlL3JlamVjdCBmdW5jdGlvbnMgbWF5IGdldCBjYWxsZWQgYW4gZXh0cmEgdGltZVxuLy8gaWYgdGhlIHVzZXIgdXNlcyBhbiBhcnJvdyBmdW5jdGlvbiBzaG9ydGhhbmQgdGhhdCBoYXBwZW5zIHRvXG4vLyByZXR1cm4gdGhhdCBQcm9taXNlLlxuZnVuY3Rpb24gb25jZSAoZm4pIHtcbiAgdmFyIGNhbGxlZCA9IGZhbHNlO1xuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIHZhciBhcmdzID0gW10sIGxlbiA9IGFyZ3VtZW50cy5sZW5ndGg7XG4gICAgd2hpbGUgKCBsZW4tLSApIGFyZ3NbIGxlbiBdID0gYXJndW1lbnRzWyBsZW4gXTtcblxuICAgIGlmIChjYWxsZWQpIHsgcmV0dXJuIH1cbiAgICBjYWxsZWQgPSB0cnVlO1xuICAgIHJldHVybiBmbi5hcHBseSh0aGlzLCBhcmdzKVxuICB9XG59XG5cbi8qICAqL1xuXG52YXIgSGlzdG9yeSA9IGZ1bmN0aW9uIEhpc3RvcnkgKHJvdXRlciwgYmFzZSkge1xuICB0aGlzLnJvdXRlciA9IHJvdXRlcjtcbiAgdGhpcy5iYXNlID0gbm9ybWFsaXplQmFzZShiYXNlKTtcbiAgLy8gc3RhcnQgd2l0aCBhIHJvdXRlIG9iamVjdCB0aGF0IHN0YW5kcyBmb3IgXCJub3doZXJlXCJcbiAgdGhpcy5jdXJyZW50ID0gU1RBUlQ7XG4gIHRoaXMucGVuZGluZyA9IG51bGw7XG4gIHRoaXMucmVhZHkgPSBmYWxzZTtcbiAgdGhpcy5yZWFkeUNicyA9IFtdO1xuICB0aGlzLnJlYWR5RXJyb3JDYnMgPSBbXTtcbiAgdGhpcy5lcnJvckNicyA9IFtdO1xuICB0aGlzLmxpc3RlbmVycyA9IFtdO1xufTtcblxuSGlzdG9yeS5wcm90b3R5cGUubGlzdGVuID0gZnVuY3Rpb24gbGlzdGVuIChjYikge1xuICB0aGlzLmNiID0gY2I7XG59O1xuXG5IaXN0b3J5LnByb3RvdHlwZS5vblJlYWR5ID0gZnVuY3Rpb24gb25SZWFkeSAoY2IsIGVycm9yQ2IpIHtcbiAgaWYgKHRoaXMucmVhZHkpIHtcbiAgICBjYigpO1xuICB9IGVsc2Uge1xuICAgIHRoaXMucmVhZHlDYnMucHVzaChjYik7XG4gICAgaWYgKGVycm9yQ2IpIHtcbiAgICAgIHRoaXMucmVhZHlFcnJvckNicy5wdXNoKGVycm9yQ2IpO1xuICAgIH1cbiAgfVxufTtcblxuSGlzdG9yeS5wcm90b3R5cGUub25FcnJvciA9IGZ1bmN0aW9uIG9uRXJyb3IgKGVycm9yQ2IpIHtcbiAgdGhpcy5lcnJvckNicy5wdXNoKGVycm9yQ2IpO1xufTtcblxuSGlzdG9yeS5wcm90b3R5cGUudHJhbnNpdGlvblRvID0gZnVuY3Rpb24gdHJhbnNpdGlvblRvIChcbiAgbG9jYXRpb24sXG4gIG9uQ29tcGxldGUsXG4gIG9uQWJvcnRcbikge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gIHZhciByb3V0ZTtcbiAgLy8gY2F0Y2ggcmVkaXJlY3Qgb3B0aW9uIGh0dHBzOi8vZ2l0aHViLmNvbS92dWVqcy92dWUtcm91dGVyL2lzc3Vlcy8zMjAxXG4gIHRyeSB7XG4gICAgcm91dGUgPSB0aGlzLnJvdXRlci5tYXRjaChsb2NhdGlvbiwgdGhpcy5jdXJyZW50KTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIHRoaXMuZXJyb3JDYnMuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgIGNiKGUpO1xuICAgIH0pO1xuICAgIC8vIEV4Y2VwdGlvbiBzaG91bGQgc3RpbGwgYmUgdGhyb3duXG4gICAgdGhyb3cgZVxuICB9XG4gIHZhciBwcmV2ID0gdGhpcy5jdXJyZW50O1xuICB0aGlzLmNvbmZpcm1UcmFuc2l0aW9uKFxuICAgIHJvdXRlLFxuICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgIHRoaXMkMS51cGRhdGVSb3V0ZShyb3V0ZSk7XG4gICAgICBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUocm91dGUpO1xuICAgICAgdGhpcyQxLmVuc3VyZVVSTCgpO1xuICAgICAgdGhpcyQxLnJvdXRlci5hZnRlckhvb2tzLmZvckVhY2goZnVuY3Rpb24gKGhvb2spIHtcbiAgICAgICAgaG9vayAmJiBob29rKHJvdXRlLCBwcmV2KTtcbiAgICAgIH0pO1xuXG4gICAgICAvLyBmaXJlIHJlYWR5IGNicyBvbmNlXG4gICAgICBpZiAoIXRoaXMkMS5yZWFkeSkge1xuICAgICAgICB0aGlzJDEucmVhZHkgPSB0cnVlO1xuICAgICAgICB0aGlzJDEucmVhZHlDYnMuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgICAgICBjYihyb3V0ZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0sXG4gICAgZnVuY3Rpb24gKGVycikge1xuICAgICAgaWYgKG9uQWJvcnQpIHtcbiAgICAgICAgb25BYm9ydChlcnIpO1xuICAgICAgfVxuICAgICAgaWYgKGVyciAmJiAhdGhpcyQxLnJlYWR5KSB7XG4gICAgICAgIC8vIEluaXRpYWwgcmVkaXJlY3Rpb24gc2hvdWxkIG5vdCBtYXJrIHRoZSBoaXN0b3J5IGFzIHJlYWR5IHlldFxuICAgICAgICAvLyBiZWNhdXNlIGl0J3MgdHJpZ2dlcmVkIGJ5IHRoZSByZWRpcmVjdGlvbiBpbnN0ZWFkXG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS92dWVqcy92dWUtcm91dGVyL2lzc3Vlcy8zMjI1XG4gICAgICAgIC8vIGh0dHBzOi8vZ2l0aHViLmNvbS92dWVqcy92dWUtcm91dGVyL2lzc3Vlcy8zMzMxXG4gICAgICAgIGlmICghaXNOYXZpZ2F0aW9uRmFpbHVyZShlcnIsIE5hdmlnYXRpb25GYWlsdXJlVHlwZS5yZWRpcmVjdGVkKSB8fCBwcmV2ICE9PSBTVEFSVCkge1xuICAgICAgICAgIHRoaXMkMS5yZWFkeSA9IHRydWU7XG4gICAgICAgICAgdGhpcyQxLnJlYWR5RXJyb3JDYnMuZm9yRWFjaChmdW5jdGlvbiAoY2IpIHtcbiAgICAgICAgICAgIGNiKGVycik7XG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gICk7XG59O1xuXG5IaXN0b3J5LnByb3RvdHlwZS5jb25maXJtVHJhbnNpdGlvbiA9IGZ1bmN0aW9uIGNvbmZpcm1UcmFuc2l0aW9uIChyb3V0ZSwgb25Db21wbGV0ZSwgb25BYm9ydCkge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gIHZhciBjdXJyZW50ID0gdGhpcy5jdXJyZW50O1xuICB0aGlzLnBlbmRpbmcgPSByb3V0ZTtcbiAgdmFyIGFib3J0ID0gZnVuY3Rpb24gKGVycikge1xuICAgIC8vIGNoYW5nZWQgYWZ0ZXIgYWRkaW5nIGVycm9ycyB3aXRoXG4gICAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3Z1ZWpzL3Z1ZS1yb3V0ZXIvcHVsbC8zMDQ3IGJlZm9yZSB0aGF0IGNoYW5nZSxcbiAgICAvLyByZWRpcmVjdCBhbmQgYWJvcnRlZCBuYXZpZ2F0aW9uIHdvdWxkIHByb2R1Y2UgYW4gZXJyID09IG51bGxcbiAgICBpZiAoIWlzTmF2aWdhdGlvbkZhaWx1cmUoZXJyKSAmJiBpc0Vycm9yKGVycikpIHtcbiAgICAgIGlmICh0aGlzJDEuZXJyb3JDYnMubGVuZ3RoKSB7XG4gICAgICAgIHRoaXMkMS5lcnJvckNicy5mb3JFYWNoKGZ1bmN0aW9uIChjYikge1xuICAgICAgICAgIGNiKGVycik7XG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgd2FybihmYWxzZSwgJ3VuY2F1Z2h0IGVycm9yIGR1cmluZyByb3V0ZSBuYXZpZ2F0aW9uOicpO1xuICAgICAgICBjb25zb2xlLmVycm9yKGVycik7XG4gICAgICB9XG4gICAgfVxuICAgIG9uQWJvcnQgJiYgb25BYm9ydChlcnIpO1xuICB9O1xuICB2YXIgbGFzdFJvdXRlSW5kZXggPSByb3V0ZS5tYXRjaGVkLmxlbmd0aCAtIDE7XG4gIHZhciBsYXN0Q3VycmVudEluZGV4ID0gY3VycmVudC5tYXRjaGVkLmxlbmd0aCAtIDE7XG4gIGlmIChcbiAgICBpc1NhbWVSb3V0ZShyb3V0ZSwgY3VycmVudCkgJiZcbiAgICAvLyBpbiB0aGUgY2FzZSB0aGUgcm91dGUgbWFwIGhhcyBiZWVuIGR5bmFtaWNhbGx5IGFwcGVuZGVkIHRvXG4gICAgbGFzdFJvdXRlSW5kZXggPT09IGxhc3RDdXJyZW50SW5kZXggJiZcbiAgICByb3V0ZS5tYXRjaGVkW2xhc3RSb3V0ZUluZGV4XSA9PT0gY3VycmVudC5tYXRjaGVkW2xhc3RDdXJyZW50SW5kZXhdXG4gICkge1xuICAgIHRoaXMuZW5zdXJlVVJMKCk7XG4gICAgcmV0dXJuIGFib3J0KGNyZWF0ZU5hdmlnYXRpb25EdXBsaWNhdGVkRXJyb3IoY3VycmVudCwgcm91dGUpKVxuICB9XG5cbiAgdmFyIHJlZiA9IHJlc29sdmVRdWV1ZShcbiAgICB0aGlzLmN1cnJlbnQubWF0Y2hlZCxcbiAgICByb3V0ZS5tYXRjaGVkXG4gICk7XG4gICAgdmFyIHVwZGF0ZWQgPSByZWYudXBkYXRlZDtcbiAgICB2YXIgZGVhY3RpdmF0ZWQgPSByZWYuZGVhY3RpdmF0ZWQ7XG4gICAgdmFyIGFjdGl2YXRlZCA9IHJlZi5hY3RpdmF0ZWQ7XG5cbiAgdmFyIHF1ZXVlID0gW10uY29uY2F0KFxuICAgIC8vIGluLWNvbXBvbmVudCBsZWF2ZSBndWFyZHNcbiAgICBleHRyYWN0TGVhdmVHdWFyZHMoZGVhY3RpdmF0ZWQpLFxuICAgIC8vIGdsb2JhbCBiZWZvcmUgaG9va3NcbiAgICB0aGlzLnJvdXRlci5iZWZvcmVIb29rcyxcbiAgICAvLyBpbi1jb21wb25lbnQgdXBkYXRlIGhvb2tzXG4gICAgZXh0cmFjdFVwZGF0ZUhvb2tzKHVwZGF0ZWQpLFxuICAgIC8vIGluLWNvbmZpZyBlbnRlciBndWFyZHNcbiAgICBhY3RpdmF0ZWQubWFwKGZ1bmN0aW9uIChtKSB7IHJldHVybiBtLmJlZm9yZUVudGVyOyB9KSxcbiAgICAvLyBhc3luYyBjb21wb25lbnRzXG4gICAgcmVzb2x2ZUFzeW5jQ29tcG9uZW50cyhhY3RpdmF0ZWQpXG4gICk7XG5cbiAgdmFyIGl0ZXJhdG9yID0gZnVuY3Rpb24gKGhvb2ssIG5leHQpIHtcbiAgICBpZiAodGhpcyQxLnBlbmRpbmcgIT09IHJvdXRlKSB7XG4gICAgICByZXR1cm4gYWJvcnQoY3JlYXRlTmF2aWdhdGlvbkNhbmNlbGxlZEVycm9yKGN1cnJlbnQsIHJvdXRlKSlcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGhvb2socm91dGUsIGN1cnJlbnQsIGZ1bmN0aW9uICh0bykge1xuICAgICAgICBpZiAodG8gPT09IGZhbHNlKSB7XG4gICAgICAgICAgLy8gbmV4dChmYWxzZSkgLT4gYWJvcnQgbmF2aWdhdGlvbiwgZW5zdXJlIGN1cnJlbnQgVVJMXG4gICAgICAgICAgdGhpcyQxLmVuc3VyZVVSTCh0cnVlKTtcbiAgICAgICAgICBhYm9ydChjcmVhdGVOYXZpZ2F0aW9uQWJvcnRlZEVycm9yKGN1cnJlbnQsIHJvdXRlKSk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNFcnJvcih0bykpIHtcbiAgICAgICAgICB0aGlzJDEuZW5zdXJlVVJMKHRydWUpO1xuICAgICAgICAgIGFib3J0KHRvKTtcbiAgICAgICAgfSBlbHNlIGlmIChcbiAgICAgICAgICB0eXBlb2YgdG8gPT09ICdzdHJpbmcnIHx8XG4gICAgICAgICAgKHR5cGVvZiB0byA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgICAgICh0eXBlb2YgdG8ucGF0aCA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHRvLm5hbWUgPT09ICdzdHJpbmcnKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgLy8gbmV4dCgnLycpIG9yIG5leHQoeyBwYXRoOiAnLycgfSkgLT4gcmVkaXJlY3RcbiAgICAgICAgICBhYm9ydChjcmVhdGVOYXZpZ2F0aW9uUmVkaXJlY3RlZEVycm9yKGN1cnJlbnQsIHJvdXRlKSk7XG4gICAgICAgICAgaWYgKHR5cGVvZiB0byA9PT0gJ29iamVjdCcgJiYgdG8ucmVwbGFjZSkge1xuICAgICAgICAgICAgdGhpcyQxLnJlcGxhY2UodG8pO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzJDEucHVzaCh0byk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIC8vIGNvbmZpcm0gdHJhbnNpdGlvbiBhbmQgcGFzcyBvbiB0aGUgdmFsdWVcbiAgICAgICAgICBuZXh0KHRvKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgYWJvcnQoZSk7XG4gICAgfVxuICB9O1xuXG4gIHJ1blF1ZXVlKHF1ZXVlLCBpdGVyYXRvciwgZnVuY3Rpb24gKCkge1xuICAgIC8vIHdhaXQgdW50aWwgYXN5bmMgY29tcG9uZW50cyBhcmUgcmVzb2x2ZWQgYmVmb3JlXG4gICAgLy8gZXh0cmFjdGluZyBpbi1jb21wb25lbnQgZW50ZXIgZ3VhcmRzXG4gICAgdmFyIGVudGVyR3VhcmRzID0gZXh0cmFjdEVudGVyR3VhcmRzKGFjdGl2YXRlZCk7XG4gICAgdmFyIHF1ZXVlID0gZW50ZXJHdWFyZHMuY29uY2F0KHRoaXMkMS5yb3V0ZXIucmVzb2x2ZUhvb2tzKTtcbiAgICBydW5RdWV1ZShxdWV1ZSwgaXRlcmF0b3IsIGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmICh0aGlzJDEucGVuZGluZyAhPT0gcm91dGUpIHtcbiAgICAgICAgcmV0dXJuIGFib3J0KGNyZWF0ZU5hdmlnYXRpb25DYW5jZWxsZWRFcnJvcihjdXJyZW50LCByb3V0ZSkpXG4gICAgICB9XG4gICAgICB0aGlzJDEucGVuZGluZyA9IG51bGw7XG4gICAgICBvbkNvbXBsZXRlKHJvdXRlKTtcbiAgICAgIGlmICh0aGlzJDEucm91dGVyLmFwcCkge1xuICAgICAgICB0aGlzJDEucm91dGVyLmFwcC4kbmV4dFRpY2soZnVuY3Rpb24gKCkge1xuICAgICAgICAgIGhhbmRsZVJvdXRlRW50ZXJlZChyb3V0ZSk7XG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0pO1xuICB9KTtcbn07XG5cbkhpc3RvcnkucHJvdG90eXBlLnVwZGF0ZVJvdXRlID0gZnVuY3Rpb24gdXBkYXRlUm91dGUgKHJvdXRlKSB7XG4gIHRoaXMuY3VycmVudCA9IHJvdXRlO1xuICB0aGlzLmNiICYmIHRoaXMuY2Iocm91dGUpO1xufTtcblxuSGlzdG9yeS5wcm90b3R5cGUuc2V0dXBMaXN0ZW5lcnMgPSBmdW5jdGlvbiBzZXR1cExpc3RlbmVycyAoKSB7XG4gIC8vIERlZmF1bHQgaW1wbGVtZW50YXRpb24gaXMgZW1wdHlcbn07XG5cbkhpc3RvcnkucHJvdG90eXBlLnRlYXJkb3duID0gZnVuY3Rpb24gdGVhcmRvd24gKCkge1xuICAvLyBjbGVhbiB1cCBldmVudCBsaXN0ZW5lcnNcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3Z1ZWpzL3Z1ZS1yb3V0ZXIvaXNzdWVzLzIzNDFcbiAgdGhpcy5saXN0ZW5lcnMuZm9yRWFjaChmdW5jdGlvbiAoY2xlYW51cExpc3RlbmVyKSB7XG4gICAgY2xlYW51cExpc3RlbmVyKCk7XG4gIH0pO1xuICB0aGlzLmxpc3RlbmVycyA9IFtdO1xuXG4gIC8vIHJlc2V0IGN1cnJlbnQgaGlzdG9yeSByb3V0ZVxuICAvLyBodHRwczovL2dpdGh1Yi5jb20vdnVlanMvdnVlLXJvdXRlci9pc3N1ZXMvMzI5NFxuICB0aGlzLmN1cnJlbnQgPSBTVEFSVDtcbiAgdGhpcy5wZW5kaW5nID0gbnVsbDtcbn07XG5cbmZ1bmN0aW9uIG5vcm1hbGl6ZUJhc2UgKGJhc2UpIHtcbiAgaWYgKCFiYXNlKSB7XG4gICAgaWYgKGluQnJvd3Nlcikge1xuICAgICAgLy8gcmVzcGVjdCA8YmFzZT4gdGFnXG4gICAgICB2YXIgYmFzZUVsID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignYmFzZScpO1xuICAgICAgYmFzZSA9IChiYXNlRWwgJiYgYmFzZUVsLmdldEF0dHJpYnV0ZSgnaHJlZicpKSB8fCAnLyc7XG4gICAgICAvLyBzdHJpcCBmdWxsIFVSTCBvcmlnaW5cbiAgICAgIGJhc2UgPSBiYXNlLnJlcGxhY2UoL15odHRwcz86XFwvXFwvW15cXC9dKy8sICcnKTtcbiAgICB9IGVsc2Uge1xuICAgICAgYmFzZSA9ICcvJztcbiAgICB9XG4gIH1cbiAgLy8gbWFrZSBzdXJlIHRoZXJlJ3MgdGhlIHN0YXJ0aW5nIHNsYXNoXG4gIGlmIChiYXNlLmNoYXJBdCgwKSAhPT0gJy8nKSB7XG4gICAgYmFzZSA9ICcvJyArIGJhc2U7XG4gIH1cbiAgLy8gcmVtb3ZlIHRyYWlsaW5nIHNsYXNoXG4gIHJldHVybiBiYXNlLnJlcGxhY2UoL1xcLyQvLCAnJylcbn1cblxuZnVuY3Rpb24gcmVzb2x2ZVF1ZXVlIChcbiAgY3VycmVudCxcbiAgbmV4dFxuKSB7XG4gIHZhciBpO1xuICB2YXIgbWF4ID0gTWF0aC5tYXgoY3VycmVudC5sZW5ndGgsIG5leHQubGVuZ3RoKTtcbiAgZm9yIChpID0gMDsgaSA8IG1heDsgaSsrKSB7XG4gICAgaWYgKGN1cnJlbnRbaV0gIT09IG5leHRbaV0pIHtcbiAgICAgIGJyZWFrXG4gICAgfVxuICB9XG4gIHJldHVybiB7XG4gICAgdXBkYXRlZDogbmV4dC5zbGljZSgwLCBpKSxcbiAgICBhY3RpdmF0ZWQ6IG5leHQuc2xpY2UoaSksXG4gICAgZGVhY3RpdmF0ZWQ6IGN1cnJlbnQuc2xpY2UoaSlcbiAgfVxufVxuXG5mdW5jdGlvbiBleHRyYWN0R3VhcmRzIChcbiAgcmVjb3JkcyxcbiAgbmFtZSxcbiAgYmluZCxcbiAgcmV2ZXJzZVxuKSB7XG4gIHZhciBndWFyZHMgPSBmbGF0TWFwQ29tcG9uZW50cyhyZWNvcmRzLCBmdW5jdGlvbiAoZGVmLCBpbnN0YW5jZSwgbWF0Y2gsIGtleSkge1xuICAgIHZhciBndWFyZCA9IGV4dHJhY3RHdWFyZChkZWYsIG5hbWUpO1xuICAgIGlmIChndWFyZCkge1xuICAgICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoZ3VhcmQpXG4gICAgICAgID8gZ3VhcmQubWFwKGZ1bmN0aW9uIChndWFyZCkgeyByZXR1cm4gYmluZChndWFyZCwgaW5zdGFuY2UsIG1hdGNoLCBrZXkpOyB9KVxuICAgICAgICA6IGJpbmQoZ3VhcmQsIGluc3RhbmNlLCBtYXRjaCwga2V5KVxuICAgIH1cbiAgfSk7XG4gIHJldHVybiBmbGF0dGVuKHJldmVyc2UgPyBndWFyZHMucmV2ZXJzZSgpIDogZ3VhcmRzKVxufVxuXG5mdW5jdGlvbiBleHRyYWN0R3VhcmQgKFxuICBkZWYsXG4gIGtleVxuKSB7XG4gIGlmICh0eXBlb2YgZGVmICE9PSAnZnVuY3Rpb24nKSB7XG4gICAgLy8gZXh0ZW5kIG5vdyBzbyB0aGF0IGdsb2JhbCBtaXhpbnMgYXJlIGFwcGxpZWQuXG4gICAgZGVmID0gX1Z1ZS5leHRlbmQoZGVmKTtcbiAgfVxuICByZXR1cm4gZGVmLm9wdGlvbnNba2V5XVxufVxuXG5mdW5jdGlvbiBleHRyYWN0TGVhdmVHdWFyZHMgKGRlYWN0aXZhdGVkKSB7XG4gIHJldHVybiBleHRyYWN0R3VhcmRzKGRlYWN0aXZhdGVkLCAnYmVmb3JlUm91dGVMZWF2ZScsIGJpbmRHdWFyZCwgdHJ1ZSlcbn1cblxuZnVuY3Rpb24gZXh0cmFjdFVwZGF0ZUhvb2tzICh1cGRhdGVkKSB7XG4gIHJldHVybiBleHRyYWN0R3VhcmRzKHVwZGF0ZWQsICdiZWZvcmVSb3V0ZVVwZGF0ZScsIGJpbmRHdWFyZClcbn1cblxuZnVuY3Rpb24gYmluZEd1YXJkIChndWFyZCwgaW5zdGFuY2UpIHtcbiAgaWYgKGluc3RhbmNlKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIGJvdW5kUm91dGVHdWFyZCAoKSB7XG4gICAgICByZXR1cm4gZ3VhcmQuYXBwbHkoaW5zdGFuY2UsIGFyZ3VtZW50cylcbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gZXh0cmFjdEVudGVyR3VhcmRzIChcbiAgYWN0aXZhdGVkXG4pIHtcbiAgcmV0dXJuIGV4dHJhY3RHdWFyZHMoXG4gICAgYWN0aXZhdGVkLFxuICAgICdiZWZvcmVSb3V0ZUVudGVyJyxcbiAgICBmdW5jdGlvbiAoZ3VhcmQsIF8sIG1hdGNoLCBrZXkpIHtcbiAgICAgIHJldHVybiBiaW5kRW50ZXJHdWFyZChndWFyZCwgbWF0Y2gsIGtleSlcbiAgICB9XG4gIClcbn1cblxuZnVuY3Rpb24gYmluZEVudGVyR3VhcmQgKFxuICBndWFyZCxcbiAgbWF0Y2gsXG4gIGtleVxuKSB7XG4gIHJldHVybiBmdW5jdGlvbiByb3V0ZUVudGVyR3VhcmQgKHRvLCBmcm9tLCBuZXh0KSB7XG4gICAgcmV0dXJuIGd1YXJkKHRvLCBmcm9tLCBmdW5jdGlvbiAoY2IpIHtcbiAgICAgIGlmICh0eXBlb2YgY2IgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgaWYgKCFtYXRjaC5lbnRlcmVkQ2JzW2tleV0pIHtcbiAgICAgICAgICBtYXRjaC5lbnRlcmVkQ2JzW2tleV0gPSBbXTtcbiAgICAgICAgfVxuICAgICAgICBtYXRjaC5lbnRlcmVkQ2JzW2tleV0ucHVzaChjYik7XG4gICAgICB9XG4gICAgICBuZXh0KGNiKTtcbiAgICB9KVxuICB9XG59XG5cbi8qICAqL1xuXG52YXIgSFRNTDVIaXN0b3J5ID0gLypAX19QVVJFX18qLyhmdW5jdGlvbiAoSGlzdG9yeSkge1xuICBmdW5jdGlvbiBIVE1MNUhpc3RvcnkgKHJvdXRlciwgYmFzZSkge1xuICAgIEhpc3RvcnkuY2FsbCh0aGlzLCByb3V0ZXIsIGJhc2UpO1xuXG4gICAgdGhpcy5fc3RhcnRMb2NhdGlvbiA9IGdldExvY2F0aW9uKHRoaXMuYmFzZSk7XG4gIH1cblxuICBpZiAoIEhpc3RvcnkgKSBIVE1MNUhpc3RvcnkuX19wcm90b19fID0gSGlzdG9yeTtcbiAgSFRNTDVIaXN0b3J5LnByb3RvdHlwZSA9IE9iamVjdC5jcmVhdGUoIEhpc3RvcnkgJiYgSGlzdG9yeS5wcm90b3R5cGUgKTtcbiAgSFRNTDVIaXN0b3J5LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEhUTUw1SGlzdG9yeTtcblxuICBIVE1MNUhpc3RvcnkucHJvdG90eXBlLnNldHVwTGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0dXBMaXN0ZW5lcnMgKCkge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgaWYgKHRoaXMubGlzdGVuZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHZhciByb3V0ZXIgPSB0aGlzLnJvdXRlcjtcbiAgICB2YXIgZXhwZWN0U2Nyb2xsID0gcm91dGVyLm9wdGlvbnMuc2Nyb2xsQmVoYXZpb3I7XG4gICAgdmFyIHN1cHBvcnRzU2Nyb2xsID0gc3VwcG9ydHNQdXNoU3RhdGUgJiYgZXhwZWN0U2Nyb2xsO1xuXG4gICAgaWYgKHN1cHBvcnRzU2Nyb2xsKSB7XG4gICAgICB0aGlzLmxpc3RlbmVycy5wdXNoKHNldHVwU2Nyb2xsKCkpO1xuICAgIH1cblxuICAgIHZhciBoYW5kbGVSb3V0aW5nRXZlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgY3VycmVudCA9IHRoaXMkMS5jdXJyZW50O1xuXG4gICAgICAvLyBBdm9pZGluZyBmaXJzdCBgcG9wc3RhdGVgIGV2ZW50IGRpc3BhdGNoZWQgaW4gc29tZSBicm93c2VycyBidXQgZmlyc3RcbiAgICAgIC8vIGhpc3Rvcnkgcm91dGUgbm90IHVwZGF0ZWQgc2luY2UgYXN5bmMgZ3VhcmQgYXQgdGhlIHNhbWUgdGltZS5cbiAgICAgIHZhciBsb2NhdGlvbiA9IGdldExvY2F0aW9uKHRoaXMkMS5iYXNlKTtcbiAgICAgIGlmICh0aGlzJDEuY3VycmVudCA9PT0gU1RBUlQgJiYgbG9jYXRpb24gPT09IHRoaXMkMS5fc3RhcnRMb2NhdGlvbikge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgdGhpcyQxLnRyYW5zaXRpb25Ubyhsb2NhdGlvbiwgZnVuY3Rpb24gKHJvdXRlKSB7XG4gICAgICAgIGlmIChzdXBwb3J0c1Njcm9sbCkge1xuICAgICAgICAgIGhhbmRsZVNjcm9sbChyb3V0ZXIsIHJvdXRlLCBjdXJyZW50LCB0cnVlKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigncG9wc3RhdGUnLCBoYW5kbGVSb3V0aW5nRXZlbnQpO1xuICAgIHRoaXMubGlzdGVuZXJzLnB1c2goZnVuY3Rpb24gKCkge1xuICAgICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3BvcHN0YXRlJywgaGFuZGxlUm91dGluZ0V2ZW50KTtcbiAgICB9KTtcbiAgfTtcblxuICBIVE1MNUhpc3RvcnkucHJvdG90eXBlLmdvID0gZnVuY3Rpb24gZ28gKG4pIHtcbiAgICB3aW5kb3cuaGlzdG9yeS5nbyhuKTtcbiAgfTtcblxuICBIVE1MNUhpc3RvcnkucHJvdG90eXBlLnB1c2ggPSBmdW5jdGlvbiBwdXNoIChsb2NhdGlvbiwgb25Db21wbGV0ZSwgb25BYm9ydCkge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgdmFyIHJlZiA9IHRoaXM7XG4gICAgdmFyIGZyb21Sb3V0ZSA9IHJlZi5jdXJyZW50O1xuICAgIHRoaXMudHJhbnNpdGlvblRvKGxvY2F0aW9uLCBmdW5jdGlvbiAocm91dGUpIHtcbiAgICAgIHB1c2hTdGF0ZShjbGVhblBhdGgodGhpcyQxLmJhc2UgKyByb3V0ZS5mdWxsUGF0aCkpO1xuICAgICAgaGFuZGxlU2Nyb2xsKHRoaXMkMS5yb3V0ZXIsIHJvdXRlLCBmcm9tUm91dGUsIGZhbHNlKTtcbiAgICAgIG9uQ29tcGxldGUgJiYgb25Db21wbGV0ZShyb3V0ZSk7XG4gICAgfSwgb25BYm9ydCk7XG4gIH07XG5cbiAgSFRNTDVIaXN0b3J5LnByb3RvdHlwZS5yZXBsYWNlID0gZnVuY3Rpb24gcmVwbGFjZSAobG9jYXRpb24sIG9uQ29tcGxldGUsIG9uQWJvcnQpIHtcbiAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIHZhciByZWYgPSB0aGlzO1xuICAgIHZhciBmcm9tUm91dGUgPSByZWYuY3VycmVudDtcbiAgICB0aGlzLnRyYW5zaXRpb25Ubyhsb2NhdGlvbiwgZnVuY3Rpb24gKHJvdXRlKSB7XG4gICAgICByZXBsYWNlU3RhdGUoY2xlYW5QYXRoKHRoaXMkMS5iYXNlICsgcm91dGUuZnVsbFBhdGgpKTtcbiAgICAgIGhhbmRsZVNjcm9sbCh0aGlzJDEucm91dGVyLCByb3V0ZSwgZnJvbVJvdXRlLCBmYWxzZSk7XG4gICAgICBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUocm91dGUpO1xuICAgIH0sIG9uQWJvcnQpO1xuICB9O1xuXG4gIEhUTUw1SGlzdG9yeS5wcm90b3R5cGUuZW5zdXJlVVJMID0gZnVuY3Rpb24gZW5zdXJlVVJMIChwdXNoKSB7XG4gICAgaWYgKGdldExvY2F0aW9uKHRoaXMuYmFzZSkgIT09IHRoaXMuY3VycmVudC5mdWxsUGF0aCkge1xuICAgICAgdmFyIGN1cnJlbnQgPSBjbGVhblBhdGgodGhpcy5iYXNlICsgdGhpcy5jdXJyZW50LmZ1bGxQYXRoKTtcbiAgICAgIHB1c2ggPyBwdXNoU3RhdGUoY3VycmVudCkgOiByZXBsYWNlU3RhdGUoY3VycmVudCk7XG4gICAgfVxuICB9O1xuXG4gIEhUTUw1SGlzdG9yeS5wcm90b3R5cGUuZ2V0Q3VycmVudExvY2F0aW9uID0gZnVuY3Rpb24gZ2V0Q3VycmVudExvY2F0aW9uICgpIHtcbiAgICByZXR1cm4gZ2V0TG9jYXRpb24odGhpcy5iYXNlKVxuICB9O1xuXG4gIHJldHVybiBIVE1MNUhpc3Rvcnk7XG59KEhpc3RvcnkpKTtcblxuZnVuY3Rpb24gZ2V0TG9jYXRpb24gKGJhc2UpIHtcbiAgdmFyIHBhdGggPSB3aW5kb3cubG9jYXRpb24ucGF0aG5hbWU7XG4gIGlmIChiYXNlICYmIHBhdGgudG9Mb3dlckNhc2UoKS5pbmRleE9mKGJhc2UudG9Mb3dlckNhc2UoKSkgPT09IDApIHtcbiAgICBwYXRoID0gcGF0aC5zbGljZShiYXNlLmxlbmd0aCk7XG4gIH1cbiAgcmV0dXJuIChwYXRoIHx8ICcvJykgKyB3aW5kb3cubG9jYXRpb24uc2VhcmNoICsgd2luZG93LmxvY2F0aW9uLmhhc2hcbn1cblxuLyogICovXG5cbnZhciBIYXNoSGlzdG9yeSA9IC8qQF9fUFVSRV9fKi8oZnVuY3Rpb24gKEhpc3RvcnkpIHtcbiAgZnVuY3Rpb24gSGFzaEhpc3RvcnkgKHJvdXRlciwgYmFzZSwgZmFsbGJhY2spIHtcbiAgICBIaXN0b3J5LmNhbGwodGhpcywgcm91dGVyLCBiYXNlKTtcbiAgICAvLyBjaGVjayBoaXN0b3J5IGZhbGxiYWNrIGRlZXBsaW5raW5nXG4gICAgaWYgKGZhbGxiYWNrICYmIGNoZWNrRmFsbGJhY2sodGhpcy5iYXNlKSkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIGVuc3VyZVNsYXNoKCk7XG4gIH1cblxuICBpZiAoIEhpc3RvcnkgKSBIYXNoSGlzdG9yeS5fX3Byb3RvX18gPSBIaXN0b3J5O1xuICBIYXNoSGlzdG9yeS5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKCBIaXN0b3J5ICYmIEhpc3RvcnkucHJvdG90eXBlICk7XG4gIEhhc2hIaXN0b3J5LnByb3RvdHlwZS5jb25zdHJ1Y3RvciA9IEhhc2hIaXN0b3J5O1xuXG4gIC8vIHRoaXMgaXMgZGVsYXllZCB1bnRpbCB0aGUgYXBwIG1vdW50c1xuICAvLyB0byBhdm9pZCB0aGUgaGFzaGNoYW5nZSBsaXN0ZW5lciBiZWluZyBmaXJlZCB0b28gZWFybHlcbiAgSGFzaEhpc3RvcnkucHJvdG90eXBlLnNldHVwTGlzdGVuZXJzID0gZnVuY3Rpb24gc2V0dXBMaXN0ZW5lcnMgKCkge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgaWYgKHRoaXMubGlzdGVuZXJzLmxlbmd0aCA+IDApIHtcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIHZhciByb3V0ZXIgPSB0aGlzLnJvdXRlcjtcbiAgICB2YXIgZXhwZWN0U2Nyb2xsID0gcm91dGVyLm9wdGlvbnMuc2Nyb2xsQmVoYXZpb3I7XG4gICAgdmFyIHN1cHBvcnRzU2Nyb2xsID0gc3VwcG9ydHNQdXNoU3RhdGUgJiYgZXhwZWN0U2Nyb2xsO1xuXG4gICAgaWYgKHN1cHBvcnRzU2Nyb2xsKSB7XG4gICAgICB0aGlzLmxpc3RlbmVycy5wdXNoKHNldHVwU2Nyb2xsKCkpO1xuICAgIH1cblxuICAgIHZhciBoYW5kbGVSb3V0aW5nRXZlbnQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgY3VycmVudCA9IHRoaXMkMS5jdXJyZW50O1xuICAgICAgaWYgKCFlbnN1cmVTbGFzaCgpKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgdGhpcyQxLnRyYW5zaXRpb25UbyhnZXRIYXNoKCksIGZ1bmN0aW9uIChyb3V0ZSkge1xuICAgICAgICBpZiAoc3VwcG9ydHNTY3JvbGwpIHtcbiAgICAgICAgICBoYW5kbGVTY3JvbGwodGhpcyQxLnJvdXRlciwgcm91dGUsIGN1cnJlbnQsIHRydWUpO1xuICAgICAgICB9XG4gICAgICAgIGlmICghc3VwcG9ydHNQdXNoU3RhdGUpIHtcbiAgICAgICAgICByZXBsYWNlSGFzaChyb3V0ZS5mdWxsUGF0aCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH07XG4gICAgdmFyIGV2ZW50VHlwZSA9IHN1cHBvcnRzUHVzaFN0YXRlID8gJ3BvcHN0YXRlJyA6ICdoYXNoY2hhbmdlJztcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihcbiAgICAgIGV2ZW50VHlwZSxcbiAgICAgIGhhbmRsZVJvdXRpbmdFdmVudFxuICAgICk7XG4gICAgdGhpcy5saXN0ZW5lcnMucHVzaChmdW5jdGlvbiAoKSB7XG4gICAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcihldmVudFR5cGUsIGhhbmRsZVJvdXRpbmdFdmVudCk7XG4gICAgfSk7XG4gIH07XG5cbiAgSGFzaEhpc3RvcnkucHJvdG90eXBlLnB1c2ggPSBmdW5jdGlvbiBwdXNoIChsb2NhdGlvbiwgb25Db21wbGV0ZSwgb25BYm9ydCkge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgdmFyIHJlZiA9IHRoaXM7XG4gICAgdmFyIGZyb21Sb3V0ZSA9IHJlZi5jdXJyZW50O1xuICAgIHRoaXMudHJhbnNpdGlvblRvKFxuICAgICAgbG9jYXRpb24sXG4gICAgICBmdW5jdGlvbiAocm91dGUpIHtcbiAgICAgICAgcHVzaEhhc2gocm91dGUuZnVsbFBhdGgpO1xuICAgICAgICBoYW5kbGVTY3JvbGwodGhpcyQxLnJvdXRlciwgcm91dGUsIGZyb21Sb3V0ZSwgZmFsc2UpO1xuICAgICAgICBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUocm91dGUpO1xuICAgICAgfSxcbiAgICAgIG9uQWJvcnRcbiAgICApO1xuICB9O1xuXG4gIEhhc2hIaXN0b3J5LnByb3RvdHlwZS5yZXBsYWNlID0gZnVuY3Rpb24gcmVwbGFjZSAobG9jYXRpb24sIG9uQ29tcGxldGUsIG9uQWJvcnQpIHtcbiAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAgIHZhciByZWYgPSB0aGlzO1xuICAgIHZhciBmcm9tUm91dGUgPSByZWYuY3VycmVudDtcbiAgICB0aGlzLnRyYW5zaXRpb25UbyhcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgZnVuY3Rpb24gKHJvdXRlKSB7XG4gICAgICAgIHJlcGxhY2VIYXNoKHJvdXRlLmZ1bGxQYXRoKTtcbiAgICAgICAgaGFuZGxlU2Nyb2xsKHRoaXMkMS5yb3V0ZXIsIHJvdXRlLCBmcm9tUm91dGUsIGZhbHNlKTtcbiAgICAgICAgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKHJvdXRlKTtcbiAgICAgIH0sXG4gICAgICBvbkFib3J0XG4gICAgKTtcbiAgfTtcblxuICBIYXNoSGlzdG9yeS5wcm90b3R5cGUuZ28gPSBmdW5jdGlvbiBnbyAobikge1xuICAgIHdpbmRvdy5oaXN0b3J5LmdvKG4pO1xuICB9O1xuXG4gIEhhc2hIaXN0b3J5LnByb3RvdHlwZS5lbnN1cmVVUkwgPSBmdW5jdGlvbiBlbnN1cmVVUkwgKHB1c2gpIHtcbiAgICB2YXIgY3VycmVudCA9IHRoaXMuY3VycmVudC5mdWxsUGF0aDtcbiAgICBpZiAoZ2V0SGFzaCgpICE9PSBjdXJyZW50KSB7XG4gICAgICBwdXNoID8gcHVzaEhhc2goY3VycmVudCkgOiByZXBsYWNlSGFzaChjdXJyZW50KTtcbiAgICB9XG4gIH07XG5cbiAgSGFzaEhpc3RvcnkucHJvdG90eXBlLmdldEN1cnJlbnRMb2NhdGlvbiA9IGZ1bmN0aW9uIGdldEN1cnJlbnRMb2NhdGlvbiAoKSB7XG4gICAgcmV0dXJuIGdldEhhc2goKVxuICB9O1xuXG4gIHJldHVybiBIYXNoSGlzdG9yeTtcbn0oSGlzdG9yeSkpO1xuXG5mdW5jdGlvbiBjaGVja0ZhbGxiYWNrIChiYXNlKSB7XG4gIHZhciBsb2NhdGlvbiA9IGdldExvY2F0aW9uKGJhc2UpO1xuICBpZiAoIS9eXFwvIy8udGVzdChsb2NhdGlvbikpIHtcbiAgICB3aW5kb3cubG9jYXRpb24ucmVwbGFjZShjbGVhblBhdGgoYmFzZSArICcvIycgKyBsb2NhdGlvbikpO1xuICAgIHJldHVybiB0cnVlXG4gIH1cbn1cblxuZnVuY3Rpb24gZW5zdXJlU2xhc2ggKCkge1xuICB2YXIgcGF0aCA9IGdldEhhc2goKTtcbiAgaWYgKHBhdGguY2hhckF0KDApID09PSAnLycpIHtcbiAgICByZXR1cm4gdHJ1ZVxuICB9XG4gIHJlcGxhY2VIYXNoKCcvJyArIHBhdGgpO1xuICByZXR1cm4gZmFsc2Vcbn1cblxuZnVuY3Rpb24gZ2V0SGFzaCAoKSB7XG4gIC8vIFdlIGNhbid0IHVzZSB3aW5kb3cubG9jYXRpb24uaGFzaCBoZXJlIGJlY2F1c2UgaXQncyBub3RcbiAgLy8gY29uc2lzdGVudCBhY3Jvc3MgYnJvd3NlcnMgLSBGaXJlZm94IHdpbGwgcHJlLWRlY29kZSBpdCFcbiAgdmFyIGhyZWYgPSB3aW5kb3cubG9jYXRpb24uaHJlZjtcbiAgdmFyIGluZGV4ID0gaHJlZi5pbmRleE9mKCcjJyk7XG4gIC8vIGVtcHR5IHBhdGhcbiAgaWYgKGluZGV4IDwgMCkgeyByZXR1cm4gJycgfVxuXG4gIGhyZWYgPSBocmVmLnNsaWNlKGluZGV4ICsgMSk7XG5cbiAgcmV0dXJuIGhyZWZcbn1cblxuZnVuY3Rpb24gZ2V0VXJsIChwYXRoKSB7XG4gIHZhciBocmVmID0gd2luZG93LmxvY2F0aW9uLmhyZWY7XG4gIHZhciBpID0gaHJlZi5pbmRleE9mKCcjJyk7XG4gIHZhciBiYXNlID0gaSA+PSAwID8gaHJlZi5zbGljZSgwLCBpKSA6IGhyZWY7XG4gIHJldHVybiAoYmFzZSArIFwiI1wiICsgcGF0aClcbn1cblxuZnVuY3Rpb24gcHVzaEhhc2ggKHBhdGgpIHtcbiAgaWYgKHN1cHBvcnRzUHVzaFN0YXRlKSB7XG4gICAgcHVzaFN0YXRlKGdldFVybChwYXRoKSk7XG4gIH0gZWxzZSB7XG4gICAgd2luZG93LmxvY2F0aW9uLmhhc2ggPSBwYXRoO1xuICB9XG59XG5cbmZ1bmN0aW9uIHJlcGxhY2VIYXNoIChwYXRoKSB7XG4gIGlmIChzdXBwb3J0c1B1c2hTdGF0ZSkge1xuICAgIHJlcGxhY2VTdGF0ZShnZXRVcmwocGF0aCkpO1xuICB9IGVsc2Uge1xuICAgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKGdldFVybChwYXRoKSk7XG4gIH1cbn1cblxuLyogICovXG5cbnZhciBBYnN0cmFjdEhpc3RvcnkgPSAvKkBfX1BVUkVfXyovKGZ1bmN0aW9uIChIaXN0b3J5KSB7XG4gIGZ1bmN0aW9uIEFic3RyYWN0SGlzdG9yeSAocm91dGVyLCBiYXNlKSB7XG4gICAgSGlzdG9yeS5jYWxsKHRoaXMsIHJvdXRlciwgYmFzZSk7XG4gICAgdGhpcy5zdGFjayA9IFtdO1xuICAgIHRoaXMuaW5kZXggPSAtMTtcbiAgfVxuXG4gIGlmICggSGlzdG9yeSApIEFic3RyYWN0SGlzdG9yeS5fX3Byb3RvX18gPSBIaXN0b3J5O1xuICBBYnN0cmFjdEhpc3RvcnkucHJvdG90eXBlID0gT2JqZWN0LmNyZWF0ZSggSGlzdG9yeSAmJiBIaXN0b3J5LnByb3RvdHlwZSApO1xuICBBYnN0cmFjdEhpc3RvcnkucHJvdG90eXBlLmNvbnN0cnVjdG9yID0gQWJzdHJhY3RIaXN0b3J5O1xuXG4gIEFic3RyYWN0SGlzdG9yeS5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uIHB1c2ggKGxvY2F0aW9uLCBvbkNvbXBsZXRlLCBvbkFib3J0KSB7XG4gICAgdmFyIHRoaXMkMSA9IHRoaXM7XG5cbiAgICB0aGlzLnRyYW5zaXRpb25UbyhcbiAgICAgIGxvY2F0aW9uLFxuICAgICAgZnVuY3Rpb24gKHJvdXRlKSB7XG4gICAgICAgIHRoaXMkMS5zdGFjayA9IHRoaXMkMS5zdGFjay5zbGljZSgwLCB0aGlzJDEuaW5kZXggKyAxKS5jb25jYXQocm91dGUpO1xuICAgICAgICB0aGlzJDEuaW5kZXgrKztcbiAgICAgICAgb25Db21wbGV0ZSAmJiBvbkNvbXBsZXRlKHJvdXRlKTtcbiAgICAgIH0sXG4gICAgICBvbkFib3J0XG4gICAgKTtcbiAgfTtcblxuICBBYnN0cmFjdEhpc3RvcnkucHJvdG90eXBlLnJlcGxhY2UgPSBmdW5jdGlvbiByZXBsYWNlIChsb2NhdGlvbiwgb25Db21wbGV0ZSwgb25BYm9ydCkge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgdGhpcy50cmFuc2l0aW9uVG8oXG4gICAgICBsb2NhdGlvbixcbiAgICAgIGZ1bmN0aW9uIChyb3V0ZSkge1xuICAgICAgICB0aGlzJDEuc3RhY2sgPSB0aGlzJDEuc3RhY2suc2xpY2UoMCwgdGhpcyQxLmluZGV4KS5jb25jYXQocm91dGUpO1xuICAgICAgICBvbkNvbXBsZXRlICYmIG9uQ29tcGxldGUocm91dGUpO1xuICAgICAgfSxcbiAgICAgIG9uQWJvcnRcbiAgICApO1xuICB9O1xuXG4gIEFic3RyYWN0SGlzdG9yeS5wcm90b3R5cGUuZ28gPSBmdW5jdGlvbiBnbyAobikge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gICAgdmFyIHRhcmdldEluZGV4ID0gdGhpcy5pbmRleCArIG47XG4gICAgaWYgKHRhcmdldEluZGV4IDwgMCB8fCB0YXJnZXRJbmRleCA+PSB0aGlzLnN0YWNrLmxlbmd0aCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuICAgIHZhciByb3V0ZSA9IHRoaXMuc3RhY2tbdGFyZ2V0SW5kZXhdO1xuICAgIHRoaXMuY29uZmlybVRyYW5zaXRpb24oXG4gICAgICByb3V0ZSxcbiAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgdmFyIHByZXYgPSB0aGlzJDEuY3VycmVudDtcbiAgICAgICAgdGhpcyQxLmluZGV4ID0gdGFyZ2V0SW5kZXg7XG4gICAgICAgIHRoaXMkMS51cGRhdGVSb3V0ZShyb3V0ZSk7XG4gICAgICAgIHRoaXMkMS5yb3V0ZXIuYWZ0ZXJIb29rcy5mb3JFYWNoKGZ1bmN0aW9uIChob29rKSB7XG4gICAgICAgICAgaG9vayAmJiBob29rKHJvdXRlLCBwcmV2KTtcbiAgICAgICAgfSk7XG4gICAgICB9LFxuICAgICAgZnVuY3Rpb24gKGVycikge1xuICAgICAgICBpZiAoaXNOYXZpZ2F0aW9uRmFpbHVyZShlcnIsIE5hdmlnYXRpb25GYWlsdXJlVHlwZS5kdXBsaWNhdGVkKSkge1xuICAgICAgICAgIHRoaXMkMS5pbmRleCA9IHRhcmdldEluZGV4O1xuICAgICAgICB9XG4gICAgICB9XG4gICAgKTtcbiAgfTtcblxuICBBYnN0cmFjdEhpc3RvcnkucHJvdG90eXBlLmdldEN1cnJlbnRMb2NhdGlvbiA9IGZ1bmN0aW9uIGdldEN1cnJlbnRMb2NhdGlvbiAoKSB7XG4gICAgdmFyIGN1cnJlbnQgPSB0aGlzLnN0YWNrW3RoaXMuc3RhY2subGVuZ3RoIC0gMV07XG4gICAgcmV0dXJuIGN1cnJlbnQgPyBjdXJyZW50LmZ1bGxQYXRoIDogJy8nXG4gIH07XG5cbiAgQWJzdHJhY3RIaXN0b3J5LnByb3RvdHlwZS5lbnN1cmVVUkwgPSBmdW5jdGlvbiBlbnN1cmVVUkwgKCkge1xuICAgIC8vIG5vb3BcbiAgfTtcblxuICByZXR1cm4gQWJzdHJhY3RIaXN0b3J5O1xufShIaXN0b3J5KSk7XG5cbi8qICAqL1xuXG52YXIgVnVlUm91dGVyID0gZnVuY3Rpb24gVnVlUm91dGVyIChvcHRpb25zKSB7XG4gIGlmICggb3B0aW9ucyA9PT0gdm9pZCAwICkgb3B0aW9ucyA9IHt9O1xuXG4gIHRoaXMuYXBwID0gbnVsbDtcbiAgdGhpcy5hcHBzID0gW107XG4gIHRoaXMub3B0aW9ucyA9IG9wdGlvbnM7XG4gIHRoaXMuYmVmb3JlSG9va3MgPSBbXTtcbiAgdGhpcy5yZXNvbHZlSG9va3MgPSBbXTtcbiAgdGhpcy5hZnRlckhvb2tzID0gW107XG4gIHRoaXMubWF0Y2hlciA9IGNyZWF0ZU1hdGNoZXIob3B0aW9ucy5yb3V0ZXMgfHwgW10sIHRoaXMpO1xuXG4gIHZhciBtb2RlID0gb3B0aW9ucy5tb2RlIHx8ICdoYXNoJztcbiAgdGhpcy5mYWxsYmFjayA9XG4gICAgbW9kZSA9PT0gJ2hpc3RvcnknICYmICFzdXBwb3J0c1B1c2hTdGF0ZSAmJiBvcHRpb25zLmZhbGxiYWNrICE9PSBmYWxzZTtcbiAgaWYgKHRoaXMuZmFsbGJhY2spIHtcbiAgICBtb2RlID0gJ2hhc2gnO1xuICB9XG4gIGlmICghaW5Ccm93c2VyKSB7XG4gICAgbW9kZSA9ICdhYnN0cmFjdCc7XG4gIH1cbiAgdGhpcy5tb2RlID0gbW9kZTtcblxuICBzd2l0Y2ggKG1vZGUpIHtcbiAgICBjYXNlICdoaXN0b3J5JzpcbiAgICAgIHRoaXMuaGlzdG9yeSA9IG5ldyBIVE1MNUhpc3RvcnkodGhpcywgb3B0aW9ucy5iYXNlKTtcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnaGFzaCc6XG4gICAgICB0aGlzLmhpc3RvcnkgPSBuZXcgSGFzaEhpc3RvcnkodGhpcywgb3B0aW9ucy5iYXNlLCB0aGlzLmZhbGxiYWNrKTtcbiAgICAgIGJyZWFrXG4gICAgY2FzZSAnYWJzdHJhY3QnOlxuICAgICAgdGhpcy5oaXN0b3J5ID0gbmV3IEFic3RyYWN0SGlzdG9yeSh0aGlzLCBvcHRpb25zLmJhc2UpO1xuICAgICAgYnJlYWtcbiAgICBkZWZhdWx0OlxuICAgICAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAgICAgYXNzZXJ0KGZhbHNlLCAoXCJpbnZhbGlkIG1vZGU6IFwiICsgbW9kZSkpO1xuICAgICAgfVxuICB9XG59O1xuXG52YXIgcHJvdG90eXBlQWNjZXNzb3JzID0geyBjdXJyZW50Um91dGU6IHsgY29uZmlndXJhYmxlOiB0cnVlIH0gfTtcblxuVnVlUm91dGVyLnByb3RvdHlwZS5tYXRjaCA9IGZ1bmN0aW9uIG1hdGNoIChyYXcsIGN1cnJlbnQsIHJlZGlyZWN0ZWRGcm9tKSB7XG4gIHJldHVybiB0aGlzLm1hdGNoZXIubWF0Y2gocmF3LCBjdXJyZW50LCByZWRpcmVjdGVkRnJvbSlcbn07XG5cbnByb3RvdHlwZUFjY2Vzc29ycy5jdXJyZW50Um91dGUuZ2V0ID0gZnVuY3Rpb24gKCkge1xuICByZXR1cm4gdGhpcy5oaXN0b3J5ICYmIHRoaXMuaGlzdG9yeS5jdXJyZW50XG59O1xuXG5WdWVSb3V0ZXIucHJvdG90eXBlLmluaXQgPSBmdW5jdGlvbiBpbml0IChhcHAgLyogVnVlIGNvbXBvbmVudCBpbnN0YW5jZSAqLykge1xuICAgIHZhciB0aGlzJDEgPSB0aGlzO1xuXG4gIHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicgJiZcbiAgICBhc3NlcnQoXG4gICAgICBpbnN0YWxsLmluc3RhbGxlZCxcbiAgICAgIFwibm90IGluc3RhbGxlZC4gTWFrZSBzdXJlIHRvIGNhbGwgYFZ1ZS51c2UoVnVlUm91dGVyKWAgXCIgK1xuICAgICAgICBcImJlZm9yZSBjcmVhdGluZyByb290IGluc3RhbmNlLlwiXG4gICAgKTtcblxuICB0aGlzLmFwcHMucHVzaChhcHApO1xuXG4gIC8vIHNldCB1cCBhcHAgZGVzdHJveWVkIGhhbmRsZXJcbiAgLy8gaHR0cHM6Ly9naXRodWIuY29tL3Z1ZWpzL3Z1ZS1yb3V0ZXIvaXNzdWVzLzI2MzlcbiAgYXBwLiRvbmNlKCdob29rOmRlc3Ryb3llZCcsIGZ1bmN0aW9uICgpIHtcbiAgICAvLyBjbGVhbiBvdXQgYXBwIGZyb20gdGhpcy5hcHBzIGFycmF5IG9uY2UgZGVzdHJveWVkXG4gICAgdmFyIGluZGV4ID0gdGhpcyQxLmFwcHMuaW5kZXhPZihhcHApO1xuICAgIGlmIChpbmRleCA+IC0xKSB7IHRoaXMkMS5hcHBzLnNwbGljZShpbmRleCwgMSk7IH1cbiAgICAvLyBlbnN1cmUgd2Ugc3RpbGwgaGF2ZSBhIG1haW4gYXBwIG9yIG51bGwgaWYgbm8gYXBwc1xuICAgIC8vIHdlIGRvIG5vdCByZWxlYXNlIHRoZSByb3V0ZXIgc28gaXQgY2FuIGJlIHJldXNlZFxuICAgIGlmICh0aGlzJDEuYXBwID09PSBhcHApIHsgdGhpcyQxLmFwcCA9IHRoaXMkMS5hcHBzWzBdIHx8IG51bGw7IH1cblxuICAgIGlmICghdGhpcyQxLmFwcCkgeyB0aGlzJDEuaGlzdG9yeS50ZWFyZG93bigpOyB9XG4gIH0pO1xuXG4gIC8vIG1haW4gYXBwIHByZXZpb3VzbHkgaW5pdGlhbGl6ZWRcbiAgLy8gcmV0dXJuIGFzIHdlIGRvbid0IG5lZWQgdG8gc2V0IHVwIG5ldyBoaXN0b3J5IGxpc3RlbmVyXG4gIGlmICh0aGlzLmFwcCkge1xuICAgIHJldHVyblxuICB9XG5cbiAgdGhpcy5hcHAgPSBhcHA7XG5cbiAgdmFyIGhpc3RvcnkgPSB0aGlzLmhpc3Rvcnk7XG5cbiAgaWYgKGhpc3RvcnkgaW5zdGFuY2VvZiBIVE1MNUhpc3RvcnkgfHwgaGlzdG9yeSBpbnN0YW5jZW9mIEhhc2hIaXN0b3J5KSB7XG4gICAgdmFyIGhhbmRsZUluaXRpYWxTY3JvbGwgPSBmdW5jdGlvbiAocm91dGVPckVycm9yKSB7XG4gICAgICB2YXIgZnJvbSA9IGhpc3RvcnkuY3VycmVudDtcbiAgICAgIHZhciBleHBlY3RTY3JvbGwgPSB0aGlzJDEub3B0aW9ucy5zY3JvbGxCZWhhdmlvcjtcbiAgICAgIHZhciBzdXBwb3J0c1Njcm9sbCA9IHN1cHBvcnRzUHVzaFN0YXRlICYmIGV4cGVjdFNjcm9sbDtcblxuICAgICAgaWYgKHN1cHBvcnRzU2Nyb2xsICYmICdmdWxsUGF0aCcgaW4gcm91dGVPckVycm9yKSB7XG4gICAgICAgIGhhbmRsZVNjcm9sbCh0aGlzJDEsIHJvdXRlT3JFcnJvciwgZnJvbSwgZmFsc2UpO1xuICAgICAgfVxuICAgIH07XG4gICAgdmFyIHNldHVwTGlzdGVuZXJzID0gZnVuY3Rpb24gKHJvdXRlT3JFcnJvcikge1xuICAgICAgaGlzdG9yeS5zZXR1cExpc3RlbmVycygpO1xuICAgICAgaGFuZGxlSW5pdGlhbFNjcm9sbChyb3V0ZU9yRXJyb3IpO1xuICAgIH07XG4gICAgaGlzdG9yeS50cmFuc2l0aW9uVG8oXG4gICAgICBoaXN0b3J5LmdldEN1cnJlbnRMb2NhdGlvbigpLFxuICAgICAgc2V0dXBMaXN0ZW5lcnMsXG4gICAgICBzZXR1cExpc3RlbmVyc1xuICAgICk7XG4gIH1cblxuICBoaXN0b3J5Lmxpc3RlbihmdW5jdGlvbiAocm91dGUpIHtcbiAgICB0aGlzJDEuYXBwcy5mb3JFYWNoKGZ1bmN0aW9uIChhcHApIHtcbiAgICAgIGFwcC5fcm91dGUgPSByb3V0ZTtcbiAgICB9KTtcbiAgfSk7XG59O1xuXG5WdWVSb3V0ZXIucHJvdG90eXBlLmJlZm9yZUVhY2ggPSBmdW5jdGlvbiBiZWZvcmVFYWNoIChmbikge1xuICByZXR1cm4gcmVnaXN0ZXJIb29rKHRoaXMuYmVmb3JlSG9va3MsIGZuKVxufTtcblxuVnVlUm91dGVyLnByb3RvdHlwZS5iZWZvcmVSZXNvbHZlID0gZnVuY3Rpb24gYmVmb3JlUmVzb2x2ZSAoZm4pIHtcbiAgcmV0dXJuIHJlZ2lzdGVySG9vayh0aGlzLnJlc29sdmVIb29rcywgZm4pXG59O1xuXG5WdWVSb3V0ZXIucHJvdG90eXBlLmFmdGVyRWFjaCA9IGZ1bmN0aW9uIGFmdGVyRWFjaCAoZm4pIHtcbiAgcmV0dXJuIHJlZ2lzdGVySG9vayh0aGlzLmFmdGVySG9va3MsIGZuKVxufTtcblxuVnVlUm91dGVyLnByb3RvdHlwZS5vblJlYWR5ID0gZnVuY3Rpb24gb25SZWFkeSAoY2IsIGVycm9yQ2IpIHtcbiAgdGhpcy5oaXN0b3J5Lm9uUmVhZHkoY2IsIGVycm9yQ2IpO1xufTtcblxuVnVlUm91dGVyLnByb3RvdHlwZS5vbkVycm9yID0gZnVuY3Rpb24gb25FcnJvciAoZXJyb3JDYikge1xuICB0aGlzLmhpc3Rvcnkub25FcnJvcihlcnJvckNiKTtcbn07XG5cblZ1ZVJvdXRlci5wcm90b3R5cGUucHVzaCA9IGZ1bmN0aW9uIHB1c2ggKGxvY2F0aW9uLCBvbkNvbXBsZXRlLCBvbkFib3J0KSB7XG4gICAgdmFyIHRoaXMkMSA9IHRoaXM7XG5cbiAgLy8gJGZsb3ctZGlzYWJsZS1saW5lXG4gIGlmICghb25Db21wbGV0ZSAmJiAhb25BYm9ydCAmJiB0eXBlb2YgUHJvbWlzZSAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgICAgdGhpcyQxLmhpc3RvcnkucHVzaChsb2NhdGlvbiwgcmVzb2x2ZSwgcmVqZWN0KTtcbiAgICB9KVxuICB9IGVsc2Uge1xuICAgIHRoaXMuaGlzdG9yeS5wdXNoKGxvY2F0aW9uLCBvbkNvbXBsZXRlLCBvbkFib3J0KTtcbiAgfVxufTtcblxuVnVlUm91dGVyLnByb3RvdHlwZS5yZXBsYWNlID0gZnVuY3Rpb24gcmVwbGFjZSAobG9jYXRpb24sIG9uQ29tcGxldGUsIG9uQWJvcnQpIHtcbiAgICB2YXIgdGhpcyQxID0gdGhpcztcblxuICAvLyAkZmxvdy1kaXNhYmxlLWxpbmVcbiAgaWYgKCFvbkNvbXBsZXRlICYmICFvbkFib3J0ICYmIHR5cGVvZiBQcm9taXNlICE9PSAndW5kZWZpbmVkJykge1xuICAgIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgICB0aGlzJDEuaGlzdG9yeS5yZXBsYWNlKGxvY2F0aW9uLCByZXNvbHZlLCByZWplY3QpO1xuICAgIH0pXG4gIH0gZWxzZSB7XG4gICAgdGhpcy5oaXN0b3J5LnJlcGxhY2UobG9jYXRpb24sIG9uQ29tcGxldGUsIG9uQWJvcnQpO1xuICB9XG59O1xuXG5WdWVSb3V0ZXIucHJvdG90eXBlLmdvID0gZnVuY3Rpb24gZ28gKG4pIHtcbiAgdGhpcy5oaXN0b3J5LmdvKG4pO1xufTtcblxuVnVlUm91dGVyLnByb3RvdHlwZS5iYWNrID0gZnVuY3Rpb24gYmFjayAoKSB7XG4gIHRoaXMuZ28oLTEpO1xufTtcblxuVnVlUm91dGVyLnByb3RvdHlwZS5mb3J3YXJkID0gZnVuY3Rpb24gZm9yd2FyZCAoKSB7XG4gIHRoaXMuZ28oMSk7XG59O1xuXG5WdWVSb3V0ZXIucHJvdG90eXBlLmdldE1hdGNoZWRDb21wb25lbnRzID0gZnVuY3Rpb24gZ2V0TWF0Y2hlZENvbXBvbmVudHMgKHRvKSB7XG4gIHZhciByb3V0ZSA9IHRvXG4gICAgPyB0by5tYXRjaGVkXG4gICAgICA/IHRvXG4gICAgICA6IHRoaXMucmVzb2x2ZSh0bykucm91dGVcbiAgICA6IHRoaXMuY3VycmVudFJvdXRlO1xuICBpZiAoIXJvdXRlKSB7XG4gICAgcmV0dXJuIFtdXG4gIH1cbiAgcmV0dXJuIFtdLmNvbmNhdC5hcHBseShcbiAgICBbXSxcbiAgICByb3V0ZS5tYXRjaGVkLm1hcChmdW5jdGlvbiAobSkge1xuICAgICAgcmV0dXJuIE9iamVjdC5rZXlzKG0uY29tcG9uZW50cykubWFwKGZ1bmN0aW9uIChrZXkpIHtcbiAgICAgICAgcmV0dXJuIG0uY29tcG9uZW50c1trZXldXG4gICAgICB9KVxuICAgIH0pXG4gIClcbn07XG5cblZ1ZVJvdXRlci5wcm90b3R5cGUucmVzb2x2ZSA9IGZ1bmN0aW9uIHJlc29sdmUgKFxuICB0byxcbiAgY3VycmVudCxcbiAgYXBwZW5kXG4pIHtcbiAgY3VycmVudCA9IGN1cnJlbnQgfHwgdGhpcy5oaXN0b3J5LmN1cnJlbnQ7XG4gIHZhciBsb2NhdGlvbiA9IG5vcm1hbGl6ZUxvY2F0aW9uKHRvLCBjdXJyZW50LCBhcHBlbmQsIHRoaXMpO1xuICB2YXIgcm91dGUgPSB0aGlzLm1hdGNoKGxvY2F0aW9uLCBjdXJyZW50KTtcbiAgdmFyIGZ1bGxQYXRoID0gcm91dGUucmVkaXJlY3RlZEZyb20gfHwgcm91dGUuZnVsbFBhdGg7XG4gIHZhciBiYXNlID0gdGhpcy5oaXN0b3J5LmJhc2U7XG4gIHZhciBocmVmID0gY3JlYXRlSHJlZihiYXNlLCBmdWxsUGF0aCwgdGhpcy5tb2RlKTtcbiAgcmV0dXJuIHtcbiAgICBsb2NhdGlvbjogbG9jYXRpb24sXG4gICAgcm91dGU6IHJvdXRlLFxuICAgIGhyZWY6IGhyZWYsXG4gICAgLy8gZm9yIGJhY2t3YXJkcyBjb21wYXRcbiAgICBub3JtYWxpemVkVG86IGxvY2F0aW9uLFxuICAgIHJlc29sdmVkOiByb3V0ZVxuICB9XG59O1xuXG5WdWVSb3V0ZXIucHJvdG90eXBlLmdldFJvdXRlcyA9IGZ1bmN0aW9uIGdldFJvdXRlcyAoKSB7XG4gIHJldHVybiB0aGlzLm1hdGNoZXIuZ2V0Um91dGVzKClcbn07XG5cblZ1ZVJvdXRlci5wcm90b3R5cGUuYWRkUm91dGUgPSBmdW5jdGlvbiBhZGRSb3V0ZSAocGFyZW50T3JSb3V0ZSwgcm91dGUpIHtcbiAgdGhpcy5tYXRjaGVyLmFkZFJvdXRlKHBhcmVudE9yUm91dGUsIHJvdXRlKTtcbiAgaWYgKHRoaXMuaGlzdG9yeS5jdXJyZW50ICE9PSBTVEFSVCkge1xuICAgIHRoaXMuaGlzdG9yeS50cmFuc2l0aW9uVG8odGhpcy5oaXN0b3J5LmdldEN1cnJlbnRMb2NhdGlvbigpKTtcbiAgfVxufTtcblxuVnVlUm91dGVyLnByb3RvdHlwZS5hZGRSb3V0ZXMgPSBmdW5jdGlvbiBhZGRSb3V0ZXMgKHJvdXRlcykge1xuICBpZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgIT09ICdwcm9kdWN0aW9uJykge1xuICAgIHdhcm4oZmFsc2UsICdyb3V0ZXIuYWRkUm91dGVzKCkgaXMgZGVwcmVjYXRlZCBhbmQgaGFzIGJlZW4gcmVtb3ZlZCBpbiBWdWUgUm91dGVyIDQuIFVzZSByb3V0ZXIuYWRkUm91dGUoKSBpbnN0ZWFkLicpO1xuICB9XG4gIHRoaXMubWF0Y2hlci5hZGRSb3V0ZXMocm91dGVzKTtcbiAgaWYgKHRoaXMuaGlzdG9yeS5jdXJyZW50ICE9PSBTVEFSVCkge1xuICAgIHRoaXMuaGlzdG9yeS50cmFuc2l0aW9uVG8odGhpcy5oaXN0b3J5LmdldEN1cnJlbnRMb2NhdGlvbigpKTtcbiAgfVxufTtcblxuT2JqZWN0LmRlZmluZVByb3BlcnRpZXMoIFZ1ZVJvdXRlci5wcm90b3R5cGUsIHByb3RvdHlwZUFjY2Vzc29ycyApO1xuXG5mdW5jdGlvbiByZWdpc3Rlckhvb2sgKGxpc3QsIGZuKSB7XG4gIGxpc3QucHVzaChmbik7XG4gIHJldHVybiBmdW5jdGlvbiAoKSB7XG4gICAgdmFyIGkgPSBsaXN0LmluZGV4T2YoZm4pO1xuICAgIGlmIChpID4gLTEpIHsgbGlzdC5zcGxpY2UoaSwgMSk7IH1cbiAgfVxufVxuXG5mdW5jdGlvbiBjcmVhdGVIcmVmIChiYXNlLCBmdWxsUGF0aCwgbW9kZSkge1xuICB2YXIgcGF0aCA9IG1vZGUgPT09ICdoYXNoJyA/ICcjJyArIGZ1bGxQYXRoIDogZnVsbFBhdGg7XG4gIHJldHVybiBiYXNlID8gY2xlYW5QYXRoKGJhc2UgKyAnLycgKyBwYXRoKSA6IHBhdGhcbn1cblxuVnVlUm91dGVyLmluc3RhbGwgPSBpbnN0YWxsO1xuVnVlUm91dGVyLnZlcnNpb24gPSAnMy41LjEnO1xuVnVlUm91dGVyLmlzTmF2aWdhdGlvbkZhaWx1cmUgPSBpc05hdmlnYXRpb25GYWlsdXJlO1xuVnVlUm91dGVyLk5hdmlnYXRpb25GYWlsdXJlVHlwZSA9IE5hdmlnYXRpb25GYWlsdXJlVHlwZTtcblZ1ZVJvdXRlci5TVEFSVF9MT0NBVElPTiA9IFNUQVJUO1xuXG5pZiAoaW5Ccm93c2VyICYmIHdpbmRvdy5WdWUpIHtcbiAgd2luZG93LlZ1ZS51c2UoVnVlUm91dGVyKTtcbn1cblxuZXhwb3J0IGRlZmF1bHQgVnVlUm91dGVyO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvdnVlLXJvdXRlci9kaXN0L3Z1ZS1yb3V0ZXIuZXNtLmpzXG4vLyBtb2R1bGUgaWQgPSAvb2NxXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:////ocq\n")},"02w1":function(module,exports,__webpack_require__){"use strict";eval("\n\nexports.__esModule = true;\nexports.removeResizeListener = exports.addResizeListener = undefined;\n\nvar _resizeObserverPolyfill = __webpack_require__(\"z+gd\");\n\nvar _resizeObserverPolyfill2 = _interopRequireDefault(_resizeObserverPolyfill);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar isServer = typeof window === 'undefined';\n\n/* istanbul ignore next */\nvar resizeHandler = function resizeHandler(entries) {\n for (var _iterator = entries, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {\n var _ref;\n\n if (_isArray) {\n if (_i >= _iterator.length) break;\n _ref = _iterator[_i++];\n } else {\n _i = _iterator.next();\n if (_i.done) break;\n _ref = _i.value;\n }\n\n var entry = _ref;\n\n var listeners = entry.target.__resizeListeners__ || [];\n if (listeners.length) {\n listeners.forEach(function (fn) {\n fn();\n });\n }\n }\n};\n\n/* istanbul ignore next */\nvar addResizeListener = exports.addResizeListener = function addResizeListener(element, fn) {\n if (isServer) return;\n if (!element.__resizeListeners__) {\n element.__resizeListeners__ = [];\n element.__ro__ = new _resizeObserverPolyfill2.default(resizeHandler);\n element.__ro__.observe(element);\n }\n element.__resizeListeners__.push(fn);\n};\n\n/* istanbul ignore next */\nvar removeResizeListener = exports.removeResizeListener = function removeResizeListener(element, fn) {\n if (!element || !element.__resizeListeners__) return;\n element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1);\n if (!element.__resizeListeners__.length) {\n element.__ro__.disconnect();\n }\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDJ3MS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9lbGVtZW50LXVpL2xpYi91dGlscy9yZXNpemUtZXZlbnQuanM/ZDM2YyJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5leHBvcnRzLnJlbW92ZVJlc2l6ZUxpc3RlbmVyID0gZXhwb3J0cy5hZGRSZXNpemVMaXN0ZW5lciA9IHVuZGVmaW5lZDtcblxudmFyIF9yZXNpemVPYnNlcnZlclBvbHlmaWxsID0gcmVxdWlyZSgncmVzaXplLW9ic2VydmVyLXBvbHlmaWxsJyk7XG5cbnZhciBfcmVzaXplT2JzZXJ2ZXJQb2x5ZmlsbDIgPSBfaW50ZXJvcFJlcXVpcmVEZWZhdWx0KF9yZXNpemVPYnNlcnZlclBvbHlmaWxsKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxudmFyIGlzU2VydmVyID0gdHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCc7XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG52YXIgcmVzaXplSGFuZGxlciA9IGZ1bmN0aW9uIHJlc2l6ZUhhbmRsZXIoZW50cmllcykge1xuICBmb3IgKHZhciBfaXRlcmF0b3IgPSBlbnRyaWVzLCBfaXNBcnJheSA9IEFycmF5LmlzQXJyYXkoX2l0ZXJhdG9yKSwgX2kgPSAwLCBfaXRlcmF0b3IgPSBfaXNBcnJheSA/IF9pdGVyYXRvciA6IF9pdGVyYXRvcltTeW1ib2wuaXRlcmF0b3JdKCk7Oykge1xuICAgIHZhciBfcmVmO1xuXG4gICAgaWYgKF9pc0FycmF5KSB7XG4gICAgICBpZiAoX2kgPj0gX2l0ZXJhdG9yLmxlbmd0aCkgYnJlYWs7XG4gICAgICBfcmVmID0gX2l0ZXJhdG9yW19pKytdO1xuICAgIH0gZWxzZSB7XG4gICAgICBfaSA9IF9pdGVyYXRvci5uZXh0KCk7XG4gICAgICBpZiAoX2kuZG9uZSkgYnJlYWs7XG4gICAgICBfcmVmID0gX2kudmFsdWU7XG4gICAgfVxuXG4gICAgdmFyIGVudHJ5ID0gX3JlZjtcblxuICAgIHZhciBsaXN0ZW5lcnMgPSBlbnRyeS50YXJnZXQuX19yZXNpemVMaXN0ZW5lcnNfXyB8fCBbXTtcbiAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCkge1xuICAgICAgbGlzdGVuZXJzLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7XG4gICAgICAgIGZuKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cbn07XG5cbi8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG52YXIgYWRkUmVzaXplTGlzdGVuZXIgPSBleHBvcnRzLmFkZFJlc2l6ZUxpc3RlbmVyID0gZnVuY3Rpb24gYWRkUmVzaXplTGlzdGVuZXIoZWxlbWVudCwgZm4pIHtcbiAgaWYgKGlzU2VydmVyKSByZXR1cm47XG4gIGlmICghZWxlbWVudC5fX3Jlc2l6ZUxpc3RlbmVyc19fKSB7XG4gICAgZWxlbWVudC5fX3Jlc2l6ZUxpc3RlbmVyc19fID0gW107XG4gICAgZWxlbWVudC5fX3JvX18gPSBuZXcgX3Jlc2l6ZU9ic2VydmVyUG9seWZpbGwyLmRlZmF1bHQocmVzaXplSGFuZGxlcik7XG4gICAgZWxlbWVudC5fX3JvX18ub2JzZXJ2ZShlbGVtZW50KTtcbiAgfVxuICBlbGVtZW50Ll9fcmVzaXplTGlzdGVuZXJzX18ucHVzaChmbik7XG59O1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xudmFyIHJlbW92ZVJlc2l6ZUxpc3RlbmVyID0gZXhwb3J0cy5yZW1vdmVSZXNpemVMaXN0ZW5lciA9IGZ1bmN0aW9uIHJlbW92ZVJlc2l6ZUxpc3RlbmVyKGVsZW1lbnQsIGZuKSB7XG4gIGlmICghZWxlbWVudCB8fCAhZWxlbWVudC5fX3Jlc2l6ZUxpc3RlbmVyc19fKSByZXR1cm47XG4gIGVsZW1lbnQuX19yZXNpemVMaXN0ZW5lcnNfXy5zcGxpY2UoZWxlbWVudC5fX3Jlc2l6ZUxpc3RlbmVyc19fLmluZGV4T2YoZm4pLCAxKTtcbiAgaWYgKCFlbGVtZW50Ll9fcmVzaXplTGlzdGVuZXJzX18ubGVuZ3RoKSB7XG4gICAgZWxlbWVudC5fX3JvX18uZGlzY29ubmVjdCgpO1xuICB9XG59O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2VsZW1lbnQtdWkvbGliL3V0aWxzL3Jlc2l6ZS1ldmVudC5qc1xuLy8gbW9kdWxlIGlkID0gMDJ3MVxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///02w1\n")},"06OY":function(module,exports,__webpack_require__){eval("var META = __webpack_require__(\"3Eo+\")('meta');\nvar isObject = __webpack_require__(\"EqjI\");\nvar has = __webpack_require__(\"D2L2\");\nvar setDesc = __webpack_require__(\"evD5\").f;\nvar id = 0;\nvar isExtensible = Object.isExtensible || function () {\n return true;\n};\nvar FREEZE = !__webpack_require__(\"S82l\")(function () {\n return isExtensible(Object.preventExtensions({}));\n});\nvar setMeta = function (it) {\n setDesc(it, META, { value: {\n i: 'O' + ++id, // object ID\n w: {} // weak collections IDs\n } });\n};\nvar fastKey = function (it, create) {\n // return primitive with prefix\n if (!isObject(it)) return typeof it == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return 'F';\n // not necessary to add metadata\n if (!create) return 'E';\n // add missing metadata\n setMeta(it);\n // return object ID\n } return it[META].i;\n};\nvar getWeak = function (it, create) {\n if (!has(it, META)) {\n // can't set metadata to uncaught frozen object\n if (!isExtensible(it)) return true;\n // not necessary to add metadata\n if (!create) return false;\n // add missing metadata\n setMeta(it);\n // return hash weak collections IDs\n } return it[META].w;\n};\n// add metadata on freeze-family methods calling\nvar onFreeze = function (it) {\n if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);\n return it;\n};\nvar meta = module.exports = {\n KEY: META,\n NEED: false,\n fastKey: fastKey,\n getWeak: getWeak,\n onFreeze: onFreeze\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDZPWS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fbWV0YS5qcz9kM2EzIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBNRVRBID0gcmVxdWlyZSgnLi9fdWlkJykoJ21ldGEnKTtcbnZhciBpc09iamVjdCA9IHJlcXVpcmUoJy4vX2lzLW9iamVjdCcpO1xudmFyIGhhcyA9IHJlcXVpcmUoJy4vX2hhcycpO1xudmFyIHNldERlc2MgPSByZXF1aXJlKCcuL19vYmplY3QtZHAnKS5mO1xudmFyIGlkID0gMDtcbnZhciBpc0V4dGVuc2libGUgPSBPYmplY3QuaXNFeHRlbnNpYmxlIHx8IGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIHRydWU7XG59O1xudmFyIEZSRUVaRSA9ICFyZXF1aXJlKCcuL19mYWlscycpKGZ1bmN0aW9uICgpIHtcbiAgcmV0dXJuIGlzRXh0ZW5zaWJsZShPYmplY3QucHJldmVudEV4dGVuc2lvbnMoe30pKTtcbn0pO1xudmFyIHNldE1ldGEgPSBmdW5jdGlvbiAoaXQpIHtcbiAgc2V0RGVzYyhpdCwgTUVUQSwgeyB2YWx1ZToge1xuICAgIGk6ICdPJyArICsraWQsIC8vIG9iamVjdCBJRFxuICAgIHc6IHt9ICAgICAgICAgIC8vIHdlYWsgY29sbGVjdGlvbnMgSURzXG4gIH0gfSk7XG59O1xudmFyIGZhc3RLZXkgPSBmdW5jdGlvbiAoaXQsIGNyZWF0ZSkge1xuICAvLyByZXR1cm4gcHJpbWl0aXZlIHdpdGggcHJlZml4XG4gIGlmICghaXNPYmplY3QoaXQpKSByZXR1cm4gdHlwZW9mIGl0ID09ICdzeW1ib2wnID8gaXQgOiAodHlwZW9mIGl0ID09ICdzdHJpbmcnID8gJ1MnIDogJ1AnKSArIGl0O1xuICBpZiAoIWhhcyhpdCwgTUVUQSkpIHtcbiAgICAvLyBjYW4ndCBzZXQgbWV0YWRhdGEgdG8gdW5jYXVnaHQgZnJvemVuIG9iamVjdFxuICAgIGlmICghaXNFeHRlbnNpYmxlKGl0KSkgcmV0dXJuICdGJztcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmICghY3JlYXRlKSByZXR1cm4gJ0UnO1xuICAgIC8vIGFkZCBtaXNzaW5nIG1ldGFkYXRhXG4gICAgc2V0TWV0YShpdCk7XG4gIC8vIHJldHVybiBvYmplY3QgSURcbiAgfSByZXR1cm4gaXRbTUVUQV0uaTtcbn07XG52YXIgZ2V0V2VhayA9IGZ1bmN0aW9uIChpdCwgY3JlYXRlKSB7XG4gIGlmICghaGFzKGl0LCBNRVRBKSkge1xuICAgIC8vIGNhbid0IHNldCBtZXRhZGF0YSB0byB1bmNhdWdodCBmcm96ZW4gb2JqZWN0XG4gICAgaWYgKCFpc0V4dGVuc2libGUoaXQpKSByZXR1cm4gdHJ1ZTtcbiAgICAvLyBub3QgbmVjZXNzYXJ5IHRvIGFkZCBtZXRhZGF0YVxuICAgIGlmICghY3JlYXRlKSByZXR1cm4gZmFsc2U7XG4gICAgLy8gYWRkIG1pc3NpbmcgbWV0YWRhdGFcbiAgICBzZXRNZXRhKGl0KTtcbiAgLy8gcmV0dXJuIGhhc2ggd2VhayBjb2xsZWN0aW9ucyBJRHNcbiAgfSByZXR1cm4gaXRbTUVUQV0udztcbn07XG4vLyBhZGQgbWV0YWRhdGEgb24gZnJlZXplLWZhbWlseSBtZXRob2RzIGNhbGxpbmdcbnZhciBvbkZyZWV6ZSA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAoRlJFRVpFICYmIG1ldGEuTkVFRCAmJiBpc0V4dGVuc2libGUoaXQpICYmICFoYXMoaXQsIE1FVEEpKSBzZXRNZXRhKGl0KTtcbiAgcmV0dXJuIGl0O1xufTtcbnZhciBtZXRhID0gbW9kdWxlLmV4cG9ydHMgPSB7XG4gIEtFWTogTUVUQSxcbiAgTkVFRDogZmFsc2UsXG4gIGZhc3RLZXk6IGZhc3RLZXksXG4gIGdldFdlYWs6IGdldFdlYWssXG4gIG9uRnJlZXplOiBvbkZyZWV6ZVxufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19tZXRhLmpzXG4vLyBtb2R1bGUgaWQgPSAwNk9ZXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///06OY\n")},"0kY3":function(module,exports,__webpack_require__){eval('module.exports =\n/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// define __esModule on exports\n/******/ \t__webpack_require__.r = function(exports) {\n/******/ \t\tif(typeof Symbol !== \'undefined\' && Symbol.toStringTag) {\n/******/ \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: \'Module\' });\n/******/ \t\t}\n/******/ \t\tObject.defineProperty(exports, \'__esModule\', { value: true });\n/******/ \t};\n/******/\n/******/ \t// create a fake namespace object\n/******/ \t// mode & 1: value is a module id, require it\n/******/ \t// mode & 2: merge all properties of value into the ns\n/******/ \t// mode & 4: return value when already ns object\n/******/ \t// mode & 8|1: behave like require\n/******/ \t__webpack_require__.t = function(value, mode) {\n/******/ \t\tif(mode & 1) value = __webpack_require__(value);\n/******/ \t\tif(mode & 8) return value;\n/******/ \t\tif((mode & 4) && typeof value === \'object\' && value && value.__esModule) return value;\n/******/ \t\tvar ns = Object.create(null);\n/******/ \t\t__webpack_require__.r(ns);\n/******/ \t\tObject.defineProperty(ns, \'default\', { enumerable: true, value: value });\n/******/ \t\tif(mode & 2 && typeof value != \'string\') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n/******/ \t\treturn ns;\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module[\'default\']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, \'a\', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = "/dist/";\n/******/\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 114);\n/******/ })\n/************************************************************************/\n/******/ ({\n\n/***/ 0:\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n"use strict";\n/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "a", function() { return normalizeComponent; });\n/* globals __VUE_SSR_CONTEXT__ */\n\n// IMPORTANT: Do NOT use ES2015 features in this file (except for modules).\n// This module is a runtime utility for cleaner component module output and will\n// be included in the final webpack user bundle.\n\nfunction normalizeComponent (\n scriptExports,\n render,\n staticRenderFns,\n functionalTemplate,\n injectStyles,\n scopeId,\n moduleIdentifier, /* server only */\n shadowMode /* vue-cli only */\n) {\n // Vue.extend constructor export interop\n var options = typeof scriptExports === \'function\'\n ? scriptExports.options\n : scriptExports\n\n // render functions\n if (render) {\n options.render = render\n options.staticRenderFns = staticRenderFns\n options._compiled = true\n }\n\n // functional template\n if (functionalTemplate) {\n options.functional = true\n }\n\n // scopedId\n if (scopeId) {\n options._scopeId = \'data-v-\' + scopeId\n }\n\n var hook\n if (moduleIdentifier) { // server build\n hook = function (context) {\n // 2.3 injection\n context =\n context || // cached call\n (this.$vnode && this.$vnode.ssrContext) || // stateful\n (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional\n // 2.2 with runInNewContext: true\n if (!context && typeof __VUE_SSR_CONTEXT__ !== \'undefined\') {\n context = __VUE_SSR_CONTEXT__\n }\n // inject component styles\n if (injectStyles) {\n injectStyles.call(this, context)\n }\n // register component module identifier for async chunk inferrence\n if (context && context._registeredComponents) {\n context._registeredComponents.add(moduleIdentifier)\n }\n }\n // used by ssr in case component is cached and beforeCreate\n // never gets called\n options._ssrRegister = hook\n } else if (injectStyles) {\n hook = shadowMode\n ? function () { injectStyles.call(this, this.$root.$options.shadowRoot) }\n : injectStyles\n }\n\n if (hook) {\n if (options.functional) {\n // for template-only hot-reload because in that case the render fn doesn\'t\n // go through the normalizer\n options._injectStyles = hook\n // register for functioal component in vue file\n var originalRender = options.render\n options.render = function renderWithStyleInjection (h, context) {\n hook.call(context)\n return originalRender(h, context)\n }\n } else {\n // inject component registration as beforeCreate hook\n var existing = options.beforeCreate\n options.beforeCreate = existing\n ? [].concat(existing, hook)\n : [hook]\n }\n }\n\n return {\n exports: scriptExports,\n options: options\n }\n}\n\n\n/***/ }),\n\n/***/ 10:\n/***/ (function(module, exports) {\n\nmodule.exports = __webpack_require__("HJMx");\n\n/***/ }),\n\n/***/ 114:\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n"use strict";\n__webpack_require__.r(__webpack_exports__);\n\n// CONCATENATED MODULE: ./node_modules/vue-loader/lib/loaders/templateLoader.js??vue-loader-options!./node_modules/vue-loader/lib??vue-loader-options!./packages/input-number/src/input-number.vue?vue&type=template&id=42f8cf66&\nvar render = function() {\n var _vm = this\n var _h = _vm.$createElement\n var _c = _vm._self._c || _h\n return _c(\n "div",\n {\n class: [\n "el-input-number",\n _vm.inputNumberSize ? "el-input-number--" + _vm.inputNumberSize : "",\n { "is-disabled": _vm.inputNumberDisabled },\n { "is-without-controls": !_vm.controls },\n { "is-controls-right": _vm.controlsAtRight }\n ],\n on: {\n dragstart: function($event) {\n $event.preventDefault()\n }\n }\n },\n [\n _vm.controls\n ? _c(\n "span",\n {\n directives: [\n {\n name: "repeat-click",\n rawName: "v-repeat-click",\n value: _vm.decrease,\n expression: "decrease"\n }\n ],\n staticClass: "el-input-number__decrease",\n class: { "is-disabled": _vm.minDisabled },\n attrs: { role: "button" },\n on: {\n keydown: function($event) {\n if (\n !("button" in $event) &&\n _vm._k($event.keyCode, "enter", 13, $event.key, "Enter")\n ) {\n return null\n }\n return _vm.decrease($event)\n }\n }\n },\n [\n _c("i", {\n class:\n "el-icon-" + (_vm.controlsAtRight ? "arrow-down" : "minus")\n })\n ]\n )\n : _vm._e(),\n _vm.controls\n ? _c(\n "span",\n {\n directives: [\n {\n name: "repeat-click",\n rawName: "v-repeat-click",\n value: _vm.increase,\n expression: "increase"\n }\n ],\n staticClass: "el-input-number__increase",\n class: { "is-disabled": _vm.maxDisabled },\n attrs: { role: "button" },\n on: {\n keydown: function($event) {\n if (\n !("button" in $event) &&\n _vm._k($event.keyCode, "enter", 13, $event.key, "Enter")\n ) {\n return null\n }\n return _vm.increase($event)\n }\n }\n },\n [\n _c("i", {\n class: "el-icon-" + (_vm.controlsAtRight ? "arrow-up" : "plus")\n })\n ]\n )\n : _vm._e(),\n _c("el-input", {\n ref: "input",\n attrs: {\n value: _vm.displayValue,\n placeholder: _vm.placeholder,\n disabled: _vm.inputNumberDisabled,\n size: _vm.inputNumberSize,\n max: _vm.max,\n min: _vm.min,\n name: _vm.name,\n label: _vm.label\n },\n on: {\n blur: _vm.handleBlur,\n focus: _vm.handleFocus,\n input: _vm.handleInput,\n change: _vm.handleInputChange\n },\n nativeOn: {\n keydown: [\n function($event) {\n if (\n !("button" in $event) &&\n _vm._k($event.keyCode, "up", 38, $event.key, ["Up", "ArrowUp"])\n ) {\n return null\n }\n $event.preventDefault()\n return _vm.increase($event)\n },\n function($event) {\n if (\n !("button" in $event) &&\n _vm._k($event.keyCode, "down", 40, $event.key, [\n "Down",\n "ArrowDown"\n ])\n ) {\n return null\n }\n $event.preventDefault()\n return _vm.decrease($event)\n }\n ]\n }\n })\n ],\n 1\n )\n}\nvar staticRenderFns = []\nrender._withStripped = true\n\n\n// CONCATENATED MODULE: ./packages/input-number/src/input-number.vue?vue&type=template&id=42f8cf66&\n\n// EXTERNAL MODULE: external "element-ui/lib/input"\nvar input_ = __webpack_require__(10);\nvar input_default = /*#__PURE__*/__webpack_require__.n(input_);\n\n// EXTERNAL MODULE: external "element-ui/lib/mixins/focus"\nvar focus_ = __webpack_require__(22);\nvar focus_default = /*#__PURE__*/__webpack_require__.n(focus_);\n\n// EXTERNAL MODULE: ./src/directives/repeat-click.js\nvar repeat_click = __webpack_require__(30);\n\n// CONCATENATED MODULE: ./node_modules/babel-loader/lib!./node_modules/vue-loader/lib??vue-loader-options!./packages/input-number/src/input-number.vue?vue&type=script&lang=js&\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//\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/* harmony default export */ var input_numbervue_type_script_lang_js_ = ({\n name: \'ElInputNumber\',\n mixins: [focus_default()(\'input\')],\n inject: {\n elForm: {\n default: \'\'\n },\n elFormItem: {\n default: \'\'\n }\n },\n directives: {\n repeatClick: repeat_click["a" /* default */]\n },\n components: {\n ElInput: input_default.a\n },\n props: {\n step: {\n type: Number,\n default: 1\n },\n stepStrictly: {\n type: Boolean,\n default: false\n },\n max: {\n type: Number,\n default: Infinity\n },\n min: {\n type: Number,\n default: -Infinity\n },\n value: {},\n disabled: Boolean,\n size: String,\n controls: {\n type: Boolean,\n default: true\n },\n controlsPosition: {\n type: String,\n default: \'\'\n },\n name: String,\n label: String,\n placeholder: String,\n precision: {\n type: Number,\n validator: function validator(val) {\n return val >= 0 && val === parseInt(val, 10);\n }\n }\n },\n data: function data() {\n return {\n currentValue: 0,\n userInput: null\n };\n },\n\n watch: {\n value: {\n immediate: true,\n handler: function handler(value) {\n var newVal = value === undefined ? value : Number(value);\n if (newVal !== undefined) {\n if (isNaN(newVal)) {\n return;\n }\n\n if (this.stepStrictly) {\n var stepPrecision = this.getPrecision(this.step);\n var precisionFactor = Math.pow(10, stepPrecision);\n newVal = Math.round(newVal / this.step) * precisionFactor * this.step / precisionFactor;\n }\n\n if (this.precision !== undefined) {\n newVal = this.toPrecision(newVal, this.precision);\n }\n }\n if (newVal >= this.max) newVal = this.max;\n if (newVal <= this.min) newVal = this.min;\n this.currentValue = newVal;\n this.userInput = null;\n this.$emit(\'input\', newVal);\n }\n }\n },\n computed: {\n minDisabled: function minDisabled() {\n return this._decrease(this.value, this.step) < this.min;\n },\n maxDisabled: function maxDisabled() {\n return this._increase(this.value, this.step) > this.max;\n },\n numPrecision: function numPrecision() {\n var value = this.value,\n step = this.step,\n getPrecision = this.getPrecision,\n precision = this.precision;\n\n var stepPrecision = getPrecision(step);\n if (precision !== undefined) {\n if (stepPrecision > precision) {\n console.warn(\'[Element Warn][InputNumber]precision should not be less than the decimal places of step\');\n }\n return precision;\n } else {\n return Math.max(getPrecision(value), stepPrecision);\n }\n },\n controlsAtRight: function controlsAtRight() {\n return this.controls && this.controlsPosition === \'right\';\n },\n _elFormItemSize: function _elFormItemSize() {\n return (this.elFormItem || {}).elFormItemSize;\n },\n inputNumberSize: function inputNumberSize() {\n return this.size || this._elFormItemSize || (this.$ELEMENT || {}).size;\n },\n inputNumberDisabled: function inputNumberDisabled() {\n return this.disabled || !!(this.elForm || {}).disabled;\n },\n displayValue: function displayValue() {\n if (this.userInput !== null) {\n return this.userInput;\n }\n\n var currentValue = this.currentValue;\n\n if (typeof currentValue === \'number\') {\n if (this.stepStrictly) {\n var stepPrecision = this.getPrecision(this.step);\n var precisionFactor = Math.pow(10, stepPrecision);\n currentValue = Math.round(currentValue / this.step) * precisionFactor * this.step / precisionFactor;\n }\n\n if (this.precision !== undefined) {\n currentValue = currentValue.toFixed(this.precision);\n }\n }\n\n return currentValue;\n }\n },\n methods: {\n toPrecision: function toPrecision(num, precision) {\n if (precision === undefined) precision = this.numPrecision;\n return parseFloat(Math.round(num * Math.pow(10, precision)) / Math.pow(10, precision));\n },\n getPrecision: function getPrecision(value) {\n if (value === undefined) return 0;\n var valueString = value.toString();\n var dotPosition = valueString.indexOf(\'.\');\n var precision = 0;\n if (dotPosition !== -1) {\n precision = valueString.length - dotPosition - 1;\n }\n return precision;\n },\n _increase: function _increase(val, step) {\n if (typeof val !== \'number\' && val !== undefined) return this.currentValue;\n\n var precisionFactor = Math.pow(10, this.numPrecision);\n // Solve the accuracy problem of JS decimal calculation by converting the value to integer.\n return this.toPrecision((precisionFactor * val + precisionFactor * step) / precisionFactor);\n },\n _decrease: function _decrease(val, step) {\n if (typeof val !== \'number\' && val !== undefined) return this.currentValue;\n\n var precisionFactor = Math.pow(10, this.numPrecision);\n\n return this.toPrecision((precisionFactor * val - precisionFactor * step) / precisionFactor);\n },\n increase: function increase() {\n if (this.inputNumberDisabled || this.maxDisabled) return;\n var value = this.value || 0;\n var newVal = this._increase(value, this.step);\n this.setCurrentValue(newVal);\n },\n decrease: function decrease() {\n if (this.inputNumberDisabled || this.minDisabled) return;\n var value = this.value || 0;\n var newVal = this._decrease(value, this.step);\n this.setCurrentValue(newVal);\n },\n handleBlur: function handleBlur(event) {\n this.$emit(\'blur\', event);\n },\n handleFocus: function handleFocus(event) {\n this.$emit(\'focus\', event);\n },\n setCurrentValue: function setCurrentValue(newVal) {\n var oldVal = this.currentValue;\n if (typeof newVal === \'number\' && this.precision !== undefined) {\n newVal = this.toPrecision(newVal, this.precision);\n }\n if (newVal >= this.max) newVal = this.max;\n if (newVal <= this.min) newVal = this.min;\n if (oldVal === newVal) return;\n this.userInput = null;\n this.$emit(\'input\', newVal);\n this.$emit(\'change\', newVal, oldVal);\n this.currentValue = newVal;\n },\n handleInput: function handleInput(value) {\n this.userInput = value;\n },\n handleInputChange: function handleInputChange(value) {\n var newVal = value === \'\' ? undefined : Number(value);\n if (!isNaN(newVal) || value === \'\') {\n this.setCurrentValue(newVal);\n }\n this.userInput = null;\n },\n select: function select() {\n this.$refs.input.select();\n }\n },\n mounted: function mounted() {\n var innerInput = this.$refs.input.$refs.input;\n innerInput.setAttribute(\'role\', \'spinbutton\');\n innerInput.setAttribute(\'aria-valuemax\', this.max);\n innerInput.setAttribute(\'aria-valuemin\', this.min);\n innerInput.setAttribute(\'aria-valuenow\', this.currentValue);\n innerInput.setAttribute(\'aria-disabled\', this.inputNumberDisabled);\n },\n updated: function updated() {\n if (!this.$refs || !this.$refs.input) return;\n var innerInput = this.$refs.input.$refs.input;\n innerInput.setAttribute(\'aria-valuenow\', this.currentValue);\n }\n});\n// CONCATENATED MODULE: ./packages/input-number/src/input-number.vue?vue&type=script&lang=js&\n /* harmony default export */ var src_input_numbervue_type_script_lang_js_ = (input_numbervue_type_script_lang_js_); \n// EXTERNAL MODULE: ./node_modules/vue-loader/lib/runtime/componentNormalizer.js\nvar componentNormalizer = __webpack_require__(0);\n\n// CONCATENATED MODULE: ./packages/input-number/src/input-number.vue\n\n\n\n\n\n/* normalize component */\n\nvar component = Object(componentNormalizer["a" /* default */])(\n src_input_numbervue_type_script_lang_js_,\n render,\n staticRenderFns,\n false,\n null,\n null,\n null\n \n)\n\n/* hot reload */\nif (false) { var api; }\ncomponent.options.__file = "packages/input-number/src/input-number.vue"\n/* harmony default export */ var input_number = (component.exports);\n// CONCATENATED MODULE: ./packages/input-number/index.js\n\n\n/* istanbul ignore next */\ninput_number.install = function (Vue) {\n Vue.component(input_number.name, input_number);\n};\n\n/* harmony default export */ var packages_input_number = __webpack_exports__["default"] = (input_number);\n\n/***/ }),\n\n/***/ 2:\n/***/ (function(module, exports) {\n\nmodule.exports = __webpack_require__("2kvA");\n\n/***/ }),\n\n/***/ 22:\n/***/ (function(module, exports) {\n\nmodule.exports = __webpack_require__("1oZe");\n\n/***/ }),\n\n/***/ 30:\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n"use strict";\n/* harmony import */ var element_ui_src_utils_dom__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);\n/* harmony import */ var element_ui_src_utils_dom__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(element_ui_src_utils_dom__WEBPACK_IMPORTED_MODULE_0__);\n\n\n/* harmony default export */ __webpack_exports__["a"] = ({\n bind: function bind(el, binding, vnode) {\n var interval = null;\n var startTime = void 0;\n var handler = function handler() {\n return vnode.context[binding.expression].apply();\n };\n var clear = function clear() {\n if (Date.now() - startTime < 100) {\n handler();\n }\n clearInterval(interval);\n interval = null;\n };\n\n Object(element_ui_src_utils_dom__WEBPACK_IMPORTED_MODULE_0__["on"])(el, \'mousedown\', function (e) {\n if (e.button !== 0) return;\n startTime = Date.now();\n Object(element_ui_src_utils_dom__WEBPACK_IMPORTED_MODULE_0__["once"])(document, \'mouseup\', clear);\n clearInterval(interval);\n interval = setInterval(handler, 100);\n });\n }\n});\n\n/***/ })\n\n/******/ });//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMGtZMy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9lbGVtZW50LXVpL2xpYi9pbnB1dC1udW1iZXIuanM/ZDI0NiJdLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9XG4vKioqKioqLyAoZnVuY3Rpb24obW9kdWxlcykgeyAvLyB3ZWJwYWNrQm9vdHN0cmFwXG4vKioqKioqLyBcdC8vIFRoZSBtb2R1bGUgY2FjaGVcbi8qKioqKiovIFx0dmFyIGluc3RhbGxlZE1vZHVsZXMgPSB7fTtcbi8qKioqKiovXG4vKioqKioqLyBcdC8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG4vKioqKioqLyBcdGZ1bmN0aW9uIF9fd2VicGFja19yZXF1aXJlX18obW9kdWxlSWQpIHtcbi8qKioqKiovXG4vKioqKioqLyBcdFx0Ly8gQ2hlY2sgaWYgbW9kdWxlIGlzIGluIGNhY2hlXG4vKioqKioqLyBcdFx0aWYoaW5zdGFsbGVkTW9kdWxlc1ttb2R1bGVJZF0pIHtcbi8qKioqKiovIFx0XHRcdHJldHVybiBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXS5leHBvcnRzO1xuLyoqKioqKi8gXHRcdH1cbi8qKioqKiovIFx0XHQvLyBDcmVhdGUgYSBuZXcgbW9kdWxlIChhbmQgcHV0IGl0IGludG8gdGhlIGNhY2hlKVxuLyoqKioqKi8gXHRcdHZhciBtb2R1bGUgPSBpbnN0YWxsZWRNb2R1bGVzW21vZHVsZUlkXSA9IHtcbi8qKioqKiovIFx0XHRcdGk6IG1vZHVsZUlkLFxuLyoqKioqKi8gXHRcdFx0bDogZmFsc2UsXG4vKioqKioqLyBcdFx0XHRleHBvcnRzOiB7fVxuLyoqKioqKi8gXHRcdH07XG4vKioqKioqL1xuLyoqKioqKi8gXHRcdC8vIEV4ZWN1dGUgdGhlIG1vZHVsZSBmdW5jdGlvblxuLyoqKioqKi8gXHRcdG1vZHVsZXNbbW9kdWxlSWRdLmNhbGwobW9kdWxlLmV4cG9ydHMsIG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuLyoqKioqKi9cbi8qKioqKiovIFx0XHQvLyBGbGFnIHRoZSBtb2R1bGUgYXMgbG9hZGVkXG4vKioqKioqLyBcdFx0bW9kdWxlLmwgPSB0cnVlO1xuLyoqKioqKi9cbi8qKioqKiovIFx0XHQvLyBSZXR1cm4gdGhlIGV4cG9ydHMgb2YgdGhlIG1vZHVsZVxuLyoqKioqKi8gXHRcdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbi8qKioqKiovIFx0fVxuLyoqKioqKi9cbi8qKioqKiovXG4vKioqKioqLyBcdC8vIGV4cG9zZSB0aGUgbW9kdWxlcyBvYmplY3QgKF9fd2VicGFja19tb2R1bGVzX18pXG4vKioqKioqLyBcdF9fd2VicGFja19yZXF1aXJlX18ubSA9IG1vZHVsZXM7XG4vKioqKioqL1xuLyoqKioqKi8gXHQvLyBleHBvc2UgdGhlIG1vZHVsZSBjYWNoZVxuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLmMgPSBpbnN0YWxsZWRNb2R1bGVzO1xuLyoqKioqKi9cbi8qKioqKiovIFx0Ly8gZGVmaW5lIGdldHRlciBmdW5jdGlvbiBmb3IgaGFybW9ueSBleHBvcnRzXG4vKioqKioqLyBcdF9fd2VicGFja19yZXF1aXJlX18uZCA9IGZ1bmN0aW9uKGV4cG9ydHMsIG5hbWUsIGdldHRlcikge1xuLyoqKioqKi8gXHRcdGlmKCFfX3dlYnBhY2tfcmVxdWlyZV9fLm8oZXhwb3J0cywgbmFtZSkpIHtcbi8qKioqKiovIFx0XHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBuYW1lLCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZ2V0dGVyIH0pO1xuLyoqKioqKi8gXHRcdH1cbi8qKioqKiovIFx0fTtcbi8qKioqKiovXG4vKioqKioqLyBcdC8vIGRlZmluZSBfX2VzTW9kdWxlIG9uIGV4cG9ydHNcbi8qKioqKiovIFx0X193ZWJwYWNrX3JlcXVpcmVfXy5yID0gZnVuY3Rpb24oZXhwb3J0cykge1xuLyoqKioqKi8gXHRcdGlmKHR5cGVvZiBTeW1ib2wgIT09ICd1bmRlZmluZWQnICYmIFN5bWJvbC50b1N0cmluZ1RhZykge1xuLyoqKioqKi8gXHRcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFN5bWJvbC50b1N0cmluZ1RhZywgeyB2YWx1ZTogJ01vZHVsZScgfSk7XG4vKioqKioqLyBcdFx0fVxuLyoqKioqKi8gXHRcdE9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCAnX19lc01vZHVsZScsIHsgdmFsdWU6IHRydWUgfSk7XG4vKioqKioqLyBcdH07XG4vKioqKioqL1xuLyoqKioqKi8gXHQvLyBjcmVhdGUgYSBmYWtlIG5hbWVzcGFjZSBvYmplY3Rcbi8qKioqKiovIFx0Ly8gbW9kZSAmIDE6IHZhbHVlIGlzIGEgbW9kdWxlIGlkLCByZXF1aXJlIGl0XG4vKioqKioqLyBcdC8vIG1vZGUgJiAyOiBtZXJnZSBhbGwgcHJvcGVydGllcyBvZiB2YWx1ZSBpbnRvIHRoZSBuc1xuLyoqKioqKi8gXHQvLyBtb2RlICYgNDogcmV0dXJuIHZhbHVlIHdoZW4gYWxyZWFkeSBucyBvYmplY3Rcbi8qKioqKiovIFx0Ly8gbW9kZSAmIDh8MTogYmVoYXZlIGxpa2UgcmVxdWlyZVxuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLnQgPSBmdW5jdGlvbih2YWx1ZSwgbW9kZSkge1xuLyoqKioqKi8gXHRcdGlmKG1vZGUgJiAxKSB2YWx1ZSA9IF9fd2VicGFja19yZXF1aXJlX18odmFsdWUpO1xuLyoqKioqKi8gXHRcdGlmKG1vZGUgJiA4KSByZXR1cm4gdmFsdWU7XG4vKioqKioqLyBcdFx0aWYoKG1vZGUgJiA0KSAmJiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnICYmIHZhbHVlICYmIHZhbHVlLl9fZXNNb2R1bGUpIHJldHVybiB2YWx1ZTtcbi8qKioqKiovIFx0XHR2YXIgbnMgPSBPYmplY3QuY3JlYXRlKG51bGwpO1xuLyoqKioqKi8gXHRcdF9fd2VicGFja19yZXF1aXJlX18ucihucyk7XG4vKioqKioqLyBcdFx0T2JqZWN0LmRlZmluZVByb3BlcnR5KG5zLCAnZGVmYXVsdCcsIHsgZW51bWVyYWJsZTogdHJ1ZSwgdmFsdWU6IHZhbHVlIH0pO1xuLyoqKioqKi8gXHRcdGlmKG1vZGUgJiAyICYmIHR5cGVvZiB2YWx1ZSAhPSAnc3RyaW5nJykgZm9yKHZhciBrZXkgaW4gdmFsdWUpIF9fd2VicGFja19yZXF1aXJlX18uZChucywga2V5LCBmdW5jdGlvbihrZXkpIHsgcmV0dXJuIHZhbHVlW2tleV07IH0uYmluZChudWxsLCBrZXkpKTtcbi8qKioqKiovIFx0XHRyZXR1cm4gbnM7XG4vKioqKioqLyBcdH07XG4vKioqKioqL1xuLyoqKioqKi8gXHQvLyBnZXREZWZhdWx0RXhwb3J0IGZ1bmN0aW9uIGZvciBjb21wYXRpYmlsaXR5IHdpdGggbm9uLWhhcm1vbnkgbW9kdWxlc1xuLyoqKioqKi8gXHRfX3dlYnBhY2tfcmVxdWlyZV9fLm4gPSBmdW5jdGlvbihtb2R1bGUpIHtcbi8qKioqKiovIFx0XHR2YXIgZ2V0dGVyID0gbW9kdWxlICYmIG1vZHVsZS5fX2VzTW9kdWxlID9cbi8qKioqKiovIFx0XHRcdGZ1bmN0aW9uIGdldERlZmF1bHQoKSB7IHJldHVybiBtb2R1bGVbJ2RlZmF1bHQnXTsgfSA6XG4vKioqKioqLyBcdFx0XHRmdW5jdGlvbiBnZXRNb2R1bGVFeHBvcnRzKCkgeyByZXR1cm4gbW9kdWxlOyB9O1xuLyoqKioqKi8gXHRcdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsICdhJywgZ2V0dGVyKTtcbi8qKioqKiovIFx0XHRyZXR1cm4gZ2V0dGVyO1xuLyoqKioqKi8gXHR9O1xuLyoqKioqKi9cbi8qKioqKiovIFx0Ly8gT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsXG4vKioqKioqLyBcdF9fd2VicGFja19yZXF1aXJlX18ubyA9IGZ1bmN0aW9uKG9iamVjdCwgcHJvcGVydHkpIHsgcmV0dXJuIE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChvYmplY3QsIHByb3BlcnR5KTsgfTtcbi8qKioqKiovXG4vKioqKioqLyBcdC8vIF9fd2VicGFja19wdWJsaWNfcGF0aF9fXG4vKioqKioqLyBcdF9fd2VicGFja19yZXF1aXJlX18ucCA9IFwiL2Rpc3QvXCI7XG4vKioqKioqL1xuLyoqKioqKi9cbi8qKioqKiovIFx0Ly8gTG9hZCBlbnRyeSBtb2R1bGUgYW5kIHJldHVybiBleHBvcnRzXG4vKioqKioqLyBcdHJldHVybiBfX3dlYnBhY2tfcmVxdWlyZV9fKF9fd2VicGFja19yZXF1aXJlX18ucyA9IDExNCk7XG4vKioqKioqLyB9KVxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbi8qKioqKiovICh7XG5cbi8qKiovIDA6XG4vKioqLyAoZnVuY3Rpb24obW9kdWxlLCBfX3dlYnBhY2tfZXhwb3J0c19fLCBfX3dlYnBhY2tfcmVxdWlyZV9fKSB7XG5cblwidXNlIHN0cmljdFwiO1xuLyogaGFybW9ueSBleHBvcnQgKGJpbmRpbmcpICovIF9fd2VicGFja19yZXF1aXJlX18uZChfX3dlYnBhY2tfZXhwb3J0c19fLCBcImFcIiwgZnVuY3Rpb24oKSB7IHJldHVybiBub3JtYWxpemVDb21wb25lbnQ7IH0pO1xuLyogZ2xvYmFscyBfX1ZVRV9TU1JfQ09OVEVYVF9fICovXG5cbi8vIElNUE9SVEFOVDogRG8gTk9UIHVzZSBFUzIwMTUgZmVhdHVyZXMgaW4gdGhpcyBmaWxlIChleGNlcHQgZm9yIG1vZHVsZXMpLlxuLy8gVGhpcyBtb2R1bGUgaXMgYSBydW50aW1lIHV0aWxpdHkgZm9yIGNsZWFuZXIgY29tcG9uZW50IG1vZHVsZSBvdXRwdXQgYW5kIHdpbGxcbi8vIGJlIGluY2x1ZGVkIGluIHRoZSBmaW5hbCB3ZWJwYWNrIHVzZXIgYnVuZGxlLlxuXG5mdW5jdGlvbiBub3JtYWxpemVDb21wb25lbnQgKFxuICBzY3JpcHRFeHBvcnRzLFxuICByZW5kZXIsXG4gIHN0YXRpY1JlbmRlckZucyxcbiAgZnVuY3Rpb25hbFRlbXBsYXRlLFxuICBpbmplY3RTdHlsZXMsXG4gIHNjb3BlSWQsXG4gIG1vZHVsZUlkZW50aWZpZXIsIC8qIHNlcnZlciBvbmx5ICovXG4gIHNoYWRvd01vZGUgLyogdnVlLWNsaSBvbmx5ICovXG4pIHtcbiAgLy8gVnVlLmV4dGVuZCBjb25zdHJ1Y3RvciBleHBvcnQgaW50ZXJvcFxuICB2YXIgb3B0aW9ucyA9IHR5cGVvZiBzY3JpcHRFeHBvcnRzID09PSAnZnVuY3Rpb24nXG4gICAgPyBzY3JpcHRFeHBvcnRzLm9wdGlvbnNcbiAgICA6IHNjcmlwdEV4cG9ydHNcblxuICAvLyByZW5kZXIgZnVuY3Rpb25zXG4gIGlmIChyZW5kZXIpIHtcbiAgICBvcHRpb25zLnJlbmRlciA9IHJlbmRlclxuICAgIG9wdGlvbnMuc3RhdGljUmVuZGVyRm5zID0gc3RhdGljUmVuZGVyRm5zXG4gICAgb3B0aW9ucy5fY29tcGlsZWQgPSB0cnVlXG4gIH1cblxuICAvLyBmdW5jdGlvbmFsIHRlbXBsYXRlXG4gIGlmIChmdW5jdGlvbmFsVGVtcGxhdGUpIHtcbiAgICBvcHRpb25zLmZ1bmN0aW9uYWwgPSB0cnVlXG4gIH1cblxuICAvLyBzY29wZWRJZFxuICBpZiAoc2NvcGVJZCkge1xuICAgIG9wdGlvbnMuX3Njb3BlSWQgPSAnZGF0YS12LScgKyBzY29wZUlkXG4gIH1cblxuICB2YXIgaG9va1xuICBpZiAobW9kdWxlSWRlbnRpZmllcikgeyAvLyBzZXJ2ZXIgYnVpbGRcbiAgICBob29rID0gZnVuY3Rpb24gKGNvbnRleHQpIHtcbiAgICAgIC8vIDIuMyBpbmplY3Rpb25cbiAgICAgIGNvbnRleHQgPVxuICAgICAgICBjb250ZXh0IHx8IC8vIGNhY2hlZCBjYWxsXG4gICAgICAgICh0aGlzLiR2bm9kZSAmJiB0aGlzLiR2bm9kZS5zc3JDb250ZXh0KSB8fCAvLyBzdGF0ZWZ1bFxuICAgICAgICAodGhpcy5wYXJlbnQgJiYgdGhpcy5wYXJlbnQuJHZub2RlICYmIHRoaXMucGFyZW50LiR2bm9kZS5zc3JDb250ZXh0KSAvLyBmdW5jdGlvbmFsXG4gICAgICAvLyAyLjIgd2l0aCBydW5Jbk5ld0NvbnRleHQ6IHRydWVcbiAgICAgIGlmICghY29udGV4dCAmJiB0eXBlb2YgX19WVUVfU1NSX0NPTlRFWFRfXyAhPT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgY29udGV4dCA9IF9fVlVFX1NTUl9DT05URVhUX19cbiAgICAgIH1cbiAgICAgIC8vIGluamVjdCBjb21wb25lbnQgc3R5bGVzXG4gICAgICBpZiAoaW5qZWN0U3R5bGVzKSB7XG4gICAgICAgIGluamVjdFN0eWxlcy5jYWxsKHRoaXMsIGNvbnRleHQpXG4gICAgICB9XG4gICAgICAvLyByZWdpc3RlciBjb21wb25lbnQgbW9kdWxlIGlkZW50aWZpZXIgZm9yIGFzeW5jIGNodW5rIGluZmVycmVuY2VcbiAgICAgIGlmIChjb250ZXh0ICYmIGNvbnRleHQuX3JlZ2lzdGVyZWRDb21wb25lbnRzKSB7XG4gICAgICAgIGNvbnRleHQuX3JlZ2lzdGVyZWRDb21wb25lbnRzLmFkZChtb2R1bGVJZGVudGlmaWVyKVxuICAgICAgfVxuICAgIH1cbiAgICAvLyB1c2VkIGJ5IHNzciBpbiBjYXNlIGNvbXBvbmVudCBpcyBjYWNoZWQgYW5kIGJlZm9yZUNyZWF0ZVxuICAgIC8vIG5ldmVyIGdldHMgY2FsbGVkXG4gICAgb3B0aW9ucy5fc3NyUmVnaXN0ZXIgPSBob29rXG4gIH0gZWxzZSBpZiAoaW5qZWN0U3R5bGVzKSB7XG4gICAgaG9vayA9IHNoYWRvd01vZGVcbiAgICAgID8gZnVuY3Rpb24gKCkgeyBpbmplY3RTdHlsZXMuY2FsbCh0aGlzLCB0aGlzLiRyb290LiRvcHRpb25zLnNoYWRvd1Jvb3QpIH1cbiAgICAgIDogaW5qZWN0U3R5bGVzXG4gIH1cblxuICBpZiAoaG9vaykge1xuICAgIGlmIChvcHRpb25zLmZ1bmN0aW9uYWwpIHtcbiAgICAgIC8vIGZvciB0ZW1wbGF0ZS1vbmx5IGhvdC1yZWxvYWQgYmVjYXVzZSBpbiB0aGF0IGNhc2UgdGhlIHJlbmRlciBmbiBkb2Vzbid0XG4gICAgICAvLyBnbyB0aHJvdWdoIHRoZSBub3JtYWxpemVyXG4gICAgICBvcHRpb25zLl9pbmplY3RTdHlsZXMgPSBob29rXG4gICAgICAvLyByZWdpc3RlciBmb3IgZnVuY3Rpb2FsIGNvbXBvbmVudCBpbiB2dWUgZmlsZVxuICAgICAgdmFyIG9yaWdpbmFsUmVuZGVyID0gb3B0aW9ucy5yZW5kZXJcbiAgICAgIG9wdGlvbnMucmVuZGVyID0gZnVuY3Rpb24gcmVuZGVyV2l0aFN0eWxlSW5qZWN0aW9uIChoLCBjb250ZXh0KSB7XG4gICAgICAgIGhvb2suY2FsbChjb250ZXh0KVxuICAgICAgICByZXR1cm4gb3JpZ2luYWxSZW5kZXIoaCwgY29udGV4dClcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaW5qZWN0IGNvbXBvbmVudCByZWdpc3RyYXRpb24gYXMgYmVmb3JlQ3JlYXRlIGhvb2tcbiAgICAgIHZhciBleGlzdGluZyA9IG9wdGlvbnMuYmVmb3JlQ3JlYXRlXG4gICAgICBvcHRpb25zLmJlZm9yZUNyZWF0ZSA9IGV4aXN0aW5nXG4gICAgICAgID8gW10uY29uY2F0KGV4aXN0aW5nLCBob29rKVxuICAgICAgICA6IFtob29rXVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZXhwb3J0czogc2NyaXB0RXhwb3J0cyxcbiAgICBvcHRpb25zOiBvcHRpb25zXG4gIH1cbn1cblxuXG4vKioqLyB9KSxcblxuLyoqKi8gMTA6XG4vKioqLyAoZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcImVsZW1lbnQtdWkvbGliL2lucHV0XCIpO1xuXG4vKioqLyB9KSxcblxuLyoqKi8gMTE0OlxuLyoqKi8gKGZ1bmN0aW9uKG1vZHVsZSwgX193ZWJwYWNrX2V4cG9ydHNfXywgX193ZWJwYWNrX3JlcXVpcmVfXykge1xuXG5cInVzZSBzdHJpY3RcIjtcbl9fd2VicGFja19yZXF1aXJlX18ucihfX3dlYnBhY2tfZXhwb3J0c19fKTtcblxuLy8gQ09OQ0FURU5BVEVEIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvdnVlLWxvYWRlci9saWIvbG9hZGVycy90ZW1wbGF0ZUxvYWRlci5qcz8/dnVlLWxvYWRlci1vcHRpb25zIS4vbm9kZV9tb2R1bGVzL3Z1ZS1sb2FkZXIvbGliPz92dWUtbG9hZGVyLW9wdGlvbnMhLi9wYWNrYWdlcy9pbnB1dC1udW1iZXIvc3JjL2lucHV0LW51bWJlci52dWU/dnVlJnR5cGU9dGVtcGxhdGUmaWQ9NDJmOGNmNjYmXG52YXIgcmVuZGVyID0gZnVuY3Rpb24oKSB7XG4gIHZhciBfdm0gPSB0aGlzXG4gIHZhciBfaCA9IF92bS4kY3JlYXRlRWxlbWVudFxuICB2YXIgX2MgPSBfdm0uX3NlbGYuX2MgfHwgX2hcbiAgcmV0dXJuIF9jKFxuICAgIFwiZGl2XCIsXG4gICAge1xuICAgICAgY2xhc3M6IFtcbiAgICAgICAgXCJlbC1pbnB1dC1udW1iZXJcIixcbiAgICAgICAgX3ZtLmlucHV0TnVtYmVyU2l6ZSA/IFwiZWwtaW5wdXQtbnVtYmVyLS1cIiArIF92bS5pbnB1dE51bWJlclNpemUgOiBcIlwiLFxuICAgICAgICB7IFwiaXMtZGlzYWJsZWRcIjogX3ZtLmlucHV0TnVtYmVyRGlzYWJsZWQgfSxcbiAgICAgICAgeyBcImlzLXdpdGhvdXQtY29udHJvbHNcIjogIV92bS5jb250cm9scyB9LFxuICAgICAgICB7IFwiaXMtY29udHJvbHMtcmlnaHRcIjogX3ZtLmNvbnRyb2xzQXRSaWdodCB9XG4gICAgICBdLFxuICAgICAgb246IHtcbiAgICAgICAgZHJhZ3N0YXJ0OiBmdW5jdGlvbigkZXZlbnQpIHtcbiAgICAgICAgICAkZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSxcbiAgICBbXG4gICAgICBfdm0uY29udHJvbHNcbiAgICAgICAgPyBfYyhcbiAgICAgICAgICAgIFwic3BhblwiLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBkaXJlY3RpdmVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgbmFtZTogXCJyZXBlYXQtY2xpY2tcIixcbiAgICAgICAgICAgICAgICAgIHJhd05hbWU6IFwidi1yZXBlYXQtY2xpY2tcIixcbiAgICAgICAgICAgICAgICAgIHZhbHVlOiBfdm0uZGVjcmVhc2UsXG4gICAgICAgICAgICAgICAgICBleHByZXNzaW9uOiBcImRlY3JlYXNlXCJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIHN0YXRpY0NsYXNzOiBcImVsLWlucHV0LW51bWJlcl9fZGVjcmVhc2VcIixcbiAgICAgICAgICAgICAgY2xhc3M6IHsgXCJpcy1kaXNhYmxlZFwiOiBfdm0ubWluRGlzYWJsZWQgfSxcbiAgICAgICAgICAgICAgYXR0cnM6IHsgcm9sZTogXCJidXR0b25cIiB9LFxuICAgICAgICAgICAgICBvbjoge1xuICAgICAgICAgICAgICAgIGtleWRvd246IGZ1bmN0aW9uKCRldmVudCkge1xuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAhKFwiYnV0dG9uXCIgaW4gJGV2ZW50KSAmJlxuICAgICAgICAgICAgICAgICAgICBfdm0uX2soJGV2ZW50LmtleUNvZGUsIFwiZW50ZXJcIiwgMTMsICRldmVudC5rZXksIFwiRW50ZXJcIilcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgcmV0dXJuIF92bS5kZWNyZWFzZSgkZXZlbnQpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICBfYyhcImlcIiwge1xuICAgICAgICAgICAgICAgIGNsYXNzOlxuICAgICAgICAgICAgICAgICAgXCJlbC1pY29uLVwiICsgKF92bS5jb250cm9sc0F0UmlnaHQgPyBcImFycm93LWRvd25cIiA6IFwibWludXNcIilcbiAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgIF1cbiAgICAgICAgICApXG4gICAgICAgIDogX3ZtLl9lKCksXG4gICAgICBfdm0uY29udHJvbHNcbiAgICAgICAgPyBfYyhcbiAgICAgICAgICAgIFwic3BhblwiLFxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICBkaXJlY3RpdmVzOiBbXG4gICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgbmFtZTogXCJyZXBlYXQtY2xpY2tcIixcbiAgICAgICAgICAgICAgICAgIHJhd05hbWU6IFwidi1yZXBlYXQtY2xpY2tcIixcbiAgICAgICAgICAgICAgICAgIHZhbHVlOiBfdm0uaW5jcmVhc2UsXG4gICAgICAgICAgICAgICAgICBleHByZXNzaW9uOiBcImluY3JlYXNlXCJcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgIHN0YXRpY0NsYXNzOiBcImVsLWlucHV0LW51bWJlcl9faW5jcmVhc2VcIixcbiAgICAgICAgICAgICAgY2xhc3M6IHsgXCJpcy1kaXNhYmxlZFwiOiBfdm0ubWF4RGlzYWJsZWQgfSxcbiAgICAgICAgICAgICAgYXR0cnM6IHsgcm9sZTogXCJidXR0b25cIiB9LFxuICAgICAgICAgICAgICBvbjoge1xuICAgICAgICAgICAgICAgIGtleWRvd246IGZ1bmN0aW9uKCRldmVudCkge1xuICAgICAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICAgICAhKFwiYnV0dG9uXCIgaW4gJGV2ZW50KSAmJlxuICAgICAgICAgICAgICAgICAgICBfdm0uX2soJGV2ZW50LmtleUNvZGUsIFwiZW50ZXJcIiwgMTMsICRldmVudC5rZXksIFwiRW50ZXJcIilcbiAgICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbnVsbFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgcmV0dXJuIF92bS5pbmNyZWFzZSgkZXZlbnQpXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW1xuICAgICAgICAgICAgICBfYyhcImlcIiwge1xuICAgICAgICAgICAgICAgIGNsYXNzOiBcImVsLWljb24tXCIgKyAoX3ZtLmNvbnRyb2xzQXRSaWdodCA/IFwiYXJyb3ctdXBcIiA6IFwicGx1c1wiKVxuICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgXVxuICAgICAgICAgIClcbiAgICAgICAgOiBfdm0uX2UoKSxcbiAgICAgIF9jKFwiZWwtaW5wdXRcIiwge1xuICAgICAgICByZWY6IFwiaW5wdXRcIixcbiAgICAgICAgYXR0cnM6IHtcbiAgICAgICAgICB2YWx1ZTogX3ZtLmRpc3BsYXlWYWx1ZSxcbiAgICAgICAgICBwbGFjZWhvbGRlcjogX3ZtLnBsYWNlaG9sZGVyLFxuICAgICAgICAgIGRpc2FibGVkOiBfdm0uaW5wdXROdW1iZXJEaXNhYmxlZCxcbiAgICAgICAgICBzaXplOiBfdm0uaW5wdXROdW1iZXJTaXplLFxuICAgICAgICAgIG1heDogX3ZtLm1heCxcbiAgICAgICAgICBtaW46IF92bS5taW4sXG4gICAgICAgICAgbmFtZTogX3ZtLm5hbWUsXG4gICAgICAgICAgbGFiZWw6IF92bS5sYWJlbFxuICAgICAgICB9LFxuICAgICAgICBvbjoge1xuICAgICAgICAgIGJsdXI6IF92bS5oYW5kbGVCbHVyLFxuICAgICAgICAgIGZvY3VzOiBfdm0uaGFuZGxlRm9jdXMsXG4gICAgICAgICAgaW5wdXQ6IF92bS5oYW5kbGVJbnB1dCxcbiAgICAgICAgICBjaGFuZ2U6IF92bS5oYW5kbGVJbnB1dENoYW5nZVxuICAgICAgICB9LFxuICAgICAgICBuYXRpdmVPbjoge1xuICAgICAgICAgIGtleWRvd246IFtcbiAgICAgICAgICAgIGZ1bmN0aW9uKCRldmVudCkge1xuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIShcImJ1dHRvblwiIGluICRldmVudCkgJiZcbiAgICAgICAgICAgICAgICBfdm0uX2soJGV2ZW50LmtleUNvZGUsIFwidXBcIiwgMzgsICRldmVudC5rZXksIFtcIlVwXCIsIFwiQXJyb3dVcFwiXSlcbiAgICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGxcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAkZXZlbnQucHJldmVudERlZmF1bHQoKVxuICAgICAgICAgICAgICByZXR1cm4gX3ZtLmluY3JlYXNlKCRldmVudClcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmdW5jdGlvbigkZXZlbnQpIHtcbiAgICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICAgICEoXCJidXR0b25cIiBpbiAkZXZlbnQpICYmXG4gICAgICAgICAgICAgICAgX3ZtLl9rKCRldmVudC5rZXlDb2RlLCBcImRvd25cIiwgNDAsICRldmVudC5rZXksIFtcbiAgICAgICAgICAgICAgICAgIFwiRG93blwiLFxuICAgICAgICAgICAgICAgICAgXCJBcnJvd0Rvd25cIlxuICAgICAgICAgICAgICAgIF0pXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgJGV2ZW50LnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgICAgICAgcmV0dXJuIF92bS5kZWNyZWFzZSgkZXZlbnQpXG4gICAgICAgICAgICB9XG4gICAgICAgICAgXVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIF0sXG4gICAgMVxuICApXG59XG52YXIgc3RhdGljUmVuZGVyRm5zID0gW11cbnJlbmRlci5fd2l0aFN0cmlwcGVkID0gdHJ1ZVxuXG5cbi8vIENPTkNBVEVOQVRFRCBNT0RVTEU6IC4vcGFja2FnZXMvaW5wdXQtbnVtYmVyL3NyYy9pbnB1dC1udW1iZXIudnVlP3Z1ZSZ0eXBlPXRlbXBsYXRlJmlkPTQyZjhjZjY2JlxuXG4vLyBFWFRFUk5BTCBNT0RVTEU6IGV4dGVybmFsIFwiZWxlbWVudC11aS9saWIvaW5wdXRcIlxudmFyIGlucHV0XyA9IF9fd2VicGFja19yZXF1aXJlX18oMTApO1xudmFyIGlucHV0X2RlZmF1bHQgPSAvKiNfX1BVUkVfXyovX193ZWJwYWNrX3JlcXVpcmVfXy5uKGlucHV0Xyk7XG5cbi8vIEVYVEVSTkFMIE1PRFVMRTogZXh0ZXJuYWwgXCJlbGVtZW50LXVpL2xpYi9taXhpbnMvZm9jdXNcIlxudmFyIGZvY3VzXyA9IF9fd2VicGFja19yZXF1aXJlX18oMjIpO1xudmFyIGZvY3VzX2RlZmF1bHQgPSAvKiNfX1BVUkVfXyovX193ZWJwYWNrX3JlcXVpcmVfXy5uKGZvY3VzXyk7XG5cbi8vIEVYVEVSTkFMIE1PRFVMRTogLi9zcmMvZGlyZWN0aXZlcy9yZXBlYXQtY2xpY2suanNcbnZhciByZXBlYXRfY2xpY2sgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDMwKTtcblxuLy8gQ09OQ0FURU5BVEVEIE1PRFVMRTogLi9ub2RlX21vZHVsZXMvYmFiZWwtbG9hZGVyL2xpYiEuL25vZGVfbW9kdWxlcy92dWUtbG9hZGVyL2xpYj8/dnVlLWxvYWRlci1vcHRpb25zIS4vcGFja2FnZXMvaW5wdXQtbnVtYmVyL3NyYy9pbnB1dC1udW1iZXIudnVlP3Z1ZSZ0eXBlPXNjcmlwdCZsYW5nPWpzJlxuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG4vL1xuLy9cbi8vXG5cblxuXG5cblxuLyogaGFybW9ueSBkZWZhdWx0IGV4cG9ydCAqLyB2YXIgaW5wdXRfbnVtYmVydnVlX3R5cGVfc2NyaXB0X2xhbmdfanNfID0gKHtcbiAgbmFtZTogJ0VsSW5wdXROdW1iZXInLFxuICBtaXhpbnM6IFtmb2N1c19kZWZhdWx0KCkoJ2lucHV0JyldLFxuICBpbmplY3Q6IHtcbiAgICBlbEZvcm06IHtcbiAgICAgIGRlZmF1bHQ6ICcnXG4gICAgfSxcbiAgICBlbEZvcm1JdGVtOiB7XG4gICAgICBkZWZhdWx0OiAnJ1xuICAgIH1cbiAgfSxcbiAgZGlyZWN0aXZlczoge1xuICAgIHJlcGVhdENsaWNrOiByZXBlYXRfY2xpY2tbXCJhXCIgLyogZGVmYXVsdCAqL11cbiAgfSxcbiAgY29tcG9uZW50czoge1xuICAgIEVsSW5wdXQ6IGlucHV0X2RlZmF1bHQuYVxuICB9LFxuICBwcm9wczoge1xuICAgIHN0ZXA6IHtcbiAgICAgIHR5cGU6IE51bWJlcixcbiAgICAgIGRlZmF1bHQ6IDFcbiAgICB9LFxuICAgIHN0ZXBTdHJpY3RseToge1xuICAgICAgdHlwZTogQm9vbGVhbixcbiAgICAgIGRlZmF1bHQ6IGZhbHNlXG4gICAgfSxcbiAgICBtYXg6IHtcbiAgICAgIHR5cGU6IE51bWJlcixcbiAgICAgIGRlZmF1bHQ6IEluZmluaXR5XG4gICAgfSxcbiAgICBtaW46IHtcbiAgICAgIHR5cGU6IE51bWJlcixcbiAgICAgIGRlZmF1bHQ6IC1JbmZpbml0eVxuICAgIH0sXG4gICAgdmFsdWU6IHt9LFxuICAgIGRpc2FibGVkOiBCb29sZWFuLFxuICAgIHNpemU6IFN0cmluZyxcbiAgICBjb250cm9sczoge1xuICAgICAgdHlwZTogQm9vbGVhbixcbiAgICAgIGRlZmF1bHQ6IHRydWVcbiAgICB9LFxuICAgIGNvbnRyb2xzUG9zaXRpb246IHtcbiAgICAgIHR5cGU6IFN0cmluZyxcbiAgICAgIGRlZmF1bHQ6ICcnXG4gICAgfSxcbiAgICBuYW1lOiBTdHJpbmcsXG4gICAgbGFiZWw6IFN0cmluZyxcbiAgICBwbGFjZWhvbGRlcjogU3RyaW5nLFxuICAgIHByZWNpc2lvbjoge1xuICAgICAgdHlwZTogTnVtYmVyLFxuICAgICAgdmFsaWRhdG9yOiBmdW5jdGlvbiB2YWxpZGF0b3IodmFsKSB7XG4gICAgICAgIHJldHVybiB2YWwgPj0gMCAmJiB2YWwgPT09IHBhcnNlSW50KHZhbCwgMTApO1xuICAgICAgfVxuICAgIH1cbiAgfSxcbiAgZGF0YTogZnVuY3Rpb24gZGF0YSgpIHtcbiAgICByZXR1cm4ge1xuICAgICAgY3VycmVudFZhbHVlOiAwLFxuICAgICAgdXNlcklucHV0OiBudWxsXG4gICAgfTtcbiAgfSxcblxuICB3YXRjaDoge1xuICAgIHZhbHVlOiB7XG4gICAgICBpbW1lZGlhdGU6IHRydWUsXG4gICAgICBoYW5kbGVyOiBmdW5jdGlvbiBoYW5kbGVyKHZhbHVlKSB7XG4gICAgICAgIHZhciBuZXdWYWwgPSB2YWx1ZSA9PT0gdW5kZWZpbmVkID8gdmFsdWUgOiBOdW1iZXIodmFsdWUpO1xuICAgICAgICBpZiAobmV3VmFsICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgICBpZiAoaXNOYU4obmV3VmFsKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmICh0aGlzLnN0ZXBTdHJpY3RseSkge1xuICAgICAgICAgICAgdmFyIHN0ZXBQcmVjaXNpb24gPSB0aGlzLmdldFByZWNpc2lvbih0aGlzLnN0ZXApO1xuICAgICAgICAgICAgdmFyIHByZWNpc2lvbkZhY3RvciA9IE1hdGgucG93KDEwLCBzdGVwUHJlY2lzaW9uKTtcbiAgICAgICAgICAgIG5ld1ZhbCA9IE1hdGgucm91bmQobmV3VmFsIC8gdGhpcy5zdGVwKSAqIHByZWNpc2lvbkZhY3RvciAqIHRoaXMuc3RlcCAvIHByZWNpc2lvbkZhY3RvcjtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAodGhpcy5wcmVjaXNpb24gIT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgbmV3VmFsID0gdGhpcy50b1ByZWNpc2lvbihuZXdWYWwsIHRoaXMucHJlY2lzaW9uKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG5ld1ZhbCA+PSB0aGlzLm1heCkgbmV3VmFsID0gdGhpcy5tYXg7XG4gICAgICAgIGlmIChuZXdWYWwgPD0gdGhpcy5taW4pIG5ld1ZhbCA9IHRoaXMubWluO1xuICAgICAgICB0aGlzLmN1cnJlbnRWYWx1ZSA9IG5ld1ZhbDtcbiAgICAgICAgdGhpcy51c2VySW5wdXQgPSBudWxsO1xuICAgICAgICB0aGlzLiRlbWl0KCdpbnB1dCcsIG5ld1ZhbCk7XG4gICAgICB9XG4gICAgfVxuICB9LFxuICBjb21wdXRlZDoge1xuICAgIG1pbkRpc2FibGVkOiBmdW5jdGlvbiBtaW5EaXNhYmxlZCgpIHtcbiAgICAgIHJldHVybiB0aGlzLl9kZWNyZWFzZSh0aGlzLnZhbHVlLCB0aGlzLnN0ZXApIDwgdGhpcy5taW47XG4gICAgfSxcbiAgICBtYXhEaXNhYmxlZDogZnVuY3Rpb24gbWF4RGlzYWJsZWQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5faW5jcmVhc2UodGhpcy52YWx1ZSwgdGhpcy5zdGVwKSA+IHRoaXMubWF4O1xuICAgIH0sXG4gICAgbnVtUHJlY2lzaW9uOiBmdW5jdGlvbiBudW1QcmVjaXNpb24oKSB7XG4gICAgICB2YXIgdmFsdWUgPSB0aGlzLnZhbHVlLFxuICAgICAgICAgIHN0ZXAgPSB0aGlzLnN0ZXAsXG4gICAgICAgICAgZ2V0UHJlY2lzaW9uID0gdGhpcy5nZXRQcmVjaXNpb24sXG4gICAgICAgICAgcHJlY2lzaW9uID0gdGhpcy5wcmVjaXNpb247XG5cbiAgICAgIHZhciBzdGVwUHJlY2lzaW9uID0gZ2V0UHJlY2lzaW9uKHN0ZXApO1xuICAgICAgaWYgKHByZWNpc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGlmIChzdGVwUHJlY2lzaW9uID4gcHJlY2lzaW9uKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdbRWxlbWVudCBXYXJuXVtJbnB1dE51bWJlcl1wcmVjaXNpb24gc2hvdWxkIG5vdCBiZSBsZXNzIHRoYW4gdGhlIGRlY2ltYWwgcGxhY2VzIG9mIHN0ZXAnKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gcHJlY2lzaW9uO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KGdldFByZWNpc2lvbih2YWx1ZSksIHN0ZXBQcmVjaXNpb24pO1xuICAgICAgfVxuICAgIH0sXG4gICAgY29udHJvbHNBdFJpZ2h0OiBmdW5jdGlvbiBjb250cm9sc0F0UmlnaHQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5jb250cm9scyAmJiB0aGlzLmNvbnRyb2xzUG9zaXRpb24gPT09ICdyaWdodCc7XG4gICAgfSxcbiAgICBfZWxGb3JtSXRlbVNpemU6IGZ1bmN0aW9uIF9lbEZvcm1JdGVtU2l6ZSgpIHtcbiAgICAgIHJldHVybiAodGhpcy5lbEZvcm1JdGVtIHx8IHt9KS5lbEZvcm1JdGVtU2l6ZTtcbiAgICB9LFxuICAgIGlucHV0TnVtYmVyU2l6ZTogZnVuY3Rpb24gaW5wdXROdW1iZXJTaXplKCkge1xuICAgICAgcmV0dXJuIHRoaXMuc2l6ZSB8fCB0aGlzLl9lbEZvcm1JdGVtU2l6ZSB8fCAodGhpcy4kRUxFTUVOVCB8fCB7fSkuc2l6ZTtcbiAgICB9LFxuICAgIGlucHV0TnVtYmVyRGlzYWJsZWQ6IGZ1bmN0aW9uIGlucHV0TnVtYmVyRGlzYWJsZWQoKSB7XG4gICAgICByZXR1cm4gdGhpcy5kaXNhYmxlZCB8fCAhISh0aGlzLmVsRm9ybSB8fCB7fSkuZGlzYWJsZWQ7XG4gICAgfSxcbiAgICBkaXNwbGF5VmFsdWU6IGZ1bmN0aW9uIGRpc3BsYXlWYWx1ZSgpIHtcbiAgICAgIGlmICh0aGlzLnVzZXJJbnB1dCAhPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdGhpcy51c2VySW5wdXQ7XG4gICAgICB9XG5cbiAgICAgIHZhciBjdXJyZW50VmFsdWUgPSB0aGlzLmN1cnJlbnRWYWx1ZTtcblxuICAgICAgaWYgKHR5cGVvZiBjdXJyZW50VmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGlmICh0aGlzLnN0ZXBTdHJpY3RseSkge1xuICAgICAgICAgIHZhciBzdGVwUHJlY2lzaW9uID0gdGhpcy5nZXRQcmVjaXNpb24odGhpcy5zdGVwKTtcbiAgICAgICAgICB2YXIgcHJlY2lzaW9uRmFjdG9yID0gTWF0aC5wb3coMTAsIHN0ZXBQcmVjaXNpb24pO1xuICAgICAgICAgIGN1cnJlbnRWYWx1ZSA9IE1hdGgucm91bmQoY3VycmVudFZhbHVlIC8gdGhpcy5zdGVwKSAqIHByZWNpc2lvbkZhY3RvciAqIHRoaXMuc3RlcCAvIHByZWNpc2lvbkZhY3RvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnByZWNpc2lvbiAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgY3VycmVudFZhbHVlID0gY3VycmVudFZhbHVlLnRvRml4ZWQodGhpcy5wcmVjaXNpb24pO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBjdXJyZW50VmFsdWU7XG4gICAgfVxuICB9LFxuICBtZXRob2RzOiB7XG4gICAgdG9QcmVjaXNpb246IGZ1bmN0aW9uIHRvUHJlY2lzaW9uKG51bSwgcHJlY2lzaW9uKSB7XG4gICAgICBpZiAocHJlY2lzaW9uID09PSB1bmRlZmluZWQpIHByZWNpc2lvbiA9IHRoaXMubnVtUHJlY2lzaW9uO1xuICAgICAgcmV0dXJuIHBhcnNlRmxvYXQoTWF0aC5yb3VuZChudW0gKiBNYXRoLnBvdygxMCwgcHJlY2lzaW9uKSkgLyBNYXRoLnBvdygxMCwgcHJlY2lzaW9uKSk7XG4gICAgfSxcbiAgICBnZXRQcmVjaXNpb246IGZ1bmN0aW9uIGdldFByZWNpc2lvbih2YWx1ZSkge1xuICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVybiAwO1xuICAgICAgdmFyIHZhbHVlU3RyaW5nID0gdmFsdWUudG9TdHJpbmcoKTtcbiAgICAgIHZhciBkb3RQb3NpdGlvbiA9IHZhbHVlU3RyaW5nLmluZGV4T2YoJy4nKTtcbiAgICAgIHZhciBwcmVjaXNpb24gPSAwO1xuICAgICAgaWYgKGRvdFBvc2l0aW9uICE9PSAtMSkge1xuICAgICAgICBwcmVjaXNpb24gPSB2YWx1ZVN0cmluZy5sZW5ndGggLSBkb3RQb3NpdGlvbiAtIDE7XG4gICAgICB9XG4gICAgICByZXR1cm4gcHJlY2lzaW9uO1xuICAgIH0sXG4gICAgX2luY3JlYXNlOiBmdW5jdGlvbiBfaW5jcmVhc2UodmFsLCBzdGVwKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbCAhPT0gJ251bWJlcicgJiYgdmFsICE9PSB1bmRlZmluZWQpIHJldHVybiB0aGlzLmN1cnJlbnRWYWx1ZTtcblxuICAgICAgdmFyIHByZWNpc2lvbkZhY3RvciA9IE1hdGgucG93KDEwLCB0aGlzLm51bVByZWNpc2lvbik7XG4gICAgICAvLyBTb2x2ZSB0aGUgYWNjdXJhY3kgcHJvYmxlbSBvZiBKUyBkZWNpbWFsIGNhbGN1bGF0aW9uIGJ5IGNvbnZlcnRpbmcgdGhlIHZhbHVlIHRvIGludGVnZXIuXG4gICAgICByZXR1cm4gdGhpcy50b1ByZWNpc2lvbigocHJlY2lzaW9uRmFjdG9yICogdmFsICsgcHJlY2lzaW9uRmFjdG9yICogc3RlcCkgLyBwcmVjaXNpb25GYWN0b3IpO1xuICAgIH0sXG4gICAgX2RlY3JlYXNlOiBmdW5jdGlvbiBfZGVjcmVhc2UodmFsLCBzdGVwKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbCAhPT0gJ251bWJlcicgJiYgdmFsICE9PSB1bmRlZmluZWQpIHJldHVybiB0aGlzLmN1cnJlbnRWYWx1ZTtcblxuICAgICAgdmFyIHByZWNpc2lvbkZhY3RvciA9IE1hdGgucG93KDEwLCB0aGlzLm51bVByZWNpc2lvbik7XG5cbiAgICAgIHJldHVybiB0aGlzLnRvUHJlY2lzaW9uKChwcmVjaXNpb25GYWN0b3IgKiB2YWwgLSBwcmVjaXNpb25GYWN0b3IgKiBzdGVwKSAvIHByZWNpc2lvbkZhY3Rvcik7XG4gICAgfSxcbiAgICBpbmNyZWFzZTogZnVuY3Rpb24gaW5jcmVhc2UoKSB7XG4gICAgICBpZiAodGhpcy5pbnB1dE51bWJlckRpc2FibGVkIHx8IHRoaXMubWF4RGlzYWJsZWQpIHJldHVybjtcbiAgICAgIHZhciB2YWx1ZSA9IHRoaXMudmFsdWUgfHwgMDtcbiAgICAgIHZhciBuZXdWYWwgPSB0aGlzLl9pbmNyZWFzZSh2YWx1ZSwgdGhpcy5zdGVwKTtcbiAgICAgIHRoaXMuc2V0Q3VycmVudFZhbHVlKG5ld1ZhbCk7XG4gICAgfSxcbiAgICBkZWNyZWFzZTogZnVuY3Rpb24gZGVjcmVhc2UoKSB7XG4gICAgICBpZiAodGhpcy5pbnB1dE51bWJlckRpc2FibGVkIHx8IHRoaXMubWluRGlzYWJsZWQpIHJldHVybjtcbiAgICAgIHZhciB2YWx1ZSA9IHRoaXMudmFsdWUgfHwgMDtcbiAgICAgIHZhciBuZXdWYWwgPSB0aGlzLl9kZWNyZWFzZSh2YWx1ZSwgdGhpcy5zdGVwKTtcbiAgICAgIHRoaXMuc2V0Q3VycmVudFZhbHVlKG5ld1ZhbCk7XG4gICAgfSxcbiAgICBoYW5kbGVCbHVyOiBmdW5jdGlvbiBoYW5kbGVCbHVyKGV2ZW50KSB7XG4gICAgICB0aGlzLiRlbWl0KCdibHVyJywgZXZlbnQpO1xuICAgIH0sXG4gICAgaGFuZGxlRm9jdXM6IGZ1bmN0aW9uIGhhbmRsZUZvY3VzKGV2ZW50KSB7XG4gICAgICB0aGlzLiRlbWl0KCdmb2N1cycsIGV2ZW50KTtcbiAgICB9LFxuICAgIHNldEN1cnJlbnRWYWx1ZTogZnVuY3Rpb24gc2V0Q3VycmVudFZhbHVlKG5ld1ZhbCkge1xuICAgICAgdmFyIG9sZFZhbCA9IHRoaXMuY3VycmVudFZhbHVlO1xuICAgICAgaWYgKHR5cGVvZiBuZXdWYWwgPT09ICdudW1iZXInICYmIHRoaXMucHJlY2lzaW9uICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgbmV3VmFsID0gdGhpcy50b1ByZWNpc2lvbihuZXdWYWwsIHRoaXMucHJlY2lzaW9uKTtcbiAgICAgIH1cbiAgICAgIGlmIChuZXdWYWwgPj0gdGhpcy5tYXgpIG5ld1ZhbCA9IHRoaXMubWF4O1xuICAgICAgaWYgKG5ld1ZhbCA8PSB0aGlzLm1pbikgbmV3VmFsID0gdGhpcy5taW47XG4gICAgICBpZiAob2xkVmFsID09PSBuZXdWYWwpIHJldHVybjtcbiAgICAgIHRoaXMudXNlcklucHV0ID0gbnVsbDtcbiAgICAgIHRoaXMuJGVtaXQoJ2lucHV0JywgbmV3VmFsKTtcbiAgICAgIHRoaXMuJGVtaXQoJ2NoYW5nZScsIG5ld1ZhbCwgb2xkVmFsKTtcbiAgICAgIHRoaXMuY3VycmVudFZhbHVlID0gbmV3VmFsO1xuICAgIH0sXG4gICAgaGFuZGxlSW5wdXQ6IGZ1bmN0aW9uIGhhbmRsZUlucHV0KHZhbHVlKSB7XG4gICAgICB0aGlzLnVzZXJJbnB1dCA9IHZhbHVlO1xuICAgIH0sXG4gICAgaGFuZGxlSW5wdXRDaGFuZ2U6IGZ1bmN0aW9uIGhhbmRsZUlucHV0Q2hhbmdlKHZhbHVlKSB7XG4gICAgICB2YXIgbmV3VmFsID0gdmFsdWUgPT09ICcnID8gdW5kZWZpbmVkIDogTnVtYmVyKHZhbHVlKTtcbiAgICAgIGlmICghaXNOYU4obmV3VmFsKSB8fCB2YWx1ZSA9PT0gJycpIHtcbiAgICAgICAgdGhpcy5zZXRDdXJyZW50VmFsdWUobmV3VmFsKTtcbiAgICAgIH1cbiAgICAgIHRoaXMudXNlcklucHV0ID0gbnVsbDtcbiAgICB9LFxuICAgIHNlbGVjdDogZnVuY3Rpb24gc2VsZWN0KCkge1xuICAgICAgdGhpcy4kcmVmcy5pbnB1dC5zZWxlY3QoKTtcbiAgICB9XG4gIH0sXG4gIG1vdW50ZWQ6IGZ1bmN0aW9uIG1vdW50ZWQoKSB7XG4gICAgdmFyIGlubmVySW5wdXQgPSB0aGlzLiRyZWZzLmlucHV0LiRyZWZzLmlucHV0O1xuICAgIGlubmVySW5wdXQuc2V0QXR0cmlidXRlKCdyb2xlJywgJ3NwaW5idXR0b24nKTtcbiAgICBpbm5lcklucHV0LnNldEF0dHJpYnV0ZSgnYXJpYS12YWx1ZW1heCcsIHRoaXMubWF4KTtcbiAgICBpbm5lcklucHV0LnNldEF0dHJpYnV0ZSgnYXJpYS12YWx1ZW1pbicsIHRoaXMubWluKTtcbiAgICBpbm5lcklucHV0LnNldEF0dHJpYnV0ZSgnYXJpYS12YWx1ZW5vdycsIHRoaXMuY3VycmVudFZhbHVlKTtcbiAgICBpbm5lcklucHV0LnNldEF0dHJpYnV0ZSgnYXJpYS1kaXNhYmxlZCcsIHRoaXMuaW5wdXROdW1iZXJEaXNhYmxlZCk7XG4gIH0sXG4gIHVwZGF0ZWQ6IGZ1bmN0aW9uIHVwZGF0ZWQoKSB7XG4gICAgaWYgKCF0aGlzLiRyZWZzIHx8ICF0aGlzLiRyZWZzLmlucHV0KSByZXR1cm47XG4gICAgdmFyIGlubmVySW5wdXQgPSB0aGlzLiRyZWZzLmlucHV0LiRyZWZzLmlucHV0O1xuICAgIGlubmVySW5wdXQuc2V0QXR0cmlidXRlKCdhcmlhLXZhbHVlbm93JywgdGhpcy5jdXJyZW50VmFsdWUpO1xuICB9XG59KTtcbi8vIENPTkNBVEVOQVRFRCBNT0RVTEU6IC4vcGFja2FnZXMvaW5wdXQtbnVtYmVyL3NyYy9pbnB1dC1udW1iZXIudnVlP3Z1ZSZ0eXBlPXNjcmlwdCZsYW5nPWpzJlxuIC8qIGhhcm1vbnkgZGVmYXVsdCBleHBvcnQgKi8gdmFyIHNyY19pbnB1dF9udW1iZXJ2dWVfdHlwZV9zY3JpcHRfbGFuZ19qc18gPSAoaW5wdXRfbnVtYmVydnVlX3R5cGVfc2NyaXB0X2xhbmdfanNfKTsgXG4vLyBFWFRFUk5BTCBNT0RVTEU6IC4vbm9kZV9tb2R1bGVzL3Z1ZS1sb2FkZXIvbGliL3J1bnRpbWUvY29tcG9uZW50Tm9ybWFsaXplci5qc1xudmFyIGNvbXBvbmVudE5vcm1hbGl6ZXIgPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDApO1xuXG4vLyBDT05DQVRFTkFURUQgTU9EVUxFOiAuL3BhY2thZ2VzL2lucHV0LW51bWJlci9zcmMvaW5wdXQtbnVtYmVyLnZ1ZVxuXG5cblxuXG5cbi8qIG5vcm1hbGl6ZSBjb21wb25lbnQgKi9cblxudmFyIGNvbXBvbmVudCA9IE9iamVjdChjb21wb25lbnROb3JtYWxpemVyW1wiYVwiIC8qIGRlZmF1bHQgKi9dKShcbiAgc3JjX2lucHV0X251bWJlcnZ1ZV90eXBlX3NjcmlwdF9sYW5nX2pzXyxcbiAgcmVuZGVyLFxuICBzdGF0aWNSZW5kZXJGbnMsXG4gIGZhbHNlLFxuICBudWxsLFxuICBudWxsLFxuICBudWxsXG4gIFxuKVxuXG4vKiBob3QgcmVsb2FkICovXG5pZiAoZmFsc2UpIHsgdmFyIGFwaTsgfVxuY29tcG9uZW50Lm9wdGlvbnMuX19maWxlID0gXCJwYWNrYWdlcy9pbnB1dC1udW1iZXIvc3JjL2lucHV0LW51bWJlci52dWVcIlxuLyogaGFybW9ueSBkZWZhdWx0IGV4cG9ydCAqLyB2YXIgaW5wdXRfbnVtYmVyID0gKGNvbXBvbmVudC5leHBvcnRzKTtcbi8vIENPTkNBVEVOQVRFRCBNT0RVTEU6IC4vcGFja2FnZXMvaW5wdXQtbnVtYmVyL2luZGV4LmpzXG5cblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmlucHV0X251bWJlci5pbnN0YWxsID0gZnVuY3Rpb24gKFZ1ZSkge1xuICBWdWUuY29tcG9uZW50KGlucHV0X251bWJlci5uYW1lLCBpbnB1dF9udW1iZXIpO1xufTtcblxuLyogaGFybW9ueSBkZWZhdWx0IGV4cG9ydCAqLyB2YXIgcGFja2FnZXNfaW5wdXRfbnVtYmVyID0gX193ZWJwYWNrX2V4cG9ydHNfX1tcImRlZmF1bHRcIl0gPSAoaW5wdXRfbnVtYmVyKTtcblxuLyoqKi8gfSksXG5cbi8qKiovIDI6XG4vKioqLyAoZnVuY3Rpb24obW9kdWxlLCBleHBvcnRzKSB7XG5cbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZShcImVsZW1lbnQtdWkvbGliL3V0aWxzL2RvbVwiKTtcblxuLyoqKi8gfSksXG5cbi8qKiovIDIyOlxuLyoqKi8gKGZ1bmN0aW9uKG1vZHVsZSwgZXhwb3J0cykge1xuXG5tb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoXCJlbGVtZW50LXVpL2xpYi9taXhpbnMvZm9jdXNcIik7XG5cbi8qKiovIH0pLFxuXG4vKioqLyAzMDpcbi8qKiovIChmdW5jdGlvbihtb2R1bGUsIF9fd2VicGFja19leHBvcnRzX18sIF9fd2VicGFja19yZXF1aXJlX18pIHtcblxuXCJ1c2Ugc3RyaWN0XCI7XG4vKiBoYXJtb255IGltcG9ydCAqLyB2YXIgZWxlbWVudF91aV9zcmNfdXRpbHNfZG9tX19XRUJQQUNLX0lNUE9SVEVEX01PRFVMRV8wX18gPSBfX3dlYnBhY2tfcmVxdWlyZV9fKDIpO1xuLyogaGFybW9ueSBpbXBvcnQgKi8gdmFyIGVsZW1lbnRfdWlfc3JjX3V0aWxzX2RvbV9fV0VCUEFDS19JTVBPUlRFRF9NT0RVTEVfMF9fX2RlZmF1bHQgPSAvKiNfX1BVUkVfXyovX193ZWJwYWNrX3JlcXVpcmVfXy5uKGVsZW1lbnRfdWlfc3JjX3V0aWxzX2RvbV9fV0VCUEFDS19JTVBPUlRFRF9NT0RVTEVfMF9fKTtcblxuXG4vKiBoYXJtb255IGRlZmF1bHQgZXhwb3J0ICovIF9fd2VicGFja19leHBvcnRzX19bXCJhXCJdID0gKHtcbiAgYmluZDogZnVuY3Rpb24gYmluZChlbCwgYmluZGluZywgdm5vZGUpIHtcbiAgICB2YXIgaW50ZXJ2YWwgPSBudWxsO1xuICAgIHZhciBzdGFydFRpbWUgPSB2b2lkIDA7XG4gICAgdmFyIGhhbmRsZXIgPSBmdW5jdGlvbiBoYW5kbGVyKCkge1xuICAgICAgcmV0dXJuIHZub2RlLmNvbnRleHRbYmluZGluZy5leHByZXNzaW9uXS5hcHBseSgpO1xuICAgIH07XG4gICAgdmFyIGNsZWFyID0gZnVuY3Rpb24gY2xlYXIoKSB7XG4gICAgICBpZiAoRGF0ZS5ub3coKSAtIHN0YXJ0VGltZSA8IDEwMCkge1xuICAgICAgICBoYW5kbGVyKCk7XG4gICAgICB9XG4gICAgICBjbGVhckludGVydmFsKGludGVydmFsKTtcbiAgICAgIGludGVydmFsID0gbnVsbDtcbiAgICB9O1xuXG4gICAgT2JqZWN0KGVsZW1lbnRfdWlfc3JjX3V0aWxzX2RvbV9fV0VCUEFDS19JTVBPUlRFRF9NT0RVTEVfMF9fW1wib25cIl0pKGVsLCAnbW91c2Vkb3duJywgZnVuY3Rpb24gKGUpIHtcbiAgICAgIGlmIChlLmJ1dHRvbiAhPT0gMCkgcmV0dXJuO1xuICAgICAgc3RhcnRUaW1lID0gRGF0ZS5ub3coKTtcbiAgICAgIE9iamVjdChlbGVtZW50X3VpX3NyY191dGlsc19kb21fX1dFQlBBQ0tfSU1QT1JURURfTU9EVUxFXzBfX1tcIm9uY2VcIl0pKGRvY3VtZW50LCAnbW91c2V1cCcsIGNsZWFyKTtcbiAgICAgIGNsZWFySW50ZXJ2YWwoaW50ZXJ2YWwpO1xuICAgICAgaW50ZXJ2YWwgPSBzZXRJbnRlcnZhbChoYW5kbGVyLCAxMDApO1xuICAgIH0pO1xuICB9XG59KTtcblxuLyoqKi8gfSlcblxuLyoqKioqKi8gfSk7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvZWxlbWVudC11aS9saWIvaW5wdXQtbnVtYmVyLmpzXG4vLyBtb2R1bGUgaWQgPSAwa1kzXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///0kY3\n')},"1Xk4":function(module,exports,__webpack_require__){"use strict";eval('\nvar window = __webpack_require__("awF4")\nvar isFunction = __webpack_require__("Rl2i")\nvar parseHeaders = __webpack_require__("sD9O")\nvar xtend = __webpack_require__("q+vg")\n\nmodule.exports = createXHR\ncreateXHR.XMLHttpRequest = window.XMLHttpRequest || noop\ncreateXHR.XDomainRequest = "withCredentials" in (new createXHR.XMLHttpRequest()) ? createXHR.XMLHttpRequest : window.XDomainRequest\n\nforEachArray(["get", "put", "post", "patch", "head", "delete"], function(method) {\n createXHR[method === "delete" ? "del" : method] = function(uri, options, callback) {\n options = initParams(uri, options, callback)\n options.method = method.toUpperCase()\n return _createXHR(options)\n }\n})\n\nfunction forEachArray(array, iterator) {\n for (var i = 0; i < array.length; i++) {\n iterator(array[i])\n }\n}\n\nfunction isEmpty(obj){\n for(var i in obj){\n if(obj.hasOwnProperty(i)) return false\n }\n return true\n}\n\nfunction initParams(uri, options, callback) {\n var params = uri\n\n if (isFunction(options)) {\n callback = options\n if (typeof uri === "string") {\n params = {uri:uri}\n }\n } else {\n params = xtend(options, {uri: uri})\n }\n\n params.callback = callback\n return params\n}\n\nfunction createXHR(uri, options, callback) {\n options = initParams(uri, options, callback)\n return _createXHR(options)\n}\n\nfunction _createXHR(options) {\n if(typeof options.callback === "undefined"){\n throw new Error("callback argument missing")\n }\n\n var called = false\n var callback = function cbOnce(err, response, body){\n if(!called){\n called = true\n options.callback(err, response, body)\n }\n }\n\n function readystatechange() {\n if (xhr.readyState === 4) {\n setTimeout(loadFunc, 0)\n }\n }\n\n function getBody() {\n // Chrome with requestType=blob throws errors arround when even testing access to responseText\n var body = undefined\n\n if (xhr.response) {\n body = xhr.response\n } else {\n body = xhr.responseText || getXml(xhr)\n }\n\n if (isJson) {\n try {\n body = JSON.parse(body)\n } catch (e) {}\n }\n\n return body\n }\n\n function errorFunc(evt) {\n clearTimeout(timeoutTimer)\n if(!(evt instanceof Error)){\n evt = new Error("" + (evt || "Unknown XMLHttpRequest Error") )\n }\n evt.statusCode = 0\n return callback(evt, failureResponse)\n }\n\n // will load the data & process the response in a special response object\n function loadFunc() {\n if (aborted) return\n var status\n clearTimeout(timeoutTimer)\n if(options.useXDR && xhr.status===undefined) {\n //IE8 CORS GET successful response doesn\'t have a status field, but body is fine\n status = 200\n } else {\n status = (xhr.status === 1223 ? 204 : xhr.status)\n }\n var response = failureResponse\n var err = null\n\n if (status !== 0){\n response = {\n body: getBody(),\n statusCode: status,\n method: method,\n headers: {},\n url: uri,\n rawRequest: xhr\n }\n if(xhr.getAllResponseHeaders){ //remember xhr can in fact be XDR for CORS in IE\n response.headers = parseHeaders(xhr.getAllResponseHeaders())\n }\n } else {\n err = new Error("Internal XMLHttpRequest Error")\n }\n return callback(err, response, response.body)\n }\n\n var xhr = options.xhr || null\n\n if (!xhr) {\n if (options.cors || options.useXDR) {\n xhr = new createXHR.XDomainRequest()\n }else{\n xhr = new createXHR.XMLHttpRequest()\n }\n }\n\n var key\n var aborted\n var uri = xhr.url = options.uri || options.url\n var method = xhr.method = options.method || "GET"\n var body = options.body || options.data\n var headers = xhr.headers = options.headers || {}\n var sync = !!options.sync\n var isJson = false\n var timeoutTimer\n var failureResponse = {\n body: undefined,\n headers: {},\n statusCode: 0,\n method: method,\n url: uri,\n rawRequest: xhr\n }\n\n if ("json" in options && options.json !== false) {\n isJson = true\n headers["accept"] || headers["Accept"] || (headers["Accept"] = "application/json") //Don\'t override existing accept header declared by user\n if (method !== "GET" && method !== "HEAD") {\n headers["content-type"] || headers["Content-Type"] || (headers["Content-Type"] = "application/json") //Don\'t override existing accept header declared by user\n body = JSON.stringify(options.json === true ? body : options.json)\n }\n }\n\n xhr.onreadystatechange = readystatechange\n xhr.onload = loadFunc\n xhr.onerror = errorFunc\n // IE9 must have onprogress be set to a unique function.\n xhr.onprogress = function () {\n // IE must die\n }\n xhr.onabort = function(){\n aborted = true;\n }\n xhr.ontimeout = errorFunc\n xhr.open(method, uri, !sync, options.username, options.password)\n //has to be after open\n if(!sync) {\n xhr.withCredentials = !!options.withCredentials\n }\n // Cannot set timeout with sync request\n // not setting timeout on the xhr object, because of old webkits etc. not handling that correctly\n // both npm\'s request and jquery 1.x use this kind of timeout, so this is being consistent\n if (!sync && options.timeout > 0 ) {\n timeoutTimer = setTimeout(function(){\n if (aborted) return\n aborted = true//IE9 may still call readystatechange\n xhr.abort("timeout")\n var e = new Error("XMLHttpRequest timeout")\n e.code = "ETIMEDOUT"\n errorFunc(e)\n }, options.timeout )\n }\n\n if (xhr.setRequestHeader) {\n for(key in headers){\n if(headers.hasOwnProperty(key)){\n xhr.setRequestHeader(key, headers[key])\n }\n }\n } else if (options.headers && !isEmpty(options.headers)) {\n throw new Error("Headers cannot be set on an XDomainRequest object")\n }\n\n if ("responseType" in options) {\n xhr.responseType = options.responseType\n }\n\n if ("beforeSend" in options &&\n typeof options.beforeSend === "function"\n ) {\n options.beforeSend(xhr)\n }\n\n // Microsoft Edge browser sends "undefined" when send is called with undefined value.\n // XMLHttpRequest spec says to pass null as body to indicate no body\n // See https://github.com/naugtur/xhr/issues/100.\n xhr.send(body || null)\n\n return xhr\n\n\n}\n\nfunction getXml(xhr) {\n if (xhr.responseType === "document") {\n return xhr.responseXML\n }\n var firefoxBugTakenEffect = xhr.responseXML && xhr.responseXML.documentElement.nodeName === "parsererror"\n if (xhr.responseType === "" && !firefoxBugTakenEffect) {\n return xhr.responseXML\n }\n\n return null\n}\n\nfunction noop() {}\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMVhrNC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy94aHIvaW5kZXguanM/ZDU3OSJdLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcbnZhciB3aW5kb3cgPSByZXF1aXJlKFwiZ2xvYmFsL3dpbmRvd1wiKVxudmFyIGlzRnVuY3Rpb24gPSByZXF1aXJlKFwiaXMtZnVuY3Rpb25cIilcbnZhciBwYXJzZUhlYWRlcnMgPSByZXF1aXJlKFwicGFyc2UtaGVhZGVyc1wiKVxudmFyIHh0ZW5kID0gcmVxdWlyZShcInh0ZW5kXCIpXG5cbm1vZHVsZS5leHBvcnRzID0gY3JlYXRlWEhSXG5jcmVhdGVYSFIuWE1MSHR0cFJlcXVlc3QgPSB3aW5kb3cuWE1MSHR0cFJlcXVlc3QgfHwgbm9vcFxuY3JlYXRlWEhSLlhEb21haW5SZXF1ZXN0ID0gXCJ3aXRoQ3JlZGVudGlhbHNcIiBpbiAobmV3IGNyZWF0ZVhIUi5YTUxIdHRwUmVxdWVzdCgpKSA/IGNyZWF0ZVhIUi5YTUxIdHRwUmVxdWVzdCA6IHdpbmRvdy5YRG9tYWluUmVxdWVzdFxuXG5mb3JFYWNoQXJyYXkoW1wiZ2V0XCIsIFwicHV0XCIsIFwicG9zdFwiLCBcInBhdGNoXCIsIFwiaGVhZFwiLCBcImRlbGV0ZVwiXSwgZnVuY3Rpb24obWV0aG9kKSB7XG4gICAgY3JlYXRlWEhSW21ldGhvZCA9PT0gXCJkZWxldGVcIiA/IFwiZGVsXCIgOiBtZXRob2RdID0gZnVuY3Rpb24odXJpLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgICAgICBvcHRpb25zID0gaW5pdFBhcmFtcyh1cmksIG9wdGlvbnMsIGNhbGxiYWNrKVxuICAgICAgICBvcHRpb25zLm1ldGhvZCA9IG1ldGhvZC50b1VwcGVyQ2FzZSgpXG4gICAgICAgIHJldHVybiBfY3JlYXRlWEhSKG9wdGlvbnMpXG4gICAgfVxufSlcblxuZnVuY3Rpb24gZm9yRWFjaEFycmF5KGFycmF5LCBpdGVyYXRvcikge1xuICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYXJyYXkubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgaXRlcmF0b3IoYXJyYXlbaV0pXG4gICAgfVxufVxuXG5mdW5jdGlvbiBpc0VtcHR5KG9iail7XG4gICAgZm9yKHZhciBpIGluIG9iail7XG4gICAgICAgIGlmKG9iai5oYXNPd25Qcm9wZXJ0eShpKSkgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHJldHVybiB0cnVlXG59XG5cbmZ1bmN0aW9uIGluaXRQYXJhbXModXJpLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIHZhciBwYXJhbXMgPSB1cmlcblxuICAgIGlmIChpc0Z1bmN0aW9uKG9wdGlvbnMpKSB7XG4gICAgICAgIGNhbGxiYWNrID0gb3B0aW9uc1xuICAgICAgICBpZiAodHlwZW9mIHVyaSA9PT0gXCJzdHJpbmdcIikge1xuICAgICAgICAgICAgcGFyYW1zID0ge3VyaTp1cml9XG4gICAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgICBwYXJhbXMgPSB4dGVuZChvcHRpb25zLCB7dXJpOiB1cml9KVxuICAgIH1cblxuICAgIHBhcmFtcy5jYWxsYmFjayA9IGNhbGxiYWNrXG4gICAgcmV0dXJuIHBhcmFtc1xufVxuXG5mdW5jdGlvbiBjcmVhdGVYSFIodXJpLCBvcHRpb25zLCBjYWxsYmFjaykge1xuICAgIG9wdGlvbnMgPSBpbml0UGFyYW1zKHVyaSwgb3B0aW9ucywgY2FsbGJhY2spXG4gICAgcmV0dXJuIF9jcmVhdGVYSFIob3B0aW9ucylcbn1cblxuZnVuY3Rpb24gX2NyZWF0ZVhIUihvcHRpb25zKSB7XG4gICAgaWYodHlwZW9mIG9wdGlvbnMuY2FsbGJhY2sgPT09IFwidW5kZWZpbmVkXCIpe1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJjYWxsYmFjayBhcmd1bWVudCBtaXNzaW5nXCIpXG4gICAgfVxuXG4gICAgdmFyIGNhbGxlZCA9IGZhbHNlXG4gICAgdmFyIGNhbGxiYWNrID0gZnVuY3Rpb24gY2JPbmNlKGVyciwgcmVzcG9uc2UsIGJvZHkpe1xuICAgICAgICBpZighY2FsbGVkKXtcbiAgICAgICAgICAgIGNhbGxlZCA9IHRydWVcbiAgICAgICAgICAgIG9wdGlvbnMuY2FsbGJhY2soZXJyLCByZXNwb25zZSwgYm9keSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHJlYWR5c3RhdGVjaGFuZ2UoKSB7XG4gICAgICAgIGlmICh4aHIucmVhZHlTdGF0ZSA9PT0gNCkge1xuICAgICAgICAgICAgc2V0VGltZW91dChsb2FkRnVuYywgMClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGdldEJvZHkoKSB7XG4gICAgICAgIC8vIENocm9tZSB3aXRoIHJlcXVlc3RUeXBlPWJsb2IgdGhyb3dzIGVycm9ycyBhcnJvdW5kIHdoZW4gZXZlbiB0ZXN0aW5nIGFjY2VzcyB0byByZXNwb25zZVRleHRcbiAgICAgICAgdmFyIGJvZHkgPSB1bmRlZmluZWRcblxuICAgICAgICBpZiAoeGhyLnJlc3BvbnNlKSB7XG4gICAgICAgICAgICBib2R5ID0geGhyLnJlc3BvbnNlXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBib2R5ID0geGhyLnJlc3BvbnNlVGV4dCB8fCBnZXRYbWwoeGhyKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzSnNvbikge1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBib2R5ID0gSlNPTi5wYXJzZShib2R5KVxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge31cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBib2R5XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gZXJyb3JGdW5jKGV2dCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dFRpbWVyKVxuICAgICAgICBpZighKGV2dCBpbnN0YW5jZW9mIEVycm9yKSl7XG4gICAgICAgICAgICBldnQgPSBuZXcgRXJyb3IoXCJcIiArIChldnQgfHwgXCJVbmtub3duIFhNTEh0dHBSZXF1ZXN0IEVycm9yXCIpIClcbiAgICAgICAgfVxuICAgICAgICBldnQuc3RhdHVzQ29kZSA9IDBcbiAgICAgICAgcmV0dXJuIGNhbGxiYWNrKGV2dCwgZmFpbHVyZVJlc3BvbnNlKVxuICAgIH1cblxuICAgIC8vIHdpbGwgbG9hZCB0aGUgZGF0YSAmIHByb2Nlc3MgdGhlIHJlc3BvbnNlIGluIGEgc3BlY2lhbCByZXNwb25zZSBvYmplY3RcbiAgICBmdW5jdGlvbiBsb2FkRnVuYygpIHtcbiAgICAgICAgaWYgKGFib3J0ZWQpIHJldHVyblxuICAgICAgICB2YXIgc3RhdHVzXG4gICAgICAgIGNsZWFyVGltZW91dCh0aW1lb3V0VGltZXIpXG4gICAgICAgIGlmKG9wdGlvbnMudXNlWERSICYmIHhoci5zdGF0dXM9PT11bmRlZmluZWQpIHtcbiAgICAgICAgICAgIC8vSUU4IENPUlMgR0VUIHN1Y2Nlc3NmdWwgcmVzcG9uc2UgZG9lc24ndCBoYXZlIGEgc3RhdHVzIGZpZWxkLCBidXQgYm9keSBpcyBmaW5lXG4gICAgICAgICAgICBzdGF0dXMgPSAyMDBcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXR1cyA9ICh4aHIuc3RhdHVzID09PSAxMjIzID8gMjA0IDogeGhyLnN0YXR1cylcbiAgICAgICAgfVxuICAgICAgICB2YXIgcmVzcG9uc2UgPSBmYWlsdXJlUmVzcG9uc2VcbiAgICAgICAgdmFyIGVyciA9IG51bGxcblxuICAgICAgICBpZiAoc3RhdHVzICE9PSAwKXtcbiAgICAgICAgICAgIHJlc3BvbnNlID0ge1xuICAgICAgICAgICAgICAgIGJvZHk6IGdldEJvZHkoKSxcbiAgICAgICAgICAgICAgICBzdGF0dXNDb2RlOiBzdGF0dXMsXG4gICAgICAgICAgICAgICAgbWV0aG9kOiBtZXRob2QsXG4gICAgICAgICAgICAgICAgaGVhZGVyczoge30sXG4gICAgICAgICAgICAgICAgdXJsOiB1cmksXG4gICAgICAgICAgICAgICAgcmF3UmVxdWVzdDogeGhyXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZih4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKXsgLy9yZW1lbWJlciB4aHIgY2FuIGluIGZhY3QgYmUgWERSIGZvciBDT1JTIGluIElFXG4gICAgICAgICAgICAgICAgcmVzcG9uc2UuaGVhZGVycyA9IHBhcnNlSGVhZGVycyh4aHIuZ2V0QWxsUmVzcG9uc2VIZWFkZXJzKCkpXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlcnIgPSBuZXcgRXJyb3IoXCJJbnRlcm5hbCBYTUxIdHRwUmVxdWVzdCBFcnJvclwiKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjYWxsYmFjayhlcnIsIHJlc3BvbnNlLCByZXNwb25zZS5ib2R5KVxuICAgIH1cblxuICAgIHZhciB4aHIgPSBvcHRpb25zLnhociB8fCBudWxsXG5cbiAgICBpZiAoIXhocikge1xuICAgICAgICBpZiAob3B0aW9ucy5jb3JzIHx8IG9wdGlvbnMudXNlWERSKSB7XG4gICAgICAgICAgICB4aHIgPSBuZXcgY3JlYXRlWEhSLlhEb21haW5SZXF1ZXN0KClcbiAgICAgICAgfWVsc2V7XG4gICAgICAgICAgICB4aHIgPSBuZXcgY3JlYXRlWEhSLlhNTEh0dHBSZXF1ZXN0KClcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBrZXlcbiAgICB2YXIgYWJvcnRlZFxuICAgIHZhciB1cmkgPSB4aHIudXJsID0gb3B0aW9ucy51cmkgfHwgb3B0aW9ucy51cmxcbiAgICB2YXIgbWV0aG9kID0geGhyLm1ldGhvZCA9IG9wdGlvbnMubWV0aG9kIHx8IFwiR0VUXCJcbiAgICB2YXIgYm9keSA9IG9wdGlvbnMuYm9keSB8fCBvcHRpb25zLmRhdGFcbiAgICB2YXIgaGVhZGVycyA9IHhoci5oZWFkZXJzID0gb3B0aW9ucy5oZWFkZXJzIHx8IHt9XG4gICAgdmFyIHN5bmMgPSAhIW9wdGlvbnMuc3luY1xuICAgIHZhciBpc0pzb24gPSBmYWxzZVxuICAgIHZhciB0aW1lb3V0VGltZXJcbiAgICB2YXIgZmFpbHVyZVJlc3BvbnNlID0ge1xuICAgICAgICBib2R5OiB1bmRlZmluZWQsXG4gICAgICAgIGhlYWRlcnM6IHt9LFxuICAgICAgICBzdGF0dXNDb2RlOiAwLFxuICAgICAgICBtZXRob2Q6IG1ldGhvZCxcbiAgICAgICAgdXJsOiB1cmksXG4gICAgICAgIHJhd1JlcXVlc3Q6IHhoclxuICAgIH1cblxuICAgIGlmIChcImpzb25cIiBpbiBvcHRpb25zICYmIG9wdGlvbnMuanNvbiAhPT0gZmFsc2UpIHtcbiAgICAgICAgaXNKc29uID0gdHJ1ZVxuICAgICAgICBoZWFkZXJzW1wiYWNjZXB0XCJdIHx8IGhlYWRlcnNbXCJBY2NlcHRcIl0gfHwgKGhlYWRlcnNbXCJBY2NlcHRcIl0gPSBcImFwcGxpY2F0aW9uL2pzb25cIikgLy9Eb24ndCBvdmVycmlkZSBleGlzdGluZyBhY2NlcHQgaGVhZGVyIGRlY2xhcmVkIGJ5IHVzZXJcbiAgICAgICAgaWYgKG1ldGhvZCAhPT0gXCJHRVRcIiAmJiBtZXRob2QgIT09IFwiSEVBRFwiKSB7XG4gICAgICAgICAgICBoZWFkZXJzW1wiY29udGVudC10eXBlXCJdIHx8IGhlYWRlcnNbXCJDb250ZW50LVR5cGVcIl0gfHwgKGhlYWRlcnNbXCJDb250ZW50LVR5cGVcIl0gPSBcImFwcGxpY2F0aW9uL2pzb25cIikgLy9Eb24ndCBvdmVycmlkZSBleGlzdGluZyBhY2NlcHQgaGVhZGVyIGRlY2xhcmVkIGJ5IHVzZXJcbiAgICAgICAgICAgIGJvZHkgPSBKU09OLnN0cmluZ2lmeShvcHRpb25zLmpzb24gPT09IHRydWUgPyBib2R5IDogb3B0aW9ucy5qc29uKVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgeGhyLm9ucmVhZHlzdGF0ZWNoYW5nZSA9IHJlYWR5c3RhdGVjaGFuZ2VcbiAgICB4aHIub25sb2FkID0gbG9hZEZ1bmNcbiAgICB4aHIub25lcnJvciA9IGVycm9yRnVuY1xuICAgIC8vIElFOSBtdXN0IGhhdmUgb25wcm9ncmVzcyBiZSBzZXQgdG8gYSB1bmlxdWUgZnVuY3Rpb24uXG4gICAgeGhyLm9ucHJvZ3Jlc3MgPSBmdW5jdGlvbiAoKSB7XG4gICAgICAgIC8vIElFIG11c3QgZGllXG4gICAgfVxuICAgIHhoci5vbmFib3J0ID0gZnVuY3Rpb24oKXtcbiAgICAgICAgYWJvcnRlZCA9IHRydWU7XG4gICAgfVxuICAgIHhoci5vbnRpbWVvdXQgPSBlcnJvckZ1bmNcbiAgICB4aHIub3BlbihtZXRob2QsIHVyaSwgIXN5bmMsIG9wdGlvbnMudXNlcm5hbWUsIG9wdGlvbnMucGFzc3dvcmQpXG4gICAgLy9oYXMgdG8gYmUgYWZ0ZXIgb3BlblxuICAgIGlmKCFzeW5jKSB7XG4gICAgICAgIHhoci53aXRoQ3JlZGVudGlhbHMgPSAhIW9wdGlvbnMud2l0aENyZWRlbnRpYWxzXG4gICAgfVxuICAgIC8vIENhbm5vdCBzZXQgdGltZW91dCB3aXRoIHN5bmMgcmVxdWVzdFxuICAgIC8vIG5vdCBzZXR0aW5nIHRpbWVvdXQgb24gdGhlIHhociBvYmplY3QsIGJlY2F1c2Ugb2Ygb2xkIHdlYmtpdHMgZXRjLiBub3QgaGFuZGxpbmcgdGhhdCBjb3JyZWN0bHlcbiAgICAvLyBib3RoIG5wbSdzIHJlcXVlc3QgYW5kIGpxdWVyeSAxLnggdXNlIHRoaXMga2luZCBvZiB0aW1lb3V0LCBzbyB0aGlzIGlzIGJlaW5nIGNvbnNpc3RlbnRcbiAgICBpZiAoIXN5bmMgJiYgb3B0aW9ucy50aW1lb3V0ID4gMCApIHtcbiAgICAgICAgdGltZW91dFRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpe1xuICAgICAgICAgICAgaWYgKGFib3J0ZWQpIHJldHVyblxuICAgICAgICAgICAgYWJvcnRlZCA9IHRydWUvL0lFOSBtYXkgc3RpbGwgY2FsbCByZWFkeXN0YXRlY2hhbmdlXG4gICAgICAgICAgICB4aHIuYWJvcnQoXCJ0aW1lb3V0XCIpXG4gICAgICAgICAgICB2YXIgZSA9IG5ldyBFcnJvcihcIlhNTEh0dHBSZXF1ZXN0IHRpbWVvdXRcIilcbiAgICAgICAgICAgIGUuY29kZSA9IFwiRVRJTUVET1VUXCJcbiAgICAgICAgICAgIGVycm9yRnVuYyhlKVxuICAgICAgICB9LCBvcHRpb25zLnRpbWVvdXQgKVxuICAgIH1cblxuICAgIGlmICh4aHIuc2V0UmVxdWVzdEhlYWRlcikge1xuICAgICAgICBmb3Ioa2V5IGluIGhlYWRlcnMpe1xuICAgICAgICAgICAgaWYoaGVhZGVycy5oYXNPd25Qcm9wZXJ0eShrZXkpKXtcbiAgICAgICAgICAgICAgICB4aHIuc2V0UmVxdWVzdEhlYWRlcihrZXksIGhlYWRlcnNba2V5XSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0gZWxzZSBpZiAob3B0aW9ucy5oZWFkZXJzICYmICFpc0VtcHR5KG9wdGlvbnMuaGVhZGVycykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSGVhZGVycyBjYW5ub3QgYmUgc2V0IG9uIGFuIFhEb21haW5SZXF1ZXN0IG9iamVjdFwiKVxuICAgIH1cblxuICAgIGlmIChcInJlc3BvbnNlVHlwZVwiIGluIG9wdGlvbnMpIHtcbiAgICAgICAgeGhyLnJlc3BvbnNlVHlwZSA9IG9wdGlvbnMucmVzcG9uc2VUeXBlXG4gICAgfVxuXG4gICAgaWYgKFwiYmVmb3JlU2VuZFwiIGluIG9wdGlvbnMgJiZcbiAgICAgICAgdHlwZW9mIG9wdGlvbnMuYmVmb3JlU2VuZCA9PT0gXCJmdW5jdGlvblwiXG4gICAgKSB7XG4gICAgICAgIG9wdGlvbnMuYmVmb3JlU2VuZCh4aHIpXG4gICAgfVxuXG4gICAgLy8gTWljcm9zb2Z0IEVkZ2UgYnJvd3NlciBzZW5kcyBcInVuZGVmaW5lZFwiIHdoZW4gc2VuZCBpcyBjYWxsZWQgd2l0aCB1bmRlZmluZWQgdmFsdWUuXG4gICAgLy8gWE1MSHR0cFJlcXVlc3Qgc3BlYyBzYXlzIHRvIHBhc3MgbnVsbCBhcyBib2R5IHRvIGluZGljYXRlIG5vIGJvZHlcbiAgICAvLyBTZWUgaHR0cHM6Ly9naXRodWIuY29tL25hdWd0dXIveGhyL2lzc3Vlcy8xMDAuXG4gICAgeGhyLnNlbmQoYm9keSB8fCBudWxsKVxuXG4gICAgcmV0dXJuIHhoclxuXG5cbn1cblxuZnVuY3Rpb24gZ2V0WG1sKHhocikge1xuICAgIGlmICh4aHIucmVzcG9uc2VUeXBlID09PSBcImRvY3VtZW50XCIpIHtcbiAgICAgICAgcmV0dXJuIHhoci5yZXNwb25zZVhNTFxuICAgIH1cbiAgICB2YXIgZmlyZWZveEJ1Z1Rha2VuRWZmZWN0ID0geGhyLnJlc3BvbnNlWE1MICYmIHhoci5yZXNwb25zZVhNTC5kb2N1bWVudEVsZW1lbnQubm9kZU5hbWUgPT09IFwicGFyc2VyZXJyb3JcIlxuICAgIGlmICh4aHIucmVzcG9uc2VUeXBlID09PSBcIlwiICYmICFmaXJlZm94QnVnVGFrZW5FZmZlY3QpIHtcbiAgICAgICAgcmV0dXJuIHhoci5yZXNwb25zZVhNTFxuICAgIH1cblxuICAgIHJldHVybiBudWxsXG59XG5cbmZ1bmN0aW9uIG5vb3AoKSB7fVxuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMveGhyL2luZGV4LmpzXG4vLyBtb2R1bGUgaWQgPSAxWGs0XG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///1Xk4\n')},"1kS7":function(module,exports){eval("exports.f = Object.getOwnPropertySymbols;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMWtTNy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fb2JqZWN0LWdvcHMuanM/ZDY0NCJdLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnRzLmYgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX29iamVjdC1nb3BzLmpzXG4vLyBtb2R1bGUgaWQgPSAxa1M3XG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///1kS7\n")},"1oZe":function(module,exports,__webpack_require__){"use strict";eval("\n\nexports.__esModule = true;\n\nexports.default = function (ref) {\n return {\n methods: {\n focus: function focus() {\n this.$refs[ref].focus();\n }\n }\n };\n};\n\n;//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMW9aZS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9lbGVtZW50LXVpL2xpYi9taXhpbnMvZm9jdXMuanM/ZDY4NiJdLCJzb3VyY2VzQ29udGVudCI6WyJcInVzZSBzdHJpY3RcIjtcblxuZXhwb3J0cy5fX2VzTW9kdWxlID0gdHJ1ZTtcblxuZXhwb3J0cy5kZWZhdWx0ID0gZnVuY3Rpb24gKHJlZikge1xuICByZXR1cm4ge1xuICAgIG1ldGhvZHM6IHtcbiAgICAgIGZvY3VzOiBmdW5jdGlvbiBmb2N1cygpIHtcbiAgICAgICAgdGhpcy4kcmVmc1tyZWZdLmZvY3VzKCk7XG4gICAgICB9XG4gICAgfVxuICB9O1xufTtcblxuO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2VsZW1lbnQtdWkvbGliL21peGlucy9mb2N1cy5qc1xuLy8gbW9kdWxlIGlkID0gMW9aZVxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///1oZe\n")},"1tcR":function(module,exports){eval("//package mp3;\n\nfunction VBRSeekInfo() {\n /**\n * What we have seen so far.\n */\n this.sum = 0;\n /**\n * How many frames we have seen in this chunk.\n */\n this.seen = 0;\n /**\n * How many frames we want to collect into one chunk.\n */\n this.want = 0;\n /**\n * Actual position in our bag.\n */\n this.pos = 0;\n /**\n * Size of our bag.\n */\n this.size = 0;\n /**\n * Pointer to our bag.\n */\n this.bag = null;\n this.nVbrNumFrames = 0;\n this.nBytesWritten = 0;\n /* VBR tag data */\n this.TotalFrameSize = 0;\n}\n\nmodule.exports = VBRSeekInfo;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMXRjUi5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvVkJSU2Vla0luZm8uanM/ZDZkNyJdLCJzb3VyY2VzQ29udGVudCI6WyIvL3BhY2thZ2UgbXAzO1xuXG5mdW5jdGlvbiBWQlJTZWVrSW5mbygpIHtcbiAgICAvKipcbiAgICAgKiBXaGF0IHdlIGhhdmUgc2VlbiBzbyBmYXIuXG4gICAgICovXG4gICAgdGhpcy5zdW0gPSAwO1xuICAgIC8qKlxuICAgICAqIEhvdyBtYW55IGZyYW1lcyB3ZSBoYXZlIHNlZW4gaW4gdGhpcyBjaHVuay5cbiAgICAgKi9cbiAgICB0aGlzLnNlZW4gPSAwO1xuICAgIC8qKlxuICAgICAqIEhvdyBtYW55IGZyYW1lcyB3ZSB3YW50IHRvIGNvbGxlY3QgaW50byBvbmUgY2h1bmsuXG4gICAgICovXG4gICAgdGhpcy53YW50ID0gMDtcbiAgICAvKipcbiAgICAgKiBBY3R1YWwgcG9zaXRpb24gaW4gb3VyIGJhZy5cbiAgICAgKi9cbiAgICB0aGlzLnBvcyA9IDA7XG4gICAgLyoqXG4gICAgICogU2l6ZSBvZiBvdXIgYmFnLlxuICAgICAqL1xuICAgIHRoaXMuc2l6ZSA9IDA7XG4gICAgLyoqXG4gICAgICogUG9pbnRlciB0byBvdXIgYmFnLlxuICAgICAqL1xuICAgIHRoaXMuYmFnID0gbnVsbDtcbiAgICB0aGlzLm5WYnJOdW1GcmFtZXMgPSAwO1xuICAgIHRoaXMubkJ5dGVzV3JpdHRlbiA9IDA7XG4gICAgLyogVkJSIHRhZyBkYXRhICovXG4gICAgdGhpcy5Ub3RhbEZyYW1lU2l6ZSA9IDA7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gVkJSU2Vla0luZm87XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvVkJSU2Vla0luZm8uanNcbi8vIG1vZHVsZSBpZCA9IDF0Y1Jcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///1tcR\n")},"21It":function(module,exports,__webpack_require__){"use strict";eval("\n\nvar createError = __webpack_require__(\"FtD3\");\n\n/**\n * Resolve or reject a Promise based on response status.\n *\n * @param {Function} resolve A function that resolves the promise.\n * @param {Function} reject A function that rejects the promise.\n * @param {object} response The response.\n */\nmodule.exports = function settle(resolve, reject, response) {\n var validateStatus = response.config.validateStatus;\n if (!response.status || !validateStatus || validateStatus(response.status)) {\n resolve(response);\n } else {\n reject(createError(\n 'Request failed with status code ' + response.status,\n response.config,\n null,\n response.request,\n response\n ));\n }\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMjFJdC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9heGlvcy9saWIvY29yZS9zZXR0bGUuanM/ZGI1MiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbnZhciBjcmVhdGVFcnJvciA9IHJlcXVpcmUoJy4vY3JlYXRlRXJyb3InKTtcblxuLyoqXG4gKiBSZXNvbHZlIG9yIHJlamVjdCBhIFByb21pc2UgYmFzZWQgb24gcmVzcG9uc2Ugc3RhdHVzLlxuICpcbiAqIEBwYXJhbSB7RnVuY3Rpb259IHJlc29sdmUgQSBmdW5jdGlvbiB0aGF0IHJlc29sdmVzIHRoZSBwcm9taXNlLlxuICogQHBhcmFtIHtGdW5jdGlvbn0gcmVqZWN0IEEgZnVuY3Rpb24gdGhhdCByZWplY3RzIHRoZSBwcm9taXNlLlxuICogQHBhcmFtIHtvYmplY3R9IHJlc3BvbnNlIFRoZSByZXNwb25zZS5cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiBzZXR0bGUocmVzb2x2ZSwgcmVqZWN0LCByZXNwb25zZSkge1xuICB2YXIgdmFsaWRhdGVTdGF0dXMgPSByZXNwb25zZS5jb25maWcudmFsaWRhdGVTdGF0dXM7XG4gIGlmICghcmVzcG9uc2Uuc3RhdHVzIHx8ICF2YWxpZGF0ZVN0YXR1cyB8fCB2YWxpZGF0ZVN0YXR1cyhyZXNwb25zZS5zdGF0dXMpKSB7XG4gICAgcmVzb2x2ZShyZXNwb25zZSk7XG4gIH0gZWxzZSB7XG4gICAgcmVqZWN0KGNyZWF0ZUVycm9yKFxuICAgICAgJ1JlcXVlc3QgZmFpbGVkIHdpdGggc3RhdHVzIGNvZGUgJyArIHJlc3BvbnNlLnN0YXR1cyxcbiAgICAgIHJlc3BvbnNlLmNvbmZpZyxcbiAgICAgIG51bGwsXG4gICAgICByZXNwb25zZS5yZXF1ZXN0LFxuICAgICAgcmVzcG9uc2VcbiAgICApKTtcbiAgfVxufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2F4aW9zL2xpYi9jb3JlL3NldHRsZS5qc1xuLy8gbW9kdWxlIGlkID0gMjFJdFxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///21It\n")},"2KxR":function(module,exports){eval("module.exports = function (it, Constructor, name, forbiddenField) {\n if (!(it instanceof Constructor) || (forbiddenField !== undefined && forbiddenField in it)) {\n throw TypeError(name + ': incorrect invocation!');\n } return it;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMkt4Ui5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYW4taW5zdGFuY2UuanM/ZDhhYyJdLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCwgQ29uc3RydWN0b3IsIG5hbWUsIGZvcmJpZGRlbkZpZWxkKSB7XG4gIGlmICghKGl0IGluc3RhbmNlb2YgQ29uc3RydWN0b3IpIHx8IChmb3JiaWRkZW5GaWVsZCAhPT0gdW5kZWZpbmVkICYmIGZvcmJpZGRlbkZpZWxkIGluIGl0KSkge1xuICAgIHRocm93IFR5cGVFcnJvcihuYW1lICsgJzogaW5jb3JyZWN0IGludm9jYXRpb24hJyk7XG4gIH0gcmV0dXJuIGl0O1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL19hbi1pbnN0YW5jZS5qc1xuLy8gbW9kdWxlIGlkID0gMkt4UlxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///2KxR\n")},"2knq":function(module,exports,__webpack_require__){eval('/*\n * psymodel.c\n *\n * Copyright (c) 1999-2000 Mark Taylor\n * Copyright (c) 2001-2002 Naoki Shibata\n * Copyright (c) 2000-2003 Takehiro Tominaga\n * Copyright (c) 2000-2008 Robert Hegemann\n * Copyright (c) 2000-2005 Gabriel Bouvigne\n * Copyright (c) 2000-2005 Alexander Leidinger\n *\n * This library is free software; you can redistribute it and/or\n * modify it under the terms of the GNU Lesser General Public\n * License as published by the Free Software Foundation; either\n * version 2 of the License, or (at your option) any later version.\n *\n * This library is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n * Library General Public License for more details.\n *\n * You should have received a copy of the GNU Lesser General Public\n * License along with this library; if not, write to the\n * Free Software Foundation, Inc., 59 Temple Place - Suite 330,\n * Boston, MA 02111-1307, USA.\n */\n\n/* $Id: PsyModel.java,v 1.27 2011/05/24 20:48:06 kenchis Exp $ */\n\n\n/*\n PSYCHO ACOUSTICS\n\n\n This routine computes the psycho acoustics, delayed by one granule.\n\n Input: buffer of PCM data (1024 samples).\n\n This window should be centered over the 576 sample granule window.\n The routine will compute the psycho acoustics for\n this granule, but return the psycho acoustics computed\n for the *previous* granule. This is because the block\n type of the previous granule can only be determined\n after we have computed the psycho acoustics for the following\n granule.\n\n Output: maskings and energies for each scalefactor band.\n block type, PE, and some correlation measures.\n The PE is used by CBR modes to determine if extra bits\n from the bit reservoir should be used. The correlation\n measures are used to determine mid/side or regular stereo.\n */\n/*\n Notation:\n\n barks: a non-linear frequency scale. Mapping from frequency to\n barks is given by freq2bark()\n\n scalefactor bands: The spectrum (frequencies) are broken into\n SBMAX "scalefactor bands". Thes bands\n are determined by the MPEG ISO spec. In\n the noise shaping/quantization code, we allocate\n bits among the partition bands to achieve the\n best possible quality\n\n partition bands: The spectrum is also broken into about\n 64 "partition bands". Each partition\n band is about .34 barks wide. There are about 2-5\n partition bands for each scalefactor band.\n\n LAME computes all psycho acoustic information for each partition\n band. Then at the end of the computations, this information\n is mapped to scalefactor bands. The energy in each scalefactor\n band is taken as the sum of the energy in all partition bands\n which overlap the scalefactor band. The maskings can be computed\n in the same way (and thus represent the average masking in that band)\n or by taking the minmum value multiplied by the number of\n partition bands used (which represents a minimum masking in that band).\n */\n/*\n The general outline is as follows:\n\n 1. compute the energy in each partition band\n 2. compute the tonality in each partition band\n 3. compute the strength of each partion band "masker"\n 4. compute the masking (via the spreading function applied to each masker)\n 5. Modifications for mid/side masking.\n\n Each partition band is considiered a "masker". The strength\n of the i\'th masker in band j is given by:\n\n s3(bark(i)-bark(j))*strength(i)\n\n The strength of the masker is a function of the energy and tonality.\n The more tonal, the less masking. LAME uses a simple linear formula\n (controlled by NMT and TMN) which says the strength is given by the\n energy divided by a linear function of the tonality.\n */\n/*\n s3() is the "spreading function". It is given by a formula\n determined via listening tests.\n\n The total masking in the j\'th partition band is the sum over\n all maskings i. It is thus given by the convolution of\n the strength with s3(), the "spreading function."\n\n masking(j) = sum_over_i s3(i-j)*strength(i) = s3 o strength\n\n where "o" = convolution operator. s3 is given by a formula determined\n via listening tests. It is normalized so that s3 o 1 = 1.\n\n Note: instead of a simple convolution, LAME also has the\n option of using "additive masking"\n\n The most critical part is step 2, computing the tonality of each\n partition band. LAME has two tonality estimators. The first\n is based on the ISO spec, and measures how predictiable the\n signal is over time. The more predictable, the more tonal.\n The second measure is based on looking at the spectrum of\n a single granule. The more peaky the spectrum, the more\n tonal. By most indications, the latter approach is better.\n\n Finally, in step 5, the maskings for the mid and side\n channel are possibly increased. Under certain circumstances,\n noise in the mid & side channels is assumed to also\n be masked by strong maskers in the L or R channels.\n\n\n Other data computed by the psy-model:\n\n ms_ratio side-channel / mid-channel masking ratio (for previous granule)\n ms_ratio_next side-channel / mid-channel masking ratio for this granule\n\n percep_entropy[2] L and R values (prev granule) of PE - A measure of how\n much pre-echo is in the previous granule\n percep_entropy_MS[2] mid and side channel values (prev granule) of percep_entropy\n energy[4] L,R,M,S energy in each channel, prev granule\n blocktype_d[2] block type to use for previous granule\n */\n//package mp3;\n\n//import java.util.Arrays;\nvar common = __webpack_require__("Dkd2");\nvar System = common.System;\nvar VbrMode = common.VbrMode;\nvar Float = common.Float;\nvar ShortBlock = common.ShortBlock;\nvar Util = common.Util;\nvar Arrays = common.Arrays;\nvar new_array_n = common.new_array_n;\nvar new_byte = common.new_byte;\nvar new_double = common.new_double;\nvar new_float = common.new_float;\nvar new_float_n = common.new_float_n;\nvar new_int = common.new_int;\nvar new_int_n = common.new_int_n;\nvar assert = common.assert;\n\nvar FFT = __webpack_require__("vHDO");\nvar Encoder = __webpack_require__("E2dQ");\n\nfunction PsyModel() {\n var MPEGMode = __webpack_require__("eWXl")\n var fft = new FFT();\n\n var LOG10 = 2.30258509299404568402;\n\n var rpelev = 2;\n var rpelev2 = 16;\n var rpelev_s = 2;\n var rpelev2_s = 16;\n\n /* size of each partition band, in barks: */\n var DELBARK = .34;\n\n /* tuned for output level (sensitive to energy scale) */\n var VO_SCALE = (1. / (14752 * 14752) / (Encoder.BLKSIZE / 2));\n\n var temporalmask_sustain_sec = 0.01;\n\n var NS_PREECHO_ATT0 = 0.8;\n var NS_PREECHO_ATT1 = 0.6;\n var NS_PREECHO_ATT2 = 0.3;\n\n var NS_MSFIX = 3.5;\n\n var NSATTACKTHRE = 4.4;\n var NSATTACKTHRE_S = 25;\n\n var NSFIRLEN = 21;\n\n /* size of each partition band, in barks: */\n var LN_TO_LOG10 = 0.2302585093;\n\n function NON_LINEAR_SCALE_ENERGY(x) {\n return x;\n }\n\n /**\n *
\n     *       L3psycho_anal.  Compute psycho acoustics.\n     *\n     *       Data returned to the calling program must be delayed by one\n     *       granule.\n     *\n     *       This is done in two places.\n     *       If we do not need to know the blocktype, the copying\n     *       can be done here at the top of the program: we copy the data for\n     *       the last granule (computed during the last call) before it is\n     *       overwritten with the new data.  It looks like this:\n     *\n     *       0. static psymodel_data\n     *       1. calling_program_data = psymodel_data\n     *       2. compute psymodel_data\n     *\n     *       For data which needs to know the blocktype, the copying must be\n     *       done at the end of this loop, and the old values must be saved:\n     *\n     *       0. static psymodel_data_old\n     *       1. compute psymodel_data\n     *       2. compute possible block type of this granule\n     *       3. compute final block type of previous granule based on #2.\n     *       4. calling_program_data = psymodel_data_old\n     *       5. psymodel_data_old = psymodel_data\n     *     psycho_loudness_approx\n     *       jd - 2001 mar 12\n     *    in:  energy   - BLKSIZE/2 elements of frequency magnitudes ^ 2\n     *         gfp      - uses out_samplerate, ATHtype (also needed for ATHformula)\n     *    returns: loudness^2 approximation, a positive value roughly tuned for a value\n     *             of 1.0 for signals near clipping.\n     *    notes:   When calibrated, feeding this function binary white noise at sample\n     *             values +32767 or -32768 should return values that approach 3.\n     *             ATHformula is used to approximate an equal loudness curve.\n     *    future:  Data indicates that the shape of the equal loudness curve varies\n     *             with intensity.  This function might be improved by using an equal\n     *             loudness curve shaped for typical playback levels (instead of the\n     *             ATH, that is shaped for the threshold).  A flexible realization might\n     *             simply bend the existing ATH curve to achieve the desired shape.\n     *             However, the potential gain may not be enough to justify an effort.\n     * 
\n */\n function psycho_loudness_approx(energy, gfc) {\n var loudness_power = 0.0;\n /* apply weights to power in freq. bands */\n for (var i = 0; i < Encoder.BLKSIZE / 2; ++i)\n loudness_power += energy[i] * gfc.ATH.eql_w[i];\n loudness_power *= VO_SCALE;\n\n return loudness_power;\n }\n\n function compute_ffts(gfp, fftenergy, fftenergy_s, wsamp_l, wsamp_lPos, wsamp_s, wsamp_sPos, gr_out, chn, buffer, bufPos) {\n var gfc = gfp.internal_flags;\n if (chn < 2) {\n fft.fft_long(gfc, wsamp_l[wsamp_lPos], chn, buffer, bufPos);\n fft.fft_short(gfc, wsamp_s[wsamp_sPos], chn, buffer, bufPos);\n }\n /* FFT data for mid and side channel is derived from L & R */\n else if (chn == 2) {\n for (var j = Encoder.BLKSIZE - 1; j >= 0; --j) {\n var l = wsamp_l[wsamp_lPos + 0][j];\n var r = wsamp_l[wsamp_lPos + 1][j];\n wsamp_l[wsamp_lPos + 0][j] = (l + r) * Util.SQRT2 * 0.5;\n wsamp_l[wsamp_lPos + 1][j] = (l - r) * Util.SQRT2 * 0.5;\n }\n for (var b = 2; b >= 0; --b) {\n for (var j = Encoder.BLKSIZE_s - 1; j >= 0; --j) {\n var l = wsamp_s[wsamp_sPos + 0][b][j];\n var r = wsamp_s[wsamp_sPos + 1][b][j];\n wsamp_s[wsamp_sPos + 0][b][j] = (l + r) * Util.SQRT2 * 0.5;\n wsamp_s[wsamp_sPos + 1][b][j] = (l - r) * Util.SQRT2 * 0.5;\n }\n }\n }\n\n /*********************************************************************\n * compute energies\n *********************************************************************/\n fftenergy[0] = NON_LINEAR_SCALE_ENERGY(wsamp_l[wsamp_lPos + 0][0]);\n fftenergy[0] *= fftenergy[0];\n\n for (var j = Encoder.BLKSIZE / 2 - 1; j >= 0; --j) {\n var re = (wsamp_l[wsamp_lPos + 0])[Encoder.BLKSIZE / 2 - j];\n var im = (wsamp_l[wsamp_lPos + 0])[Encoder.BLKSIZE / 2 + j];\n fftenergy[Encoder.BLKSIZE / 2 - j] = NON_LINEAR_SCALE_ENERGY((re\n * re + im * im) * 0.5);\n }\n for (var b = 2; b >= 0; --b) {\n fftenergy_s[b][0] = (wsamp_s[wsamp_sPos + 0])[b][0];\n fftenergy_s[b][0] *= fftenergy_s[b][0];\n for (var j = Encoder.BLKSIZE_s / 2 - 1; j >= 0; --j) {\n var re = (wsamp_s[wsamp_sPos + 0])[b][Encoder.BLKSIZE_s\n / 2 - j];\n var im = (wsamp_s[wsamp_sPos + 0])[b][Encoder.BLKSIZE_s\n / 2 + j];\n fftenergy_s[b][Encoder.BLKSIZE_s / 2 - j] = NON_LINEAR_SCALE_ENERGY((re\n * re + im * im) * 0.5);\n }\n }\n /* total energy */\n {\n var totalenergy = 0.0;\n for (var j = 11; j < Encoder.HBLKSIZE; j++)\n totalenergy += fftenergy[j];\n\n gfc.tot_ener[chn] = totalenergy;\n }\n\n if (gfp.analysis) {\n for (var j = 0; j < Encoder.HBLKSIZE; j++) {\n gfc.pinfo.energy[gr_out][chn][j] = gfc.pinfo.energy_save[chn][j];\n gfc.pinfo.energy_save[chn][j] = fftenergy[j];\n }\n gfc.pinfo.pe[gr_out][chn] = gfc.pe[chn];\n }\n\n /*********************************************************************\n * compute loudness approximation (used for ATH auto-level adjustment)\n *********************************************************************/\n if (gfp.athaa_loudapprox == 2 && chn < 2) {\n // no loudness for mid/side ch\n gfc.loudness_sq[gr_out][chn] = gfc.loudness_sq_save[chn];\n gfc.loudness_sq_save[chn] = psycho_loudness_approx(fftenergy, gfc);\n }\n }\n\n /* mask_add optimization */\n /* init the limit values used to avoid computing log in mask_add when it is not necessary */\n\n /**\n *
\n     *  For example, with i = 10*log10(m2/m1)/10*16         (= log10(m2/m1)*16)\n     *\n     * abs(i)>8 is equivalent (as i is an integer) to\n     * abs(i)>=9\n     * i>=9 || i<=-9\n     * equivalent to (as i is the biggest integer smaller than log10(m2/m1)*16\n     * or the smallest integer bigger than log10(m2/m1)*16 depending on the sign of log10(m2/m1)*16)\n     * log10(m2/m1)>=9/16 || log10(m2/m1)<=-9/16\n     * exp10 is strictly increasing thus this is equivalent to\n     * m2/m1 >= 10^(9/16) || m2/m1<=10^(-9/16) which are comparisons to constants\n     * 
\n */\n\n /**\n * as in if(i>8)\n */\n var I1LIMIT = 8;\n /**\n * as in if(i>24) . changed 23\n */\n var I2LIMIT = 23;\n /**\n * as in if(m<15)\n */\n var MLIMIT = 15;\n\n var ma_max_i1;\n var ma_max_i2;\n var ma_max_m;\n\n /**\n * This is the masking table:
\n * According to tonality, values are going from 0dB (TMN) to 9.3dB (NMT).
\n * After additive masking computation, 8dB are added, so final values are\n * going from 8dB to 17.3dB\n *\n * pow(10, -0.0..-0.6)\n */\n var tab = [1.0, 0.79433, 0.63096, 0.63096,\n 0.63096, 0.63096, 0.63096, 0.25119, 0.11749];\n\n function init_mask_add_max_values() {\n ma_max_i1 = Math.pow(10, (I1LIMIT + 1) / 16.0);\n ma_max_i2 = Math.pow(10, (I2LIMIT + 1) / 16.0);\n ma_max_m = Math.pow(10, (MLIMIT) / 10.0);\n }\n\n var table1 = [3.3246 * 3.3246,\n 3.23837 * 3.23837, 3.15437 * 3.15437, 3.00412 * 3.00412,\n 2.86103 * 2.86103, 2.65407 * 2.65407, 2.46209 * 2.46209,\n 2.284 * 2.284, 2.11879 * 2.11879, 1.96552 * 1.96552,\n 1.82335 * 1.82335, 1.69146 * 1.69146, 1.56911 * 1.56911,\n 1.46658 * 1.46658, 1.37074 * 1.37074, 1.31036 * 1.31036,\n 1.25264 * 1.25264, 1.20648 * 1.20648, 1.16203 * 1.16203,\n 1.12765 * 1.12765, 1.09428 * 1.09428, 1.0659 * 1.0659,\n 1.03826 * 1.03826, 1.01895 * 1.01895, 1];\n\n var table2 = [1.33352 * 1.33352,\n 1.35879 * 1.35879, 1.38454 * 1.38454, 1.39497 * 1.39497,\n 1.40548 * 1.40548, 1.3537 * 1.3537, 1.30382 * 1.30382,\n 1.22321 * 1.22321, 1.14758 * 1.14758, 1];\n\n var table3 = [2.35364 * 2.35364,\n 2.29259 * 2.29259, 2.23313 * 2.23313, 2.12675 * 2.12675,\n 2.02545 * 2.02545, 1.87894 * 1.87894, 1.74303 * 1.74303,\n 1.61695 * 1.61695, 1.49999 * 1.49999, 1.39148 * 1.39148,\n 1.29083 * 1.29083, 1.19746 * 1.19746, 1.11084 * 1.11084,\n 1.03826 * 1.03826];\n\n /**\n * addition of simultaneous masking Naoki Shibata 2000/7\n */\n function mask_add(m1, m2, kk, b, gfc, shortblock) {\n var ratio;\n\n if (m2 > m1) {\n if (m2 < (m1 * ma_max_i2))\n ratio = m2 / m1;\n else\n return (m1 + m2);\n } else {\n if (m1 >= (m2 * ma_max_i2))\n return (m1 + m2);\n ratio = m1 / m2;\n }\n\n /* Should always be true, just checking */\n assert(m1 >= 0);\n assert(m2 >= 0);\n\n m1 += m2;\n //if (((long)(b + 3) & 0xffffffff) <= 3 + 3) {\n if ((b + 3) <= 3 + 3) {\n /* approximately, 1 bark = 3 partitions */\n /* 65% of the cases */\n /* originally \'if(i > 8)\' */\n if (ratio >= ma_max_i1) {\n /* 43% of the total */\n return m1;\n }\n\n /* 22% of the total */\n var i = 0 | (Util.FAST_LOG10_X(ratio, 16.0));\n return m1 * table2[i];\n }\n\n /**\n *
\n         * m<15 equ log10((m1+m2)/gfc.ATH.cb[k])<1.5\n         * equ (m1+m2)/gfc.ATH.cb[k]<10^1.5\n         * equ (m1+m2)<10^1.5 * gfc.ATH.cb[k]\n         * 
\n */\n var i = 0 | Util.FAST_LOG10_X(ratio, 16.0);\n if (shortblock != 0) {\n m2 = gfc.ATH.cb_s[kk] * gfc.ATH.adjust;\n } else {\n m2 = gfc.ATH.cb_l[kk] * gfc.ATH.adjust;\n }\n assert(m2 >= 0);\n if (m1 < ma_max_m * m2) {\n /* 3% of the total */\n /* Originally if (m > 0) { */\n if (m1 > m2) {\n var f, r;\n\n f = 1.0;\n if (i <= 13)\n f = table3[i];\n\n r = Util.FAST_LOG10_X(m1 / m2, 10.0 / 15.0);\n return m1 * ((table1[i] - f) * r + f);\n }\n\n if (i > 13)\n return m1;\n\n return m1 * table3[i];\n }\n\n /* 10% of total */\n return m1 * table1[i];\n }\n\n var table2_ = [1.33352 * 1.33352,\n 1.35879 * 1.35879, 1.38454 * 1.38454, 1.39497 * 1.39497,\n 1.40548 * 1.40548, 1.3537 * 1.3537, 1.30382 * 1.30382,\n 1.22321 * 1.22321, 1.14758 * 1.14758, 1];\n\n /**\n * addition of simultaneous masking Naoki Shibata 2000/7\n */\n function vbrpsy_mask_add(m1, m2, b) {\n var ratio;\n\n if (m1 < 0) {\n m1 = 0;\n }\n if (m2 < 0) {\n m2 = 0;\n }\n if (m1 <= 0) {\n return m2;\n }\n if (m2 <= 0) {\n return m1;\n }\n if (m2 > m1) {\n ratio = m2 / m1;\n } else {\n ratio = m1 / m2;\n }\n if (-2 <= b && b <= 2) {\n /* approximately, 1 bark = 3 partitions */\n /* originally \'if(i > 8)\' */\n if (ratio >= ma_max_i1) {\n return m1 + m2;\n } else {\n var i = 0 | (Util.FAST_LOG10_X(ratio, 16.0));\n return (m1 + m2) * table2_[i];\n }\n }\n if (ratio < ma_max_i2) {\n return m1 + m2;\n }\n if (m1 < m2) {\n m1 = m2;\n }\n return m1;\n }\n\n /**\n * compute interchannel masking effects\n */\n function calc_interchannel_masking(gfp, ratio) {\n var gfc = gfp.internal_flags;\n if (gfc.channels_out > 1) {\n for (var sb = 0; sb < Encoder.SBMAX_l; sb++) {\n var l = gfc.thm[0].l[sb];\n var r = gfc.thm[1].l[sb];\n gfc.thm[0].l[sb] += r * ratio;\n gfc.thm[1].l[sb] += l * ratio;\n }\n for (var sb = 0; sb < Encoder.SBMAX_s; sb++) {\n for (var sblock = 0; sblock < 3; sblock++) {\n var l = gfc.thm[0].s[sb][sblock];\n var r = gfc.thm[1].s[sb][sblock];\n gfc.thm[0].s[sb][sblock] += r * ratio;\n gfc.thm[1].s[sb][sblock] += l * ratio;\n }\n }\n }\n }\n\n /**\n * compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper\n */\n function msfix1(gfc) {\n for (var sb = 0; sb < Encoder.SBMAX_l; sb++) {\n /* use this fix if L & R masking differs by 2db or less */\n /* if db = 10*log10(x2/x1) < 2 */\n /* if (x2 < 1.58*x1) { */\n if (gfc.thm[0].l[sb] > 1.58 * gfc.thm[1].l[sb]\n || gfc.thm[1].l[sb] > 1.58 * gfc.thm[0].l[sb])\n continue;\n var mld = gfc.mld_l[sb] * gfc.en[3].l[sb];\n var rmid = Math.max(gfc.thm[2].l[sb],\n Math.min(gfc.thm[3].l[sb], mld));\n\n mld = gfc.mld_l[sb] * gfc.en[2].l[sb];\n var rside = Math.max(gfc.thm[3].l[sb],\n Math.min(gfc.thm[2].l[sb], mld));\n gfc.thm[2].l[sb] = rmid;\n gfc.thm[3].l[sb] = rside;\n }\n\n for (var sb = 0; sb < Encoder.SBMAX_s; sb++) {\n for (var sblock = 0; sblock < 3; sblock++) {\n if (gfc.thm[0].s[sb][sblock] > 1.58 * gfc.thm[1].s[sb][sblock]\n || gfc.thm[1].s[sb][sblock] > 1.58 * gfc.thm[0].s[sb][sblock])\n continue;\n var mld = gfc.mld_s[sb] * gfc.en[3].s[sb][sblock];\n var rmid = Math.max(gfc.thm[2].s[sb][sblock],\n Math.min(gfc.thm[3].s[sb][sblock], mld));\n\n mld = gfc.mld_s[sb] * gfc.en[2].s[sb][sblock];\n var rside = Math.max(gfc.thm[3].s[sb][sblock],\n Math.min(gfc.thm[2].s[sb][sblock], mld));\n\n gfc.thm[2].s[sb][sblock] = rmid;\n gfc.thm[3].s[sb][sblock] = rside;\n }\n }\n }\n\n /**\n * Adjust M/S maskings if user set "msfix"\n *\n * Naoki Shibata 2000\n */\n function ns_msfix(gfc, msfix, athadjust) {\n var msfix2 = msfix;\n var athlower = Math.pow(10, athadjust);\n\n msfix *= 2.0;\n msfix2 *= 2.0;\n for (var sb = 0; sb < Encoder.SBMAX_l; sb++) {\n var thmLR, thmM, thmS, ath;\n ath = (gfc.ATH.cb_l[gfc.bm_l[sb]]) * athlower;\n thmLR = Math.min(Math.max(gfc.thm[0].l[sb], ath),\n Math.max(gfc.thm[1].l[sb], ath));\n thmM = Math.max(gfc.thm[2].l[sb], ath);\n thmS = Math.max(gfc.thm[3].l[sb], ath);\n if (thmLR * msfix < thmM + thmS) {\n var f = thmLR * msfix2 / (thmM + thmS);\n thmM *= f;\n thmS *= f;\n assert(thmM + thmS > 0);\n }\n gfc.thm[2].l[sb] = Math.min(thmM, gfc.thm[2].l[sb]);\n gfc.thm[3].l[sb] = Math.min(thmS, gfc.thm[3].l[sb]);\n }\n\n athlower *= ( Encoder.BLKSIZE_s / Encoder.BLKSIZE);\n for (var sb = 0; sb < Encoder.SBMAX_s; sb++) {\n for (var sblock = 0; sblock < 3; sblock++) {\n var thmLR, thmM, thmS, ath;\n ath = (gfc.ATH.cb_s[gfc.bm_s[sb]]) * athlower;\n thmLR = Math.min(Math.max(gfc.thm[0].s[sb][sblock], ath),\n Math.max(gfc.thm[1].s[sb][sblock], ath));\n thmM = Math.max(gfc.thm[2].s[sb][sblock], ath);\n thmS = Math.max(gfc.thm[3].s[sb][sblock], ath);\n\n if (thmLR * msfix < thmM + thmS) {\n var f = thmLR * msfix / (thmM + thmS);\n thmM *= f;\n thmS *= f;\n assert(thmM + thmS > 0);\n }\n gfc.thm[2].s[sb][sblock] = Math.min(gfc.thm[2].s[sb][sblock],\n thmM);\n gfc.thm[3].s[sb][sblock] = Math.min(gfc.thm[3].s[sb][sblock],\n thmS);\n }\n }\n }\n\n /**\n * short block threshold calculation (part 2)\n *\n * partition band bo_s[sfb] is at the transition from scalefactor band sfb\n * to the next one sfb+1; enn and thmm have to be split between them\n */\n function convert_partition2scalefac_s(gfc, eb, thr, chn, sblock) {\n var sb, b;\n var enn = 0.0;\n var thmm = 0.0;\n for (sb = b = 0; sb < Encoder.SBMAX_s; ++b, ++sb) {\n var bo_s_sb = gfc.bo_s[sb];\n var npart_s = gfc.npart_s;\n var b_lim = bo_s_sb < npart_s ? bo_s_sb : npart_s;\n while (b < b_lim) {\n assert(eb[b] >= 0);\n // iff failed, it may indicate some index error elsewhere\n assert(thr[b] >= 0);\n enn += eb[b];\n thmm += thr[b];\n b++;\n }\n gfc.en[chn].s[sb][sblock] = enn;\n gfc.thm[chn].s[sb][sblock] = thmm;\n\n if (b >= npart_s) {\n ++sb;\n break;\n }\n assert(eb[b] >= 0);\n // iff failed, it may indicate some index error elsewhere\n assert(thr[b] >= 0);\n {\n /* at transition sfb . sfb+1 */\n var w_curr = gfc.PSY.bo_s_weight[sb];\n var w_next = 1.0 - w_curr;\n enn = w_curr * eb[b];\n thmm = w_curr * thr[b];\n gfc.en[chn].s[sb][sblock] += enn;\n gfc.thm[chn].s[sb][sblock] += thmm;\n enn = w_next * eb[b];\n thmm = w_next * thr[b];\n }\n }\n /* zero initialize the rest */\n for (; sb < Encoder.SBMAX_s; ++sb) {\n gfc.en[chn].s[sb][sblock] = 0;\n gfc.thm[chn].s[sb][sblock] = 0;\n }\n }\n\n /**\n * longblock threshold calculation (part 2)\n */\n function convert_partition2scalefac_l(gfc, eb, thr, chn) {\n var sb, b;\n var enn = 0.0;\n var thmm = 0.0;\n for (sb = b = 0; sb < Encoder.SBMAX_l; ++b, ++sb) {\n var bo_l_sb = gfc.bo_l[sb];\n var npart_l = gfc.npart_l;\n var b_lim = bo_l_sb < npart_l ? bo_l_sb : npart_l;\n while (b < b_lim) {\n assert(eb[b] >= 0);\n // iff failed, it may indicate some index error elsewhere\n assert(thr[b] >= 0);\n enn += eb[b];\n thmm += thr[b];\n b++;\n }\n gfc.en[chn].l[sb] = enn;\n gfc.thm[chn].l[sb] = thmm;\n\n if (b >= npart_l) {\n ++sb;\n break;\n }\n assert(eb[b] >= 0);\n assert(thr[b] >= 0);\n {\n /* at transition sfb . sfb+1 */\n var w_curr = gfc.PSY.bo_l_weight[sb];\n var w_next = 1.0 - w_curr;\n enn = w_curr * eb[b];\n thmm = w_curr * thr[b];\n gfc.en[chn].l[sb] += enn;\n gfc.thm[chn].l[sb] += thmm;\n enn = w_next * eb[b];\n thmm = w_next * thr[b];\n }\n }\n /* zero initialize the rest */\n for (; sb < Encoder.SBMAX_l; ++sb) {\n gfc.en[chn].l[sb] = 0;\n gfc.thm[chn].l[sb] = 0;\n }\n }\n\n function compute_masking_s(gfp, fftenergy_s, eb, thr, chn, sblock) {\n var gfc = gfp.internal_flags;\n var j, b;\n\n for (b = j = 0; b < gfc.npart_s; ++b) {\n var ebb = 0, m = 0;\n var n = gfc.numlines_s[b];\n for (var i = 0; i < n; ++i, ++j) {\n var el = fftenergy_s[sblock][j];\n ebb += el;\n if (m < el)\n m = el;\n }\n eb[b] = ebb;\n }\n assert(b == gfc.npart_s);\n assert(j == 129);\n for (j = b = 0; b < gfc.npart_s; b++) {\n var kk = gfc.s3ind_s[b][0];\n var ecb = gfc.s3_ss[j++] * eb[kk];\n ++kk;\n while (kk <= gfc.s3ind_s[b][1]) {\n ecb += gfc.s3_ss[j] * eb[kk];\n ++j;\n ++kk;\n }\n\n { /* limit calculated threshold by previous granule */\n var x = rpelev_s * gfc.nb_s1[chn][b];\n thr[b] = Math.min(ecb, x);\n }\n if (gfc.blocktype_old[chn & 1] == Encoder.SHORT_TYPE) {\n /* limit calculated threshold by even older granule */\n var x = rpelev2_s * gfc.nb_s2[chn][b];\n var y = thr[b];\n thr[b] = Math.min(x, y);\n }\n\n gfc.nb_s2[chn][b] = gfc.nb_s1[chn][b];\n gfc.nb_s1[chn][b] = ecb;\n assert(thr[b] >= 0);\n }\n for (; b <= Encoder.CBANDS; ++b) {\n eb[b] = 0;\n thr[b] = 0;\n }\n }\n\n function block_type_set(gfp, uselongblock, blocktype_d, blocktype) {\n var gfc = gfp.internal_flags;\n\n if (gfp.short_blocks == ShortBlock.short_block_coupled\n /* force both channels to use the same block type */\n /* this is necessary if the frame is to be encoded in ms_stereo. */\n /* But even without ms_stereo, FhG does this */\n && !(uselongblock[0] != 0 && uselongblock[1] != 0))\n uselongblock[0] = uselongblock[1] = 0;\n\n /*\n * update the blocktype of the previous granule, since it depends on\n * what happend in this granule\n */\n for (var chn = 0; chn < gfc.channels_out; chn++) {\n blocktype[chn] = Encoder.NORM_TYPE;\n /* disable short blocks */\n if (gfp.short_blocks == ShortBlock.short_block_dispensed)\n uselongblock[chn] = 1;\n if (gfp.short_blocks == ShortBlock.short_block_forced)\n uselongblock[chn] = 0;\n\n if (uselongblock[chn] != 0) {\n /* no attack : use long blocks */\n assert(gfc.blocktype_old[chn] != Encoder.START_TYPE);\n if (gfc.blocktype_old[chn] == Encoder.SHORT_TYPE)\n blocktype[chn] = Encoder.STOP_TYPE;\n } else {\n /* attack : use short blocks */\n blocktype[chn] = Encoder.SHORT_TYPE;\n if (gfc.blocktype_old[chn] == Encoder.NORM_TYPE) {\n gfc.blocktype_old[chn] = Encoder.START_TYPE;\n }\n if (gfc.blocktype_old[chn] == Encoder.STOP_TYPE)\n gfc.blocktype_old[chn] = Encoder.SHORT_TYPE;\n }\n\n blocktype_d[chn] = gfc.blocktype_old[chn];\n // value returned to calling program\n gfc.blocktype_old[chn] = blocktype[chn];\n // save for next call to l3psy_anal\n }\n }\n\n function NS_INTERP(x, y, r) {\n /* was pow((x),(r))*pow((y),1-(r)) */\n if (r >= 1.0) {\n /* 99.7% of the time */\n return x;\n }\n if (r <= 0.0)\n return y;\n if (y > 0.0) {\n /* rest of the time */\n return (Math.pow(x / y, r) * y);\n }\n /* never happens */\n return 0.0;\n }\n\n /**\n * these values are tuned only for 44.1kHz...\n */\n var regcoef_s = [11.8, 13.6, 17.2, 32, 46.5,\n 51.3, 57.5, 67.1, 71.5, 84.6, 97.6, 130,\n /* 255.8 */\n ];\n\n function pecalc_s(mr, masking_lower) {\n var pe_s = 1236.28 / 4;\n for (var sb = 0; sb < Encoder.SBMAX_s - 1; sb++) {\n for (var sblock = 0; sblock < 3; sblock++) {\n var thm = mr.thm.s[sb][sblock];\n assert(sb < regcoef_s.length);\n if (thm > 0.0) {\n var x = thm * masking_lower;\n var en = mr.en.s[sb][sblock];\n if (en > x) {\n if (en > x * 1e10) {\n pe_s += regcoef_s[sb] * (10.0 * LOG10);\n } else {\n assert(x > 0);\n pe_s += regcoef_s[sb] * Util.FAST_LOG10(en / x);\n }\n }\n }\n }\n }\n\n return pe_s;\n }\n\n /**\n * these values are tuned only for 44.1kHz...\n */\n var regcoef_l = [6.8, 5.8, 5.8, 6.4, 6.5, 9.9,\n 12.1, 14.4, 15, 18.9, 21.6, 26.9, 34.2, 40.2, 46.8, 56.5,\n 60.7, 73.9, 85.7, 93.4, 126.1,\n /* 241.3 */\n ];\n\n function pecalc_l(mr, masking_lower) {\n var pe_l = 1124.23 / 4;\n for (var sb = 0; sb < Encoder.SBMAX_l - 1; sb++) {\n var thm = mr.thm.l[sb];\n assert(sb < regcoef_l.length);\n if (thm > 0.0) {\n var x = thm * masking_lower;\n var en = mr.en.l[sb];\n if (en > x) {\n if (en > x * 1e10) {\n pe_l += regcoef_l[sb] * (10.0 * LOG10);\n } else {\n assert(x > 0);\n pe_l += regcoef_l[sb] * Util.FAST_LOG10(en / x);\n }\n }\n }\n }\n return pe_l;\n }\n\n function calc_energy(gfc, fftenergy, eb, max, avg) {\n var b, j;\n\n for (b = j = 0; b < gfc.npart_l; ++b) {\n var ebb = 0, m = 0;\n var i;\n for (i = 0; i < gfc.numlines_l[b]; ++i, ++j) {\n var el = fftenergy[j];\n assert(el >= 0);\n ebb += el;\n if (m < el)\n m = el;\n }\n eb[b] = ebb;\n max[b] = m;\n avg[b] = ebb * gfc.rnumlines_l[b];\n assert(gfc.rnumlines_l[b] >= 0);\n assert(ebb >= 0);\n assert(eb[b] >= 0);\n assert(max[b] >= 0);\n assert(avg[b] >= 0);\n }\n }\n\n function calc_mask_index_l(gfc, max, avg, mask_idx) {\n var last_tab_entry = tab.length - 1;\n var b = 0;\n var a = avg[b] + avg[b + 1];\n assert(a >= 0);\n if (a > 0.0) {\n var m = max[b];\n if (m < max[b + 1])\n m = max[b + 1];\n assert((gfc.numlines_l[b] + gfc.numlines_l[b + 1] - 1) > 0);\n a = 20.0 * (m * 2.0 - a)\n / (a * (gfc.numlines_l[b] + gfc.numlines_l[b + 1] - 1));\n var k = 0 | a;\n if (k > last_tab_entry)\n k = last_tab_entry;\n mask_idx[b] = k;\n } else {\n mask_idx[b] = 0;\n }\n\n for (b = 1; b < gfc.npart_l - 1; b++) {\n a = avg[b - 1] + avg[b] + avg[b + 1];\n assert(a >= 0);\n if (a > 0.0) {\n var m = max[b - 1];\n if (m < max[b])\n m = max[b];\n if (m < max[b + 1])\n m = max[b + 1];\n assert((gfc.numlines_l[b - 1] + gfc.numlines_l[b] + gfc.numlines_l[b + 1] - 1) > 0);\n a = 20.0\n * (m * 3.0 - a)\n / (a * (gfc.numlines_l[b - 1] + gfc.numlines_l[b]\n + gfc.numlines_l[b + 1] - 1));\n var k = 0 | a;\n if (k > last_tab_entry)\n k = last_tab_entry;\n mask_idx[b] = k;\n } else {\n mask_idx[b] = 0;\n }\n }\n assert(b > 0);\n assert(b == gfc.npart_l - 1);\n\n a = avg[b - 1] + avg[b];\n assert(a >= 0);\n if (a > 0.0) {\n var m = max[b - 1];\n if (m < max[b])\n m = max[b];\n assert((gfc.numlines_l[b - 1] + gfc.numlines_l[b] - 1) > 0);\n a = 20.0 * (m * 2.0 - a)\n / (a * (gfc.numlines_l[b - 1] + gfc.numlines_l[b] - 1));\n var k = 0 | a;\n if (k > last_tab_entry)\n k = last_tab_entry;\n mask_idx[b] = k;\n } else {\n mask_idx[b] = 0;\n }\n assert(b == (gfc.npart_l - 1));\n }\n\n var fircoef = [\n -8.65163e-18 * 2, -0.00851586 * 2, -6.74764e-18 * 2, 0.0209036 * 2,\n -3.36639e-17 * 2, -0.0438162 * 2, -1.54175e-17 * 2, 0.0931738 * 2,\n -5.52212e-17 * 2, -0.313819 * 2\n ];\n\n this.L3psycho_anal_ns = function (gfp, buffer, bufPos, gr_out, masking_ratio, masking_MS_ratio, percep_entropy, percep_MS_entropy, energy, blocktype_d) {\n /*\n * to get a good cache performance, one has to think about the sequence,\n * in which the variables are used.\n */\n var gfc = gfp.internal_flags;\n\n /* fft and energy calculation */\n var wsamp_L = new_float_n([2, Encoder.BLKSIZE]);\n var wsamp_S = new_float_n([2, 3, Encoder.BLKSIZE_s]);\n\n /* convolution */\n var eb_l = new_float(Encoder.CBANDS + 1);\n var eb_s = new_float(Encoder.CBANDS + 1);\n var thr = new_float(Encoder.CBANDS + 2);\n\n /* block type */\n var blocktype = new_int(2), uselongblock = new_int(2);\n\n /* usual variables like loop indices, etc.. */\n var numchn, chn;\n var b, i, j, k;\n var sb, sblock;\n\n /* variables used for --nspsytune */\n var ns_hpfsmpl = new_float_n([2, 576]);\n var pcfact;\n var mask_idx_l = new_int(Encoder.CBANDS + 2), mask_idx_s = new_int(Encoder.CBANDS + 2);\n\n Arrays.fill(mask_idx_s, 0);\n\n numchn = gfc.channels_out;\n /* chn=2 and 3 = Mid and Side channels */\n if (gfp.mode == MPEGMode.JOINT_STEREO)\n numchn = 4;\n\n if (gfp.VBR == VbrMode.vbr_off)\n pcfact = gfc.ResvMax == 0 ? 0 : ( gfc.ResvSize)\n / gfc.ResvMax * 0.5;\n else if (gfp.VBR == VbrMode.vbr_rh || gfp.VBR == VbrMode.vbr_mtrh\n || gfp.VBR == VbrMode.vbr_mt) {\n pcfact = 0.6;\n } else\n pcfact = 1.0;\n\n /**********************************************************************\n * Apply HPF of fs/4 to the input signal. This is used for attack\n * detection / handling.\n **********************************************************************/\n /* Don\'t copy the input buffer into a temporary buffer */\n /* unroll the loop 2 times */\n for (chn = 0; chn < gfc.channels_out; chn++) {\n /* apply high pass filter of fs/4 */\n var firbuf = buffer[chn];\n var firbufPos = bufPos + 576 - 350 - NSFIRLEN + 192;\n assert(fircoef.length == ((NSFIRLEN - 1) / 2));\n for (i = 0; i < 576; i++) {\n var sum1, sum2;\n sum1 = firbuf[firbufPos + i + 10];\n sum2 = 0.0;\n for (j = 0; j < ((NSFIRLEN - 1) / 2) - 1; j += 2) {\n sum1 += fircoef[j]\n * (firbuf[firbufPos + i + j] + firbuf[firbufPos + i\n + NSFIRLEN - j]);\n sum2 += fircoef[j + 1]\n * (firbuf[firbufPos + i + j + 1] + firbuf[firbufPos\n + i + NSFIRLEN - j - 1]);\n }\n ns_hpfsmpl[chn][i] = sum1 + sum2;\n }\n masking_ratio[gr_out][chn].en.assign(gfc.en[chn]);\n masking_ratio[gr_out][chn].thm.assign(gfc.thm[chn]);\n if (numchn > 2) {\n /* MS maskings */\n /* percep_MS_entropy [chn-2] = gfc . pe [chn]; */\n masking_MS_ratio[gr_out][chn].en.assign(gfc.en[chn + 2]);\n masking_MS_ratio[gr_out][chn].thm.assign(gfc.thm[chn + 2]);\n }\n }\n\n for (chn = 0; chn < numchn; chn++) {\n var wsamp_l;\n var wsamp_s;\n var en_subshort = new_float(12);\n var en_short = [0, 0, 0, 0];\n var attack_intensity = new_float(12);\n var ns_uselongblock = 1;\n var attackThreshold;\n var max = new_float(Encoder.CBANDS), avg = new_float(Encoder.CBANDS);\n var ns_attacks = [0, 0, 0, 0];\n var fftenergy = new_float(Encoder.HBLKSIZE);\n var fftenergy_s = new_float_n([3, Encoder.HBLKSIZE_s]);\n\n /*\n * rh 20040301: the following loops do access one off the limits so\n * I increase the array dimensions by one and initialize the\n * accessed values to zero\n */\n assert(gfc.npart_s <= Encoder.CBANDS);\n assert(gfc.npart_l <= Encoder.CBANDS);\n\n /***************************************************************\n * determine the block type (window type)\n ***************************************************************/\n /* calculate energies of each sub-shortblocks */\n for (i = 0; i < 3; i++) {\n en_subshort[i] = gfc.nsPsy.last_en_subshort[chn][i + 6];\n assert(gfc.nsPsy.last_en_subshort[chn][i + 4] > 0);\n attack_intensity[i] = en_subshort[i]\n / gfc.nsPsy.last_en_subshort[chn][i + 4];\n en_short[0] += en_subshort[i];\n }\n\n if (chn == 2) {\n for (i = 0; i < 576; i++) {\n var l, r;\n l = ns_hpfsmpl[0][i];\n r = ns_hpfsmpl[1][i];\n ns_hpfsmpl[0][i] = l + r;\n ns_hpfsmpl[1][i] = l - r;\n }\n }\n {\n var pf = ns_hpfsmpl[chn & 1];\n var pfPos = 0;\n for (i = 0; i < 9; i++) {\n var pfe = pfPos + 576 / 9;\n var p = 1.;\n for (; pfPos < pfe; pfPos++)\n if (p < Math.abs(pf[pfPos]))\n p = Math.abs(pf[pfPos]);\n\n gfc.nsPsy.last_en_subshort[chn][i] = en_subshort[i + 3] = p;\n en_short[1 + i / 3] += p;\n if (p > en_subshort[i + 3 - 2]) {\n assert(en_subshort[i + 3 - 2] > 0);\n p = p / en_subshort[i + 3 - 2];\n } else if (en_subshort[i + 3 - 2] > p * 10.0) {\n assert(p > 0);\n p = en_subshort[i + 3 - 2] / (p * 10.0);\n } else\n p = 0.0;\n attack_intensity[i + 3] = p;\n }\n }\n\n if (gfp.analysis) {\n var x = attack_intensity[0];\n for (i = 1; i < 12; i++)\n if (x < attack_intensity[i])\n x = attack_intensity[i];\n gfc.pinfo.ers[gr_out][chn] = gfc.pinfo.ers_save[chn];\n gfc.pinfo.ers_save[chn] = x;\n }\n\n /* compare energies between sub-shortblocks */\n attackThreshold = (chn == 3) ? gfc.nsPsy.attackthre_s\n : gfc.nsPsy.attackthre;\n for (i = 0; i < 12; i++)\n if (0 == ns_attacks[i / 3]\n && attack_intensity[i] > attackThreshold)\n ns_attacks[i / 3] = (i % 3) + 1;\n\n /*\n * should have energy change between short blocks, in order to avoid\n * periodic signals\n */\n for (i = 1; i < 4; i++) {\n var ratio;\n if (en_short[i - 1] > en_short[i]) {\n assert(en_short[i] > 0);\n ratio = en_short[i - 1] / en_short[i];\n } else {\n assert(en_short[i - 1] > 0);\n ratio = en_short[i] / en_short[i - 1];\n }\n if (ratio < 1.7) {\n ns_attacks[i] = 0;\n if (i == 1)\n ns_attacks[0] = 0;\n }\n }\n\n if (ns_attacks[0] != 0 && gfc.nsPsy.lastAttacks[chn] != 0)\n ns_attacks[0] = 0;\n\n if (gfc.nsPsy.lastAttacks[chn] == 3\n || (ns_attacks[0] + ns_attacks[1] + ns_attacks[2] + ns_attacks[3]) != 0) {\n ns_uselongblock = 0;\n\n if (ns_attacks[1] != 0 && ns_attacks[0] != 0)\n ns_attacks[1] = 0;\n if (ns_attacks[2] != 0 && ns_attacks[1] != 0)\n ns_attacks[2] = 0;\n if (ns_attacks[3] != 0 && ns_attacks[2] != 0)\n ns_attacks[3] = 0;\n }\n\n if (chn < 2) {\n uselongblock[chn] = ns_uselongblock;\n } else {\n if (ns_uselongblock == 0) {\n uselongblock[0] = uselongblock[1] = 0;\n }\n }\n\n /*\n * there is a one granule delay. Copy maskings computed last call\n * into masking_ratio to return to calling program.\n */\n energy[chn] = gfc.tot_ener[chn];\n\n /*********************************************************************\n * compute FFTs\n *********************************************************************/\n wsamp_s = wsamp_S;\n wsamp_l = wsamp_L;\n compute_ffts(gfp, fftenergy, fftenergy_s, wsamp_l, (chn & 1),\n wsamp_s, (chn & 1), gr_out, chn, buffer, bufPos);\n\n /*********************************************************************\n * Calculate the energy and the tonality of each partition.\n *********************************************************************/\n calc_energy(gfc, fftenergy, eb_l, max, avg);\n calc_mask_index_l(gfc, max, avg, mask_idx_l);\n /* compute masking thresholds for short blocks */\n for (sblock = 0; sblock < 3; sblock++) {\n var enn, thmm;\n compute_masking_s(gfp, fftenergy_s, eb_s, thr, chn, sblock);\n convert_partition2scalefac_s(gfc, eb_s, thr, chn, sblock);\n /**** short block pre-echo control ****/\n for (sb = 0; sb < Encoder.SBMAX_s; sb++) {\n thmm = gfc.thm[chn].s[sb][sblock];\n\n thmm *= NS_PREECHO_ATT0;\n if (ns_attacks[sblock] >= 2 || ns_attacks[sblock + 1] == 1) {\n var idx = (sblock != 0) ? sblock - 1 : 2;\n var p = NS_INTERP(gfc.thm[chn].s[sb][idx], thmm,\n NS_PREECHO_ATT1 * pcfact);\n thmm = Math.min(thmm, p);\n }\n\n if (ns_attacks[sblock] == 1) {\n var idx = (sblock != 0) ? sblock - 1 : 2;\n var p = NS_INTERP(gfc.thm[chn].s[sb][idx], thmm,\n NS_PREECHO_ATT2 * pcfact);\n thmm = Math.min(thmm, p);\n } else if ((sblock != 0 && ns_attacks[sblock - 1] == 3)\n || (sblock == 0 && gfc.nsPsy.lastAttacks[chn] == 3)) {\n var idx = (sblock != 2) ? sblock + 1 : 0;\n var p = NS_INTERP(gfc.thm[chn].s[sb][idx], thmm,\n NS_PREECHO_ATT2 * pcfact);\n thmm = Math.min(thmm, p);\n }\n\n /* pulse like signal detection for fatboy.wav and so on */\n enn = en_subshort[sblock * 3 + 3]\n + en_subshort[sblock * 3 + 4]\n + en_subshort[sblock * 3 + 5];\n if (en_subshort[sblock * 3 + 5] * 6 < enn) {\n thmm *= 0.5;\n if (en_subshort[sblock * 3 + 4] * 6 < enn)\n thmm *= 0.5;\n }\n\n gfc.thm[chn].s[sb][sblock] = thmm;\n }\n }\n gfc.nsPsy.lastAttacks[chn] = ns_attacks[2];\n\n /*********************************************************************\n * convolve the partitioned energy and unpredictability with the\n * spreading function, s3_l[b][k]\n ********************************************************************/\n k = 0;\n {\n for (b = 0; b < gfc.npart_l; b++) {\n /*\n * convolve the partitioned energy with the spreading\n * function\n */\n var kk = gfc.s3ind[b][0];\n var eb2 = eb_l[kk] * tab[mask_idx_l[kk]];\n var ecb = gfc.s3_ll[k++] * eb2;\n while (++kk <= gfc.s3ind[b][1]) {\n eb2 = eb_l[kk] * tab[mask_idx_l[kk]];\n ecb = mask_add(ecb, gfc.s3_ll[k++] * eb2, kk, kk - b,\n gfc, 0);\n }\n ecb *= 0.158489319246111;\n /* pow(10,-0.8) */\n\n /**** long block pre-echo control ****/\n /**\n *
\n                     * dont use long block pre-echo control if previous granule was\n                     * a short block.  This is to avoid the situation:\n                     * frame0:  quiet (very low masking)\n                     * frame1:  surge  (triggers short blocks)\n                     * frame2:  regular frame.  looks like pre-echo when compared to\n                     *          frame0, but all pre-echo was in frame1.\n                     * 
\n */\n /*\n * chn=0,1 L and R channels\n *\n * chn=2,3 S and M channels.\n */\n\n if (gfc.blocktype_old[chn & 1] == Encoder.SHORT_TYPE)\n thr[b] = ecb;\n else\n thr[b] = NS_INTERP(\n Math.min(ecb, Math.min(rpelev\n * gfc.nb_1[chn][b], rpelev2\n * gfc.nb_2[chn][b])), ecb, pcfact);\n\n gfc.nb_2[chn][b] = gfc.nb_1[chn][b];\n gfc.nb_1[chn][b] = ecb;\n }\n }\n for (; b <= Encoder.CBANDS; ++b) {\n eb_l[b] = 0;\n thr[b] = 0;\n }\n /* compute masking thresholds for long blocks */\n convert_partition2scalefac_l(gfc, eb_l, thr, chn);\n }\n /* end loop over chn */\n\n if (gfp.mode == MPEGMode.STEREO || gfp.mode == MPEGMode.JOINT_STEREO) {\n if (gfp.interChRatio > 0.0) {\n calc_interchannel_masking(gfp, gfp.interChRatio);\n }\n }\n\n if (gfp.mode == MPEGMode.JOINT_STEREO) {\n var msfix;\n msfix1(gfc);\n msfix = gfp.msfix;\n if (Math.abs(msfix) > 0.0)\n ns_msfix(gfc, msfix, gfp.ATHlower * gfc.ATH.adjust);\n }\n\n /***************************************************************\n * determine final block type\n ***************************************************************/\n block_type_set(gfp, uselongblock, blocktype_d, blocktype);\n\n /*********************************************************************\n * compute the value of PE to return ... no delay and advance\n *********************************************************************/\n for (chn = 0; chn < numchn; chn++) {\n var ppe;\n var ppePos = 0;\n var type;\n var mr;\n\n if (chn > 1) {\n ppe = percep_MS_entropy;\n ppePos = -2;\n type = Encoder.NORM_TYPE;\n if (blocktype_d[0] == Encoder.SHORT_TYPE\n || blocktype_d[1] == Encoder.SHORT_TYPE)\n type = Encoder.SHORT_TYPE;\n mr = masking_MS_ratio[gr_out][chn - 2];\n } else {\n ppe = percep_entropy;\n ppePos = 0;\n type = blocktype_d[chn];\n mr = masking_ratio[gr_out][chn];\n }\n\n if (type == Encoder.SHORT_TYPE)\n ppe[ppePos + chn] = pecalc_s(mr, gfc.masking_lower);\n else\n ppe[ppePos + chn] = pecalc_l(mr, gfc.masking_lower);\n\n if (gfp.analysis)\n gfc.pinfo.pe[gr_out][chn] = ppe[ppePos + chn];\n\n }\n return 0;\n }\n\n function vbrpsy_compute_fft_l(gfp, buffer, bufPos, chn, gr_out, fftenergy, wsamp_l, wsamp_lPos) {\n var gfc = gfp.internal_flags;\n if (chn < 2) {\n fft.fft_long(gfc, wsamp_l[wsamp_lPos], chn, buffer, bufPos);\n } else if (chn == 2) {\n /* FFT data for mid and side channel is derived from L & R */\n for (var j = Encoder.BLKSIZE - 1; j >= 0; --j) {\n var l = wsamp_l[wsamp_lPos + 0][j];\n var r = wsamp_l[wsamp_lPos + 1][j];\n wsamp_l[wsamp_lPos + 0][j] = (l + r) * Util.SQRT2 * 0.5;\n wsamp_l[wsamp_lPos + 1][j] = (l - r) * Util.SQRT2 * 0.5;\n }\n }\n\n /*********************************************************************\n * compute energies\n *********************************************************************/\n fftenergy[0] = NON_LINEAR_SCALE_ENERGY(wsamp_l[wsamp_lPos + 0][0]);\n fftenergy[0] *= fftenergy[0];\n\n for (var j = Encoder.BLKSIZE / 2 - 1; j >= 0; --j) {\n var re = wsamp_l[wsamp_lPos + 0][Encoder.BLKSIZE / 2 - j];\n var im = wsamp_l[wsamp_lPos + 0][Encoder.BLKSIZE / 2 + j];\n fftenergy[Encoder.BLKSIZE / 2 - j] = NON_LINEAR_SCALE_ENERGY((re\n * re + im * im) * 0.5);\n }\n /* total energy */\n {\n var totalenergy = 0.0;\n for (var j = 11; j < Encoder.HBLKSIZE; j++)\n totalenergy += fftenergy[j];\n\n gfc.tot_ener[chn] = totalenergy;\n }\n\n if (gfp.analysis) {\n for (var j = 0; j < Encoder.HBLKSIZE; j++) {\n gfc.pinfo.energy[gr_out][chn][j] = gfc.pinfo.energy_save[chn][j];\n gfc.pinfo.energy_save[chn][j] = fftenergy[j];\n }\n gfc.pinfo.pe[gr_out][chn] = gfc.pe[chn];\n }\n }\n\n function vbrpsy_compute_fft_s(gfp, buffer, bufPos, chn, sblock, fftenergy_s, wsamp_s, wsamp_sPos) {\n var gfc = gfp.internal_flags;\n\n if (sblock == 0 && chn < 2) {\n fft.fft_short(gfc, wsamp_s[wsamp_sPos], chn, buffer, bufPos);\n }\n if (chn == 2) {\n /* FFT data for mid and side channel is derived from L & R */\n for (var j = Encoder.BLKSIZE_s - 1; j >= 0; --j) {\n var l = wsamp_s[wsamp_sPos + 0][sblock][j];\n var r = wsamp_s[wsamp_sPos + 1][sblock][j];\n wsamp_s[wsamp_sPos + 0][sblock][j] = (l + r) * Util.SQRT2 * 0.5;\n wsamp_s[wsamp_sPos + 1][sblock][j] = (l - r) * Util.SQRT2 * 0.5;\n }\n }\n\n /*********************************************************************\n * compute energies\n *********************************************************************/\n fftenergy_s[sblock][0] = wsamp_s[wsamp_sPos + 0][sblock][0];\n fftenergy_s[sblock][0] *= fftenergy_s[sblock][0];\n for (var j = Encoder.BLKSIZE_s / 2 - 1; j >= 0; --j) {\n var re = wsamp_s[wsamp_sPos + 0][sblock][Encoder.BLKSIZE_s / 2 - j];\n var im = wsamp_s[wsamp_sPos + 0][sblock][Encoder.BLKSIZE_s / 2 + j];\n fftenergy_s[sblock][Encoder.BLKSIZE_s / 2 - j] = NON_LINEAR_SCALE_ENERGY((re\n * re + im * im) * 0.5);\n }\n }\n\n /**\n * compute loudness approximation (used for ATH auto-level adjustment)\n */\n function vbrpsy_compute_loudness_approximation_l(gfp, gr_out, chn, fftenergy) {\n var gfc = gfp.internal_flags;\n if (gfp.athaa_loudapprox == 2 && chn < 2) {\n // no loudness for mid/side ch\n gfc.loudness_sq[gr_out][chn] = gfc.loudness_sq_save[chn];\n gfc.loudness_sq_save[chn] = psycho_loudness_approx(fftenergy, gfc);\n }\n }\n\n var fircoef_ = [-8.65163e-18 * 2,\n -0.00851586 * 2, -6.74764e-18 * 2, 0.0209036 * 2,\n -3.36639e-17 * 2, -0.0438162 * 2, -1.54175e-17 * 2,\n 0.0931738 * 2, -5.52212e-17 * 2, -0.313819 * 2];\n\n /**\n * Apply HPF of fs/4 to the input signal. This is used for attack detection\n * / handling.\n */\n function vbrpsy_attack_detection(gfp, buffer, bufPos, gr_out, masking_ratio, masking_MS_ratio, energy, sub_short_factor, ns_attacks, uselongblock) {\n var ns_hpfsmpl = new_float_n([2, 576]);\n var gfc = gfp.internal_flags;\n var n_chn_out = gfc.channels_out;\n /* chn=2 and 3 = Mid and Side channels */\n var n_chn_psy = (gfp.mode == MPEGMode.JOINT_STEREO) ? 4 : n_chn_out;\n /* Don\'t copy the input buffer into a temporary buffer */\n /* unroll the loop 2 times */\n for (var chn = 0; chn < n_chn_out; chn++) {\n /* apply high pass filter of fs/4 */\n firbuf = buffer[chn];\n var firbufPos = bufPos + 576 - 350 - NSFIRLEN + 192;\n assert(fircoef_.length == ((NSFIRLEN - 1) / 2));\n for (var i = 0; i < 576; i++) {\n var sum1, sum2;\n sum1 = firbuf[firbufPos + i + 10];\n sum2 = 0.0;\n for (var j = 0; j < ((NSFIRLEN - 1) / 2) - 1; j += 2) {\n sum1 += fircoef_[j]\n * (firbuf[firbufPos + i + j] + firbuf[firbufPos + i\n + NSFIRLEN - j]);\n sum2 += fircoef_[j + 1]\n * (firbuf[firbufPos + i + j + 1] + firbuf[firbufPos\n + i + NSFIRLEN - j - 1]);\n }\n ns_hpfsmpl[chn][i] = sum1 + sum2;\n }\n masking_ratio[gr_out][chn].en.assign(gfc.en[chn]);\n masking_ratio[gr_out][chn].thm.assign(gfc.thm[chn]);\n if (n_chn_psy > 2) {\n /* MS maskings */\n /* percep_MS_entropy [chn-2] = gfc . pe [chn]; */\n masking_MS_ratio[gr_out][chn].en.assign(gfc.en[chn + 2]);\n masking_MS_ratio[gr_out][chn].thm.assign(gfc.thm[chn + 2]);\n }\n }\n for (var chn = 0; chn < n_chn_psy; chn++) {\n var attack_intensity = new_float(12);\n var en_subshort = new_float(12);\n var en_short = [0, 0, 0, 0];\n var pf = ns_hpfsmpl[chn & 1];\n var pfPos = 0;\n var attackThreshold = (chn == 3) ? gfc.nsPsy.attackthre_s\n : gfc.nsPsy.attackthre;\n var ns_uselongblock = 1;\n\n if (chn == 2) {\n for (var i = 0, j = 576; j > 0; ++i, --j) {\n var l = ns_hpfsmpl[0][i];\n var r = ns_hpfsmpl[1][i];\n ns_hpfsmpl[0][i] = l + r;\n ns_hpfsmpl[1][i] = l - r;\n }\n }\n /***************************************************************\n * determine the block type (window type)\n ***************************************************************/\n /* calculate energies of each sub-shortblocks */\n for (var i = 0; i < 3; i++) {\n en_subshort[i] = gfc.nsPsy.last_en_subshort[chn][i + 6];\n assert(gfc.nsPsy.last_en_subshort[chn][i + 4] > 0);\n attack_intensity[i] = en_subshort[i]\n / gfc.nsPsy.last_en_subshort[chn][i + 4];\n en_short[0] += en_subshort[i];\n }\n\n for (var i = 0; i < 9; i++) {\n var pfe = pfPos + 576 / 9;\n var p = 1.;\n for (; pfPos < pfe; pfPos++)\n if (p < Math.abs(pf[pfPos]))\n p = Math.abs(pf[pfPos]);\n\n gfc.nsPsy.last_en_subshort[chn][i] = en_subshort[i + 3] = p;\n en_short[1 + i / 3] += p;\n if (p > en_subshort[i + 3 - 2]) {\n assert(en_subshort[i + 3 - 2] > 0);\n p = p / en_subshort[i + 3 - 2];\n } else if (en_subshort[i + 3 - 2] > p * 10.0) {\n assert(p > 0);\n p = en_subshort[i + 3 - 2] / (p * 10.0);\n } else {\n p = 0.0;\n }\n attack_intensity[i + 3] = p;\n }\n /* pulse like signal detection for fatboy.wav and so on */\n for (var i = 0; i < 3; ++i) {\n var enn = en_subshort[i * 3 + 3]\n + en_subshort[i * 3 + 4] + en_subshort[i * 3 + 5];\n var factor = 1.;\n if (en_subshort[i * 3 + 5] * 6 < enn) {\n factor *= 0.5;\n if (en_subshort[i * 3 + 4] * 6 < enn) {\n factor *= 0.5;\n }\n }\n sub_short_factor[chn][i] = factor;\n }\n\n if (gfp.analysis) {\n var x = attack_intensity[0];\n for (var i = 1; i < 12; i++) {\n if (x < attack_intensity[i]) {\n x = attack_intensity[i];\n }\n }\n gfc.pinfo.ers[gr_out][chn] = gfc.pinfo.ers_save[chn];\n gfc.pinfo.ers_save[chn] = x;\n }\n\n /* compare energies between sub-shortblocks */\n for (var i = 0; i < 12; i++) {\n if (0 == ns_attacks[chn][i / 3]\n && attack_intensity[i] > attackThreshold) {\n ns_attacks[chn][i / 3] = (i % 3) + 1;\n }\n }\n\n /*\n * should have energy change between short blocks, in order to avoid\n * periodic signals\n */\n /* Good samples to show the effect are Trumpet test songs */\n /*\n * GB: tuned (1) to avoid too many short blocks for test sample\n * TRUMPET\n */\n /*\n * RH: tuned (2) to let enough short blocks through for test sample\n * FSOL and SNAPS\n */\n for (var i = 1; i < 4; i++) {\n var u = en_short[i - 1];\n var v = en_short[i];\n var m = Math.max(u, v);\n if (m < 40000) { /* (2) */\n if (u < 1.7 * v && v < 1.7 * u) { /* (1) */\n if (i == 1 && ns_attacks[chn][0] <= ns_attacks[chn][i]) {\n ns_attacks[chn][0] = 0;\n }\n ns_attacks[chn][i] = 0;\n }\n }\n }\n\n if (ns_attacks[chn][0] <= gfc.nsPsy.lastAttacks[chn]) {\n ns_attacks[chn][0] = 0;\n }\n\n if (gfc.nsPsy.lastAttacks[chn] == 3\n || (ns_attacks[chn][0] + ns_attacks[chn][1]\n + ns_attacks[chn][2] + ns_attacks[chn][3]) != 0) {\n ns_uselongblock = 0;\n\n if (ns_attacks[chn][1] != 0 && ns_attacks[chn][0] != 0) {\n ns_attacks[chn][1] = 0;\n }\n if (ns_attacks[chn][2] != 0 && ns_attacks[chn][1] != 0) {\n ns_attacks[chn][2] = 0;\n }\n if (ns_attacks[chn][3] != 0 && ns_attacks[chn][2] != 0) {\n ns_attacks[chn][3] = 0;\n }\n }\n if (chn < 2) {\n uselongblock[chn] = ns_uselongblock;\n } else {\n if (ns_uselongblock == 0) {\n uselongblock[0] = uselongblock[1] = 0;\n }\n }\n\n /*\n * there is a one granule delay. Copy maskings computed last call\n * into masking_ratio to return to calling program.\n */\n energy[chn] = gfc.tot_ener[chn];\n }\n }\n\n function vbrpsy_skip_masking_s(gfc, chn, sblock) {\n if (sblock == 0) {\n for (var b = 0; b < gfc.npart_s; b++) {\n gfc.nb_s2[chn][b] = gfc.nb_s1[chn][b];\n gfc.nb_s1[chn][b] = 0;\n }\n }\n }\n\n function vbrpsy_skip_masking_l(gfc, chn) {\n for (var b = 0; b < gfc.npart_l; b++) {\n gfc.nb_2[chn][b] = gfc.nb_1[chn][b];\n gfc.nb_1[chn][b] = 0;\n }\n }\n\n function psyvbr_calc_mask_index_s(gfc, max, avg, mask_idx) {\n var last_tab_entry = tab.length - 1;\n var b = 0;\n var a = avg[b] + avg[b + 1];\n assert(a >= 0);\n if (a > 0.0) {\n var m = max[b];\n if (m < max[b + 1])\n m = max[b + 1];\n assert((gfc.numlines_s[b] + gfc.numlines_s[b + 1] - 1) > 0);\n a = 20.0 * (m * 2.0 - a)\n / (a * (gfc.numlines_s[b] + gfc.numlines_s[b + 1] - 1));\n var k = 0 | a;\n if (k > last_tab_entry)\n k = last_tab_entry;\n mask_idx[b] = k;\n } else {\n mask_idx[b] = 0;\n }\n\n for (b = 1; b < gfc.npart_s - 1; b++) {\n a = avg[b - 1] + avg[b] + avg[b + 1];\n assert(b + 1 < gfc.npart_s);\n assert(a >= 0);\n if (a > 0.0) {\n var m = max[b - 1];\n if (m < max[b])\n m = max[b];\n if (m < max[b + 1])\n m = max[b + 1];\n assert((gfc.numlines_s[b - 1] + gfc.numlines_s[b] + gfc.numlines_s[b + 1] - 1) > 0);\n a = 20.0\n * (m * 3.0 - a)\n / (a * (gfc.numlines_s[b - 1] + gfc.numlines_s[b]\n + gfc.numlines_s[b + 1] - 1));\n var k = 0 | a;\n if (k > last_tab_entry)\n k = last_tab_entry;\n mask_idx[b] = k;\n } else {\n mask_idx[b] = 0;\n }\n }\n assert(b > 0);\n assert(b == gfc.npart_s - 1);\n\n a = avg[b - 1] + avg[b];\n assert(a >= 0);\n if (a > 0.0) {\n var m = max[b - 1];\n if (m < max[b])\n m = max[b];\n assert((gfc.numlines_s[b - 1] + gfc.numlines_s[b] - 1) > 0);\n a = 20.0 * (m * 2.0 - a)\n / (a * (gfc.numlines_s[b - 1] + gfc.numlines_s[b] - 1));\n var k = 0 | a;\n if (k > last_tab_entry)\n k = last_tab_entry;\n mask_idx[b] = k;\n } else {\n mask_idx[b] = 0;\n }\n assert(b == (gfc.npart_s - 1));\n }\n\n function vbrpsy_compute_masking_s(gfp, fftenergy_s, eb, thr, chn, sblock) {\n var gfc = gfp.internal_flags;\n var max = new float[Encoder.CBANDS], avg = new_float(Encoder.CBANDS);\n var i, j, b;\n var mask_idx_s = new int[Encoder.CBANDS];\n\n for (b = j = 0; b < gfc.npart_s; ++b) {\n var ebb = 0, m = 0;\n var n = gfc.numlines_s[b];\n for (i = 0; i < n; ++i, ++j) {\n var el = fftenergy_s[sblock][j];\n ebb += el;\n if (m < el)\n m = el;\n }\n eb[b] = ebb;\n assert(ebb >= 0);\n max[b] = m;\n assert(n > 0);\n avg[b] = ebb / n;\n assert(avg[b] >= 0);\n }\n assert(b == gfc.npart_s);\n assert(j == 129);\n for (; b < Encoder.CBANDS; ++b) {\n max[b] = 0;\n avg[b] = 0;\n }\n psyvbr_calc_mask_index_s(gfc, max, avg, mask_idx_s);\n for (j = b = 0; b < gfc.npart_s; b++) {\n var kk = gfc.s3ind_s[b][0];\n var last = gfc.s3ind_s[b][1];\n var dd, dd_n;\n var x, ecb, avg_mask;\n dd = mask_idx_s[kk];\n dd_n = 1;\n ecb = gfc.s3_ss[j] * eb[kk] * tab[mask_idx_s[kk]];\n ++j;\n ++kk;\n while (kk <= last) {\n dd += mask_idx_s[kk];\n dd_n += 1;\n x = gfc.s3_ss[j] * eb[kk] * tab[mask_idx_s[kk]];\n ecb = vbrpsy_mask_add(ecb, x, kk - b);\n ++j;\n ++kk;\n }\n dd = (1 + 2 * dd) / (2 * dd_n);\n avg_mask = tab[dd] * 0.5;\n ecb *= avg_mask;\n thr[b] = ecb;\n gfc.nb_s2[chn][b] = gfc.nb_s1[chn][b];\n gfc.nb_s1[chn][b] = ecb;\n {\n /*\n * if THR exceeds EB, the quantization routines will take the\n * difference from other bands. in case of strong tonal samples\n * (tonaltest.wav) this leads to heavy distortions. that\'s why\n * we limit THR here.\n */\n x = max[b];\n x *= gfc.minval_s[b];\n x *= avg_mask;\n if (thr[b] > x) {\n thr[b] = x;\n }\n }\n if (gfc.masking_lower > 1) {\n thr[b] *= gfc.masking_lower;\n }\n if (thr[b] > eb[b]) {\n thr[b] = eb[b];\n }\n if (gfc.masking_lower < 1) {\n thr[b] *= gfc.masking_lower;\n }\n\n assert(thr[b] >= 0);\n }\n for (; b < Encoder.CBANDS; ++b) {\n eb[b] = 0;\n thr[b] = 0;\n }\n }\n\n function vbrpsy_compute_masking_l(gfc, fftenergy, eb_l, thr, chn) {\n var max = new_float(Encoder.CBANDS), avg = new_float(Encoder.CBANDS);\n var mask_idx_l = new_int(Encoder.CBANDS + 2);\n var b;\n\n /*********************************************************************\n * Calculate the energy and the tonality of each partition.\n *********************************************************************/\n calc_energy(gfc, fftenergy, eb_l, max, avg);\n calc_mask_index_l(gfc, max, avg, mask_idx_l);\n\n /*********************************************************************\n * convolve the partitioned energy and unpredictability with the\n * spreading function, s3_l[b][k]\n ********************************************************************/\n var k = 0;\n for (b = 0; b < gfc.npart_l; b++) {\n var x, ecb, avg_mask, t;\n /* convolve the partitioned energy with the spreading function */\n var kk = gfc.s3ind[b][0];\n var last = gfc.s3ind[b][1];\n var dd = 0, dd_n = 0;\n dd = mask_idx_l[kk];\n dd_n += 1;\n ecb = gfc.s3_ll[k] * eb_l[kk] * tab[mask_idx_l[kk]];\n ++k;\n ++kk;\n while (kk <= last) {\n dd += mask_idx_l[kk];\n dd_n += 1;\n x = gfc.s3_ll[k] * eb_l[kk] * tab[mask_idx_l[kk]];\n t = vbrpsy_mask_add(ecb, x, kk - b);\n ecb = t;\n ++k;\n ++kk;\n }\n dd = (1 + 2 * dd) / (2 * dd_n);\n avg_mask = tab[dd] * 0.5;\n ecb *= avg_mask;\n\n /**** long block pre-echo control ****/\n /**\n *
\n             * dont use long block pre-echo control if previous granule was\n             * a short block.  This is to avoid the situation:\n             * frame0:  quiet (very low masking)\n             * frame1:  surge  (triggers short blocks)\n             * frame2:  regular frame.  looks like pre-echo when compared to\n             *          frame0, but all pre-echo was in frame1.\n             * 
\n */\n /*\n * chn=0,1 L and R channels chn=2,3 S and M channels.\n */\n if (gfc.blocktype_old[chn & 0x01] == Encoder.SHORT_TYPE) {\n var ecb_limit = rpelev * gfc.nb_1[chn][b];\n if (ecb_limit > 0) {\n thr[b] = Math.min(ecb, ecb_limit);\n } else {\n /**\n *
\n                     * Robert 071209:\n                     * Because we don\'t calculate long block psy when we know a granule\n                     * should be of short blocks, we don\'t have any clue how the granule\n                     * before would have looked like as a long block. So we have to guess\n                     * a little bit for this END_TYPE block.\n                     * Most of the time we get away with this sloppyness. (fingers crossed :)\n                     * The speed increase is worth it.\n                     * 
\n */\n thr[b] = Math.min(ecb, eb_l[b] * NS_PREECHO_ATT2);\n }\n } else {\n var ecb_limit_2 = rpelev2 * gfc.nb_2[chn][b];\n var ecb_limit_1 = rpelev * gfc.nb_1[chn][b];\n var ecb_limit;\n if (ecb_limit_2 <= 0) {\n ecb_limit_2 = ecb;\n }\n if (ecb_limit_1 <= 0) {\n ecb_limit_1 = ecb;\n }\n if (gfc.blocktype_old[chn & 0x01] == Encoder.NORM_TYPE) {\n ecb_limit = Math.min(ecb_limit_1, ecb_limit_2);\n } else {\n ecb_limit = ecb_limit_1;\n }\n thr[b] = Math.min(ecb, ecb_limit);\n }\n gfc.nb_2[chn][b] = gfc.nb_1[chn][b];\n gfc.nb_1[chn][b] = ecb;\n {\n /*\n * if THR exceeds EB, the quantization routines will take the\n * difference from other bands. in case of strong tonal samples\n * (tonaltest.wav) this leads to heavy distortions. that\'s why\n * we limit THR here.\n */\n x = max[b];\n x *= gfc.minval_l[b];\n x *= avg_mask;\n if (thr[b] > x) {\n thr[b] = x;\n }\n }\n if (gfc.masking_lower > 1) {\n thr[b] *= gfc.masking_lower;\n }\n if (thr[b] > eb_l[b]) {\n thr[b] = eb_l[b];\n }\n if (gfc.masking_lower < 1) {\n thr[b] *= gfc.masking_lower;\n }\n assert(thr[b] >= 0);\n }\n for (; b < Encoder.CBANDS; ++b) {\n eb_l[b] = 0;\n thr[b] = 0;\n }\n }\n\n function vbrpsy_compute_block_type(gfp, uselongblock) {\n var gfc = gfp.internal_flags;\n\n if (gfp.short_blocks == ShortBlock.short_block_coupled\n /* force both channels to use the same block type */\n /* this is necessary if the frame is to be encoded in ms_stereo. */\n /* But even without ms_stereo, FhG does this */\n && !(uselongblock[0] != 0 && uselongblock[1] != 0))\n uselongblock[0] = uselongblock[1] = 0;\n\n for (var chn = 0; chn < gfc.channels_out; chn++) {\n /* disable short blocks */\n if (gfp.short_blocks == ShortBlock.short_block_dispensed) {\n uselongblock[chn] = 1;\n }\n if (gfp.short_blocks == ShortBlock.short_block_forced) {\n uselongblock[chn] = 0;\n }\n }\n }\n\n function vbrpsy_apply_block_type(gfp, uselongblock, blocktype_d) {\n var gfc = gfp.internal_flags;\n\n /*\n * update the blocktype of the previous granule, since it depends on\n * what happend in this granule\n */\n for (var chn = 0; chn < gfc.channels_out; chn++) {\n var blocktype = Encoder.NORM_TYPE;\n /* disable short blocks */\n\n if (uselongblock[chn] != 0) {\n /* no attack : use long blocks */\n assert(gfc.blocktype_old[chn] != Encoder.START_TYPE);\n if (gfc.blocktype_old[chn] == Encoder.SHORT_TYPE)\n blocktype = Encoder.STOP_TYPE;\n } else {\n /* attack : use short blocks */\n blocktype = Encoder.SHORT_TYPE;\n if (gfc.blocktype_old[chn] == Encoder.NORM_TYPE) {\n gfc.blocktype_old[chn] = Encoder.START_TYPE;\n }\n if (gfc.blocktype_old[chn] == Encoder.STOP_TYPE)\n gfc.blocktype_old[chn] = Encoder.SHORT_TYPE;\n }\n\n blocktype_d[chn] = gfc.blocktype_old[chn];\n // value returned to calling program\n gfc.blocktype_old[chn] = blocktype;\n // save for next call to l3psy_anal\n }\n }\n\n /**\n * compute M/S thresholds from Johnston & Ferreira 1992 ICASSP paper\n */\n function vbrpsy_compute_MS_thresholds(eb, thr, cb_mld, ath_cb, athadjust, msfix, n) {\n var msfix2 = msfix * 2;\n var athlower = msfix > 0 ? Math.pow(10, athadjust) : 1;\n var rside, rmid;\n for (var b = 0; b < n; ++b) {\n var ebM = eb[2][b];\n var ebS = eb[3][b];\n var thmL = thr[0][b];\n var thmR = thr[1][b];\n var thmM = thr[2][b];\n var thmS = thr[3][b];\n\n /* use this fix if L & R masking differs by 2db or less */\n if (thmL <= 1.58 * thmR && thmR <= 1.58 * thmL) {\n var mld_m = cb_mld[b] * ebS;\n var mld_s = cb_mld[b] * ebM;\n rmid = Math.max(thmM, Math.min(thmS, mld_m));\n rside = Math.max(thmS, Math.min(thmM, mld_s));\n } else {\n rmid = thmM;\n rside = thmS;\n }\n if (msfix > 0) {\n /***************************************************************/\n /* Adjust M/S maskings if user set "msfix" */\n /***************************************************************/\n /* Naoki Shibata 2000 */\n var thmLR, thmMS;\n var ath = ath_cb[b] * athlower;\n thmLR = Math.min(Math.max(thmL, ath), Math.max(thmR, ath));\n thmM = Math.max(rmid, ath);\n thmS = Math.max(rside, ath);\n thmMS = thmM + thmS;\n if (thmMS > 0 && (thmLR * msfix2) < thmMS) {\n var f = thmLR * msfix2 / thmMS;\n thmM *= f;\n thmS *= f;\n assert(thmMS > 0);\n }\n rmid = Math.min(thmM, rmid);\n rside = Math.min(thmS, rside);\n }\n if (rmid > ebM) {\n rmid = ebM;\n }\n if (rside > ebS) {\n rside = ebS;\n }\n thr[2][b] = rmid;\n thr[3][b] = rside;\n }\n }\n\n this.L3psycho_anal_vbr = function (gfp, buffer, bufPos, gr_out, masking_ratio, masking_MS_ratio, percep_entropy, percep_MS_entropy, energy, blocktype_d) {\n var gfc = gfp.internal_flags;\n\n /* fft and energy calculation */\n var wsamp_l;\n var wsamp_s;\n var fftenergy = new_float(Encoder.HBLKSIZE);\n var fftenergy_s = new_float_n([3, Encoder.HBLKSIZE_s]);\n var wsamp_L = new_float_n([2, Encoder.BLKSIZE]);\n var wsamp_S = new_float_n([2, 3, Encoder.BLKSIZE_s]);\n var eb = new_float_n([4, Encoder.CBANDS]), thr = new_float_n([4, Encoder.CBANDS]);\n var sub_short_factor = new_float_n([4, 3]);\n var pcfact = 0.6;\n\n /* block type */\n var ns_attacks = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0],\n [0, 0, 0, 0]];\n var uselongblock = new_int(2);\n\n /* usual variables like loop indices, etc.. */\n\n /* chn=2 and 3 = Mid and Side channels */\n var n_chn_psy = (gfp.mode == MPEGMode.JOINT_STEREO) ? 4\n : gfc.channels_out;\n\n vbrpsy_attack_detection(gfp, buffer, bufPos, gr_out, masking_ratio,\n masking_MS_ratio, energy, sub_short_factor, ns_attacks,\n uselongblock);\n\n vbrpsy_compute_block_type(gfp, uselongblock);\n\n /* LONG BLOCK CASE */\n {\n for (var chn = 0; chn < n_chn_psy; chn++) {\n var ch01 = chn & 0x01;\n wsamp_l = wsamp_L;\n vbrpsy_compute_fft_l(gfp, buffer, bufPos, chn, gr_out,\n fftenergy, wsamp_l, ch01);\n\n vbrpsy_compute_loudness_approximation_l(gfp, gr_out, chn,\n fftenergy);\n\n if (uselongblock[ch01] != 0) {\n vbrpsy_compute_masking_l(gfc, fftenergy, eb[chn], thr[chn],\n chn);\n } else {\n vbrpsy_skip_masking_l(gfc, chn);\n }\n }\n if ((uselongblock[0] + uselongblock[1]) == 2) {\n /* M/S channel */\n if (gfp.mode == MPEGMode.JOINT_STEREO) {\n vbrpsy_compute_MS_thresholds(eb, thr, gfc.mld_cb_l,\n gfc.ATH.cb_l, gfp.ATHlower * gfc.ATH.adjust,\n gfp.msfix, gfc.npart_l);\n }\n }\n /* TODO: apply adaptive ATH masking here ?? */\n for (var chn = 0; chn < n_chn_psy; chn++) {\n var ch01 = chn & 0x01;\n if (uselongblock[ch01] != 0) {\n convert_partition2scalefac_l(gfc, eb[chn], thr[chn], chn);\n }\n }\n }\n\n /* SHORT BLOCKS CASE */\n {\n for (var sblock = 0; sblock < 3; sblock++) {\n for (var chn = 0; chn < n_chn_psy; ++chn) {\n var ch01 = chn & 0x01;\n\n if (uselongblock[ch01] != 0) {\n vbrpsy_skip_masking_s(gfc, chn, sblock);\n } else {\n /* compute masking thresholds for short blocks */\n wsamp_s = wsamp_S;\n vbrpsy_compute_fft_s(gfp, buffer, bufPos, chn, sblock,\n fftenergy_s, wsamp_s, ch01);\n vbrpsy_compute_masking_s(gfp, fftenergy_s, eb[chn],\n thr[chn], chn, sblock);\n }\n }\n if ((uselongblock[0] + uselongblock[1]) == 0) {\n /* M/S channel */\n if (gfp.mode == MPEGMode.JOINT_STEREO) {\n vbrpsy_compute_MS_thresholds(eb, thr, gfc.mld_cb_s,\n gfc.ATH.cb_s, gfp.ATHlower * gfc.ATH.adjust,\n gfp.msfix, gfc.npart_s);\n }\n /* L/R channel */\n }\n /* TODO: apply adaptive ATH masking here ?? */\n for (var chn = 0; chn < n_chn_psy; ++chn) {\n var ch01 = chn & 0x01;\n if (0 == uselongblock[ch01]) {\n convert_partition2scalefac_s(gfc, eb[chn], thr[chn],\n chn, sblock);\n }\n }\n }\n\n /**** short block pre-echo control ****/\n for (var chn = 0; chn < n_chn_psy; chn++) {\n var ch01 = chn & 0x01;\n\n if (uselongblock[ch01] != 0) {\n continue;\n }\n for (var sb = 0; sb < Encoder.SBMAX_s; sb++) {\n var new_thmm = new_float(3);\n for (var sblock = 0; sblock < 3; sblock++) {\n var thmm = gfc.thm[chn].s[sb][sblock];\n thmm *= NS_PREECHO_ATT0;\n\n if (ns_attacks[chn][sblock] >= 2\n || ns_attacks[chn][sblock + 1] == 1) {\n var idx = (sblock != 0) ? sblock - 1 : 2;\n var p = NS_INTERP(gfc.thm[chn].s[sb][idx], thmm,\n NS_PREECHO_ATT1 * pcfact);\n thmm = Math.min(thmm, p);\n } else if (ns_attacks[chn][sblock] == 1) {\n var idx = (sblock != 0) ? sblock - 1 : 2;\n var p = NS_INTERP(gfc.thm[chn].s[sb][idx], thmm,\n NS_PREECHO_ATT2 * pcfact);\n thmm = Math.min(thmm, p);\n } else if ((sblock != 0 && ns_attacks[chn][sblock - 1] == 3)\n || (sblock == 0 && gfc.nsPsy.lastAttacks[chn] == 3)) {\n var idx = (sblock != 2) ? sblock + 1 : 0;\n var p = NS_INTERP(gfc.thm[chn].s[sb][idx], thmm,\n NS_PREECHO_ATT2 * pcfact);\n thmm = Math.min(thmm, p);\n }\n\n /* pulse like signal detection for fatboy.wav and so on */\n thmm *= sub_short_factor[chn][sblock];\n\n new_thmm[sblock] = thmm;\n }\n for (var sblock = 0; sblock < 3; sblock++) {\n gfc.thm[chn].s[sb][sblock] = new_thmm[sblock];\n }\n }\n }\n }\n for (var chn = 0; chn < n_chn_psy; chn++) {\n gfc.nsPsy.lastAttacks[chn] = ns_attacks[chn][2];\n }\n\n /***************************************************************\n * determine final block type\n ***************************************************************/\n vbrpsy_apply_block_type(gfp, uselongblock, blocktype_d);\n\n /*********************************************************************\n * compute the value of PE to return ... no delay and advance\n *********************************************************************/\n for (var chn = 0; chn < n_chn_psy; chn++) {\n var ppe;\n var ppePos;\n var type;\n var mr;\n\n if (chn > 1) {\n ppe = percep_MS_entropy;\n ppePos = -2;\n type = Encoder.NORM_TYPE;\n if (blocktype_d[0] == Encoder.SHORT_TYPE\n || blocktype_d[1] == Encoder.SHORT_TYPE)\n type = Encoder.SHORT_TYPE;\n mr = masking_MS_ratio[gr_out][chn - 2];\n } else {\n ppe = percep_entropy;\n ppePos = 0;\n type = blocktype_d[chn];\n mr = masking_ratio[gr_out][chn];\n }\n\n if (type == Encoder.SHORT_TYPE) {\n ppe[ppePos + chn] = pecalc_s(mr, gfc.masking_lower);\n } else {\n ppe[ppePos + chn] = pecalc_l(mr, gfc.masking_lower);\n }\n\n if (gfp.analysis) {\n gfc.pinfo.pe[gr_out][chn] = ppe[ppePos + chn];\n }\n }\n return 0;\n }\n\n function s3_func_x(bark, hf_slope) {\n var tempx = bark, tempy;\n\n if (tempx >= 0) {\n tempy = -tempx * 27;\n } else {\n tempy = tempx * hf_slope;\n }\n if (tempy <= -72.0) {\n return 0;\n }\n return Math.exp(tempy * LN_TO_LOG10);\n }\n\n function norm_s3_func_x(hf_slope) {\n var lim_a = 0, lim_b = 0;\n {\n var x = 0, l, h;\n for (x = 0; s3_func_x(x, hf_slope) > 1e-20; x -= 1)\n ;\n l = x;\n h = 0;\n while (Math.abs(h - l) > 1e-12) {\n x = (h + l) / 2;\n if (s3_func_x(x, hf_slope) > 0) {\n h = x;\n } else {\n l = x;\n }\n }\n lim_a = l;\n }\n {\n var x = 0, l, h;\n for (x = 0; s3_func_x(x, hf_slope) > 1e-20; x += 1)\n ;\n l = 0;\n h = x;\n while (Math.abs(h - l) > 1e-12) {\n x = (h + l) / 2;\n if (s3_func_x(x, hf_slope) > 0) {\n l = x;\n } else {\n h = x;\n }\n }\n lim_b = h;\n }\n {\n var sum = 0;\n var m = 1000;\n var i;\n for (i = 0; i <= m; ++i) {\n var x = lim_a + i * (lim_b - lim_a) / m;\n var y = s3_func_x(x, hf_slope);\n sum += y;\n }\n {\n var norm = (m + 1) / (sum * (lim_b - lim_a));\n /* printf( "norm = %lf\\n",norm); */\n return norm;\n }\n }\n }\n\n /**\n * The spreading function. Values returned in units of energy\n */\n function s3_func(bark) {\n var tempx, x, tempy, temp;\n tempx = bark;\n if (tempx >= 0)\n tempx *= 3;\n else\n tempx *= 1.5;\n\n if (tempx >= 0.5 && tempx <= 2.5) {\n temp = tempx - 0.5;\n x = 8.0 * (temp * temp - 2.0 * temp);\n } else\n x = 0.0;\n tempx += 0.474;\n tempy = 15.811389 + 7.5 * tempx - 17.5\n * Math.sqrt(1.0 + tempx * tempx);\n\n if (tempy <= -60.0)\n return 0.0;\n\n tempx = Math.exp((x + tempy) * LN_TO_LOG10);\n\n /**\n *
\n         * Normalization.  The spreading function should be normalized so that:\n         * +inf\n         * /\n         * |  s3 [ bark ]  d(bark)   =  1\n         * /\n         * -inf\n         * 
\n */\n tempx /= .6609193;\n return tempx;\n }\n\n /**\n * see for example "Zwicker: Psychoakustik, 1982; ISBN 3-540-11401-7\n */\n function freq2bark(freq) {\n /* input: freq in hz output: barks */\n if (freq < 0)\n freq = 0;\n freq = freq * 0.001;\n return 13.0 * Math.atan(.76 * freq) + 3.5\n * Math.atan(freq * freq / (7.5 * 7.5));\n }\n\n function init_numline(numlines, bo, bm, bval, bval_width, mld, bo_w, sfreq, blksize, scalepos, deltafreq, sbmax) {\n var b_frq = new_float(Encoder.CBANDS + 1);\n var sample_freq_frac = sfreq / (sbmax > 15 ? 2 * 576 : 2 * 192);\n var partition = new_int(Encoder.HBLKSIZE);\n var i;\n sfreq /= blksize;\n var j = 0;\n var ni = 0;\n /* compute numlines, the number of spectral lines in each partition band */\n /* each partition band should be about DELBARK wide. */\n for (i = 0; i < Encoder.CBANDS; i++) {\n var bark1;\n var j2;\n bark1 = freq2bark(sfreq * j);\n\n b_frq[i] = sfreq * j;\n\n for (j2 = j; freq2bark(sfreq * j2) - bark1 < DELBARK\n && j2 <= blksize / 2; j2++)\n ;\n\n numlines[i] = j2 - j;\n ni = i + 1;\n\n while (j < j2) {\n assert(j < Encoder.HBLKSIZE);\n partition[j++] = i;\n }\n if (j > blksize / 2) {\n j = blksize / 2;\n ++i;\n break;\n }\n }\n assert(i < Encoder.CBANDS);\n b_frq[i] = sfreq * j;\n\n for (var sfb = 0; sfb < sbmax; sfb++) {\n var i1, i2, start, end;\n var arg;\n start = scalepos[sfb];\n end = scalepos[sfb + 1];\n\n i1 = 0 | Math.floor(.5 + deltafreq * (start - .5));\n if (i1 < 0)\n i1 = 0;\n i2 = 0 | Math.floor(.5 + deltafreq * (end - .5));\n\n if (i2 > blksize / 2)\n i2 = blksize / 2;\n\n bm[sfb] = (partition[i1] + partition[i2]) / 2;\n bo[sfb] = partition[i2];\n var f_tmp = sample_freq_frac * end;\n /*\n * calculate how much of this band belongs to current scalefactor\n * band\n */\n bo_w[sfb] = (f_tmp - b_frq[bo[sfb]])\n / (b_frq[bo[sfb] + 1] - b_frq[bo[sfb]]);\n if (bo_w[sfb] < 0) {\n bo_w[sfb] = 0;\n } else {\n if (bo_w[sfb] > 1) {\n bo_w[sfb] = 1;\n }\n }\n /* setup stereo demasking thresholds */\n /* formula reverse enginerred from plot in paper */\n arg = freq2bark(sfreq * scalepos[sfb] * deltafreq);\n arg = ( Math.min(arg, 15.5) / 15.5);\n\n mld[sfb] = Math.pow(10.0,\n 1.25 * (1 - Math.cos(Math.PI * arg)) - 2.5);\n }\n\n /* compute bark values of each critical band */\n j = 0;\n for (var k = 0; k < ni; k++) {\n var w = numlines[k];\n var bark1, bark2;\n\n bark1 = freq2bark(sfreq * (j));\n bark2 = freq2bark(sfreq * (j + w - 1));\n bval[k] = .5 * (bark1 + bark2);\n\n bark1 = freq2bark(sfreq * (j - .5));\n bark2 = freq2bark(sfreq * (j + w - .5));\n bval_width[k] = bark2 - bark1;\n j += w;\n }\n\n return ni;\n }\n\n function init_s3_values(s3ind, npart, bval, bval_width, norm, use_old_s3) {\n var s3 = new_float_n([Encoder.CBANDS, Encoder.CBANDS]);\n /*\n * The s3 array is not linear in the bark scale.\n *\n * bval[x] should be used to get the bark value.\n */\n var j;\n var numberOfNoneZero = 0;\n\n /**\n *
\n         * s[i][j], the value of the spreading function,\n         * centered at band j (masker), for band i (maskee)\n         *\n         * i.e.: sum over j to spread into signal barkval=i\n         * NOTE: i and j are used opposite as in the ISO docs\n         * 
\n */\n if (use_old_s3) {\n for (var i = 0; i < npart; i++) {\n for (j = 0; j < npart; j++) {\n var v = s3_func(bval[i] - bval[j]) * bval_width[j];\n s3[i][j] = v * norm[i];\n }\n }\n } else {\n for (j = 0; j < npart; j++) {\n var hf_slope = 15 + Math.min(21 / bval[j], 12);\n var s3_x_norm = norm_s3_func_x(hf_slope);\n for (var i = 0; i < npart; i++) {\n var v = s3_x_norm\n * s3_func_x(bval[i] - bval[j], hf_slope)\n * bval_width[j];\n s3[i][j] = v * norm[i];\n }\n }\n }\n for (var i = 0; i < npart; i++) {\n for (j = 0; j < npart; j++) {\n if (s3[i][j] > 0.0)\n break;\n }\n s3ind[i][0] = j;\n\n for (j = npart - 1; j > 0; j--) {\n if (s3[i][j] > 0.0)\n break;\n }\n s3ind[i][1] = j;\n numberOfNoneZero += (s3ind[i][1] - s3ind[i][0] + 1);\n }\n\n var p = new_float(numberOfNoneZero);\n var k = 0;\n for (var i = 0; i < npart; i++)\n for (j = s3ind[i][0]; j <= s3ind[i][1]; j++)\n p[k++] = s3[i][j];\n\n return p;\n }\n\n function stereo_demask(f) {\n /* setup stereo demasking thresholds */\n /* formula reverse enginerred from plot in paper */\n var arg = freq2bark(f);\n arg = (Math.min(arg, 15.5) / 15.5);\n\n return Math.pow(10.0,\n 1.25 * (1 - Math.cos(Math.PI * arg)) - 2.5);\n }\n\n /**\n * NOTE: the bitrate reduction from the inter-channel masking effect is low\n * compared to the chance of getting annyoing artefacts. L3psycho_anal_vbr\n * does not use this feature. (Robert 071216)\n */\n this.psymodel_init = function (gfp) {\n var gfc = gfp.internal_flags;\n var i;\n var useOldS3 = true;\n var bvl_a = 13, bvl_b = 24;\n var snr_l_a = 0, snr_l_b = 0;\n var snr_s_a = -8.25, snr_s_b = -4.5;\n var bval = new_float(Encoder.CBANDS);\n var bval_width = new_float(Encoder.CBANDS);\n var norm = new_float(Encoder.CBANDS);\n var sfreq = gfp.out_samplerate;\n\n switch (gfp.experimentalZ) {\n default:\n case 0:\n useOldS3 = true;\n break;\n case 1:\n useOldS3 = (gfp.VBR == VbrMode.vbr_mtrh || gfp.VBR == VbrMode.vbr_mt) ? false\n : true;\n break;\n case 2:\n useOldS3 = false;\n break;\n case 3:\n bvl_a = 8;\n snr_l_a = -1.75;\n snr_l_b = -0.0125;\n snr_s_a = -8.25;\n snr_s_b = -2.25;\n break;\n }\n gfc.ms_ener_ratio_old = .25;\n gfc.blocktype_old[0] = gfc.blocktype_old[1] = Encoder.NORM_TYPE;\n // the vbr header is long blocks\n\n for (i = 0; i < 4; ++i) {\n for (var j = 0; j < Encoder.CBANDS; ++j) {\n gfc.nb_1[i][j] = 1e20;\n gfc.nb_2[i][j] = 1e20;\n gfc.nb_s1[i][j] = gfc.nb_s2[i][j] = 1.0;\n }\n for (var sb = 0; sb < Encoder.SBMAX_l; sb++) {\n gfc.en[i].l[sb] = 1e20;\n gfc.thm[i].l[sb] = 1e20;\n }\n for (var j = 0; j < 3; ++j) {\n for (var sb = 0; sb < Encoder.SBMAX_s; sb++) {\n gfc.en[i].s[sb][j] = 1e20;\n gfc.thm[i].s[sb][j] = 1e20;\n }\n gfc.nsPsy.lastAttacks[i] = 0;\n }\n for (var j = 0; j < 9; j++)\n gfc.nsPsy.last_en_subshort[i][j] = 10.;\n }\n\n /* init. for loudness approx. -jd 2001 mar 27 */\n gfc.loudness_sq_save[0] = gfc.loudness_sq_save[1] = 0.0;\n\n /*************************************************************************\n * now compute the psychoacoustic model specific constants\n ************************************************************************/\n /* compute numlines, bo, bm, bval, bval_width, mld */\n\n gfc.npart_l = init_numline(gfc.numlines_l, gfc.bo_l, gfc.bm_l, bval,\n bval_width, gfc.mld_l, gfc.PSY.bo_l_weight, sfreq,\n Encoder.BLKSIZE, gfc.scalefac_band.l, Encoder.BLKSIZE\n / (2.0 * 576), Encoder.SBMAX_l);\n assert(gfc.npart_l < Encoder.CBANDS);\n /* compute the spreading function */\n for (i = 0; i < gfc.npart_l; i++) {\n var snr = snr_l_a;\n if (bval[i] >= bvl_a) {\n snr = snr_l_b * (bval[i] - bvl_a) / (bvl_b - bvl_a) + snr_l_a\n * (bvl_b - bval[i]) / (bvl_b - bvl_a);\n }\n norm[i] = Math.pow(10.0, snr / 10.0);\n if (gfc.numlines_l[i] > 0) {\n gfc.rnumlines_l[i] = 1.0 / gfc.numlines_l[i];\n } else {\n gfc.rnumlines_l[i] = 0;\n }\n }\n gfc.s3_ll = init_s3_values(gfc.s3ind, gfc.npart_l, bval, bval_width,\n norm, useOldS3);\n\n /* compute long block specific values, ATH and MINVAL */\n var j = 0;\n for (i = 0; i < gfc.npart_l; i++) {\n var x;\n\n /* ATH */\n x = Float.MAX_VALUE;\n for (var k = 0; k < gfc.numlines_l[i]; k++, j++) {\n var freq = sfreq * j / (1000.0 * Encoder.BLKSIZE);\n var level;\n /*\n * ATH below 100 Hz constant, not further climbing\n */\n level = this.ATHformula(freq * 1000, gfp) - 20;\n // scale to FFT units; returned value is in dB\n level = Math.pow(10., 0.1 * level);\n // convert from dB . energy\n level *= gfc.numlines_l[i];\n if (x > level)\n x = level;\n }\n gfc.ATH.cb_l[i] = x;\n\n /*\n * MINVAL. For low freq, the strength of the masking is limited by\n * minval this is an ISO MPEG1 thing, dont know if it is really\n * needed\n */\n /*\n * FIXME: it does work to reduce low-freq problems in S53-Wind-Sax\n * and lead-voice samples, but introduces some 3 kbps bit bloat too.\n * TODO: Further refinement of the shape of this hack.\n */\n x = -20 + bval[i] * 20 / 10;\n if (x > 6) {\n x = 100;\n }\n if (x < -15) {\n x = -15;\n }\n x -= 8.;\n gfc.minval_l[i] = (Math.pow(10.0, x / 10.) * gfc.numlines_l[i]);\n }\n\n /************************************************************************\n * do the same things for short blocks\n ************************************************************************/\n gfc.npart_s = init_numline(gfc.numlines_s, gfc.bo_s, gfc.bm_s, bval,\n bval_width, gfc.mld_s, gfc.PSY.bo_s_weight, sfreq,\n Encoder.BLKSIZE_s, gfc.scalefac_band.s, Encoder.BLKSIZE_s\n / (2.0 * 192), Encoder.SBMAX_s);\n assert(gfc.npart_s < Encoder.CBANDS);\n\n /* SNR formula. short block is normalized by SNR. is it still right ? */\n j = 0;\n for (i = 0; i < gfc.npart_s; i++) {\n var x;\n var snr = snr_s_a;\n if (bval[i] >= bvl_a) {\n snr = snr_s_b * (bval[i] - bvl_a) / (bvl_b - bvl_a) + snr_s_a\n * (bvl_b - bval[i]) / (bvl_b - bvl_a);\n }\n norm[i] = Math.pow(10.0, snr / 10.0);\n\n /* ATH */\n x = Float.MAX_VALUE;\n for (var k = 0; k < gfc.numlines_s[i]; k++, j++) {\n var freq = sfreq * j / (1000.0 * Encoder.BLKSIZE_s);\n var level;\n /* freq = Min(.1,freq); */\n /*\n * ATH below 100 Hz constant, not\n * further climbing\n */\n level = this.ATHformula(freq * 1000, gfp) - 20;\n // scale to FFT units; returned value is in dB\n level = Math.pow(10., 0.1 * level);\n // convert from dB . energy\n level *= gfc.numlines_s[i];\n if (x > level)\n x = level;\n }\n gfc.ATH.cb_s[i] = x;\n\n /*\n * MINVAL. For low freq, the strength of the masking is limited by\n * minval this is an ISO MPEG1 thing, dont know if it is really\n * needed\n */\n x = (-7.0 + bval[i] * 7.0 / 12.0);\n if (bval[i] > 12) {\n x *= 1 + Math.log(1 + x) * 3.1;\n }\n if (bval[i] < 12) {\n x *= 1 + Math.log(1 - x) * 2.3;\n }\n if (x < -15) {\n x = -15;\n }\n x -= 8;\n gfc.minval_s[i] = Math.pow(10.0, x / 10)\n * gfc.numlines_s[i];\n }\n\n gfc.s3_ss = init_s3_values(gfc.s3ind_s, gfc.npart_s, bval, bval_width,\n norm, useOldS3);\n\n init_mask_add_max_values();\n fft.init_fft(gfc);\n\n /* setup temporal masking */\n gfc.decay = Math.exp(-1.0 * LOG10\n / (temporalmask_sustain_sec * sfreq / 192.0));\n\n {\n var msfix;\n msfix = NS_MSFIX;\n if ((gfp.exp_nspsytune & 2) != 0)\n msfix = 1.0;\n if (Math.abs(gfp.msfix) > 0.0)\n msfix = gfp.msfix;\n gfp.msfix = msfix;\n\n /*\n * spread only from npart_l bands. Normally, we use the spreading\n * function to convolve from npart_l down to npart_l bands\n */\n for (var b = 0; b < gfc.npart_l; b++)\n if (gfc.s3ind[b][1] > gfc.npart_l - 1)\n gfc.s3ind[b][1] = gfc.npart_l - 1;\n }\n\n /*\n * prepare for ATH auto adjustment: we want to decrease the ATH by 12 dB\n * per second\n */\n var frame_duration = (576. * gfc.mode_gr / sfreq);\n gfc.ATH.decay = Math.pow(10., -12. / 10. * frame_duration);\n gfc.ATH.adjust = 0.01;\n /* minimum, for leading low loudness */\n gfc.ATH.adjustLimit = 1.0;\n /* on lead, allow adjust up to maximum */\n\n assert(gfc.bo_l[Encoder.SBMAX_l - 1] <= gfc.npart_l);\n assert(gfc.bo_s[Encoder.SBMAX_s - 1] <= gfc.npart_s);\n\n if (gfp.ATHtype != -1) {\n /* compute equal loudness weights (eql_w) */\n var freq;\n var freq_inc = gfp.out_samplerate\n / (Encoder.BLKSIZE);\n var eql_balance = 0.0;\n freq = 0.0;\n for (i = 0; i < Encoder.BLKSIZE / 2; ++i) {\n /* convert ATH dB to relative power (not dB) */\n /* to determine eql_w */\n freq += freq_inc;\n gfc.ATH.eql_w[i] = 1. / Math.pow(10, this.ATHformula(freq, gfp) / 10);\n eql_balance += gfc.ATH.eql_w[i];\n }\n eql_balance = 1.0 / eql_balance;\n for (i = Encoder.BLKSIZE / 2; --i >= 0;) { /* scale weights */\n gfc.ATH.eql_w[i] *= eql_balance;\n }\n }\n {\n for (var b = j = 0; b < gfc.npart_s; ++b) {\n for (i = 0; i < gfc.numlines_s[b]; ++i) {\n ++j;\n }\n }\n assert(j == 129);\n for (var b = j = 0; b < gfc.npart_l; ++b) {\n for (i = 0; i < gfc.numlines_l[b]; ++i) {\n ++j;\n }\n }\n assert(j == 513);\n }\n j = 0;\n for (i = 0; i < gfc.npart_l; i++) {\n var freq = sfreq * (j + gfc.numlines_l[i] / 2) / (1.0 * Encoder.BLKSIZE);\n gfc.mld_cb_l[i] = stereo_demask(freq);\n j += gfc.numlines_l[i];\n }\n for (; i < Encoder.CBANDS; ++i) {\n gfc.mld_cb_l[i] = 1;\n }\n j = 0;\n for (i = 0; i < gfc.npart_s; i++) {\n var freq = sfreq * (j + gfc.numlines_s[i] / 2) / (1.0 * Encoder.BLKSIZE_s);\n gfc.mld_cb_s[i] = stereo_demask(freq);\n j += gfc.numlines_s[i];\n }\n for (; i < Encoder.CBANDS; ++i) {\n gfc.mld_cb_s[i] = 1;\n }\n return 0;\n }\n\n /**\n * Those ATH formulas are returning their minimum value for input = -1\n */\n function ATHformula_GB(f, value) {\n /**\n *
\n         *  from Painter & Spanias\n         *           modified by Gabriel Bouvigne to better fit the reality\n         *           ath =    3.640 * pow(f,-0.8)\n         *           - 6.800 * exp(-0.6*pow(f-3.4,2.0))\n         *           + 6.000 * exp(-0.15*pow(f-8.7,2.0))\n         *           + 0.6* 0.001 * pow(f,4.0);\n         *\n         *\n         *           In the past LAME was using the Painter &Spanias formula.\n         *           But we had some recurrent problems with HF content.\n         *           We measured real ATH values, and found the older formula\n         *           to be inaccurate in the higher part. So we made this new\n         *           formula and this solved most of HF problematic test cases.\n         *           The tradeoff is that in VBR mode it increases a lot the\n         *           bitrate.\n         * 
\n */\n\n /*\n * This curve can be adjusted according to the VBR scale: it adjusts\n * from something close to Painter & Spanias on V9 up to Bouvigne\'s\n * formula for V0. This way the VBR bitrate is more balanced according\n * to the -V value.\n */\n\n // the following Hack allows to ask for the lowest value\n if (f < -.3)\n f = 3410;\n\n // convert to khz\n f /= 1000;\n f = Math.max(0.1, f);\n var ath = 3.640 * Math.pow(f, -0.8) - 6.800\n * Math.exp(-0.6 * Math.pow(f - 3.4, 2.0)) + 6.000\n * Math.exp(-0.15 * Math.pow(f - 8.7, 2.0))\n + (0.6 + 0.04 * value) * 0.001 * Math.pow(f, 4.0);\n return ath;\n }\n\n this.ATHformula = function (f, gfp) {\n var ath;\n switch (gfp.ATHtype) {\n case 0:\n ath = ATHformula_GB(f, 9);\n break;\n case 1:\n // over sensitive, should probably be removed\n ath = ATHformula_GB(f, -1);\n break;\n case 2:\n ath = ATHformula_GB(f, 0);\n break;\n case 3:\n // modification of GB formula by Roel\n ath = ATHformula_GB(f, 1) + 6;\n break;\n case 4:\n ath = ATHformula_GB(f, gfp.ATHcurve);\n break;\n default:\n ath = ATHformula_GB(f, 0);\n break;\n }\n return ath;\n }\n\n}\n\nmodule.exports = PsyModel;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMmtucS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvUHN5TW9kZWwuanM/ZGE0OSJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogICAgICBwc3ltb2RlbC5jXG4gKlxuICogICAgICBDb3B5cmlnaHQgKGMpIDE5OTktMjAwMCBNYXJrIFRheWxvclxuICogICAgICBDb3B5cmlnaHQgKGMpIDIwMDEtMjAwMiBOYW9raSBTaGliYXRhXG4gKiAgICAgIENvcHlyaWdodCAoYykgMjAwMC0yMDAzIFRha2VoaXJvIFRvbWluYWdhXG4gKiAgICAgIENvcHlyaWdodCAoYykgMjAwMC0yMDA4IFJvYmVydCBIZWdlbWFublxuICogICAgICBDb3B5cmlnaHQgKGMpIDIwMDAtMjAwNSBHYWJyaWVsIEJvdXZpZ25lXG4gKiAgICAgIENvcHlyaWdodCAoYykgMjAwMC0yMDA1IEFsZXhhbmRlciBMZWlkaW5nZXJcbiAqXG4gKiBUaGlzIGxpYnJhcnkgaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yXG4gKiBtb2RpZnkgaXQgdW5kZXIgdGhlIHRlcm1zIG9mIHRoZSBHTlUgTGVzc2VyIEdlbmVyYWwgUHVibGljXG4gKiBMaWNlbnNlIGFzIHB1Ymxpc2hlZCBieSB0aGUgRnJlZSBTb2Z0d2FyZSBGb3VuZGF0aW9uOyBlaXRoZXJcbiAqIHZlcnNpb24gMiBvZiB0aGUgTGljZW5zZSwgb3IgKGF0IHlvdXIgb3B0aW9uKSBhbnkgbGF0ZXIgdmVyc2lvbi5cbiAqXG4gKiBUaGlzIGxpYnJhcnkgaXMgZGlzdHJpYnV0ZWQgaW4gdGhlIGhvcGUgdGhhdCBpdCB3aWxsIGJlIHVzZWZ1bCxcbiAqIGJ1dCBXSVRIT1VUIEFOWSBXQVJSQU5UWTsgd2l0aG91dCBldmVuIHRoZSBpbXBsaWVkIHdhcnJhbnR5IG9mXG4gKiBNRVJDSEFOVEFCSUxJVFkgb3IgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UuICBTZWUgdGhlIEdOVVxuICogTGlicmFyeSBHZW5lcmFsIFB1YmxpYyBMaWNlbnNlIGZvciBtb3JlIGRldGFpbHMuXG4gKlxuICogWW91IHNob3VsZCBoYXZlIHJlY2VpdmVkIGEgY29weSBvZiB0aGUgR05VIExlc3NlciBHZW5lcmFsIFB1YmxpY1xuICogTGljZW5zZSBhbG9uZyB3aXRoIHRoaXMgbGlicmFyeTsgaWYgbm90LCB3cml0ZSB0byB0aGVcbiAqIEZyZWUgU29mdHdhcmUgRm91bmRhdGlvbiwgSW5jLiwgNTkgVGVtcGxlIFBsYWNlIC0gU3VpdGUgMzMwLFxuICogQm9zdG9uLCBNQSAwMjExMS0xMzA3LCBVU0EuXG4gKi9cblxuLyogJElkOiBQc3lNb2RlbC5qYXZhLHYgMS4yNyAyMDExLzA1LzI0IDIwOjQ4OjA2IGtlbmNoaXMgRXhwICQgKi9cblxuXG4vKlxuIFBTWUNITyBBQ09VU1RJQ1NcblxuXG4gVGhpcyByb3V0aW5lIGNvbXB1dGVzIHRoZSBwc3ljaG8gYWNvdXN0aWNzLCBkZWxheWVkIGJ5IG9uZSBncmFudWxlLlxuXG4gSW5wdXQ6IGJ1ZmZlciBvZiBQQ00gZGF0YSAoMTAyNCBzYW1wbGVzKS5cblxuIFRoaXMgd2luZG93IHNob3VsZCBiZSBjZW50ZXJlZCBvdmVyIHRoZSA1NzYgc2FtcGxlIGdyYW51bGUgd2luZG93LlxuIFRoZSByb3V0aW5lIHdpbGwgY29tcHV0ZSB0aGUgcHN5Y2hvIGFjb3VzdGljcyBmb3JcbiB0aGlzIGdyYW51bGUsIGJ1dCByZXR1cm4gdGhlIHBzeWNobyBhY291c3RpY3MgY29tcHV0ZWRcbiBmb3IgdGhlICpwcmV2aW91cyogZ3JhbnVsZS4gIFRoaXMgaXMgYmVjYXVzZSB0aGUgYmxvY2tcbiB0eXBlIG9mIHRoZSBwcmV2aW91cyBncmFudWxlIGNhbiBvbmx5IGJlIGRldGVybWluZWRcbiBhZnRlciB3ZSBoYXZlIGNvbXB1dGVkIHRoZSBwc3ljaG8gYWNvdXN0aWNzIGZvciB0aGUgZm9sbG93aW5nXG4gZ3JhbnVsZS5cblxuIE91dHB1dDogIG1hc2tpbmdzIGFuZCBlbmVyZ2llcyBmb3IgZWFjaCBzY2FsZWZhY3RvciBiYW5kLlxuIGJsb2NrIHR5cGUsIFBFLCBhbmQgc29tZSBjb3JyZWxhdGlvbiBtZWFzdXJlcy5cbiBUaGUgUEUgaXMgdXNlZCBieSBDQlIgbW9kZXMgdG8gZGV0ZXJtaW5lIGlmIGV4dHJhIGJpdHNcbiBmcm9tIHRoZSBiaXQgcmVzZXJ2b2lyIHNob3VsZCBiZSB1c2VkLiAgVGhlIGNvcnJlbGF0aW9uXG4gbWVhc3VyZXMgYXJlIHVzZWQgdG8gZGV0ZXJtaW5lIG1pZC9zaWRlIG9yIHJlZ3VsYXIgc3RlcmVvLlxuICovXG4vKlxuIE5vdGF0aW9uOlxuXG4gYmFya3M6ICBhIG5vbi1saW5lYXIgZnJlcXVlbmN5IHNjYWxlLiAgTWFwcGluZyBmcm9tIGZyZXF1ZW5jeSB0b1xuIGJhcmtzIGlzIGdpdmVuIGJ5IGZyZXEyYmFyaygpXG5cbiBzY2FsZWZhY3RvciBiYW5kczogVGhlIHNwZWN0cnVtIChmcmVxdWVuY2llcykgYXJlIGJyb2tlbiBpbnRvXG4gU0JNQVggXCJzY2FsZWZhY3RvciBiYW5kc1wiLiAgVGhlcyBiYW5kc1xuIGFyZSBkZXRlcm1pbmVkIGJ5IHRoZSBNUEVHIElTTyBzcGVjLiAgSW5cbiB0aGUgbm9pc2Ugc2hhcGluZy9xdWFudGl6YXRpb24gY29kZSwgd2UgYWxsb2NhdGVcbiBiaXRzIGFtb25nIHRoZSBwYXJ0aXRpb24gYmFuZHMgdG8gYWNoaWV2ZSB0aGVcbiBiZXN0IHBvc3NpYmxlIHF1YWxpdHlcblxuIHBhcnRpdGlvbiBiYW5kczogICBUaGUgc3BlY3RydW0gaXMgYWxzbyBicm9rZW4gaW50byBhYm91dFxuIDY0IFwicGFydGl0aW9uIGJhbmRzXCIuICBFYWNoIHBhcnRpdGlvblxuIGJhbmQgaXMgYWJvdXQgLjM0IGJhcmtzIHdpZGUuICBUaGVyZSBhcmUgYWJvdXQgMi01XG4gcGFydGl0aW9uIGJhbmRzIGZvciBlYWNoIHNjYWxlZmFjdG9yIGJhbmQuXG5cbiBMQU1FIGNvbXB1dGVzIGFsbCBwc3ljaG8gYWNvdXN0aWMgaW5mb3JtYXRpb24gZm9yIGVhY2ggcGFydGl0aW9uXG4gYmFuZC4gIFRoZW4gYXQgdGhlIGVuZCBvZiB0aGUgY29tcHV0YXRpb25zLCB0aGlzIGluZm9ybWF0aW9uXG4gaXMgbWFwcGVkIHRvIHNjYWxlZmFjdG9yIGJhbmRzLiAgVGhlIGVuZXJneSBpbiBlYWNoIHNjYWxlZmFjdG9yXG4gYmFuZCBpcyB0YWtlbiBhcyB0aGUgc3VtIG9mIHRoZSBlbmVyZ3kgaW4gYWxsIHBhcnRpdGlvbiBiYW5kc1xuIHdoaWNoIG92ZXJsYXAgdGhlIHNjYWxlZmFjdG9yIGJhbmQuICBUaGUgbWFza2luZ3MgY2FuIGJlIGNvbXB1dGVkXG4gaW4gdGhlIHNhbWUgd2F5IChhbmQgdGh1cyByZXByZXNlbnQgdGhlIGF2ZXJhZ2UgbWFza2luZyBpbiB0aGF0IGJhbmQpXG4gb3IgYnkgdGFraW5nIHRoZSBtaW5tdW0gdmFsdWUgbXVsdGlwbGllZCBieSB0aGUgbnVtYmVyIG9mXG4gcGFydGl0aW9uIGJhbmRzIHVzZWQgKHdoaWNoIHJlcHJlc2VudHMgYSBtaW5pbXVtIG1hc2tpbmcgaW4gdGhhdCBiYW5kKS5cbiAqL1xuLypcbiBUaGUgZ2VuZXJhbCBvdXRsaW5lIGlzIGFzIGZvbGxvd3M6XG5cbiAxLiBjb21wdXRlIHRoZSBlbmVyZ3kgaW4gZWFjaCBwYXJ0aXRpb24gYmFuZFxuIDIuIGNvbXB1dGUgdGhlIHRvbmFsaXR5IGluIGVhY2ggcGFydGl0aW9uIGJhbmRcbiAzLiBjb21wdXRlIHRoZSBzdHJlbmd0aCBvZiBlYWNoIHBhcnRpb24gYmFuZCBcIm1hc2tlclwiXG4gNC4gY29tcHV0ZSB0aGUgbWFza2luZyAodmlhIHRoZSBzcHJlYWRpbmcgZnVuY3Rpb24gYXBwbGllZCB0byBlYWNoIG1hc2tlcilcbiA1LiBNb2RpZmljYXRpb25zIGZvciBtaWQvc2lkZSBtYXNraW5nLlxuXG4gRWFjaCBwYXJ0aXRpb24gYmFuZCBpcyBjb25zaWRpZXJlZCBhIFwibWFza2VyXCIuICBUaGUgc3RyZW5ndGhcbiBvZiB0aGUgaSd0aCBtYXNrZXIgaW4gYmFuZCBqIGlzIGdpdmVuIGJ5OlxuXG4gczMoYmFyayhpKS1iYXJrKGopKSpzdHJlbmd0aChpKVxuXG4gVGhlIHN0cmVuZ3RoIG9mIHRoZSBtYXNrZXIgaXMgYSBmdW5jdGlvbiBvZiB0aGUgZW5lcmd5IGFuZCB0b25hbGl0eS5cbiBUaGUgbW9yZSB0b25hbCwgdGhlIGxlc3MgbWFza2luZy4gIExBTUUgdXNlcyBhIHNpbXBsZSBsaW5lYXIgZm9ybXVsYVxuIChjb250cm9sbGVkIGJ5IE5NVCBhbmQgVE1OKSB3aGljaCBzYXlzIHRoZSBzdHJlbmd0aCBpcyBnaXZlbiBieSB0aGVcbiBlbmVyZ3kgZGl2aWRlZCBieSBhIGxpbmVhciBmdW5jdGlvbiBvZiB0aGUgdG9uYWxpdHkuXG4gKi9cbi8qXG4gczMoKSBpcyB0aGUgXCJzcHJlYWRpbmcgZnVuY3Rpb25cIi4gIEl0IGlzIGdpdmVuIGJ5IGEgZm9ybXVsYVxuIGRldGVybWluZWQgdmlhIGxpc3RlbmluZyB0ZXN0cy5cblxuIFRoZSB0b3RhbCBtYXNraW5nIGluIHRoZSBqJ3RoIHBhcnRpdGlvbiBiYW5kIGlzIHRoZSBzdW0gb3ZlclxuIGFsbCBtYXNraW5ncyBpLiAgSXQgaXMgdGh1cyBnaXZlbiBieSB0aGUgY29udm9sdXRpb24gb2ZcbiB0aGUgc3RyZW5ndGggd2l0aCBzMygpLCB0aGUgXCJzcHJlYWRpbmcgZnVuY3Rpb24uXCJcblxuIG1hc2tpbmcoaikgPSBzdW1fb3Zlcl9pICBzMyhpLWopKnN0cmVuZ3RoKGkpICA9IHMzIG8gc3RyZW5ndGhcblxuIHdoZXJlIFwib1wiID0gY29udm9sdXRpb24gb3BlcmF0b3IuICBzMyBpcyBnaXZlbiBieSBhIGZvcm11bGEgZGV0ZXJtaW5lZFxuIHZpYSBsaXN0ZW5pbmcgdGVzdHMuICBJdCBpcyBub3JtYWxpemVkIHNvIHRoYXQgczMgbyAxID0gMS5cblxuIE5vdGU6IGluc3RlYWQgb2YgYSBzaW1wbGUgY29udm9sdXRpb24sIExBTUUgYWxzbyBoYXMgdGhlXG4gb3B0aW9uIG9mIHVzaW5nIFwiYWRkaXRpdmUgbWFza2luZ1wiXG5cbiBUaGUgbW9zdCBjcml0aWNhbCBwYXJ0IGlzIHN0ZXAgMiwgY29tcHV0aW5nIHRoZSB0b25hbGl0eSBvZiBlYWNoXG4gcGFydGl0aW9uIGJhbmQuICBMQU1FIGhhcyB0d28gdG9uYWxpdHkgZXN0aW1hdG9ycy4gIFRoZSBmaXJzdFxuIGlzIGJhc2VkIG9uIHRoZSBJU08gc3BlYywgYW5kIG1lYXN1cmVzIGhvdyBwcmVkaWN0aWFibGUgdGhlXG4gc2lnbmFsIGlzIG92ZXIgdGltZS4gIFRoZSBtb3JlIHByZWRpY3RhYmxlLCB0aGUgbW9yZSB0b25hbC5cbiBUaGUgc2Vjb25kIG1lYXN1cmUgaXMgYmFzZWQgb24gbG9va2luZyBhdCB0aGUgc3BlY3RydW0gb2ZcbiBhIHNpbmdsZSBncmFudWxlLiAgVGhlIG1vcmUgcGVha3kgdGhlIHNwZWN0cnVtLCB0aGUgbW9yZVxuIHRvbmFsLiAgQnkgbW9zdCBpbmRpY2F0aW9ucywgdGhlIGxhdHRlciBhcHByb2FjaCBpcyBiZXR0ZXIuXG5cbiBGaW5hbGx5LCBpbiBzdGVwIDUsIHRoZSBtYXNraW5ncyBmb3IgdGhlIG1pZCBhbmQgc2lkZVxuIGNoYW5uZWwgYXJlIHBvc3NpYmx5IGluY3JlYXNlZC4gIFVuZGVyIGNlcnRhaW4gY2lyY3Vtc3RhbmNlcyxcbiBub2lzZSBpbiB0aGUgbWlkICYgc2lkZSBjaGFubmVscyBpcyBhc3N1bWVkIHRvIGFsc29cbiBiZSBtYXNrZWQgYnkgc3Ryb25nIG1hc2tlcnMgaW4gdGhlIEwgb3IgUiBjaGFubmVscy5cblxuXG4gT3RoZXIgZGF0YSBjb21wdXRlZCBieSB0aGUgcHN5LW1vZGVsOlxuXG4gbXNfcmF0aW8gICAgICAgIHNpZGUtY2hhbm5lbCAvIG1pZC1jaGFubmVsIG1hc2tpbmcgcmF0aW8gKGZvciBwcmV2aW91cyBncmFudWxlKVxuIG1zX3JhdGlvX25leHQgICBzaWRlLWNoYW5uZWwgLyBtaWQtY2hhbm5lbCBtYXNraW5nIHJhdGlvIGZvciB0aGlzIGdyYW51bGVcblxuIHBlcmNlcF9lbnRyb3B5WzJdICAgICBMIGFuZCBSIHZhbHVlcyAocHJldiBncmFudWxlKSBvZiBQRSAtIEEgbWVhc3VyZSBvZiBob3dcbiBtdWNoIHByZS1lY2hvIGlzIGluIHRoZSBwcmV2aW91cyBncmFudWxlXG4gcGVyY2VwX2VudHJvcHlfTVNbMl0gIG1pZCBhbmQgc2lkZSBjaGFubmVsIHZhbHVlcyAocHJldiBncmFudWxlKSBvZiBwZXJjZXBfZW50cm9weVxuIGVuZXJneVs0XSAgICAgICAgICAgICBMLFIsTSxTIGVuZXJneSBpbiBlYWNoIGNoYW5uZWwsIHByZXYgZ3JhbnVsZVxuIGJsb2NrdHlwZV9kWzJdICAgICAgICBibG9jayB0eXBlIHRvIHVzZSBmb3IgcHJldmlvdXMgZ3JhbnVsZVxuICovXG4vL3BhY2thZ2UgbXAzO1xuXG4vL2ltcG9ydCBqYXZhLnV0aWwuQXJyYXlzO1xudmFyIGNvbW1vbiA9IHJlcXVpcmUoJy4vY29tbW9uLmpzJyk7XG52YXIgU3lzdGVtID0gY29tbW9uLlN5c3RlbTtcbnZhciBWYnJNb2RlID0gY29tbW9uLlZick1vZGU7XG52YXIgRmxvYXQgPSBjb21tb24uRmxvYXQ7XG52YXIgU2hvcnRCbG9jayA9IGNvbW1vbi5TaG9ydEJsb2NrO1xudmFyIFV0aWwgPSBjb21tb24uVXRpbDtcbnZhciBBcnJheXMgPSBjb21tb24uQXJyYXlzO1xudmFyIG5ld19hcnJheV9uID0gY29tbW9uLm5ld19hcnJheV9uO1xudmFyIG5ld19ieXRlID0gY29tbW9uLm5ld19ieXRlO1xudmFyIG5ld19kb3VibGUgPSBjb21tb24ubmV3X2RvdWJsZTtcbnZhciBuZXdfZmxvYXQgPSBjb21tb24ubmV3X2Zsb2F0O1xudmFyIG5ld19mbG9hdF9uID0gY29tbW9uLm5ld19mbG9hdF9uO1xudmFyIG5ld19pbnQgPSBjb21tb24ubmV3X2ludDtcbnZhciBuZXdfaW50X24gPSBjb21tb24ubmV3X2ludF9uO1xudmFyIGFzc2VydCA9IGNvbW1vbi5hc3NlcnQ7XG5cbnZhciBGRlQgPSByZXF1aXJlKFwiLi9GRlQuanNcIik7XG52YXIgRW5jb2RlciA9IHJlcXVpcmUoXCIuL0VuY29kZXIuanNcIik7XG5cbmZ1bmN0aW9uIFBzeU1vZGVsKCkge1xuICAgIHZhciBNUEVHTW9kZSA9IHJlcXVpcmUoJy4vTVBFR01vZGUuanMnKVxuICAgIHZhciBmZnQgPSBuZXcgRkZUKCk7XG5cbiAgICB2YXIgTE9HMTAgPSAyLjMwMjU4NTA5Mjk5NDA0NTY4NDAyO1xuXG4gICAgdmFyIHJwZWxldiA9IDI7XG4gICAgdmFyIHJwZWxldjIgPSAxNjtcbiAgICB2YXIgcnBlbGV2X3MgPSAyO1xuICAgIHZhciBycGVsZXYyX3MgPSAxNjtcblxuICAgIC8qIHNpemUgb2YgZWFjaCBwYXJ0aXRpb24gYmFuZCwgaW4gYmFya3M6ICovXG4gICAgdmFyIERFTEJBUksgPSAuMzQ7XG5cbiAgICAvKiB0dW5lZCBmb3Igb3V0cHV0IGxldmVsIChzZW5zaXRpdmUgdG8gZW5lcmd5IHNjYWxlKSAqL1xuICAgIHZhciBWT19TQ0FMRSA9ICgxLiAvICgxNDc1MiAqIDE0NzUyKSAvIChFbmNvZGVyLkJMS1NJWkUgLyAyKSk7XG5cbiAgICB2YXIgdGVtcG9yYWxtYXNrX3N1c3RhaW5fc2VjID0gMC4wMTtcblxuICAgIHZhciBOU19QUkVFQ0hPX0FUVDAgPSAwLjg7XG4gICAgdmFyIE5TX1BSRUVDSE9fQVRUMSA9IDAuNjtcbiAgICB2YXIgTlNfUFJFRUNIT19BVFQyID0gMC4zO1xuXG4gICAgdmFyIE5TX01TRklYID0gMy41O1xuXG4gICAgdmFyIE5TQVRUQUNLVEhSRSA9IDQuNDtcbiAgICB2YXIgTlNBVFRBQ0tUSFJFX1MgPSAyNTtcblxuICAgIHZhciBOU0ZJUkxFTiA9IDIxO1xuXG4gICAgLyogc2l6ZSBvZiBlYWNoIHBhcnRpdGlvbiBiYW5kLCBpbiBiYXJrczogKi9cbiAgICB2YXIgTE5fVE9fTE9HMTAgPSAwLjIzMDI1ODUwOTM7XG5cbiAgICBmdW5jdGlvbiBOT05fTElORUFSX1NDQUxFX0VORVJHWSh4KSB7XG4gICAgICAgIHJldHVybiB4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIDxQUkU+XG4gICAgICogICAgICAgTDNwc3ljaG9fYW5hbC4gIENvbXB1dGUgcHN5Y2hvIGFjb3VzdGljcy5cbiAgICAgKlxuICAgICAqICAgICAgIERhdGEgcmV0dXJuZWQgdG8gdGhlIGNhbGxpbmcgcHJvZ3JhbSBtdXN0IGJlIGRlbGF5ZWQgYnkgb25lXG4gICAgICogICAgICAgZ3JhbnVsZS5cbiAgICAgKlxuICAgICAqICAgICAgIFRoaXMgaXMgZG9uZSBpbiB0d28gcGxhY2VzLlxuICAgICAqICAgICAgIElmIHdlIGRvIG5vdCBuZWVkIHRvIGtub3cgdGhlIGJsb2NrdHlwZSwgdGhlIGNvcHlpbmdcbiAgICAgKiAgICAgICBjYW4gYmUgZG9uZSBoZXJlIGF0IHRoZSB0b3Agb2YgdGhlIHByb2dyYW06IHdlIGNvcHkgdGhlIGRhdGEgZm9yXG4gICAgICogICAgICAgdGhlIGxhc3QgZ3JhbnVsZSAoY29tcHV0ZWQgZHVyaW5nIHRoZSBsYXN0IGNhbGwpIGJlZm9yZSBpdCBpc1xuICAgICAqICAgICAgIG92ZXJ3cml0dGVuIHdpdGggdGhlIG5ldyBkYXRhLiAgSXQgbG9va3MgbGlrZSB0aGlzOlxuICAgICAqXG4gICAgICogICAgICAgMC4gc3RhdGljIHBzeW1vZGVsX2RhdGFcbiAgICAgKiAgICAgICAxLiBjYWxsaW5nX3Byb2dyYW1fZGF0YSA9IHBzeW1vZGVsX2RhdGFcbiAgICAgKiAgICAgICAyLiBjb21wdXRlIHBzeW1vZGVsX2RhdGFcbiAgICAgKlxuICAgICAqICAgICAgIEZvciBkYXRhIHdoaWNoIG5lZWRzIHRvIGtub3cgdGhlIGJsb2NrdHlwZSwgdGhlIGNvcHlpbmcgbXVzdCBiZVxuICAgICAqICAgICAgIGRvbmUgYXQgdGhlIGVuZCBvZiB0aGlzIGxvb3AsIGFuZCB0aGUgb2xkIHZhbHVlcyBtdXN0IGJlIHNhdmVkOlxuICAgICAqXG4gICAgICogICAgICAgMC4gc3RhdGljIHBzeW1vZGVsX2RhdGFfb2xkXG4gICAgICogICAgICAgMS4gY29tcHV0ZSBwc3ltb2RlbF9kYXRhXG4gICAgICogICAgICAgMi4gY29tcHV0ZSBwb3NzaWJsZSBibG9jayB0eXBlIG9mIHRoaXMgZ3JhbnVsZVxuICAgICAqICAgICAgIDMuIGNvbXB1dGUgZmluYWwgYmxvY2sgdHlwZSBvZiBwcmV2aW91cyBncmFudWxlIGJhc2VkIG9uICMyLlxuICAgICAqICAgICAgIDQuIGNhbGxpbmdfcHJvZ3JhbV9kYXRhID0gcHN5bW9kZWxfZGF0YV9vbGRcbiAgICAgKiAgICAgICA1LiBwc3ltb2RlbF9kYXRhX29sZCA9IHBzeW1vZGVsX2RhdGFcbiAgICAgKiAgICAgcHN5Y2hvX2xvdWRuZXNzX2FwcHJveFxuICAgICAqICAgICAgIGpkIC0gMjAwMSBtYXIgMTJcbiAgICAgKiAgICBpbjogIGVuZXJneSAgIC0gQkxLU0laRS8yIGVsZW1lbnRzIG9mIGZyZXF1ZW5jeSBtYWduaXR1ZGVzIF4gMlxuICAgICAqICAgICAgICAgZ2ZwICAgICAgLSB1c2VzIG91dF9zYW1wbGVyYXRlLCBBVEh0eXBlIChhbHNvIG5lZWRlZCBmb3IgQVRIZm9ybXVsYSlcbiAgICAgKiAgICByZXR1cm5zOiBsb3VkbmVzc14yIGFwcHJveGltYXRpb24sIGEgcG9zaXRpdmUgdmFsdWUgcm91Z2hseSB0dW5lZCBmb3IgYSB2YWx1ZVxuICAgICAqICAgICAgICAgICAgIG9mIDEuMCBmb3Igc2lnbmFscyBuZWFyIGNsaXBwaW5nLlxuICAgICAqICAgIG5vdGVzOiAgIFdoZW4gY2FsaWJyYXRlZCwgZmVlZGluZyB0aGlzIGZ1bmN0aW9uIGJpbmFyeSB3aGl0ZSBub2lzZSBhdCBzYW1wbGVcbiAgICAgKiAgICAgICAgICAgICB2YWx1ZXMgKzMyNzY3IG9yIC0zMjc2OCBzaG91bGQgcmV0dXJuIHZhbHVlcyB0aGF0IGFwcHJvYWNoIDMuXG4gICAgICogICAgICAgICAgICAgQVRIZm9ybXVsYSBpcyB1c2VkIHRvIGFwcHJveGltYXRlIGFuIGVxdWFsIGxvdWRuZXNzIGN1cnZlLlxuICAgICAqICAgIGZ1dHVyZTogIERhdGEgaW5kaWNhdGVzIHRoYXQgdGhlIHNoYXBlIG9mIHRoZSBlcXVhbCBsb3VkbmVzcyBjdXJ2ZSB2YXJpZXNcbiAgICAgKiAgICAgICAgICAgICB3aXRoIGludGVuc2l0eS4gIFRoaXMgZnVuY3Rpb24gbWlnaHQgYmUgaW1wcm92ZWQgYnkgdXNpbmcgYW4gZXF1YWxcbiAgICAgKiAgICAgICAgICAgICBsb3VkbmVzcyBjdXJ2ZSBzaGFwZWQgZm9yIHR5cGljYWwgcGxheWJhY2sgbGV2ZWxzIChpbnN0ZWFkIG9mIHRoZVxuICAgICAqICAgICAgICAgICAgIEFUSCwgdGhhdCBpcyBzaGFwZWQgZm9yIHRoZSB0aHJlc2hvbGQpLiAgQSBmbGV4aWJsZSByZWFsaXphdGlvbiBtaWdodFxuICAgICAqICAgICAgICAgICAgIHNpbXBseSBiZW5kIHRoZSBleGlzdGluZyBBVEggY3VydmUgdG8gYWNoaWV2ZSB0aGUgZGVzaXJlZCBzaGFwZS5cbiAgICAgKiAgICAgICAgICAgICBIb3dldmVyLCB0aGUgcG90ZW50aWFsIGdhaW4gbWF5IG5vdCBiZSBlbm91Z2ggdG8ganVzdGlmeSBhbiBlZmZvcnQuXG4gICAgICogPC9QUkU+XG4gICAgICovXG4gICAgZnVuY3Rpb24gcHN5Y2hvX2xvdWRuZXNzX2FwcHJveChlbmVyZ3ksIGdmYykge1xuICAgICAgICB2YXIgbG91ZG5lc3NfcG93ZXIgPSAwLjA7XG4gICAgICAgIC8qIGFwcGx5IHdlaWdodHMgdG8gcG93ZXIgaW4gZnJlcS4gYmFuZHMgKi9cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBFbmNvZGVyLkJMS1NJWkUgLyAyOyArK2kpXG4gICAgICAgICAgICBsb3VkbmVzc19wb3dlciArPSBlbmVyZ3lbaV0gKiBnZmMuQVRILmVxbF93W2ldO1xuICAgICAgICBsb3VkbmVzc19wb3dlciAqPSBWT19TQ0FMRTtcblxuICAgICAgICByZXR1cm4gbG91ZG5lc3NfcG93ZXI7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY29tcHV0ZV9mZnRzKGdmcCwgZmZ0ZW5lcmd5LCBmZnRlbmVyZ3lfcywgd3NhbXBfbCwgd3NhbXBfbFBvcywgd3NhbXBfcywgd3NhbXBfc1BvcywgZ3Jfb3V0LCBjaG4sIGJ1ZmZlciwgYnVmUG9zKSB7XG4gICAgICAgIHZhciBnZmMgPSBnZnAuaW50ZXJuYWxfZmxhZ3M7XG4gICAgICAgIGlmIChjaG4gPCAyKSB7XG4gICAgICAgICAgICBmZnQuZmZ0X2xvbmcoZ2ZjLCB3c2FtcF9sW3dzYW1wX2xQb3NdLCBjaG4sIGJ1ZmZlciwgYnVmUG9zKTtcbiAgICAgICAgICAgIGZmdC5mZnRfc2hvcnQoZ2ZjLCB3c2FtcF9zW3dzYW1wX3NQb3NdLCBjaG4sIGJ1ZmZlciwgYnVmUG9zKTtcbiAgICAgICAgfVxuICAgICAgICAvKiBGRlQgZGF0YSBmb3IgbWlkIGFuZCBzaWRlIGNoYW5uZWwgaXMgZGVyaXZlZCBmcm9tIEwgJiBSICovXG4gICAgICAgIGVsc2UgaWYgKGNobiA9PSAyKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gRW5jb2Rlci5CTEtTSVpFIC0gMTsgaiA+PSAwOyAtLWopIHtcbiAgICAgICAgICAgICAgICB2YXIgbCA9IHdzYW1wX2xbd3NhbXBfbFBvcyArIDBdW2pdO1xuICAgICAgICAgICAgICAgIHZhciByID0gd3NhbXBfbFt3c2FtcF9sUG9zICsgMV1bal07XG4gICAgICAgICAgICAgICAgd3NhbXBfbFt3c2FtcF9sUG9zICsgMF1bal0gPSAobCArIHIpICogVXRpbC5TUVJUMiAqIDAuNTtcbiAgICAgICAgICAgICAgICB3c2FtcF9sW3dzYW1wX2xQb3MgKyAxXVtqXSA9IChsIC0gcikgKiBVdGlsLlNRUlQyICogMC41O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgYiA9IDI7IGIgPj0gMDsgLS1iKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IEVuY29kZXIuQkxLU0laRV9zIC0gMTsgaiA+PSAwOyAtLWopIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGwgPSB3c2FtcF9zW3dzYW1wX3NQb3MgKyAwXVtiXVtqXTtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHIgPSB3c2FtcF9zW3dzYW1wX3NQb3MgKyAxXVtiXVtqXTtcbiAgICAgICAgICAgICAgICAgICAgd3NhbXBfc1t3c2FtcF9zUG9zICsgMF1bYl1bal0gPSAobCArIHIpICogVXRpbC5TUVJUMiAqIDAuNTtcbiAgICAgICAgICAgICAgICAgICAgd3NhbXBfc1t3c2FtcF9zUG9zICsgMV1bYl1bal0gPSAobCAtIHIpICogVXRpbC5TUVJUMiAqIDAuNTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgICAqIGNvbXB1dGUgZW5lcmdpZXNcbiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbiAgICAgICAgZmZ0ZW5lcmd5WzBdID0gTk9OX0xJTkVBUl9TQ0FMRV9FTkVSR1kod3NhbXBfbFt3c2FtcF9sUG9zICsgMF1bMF0pO1xuICAgICAgICBmZnRlbmVyZ3lbMF0gKj0gZmZ0ZW5lcmd5WzBdO1xuXG4gICAgICAgIGZvciAodmFyIGogPSBFbmNvZGVyLkJMS1NJWkUgLyAyIC0gMTsgaiA+PSAwOyAtLWopIHtcbiAgICAgICAgICAgIHZhciByZSA9ICh3c2FtcF9sW3dzYW1wX2xQb3MgKyAwXSlbRW5jb2Rlci5CTEtTSVpFIC8gMiAtIGpdO1xuICAgICAgICAgICAgdmFyIGltID0gKHdzYW1wX2xbd3NhbXBfbFBvcyArIDBdKVtFbmNvZGVyLkJMS1NJWkUgLyAyICsgal07XG4gICAgICAgICAgICBmZnRlbmVyZ3lbRW5jb2Rlci5CTEtTSVpFIC8gMiAtIGpdID0gTk9OX0xJTkVBUl9TQ0FMRV9FTkVSR1koKHJlXG4gICAgICAgICAgICAgICAgKiByZSArIGltICogaW0pICogMC41KTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKHZhciBiID0gMjsgYiA+PSAwOyAtLWIpIHtcbiAgICAgICAgICAgIGZmdGVuZXJneV9zW2JdWzBdID0gKHdzYW1wX3Nbd3NhbXBfc1BvcyArIDBdKVtiXVswXTtcbiAgICAgICAgICAgIGZmdGVuZXJneV9zW2JdWzBdICo9IGZmdGVuZXJneV9zW2JdWzBdO1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IEVuY29kZXIuQkxLU0laRV9zIC8gMiAtIDE7IGogPj0gMDsgLS1qKSB7XG4gICAgICAgICAgICAgICAgdmFyIHJlID0gKHdzYW1wX3Nbd3NhbXBfc1BvcyArIDBdKVtiXVtFbmNvZGVyLkJMS1NJWkVfc1xuICAgICAgICAgICAgICAgIC8gMiAtIGpdO1xuICAgICAgICAgICAgICAgIHZhciBpbSA9ICh3c2FtcF9zW3dzYW1wX3NQb3MgKyAwXSlbYl1bRW5jb2Rlci5CTEtTSVpFX3NcbiAgICAgICAgICAgICAgICAvIDIgKyBqXTtcbiAgICAgICAgICAgICAgICBmZnRlbmVyZ3lfc1tiXVtFbmNvZGVyLkJMS1NJWkVfcyAvIDIgLSBqXSA9IE5PTl9MSU5FQVJfU0NBTEVfRU5FUkdZKChyZVxuICAgICAgICAgICAgICAgICAgICAqIHJlICsgaW0gKiBpbSkgKiAwLjUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIC8qIHRvdGFsIGVuZXJneSAqL1xuICAgICAgICB7XG4gICAgICAgICAgICB2YXIgdG90YWxlbmVyZ3kgPSAwLjA7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMTE7IGogPCBFbmNvZGVyLkhCTEtTSVpFOyBqKyspXG4gICAgICAgICAgICAgICAgdG90YWxlbmVyZ3kgKz0gZmZ0ZW5lcmd5W2pdO1xuXG4gICAgICAgICAgICBnZmMudG90X2VuZXJbY2huXSA9IHRvdGFsZW5lcmd5O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdmcC5hbmFseXNpcykge1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCBFbmNvZGVyLkhCTEtTSVpFOyBqKyspIHtcbiAgICAgICAgICAgICAgICBnZmMucGluZm8uZW5lcmd5W2dyX291dF1bY2huXVtqXSA9IGdmYy5waW5mby5lbmVyZ3lfc2F2ZVtjaG5dW2pdO1xuICAgICAgICAgICAgICAgIGdmYy5waW5mby5lbmVyZ3lfc2F2ZVtjaG5dW2pdID0gZmZ0ZW5lcmd5W2pdO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ2ZjLnBpbmZvLnBlW2dyX291dF1bY2huXSA9IGdmYy5wZVtjaG5dO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICAgKiBjb21wdXRlIGxvdWRuZXNzIGFwcHJveGltYXRpb24gKHVzZWQgZm9yIEFUSCBhdXRvLWxldmVsIGFkanVzdG1lbnQpXG4gICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgIGlmIChnZnAuYXRoYWFfbG91ZGFwcHJveCA9PSAyICYmIGNobiA8IDIpIHtcbiAgICAgICAgICAgIC8vIG5vIGxvdWRuZXNzIGZvciBtaWQvc2lkZSBjaFxuICAgICAgICAgICAgZ2ZjLmxvdWRuZXNzX3NxW2dyX291dF1bY2huXSA9IGdmYy5sb3VkbmVzc19zcV9zYXZlW2Nobl07XG4gICAgICAgICAgICBnZmMubG91ZG5lc3Nfc3Ffc2F2ZVtjaG5dID0gcHN5Y2hvX2xvdWRuZXNzX2FwcHJveChmZnRlbmVyZ3ksIGdmYyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKiBtYXNrX2FkZCBvcHRpbWl6YXRpb24gKi9cbiAgICAvKiBpbml0IHRoZSBsaW1pdCB2YWx1ZXMgdXNlZCB0byBhdm9pZCBjb21wdXRpbmcgbG9nIGluIG1hc2tfYWRkIHdoZW4gaXQgaXMgbm90IG5lY2Vzc2FyeSAqL1xuXG4gICAgLyoqXG4gICAgICogPFBSRT5cbiAgICAgKiAgRm9yIGV4YW1wbGUsIHdpdGggaSA9IDEwKmxvZzEwKG0yL20xKS8xMCoxNiAgICAgICAgICg9IGxvZzEwKG0yL20xKSoxNilcbiAgICAgKlxuICAgICAqIGFicyhpKT44IGlzIGVxdWl2YWxlbnQgKGFzIGkgaXMgYW4gaW50ZWdlcikgdG9cbiAgICAgKiBhYnMoaSk+PTlcbiAgICAgKiBpPj05IHx8IGk8PS05XG4gICAgICogZXF1aXZhbGVudCB0byAoYXMgaSBpcyB0aGUgYmlnZ2VzdCBpbnRlZ2VyIHNtYWxsZXIgdGhhbiBsb2cxMChtMi9tMSkqMTZcbiAgICAgKiBvciB0aGUgc21hbGxlc3QgaW50ZWdlciBiaWdnZXIgdGhhbiBsb2cxMChtMi9tMSkqMTYgZGVwZW5kaW5nIG9uIHRoZSBzaWduIG9mIGxvZzEwKG0yL20xKSoxNilcbiAgICAgKiBsb2cxMChtMi9tMSk+PTkvMTYgfHwgbG9nMTAobTIvbTEpPD0tOS8xNlxuICAgICAqIGV4cDEwIGlzIHN0cmljdGx5IGluY3JlYXNpbmcgdGh1cyB0aGlzIGlzIGVxdWl2YWxlbnQgdG9cbiAgICAgKiBtMi9tMSA+PSAxMF4oOS8xNikgfHwgbTIvbTE8PTEwXigtOS8xNikgd2hpY2ggYXJlIGNvbXBhcmlzb25zIHRvIGNvbnN0YW50c1xuICAgICAqIDwvUFJFPlxuICAgICAqL1xuXG4gICAgLyoqXG4gICAgICogYXMgaW4gaWYoaT44KVxuICAgICAqL1xuICAgIHZhciBJMUxJTUlUID0gODtcbiAgICAvKipcbiAgICAgKiBhcyBpbiBpZihpPjI0KSAuIGNoYW5nZWQgMjNcbiAgICAgKi9cbiAgICB2YXIgSTJMSU1JVCA9IDIzO1xuICAgIC8qKlxuICAgICAqIGFzIGluIGlmKG08MTUpXG4gICAgICovXG4gICAgdmFyIE1MSU1JVCA9IDE1O1xuXG4gICAgdmFyIG1hX21heF9pMTtcbiAgICB2YXIgbWFfbWF4X2kyO1xuICAgIHZhciBtYV9tYXhfbTtcblxuICAgIC8qKlxuICAgICAqIFRoaXMgaXMgdGhlIG1hc2tpbmcgdGFibGU6PEJSPlxuICAgICAqIEFjY29yZGluZyB0byB0b25hbGl0eSwgdmFsdWVzIGFyZSBnb2luZyBmcm9tIDBkQiAoVE1OKSB0byA5LjNkQiAoTk1UKS48QlI+XG4gICAgICogQWZ0ZXIgYWRkaXRpdmUgbWFza2luZyBjb21wdXRhdGlvbiwgOGRCIGFyZSBhZGRlZCwgc28gZmluYWwgdmFsdWVzIGFyZVxuICAgICAqIGdvaW5nIGZyb20gOGRCIHRvIDE3LjNkQlxuICAgICAqXG4gICAgICogcG93KDEwLCAtMC4wLi4tMC42KVxuICAgICAqL1xuICAgIHZhciB0YWIgPSBbMS4wLCAwLjc5NDMzLCAwLjYzMDk2LCAwLjYzMDk2LFxuICAgICAgICAwLjYzMDk2LCAwLjYzMDk2LCAwLjYzMDk2LCAwLjI1MTE5LCAwLjExNzQ5XTtcblxuICAgIGZ1bmN0aW9uIGluaXRfbWFza19hZGRfbWF4X3ZhbHVlcygpIHtcbiAgICAgICAgbWFfbWF4X2kxID0gTWF0aC5wb3coMTAsIChJMUxJTUlUICsgMSkgLyAxNi4wKTtcbiAgICAgICAgbWFfbWF4X2kyID0gTWF0aC5wb3coMTAsIChJMkxJTUlUICsgMSkgLyAxNi4wKTtcbiAgICAgICAgbWFfbWF4X20gPSBNYXRoLnBvdygxMCwgKE1MSU1JVCkgLyAxMC4wKTtcbiAgICB9XG5cbiAgICB2YXIgdGFibGUxID0gWzMuMzI0NiAqIDMuMzI0NixcbiAgICAgICAgMy4yMzgzNyAqIDMuMjM4MzcsIDMuMTU0MzcgKiAzLjE1NDM3LCAzLjAwNDEyICogMy4wMDQxMixcbiAgICAgICAgMi44NjEwMyAqIDIuODYxMDMsIDIuNjU0MDcgKiAyLjY1NDA3LCAyLjQ2MjA5ICogMi40NjIwOSxcbiAgICAgICAgMi4yODQgKiAyLjI4NCwgMi4xMTg3OSAqIDIuMTE4NzksIDEuOTY1NTIgKiAxLjk2NTUyLFxuICAgICAgICAxLjgyMzM1ICogMS44MjMzNSwgMS42OTE0NiAqIDEuNjkxNDYsIDEuNTY5MTEgKiAxLjU2OTExLFxuICAgICAgICAxLjQ2NjU4ICogMS40NjY1OCwgMS4zNzA3NCAqIDEuMzcwNzQsIDEuMzEwMzYgKiAxLjMxMDM2LFxuICAgICAgICAxLjI1MjY0ICogMS4yNTI2NCwgMS4yMDY0OCAqIDEuMjA2NDgsIDEuMTYyMDMgKiAxLjE2MjAzLFxuICAgICAgICAxLjEyNzY1ICogMS4xMjc2NSwgMS4wOTQyOCAqIDEuMDk0MjgsIDEuMDY1OSAqIDEuMDY1OSxcbiAgICAgICAgMS4wMzgyNiAqIDEuMDM4MjYsIDEuMDE4OTUgKiAxLjAxODk1LCAxXTtcblxuICAgIHZhciB0YWJsZTIgPSBbMS4zMzM1MiAqIDEuMzMzNTIsXG4gICAgICAgIDEuMzU4NzkgKiAxLjM1ODc5LCAxLjM4NDU0ICogMS4zODQ1NCwgMS4zOTQ5NyAqIDEuMzk0OTcsXG4gICAgICAgIDEuNDA1NDggKiAxLjQwNTQ4LCAxLjM1MzcgKiAxLjM1MzcsIDEuMzAzODIgKiAxLjMwMzgyLFxuICAgICAgICAxLjIyMzIxICogMS4yMjMyMSwgMS4xNDc1OCAqIDEuMTQ3NTgsIDFdO1xuXG4gICAgdmFyIHRhYmxlMyA9IFsyLjM1MzY0ICogMi4zNTM2NCxcbiAgICAgICAgMi4yOTI1OSAqIDIuMjkyNTksIDIuMjMzMTMgKiAyLjIzMzEzLCAyLjEyNjc1ICogMi4xMjY3NSxcbiAgICAgICAgMi4wMjU0NSAqIDIuMDI1NDUsIDEuODc4OTQgKiAxLjg3ODk0LCAxLjc0MzAzICogMS43NDMwMyxcbiAgICAgICAgMS42MTY5NSAqIDEuNjE2OTUsIDEuNDk5OTkgKiAxLjQ5OTk5LCAxLjM5MTQ4ICogMS4zOTE0OCxcbiAgICAgICAgMS4yOTA4MyAqIDEuMjkwODMsIDEuMTk3NDYgKiAxLjE5NzQ2LCAxLjExMDg0ICogMS4xMTA4NCxcbiAgICAgICAgMS4wMzgyNiAqIDEuMDM4MjZdO1xuXG4gICAgLyoqXG4gICAgICogYWRkaXRpb24gb2Ygc2ltdWx0YW5lb3VzIG1hc2tpbmcgTmFva2kgU2hpYmF0YSAyMDAwLzdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBtYXNrX2FkZChtMSwgbTIsIGtrLCBiLCBnZmMsIHNob3J0YmxvY2spIHtcbiAgICAgICAgdmFyIHJhdGlvO1xuXG4gICAgICAgIGlmIChtMiA+IG0xKSB7XG4gICAgICAgICAgICBpZiAobTIgPCAobTEgKiBtYV9tYXhfaTIpKVxuICAgICAgICAgICAgICAgIHJhdGlvID0gbTIgLyBtMTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICByZXR1cm4gKG0xICsgbTIpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKG0xID49IChtMiAqIG1hX21heF9pMikpXG4gICAgICAgICAgICAgICAgcmV0dXJuIChtMSArIG0yKTtcbiAgICAgICAgICAgIHJhdGlvID0gbTEgLyBtMjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qIFNob3VsZCBhbHdheXMgYmUgdHJ1ZSwganVzdCBjaGVja2luZyAqL1xuICAgICAgICBhc3NlcnQobTEgPj0gMCk7XG4gICAgICAgIGFzc2VydChtMiA+PSAwKTtcblxuICAgICAgICBtMSArPSBtMjtcbiAgICAgICAgLy9pZiAoKChsb25nKShiICsgMykgJiAweGZmZmZmZmZmKSA8PSAzICsgMykge1xuICAgICAgICBpZiAoKGIgKyAzKSA8PSAzICsgMykge1xuICAgICAgICAgICAgLyogYXBwcm94aW1hdGVseSwgMSBiYXJrID0gMyBwYXJ0aXRpb25zICovXG4gICAgICAgICAgICAvKiA2NSUgb2YgdGhlIGNhc2VzICovXG4gICAgICAgICAgICAvKiBvcmlnaW5hbGx5ICdpZihpID4gOCknICovXG4gICAgICAgICAgICBpZiAocmF0aW8gPj0gbWFfbWF4X2kxKSB7XG4gICAgICAgICAgICAgICAgLyogNDMlIG9mIHRoZSB0b3RhbCAqL1xuICAgICAgICAgICAgICAgIHJldHVybiBtMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyogMjIlIG9mIHRoZSB0b3RhbCAqL1xuICAgICAgICAgICAgdmFyIGkgPSAwIHwgKFV0aWwuRkFTVF9MT0cxMF9YKHJhdGlvLCAxNi4wKSk7XG4gICAgICAgICAgICByZXR1cm4gbTEgKiB0YWJsZTJbaV07XG4gICAgICAgIH1cblxuICAgICAgICAvKipcbiAgICAgICAgICogPFBSRT5cbiAgICAgICAgICogbTwxNSBlcXUgbG9nMTAoKG0xK20yKS9nZmMuQVRILmNiW2tdKTwxLjVcbiAgICAgICAgICogZXF1IChtMSttMikvZ2ZjLkFUSC5jYltrXTwxMF4xLjVcbiAgICAgICAgICogZXF1IChtMSttMik8MTBeMS41ICogZ2ZjLkFUSC5jYltrXVxuICAgICAgICAgKiA8L1BSRT5cbiAgICAgICAgICovXG4gICAgICAgIHZhciBpID0gMCB8IFV0aWwuRkFTVF9MT0cxMF9YKHJhdGlvLCAxNi4wKTtcbiAgICAgICAgaWYgKHNob3J0YmxvY2sgIT0gMCkge1xuICAgICAgICAgICAgbTIgPSBnZmMuQVRILmNiX3Nba2tdICogZ2ZjLkFUSC5hZGp1c3Q7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBtMiA9IGdmYy5BVEguY2JfbFtra10gKiBnZmMuQVRILmFkanVzdDtcbiAgICAgICAgfVxuICAgICAgICBhc3NlcnQobTIgPj0gMCk7XG4gICAgICAgIGlmIChtMSA8IG1hX21heF9tICogbTIpIHtcbiAgICAgICAgICAgIC8qIDMlIG9mIHRoZSB0b3RhbCAqL1xuICAgICAgICAgICAgLyogT3JpZ2luYWxseSBpZiAobSA+IDApIHsgKi9cbiAgICAgICAgICAgIGlmIChtMSA+IG0yKSB7XG4gICAgICAgICAgICAgICAgdmFyIGYsIHI7XG5cbiAgICAgICAgICAgICAgICBmID0gMS4wO1xuICAgICAgICAgICAgICAgIGlmIChpIDw9IDEzKVxuICAgICAgICAgICAgICAgICAgICBmID0gdGFibGUzW2ldO1xuXG4gICAgICAgICAgICAgICAgciA9IFV0aWwuRkFTVF9MT0cxMF9YKG0xIC8gbTIsIDEwLjAgLyAxNS4wKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gbTEgKiAoKHRhYmxlMVtpXSAtIGYpICogciArIGYpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoaSA+IDEzKVxuICAgICAgICAgICAgICAgIHJldHVybiBtMTtcblxuICAgICAgICAgICAgcmV0dXJuIG0xICogdGFibGUzW2ldO1xuICAgICAgICB9XG5cbiAgICAgICAgLyogMTAlIG9mIHRvdGFsICovXG4gICAgICAgIHJldHVybiBtMSAqIHRhYmxlMVtpXTtcbiAgICB9XG5cbiAgICB2YXIgdGFibGUyXyA9IFsxLjMzMzUyICogMS4zMzM1MixcbiAgICAgICAgMS4zNTg3OSAqIDEuMzU4NzksIDEuMzg0NTQgKiAxLjM4NDU0LCAxLjM5NDk3ICogMS4zOTQ5NyxcbiAgICAgICAgMS40MDU0OCAqIDEuNDA1NDgsIDEuMzUzNyAqIDEuMzUzNywgMS4zMDM4MiAqIDEuMzAzODIsXG4gICAgICAgIDEuMjIzMjEgKiAxLjIyMzIxLCAxLjE0NzU4ICogMS4xNDc1OCwgMV07XG5cbiAgICAvKipcbiAgICAgKiBhZGRpdGlvbiBvZiBzaW11bHRhbmVvdXMgbWFza2luZyBOYW9raSBTaGliYXRhIDIwMDAvN1xuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZicnBzeV9tYXNrX2FkZChtMSwgbTIsIGIpIHtcbiAgICAgICAgdmFyIHJhdGlvO1xuXG4gICAgICAgIGlmIChtMSA8IDApIHtcbiAgICAgICAgICAgIG0xID0gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAobTIgPCAwKSB7XG4gICAgICAgICAgICBtMiA9IDA7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKG0xIDw9IDApIHtcbiAgICAgICAgICAgIHJldHVybiBtMjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobTIgPD0gMCkge1xuICAgICAgICAgICAgcmV0dXJuIG0xO1xuICAgICAgICB9XG4gICAgICAgIGlmIChtMiA+IG0xKSB7XG4gICAgICAgICAgICByYXRpbyA9IG0yIC8gbTE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByYXRpbyA9IG0xIC8gbTI7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKC0yIDw9IGIgJiYgYiA8PSAyKSB7XG4gICAgICAgICAgICAvKiBhcHByb3hpbWF0ZWx5LCAxIGJhcmsgPSAzIHBhcnRpdGlvbnMgKi9cbiAgICAgICAgICAgIC8qIG9yaWdpbmFsbHkgJ2lmKGkgPiA4KScgKi9cbiAgICAgICAgICAgIGlmIChyYXRpbyA+PSBtYV9tYXhfaTEpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gbTEgKyBtMjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFyIGkgPSAwIHwgKFV0aWwuRkFTVF9MT0cxMF9YKHJhdGlvLCAxNi4wKSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIChtMSArIG0yKSAqIHRhYmxlMl9baV07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHJhdGlvIDwgbWFfbWF4X2kyKSB7XG4gICAgICAgICAgICByZXR1cm4gbTEgKyBtMjtcbiAgICAgICAgfVxuICAgICAgICBpZiAobTEgPCBtMikge1xuICAgICAgICAgICAgbTEgPSBtMjtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gbTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogY29tcHV0ZSBpbnRlcmNoYW5uZWwgbWFza2luZyBlZmZlY3RzXG4gICAgICovXG4gICAgZnVuY3Rpb24gY2FsY19pbnRlcmNoYW5uZWxfbWFza2luZyhnZnAsIHJhdGlvKSB7XG4gICAgICAgIHZhciBnZmMgPSBnZnAuaW50ZXJuYWxfZmxhZ3M7XG4gICAgICAgIGlmIChnZmMuY2hhbm5lbHNfb3V0ID4gMSkge1xuICAgICAgICAgICAgZm9yICh2YXIgc2IgPSAwOyBzYiA8IEVuY29kZXIuU0JNQVhfbDsgc2IrKykge1xuICAgICAgICAgICAgICAgIHZhciBsID0gZ2ZjLnRobVswXS5sW3NiXTtcbiAgICAgICAgICAgICAgICB2YXIgciA9IGdmYy50aG1bMV0ubFtzYl07XG4gICAgICAgICAgICAgICAgZ2ZjLnRobVswXS5sW3NiXSArPSByICogcmF0aW87XG4gICAgICAgICAgICAgICAgZ2ZjLnRobVsxXS5sW3NiXSArPSBsICogcmF0aW87XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBzYiA9IDA7IHNiIDwgRW5jb2Rlci5TQk1BWF9zOyBzYisrKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgc2Jsb2NrID0gMDsgc2Jsb2NrIDwgMzsgc2Jsb2NrKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGwgPSBnZmMudGhtWzBdLnNbc2JdW3NibG9ja107XG4gICAgICAgICAgICAgICAgICAgIHZhciByID0gZ2ZjLnRobVsxXS5zW3NiXVtzYmxvY2tdO1xuICAgICAgICAgICAgICAgICAgICBnZmMudGhtWzBdLnNbc2JdW3NibG9ja10gKz0gciAqIHJhdGlvO1xuICAgICAgICAgICAgICAgICAgICBnZmMudGhtWzFdLnNbc2JdW3NibG9ja10gKz0gbCAqIHJhdGlvO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGNvbXB1dGUgTS9TIHRocmVzaG9sZHMgZnJvbSBKb2huc3RvbiAmIEZlcnJlaXJhIDE5OTIgSUNBU1NQIHBhcGVyXG4gICAgICovXG4gICAgZnVuY3Rpb24gbXNmaXgxKGdmYykge1xuICAgICAgICBmb3IgKHZhciBzYiA9IDA7IHNiIDwgRW5jb2Rlci5TQk1BWF9sOyBzYisrKSB7XG4gICAgICAgICAgICAvKiB1c2UgdGhpcyBmaXggaWYgTCAmIFIgbWFza2luZyBkaWZmZXJzIGJ5IDJkYiBvciBsZXNzICovXG4gICAgICAgICAgICAvKiBpZiBkYiA9IDEwKmxvZzEwKHgyL3gxKSA8IDIgKi9cbiAgICAgICAgICAgIC8qIGlmICh4MiA8IDEuNTgqeDEpIHsgKi9cbiAgICAgICAgICAgIGlmIChnZmMudGhtWzBdLmxbc2JdID4gMS41OCAqIGdmYy50aG1bMV0ubFtzYl1cbiAgICAgICAgICAgICAgICB8fCBnZmMudGhtWzFdLmxbc2JdID4gMS41OCAqIGdmYy50aG1bMF0ubFtzYl0pXG4gICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICB2YXIgbWxkID0gZ2ZjLm1sZF9sW3NiXSAqIGdmYy5lblszXS5sW3NiXTtcbiAgICAgICAgICAgIHZhciBybWlkID0gTWF0aC5tYXgoZ2ZjLnRobVsyXS5sW3NiXSxcbiAgICAgICAgICAgICAgICBNYXRoLm1pbihnZmMudGhtWzNdLmxbc2JdLCBtbGQpKTtcblxuICAgICAgICAgICAgbWxkID0gZ2ZjLm1sZF9sW3NiXSAqIGdmYy5lblsyXS5sW3NiXTtcbiAgICAgICAgICAgIHZhciByc2lkZSA9IE1hdGgubWF4KGdmYy50aG1bM10ubFtzYl0sXG4gICAgICAgICAgICAgICAgTWF0aC5taW4oZ2ZjLnRobVsyXS5sW3NiXSwgbWxkKSk7XG4gICAgICAgICAgICBnZmMudGhtWzJdLmxbc2JdID0gcm1pZDtcbiAgICAgICAgICAgIGdmYy50aG1bM10ubFtzYl0gPSByc2lkZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAodmFyIHNiID0gMDsgc2IgPCBFbmNvZGVyLlNCTUFYX3M7IHNiKyspIHtcbiAgICAgICAgICAgIGZvciAodmFyIHNibG9jayA9IDA7IHNibG9jayA8IDM7IHNibG9jaysrKSB7XG4gICAgICAgICAgICAgICAgaWYgKGdmYy50aG1bMF0uc1tzYl1bc2Jsb2NrXSA+IDEuNTggKiBnZmMudGhtWzFdLnNbc2JdW3NibG9ja11cbiAgICAgICAgICAgICAgICAgICAgfHwgZ2ZjLnRobVsxXS5zW3NiXVtzYmxvY2tdID4gMS41OCAqIGdmYy50aG1bMF0uc1tzYl1bc2Jsb2NrXSlcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgdmFyIG1sZCA9IGdmYy5tbGRfc1tzYl0gKiBnZmMuZW5bM10uc1tzYl1bc2Jsb2NrXTtcbiAgICAgICAgICAgICAgICB2YXIgcm1pZCA9IE1hdGgubWF4KGdmYy50aG1bMl0uc1tzYl1bc2Jsb2NrXSxcbiAgICAgICAgICAgICAgICAgICAgTWF0aC5taW4oZ2ZjLnRobVszXS5zW3NiXVtzYmxvY2tdLCBtbGQpKTtcblxuICAgICAgICAgICAgICAgIG1sZCA9IGdmYy5tbGRfc1tzYl0gKiBnZmMuZW5bMl0uc1tzYl1bc2Jsb2NrXTtcbiAgICAgICAgICAgICAgICB2YXIgcnNpZGUgPSBNYXRoLm1heChnZmMudGhtWzNdLnNbc2JdW3NibG9ja10sXG4gICAgICAgICAgICAgICAgICAgIE1hdGgubWluKGdmYy50aG1bMl0uc1tzYl1bc2Jsb2NrXSwgbWxkKSk7XG5cbiAgICAgICAgICAgICAgICBnZmMudGhtWzJdLnNbc2JdW3NibG9ja10gPSBybWlkO1xuICAgICAgICAgICAgICAgIGdmYy50aG1bM10uc1tzYl1bc2Jsb2NrXSA9IHJzaWRlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRqdXN0IE0vUyBtYXNraW5ncyBpZiB1c2VyIHNldCBcIm1zZml4XCJcbiAgICAgKlxuICAgICAqIE5hb2tpIFNoaWJhdGEgMjAwMFxuICAgICAqL1xuICAgIGZ1bmN0aW9uIG5zX21zZml4KGdmYywgbXNmaXgsIGF0aGFkanVzdCkge1xuICAgICAgICB2YXIgbXNmaXgyID0gbXNmaXg7XG4gICAgICAgIHZhciBhdGhsb3dlciA9IE1hdGgucG93KDEwLCBhdGhhZGp1c3QpO1xuXG4gICAgICAgIG1zZml4ICo9IDIuMDtcbiAgICAgICAgbXNmaXgyICo9IDIuMDtcbiAgICAgICAgZm9yICh2YXIgc2IgPSAwOyBzYiA8IEVuY29kZXIuU0JNQVhfbDsgc2IrKykge1xuICAgICAgICAgICAgdmFyIHRobUxSLCB0aG1NLCB0aG1TLCBhdGg7XG4gICAgICAgICAgICBhdGggPSAoZ2ZjLkFUSC5jYl9sW2dmYy5ibV9sW3NiXV0pICogYXRobG93ZXI7XG4gICAgICAgICAgICB0aG1MUiA9IE1hdGgubWluKE1hdGgubWF4KGdmYy50aG1bMF0ubFtzYl0sIGF0aCksXG4gICAgICAgICAgICAgICAgTWF0aC5tYXgoZ2ZjLnRobVsxXS5sW3NiXSwgYXRoKSk7XG4gICAgICAgICAgICB0aG1NID0gTWF0aC5tYXgoZ2ZjLnRobVsyXS5sW3NiXSwgYXRoKTtcbiAgICAgICAgICAgIHRobVMgPSBNYXRoLm1heChnZmMudGhtWzNdLmxbc2JdLCBhdGgpO1xuICAgICAgICAgICAgaWYgKHRobUxSICogbXNmaXggPCB0aG1NICsgdGhtUykge1xuICAgICAgICAgICAgICAgIHZhciBmID0gdGhtTFIgKiBtc2ZpeDIgLyAodGhtTSArIHRobVMpO1xuICAgICAgICAgICAgICAgIHRobU0gKj0gZjtcbiAgICAgICAgICAgICAgICB0aG1TICo9IGY7XG4gICAgICAgICAgICAgICAgYXNzZXJ0KHRobU0gKyB0aG1TID4gMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBnZmMudGhtWzJdLmxbc2JdID0gTWF0aC5taW4odGhtTSwgZ2ZjLnRobVsyXS5sW3NiXSk7XG4gICAgICAgICAgICBnZmMudGhtWzNdLmxbc2JdID0gTWF0aC5taW4odGhtUywgZ2ZjLnRobVszXS5sW3NiXSk7XG4gICAgICAgIH1cblxuICAgICAgICBhdGhsb3dlciAqPSAoIEVuY29kZXIuQkxLU0laRV9zIC8gRW5jb2Rlci5CTEtTSVpFKTtcbiAgICAgICAgZm9yICh2YXIgc2IgPSAwOyBzYiA8IEVuY29kZXIuU0JNQVhfczsgc2IrKykge1xuICAgICAgICAgICAgZm9yICh2YXIgc2Jsb2NrID0gMDsgc2Jsb2NrIDwgMzsgc2Jsb2NrKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgdGhtTFIsIHRobU0sIHRobVMsIGF0aDtcbiAgICAgICAgICAgICAgICBhdGggPSAoZ2ZjLkFUSC5jYl9zW2dmYy5ibV9zW3NiXV0pICogYXRobG93ZXI7XG4gICAgICAgICAgICAgICAgdGhtTFIgPSBNYXRoLm1pbihNYXRoLm1heChnZmMudGhtWzBdLnNbc2JdW3NibG9ja10sIGF0aCksXG4gICAgICAgICAgICAgICAgICAgIE1hdGgubWF4KGdmYy50aG1bMV0uc1tzYl1bc2Jsb2NrXSwgYXRoKSk7XG4gICAgICAgICAgICAgICAgdGhtTSA9IE1hdGgubWF4KGdmYy50aG1bMl0uc1tzYl1bc2Jsb2NrXSwgYXRoKTtcbiAgICAgICAgICAgICAgICB0aG1TID0gTWF0aC5tYXgoZ2ZjLnRobVszXS5zW3NiXVtzYmxvY2tdLCBhdGgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHRobUxSICogbXNmaXggPCB0aG1NICsgdGhtUykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgZiA9IHRobUxSICogbXNmaXggLyAodGhtTSArIHRobVMpO1xuICAgICAgICAgICAgICAgICAgICB0aG1NICo9IGY7XG4gICAgICAgICAgICAgICAgICAgIHRobVMgKj0gZjtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KHRobU0gKyB0aG1TID4gMCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGdmYy50aG1bMl0uc1tzYl1bc2Jsb2NrXSA9IE1hdGgubWluKGdmYy50aG1bMl0uc1tzYl1bc2Jsb2NrXSxcbiAgICAgICAgICAgICAgICAgICAgdGhtTSk7XG4gICAgICAgICAgICAgICAgZ2ZjLnRobVszXS5zW3NiXVtzYmxvY2tdID0gTWF0aC5taW4oZ2ZjLnRobVszXS5zW3NiXVtzYmxvY2tdLFxuICAgICAgICAgICAgICAgICAgICB0aG1TKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHNob3J0IGJsb2NrIHRocmVzaG9sZCBjYWxjdWxhdGlvbiAocGFydCAyKVxuICAgICAqXG4gICAgICogcGFydGl0aW9uIGJhbmQgYm9fc1tzZmJdIGlzIGF0IHRoZSB0cmFuc2l0aW9uIGZyb20gc2NhbGVmYWN0b3IgYmFuZCBzZmJcbiAgICAgKiB0byB0aGUgbmV4dCBvbmUgc2ZiKzE7IGVubiBhbmQgdGhtbSBoYXZlIHRvIGJlIHNwbGl0IGJldHdlZW4gdGhlbVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNvbnZlcnRfcGFydGl0aW9uMnNjYWxlZmFjX3MoZ2ZjLCBlYiwgdGhyLCBjaG4sIHNibG9jaykge1xuICAgICAgICB2YXIgc2IsIGI7XG4gICAgICAgIHZhciBlbm4gPSAwLjA7XG4gICAgICAgIHZhciB0aG1tID0gMC4wO1xuICAgICAgICBmb3IgKHNiID0gYiA9IDA7IHNiIDwgRW5jb2Rlci5TQk1BWF9zOyArK2IsICsrc2IpIHtcbiAgICAgICAgICAgIHZhciBib19zX3NiID0gZ2ZjLmJvX3Nbc2JdO1xuICAgICAgICAgICAgdmFyIG5wYXJ0X3MgPSBnZmMubnBhcnRfcztcbiAgICAgICAgICAgIHZhciBiX2xpbSA9IGJvX3Nfc2IgPCBucGFydF9zID8gYm9fc19zYiA6IG5wYXJ0X3M7XG4gICAgICAgICAgICB3aGlsZSAoYiA8IGJfbGltKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0KGViW2JdID49IDApO1xuICAgICAgICAgICAgICAgIC8vIGlmZiBmYWlsZWQsIGl0IG1heSBpbmRpY2F0ZSBzb21lIGluZGV4IGVycm9yIGVsc2V3aGVyZVxuICAgICAgICAgICAgICAgIGFzc2VydCh0aHJbYl0gPj0gMCk7XG4gICAgICAgICAgICAgICAgZW5uICs9IGViW2JdO1xuICAgICAgICAgICAgICAgIHRobW0gKz0gdGhyW2JdO1xuICAgICAgICAgICAgICAgIGIrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGdmYy5lbltjaG5dLnNbc2JdW3NibG9ja10gPSBlbm47XG4gICAgICAgICAgICBnZmMudGhtW2Nobl0uc1tzYl1bc2Jsb2NrXSA9IHRobW07XG5cbiAgICAgICAgICAgIGlmIChiID49IG5wYXJ0X3MpIHtcbiAgICAgICAgICAgICAgICArK3NiO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgYXNzZXJ0KGViW2JdID49IDApO1xuICAgICAgICAgICAgLy8gaWZmIGZhaWxlZCwgaXQgbWF5IGluZGljYXRlIHNvbWUgaW5kZXggZXJyb3IgZWxzZXdoZXJlXG4gICAgICAgICAgICBhc3NlcnQodGhyW2JdID49IDApO1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIC8qIGF0IHRyYW5zaXRpb24gc2ZiIC4gc2ZiKzEgKi9cbiAgICAgICAgICAgICAgICB2YXIgd19jdXJyID0gZ2ZjLlBTWS5ib19zX3dlaWdodFtzYl07XG4gICAgICAgICAgICAgICAgdmFyIHdfbmV4dCA9IDEuMCAtIHdfY3VycjtcbiAgICAgICAgICAgICAgICBlbm4gPSB3X2N1cnIgKiBlYltiXTtcbiAgICAgICAgICAgICAgICB0aG1tID0gd19jdXJyICogdGhyW2JdO1xuICAgICAgICAgICAgICAgIGdmYy5lbltjaG5dLnNbc2JdW3NibG9ja10gKz0gZW5uO1xuICAgICAgICAgICAgICAgIGdmYy50aG1bY2huXS5zW3NiXVtzYmxvY2tdICs9IHRobW07XG4gICAgICAgICAgICAgICAgZW5uID0gd19uZXh0ICogZWJbYl07XG4gICAgICAgICAgICAgICAgdGhtbSA9IHdfbmV4dCAqIHRocltiXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAvKiB6ZXJvIGluaXRpYWxpemUgdGhlIHJlc3QgKi9cbiAgICAgICAgZm9yICg7IHNiIDwgRW5jb2Rlci5TQk1BWF9zOyArK3NiKSB7XG4gICAgICAgICAgICBnZmMuZW5bY2huXS5zW3NiXVtzYmxvY2tdID0gMDtcbiAgICAgICAgICAgIGdmYy50aG1bY2huXS5zW3NiXVtzYmxvY2tdID0gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGxvbmdibG9jayB0aHJlc2hvbGQgY2FsY3VsYXRpb24gKHBhcnQgMilcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjb252ZXJ0X3BhcnRpdGlvbjJzY2FsZWZhY19sKGdmYywgZWIsIHRociwgY2huKSB7XG4gICAgICAgIHZhciBzYiwgYjtcbiAgICAgICAgdmFyIGVubiA9IDAuMDtcbiAgICAgICAgdmFyIHRobW0gPSAwLjA7XG4gICAgICAgIGZvciAoc2IgPSBiID0gMDsgc2IgPCBFbmNvZGVyLlNCTUFYX2w7ICsrYiwgKytzYikge1xuICAgICAgICAgICAgdmFyIGJvX2xfc2IgPSBnZmMuYm9fbFtzYl07XG4gICAgICAgICAgICB2YXIgbnBhcnRfbCA9IGdmYy5ucGFydF9sO1xuICAgICAgICAgICAgdmFyIGJfbGltID0gYm9fbF9zYiA8IG5wYXJ0X2wgPyBib19sX3NiIDogbnBhcnRfbDtcbiAgICAgICAgICAgIHdoaWxlIChiIDwgYl9saW0pIHtcbiAgICAgICAgICAgICAgICBhc3NlcnQoZWJbYl0gPj0gMCk7XG4gICAgICAgICAgICAgICAgLy8gaWZmIGZhaWxlZCwgaXQgbWF5IGluZGljYXRlIHNvbWUgaW5kZXggZXJyb3IgZWxzZXdoZXJlXG4gICAgICAgICAgICAgICAgYXNzZXJ0KHRocltiXSA+PSAwKTtcbiAgICAgICAgICAgICAgICBlbm4gKz0gZWJbYl07XG4gICAgICAgICAgICAgICAgdGhtbSArPSB0aHJbYl07XG4gICAgICAgICAgICAgICAgYisrO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ2ZjLmVuW2Nobl0ubFtzYl0gPSBlbm47XG4gICAgICAgICAgICBnZmMudGhtW2Nobl0ubFtzYl0gPSB0aG1tO1xuXG4gICAgICAgICAgICBpZiAoYiA+PSBucGFydF9sKSB7XG4gICAgICAgICAgICAgICAgKytzYjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzc2VydChlYltiXSA+PSAwKTtcbiAgICAgICAgICAgIGFzc2VydCh0aHJbYl0gPj0gMCk7XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgLyogYXQgdHJhbnNpdGlvbiBzZmIgLiBzZmIrMSAqL1xuICAgICAgICAgICAgICAgIHZhciB3X2N1cnIgPSBnZmMuUFNZLmJvX2xfd2VpZ2h0W3NiXTtcbiAgICAgICAgICAgICAgICB2YXIgd19uZXh0ID0gMS4wIC0gd19jdXJyO1xuICAgICAgICAgICAgICAgIGVubiA9IHdfY3VyciAqIGViW2JdO1xuICAgICAgICAgICAgICAgIHRobW0gPSB3X2N1cnIgKiB0aHJbYl07XG4gICAgICAgICAgICAgICAgZ2ZjLmVuW2Nobl0ubFtzYl0gKz0gZW5uO1xuICAgICAgICAgICAgICAgIGdmYy50aG1bY2huXS5sW3NiXSArPSB0aG1tO1xuICAgICAgICAgICAgICAgIGVubiA9IHdfbmV4dCAqIGViW2JdO1xuICAgICAgICAgICAgICAgIHRobW0gPSB3X25leHQgKiB0aHJbYl07XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgLyogemVybyBpbml0aWFsaXplIHRoZSByZXN0ICovXG4gICAgICAgIGZvciAoOyBzYiA8IEVuY29kZXIuU0JNQVhfbDsgKytzYikge1xuICAgICAgICAgICAgZ2ZjLmVuW2Nobl0ubFtzYl0gPSAwO1xuICAgICAgICAgICAgZ2ZjLnRobVtjaG5dLmxbc2JdID0gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNvbXB1dGVfbWFza2luZ19zKGdmcCwgZmZ0ZW5lcmd5X3MsIGViLCB0aHIsIGNobiwgc2Jsb2NrKSB7XG4gICAgICAgIHZhciBnZmMgPSBnZnAuaW50ZXJuYWxfZmxhZ3M7XG4gICAgICAgIHZhciBqLCBiO1xuXG4gICAgICAgIGZvciAoYiA9IGogPSAwOyBiIDwgZ2ZjLm5wYXJ0X3M7ICsrYikge1xuICAgICAgICAgICAgdmFyIGViYiA9IDAsIG0gPSAwO1xuICAgICAgICAgICAgdmFyIG4gPSBnZmMubnVtbGluZXNfc1tiXTtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpLCArK2opIHtcbiAgICAgICAgICAgICAgICB2YXIgZWwgPSBmZnRlbmVyZ3lfc1tzYmxvY2tdW2pdO1xuICAgICAgICAgICAgICAgIGViYiArPSBlbDtcbiAgICAgICAgICAgICAgICBpZiAobSA8IGVsKVxuICAgICAgICAgICAgICAgICAgICBtID0gZWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlYltiXSA9IGViYjtcbiAgICAgICAgfVxuICAgICAgICBhc3NlcnQoYiA9PSBnZmMubnBhcnRfcyk7XG4gICAgICAgIGFzc2VydChqID09IDEyOSk7XG4gICAgICAgIGZvciAoaiA9IGIgPSAwOyBiIDwgZ2ZjLm5wYXJ0X3M7IGIrKykge1xuICAgICAgICAgICAgdmFyIGtrID0gZ2ZjLnMzaW5kX3NbYl1bMF07XG4gICAgICAgICAgICB2YXIgZWNiID0gZ2ZjLnMzX3NzW2orK10gKiBlYltra107XG4gICAgICAgICAgICArK2trO1xuICAgICAgICAgICAgd2hpbGUgKGtrIDw9IGdmYy5zM2luZF9zW2JdWzFdKSB7XG4gICAgICAgICAgICAgICAgZWNiICs9IGdmYy5zM19zc1tqXSAqIGViW2trXTtcbiAgICAgICAgICAgICAgICArK2o7XG4gICAgICAgICAgICAgICAgKytraztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgeyAvKiBsaW1pdCBjYWxjdWxhdGVkIHRocmVzaG9sZCBieSBwcmV2aW91cyBncmFudWxlICovXG4gICAgICAgICAgICAgICAgdmFyIHggPSBycGVsZXZfcyAqIGdmYy5uYl9zMVtjaG5dW2JdO1xuICAgICAgICAgICAgICAgIHRocltiXSA9IE1hdGgubWluKGVjYiwgeCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZ2ZjLmJsb2NrdHlwZV9vbGRbY2huICYgMV0gPT0gRW5jb2Rlci5TSE9SVF9UWVBFKSB7XG4gICAgICAgICAgICAgICAgLyogbGltaXQgY2FsY3VsYXRlZCB0aHJlc2hvbGQgYnkgZXZlbiBvbGRlciBncmFudWxlICovXG4gICAgICAgICAgICAgICAgdmFyIHggPSBycGVsZXYyX3MgKiBnZmMubmJfczJbY2huXVtiXTtcbiAgICAgICAgICAgICAgICB2YXIgeSA9IHRocltiXTtcbiAgICAgICAgICAgICAgICB0aHJbYl0gPSBNYXRoLm1pbih4LCB5KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZ2ZjLm5iX3MyW2Nobl1bYl0gPSBnZmMubmJfczFbY2huXVtiXTtcbiAgICAgICAgICAgIGdmYy5uYl9zMVtjaG5dW2JdID0gZWNiO1xuICAgICAgICAgICAgYXNzZXJ0KHRocltiXSA+PSAwKTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKDsgYiA8PSBFbmNvZGVyLkNCQU5EUzsgKytiKSB7XG4gICAgICAgICAgICBlYltiXSA9IDA7XG4gICAgICAgICAgICB0aHJbYl0gPSAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gYmxvY2tfdHlwZV9zZXQoZ2ZwLCB1c2Vsb25nYmxvY2ssIGJsb2NrdHlwZV9kLCBibG9ja3R5cGUpIHtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcblxuICAgICAgICBpZiAoZ2ZwLnNob3J0X2Jsb2NrcyA9PSBTaG9ydEJsb2NrLnNob3J0X2Jsb2NrX2NvdXBsZWRcbiAgICAgICAgICAgICAgICAvKiBmb3JjZSBib3RoIGNoYW5uZWxzIHRvIHVzZSB0aGUgc2FtZSBibG9jayB0eXBlICovXG4gICAgICAgICAgICAgICAgLyogdGhpcyBpcyBuZWNlc3NhcnkgaWYgdGhlIGZyYW1lIGlzIHRvIGJlIGVuY29kZWQgaW4gbXNfc3RlcmVvLiAqL1xuICAgICAgICAgICAgICAgIC8qIEJ1dCBldmVuIHdpdGhvdXQgbXNfc3RlcmVvLCBGaEcgZG9lcyB0aGlzICovXG4gICAgICAgICAgICAmJiAhKHVzZWxvbmdibG9ja1swXSAhPSAwICYmIHVzZWxvbmdibG9ja1sxXSAhPSAwKSlcbiAgICAgICAgICAgIHVzZWxvbmdibG9ja1swXSA9IHVzZWxvbmdibG9ja1sxXSA9IDA7XG5cbiAgICAgICAgLypcbiAgICAgICAgICogdXBkYXRlIHRoZSBibG9ja3R5cGUgb2YgdGhlIHByZXZpb3VzIGdyYW51bGUsIHNpbmNlIGl0IGRlcGVuZHMgb25cbiAgICAgICAgICogd2hhdCBoYXBwZW5kIGluIHRoaXMgZ3JhbnVsZVxuICAgICAgICAgKi9cbiAgICAgICAgZm9yICh2YXIgY2huID0gMDsgY2huIDwgZ2ZjLmNoYW5uZWxzX291dDsgY2huKyspIHtcbiAgICAgICAgICAgIGJsb2NrdHlwZVtjaG5dID0gRW5jb2Rlci5OT1JNX1RZUEU7XG4gICAgICAgICAgICAvKiBkaXNhYmxlIHNob3J0IGJsb2NrcyAqL1xuICAgICAgICAgICAgaWYgKGdmcC5zaG9ydF9ibG9ja3MgPT0gU2hvcnRCbG9jay5zaG9ydF9ibG9ja19kaXNwZW5zZWQpXG4gICAgICAgICAgICAgICAgdXNlbG9uZ2Jsb2NrW2Nobl0gPSAxO1xuICAgICAgICAgICAgaWYgKGdmcC5zaG9ydF9ibG9ja3MgPT0gU2hvcnRCbG9jay5zaG9ydF9ibG9ja19mb3JjZWQpXG4gICAgICAgICAgICAgICAgdXNlbG9uZ2Jsb2NrW2Nobl0gPSAwO1xuXG4gICAgICAgICAgICBpZiAodXNlbG9uZ2Jsb2NrW2Nobl0gIT0gMCkge1xuICAgICAgICAgICAgICAgIC8qIG5vIGF0dGFjayA6IHVzZSBsb25nIGJsb2NrcyAqL1xuICAgICAgICAgICAgICAgIGFzc2VydChnZmMuYmxvY2t0eXBlX29sZFtjaG5dICE9IEVuY29kZXIuU1RBUlRfVFlQRSk7XG4gICAgICAgICAgICAgICAgaWYgKGdmYy5ibG9ja3R5cGVfb2xkW2Nobl0gPT0gRW5jb2Rlci5TSE9SVF9UWVBFKVxuICAgICAgICAgICAgICAgICAgICBibG9ja3R5cGVbY2huXSA9IEVuY29kZXIuU1RPUF9UWVBFO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvKiBhdHRhY2sgOiB1c2Ugc2hvcnQgYmxvY2tzICovXG4gICAgICAgICAgICAgICAgYmxvY2t0eXBlW2Nobl0gPSBFbmNvZGVyLlNIT1JUX1RZUEU7XG4gICAgICAgICAgICAgICAgaWYgKGdmYy5ibG9ja3R5cGVfb2xkW2Nobl0gPT0gRW5jb2Rlci5OT1JNX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2ZjLmJsb2NrdHlwZV9vbGRbY2huXSA9IEVuY29kZXIuU1RBUlRfVFlQRTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGdmYy5ibG9ja3R5cGVfb2xkW2Nobl0gPT0gRW5jb2Rlci5TVE9QX1RZUEUpXG4gICAgICAgICAgICAgICAgICAgIGdmYy5ibG9ja3R5cGVfb2xkW2Nobl0gPSBFbmNvZGVyLlNIT1JUX1RZUEU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJsb2NrdHlwZV9kW2Nobl0gPSBnZmMuYmxvY2t0eXBlX29sZFtjaG5dO1xuICAgICAgICAgICAgLy8gdmFsdWUgcmV0dXJuZWQgdG8gY2FsbGluZyBwcm9ncmFtXG4gICAgICAgICAgICBnZmMuYmxvY2t0eXBlX29sZFtjaG5dID0gYmxvY2t0eXBlW2Nobl07XG4gICAgICAgICAgICAvLyBzYXZlIGZvciBuZXh0IGNhbGwgdG8gbDNwc3lfYW5hbFxuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gTlNfSU5URVJQKHgsIHksIHIpIHtcbiAgICAgICAgLyogd2FzIHBvdygoeCksKHIpKSpwb3coKHkpLDEtKHIpKSAqL1xuICAgICAgICBpZiAociA+PSAxLjApIHtcbiAgICAgICAgICAgIC8qIDk5LjclIG9mIHRoZSB0aW1lICovXG4gICAgICAgICAgICByZXR1cm4geDtcbiAgICAgICAgfVxuICAgICAgICBpZiAociA8PSAwLjApXG4gICAgICAgICAgICByZXR1cm4geTtcbiAgICAgICAgaWYgKHkgPiAwLjApIHtcbiAgICAgICAgICAgIC8qIHJlc3Qgb2YgdGhlIHRpbWUgKi9cbiAgICAgICAgICAgIHJldHVybiAoTWF0aC5wb3coeCAvIHksIHIpICogeSk7XG4gICAgICAgIH1cbiAgICAgICAgLyogbmV2ZXIgaGFwcGVucyAqL1xuICAgICAgICByZXR1cm4gMC4wO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIHRoZXNlIHZhbHVlcyBhcmUgdHVuZWQgb25seSBmb3IgNDQuMWtIei4uLlxuICAgICAqL1xuICAgIHZhciByZWdjb2VmX3MgPSBbMTEuOCwgMTMuNiwgMTcuMiwgMzIsIDQ2LjUsXG4gICAgICAgIDUxLjMsIDU3LjUsIDY3LjEsIDcxLjUsIDg0LjYsIDk3LjYsIDEzMCxcbiAgICAgICAgLyogMjU1LjggKi9cbiAgICBdO1xuXG4gICAgZnVuY3Rpb24gcGVjYWxjX3MobXIsIG1hc2tpbmdfbG93ZXIpIHtcbiAgICAgICAgdmFyIHBlX3MgPSAxMjM2LjI4IC8gNDtcbiAgICAgICAgZm9yICh2YXIgc2IgPSAwOyBzYiA8IEVuY29kZXIuU0JNQVhfcyAtIDE7IHNiKyspIHtcbiAgICAgICAgICAgIGZvciAodmFyIHNibG9jayA9IDA7IHNibG9jayA8IDM7IHNibG9jaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHRobSA9IG1yLnRobS5zW3NiXVtzYmxvY2tdO1xuICAgICAgICAgICAgICAgIGFzc2VydChzYiA8IHJlZ2NvZWZfcy5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGlmICh0aG0gPiAwLjApIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHggPSB0aG0gKiBtYXNraW5nX2xvd2VyO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZW4gPSBtci5lbi5zW3NiXVtzYmxvY2tdO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW4gPiB4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZW4gPiB4ICogMWUxMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlX3MgKz0gcmVnY29lZl9zW3NiXSAqICgxMC4wICogTE9HMTApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQoeCA+IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlX3MgKz0gcmVnY29lZl9zW3NiXSAqIFV0aWwuRkFTVF9MT0cxMChlbiAvIHgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBlX3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogdGhlc2UgdmFsdWVzIGFyZSB0dW5lZCBvbmx5IGZvciA0NC4xa0h6Li4uXG4gICAgICovXG4gICAgdmFyIHJlZ2NvZWZfbCA9IFs2LjgsIDUuOCwgNS44LCA2LjQsIDYuNSwgOS45LFxuICAgICAgICAxMi4xLCAxNC40LCAxNSwgMTguOSwgMjEuNiwgMjYuOSwgMzQuMiwgNDAuMiwgNDYuOCwgNTYuNSxcbiAgICAgICAgNjAuNywgNzMuOSwgODUuNywgOTMuNCwgMTI2LjEsXG4gICAgICAgIC8qIDI0MS4zICovXG4gICAgXTtcblxuICAgIGZ1bmN0aW9uIHBlY2FsY19sKG1yLCBtYXNraW5nX2xvd2VyKSB7XG4gICAgICAgIHZhciBwZV9sID0gMTEyNC4yMyAvIDQ7XG4gICAgICAgIGZvciAodmFyIHNiID0gMDsgc2IgPCBFbmNvZGVyLlNCTUFYX2wgLSAxOyBzYisrKSB7XG4gICAgICAgICAgICB2YXIgdGhtID0gbXIudGhtLmxbc2JdO1xuICAgICAgICAgICAgYXNzZXJ0KHNiIDwgcmVnY29lZl9sLmxlbmd0aCk7XG4gICAgICAgICAgICBpZiAodGhtID4gMC4wKSB7XG4gICAgICAgICAgICAgICAgdmFyIHggPSB0aG0gKiBtYXNraW5nX2xvd2VyO1xuICAgICAgICAgICAgICAgIHZhciBlbiA9IG1yLmVuLmxbc2JdO1xuICAgICAgICAgICAgICAgIGlmIChlbiA+IHgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGVuID4geCAqIDFlMTApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlX2wgKz0gcmVnY29lZl9sW3NiXSAqICgxMC4wICogTE9HMTApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KHggPiAwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBlX2wgKz0gcmVnY29lZl9sW3NiXSAqIFV0aWwuRkFTVF9MT0cxMChlbiAvIHgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwZV9sO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIGNhbGNfZW5lcmd5KGdmYywgZmZ0ZW5lcmd5LCBlYiwgbWF4LCBhdmcpIHtcbiAgICAgICAgdmFyIGIsIGo7XG5cbiAgICAgICAgZm9yIChiID0gaiA9IDA7IGIgPCBnZmMubnBhcnRfbDsgKytiKSB7XG4gICAgICAgICAgICB2YXIgZWJiID0gMCwgbSA9IDA7XG4gICAgICAgICAgICB2YXIgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCBnZmMubnVtbGluZXNfbFtiXTsgKytpLCArK2opIHtcbiAgICAgICAgICAgICAgICB2YXIgZWwgPSBmZnRlbmVyZ3lbal07XG4gICAgICAgICAgICAgICAgYXNzZXJ0KGVsID49IDApO1xuICAgICAgICAgICAgICAgIGViYiArPSBlbDtcbiAgICAgICAgICAgICAgICBpZiAobSA8IGVsKVxuICAgICAgICAgICAgICAgICAgICBtID0gZWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlYltiXSA9IGViYjtcbiAgICAgICAgICAgIG1heFtiXSA9IG07XG4gICAgICAgICAgICBhdmdbYl0gPSBlYmIgKiBnZmMucm51bWxpbmVzX2xbYl07XG4gICAgICAgICAgICBhc3NlcnQoZ2ZjLnJudW1saW5lc19sW2JdID49IDApO1xuICAgICAgICAgICAgYXNzZXJ0KGViYiA+PSAwKTtcbiAgICAgICAgICAgIGFzc2VydChlYltiXSA+PSAwKTtcbiAgICAgICAgICAgIGFzc2VydChtYXhbYl0gPj0gMCk7XG4gICAgICAgICAgICBhc3NlcnQoYXZnW2JdID49IDApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gY2FsY19tYXNrX2luZGV4X2woZ2ZjLCBtYXgsIGF2ZywgbWFza19pZHgpIHtcbiAgICAgICAgdmFyIGxhc3RfdGFiX2VudHJ5ID0gdGFiLmxlbmd0aCAtIDE7XG4gICAgICAgIHZhciBiID0gMDtcbiAgICAgICAgdmFyIGEgPSBhdmdbYl0gKyBhdmdbYiArIDFdO1xuICAgICAgICBhc3NlcnQoYSA+PSAwKTtcbiAgICAgICAgaWYgKGEgPiAwLjApIHtcbiAgICAgICAgICAgIHZhciBtID0gbWF4W2JdO1xuICAgICAgICAgICAgaWYgKG0gPCBtYXhbYiArIDFdKVxuICAgICAgICAgICAgICAgIG0gPSBtYXhbYiArIDFdO1xuICAgICAgICAgICAgYXNzZXJ0KChnZmMubnVtbGluZXNfbFtiXSArIGdmYy5udW1saW5lc19sW2IgKyAxXSAtIDEpID4gMCk7XG4gICAgICAgICAgICBhID0gMjAuMCAqIChtICogMi4wIC0gYSlcbiAgICAgICAgICAgICAgICAvIChhICogKGdmYy5udW1saW5lc19sW2JdICsgZ2ZjLm51bWxpbmVzX2xbYiArIDFdIC0gMSkpO1xuICAgICAgICAgICAgdmFyIGsgPSAwIHwgYTtcbiAgICAgICAgICAgIGlmIChrID4gbGFzdF90YWJfZW50cnkpXG4gICAgICAgICAgICAgICAgayA9IGxhc3RfdGFiX2VudHJ5O1xuICAgICAgICAgICAgbWFza19pZHhbYl0gPSBrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbWFza19pZHhbYl0gPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChiID0gMTsgYiA8IGdmYy5ucGFydF9sIC0gMTsgYisrKSB7XG4gICAgICAgICAgICBhID0gYXZnW2IgLSAxXSArIGF2Z1tiXSArIGF2Z1tiICsgMV07XG4gICAgICAgICAgICBhc3NlcnQoYSA+PSAwKTtcbiAgICAgICAgICAgIGlmIChhID4gMC4wKSB7XG4gICAgICAgICAgICAgICAgdmFyIG0gPSBtYXhbYiAtIDFdO1xuICAgICAgICAgICAgICAgIGlmIChtIDwgbWF4W2JdKVxuICAgICAgICAgICAgICAgICAgICBtID0gbWF4W2JdO1xuICAgICAgICAgICAgICAgIGlmIChtIDwgbWF4W2IgKyAxXSlcbiAgICAgICAgICAgICAgICAgICAgbSA9IG1heFtiICsgMV07XG4gICAgICAgICAgICAgICAgYXNzZXJ0KChnZmMubnVtbGluZXNfbFtiIC0gMV0gKyBnZmMubnVtbGluZXNfbFtiXSArIGdmYy5udW1saW5lc19sW2IgKyAxXSAtIDEpID4gMCk7XG4gICAgICAgICAgICAgICAgYSA9IDIwLjBcbiAgICAgICAgICAgICAgICAgICAgKiAobSAqIDMuMCAtIGEpXG4gICAgICAgICAgICAgICAgICAgIC8gKGEgKiAoZ2ZjLm51bWxpbmVzX2xbYiAtIDFdICsgZ2ZjLm51bWxpbmVzX2xbYl1cbiAgICAgICAgICAgICAgICAgICAgKyBnZmMubnVtbGluZXNfbFtiICsgMV0gLSAxKSk7XG4gICAgICAgICAgICAgICAgdmFyIGsgPSAwIHwgYTtcbiAgICAgICAgICAgICAgICBpZiAoayA+IGxhc3RfdGFiX2VudHJ5KVxuICAgICAgICAgICAgICAgICAgICBrID0gbGFzdF90YWJfZW50cnk7XG4gICAgICAgICAgICAgICAgbWFza19pZHhbYl0gPSBrO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtYXNrX2lkeFtiXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgYXNzZXJ0KGIgPiAwKTtcbiAgICAgICAgYXNzZXJ0KGIgPT0gZ2ZjLm5wYXJ0X2wgLSAxKTtcblxuICAgICAgICBhID0gYXZnW2IgLSAxXSArIGF2Z1tiXTtcbiAgICAgICAgYXNzZXJ0KGEgPj0gMCk7XG4gICAgICAgIGlmIChhID4gMC4wKSB7XG4gICAgICAgICAgICB2YXIgbSA9IG1heFtiIC0gMV07XG4gICAgICAgICAgICBpZiAobSA8IG1heFtiXSlcbiAgICAgICAgICAgICAgICBtID0gbWF4W2JdO1xuICAgICAgICAgICAgYXNzZXJ0KChnZmMubnVtbGluZXNfbFtiIC0gMV0gKyBnZmMubnVtbGluZXNfbFtiXSAtIDEpID4gMCk7XG4gICAgICAgICAgICBhID0gMjAuMCAqIChtICogMi4wIC0gYSlcbiAgICAgICAgICAgICAgICAvIChhICogKGdmYy5udW1saW5lc19sW2IgLSAxXSArIGdmYy5udW1saW5lc19sW2JdIC0gMSkpO1xuICAgICAgICAgICAgdmFyIGsgPSAwIHwgYTtcbiAgICAgICAgICAgIGlmIChrID4gbGFzdF90YWJfZW50cnkpXG4gICAgICAgICAgICAgICAgayA9IGxhc3RfdGFiX2VudHJ5O1xuICAgICAgICAgICAgbWFza19pZHhbYl0gPSBrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbWFza19pZHhbYl0gPSAwO1xuICAgICAgICB9XG4gICAgICAgIGFzc2VydChiID09IChnZmMubnBhcnRfbCAtIDEpKTtcbiAgICB9XG5cbiAgICB2YXIgZmlyY29lZiA9IFtcbiAgICAgICAgLTguNjUxNjNlLTE4ICogMiwgLTAuMDA4NTE1ODYgKiAyLCAtNi43NDc2NGUtMTggKiAyLCAwLjAyMDkwMzYgKiAyLFxuICAgICAgICAtMy4zNjYzOWUtMTcgKiAyLCAtMC4wNDM4MTYyICogMiwgLTEuNTQxNzVlLTE3ICogMiwgMC4wOTMxNzM4ICogMixcbiAgICAgICAgLTUuNTIyMTJlLTE3ICogMiwgLTAuMzEzODE5ICogMlxuICAgIF07XG5cbiAgICB0aGlzLkwzcHN5Y2hvX2FuYWxfbnMgPSBmdW5jdGlvbiAoZ2ZwLCBidWZmZXIsIGJ1ZlBvcywgZ3Jfb3V0LCBtYXNraW5nX3JhdGlvLCBtYXNraW5nX01TX3JhdGlvLCBwZXJjZXBfZW50cm9weSwgcGVyY2VwX01TX2VudHJvcHksIGVuZXJneSwgYmxvY2t0eXBlX2QpIHtcbiAgICAgICAgLypcbiAgICAgICAgICogdG8gZ2V0IGEgZ29vZCBjYWNoZSBwZXJmb3JtYW5jZSwgb25lIGhhcyB0byB0aGluayBhYm91dCB0aGUgc2VxdWVuY2UsXG4gICAgICAgICAqIGluIHdoaWNoIHRoZSB2YXJpYWJsZXMgYXJlIHVzZWQuXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgZ2ZjID0gZ2ZwLmludGVybmFsX2ZsYWdzO1xuXG4gICAgICAgIC8qIGZmdCBhbmQgZW5lcmd5IGNhbGN1bGF0aW9uICovXG4gICAgICAgIHZhciB3c2FtcF9MID0gbmV3X2Zsb2F0X24oWzIsIEVuY29kZXIuQkxLU0laRV0pO1xuICAgICAgICB2YXIgd3NhbXBfUyA9IG5ld19mbG9hdF9uKFsyLCAzLCBFbmNvZGVyLkJMS1NJWkVfc10pO1xuXG4gICAgICAgIC8qIGNvbnZvbHV0aW9uICovXG4gICAgICAgIHZhciBlYl9sID0gbmV3X2Zsb2F0KEVuY29kZXIuQ0JBTkRTICsgMSk7XG4gICAgICAgIHZhciBlYl9zID0gbmV3X2Zsb2F0KEVuY29kZXIuQ0JBTkRTICsgMSk7XG4gICAgICAgIHZhciB0aHIgPSBuZXdfZmxvYXQoRW5jb2Rlci5DQkFORFMgKyAyKTtcblxuICAgICAgICAvKiBibG9jayB0eXBlICovXG4gICAgICAgIHZhciBibG9ja3R5cGUgPSBuZXdfaW50KDIpLCB1c2Vsb25nYmxvY2sgPSBuZXdfaW50KDIpO1xuXG4gICAgICAgIC8qIHVzdWFsIHZhcmlhYmxlcyBsaWtlIGxvb3AgaW5kaWNlcywgZXRjLi4gKi9cbiAgICAgICAgdmFyIG51bWNobiwgY2huO1xuICAgICAgICB2YXIgYiwgaSwgaiwgaztcbiAgICAgICAgdmFyIHNiLCBzYmxvY2s7XG5cbiAgICAgICAgLyogdmFyaWFibGVzIHVzZWQgZm9yIC0tbnNwc3l0dW5lICovXG4gICAgICAgIHZhciBuc19ocGZzbXBsID0gbmV3X2Zsb2F0X24oWzIsIDU3Nl0pO1xuICAgICAgICB2YXIgcGNmYWN0O1xuICAgICAgICB2YXIgbWFza19pZHhfbCA9IG5ld19pbnQoRW5jb2Rlci5DQkFORFMgKyAyKSwgbWFza19pZHhfcyA9IG5ld19pbnQoRW5jb2Rlci5DQkFORFMgKyAyKTtcblxuICAgICAgICBBcnJheXMuZmlsbChtYXNrX2lkeF9zLCAwKTtcblxuICAgICAgICBudW1jaG4gPSBnZmMuY2hhbm5lbHNfb3V0O1xuICAgICAgICAvKiBjaG49MiBhbmQgMyA9IE1pZCBhbmQgU2lkZSBjaGFubmVscyAqL1xuICAgICAgICBpZiAoZ2ZwLm1vZGUgPT0gTVBFR01vZGUuSk9JTlRfU1RFUkVPKVxuICAgICAgICAgICAgbnVtY2huID0gNDtcblxuICAgICAgICBpZiAoZ2ZwLlZCUiA9PSBWYnJNb2RlLnZicl9vZmYpXG4gICAgICAgICAgICBwY2ZhY3QgPSBnZmMuUmVzdk1heCA9PSAwID8gMCA6ICggZ2ZjLlJlc3ZTaXplKVxuICAgICAgICAgICAgLyBnZmMuUmVzdk1heCAqIDAuNTtcbiAgICAgICAgZWxzZSBpZiAoZ2ZwLlZCUiA9PSBWYnJNb2RlLnZicl9yaCB8fCBnZnAuVkJSID09IFZick1vZGUudmJyX210cmhcbiAgICAgICAgICAgIHx8IGdmcC5WQlIgPT0gVmJyTW9kZS52YnJfbXQpIHtcbiAgICAgICAgICAgIHBjZmFjdCA9IDAuNjtcbiAgICAgICAgfSBlbHNlXG4gICAgICAgICAgICBwY2ZhY3QgPSAxLjA7XG5cbiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgICAgICogQXBwbHkgSFBGIG9mIGZzLzQgdG8gdGhlIGlucHV0IHNpZ25hbC4gVGhpcyBpcyB1c2VkIGZvciBhdHRhY2tcbiAgICAgICAgICogZGV0ZWN0aW9uIC8gaGFuZGxpbmcuXG4gICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuICAgICAgICAvKiBEb24ndCBjb3B5IHRoZSBpbnB1dCBidWZmZXIgaW50byBhIHRlbXBvcmFyeSBidWZmZXIgKi9cbiAgICAgICAgLyogdW5yb2xsIHRoZSBsb29wIDIgdGltZXMgKi9cbiAgICAgICAgZm9yIChjaG4gPSAwOyBjaG4gPCBnZmMuY2hhbm5lbHNfb3V0OyBjaG4rKykge1xuICAgICAgICAgICAgLyogYXBwbHkgaGlnaCBwYXNzIGZpbHRlciBvZiBmcy80ICovXG4gICAgICAgICAgICB2YXIgZmlyYnVmID0gYnVmZmVyW2Nobl07XG4gICAgICAgICAgICB2YXIgZmlyYnVmUG9zID0gYnVmUG9zICsgNTc2IC0gMzUwIC0gTlNGSVJMRU4gKyAxOTI7XG4gICAgICAgICAgICBhc3NlcnQoZmlyY29lZi5sZW5ndGggPT0gKChOU0ZJUkxFTiAtIDEpIC8gMikpO1xuICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IDU3NjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHN1bTEsIHN1bTI7XG4gICAgICAgICAgICAgICAgc3VtMSA9IGZpcmJ1ZltmaXJidWZQb3MgKyBpICsgMTBdO1xuICAgICAgICAgICAgICAgIHN1bTIgPSAwLjA7XG4gICAgICAgICAgICAgICAgZm9yIChqID0gMDsgaiA8ICgoTlNGSVJMRU4gLSAxKSAvIDIpIC0gMTsgaiArPSAyKSB7XG4gICAgICAgICAgICAgICAgICAgIHN1bTEgKz0gZmlyY29lZltqXVxuICAgICAgICAgICAgICAgICAgICAgICAgKiAoZmlyYnVmW2ZpcmJ1ZlBvcyArIGkgKyBqXSArIGZpcmJ1ZltmaXJidWZQb3MgKyBpXG4gICAgICAgICAgICAgICAgICAgICAgICArIE5TRklSTEVOIC0gal0pO1xuICAgICAgICAgICAgICAgICAgICBzdW0yICs9IGZpcmNvZWZbaiArIDFdXG4gICAgICAgICAgICAgICAgICAgICAgICAqIChmaXJidWZbZmlyYnVmUG9zICsgaSArIGogKyAxXSArIGZpcmJ1ZltmaXJidWZQb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICsgaSArIE5TRklSTEVOIC0gaiAtIDFdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbnNfaHBmc21wbFtjaG5dW2ldID0gc3VtMSArIHN1bTI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtYXNraW5nX3JhdGlvW2dyX291dF1bY2huXS5lbi5hc3NpZ24oZ2ZjLmVuW2Nobl0pO1xuICAgICAgICAgICAgbWFza2luZ19yYXRpb1tncl9vdXRdW2Nobl0udGhtLmFzc2lnbihnZmMudGhtW2Nobl0pO1xuICAgICAgICAgICAgaWYgKG51bWNobiA+IDIpIHtcbiAgICAgICAgICAgICAgICAvKiBNUyBtYXNraW5ncyAqL1xuICAgICAgICAgICAgICAgIC8qIHBlcmNlcF9NU19lbnRyb3B5IFtjaG4tMl0gPSBnZmMgLiBwZSBbY2huXTsgKi9cbiAgICAgICAgICAgICAgICBtYXNraW5nX01TX3JhdGlvW2dyX291dF1bY2huXS5lbi5hc3NpZ24oZ2ZjLmVuW2NobiArIDJdKTtcbiAgICAgICAgICAgICAgICBtYXNraW5nX01TX3JhdGlvW2dyX291dF1bY2huXS50aG0uYXNzaWduKGdmYy50aG1bY2huICsgMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgZm9yIChjaG4gPSAwOyBjaG4gPCBudW1jaG47IGNobisrKSB7XG4gICAgICAgICAgICB2YXIgd3NhbXBfbDtcbiAgICAgICAgICAgIHZhciB3c2FtcF9zO1xuICAgICAgICAgICAgdmFyIGVuX3N1YnNob3J0ID0gbmV3X2Zsb2F0KDEyKTtcbiAgICAgICAgICAgIHZhciBlbl9zaG9ydCA9IFswLCAwLCAwLCAwXTtcbiAgICAgICAgICAgIHZhciBhdHRhY2tfaW50ZW5zaXR5ID0gbmV3X2Zsb2F0KDEyKTtcbiAgICAgICAgICAgIHZhciBuc191c2Vsb25nYmxvY2sgPSAxO1xuICAgICAgICAgICAgdmFyIGF0dGFja1RocmVzaG9sZDtcbiAgICAgICAgICAgIHZhciBtYXggPSBuZXdfZmxvYXQoRW5jb2Rlci5DQkFORFMpLCBhdmcgPSBuZXdfZmxvYXQoRW5jb2Rlci5DQkFORFMpO1xuICAgICAgICAgICAgdmFyIG5zX2F0dGFja3MgPSBbMCwgMCwgMCwgMF07XG4gICAgICAgICAgICB2YXIgZmZ0ZW5lcmd5ID0gbmV3X2Zsb2F0KEVuY29kZXIuSEJMS1NJWkUpO1xuICAgICAgICAgICAgdmFyIGZmdGVuZXJneV9zID0gbmV3X2Zsb2F0X24oWzMsIEVuY29kZXIuSEJMS1NJWkVfc10pO1xuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogcmggMjAwNDAzMDE6IHRoZSBmb2xsb3dpbmcgbG9vcHMgZG8gYWNjZXNzIG9uZSBvZmYgdGhlIGxpbWl0cyBzb1xuICAgICAgICAgICAgICogSSBpbmNyZWFzZSB0aGUgYXJyYXkgZGltZW5zaW9ucyBieSBvbmUgYW5kIGluaXRpYWxpemUgdGhlXG4gICAgICAgICAgICAgKiBhY2Nlc3NlZCB2YWx1ZXMgdG8gemVyb1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBhc3NlcnQoZ2ZjLm5wYXJ0X3MgPD0gRW5jb2Rlci5DQkFORFMpO1xuICAgICAgICAgICAgYXNzZXJ0KGdmYy5ucGFydF9sIDw9IEVuY29kZXIuQ0JBTkRTKTtcblxuICAgICAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICAgICAgICogZGV0ZXJtaW5lIHRoZSBibG9jayB0eXBlICh3aW5kb3cgdHlwZSlcbiAgICAgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgICAgICAvKiBjYWxjdWxhdGUgZW5lcmdpZXMgb2YgZWFjaCBzdWItc2hvcnRibG9ja3MgKi9cbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPCAzOyBpKyspIHtcbiAgICAgICAgICAgICAgICBlbl9zdWJzaG9ydFtpXSA9IGdmYy5uc1BzeS5sYXN0X2VuX3N1YnNob3J0W2Nobl1baSArIDZdO1xuICAgICAgICAgICAgICAgIGFzc2VydChnZmMubnNQc3kubGFzdF9lbl9zdWJzaG9ydFtjaG5dW2kgKyA0XSA+IDApO1xuICAgICAgICAgICAgICAgIGF0dGFja19pbnRlbnNpdHlbaV0gPSBlbl9zdWJzaG9ydFtpXVxuICAgICAgICAgICAgICAgICAgICAvIGdmYy5uc1BzeS5sYXN0X2VuX3N1YnNob3J0W2Nobl1baSArIDRdO1xuICAgICAgICAgICAgICAgIGVuX3Nob3J0WzBdICs9IGVuX3N1YnNob3J0W2ldO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoY2huID09IDIpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgNTc2OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIGwsIHI7XG4gICAgICAgICAgICAgICAgICAgIGwgPSBuc19ocGZzbXBsWzBdW2ldO1xuICAgICAgICAgICAgICAgICAgICByID0gbnNfaHBmc21wbFsxXVtpXTtcbiAgICAgICAgICAgICAgICAgICAgbnNfaHBmc21wbFswXVtpXSA9IGwgKyByO1xuICAgICAgICAgICAgICAgICAgICBuc19ocGZzbXBsWzFdW2ldID0gbCAtIHI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIHZhciBwZiA9IG5zX2hwZnNtcGxbY2huICYgMV07XG4gICAgICAgICAgICAgICAgdmFyIHBmUG9zID0gMDtcbiAgICAgICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgOTsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwZmUgPSBwZlBvcyArIDU3NiAvIDk7XG4gICAgICAgICAgICAgICAgICAgIHZhciBwID0gMS47XG4gICAgICAgICAgICAgICAgICAgIGZvciAoOyBwZlBvcyA8IHBmZTsgcGZQb3MrKylcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChwIDwgTWF0aC5hYnMocGZbcGZQb3NdKSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwID0gTWF0aC5hYnMocGZbcGZQb3NdKTtcblxuICAgICAgICAgICAgICAgICAgICBnZmMubnNQc3kubGFzdF9lbl9zdWJzaG9ydFtjaG5dW2ldID0gZW5fc3Vic2hvcnRbaSArIDNdID0gcDtcbiAgICAgICAgICAgICAgICAgICAgZW5fc2hvcnRbMSArIGkgLyAzXSArPSBwO1xuICAgICAgICAgICAgICAgICAgICBpZiAocCA+IGVuX3N1YnNob3J0W2kgKyAzIC0gMl0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGFzc2VydChlbl9zdWJzaG9ydFtpICsgMyAtIDJdID4gMCk7XG4gICAgICAgICAgICAgICAgICAgICAgICBwID0gcCAvIGVuX3N1YnNob3J0W2kgKyAzIC0gMl07XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZW5fc3Vic2hvcnRbaSArIDMgLSAyXSA+IHAgKiAxMC4wKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBhc3NlcnQocCA+IDApO1xuICAgICAgICAgICAgICAgICAgICAgICAgcCA9IGVuX3N1YnNob3J0W2kgKyAzIC0gMl0gLyAocCAqIDEwLjApO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHAgPSAwLjA7XG4gICAgICAgICAgICAgICAgICAgIGF0dGFja19pbnRlbnNpdHlbaSArIDNdID0gcDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChnZnAuYW5hbHlzaXMpIHtcbiAgICAgICAgICAgICAgICB2YXIgeCA9IGF0dGFja19pbnRlbnNpdHlbMF07XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IDEyOyBpKyspXG4gICAgICAgICAgICAgICAgICAgIGlmICh4IDwgYXR0YWNrX2ludGVuc2l0eVtpXSlcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSBhdHRhY2tfaW50ZW5zaXR5W2ldO1xuICAgICAgICAgICAgICAgIGdmYy5waW5mby5lcnNbZ3Jfb3V0XVtjaG5dID0gZ2ZjLnBpbmZvLmVyc19zYXZlW2Nobl07XG4gICAgICAgICAgICAgICAgZ2ZjLnBpbmZvLmVyc19zYXZlW2Nobl0gPSB4O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKiBjb21wYXJlIGVuZXJnaWVzIGJldHdlZW4gc3ViLXNob3J0YmxvY2tzICovXG4gICAgICAgICAgICBhdHRhY2tUaHJlc2hvbGQgPSAoY2huID09IDMpID8gZ2ZjLm5zUHN5LmF0dGFja3RocmVfc1xuICAgICAgICAgICAgICAgIDogZ2ZjLm5zUHN5LmF0dGFja3RocmU7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgMTI7IGkrKylcbiAgICAgICAgICAgICAgICBpZiAoMCA9PSBuc19hdHRhY2tzW2kgLyAzXVxuICAgICAgICAgICAgICAgICAgICAmJiBhdHRhY2tfaW50ZW5zaXR5W2ldID4gYXR0YWNrVGhyZXNob2xkKVxuICAgICAgICAgICAgICAgICAgICBuc19hdHRhY2tzW2kgLyAzXSA9IChpICUgMykgKyAxO1xuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogc2hvdWxkIGhhdmUgZW5lcmd5IGNoYW5nZSBiZXR3ZWVuIHNob3J0IGJsb2NrcywgaW4gb3JkZXIgdG8gYXZvaWRcbiAgICAgICAgICAgICAqIHBlcmlvZGljIHNpZ25hbHNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZm9yIChpID0gMTsgaSA8IDQ7IGkrKykge1xuICAgICAgICAgICAgICAgIHZhciByYXRpbztcbiAgICAgICAgICAgICAgICBpZiAoZW5fc2hvcnRbaSAtIDFdID4gZW5fc2hvcnRbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KGVuX3Nob3J0W2ldID4gMCk7XG4gICAgICAgICAgICAgICAgICAgIHJhdGlvID0gZW5fc2hvcnRbaSAtIDFdIC8gZW5fc2hvcnRbaV07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KGVuX3Nob3J0W2kgLSAxXSA+IDApO1xuICAgICAgICAgICAgICAgICAgICByYXRpbyA9IGVuX3Nob3J0W2ldIC8gZW5fc2hvcnRbaSAtIDFdO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAocmF0aW8gPCAxLjcpIHtcbiAgICAgICAgICAgICAgICAgICAgbnNfYXR0YWNrc1tpXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpID09IDEpXG4gICAgICAgICAgICAgICAgICAgICAgICBuc19hdHRhY2tzWzBdID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChuc19hdHRhY2tzWzBdICE9IDAgJiYgZ2ZjLm5zUHN5Lmxhc3RBdHRhY2tzW2Nobl0gIT0gMClcbiAgICAgICAgICAgICAgICBuc19hdHRhY2tzWzBdID0gMDtcblxuICAgICAgICAgICAgaWYgKGdmYy5uc1BzeS5sYXN0QXR0YWNrc1tjaG5dID09IDNcbiAgICAgICAgICAgICAgICB8fCAobnNfYXR0YWNrc1swXSArIG5zX2F0dGFja3NbMV0gKyBuc19hdHRhY2tzWzJdICsgbnNfYXR0YWNrc1szXSkgIT0gMCkge1xuICAgICAgICAgICAgICAgIG5zX3VzZWxvbmdibG9jayA9IDA7XG5cbiAgICAgICAgICAgICAgICBpZiAobnNfYXR0YWNrc1sxXSAhPSAwICYmIG5zX2F0dGFja3NbMF0gIT0gMClcbiAgICAgICAgICAgICAgICAgICAgbnNfYXR0YWNrc1sxXSA9IDA7XG4gICAgICAgICAgICAgICAgaWYgKG5zX2F0dGFja3NbMl0gIT0gMCAmJiBuc19hdHRhY2tzWzFdICE9IDApXG4gICAgICAgICAgICAgICAgICAgIG5zX2F0dGFja3NbMl0gPSAwO1xuICAgICAgICAgICAgICAgIGlmIChuc19hdHRhY2tzWzNdICE9IDAgJiYgbnNfYXR0YWNrc1syXSAhPSAwKVxuICAgICAgICAgICAgICAgICAgICBuc19hdHRhY2tzWzNdID0gMDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGNobiA8IDIpIHtcbiAgICAgICAgICAgICAgICB1c2Vsb25nYmxvY2tbY2huXSA9IG5zX3VzZWxvbmdibG9jaztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKG5zX3VzZWxvbmdibG9jayA9PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHVzZWxvbmdibG9ja1swXSA9IHVzZWxvbmdibG9ja1sxXSA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogdGhlcmUgaXMgYSBvbmUgZ3JhbnVsZSBkZWxheS4gQ29weSBtYXNraW5ncyBjb21wdXRlZCBsYXN0IGNhbGxcbiAgICAgICAgICAgICAqIGludG8gbWFza2luZ19yYXRpbyB0byByZXR1cm4gdG8gY2FsbGluZyBwcm9ncmFtLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBlbmVyZ3lbY2huXSA9IGdmYy50b3RfZW5lcltjaG5dO1xuXG4gICAgICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgICAgICAgKiBjb21wdXRlIEZGVHNcbiAgICAgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgICAgICB3c2FtcF9zID0gd3NhbXBfUztcbiAgICAgICAgICAgIHdzYW1wX2wgPSB3c2FtcF9MO1xuICAgICAgICAgICAgY29tcHV0ZV9mZnRzKGdmcCwgZmZ0ZW5lcmd5LCBmZnRlbmVyZ3lfcywgd3NhbXBfbCwgKGNobiAmIDEpLFxuICAgICAgICAgICAgICAgIHdzYW1wX3MsIChjaG4gJiAxKSwgZ3Jfb3V0LCBjaG4sIGJ1ZmZlciwgYnVmUG9zKTtcblxuICAgICAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICAgICAgICogQ2FsY3VsYXRlIHRoZSBlbmVyZ3kgYW5kIHRoZSB0b25hbGl0eSBvZiBlYWNoIHBhcnRpdGlvbi5cbiAgICAgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgICAgICBjYWxjX2VuZXJneShnZmMsIGZmdGVuZXJneSwgZWJfbCwgbWF4LCBhdmcpO1xuICAgICAgICAgICAgY2FsY19tYXNrX2luZGV4X2woZ2ZjLCBtYXgsIGF2ZywgbWFza19pZHhfbCk7XG4gICAgICAgICAgICAvKiBjb21wdXRlIG1hc2tpbmcgdGhyZXNob2xkcyBmb3Igc2hvcnQgYmxvY2tzICovXG4gICAgICAgICAgICBmb3IgKHNibG9jayA9IDA7IHNibG9jayA8IDM7IHNibG9jaysrKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVubiwgdGhtbTtcbiAgICAgICAgICAgICAgICBjb21wdXRlX21hc2tpbmdfcyhnZnAsIGZmdGVuZXJneV9zLCBlYl9zLCB0aHIsIGNobiwgc2Jsb2NrKTtcbiAgICAgICAgICAgICAgICBjb252ZXJ0X3BhcnRpdGlvbjJzY2FsZWZhY19zKGdmYywgZWJfcywgdGhyLCBjaG4sIHNibG9jayk7XG4gICAgICAgICAgICAgICAgLyoqKiogc2hvcnQgYmxvY2sgcHJlLWVjaG8gY29udHJvbCAqKioqL1xuICAgICAgICAgICAgICAgIGZvciAoc2IgPSAwOyBzYiA8IEVuY29kZXIuU0JNQVhfczsgc2IrKykge1xuICAgICAgICAgICAgICAgICAgICB0aG1tID0gZ2ZjLnRobVtjaG5dLnNbc2JdW3NibG9ja107XG5cbiAgICAgICAgICAgICAgICAgICAgdGhtbSAqPSBOU19QUkVFQ0hPX0FUVDA7XG4gICAgICAgICAgICAgICAgICAgIGlmIChuc19hdHRhY2tzW3NibG9ja10gPj0gMiB8fCBuc19hdHRhY2tzW3NibG9jayArIDFdID09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpZHggPSAoc2Jsb2NrICE9IDApID8gc2Jsb2NrIC0gMSA6IDI7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgcCA9IE5TX0lOVEVSUChnZmMudGhtW2Nobl0uc1tzYl1baWR4XSwgdGhtbSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBOU19QUkVFQ0hPX0FUVDEgKiBwY2ZhY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhtbSA9IE1hdGgubWluKHRobW0sIHApO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKG5zX2F0dGFja3Nbc2Jsb2NrXSA9PSAxKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaWR4ID0gKHNibG9jayAhPSAwKSA/IHNibG9jayAtIDEgOiAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHAgPSBOU19JTlRFUlAoZ2ZjLnRobVtjaG5dLnNbc2JdW2lkeF0sIHRobW0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTlNfUFJFRUNIT19BVFQyICogcGNmYWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRobW0gPSBNYXRoLm1pbih0aG1tLCBwKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoc2Jsb2NrICE9IDAgJiYgbnNfYXR0YWNrc1tzYmxvY2sgLSAxXSA9PSAzKVxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgKHNibG9jayA9PSAwICYmIGdmYy5uc1BzeS5sYXN0QXR0YWNrc1tjaG5dID09IDMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgaWR4ID0gKHNibG9jayAhPSAyKSA/IHNibG9jayArIDEgOiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHAgPSBOU19JTlRFUlAoZ2ZjLnRobVtjaG5dLnNbc2JdW2lkeF0sIHRobW0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgTlNfUFJFRUNIT19BVFQyICogcGNmYWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRobW0gPSBNYXRoLm1pbih0aG1tLCBwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8qIHB1bHNlIGxpa2Ugc2lnbmFsIGRldGVjdGlvbiBmb3IgZmF0Ym95LndhdiBhbmQgc28gb24gKi9cbiAgICAgICAgICAgICAgICAgICAgZW5uID0gZW5fc3Vic2hvcnRbc2Jsb2NrICogMyArIDNdXG4gICAgICAgICAgICAgICAgICAgICAgICArIGVuX3N1YnNob3J0W3NibG9jayAqIDMgKyA0XVxuICAgICAgICAgICAgICAgICAgICAgICAgKyBlbl9zdWJzaG9ydFtzYmxvY2sgKiAzICsgNV07XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbl9zdWJzaG9ydFtzYmxvY2sgKiAzICsgNV0gKiA2IDwgZW5uKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aG1tICo9IDAuNTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChlbl9zdWJzaG9ydFtzYmxvY2sgKiAzICsgNF0gKiA2IDwgZW5uKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRobW0gKj0gMC41O1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgZ2ZjLnRobVtjaG5dLnNbc2JdW3NibG9ja10gPSB0aG1tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGdmYy5uc1BzeS5sYXN0QXR0YWNrc1tjaG5dID0gbnNfYXR0YWNrc1syXTtcblxuICAgICAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICAgICAgICogY29udm9sdmUgdGhlIHBhcnRpdGlvbmVkIGVuZXJneSBhbmQgdW5wcmVkaWN0YWJpbGl0eSB3aXRoIHRoZVxuICAgICAgICAgICAgICogc3ByZWFkaW5nIGZ1bmN0aW9uLCBzM19sW2JdW2tdXG4gICAgICAgICAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgICAgICBrID0gMDtcbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBmb3IgKGIgPSAwOyBiIDwgZ2ZjLm5wYXJ0X2w7IGIrKykge1xuICAgICAgICAgICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgICAgICAgKiBjb252b2x2ZSB0aGUgcGFydGl0aW9uZWQgZW5lcmd5IHdpdGggdGhlIHNwcmVhZGluZ1xuICAgICAgICAgICAgICAgICAgICAgKiBmdW5jdGlvblxuICAgICAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICAgICAgdmFyIGtrID0gZ2ZjLnMzaW5kW2JdWzBdO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZWIyID0gZWJfbFtra10gKiB0YWJbbWFza19pZHhfbFtra11dO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZWNiID0gZ2ZjLnMzX2xsW2srK10gKiBlYjI7XG4gICAgICAgICAgICAgICAgICAgIHdoaWxlICgrK2trIDw9IGdmYy5zM2luZFtiXVsxXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZWIyID0gZWJfbFtra10gKiB0YWJbbWFza19pZHhfbFtra11dO1xuICAgICAgICAgICAgICAgICAgICAgICAgZWNiID0gbWFza19hZGQoZWNiLCBnZmMuczNfbGxbaysrXSAqIGViMiwga2ssIGtrIC0gYixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZmMsIDApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGVjYiAqPSAwLjE1ODQ4OTMxOTI0NjExMTtcbiAgICAgICAgICAgICAgICAgICAgLyogcG93KDEwLC0wLjgpICovXG5cbiAgICAgICAgICAgICAgICAgICAgLyoqKiogbG9uZyBibG9jayBwcmUtZWNobyBjb250cm9sICoqKiovXG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiA8UFJFPlxuICAgICAgICAgICAgICAgICAgICAgKiBkb250IHVzZSBsb25nIGJsb2NrIHByZS1lY2hvIGNvbnRyb2wgaWYgcHJldmlvdXMgZ3JhbnVsZSB3YXNcbiAgICAgICAgICAgICAgICAgICAgICogYSBzaG9ydCBibG9jay4gIFRoaXMgaXMgdG8gYXZvaWQgdGhlIHNpdHVhdGlvbjpcbiAgICAgICAgICAgICAgICAgICAgICogZnJhbWUwOiAgcXVpZXQgKHZlcnkgbG93IG1hc2tpbmcpXG4gICAgICAgICAgICAgICAgICAgICAqIGZyYW1lMTogIHN1cmdlICAodHJpZ2dlcnMgc2hvcnQgYmxvY2tzKVxuICAgICAgICAgICAgICAgICAgICAgKiBmcmFtZTI6ICByZWd1bGFyIGZyYW1lLiAgbG9va3MgbGlrZSBwcmUtZWNobyB3aGVuIGNvbXBhcmVkIHRvXG4gICAgICAgICAgICAgICAgICAgICAqICAgICAgICAgIGZyYW1lMCwgYnV0IGFsbCBwcmUtZWNobyB3YXMgaW4gZnJhbWUxLlxuICAgICAgICAgICAgICAgICAgICAgKiA8L1BSRT5cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICAgICAqIGNobj0wLDEgTCBhbmQgUiBjaGFubmVsc1xuICAgICAgICAgICAgICAgICAgICAgKlxuICAgICAgICAgICAgICAgICAgICAgKiBjaG49MiwzIFMgYW5kIE0gY2hhbm5lbHMuXG4gICAgICAgICAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAgICAgICAgIGlmIChnZmMuYmxvY2t0eXBlX29sZFtjaG4gJiAxXSA9PSBFbmNvZGVyLlNIT1JUX1RZUEUpXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJbYl0gPSBlY2I7XG4gICAgICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocltiXSA9IE5TX0lOVEVSUChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBNYXRoLm1pbihlY2IsIE1hdGgubWluKHJwZWxldlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIGdmYy5uYl8xW2Nobl1bYl0sIHJwZWxldjJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBnZmMubmJfMltjaG5dW2JdKSksIGVjYiwgcGNmYWN0KTtcblxuICAgICAgICAgICAgICAgICAgICBnZmMubmJfMltjaG5dW2JdID0gZ2ZjLm5iXzFbY2huXVtiXTtcbiAgICAgICAgICAgICAgICAgICAgZ2ZjLm5iXzFbY2huXVtiXSA9IGVjYjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKDsgYiA8PSBFbmNvZGVyLkNCQU5EUzsgKytiKSB7XG4gICAgICAgICAgICAgICAgZWJfbFtiXSA9IDA7XG4gICAgICAgICAgICAgICAgdGhyW2JdID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8qIGNvbXB1dGUgbWFza2luZyB0aHJlc2hvbGRzIGZvciBsb25nIGJsb2NrcyAqL1xuICAgICAgICAgICAgY29udmVydF9wYXJ0aXRpb24yc2NhbGVmYWNfbChnZmMsIGViX2wsIHRociwgY2huKTtcbiAgICAgICAgfVxuICAgICAgICAvKiBlbmQgbG9vcCBvdmVyIGNobiAqL1xuXG4gICAgICAgIGlmIChnZnAubW9kZSA9PSBNUEVHTW9kZS5TVEVSRU8gfHwgZ2ZwLm1vZGUgPT0gTVBFR01vZGUuSk9JTlRfU1RFUkVPKSB7XG4gICAgICAgICAgICBpZiAoZ2ZwLmludGVyQ2hSYXRpbyA+IDAuMCkge1xuICAgICAgICAgICAgICAgIGNhbGNfaW50ZXJjaGFubmVsX21hc2tpbmcoZ2ZwLCBnZnAuaW50ZXJDaFJhdGlvKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChnZnAubW9kZSA9PSBNUEVHTW9kZS5KT0lOVF9TVEVSRU8pIHtcbiAgICAgICAgICAgIHZhciBtc2ZpeDtcbiAgICAgICAgICAgIG1zZml4MShnZmMpO1xuICAgICAgICAgICAgbXNmaXggPSBnZnAubXNmaXg7XG4gICAgICAgICAgICBpZiAoTWF0aC5hYnMobXNmaXgpID4gMC4wKVxuICAgICAgICAgICAgICAgIG5zX21zZml4KGdmYywgbXNmaXgsIGdmcC5BVEhsb3dlciAqIGdmYy5BVEguYWRqdXN0KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgICAgICogZGV0ZXJtaW5lIGZpbmFsIGJsb2NrIHR5cGVcbiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbiAgICAgICAgYmxvY2tfdHlwZV9zZXQoZ2ZwLCB1c2Vsb25nYmxvY2ssIGJsb2NrdHlwZV9kLCBibG9ja3R5cGUpO1xuXG4gICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgICAgICogY29tcHV0ZSB0aGUgdmFsdWUgb2YgUEUgdG8gcmV0dXJuIC4uLiBubyBkZWxheSBhbmQgYWR2YW5jZVxuICAgICAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuICAgICAgICBmb3IgKGNobiA9IDA7IGNobiA8IG51bWNobjsgY2huKyspIHtcbiAgICAgICAgICAgIHZhciBwcGU7XG4gICAgICAgICAgICB2YXIgcHBlUG9zID0gMDtcbiAgICAgICAgICAgIHZhciB0eXBlO1xuICAgICAgICAgICAgdmFyIG1yO1xuXG4gICAgICAgICAgICBpZiAoY2huID4gMSkge1xuICAgICAgICAgICAgICAgIHBwZSA9IHBlcmNlcF9NU19lbnRyb3B5O1xuICAgICAgICAgICAgICAgIHBwZVBvcyA9IC0yO1xuICAgICAgICAgICAgICAgIHR5cGUgPSBFbmNvZGVyLk5PUk1fVFlQRTtcbiAgICAgICAgICAgICAgICBpZiAoYmxvY2t0eXBlX2RbMF0gPT0gRW5jb2Rlci5TSE9SVF9UWVBFXG4gICAgICAgICAgICAgICAgICAgIHx8IGJsb2NrdHlwZV9kWzFdID09IEVuY29kZXIuU0hPUlRfVFlQRSlcbiAgICAgICAgICAgICAgICAgICAgdHlwZSA9IEVuY29kZXIuU0hPUlRfVFlQRTtcbiAgICAgICAgICAgICAgICBtciA9IG1hc2tpbmdfTVNfcmF0aW9bZ3Jfb3V0XVtjaG4gLSAyXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcHBlID0gcGVyY2VwX2VudHJvcHk7XG4gICAgICAgICAgICAgICAgcHBlUG9zID0gMDtcbiAgICAgICAgICAgICAgICB0eXBlID0gYmxvY2t0eXBlX2RbY2huXTtcbiAgICAgICAgICAgICAgICBtciA9IG1hc2tpbmdfcmF0aW9bZ3Jfb3V0XVtjaG5dO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodHlwZSA9PSBFbmNvZGVyLlNIT1JUX1RZUEUpXG4gICAgICAgICAgICAgICAgcHBlW3BwZVBvcyArIGNobl0gPSBwZWNhbGNfcyhtciwgZ2ZjLm1hc2tpbmdfbG93ZXIpO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIHBwZVtwcGVQb3MgKyBjaG5dID0gcGVjYWxjX2wobXIsIGdmYy5tYXNraW5nX2xvd2VyKTtcblxuICAgICAgICAgICAgaWYgKGdmcC5hbmFseXNpcylcbiAgICAgICAgICAgICAgICBnZmMucGluZm8ucGVbZ3Jfb3V0XVtjaG5dID0gcHBlW3BwZVBvcyArIGNobl07XG5cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2YnJwc3lfY29tcHV0ZV9mZnRfbChnZnAsIGJ1ZmZlciwgYnVmUG9zLCBjaG4sIGdyX291dCwgZmZ0ZW5lcmd5LCB3c2FtcF9sLCB3c2FtcF9sUG9zKSB7XG4gICAgICAgIHZhciBnZmMgPSBnZnAuaW50ZXJuYWxfZmxhZ3M7XG4gICAgICAgIGlmIChjaG4gPCAyKSB7XG4gICAgICAgICAgICBmZnQuZmZ0X2xvbmcoZ2ZjLCB3c2FtcF9sW3dzYW1wX2xQb3NdLCBjaG4sIGJ1ZmZlciwgYnVmUG9zKTtcbiAgICAgICAgfSBlbHNlIGlmIChjaG4gPT0gMikge1xuICAgICAgICAgICAgLyogRkZUIGRhdGEgZm9yIG1pZCBhbmQgc2lkZSBjaGFubmVsIGlzIGRlcml2ZWQgZnJvbSBMICYgUiAqL1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IEVuY29kZXIuQkxLU0laRSAtIDE7IGogPj0gMDsgLS1qKSB7XG4gICAgICAgICAgICAgICAgdmFyIGwgPSB3c2FtcF9sW3dzYW1wX2xQb3MgKyAwXVtqXTtcbiAgICAgICAgICAgICAgICB2YXIgciA9IHdzYW1wX2xbd3NhbXBfbFBvcyArIDFdW2pdO1xuICAgICAgICAgICAgICAgIHdzYW1wX2xbd3NhbXBfbFBvcyArIDBdW2pdID0gKGwgKyByKSAqIFV0aWwuU1FSVDIgKiAwLjU7XG4gICAgICAgICAgICAgICAgd3NhbXBfbFt3c2FtcF9sUG9zICsgMV1bal0gPSAobCAtIHIpICogVXRpbC5TUVJUMiAqIDAuNTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgICAgICogY29tcHV0ZSBlbmVyZ2llc1xuICAgICAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuICAgICAgICBmZnRlbmVyZ3lbMF0gPSBOT05fTElORUFSX1NDQUxFX0VORVJHWSh3c2FtcF9sW3dzYW1wX2xQb3MgKyAwXVswXSk7XG4gICAgICAgIGZmdGVuZXJneVswXSAqPSBmZnRlbmVyZ3lbMF07XG5cbiAgICAgICAgZm9yICh2YXIgaiA9IEVuY29kZXIuQkxLU0laRSAvIDIgLSAxOyBqID49IDA7IC0taikge1xuICAgICAgICAgICAgdmFyIHJlID0gd3NhbXBfbFt3c2FtcF9sUG9zICsgMF1bRW5jb2Rlci5CTEtTSVpFIC8gMiAtIGpdO1xuICAgICAgICAgICAgdmFyIGltID0gd3NhbXBfbFt3c2FtcF9sUG9zICsgMF1bRW5jb2Rlci5CTEtTSVpFIC8gMiArIGpdO1xuICAgICAgICAgICAgZmZ0ZW5lcmd5W0VuY29kZXIuQkxLU0laRSAvIDIgLSBqXSA9IE5PTl9MSU5FQVJfU0NBTEVfRU5FUkdZKChyZVxuICAgICAgICAgICAgICAgICogcmUgKyBpbSAqIGltKSAqIDAuNSk7XG4gICAgICAgIH1cbiAgICAgICAgLyogdG90YWwgZW5lcmd5ICovXG4gICAgICAgIHtcbiAgICAgICAgICAgIHZhciB0b3RhbGVuZXJneSA9IDAuMDtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAxMTsgaiA8IEVuY29kZXIuSEJMS1NJWkU7IGorKylcbiAgICAgICAgICAgICAgICB0b3RhbGVuZXJneSArPSBmZnRlbmVyZ3lbal07XG5cbiAgICAgICAgICAgIGdmYy50b3RfZW5lcltjaG5dID0gdG90YWxlbmVyZ3k7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2ZwLmFuYWx5c2lzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IEVuY29kZXIuSEJMS1NJWkU7IGorKykge1xuICAgICAgICAgICAgICAgIGdmYy5waW5mby5lbmVyZ3lbZ3Jfb3V0XVtjaG5dW2pdID0gZ2ZjLnBpbmZvLmVuZXJneV9zYXZlW2Nobl1bal07XG4gICAgICAgICAgICAgICAgZ2ZjLnBpbmZvLmVuZXJneV9zYXZlW2Nobl1bal0gPSBmZnRlbmVyZ3lbal07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBnZmMucGluZm8ucGVbZ3Jfb3V0XVtjaG5dID0gZ2ZjLnBlW2Nobl07XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2YnJwc3lfY29tcHV0ZV9mZnRfcyhnZnAsIGJ1ZmZlciwgYnVmUG9zLCBjaG4sIHNibG9jaywgZmZ0ZW5lcmd5X3MsIHdzYW1wX3MsIHdzYW1wX3NQb3MpIHtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcblxuICAgICAgICBpZiAoc2Jsb2NrID09IDAgJiYgY2huIDwgMikge1xuICAgICAgICAgICAgZmZ0LmZmdF9zaG9ydChnZmMsIHdzYW1wX3Nbd3NhbXBfc1Bvc10sIGNobiwgYnVmZmVyLCBidWZQb3MpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChjaG4gPT0gMikge1xuICAgICAgICAgICAgLyogRkZUIGRhdGEgZm9yIG1pZCBhbmQgc2lkZSBjaGFubmVsIGlzIGRlcml2ZWQgZnJvbSBMICYgUiAqL1xuICAgICAgICAgICAgZm9yICh2YXIgaiA9IEVuY29kZXIuQkxLU0laRV9zIC0gMTsgaiA+PSAwOyAtLWopIHtcbiAgICAgICAgICAgICAgICB2YXIgbCA9IHdzYW1wX3Nbd3NhbXBfc1BvcyArIDBdW3NibG9ja11bal07XG4gICAgICAgICAgICAgICAgdmFyIHIgPSB3c2FtcF9zW3dzYW1wX3NQb3MgKyAxXVtzYmxvY2tdW2pdO1xuICAgICAgICAgICAgICAgIHdzYW1wX3Nbd3NhbXBfc1BvcyArIDBdW3NibG9ja11bal0gPSAobCArIHIpICogVXRpbC5TUVJUMiAqIDAuNTtcbiAgICAgICAgICAgICAgICB3c2FtcF9zW3dzYW1wX3NQb3MgKyAxXVtzYmxvY2tdW2pdID0gKGwgLSByKSAqIFV0aWwuU1FSVDIgKiAwLjU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgICAqIGNvbXB1dGUgZW5lcmdpZXNcbiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbiAgICAgICAgZmZ0ZW5lcmd5X3Nbc2Jsb2NrXVswXSA9IHdzYW1wX3Nbd3NhbXBfc1BvcyArIDBdW3NibG9ja11bMF07XG4gICAgICAgIGZmdGVuZXJneV9zW3NibG9ja11bMF0gKj0gZmZ0ZW5lcmd5X3Nbc2Jsb2NrXVswXTtcbiAgICAgICAgZm9yICh2YXIgaiA9IEVuY29kZXIuQkxLU0laRV9zIC8gMiAtIDE7IGogPj0gMDsgLS1qKSB7XG4gICAgICAgICAgICB2YXIgcmUgPSB3c2FtcF9zW3dzYW1wX3NQb3MgKyAwXVtzYmxvY2tdW0VuY29kZXIuQkxLU0laRV9zIC8gMiAtIGpdO1xuICAgICAgICAgICAgdmFyIGltID0gd3NhbXBfc1t3c2FtcF9zUG9zICsgMF1bc2Jsb2NrXVtFbmNvZGVyLkJMS1NJWkVfcyAvIDIgKyBqXTtcbiAgICAgICAgICAgIGZmdGVuZXJneV9zW3NibG9ja11bRW5jb2Rlci5CTEtTSVpFX3MgLyAyIC0gal0gPSBOT05fTElORUFSX1NDQUxFX0VORVJHWSgocmVcbiAgICAgICAgICAgICAgICAqIHJlICsgaW0gKiBpbSkgKiAwLjUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogY29tcHV0ZSBsb3VkbmVzcyBhcHByb3hpbWF0aW9uICh1c2VkIGZvciBBVEggYXV0by1sZXZlbCBhZGp1c3RtZW50KVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHZicnBzeV9jb21wdXRlX2xvdWRuZXNzX2FwcHJveGltYXRpb25fbChnZnAsIGdyX291dCwgY2huLCBmZnRlbmVyZ3kpIHtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcbiAgICAgICAgaWYgKGdmcC5hdGhhYV9sb3VkYXBwcm94ID09IDIgJiYgY2huIDwgMikge1xuICAgICAgICAgICAgLy8gbm8gbG91ZG5lc3MgZm9yIG1pZC9zaWRlIGNoXG4gICAgICAgICAgICBnZmMubG91ZG5lc3Nfc3FbZ3Jfb3V0XVtjaG5dID0gZ2ZjLmxvdWRuZXNzX3NxX3NhdmVbY2huXTtcbiAgICAgICAgICAgIGdmYy5sb3VkbmVzc19zcV9zYXZlW2Nobl0gPSBwc3ljaG9fbG91ZG5lc3NfYXBwcm94KGZmdGVuZXJneSwgZ2ZjKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHZhciBmaXJjb2VmXyA9IFstOC42NTE2M2UtMTggKiAyLFxuICAgICAgICAtMC4wMDg1MTU4NiAqIDIsIC02Ljc0NzY0ZS0xOCAqIDIsIDAuMDIwOTAzNiAqIDIsXG4gICAgICAgIC0zLjM2NjM5ZS0xNyAqIDIsIC0wLjA0MzgxNjIgKiAyLCAtMS41NDE3NWUtMTcgKiAyLFxuICAgICAgICAwLjA5MzE3MzggKiAyLCAtNS41MjIxMmUtMTcgKiAyLCAtMC4zMTM4MTkgKiAyXTtcblxuICAgIC8qKlxuICAgICAqIEFwcGx5IEhQRiBvZiBmcy80IHRvIHRoZSBpbnB1dCBzaWduYWwuIFRoaXMgaXMgdXNlZCBmb3IgYXR0YWNrIGRldGVjdGlvblxuICAgICAqIC8gaGFuZGxpbmcuXG4gICAgICovXG4gICAgZnVuY3Rpb24gdmJycHN5X2F0dGFja19kZXRlY3Rpb24oZ2ZwLCBidWZmZXIsIGJ1ZlBvcywgZ3Jfb3V0LCBtYXNraW5nX3JhdGlvLCBtYXNraW5nX01TX3JhdGlvLCBlbmVyZ3ksIHN1Yl9zaG9ydF9mYWN0b3IsIG5zX2F0dGFja3MsIHVzZWxvbmdibG9jaykge1xuICAgICAgICB2YXIgbnNfaHBmc21wbCA9IG5ld19mbG9hdF9uKFsyLCA1NzZdKTtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcbiAgICAgICAgdmFyIG5fY2huX291dCA9IGdmYy5jaGFubmVsc19vdXQ7XG4gICAgICAgIC8qIGNobj0yIGFuZCAzID0gTWlkIGFuZCBTaWRlIGNoYW5uZWxzICovXG4gICAgICAgIHZhciBuX2Nobl9wc3kgPSAoZ2ZwLm1vZGUgPT0gTVBFR01vZGUuSk9JTlRfU1RFUkVPKSA/IDQgOiBuX2Nobl9vdXQ7XG4gICAgICAgIC8qIERvbid0IGNvcHkgdGhlIGlucHV0IGJ1ZmZlciBpbnRvIGEgdGVtcG9yYXJ5IGJ1ZmZlciAqL1xuICAgICAgICAvKiB1bnJvbGwgdGhlIGxvb3AgMiB0aW1lcyAqL1xuICAgICAgICBmb3IgKHZhciBjaG4gPSAwOyBjaG4gPCBuX2Nobl9vdXQ7IGNobisrKSB7XG4gICAgICAgICAgICAvKiBhcHBseSBoaWdoIHBhc3MgZmlsdGVyIG9mIGZzLzQgKi9cbiAgICAgICAgICAgIGZpcmJ1ZiA9IGJ1ZmZlcltjaG5dO1xuICAgICAgICAgICAgdmFyIGZpcmJ1ZlBvcyA9IGJ1ZlBvcyArIDU3NiAtIDM1MCAtIE5TRklSTEVOICsgMTkyO1xuICAgICAgICAgICAgYXNzZXJ0KGZpcmNvZWZfLmxlbmd0aCA9PSAoKE5TRklSTEVOIC0gMSkgLyAyKSk7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDU3NjsgaSsrKSB7XG4gICAgICAgICAgICAgICAgdmFyIHN1bTEsIHN1bTI7XG4gICAgICAgICAgICAgICAgc3VtMSA9IGZpcmJ1ZltmaXJidWZQb3MgKyBpICsgMTBdO1xuICAgICAgICAgICAgICAgIHN1bTIgPSAwLjA7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaiA9IDA7IGogPCAoKE5TRklSTEVOIC0gMSkgLyAyKSAtIDE7IGogKz0gMikge1xuICAgICAgICAgICAgICAgICAgICBzdW0xICs9IGZpcmNvZWZfW2pdXG4gICAgICAgICAgICAgICAgICAgICAgICAqIChmaXJidWZbZmlyYnVmUG9zICsgaSArIGpdICsgZmlyYnVmW2ZpcmJ1ZlBvcyArIGlcbiAgICAgICAgICAgICAgICAgICAgICAgICsgTlNGSVJMRU4gLSBqXSk7XG4gICAgICAgICAgICAgICAgICAgIHN1bTIgKz0gZmlyY29lZl9baiArIDFdXG4gICAgICAgICAgICAgICAgICAgICAgICAqIChmaXJidWZbZmlyYnVmUG9zICsgaSArIGogKyAxXSArIGZpcmJ1ZltmaXJidWZQb3NcbiAgICAgICAgICAgICAgICAgICAgICAgICsgaSArIE5TRklSTEVOIC0gaiAtIDFdKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbnNfaHBmc21wbFtjaG5dW2ldID0gc3VtMSArIHN1bTI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBtYXNraW5nX3JhdGlvW2dyX291dF1bY2huXS5lbi5hc3NpZ24oZ2ZjLmVuW2Nobl0pO1xuICAgICAgICAgICAgbWFza2luZ19yYXRpb1tncl9vdXRdW2Nobl0udGhtLmFzc2lnbihnZmMudGhtW2Nobl0pO1xuICAgICAgICAgICAgaWYgKG5fY2huX3BzeSA+IDIpIHtcbiAgICAgICAgICAgICAgICAvKiBNUyBtYXNraW5ncyAqL1xuICAgICAgICAgICAgICAgIC8qIHBlcmNlcF9NU19lbnRyb3B5IFtjaG4tMl0gPSBnZmMgLiBwZSBbY2huXTsgKi9cbiAgICAgICAgICAgICAgICBtYXNraW5nX01TX3JhdGlvW2dyX291dF1bY2huXS5lbi5hc3NpZ24oZ2ZjLmVuW2NobiArIDJdKTtcbiAgICAgICAgICAgICAgICBtYXNraW5nX01TX3JhdGlvW2dyX291dF1bY2huXS50aG0uYXNzaWduKGdmYy50aG1bY2huICsgMl0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGZvciAodmFyIGNobiA9IDA7IGNobiA8IG5fY2huX3BzeTsgY2huKyspIHtcbiAgICAgICAgICAgIHZhciBhdHRhY2tfaW50ZW5zaXR5ID0gbmV3X2Zsb2F0KDEyKTtcbiAgICAgICAgICAgIHZhciBlbl9zdWJzaG9ydCA9IG5ld19mbG9hdCgxMik7XG4gICAgICAgICAgICB2YXIgZW5fc2hvcnQgPSBbMCwgMCwgMCwgMF07XG4gICAgICAgICAgICB2YXIgcGYgPSBuc19ocGZzbXBsW2NobiAmIDFdO1xuICAgICAgICAgICAgdmFyIHBmUG9zID0gMDtcbiAgICAgICAgICAgIHZhciBhdHRhY2tUaHJlc2hvbGQgPSAoY2huID09IDMpID8gZ2ZjLm5zUHN5LmF0dGFja3RocmVfc1xuICAgICAgICAgICAgICAgIDogZ2ZjLm5zUHN5LmF0dGFja3RocmU7XG4gICAgICAgICAgICB2YXIgbnNfdXNlbG9uZ2Jsb2NrID0gMTtcblxuICAgICAgICAgICAgaWYgKGNobiA9PSAyKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDAsIGogPSA1NzY7IGogPiAwOyArK2ksIC0taikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbCA9IG5zX2hwZnNtcGxbMF1baV07XG4gICAgICAgICAgICAgICAgICAgIHZhciByID0gbnNfaHBmc21wbFsxXVtpXTtcbiAgICAgICAgICAgICAgICAgICAgbnNfaHBmc21wbFswXVtpXSA9IGwgKyByO1xuICAgICAgICAgICAgICAgICAgICBuc19ocGZzbXBsWzFdW2ldID0gbCAtIHI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICAgICAgICogZGV0ZXJtaW5lIHRoZSBibG9jayB0eXBlICh3aW5kb3cgdHlwZSlcbiAgICAgICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgICAgICAvKiBjYWxjdWxhdGUgZW5lcmdpZXMgb2YgZWFjaCBzdWItc2hvcnRibG9ja3MgKi9cbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgMzsgaSsrKSB7XG4gICAgICAgICAgICAgICAgZW5fc3Vic2hvcnRbaV0gPSBnZmMubnNQc3kubGFzdF9lbl9zdWJzaG9ydFtjaG5dW2kgKyA2XTtcbiAgICAgICAgICAgICAgICBhc3NlcnQoZ2ZjLm5zUHN5Lmxhc3RfZW5fc3Vic2hvcnRbY2huXVtpICsgNF0gPiAwKTtcbiAgICAgICAgICAgICAgICBhdHRhY2tfaW50ZW5zaXR5W2ldID0gZW5fc3Vic2hvcnRbaV1cbiAgICAgICAgICAgICAgICAgICAgLyBnZmMubnNQc3kubGFzdF9lbl9zdWJzaG9ydFtjaG5dW2kgKyA0XTtcbiAgICAgICAgICAgICAgICBlbl9zaG9ydFswXSArPSBlbl9zdWJzaG9ydFtpXTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCA5OyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgcGZlID0gcGZQb3MgKyA1NzYgLyA5O1xuICAgICAgICAgICAgICAgIHZhciBwID0gMS47XG4gICAgICAgICAgICAgICAgZm9yICg7IHBmUG9zIDwgcGZlOyBwZlBvcysrKVxuICAgICAgICAgICAgICAgICAgICBpZiAocCA8IE1hdGguYWJzKHBmW3BmUG9zXSkpXG4gICAgICAgICAgICAgICAgICAgICAgICBwID0gTWF0aC5hYnMocGZbcGZQb3NdKTtcblxuICAgICAgICAgICAgICAgIGdmYy5uc1BzeS5sYXN0X2VuX3N1YnNob3J0W2Nobl1baV0gPSBlbl9zdWJzaG9ydFtpICsgM10gPSBwO1xuICAgICAgICAgICAgICAgIGVuX3Nob3J0WzEgKyBpIC8gM10gKz0gcDtcbiAgICAgICAgICAgICAgICBpZiAocCA+IGVuX3N1YnNob3J0W2kgKyAzIC0gMl0pIHtcbiAgICAgICAgICAgICAgICAgICAgYXNzZXJ0KGVuX3N1YnNob3J0W2kgKyAzIC0gMl0gPiAwKTtcbiAgICAgICAgICAgICAgICAgICAgcCA9IHAgLyBlbl9zdWJzaG9ydFtpICsgMyAtIDJdO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoZW5fc3Vic2hvcnRbaSArIDMgLSAyXSA+IHAgKiAxMC4wKSB7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydChwID4gMCk7XG4gICAgICAgICAgICAgICAgICAgIHAgPSBlbl9zdWJzaG9ydFtpICsgMyAtIDJdIC8gKHAgKiAxMC4wKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwID0gMC4wO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBhdHRhY2tfaW50ZW5zaXR5W2kgKyAzXSA9IHA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvKiBwdWxzZSBsaWtlIHNpZ25hbCBkZXRlY3Rpb24gZm9yIGZhdGJveS53YXYgYW5kIHNvIG9uICovXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDM7ICsraSkge1xuICAgICAgICAgICAgICAgIHZhciBlbm4gPSBlbl9zdWJzaG9ydFtpICogMyArIDNdXG4gICAgICAgICAgICAgICAgICAgICsgZW5fc3Vic2hvcnRbaSAqIDMgKyA0XSArIGVuX3N1YnNob3J0W2kgKiAzICsgNV07XG4gICAgICAgICAgICAgICAgdmFyIGZhY3RvciA9IDEuO1xuICAgICAgICAgICAgICAgIGlmIChlbl9zdWJzaG9ydFtpICogMyArIDVdICogNiA8IGVubikge1xuICAgICAgICAgICAgICAgICAgICBmYWN0b3IgKj0gMC41O1xuICAgICAgICAgICAgICAgICAgICBpZiAoZW5fc3Vic2hvcnRbaSAqIDMgKyA0XSAqIDYgPCBlbm4pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZhY3RvciAqPSAwLjU7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgc3ViX3Nob3J0X2ZhY3RvcltjaG5dW2ldID0gZmFjdG9yO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZ2ZwLmFuYWx5c2lzKSB7XG4gICAgICAgICAgICAgICAgdmFyIHggPSBhdHRhY2tfaW50ZW5zaXR5WzBdO1xuICAgICAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgMTI7IGkrKykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoeCA8IGF0dGFja19pbnRlbnNpdHlbaV0pIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHggPSBhdHRhY2tfaW50ZW5zaXR5W2ldO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGdmYy5waW5mby5lcnNbZ3Jfb3V0XVtjaG5dID0gZ2ZjLnBpbmZvLmVyc19zYXZlW2Nobl07XG4gICAgICAgICAgICAgICAgZ2ZjLnBpbmZvLmVyc19zYXZlW2Nobl0gPSB4O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvKiBjb21wYXJlIGVuZXJnaWVzIGJldHdlZW4gc3ViLXNob3J0YmxvY2tzICovXG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IDEyOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoMCA9PSBuc19hdHRhY2tzW2Nobl1baSAvIDNdXG4gICAgICAgICAgICAgICAgICAgICYmIGF0dGFja19pbnRlbnNpdHlbaV0gPiBhdHRhY2tUaHJlc2hvbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgbnNfYXR0YWNrc1tjaG5dW2kgLyAzXSA9IChpICUgMykgKyAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIHNob3VsZCBoYXZlIGVuZXJneSBjaGFuZ2UgYmV0d2VlbiBzaG9ydCBibG9ja3MsIGluIG9yZGVyIHRvIGF2b2lkXG4gICAgICAgICAgICAgKiBwZXJpb2RpYyBzaWduYWxzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIC8qIEdvb2Qgc2FtcGxlcyB0byBzaG93IHRoZSBlZmZlY3QgYXJlIFRydW1wZXQgdGVzdCBzb25ncyAqL1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIEdCOiB0dW5lZCAoMSkgdG8gYXZvaWQgdG9vIG1hbnkgc2hvcnQgYmxvY2tzIGZvciB0ZXN0IHNhbXBsZVxuICAgICAgICAgICAgICogVFJVTVBFVFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogUkg6IHR1bmVkICgyKSB0byBsZXQgZW5vdWdoIHNob3J0IGJsb2NrcyB0aHJvdWdoIGZvciB0ZXN0IHNhbXBsZVxuICAgICAgICAgICAgICogRlNPTCBhbmQgU05BUFNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCA0OyBpKyspIHtcbiAgICAgICAgICAgICAgICB2YXIgdSA9IGVuX3Nob3J0W2kgLSAxXTtcbiAgICAgICAgICAgICAgICB2YXIgdiA9IGVuX3Nob3J0W2ldO1xuICAgICAgICAgICAgICAgIHZhciBtID0gTWF0aC5tYXgodSwgdik7XG4gICAgICAgICAgICAgICAgaWYgKG0gPCA0MDAwMCkgeyAvKiAoMikgKi9cbiAgICAgICAgICAgICAgICAgICAgaWYgKHUgPCAxLjcgKiB2ICYmIHYgPCAxLjcgKiB1KSB7IC8qICgxKSAqL1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGkgPT0gMSAmJiBuc19hdHRhY2tzW2Nobl1bMF0gPD0gbnNfYXR0YWNrc1tjaG5dW2ldKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbnNfYXR0YWNrc1tjaG5dWzBdID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIG5zX2F0dGFja3NbY2huXVtpXSA9IDA7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChuc19hdHRhY2tzW2Nobl1bMF0gPD0gZ2ZjLm5zUHN5Lmxhc3RBdHRhY2tzW2Nobl0pIHtcbiAgICAgICAgICAgICAgICBuc19hdHRhY2tzW2Nobl1bMF0gPSAwO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZ2ZjLm5zUHN5Lmxhc3RBdHRhY2tzW2Nobl0gPT0gM1xuICAgICAgICAgICAgICAgIHx8IChuc19hdHRhY2tzW2Nobl1bMF0gKyBuc19hdHRhY2tzW2Nobl1bMV1cbiAgICAgICAgICAgICAgICArIG5zX2F0dGFja3NbY2huXVsyXSArIG5zX2F0dGFja3NbY2huXVszXSkgIT0gMCkge1xuICAgICAgICAgICAgICAgIG5zX3VzZWxvbmdibG9jayA9IDA7XG5cbiAgICAgICAgICAgICAgICBpZiAobnNfYXR0YWNrc1tjaG5dWzFdICE9IDAgJiYgbnNfYXR0YWNrc1tjaG5dWzBdICE9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgbnNfYXR0YWNrc1tjaG5dWzFdID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKG5zX2F0dGFja3NbY2huXVsyXSAhPSAwICYmIG5zX2F0dGFja3NbY2huXVsxXSAhPSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIG5zX2F0dGFja3NbY2huXVsyXSA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChuc19hdHRhY2tzW2Nobl1bM10gIT0gMCAmJiBuc19hdHRhY2tzW2Nobl1bMl0gIT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBuc19hdHRhY2tzW2Nobl1bM10gPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjaG4gPCAyKSB7XG4gICAgICAgICAgICAgICAgdXNlbG9uZ2Jsb2NrW2Nobl0gPSBuc191c2Vsb25nYmxvY2s7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmIChuc191c2Vsb25nYmxvY2sgPT0gMCkge1xuICAgICAgICAgICAgICAgICAgICB1c2Vsb25nYmxvY2tbMF0gPSB1c2Vsb25nYmxvY2tbMV0gPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIHRoZXJlIGlzIGEgb25lIGdyYW51bGUgZGVsYXkuIENvcHkgbWFza2luZ3MgY29tcHV0ZWQgbGFzdCBjYWxsXG4gICAgICAgICAgICAgKiBpbnRvIG1hc2tpbmdfcmF0aW8gdG8gcmV0dXJuIHRvIGNhbGxpbmcgcHJvZ3JhbS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZW5lcmd5W2Nobl0gPSBnZmMudG90X2VuZXJbY2huXTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZicnBzeV9za2lwX21hc2tpbmdfcyhnZmMsIGNobiwgc2Jsb2NrKSB7XG4gICAgICAgIGlmIChzYmxvY2sgPT0gMCkge1xuICAgICAgICAgICAgZm9yICh2YXIgYiA9IDA7IGIgPCBnZmMubnBhcnRfczsgYisrKSB7XG4gICAgICAgICAgICAgICAgZ2ZjLm5iX3MyW2Nobl1bYl0gPSBnZmMubmJfczFbY2huXVtiXTtcbiAgICAgICAgICAgICAgICBnZmMubmJfczFbY2huXVtiXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2YnJwc3lfc2tpcF9tYXNraW5nX2woZ2ZjLCBjaG4pIHtcbiAgICAgICAgZm9yICh2YXIgYiA9IDA7IGIgPCBnZmMubnBhcnRfbDsgYisrKSB7XG4gICAgICAgICAgICBnZmMubmJfMltjaG5dW2JdID0gZ2ZjLm5iXzFbY2huXVtiXTtcbiAgICAgICAgICAgIGdmYy5uYl8xW2Nobl1bYl0gPSAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcHN5dmJyX2NhbGNfbWFza19pbmRleF9zKGdmYywgbWF4LCBhdmcsIG1hc2tfaWR4KSB7XG4gICAgICAgIHZhciBsYXN0X3RhYl9lbnRyeSA9IHRhYi5sZW5ndGggLSAxO1xuICAgICAgICB2YXIgYiA9IDA7XG4gICAgICAgIHZhciBhID0gYXZnW2JdICsgYXZnW2IgKyAxXTtcbiAgICAgICAgYXNzZXJ0KGEgPj0gMCk7XG4gICAgICAgIGlmIChhID4gMC4wKSB7XG4gICAgICAgICAgICB2YXIgbSA9IG1heFtiXTtcbiAgICAgICAgICAgIGlmIChtIDwgbWF4W2IgKyAxXSlcbiAgICAgICAgICAgICAgICBtID0gbWF4W2IgKyAxXTtcbiAgICAgICAgICAgIGFzc2VydCgoZ2ZjLm51bWxpbmVzX3NbYl0gKyBnZmMubnVtbGluZXNfc1tiICsgMV0gLSAxKSA+IDApO1xuICAgICAgICAgICAgYSA9IDIwLjAgKiAobSAqIDIuMCAtIGEpXG4gICAgICAgICAgICAgICAgLyAoYSAqIChnZmMubnVtbGluZXNfc1tiXSArIGdmYy5udW1saW5lc19zW2IgKyAxXSAtIDEpKTtcbiAgICAgICAgICAgIHZhciBrID0gMCB8IGE7XG4gICAgICAgICAgICBpZiAoayA+IGxhc3RfdGFiX2VudHJ5KVxuICAgICAgICAgICAgICAgIGsgPSBsYXN0X3RhYl9lbnRyeTtcbiAgICAgICAgICAgIG1hc2tfaWR4W2JdID0gaztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1hc2tfaWR4W2JdID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZvciAoYiA9IDE7IGIgPCBnZmMubnBhcnRfcyAtIDE7IGIrKykge1xuICAgICAgICAgICAgYSA9IGF2Z1tiIC0gMV0gKyBhdmdbYl0gKyBhdmdbYiArIDFdO1xuICAgICAgICAgICAgYXNzZXJ0KGIgKyAxIDwgZ2ZjLm5wYXJ0X3MpO1xuICAgICAgICAgICAgYXNzZXJ0KGEgPj0gMCk7XG4gICAgICAgICAgICBpZiAoYSA+IDAuMCkge1xuICAgICAgICAgICAgICAgIHZhciBtID0gbWF4W2IgLSAxXTtcbiAgICAgICAgICAgICAgICBpZiAobSA8IG1heFtiXSlcbiAgICAgICAgICAgICAgICAgICAgbSA9IG1heFtiXTtcbiAgICAgICAgICAgICAgICBpZiAobSA8IG1heFtiICsgMV0pXG4gICAgICAgICAgICAgICAgICAgIG0gPSBtYXhbYiArIDFdO1xuICAgICAgICAgICAgICAgIGFzc2VydCgoZ2ZjLm51bWxpbmVzX3NbYiAtIDFdICsgZ2ZjLm51bWxpbmVzX3NbYl0gKyBnZmMubnVtbGluZXNfc1tiICsgMV0gLSAxKSA+IDApO1xuICAgICAgICAgICAgICAgIGEgPSAyMC4wXG4gICAgICAgICAgICAgICAgICAgICogKG0gKiAzLjAgLSBhKVxuICAgICAgICAgICAgICAgICAgICAvIChhICogKGdmYy5udW1saW5lc19zW2IgLSAxXSArIGdmYy5udW1saW5lc19zW2JdXG4gICAgICAgICAgICAgICAgICAgICsgZ2ZjLm51bWxpbmVzX3NbYiArIDFdIC0gMSkpO1xuICAgICAgICAgICAgICAgIHZhciBrID0gMCB8IGE7XG4gICAgICAgICAgICAgICAgaWYgKGsgPiBsYXN0X3RhYl9lbnRyeSlcbiAgICAgICAgICAgICAgICAgICAgayA9IGxhc3RfdGFiX2VudHJ5O1xuICAgICAgICAgICAgICAgIG1hc2tfaWR4W2JdID0gaztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgbWFza19pZHhbYl0gPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGFzc2VydChiID4gMCk7XG4gICAgICAgIGFzc2VydChiID09IGdmYy5ucGFydF9zIC0gMSk7XG5cbiAgICAgICAgYSA9IGF2Z1tiIC0gMV0gKyBhdmdbYl07XG4gICAgICAgIGFzc2VydChhID49IDApO1xuICAgICAgICBpZiAoYSA+IDAuMCkge1xuICAgICAgICAgICAgdmFyIG0gPSBtYXhbYiAtIDFdO1xuICAgICAgICAgICAgaWYgKG0gPCBtYXhbYl0pXG4gICAgICAgICAgICAgICAgbSA9IG1heFtiXTtcbiAgICAgICAgICAgIGFzc2VydCgoZ2ZjLm51bWxpbmVzX3NbYiAtIDFdICsgZ2ZjLm51bWxpbmVzX3NbYl0gLSAxKSA+IDApO1xuICAgICAgICAgICAgYSA9IDIwLjAgKiAobSAqIDIuMCAtIGEpXG4gICAgICAgICAgICAgICAgLyAoYSAqIChnZmMubnVtbGluZXNfc1tiIC0gMV0gKyBnZmMubnVtbGluZXNfc1tiXSAtIDEpKTtcbiAgICAgICAgICAgIHZhciBrID0gMCB8IGE7XG4gICAgICAgICAgICBpZiAoayA+IGxhc3RfdGFiX2VudHJ5KVxuICAgICAgICAgICAgICAgIGsgPSBsYXN0X3RhYl9lbnRyeTtcbiAgICAgICAgICAgIG1hc2tfaWR4W2JdID0gaztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG1hc2tfaWR4W2JdID0gMDtcbiAgICAgICAgfVxuICAgICAgICBhc3NlcnQoYiA9PSAoZ2ZjLm5wYXJ0X3MgLSAxKSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmJycHN5X2NvbXB1dGVfbWFza2luZ19zKGdmcCwgZmZ0ZW5lcmd5X3MsIGViLCB0aHIsIGNobiwgc2Jsb2NrKSB7XG4gICAgICAgIHZhciBnZmMgPSBnZnAuaW50ZXJuYWxfZmxhZ3M7XG4gICAgICAgIHZhciBtYXggPSBuZXcgZmxvYXRbRW5jb2Rlci5DQkFORFNdLCBhdmcgPSBuZXdfZmxvYXQoRW5jb2Rlci5DQkFORFMpO1xuICAgICAgICB2YXIgaSwgaiwgYjtcbiAgICAgICAgdmFyIG1hc2tfaWR4X3MgPSBuZXcgaW50W0VuY29kZXIuQ0JBTkRTXTtcblxuICAgICAgICBmb3IgKGIgPSBqID0gMDsgYiA8IGdmYy5ucGFydF9zOyArK2IpIHtcbiAgICAgICAgICAgIHZhciBlYmIgPSAwLCBtID0gMDtcbiAgICAgICAgICAgIHZhciBuID0gZ2ZjLm51bWxpbmVzX3NbYl07XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgbjsgKytpLCArK2opIHtcbiAgICAgICAgICAgICAgICB2YXIgZWwgPSBmZnRlbmVyZ3lfc1tzYmxvY2tdW2pdO1xuICAgICAgICAgICAgICAgIGViYiArPSBlbDtcbiAgICAgICAgICAgICAgICBpZiAobSA8IGVsKVxuICAgICAgICAgICAgICAgICAgICBtID0gZWw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlYltiXSA9IGViYjtcbiAgICAgICAgICAgIGFzc2VydChlYmIgPj0gMCk7XG4gICAgICAgICAgICBtYXhbYl0gPSBtO1xuICAgICAgICAgICAgYXNzZXJ0KG4gPiAwKTtcbiAgICAgICAgICAgIGF2Z1tiXSA9IGViYiAvIG47XG4gICAgICAgICAgICBhc3NlcnQoYXZnW2JdID49IDApO1xuICAgICAgICB9XG4gICAgICAgIGFzc2VydChiID09IGdmYy5ucGFydF9zKTtcbiAgICAgICAgYXNzZXJ0KGogPT0gMTI5KTtcbiAgICAgICAgZm9yICg7IGIgPCBFbmNvZGVyLkNCQU5EUzsgKytiKSB7XG4gICAgICAgICAgICBtYXhbYl0gPSAwO1xuICAgICAgICAgICAgYXZnW2JdID0gMDtcbiAgICAgICAgfVxuICAgICAgICBwc3l2YnJfY2FsY19tYXNrX2luZGV4X3MoZ2ZjLCBtYXgsIGF2ZywgbWFza19pZHhfcyk7XG4gICAgICAgIGZvciAoaiA9IGIgPSAwOyBiIDwgZ2ZjLm5wYXJ0X3M7IGIrKykge1xuICAgICAgICAgICAgdmFyIGtrID0gZ2ZjLnMzaW5kX3NbYl1bMF07XG4gICAgICAgICAgICB2YXIgbGFzdCA9IGdmYy5zM2luZF9zW2JdWzFdO1xuICAgICAgICAgICAgdmFyIGRkLCBkZF9uO1xuICAgICAgICAgICAgdmFyIHgsIGVjYiwgYXZnX21hc2s7XG4gICAgICAgICAgICBkZCA9IG1hc2tfaWR4X3Nba2tdO1xuICAgICAgICAgICAgZGRfbiA9IDE7XG4gICAgICAgICAgICBlY2IgPSBnZmMuczNfc3Nbal0gKiBlYltra10gKiB0YWJbbWFza19pZHhfc1tra11dO1xuICAgICAgICAgICAgKytqO1xuICAgICAgICAgICAgKytraztcbiAgICAgICAgICAgIHdoaWxlIChrayA8PSBsYXN0KSB7XG4gICAgICAgICAgICAgICAgZGQgKz0gbWFza19pZHhfc1tra107XG4gICAgICAgICAgICAgICAgZGRfbiArPSAxO1xuICAgICAgICAgICAgICAgIHggPSBnZmMuczNfc3Nbal0gKiBlYltra10gKiB0YWJbbWFza19pZHhfc1tra11dO1xuICAgICAgICAgICAgICAgIGVjYiA9IHZicnBzeV9tYXNrX2FkZChlY2IsIHgsIGtrIC0gYik7XG4gICAgICAgICAgICAgICAgKytqO1xuICAgICAgICAgICAgICAgICsra2s7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZCA9ICgxICsgMiAqIGRkKSAvICgyICogZGRfbik7XG4gICAgICAgICAgICBhdmdfbWFzayA9IHRhYltkZF0gKiAwLjU7XG4gICAgICAgICAgICBlY2IgKj0gYXZnX21hc2s7XG4gICAgICAgICAgICB0aHJbYl0gPSBlY2I7XG4gICAgICAgICAgICBnZmMubmJfczJbY2huXVtiXSA9IGdmYy5uYl9zMVtjaG5dW2JdO1xuICAgICAgICAgICAgZ2ZjLm5iX3MxW2Nobl1bYl0gPSBlY2I7XG4gICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAgICAgKiBpZiBUSFIgZXhjZWVkcyBFQiwgdGhlIHF1YW50aXphdGlvbiByb3V0aW5lcyB3aWxsIHRha2UgdGhlXG4gICAgICAgICAgICAgICAgICogZGlmZmVyZW5jZSBmcm9tIG90aGVyIGJhbmRzLiBpbiBjYXNlIG9mIHN0cm9uZyB0b25hbCBzYW1wbGVzXG4gICAgICAgICAgICAgICAgICogKHRvbmFsdGVzdC53YXYpIHRoaXMgbGVhZHMgdG8gaGVhdnkgZGlzdG9ydGlvbnMuIHRoYXQncyB3aHlcbiAgICAgICAgICAgICAgICAgKiB3ZSBsaW1pdCBUSFIgaGVyZS5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICB4ID0gbWF4W2JdO1xuICAgICAgICAgICAgICAgIHggKj0gZ2ZjLm1pbnZhbF9zW2JdO1xuICAgICAgICAgICAgICAgIHggKj0gYXZnX21hc2s7XG4gICAgICAgICAgICAgICAgaWYgKHRocltiXSA+IHgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyW2JdID0geDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZ2ZjLm1hc2tpbmdfbG93ZXIgPiAxKSB7XG4gICAgICAgICAgICAgICAgdGhyW2JdICo9IGdmYy5tYXNraW5nX2xvd2VyO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHRocltiXSA+IGViW2JdKSB7XG4gICAgICAgICAgICAgICAgdGhyW2JdID0gZWJbYl07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoZ2ZjLm1hc2tpbmdfbG93ZXIgPCAxKSB7XG4gICAgICAgICAgICAgICAgdGhyW2JdICo9IGdmYy5tYXNraW5nX2xvd2VyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhc3NlcnQodGhyW2JdID49IDApO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoOyBiIDwgRW5jb2Rlci5DQkFORFM7ICsrYikge1xuICAgICAgICAgICAgZWJbYl0gPSAwO1xuICAgICAgICAgICAgdGhyW2JdID0gMDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHZicnBzeV9jb21wdXRlX21hc2tpbmdfbChnZmMsIGZmdGVuZXJneSwgZWJfbCwgdGhyLCBjaG4pIHtcbiAgICAgICAgdmFyIG1heCA9IG5ld19mbG9hdChFbmNvZGVyLkNCQU5EUyksIGF2ZyA9IG5ld19mbG9hdChFbmNvZGVyLkNCQU5EUyk7XG4gICAgICAgIHZhciBtYXNrX2lkeF9sID0gbmV3X2ludChFbmNvZGVyLkNCQU5EUyArIDIpO1xuICAgICAgICB2YXIgYjtcblxuICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgICAqIENhbGN1bGF0ZSB0aGUgZW5lcmd5IGFuZCB0aGUgdG9uYWxpdHkgb2YgZWFjaCBwYXJ0aXRpb24uXG4gICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgIGNhbGNfZW5lcmd5KGdmYywgZmZ0ZW5lcmd5LCBlYl9sLCBtYXgsIGF2Zyk7XG4gICAgICAgIGNhbGNfbWFza19pbmRleF9sKGdmYywgbWF4LCBhdmcsIG1hc2tfaWR4X2wpO1xuXG4gICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbiAgICAgICAgICogY29udm9sdmUgdGhlIHBhcnRpdGlvbmVkIGVuZXJneSBhbmQgdW5wcmVkaWN0YWJpbGl0eSB3aXRoIHRoZVxuICAgICAgICAgKiBzcHJlYWRpbmcgZnVuY3Rpb24sIHMzX2xbYl1ba11cbiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuICAgICAgICB2YXIgayA9IDA7XG4gICAgICAgIGZvciAoYiA9IDA7IGIgPCBnZmMubnBhcnRfbDsgYisrKSB7XG4gICAgICAgICAgICB2YXIgeCwgZWNiLCBhdmdfbWFzaywgdDtcbiAgICAgICAgICAgIC8qIGNvbnZvbHZlIHRoZSBwYXJ0aXRpb25lZCBlbmVyZ3kgd2l0aCB0aGUgc3ByZWFkaW5nIGZ1bmN0aW9uICovXG4gICAgICAgICAgICB2YXIga2sgPSBnZmMuczNpbmRbYl1bMF07XG4gICAgICAgICAgICB2YXIgbGFzdCA9IGdmYy5zM2luZFtiXVsxXTtcbiAgICAgICAgICAgIHZhciBkZCA9IDAsIGRkX24gPSAwO1xuICAgICAgICAgICAgZGQgPSBtYXNrX2lkeF9sW2trXTtcbiAgICAgICAgICAgIGRkX24gKz0gMTtcbiAgICAgICAgICAgIGVjYiA9IGdmYy5zM19sbFtrXSAqIGViX2xba2tdICogdGFiW21hc2tfaWR4X2xba2tdXTtcbiAgICAgICAgICAgICsraztcbiAgICAgICAgICAgICsra2s7XG4gICAgICAgICAgICB3aGlsZSAoa2sgPD0gbGFzdCkge1xuICAgICAgICAgICAgICAgIGRkICs9IG1hc2tfaWR4X2xba2tdO1xuICAgICAgICAgICAgICAgIGRkX24gKz0gMTtcbiAgICAgICAgICAgICAgICB4ID0gZ2ZjLnMzX2xsW2tdICogZWJfbFtra10gKiB0YWJbbWFza19pZHhfbFtra11dO1xuICAgICAgICAgICAgICAgIHQgPSB2YnJwc3lfbWFza19hZGQoZWNiLCB4LCBrayAtIGIpO1xuICAgICAgICAgICAgICAgIGVjYiA9IHQ7XG4gICAgICAgICAgICAgICAgKytrO1xuICAgICAgICAgICAgICAgICsra2s7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBkZCA9ICgxICsgMiAqIGRkKSAvICgyICogZGRfbik7XG4gICAgICAgICAgICBhdmdfbWFzayA9IHRhYltkZF0gKiAwLjU7XG4gICAgICAgICAgICBlY2IgKj0gYXZnX21hc2s7XG5cbiAgICAgICAgICAgIC8qKioqIGxvbmcgYmxvY2sgcHJlLWVjaG8gY29udHJvbCAqKioqL1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiA8UFJFPlxuICAgICAgICAgICAgICogZG9udCB1c2UgbG9uZyBibG9jayBwcmUtZWNobyBjb250cm9sIGlmIHByZXZpb3VzIGdyYW51bGUgd2FzXG4gICAgICAgICAgICAgKiBhIHNob3J0IGJsb2NrLiAgVGhpcyBpcyB0byBhdm9pZCB0aGUgc2l0dWF0aW9uOlxuICAgICAgICAgICAgICogZnJhbWUwOiAgcXVpZXQgKHZlcnkgbG93IG1hc2tpbmcpXG4gICAgICAgICAgICAgKiBmcmFtZTE6ICBzdXJnZSAgKHRyaWdnZXJzIHNob3J0IGJsb2NrcylcbiAgICAgICAgICAgICAqIGZyYW1lMjogIHJlZ3VsYXIgZnJhbWUuICBsb29rcyBsaWtlIHByZS1lY2hvIHdoZW4gY29tcGFyZWQgdG9cbiAgICAgICAgICAgICAqICAgICAgICAgIGZyYW1lMCwgYnV0IGFsbCBwcmUtZWNobyB3YXMgaW4gZnJhbWUxLlxuICAgICAgICAgICAgICogPC9QUkU+XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBjaG49MCwxIEwgYW5kIFIgY2hhbm5lbHMgY2huPTIsMyBTIGFuZCBNIGNoYW5uZWxzLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpZiAoZ2ZjLmJsb2NrdHlwZV9vbGRbY2huICYgMHgwMV0gPT0gRW5jb2Rlci5TSE9SVF9UWVBFKSB7XG4gICAgICAgICAgICAgICAgdmFyIGVjYl9saW1pdCA9IHJwZWxldiAqIGdmYy5uYl8xW2Nobl1bYl07XG4gICAgICAgICAgICAgICAgaWYgKGVjYl9saW1pdCA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgdGhyW2JdID0gTWF0aC5taW4oZWNiLCBlY2JfbGltaXQpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgKiA8UFJFPlxuICAgICAgICAgICAgICAgICAgICAgKiBSb2JlcnQgMDcxMjA5OlxuICAgICAgICAgICAgICAgICAgICAgKiBCZWNhdXNlIHdlIGRvbid0IGNhbGN1bGF0ZSBsb25nIGJsb2NrIHBzeSB3aGVuIHdlIGtub3cgYSBncmFudWxlXG4gICAgICAgICAgICAgICAgICAgICAqIHNob3VsZCBiZSBvZiBzaG9ydCBibG9ja3MsIHdlIGRvbid0IGhhdmUgYW55IGNsdWUgaG93IHRoZSBncmFudWxlXG4gICAgICAgICAgICAgICAgICAgICAqIGJlZm9yZSB3b3VsZCBoYXZlIGxvb2tlZCBsaWtlIGFzIGEgbG9uZyBibG9jay4gU28gd2UgaGF2ZSB0byBndWVzc1xuICAgICAgICAgICAgICAgICAgICAgKiBhIGxpdHRsZSBiaXQgZm9yIHRoaXMgRU5EX1RZUEUgYmxvY2suXG4gICAgICAgICAgICAgICAgICAgICAqIE1vc3Qgb2YgdGhlIHRpbWUgd2UgZ2V0IGF3YXkgd2l0aCB0aGlzIHNsb3BweW5lc3MuIChmaW5nZXJzIGNyb3NzZWQgOilcbiAgICAgICAgICAgICAgICAgICAgICogVGhlIHNwZWVkIGluY3JlYXNlIGlzIHdvcnRoIGl0LlxuICAgICAgICAgICAgICAgICAgICAgKiA8L1BSRT5cbiAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgIHRocltiXSA9IE1hdGgubWluKGVjYiwgZWJfbFtiXSAqIE5TX1BSRUVDSE9fQVRUMik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgZWNiX2xpbWl0XzIgPSBycGVsZXYyICogZ2ZjLm5iXzJbY2huXVtiXTtcbiAgICAgICAgICAgICAgICB2YXIgZWNiX2xpbWl0XzEgPSBycGVsZXYgKiBnZmMubmJfMVtjaG5dW2JdO1xuICAgICAgICAgICAgICAgIHZhciBlY2JfbGltaXQ7XG4gICAgICAgICAgICAgICAgaWYgKGVjYl9saW1pdF8yIDw9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgZWNiX2xpbWl0XzIgPSBlY2I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChlY2JfbGltaXRfMSA8PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGVjYl9saW1pdF8xID0gZWNiO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoZ2ZjLmJsb2NrdHlwZV9vbGRbY2huICYgMHgwMV0gPT0gRW5jb2Rlci5OT1JNX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgZWNiX2xpbWl0ID0gTWF0aC5taW4oZWNiX2xpbWl0XzEsIGVjYl9saW1pdF8yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBlY2JfbGltaXQgPSBlY2JfbGltaXRfMTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgdGhyW2JdID0gTWF0aC5taW4oZWNiLCBlY2JfbGltaXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZ2ZjLm5iXzJbY2huXVtiXSA9IGdmYy5uYl8xW2Nobl1bYl07XG4gICAgICAgICAgICBnZmMubmJfMVtjaG5dW2JdID0gZWNiO1xuICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICogaWYgVEhSIGV4Y2VlZHMgRUIsIHRoZSBxdWFudGl6YXRpb24gcm91dGluZXMgd2lsbCB0YWtlIHRoZVxuICAgICAgICAgICAgICAgICAqIGRpZmZlcmVuY2UgZnJvbSBvdGhlciBiYW5kcy4gaW4gY2FzZSBvZiBzdHJvbmcgdG9uYWwgc2FtcGxlc1xuICAgICAgICAgICAgICAgICAqICh0b25hbHRlc3Qud2F2KSB0aGlzIGxlYWRzIHRvIGhlYXZ5IGRpc3RvcnRpb25zLiB0aGF0J3Mgd2h5XG4gICAgICAgICAgICAgICAgICogd2UgbGltaXQgVEhSIGhlcmUuXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgeCA9IG1heFtiXTtcbiAgICAgICAgICAgICAgICB4ICo9IGdmYy5taW52YWxfbFtiXTtcbiAgICAgICAgICAgICAgICB4ICo9IGF2Z19tYXNrO1xuICAgICAgICAgICAgICAgIGlmICh0aHJbYl0gPiB4KSB7XG4gICAgICAgICAgICAgICAgICAgIHRocltiXSA9IHg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdmYy5tYXNraW5nX2xvd2VyID4gMSkge1xuICAgICAgICAgICAgICAgIHRocltiXSAqPSBnZmMubWFza2luZ19sb3dlcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh0aHJbYl0gPiBlYl9sW2JdKSB7XG4gICAgICAgICAgICAgICAgdGhyW2JdID0gZWJfbFtiXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChnZmMubWFza2luZ19sb3dlciA8IDEpIHtcbiAgICAgICAgICAgICAgICB0aHJbYl0gKj0gZ2ZjLm1hc2tpbmdfbG93ZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBhc3NlcnQodGhyW2JdID49IDApO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoOyBiIDwgRW5jb2Rlci5DQkFORFM7ICsrYikge1xuICAgICAgICAgICAgZWJfbFtiXSA9IDA7XG4gICAgICAgICAgICB0aHJbYl0gPSAwO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gdmJycHN5X2NvbXB1dGVfYmxvY2tfdHlwZShnZnAsIHVzZWxvbmdibG9jaykge1xuICAgICAgICB2YXIgZ2ZjID0gZ2ZwLmludGVybmFsX2ZsYWdzO1xuXG4gICAgICAgIGlmIChnZnAuc2hvcnRfYmxvY2tzID09IFNob3J0QmxvY2suc2hvcnRfYmxvY2tfY291cGxlZFxuICAgICAgICAgICAgICAgIC8qIGZvcmNlIGJvdGggY2hhbm5lbHMgdG8gdXNlIHRoZSBzYW1lIGJsb2NrIHR5cGUgKi9cbiAgICAgICAgICAgICAgICAvKiB0aGlzIGlzIG5lY2Vzc2FyeSBpZiB0aGUgZnJhbWUgaXMgdG8gYmUgZW5jb2RlZCBpbiBtc19zdGVyZW8uICovXG4gICAgICAgICAgICAgICAgLyogQnV0IGV2ZW4gd2l0aG91dCBtc19zdGVyZW8sIEZoRyBkb2VzIHRoaXMgKi9cbiAgICAgICAgICAgICYmICEodXNlbG9uZ2Jsb2NrWzBdICE9IDAgJiYgdXNlbG9uZ2Jsb2NrWzFdICE9IDApKVxuICAgICAgICAgICAgdXNlbG9uZ2Jsb2NrWzBdID0gdXNlbG9uZ2Jsb2NrWzFdID0gMDtcblxuICAgICAgICBmb3IgKHZhciBjaG4gPSAwOyBjaG4gPCBnZmMuY2hhbm5lbHNfb3V0OyBjaG4rKykge1xuICAgICAgICAgICAgLyogZGlzYWJsZSBzaG9ydCBibG9ja3MgKi9cbiAgICAgICAgICAgIGlmIChnZnAuc2hvcnRfYmxvY2tzID09IFNob3J0QmxvY2suc2hvcnRfYmxvY2tfZGlzcGVuc2VkKSB7XG4gICAgICAgICAgICAgICAgdXNlbG9uZ2Jsb2NrW2Nobl0gPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGdmcC5zaG9ydF9ibG9ja3MgPT0gU2hvcnRCbG9jay5zaG9ydF9ibG9ja19mb3JjZWQpIHtcbiAgICAgICAgICAgICAgICB1c2Vsb25nYmxvY2tbY2huXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBmdW5jdGlvbiB2YnJwc3lfYXBwbHlfYmxvY2tfdHlwZShnZnAsIHVzZWxvbmdibG9jaywgYmxvY2t0eXBlX2QpIHtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcblxuICAgICAgICAvKlxuICAgICAgICAgKiB1cGRhdGUgdGhlIGJsb2NrdHlwZSBvZiB0aGUgcHJldmlvdXMgZ3JhbnVsZSwgc2luY2UgaXQgZGVwZW5kcyBvblxuICAgICAgICAgKiB3aGF0IGhhcHBlbmQgaW4gdGhpcyBncmFudWxlXG4gICAgICAgICAqL1xuICAgICAgICBmb3IgKHZhciBjaG4gPSAwOyBjaG4gPCBnZmMuY2hhbm5lbHNfb3V0OyBjaG4rKykge1xuICAgICAgICAgICAgdmFyIGJsb2NrdHlwZSA9IEVuY29kZXIuTk9STV9UWVBFO1xuICAgICAgICAgICAgLyogZGlzYWJsZSBzaG9ydCBibG9ja3MgKi9cblxuICAgICAgICAgICAgaWYgKHVzZWxvbmdibG9ja1tjaG5dICE9IDApIHtcbiAgICAgICAgICAgICAgICAvKiBubyBhdHRhY2sgOiB1c2UgbG9uZyBibG9ja3MgKi9cbiAgICAgICAgICAgICAgICBhc3NlcnQoZ2ZjLmJsb2NrdHlwZV9vbGRbY2huXSAhPSBFbmNvZGVyLlNUQVJUX1RZUEUpO1xuICAgICAgICAgICAgICAgIGlmIChnZmMuYmxvY2t0eXBlX29sZFtjaG5dID09IEVuY29kZXIuU0hPUlRfVFlQRSlcbiAgICAgICAgICAgICAgICAgICAgYmxvY2t0eXBlID0gRW5jb2Rlci5TVE9QX1RZUEU7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8qIGF0dGFjayA6IHVzZSBzaG9ydCBibG9ja3MgKi9cbiAgICAgICAgICAgICAgICBibG9ja3R5cGUgPSBFbmNvZGVyLlNIT1JUX1RZUEU7XG4gICAgICAgICAgICAgICAgaWYgKGdmYy5ibG9ja3R5cGVfb2xkW2Nobl0gPT0gRW5jb2Rlci5OT1JNX1RZUEUpIHtcbiAgICAgICAgICAgICAgICAgICAgZ2ZjLmJsb2NrdHlwZV9vbGRbY2huXSA9IEVuY29kZXIuU1RBUlRfVFlQRTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGdmYy5ibG9ja3R5cGVfb2xkW2Nobl0gPT0gRW5jb2Rlci5TVE9QX1RZUEUpXG4gICAgICAgICAgICAgICAgICAgIGdmYy5ibG9ja3R5cGVfb2xkW2Nobl0gPSBFbmNvZGVyLlNIT1JUX1RZUEU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGJsb2NrdHlwZV9kW2Nobl0gPSBnZmMuYmxvY2t0eXBlX29sZFtjaG5dO1xuICAgICAgICAgICAgLy8gdmFsdWUgcmV0dXJuZWQgdG8gY2FsbGluZyBwcm9ncmFtXG4gICAgICAgICAgICBnZmMuYmxvY2t0eXBlX29sZFtjaG5dID0gYmxvY2t0eXBlO1xuICAgICAgICAgICAgLy8gc2F2ZSBmb3IgbmV4dCBjYWxsIHRvIGwzcHN5X2FuYWxcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIGNvbXB1dGUgTS9TIHRocmVzaG9sZHMgZnJvbSBKb2huc3RvbiAmIEZlcnJlaXJhIDE5OTIgSUNBU1NQIHBhcGVyXG4gICAgICovXG4gICAgZnVuY3Rpb24gdmJycHN5X2NvbXB1dGVfTVNfdGhyZXNob2xkcyhlYiwgdGhyLCBjYl9tbGQsIGF0aF9jYiwgYXRoYWRqdXN0LCBtc2ZpeCwgbikge1xuICAgICAgICB2YXIgbXNmaXgyID0gbXNmaXggKiAyO1xuICAgICAgICB2YXIgYXRobG93ZXIgPSBtc2ZpeCA+IDAgPyBNYXRoLnBvdygxMCwgYXRoYWRqdXN0KSA6IDE7XG4gICAgICAgIHZhciByc2lkZSwgcm1pZDtcbiAgICAgICAgZm9yICh2YXIgYiA9IDA7IGIgPCBuOyArK2IpIHtcbiAgICAgICAgICAgIHZhciBlYk0gPSBlYlsyXVtiXTtcbiAgICAgICAgICAgIHZhciBlYlMgPSBlYlszXVtiXTtcbiAgICAgICAgICAgIHZhciB0aG1MID0gdGhyWzBdW2JdO1xuICAgICAgICAgICAgdmFyIHRobVIgPSB0aHJbMV1bYl07XG4gICAgICAgICAgICB2YXIgdGhtTSA9IHRoclsyXVtiXTtcbiAgICAgICAgICAgIHZhciB0aG1TID0gdGhyWzNdW2JdO1xuXG4gICAgICAgICAgICAvKiB1c2UgdGhpcyBmaXggaWYgTCAmIFIgbWFza2luZyBkaWZmZXJzIGJ5IDJkYiBvciBsZXNzICovXG4gICAgICAgICAgICBpZiAodGhtTCA8PSAxLjU4ICogdGhtUiAmJiB0aG1SIDw9IDEuNTggKiB0aG1MKSB7XG4gICAgICAgICAgICAgICAgdmFyIG1sZF9tID0gY2JfbWxkW2JdICogZWJTO1xuICAgICAgICAgICAgICAgIHZhciBtbGRfcyA9IGNiX21sZFtiXSAqIGViTTtcbiAgICAgICAgICAgICAgICBybWlkID0gTWF0aC5tYXgodGhtTSwgTWF0aC5taW4odGhtUywgbWxkX20pKTtcbiAgICAgICAgICAgICAgICByc2lkZSA9IE1hdGgubWF4KHRobVMsIE1hdGgubWluKHRobU0sIG1sZF9zKSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJtaWQgPSB0aG1NO1xuICAgICAgICAgICAgICAgIHJzaWRlID0gdGhtUztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChtc2ZpeCA+IDApIHtcbiAgICAgICAgICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqL1xuICAgICAgICAgICAgICAgIC8qIEFkanVzdCBNL1MgbWFza2luZ3MgaWYgdXNlciBzZXQgXCJtc2ZpeFwiICovXG4gICAgICAgICAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbiAgICAgICAgICAgICAgICAvKiBOYW9raSBTaGliYXRhIDIwMDAgKi9cbiAgICAgICAgICAgICAgICB2YXIgdGhtTFIsIHRobU1TO1xuICAgICAgICAgICAgICAgIHZhciBhdGggPSBhdGhfY2JbYl0gKiBhdGhsb3dlcjtcbiAgICAgICAgICAgICAgICB0aG1MUiA9IE1hdGgubWluKE1hdGgubWF4KHRobUwsIGF0aCksIE1hdGgubWF4KHRobVIsIGF0aCkpO1xuICAgICAgICAgICAgICAgIHRobU0gPSBNYXRoLm1heChybWlkLCBhdGgpO1xuICAgICAgICAgICAgICAgIHRobVMgPSBNYXRoLm1heChyc2lkZSwgYXRoKTtcbiAgICAgICAgICAgICAgICB0aG1NUyA9IHRobU0gKyB0aG1TO1xuICAgICAgICAgICAgICAgIGlmICh0aG1NUyA+IDAgJiYgKHRobUxSICogbXNmaXgyKSA8IHRobU1TKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBmID0gdGhtTFIgKiBtc2ZpeDIgLyB0aG1NUztcbiAgICAgICAgICAgICAgICAgICAgdGhtTSAqPSBmO1xuICAgICAgICAgICAgICAgICAgICB0aG1TICo9IGY7XG4gICAgICAgICAgICAgICAgICAgIGFzc2VydCh0aG1NUyA+IDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBybWlkID0gTWF0aC5taW4odGhtTSwgcm1pZCk7XG4gICAgICAgICAgICAgICAgcnNpZGUgPSBNYXRoLm1pbih0aG1TLCByc2lkZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocm1pZCA+IGViTSkge1xuICAgICAgICAgICAgICAgIHJtaWQgPSBlYk07XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAocnNpZGUgPiBlYlMpIHtcbiAgICAgICAgICAgICAgICByc2lkZSA9IGViUztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHRoclsyXVtiXSA9IHJtaWQ7XG4gICAgICAgICAgICB0aHJbM11bYl0gPSByc2lkZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuTDNwc3ljaG9fYW5hbF92YnIgPSBmdW5jdGlvbiAoZ2ZwLCBidWZmZXIsIGJ1ZlBvcywgZ3Jfb3V0LCBtYXNraW5nX3JhdGlvLCBtYXNraW5nX01TX3JhdGlvLCBwZXJjZXBfZW50cm9weSwgcGVyY2VwX01TX2VudHJvcHksIGVuZXJneSwgYmxvY2t0eXBlX2QpIHtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcblxuICAgICAgICAvKiBmZnQgYW5kIGVuZXJneSBjYWxjdWxhdGlvbiAqL1xuICAgICAgICB2YXIgd3NhbXBfbDtcbiAgICAgICAgdmFyIHdzYW1wX3M7XG4gICAgICAgIHZhciBmZnRlbmVyZ3kgPSBuZXdfZmxvYXQoRW5jb2Rlci5IQkxLU0laRSk7XG4gICAgICAgIHZhciBmZnRlbmVyZ3lfcyA9IG5ld19mbG9hdF9uKFszLCBFbmNvZGVyLkhCTEtTSVpFX3NdKTtcbiAgICAgICAgdmFyIHdzYW1wX0wgPSBuZXdfZmxvYXRfbihbMiwgRW5jb2Rlci5CTEtTSVpFXSk7XG4gICAgICAgIHZhciB3c2FtcF9TID0gbmV3X2Zsb2F0X24oWzIsIDMsIEVuY29kZXIuQkxLU0laRV9zXSk7XG4gICAgICAgIHZhciBlYiA9IG5ld19mbG9hdF9uKFs0LCBFbmNvZGVyLkNCQU5EU10pLCB0aHIgPSBuZXdfZmxvYXRfbihbNCwgRW5jb2Rlci5DQkFORFNdKTtcbiAgICAgICAgdmFyIHN1Yl9zaG9ydF9mYWN0b3IgPSBuZXdfZmxvYXRfbihbNCwgM10pO1xuICAgICAgICB2YXIgcGNmYWN0ID0gMC42O1xuXG4gICAgICAgIC8qIGJsb2NrIHR5cGUgKi9cbiAgICAgICAgdmFyIG5zX2F0dGFja3MgPSBbWzAsIDAsIDAsIDBdLCBbMCwgMCwgMCwgMF0sIFswLCAwLCAwLCAwXSxcbiAgICAgICAgICAgIFswLCAwLCAwLCAwXV07XG4gICAgICAgIHZhciB1c2Vsb25nYmxvY2sgPSBuZXdfaW50KDIpO1xuXG4gICAgICAgIC8qIHVzdWFsIHZhcmlhYmxlcyBsaWtlIGxvb3AgaW5kaWNlcywgZXRjLi4gKi9cblxuICAgICAgICAvKiBjaG49MiBhbmQgMyA9IE1pZCBhbmQgU2lkZSBjaGFubmVscyAqL1xuICAgICAgICB2YXIgbl9jaG5fcHN5ID0gKGdmcC5tb2RlID09IE1QRUdNb2RlLkpPSU5UX1NURVJFTykgPyA0XG4gICAgICAgICAgICA6IGdmYy5jaGFubmVsc19vdXQ7XG5cbiAgICAgICAgdmJycHN5X2F0dGFja19kZXRlY3Rpb24oZ2ZwLCBidWZmZXIsIGJ1ZlBvcywgZ3Jfb3V0LCBtYXNraW5nX3JhdGlvLFxuICAgICAgICAgICAgbWFza2luZ19NU19yYXRpbywgZW5lcmd5LCBzdWJfc2hvcnRfZmFjdG9yLCBuc19hdHRhY2tzLFxuICAgICAgICAgICAgdXNlbG9uZ2Jsb2NrKTtcblxuICAgICAgICB2YnJwc3lfY29tcHV0ZV9ibG9ja190eXBlKGdmcCwgdXNlbG9uZ2Jsb2NrKTtcblxuICAgICAgICAvKiBMT05HIEJMT0NLIENBU0UgKi9cbiAgICAgICAge1xuICAgICAgICAgICAgZm9yICh2YXIgY2huID0gMDsgY2huIDwgbl9jaG5fcHN5OyBjaG4rKykge1xuICAgICAgICAgICAgICAgIHZhciBjaDAxID0gY2huICYgMHgwMTtcbiAgICAgICAgICAgICAgICB3c2FtcF9sID0gd3NhbXBfTDtcbiAgICAgICAgICAgICAgICB2YnJwc3lfY29tcHV0ZV9mZnRfbChnZnAsIGJ1ZmZlciwgYnVmUG9zLCBjaG4sIGdyX291dCxcbiAgICAgICAgICAgICAgICAgICAgZmZ0ZW5lcmd5LCB3c2FtcF9sLCBjaDAxKTtcblxuICAgICAgICAgICAgICAgIHZicnBzeV9jb21wdXRlX2xvdWRuZXNzX2FwcHJveGltYXRpb25fbChnZnAsIGdyX291dCwgY2huLFxuICAgICAgICAgICAgICAgICAgICBmZnRlbmVyZ3kpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHVzZWxvbmdibG9ja1tjaDAxXSAhPSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIHZicnBzeV9jb21wdXRlX21hc2tpbmdfbChnZmMsIGZmdGVuZXJneSwgZWJbY2huXSwgdGhyW2Nobl0sXG4gICAgICAgICAgICAgICAgICAgICAgICBjaG4pO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZicnBzeV9za2lwX21hc2tpbmdfbChnZmMsIGNobik7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCh1c2Vsb25nYmxvY2tbMF0gKyB1c2Vsb25nYmxvY2tbMV0pID09IDIpIHtcbiAgICAgICAgICAgICAgICAvKiBNL1MgY2hhbm5lbCAqL1xuICAgICAgICAgICAgICAgIGlmIChnZnAubW9kZSA9PSBNUEVHTW9kZS5KT0lOVF9TVEVSRU8pIHtcbiAgICAgICAgICAgICAgICAgICAgdmJycHN5X2NvbXB1dGVfTVNfdGhyZXNob2xkcyhlYiwgdGhyLCBnZmMubWxkX2NiX2wsXG4gICAgICAgICAgICAgICAgICAgICAgICBnZmMuQVRILmNiX2wsIGdmcC5BVEhsb3dlciAqIGdmYy5BVEguYWRqdXN0LFxuICAgICAgICAgICAgICAgICAgICAgICAgZ2ZwLm1zZml4LCBnZmMubnBhcnRfbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLyogVE9ETzogYXBwbHkgYWRhcHRpdmUgQVRIIG1hc2tpbmcgaGVyZSA/PyAqL1xuICAgICAgICAgICAgZm9yICh2YXIgY2huID0gMDsgY2huIDwgbl9jaG5fcHN5OyBjaG4rKykge1xuICAgICAgICAgICAgICAgIHZhciBjaDAxID0gY2huICYgMHgwMTtcbiAgICAgICAgICAgICAgICBpZiAodXNlbG9uZ2Jsb2NrW2NoMDFdICE9IDApIHtcbiAgICAgICAgICAgICAgICAgICAgY29udmVydF9wYXJ0aXRpb24yc2NhbGVmYWNfbChnZmMsIGViW2Nobl0sIHRocltjaG5dLCBjaG4pO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8qIFNIT1JUIEJMT0NLUyBDQVNFICovXG4gICAgICAgIHtcbiAgICAgICAgICAgIGZvciAodmFyIHNibG9jayA9IDA7IHNibG9jayA8IDM7IHNibG9jaysrKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgY2huID0gMDsgY2huIDwgbl9jaG5fcHN5OyArK2Nobikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2gwMSA9IGNobiAmIDB4MDE7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHVzZWxvbmdibG9ja1tjaDAxXSAhPSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YnJwc3lfc2tpcF9tYXNraW5nX3MoZ2ZjLCBjaG4sIHNibG9jayk7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvKiBjb21wdXRlIG1hc2tpbmcgdGhyZXNob2xkcyBmb3Igc2hvcnQgYmxvY2tzICovXG4gICAgICAgICAgICAgICAgICAgICAgICB3c2FtcF9zID0gd3NhbXBfUztcbiAgICAgICAgICAgICAgICAgICAgICAgIHZicnBzeV9jb21wdXRlX2ZmdF9zKGdmcCwgYnVmZmVyLCBidWZQb3MsIGNobiwgc2Jsb2NrLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZmdGVuZXJneV9zLCB3c2FtcF9zLCBjaDAxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZicnBzeV9jb21wdXRlX21hc2tpbmdfcyhnZnAsIGZmdGVuZXJneV9zLCBlYltjaG5dLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRocltjaG5dLCBjaG4sIHNibG9jayk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKCh1c2Vsb25nYmxvY2tbMF0gKyB1c2Vsb25nYmxvY2tbMV0pID09IDApIHtcbiAgICAgICAgICAgICAgICAgICAgLyogTS9TIGNoYW5uZWwgKi9cbiAgICAgICAgICAgICAgICAgICAgaWYgKGdmcC5tb2RlID09IE1QRUdNb2RlLkpPSU5UX1NURVJFTykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmJycHN5X2NvbXB1dGVfTVNfdGhyZXNob2xkcyhlYiwgdGhyLCBnZmMubWxkX2NiX3MsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2ZjLkFUSC5jYl9zLCBnZnAuQVRIbG93ZXIgKiBnZmMuQVRILmFkanVzdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZnAubXNmaXgsIGdmYy5ucGFydF9zKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAvKiBML1IgY2hhbm5lbCAqL1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvKiBUT0RPOiBhcHBseSBhZGFwdGl2ZSBBVEggbWFza2luZyBoZXJlID8/ICovXG4gICAgICAgICAgICAgICAgZm9yICh2YXIgY2huID0gMDsgY2huIDwgbl9jaG5fcHN5OyArK2Nobikge1xuICAgICAgICAgICAgICAgICAgICB2YXIgY2gwMSA9IGNobiAmIDB4MDE7XG4gICAgICAgICAgICAgICAgICAgIGlmICgwID09IHVzZWxvbmdibG9ja1tjaDAxXSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udmVydF9wYXJ0aXRpb24yc2NhbGVmYWNfcyhnZmMsIGViW2Nobl0sIHRocltjaG5dLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNobiwgc2Jsb2NrKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLyoqKiogc2hvcnQgYmxvY2sgcHJlLWVjaG8gY29udHJvbCAqKioqL1xuICAgICAgICAgICAgZm9yICh2YXIgY2huID0gMDsgY2huIDwgbl9jaG5fcHN5OyBjaG4rKykge1xuICAgICAgICAgICAgICAgIHZhciBjaDAxID0gY2huICYgMHgwMTtcblxuICAgICAgICAgICAgICAgIGlmICh1c2Vsb25nYmxvY2tbY2gwMV0gIT0gMCkge1xuICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgc2IgPSAwOyBzYiA8IEVuY29kZXIuU0JNQVhfczsgc2IrKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbmV3X3RobW0gPSBuZXdfZmxvYXQoMyk7XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHNibG9jayA9IDA7IHNibG9jayA8IDM7IHNibG9jaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YXIgdGhtbSA9IGdmYy50aG1bY2huXS5zW3NiXVtzYmxvY2tdO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhtbSAqPSBOU19QUkVFQ0hPX0FUVDA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChuc19hdHRhY2tzW2Nobl1bc2Jsb2NrXSA+PSAyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgbnNfYXR0YWNrc1tjaG5dW3NibG9jayArIDFdID09IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgaWR4ID0gKHNibG9jayAhPSAwKSA/IHNibG9jayAtIDEgOiAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBwID0gTlNfSU5URVJQKGdmYy50aG1bY2huXS5zW3NiXVtpZHhdLCB0aG1tLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBOU19QUkVFQ0hPX0FUVDEgKiBwY2ZhY3QpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRobW0gPSBNYXRoLm1pbih0aG1tLCBwKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobnNfYXR0YWNrc1tjaG5dW3NibG9ja10gPT0gMSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhciBpZHggPSAoc2Jsb2NrICE9IDApID8gc2Jsb2NrIC0gMSA6IDI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIHAgPSBOU19JTlRFUlAoZ2ZjLnRobVtjaG5dLnNbc2JdW2lkeF0sIHRobW0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIE5TX1BSRUVDSE9fQVRUMiAqIHBjZmFjdCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhtbSA9IE1hdGgubWluKHRobW0sIHApO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICgoc2Jsb2NrICE9IDAgJiYgbnNfYXR0YWNrc1tjaG5dW3NibG9jayAtIDFdID09IDMpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgKHNibG9jayA9PSAwICYmIGdmYy5uc1BzeS5sYXN0QXR0YWNrc1tjaG5dID09IDMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFyIGlkeCA9IChzYmxvY2sgIT0gMikgPyBzYmxvY2sgKyAxIDogMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YXIgcCA9IE5TX0lOVEVSUChnZmMudGhtW2Nobl0uc1tzYl1baWR4XSwgdGhtbSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgTlNfUFJFRUNIT19BVFQyICogcGNmYWN0KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aG1tID0gTWF0aC5taW4odGhtbSwgcCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8qIHB1bHNlIGxpa2Ugc2lnbmFsIGRldGVjdGlvbiBmb3IgZmF0Ym95LndhdiBhbmQgc28gb24gKi9cbiAgICAgICAgICAgICAgICAgICAgICAgIHRobW0gKj0gc3ViX3Nob3J0X2ZhY3RvcltjaG5dW3NibG9ja107XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIG5ld190aG1tW3NibG9ja10gPSB0aG1tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGZvciAodmFyIHNibG9jayA9IDA7IHNibG9jayA8IDM7IHNibG9jaysrKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBnZmMudGhtW2Nobl0uc1tzYl1bc2Jsb2NrXSA9IG5ld190aG1tW3NibG9ja107XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgY2huID0gMDsgY2huIDwgbl9jaG5fcHN5OyBjaG4rKykge1xuICAgICAgICAgICAgZ2ZjLm5zUHN5Lmxhc3RBdHRhY2tzW2Nobl0gPSBuc19hdHRhY2tzW2Nobl1bMl07XG4gICAgICAgIH1cblxuICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgICAqIGRldGVybWluZSBmaW5hbCBibG9jayB0eXBlXG4gICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgIHZicnBzeV9hcHBseV9ibG9ja190eXBlKGdmcCwgdXNlbG9uZ2Jsb2NrLCBibG9ja3R5cGVfZCk7XG5cbiAgICAgICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxuICAgICAgICAgKiBjb21wdXRlIHRoZSB2YWx1ZSBvZiBQRSB0byByZXR1cm4gLi4uIG5vIGRlbGF5IGFuZCBhZHZhbmNlXG4gICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgIGZvciAodmFyIGNobiA9IDA7IGNobiA8IG5fY2huX3BzeTsgY2huKyspIHtcbiAgICAgICAgICAgIHZhciBwcGU7XG4gICAgICAgICAgICB2YXIgcHBlUG9zO1xuICAgICAgICAgICAgdmFyIHR5cGU7XG4gICAgICAgICAgICB2YXIgbXI7XG5cbiAgICAgICAgICAgIGlmIChjaG4gPiAxKSB7XG4gICAgICAgICAgICAgICAgcHBlID0gcGVyY2VwX01TX2VudHJvcHk7XG4gICAgICAgICAgICAgICAgcHBlUG9zID0gLTI7XG4gICAgICAgICAgICAgICAgdHlwZSA9IEVuY29kZXIuTk9STV9UWVBFO1xuICAgICAgICAgICAgICAgIGlmIChibG9ja3R5cGVfZFswXSA9PSBFbmNvZGVyLlNIT1JUX1RZUEVcbiAgICAgICAgICAgICAgICAgICAgfHwgYmxvY2t0eXBlX2RbMV0gPT0gRW5jb2Rlci5TSE9SVF9UWVBFKVxuICAgICAgICAgICAgICAgICAgICB0eXBlID0gRW5jb2Rlci5TSE9SVF9UWVBFO1xuICAgICAgICAgICAgICAgIG1yID0gbWFza2luZ19NU19yYXRpb1tncl9vdXRdW2NobiAtIDJdO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwcGUgPSBwZXJjZXBfZW50cm9weTtcbiAgICAgICAgICAgICAgICBwcGVQb3MgPSAwO1xuICAgICAgICAgICAgICAgIHR5cGUgPSBibG9ja3R5cGVfZFtjaG5dO1xuICAgICAgICAgICAgICAgIG1yID0gbWFza2luZ19yYXRpb1tncl9vdXRdW2Nobl07XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0eXBlID09IEVuY29kZXIuU0hPUlRfVFlQRSkge1xuICAgICAgICAgICAgICAgIHBwZVtwcGVQb3MgKyBjaG5dID0gcGVjYWxjX3MobXIsIGdmYy5tYXNraW5nX2xvd2VyKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcHBlW3BwZVBvcyArIGNobl0gPSBwZWNhbGNfbChtciwgZ2ZjLm1hc2tpbmdfbG93ZXIpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoZ2ZwLmFuYWx5c2lzKSB7XG4gICAgICAgICAgICAgICAgZ2ZjLnBpbmZvLnBlW2dyX291dF1bY2huXSA9IHBwZVtwcGVQb3MgKyBjaG5dO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHMzX2Z1bmNfeChiYXJrLCBoZl9zbG9wZSkge1xuICAgICAgICB2YXIgdGVtcHggPSBiYXJrLCB0ZW1weTtcblxuICAgICAgICBpZiAodGVtcHggPj0gMCkge1xuICAgICAgICAgICAgdGVtcHkgPSAtdGVtcHggKiAyNztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRlbXB5ID0gdGVtcHggKiBoZl9zbG9wZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodGVtcHkgPD0gLTcyLjApIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBNYXRoLmV4cCh0ZW1weSAqIExOX1RPX0xPRzEwKTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBub3JtX3MzX2Z1bmNfeChoZl9zbG9wZSkge1xuICAgICAgICB2YXIgbGltX2EgPSAwLCBsaW1fYiA9IDA7XG4gICAgICAgIHtcbiAgICAgICAgICAgIHZhciB4ID0gMCwgbCwgaDtcbiAgICAgICAgICAgIGZvciAoeCA9IDA7IHMzX2Z1bmNfeCh4LCBoZl9zbG9wZSkgPiAxZS0yMDsgeCAtPSAxKVxuICAgICAgICAgICAgICAgIDtcbiAgICAgICAgICAgIGwgPSB4O1xuICAgICAgICAgICAgaCA9IDA7XG4gICAgICAgICAgICB3aGlsZSAoTWF0aC5hYnMoaCAtIGwpID4gMWUtMTIpIHtcbiAgICAgICAgICAgICAgICB4ID0gKGggKyBsKSAvIDI7XG4gICAgICAgICAgICAgICAgaWYgKHMzX2Z1bmNfeCh4LCBoZl9zbG9wZSkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgIGggPSB4O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGwgPSB4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGxpbV9hID0gbDtcbiAgICAgICAgfVxuICAgICAgICB7XG4gICAgICAgICAgICB2YXIgeCA9IDAsIGwsIGg7XG4gICAgICAgICAgICBmb3IgKHggPSAwOyBzM19mdW5jX3goeCwgaGZfc2xvcGUpID4gMWUtMjA7IHggKz0gMSlcbiAgICAgICAgICAgICAgICA7XG4gICAgICAgICAgICBsID0gMDtcbiAgICAgICAgICAgIGggPSB4O1xuICAgICAgICAgICAgd2hpbGUgKE1hdGguYWJzKGggLSBsKSA+IDFlLTEyKSB7XG4gICAgICAgICAgICAgICAgeCA9IChoICsgbCkgLyAyO1xuICAgICAgICAgICAgICAgIGlmIChzM19mdW5jX3goeCwgaGZfc2xvcGUpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICBsID0geDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBoID0geDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBsaW1fYiA9IGg7XG4gICAgICAgIH1cbiAgICAgICAge1xuICAgICAgICAgICAgdmFyIHN1bSA9IDA7XG4gICAgICAgICAgICB2YXIgbSA9IDEwMDA7XG4gICAgICAgICAgICB2YXIgaTtcbiAgICAgICAgICAgIGZvciAoaSA9IDA7IGkgPD0gbTsgKytpKSB7XG4gICAgICAgICAgICAgICAgdmFyIHggPSBsaW1fYSArIGkgKiAobGltX2IgLSBsaW1fYSkgLyBtO1xuICAgICAgICAgICAgICAgIHZhciB5ID0gczNfZnVuY194KHgsIGhmX3Nsb3BlKTtcbiAgICAgICAgICAgICAgICBzdW0gKz0geTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICB2YXIgbm9ybSA9IChtICsgMSkgLyAoc3VtICogKGxpbV9iIC0gbGltX2EpKTtcbiAgICAgICAgICAgICAgICAvKiBwcmludGYoIFwibm9ybSA9ICVsZlxcblwiLG5vcm0pOyAqL1xuICAgICAgICAgICAgICAgIHJldHVybiBub3JtO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogICBUaGUgc3ByZWFkaW5nIGZ1bmN0aW9uLiAgVmFsdWVzIHJldHVybmVkIGluIHVuaXRzIG9mIGVuZXJneVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHMzX2Z1bmMoYmFyaykge1xuICAgICAgICB2YXIgdGVtcHgsIHgsIHRlbXB5LCB0ZW1wO1xuICAgICAgICB0ZW1weCA9IGJhcms7XG4gICAgICAgIGlmICh0ZW1weCA+PSAwKVxuICAgICAgICAgICAgdGVtcHggKj0gMztcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdGVtcHggKj0gMS41O1xuXG4gICAgICAgIGlmICh0ZW1weCA+PSAwLjUgJiYgdGVtcHggPD0gMi41KSB7XG4gICAgICAgICAgICB0ZW1wID0gdGVtcHggLSAwLjU7XG4gICAgICAgICAgICB4ID0gOC4wICogKHRlbXAgKiB0ZW1wIC0gMi4wICogdGVtcCk7XG4gICAgICAgIH0gZWxzZVxuICAgICAgICAgICAgeCA9IDAuMDtcbiAgICAgICAgdGVtcHggKz0gMC40NzQ7XG4gICAgICAgIHRlbXB5ID0gMTUuODExMzg5ICsgNy41ICogdGVtcHggLSAxNy41XG4gICAgICAgICAgICAqIE1hdGguc3FydCgxLjAgKyB0ZW1weCAqIHRlbXB4KTtcblxuICAgICAgICBpZiAodGVtcHkgPD0gLTYwLjApXG4gICAgICAgICAgICByZXR1cm4gMC4wO1xuXG4gICAgICAgIHRlbXB4ID0gTWF0aC5leHAoKHggKyB0ZW1weSkgKiBMTl9UT19MT0cxMCk7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxQUkU+XG4gICAgICAgICAqIE5vcm1hbGl6YXRpb24uICBUaGUgc3ByZWFkaW5nIGZ1bmN0aW9uIHNob3VsZCBiZSBub3JtYWxpemVkIHNvIHRoYXQ6XG4gICAgICAgICAqICtpbmZcbiAgICAgICAgICogL1xuICAgICAgICAgKiB8ICBzMyBbIGJhcmsgXSAgZChiYXJrKSAgID0gIDFcbiAgICAgICAgICogL1xuICAgICAgICAgKiAtaW5mXG4gICAgICAgICAqIDwvUFJFPlxuICAgICAgICAgKi9cbiAgICAgICAgdGVtcHggLz0gLjY2MDkxOTM7XG4gICAgICAgIHJldHVybiB0ZW1weDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBzZWUgZm9yIGV4YW1wbGUgXCJad2lja2VyOiBQc3ljaG9ha3VzdGlrLCAxOTgyOyBJU0JOIDMtNTQwLTExNDAxLTdcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBmcmVxMmJhcmsoZnJlcSkge1xuICAgICAgICAvKiBpbnB1dDogZnJlcSBpbiBoeiBvdXRwdXQ6IGJhcmtzICovXG4gICAgICAgIGlmIChmcmVxIDwgMClcbiAgICAgICAgICAgIGZyZXEgPSAwO1xuICAgICAgICBmcmVxID0gZnJlcSAqIDAuMDAxO1xuICAgICAgICByZXR1cm4gMTMuMCAqIE1hdGguYXRhbiguNzYgKiBmcmVxKSArIDMuNVxuICAgICAgICAgICAgKiBNYXRoLmF0YW4oZnJlcSAqIGZyZXEgLyAoNy41ICogNy41KSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gaW5pdF9udW1saW5lKG51bWxpbmVzLCBibywgYm0sIGJ2YWwsIGJ2YWxfd2lkdGgsIG1sZCwgYm9fdywgc2ZyZXEsIGJsa3NpemUsIHNjYWxlcG9zLCBkZWx0YWZyZXEsIHNibWF4KSB7XG4gICAgICAgIHZhciBiX2ZycSA9IG5ld19mbG9hdChFbmNvZGVyLkNCQU5EUyArIDEpO1xuICAgICAgICB2YXIgc2FtcGxlX2ZyZXFfZnJhYyA9IHNmcmVxIC8gKHNibWF4ID4gMTUgPyAyICogNTc2IDogMiAqIDE5Mik7XG4gICAgICAgIHZhciBwYXJ0aXRpb24gPSBuZXdfaW50KEVuY29kZXIuSEJMS1NJWkUpO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgc2ZyZXEgLz0gYmxrc2l6ZTtcbiAgICAgICAgdmFyIGogPSAwO1xuICAgICAgICB2YXIgbmkgPSAwO1xuICAgICAgICAvKiBjb21wdXRlIG51bWxpbmVzLCB0aGUgbnVtYmVyIG9mIHNwZWN0cmFsIGxpbmVzIGluIGVhY2ggcGFydGl0aW9uIGJhbmQgKi9cbiAgICAgICAgLyogZWFjaCBwYXJ0aXRpb24gYmFuZCBzaG91bGQgYmUgYWJvdXQgREVMQkFSSyB3aWRlLiAqL1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgRW5jb2Rlci5DQkFORFM7IGkrKykge1xuICAgICAgICAgICAgdmFyIGJhcmsxO1xuICAgICAgICAgICAgdmFyIGoyO1xuICAgICAgICAgICAgYmFyazEgPSBmcmVxMmJhcmsoc2ZyZXEgKiBqKTtcblxuICAgICAgICAgICAgYl9mcnFbaV0gPSBzZnJlcSAqIGo7XG5cbiAgICAgICAgICAgIGZvciAoajIgPSBqOyBmcmVxMmJhcmsoc2ZyZXEgKiBqMikgLSBiYXJrMSA8IERFTEJBUktcbiAgICAgICAgICAgICYmIGoyIDw9IGJsa3NpemUgLyAyOyBqMisrKVxuICAgICAgICAgICAgICAgIDtcblxuICAgICAgICAgICAgbnVtbGluZXNbaV0gPSBqMiAtIGo7XG4gICAgICAgICAgICBuaSA9IGkgKyAxO1xuXG4gICAgICAgICAgICB3aGlsZSAoaiA8IGoyKSB7XG4gICAgICAgICAgICAgICAgYXNzZXJ0KGogPCBFbmNvZGVyLkhCTEtTSVpFKTtcbiAgICAgICAgICAgICAgICBwYXJ0aXRpb25baisrXSA9IGk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaiA+IGJsa3NpemUgLyAyKSB7XG4gICAgICAgICAgICAgICAgaiA9IGJsa3NpemUgLyAyO1xuICAgICAgICAgICAgICAgICsraTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBhc3NlcnQoaSA8IEVuY29kZXIuQ0JBTkRTKTtcbiAgICAgICAgYl9mcnFbaV0gPSBzZnJlcSAqIGo7XG5cbiAgICAgICAgZm9yICh2YXIgc2ZiID0gMDsgc2ZiIDwgc2JtYXg7IHNmYisrKSB7XG4gICAgICAgICAgICB2YXIgaTEsIGkyLCBzdGFydCwgZW5kO1xuICAgICAgICAgICAgdmFyIGFyZztcbiAgICAgICAgICAgIHN0YXJ0ID0gc2NhbGVwb3Nbc2ZiXTtcbiAgICAgICAgICAgIGVuZCA9IHNjYWxlcG9zW3NmYiArIDFdO1xuXG4gICAgICAgICAgICBpMSA9IDAgfCBNYXRoLmZsb29yKC41ICsgZGVsdGFmcmVxICogKHN0YXJ0IC0gLjUpKTtcbiAgICAgICAgICAgIGlmIChpMSA8IDApXG4gICAgICAgICAgICAgICAgaTEgPSAwO1xuICAgICAgICAgICAgaTIgPSAwIHwgTWF0aC5mbG9vciguNSArIGRlbHRhZnJlcSAqIChlbmQgLSAuNSkpO1xuXG4gICAgICAgICAgICBpZiAoaTIgPiBibGtzaXplIC8gMilcbiAgICAgICAgICAgICAgICBpMiA9IGJsa3NpemUgLyAyO1xuXG4gICAgICAgICAgICBibVtzZmJdID0gKHBhcnRpdGlvbltpMV0gKyBwYXJ0aXRpb25baTJdKSAvIDI7XG4gICAgICAgICAgICBib1tzZmJdID0gcGFydGl0aW9uW2kyXTtcbiAgICAgICAgICAgIHZhciBmX3RtcCA9IHNhbXBsZV9mcmVxX2ZyYWMgKiBlbmQ7XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogY2FsY3VsYXRlIGhvdyBtdWNoIG9mIHRoaXMgYmFuZCBiZWxvbmdzIHRvIGN1cnJlbnQgc2NhbGVmYWN0b3JcbiAgICAgICAgICAgICAqIGJhbmRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgYm9fd1tzZmJdID0gKGZfdG1wIC0gYl9mcnFbYm9bc2ZiXV0pXG4gICAgICAgICAgICAgICAgLyAoYl9mcnFbYm9bc2ZiXSArIDFdIC0gYl9mcnFbYm9bc2ZiXV0pO1xuICAgICAgICAgICAgaWYgKGJvX3dbc2ZiXSA8IDApIHtcbiAgICAgICAgICAgICAgICBib193W3NmYl0gPSAwO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoYm9fd1tzZmJdID4gMSkge1xuICAgICAgICAgICAgICAgICAgICBib193W3NmYl0gPSAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8qIHNldHVwIHN0ZXJlbyBkZW1hc2tpbmcgdGhyZXNob2xkcyAqL1xuICAgICAgICAgICAgLyogZm9ybXVsYSByZXZlcnNlIGVuZ2luZXJyZWQgZnJvbSBwbG90IGluIHBhcGVyICovXG4gICAgICAgICAgICBhcmcgPSBmcmVxMmJhcmsoc2ZyZXEgKiBzY2FsZXBvc1tzZmJdICogZGVsdGFmcmVxKTtcbiAgICAgICAgICAgIGFyZyA9ICggTWF0aC5taW4oYXJnLCAxNS41KSAvIDE1LjUpO1xuXG4gICAgICAgICAgICBtbGRbc2ZiXSA9IE1hdGgucG93KDEwLjAsXG4gICAgICAgICAgICAgICAgMS4yNSAqICgxIC0gTWF0aC5jb3MoTWF0aC5QSSAqIGFyZykpIC0gMi41KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qIGNvbXB1dGUgYmFyayB2YWx1ZXMgb2YgZWFjaCBjcml0aWNhbCBiYW5kICovXG4gICAgICAgIGogPSAwO1xuICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IG5pOyBrKyspIHtcbiAgICAgICAgICAgIHZhciB3ID0gbnVtbGluZXNba107XG4gICAgICAgICAgICB2YXIgYmFyazEsIGJhcmsyO1xuXG4gICAgICAgICAgICBiYXJrMSA9IGZyZXEyYmFyayhzZnJlcSAqIChqKSk7XG4gICAgICAgICAgICBiYXJrMiA9IGZyZXEyYmFyayhzZnJlcSAqIChqICsgdyAtIDEpKTtcbiAgICAgICAgICAgIGJ2YWxba10gPSAuNSAqIChiYXJrMSArIGJhcmsyKTtcblxuICAgICAgICAgICAgYmFyazEgPSBmcmVxMmJhcmsoc2ZyZXEgKiAoaiAtIC41KSk7XG4gICAgICAgICAgICBiYXJrMiA9IGZyZXEyYmFyayhzZnJlcSAqIChqICsgdyAtIC41KSk7XG4gICAgICAgICAgICBidmFsX3dpZHRoW2tdID0gYmFyazIgLSBiYXJrMTtcbiAgICAgICAgICAgIGogKz0gdztcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBuaTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBpbml0X3MzX3ZhbHVlcyhzM2luZCwgbnBhcnQsIGJ2YWwsIGJ2YWxfd2lkdGgsIG5vcm0sIHVzZV9vbGRfczMpIHtcbiAgICAgICAgdmFyIHMzID0gbmV3X2Zsb2F0X24oW0VuY29kZXIuQ0JBTkRTLCBFbmNvZGVyLkNCQU5EU10pO1xuICAgICAgICAvKlxuICAgICAgICAgKiBUaGUgczMgYXJyYXkgaXMgbm90IGxpbmVhciBpbiB0aGUgYmFyayBzY2FsZS5cbiAgICAgICAgICpcbiAgICAgICAgICogYnZhbFt4XSBzaG91bGQgYmUgdXNlZCB0byBnZXQgdGhlIGJhcmsgdmFsdWUuXG4gICAgICAgICAqL1xuICAgICAgICB2YXIgajtcbiAgICAgICAgdmFyIG51bWJlck9mTm9uZVplcm8gPSAwO1xuXG4gICAgICAgIC8qKlxuICAgICAgICAgKiA8UFJFPlxuICAgICAgICAgKiBzW2ldW2pdLCB0aGUgdmFsdWUgb2YgdGhlIHNwcmVhZGluZyBmdW5jdGlvbixcbiAgICAgICAgICogY2VudGVyZWQgYXQgYmFuZCBqIChtYXNrZXIpLCBmb3IgYmFuZCBpIChtYXNrZWUpXG4gICAgICAgICAqXG4gICAgICAgICAqIGkuZS46IHN1bSBvdmVyIGogdG8gc3ByZWFkIGludG8gc2lnbmFsIGJhcmt2YWw9aVxuICAgICAgICAgKiBOT1RFOiBpIGFuZCBqIGFyZSB1c2VkIG9wcG9zaXRlIGFzIGluIHRoZSBJU08gZG9jc1xuICAgICAgICAgKiA8L1BSRT5cbiAgICAgICAgICovXG4gICAgICAgIGlmICh1c2Vfb2xkX3MzKSB7XG4gICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5wYXJ0OyBpKyspIHtcbiAgICAgICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbnBhcnQ7IGorKykge1xuICAgICAgICAgICAgICAgICAgICB2YXIgdiA9IHMzX2Z1bmMoYnZhbFtpXSAtIGJ2YWxbal0pICogYnZhbF93aWR0aFtqXTtcbiAgICAgICAgICAgICAgICAgICAgczNbaV1bal0gPSB2ICogbm9ybVtpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbnBhcnQ7IGorKykge1xuICAgICAgICAgICAgICAgIHZhciBoZl9zbG9wZSA9IDE1ICsgTWF0aC5taW4oMjEgLyBidmFsW2pdLCAxMik7XG4gICAgICAgICAgICAgICAgdmFyIHMzX3hfbm9ybSA9IG5vcm1fczNfZnVuY194KGhmX3Nsb3BlKTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5wYXJ0OyBpKyspIHtcbiAgICAgICAgICAgICAgICAgICAgdmFyIHYgPSBzM194X25vcm1cbiAgICAgICAgICAgICAgICAgICAgICAgICogczNfZnVuY194KGJ2YWxbaV0gLSBidmFsW2pdLCBoZl9zbG9wZSlcbiAgICAgICAgICAgICAgICAgICAgICAgICogYnZhbF93aWR0aFtqXTtcbiAgICAgICAgICAgICAgICAgICAgczNbaV1bal0gPSB2ICogbm9ybVtpXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBucGFydDsgaSsrKSB7XG4gICAgICAgICAgICBmb3IgKGogPSAwOyBqIDwgbnBhcnQ7IGorKykge1xuICAgICAgICAgICAgICAgIGlmIChzM1tpXVtqXSA+IDAuMClcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzM2luZFtpXVswXSA9IGo7XG5cbiAgICAgICAgICAgIGZvciAoaiA9IG5wYXJ0IC0gMTsgaiA+IDA7IGotLSkge1xuICAgICAgICAgICAgICAgIGlmIChzM1tpXVtqXSA+IDAuMClcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzM2luZFtpXVsxXSA9IGo7XG4gICAgICAgICAgICBudW1iZXJPZk5vbmVaZXJvICs9IChzM2luZFtpXVsxXSAtIHMzaW5kW2ldWzBdICsgMSk7XG4gICAgICAgIH1cblxuICAgICAgICB2YXIgcCA9IG5ld19mbG9hdChudW1iZXJPZk5vbmVaZXJvKTtcbiAgICAgICAgdmFyIGsgPSAwO1xuICAgICAgICBmb3IgKHZhciBpID0gMDsgaSA8IG5wYXJ0OyBpKyspXG4gICAgICAgICAgICBmb3IgKGogPSBzM2luZFtpXVswXTsgaiA8PSBzM2luZFtpXVsxXTsgaisrKVxuICAgICAgICAgICAgICAgIHBbaysrXSA9IHMzW2ldW2pdO1xuXG4gICAgICAgIHJldHVybiBwO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHN0ZXJlb19kZW1hc2soZikge1xuICAgICAgICAvKiBzZXR1cCBzdGVyZW8gZGVtYXNraW5nIHRocmVzaG9sZHMgKi9cbiAgICAgICAgLyogZm9ybXVsYSByZXZlcnNlIGVuZ2luZXJyZWQgZnJvbSBwbG90IGluIHBhcGVyICovXG4gICAgICAgIHZhciBhcmcgPSBmcmVxMmJhcmsoZik7XG4gICAgICAgIGFyZyA9IChNYXRoLm1pbihhcmcsIDE1LjUpIC8gMTUuNSk7XG5cbiAgICAgICAgcmV0dXJuIE1hdGgucG93KDEwLjAsXG4gICAgICAgICAgICAxLjI1ICogKDEgLSBNYXRoLmNvcyhNYXRoLlBJICogYXJnKSkgLSAyLjUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE5PVEU6IHRoZSBiaXRyYXRlIHJlZHVjdGlvbiBmcm9tIHRoZSBpbnRlci1jaGFubmVsIG1hc2tpbmcgZWZmZWN0IGlzIGxvd1xuICAgICAqIGNvbXBhcmVkIHRvIHRoZSBjaGFuY2Ugb2YgZ2V0dGluZyBhbm55b2luZyBhcnRlZmFjdHMuIEwzcHN5Y2hvX2FuYWxfdmJyXG4gICAgICogZG9lcyBub3QgdXNlIHRoaXMgZmVhdHVyZS4gKFJvYmVydCAwNzEyMTYpXG4gICAgICovXG4gICAgdGhpcy5wc3ltb2RlbF9pbml0ID0gZnVuY3Rpb24gKGdmcCkge1xuICAgICAgICB2YXIgZ2ZjID0gZ2ZwLmludGVybmFsX2ZsYWdzO1xuICAgICAgICB2YXIgaTtcbiAgICAgICAgdmFyIHVzZU9sZFMzID0gdHJ1ZTtcbiAgICAgICAgdmFyIGJ2bF9hID0gMTMsIGJ2bF9iID0gMjQ7XG4gICAgICAgIHZhciBzbnJfbF9hID0gMCwgc25yX2xfYiA9IDA7XG4gICAgICAgIHZhciBzbnJfc19hID0gLTguMjUsIHNucl9zX2IgPSAtNC41O1xuICAgICAgICB2YXIgYnZhbCA9IG5ld19mbG9hdChFbmNvZGVyLkNCQU5EUyk7XG4gICAgICAgIHZhciBidmFsX3dpZHRoID0gbmV3X2Zsb2F0KEVuY29kZXIuQ0JBTkRTKTtcbiAgICAgICAgdmFyIG5vcm0gPSBuZXdfZmxvYXQoRW5jb2Rlci5DQkFORFMpO1xuICAgICAgICB2YXIgc2ZyZXEgPSBnZnAub3V0X3NhbXBsZXJhdGU7XG5cbiAgICAgICAgc3dpdGNoIChnZnAuZXhwZXJpbWVudGFsWikge1xuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICB1c2VPbGRTMyA9IHRydWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgdXNlT2xkUzMgPSAoZ2ZwLlZCUiA9PSBWYnJNb2RlLnZicl9tdHJoIHx8IGdmcC5WQlIgPT0gVmJyTW9kZS52YnJfbXQpID8gZmFsc2VcbiAgICAgICAgICAgICAgICAgICAgOiB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIHVzZU9sZFMzID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgYnZsX2EgPSA4O1xuICAgICAgICAgICAgICAgIHNucl9sX2EgPSAtMS43NTtcbiAgICAgICAgICAgICAgICBzbnJfbF9iID0gLTAuMDEyNTtcbiAgICAgICAgICAgICAgICBzbnJfc19hID0gLTguMjU7XG4gICAgICAgICAgICAgICAgc25yX3NfYiA9IC0yLjI1O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGdmYy5tc19lbmVyX3JhdGlvX29sZCA9IC4yNTtcbiAgICAgICAgZ2ZjLmJsb2NrdHlwZV9vbGRbMF0gPSBnZmMuYmxvY2t0eXBlX29sZFsxXSA9IEVuY29kZXIuTk9STV9UWVBFO1xuICAgICAgICAvLyB0aGUgdmJyIGhlYWRlciBpcyBsb25nIGJsb2Nrc1xuXG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCA0OyArK2kpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgRW5jb2Rlci5DQkFORFM7ICsraikge1xuICAgICAgICAgICAgICAgIGdmYy5uYl8xW2ldW2pdID0gMWUyMDtcbiAgICAgICAgICAgICAgICBnZmMubmJfMltpXVtqXSA9IDFlMjA7XG4gICAgICAgICAgICAgICAgZ2ZjLm5iX3MxW2ldW2pdID0gZ2ZjLm5iX3MyW2ldW2pdID0gMS4wO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZm9yICh2YXIgc2IgPSAwOyBzYiA8IEVuY29kZXIuU0JNQVhfbDsgc2IrKykge1xuICAgICAgICAgICAgICAgIGdmYy5lbltpXS5sW3NiXSA9IDFlMjA7XG4gICAgICAgICAgICAgICAgZ2ZjLnRobVtpXS5sW3NiXSA9IDFlMjA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDM7ICsraikge1xuICAgICAgICAgICAgICAgIGZvciAodmFyIHNiID0gMDsgc2IgPCBFbmNvZGVyLlNCTUFYX3M7IHNiKyspIHtcbiAgICAgICAgICAgICAgICAgICAgZ2ZjLmVuW2ldLnNbc2JdW2pdID0gMWUyMDtcbiAgICAgICAgICAgICAgICAgICAgZ2ZjLnRobVtpXS5zW3NiXVtqXSA9IDFlMjA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGdmYy5uc1BzeS5sYXN0QXR0YWNrc1tpXSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBmb3IgKHZhciBqID0gMDsgaiA8IDk7IGorKylcbiAgICAgICAgICAgICAgICBnZmMubnNQc3kubGFzdF9lbl9zdWJzaG9ydFtpXVtqXSA9IDEwLjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8qIGluaXQuIGZvciBsb3VkbmVzcyBhcHByb3guIC1qZCAyMDAxIG1hciAyNyAqL1xuICAgICAgICBnZmMubG91ZG5lc3Nfc3Ffc2F2ZVswXSA9IGdmYy5sb3VkbmVzc19zcV9zYXZlWzFdID0gMC4wO1xuXG4gICAgICAgIC8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgICAqIG5vdyBjb21wdXRlIHRoZSBwc3ljaG9hY291c3RpYyBtb2RlbCBzcGVjaWZpYyBjb25zdGFudHNcbiAgICAgICAgICoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKi9cbiAgICAgICAgLyogY29tcHV0ZSBudW1saW5lcywgYm8sIGJtLCBidmFsLCBidmFsX3dpZHRoLCBtbGQgKi9cblxuICAgICAgICBnZmMubnBhcnRfbCA9IGluaXRfbnVtbGluZShnZmMubnVtbGluZXNfbCwgZ2ZjLmJvX2wsIGdmYy5ibV9sLCBidmFsLFxuICAgICAgICAgICAgYnZhbF93aWR0aCwgZ2ZjLm1sZF9sLCBnZmMuUFNZLmJvX2xfd2VpZ2h0LCBzZnJlcSxcbiAgICAgICAgICAgIEVuY29kZXIuQkxLU0laRSwgZ2ZjLnNjYWxlZmFjX2JhbmQubCwgRW5jb2Rlci5CTEtTSVpFXG4gICAgICAgICAgICAvICgyLjAgKiA1NzYpLCBFbmNvZGVyLlNCTUFYX2wpO1xuICAgICAgICBhc3NlcnQoZ2ZjLm5wYXJ0X2wgPCBFbmNvZGVyLkNCQU5EUyk7XG4gICAgICAgIC8qIGNvbXB1dGUgdGhlIHNwcmVhZGluZyBmdW5jdGlvbiAqL1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgZ2ZjLm5wYXJ0X2w7IGkrKykge1xuICAgICAgICAgICAgdmFyIHNuciA9IHNucl9sX2E7XG4gICAgICAgICAgICBpZiAoYnZhbFtpXSA+PSBidmxfYSkge1xuICAgICAgICAgICAgICAgIHNuciA9IHNucl9sX2IgKiAoYnZhbFtpXSAtIGJ2bF9hKSAvIChidmxfYiAtIGJ2bF9hKSArIHNucl9sX2FcbiAgICAgICAgICAgICAgICAgICAgKiAoYnZsX2IgLSBidmFsW2ldKSAvIChidmxfYiAtIGJ2bF9hKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5vcm1baV0gPSBNYXRoLnBvdygxMC4wLCBzbnIgLyAxMC4wKTtcbiAgICAgICAgICAgIGlmIChnZmMubnVtbGluZXNfbFtpXSA+IDApIHtcbiAgICAgICAgICAgICAgICBnZmMucm51bWxpbmVzX2xbaV0gPSAxLjAgLyBnZmMubnVtbGluZXNfbFtpXTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZ2ZjLnJudW1saW5lc19sW2ldID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBnZmMuczNfbGwgPSBpbml0X3MzX3ZhbHVlcyhnZmMuczNpbmQsIGdmYy5ucGFydF9sLCBidmFsLCBidmFsX3dpZHRoLFxuICAgICAgICAgICAgbm9ybSwgdXNlT2xkUzMpO1xuXG4gICAgICAgIC8qIGNvbXB1dGUgbG9uZyBibG9jayBzcGVjaWZpYyB2YWx1ZXMsIEFUSCBhbmQgTUlOVkFMICovXG4gICAgICAgIHZhciBqID0gMDtcbiAgICAgICAgZm9yIChpID0gMDsgaSA8IGdmYy5ucGFydF9sOyBpKyspIHtcbiAgICAgICAgICAgIHZhciB4O1xuXG4gICAgICAgICAgICAvKiBBVEggKi9cbiAgICAgICAgICAgIHggPSBGbG9hdC5NQVhfVkFMVUU7XG4gICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGdmYy5udW1saW5lc19sW2ldOyBrKyssIGorKykge1xuICAgICAgICAgICAgICAgIHZhciBmcmVxID0gc2ZyZXEgKiBqIC8gKDEwMDAuMCAqIEVuY29kZXIuQkxLU0laRSk7XG4gICAgICAgICAgICAgICAgdmFyIGxldmVsO1xuICAgICAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgICAgICogQVRIIGJlbG93IDEwMCBIeiBjb25zdGFudCwgbm90IGZ1cnRoZXIgY2xpbWJpbmdcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBsZXZlbCA9IHRoaXMuQVRIZm9ybXVsYShmcmVxICogMTAwMCwgZ2ZwKSAtIDIwO1xuICAgICAgICAgICAgICAgIC8vIHNjYWxlIHRvIEZGVCB1bml0czsgcmV0dXJuZWQgdmFsdWUgaXMgaW4gZEJcbiAgICAgICAgICAgICAgICBsZXZlbCA9IE1hdGgucG93KDEwLiwgMC4xICogbGV2ZWwpO1xuICAgICAgICAgICAgICAgIC8vIGNvbnZlcnQgZnJvbSBkQiAuIGVuZXJneVxuICAgICAgICAgICAgICAgIGxldmVsICo9IGdmYy5udW1saW5lc19sW2ldO1xuICAgICAgICAgICAgICAgIGlmICh4ID4gbGV2ZWwpXG4gICAgICAgICAgICAgICAgICAgIHggPSBsZXZlbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGdmYy5BVEguY2JfbFtpXSA9IHg7XG5cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBNSU5WQUwuIEZvciBsb3cgZnJlcSwgdGhlIHN0cmVuZ3RoIG9mIHRoZSBtYXNraW5nIGlzIGxpbWl0ZWQgYnlcbiAgICAgICAgICAgICAqIG1pbnZhbCB0aGlzIGlzIGFuIElTTyBNUEVHMSB0aGluZywgZG9udCBrbm93IGlmIGl0IGlzIHJlYWxseVxuICAgICAgICAgICAgICogbmVlZGVkXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBGSVhNRTogaXQgZG9lcyB3b3JrIHRvIHJlZHVjZSBsb3ctZnJlcSBwcm9ibGVtcyBpbiBTNTMtV2luZC1TYXhcbiAgICAgICAgICAgICAqIGFuZCBsZWFkLXZvaWNlIHNhbXBsZXMsIGJ1dCBpbnRyb2R1Y2VzIHNvbWUgMyBrYnBzIGJpdCBibG9hdCB0b28uXG4gICAgICAgICAgICAgKiBUT0RPOiBGdXJ0aGVyIHJlZmluZW1lbnQgb2YgdGhlIHNoYXBlIG9mIHRoaXMgaGFjay5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgeCA9IC0yMCArIGJ2YWxbaV0gKiAyMCAvIDEwO1xuICAgICAgICAgICAgaWYgKHggPiA2KSB7XG4gICAgICAgICAgICAgICAgeCA9IDEwMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICh4IDwgLTE1KSB7XG4gICAgICAgICAgICAgICAgeCA9IC0xNTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHggLT0gOC47XG4gICAgICAgICAgICBnZmMubWludmFsX2xbaV0gPSAoTWF0aC5wb3coMTAuMCwgeCAvIDEwLikgKiBnZmMubnVtbGluZXNfbFtpXSk7XG4gICAgICAgIH1cblxuICAgICAgICAvKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICAgICAqIGRvIHRoZSBzYW1lIHRoaW5ncyBmb3Igc2hvcnQgYmxvY2tzXG4gICAgICAgICAqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG4gICAgICAgIGdmYy5ucGFydF9zID0gaW5pdF9udW1saW5lKGdmYy5udW1saW5lc19zLCBnZmMuYm9fcywgZ2ZjLmJtX3MsIGJ2YWwsXG4gICAgICAgICAgICBidmFsX3dpZHRoLCBnZmMubWxkX3MsIGdmYy5QU1kuYm9fc193ZWlnaHQsIHNmcmVxLFxuICAgICAgICAgICAgRW5jb2Rlci5CTEtTSVpFX3MsIGdmYy5zY2FsZWZhY19iYW5kLnMsIEVuY29kZXIuQkxLU0laRV9zXG4gICAgICAgICAgICAvICgyLjAgKiAxOTIpLCBFbmNvZGVyLlNCTUFYX3MpO1xuICAgICAgICBhc3NlcnQoZ2ZjLm5wYXJ0X3MgPCBFbmNvZGVyLkNCQU5EUyk7XG5cbiAgICAgICAgLyogU05SIGZvcm11bGEuIHNob3J0IGJsb2NrIGlzIG5vcm1hbGl6ZWQgYnkgU05SLiBpcyBpdCBzdGlsbCByaWdodCA/ICovXG4gICAgICAgIGogPSAwO1xuICAgICAgICBmb3IgKGkgPSAwOyBpIDwgZ2ZjLm5wYXJ0X3M7IGkrKykge1xuICAgICAgICAgICAgdmFyIHg7XG4gICAgICAgICAgICB2YXIgc25yID0gc25yX3NfYTtcbiAgICAgICAgICAgIGlmIChidmFsW2ldID49IGJ2bF9hKSB7XG4gICAgICAgICAgICAgICAgc25yID0gc25yX3NfYiAqIChidmFsW2ldIC0gYnZsX2EpIC8gKGJ2bF9iIC0gYnZsX2EpICsgc25yX3NfYVxuICAgICAgICAgICAgICAgICAgICAqIChidmxfYiAtIGJ2YWxbaV0pIC8gKGJ2bF9iIC0gYnZsX2EpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgbm9ybVtpXSA9IE1hdGgucG93KDEwLjAsIHNuciAvIDEwLjApO1xuXG4gICAgICAgICAgICAvKiBBVEggKi9cbiAgICAgICAgICAgIHggPSBGbG9hdC5NQVhfVkFMVUU7XG4gICAgICAgICAgICBmb3IgKHZhciBrID0gMDsgayA8IGdmYy5udW1saW5lc19zW2ldOyBrKyssIGorKykge1xuICAgICAgICAgICAgICAgIHZhciBmcmVxID0gc2ZyZXEgKiBqIC8gKDEwMDAuMCAqIEVuY29kZXIuQkxLU0laRV9zKTtcbiAgICAgICAgICAgICAgICB2YXIgbGV2ZWw7XG4gICAgICAgICAgICAgICAgLyogZnJlcSA9IE1pbiguMSxmcmVxKTsgKi9cbiAgICAgICAgICAgICAgICAvKlxuICAgICAgICAgICAgICAgICAqIEFUSCBiZWxvdyAxMDAgSHogY29uc3RhbnQsIG5vdFxuICAgICAgICAgICAgICAgICAqIGZ1cnRoZXIgY2xpbWJpbmdcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBsZXZlbCA9IHRoaXMuQVRIZm9ybXVsYShmcmVxICogMTAwMCwgZ2ZwKSAtIDIwO1xuICAgICAgICAgICAgICAgIC8vIHNjYWxlIHRvIEZGVCB1bml0czsgcmV0dXJuZWQgdmFsdWUgaXMgaW4gZEJcbiAgICAgICAgICAgICAgICBsZXZlbCA9IE1hdGgucG93KDEwLiwgMC4xICogbGV2ZWwpO1xuICAgICAgICAgICAgICAgIC8vIGNvbnZlcnQgZnJvbSBkQiAuIGVuZXJneVxuICAgICAgICAgICAgICAgIGxldmVsICo9IGdmYy5udW1saW5lc19zW2ldO1xuICAgICAgICAgICAgICAgIGlmICh4ID4gbGV2ZWwpXG4gICAgICAgICAgICAgICAgICAgIHggPSBsZXZlbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGdmYy5BVEguY2Jfc1tpXSA9IHg7XG5cbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBNSU5WQUwuIEZvciBsb3cgZnJlcSwgdGhlIHN0cmVuZ3RoIG9mIHRoZSBtYXNraW5nIGlzIGxpbWl0ZWQgYnlcbiAgICAgICAgICAgICAqIG1pbnZhbCB0aGlzIGlzIGFuIElTTyBNUEVHMSB0aGluZywgZG9udCBrbm93IGlmIGl0IGlzIHJlYWxseVxuICAgICAgICAgICAgICogbmVlZGVkXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHggPSAoLTcuMCArIGJ2YWxbaV0gKiA3LjAgLyAxMi4wKTtcbiAgICAgICAgICAgIGlmIChidmFsW2ldID4gMTIpIHtcbiAgICAgICAgICAgICAgICB4ICo9IDEgKyBNYXRoLmxvZygxICsgeCkgKiAzLjE7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoYnZhbFtpXSA8IDEyKSB7XG4gICAgICAgICAgICAgICAgeCAqPSAxICsgTWF0aC5sb2coMSAtIHgpICogMi4zO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKHggPCAtMTUpIHtcbiAgICAgICAgICAgICAgICB4ID0gLTE1O1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgeCAtPSA4O1xuICAgICAgICAgICAgZ2ZjLm1pbnZhbF9zW2ldID0gTWF0aC5wb3coMTAuMCwgeCAvIDEwKVxuICAgICAgICAgICAgICAgICogZ2ZjLm51bWxpbmVzX3NbaV07XG4gICAgICAgIH1cblxuICAgICAgICBnZmMuczNfc3MgPSBpbml0X3MzX3ZhbHVlcyhnZmMuczNpbmRfcywgZ2ZjLm5wYXJ0X3MsIGJ2YWwsIGJ2YWxfd2lkdGgsXG4gICAgICAgICAgICBub3JtLCB1c2VPbGRTMyk7XG5cbiAgICAgICAgaW5pdF9tYXNrX2FkZF9tYXhfdmFsdWVzKCk7XG4gICAgICAgIGZmdC5pbml0X2ZmdChnZmMpO1xuXG4gICAgICAgIC8qIHNldHVwIHRlbXBvcmFsIG1hc2tpbmcgKi9cbiAgICAgICAgZ2ZjLmRlY2F5ID0gTWF0aC5leHAoLTEuMCAqIExPRzEwXG4gICAgICAgICAgICAvICh0ZW1wb3JhbG1hc2tfc3VzdGFpbl9zZWMgKiBzZnJlcSAvIDE5Mi4wKSk7XG5cbiAgICAgICAge1xuICAgICAgICAgICAgdmFyIG1zZml4O1xuICAgICAgICAgICAgbXNmaXggPSBOU19NU0ZJWDtcbiAgICAgICAgICAgIGlmICgoZ2ZwLmV4cF9uc3BzeXR1bmUgJiAyKSAhPSAwKVxuICAgICAgICAgICAgICAgIG1zZml4ID0gMS4wO1xuICAgICAgICAgICAgaWYgKE1hdGguYWJzKGdmcC5tc2ZpeCkgPiAwLjApXG4gICAgICAgICAgICAgICAgbXNmaXggPSBnZnAubXNmaXg7XG4gICAgICAgICAgICBnZnAubXNmaXggPSBtc2ZpeDtcblxuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIHNwcmVhZCBvbmx5IGZyb20gbnBhcnRfbCBiYW5kcy4gTm9ybWFsbHksIHdlIHVzZSB0aGUgc3ByZWFkaW5nXG4gICAgICAgICAgICAgKiBmdW5jdGlvbiB0byBjb252b2x2ZSBmcm9tIG5wYXJ0X2wgZG93biB0byBucGFydF9sIGJhbmRzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGZvciAodmFyIGIgPSAwOyBiIDwgZ2ZjLm5wYXJ0X2w7IGIrKylcbiAgICAgICAgICAgICAgICBpZiAoZ2ZjLnMzaW5kW2JdWzFdID4gZ2ZjLm5wYXJ0X2wgLSAxKVxuICAgICAgICAgICAgICAgICAgICBnZmMuczNpbmRbYl1bMV0gPSBnZmMubnBhcnRfbCAtIDE7XG4gICAgICAgIH1cblxuICAgICAgICAvKlxuICAgICAgICAgKiBwcmVwYXJlIGZvciBBVEggYXV0byBhZGp1c3RtZW50OiB3ZSB3YW50IHRvIGRlY3JlYXNlIHRoZSBBVEggYnkgMTIgZEJcbiAgICAgICAgICogcGVyIHNlY29uZFxuICAgICAgICAgKi9cbiAgICAgICAgdmFyIGZyYW1lX2R1cmF0aW9uID0gKDU3Ni4gKiBnZmMubW9kZV9nciAvIHNmcmVxKTtcbiAgICAgICAgZ2ZjLkFUSC5kZWNheSA9IE1hdGgucG93KDEwLiwgLTEyLiAvIDEwLiAqIGZyYW1lX2R1cmF0aW9uKTtcbiAgICAgICAgZ2ZjLkFUSC5hZGp1c3QgPSAwLjAxO1xuICAgICAgICAvKiBtaW5pbXVtLCBmb3IgbGVhZGluZyBsb3cgbG91ZG5lc3MgKi9cbiAgICAgICAgZ2ZjLkFUSC5hZGp1c3RMaW1pdCA9IDEuMDtcbiAgICAgICAgLyogb24gbGVhZCwgYWxsb3cgYWRqdXN0IHVwIHRvIG1heGltdW0gKi9cblxuICAgICAgICBhc3NlcnQoZ2ZjLmJvX2xbRW5jb2Rlci5TQk1BWF9sIC0gMV0gPD0gZ2ZjLm5wYXJ0X2wpO1xuICAgICAgICBhc3NlcnQoZ2ZjLmJvX3NbRW5jb2Rlci5TQk1BWF9zIC0gMV0gPD0gZ2ZjLm5wYXJ0X3MpO1xuXG4gICAgICAgIGlmIChnZnAuQVRIdHlwZSAhPSAtMSkge1xuICAgICAgICAgICAgLyogY29tcHV0ZSBlcXVhbCBsb3VkbmVzcyB3ZWlnaHRzIChlcWxfdykgKi9cbiAgICAgICAgICAgIHZhciBmcmVxO1xuICAgICAgICAgICAgdmFyIGZyZXFfaW5jID0gZ2ZwLm91dF9zYW1wbGVyYXRlXG4gICAgICAgICAgICAgICAgLyAoRW5jb2Rlci5CTEtTSVpFKTtcbiAgICAgICAgICAgIHZhciBlcWxfYmFsYW5jZSA9IDAuMDtcbiAgICAgICAgICAgIGZyZXEgPSAwLjA7XG4gICAgICAgICAgICBmb3IgKGkgPSAwOyBpIDwgRW5jb2Rlci5CTEtTSVpFIC8gMjsgKytpKSB7XG4gICAgICAgICAgICAgICAgLyogY29udmVydCBBVEggZEIgdG8gcmVsYXRpdmUgcG93ZXIgKG5vdCBkQikgKi9cbiAgICAgICAgICAgICAgICAvKiB0byBkZXRlcm1pbmUgZXFsX3cgKi9cbiAgICAgICAgICAgICAgICBmcmVxICs9IGZyZXFfaW5jO1xuICAgICAgICAgICAgICAgIGdmYy5BVEguZXFsX3dbaV0gPSAxLiAvIE1hdGgucG93KDEwLCB0aGlzLkFUSGZvcm11bGEoZnJlcSwgZ2ZwKSAvIDEwKTtcbiAgICAgICAgICAgICAgICBlcWxfYmFsYW5jZSArPSBnZmMuQVRILmVxbF93W2ldO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZXFsX2JhbGFuY2UgPSAxLjAgLyBlcWxfYmFsYW5jZTtcbiAgICAgICAgICAgIGZvciAoaSA9IEVuY29kZXIuQkxLU0laRSAvIDI7IC0taSA+PSAwOykgeyAvKiBzY2FsZSB3ZWlnaHRzICovXG4gICAgICAgICAgICAgICAgZ2ZjLkFUSC5lcWxfd1tpXSAqPSBlcWxfYmFsYW5jZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB7XG4gICAgICAgICAgICBmb3IgKHZhciBiID0gaiA9IDA7IGIgPCBnZmMubnBhcnRfczsgKytiKSB7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGdmYy5udW1saW5lc19zW2JdOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgKytqO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzc2VydChqID09IDEyOSk7XG4gICAgICAgICAgICBmb3IgKHZhciBiID0gaiA9IDA7IGIgPCBnZmMubnBhcnRfbDsgKytiKSB7XG4gICAgICAgICAgICAgICAgZm9yIChpID0gMDsgaSA8IGdmYy5udW1saW5lc19sW2JdOyArK2kpIHtcbiAgICAgICAgICAgICAgICAgICAgKytqO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGFzc2VydChqID09IDUxMyk7XG4gICAgICAgIH1cbiAgICAgICAgaiA9IDA7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBnZmMubnBhcnRfbDsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZnJlcSA9IHNmcmVxICogKGogKyBnZmMubnVtbGluZXNfbFtpXSAvIDIpIC8gKDEuMCAqIEVuY29kZXIuQkxLU0laRSk7XG4gICAgICAgICAgICBnZmMubWxkX2NiX2xbaV0gPSBzdGVyZW9fZGVtYXNrKGZyZXEpO1xuICAgICAgICAgICAgaiArPSBnZmMubnVtbGluZXNfbFtpXTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKDsgaSA8IEVuY29kZXIuQ0JBTkRTOyArK2kpIHtcbiAgICAgICAgICAgIGdmYy5tbGRfY2JfbFtpXSA9IDE7XG4gICAgICAgIH1cbiAgICAgICAgaiA9IDA7XG4gICAgICAgIGZvciAoaSA9IDA7IGkgPCBnZmMubnBhcnRfczsgaSsrKSB7XG4gICAgICAgICAgICB2YXIgZnJlcSA9IHNmcmVxICogKGogKyBnZmMubnVtbGluZXNfc1tpXSAvIDIpIC8gKDEuMCAqIEVuY29kZXIuQkxLU0laRV9zKTtcbiAgICAgICAgICAgIGdmYy5tbGRfY2Jfc1tpXSA9IHN0ZXJlb19kZW1hc2soZnJlcSk7XG4gICAgICAgICAgICBqICs9IGdmYy5udW1saW5lc19zW2ldO1xuICAgICAgICB9XG4gICAgICAgIGZvciAoOyBpIDwgRW5jb2Rlci5DQkFORFM7ICsraSkge1xuICAgICAgICAgICAgZ2ZjLm1sZF9jYl9zW2ldID0gMTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaG9zZSBBVEggZm9ybXVsYXMgYXJlIHJldHVybmluZyB0aGVpciBtaW5pbXVtIHZhbHVlIGZvciBpbnB1dCA9IC0xXG4gICAgICovXG4gICAgZnVuY3Rpb24gQVRIZm9ybXVsYV9HQihmLCB2YWx1ZSkge1xuICAgICAgICAvKipcbiAgICAgICAgICogPFBSRT5cbiAgICAgICAgICogIGZyb20gUGFpbnRlciAmIFNwYW5pYXNcbiAgICAgICAgICogICAgICAgICAgIG1vZGlmaWVkIGJ5IEdhYnJpZWwgQm91dmlnbmUgdG8gYmV0dGVyIGZpdCB0aGUgcmVhbGl0eVxuICAgICAgICAgKiAgICAgICAgICAgYXRoID0gICAgMy42NDAgKiBwb3coZiwtMC44KVxuICAgICAgICAgKiAgICAgICAgICAgLSA2LjgwMCAqIGV4cCgtMC42KnBvdyhmLTMuNCwyLjApKVxuICAgICAgICAgKiAgICAgICAgICAgKyA2LjAwMCAqIGV4cCgtMC4xNSpwb3coZi04LjcsMi4wKSlcbiAgICAgICAgICogICAgICAgICAgICsgMC42KiAwLjAwMSAqIHBvdyhmLDQuMCk7XG4gICAgICAgICAqXG4gICAgICAgICAqXG4gICAgICAgICAqICAgICAgICAgICBJbiB0aGUgcGFzdCBMQU1FIHdhcyB1c2luZyB0aGUgUGFpbnRlciAmU3BhbmlhcyBmb3JtdWxhLlxuICAgICAgICAgKiAgICAgICAgICAgQnV0IHdlIGhhZCBzb21lIHJlY3VycmVudCBwcm9ibGVtcyB3aXRoIEhGIGNvbnRlbnQuXG4gICAgICAgICAqICAgICAgICAgICBXZSBtZWFzdXJlZCByZWFsIEFUSCB2YWx1ZXMsIGFuZCBmb3VuZCB0aGUgb2xkZXIgZm9ybXVsYVxuICAgICAgICAgKiAgICAgICAgICAgdG8gYmUgaW5hY2N1cmF0ZSBpbiB0aGUgaGlnaGVyIHBhcnQuIFNvIHdlIG1hZGUgdGhpcyBuZXdcbiAgICAgICAgICogICAgICAgICAgIGZvcm11bGEgYW5kIHRoaXMgc29sdmVkIG1vc3Qgb2YgSEYgcHJvYmxlbWF0aWMgdGVzdCBjYXNlcy5cbiAgICAgICAgICogICAgICAgICAgIFRoZSB0cmFkZW9mZiBpcyB0aGF0IGluIFZCUiBtb2RlIGl0IGluY3JlYXNlcyBhIGxvdCB0aGVcbiAgICAgICAgICogICAgICAgICAgIGJpdHJhdGUuXG4gICAgICAgICAqIDwvUFJFPlxuICAgICAgICAgKi9cblxuICAgICAgICAvKlxuICAgICAgICAgKiBUaGlzIGN1cnZlIGNhbiBiZSBhZGp1c3RlZCBhY2NvcmRpbmcgdG8gdGhlIFZCUiBzY2FsZTogaXQgYWRqdXN0c1xuICAgICAgICAgKiBmcm9tIHNvbWV0aGluZyBjbG9zZSB0byBQYWludGVyICYgU3BhbmlhcyBvbiBWOSB1cCB0byBCb3V2aWduZSdzXG4gICAgICAgICAqIGZvcm11bGEgZm9yIFYwLiBUaGlzIHdheSB0aGUgVkJSIGJpdHJhdGUgaXMgbW9yZSBiYWxhbmNlZCBhY2NvcmRpbmdcbiAgICAgICAgICogdG8gdGhlIC1WIHZhbHVlLlxuICAgICAgICAgKi9cblxuICAgICAgICAvLyB0aGUgZm9sbG93aW5nIEhhY2sgYWxsb3dzIHRvIGFzayBmb3IgdGhlIGxvd2VzdCB2YWx1ZVxuICAgICAgICBpZiAoZiA8IC0uMylcbiAgICAgICAgICAgIGYgPSAzNDEwO1xuXG4gICAgICAgIC8vIGNvbnZlcnQgdG8ga2h6XG4gICAgICAgIGYgLz0gMTAwMDtcbiAgICAgICAgZiA9IE1hdGgubWF4KDAuMSwgZik7XG4gICAgICAgIHZhciBhdGggPSAzLjY0MCAqIE1hdGgucG93KGYsIC0wLjgpIC0gNi44MDBcbiAgICAgICAgICAgICogTWF0aC5leHAoLTAuNiAqIE1hdGgucG93KGYgLSAzLjQsIDIuMCkpICsgNi4wMDBcbiAgICAgICAgICAgICogTWF0aC5leHAoLTAuMTUgKiBNYXRoLnBvdyhmIC0gOC43LCAyLjApKVxuICAgICAgICAgICAgKyAoMC42ICsgMC4wNCAqIHZhbHVlKSAqIDAuMDAxICogTWF0aC5wb3coZiwgNC4wKTtcbiAgICAgICAgcmV0dXJuIGF0aDtcbiAgICB9XG5cbiAgICB0aGlzLkFUSGZvcm11bGEgPSBmdW5jdGlvbiAoZiwgZ2ZwKSB7XG4gICAgICAgIHZhciBhdGg7XG4gICAgICAgIHN3aXRjaCAoZ2ZwLkFUSHR5cGUpIHtcbiAgICAgICAgICAgIGNhc2UgMDpcbiAgICAgICAgICAgICAgICBhdGggPSBBVEhmb3JtdWxhX0dCKGYsIDkpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIC8vIG92ZXIgc2Vuc2l0aXZlLCBzaG91bGQgcHJvYmFibHkgYmUgcmVtb3ZlZFxuICAgICAgICAgICAgICAgIGF0aCA9IEFUSGZvcm11bGFfR0IoZiwgLTEpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGF0aCA9IEFUSGZvcm11bGFfR0IoZiwgMCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDM6XG4gICAgICAgICAgICAgICAgLy8gbW9kaWZpY2F0aW9uIG9mIEdCIGZvcm11bGEgYnkgUm9lbFxuICAgICAgICAgICAgICAgIGF0aCA9IEFUSGZvcm11bGFfR0IoZiwgMSkgKyA2O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIGF0aCA9IEFUSGZvcm11bGFfR0IoZiwgZ2ZwLkFUSGN1cnZlKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgYXRoID0gQVRIZm9ybXVsYV9HQihmLCAwKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gYXRoO1xuICAgIH1cblxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFBzeU1vZGVsO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvX2xhbWVqc0AxLjIuMUBsYW1lanMvc3JjL2pzL1BzeU1vZGVsLmpzXG4vLyBtb2R1bGUgaWQgPSAya25xXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///2knq\n')},"2kvA":function(module,exports,__webpack_require__){"use strict";eval("\n\nexports.__esModule = true;\nexports.isInContainer = exports.getScrollContainer = exports.isScroll = exports.getStyle = exports.once = exports.off = exports.on = undefined;\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; }; /* istanbul ignore next */\n\nexports.hasClass = hasClass;\nexports.addClass = addClass;\nexports.removeClass = removeClass;\nexports.setStyle = setStyle;\n\nvar _vue = __webpack_require__(\"7+uW\");\n\nvar _vue2 = _interopRequireDefault(_vue);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar isServer = _vue2.default.prototype.$isServer;\nvar SPECIAL_CHARS_REGEXP = /([\\:\\-\\_]+(.))/g;\nvar MOZ_HACK_REGEXP = /^moz([A-Z])/;\nvar ieVersion = isServer ? 0 : Number(document.documentMode);\n\n/* istanbul ignore next */\nvar trim = function trim(string) {\n return (string || '').replace(/^[\\s\\uFEFF]+|[\\s\\uFEFF]+$/g, '');\n};\n/* istanbul ignore next */\nvar camelCase = function camelCase(name) {\n return name.replace(SPECIAL_CHARS_REGEXP, function (_, separator, letter, offset) {\n return offset ? letter.toUpperCase() : letter;\n }).replace(MOZ_HACK_REGEXP, 'Moz$1');\n};\n\n/* istanbul ignore next */\nvar on = exports.on = function () {\n if (!isServer && document.addEventListener) {\n return function (element, event, handler) {\n if (element && event && handler) {\n element.addEventListener(event, handler, false);\n }\n };\n } else {\n return function (element, event, handler) {\n if (element && event && handler) {\n element.attachEvent('on' + event, handler);\n }\n };\n }\n}();\n\n/* istanbul ignore next */\nvar off = exports.off = function () {\n if (!isServer && document.removeEventListener) {\n return function (element, event, handler) {\n if (element && event) {\n element.removeEventListener(event, handler, false);\n }\n };\n } else {\n return function (element, event, handler) {\n if (element && event) {\n element.detachEvent('on' + event, handler);\n }\n };\n }\n}();\n\n/* istanbul ignore next */\nvar once = exports.once = function once(el, event, fn) {\n var listener = function listener() {\n if (fn) {\n fn.apply(this, arguments);\n }\n off(el, event, listener);\n };\n on(el, event, listener);\n};\n\n/* istanbul ignore next */\nfunction hasClass(el, cls) {\n if (!el || !cls) return false;\n if (cls.indexOf(' ') !== -1) throw new Error('className should not contain space.');\n if (el.classList) {\n return el.classList.contains(cls);\n } else {\n return (' ' + el.className + ' ').indexOf(' ' + cls + ' ') > -1;\n }\n};\n\n/* istanbul ignore next */\nfunction addClass(el, cls) {\n if (!el) return;\n var curClass = el.className;\n var classes = (cls || '').split(' ');\n\n for (var i = 0, j = classes.length; i < j; i++) {\n var clsName = classes[i];\n if (!clsName) continue;\n\n if (el.classList) {\n el.classList.add(clsName);\n } else if (!hasClass(el, clsName)) {\n curClass += ' ' + clsName;\n }\n }\n if (!el.classList) {\n el.className = curClass;\n }\n};\n\n/* istanbul ignore next */\nfunction removeClass(el, cls) {\n if (!el || !cls) return;\n var classes = cls.split(' ');\n var curClass = ' ' + el.className + ' ';\n\n for (var i = 0, j = classes.length; i < j; i++) {\n var clsName = classes[i];\n if (!clsName) continue;\n\n if (el.classList) {\n el.classList.remove(clsName);\n } else if (hasClass(el, clsName)) {\n curClass = curClass.replace(' ' + clsName + ' ', ' ');\n }\n }\n if (!el.classList) {\n el.className = trim(curClass);\n }\n};\n\n/* istanbul ignore next */\nvar getStyle = exports.getStyle = ieVersion < 9 ? function (element, styleName) {\n if (isServer) return;\n if (!element || !styleName) return null;\n styleName = camelCase(styleName);\n if (styleName === 'float') {\n styleName = 'styleFloat';\n }\n try {\n switch (styleName) {\n case 'opacity':\n try {\n return element.filters.item('alpha').opacity / 100;\n } catch (e) {\n return 1.0;\n }\n default:\n return element.style[styleName] || element.currentStyle ? element.currentStyle[styleName] : null;\n }\n } catch (e) {\n return element.style[styleName];\n }\n} : function (element, styleName) {\n if (isServer) return;\n if (!element || !styleName) return null;\n styleName = camelCase(styleName);\n if (styleName === 'float') {\n styleName = 'cssFloat';\n }\n try {\n var computed = document.defaultView.getComputedStyle(element, '');\n return element.style[styleName] || computed ? computed[styleName] : null;\n } catch (e) {\n return element.style[styleName];\n }\n};\n\n/* istanbul ignore next */\nfunction setStyle(element, styleName, value) {\n if (!element || !styleName) return;\n\n if ((typeof styleName === 'undefined' ? 'undefined' : _typeof(styleName)) === 'object') {\n for (var prop in styleName) {\n if (styleName.hasOwnProperty(prop)) {\n setStyle(element, prop, styleName[prop]);\n }\n }\n } else {\n styleName = camelCase(styleName);\n if (styleName === 'opacity' && ieVersion < 9) {\n element.style.filter = isNaN(value) ? '' : 'alpha(opacity=' + value * 100 + ')';\n } else {\n element.style[styleName] = value;\n }\n }\n};\n\nvar isScroll = exports.isScroll = function isScroll(el, vertical) {\n if (isServer) return;\n\n var determinedDirection = vertical !== null || vertical !== undefined;\n var overflow = determinedDirection ? vertical ? getStyle(el, 'overflow-y') : getStyle(el, 'overflow-x') : getStyle(el, 'overflow');\n\n return overflow.match(/(scroll|auto)/);\n};\n\nvar getScrollContainer = exports.getScrollContainer = function getScrollContainer(el, vertical) {\n if (isServer) return;\n\n var parent = el;\n while (parent) {\n if ([window, document, document.documentElement].includes(parent)) {\n return window;\n }\n if (isScroll(parent, vertical)) {\n return parent;\n }\n parent = parent.parentNode;\n }\n\n return parent;\n};\n\nvar isInContainer = exports.isInContainer = function isInContainer(el, container) {\n if (isServer || !el || !container) return false;\n\n var elRect = el.getBoundingClientRect();\n var containerRect = void 0;\n\n if ([window, document, document.documentElement, null, undefined].includes(container)) {\n containerRect = {\n top: 0,\n right: window.innerWidth,\n bottom: window.innerHeight,\n left: 0\n };\n } else {\n containerRect = container.getBoundingClientRect();\n }\n\n return elRect.top < containerRect.bottom && elRect.bottom > containerRect.top && elRect.right > containerRect.left && elRect.left < containerRect.right;\n};//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMmt2QS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9lbGVtZW50LXVpL2xpYi91dGlscy9kb20uanM/ZGE0YiJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5leHBvcnRzLmlzSW5Db250YWluZXIgPSBleHBvcnRzLmdldFNjcm9sbENvbnRhaW5lciA9IGV4cG9ydHMuaXNTY3JvbGwgPSBleHBvcnRzLmdldFN0eWxlID0gZXhwb3J0cy5vbmNlID0gZXhwb3J0cy5vZmYgPSBleHBvcnRzLm9uID0gdW5kZWZpbmVkO1xuXG52YXIgX3R5cGVvZiA9IHR5cGVvZiBTeW1ib2wgPT09IFwiZnVuY3Rpb25cIiAmJiB0eXBlb2YgU3ltYm9sLml0ZXJhdG9yID09PSBcInN5bWJvbFwiID8gZnVuY3Rpb24gKG9iaikgeyByZXR1cm4gdHlwZW9mIG9iajsgfSA6IGZ1bmN0aW9uIChvYmopIHsgcmV0dXJuIG9iaiAmJiB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb2JqLmNvbnN0cnVjdG9yID09PSBTeW1ib2wgJiYgb2JqICE9PSBTeW1ib2wucHJvdG90eXBlID8gXCJzeW1ib2xcIiA6IHR5cGVvZiBvYmo7IH07IC8qIGlzdGFuYnVsIGlnbm9yZSBuZXh0ICovXG5cbmV4cG9ydHMuaGFzQ2xhc3MgPSBoYXNDbGFzcztcbmV4cG9ydHMuYWRkQ2xhc3MgPSBhZGRDbGFzcztcbmV4cG9ydHMucmVtb3ZlQ2xhc3MgPSByZW1vdmVDbGFzcztcbmV4cG9ydHMuc2V0U3R5bGUgPSBzZXRTdHlsZTtcblxudmFyIF92dWUgPSByZXF1aXJlKCd2dWUnKTtcblxudmFyIF92dWUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfdnVlKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxudmFyIGlzU2VydmVyID0gX3Z1ZTIuZGVmYXVsdC5wcm90b3R5cGUuJGlzU2VydmVyO1xudmFyIFNQRUNJQUxfQ0hBUlNfUkVHRVhQID0gLyhbXFw6XFwtXFxfXSsoLikpL2c7XG52YXIgTU9aX0hBQ0tfUkVHRVhQID0gL15tb3ooW0EtWl0pLztcbnZhciBpZVZlcnNpb24gPSBpc1NlcnZlciA/IDAgOiBOdW1iZXIoZG9jdW1lbnQuZG9jdW1lbnRNb2RlKTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbnZhciB0cmltID0gZnVuY3Rpb24gdHJpbShzdHJpbmcpIHtcbiAgcmV0dXJuIChzdHJpbmcgfHwgJycpLnJlcGxhY2UoL15bXFxzXFx1RkVGRl0rfFtcXHNcXHVGRUZGXSskL2csICcnKTtcbn07XG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xudmFyIGNhbWVsQ2FzZSA9IGZ1bmN0aW9uIGNhbWVsQ2FzZShuYW1lKSB7XG4gIHJldHVybiBuYW1lLnJlcGxhY2UoU1BFQ0lBTF9DSEFSU19SRUdFWFAsIGZ1bmN0aW9uIChfLCBzZXBhcmF0b3IsIGxldHRlciwgb2Zmc2V0KSB7XG4gICAgcmV0dXJuIG9mZnNldCA/IGxldHRlci50b1VwcGVyQ2FzZSgpIDogbGV0dGVyO1xuICB9KS5yZXBsYWNlKE1PWl9IQUNLX1JFR0VYUCwgJ01veiQxJyk7XG59O1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xudmFyIG9uID0gZXhwb3J0cy5vbiA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKCFpc1NlcnZlciAmJiBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChlbGVtZW50LCBldmVudCwgaGFuZGxlcikge1xuICAgICAgaWYgKGVsZW1lbnQgJiYgZXZlbnQgJiYgaGFuZGxlcikge1xuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIGhhbmRsZXIsIGZhbHNlKTtcbiAgICAgIH1cbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIHJldHVybiBmdW5jdGlvbiAoZWxlbWVudCwgZXZlbnQsIGhhbmRsZXIpIHtcbiAgICAgIGlmIChlbGVtZW50ICYmIGV2ZW50ICYmIGhhbmRsZXIpIHtcbiAgICAgICAgZWxlbWVudC5hdHRhY2hFdmVudCgnb24nICsgZXZlbnQsIGhhbmRsZXIpO1xuICAgICAgfVxuICAgIH07XG4gIH1cbn0oKTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbnZhciBvZmYgPSBleHBvcnRzLm9mZiA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKCFpc1NlcnZlciAmJiBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChlbGVtZW50LCBldmVudCwgaGFuZGxlcikge1xuICAgICAgaWYgKGVsZW1lbnQgJiYgZXZlbnQpIHtcbiAgICAgICAgZWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyLCBmYWxzZSk7XG4gICAgICB9XG4gICAgfTtcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gZnVuY3Rpb24gKGVsZW1lbnQsIGV2ZW50LCBoYW5kbGVyKSB7XG4gICAgICBpZiAoZWxlbWVudCAmJiBldmVudCkge1xuICAgICAgICBlbGVtZW50LmRldGFjaEV2ZW50KCdvbicgKyBldmVudCwgaGFuZGxlcik7XG4gICAgICB9XG4gICAgfTtcbiAgfVxufSgpO1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xudmFyIG9uY2UgPSBleHBvcnRzLm9uY2UgPSBmdW5jdGlvbiBvbmNlKGVsLCBldmVudCwgZm4pIHtcbiAgdmFyIGxpc3RlbmVyID0gZnVuY3Rpb24gbGlzdGVuZXIoKSB7XG4gICAgaWYgKGZuKSB7XG4gICAgICBmbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xuICAgIH1cbiAgICBvZmYoZWwsIGV2ZW50LCBsaXN0ZW5lcik7XG4gIH07XG4gIG9uKGVsLCBldmVudCwgbGlzdGVuZXIpO1xufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIGhhc0NsYXNzKGVsLCBjbHMpIHtcbiAgaWYgKCFlbCB8fCAhY2xzKSByZXR1cm4gZmFsc2U7XG4gIGlmIChjbHMuaW5kZXhPZignICcpICE9PSAtMSkgdGhyb3cgbmV3IEVycm9yKCdjbGFzc05hbWUgc2hvdWxkIG5vdCBjb250YWluIHNwYWNlLicpO1xuICBpZiAoZWwuY2xhc3NMaXN0KSB7XG4gICAgcmV0dXJuIGVsLmNsYXNzTGlzdC5jb250YWlucyhjbHMpO1xuICB9IGVsc2Uge1xuICAgIHJldHVybiAoJyAnICsgZWwuY2xhc3NOYW1lICsgJyAnKS5pbmRleE9mKCcgJyArIGNscyArICcgJykgPiAtMTtcbiAgfVxufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIGFkZENsYXNzKGVsLCBjbHMpIHtcbiAgaWYgKCFlbCkgcmV0dXJuO1xuICB2YXIgY3VyQ2xhc3MgPSBlbC5jbGFzc05hbWU7XG4gIHZhciBjbGFzc2VzID0gKGNscyB8fCAnJykuc3BsaXQoJyAnKTtcblxuICBmb3IgKHZhciBpID0gMCwgaiA9IGNsYXNzZXMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XG4gICAgdmFyIGNsc05hbWUgPSBjbGFzc2VzW2ldO1xuICAgIGlmICghY2xzTmFtZSkgY29udGludWU7XG5cbiAgICBpZiAoZWwuY2xhc3NMaXN0KSB7XG4gICAgICBlbC5jbGFzc0xpc3QuYWRkKGNsc05hbWUpO1xuICAgIH0gZWxzZSBpZiAoIWhhc0NsYXNzKGVsLCBjbHNOYW1lKSkge1xuICAgICAgY3VyQ2xhc3MgKz0gJyAnICsgY2xzTmFtZTtcbiAgICB9XG4gIH1cbiAgaWYgKCFlbC5jbGFzc0xpc3QpIHtcbiAgICBlbC5jbGFzc05hbWUgPSBjdXJDbGFzcztcbiAgfVxufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbmZ1bmN0aW9uIHJlbW92ZUNsYXNzKGVsLCBjbHMpIHtcbiAgaWYgKCFlbCB8fCAhY2xzKSByZXR1cm47XG4gIHZhciBjbGFzc2VzID0gY2xzLnNwbGl0KCcgJyk7XG4gIHZhciBjdXJDbGFzcyA9ICcgJyArIGVsLmNsYXNzTmFtZSArICcgJztcblxuICBmb3IgKHZhciBpID0gMCwgaiA9IGNsYXNzZXMubGVuZ3RoOyBpIDwgajsgaSsrKSB7XG4gICAgdmFyIGNsc05hbWUgPSBjbGFzc2VzW2ldO1xuICAgIGlmICghY2xzTmFtZSkgY29udGludWU7XG5cbiAgICBpZiAoZWwuY2xhc3NMaXN0KSB7XG4gICAgICBlbC5jbGFzc0xpc3QucmVtb3ZlKGNsc05hbWUpO1xuICAgIH0gZWxzZSBpZiAoaGFzQ2xhc3MoZWwsIGNsc05hbWUpKSB7XG4gICAgICBjdXJDbGFzcyA9IGN1ckNsYXNzLnJlcGxhY2UoJyAnICsgY2xzTmFtZSArICcgJywgJyAnKTtcbiAgICB9XG4gIH1cbiAgaWYgKCFlbC5jbGFzc0xpc3QpIHtcbiAgICBlbC5jbGFzc05hbWUgPSB0cmltKGN1ckNsYXNzKTtcbiAgfVxufTtcblxuLyogaXN0YW5idWwgaWdub3JlIG5leHQgKi9cbnZhciBnZXRTdHlsZSA9IGV4cG9ydHMuZ2V0U3R5bGUgPSBpZVZlcnNpb24gPCA5ID8gZnVuY3Rpb24gKGVsZW1lbnQsIHN0eWxlTmFtZSkge1xuICBpZiAoaXNTZXJ2ZXIpIHJldHVybjtcbiAgaWYgKCFlbGVtZW50IHx8ICFzdHlsZU5hbWUpIHJldHVybiBudWxsO1xuICBzdHlsZU5hbWUgPSBjYW1lbENhc2Uoc3R5bGVOYW1lKTtcbiAgaWYgKHN0eWxlTmFtZSA9PT0gJ2Zsb2F0Jykge1xuICAgIHN0eWxlTmFtZSA9ICdzdHlsZUZsb2F0JztcbiAgfVxuICB0cnkge1xuICAgIHN3aXRjaCAoc3R5bGVOYW1lKSB7XG4gICAgICBjYXNlICdvcGFjaXR5JzpcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICByZXR1cm4gZWxlbWVudC5maWx0ZXJzLml0ZW0oJ2FscGhhJykub3BhY2l0eSAvIDEwMDtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgIHJldHVybiAxLjA7XG4gICAgICAgIH1cbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBlbGVtZW50LnN0eWxlW3N0eWxlTmFtZV0gfHwgZWxlbWVudC5jdXJyZW50U3R5bGUgPyBlbGVtZW50LmN1cnJlbnRTdHlsZVtzdHlsZU5hbWVdIDogbnVsbDtcbiAgICB9XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZWxlbWVudC5zdHlsZVtzdHlsZU5hbWVdO1xuICB9XG59IDogZnVuY3Rpb24gKGVsZW1lbnQsIHN0eWxlTmFtZSkge1xuICBpZiAoaXNTZXJ2ZXIpIHJldHVybjtcbiAgaWYgKCFlbGVtZW50IHx8ICFzdHlsZU5hbWUpIHJldHVybiBudWxsO1xuICBzdHlsZU5hbWUgPSBjYW1lbENhc2Uoc3R5bGVOYW1lKTtcbiAgaWYgKHN0eWxlTmFtZSA9PT0gJ2Zsb2F0Jykge1xuICAgIHN0eWxlTmFtZSA9ICdjc3NGbG9hdCc7XG4gIH1cbiAgdHJ5IHtcbiAgICB2YXIgY29tcHV0ZWQgPSBkb2N1bWVudC5kZWZhdWx0Vmlldy5nZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQsICcnKTtcbiAgICByZXR1cm4gZWxlbWVudC5zdHlsZVtzdHlsZU5hbWVdIHx8IGNvbXB1dGVkID8gY29tcHV0ZWRbc3R5bGVOYW1lXSA6IG51bGw7XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICByZXR1cm4gZWxlbWVudC5zdHlsZVtzdHlsZU5hbWVdO1xuICB9XG59O1xuXG4vKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dCAqL1xuZnVuY3Rpb24gc2V0U3R5bGUoZWxlbWVudCwgc3R5bGVOYW1lLCB2YWx1ZSkge1xuICBpZiAoIWVsZW1lbnQgfHwgIXN0eWxlTmFtZSkgcmV0dXJuO1xuXG4gIGlmICgodHlwZW9mIHN0eWxlTmFtZSA9PT0gJ3VuZGVmaW5lZCcgPyAndW5kZWZpbmVkJyA6IF90eXBlb2Yoc3R5bGVOYW1lKSkgPT09ICdvYmplY3QnKSB7XG4gICAgZm9yICh2YXIgcHJvcCBpbiBzdHlsZU5hbWUpIHtcbiAgICAgIGlmIChzdHlsZU5hbWUuaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgc2V0U3R5bGUoZWxlbWVudCwgcHJvcCwgc3R5bGVOYW1lW3Byb3BdKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgc3R5bGVOYW1lID0gY2FtZWxDYXNlKHN0eWxlTmFtZSk7XG4gICAgaWYgKHN0eWxlTmFtZSA9PT0gJ29wYWNpdHknICYmIGllVmVyc2lvbiA8IDkpIHtcbiAgICAgIGVsZW1lbnQuc3R5bGUuZmlsdGVyID0gaXNOYU4odmFsdWUpID8gJycgOiAnYWxwaGEob3BhY2l0eT0nICsgdmFsdWUgKiAxMDAgKyAnKSc7XG4gICAgfSBlbHNlIHtcbiAgICAgIGVsZW1lbnQuc3R5bGVbc3R5bGVOYW1lXSA9IHZhbHVlO1xuICAgIH1cbiAgfVxufTtcblxudmFyIGlzU2Nyb2xsID0gZXhwb3J0cy5pc1Njcm9sbCA9IGZ1bmN0aW9uIGlzU2Nyb2xsKGVsLCB2ZXJ0aWNhbCkge1xuICBpZiAoaXNTZXJ2ZXIpIHJldHVybjtcblxuICB2YXIgZGV0ZXJtaW5lZERpcmVjdGlvbiA9IHZlcnRpY2FsICE9PSBudWxsIHx8IHZlcnRpY2FsICE9PSB1bmRlZmluZWQ7XG4gIHZhciBvdmVyZmxvdyA9IGRldGVybWluZWREaXJlY3Rpb24gPyB2ZXJ0aWNhbCA/IGdldFN0eWxlKGVsLCAnb3ZlcmZsb3cteScpIDogZ2V0U3R5bGUoZWwsICdvdmVyZmxvdy14JykgOiBnZXRTdHlsZShlbCwgJ292ZXJmbG93Jyk7XG5cbiAgcmV0dXJuIG92ZXJmbG93Lm1hdGNoKC8oc2Nyb2xsfGF1dG8pLyk7XG59O1xuXG52YXIgZ2V0U2Nyb2xsQ29udGFpbmVyID0gZXhwb3J0cy5nZXRTY3JvbGxDb250YWluZXIgPSBmdW5jdGlvbiBnZXRTY3JvbGxDb250YWluZXIoZWwsIHZlcnRpY2FsKSB7XG4gIGlmIChpc1NlcnZlcikgcmV0dXJuO1xuXG4gIHZhciBwYXJlbnQgPSBlbDtcbiAgd2hpbGUgKHBhcmVudCkge1xuICAgIGlmIChbd2luZG93LCBkb2N1bWVudCwgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50XS5pbmNsdWRlcyhwYXJlbnQpKSB7XG4gICAgICByZXR1cm4gd2luZG93O1xuICAgIH1cbiAgICBpZiAoaXNTY3JvbGwocGFyZW50LCB2ZXJ0aWNhbCkpIHtcbiAgICAgIHJldHVybiBwYXJlbnQ7XG4gICAgfVxuICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnROb2RlO1xuICB9XG5cbiAgcmV0dXJuIHBhcmVudDtcbn07XG5cbnZhciBpc0luQ29udGFpbmVyID0gZXhwb3J0cy5pc0luQ29udGFpbmVyID0gZnVuY3Rpb24gaXNJbkNvbnRhaW5lcihlbCwgY29udGFpbmVyKSB7XG4gIGlmIChpc1NlcnZlciB8fCAhZWwgfHwgIWNvbnRhaW5lcikgcmV0dXJuIGZhbHNlO1xuXG4gIHZhciBlbFJlY3QgPSBlbC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgdmFyIGNvbnRhaW5lclJlY3QgPSB2b2lkIDA7XG5cbiAgaWYgKFt3aW5kb3csIGRvY3VtZW50LCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQsIG51bGwsIHVuZGVmaW5lZF0uaW5jbHVkZXMoY29udGFpbmVyKSkge1xuICAgIGNvbnRhaW5lclJlY3QgPSB7XG4gICAgICB0b3A6IDAsXG4gICAgICByaWdodDogd2luZG93LmlubmVyV2lkdGgsXG4gICAgICBib3R0b206IHdpbmRvdy5pbm5lckhlaWdodCxcbiAgICAgIGxlZnQ6IDBcbiAgICB9O1xuICB9IGVsc2Uge1xuICAgIGNvbnRhaW5lclJlY3QgPSBjb250YWluZXIuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gIH1cblxuICByZXR1cm4gZWxSZWN0LnRvcCA8IGNvbnRhaW5lclJlY3QuYm90dG9tICYmIGVsUmVjdC5ib3R0b20gPiBjb250YWluZXJSZWN0LnRvcCAmJiBlbFJlY3QucmlnaHQgPiBjb250YWluZXJSZWN0LmxlZnQgJiYgZWxSZWN0LmxlZnQgPCBjb250YWluZXJSZWN0LnJpZ2h0O1xufTtcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9lbGVtZW50LXVpL2xpYi91dGlscy9kb20uanNcbi8vIG1vZHVsZSBpZCA9IDJrdkFcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///2kvA\n")},"2tKw":function(module,exports){eval("function MeanBits(meanBits) {\n this.bits = meanBits;\n}\n\nmodule.exports = MeanBits;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMnRLdy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvTWVhbkJpdHMuanM/ZGFkMiJdLCJzb3VyY2VzQ29udGVudCI6WyJmdW5jdGlvbiBNZWFuQml0cyhtZWFuQml0cykge1xuICAgIHRoaXMuYml0cyA9IG1lYW5CaXRzO1xufVxuXG5tb2R1bGUuZXhwb3J0cyA9IE1lYW5CaXRzO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvX2xhbWVqc0AxLjIuMUBsYW1lanMvc3JjL2pzL01lYW5CaXRzLmpzXG4vLyBtb2R1bGUgaWQgPSAydEt3XG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///2tKw\n")},"3Eo+":function(module,exports){eval("var id = 0;\nvar px = Math.random();\nmodule.exports = function (key) {\n return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiM0VvKy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdWlkLmpzP2RjNGEiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIGlkID0gMDtcbnZhciBweCA9IE1hdGgucmFuZG9tKCk7XG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChrZXkpIHtcbiAgcmV0dXJuICdTeW1ib2woJy5jb25jYXQoa2V5ID09PSB1bmRlZmluZWQgPyAnJyA6IGtleSwgJylfJywgKCsraWQgKyBweCkudG9TdHJpbmcoMzYpKTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fdWlkLmpzXG4vLyBtb2R1bGUgaWQgPSAzRW8rXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///3Eo+\n")},"3OGR":function(module,exports,__webpack_require__){eval('var common = __webpack_require__("Dkd2");\nvar System = common.System;\nvar VbrMode = common.VbrMode;\nvar Float = common.Float;\nvar ShortBlock = common.ShortBlock;\nvar Util = common.Util;\nvar Arrays = common.Arrays;\nvar new_array_n = common.new_array_n;\nvar new_byte = common.new_byte;\nvar new_double = common.new_double;\nvar new_float = common.new_float;\nvar new_float_n = common.new_float_n;\nvar new_int = common.new_int;\nvar new_int_n = common.new_int_n;\nvar assert = common.assert;\n\n/**\n * A Vbr header may be present in the ancillary data field of the first frame of\n * an mp3 bitstream
\n * The Vbr header (optionally) contains\n *
    \n *
  • frames total number of audio frames in the bitstream\n *
  • bytes total number of bytes in the bitstream\n *
  • toc table of contents\n *
\n *\n * toc (table of contents) gives seek points for random access.
\n * The ith entry determines the seek point for i-percent duration.
\n * seek point in bytes = (toc[i]/256.0) * total_bitstream_bytes
\n * e.g. half duration seek point = (toc[50]/256.0) * total_bitstream_bytes\n */\nVBRTag.NUMTOCENTRIES = 100;\nVBRTag.MAXFRAMESIZE = 2880;\n\nfunction VBRTag() {\n\n var lame;\n var bs;\n var v;\n\n this.setModules = function (_lame, _bs, _v) {\n lame = _lame;\n bs = _bs;\n v = _v;\n };\n\n var FRAMES_FLAG = 0x0001;\n var BYTES_FLAG = 0x0002;\n var TOC_FLAG = 0x0004;\n var VBR_SCALE_FLAG = 0x0008;\n\n var NUMTOCENTRIES = VBRTag.NUMTOCENTRIES;\n\n /**\n * (0xB40) the max freeformat 640 32kHz framesize.\n */\n var MAXFRAMESIZE = VBRTag.MAXFRAMESIZE;\n\n /**\n *
\n     *    4 bytes for Header Tag\n     *    4 bytes for Header Flags\n     *  100 bytes for entry (toc)\n     *    4 bytes for frame size\n     *    4 bytes for stream size\n     *    4 bytes for VBR scale. a VBR quality indicator: 0=best 100=worst\n     *   20 bytes for LAME tag.  for example, "LAME3.12 (beta 6)"\n     * ___________\n     *  140 bytes\n     * 
\n */\n var VBRHEADERSIZE = (NUMTOCENTRIES + 4 + 4 + 4 + 4 + 4);\n\n var LAMEHEADERSIZE = (VBRHEADERSIZE + 9 + 1 + 1 + 8\n + 1 + 1 + 3 + 1 + 1 + 2 + 4 + 2 + 2);\n\n /**\n * The size of the Xing header MPEG-1, bit rate in kbps.\n */\n var XING_BITRATE1 = 128;\n /**\n * The size of the Xing header MPEG-2, bit rate in kbps.\n */\n var XING_BITRATE2 = 64;\n /**\n * The size of the Xing header MPEG-2.5, bit rate in kbps.\n */\n var XING_BITRATE25 = 32;\n\n /**\n * ISO-8859-1 charset for byte to string operations.\n */\n var ISO_8859_1 = null; //Charset.forName("ISO-8859-1");\n\n /**\n * VBR header magic string.\n */\n var VBRTag0 = "Xing";\n /**\n * VBR header magic string (VBR == VBRMode.vbr_off).\n */\n var VBRTag1 = "Info";\n\n /**\n * Lookup table for fast CRC-16 computation. Uses the polynomial\n * x^16+x^15+x^2+1\n */\n var crc16Lookup = [0x0000, 0xC0C1, 0xC181, 0x0140,\n 0xC301, 0x03C0, 0x0280, 0xC241, 0xC601, 0x06C0, 0x0780, 0xC741,\n 0x0500, 0xC5C1, 0xC481, 0x0440, 0xCC01, 0x0CC0, 0x0D80, 0xCD41,\n 0x0F00, 0xCFC1, 0xCE81, 0x0E40, 0x0A00, 0xCAC1, 0xCB81, 0x0B40,\n 0xC901, 0x09C0, 0x0880, 0xC841, 0xD801, 0x18C0, 0x1980, 0xD941,\n 0x1B00, 0xDBC1, 0xDA81, 0x1A40, 0x1E00, 0xDEC1, 0xDF81, 0x1F40,\n 0xDD01, 0x1DC0, 0x1C80, 0xDC41, 0x1400, 0xD4C1, 0xD581, 0x1540,\n 0xD701, 0x17C0, 0x1680, 0xD641, 0xD201, 0x12C0, 0x1380, 0xD341,\n 0x1100, 0xD1C1, 0xD081, 0x1040, 0xF001, 0x30C0, 0x3180, 0xF141,\n 0x3300, 0xF3C1, 0xF281, 0x3240, 0x3600, 0xF6C1, 0xF781, 0x3740,\n 0xF501, 0x35C0, 0x3480, 0xF441, 0x3C00, 0xFCC1, 0xFD81, 0x3D40,\n 0xFF01, 0x3FC0, 0x3E80, 0xFE41, 0xFA01, 0x3AC0, 0x3B80, 0xFB41,\n 0x3900, 0xF9C1, 0xF881, 0x3840, 0x2800, 0xE8C1, 0xE981, 0x2940,\n 0xEB01, 0x2BC0, 0x2A80, 0xEA41, 0xEE01, 0x2EC0, 0x2F80, 0xEF41,\n 0x2D00, 0xEDC1, 0xEC81, 0x2C40, 0xE401, 0x24C0, 0x2580, 0xE541,\n 0x2700, 0xE7C1, 0xE681, 0x2640, 0x2200, 0xE2C1, 0xE381, 0x2340,\n 0xE101, 0x21C0, 0x2080, 0xE041, 0xA001, 0x60C0, 0x6180, 0xA141,\n 0x6300, 0xA3C1, 0xA281, 0x6240, 0x6600, 0xA6C1, 0xA781, 0x6740,\n 0xA501, 0x65C0, 0x6480, 0xA441, 0x6C00, 0xACC1, 0xAD81, 0x6D40,\n 0xAF01, 0x6FC0, 0x6E80, 0xAE41, 0xAA01, 0x6AC0, 0x6B80, 0xAB41,\n 0x6900, 0xA9C1, 0xA881, 0x6840, 0x7800, 0xB8C1, 0xB981, 0x7940,\n 0xBB01, 0x7BC0, 0x7A80, 0xBA41, 0xBE01, 0x7EC0, 0x7F80, 0xBF41,\n 0x7D00, 0xBDC1, 0xBC81, 0x7C40, 0xB401, 0x74C0, 0x7580, 0xB541,\n 0x7700, 0xB7C1, 0xB681, 0x7640, 0x7200, 0xB2C1, 0xB381, 0x7340,\n 0xB101, 0x71C0, 0x7080, 0xB041, 0x5000, 0x90C1, 0x9181, 0x5140,\n 0x9301, 0x53C0, 0x5280, 0x9241, 0x9601, 0x56C0, 0x5780, 0x9741,\n 0x5500, 0x95C1, 0x9481, 0x5440, 0x9C01, 0x5CC0, 0x5D80, 0x9D41,\n 0x5F00, 0x9FC1, 0x9E81, 0x5E40, 0x5A00, 0x9AC1, 0x9B81, 0x5B40,\n 0x9901, 0x59C0, 0x5880, 0x9841, 0x8801, 0x48C0, 0x4980, 0x8941,\n 0x4B00, 0x8BC1, 0x8A81, 0x4A40, 0x4E00, 0x8EC1, 0x8F81, 0x4F40,\n 0x8D01, 0x4DC0, 0x4C80, 0x8C41, 0x4400, 0x84C1, 0x8581, 0x4540,\n 0x8701, 0x47C0, 0x4680, 0x8641, 0x8201, 0x42C0, 0x4380, 0x8341,\n 0x4100, 0x81C1, 0x8081, 0x4040];\n\n /***********************************************************************\n * Robert Hegemann 2001-01-17\n ***********************************************************************/\n\n function addVbr(v, bitrate) {\n v.nVbrNumFrames++;\n v.sum += bitrate;\n v.seen++;\n\n if (v.seen < v.want) {\n return;\n }\n\n if (v.pos < v.size) {\n v.bag[v.pos] = v.sum;\n v.pos++;\n v.seen = 0;\n }\n if (v.pos == v.size) {\n for (var i = 1; i < v.size; i += 2) {\n v.bag[i / 2] = v.bag[i];\n }\n v.want *= 2;\n v.pos /= 2;\n }\n }\n\n function xingSeekTable(v, t) {\n if (v.pos <= 0)\n return;\n\n for (var i = 1; i < NUMTOCENTRIES; ++i) {\n var j = i / NUMTOCENTRIES, act, sum;\n var indx = 0 | (Math.floor(j * v.pos));\n if (indx > v.pos - 1)\n indx = v.pos - 1;\n act = v.bag[indx];\n sum = v.sum;\n var seek_point = 0 | (256. * act / sum);\n if (seek_point > 255)\n seek_point = 255;\n t[i] = 0xff & seek_point;\n }\n }\n\n /**\n * Add VBR entry, used to fill the VBR TOC entries.\n *\n * @param gfp\n * global flags\n */\n this.addVbrFrame = function (gfp) {\n var gfc = gfp.internal_flags;\n var kbps = Tables.bitrate_table[gfp.version][gfc.bitrate_index];\n assert(gfc.VBR_seek_table.bag != null);\n addVbr(gfc.VBR_seek_table, kbps);\n }\n\n /**\n * Read big endian integer (4-bytes) from header.\n *\n * @param buf\n * header containing the integer\n * @param bufPos\n * offset into the header\n * @return extracted integer\n */\n function extractInteger(buf, bufPos) {\n var x = buf[bufPos + 0] & 0xff;\n x <<= 8;\n x |= buf[bufPos + 1] & 0xff;\n x <<= 8;\n x |= buf[bufPos + 2] & 0xff;\n x <<= 8;\n x |= buf[bufPos + 3] & 0xff;\n return x;\n }\n\n /**\n * Write big endian integer (4-bytes) in the header.\n *\n * @param buf\n * header to write the integer into\n * @param bufPos\n * offset into the header\n * @param value\n * integer value to write\n */\n function createInteger(buf, bufPos, value) {\n buf[bufPos + 0] = 0xff & ((value >> 24) & 0xff);\n buf[bufPos + 1] = 0xff & ((value >> 16) & 0xff);\n buf[bufPos + 2] = 0xff & ((value >> 8) & 0xff);\n buf[bufPos + 3] = 0xff & (value & 0xff);\n }\n\n /**\n * Write big endian short (2-bytes) in the header.\n *\n * @param buf\n * header to write the integer into\n * @param bufPos\n * offset into the header\n * @param value\n * integer value to write\n */\n function createShort(buf, bufPos, value) {\n buf[bufPos + 0] = 0xff & ((value >> 8) & 0xff);\n buf[bufPos + 1] = 0xff & (value & 0xff);\n }\n\n /**\n * Check for magic strings (Xing/Info).\n *\n * @param buf\n * header to check\n * @param bufPos\n * header offset to check\n * @return magic string found\n */\n function isVbrTag(buf, bufPos) {\n return new String(buf, bufPos, VBRTag0.length(), ISO_8859_1)\n .equals(VBRTag0)\n || new String(buf, bufPos, VBRTag1.length(), ISO_8859_1)\n .equals(VBRTag1);\n }\n\n function shiftInBitsValue(x, n, v) {\n return 0xff & ((x << n) | (v & ~(-1 << n)));\n }\n\n /**\n * Construct the MP3 header using the settings of the global flags.\n *\n * \n *\n * @param gfp\n * global flags\n * @param buffer\n * header\n */\n function setLameTagFrameHeader(gfp, buffer) {\n var gfc = gfp.internal_flags;\n\n // MP3 Sync Word\n buffer[0] = shiftInBitsValue(buffer[0], 8, 0xff);\n\n buffer[1] = shiftInBitsValue(buffer[1], 3, 7);\n buffer[1] = shiftInBitsValue(buffer[1], 1,\n (gfp.out_samplerate < 16000) ? 0 : 1);\n // Version\n buffer[1] = shiftInBitsValue(buffer[1], 1, gfp.version);\n // 01 == Layer 3\n buffer[1] = shiftInBitsValue(buffer[1], 2, 4 - 3);\n // Error protection\n buffer[1] = shiftInBitsValue(buffer[1], 1, (!gfp.error_protection) ? 1\n : 0);\n\n // Bit rate\n buffer[2] = shiftInBitsValue(buffer[2], 4, gfc.bitrate_index);\n // Frequency\n buffer[2] = shiftInBitsValue(buffer[2], 2, gfc.samplerate_index);\n // Pad. Bit\n buffer[2] = shiftInBitsValue(buffer[2], 1, 0);\n // Priv. Bit\n buffer[2] = shiftInBitsValue(buffer[2], 1, gfp.extension);\n\n // Mode\n buffer[3] = shiftInBitsValue(buffer[3], 2, gfp.mode.ordinal());\n // Mode extension (Used with Joint Stereo)\n buffer[3] = shiftInBitsValue(buffer[3], 2, gfc.mode_ext);\n // Copy\n buffer[3] = shiftInBitsValue(buffer[3], 1, gfp.copyright);\n // Original\n buffer[3] = shiftInBitsValue(buffer[3], 1, gfp.original);\n // Emphasis\n buffer[3] = shiftInBitsValue(buffer[3], 2, gfp.emphasis);\n\n /* the default VBR header. 48 kbps layer III, no padding, no crc */\n /* but sampling freq, mode and copyright/copy protection taken */\n /* from first valid frame */\n buffer[0] = 0xff;\n var abyte = 0xff & (buffer[1] & 0xf1);\n var bitrate;\n if (1 == gfp.version) {\n bitrate = XING_BITRATE1;\n } else {\n if (gfp.out_samplerate < 16000)\n bitrate = XING_BITRATE25;\n else\n bitrate = XING_BITRATE2;\n }\n\n if (gfp.VBR == VbrMode.vbr_off)\n bitrate = gfp.brate;\n\n var bbyte;\n if (gfp.free_format)\n bbyte = 0x00;\n else\n bbyte = 0xff & (16 * lame.BitrateIndex(bitrate, gfp.version,\n gfp.out_samplerate));\n\n /*\n * Use as much of the info from the real frames in the Xing header:\n * samplerate, channels, crc, etc...\n */\n if (gfp.version == 1) {\n /* MPEG1 */\n buffer[1] = 0xff & (abyte | 0x0a);\n /* was 0x0b; */\n abyte = 0xff & (buffer[2] & 0x0d);\n /* AF keep also private bit */\n buffer[2] = 0xff & (bbyte | abyte);\n /* 64kbs MPEG1 frame */\n } else {\n /* MPEG2 */\n buffer[1] = 0xff & (abyte | 0x02);\n /* was 0x03; */\n abyte = 0xff & (buffer[2] & 0x0d);\n /* AF keep also private bit */\n buffer[2] = 0xff & (bbyte | abyte);\n /* 64kbs MPEG2 frame */\n }\n }\n\n /**\n * Get VBR tag information\n *\n * @param buf\n * header to analyze\n * @param bufPos\n * offset into the header\n * @return VBR tag data\n */\n this.getVbrTag = function (buf) {\n var pTagData = new VBRTagData();\n var bufPos = 0;\n\n /* get Vbr header data */\n pTagData.flags = 0;\n\n /* get selected MPEG header data */\n var hId = (buf[bufPos + 1] >> 3) & 1;\n var hSrIndex = (buf[bufPos + 2] >> 2) & 3;\n var hMode = (buf[bufPos + 3] >> 6) & 3;\n var hBitrate = ((buf[bufPos + 2] >> 4) & 0xf);\n hBitrate = Tables.bitrate_table[hId][hBitrate];\n\n /* check for FFE syncword */\n if ((buf[bufPos + 1] >> 4) == 0xE)\n pTagData.samprate = Tables.samplerate_table[2][hSrIndex];\n else\n pTagData.samprate = Tables.samplerate_table[hId][hSrIndex];\n\n /* determine offset of header */\n if (hId != 0) {\n /* mpeg1 */\n if (hMode != 3)\n bufPos += (32 + 4);\n else\n bufPos += (17 + 4);\n } else {\n /* mpeg2 */\n if (hMode != 3)\n bufPos += (17 + 4);\n else\n bufPos += (9 + 4);\n }\n\n if (!isVbrTag(buf, bufPos))\n return null;\n\n bufPos += 4;\n\n pTagData.hId = hId;\n\n /* get flags */\n var head_flags = pTagData.flags = extractInteger(buf, bufPos);\n bufPos += 4;\n\n if ((head_flags & FRAMES_FLAG) != 0) {\n pTagData.frames = extractInteger(buf, bufPos);\n bufPos += 4;\n }\n\n if ((head_flags & BYTES_FLAG) != 0) {\n pTagData.bytes = extractInteger(buf, bufPos);\n bufPos += 4;\n }\n\n if ((head_flags & TOC_FLAG) != 0) {\n if (pTagData.toc != null) {\n for (var i = 0; i < NUMTOCENTRIES; i++)\n pTagData.toc[i] = buf[bufPos + i];\n }\n bufPos += NUMTOCENTRIES;\n }\n\n pTagData.vbrScale = -1;\n\n if ((head_flags & VBR_SCALE_FLAG) != 0) {\n pTagData.vbrScale = extractInteger(buf, bufPos);\n bufPos += 4;\n }\n\n pTagData.headersize = ((hId + 1) * 72000 * hBitrate)\n / pTagData.samprate;\n\n bufPos += 21;\n var encDelay = buf[bufPos + 0] << 4;\n encDelay += buf[bufPos + 1] >> 4;\n var encPadding = (buf[bufPos + 1] & 0x0F) << 8;\n encPadding += buf[bufPos + 2] & 0xff;\n /* check for reasonable values (this may be an old Xing header, */\n /* not a INFO tag) */\n if (encDelay < 0 || encDelay > 3000)\n encDelay = -1;\n if (encPadding < 0 || encPadding > 3000)\n encPadding = -1;\n\n pTagData.encDelay = encDelay;\n pTagData.encPadding = encPadding;\n\n /* success */\n return pTagData;\n }\n\n /**\n * Initializes the header\n *\n * @param gfp\n * global flags\n */\n this.InitVbrTag = function (gfp) {\n var gfc = gfp.internal_flags;\n\n /**\n *
\n         * Xing VBR pretends to be a 48kbs layer III frame.  (at 44.1kHz).\n         * (at 48kHz they use 56kbs since 48kbs frame not big enough for\n         * table of contents)\n         * let\'s always embed Xing header inside a 64kbs layer III frame.\n         * this gives us enough room for a LAME version string too.\n         * size determined by sampling frequency (MPEG1)\n         * 32kHz:    216 bytes@48kbs    288bytes@ 64kbs\n         * 44.1kHz:  156 bytes          208bytes@64kbs     (+1 if padding = 1)\n         * 48kHz:    144 bytes          192\n         *\n         * MPEG 2 values are the same since the framesize and samplerate\n         * are each reduced by a factor of 2.\n         * 
\n */\n var kbps_header;\n if (1 == gfp.version) {\n kbps_header = XING_BITRATE1;\n } else {\n if (gfp.out_samplerate < 16000)\n kbps_header = XING_BITRATE25;\n else\n kbps_header = XING_BITRATE2;\n }\n\n if (gfp.VBR == VbrMode.vbr_off)\n kbps_header = gfp.brate;\n\n // make sure LAME Header fits into Frame\n var totalFrameSize = ((gfp.version + 1) * 72000 * kbps_header)\n / gfp.out_samplerate;\n var headerSize = (gfc.sideinfo_len + LAMEHEADERSIZE);\n gfc.VBR_seek_table.TotalFrameSize = totalFrameSize;\n if (totalFrameSize < headerSize || totalFrameSize > MAXFRAMESIZE) {\n /* disable tag, it wont fit */\n gfp.bWriteVbrTag = false;\n return;\n }\n\n gfc.VBR_seek_table.nVbrNumFrames = 0;\n gfc.VBR_seek_table.nBytesWritten = 0;\n gfc.VBR_seek_table.sum = 0;\n\n gfc.VBR_seek_table.seen = 0;\n gfc.VBR_seek_table.want = 1;\n gfc.VBR_seek_table.pos = 0;\n\n if (gfc.VBR_seek_table.bag == null) {\n gfc.VBR_seek_table.bag = new int[400];\n gfc.VBR_seek_table.size = 400;\n }\n\n // write dummy VBR tag of all 0\'s into bitstream\n var buffer = new_byte(MAXFRAMESIZE);\n\n setLameTagFrameHeader(gfp, buffer);\n var n = gfc.VBR_seek_table.TotalFrameSize;\n for (var i = 0; i < n; ++i) {\n bs.add_dummy_byte(gfp, buffer[i] & 0xff, 1);\n }\n }\n\n /**\n * Fast CRC-16 computation (uses table crc16Lookup).\n *\n * @param value\n * @param crc\n * @return\n */\n function crcUpdateLookup(value, crc) {\n var tmp = crc ^ value;\n crc = (crc >> 8) ^ crc16Lookup[tmp & 0xff];\n return crc;\n }\n\n this.updateMusicCRC = function (crc, buffer, bufferPos, size) {\n for (var i = 0; i < size; ++i)\n crc[0] = crcUpdateLookup(buffer[bufferPos + i], crc[0]);\n }\n\n /**\n * Write LAME info: mini version + info on various switches used (Jonathan\n * Dee 2001/08/31).\n *\n * @param gfp\n * global flags\n * @param musicLength\n * music length\n * @param streamBuffer\n * pointer to output buffer\n * @param streamBufferPos\n * offset into the output buffer\n * @param crc\n * computation of CRC-16 of Lame Tag so far (starting at frame\n * sync)\n * @return number of bytes written to the stream\n */\n function putLameVBR(gfp, musicLength, streamBuffer, streamBufferPos, crc) {\n var gfc = gfp.internal_flags;\n var bytesWritten = 0;\n\n /* encoder delay */\n var encDelay = gfp.encoder_delay;\n /* encoder padding */\n var encPadding = gfp.encoder_padding;\n\n /* recall: gfp.VBR_q is for example set by the switch -V */\n /* gfp.quality by -q, -h, -f, etc */\n var quality = (100 - 10 * gfp.VBR_q - gfp.quality);\n\n var version = v.getLameVeryShortVersion();\n var vbr;\n var revision = 0x00;\n var revMethod;\n // numbering different in vbr_mode vs. Lame tag\n var vbrTypeTranslator = [1, 5, 3, 2, 4, 0, 3];\n var lowpass = 0 | (((gfp.lowpassfreq / 100.0) + .5) > 255 ? 255\n : (gfp.lowpassfreq / 100.0) + .5);\n var peakSignalAmplitude = 0;\n var radioReplayGain = 0;\n var audiophileReplayGain = 0;\n var noiseShaping = gfp.internal_flags.noise_shaping;\n var stereoMode = 0;\n var nonOptimal = 0;\n var sourceFreq = 0;\n var misc = 0;\n var musicCRC = 0;\n\n // psy model type: Gpsycho or NsPsytune\n var expNPsyTune = (gfp.exp_nspsytune & 1) != 0;\n var safeJoint = (gfp.exp_nspsytune & 2) != 0;\n var noGapMore = false;\n var noGapPrevious = false;\n var noGapCount = gfp.internal_flags.nogap_total;\n var noGapCurr = gfp.internal_flags.nogap_current;\n\n // 4 bits\n var athType = gfp.ATHtype;\n var flags = 0;\n\n // vbr modes\n var abrBitrate;\n switch (gfp.VBR) {\n case vbr_abr:\n abrBitrate = gfp.VBR_mean_bitrate_kbps;\n break;\n case vbr_off:\n abrBitrate = gfp.brate;\n break;\n default:\n abrBitrate = gfp.VBR_min_bitrate_kbps;\n }\n\n // revision and vbr method\n if (gfp.VBR.ordinal() < vbrTypeTranslator.length)\n vbr = vbrTypeTranslator[gfp.VBR.ordinal()];\n else\n vbr = 0x00; // unknown\n\n revMethod = 0x10 * revision + vbr;\n\n // ReplayGain\n if (gfc.findReplayGain) {\n if (gfc.RadioGain > 0x1FE)\n gfc.RadioGain = 0x1FE;\n if (gfc.RadioGain < -0x1FE)\n gfc.RadioGain = -0x1FE;\n\n // set name code\n radioReplayGain = 0x2000;\n // set originator code to `determined automatically\'\n radioReplayGain |= 0xC00;\n\n if (gfc.RadioGain >= 0) {\n // set gain adjustment\n radioReplayGain |= gfc.RadioGain;\n } else {\n // set the sign bit\n radioReplayGain |= 0x200;\n // set gain adjustment\n radioReplayGain |= -gfc.RadioGain;\n }\n }\n\n // peak sample\n if (gfc.findPeakSample)\n peakSignalAmplitude = Math\n .abs(0 | ((( gfc.PeakSample) / 32767.0) * Math.pow(2, 23) + .5));\n\n // nogap\n if (noGapCount != -1) {\n if (noGapCurr > 0)\n noGapPrevious = true;\n\n if (noGapCurr < noGapCount - 1)\n noGapMore = true;\n }\n\n // flags\n flags = athType + ((expNPsyTune ? 1 : 0) << 4)\n + ((safeJoint ? 1 : 0) << 5) + ((noGapMore ? 1 : 0) << 6)\n + ((noGapPrevious ? 1 : 0) << 7);\n\n if (quality < 0)\n quality = 0;\n\n // stereo mode field (Intensity stereo is not implemented)\n switch (gfp.mode) {\n case MONO:\n stereoMode = 0;\n break;\n case STEREO:\n stereoMode = 1;\n break;\n case DUAL_CHANNEL:\n stereoMode = 2;\n break;\n case JOINT_STEREO:\n if (gfp.force_ms)\n stereoMode = 4;\n else\n stereoMode = 3;\n break;\n case NOT_SET:\n //$FALL-THROUGH$\n default:\n stereoMode = 7;\n break;\n }\n\n if (gfp.in_samplerate <= 32000)\n sourceFreq = 0x00;\n else if (gfp.in_samplerate == 48000)\n sourceFreq = 0x02;\n else if (gfp.in_samplerate > 48000)\n sourceFreq = 0x03;\n else {\n // default is 44100Hz\n sourceFreq = 0x01;\n }\n\n // Check if the user overrided the default LAME behavior with some\n // nasty options\n if (gfp.short_blocks == ShortBlock.short_block_forced\n || gfp.short_blocks == ShortBlock.short_block_dispensed\n || ((gfp.lowpassfreq == -1) && (gfp.highpassfreq == -1)) || /* "-k" */\n (gfp.scale_left < gfp.scale_right)\n || (gfp.scale_left > gfp.scale_right)\n || (gfp.disable_reservoir && gfp.brate < 320) || gfp.noATH\n || gfp.ATHonly || (athType == 0) || gfp.in_samplerate <= 32000)\n nonOptimal = 1;\n\n misc = noiseShaping + (stereoMode << 2) + (nonOptimal << 5)\n + (sourceFreq << 6);\n\n musicCRC = gfc.nMusicCRC;\n\n // Write all this information into the stream\n\n createInteger(streamBuffer, streamBufferPos + bytesWritten, quality);\n bytesWritten += 4;\n\n for (var j = 0; j < 9; j++) {\n streamBuffer[streamBufferPos + bytesWritten + j] = 0xff & version .charAt(j);\n }\n bytesWritten += 9;\n\n streamBuffer[streamBufferPos + bytesWritten] = 0xff & revMethod;\n bytesWritten++;\n\n streamBuffer[streamBufferPos + bytesWritten] = 0xff & lowpass;\n bytesWritten++;\n\n createInteger(streamBuffer, streamBufferPos + bytesWritten,\n peakSignalAmplitude);\n bytesWritten += 4;\n\n createShort(streamBuffer, streamBufferPos + bytesWritten,\n radioReplayGain);\n bytesWritten += 2;\n\n createShort(streamBuffer, streamBufferPos + bytesWritten,\n audiophileReplayGain);\n bytesWritten += 2;\n\n streamBuffer[streamBufferPos + bytesWritten] = 0xff & flags;\n bytesWritten++;\n\n if (abrBitrate >= 255)\n streamBuffer[streamBufferPos + bytesWritten] = 0xFF;\n else\n streamBuffer[streamBufferPos + bytesWritten] = 0xff & abrBitrate;\n bytesWritten++;\n\n streamBuffer[streamBufferPos + bytesWritten] = 0xff & (encDelay >> 4);\n streamBuffer[streamBufferPos + bytesWritten + 1] = 0xff & ((encDelay << 4) + (encPadding >> 8));\n streamBuffer[streamBufferPos + bytesWritten + 2] = 0xff & encPadding;\n\n bytesWritten += 3;\n\n streamBuffer[streamBufferPos + bytesWritten] = 0xff & misc;\n bytesWritten++;\n\n // unused in rev0\n streamBuffer[streamBufferPos + bytesWritten++] = 0;\n\n createShort(streamBuffer, streamBufferPos + bytesWritten, gfp.preset);\n bytesWritten += 2;\n\n createInteger(streamBuffer, streamBufferPos + bytesWritten, musicLength);\n bytesWritten += 4;\n\n createShort(streamBuffer, streamBufferPos + bytesWritten, musicCRC);\n bytesWritten += 2;\n\n // Calculate tag CRC.... must be done here, since it includes previous\n // information\n\n for (var i = 0; i < bytesWritten; i++)\n crc = crcUpdateLookup(streamBuffer[streamBufferPos + i], crc);\n\n createShort(streamBuffer, streamBufferPos + bytesWritten, crc);\n bytesWritten += 2;\n\n return bytesWritten;\n }\n\n function skipId3v2(fpStream) {\n // seek to the beginning of the stream\n fpStream.seek(0);\n // read 10 bytes in case there\'s an ID3 version 2 header here\n var id3v2Header = new_byte(10);\n fpStream.readFully(id3v2Header);\n /* does the stream begin with the ID3 version 2 file identifier? */\n var id3v2TagSize;\n if (!new String(id3v2Header, "ISO-8859-1").startsWith("ID3")) {\n /*\n * the tag size (minus the 10-byte header) is encoded into four\n * bytes where the most significant bit is clear in each byte\n */\n id3v2TagSize = (((id3v2Header[6] & 0x7f) << 21)\n | ((id3v2Header[7] & 0x7f) << 14)\n | ((id3v2Header[8] & 0x7f) << 7) | (id3v2Header[9] & 0x7f))\n + id3v2Header.length;\n } else {\n /* no ID3 version 2 tag in this stream */\n id3v2TagSize = 0;\n }\n return id3v2TagSize;\n }\n\n this.getLameTagFrame = function (gfp, buffer) {\n var gfc = gfp.internal_flags;\n\n if (!gfp.bWriteVbrTag) {\n return 0;\n }\n if (gfc.Class_ID != Lame.LAME_ID) {\n return 0;\n }\n if (gfc.VBR_seek_table.pos <= 0) {\n return 0;\n }\n if (buffer.length < gfc.VBR_seek_table.TotalFrameSize) {\n return gfc.VBR_seek_table.TotalFrameSize;\n }\n\n Arrays.fill(buffer, 0, gfc.VBR_seek_table.TotalFrameSize, 0);\n\n // 4 bytes frame header\n setLameTagFrameHeader(gfp, buffer);\n\n // Create TOC entries\n var toc = new_byte(NUMTOCENTRIES);\n\n if (gfp.free_format) {\n for (var i = 1; i < NUMTOCENTRIES; ++i)\n toc[i] = 0xff & (255 * i / 100);\n } else {\n xingSeekTable(gfc.VBR_seek_table, toc);\n }\n\n // Start writing the tag after the zero frame\n var streamIndex = gfc.sideinfo_len;\n /**\n * Note: Xing header specifies that Xing data goes in the ancillary data\n * with NO ERROR PROTECTION. If error protecton in enabled, the Xing\n * data still starts at the same offset, and now it is in sideinfo data\n * block, and thus will not decode correctly by non-Xing tag aware\n * players\n */\n if (gfp.error_protection)\n streamIndex -= 2;\n\n // Put Vbr tag\n if (gfp.VBR == VbrMode.vbr_off) {\n buffer[streamIndex++] = 0xff & VBRTag1.charAt(0);\n buffer[streamIndex++] = 0xff & VBRTag1.charAt(1);\n buffer[streamIndex++] = 0xff & VBRTag1.charAt(2);\n buffer[streamIndex++] = 0xff & VBRTag1.charAt(3);\n\n } else {\n buffer[streamIndex++] = 0xff & VBRTag0.charAt(0);\n buffer[streamIndex++] = 0xff & VBRTag0.charAt(1);\n buffer[streamIndex++] = 0xff & VBRTag0.charAt(2);\n buffer[streamIndex++] = 0xff & VBRTag0.charAt(3);\n }\n\n // Put header flags\n createInteger(buffer, streamIndex, FRAMES_FLAG + BYTES_FLAG + TOC_FLAG\n + VBR_SCALE_FLAG);\n streamIndex += 4;\n\n // Put Total Number of frames\n createInteger(buffer, streamIndex, gfc.VBR_seek_table.nVbrNumFrames);\n streamIndex += 4;\n\n // Put total audio stream size, including Xing/LAME Header\n var streamSize = (gfc.VBR_seek_table.nBytesWritten + gfc.VBR_seek_table.TotalFrameSize);\n createInteger(buffer, streamIndex, 0 | streamSize);\n streamIndex += 4;\n\n /* Put TOC */\n System.arraycopy(toc, 0, buffer, streamIndex, toc.length);\n streamIndex += toc.length;\n\n if (gfp.error_protection) {\n // (jo) error_protection: add crc16 information to header\n bs.CRC_writeheader(gfc, buffer);\n }\n\n // work out CRC so far: initially crc = 0\n var crc = 0x00;\n for (var i = 0; i < streamIndex; i++)\n crc = crcUpdateLookup(buffer[i], crc);\n // Put LAME VBR info\n streamIndex += putLameVBR(gfp, streamSize, buffer, streamIndex, crc);\n\n return gfc.VBR_seek_table.TotalFrameSize;\n }\n\n /**\n * Write final VBR tag to the file.\n *\n * @param gfp\n * global flags\n * @param stream\n * stream to add the VBR tag to\n * @return 0 (OK), -1 else\n * @throws IOException\n * I/O error\n */\n this.putVbrTag = function (gfp, stream) {\n var gfc = gfp.internal_flags;\n\n if (gfc.VBR_seek_table.pos <= 0)\n return -1;\n\n // Seek to end of file\n stream.seek(stream.length());\n\n // Get file size, abort if file has zero length.\n if (stream.length() == 0)\n return -1;\n\n // The VBR tag may NOT be located at the beginning of the stream. If an\n // ID3 version 2 tag was added, then it must be skipped to write the VBR\n // tag data.\n var id3v2TagSize = skipId3v2(stream);\n\n // Seek to the beginning of the stream\n stream.seek(id3v2TagSize);\n\n var buffer = new_byte(MAXFRAMESIZE);\n var bytes = getLameTagFrame(gfp, buffer);\n if (bytes > buffer.length) {\n return -1;\n }\n\n if (bytes < 1) {\n return 0;\n }\n\n // Put it all to disk again\n stream.write(buffer, 0, bytes);\n // success\n return 0;\n }\n\n}\n\nmodule.exports = VBRTag;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiM09HUi5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvVkJSVGFnLmpzP2RjZTEiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIGNvbW1vbiA9IHJlcXVpcmUoJy4vY29tbW9uLmpzJyk7XG52YXIgU3lzdGVtID0gY29tbW9uLlN5c3RlbTtcbnZhciBWYnJNb2RlID0gY29tbW9uLlZick1vZGU7XG52YXIgRmxvYXQgPSBjb21tb24uRmxvYXQ7XG52YXIgU2hvcnRCbG9jayA9IGNvbW1vbi5TaG9ydEJsb2NrO1xudmFyIFV0aWwgPSBjb21tb24uVXRpbDtcbnZhciBBcnJheXMgPSBjb21tb24uQXJyYXlzO1xudmFyIG5ld19hcnJheV9uID0gY29tbW9uLm5ld19hcnJheV9uO1xudmFyIG5ld19ieXRlID0gY29tbW9uLm5ld19ieXRlO1xudmFyIG5ld19kb3VibGUgPSBjb21tb24ubmV3X2RvdWJsZTtcbnZhciBuZXdfZmxvYXQgPSBjb21tb24ubmV3X2Zsb2F0O1xudmFyIG5ld19mbG9hdF9uID0gY29tbW9uLm5ld19mbG9hdF9uO1xudmFyIG5ld19pbnQgPSBjb21tb24ubmV3X2ludDtcbnZhciBuZXdfaW50X24gPSBjb21tb24ubmV3X2ludF9uO1xudmFyIGFzc2VydCA9IGNvbW1vbi5hc3NlcnQ7XG5cbi8qKlxuICogQSBWYnIgaGVhZGVyIG1heSBiZSBwcmVzZW50IGluIHRoZSBhbmNpbGxhcnkgZGF0YSBmaWVsZCBvZiB0aGUgZmlyc3QgZnJhbWUgb2ZcbiAqIGFuIG1wMyBiaXRzdHJlYW08QlI+XG4gKiBUaGUgVmJyIGhlYWRlciAob3B0aW9uYWxseSkgY29udGFpbnNcbiAqIDxVTD5cbiAqIDxMST5mcmFtZXMgdG90YWwgbnVtYmVyIG9mIGF1ZGlvIGZyYW1lcyBpbiB0aGUgYml0c3RyZWFtXG4gKiA8TEk+Ynl0ZXMgdG90YWwgbnVtYmVyIG9mIGJ5dGVzIGluIHRoZSBiaXRzdHJlYW1cbiAqIDxMST50b2MgdGFibGUgb2YgY29udGVudHNcbiAqIDwvVUw+XG4gKlxuICogdG9jICh0YWJsZSBvZiBjb250ZW50cykgZ2l2ZXMgc2VlayBwb2ludHMgZm9yIHJhbmRvbSBhY2Nlc3MuPEJSPlxuICogVGhlIGl0aCBlbnRyeSBkZXRlcm1pbmVzIHRoZSBzZWVrIHBvaW50IGZvciBpLXBlcmNlbnQgZHVyYXRpb24uPEJSPlxuICogc2VlayBwb2ludCBpbiBieXRlcyA9ICh0b2NbaV0vMjU2LjApICogdG90YWxfYml0c3RyZWFtX2J5dGVzPEJSPlxuICogZS5nLiBoYWxmIGR1cmF0aW9uIHNlZWsgcG9pbnQgPSAodG9jWzUwXS8yNTYuMCkgKiB0b3RhbF9iaXRzdHJlYW1fYnl0ZXNcbiAqL1xuVkJSVGFnLk5VTVRPQ0VOVFJJRVMgPSAxMDA7XG5WQlJUYWcuTUFYRlJBTUVTSVpFID0gMjg4MDtcblxuZnVuY3Rpb24gVkJSVGFnKCkge1xuXG4gICAgdmFyIGxhbWU7XG4gICAgdmFyIGJzO1xuICAgIHZhciB2O1xuXG4gICAgdGhpcy5zZXRNb2R1bGVzID0gZnVuY3Rpb24gKF9sYW1lLCBfYnMsIF92KSB7XG4gICAgICAgIGxhbWUgPSBfbGFtZTtcbiAgICAgICAgYnMgPSBfYnM7XG4gICAgICAgIHYgPSBfdjtcbiAgICB9O1xuXG4gICAgdmFyIEZSQU1FU19GTEFHID0gMHgwMDAxO1xuICAgIHZhciBCWVRFU19GTEFHID0gMHgwMDAyO1xuICAgIHZhciBUT0NfRkxBRyA9IDB4MDAwNDtcbiAgICB2YXIgVkJSX1NDQUxFX0ZMQUcgPSAweDAwMDg7XG5cbiAgICB2YXIgTlVNVE9DRU5UUklFUyA9IFZCUlRhZy5OVU1UT0NFTlRSSUVTO1xuXG4gICAgLyoqXG4gICAgICogKDB4QjQwKSB0aGUgbWF4IGZyZWVmb3JtYXQgNjQwIDMya0h6IGZyYW1lc2l6ZS5cbiAgICAgKi9cbiAgICB2YXIgTUFYRlJBTUVTSVpFID0gVkJSVGFnLk1BWEZSQU1FU0laRTtcblxuICAgIC8qKlxuICAgICAqIDxQUkU+XG4gICAgICogICAgNCBieXRlcyBmb3IgSGVhZGVyIFRhZ1xuICAgICAqICAgIDQgYnl0ZXMgZm9yIEhlYWRlciBGbGFnc1xuICAgICAqICAxMDAgYnl0ZXMgZm9yIGVudHJ5ICh0b2MpXG4gICAgICogICAgNCBieXRlcyBmb3IgZnJhbWUgc2l6ZVxuICAgICAqICAgIDQgYnl0ZXMgZm9yIHN0cmVhbSBzaXplXG4gICAgICogICAgNCBieXRlcyBmb3IgVkJSIHNjYWxlLiBhIFZCUiBxdWFsaXR5IGluZGljYXRvcjogMD1iZXN0IDEwMD13b3JzdFxuICAgICAqICAgMjAgYnl0ZXMgZm9yIExBTUUgdGFnLiAgZm9yIGV4YW1wbGUsIFwiTEFNRTMuMTIgKGJldGEgNilcIlxuICAgICAqIF9fX19fX19fX19fXG4gICAgICogIDE0MCBieXRlc1xuICAgICAqIDwvUFJFPlxuICAgICAqL1xuICAgIHZhciBWQlJIRUFERVJTSVpFID0gKE5VTVRPQ0VOVFJJRVMgKyA0ICsgNCArIDQgKyA0ICsgNCk7XG5cbiAgICB2YXIgTEFNRUhFQURFUlNJWkUgPSAoVkJSSEVBREVSU0laRSArIDkgKyAxICsgMSArIDhcbiAgICArIDEgKyAxICsgMyArIDEgKyAxICsgMiArIDQgKyAyICsgMik7XG5cbiAgICAvKipcbiAgICAgKiBUaGUgc2l6ZSBvZiB0aGUgWGluZyBoZWFkZXIgTVBFRy0xLCBiaXQgcmF0ZSBpbiBrYnBzLlxuICAgICAqL1xuICAgIHZhciBYSU5HX0JJVFJBVEUxID0gMTI4O1xuICAgIC8qKlxuICAgICAqIFRoZSBzaXplIG9mIHRoZSBYaW5nIGhlYWRlciBNUEVHLTIsIGJpdCByYXRlIGluIGticHMuXG4gICAgICovXG4gICAgdmFyIFhJTkdfQklUUkFURTIgPSA2NDtcbiAgICAvKipcbiAgICAgKiBUaGUgc2l6ZSBvZiB0aGUgWGluZyBoZWFkZXIgTVBFRy0yLjUsIGJpdCByYXRlIGluIGticHMuXG4gICAgICovXG4gICAgdmFyIFhJTkdfQklUUkFURTI1ID0gMzI7XG5cbiAgICAvKipcbiAgICAgKiBJU08tODg1OS0xIGNoYXJzZXQgZm9yIGJ5dGUgdG8gc3RyaW5nIG9wZXJhdGlvbnMuXG4gICAgICovXG4gICAgdmFyIElTT184ODU5XzEgPSBudWxsOyAvL0NoYXJzZXQuZm9yTmFtZShcIklTTy04ODU5LTFcIik7XG5cbiAgICAvKipcbiAgICAgKiBWQlIgaGVhZGVyIG1hZ2ljIHN0cmluZy5cbiAgICAgKi9cbiAgICB2YXIgVkJSVGFnMCA9IFwiWGluZ1wiO1xuICAgIC8qKlxuICAgICAqIFZCUiBoZWFkZXIgbWFnaWMgc3RyaW5nIChWQlIgPT0gVkJSTW9kZS52YnJfb2ZmKS5cbiAgICAgKi9cbiAgICB2YXIgVkJSVGFnMSA9IFwiSW5mb1wiO1xuXG4gICAgLyoqXG4gICAgICogTG9va3VwIHRhYmxlIGZvciBmYXN0IENSQy0xNiBjb21wdXRhdGlvbi4gVXNlcyB0aGUgcG9seW5vbWlhbFxuICAgICAqIHheMTYreF4xNSt4XjIrMVxuICAgICAqL1xuICAgIHZhciBjcmMxNkxvb2t1cCA9IFsweDAwMDAsIDB4QzBDMSwgMHhDMTgxLCAweDAxNDAsXG4gICAgICAgIDB4QzMwMSwgMHgwM0MwLCAweDAyODAsIDB4QzI0MSwgMHhDNjAxLCAweDA2QzAsIDB4MDc4MCwgMHhDNzQxLFxuICAgICAgICAweDA1MDAsIDB4QzVDMSwgMHhDNDgxLCAweDA0NDAsIDB4Q0MwMSwgMHgwQ0MwLCAweDBEODAsIDB4Q0Q0MSxcbiAgICAgICAgMHgwRjAwLCAweENGQzEsIDB4Q0U4MSwgMHgwRTQwLCAweDBBMDAsIDB4Q0FDMSwgMHhDQjgxLCAweDBCNDAsXG4gICAgICAgIDB4QzkwMSwgMHgwOUMwLCAweDA4ODAsIDB4Qzg0MSwgMHhEODAxLCAweDE4QzAsIDB4MTk4MCwgMHhEOTQxLFxuICAgICAgICAweDFCMDAsIDB4REJDMSwgMHhEQTgxLCAweDFBNDAsIDB4MUUwMCwgMHhERUMxLCAweERGODEsIDB4MUY0MCxcbiAgICAgICAgMHhERDAxLCAweDFEQzAsIDB4MUM4MCwgMHhEQzQxLCAweDE0MDAsIDB4RDRDMSwgMHhENTgxLCAweDE1NDAsXG4gICAgICAgIDB4RDcwMSwgMHgxN0MwLCAweDE2ODAsIDB4RDY0MSwgMHhEMjAxLCAweDEyQzAsIDB4MTM4MCwgMHhEMzQxLFxuICAgICAgICAweDExMDAsIDB4RDFDMSwgMHhEMDgxLCAweDEwNDAsIDB4RjAwMSwgMHgzMEMwLCAweDMxODAsIDB4RjE0MSxcbiAgICAgICAgMHgzMzAwLCAweEYzQzEsIDB4RjI4MSwgMHgzMjQwLCAweDM2MDAsIDB4RjZDMSwgMHhGNzgxLCAweDM3NDAsXG4gICAgICAgIDB4RjUwMSwgMHgzNUMwLCAweDM0ODAsIDB4RjQ0MSwgMHgzQzAwLCAweEZDQzEsIDB4RkQ4MSwgMHgzRDQwLFxuICAgICAgICAweEZGMDEsIDB4M0ZDMCwgMHgzRTgwLCAweEZFNDEsIDB4RkEwMSwgMHgzQUMwLCAweDNCODAsIDB4RkI0MSxcbiAgICAgICAgMHgzOTAwLCAweEY5QzEsIDB4Rjg4MSwgMHgzODQwLCAweDI4MDAsIDB4RThDMSwgMHhFOTgxLCAweDI5NDAsXG4gICAgICAgIDB4RUIwMSwgMHgyQkMwLCAweDJBODAsIDB4RUE0MSwgMHhFRTAxLCAweDJFQzAsIDB4MkY4MCwgMHhFRjQxLFxuICAgICAgICAweDJEMDAsIDB4RURDMSwgMHhFQzgxLCAweDJDNDAsIDB4RTQwMSwgMHgyNEMwLCAweDI1ODAsIDB4RTU0MSxcbiAgICAgICAgMHgyNzAwLCAweEU3QzEsIDB4RTY4MSwgMHgyNjQwLCAweDIyMDAsIDB4RTJDMSwgMHhFMzgxLCAweDIzNDAsXG4gICAgICAgIDB4RTEwMSwgMHgyMUMwLCAweDIwODAsIDB4RTA0MSwgMHhBMDAxLCAweDYwQzAsIDB4NjE4MCwgMHhBMTQxLFxuICAgICAgICAweDYzMDAsIDB4QTNDMSwgMHhBMjgxLCAweDYyNDAsIDB4NjYwMCwgMHhBNkMxLCAweEE3ODEsIDB4Njc0MCxcbiAgICAgICAgMHhBNTAxLCAweDY1QzAsIDB4NjQ4MCwgMHhBNDQxLCAweDZDMDAsIDB4QUNDMSwgMHhBRDgxLCAweDZENDAsXG4gICAgICAgIDB4QUYwMSwgMHg2RkMwLCAweDZFODAsIDB4QUU0MSwgMHhBQTAxLCAweDZBQzAsIDB4NkI4MCwgMHhBQjQxLFxuICAgICAgICAweDY5MDAsIDB4QTlDMSwgMHhBODgxLCAweDY4NDAsIDB4NzgwMCwgMHhCOEMxLCAweEI5ODEsIDB4Nzk0MCxcbiAgICAgICAgMHhCQjAxLCAweDdCQzAsIDB4N0E4MCwgMHhCQTQxLCAweEJFMDEsIDB4N0VDMCwgMHg3RjgwLCAweEJGNDEsXG4gICAgICAgIDB4N0QwMCwgMHhCREMxLCAweEJDODEsIDB4N0M0MCwgMHhCNDAxLCAweDc0QzAsIDB4NzU4MCwgMHhCNTQxLFxuICAgICAgICAweDc3MDAsIDB4QjdDMSwgMHhCNjgxLCAweDc2NDAsIDB4NzIwMCwgMHhCMkMxLCAweEIzODEsIDB4NzM0MCxcbiAgICAgICAgMHhCMTAxLCAweDcxQzAsIDB4NzA4MCwgMHhCMDQxLCAweDUwMDAsIDB4OTBDMSwgMHg5MTgxLCAweDUxNDAsXG4gICAgICAgIDB4OTMwMSwgMHg1M0MwLCAweDUyODAsIDB4OTI0MSwgMHg5NjAxLCAweDU2QzAsIDB4NTc4MCwgMHg5NzQxLFxuICAgICAgICAweDU1MDAsIDB4OTVDMSwgMHg5NDgxLCAweDU0NDAsIDB4OUMwMSwgMHg1Q0MwLCAweDVEODAsIDB4OUQ0MSxcbiAgICAgICAgMHg1RjAwLCAweDlGQzEsIDB4OUU4MSwgMHg1RTQwLCAweDVBMDAsIDB4OUFDMSwgMHg5QjgxLCAweDVCNDAsXG4gICAgICAgIDB4OTkwMSwgMHg1OUMwLCAweDU4ODAsIDB4OTg0MSwgMHg4ODAxLCAweDQ4QzAsIDB4NDk4MCwgMHg4OTQxLFxuICAgICAgICAweDRCMDAsIDB4OEJDMSwgMHg4QTgxLCAweDRBNDAsIDB4NEUwMCwgMHg4RUMxLCAweDhGODEsIDB4NEY0MCxcbiAgICAgICAgMHg4RDAxLCAweDREQzAsIDB4NEM4MCwgMHg4QzQxLCAweDQ0MDAsIDB4ODRDMSwgMHg4NTgxLCAweDQ1NDAsXG4gICAgICAgIDB4ODcwMSwgMHg0N0MwLCAweDQ2ODAsIDB4ODY0MSwgMHg4MjAxLCAweDQyQzAsIDB4NDM4MCwgMHg4MzQxLFxuICAgICAgICAweDQxMDAsIDB4ODFDMSwgMHg4MDgxLCAweDQwNDBdO1xuXG4gICAgLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqXG4gICAgICogUm9iZXJ0IEhlZ2VtYW5uIDIwMDEtMDEtMTdcbiAgICAgKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiovXG5cbiAgICBmdW5jdGlvbiBhZGRWYnIodiwgYml0cmF0ZSkge1xuICAgICAgICB2Lm5WYnJOdW1GcmFtZXMrKztcbiAgICAgICAgdi5zdW0gKz0gYml0cmF0ZTtcbiAgICAgICAgdi5zZWVuKys7XG5cbiAgICAgICAgaWYgKHYuc2VlbiA8IHYud2FudCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHYucG9zIDwgdi5zaXplKSB7XG4gICAgICAgICAgICB2LmJhZ1t2LnBvc10gPSB2LnN1bTtcbiAgICAgICAgICAgIHYucG9zKys7XG4gICAgICAgICAgICB2LnNlZW4gPSAwO1xuICAgICAgICB9XG4gICAgICAgIGlmICh2LnBvcyA9PSB2LnNpemUpIHtcbiAgICAgICAgICAgIGZvciAodmFyIGkgPSAxOyBpIDwgdi5zaXplOyBpICs9IDIpIHtcbiAgICAgICAgICAgICAgICB2LmJhZ1tpIC8gMl0gPSB2LmJhZ1tpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHYud2FudCAqPSAyO1xuICAgICAgICAgICAgdi5wb3MgLz0gMjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGZ1bmN0aW9uIHhpbmdTZWVrVGFibGUodiwgdCkge1xuICAgICAgICBpZiAodi5wb3MgPD0gMClcbiAgICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBmb3IgKHZhciBpID0gMTsgaSA8IE5VTVRPQ0VOVFJJRVM7ICsraSkge1xuICAgICAgICAgICAgdmFyIGogPSBpIC8gTlVNVE9DRU5UUklFUywgYWN0LCBzdW07XG4gICAgICAgICAgICB2YXIgaW5keCA9IDAgfCAoTWF0aC5mbG9vcihqICogdi5wb3MpKTtcbiAgICAgICAgICAgIGlmIChpbmR4ID4gdi5wb3MgLSAxKVxuICAgICAgICAgICAgICAgIGluZHggPSB2LnBvcyAtIDE7XG4gICAgICAgICAgICBhY3QgPSB2LmJhZ1tpbmR4XTtcbiAgICAgICAgICAgIHN1bSA9IHYuc3VtO1xuICAgICAgICAgICAgdmFyIHNlZWtfcG9pbnQgPSAwIHwgKDI1Ni4gKiBhY3QgLyBzdW0pO1xuICAgICAgICAgICAgaWYgKHNlZWtfcG9pbnQgPiAyNTUpXG4gICAgICAgICAgICAgICAgc2Vla19wb2ludCA9IDI1NTtcbiAgICAgICAgICAgIHRbaV0gPSAweGZmICYgc2Vla19wb2ludDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBWQlIgZW50cnksIHVzZWQgdG8gZmlsbCB0aGUgVkJSIFRPQyBlbnRyaWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIGdmcFxuICAgICAqICAgICAgICAgICAgZ2xvYmFsIGZsYWdzXG4gICAgICovXG4gICAgdGhpcy5hZGRWYnJGcmFtZSA9IGZ1bmN0aW9uIChnZnApIHtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcbiAgICAgICAgdmFyIGticHMgPSBUYWJsZXMuYml0cmF0ZV90YWJsZVtnZnAudmVyc2lvbl1bZ2ZjLmJpdHJhdGVfaW5kZXhdO1xuICAgICAgICBhc3NlcnQoZ2ZjLlZCUl9zZWVrX3RhYmxlLmJhZyAhPSBudWxsKTtcbiAgICAgICAgYWRkVmJyKGdmYy5WQlJfc2Vla190YWJsZSwga2Jwcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVhZCBiaWcgZW5kaWFuIGludGVnZXIgKDQtYnl0ZXMpIGZyb20gaGVhZGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIGJ1ZlxuICAgICAqICAgICAgICAgICAgaGVhZGVyIGNvbnRhaW5pbmcgdGhlIGludGVnZXJcbiAgICAgKiBAcGFyYW0gYnVmUG9zXG4gICAgICogICAgICAgICAgICBvZmZzZXQgaW50byB0aGUgaGVhZGVyXG4gICAgICogQHJldHVybiBleHRyYWN0ZWQgaW50ZWdlclxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGV4dHJhY3RJbnRlZ2VyKGJ1ZiwgYnVmUG9zKSB7XG4gICAgICAgIHZhciB4ID0gYnVmW2J1ZlBvcyArIDBdICYgMHhmZjtcbiAgICAgICAgeCA8PD0gODtcbiAgICAgICAgeCB8PSBidWZbYnVmUG9zICsgMV0gJiAweGZmO1xuICAgICAgICB4IDw8PSA4O1xuICAgICAgICB4IHw9IGJ1ZltidWZQb3MgKyAyXSAmIDB4ZmY7XG4gICAgICAgIHggPDw9IDg7XG4gICAgICAgIHggfD0gYnVmW2J1ZlBvcyArIDNdICYgMHhmZjtcbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV3JpdGUgYmlnIGVuZGlhbiBpbnRlZ2VyICg0LWJ5dGVzKSBpbiB0aGUgaGVhZGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIGJ1ZlxuICAgICAqICAgICAgICAgICAgaGVhZGVyIHRvIHdyaXRlIHRoZSBpbnRlZ2VyIGludG9cbiAgICAgKiBAcGFyYW0gYnVmUG9zXG4gICAgICogICAgICAgICAgICBvZmZzZXQgaW50byB0aGUgaGVhZGVyXG4gICAgICogQHBhcmFtIHZhbHVlXG4gICAgICogICAgICAgICAgICBpbnRlZ2VyIHZhbHVlIHRvIHdyaXRlXG4gICAgICovXG4gICAgZnVuY3Rpb24gY3JlYXRlSW50ZWdlcihidWYsIGJ1ZlBvcywgdmFsdWUpIHtcbiAgICAgICAgYnVmW2J1ZlBvcyArIDBdID0gMHhmZiAmICgodmFsdWUgPj4gMjQpICYgMHhmZik7XG4gICAgICAgIGJ1ZltidWZQb3MgKyAxXSA9IDB4ZmYgJiAoKHZhbHVlID4+IDE2KSAmIDB4ZmYpO1xuICAgICAgICBidWZbYnVmUG9zICsgMl0gPSAweGZmICYgKCh2YWx1ZSA+PiA4KSAmIDB4ZmYpO1xuICAgICAgICBidWZbYnVmUG9zICsgM10gPSAweGZmICYgKHZhbHVlICYgMHhmZik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV3JpdGUgYmlnIGVuZGlhbiBzaG9ydCAoMi1ieXRlcykgaW4gdGhlIGhlYWRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBidWZcbiAgICAgKiAgICAgICAgICAgIGhlYWRlciB0byB3cml0ZSB0aGUgaW50ZWdlciBpbnRvXG4gICAgICogQHBhcmFtIGJ1ZlBvc1xuICAgICAqICAgICAgICAgICAgb2Zmc2V0IGludG8gdGhlIGhlYWRlclxuICAgICAqIEBwYXJhbSB2YWx1ZVxuICAgICAqICAgICAgICAgICAgaW50ZWdlciB2YWx1ZSB0byB3cml0ZVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNyZWF0ZVNob3J0KGJ1ZiwgYnVmUG9zLCB2YWx1ZSkge1xuICAgICAgICBidWZbYnVmUG9zICsgMF0gPSAweGZmICYgKCh2YWx1ZSA+PiA4KSAmIDB4ZmYpO1xuICAgICAgICBidWZbYnVmUG9zICsgMV0gPSAweGZmICYgKHZhbHVlICYgMHhmZik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgZm9yIG1hZ2ljIHN0cmluZ3MgKFhpbmcvSW5mbykuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gYnVmXG4gICAgICogICAgICAgICAgICBoZWFkZXIgdG8gY2hlY2tcbiAgICAgKiBAcGFyYW0gYnVmUG9zXG4gICAgICogICAgICAgICAgICBoZWFkZXIgb2Zmc2V0IHRvIGNoZWNrXG4gICAgICogQHJldHVybiBtYWdpYyBzdHJpbmcgZm91bmRcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBpc1ZiclRhZyhidWYsIGJ1ZlBvcykge1xuICAgICAgICByZXR1cm4gbmV3IFN0cmluZyhidWYsIGJ1ZlBvcywgVkJSVGFnMC5sZW5ndGgoKSwgSVNPXzg4NTlfMSlcbiAgICAgICAgICAgICAgICAuZXF1YWxzKFZCUlRhZzApXG4gICAgICAgICAgICB8fCBuZXcgU3RyaW5nKGJ1ZiwgYnVmUG9zLCBWQlJUYWcxLmxlbmd0aCgpLCBJU09fODg1OV8xKVxuICAgICAgICAgICAgICAgIC5lcXVhbHMoVkJSVGFnMSk7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gc2hpZnRJbkJpdHNWYWx1ZSh4LCBuLCB2KSB7XG4gICAgICAgIHJldHVybiAweGZmICYgKCh4IDw8IG4pIHwgKHYgJiB+KC0xIDw8IG4pKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0IHRoZSBNUDMgaGVhZGVyIHVzaW5nIHRoZSBzZXR0aW5ncyBvZiB0aGUgZ2xvYmFsIGZsYWdzLlxuICAgICAqXG4gICAgICogPGltZyBzcmM9XCIxMDAwcHgtTXAzZmlsZXN0cnVjdHVyZS5zdmcucG5nXCI+XG4gICAgICpcbiAgICAgKiBAcGFyYW0gZ2ZwXG4gICAgICogICAgICAgICAgICBnbG9iYWwgZmxhZ3NcbiAgICAgKiBAcGFyYW0gYnVmZmVyXG4gICAgICogICAgICAgICAgICBoZWFkZXJcbiAgICAgKi9cbiAgICBmdW5jdGlvbiBzZXRMYW1lVGFnRnJhbWVIZWFkZXIoZ2ZwLCBidWZmZXIpIHtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcblxuICAgICAgICAvLyBNUDMgU3luYyBXb3JkXG4gICAgICAgIGJ1ZmZlclswXSA9IHNoaWZ0SW5CaXRzVmFsdWUoYnVmZmVyWzBdLCA4LCAweGZmKTtcblxuICAgICAgICBidWZmZXJbMV0gPSBzaGlmdEluQml0c1ZhbHVlKGJ1ZmZlclsxXSwgMywgNyk7XG4gICAgICAgIGJ1ZmZlclsxXSA9IHNoaWZ0SW5CaXRzVmFsdWUoYnVmZmVyWzFdLCAxLFxuICAgICAgICAgICAgKGdmcC5vdXRfc2FtcGxlcmF0ZSA8IDE2MDAwKSA/IDAgOiAxKTtcbiAgICAgICAgLy8gVmVyc2lvblxuICAgICAgICBidWZmZXJbMV0gPSBzaGlmdEluQml0c1ZhbHVlKGJ1ZmZlclsxXSwgMSwgZ2ZwLnZlcnNpb24pO1xuICAgICAgICAvLyAwMSA9PSBMYXllciAzXG4gICAgICAgIGJ1ZmZlclsxXSA9IHNoaWZ0SW5CaXRzVmFsdWUoYnVmZmVyWzFdLCAyLCA0IC0gMyk7XG4gICAgICAgIC8vIEVycm9yIHByb3RlY3Rpb25cbiAgICAgICAgYnVmZmVyWzFdID0gc2hpZnRJbkJpdHNWYWx1ZShidWZmZXJbMV0sIDEsICghZ2ZwLmVycm9yX3Byb3RlY3Rpb24pID8gMVxuICAgICAgICAgICAgOiAwKTtcblxuICAgICAgICAvLyBCaXQgcmF0ZVxuICAgICAgICBidWZmZXJbMl0gPSBzaGlmdEluQml0c1ZhbHVlKGJ1ZmZlclsyXSwgNCwgZ2ZjLmJpdHJhdGVfaW5kZXgpO1xuICAgICAgICAvLyBGcmVxdWVuY3lcbiAgICAgICAgYnVmZmVyWzJdID0gc2hpZnRJbkJpdHNWYWx1ZShidWZmZXJbMl0sIDIsIGdmYy5zYW1wbGVyYXRlX2luZGV4KTtcbiAgICAgICAgLy8gUGFkLiBCaXRcbiAgICAgICAgYnVmZmVyWzJdID0gc2hpZnRJbkJpdHNWYWx1ZShidWZmZXJbMl0sIDEsIDApO1xuICAgICAgICAvLyBQcml2LiBCaXRcbiAgICAgICAgYnVmZmVyWzJdID0gc2hpZnRJbkJpdHNWYWx1ZShidWZmZXJbMl0sIDEsIGdmcC5leHRlbnNpb24pO1xuXG4gICAgICAgIC8vIE1vZGVcbiAgICAgICAgYnVmZmVyWzNdID0gc2hpZnRJbkJpdHNWYWx1ZShidWZmZXJbM10sIDIsIGdmcC5tb2RlLm9yZGluYWwoKSk7XG4gICAgICAgIC8vIE1vZGUgZXh0ZW5zaW9uIChVc2VkIHdpdGggSm9pbnQgU3RlcmVvKVxuICAgICAgICBidWZmZXJbM10gPSBzaGlmdEluQml0c1ZhbHVlKGJ1ZmZlclszXSwgMiwgZ2ZjLm1vZGVfZXh0KTtcbiAgICAgICAgLy8gQ29weVxuICAgICAgICBidWZmZXJbM10gPSBzaGlmdEluQml0c1ZhbHVlKGJ1ZmZlclszXSwgMSwgZ2ZwLmNvcHlyaWdodCk7XG4gICAgICAgIC8vIE9yaWdpbmFsXG4gICAgICAgIGJ1ZmZlclszXSA9IHNoaWZ0SW5CaXRzVmFsdWUoYnVmZmVyWzNdLCAxLCBnZnAub3JpZ2luYWwpO1xuICAgICAgICAvLyBFbXBoYXNpc1xuICAgICAgICBidWZmZXJbM10gPSBzaGlmdEluQml0c1ZhbHVlKGJ1ZmZlclszXSwgMiwgZ2ZwLmVtcGhhc2lzKTtcblxuICAgICAgICAvKiB0aGUgZGVmYXVsdCBWQlIgaGVhZGVyLiA0OCBrYnBzIGxheWVyIElJSSwgbm8gcGFkZGluZywgbm8gY3JjICovXG4gICAgICAgIC8qIGJ1dCBzYW1wbGluZyBmcmVxLCBtb2RlIGFuZCBjb3B5cmlnaHQvY29weSBwcm90ZWN0aW9uIHRha2VuICovXG4gICAgICAgIC8qIGZyb20gZmlyc3QgdmFsaWQgZnJhbWUgKi9cbiAgICAgICAgYnVmZmVyWzBdID0gMHhmZjtcbiAgICAgICAgdmFyIGFieXRlID0gMHhmZiAmIChidWZmZXJbMV0gJiAweGYxKTtcbiAgICAgICAgdmFyIGJpdHJhdGU7XG4gICAgICAgIGlmICgxID09IGdmcC52ZXJzaW9uKSB7XG4gICAgICAgICAgICBiaXRyYXRlID0gWElOR19CSVRSQVRFMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChnZnAub3V0X3NhbXBsZXJhdGUgPCAxNjAwMClcbiAgICAgICAgICAgICAgICBiaXRyYXRlID0gWElOR19CSVRSQVRFMjU7XG4gICAgICAgICAgICBlbHNlXG4gICAgICAgICAgICAgICAgYml0cmF0ZSA9IFhJTkdfQklUUkFURTI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2ZwLlZCUiA9PSBWYnJNb2RlLnZicl9vZmYpXG4gICAgICAgICAgICBiaXRyYXRlID0gZ2ZwLmJyYXRlO1xuXG4gICAgICAgIHZhciBiYnl0ZTtcbiAgICAgICAgaWYgKGdmcC5mcmVlX2Zvcm1hdClcbiAgICAgICAgICAgIGJieXRlID0gMHgwMDtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgYmJ5dGUgPSAweGZmICYgKDE2ICogbGFtZS5CaXRyYXRlSW5kZXgoYml0cmF0ZSwgZ2ZwLnZlcnNpb24sXG4gICAgICAgICAgICAgICAgICAgIGdmcC5vdXRfc2FtcGxlcmF0ZSkpO1xuXG4gICAgICAgIC8qXG4gICAgICAgICAqIFVzZSBhcyBtdWNoIG9mIHRoZSBpbmZvIGZyb20gdGhlIHJlYWwgZnJhbWVzIGluIHRoZSBYaW5nIGhlYWRlcjpcbiAgICAgICAgICogc2FtcGxlcmF0ZSwgY2hhbm5lbHMsIGNyYywgZXRjLi4uXG4gICAgICAgICAqL1xuICAgICAgICBpZiAoZ2ZwLnZlcnNpb24gPT0gMSkge1xuICAgICAgICAgICAgLyogTVBFRzEgKi9cbiAgICAgICAgICAgIGJ1ZmZlclsxXSA9IDB4ZmYgJiAoYWJ5dGUgfCAweDBhKTtcbiAgICAgICAgICAgIC8qIHdhcyAweDBiOyAqL1xuICAgICAgICAgICAgYWJ5dGUgPSAweGZmICYgKGJ1ZmZlclsyXSAmIDB4MGQpO1xuICAgICAgICAgICAgLyogQUYga2VlcCBhbHNvIHByaXZhdGUgYml0ICovXG4gICAgICAgICAgICBidWZmZXJbMl0gPSAweGZmICYgKGJieXRlIHwgYWJ5dGUpO1xuICAgICAgICAgICAgLyogNjRrYnMgTVBFRzEgZnJhbWUgKi9cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8qIE1QRUcyICovXG4gICAgICAgICAgICBidWZmZXJbMV0gPSAweGZmICYgKGFieXRlIHwgMHgwMik7XG4gICAgICAgICAgICAvKiB3YXMgMHgwMzsgKi9cbiAgICAgICAgICAgIGFieXRlID0gMHhmZiAmIChidWZmZXJbMl0gJiAweDBkKTtcbiAgICAgICAgICAgIC8qIEFGIGtlZXAgYWxzbyBwcml2YXRlIGJpdCAqL1xuICAgICAgICAgICAgYnVmZmVyWzJdID0gMHhmZiAmIChiYnl0ZSB8IGFieXRlKTtcbiAgICAgICAgICAgIC8qIDY0a2JzIE1QRUcyIGZyYW1lICovXG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXQgVkJSIHRhZyBpbmZvcm1hdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIGJ1ZlxuICAgICAqICAgICAgICAgICAgaGVhZGVyIHRvIGFuYWx5emVcbiAgICAgKiBAcGFyYW0gYnVmUG9zXG4gICAgICogICAgICAgICAgICBvZmZzZXQgaW50byB0aGUgaGVhZGVyXG4gICAgICogQHJldHVybiBWQlIgdGFnIGRhdGFcbiAgICAgKi9cbiAgICB0aGlzLmdldFZiclRhZyA9IGZ1bmN0aW9uIChidWYpIHtcbiAgICAgICAgdmFyIHBUYWdEYXRhID0gbmV3IFZCUlRhZ0RhdGEoKTtcbiAgICAgICAgdmFyIGJ1ZlBvcyA9IDA7XG5cbiAgICAgICAgLyogZ2V0IFZiciBoZWFkZXIgZGF0YSAqL1xuICAgICAgICBwVGFnRGF0YS5mbGFncyA9IDA7XG5cbiAgICAgICAgLyogZ2V0IHNlbGVjdGVkIE1QRUcgaGVhZGVyIGRhdGEgKi9cbiAgICAgICAgdmFyIGhJZCA9IChidWZbYnVmUG9zICsgMV0gPj4gMykgJiAxO1xuICAgICAgICB2YXIgaFNySW5kZXggPSAoYnVmW2J1ZlBvcyArIDJdID4+IDIpICYgMztcbiAgICAgICAgdmFyIGhNb2RlID0gKGJ1ZltidWZQb3MgKyAzXSA+PiA2KSAmIDM7XG4gICAgICAgIHZhciBoQml0cmF0ZSA9ICgoYnVmW2J1ZlBvcyArIDJdID4+IDQpICYgMHhmKTtcbiAgICAgICAgaEJpdHJhdGUgPSBUYWJsZXMuYml0cmF0ZV90YWJsZVtoSWRdW2hCaXRyYXRlXTtcblxuICAgICAgICAvKiBjaGVjayBmb3IgRkZFIHN5bmN3b3JkICovXG4gICAgICAgIGlmICgoYnVmW2J1ZlBvcyArIDFdID4+IDQpID09IDB4RSlcbiAgICAgICAgICAgIHBUYWdEYXRhLnNhbXByYXRlID0gVGFibGVzLnNhbXBsZXJhdGVfdGFibGVbMl1baFNySW5kZXhdO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBwVGFnRGF0YS5zYW1wcmF0ZSA9IFRhYmxlcy5zYW1wbGVyYXRlX3RhYmxlW2hJZF1baFNySW5kZXhdO1xuXG4gICAgICAgIC8qIGRldGVybWluZSBvZmZzZXQgb2YgaGVhZGVyICovXG4gICAgICAgIGlmIChoSWQgIT0gMCkge1xuICAgICAgICAgICAgLyogbXBlZzEgKi9cbiAgICAgICAgICAgIGlmIChoTW9kZSAhPSAzKVxuICAgICAgICAgICAgICAgIGJ1ZlBvcyArPSAoMzIgKyA0KTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBidWZQb3MgKz0gKDE3ICsgNCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvKiBtcGVnMiAqL1xuICAgICAgICAgICAgaWYgKGhNb2RlICE9IDMpXG4gICAgICAgICAgICAgICAgYnVmUG9zICs9ICgxNyArIDQpO1xuICAgICAgICAgICAgZWxzZVxuICAgICAgICAgICAgICAgIGJ1ZlBvcyArPSAoOSArIDQpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFpc1ZiclRhZyhidWYsIGJ1ZlBvcykpXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcblxuICAgICAgICBidWZQb3MgKz0gNDtcblxuICAgICAgICBwVGFnRGF0YS5oSWQgPSBoSWQ7XG5cbiAgICAgICAgLyogZ2V0IGZsYWdzICovXG4gICAgICAgIHZhciBoZWFkX2ZsYWdzID0gcFRhZ0RhdGEuZmxhZ3MgPSBleHRyYWN0SW50ZWdlcihidWYsIGJ1ZlBvcyk7XG4gICAgICAgIGJ1ZlBvcyArPSA0O1xuXG4gICAgICAgIGlmICgoaGVhZF9mbGFncyAmIEZSQU1FU19GTEFHKSAhPSAwKSB7XG4gICAgICAgICAgICBwVGFnRGF0YS5mcmFtZXMgPSBleHRyYWN0SW50ZWdlcihidWYsIGJ1ZlBvcyk7XG4gICAgICAgICAgICBidWZQb3MgKz0gNDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgoaGVhZF9mbGFncyAmIEJZVEVTX0ZMQUcpICE9IDApIHtcbiAgICAgICAgICAgIHBUYWdEYXRhLmJ5dGVzID0gZXh0cmFjdEludGVnZXIoYnVmLCBidWZQb3MpO1xuICAgICAgICAgICAgYnVmUG9zICs9IDQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKGhlYWRfZmxhZ3MgJiBUT0NfRkxBRykgIT0gMCkge1xuICAgICAgICAgICAgaWYgKHBUYWdEYXRhLnRvYyAhPSBudWxsKSB7XG4gICAgICAgICAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBOVU1UT0NFTlRSSUVTOyBpKyspXG4gICAgICAgICAgICAgICAgICAgIHBUYWdEYXRhLnRvY1tpXSA9IGJ1ZltidWZQb3MgKyBpXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGJ1ZlBvcyArPSBOVU1UT0NFTlRSSUVTO1xuICAgICAgICB9XG5cbiAgICAgICAgcFRhZ0RhdGEudmJyU2NhbGUgPSAtMTtcblxuICAgICAgICBpZiAoKGhlYWRfZmxhZ3MgJiBWQlJfU0NBTEVfRkxBRykgIT0gMCkge1xuICAgICAgICAgICAgcFRhZ0RhdGEudmJyU2NhbGUgPSBleHRyYWN0SW50ZWdlcihidWYsIGJ1ZlBvcyk7XG4gICAgICAgICAgICBidWZQb3MgKz0gNDtcbiAgICAgICAgfVxuXG4gICAgICAgIHBUYWdEYXRhLmhlYWRlcnNpemUgPSAoKGhJZCArIDEpICogNzIwMDAgKiBoQml0cmF0ZSlcbiAgICAgICAgICAgIC8gcFRhZ0RhdGEuc2FtcHJhdGU7XG5cbiAgICAgICAgYnVmUG9zICs9IDIxO1xuICAgICAgICB2YXIgZW5jRGVsYXkgPSBidWZbYnVmUG9zICsgMF0gPDwgNDtcbiAgICAgICAgZW5jRGVsYXkgKz0gYnVmW2J1ZlBvcyArIDFdID4+IDQ7XG4gICAgICAgIHZhciBlbmNQYWRkaW5nID0gKGJ1ZltidWZQb3MgKyAxXSAmIDB4MEYpIDw8IDg7XG4gICAgICAgIGVuY1BhZGRpbmcgKz0gYnVmW2J1ZlBvcyArIDJdICYgMHhmZjtcbiAgICAgICAgLyogY2hlY2sgZm9yIHJlYXNvbmFibGUgdmFsdWVzICh0aGlzIG1heSBiZSBhbiBvbGQgWGluZyBoZWFkZXIsICovXG4gICAgICAgIC8qIG5vdCBhIElORk8gdGFnKSAqL1xuICAgICAgICBpZiAoZW5jRGVsYXkgPCAwIHx8IGVuY0RlbGF5ID4gMzAwMClcbiAgICAgICAgICAgIGVuY0RlbGF5ID0gLTE7XG4gICAgICAgIGlmIChlbmNQYWRkaW5nIDwgMCB8fCBlbmNQYWRkaW5nID4gMzAwMClcbiAgICAgICAgICAgIGVuY1BhZGRpbmcgPSAtMTtcblxuICAgICAgICBwVGFnRGF0YS5lbmNEZWxheSA9IGVuY0RlbGF5O1xuICAgICAgICBwVGFnRGF0YS5lbmNQYWRkaW5nID0gZW5jUGFkZGluZztcblxuICAgICAgICAvKiBzdWNjZXNzICovXG4gICAgICAgIHJldHVybiBwVGFnRGF0YTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplcyB0aGUgaGVhZGVyXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZ2ZwXG4gICAgICogICAgICAgICAgICBnbG9iYWwgZmxhZ3NcbiAgICAgKi9cbiAgICB0aGlzLkluaXRWYnJUYWcgPSBmdW5jdGlvbiAoZ2ZwKSB7XG4gICAgICAgIHZhciBnZmMgPSBnZnAuaW50ZXJuYWxfZmxhZ3M7XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIDxQUkU+XG4gICAgICAgICAqIFhpbmcgVkJSIHByZXRlbmRzIHRvIGJlIGEgNDhrYnMgbGF5ZXIgSUlJIGZyYW1lLiAgKGF0IDQ0LjFrSHopLlxuICAgICAgICAgKiAoYXQgNDhrSHogdGhleSB1c2UgNTZrYnMgc2luY2UgNDhrYnMgZnJhbWUgbm90IGJpZyBlbm91Z2ggZm9yXG4gICAgICAgICAqIHRhYmxlIG9mIGNvbnRlbnRzKVxuICAgICAgICAgKiBsZXQncyBhbHdheXMgZW1iZWQgWGluZyBoZWFkZXIgaW5zaWRlIGEgNjRrYnMgbGF5ZXIgSUlJIGZyYW1lLlxuICAgICAgICAgKiB0aGlzIGdpdmVzIHVzIGVub3VnaCByb29tIGZvciBhIExBTUUgdmVyc2lvbiBzdHJpbmcgdG9vLlxuICAgICAgICAgKiBzaXplIGRldGVybWluZWQgYnkgc2FtcGxpbmcgZnJlcXVlbmN5IChNUEVHMSlcbiAgICAgICAgICogMzJrSHo6ICAgIDIxNiBieXRlc0A0OGticyAgICAyODhieXRlc0AgNjRrYnNcbiAgICAgICAgICogNDQuMWtIejogIDE1NiBieXRlcyAgICAgICAgICAyMDhieXRlc0A2NGticyAgICAgKCsxIGlmIHBhZGRpbmcgPSAxKVxuICAgICAgICAgKiA0OGtIejogICAgMTQ0IGJ5dGVzICAgICAgICAgIDE5MlxuICAgICAgICAgKlxuICAgICAgICAgKiBNUEVHIDIgdmFsdWVzIGFyZSB0aGUgc2FtZSBzaW5jZSB0aGUgZnJhbWVzaXplIGFuZCBzYW1wbGVyYXRlXG4gICAgICAgICAqIGFyZSBlYWNoIHJlZHVjZWQgYnkgYSBmYWN0b3Igb2YgMi5cbiAgICAgICAgICogPC9QUkU+XG4gICAgICAgICAqL1xuICAgICAgICB2YXIga2Jwc19oZWFkZXI7XG4gICAgICAgIGlmICgxID09IGdmcC52ZXJzaW9uKSB7XG4gICAgICAgICAgICBrYnBzX2hlYWRlciA9IFhJTkdfQklUUkFURTE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAoZ2ZwLm91dF9zYW1wbGVyYXRlIDwgMTYwMDApXG4gICAgICAgICAgICAgICAga2Jwc19oZWFkZXIgPSBYSU5HX0JJVFJBVEUyNTtcbiAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICBrYnBzX2hlYWRlciA9IFhJTkdfQklUUkFURTI7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZ2ZwLlZCUiA9PSBWYnJNb2RlLnZicl9vZmYpXG4gICAgICAgICAgICBrYnBzX2hlYWRlciA9IGdmcC5icmF0ZTtcblxuICAgICAgICAvLyBtYWtlIHN1cmUgTEFNRSBIZWFkZXIgZml0cyBpbnRvIEZyYW1lXG4gICAgICAgIHZhciB0b3RhbEZyYW1lU2l6ZSA9ICgoZ2ZwLnZlcnNpb24gKyAxKSAqIDcyMDAwICoga2Jwc19oZWFkZXIpXG4gICAgICAgICAgICAvIGdmcC5vdXRfc2FtcGxlcmF0ZTtcbiAgICAgICAgdmFyIGhlYWRlclNpemUgPSAoZ2ZjLnNpZGVpbmZvX2xlbiArIExBTUVIRUFERVJTSVpFKTtcbiAgICAgICAgZ2ZjLlZCUl9zZWVrX3RhYmxlLlRvdGFsRnJhbWVTaXplID0gdG90YWxGcmFtZVNpemU7XG4gICAgICAgIGlmICh0b3RhbEZyYW1lU2l6ZSA8IGhlYWRlclNpemUgfHwgdG90YWxGcmFtZVNpemUgPiBNQVhGUkFNRVNJWkUpIHtcbiAgICAgICAgICAgIC8qIGRpc2FibGUgdGFnLCBpdCB3b250IGZpdCAqL1xuICAgICAgICAgICAgZ2ZwLmJXcml0ZVZiclRhZyA9IGZhbHNlO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZ2ZjLlZCUl9zZWVrX3RhYmxlLm5WYnJOdW1GcmFtZXMgPSAwO1xuICAgICAgICBnZmMuVkJSX3NlZWtfdGFibGUubkJ5dGVzV3JpdHRlbiA9IDA7XG4gICAgICAgIGdmYy5WQlJfc2Vla190YWJsZS5zdW0gPSAwO1xuXG4gICAgICAgIGdmYy5WQlJfc2Vla190YWJsZS5zZWVuID0gMDtcbiAgICAgICAgZ2ZjLlZCUl9zZWVrX3RhYmxlLndhbnQgPSAxO1xuICAgICAgICBnZmMuVkJSX3NlZWtfdGFibGUucG9zID0gMDtcblxuICAgICAgICBpZiAoZ2ZjLlZCUl9zZWVrX3RhYmxlLmJhZyA9PSBudWxsKSB7XG4gICAgICAgICAgICBnZmMuVkJSX3NlZWtfdGFibGUuYmFnID0gbmV3IGludFs0MDBdO1xuICAgICAgICAgICAgZ2ZjLlZCUl9zZWVrX3RhYmxlLnNpemUgPSA0MDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyB3cml0ZSBkdW1teSBWQlIgdGFnIG9mIGFsbCAwJ3MgaW50byBiaXRzdHJlYW1cbiAgICAgICAgdmFyIGJ1ZmZlciA9IG5ld19ieXRlKE1BWEZSQU1FU0laRSk7XG5cbiAgICAgICAgc2V0TGFtZVRhZ0ZyYW1lSGVhZGVyKGdmcCwgYnVmZmVyKTtcbiAgICAgICAgdmFyIG4gPSBnZmMuVkJSX3NlZWtfdGFibGUuVG90YWxGcmFtZVNpemU7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgbjsgKytpKSB7XG4gICAgICAgICAgICBicy5hZGRfZHVtbXlfYnl0ZShnZnAsIGJ1ZmZlcltpXSAmIDB4ZmYsIDEpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmFzdCBDUkMtMTYgY29tcHV0YXRpb24gKHVzZXMgdGFibGUgY3JjMTZMb29rdXApLlxuICAgICAqXG4gICAgICogQHBhcmFtIHZhbHVlXG4gICAgICogQHBhcmFtIGNyY1xuICAgICAqIEByZXR1cm5cbiAgICAgKi9cbiAgICBmdW5jdGlvbiBjcmNVcGRhdGVMb29rdXAodmFsdWUsIGNyYykge1xuICAgICAgICB2YXIgdG1wID0gY3JjIF4gdmFsdWU7XG4gICAgICAgIGNyYyA9IChjcmMgPj4gOCkgXiBjcmMxNkxvb2t1cFt0bXAgJiAweGZmXTtcbiAgICAgICAgcmV0dXJuIGNyYztcbiAgICB9XG5cbiAgICB0aGlzLnVwZGF0ZU11c2ljQ1JDID0gZnVuY3Rpb24gKGNyYywgYnVmZmVyLCBidWZmZXJQb3MsIHNpemUpIHtcbiAgICAgICAgZm9yICh2YXIgaSA9IDA7IGkgPCBzaXplOyArK2kpXG4gICAgICAgICAgICBjcmNbMF0gPSBjcmNVcGRhdGVMb29rdXAoYnVmZmVyW2J1ZmZlclBvcyArIGldLCBjcmNbMF0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdyaXRlIExBTUUgaW5mbzogbWluaSB2ZXJzaW9uICsgaW5mbyBvbiB2YXJpb3VzIHN3aXRjaGVzIHVzZWQgKEpvbmF0aGFuXG4gICAgICogRGVlIDIwMDEvMDgvMzEpLlxuICAgICAqXG4gICAgICogQHBhcmFtIGdmcFxuICAgICAqICAgICAgICAgICAgZ2xvYmFsIGZsYWdzXG4gICAgICogQHBhcmFtIG11c2ljTGVuZ3RoXG4gICAgICogICAgICAgICAgICBtdXNpYyBsZW5ndGhcbiAgICAgKiBAcGFyYW0gc3RyZWFtQnVmZmVyXG4gICAgICogICAgICAgICAgICBwb2ludGVyIHRvIG91dHB1dCBidWZmZXJcbiAgICAgKiBAcGFyYW0gc3RyZWFtQnVmZmVyUG9zXG4gICAgICogICAgICAgICAgICBvZmZzZXQgaW50byB0aGUgb3V0cHV0IGJ1ZmZlclxuICAgICAqIEBwYXJhbSBjcmNcbiAgICAgKiAgICAgICAgICAgIGNvbXB1dGF0aW9uIG9mIENSQy0xNiBvZiBMYW1lIFRhZyBzbyBmYXIgKHN0YXJ0aW5nIGF0IGZyYW1lXG4gICAgICogICAgICAgICAgICBzeW5jKVxuICAgICAqIEByZXR1cm4gbnVtYmVyIG9mIGJ5dGVzIHdyaXR0ZW4gdG8gdGhlIHN0cmVhbVxuICAgICAqL1xuICAgIGZ1bmN0aW9uIHB1dExhbWVWQlIoZ2ZwLCBtdXNpY0xlbmd0aCwgc3RyZWFtQnVmZmVyLCBzdHJlYW1CdWZmZXJQb3MsIGNyYykge1xuICAgICAgICB2YXIgZ2ZjID0gZ2ZwLmludGVybmFsX2ZsYWdzO1xuICAgICAgICB2YXIgYnl0ZXNXcml0dGVuID0gMDtcblxuICAgICAgICAvKiBlbmNvZGVyIGRlbGF5ICovXG4gICAgICAgIHZhciBlbmNEZWxheSA9IGdmcC5lbmNvZGVyX2RlbGF5O1xuICAgICAgICAvKiBlbmNvZGVyIHBhZGRpbmcgKi9cbiAgICAgICAgdmFyIGVuY1BhZGRpbmcgPSBnZnAuZW5jb2Rlcl9wYWRkaW5nO1xuXG4gICAgICAgIC8qIHJlY2FsbDogZ2ZwLlZCUl9xIGlzIGZvciBleGFtcGxlIHNldCBieSB0aGUgc3dpdGNoIC1WICovXG4gICAgICAgIC8qIGdmcC5xdWFsaXR5IGJ5IC1xLCAtaCwgLWYsIGV0YyAqL1xuICAgICAgICB2YXIgcXVhbGl0eSA9ICgxMDAgLSAxMCAqIGdmcC5WQlJfcSAtIGdmcC5xdWFsaXR5KTtcblxuICAgICAgICB2YXIgdmVyc2lvbiA9IHYuZ2V0TGFtZVZlcnlTaG9ydFZlcnNpb24oKTtcbiAgICAgICAgdmFyIHZicjtcbiAgICAgICAgdmFyIHJldmlzaW9uID0gMHgwMDtcbiAgICAgICAgdmFyIHJldk1ldGhvZDtcbiAgICAgICAgLy8gbnVtYmVyaW5nIGRpZmZlcmVudCBpbiB2YnJfbW9kZSB2cy4gTGFtZSB0YWdcbiAgICAgICAgdmFyIHZiclR5cGVUcmFuc2xhdG9yID0gWzEsIDUsIDMsIDIsIDQsIDAsIDNdO1xuICAgICAgICB2YXIgbG93cGFzcyA9IDAgfCAoKChnZnAubG93cGFzc2ZyZXEgLyAxMDAuMCkgKyAuNSkgPiAyNTUgPyAyNTVcbiAgICAgICAgICAgICAgICA6IChnZnAubG93cGFzc2ZyZXEgLyAxMDAuMCkgKyAuNSk7XG4gICAgICAgIHZhciBwZWFrU2lnbmFsQW1wbGl0dWRlID0gMDtcbiAgICAgICAgdmFyIHJhZGlvUmVwbGF5R2FpbiA9IDA7XG4gICAgICAgIHZhciBhdWRpb3BoaWxlUmVwbGF5R2FpbiA9IDA7XG4gICAgICAgIHZhciBub2lzZVNoYXBpbmcgPSBnZnAuaW50ZXJuYWxfZmxhZ3Mubm9pc2Vfc2hhcGluZztcbiAgICAgICAgdmFyIHN0ZXJlb01vZGUgPSAwO1xuICAgICAgICB2YXIgbm9uT3B0aW1hbCA9IDA7XG4gICAgICAgIHZhciBzb3VyY2VGcmVxID0gMDtcbiAgICAgICAgdmFyIG1pc2MgPSAwO1xuICAgICAgICB2YXIgbXVzaWNDUkMgPSAwO1xuXG4gICAgICAgIC8vIHBzeSBtb2RlbCB0eXBlOiBHcHN5Y2hvIG9yIE5zUHN5dHVuZVxuICAgICAgICB2YXIgZXhwTlBzeVR1bmUgPSAoZ2ZwLmV4cF9uc3BzeXR1bmUgJiAxKSAhPSAwO1xuICAgICAgICB2YXIgc2FmZUpvaW50ID0gKGdmcC5leHBfbnNwc3l0dW5lICYgMikgIT0gMDtcbiAgICAgICAgdmFyIG5vR2FwTW9yZSA9IGZhbHNlO1xuICAgICAgICB2YXIgbm9HYXBQcmV2aW91cyA9IGZhbHNlO1xuICAgICAgICB2YXIgbm9HYXBDb3VudCA9IGdmcC5pbnRlcm5hbF9mbGFncy5ub2dhcF90b3RhbDtcbiAgICAgICAgdmFyIG5vR2FwQ3VyciA9IGdmcC5pbnRlcm5hbF9mbGFncy5ub2dhcF9jdXJyZW50O1xuXG4gICAgICAgIC8vIDQgYml0c1xuICAgICAgICB2YXIgYXRoVHlwZSA9IGdmcC5BVEh0eXBlO1xuICAgICAgICB2YXIgZmxhZ3MgPSAwO1xuXG4gICAgICAgIC8vIHZiciBtb2Rlc1xuICAgICAgICB2YXIgYWJyQml0cmF0ZTtcbiAgICAgICAgc3dpdGNoIChnZnAuVkJSKSB7XG4gICAgICAgICAgICBjYXNlIHZicl9hYnI6XG4gICAgICAgICAgICAgICAgYWJyQml0cmF0ZSA9IGdmcC5WQlJfbWVhbl9iaXRyYXRlX2ticHM7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIHZicl9vZmY6XG4gICAgICAgICAgICAgICAgYWJyQml0cmF0ZSA9IGdmcC5icmF0ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgYWJyQml0cmF0ZSA9IGdmcC5WQlJfbWluX2JpdHJhdGVfa2JwcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIHJldmlzaW9uIGFuZCB2YnIgbWV0aG9kXG4gICAgICAgIGlmIChnZnAuVkJSLm9yZGluYWwoKSA8IHZiclR5cGVUcmFuc2xhdG9yLmxlbmd0aClcbiAgICAgICAgICAgIHZiciA9IHZiclR5cGVUcmFuc2xhdG9yW2dmcC5WQlIub3JkaW5hbCgpXTtcbiAgICAgICAgZWxzZVxuICAgICAgICAgICAgdmJyID0gMHgwMDsgLy8gdW5rbm93blxuXG4gICAgICAgIHJldk1ldGhvZCA9IDB4MTAgKiByZXZpc2lvbiArIHZicjtcblxuICAgICAgICAvLyBSZXBsYXlHYWluXG4gICAgICAgIGlmIChnZmMuZmluZFJlcGxheUdhaW4pIHtcbiAgICAgICAgICAgIGlmIChnZmMuUmFkaW9HYWluID4gMHgxRkUpXG4gICAgICAgICAgICAgICAgZ2ZjLlJhZGlvR2FpbiA9IDB4MUZFO1xuICAgICAgICAgICAgaWYgKGdmYy5SYWRpb0dhaW4gPCAtMHgxRkUpXG4gICAgICAgICAgICAgICAgZ2ZjLlJhZGlvR2FpbiA9IC0weDFGRTtcblxuICAgICAgICAgICAgLy8gc2V0IG5hbWUgY29kZVxuICAgICAgICAgICAgcmFkaW9SZXBsYXlHYWluID0gMHgyMDAwO1xuICAgICAgICAgICAgLy8gc2V0IG9yaWdpbmF0b3IgY29kZSB0byBgZGV0ZXJtaW5lZCBhdXRvbWF0aWNhbGx5J1xuICAgICAgICAgICAgcmFkaW9SZXBsYXlHYWluIHw9IDB4QzAwO1xuXG4gICAgICAgICAgICBpZiAoZ2ZjLlJhZGlvR2FpbiA+PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gc2V0IGdhaW4gYWRqdXN0bWVudFxuICAgICAgICAgICAgICAgIHJhZGlvUmVwbGF5R2FpbiB8PSBnZmMuUmFkaW9HYWluO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBzZXQgdGhlIHNpZ24gYml0XG4gICAgICAgICAgICAgICAgcmFkaW9SZXBsYXlHYWluIHw9IDB4MjAwO1xuICAgICAgICAgICAgICAgIC8vIHNldCBnYWluIGFkanVzdG1lbnRcbiAgICAgICAgICAgICAgICByYWRpb1JlcGxheUdhaW4gfD0gLWdmYy5SYWRpb0dhaW47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBwZWFrIHNhbXBsZVxuICAgICAgICBpZiAoZ2ZjLmZpbmRQZWFrU2FtcGxlKVxuICAgICAgICAgICAgcGVha1NpZ25hbEFtcGxpdHVkZSA9IE1hdGhcbiAgICAgICAgICAgICAgICAuYWJzKDAgfCAoKCggZ2ZjLlBlYWtTYW1wbGUpIC8gMzI3NjcuMCkgKiBNYXRoLnBvdygyLCAyMykgKyAuNSkpO1xuXG4gICAgICAgIC8vIG5vZ2FwXG4gICAgICAgIGlmIChub0dhcENvdW50ICE9IC0xKSB7XG4gICAgICAgICAgICBpZiAobm9HYXBDdXJyID4gMClcbiAgICAgICAgICAgICAgICBub0dhcFByZXZpb3VzID0gdHJ1ZTtcblxuICAgICAgICAgICAgaWYgKG5vR2FwQ3VyciA8IG5vR2FwQ291bnQgLSAxKVxuICAgICAgICAgICAgICAgIG5vR2FwTW9yZSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBmbGFnc1xuICAgICAgICBmbGFncyA9IGF0aFR5cGUgKyAoKGV4cE5Qc3lUdW5lID8gMSA6IDApIDw8IDQpXG4gICAgICAgICAgICArICgoc2FmZUpvaW50ID8gMSA6IDApIDw8IDUpICsgKChub0dhcE1vcmUgPyAxIDogMCkgPDwgNilcbiAgICAgICAgICAgICsgKChub0dhcFByZXZpb3VzID8gMSA6IDApIDw8IDcpO1xuXG4gICAgICAgIGlmIChxdWFsaXR5IDwgMClcbiAgICAgICAgICAgIHF1YWxpdHkgPSAwO1xuXG4gICAgICAgIC8vIHN0ZXJlbyBtb2RlIGZpZWxkIChJbnRlbnNpdHkgc3RlcmVvIGlzIG5vdCBpbXBsZW1lbnRlZClcbiAgICAgICAgc3dpdGNoIChnZnAubW9kZSkge1xuICAgICAgICAgICAgY2FzZSBNT05POlxuICAgICAgICAgICAgICAgIHN0ZXJlb01vZGUgPSAwO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBTVEVSRU86XG4gICAgICAgICAgICAgICAgc3RlcmVvTW9kZSA9IDE7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIERVQUxfQ0hBTk5FTDpcbiAgICAgICAgICAgICAgICBzdGVyZW9Nb2RlID0gMjtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgSk9JTlRfU1RFUkVPOlxuICAgICAgICAgICAgICAgIGlmIChnZnAuZm9yY2VfbXMpXG4gICAgICAgICAgICAgICAgICAgIHN0ZXJlb01vZGUgPSA0O1xuICAgICAgICAgICAgICAgIGVsc2VcbiAgICAgICAgICAgICAgICAgICAgc3RlcmVvTW9kZSA9IDM7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIE5PVF9TRVQ6XG4gICAgICAgICAgICAvLyRGQUxMLVRIUk9VR0gkXG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIHN0ZXJlb01vZGUgPSA3O1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGdmcC5pbl9zYW1wbGVyYXRlIDw9IDMyMDAwKVxuICAgICAgICAgICAgc291cmNlRnJlcSA9IDB4MDA7XG4gICAgICAgIGVsc2UgaWYgKGdmcC5pbl9zYW1wbGVyYXRlID09IDQ4MDAwKVxuICAgICAgICAgICAgc291cmNlRnJlcSA9IDB4MDI7XG4gICAgICAgIGVsc2UgaWYgKGdmcC5pbl9zYW1wbGVyYXRlID4gNDgwMDApXG4gICAgICAgICAgICBzb3VyY2VGcmVxID0gMHgwMztcbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAvLyBkZWZhdWx0IGlzIDQ0MTAwSHpcbiAgICAgICAgICAgIHNvdXJjZUZyZXEgPSAweDAxO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIHVzZXIgb3ZlcnJpZGVkIHRoZSBkZWZhdWx0IExBTUUgYmVoYXZpb3Igd2l0aCBzb21lXG4gICAgICAgIC8vIG5hc3R5IG9wdGlvbnNcbiAgICAgICAgaWYgKGdmcC5zaG9ydF9ibG9ja3MgPT0gU2hvcnRCbG9jay5zaG9ydF9ibG9ja19mb3JjZWRcbiAgICAgICAgICAgIHx8IGdmcC5zaG9ydF9ibG9ja3MgPT0gU2hvcnRCbG9jay5zaG9ydF9ibG9ja19kaXNwZW5zZWRcbiAgICAgICAgICAgIHx8ICgoZ2ZwLmxvd3Bhc3NmcmVxID09IC0xKSAmJiAoZ2ZwLmhpZ2hwYXNzZnJlcSA9PSAtMSkpIHx8IC8qIFwiLWtcIiAqL1xuICAgICAgICAgICAgKGdmcC5zY2FsZV9sZWZ0IDwgZ2ZwLnNjYWxlX3JpZ2h0KVxuICAgICAgICAgICAgfHwgKGdmcC5zY2FsZV9sZWZ0ID4gZ2ZwLnNjYWxlX3JpZ2h0KVxuICAgICAgICAgICAgfHwgKGdmcC5kaXNhYmxlX3Jlc2Vydm9pciAmJiBnZnAuYnJhdGUgPCAzMjApIHx8IGdmcC5ub0FUSFxuICAgICAgICAgICAgfHwgZ2ZwLkFUSG9ubHkgfHwgKGF0aFR5cGUgPT0gMCkgfHwgZ2ZwLmluX3NhbXBsZXJhdGUgPD0gMzIwMDApXG4gICAgICAgICAgICBub25PcHRpbWFsID0gMTtcblxuICAgICAgICBtaXNjID0gbm9pc2VTaGFwaW5nICsgKHN0ZXJlb01vZGUgPDwgMikgKyAobm9uT3B0aW1hbCA8PCA1KVxuICAgICAgICAgICAgKyAoc291cmNlRnJlcSA8PCA2KTtcblxuICAgICAgICBtdXNpY0NSQyA9IGdmYy5uTXVzaWNDUkM7XG5cbiAgICAgICAgLy8gV3JpdGUgYWxsIHRoaXMgaW5mb3JtYXRpb24gaW50byB0aGUgc3RyZWFtXG5cbiAgICAgICAgY3JlYXRlSW50ZWdlcihzdHJlYW1CdWZmZXIsIHN0cmVhbUJ1ZmZlclBvcyArIGJ5dGVzV3JpdHRlbiwgcXVhbGl0eSk7XG4gICAgICAgIGJ5dGVzV3JpdHRlbiArPSA0O1xuXG4gICAgICAgIGZvciAodmFyIGogPSAwOyBqIDwgOTsgaisrKSB7XG4gICAgICAgICAgICBzdHJlYW1CdWZmZXJbc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuICsgal0gPSAweGZmICYgdmVyc2lvbiAuY2hhckF0KGopO1xuICAgICAgICB9XG4gICAgICAgIGJ5dGVzV3JpdHRlbiArPSA5O1xuXG4gICAgICAgIHN0cmVhbUJ1ZmZlcltzdHJlYW1CdWZmZXJQb3MgKyBieXRlc1dyaXR0ZW5dID0gMHhmZiAmIHJldk1ldGhvZDtcbiAgICAgICAgYnl0ZXNXcml0dGVuKys7XG5cbiAgICAgICAgc3RyZWFtQnVmZmVyW3N0cmVhbUJ1ZmZlclBvcyArIGJ5dGVzV3JpdHRlbl0gPSAweGZmICYgbG93cGFzcztcbiAgICAgICAgYnl0ZXNXcml0dGVuKys7XG5cbiAgICAgICAgY3JlYXRlSW50ZWdlcihzdHJlYW1CdWZmZXIsIHN0cmVhbUJ1ZmZlclBvcyArIGJ5dGVzV3JpdHRlbixcbiAgICAgICAgICAgIHBlYWtTaWduYWxBbXBsaXR1ZGUpO1xuICAgICAgICBieXRlc1dyaXR0ZW4gKz0gNDtcblxuICAgICAgICBjcmVhdGVTaG9ydChzdHJlYW1CdWZmZXIsIHN0cmVhbUJ1ZmZlclBvcyArIGJ5dGVzV3JpdHRlbixcbiAgICAgICAgICAgIHJhZGlvUmVwbGF5R2Fpbik7XG4gICAgICAgIGJ5dGVzV3JpdHRlbiArPSAyO1xuXG4gICAgICAgIGNyZWF0ZVNob3J0KHN0cmVhbUJ1ZmZlciwgc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuLFxuICAgICAgICAgICAgYXVkaW9waGlsZVJlcGxheUdhaW4pO1xuICAgICAgICBieXRlc1dyaXR0ZW4gKz0gMjtcblxuICAgICAgICBzdHJlYW1CdWZmZXJbc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuXSA9IDB4ZmYgJiBmbGFncztcbiAgICAgICAgYnl0ZXNXcml0dGVuKys7XG5cbiAgICAgICAgaWYgKGFickJpdHJhdGUgPj0gMjU1KVxuICAgICAgICAgICAgc3RyZWFtQnVmZmVyW3N0cmVhbUJ1ZmZlclBvcyArIGJ5dGVzV3JpdHRlbl0gPSAweEZGO1xuICAgICAgICBlbHNlXG4gICAgICAgICAgICBzdHJlYW1CdWZmZXJbc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuXSA9IDB4ZmYgJiBhYnJCaXRyYXRlO1xuICAgICAgICBieXRlc1dyaXR0ZW4rKztcblxuICAgICAgICBzdHJlYW1CdWZmZXJbc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuXSA9IDB4ZmYgJiAoZW5jRGVsYXkgPj4gNCk7XG4gICAgICAgIHN0cmVhbUJ1ZmZlcltzdHJlYW1CdWZmZXJQb3MgKyBieXRlc1dyaXR0ZW4gKyAxXSA9IDB4ZmYgJiAoKGVuY0RlbGF5IDw8IDQpICsgKGVuY1BhZGRpbmcgPj4gOCkpO1xuICAgICAgICBzdHJlYW1CdWZmZXJbc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuICsgMl0gPSAweGZmICYgZW5jUGFkZGluZztcblxuICAgICAgICBieXRlc1dyaXR0ZW4gKz0gMztcblxuICAgICAgICBzdHJlYW1CdWZmZXJbc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuXSA9IDB4ZmYgJiBtaXNjO1xuICAgICAgICBieXRlc1dyaXR0ZW4rKztcblxuICAgICAgICAvLyB1bnVzZWQgaW4gcmV2MFxuICAgICAgICBzdHJlYW1CdWZmZXJbc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuKytdID0gMDtcblxuICAgICAgICBjcmVhdGVTaG9ydChzdHJlYW1CdWZmZXIsIHN0cmVhbUJ1ZmZlclBvcyArIGJ5dGVzV3JpdHRlbiwgZ2ZwLnByZXNldCk7XG4gICAgICAgIGJ5dGVzV3JpdHRlbiArPSAyO1xuXG4gICAgICAgIGNyZWF0ZUludGVnZXIoc3RyZWFtQnVmZmVyLCBzdHJlYW1CdWZmZXJQb3MgKyBieXRlc1dyaXR0ZW4sIG11c2ljTGVuZ3RoKTtcbiAgICAgICAgYnl0ZXNXcml0dGVuICs9IDQ7XG5cbiAgICAgICAgY3JlYXRlU2hvcnQoc3RyZWFtQnVmZmVyLCBzdHJlYW1CdWZmZXJQb3MgKyBieXRlc1dyaXR0ZW4sIG11c2ljQ1JDKTtcbiAgICAgICAgYnl0ZXNXcml0dGVuICs9IDI7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRhZyBDUkMuLi4uIG11c3QgYmUgZG9uZSBoZXJlLCBzaW5jZSBpdCBpbmNsdWRlcyBwcmV2aW91c1xuICAgICAgICAvLyBpbmZvcm1hdGlvblxuXG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgYnl0ZXNXcml0dGVuOyBpKyspXG4gICAgICAgICAgICBjcmMgPSBjcmNVcGRhdGVMb29rdXAoc3RyZWFtQnVmZmVyW3N0cmVhbUJ1ZmZlclBvcyArIGldLCBjcmMpO1xuXG4gICAgICAgIGNyZWF0ZVNob3J0KHN0cmVhbUJ1ZmZlciwgc3RyZWFtQnVmZmVyUG9zICsgYnl0ZXNXcml0dGVuLCBjcmMpO1xuICAgICAgICBieXRlc1dyaXR0ZW4gKz0gMjtcblxuICAgICAgICByZXR1cm4gYnl0ZXNXcml0dGVuO1xuICAgIH1cblxuICAgIGZ1bmN0aW9uIHNraXBJZDN2MihmcFN0cmVhbSkge1xuICAgICAgICAvLyBzZWVrIHRvIHRoZSBiZWdpbm5pbmcgb2YgdGhlIHN0cmVhbVxuICAgICAgICBmcFN0cmVhbS5zZWVrKDApO1xuICAgICAgICAvLyByZWFkIDEwIGJ5dGVzIGluIGNhc2UgdGhlcmUncyBhbiBJRDMgdmVyc2lvbiAyIGhlYWRlciBoZXJlXG4gICAgICAgIHZhciBpZDN2MkhlYWRlciA9IG5ld19ieXRlKDEwKTtcbiAgICAgICAgZnBTdHJlYW0ucmVhZEZ1bGx5KGlkM3YySGVhZGVyKTtcbiAgICAgICAgLyogZG9lcyB0aGUgc3RyZWFtIGJlZ2luIHdpdGggdGhlIElEMyB2ZXJzaW9uIDIgZmlsZSBpZGVudGlmaWVyPyAqL1xuICAgICAgICB2YXIgaWQzdjJUYWdTaXplO1xuICAgICAgICBpZiAoIW5ldyBTdHJpbmcoaWQzdjJIZWFkZXIsIFwiSVNPLTg4NTktMVwiKS5zdGFydHNXaXRoKFwiSUQzXCIpKSB7XG4gICAgICAgICAgICAvKlxuICAgICAgICAgICAgICogdGhlIHRhZyBzaXplIChtaW51cyB0aGUgMTAtYnl0ZSBoZWFkZXIpIGlzIGVuY29kZWQgaW50byBmb3VyXG4gICAgICAgICAgICAgKiBieXRlcyB3aGVyZSB0aGUgbW9zdCBzaWduaWZpY2FudCBiaXQgaXMgY2xlYXIgaW4gZWFjaCBieXRlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGlkM3YyVGFnU2l6ZSA9ICgoKGlkM3YySGVhZGVyWzZdICYgMHg3ZikgPDwgMjEpXG4gICAgICAgICAgICAgICAgfCAoKGlkM3YySGVhZGVyWzddICYgMHg3ZikgPDwgMTQpXG4gICAgICAgICAgICAgICAgfCAoKGlkM3YySGVhZGVyWzhdICYgMHg3ZikgPDwgNykgfCAoaWQzdjJIZWFkZXJbOV0gJiAweDdmKSlcbiAgICAgICAgICAgICAgICArIGlkM3YySGVhZGVyLmxlbmd0aDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8qIG5vIElEMyB2ZXJzaW9uIDIgdGFnIGluIHRoaXMgc3RyZWFtICovXG4gICAgICAgICAgICBpZDN2MlRhZ1NpemUgPSAwO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpZDN2MlRhZ1NpemU7XG4gICAgfVxuXG4gICAgdGhpcy5nZXRMYW1lVGFnRnJhbWUgPSBmdW5jdGlvbiAoZ2ZwLCBidWZmZXIpIHtcbiAgICAgICAgdmFyIGdmYyA9IGdmcC5pbnRlcm5hbF9mbGFncztcblxuICAgICAgICBpZiAoIWdmcC5iV3JpdGVWYnJUYWcpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG4gICAgICAgIGlmIChnZmMuQ2xhc3NfSUQgIT0gTGFtZS5MQU1FX0lEKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoZ2ZjLlZCUl9zZWVrX3RhYmxlLnBvcyA8PSAwKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnVmZmVyLmxlbmd0aCA8IGdmYy5WQlJfc2Vla190YWJsZS5Ub3RhbEZyYW1lU2l6ZSkge1xuICAgICAgICAgICAgcmV0dXJuIGdmYy5WQlJfc2Vla190YWJsZS5Ub3RhbEZyYW1lU2l6ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIEFycmF5cy5maWxsKGJ1ZmZlciwgMCwgZ2ZjLlZCUl9zZWVrX3RhYmxlLlRvdGFsRnJhbWVTaXplLCAwKTtcblxuICAgICAgICAvLyA0IGJ5dGVzIGZyYW1lIGhlYWRlclxuICAgICAgICBzZXRMYW1lVGFnRnJhbWVIZWFkZXIoZ2ZwLCBidWZmZXIpO1xuXG4gICAgICAgIC8vIENyZWF0ZSBUT0MgZW50cmllc1xuICAgICAgICB2YXIgdG9jID0gbmV3X2J5dGUoTlVNVE9DRU5UUklFUyk7XG5cbiAgICAgICAgaWYgKGdmcC5mcmVlX2Zvcm1hdCkge1xuICAgICAgICAgICAgZm9yICh2YXIgaSA9IDE7IGkgPCBOVU1UT0NFTlRSSUVTOyArK2kpXG4gICAgICAgICAgICAgICAgdG9jW2ldID0gMHhmZiAmICgyNTUgKiBpIC8gMTAwKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHhpbmdTZWVrVGFibGUoZ2ZjLlZCUl9zZWVrX3RhYmxlLCB0b2MpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3RhcnQgd3JpdGluZyB0aGUgdGFnIGFmdGVyIHRoZSB6ZXJvIGZyYW1lXG4gICAgICAgIHZhciBzdHJlYW1JbmRleCA9IGdmYy5zaWRlaW5mb19sZW47XG4gICAgICAgIC8qKlxuICAgICAgICAgKiBOb3RlOiBYaW5nIGhlYWRlciBzcGVjaWZpZXMgdGhhdCBYaW5nIGRhdGEgZ29lcyBpbiB0aGUgYW5jaWxsYXJ5IGRhdGFcbiAgICAgICAgICogd2l0aCBOTyBFUlJPUiBQUk9URUNUSU9OLiBJZiBlcnJvciBwcm90ZWN0b24gaW4gZW5hYmxlZCwgdGhlIFhpbmdcbiAgICAgICAgICogZGF0YSBzdGlsbCBzdGFydHMgYXQgdGhlIHNhbWUgb2Zmc2V0LCBhbmQgbm93IGl0IGlzIGluIHNpZGVpbmZvIGRhdGFcbiAgICAgICAgICogYmxvY2ssIGFuZCB0aHVzIHdpbGwgbm90IGRlY29kZSBjb3JyZWN0bHkgYnkgbm9uLVhpbmcgdGFnIGF3YXJlXG4gICAgICAgICAqIHBsYXllcnNcbiAgICAgICAgICovXG4gICAgICAgIGlmIChnZnAuZXJyb3JfcHJvdGVjdGlvbilcbiAgICAgICAgICAgIHN0cmVhbUluZGV4IC09IDI7XG5cbiAgICAgICAgLy8gUHV0IFZiciB0YWdcbiAgICAgICAgaWYgKGdmcC5WQlIgPT0gVmJyTW9kZS52YnJfb2ZmKSB7XG4gICAgICAgICAgICBidWZmZXJbc3RyZWFtSW5kZXgrK10gPSAweGZmICYgVkJSVGFnMS5jaGFyQXQoMCk7XG4gICAgICAgICAgICBidWZmZXJbc3RyZWFtSW5kZXgrK10gPSAweGZmICYgVkJSVGFnMS5jaGFyQXQoMSk7XG4gICAgICAgICAgICBidWZmZXJbc3RyZWFtSW5kZXgrK10gPSAweGZmICYgVkJSVGFnMS5jaGFyQXQoMik7XG4gICAgICAgICAgICBidWZmZXJbc3RyZWFtSW5kZXgrK10gPSAweGZmICYgVkJSVGFnMS5jaGFyQXQoMyk7XG5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGJ1ZmZlcltzdHJlYW1JbmRleCsrXSA9IDB4ZmYgJiBWQlJUYWcwLmNoYXJBdCgwKTtcbiAgICAgICAgICAgIGJ1ZmZlcltzdHJlYW1JbmRleCsrXSA9IDB4ZmYgJiBWQlJUYWcwLmNoYXJBdCgxKTtcbiAgICAgICAgICAgIGJ1ZmZlcltzdHJlYW1JbmRleCsrXSA9IDB4ZmYgJiBWQlJUYWcwLmNoYXJBdCgyKTtcbiAgICAgICAgICAgIGJ1ZmZlcltzdHJlYW1JbmRleCsrXSA9IDB4ZmYgJiBWQlJUYWcwLmNoYXJBdCgzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFB1dCBoZWFkZXIgZmxhZ3NcbiAgICAgICAgY3JlYXRlSW50ZWdlcihidWZmZXIsIHN0cmVhbUluZGV4LCBGUkFNRVNfRkxBRyArIEJZVEVTX0ZMQUcgKyBUT0NfRkxBR1xuICAgICAgICAgICAgKyBWQlJfU0NBTEVfRkxBRyk7XG4gICAgICAgIHN0cmVhbUluZGV4ICs9IDQ7XG5cbiAgICAgICAgLy8gUHV0IFRvdGFsIE51bWJlciBvZiBmcmFtZXNcbiAgICAgICAgY3JlYXRlSW50ZWdlcihidWZmZXIsIHN0cmVhbUluZGV4LCBnZmMuVkJSX3NlZWtfdGFibGUublZick51bUZyYW1lcyk7XG4gICAgICAgIHN0cmVhbUluZGV4ICs9IDQ7XG5cbiAgICAgICAgLy8gUHV0IHRvdGFsIGF1ZGlvIHN0cmVhbSBzaXplLCBpbmNsdWRpbmcgWGluZy9MQU1FIEhlYWRlclxuICAgICAgICB2YXIgc3RyZWFtU2l6ZSA9IChnZmMuVkJSX3NlZWtfdGFibGUubkJ5dGVzV3JpdHRlbiArIGdmYy5WQlJfc2Vla190YWJsZS5Ub3RhbEZyYW1lU2l6ZSk7XG4gICAgICAgIGNyZWF0ZUludGVnZXIoYnVmZmVyLCBzdHJlYW1JbmRleCwgMCB8IHN0cmVhbVNpemUpO1xuICAgICAgICBzdHJlYW1JbmRleCArPSA0O1xuXG4gICAgICAgIC8qIFB1dCBUT0MgKi9cbiAgICAgICAgU3lzdGVtLmFycmF5Y29weSh0b2MsIDAsIGJ1ZmZlciwgc3RyZWFtSW5kZXgsIHRvYy5sZW5ndGgpO1xuICAgICAgICBzdHJlYW1JbmRleCArPSB0b2MubGVuZ3RoO1xuXG4gICAgICAgIGlmIChnZnAuZXJyb3JfcHJvdGVjdGlvbikge1xuICAgICAgICAgICAgLy8gKGpvKSBlcnJvcl9wcm90ZWN0aW9uOiBhZGQgY3JjMTYgaW5mb3JtYXRpb24gdG8gaGVhZGVyXG4gICAgICAgICAgICBicy5DUkNfd3JpdGVoZWFkZXIoZ2ZjLCBidWZmZXIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gd29yayBvdXQgQ1JDIHNvIGZhcjogaW5pdGlhbGx5IGNyYyA9IDBcbiAgICAgICAgdmFyIGNyYyA9IDB4MDA7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgc3RyZWFtSW5kZXg7IGkrKylcbiAgICAgICAgICAgIGNyYyA9IGNyY1VwZGF0ZUxvb2t1cChidWZmZXJbaV0sIGNyYyk7XG4gICAgICAgIC8vIFB1dCBMQU1FIFZCUiBpbmZvXG4gICAgICAgIHN0cmVhbUluZGV4ICs9IHB1dExhbWVWQlIoZ2ZwLCBzdHJlYW1TaXplLCBidWZmZXIsIHN0cmVhbUluZGV4LCBjcmMpO1xuXG4gICAgICAgIHJldHVybiBnZmMuVkJSX3NlZWtfdGFibGUuVG90YWxGcmFtZVNpemU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV3JpdGUgZmluYWwgVkJSIHRhZyB0byB0aGUgZmlsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBnZnBcbiAgICAgKiAgICAgICAgICAgIGdsb2JhbCBmbGFnc1xuICAgICAqIEBwYXJhbSBzdHJlYW1cbiAgICAgKiAgICAgICAgICAgIHN0cmVhbSB0byBhZGQgdGhlIFZCUiB0YWcgdG9cbiAgICAgKiBAcmV0dXJuIDAgKE9LKSwgLTEgZWxzZVxuICAgICAqIEB0aHJvd3MgSU9FeGNlcHRpb25cbiAgICAgKiAgICAgICAgICAgICBJL08gZXJyb3JcbiAgICAgKi9cbiAgICB0aGlzLnB1dFZiclRhZyA9IGZ1bmN0aW9uIChnZnAsIHN0cmVhbSkge1xuICAgICAgICB2YXIgZ2ZjID0gZ2ZwLmludGVybmFsX2ZsYWdzO1xuXG4gICAgICAgIGlmIChnZmMuVkJSX3NlZWtfdGFibGUucG9zIDw9IDApXG4gICAgICAgICAgICByZXR1cm4gLTE7XG5cbiAgICAgICAgLy8gU2VlayB0byBlbmQgb2YgZmlsZVxuICAgICAgICBzdHJlYW0uc2VlayhzdHJlYW0ubGVuZ3RoKCkpO1xuXG4gICAgICAgIC8vIEdldCBmaWxlIHNpemUsIGFib3J0IGlmIGZpbGUgaGFzIHplcm8gbGVuZ3RoLlxuICAgICAgICBpZiAoc3RyZWFtLmxlbmd0aCgpID09IDApXG4gICAgICAgICAgICByZXR1cm4gLTE7XG5cbiAgICAgICAgLy8gVGhlIFZCUiB0YWcgbWF5IE5PVCBiZSBsb2NhdGVkIGF0IHRoZSBiZWdpbm5pbmcgb2YgdGhlIHN0cmVhbS4gSWYgYW5cbiAgICAgICAgLy8gSUQzIHZlcnNpb24gMiB0YWcgd2FzIGFkZGVkLCB0aGVuIGl0IG11c3QgYmUgc2tpcHBlZCB0byB3cml0ZSB0aGUgVkJSXG4gICAgICAgIC8vIHRhZyBkYXRhLlxuICAgICAgICB2YXIgaWQzdjJUYWdTaXplID0gc2tpcElkM3YyKHN0cmVhbSk7XG5cbiAgICAgICAgLy8gU2VlayB0byB0aGUgYmVnaW5uaW5nIG9mIHRoZSBzdHJlYW1cbiAgICAgICAgc3RyZWFtLnNlZWsoaWQzdjJUYWdTaXplKTtcblxuICAgICAgICB2YXIgYnVmZmVyID0gbmV3X2J5dGUoTUFYRlJBTUVTSVpFKTtcbiAgICAgICAgdmFyIGJ5dGVzID0gZ2V0TGFtZVRhZ0ZyYW1lKGdmcCwgYnVmZmVyKTtcbiAgICAgICAgaWYgKGJ5dGVzID4gYnVmZmVyLmxlbmd0aCkge1xuICAgICAgICAgICAgcmV0dXJuIC0xO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJ5dGVzIDwgMSkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQdXQgaXQgYWxsIHRvIGRpc2sgYWdhaW5cbiAgICAgICAgc3RyZWFtLndyaXRlKGJ1ZmZlciwgMCwgYnl0ZXMpO1xuICAgICAgICAvLyBzdWNjZXNzXG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cblxufVxuXG5tb2R1bGUuZXhwb3J0cyA9IFZCUlRhZztcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL19sYW1lanNAMS4yLjFAbGFtZWpzL3NyYy9qcy9WQlJUYWcuanNcbi8vIG1vZHVsZSBpZCA9IDNPR1Jcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///3OGR\n')},"3a40":function(module,exports){eval("/*\n * Released under BSD License\n * Copyright (c) 2014-2021 hizzgdev@163.com\n * \n * Project Home:\n * https://github.com/hizzgdev/jsmind/\n */\n\n(function ($w) {\n 'use strict';\n\n var __name__ = 'jsMind';\n var jsMind = $w[__name__];\n if (!jsMind) { return; }\n if (typeof jsMind.screenshot != 'undefined') { return; }\n\n var $d = $w.document;\n var $c = function (tag) { return $d.createElement(tag); };\n\n var css = function (cstyle, property_name) {\n return cstyle.getPropertyValue(property_name);\n };\n var is_visible = function (cstyle) {\n var visibility = css(cstyle, 'visibility');\n var display = css(cstyle, 'display');\n return (visibility !== 'hidden' && display !== 'none');\n };\n var jcanvas = {};\n jcanvas.rect = function (ctx, x, y, w, h, r) {\n if (w < 2 * r) r = w / 2;\n if (h < 2 * r) r = h / 2;\n ctx.moveTo(x + r, y);\n ctx.arcTo(x + w, y, x + w, y + h, r);\n ctx.arcTo(x + w, y + h, x, y + h, r);\n ctx.arcTo(x, y + h, x, y, r);\n ctx.arcTo(x, y, x + w, y, r);\n };\n\n jcanvas.text_multiline = function (ctx, text, x, y, w, h, lineheight) {\n var line = '';\n var text_len = text.length;\n var chars = text.split('');\n var test_line = null;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n for (var i = 0; i < text_len; i++) {\n test_line = line + chars[i];\n if (ctx.measureText(test_line).width > w && i > 0) {\n ctx.fillText(line, x, y);\n line = chars[i];\n y += lineheight;\n } else {\n line = test_line;\n }\n }\n ctx.fillText(line, x, y);\n };\n\n jcanvas.text_ellipsis = function (ctx, text, x, y, w, h) {\n var center_y = y + h / 2;\n var text = jcanvas.fittingString(ctx, text, w);\n ctx.textAlign = 'left';\n ctx.textBaseline = 'middle';\n ctx.fillText(text, x, center_y, w);\n };\n\n jcanvas.fittingString = function (ctx, text, max_width) {\n var width = ctx.measureText(text).width;\n var ellipsis = '…';\n var ellipsis_width = ctx.measureText(ellipsis).width;\n if (width <= max_width || width <= ellipsis_width) {\n return text;\n } else {\n var len = text.length;\n while (width >= max_width - ellipsis_width && len-- > 0) {\n text = text.substring(0, len);\n width = ctx.measureText(text).width;\n }\n return text + ellipsis;\n }\n };\n\n jcanvas.image = function (ctx, url, x, y, w, h, r, rotation, callback) {\n var img = new Image();\n img.onload = function () {\n ctx.save();\n ctx.translate(x, y);\n ctx.save();\n ctx.beginPath();\n jcanvas.rect(ctx, 0, 0, w, h, r);\n ctx.closePath();\n ctx.clip();\n ctx.translate(w / 2, h / 2);\n ctx.rotate(rotation * Math.PI / 180);\n ctx.drawImage(img, -w / 2, -h / 2);\n ctx.restore();\n ctx.restore();\n !!callback && callback();\n }\n img.src = url;\n };\n\n jsMind.screenshot = function (jm) {\n this.jm = jm;\n this.canvas_elem = null;\n this.canvas_ctx = null;\n this._inited = false;\n };\n\n jsMind.screenshot.prototype = {\n init: function () {\n if (this._inited) { return; }\n console.log('init');\n var c = $c('canvas');\n var ctx = c.getContext('2d');\n\n this.canvas_elem = c;\n this.canvas_ctx = ctx;\n this.jm.view.e_panel.appendChild(c);\n this._inited = true;\n this.resize();\n },\n\n shoot: function (callback) {\n this.init();\n this._draw(function () {\n !!callback && callback();\n this.clean();\n }.bind(this));\n this._watermark();\n },\n\n shootDownload: function () {\n this.shoot(function () {\n this._download();\n }.bind(this));\n },\n\n shootAsDataURL: function (callback) {\n this.shoot(function () {\n !!callback && callback(this.canvas_elem.toDataURL());\n }.bind(this));\n },\n\n resize: function () {\n if (this._inited) {\n this.canvas_elem.width = this.jm.view.size.w;\n this.canvas_elem.height = this.jm.view.size.h;\n }\n },\n\n clean: function () {\n var c = this.canvas_elem;\n this.canvas_ctx.clearRect(0, 0, c.width, c.height);\n },\n\n _draw: function (callback) {\n var ctx = this.canvas_ctx;\n ctx.textAlign = 'left';\n ctx.textBaseline = 'top';\n this._draw_lines(function () {\n this._draw_nodes(callback);\n }.bind(this));\n },\n\n _watermark: function () {\n var c = this.canvas_elem;\n var ctx = this.canvas_ctx;\n ctx.textAlign = 'right';\n ctx.textBaseline = 'bottom';\n ctx.fillStyle = '#000';\n ctx.font = '11px Verdana,Arial,Helvetica,sans-serif';\n ctx.fillText('hizzgdev.github.io/jsmind', c.width - 5.5, c.height - 2.5);\n ctx.textAlign = 'left';\n ctx.fillText($w.location, 5.5, c.height - 2.5);\n },\n\n _draw_lines: function (callback) {\n this.jm.view.graph.copy_to(this.canvas_ctx, callback);\n },\n\n _draw_nodes: function (callback) {\n var nodes = this.jm.mind.nodes;\n var node;\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n this._draw_node(node);\n }\n\n function check_nodes_ready() {\n console.log('check_node_ready' + new Date());\n var allOk = true;\n for (var nodeid in nodes) {\n node = nodes[nodeid];\n allOk = allOk & node.ready;\n }\n\n if (!allOk) {\n $w.setTimeout(check_nodes_ready, 200);\n } else {\n $w.setTimeout(callback, 200);\n }\n }\n check_nodes_ready();\n },\n\n _draw_node: function (node) {\n var ctx = this.canvas_ctx;\n var view_data = node._data.view;\n var node_element = view_data.element;\n var ncs = getComputedStyle(node_element);\n if (!is_visible(ncs)) {\n node.ready = true;\n return;\n }\n\n var bgcolor = css(ncs, 'background-color');\n var round_radius = parseInt(css(ncs, 'border-top-left-radius'));\n var color = css(ncs, 'color');\n var padding_left = parseInt(css(ncs, 'padding-left'));\n var padding_right = parseInt(css(ncs, 'padding-right'));\n var padding_top = parseInt(css(ncs, 'padding-top'));\n var padding_bottom = parseInt(css(ncs, 'padding-bottom'));\n var text_overflow = css(ncs, 'text-overflow');\n var font = css(ncs, 'font-style') + ' ' +\n css(ncs, 'font-variant') + ' ' +\n css(ncs, 'font-weight') + ' ' +\n css(ncs, 'font-size') + '/' + css(ncs, 'line-height') + ' ' +\n css(ncs, 'font-family');\n\n var rb = {\n x: view_data.abs_x,\n y: view_data.abs_y,\n w: view_data.width + 1,\n h: view_data.height + 1\n };\n var tb = {\n x: rb.x + padding_left,\n y: rb.y + padding_top,\n w: rb.w - padding_left - padding_right,\n h: rb.h - padding_top - padding_bottom\n };\n\n ctx.font = font;\n ctx.fillStyle = bgcolor;\n ctx.beginPath();\n jcanvas.rect(ctx, rb.x, rb.y, rb.w, rb.h, round_radius);\n ctx.closePath();\n ctx.fill();\n\n ctx.fillStyle = color;\n if ('background-image' in node.data) {\n var backgroundUrl = css(ncs, 'background-image').slice(5, -2);\n node.ready = false;\n var rotation = 0;\n if ('background-rotation' in node.data) {\n rotation = node.data['background-rotation'];\n }\n jcanvas.image(ctx, backgroundUrl, rb.x, rb.y, rb.w, rb.h, round_radius, rotation,\n function () {\n node.ready = true;\n });\n }\n if (!!node.topic) {\n if (text_overflow === 'ellipsis') {\n jcanvas.text_ellipsis(ctx, node.topic, tb.x, tb.y, tb.w, tb.h);\n } else {\n var line_height = parseInt(css(ncs, 'line-height'));\n jcanvas.text_multiline(ctx, node.topic, tb.x, tb.y, tb.w, tb.h, line_height);\n }\n }\n if (!!view_data.expander) {\n this._draw_expander(view_data.expander);\n }\n if (!('background-image' in node.data)) {\n node.ready = true;\n }\n },\n\n _draw_expander: function (expander) {\n var ctx = this.canvas_ctx;\n var ncs = getComputedStyle(expander);\n if (!is_visible(ncs)) { return; }\n\n var style_left = css(ncs, 'left');\n var style_top = css(ncs, 'top');\n var font = css(ncs, 'font');\n var left = parseInt(style_left);\n var top = parseInt(style_top);\n var is_plus = expander.innerHTML === '+';\n\n ctx.lineWidth = 1;\n\n ctx.beginPath();\n ctx.arc(left + 7, top + 7, 5, 0, Math.PI * 2, true);\n ctx.moveTo(left + 10, top + 7);\n ctx.lineTo(left + 4, top + 7);\n if (is_plus) {\n ctx.moveTo(left + 7, top + 4);\n ctx.lineTo(left + 7, top + 10);\n }\n ctx.closePath();\n ctx.stroke();\n },\n\n _download: function () {\n var c = this.canvas_elem;\n var name = this.jm.mind.name + '.png';\n\n if (navigator.msSaveBlob && (!!c.msToBlob)) {\n var blob = c.msToBlob();\n navigator.msSaveBlob(blob, name);\n } else {\n var bloburl = this.canvas_elem.toDataURL();\n var anchor = $c('a');\n if ('download' in anchor) {\n anchor.style.visibility = 'hidden';\n anchor.href = bloburl;\n anchor.download = name;\n $d.body.appendChild(anchor);\n var evt = $d.createEvent('MouseEvents');\n evt.initEvent('click', true, true);\n anchor.dispatchEvent(evt);\n $d.body.removeChild(anchor);\n } else {\n location.href = bloburl;\n }\n }\n },\n\n jm_event_handle: function (type, data) {\n if (type === jsMind.event_type.resize) {\n this.resize();\n }\n }\n };\n\n var screenshot_plugin = new jsMind.plugin('screenshot', function (jm) {\n var jss = new jsMind.screenshot(jm);\n jm.screenshot = jss;\n jm.shoot = function () {\n jss.shoot();\n };\n jm.add_event_listener(function (type, data) {\n jss.jm_event_handle.call(jss, type, data);\n });\n });\n\n jsMind.register_plugin(screenshot_plugin);\n\n})(window);\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiM2E0MC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9qc21pbmQvanMvanNtaW5kLnNjcmVlbnNob3QuanM/ZGRhZSJdLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogUmVsZWFzZWQgdW5kZXIgQlNEIExpY2Vuc2VcbiAqIENvcHlyaWdodCAoYykgMjAxNC0yMDIxIGhpenpnZGV2QDE2My5jb21cbiAqIFxuICogUHJvamVjdCBIb21lOlxuICogICBodHRwczovL2dpdGh1Yi5jb20vaGl6emdkZXYvanNtaW5kL1xuICovXG5cbihmdW5jdGlvbiAoJHcpIHtcbiAgICAndXNlIHN0cmljdCc7XG5cbiAgICB2YXIgX19uYW1lX18gPSAnanNNaW5kJztcbiAgICB2YXIganNNaW5kID0gJHdbX19uYW1lX19dO1xuICAgIGlmICghanNNaW5kKSB7IHJldHVybjsgfVxuICAgIGlmICh0eXBlb2YganNNaW5kLnNjcmVlbnNob3QgIT0gJ3VuZGVmaW5lZCcpIHsgcmV0dXJuOyB9XG5cbiAgICB2YXIgJGQgPSAkdy5kb2N1bWVudDtcbiAgICB2YXIgJGMgPSBmdW5jdGlvbiAodGFnKSB7IHJldHVybiAkZC5jcmVhdGVFbGVtZW50KHRhZyk7IH07XG5cbiAgICB2YXIgY3NzID0gZnVuY3Rpb24gKGNzdHlsZSwgcHJvcGVydHlfbmFtZSkge1xuICAgICAgICByZXR1cm4gY3N0eWxlLmdldFByb3BlcnR5VmFsdWUocHJvcGVydHlfbmFtZSk7XG4gICAgfTtcbiAgICB2YXIgaXNfdmlzaWJsZSA9IGZ1bmN0aW9uIChjc3R5bGUpIHtcbiAgICAgICAgdmFyIHZpc2liaWxpdHkgPSBjc3MoY3N0eWxlLCAndmlzaWJpbGl0eScpO1xuICAgICAgICB2YXIgZGlzcGxheSA9IGNzcyhjc3R5bGUsICdkaXNwbGF5Jyk7XG4gICAgICAgIHJldHVybiAodmlzaWJpbGl0eSAhPT0gJ2hpZGRlbicgJiYgZGlzcGxheSAhPT0gJ25vbmUnKTtcbiAgICB9O1xuICAgIHZhciBqY2FudmFzID0ge307XG4gICAgamNhbnZhcy5yZWN0ID0gZnVuY3Rpb24gKGN0eCwgeCwgeSwgdywgaCwgcikge1xuICAgICAgICBpZiAodyA8IDIgKiByKSByID0gdyAvIDI7XG4gICAgICAgIGlmIChoIDwgMiAqIHIpIHIgPSBoIC8gMjtcbiAgICAgICAgY3R4Lm1vdmVUbyh4ICsgciwgeSk7XG4gICAgICAgIGN0eC5hcmNUbyh4ICsgdywgeSwgeCArIHcsIHkgKyBoLCByKTtcbiAgICAgICAgY3R4LmFyY1RvKHggKyB3LCB5ICsgaCwgeCwgeSArIGgsIHIpO1xuICAgICAgICBjdHguYXJjVG8oeCwgeSArIGgsIHgsIHksIHIpO1xuICAgICAgICBjdHguYXJjVG8oeCwgeSwgeCArIHcsIHksIHIpO1xuICAgIH07XG5cbiAgICBqY2FudmFzLnRleHRfbXVsdGlsaW5lID0gZnVuY3Rpb24gKGN0eCwgdGV4dCwgeCwgeSwgdywgaCwgbGluZWhlaWdodCkge1xuICAgICAgICB2YXIgbGluZSA9ICcnO1xuICAgICAgICB2YXIgdGV4dF9sZW4gPSB0ZXh0Lmxlbmd0aDtcbiAgICAgICAgdmFyIGNoYXJzID0gdGV4dC5zcGxpdCgnJyk7XG4gICAgICAgIHZhciB0ZXN0X2xpbmUgPSBudWxsO1xuICAgICAgICBjdHgudGV4dEFsaWduID0gJ2xlZnQnO1xuICAgICAgICBjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCc7XG4gICAgICAgIGZvciAodmFyIGkgPSAwOyBpIDwgdGV4dF9sZW47IGkrKykge1xuICAgICAgICAgICAgdGVzdF9saW5lID0gbGluZSArIGNoYXJzW2ldO1xuICAgICAgICAgICAgaWYgKGN0eC5tZWFzdXJlVGV4dCh0ZXN0X2xpbmUpLndpZHRoID4gdyAmJiBpID4gMCkge1xuICAgICAgICAgICAgICAgIGN0eC5maWxsVGV4dChsaW5lLCB4LCB5KTtcbiAgICAgICAgICAgICAgICBsaW5lID0gY2hhcnNbaV07XG4gICAgICAgICAgICAgICAgeSArPSBsaW5laGVpZ2h0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBsaW5lID0gdGVzdF9saW5lO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGN0eC5maWxsVGV4dChsaW5lLCB4LCB5KTtcbiAgICB9O1xuXG4gICAgamNhbnZhcy50ZXh0X2VsbGlwc2lzID0gZnVuY3Rpb24gKGN0eCwgdGV4dCwgeCwgeSwgdywgaCkge1xuICAgICAgICB2YXIgY2VudGVyX3kgPSB5ICsgaCAvIDI7XG4gICAgICAgIHZhciB0ZXh0ID0gamNhbnZhcy5maXR0aW5nU3RyaW5nKGN0eCwgdGV4dCwgdyk7XG4gICAgICAgIGN0eC50ZXh0QWxpZ24gPSAnbGVmdCc7XG4gICAgICAgIGN0eC50ZXh0QmFzZWxpbmUgPSAnbWlkZGxlJztcbiAgICAgICAgY3R4LmZpbGxUZXh0KHRleHQsIHgsIGNlbnRlcl95LCB3KTtcbiAgICB9O1xuXG4gICAgamNhbnZhcy5maXR0aW5nU3RyaW5nID0gZnVuY3Rpb24gKGN0eCwgdGV4dCwgbWF4X3dpZHRoKSB7XG4gICAgICAgIHZhciB3aWR0aCA9IGN0eC5tZWFzdXJlVGV4dCh0ZXh0KS53aWR0aDtcbiAgICAgICAgdmFyIGVsbGlwc2lzID0gJ+KApic7XG4gICAgICAgIHZhciBlbGxpcHNpc193aWR0aCA9IGN0eC5tZWFzdXJlVGV4dChlbGxpcHNpcykud2lkdGg7XG4gICAgICAgIGlmICh3aWR0aCA8PSBtYXhfd2lkdGggfHwgd2lkdGggPD0gZWxsaXBzaXNfd2lkdGgpIHtcbiAgICAgICAgICAgIHJldHVybiB0ZXh0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFyIGxlbiA9IHRleHQubGVuZ3RoO1xuICAgICAgICAgICAgd2hpbGUgKHdpZHRoID49IG1heF93aWR0aCAtIGVsbGlwc2lzX3dpZHRoICYmIGxlbi0tID4gMCkge1xuICAgICAgICAgICAgICAgIHRleHQgPSB0ZXh0LnN1YnN0cmluZygwLCBsZW4pO1xuICAgICAgICAgICAgICAgIHdpZHRoID0gY3R4Lm1lYXN1cmVUZXh0KHRleHQpLndpZHRoO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHRleHQgKyBlbGxpcHNpcztcbiAgICAgICAgfVxuICAgIH07XG5cbiAgICBqY2FudmFzLmltYWdlID0gZnVuY3Rpb24gKGN0eCwgdXJsLCB4LCB5LCB3LCBoLCByLCByb3RhdGlvbiwgY2FsbGJhY2spIHtcbiAgICAgICAgdmFyIGltZyA9IG5ldyBJbWFnZSgpO1xuICAgICAgICBpbWcub25sb2FkID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgY3R4LnNhdmUoKTtcbiAgICAgICAgICAgIGN0eC50cmFuc2xhdGUoeCwgeSk7XG4gICAgICAgICAgICBjdHguc2F2ZSgpO1xuICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgamNhbnZhcy5yZWN0KGN0eCwgMCwgMCwgdywgaCwgcik7XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgICAgICBjdHguY2xpcCgpO1xuICAgICAgICAgICAgY3R4LnRyYW5zbGF0ZSh3IC8gMiwgaCAvIDIpO1xuICAgICAgICAgICAgY3R4LnJvdGF0ZShyb3RhdGlvbiAqIE1hdGguUEkgLyAxODApO1xuICAgICAgICAgICAgY3R4LmRyYXdJbWFnZShpbWcsIC13IC8gMiwgLWggLyAyKTtcbiAgICAgICAgICAgIGN0eC5yZXN0b3JlKCk7XG4gICAgICAgICAgICBjdHgucmVzdG9yZSgpO1xuICAgICAgICAgICAgISFjYWxsYmFjayAmJiBjYWxsYmFjaygpO1xuICAgICAgICB9XG4gICAgICAgIGltZy5zcmMgPSB1cmw7XG4gICAgfTtcblxuICAgIGpzTWluZC5zY3JlZW5zaG90ID0gZnVuY3Rpb24gKGptKSB7XG4gICAgICAgIHRoaXMuam0gPSBqbTtcbiAgICAgICAgdGhpcy5jYW52YXNfZWxlbSA9IG51bGw7XG4gICAgICAgIHRoaXMuY2FudmFzX2N0eCA9IG51bGw7XG4gICAgICAgIHRoaXMuX2luaXRlZCA9IGZhbHNlO1xuICAgIH07XG5cbiAgICBqc01pbmQuc2NyZWVuc2hvdC5wcm90b3R5cGUgPSB7XG4gICAgICAgIGluaXQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9pbml0ZWQpIHsgcmV0dXJuOyB9XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnaW5pdCcpO1xuICAgICAgICAgICAgdmFyIGMgPSAkYygnY2FudmFzJyk7XG4gICAgICAgICAgICB2YXIgY3R4ID0gYy5nZXRDb250ZXh0KCcyZCcpO1xuXG4gICAgICAgICAgICB0aGlzLmNhbnZhc19lbGVtID0gYztcbiAgICAgICAgICAgIHRoaXMuY2FudmFzX2N0eCA9IGN0eDtcbiAgICAgICAgICAgIHRoaXMuam0udmlldy5lX3BhbmVsLmFwcGVuZENoaWxkKGMpO1xuICAgICAgICAgICAgdGhpcy5faW5pdGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMucmVzaXplKCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgc2hvb3Q6IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICAgICAgdGhpcy5pbml0KCk7XG4gICAgICAgICAgICB0aGlzLl9kcmF3KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAhIWNhbGxiYWNrICYmIGNhbGxiYWNrKCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jbGVhbigpO1xuICAgICAgICAgICAgfS5iaW5kKHRoaXMpKTtcbiAgICAgICAgICAgIHRoaXMuX3dhdGVybWFyaygpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHNob290RG93bmxvYWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHRoaXMuc2hvb3QoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2Rvd25sb2FkKCk7XG4gICAgICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHNob290QXNEYXRhVVJMOiBmdW5jdGlvbiAoY2FsbGJhY2spIHtcbiAgICAgICAgICAgIHRoaXMuc2hvb3QoZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgICEhY2FsbGJhY2sgJiYgY2FsbGJhY2sodGhpcy5jYW52YXNfZWxlbS50b0RhdGFVUkwoKSk7XG4gICAgICAgICAgICB9LmJpbmQodGhpcykpO1xuICAgICAgICB9LFxuXG4gICAgICAgIHJlc2l6ZTogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuX2luaXRlZCkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzX2VsZW0ud2lkdGggPSB0aGlzLmptLnZpZXcuc2l6ZS53O1xuICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzX2VsZW0uaGVpZ2h0ID0gdGhpcy5qbS52aWV3LnNpemUuaDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBjbGVhbjogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGMgPSB0aGlzLmNhbnZhc19lbGVtO1xuICAgICAgICAgICAgdGhpcy5jYW52YXNfY3R4LmNsZWFyUmVjdCgwLCAwLCBjLndpZHRoLCBjLmhlaWdodCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgX2RyYXc6IGZ1bmN0aW9uIChjYWxsYmFjaykge1xuICAgICAgICAgICAgdmFyIGN0eCA9IHRoaXMuY2FudmFzX2N0eDtcbiAgICAgICAgICAgIGN0eC50ZXh0QWxpZ24gPSAnbGVmdCc7XG4gICAgICAgICAgICBjdHgudGV4dEJhc2VsaW5lID0gJ3RvcCc7XG4gICAgICAgICAgICB0aGlzLl9kcmF3X2xpbmVzKGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9kcmF3X25vZGVzKGNhbGxiYWNrKTtcbiAgICAgICAgICAgIH0uYmluZCh0aGlzKSk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgX3dhdGVybWFyazogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgdmFyIGMgPSB0aGlzLmNhbnZhc19lbGVtO1xuICAgICAgICAgICAgdmFyIGN0eCA9IHRoaXMuY2FudmFzX2N0eDtcbiAgICAgICAgICAgIGN0eC50ZXh0QWxpZ24gPSAncmlnaHQnO1xuICAgICAgICAgICAgY3R4LnRleHRCYXNlbGluZSA9ICdib3R0b20nO1xuICAgICAgICAgICAgY3R4LmZpbGxTdHlsZSA9ICcjMDAwJztcbiAgICAgICAgICAgIGN0eC5mb250ID0gJzExcHggVmVyZGFuYSxBcmlhbCxIZWx2ZXRpY2Esc2Fucy1zZXJpZic7XG4gICAgICAgICAgICBjdHguZmlsbFRleHQoJ2hpenpnZGV2LmdpdGh1Yi5pby9qc21pbmQnLCBjLndpZHRoIC0gNS41LCBjLmhlaWdodCAtIDIuNSk7XG4gICAgICAgICAgICBjdHgudGV4dEFsaWduID0gJ2xlZnQnO1xuICAgICAgICAgICAgY3R4LmZpbGxUZXh0KCR3LmxvY2F0aW9uLCA1LjUsIGMuaGVpZ2h0IC0gMi41KTtcbiAgICAgICAgfSxcblxuICAgICAgICBfZHJhd19saW5lczogZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB0aGlzLmptLnZpZXcuZ3JhcGguY29weV90byh0aGlzLmNhbnZhc19jdHgsIGNhbGxiYWNrKTtcbiAgICAgICAgfSxcblxuICAgICAgICBfZHJhd19ub2RlczogZnVuY3Rpb24gKGNhbGxiYWNrKSB7XG4gICAgICAgICAgICB2YXIgbm9kZXMgPSB0aGlzLmptLm1pbmQubm9kZXM7XG4gICAgICAgICAgICB2YXIgbm9kZTtcbiAgICAgICAgICAgIGZvciAodmFyIG5vZGVpZCBpbiBub2Rlcykge1xuICAgICAgICAgICAgICAgIG5vZGUgPSBub2Rlc1tub2RlaWRdO1xuICAgICAgICAgICAgICAgIHRoaXMuX2RyYXdfbm9kZShub2RlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZnVuY3Rpb24gY2hlY2tfbm9kZXNfcmVhZHkoKSB7XG4gICAgICAgICAgICAgICAgY29uc29sZS5sb2coJ2NoZWNrX25vZGVfcmVhZHknICsgbmV3IERhdGUoKSk7XG4gICAgICAgICAgICAgICAgdmFyIGFsbE9rID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBmb3IgKHZhciBub2RlaWQgaW4gbm9kZXMpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9kZSA9IG5vZGVzW25vZGVpZF07XG4gICAgICAgICAgICAgICAgICAgIGFsbE9rID0gYWxsT2sgJiBub2RlLnJlYWR5O1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghYWxsT2spIHtcbiAgICAgICAgICAgICAgICAgICAgJHcuc2V0VGltZW91dChjaGVja19ub2Rlc19yZWFkeSwgMjAwKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAkdy5zZXRUaW1lb3V0KGNhbGxiYWNrLCAyMDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNoZWNrX25vZGVzX3JlYWR5KCk7XG4gICAgICAgIH0sXG5cbiAgICAgICAgX2RyYXdfbm9kZTogZnVuY3Rpb24gKG5vZGUpIHtcbiAgICAgICAgICAgIHZhciBjdHggPSB0aGlzLmNhbnZhc19jdHg7XG4gICAgICAgICAgICB2YXIgdmlld19kYXRhID0gbm9kZS5fZGF0YS52aWV3O1xuICAgICAgICAgICAgdmFyIG5vZGVfZWxlbWVudCA9IHZpZXdfZGF0YS5lbGVtZW50O1xuICAgICAgICAgICAgdmFyIG5jcyA9IGdldENvbXB1dGVkU3R5bGUobm9kZV9lbGVtZW50KTtcbiAgICAgICAgICAgIGlmICghaXNfdmlzaWJsZShuY3MpKSB7XG4gICAgICAgICAgICAgICAgbm9kZS5yZWFkeSA9IHRydWU7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB2YXIgYmdjb2xvciA9IGNzcyhuY3MsICdiYWNrZ3JvdW5kLWNvbG9yJyk7XG4gICAgICAgICAgICB2YXIgcm91bmRfcmFkaXVzID0gcGFyc2VJbnQoY3NzKG5jcywgJ2JvcmRlci10b3AtbGVmdC1yYWRpdXMnKSk7XG4gICAgICAgICAgICB2YXIgY29sb3IgPSBjc3MobmNzLCAnY29sb3InKTtcbiAgICAgICAgICAgIHZhciBwYWRkaW5nX2xlZnQgPSBwYXJzZUludChjc3MobmNzLCAncGFkZGluZy1sZWZ0JykpO1xuICAgICAgICAgICAgdmFyIHBhZGRpbmdfcmlnaHQgPSBwYXJzZUludChjc3MobmNzLCAncGFkZGluZy1yaWdodCcpKTtcbiAgICAgICAgICAgIHZhciBwYWRkaW5nX3RvcCA9IHBhcnNlSW50KGNzcyhuY3MsICdwYWRkaW5nLXRvcCcpKTtcbiAgICAgICAgICAgIHZhciBwYWRkaW5nX2JvdHRvbSA9IHBhcnNlSW50KGNzcyhuY3MsICdwYWRkaW5nLWJvdHRvbScpKTtcbiAgICAgICAgICAgIHZhciB0ZXh0X292ZXJmbG93ID0gY3NzKG5jcywgJ3RleHQtb3ZlcmZsb3cnKTtcbiAgICAgICAgICAgIHZhciBmb250ID0gY3NzKG5jcywgJ2ZvbnQtc3R5bGUnKSArICcgJyArXG4gICAgICAgICAgICAgICAgY3NzKG5jcywgJ2ZvbnQtdmFyaWFudCcpICsgJyAnICtcbiAgICAgICAgICAgICAgICBjc3MobmNzLCAnZm9udC13ZWlnaHQnKSArICcgJyArXG4gICAgICAgICAgICAgICAgY3NzKG5jcywgJ2ZvbnQtc2l6ZScpICsgJy8nICsgY3NzKG5jcywgJ2xpbmUtaGVpZ2h0JykgKyAnICcgK1xuICAgICAgICAgICAgICAgIGNzcyhuY3MsICdmb250LWZhbWlseScpO1xuXG4gICAgICAgICAgICB2YXIgcmIgPSB7XG4gICAgICAgICAgICAgICAgeDogdmlld19kYXRhLmFic194LFxuICAgICAgICAgICAgICAgIHk6IHZpZXdfZGF0YS5hYnNfeSxcbiAgICAgICAgICAgICAgICB3OiB2aWV3X2RhdGEud2lkdGggKyAxLFxuICAgICAgICAgICAgICAgIGg6IHZpZXdfZGF0YS5oZWlnaHQgKyAxXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgdmFyIHRiID0ge1xuICAgICAgICAgICAgICAgIHg6IHJiLnggKyBwYWRkaW5nX2xlZnQsXG4gICAgICAgICAgICAgICAgeTogcmIueSArIHBhZGRpbmdfdG9wLFxuICAgICAgICAgICAgICAgIHc6IHJiLncgLSBwYWRkaW5nX2xlZnQgLSBwYWRkaW5nX3JpZ2h0LFxuICAgICAgICAgICAgICAgIGg6IHJiLmggLSBwYWRkaW5nX3RvcCAtIHBhZGRpbmdfYm90dG9tXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICBjdHguZm9udCA9IGZvbnQ7XG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gYmdjb2xvcjtcbiAgICAgICAgICAgIGN0eC5iZWdpblBhdGgoKTtcbiAgICAgICAgICAgIGpjYW52YXMucmVjdChjdHgsIHJiLngsIHJiLnksIHJiLncsIHJiLmgsIHJvdW5kX3JhZGl1cyk7XG4gICAgICAgICAgICBjdHguY2xvc2VQYXRoKCk7XG4gICAgICAgICAgICBjdHguZmlsbCgpO1xuXG4gICAgICAgICAgICBjdHguZmlsbFN0eWxlID0gY29sb3I7XG4gICAgICAgICAgICBpZiAoJ2JhY2tncm91bmQtaW1hZ2UnIGluIG5vZGUuZGF0YSkge1xuICAgICAgICAgICAgICAgIHZhciBiYWNrZ3JvdW5kVXJsID0gY3NzKG5jcywgJ2JhY2tncm91bmQtaW1hZ2UnKS5zbGljZSg1LCAtMik7XG4gICAgICAgICAgICAgICAgbm9kZS5yZWFkeSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIHZhciByb3RhdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgaWYgKCdiYWNrZ3JvdW5kLXJvdGF0aW9uJyBpbiBub2RlLmRhdGEpIHtcbiAgICAgICAgICAgICAgICAgICAgcm90YXRpb24gPSBub2RlLmRhdGFbJ2JhY2tncm91bmQtcm90YXRpb24nXTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgamNhbnZhcy5pbWFnZShjdHgsIGJhY2tncm91bmRVcmwsIHJiLngsIHJiLnksIHJiLncsIHJiLmgsIHJvdW5kX3JhZGl1cywgcm90YXRpb24sXG4gICAgICAgICAgICAgICAgICAgIGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG5vZGUucmVhZHkgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghIW5vZGUudG9waWMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGV4dF9vdmVyZmxvdyA9PT0gJ2VsbGlwc2lzJykge1xuICAgICAgICAgICAgICAgICAgICBqY2FudmFzLnRleHRfZWxsaXBzaXMoY3R4LCBub2RlLnRvcGljLCB0Yi54LCB0Yi55LCB0Yi53LCB0Yi5oKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB2YXIgbGluZV9oZWlnaHQgPSBwYXJzZUludChjc3MobmNzLCAnbGluZS1oZWlnaHQnKSk7XG4gICAgICAgICAgICAgICAgICAgIGpjYW52YXMudGV4dF9tdWx0aWxpbmUoY3R4LCBub2RlLnRvcGljLCB0Yi54LCB0Yi55LCB0Yi53LCB0Yi5oLCBsaW5lX2hlaWdodCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEhdmlld19kYXRhLmV4cGFuZGVyKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fZHJhd19leHBhbmRlcih2aWV3X2RhdGEuZXhwYW5kZXIpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCEoJ2JhY2tncm91bmQtaW1hZ2UnIGluIG5vZGUuZGF0YSkpIHtcbiAgICAgICAgICAgICAgICBub2RlLnJlYWR5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBfZHJhd19leHBhbmRlcjogZnVuY3Rpb24gKGV4cGFuZGVyKSB7XG4gICAgICAgICAgICB2YXIgY3R4ID0gdGhpcy5jYW52YXNfY3R4O1xuICAgICAgICAgICAgdmFyIG5jcyA9IGdldENvbXB1dGVkU3R5bGUoZXhwYW5kZXIpO1xuICAgICAgICAgICAgaWYgKCFpc192aXNpYmxlKG5jcykpIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgICAgIHZhciBzdHlsZV9sZWZ0ID0gY3NzKG5jcywgJ2xlZnQnKTtcbiAgICAgICAgICAgIHZhciBzdHlsZV90b3AgPSBjc3MobmNzLCAndG9wJyk7XG4gICAgICAgICAgICB2YXIgZm9udCA9IGNzcyhuY3MsICdmb250Jyk7XG4gICAgICAgICAgICB2YXIgbGVmdCA9IHBhcnNlSW50KHN0eWxlX2xlZnQpO1xuICAgICAgICAgICAgdmFyIHRvcCA9IHBhcnNlSW50KHN0eWxlX3RvcCk7XG4gICAgICAgICAgICB2YXIgaXNfcGx1cyA9IGV4cGFuZGVyLmlubmVySFRNTCA9PT0gJysnO1xuXG4gICAgICAgICAgICBjdHgubGluZVdpZHRoID0gMTtcblxuICAgICAgICAgICAgY3R4LmJlZ2luUGF0aCgpO1xuICAgICAgICAgICAgY3R4LmFyYyhsZWZ0ICsgNywgdG9wICsgNywgNSwgMCwgTWF0aC5QSSAqIDIsIHRydWUpO1xuICAgICAgICAgICAgY3R4Lm1vdmVUbyhsZWZ0ICsgMTAsIHRvcCArIDcpO1xuICAgICAgICAgICAgY3R4LmxpbmVUbyhsZWZ0ICsgNCwgdG9wICsgNyk7XG4gICAgICAgICAgICBpZiAoaXNfcGx1cykge1xuICAgICAgICAgICAgICAgIGN0eC5tb3ZlVG8obGVmdCArIDcsIHRvcCArIDQpO1xuICAgICAgICAgICAgICAgIGN0eC5saW5lVG8obGVmdCArIDcsIHRvcCArIDEwKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGN0eC5jbG9zZVBhdGgoKTtcbiAgICAgICAgICAgIGN0eC5zdHJva2UoKTtcbiAgICAgICAgfSxcblxuICAgICAgICBfZG93bmxvYWQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgIHZhciBjID0gdGhpcy5jYW52YXNfZWxlbTtcbiAgICAgICAgICAgIHZhciBuYW1lID0gdGhpcy5qbS5taW5kLm5hbWUgKyAnLnBuZyc7XG5cbiAgICAgICAgICAgIGlmIChuYXZpZ2F0b3IubXNTYXZlQmxvYiAmJiAoISFjLm1zVG9CbG9iKSkge1xuICAgICAgICAgICAgICAgIHZhciBibG9iID0gYy5tc1RvQmxvYigpO1xuICAgICAgICAgICAgICAgIG5hdmlnYXRvci5tc1NhdmVCbG9iKGJsb2IsIG5hbWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YXIgYmxvYnVybCA9IHRoaXMuY2FudmFzX2VsZW0udG9EYXRhVVJMKCk7XG4gICAgICAgICAgICAgICAgdmFyIGFuY2hvciA9ICRjKCdhJyk7XG4gICAgICAgICAgICAgICAgaWYgKCdkb3dubG9hZCcgaW4gYW5jaG9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGFuY2hvci5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG4gICAgICAgICAgICAgICAgICAgIGFuY2hvci5ocmVmID0gYmxvYnVybDtcbiAgICAgICAgICAgICAgICAgICAgYW5jaG9yLmRvd25sb2FkID0gbmFtZTtcbiAgICAgICAgICAgICAgICAgICAgJGQuYm9keS5hcHBlbmRDaGlsZChhbmNob3IpO1xuICAgICAgICAgICAgICAgICAgICB2YXIgZXZ0ID0gJGQuY3JlYXRlRXZlbnQoJ01vdXNlRXZlbnRzJyk7XG4gICAgICAgICAgICAgICAgICAgIGV2dC5pbml0RXZlbnQoJ2NsaWNrJywgdHJ1ZSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIGFuY2hvci5kaXNwYXRjaEV2ZW50KGV2dCk7XG4gICAgICAgICAgICAgICAgICAgICRkLmJvZHkucmVtb3ZlQ2hpbGQoYW5jaG9yKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBsb2NhdGlvbi5ocmVmID0gYmxvYnVybDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG5cbiAgICAgICAgam1fZXZlbnRfaGFuZGxlOiBmdW5jdGlvbiAodHlwZSwgZGF0YSkge1xuICAgICAgICAgICAgaWYgKHR5cGUgPT09IGpzTWluZC5ldmVudF90eXBlLnJlc2l6ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgdmFyIHNjcmVlbnNob3RfcGx1Z2luID0gbmV3IGpzTWluZC5wbHVnaW4oJ3NjcmVlbnNob3QnLCBmdW5jdGlvbiAoam0pIHtcbiAgICAgICAgdmFyIGpzcyA9IG5ldyBqc01pbmQuc2NyZWVuc2hvdChqbSk7XG4gICAgICAgIGptLnNjcmVlbnNob3QgPSBqc3M7XG4gICAgICAgIGptLnNob290ID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAganNzLnNob290KCk7XG4gICAgICAgIH07XG4gICAgICAgIGptLmFkZF9ldmVudF9saXN0ZW5lcihmdW5jdGlvbiAodHlwZSwgZGF0YSkge1xuICAgICAgICAgICAganNzLmptX2V2ZW50X2hhbmRsZS5jYWxsKGpzcywgdHlwZSwgZGF0YSk7XG4gICAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAganNNaW5kLnJlZ2lzdGVyX3BsdWdpbihzY3JlZW5zaG90X3BsdWdpbik7XG5cbn0pKHdpbmRvdyk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9qc21pbmQvanMvanNtaW5kLnNjcmVlbnNob3QuanNcbi8vIG1vZHVsZSBpZCA9IDNhNDBcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///3a40\n")},"3b9h":function(module,exports,__webpack_require__){eval('//package mp3;\n\nvar III_psy_xmin = __webpack_require__("jp3Q");\n\nfunction III_psy_ratio() {\n\tthis.thm = new III_psy_xmin();\n\tthis.en = new III_psy_xmin();\n}\n\nmodule.exports = III_psy_ratio;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiM2I5aC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvSUlJX3BzeV9yYXRpby5qcz9kZGJmIl0sInNvdXJjZXNDb250ZW50IjpbIi8vcGFja2FnZSBtcDM7XG5cbnZhciBJSUlfcHN5X3htaW4gPSByZXF1aXJlKCcuL0lJSV9wc3lfeG1pbi5qcycpO1xuXG5mdW5jdGlvbiBJSUlfcHN5X3JhdGlvKCkge1xuXHR0aGlzLnRobSA9IG5ldyBJSUlfcHN5X3htaW4oKTtcblx0dGhpcy5lbiA9IG5ldyBJSUlfcHN5X3htaW4oKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBJSUlfcHN5X3JhdGlvO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvX2xhbWVqc0AxLjIuMUBsYW1lanMvc3JjL2pzL0lJSV9wc3lfcmF0aW8uanNcbi8vIG1vZHVsZSBpZCA9IDNiOWhcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///3b9h\n')},"3fo+":function(module,exports,__webpack_require__){eval('module.exports = __webpack_require__("YAhB");\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiM2ZvKy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9ub3JtYWxpemUtd2hlZWwvaW5kZXguanM/ZGRmYSJdLCJzb3VyY2VzQ29udGVudCI6WyJtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vc3JjL25vcm1hbGl6ZVdoZWVsLmpzJyk7XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9ub3JtYWxpemUtd2hlZWwvaW5kZXguanNcbi8vIG1vZHVsZSBpZCA9IDNmbytcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///3fo+\n')},"3fs2":function(module,exports,__webpack_require__){eval('var classof = __webpack_require__("RY/4");\nvar ITERATOR = __webpack_require__("dSzd")(\'iterator\');\nvar Iterators = __webpack_require__("/bQp");\nmodule.exports = __webpack_require__("FeBl").getIteratorMethod = function (it) {\n if (it != undefined) return it[ITERATOR]\n || it[\'@@iterator\']\n || Iterators[classof(it)];\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiM2ZzMi5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9jb3JlLmdldC1pdGVyYXRvci1tZXRob2QuanM/ZGRmYiJdLCJzb3VyY2VzQ29udGVudCI6WyJ2YXIgY2xhc3NvZiA9IHJlcXVpcmUoJy4vX2NsYXNzb2YnKTtcbnZhciBJVEVSQVRPUiA9IHJlcXVpcmUoJy4vX3drcycpKCdpdGVyYXRvcicpO1xudmFyIEl0ZXJhdG9ycyA9IHJlcXVpcmUoJy4vX2l0ZXJhdG9ycycpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL19jb3JlJykuZ2V0SXRlcmF0b3JNZXRob2QgPSBmdW5jdGlvbiAoaXQpIHtcbiAgaWYgKGl0ICE9IHVuZGVmaW5lZCkgcmV0dXJuIGl0W0lURVJBVE9SXVxuICAgIHx8IGl0WydAQGl0ZXJhdG9yJ11cbiAgICB8fCBJdGVyYXRvcnNbY2xhc3NvZihpdCldO1xufTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9tb2R1bGVzL2NvcmUuZ2V0LWl0ZXJhdG9yLW1ldGhvZC5qc1xuLy8gbW9kdWxlIGlkID0gM2ZzMlxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///3fs2\n')},"4W5c":function(module,exports,__webpack_require__){eval('var common = __webpack_require__("Dkd2");\nvar new_float = common.new_float;\nvar new_int = common.new_int;\nvar assert = common.assert;\n\nfunction CalcNoiseData() {\n this.global_gain = 0;\n this.sfb_count1 = 0;\n this.step = new_int(39);\n this.noise = new_float(39);\n this.noise_log = new_float(39);\n}\n\nmodule.exports = CalcNoiseData;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNFc1Yy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9fbGFtZWpzQDEuMi4xQGxhbWVqcy9zcmMvanMvQ2FsY05vaXNlRGF0YS5qcz9lMTZlIl0sInNvdXJjZXNDb250ZW50IjpbInZhciBjb21tb24gPSByZXF1aXJlKCcuL2NvbW1vbi5qcycpO1xudmFyIG5ld19mbG9hdCA9IGNvbW1vbi5uZXdfZmxvYXQ7XG52YXIgbmV3X2ludCA9IGNvbW1vbi5uZXdfaW50O1xudmFyIGFzc2VydCA9IGNvbW1vbi5hc3NlcnQ7XG5cbmZ1bmN0aW9uIENhbGNOb2lzZURhdGEoKSB7XG4gICAgdGhpcy5nbG9iYWxfZ2FpbiA9IDA7XG4gICAgdGhpcy5zZmJfY291bnQxID0gMDtcbiAgICB0aGlzLnN0ZXAgPSBuZXdfaW50KDM5KTtcbiAgICB0aGlzLm5vaXNlID0gbmV3X2Zsb2F0KDM5KTtcbiAgICB0aGlzLm5vaXNlX2xvZyA9IG5ld19mbG9hdCgzOSk7XG59XG5cbm1vZHVsZS5leHBvcnRzID0gQ2FsY05vaXNlRGF0YTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL19sYW1lanNAMS4yLjFAbGFtZWpzL3NyYy9qcy9DYWxjTm9pc2VEYXRhLmpzXG4vLyBtb2R1bGUgaWQgPSA0VzVjXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///4W5c\n')},"4WTo":function(module,exports,__webpack_require__){eval('var forOf = __webpack_require__("NWt+");\n\nmodule.exports = function (iter, ITERATOR) {\n var result = [];\n forOf(iter, false, result.push, result, ITERATOR);\n return result;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNFdUby5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYXJyYXktZnJvbS1pdGVyYWJsZS5qcz9lMTY0Il0sInNvdXJjZXNDb250ZW50IjpbInZhciBmb3JPZiA9IHJlcXVpcmUoJy4vX2Zvci1vZicpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdGVyLCBJVEVSQVRPUikge1xuICB2YXIgcmVzdWx0ID0gW107XG4gIGZvck9mKGl0ZXIsIGZhbHNlLCByZXN1bHQucHVzaCwgcmVzdWx0LCBJVEVSQVRPUik7XG4gIHJldHVybiByZXN1bHQ7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvY29yZS1qcy9saWJyYXJ5L21vZHVsZXMvX2FycmF5LWZyb20taXRlcmFibGUuanNcbi8vIG1vZHVsZSBpZCA9IDRXVG9cbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///4WTo\n')},"4mcu":function(module,exports){eval("module.exports = function () { /* empty */ };\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNG1jdS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYWRkLXRvLXVuc2NvcGFibGVzLmpzP2UyNjciXSwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSBmdW5jdGlvbiAoKSB7IC8qIGVtcHR5ICovIH07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fYWRkLXRvLXVuc2NvcGFibGVzLmpzXG4vLyBtb2R1bGUgaWQgPSA0bWN1XG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///4mcu\n")},"52gC":function(module,exports){eval('// 7.2.1 RequireObjectCoercible(argument)\nmodule.exports = function (it) {\n if (it == undefined) throw TypeError("Can\'t call method on " + it);\n return it;\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNTJnQy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZGVmaW5lZC5qcz9lNzY4Il0sInNvdXJjZXNDb250ZW50IjpbIi8vIDcuMi4xIFJlcXVpcmVPYmplY3RDb2VyY2libGUoYXJndW1lbnQpXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIChpdCkge1xuICBpZiAoaXQgPT0gdW5kZWZpbmVkKSB0aHJvdyBUeXBlRXJyb3IoXCJDYW4ndCBjYWxsIG1ldGhvZCBvbiAgXCIgKyBpdCk7XG4gIHJldHVybiBpdDtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9fZGVmaW5lZC5qc1xuLy8gbW9kdWxlIGlkID0gNTJnQ1xuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///52gC\n')},"5PlU":function(module,exports,__webpack_require__){eval('var classof = __webpack_require__("RY/4");\nvar ITERATOR = __webpack_require__("dSzd")(\'iterator\');\nvar Iterators = __webpack_require__("/bQp");\nmodule.exports = __webpack_require__("FeBl").isIterable = function (it) {\n var O = Object(it);\n return O[ITERATOR] !== undefined\n || \'@@iterator\' in O\n // eslint-disable-next-line no-prototype-builtins\n || Iterators.hasOwnProperty(classof(O));\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNVBsVS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9jb3JlLmlzLWl0ZXJhYmxlLmpzP2U0ZjkiXSwic291cmNlc0NvbnRlbnQiOlsidmFyIGNsYXNzb2YgPSByZXF1aXJlKCcuL19jbGFzc29mJyk7XG52YXIgSVRFUkFUT1IgPSByZXF1aXJlKCcuL193a3MnKSgnaXRlcmF0b3InKTtcbnZhciBJdGVyYXRvcnMgPSByZXF1aXJlKCcuL19pdGVyYXRvcnMnKTtcbm1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9fY29yZScpLmlzSXRlcmFibGUgPSBmdW5jdGlvbiAoaXQpIHtcbiAgdmFyIE8gPSBPYmplY3QoaXQpO1xuICByZXR1cm4gT1tJVEVSQVRPUl0gIT09IHVuZGVmaW5lZFxuICAgIHx8ICdAQGl0ZXJhdG9yJyBpbiBPXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIG5vLXByb3RvdHlwZS1idWlsdGluc1xuICAgIHx8IEl0ZXJhdG9ycy5oYXNPd25Qcm9wZXJ0eShjbGFzc29mKE8pKTtcbn07XG5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvbW9kdWxlcy9jb3JlLmlzLWl0ZXJhYmxlLmpzXG4vLyBtb2R1bGUgaWQgPSA1UGxVXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Iiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///5PlU\n')},"5QVw":function(module,exports,__webpack_require__){eval('module.exports = { "default": __webpack_require__("BwfY"), __esModule: true };//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNVFWdy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9iYWJlbC1ydW50aW1lL2NvcmUtanMvc3ltYm9sLmpzP2U1MDUiXSwic291cmNlc0NvbnRlbnQiOlsibW9kdWxlLmV4cG9ydHMgPSB7IFwiZGVmYXVsdFwiOiByZXF1aXJlKFwiY29yZS1qcy9saWJyYXJ5L2ZuL3N5bWJvbFwiKSwgX19lc01vZHVsZTogdHJ1ZSB9O1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2JhYmVsLXJ1bnRpbWUvY29yZS1qcy9zeW1ib2wuanNcbi8vIG1vZHVsZSBpZCA9IDVRVndcbi8vIG1vZHVsZSBjaHVua3MgPSAyIl0sIm1hcHBpbmdzIjoiQUFBQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///5QVw\n')},"5VQ+":function(module,exports,__webpack_require__){"use strict";eval('\n\nvar utils = __webpack_require__("cGG2");\n\nmodule.exports = function normalizeHeaderName(headers, normalizedName) {\n utils.forEach(headers, function processHeader(value, name) {\n if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) {\n headers[normalizedName] = value;\n delete headers[name];\n }\n });\n};\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNVZRKy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9heGlvcy9saWIvaGVscGVycy9ub3JtYWxpemVIZWFkZXJOYW1lLmpzP2U1NTQiXSwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnO1xuXG52YXIgdXRpbHMgPSByZXF1aXJlKCcuLi91dGlscycpO1xuXG5tb2R1bGUuZXhwb3J0cyA9IGZ1bmN0aW9uIG5vcm1hbGl6ZUhlYWRlck5hbWUoaGVhZGVycywgbm9ybWFsaXplZE5hbWUpIHtcbiAgdXRpbHMuZm9yRWFjaChoZWFkZXJzLCBmdW5jdGlvbiBwcm9jZXNzSGVhZGVyKHZhbHVlLCBuYW1lKSB7XG4gICAgaWYgKG5hbWUgIT09IG5vcm1hbGl6ZWROYW1lICYmIG5hbWUudG9VcHBlckNhc2UoKSA9PT0gbm9ybWFsaXplZE5hbWUudG9VcHBlckNhc2UoKSkge1xuICAgICAgaGVhZGVyc1tub3JtYWxpemVkTmFtZV0gPSB2YWx1ZTtcbiAgICAgIGRlbGV0ZSBoZWFkZXJzW25hbWVdO1xuICAgIH1cbiAgfSk7XG59O1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvYXhpb3MvbGliL2hlbHBlcnMvbm9ybWFsaXplSGVhZGVyTmFtZS5qc1xuLy8gbW9kdWxlIGlkID0gNVZRK1xuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTsiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///5VQ+\n')},"5zde":function(module,exports,__webpack_require__){eval('__webpack_require__("zQR9");\n__webpack_require__("qyJz");\nmodule.exports = __webpack_require__("FeBl").Array.from;\n//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNXpkZS5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9jb3JlLWpzL2xpYnJhcnkvZm4vYXJyYXkvZnJvbS5qcz9lNzM3Il0sInNvdXJjZXNDb250ZW50IjpbInJlcXVpcmUoJy4uLy4uL21vZHVsZXMvZXM2LnN0cmluZy5pdGVyYXRvcicpO1xucmVxdWlyZSgnLi4vLi4vbW9kdWxlcy9lczYuYXJyYXkuZnJvbScpO1xubW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuLi8uLi9tb2R1bGVzL19jb3JlJykuQXJyYXkuZnJvbTtcblxuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2NvcmUtanMvbGlicmFyeS9mbi9hcnJheS9mcm9tLmpzXG4vLyBtb2R1bGUgaWQgPSA1emRlXG4vLyBtb2R1bGUgY2h1bmtzID0gMiJdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBOyIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///5zde\n')},"6Twh":function(module,exports,__webpack_require__){"use strict";eval("\n\nexports.__esModule = true;\n\nexports.default = function () {\n if (_vue2.default.prototype.$isServer) return 0;\n if (scrollBarWidth !== undefined) return scrollBarWidth;\n\n var outer = document.createElement('div');\n outer.className = 'el-scrollbar__wrap';\n outer.style.visibility = 'hidden';\n outer.style.width = '100px';\n outer.style.position = 'absolute';\n outer.style.top = '-9999px';\n document.body.appendChild(outer);\n\n var widthNoScroll = outer.offsetWidth;\n outer.style.overflow = 'scroll';\n\n var inner = document.createElement('div');\n inner.style.width = '100%';\n outer.appendChild(inner);\n\n var widthWithScroll = inner.offsetWidth;\n outer.parentNode.removeChild(outer);\n scrollBarWidth = widthNoScroll - widthWithScroll;\n\n return scrollBarWidth;\n};\n\nvar _vue = __webpack_require__(\"7+uW\");\n\nvar _vue2 = _interopRequireDefault(_vue);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nvar scrollBarWidth = void 0;\n\n;//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNlR3aC5qcyIsInNvdXJjZXMiOlsid2VicGFjazovLy8uL25vZGVfbW9kdWxlcy9lbGVtZW50LXVpL2xpYi91dGlscy9zY3JvbGxiYXItd2lkdGguanM/ZTkzYyJdLCJzb3VyY2VzQ29udGVudCI6WyIndXNlIHN0cmljdCc7XG5cbmV4cG9ydHMuX19lc01vZHVsZSA9IHRydWU7XG5cbmV4cG9ydHMuZGVmYXVsdCA9IGZ1bmN0aW9uICgpIHtcbiAgaWYgKF92dWUyLmRlZmF1bHQucHJvdG90eXBlLiRpc1NlcnZlcikgcmV0dXJuIDA7XG4gIGlmIChzY3JvbGxCYXJXaWR0aCAhPT0gdW5kZWZpbmVkKSByZXR1cm4gc2Nyb2xsQmFyV2lkdGg7XG5cbiAgdmFyIG91dGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIG91dGVyLmNsYXNzTmFtZSA9ICdlbC1zY3JvbGxiYXJfX3dyYXAnO1xuICBvdXRlci5zdHlsZS52aXNpYmlsaXR5ID0gJ2hpZGRlbic7XG4gIG91dGVyLnN0eWxlLndpZHRoID0gJzEwMHB4JztcbiAgb3V0ZXIuc3R5bGUucG9zaXRpb24gPSAnYWJzb2x1dGUnO1xuICBvdXRlci5zdHlsZS50b3AgPSAnLTk5OTlweCc7XG4gIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQob3V0ZXIpO1xuXG4gIHZhciB3aWR0aE5vU2Nyb2xsID0gb3V0ZXIub2Zmc2V0V2lkdGg7XG4gIG91dGVyLnN0eWxlLm92ZXJmbG93ID0gJ3Njcm9sbCc7XG5cbiAgdmFyIGlubmVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jyk7XG4gIGlubmVyLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICBvdXRlci5hcHBlbmRDaGlsZChpbm5lcik7XG5cbiAgdmFyIHdpZHRoV2l0aFNjcm9sbCA9IGlubmVyLm9mZnNldFdpZHRoO1xuICBvdXRlci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKG91dGVyKTtcbiAgc2Nyb2xsQmFyV2lkdGggPSB3aWR0aE5vU2Nyb2xsIC0gd2lkdGhXaXRoU2Nyb2xsO1xuXG4gIHJldHVybiBzY3JvbGxCYXJXaWR0aDtcbn07XG5cbnZhciBfdnVlID0gcmVxdWlyZSgndnVlJyk7XG5cbnZhciBfdnVlMiA9IF9pbnRlcm9wUmVxdWlyZURlZmF1bHQoX3Z1ZSk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbnZhciBzY3JvbGxCYXJXaWR0aCA9IHZvaWQgMDtcblxuO1xuXG5cbi8vLy8vLy8vLy8vLy8vLy8vL1xuLy8gV0VCUEFDSyBGT09URVJcbi8vIC4vbm9kZV9tb2R1bGVzL2VsZW1lbnQtdWkvbGliL3V0aWxzL3Njcm9sbGJhci13aWR0aC5qc1xuLy8gbW9kdWxlIGlkID0gNlR3aFxuLy8gbW9kdWxlIGNodW5rcyA9IDIiXSwibWFwcGluZ3MiOiJBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///6Twh\n")},"7+uW":function(module,__webpack_exports__,__webpack_require__){"use strict";eval("Object.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* WEBPACK VAR INJECTION */(function(global) {/*!\n * Vue.js v2.6.12\n * (c) 2014-2020 Evan You\n * Released under the MIT License.\n */\n/* */\n\nvar emptyObject = Object.freeze({});\n\n// These helpers produce better VM code in JS engines due to their\n// explicitness and function inlining.\nfunction isUndef (v) {\n return v === undefined || v === null\n}\n\nfunction isDef (v) {\n return v !== undefined && v !== null\n}\n\nfunction isTrue (v) {\n return v === true\n}\n\nfunction isFalse (v) {\n return v === false\n}\n\n/**\n * Check if value is primitive.\n */\nfunction isPrimitive (value) {\n return (\n typeof value === 'string' ||\n typeof value === 'number' ||\n // $flow-disable-line\n typeof value === 'symbol' ||\n typeof value === 'boolean'\n )\n}\n\n/**\n * Quick object check - this is primarily used to tell\n * Objects from primitive values when we know the value\n * is a JSON-compliant type.\n */\nfunction isObject (obj) {\n return obj !== null && typeof obj === 'object'\n}\n\n/**\n * Get the raw type string of a value, e.g., [object Object].\n */\nvar _toString = Object.prototype.toString;\n\nfunction toRawType (value) {\n return _toString.call(value).slice(8, -1)\n}\n\n/**\n * Strict object type check. Only returns true\n * for plain JavaScript objects.\n */\nfunction isPlainObject (obj) {\n return _toString.call(obj) === '[object Object]'\n}\n\nfunction isRegExp (v) {\n return _toString.call(v) === '[object RegExp]'\n}\n\n/**\n * Check if val is a valid array index.\n */\nfunction isValidArrayIndex (val) {\n var n = parseFloat(String(val));\n return n >= 0 && Math.floor(n) === n && isFinite(val)\n}\n\nfunction isPromise (val) {\n return (\n isDef(val) &&\n typeof val.then === 'function' &&\n typeof val.catch === 'function'\n )\n}\n\n/**\n * Convert a value to a string that is actually rendered.\n */\nfunction toString (val) {\n return val == null\n ? ''\n : Array.isArray(val) || (isPlainObject(val) && val.toString === _toString)\n ? JSON.stringify(val, null, 2)\n : String(val)\n}\n\n/**\n * Convert an input value to a number for persistence.\n * If the conversion fails, return original string.\n */\nfunction toNumber (val) {\n var n = parseFloat(val);\n return isNaN(n) ? val : n\n}\n\n/**\n * Make a map and return a function for checking if a key\n * is in that map.\n */\nfunction makeMap (\n str,\n expectsLowerCase\n) {\n var map = Object.create(null);\n var list = str.split(',');\n for (var i = 0; i < list.length; i++) {\n map[list[i]] = true;\n }\n return expectsLowerCase\n ? function (val) { return map[val.toLowerCase()]; }\n : function (val) { return map[val]; }\n}\n\n/**\n * Check if a tag is a built-in tag.\n */\nvar isBuiltInTag = makeMap('slot,component', true);\n\n/**\n * Check if an attribute is a reserved attribute.\n */\nvar isReservedAttribute = makeMap('key,ref,slot,slot-scope,is');\n\n/**\n * Remove an item from an array.\n */\nfunction remove (arr, item) {\n if (arr.length) {\n var index = arr.indexOf(item);\n if (index > -1) {\n return arr.splice(index, 1)\n }\n }\n}\n\n/**\n * Check whether an object has the property.\n */\nvar hasOwnProperty = Object.prototype.hasOwnProperty;\nfunction hasOwn (obj, key) {\n return hasOwnProperty.call(obj, key)\n}\n\n/**\n * Create a cached version of a pure function.\n */\nfunction cached (fn) {\n var cache = Object.create(null);\n return (function cachedFn (str) {\n var hit = cache[str];\n return hit || (cache[str] = fn(str))\n })\n}\n\n/**\n * Camelize a hyphen-delimited string.\n */\nvar camelizeRE = /-(\\w)/g;\nvar camelize = cached(function (str) {\n return str.replace(camelizeRE, function (_, c) { return c ? c.toUpperCase() : ''; })\n});\n\n/**\n * Capitalize a string.\n */\nvar capitalize = cached(function (str) {\n return str.charAt(0).toUpperCase() + str.slice(1)\n});\n\n/**\n * Hyphenate a camelCase string.\n */\nvar hyphenateRE = /\\B([A-Z])/g;\nvar hyphenate = cached(function (str) {\n return str.replace(hyphenateRE, '-$1').toLowerCase()\n});\n\n/**\n * Simple bind polyfill for environments that do not support it,\n * e.g., PhantomJS 1.x. Technically, we don't need this anymore\n * since native bind is now performant enough in most browsers.\n * But removing it would mean breaking code that was able to run in\n * PhantomJS 1.x, so this must be kept for backward compatibility.\n */\n\n/* istanbul ignore next */\nfunction polyfillBind (fn, ctx) {\n function boundFn (a) {\n var l = arguments.length;\n return l\n ? l > 1\n ? fn.apply(ctx, arguments)\n : fn.call(ctx, a)\n : fn.call(ctx)\n }\n\n boundFn._length = fn.length;\n return boundFn\n}\n\nfunction nativeBind (fn, ctx) {\n return fn.bind(ctx)\n}\n\nvar bind = Function.prototype.bind\n ? nativeBind\n : polyfillBind;\n\n/**\n * Convert an Array-like object to a real Array.\n */\nfunction toArray (list, start) {\n start = start || 0;\n var i = list.length - start;\n var ret = new Array(i);\n while (i--) {\n ret[i] = list[i + start];\n }\n return ret\n}\n\n/**\n * Mix properties into target object.\n */\nfunction extend (to, _from) {\n for (var key in _from) {\n to[key] = _from[key];\n }\n return to\n}\n\n/**\n * Merge an Array of Objects into a single Object.\n */\nfunction toObject (arr) {\n var res = {};\n for (var i = 0; i < arr.length; i++) {\n if (arr[i]) {\n extend(res, arr[i]);\n }\n }\n return res\n}\n\n/* eslint-disable no-unused-vars */\n\n/**\n * Perform no operation.\n * Stubbing args to make Flow happy without leaving useless transpiled code\n * with ...rest (https://flow.org/blog/2017/05/07/Strict-Function-Call-Arity/).\n */\nfunction noop (a, b, c) {}\n\n/**\n * Always return false.\n */\nvar no = function (a, b, c) { return false; };\n\n/* eslint-enable no-unused-vars */\n\n/**\n * Return the same value.\n */\nvar identity = function (_) { return _; };\n\n/**\n * Generate a string containing static keys from compiler modules.\n */\nfunction genStaticKeys (modules) {\n return modules.reduce(function (keys, m) {\n return keys.concat(m.staticKeys || [])\n }, []).join(',')\n}\n\n/**\n * Check if two values are loosely equal - that is,\n * if they are plain objects, do they have the same shape?\n */\nfunction looseEqual (a, b) {\n if (a === b) { return true }\n var isObjectA = isObject(a);\n var isObjectB = isObject(b);\n if (isObjectA && isObjectB) {\n try {\n var isArrayA = Array.isArray(a);\n var isArrayB = Array.isArray(b);\n if (isArrayA && isArrayB) {\n return a.length === b.length && a.every(function (e, i) {\n return looseEqual(e, b[i])\n })\n } else if (a instanceof Date && b instanceof Date) {\n return a.getTime() === b.getTime()\n } else if (!isArrayA && !isArrayB) {\n var keysA = Object.keys(a);\n var keysB = Object.keys(b);\n return keysA.length === keysB.length && keysA.every(function (key) {\n return looseEqual(a[key], b[key])\n })\n } else {\n /* istanbul ignore next */\n return false\n }\n } catch (e) {\n /* istanbul ignore next */\n return false\n }\n } else if (!isObjectA && !isObjectB) {\n return String(a) === String(b)\n } else {\n return false\n }\n}\n\n/**\n * Return the first index at which a loosely equal value can be\n * found in the array (if value is a plain object, the array must\n * contain an object of the same shape), or -1 if it is not present.\n */\nfunction looseIndexOf (arr, val) {\n for (var i = 0; i < arr.length; i++) {\n if (looseEqual(arr[i], val)) { return i }\n }\n return -1\n}\n\n/**\n * Ensure a function is called only once.\n */\nfunction once (fn) {\n var called = false;\n return function () {\n if (!called) {\n called = true;\n fn.apply(this, arguments);\n }\n }\n}\n\nvar SSR_ATTR = 'data-server-rendered';\n\nvar ASSET_TYPES = [\n 'component',\n 'directive',\n 'filter'\n];\n\nvar LIFECYCLE_HOOKS = [\n 'beforeCreate',\n 'created',\n 'beforeMount',\n 'mounted',\n 'beforeUpdate',\n 'updated',\n 'beforeDestroy',\n 'destroyed',\n 'activated',\n 'deactivated',\n 'errorCaptured',\n 'serverPrefetch'\n];\n\n/* */\n\n\n\nvar config = ({\n /**\n * Option merge strategies (used in core/util/options)\n */\n // $flow-disable-line\n optionMergeStrategies: Object.create(null),\n\n /**\n * Whether to suppress warnings.\n */\n silent: false,\n\n /**\n * Show production mode tip message on boot?\n */\n productionTip: \"production\" !== 'production',\n\n /**\n * Whether to enable devtools\n */\n devtools: \"production\" !== 'production',\n\n /**\n * Whether to record perf\n */\n performance: false,\n\n /**\n * Error handler for watcher errors\n */\n errorHandler: null,\n\n /**\n * Warn handler for watcher warns\n */\n warnHandler: null,\n\n /**\n * Ignore certain custom elements\n */\n ignoredElements: [],\n\n /**\n * Custom user key aliases for v-on\n */\n // $flow-disable-line\n keyCodes: Object.create(null),\n\n /**\n * Check if a tag is reserved so that it cannot be registered as a\n * component. This is platform-dependent and may be overwritten.\n */\n isReservedTag: no,\n\n /**\n * Check if an attribute is reserved so that it cannot be used as a component\n * prop. This is platform-dependent and may be overwritten.\n */\n isReservedAttr: no,\n\n /**\n * Check if a tag is an unknown element.\n * Platform-dependent.\n */\n isUnknownElement: no,\n\n /**\n * Get the namespace of an element\n */\n getTagNamespace: noop,\n\n /**\n * Parse the real tag name for the specific platform.\n */\n parsePlatformTagName: identity,\n\n /**\n * Check if an attribute must be bound using property, e.g. value\n * Platform-dependent.\n */\n mustUseProp: no,\n\n /**\n * Perform updates asynchronously. Intended to be used by Vue Test Utils\n * This will significantly reduce performance if set to false.\n */\n async: true,\n\n /**\n * Exposed for legacy reasons\n */\n _lifecycleHooks: LIFECYCLE_HOOKS\n});\n\n/* */\n\n/**\n * unicode letters used for parsing html tags, component names and property paths.\n * using https://www.w3.org/TR/html53/semantics-scripting.html#potentialcustomelementname\n * skipping \\u10000-\\uEFFFF due to it freezing up PhantomJS\n */\nvar unicodeRegExp = /a-zA-Z\\u00B7\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u203F-\\u2040\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD/;\n\n/**\n * Check if a string starts with $ or _\n */\nfunction isReserved (str) {\n var c = (str + '').charCodeAt(0);\n return c === 0x24 || c === 0x5F\n}\n\n/**\n * Define a property.\n */\nfunction def (obj, key, val, enumerable) {\n Object.defineProperty(obj, key, {\n value: val,\n enumerable: !!enumerable,\n writable: true,\n configurable: true\n });\n}\n\n/**\n * Parse simple path.\n */\nvar bailRE = new RegExp((\"[^\" + (unicodeRegExp.source) + \".$_\\\\d]\"));\nfunction parsePath (path) {\n if (bailRE.test(path)) {\n return\n }\n var segments = path.split('.');\n return function (obj) {\n for (var i = 0; i < segments.length; i++) {\n if (!obj) { return }\n obj = obj[segments[i]];\n }\n return obj\n }\n}\n\n/* */\n\n// can we use __proto__?\nvar hasProto = '__proto__' in {};\n\n// Browser environment sniffing\nvar inBrowser = typeof window !== 'undefined';\nvar inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform;\nvar weexPlatform = inWeex && WXEnvironment.platform.toLowerCase();\nvar UA = inBrowser && window.navigator.userAgent.toLowerCase();\nvar isIE = UA && /msie|trident/.test(UA);\nvar isIE9 = UA && UA.indexOf('msie 9.0') > 0;\nvar isEdge = UA && UA.indexOf('edge/') > 0;\nvar isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android');\nvar isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios');\nvar isChrome = UA && /chrome\\/\\d+/.test(UA) && !isEdge;\nvar isPhantomJS = UA && /phantomjs/.test(UA);\nvar isFF = UA && UA.match(/firefox\\/(\\d+)/);\n\n// Firefox has a \"watch\" function on Object.prototype...\nvar nativeWatch = ({}).watch;\n\nvar supportsPassive = false;\nif (inBrowser) {\n try {\n var opts = {};\n Object.defineProperty(opts, 'passive', ({\n get: function get () {\n /* istanbul ignore next */\n supportsPassive = true;\n }\n })); // https://github.com/facebook/flow/issues/285\n window.addEventListener('test-passive', null, opts);\n } catch (e) {}\n}\n\n// this needs to be lazy-evaled because vue may be required before\n// vue-server-renderer can set VUE_ENV\nvar _isServer;\nvar isServerRendering = function () {\n if (_isServer === undefined) {\n /* istanbul ignore if */\n if (!inBrowser && !inWeex && typeof global !== 'undefined') {\n // detect presence of vue-server-renderer and avoid\n // Webpack shimming the process\n _isServer = global['process'] && global['process'].env.VUE_ENV === 'server';\n } else {\n _isServer = false;\n }\n }\n return _isServer\n};\n\n// detect devtools\nvar devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__;\n\n/* istanbul ignore next */\nfunction isNative (Ctor) {\n return typeof Ctor === 'function' && /native code/.test(Ctor.toString())\n}\n\nvar hasSymbol =\n typeof Symbol !== 'undefined' && isNative(Symbol) &&\n typeof Reflect !== 'undefined' && isNative(Reflect.ownKeys);\n\nvar _Set;\n/* istanbul ignore if */ // $flow-disable-line\nif (typeof Set !== 'undefined' && isNative(Set)) {\n // use native Set when available.\n _Set = Set;\n} else {\n // a non-standard Set polyfill that only works with primitive keys.\n _Set = /*@__PURE__*/(function () {\n function Set () {\n this.set = Object.create(null);\n }\n Set.prototype.has = function has (key) {\n return this.set[key] === true\n };\n Set.prototype.add = function add (key) {\n this.set[key] = true;\n };\n Set.prototype.clear = function clear () {\n this.set = Object.create(null);\n };\n\n return Set;\n }());\n}\n\n/* */\n\nvar warn = noop;\nvar tip = noop;\nvar generateComponentTrace = (noop); // work around flow check\nvar formatComponentName = (noop);\n\nif (false) {\n var hasConsole = typeof console !== 'undefined';\n var classifyRE = /(?:^|[-_])(\\w)/g;\n var classify = function (str) { return str\n .replace(classifyRE, function (c) { return c.toUpperCase(); })\n .replace(/[-_]/g, ''); };\n\n warn = function (msg, vm) {\n var trace = vm ? generateComponentTrace(vm) : '';\n\n if (config.warnHandler) {\n config.warnHandler.call(null, msg, vm, trace);\n } else if (hasConsole && (!config.silent)) {\n console.error((\"[Vue warn]: \" + msg + trace));\n }\n };\n\n tip = function (msg, vm) {\n if (hasConsole && (!config.silent)) {\n console.warn(\"[Vue tip]: \" + msg + (\n vm ? generateComponentTrace(vm) : ''\n ));\n }\n };\n\n formatComponentName = function (vm, includeFile) {\n if (vm.$root === vm) {\n return ''\n }\n var options = typeof vm === 'function' && vm.cid != null\n ? vm.options\n : vm._isVue\n ? vm.$options || vm.constructor.options\n : vm;\n var name = options.name || options._componentTag;\n var file = options.__file;\n if (!name && file) {\n var match = file.match(/([^/\\\\]+)\\.vue$/);\n name = match && match[1];\n }\n\n return (\n (name ? (\"<\" + (classify(name)) + \">\") : \"\") +\n (file && includeFile !== false ? (\" at \" + file) : '')\n )\n };\n\n var repeat = function (str, n) {\n var res = '';\n while (n) {\n if (n % 2 === 1) { res += str; }\n if (n > 1) { str += str; }\n n >>= 1;\n }\n return res\n };\n\n generateComponentTrace = function (vm) {\n if (vm._isVue && vm.$parent) {\n var tree = [];\n var currentRecursiveSequence = 0;\n while (vm) {\n if (tree.length > 0) {\n var last = tree[tree.length - 1];\n if (last.constructor === vm.constructor) {\n currentRecursiveSequence++;\n vm = vm.$parent;\n continue\n } else if (currentRecursiveSequence > 0) {\n tree[tree.length - 1] = [last, currentRecursiveSequence];\n currentRecursiveSequence = 0;\n }\n }\n tree.push(vm);\n vm = vm.$parent;\n }\n return '\\n\\nfound in\\n\\n' + tree\n .map(function (vm, i) { return (\"\" + (i === 0 ? '---\x3e ' : repeat(' ', 5 + i * 2)) + (Array.isArray(vm)\n ? ((formatComponentName(vm[0])) + \"... (\" + (vm[1]) + \" recursive calls)\")\n : formatComponentName(vm))); })\n .join('\\n')\n } else {\n return (\"\\n\\n(found in \" + (formatComponentName(vm)) + \")\")\n }\n };\n}\n\n/* */\n\nvar uid = 0;\n\n/**\n * A dep is an observable that can have multiple\n * directives subscribing to it.\n */\nvar Dep = function Dep () {\n this.id = uid++;\n this.subs = [];\n};\n\nDep.prototype.addSub = function addSub (sub) {\n this.subs.push(sub);\n};\n\nDep.prototype.removeSub = function removeSub (sub) {\n remove(this.subs, sub);\n};\n\nDep.prototype.depend = function depend () {\n if (Dep.target) {\n Dep.target.addDep(this);\n }\n};\n\nDep.prototype.notify = function notify () {\n // stabilize the subscriber list first\n var subs = this.subs.slice();\n if (false) {\n // subs aren't sorted in scheduler if not running async\n // we need to sort them now to make sure they fire in correct\n // order\n subs.sort(function (a, b) { return a.id - b.id; });\n }\n for (var i = 0, l = subs.length; i < l; i++) {\n subs[i].update();\n }\n};\n\n// The current target watcher being evaluated.\n// This is globally unique because only one watcher\n// can be evaluated at a time.\nDep.target = null;\nvar targetStack = [];\n\nfunction pushTarget (target) {\n targetStack.push(target);\n Dep.target = target;\n}\n\nfunction popTarget () {\n targetStack.pop();\n Dep.target = targetStack[targetStack.length - 1];\n}\n\n/* */\n\nvar VNode = function VNode (\n tag,\n data,\n children,\n text,\n elm,\n context,\n componentOptions,\n asyncFactory\n) {\n this.tag = tag;\n this.data = data;\n this.children = children;\n this.text = text;\n this.elm = elm;\n this.ns = undefined;\n this.context = context;\n this.fnContext = undefined;\n this.fnOptions = undefined;\n this.fnScopeId = undefined;\n this.key = data && data.key;\n this.componentOptions = componentOptions;\n this.componentInstance = undefined;\n this.parent = undefined;\n this.raw = false;\n this.isStatic = false;\n this.isRootInsert = true;\n this.isComment = false;\n this.isCloned = false;\n this.isOnce = false;\n this.asyncFactory = asyncFactory;\n this.asyncMeta = undefined;\n this.isAsyncPlaceholder = false;\n};\n\nvar prototypeAccessors = { child: { configurable: true } };\n\n// DEPRECATED: alias for componentInstance for backwards compat.\n/* istanbul ignore next */\nprototypeAccessors.child.get = function () {\n return this.componentInstance\n};\n\nObject.defineProperties( VNode.prototype, prototypeAccessors );\n\nvar createEmptyVNode = function (text) {\n if ( text === void 0 ) text = '';\n\n var node = new VNode();\n node.text = text;\n node.isComment = true;\n return node\n};\n\nfunction createTextVNode (val) {\n return new VNode(undefined, undefined, undefined, String(val))\n}\n\n// optimized shallow clone\n// used for static nodes and slot nodes because they may be reused across\n// multiple renders, cloning them avoids errors when DOM manipulations rely\n// on their elm reference.\nfunction cloneVNode (vnode) {\n var cloned = new VNode(\n vnode.tag,\n vnode.data,\n // #7975\n // clone children array to avoid mutating original in case of cloning\n // a child.\n vnode.children && vnode.children.slice(),\n vnode.text,\n vnode.elm,\n vnode.context,\n vnode.componentOptions,\n vnode.asyncFactory\n );\n cloned.ns = vnode.ns;\n cloned.isStatic = vnode.isStatic;\n cloned.key = vnode.key;\n cloned.isComment = vnode.isComment;\n cloned.fnContext = vnode.fnContext;\n cloned.fnOptions = vnode.fnOptions;\n cloned.fnScopeId = vnode.fnScopeId;\n cloned.asyncMeta = vnode.asyncMeta;\n cloned.isCloned = true;\n return cloned\n}\n\n/*\n * not type checking this file because flow doesn't play well with\n * dynamically accessing methods on Array prototype\n */\n\nvar arrayProto = Array.prototype;\nvar arrayMethods = Object.create(arrayProto);\n\nvar methodsToPatch = [\n 'push',\n 'pop',\n 'shift',\n 'unshift',\n 'splice',\n 'sort',\n 'reverse'\n];\n\n/**\n * Intercept mutating methods and emit events\n */\nmethodsToPatch.forEach(function (method) {\n // cache original method\n var original = arrayProto[method];\n def(arrayMethods, method, function mutator () {\n var args = [], len = arguments.length;\n while ( len-- ) args[ len ] = arguments[ len ];\n\n var result = original.apply(this, args);\n var ob = this.__ob__;\n var inserted;\n switch (method) {\n case 'push':\n case 'unshift':\n inserted = args;\n break\n case 'splice':\n inserted = args.slice(2);\n break\n }\n if (inserted) { ob.observeArray(inserted); }\n // notify change\n ob.dep.notify();\n return result\n });\n});\n\n/* */\n\nvar arrayKeys = Object.getOwnPropertyNames(arrayMethods);\n\n/**\n * In some cases we may want to disable observation inside a component's\n * update computation.\n */\nvar shouldObserve = true;\n\nfunction toggleObserving (value) {\n shouldObserve = value;\n}\n\n/**\n * Observer class that is attached to each observed\n * object. Once attached, the observer converts the target\n * object's property keys into getter/setters that\n * collect dependencies and dispatch updates.\n */\nvar Observer = function Observer (value) {\n this.value = value;\n this.dep = new Dep();\n this.vmCount = 0;\n def(value, '__ob__', this);\n if (Array.isArray(value)) {\n if (hasProto) {\n protoAugment(value, arrayMethods);\n } else {\n copyAugment(value, arrayMethods, arrayKeys);\n }\n this.observeArray(value);\n } else {\n this.walk(value);\n }\n};\n\n/**\n * Walk through all properties and convert them into\n * getter/setters. This method should only be called when\n * value type is Object.\n */\nObserver.prototype.walk = function walk (obj) {\n var keys = Object.keys(obj);\n for (var i = 0; i < keys.length; i++) {\n defineReactive$$1(obj, keys[i]);\n }\n};\n\n/**\n * Observe a list of Array items.\n */\nObserver.prototype.observeArray = function observeArray (items) {\n for (var i = 0, l = items.length; i < l; i++) {\n observe(items[i]);\n }\n};\n\n// helpers\n\n/**\n * Augment a target Object or Array by intercepting\n * the prototype chain using __proto__\n */\nfunction protoAugment (target, src) {\n /* eslint-disable no-proto */\n target.__proto__ = src;\n /* eslint-enable no-proto */\n}\n\n/**\n * Augment a target Object or Array by defining\n * hidden properties.\n */\n/* istanbul ignore next */\nfunction copyAugment (target, src, keys) {\n for (var i = 0, l = keys.length; i < l; i++) {\n var key = keys[i];\n def(target, key, src[key]);\n }\n}\n\n/**\n * Attempt to create an observer instance for a value,\n * returns the new observer if successfully observed,\n * or the existing observer if the value already has one.\n */\nfunction observe (value, asRootData) {\n if (!isObject(value) || value instanceof VNode) {\n return\n }\n var ob;\n if (hasOwn(value, '__ob__') && value.__ob__ instanceof Observer) {\n ob = value.__ob__;\n } else if (\n shouldObserve &&\n !isServerRendering() &&\n (Array.isArray(value) || isPlainObject(value)) &&\n Object.isExtensible(value) &&\n !value._isVue\n ) {\n ob = new Observer(value);\n }\n if (asRootData && ob) {\n ob.vmCount++;\n }\n return ob\n}\n\n/**\n * Define a reactive property on an Object.\n */\nfunction defineReactive$$1 (\n obj,\n key,\n val,\n customSetter,\n shallow\n) {\n var dep = new Dep();\n\n var property = Object.getOwnPropertyDescriptor(obj, key);\n if (property && property.configurable === false) {\n return\n }\n\n // cater for pre-defined getter/setters\n var getter = property && property.get;\n var setter = property && property.set;\n if ((!getter || setter) && arguments.length === 2) {\n val = obj[key];\n }\n\n var childOb = !shallow && observe(val);\n Object.defineProperty(obj, key, {\n enumerable: true,\n configurable: true,\n get: function reactiveGetter () {\n var value = getter ? getter.call(obj) : val;\n if (Dep.target) {\n dep.depend();\n if (childOb) {\n childOb.dep.depend();\n if (Array.isArray(value)) {\n dependArray(value);\n }\n }\n }\n return value\n },\n set: function reactiveSetter (newVal) {\n var value = getter ? getter.call(obj) : val;\n /* eslint-disable no-self-compare */\n if (newVal === value || (newVal !== newVal && value !== value)) {\n return\n }\n /* eslint-enable no-self-compare */\n if (false) {\n customSetter();\n }\n // #7981: for accessor properties without setter\n if (getter && !setter) { return }\n if (setter) {\n setter.call(obj, newVal);\n } else {\n val = newVal;\n }\n childOb = !shallow && observe(newVal);\n dep.notify();\n }\n });\n}\n\n/**\n * Set a property on an object. Adds the new property and\n * triggers change notification if the property doesn't\n * already exist.\n */\nfunction set (target, key, val) {\n if (false\n ) {\n warn((\"Cannot set reactive property on undefined, null, or primitive value: \" + ((target))));\n }\n if (Array.isArray(target) && isValidArrayIndex(key)) {\n target.length = Math.max(target.length, key);\n target.splice(key, 1, val);\n return val\n }\n if (key in target && !(key in Object.prototype)) {\n target[key] = val;\n return val\n }\n var ob = (target).__ob__;\n if (target._isVue || (ob && ob.vmCount)) {\n \"production\" !== 'production' && warn(\n 'Avoid adding reactive properties to a Vue instance or its root $data ' +\n 'at runtime - declare it upfront in the data option.'\n );\n return val\n }\n if (!ob) {\n target[key] = val;\n return val\n }\n defineReactive$$1(ob.value, key, val);\n ob.dep.notify();\n return val\n}\n\n/**\n * Delete a property and trigger change if necessary.\n */\nfunction del (target, key) {\n if (false\n ) {\n warn((\"Cannot delete reactive property on undefined, null, or primitive value: \" + ((target))));\n }\n if (Array.isArray(target) && isValidArrayIndex(key)) {\n target.splice(key, 1);\n return\n }\n var ob = (target).__ob__;\n if (target._isVue || (ob && ob.vmCount)) {\n \"production\" !== 'production' && warn(\n 'Avoid deleting properties on a Vue instance or its root $data ' +\n '- just set it to null.'\n );\n return\n }\n if (!hasOwn(target, key)) {\n return\n }\n delete target[key];\n if (!ob) {\n return\n }\n ob.dep.notify();\n}\n\n/**\n * Collect dependencies on array elements when the array is touched, since\n * we cannot intercept array element access like property getters.\n */\nfunction dependArray (value) {\n for (var e = (void 0), i = 0, l = value.length; i < l; i++) {\n e = value[i];\n e && e.__ob__ && e.__ob__.dep.depend();\n if (Array.isArray(e)) {\n dependArray(e);\n }\n }\n}\n\n/* */\n\n/**\n * Option overwriting strategies are functions that handle\n * how to merge a parent option value and a child option\n * value into the final value.\n */\nvar strats = config.optionMergeStrategies;\n\n/**\n * Options with restrictions\n */\nif (false) {\n strats.el = strats.propsData = function (parent, child, vm, key) {\n if (!vm) {\n warn(\n \"option \\\"\" + key + \"\\\" can only be used during instance \" +\n 'creation with the `new` keyword.'\n );\n }\n return defaultStrat(parent, child)\n };\n}\n\n/**\n * Helper that recursively merges two data objects together.\n */\nfunction mergeData (to, from) {\n if (!from) { return to }\n var key, toVal, fromVal;\n\n var keys = hasSymbol\n ? Reflect.ownKeys(from)\n : Object.keys(from);\n\n for (var i = 0; i < keys.length; i++) {\n key = keys[i];\n // in case the object is already observed...\n if (key === '__ob__') { continue }\n toVal = to[key];\n fromVal = from[key];\n if (!hasOwn(to, key)) {\n set(to, key, fromVal);\n } else if (\n toVal !== fromVal &&\n isPlainObject(toVal) &&\n isPlainObject(fromVal)\n ) {\n mergeData(toVal, fromVal);\n }\n }\n return to\n}\n\n/**\n * Data\n */\nfunction mergeDataOrFn (\n parentVal,\n childVal,\n vm\n) {\n if (!vm) {\n // in a Vue.extend merge, both should be functions\n if (!childVal) {\n return parentVal\n }\n if (!parentVal) {\n return childVal\n }\n // when parentVal & childVal are both present,\n // we need to return a function that returns the\n // merged result of both functions... no need to\n // check if parentVal is a function here because\n // it has to be a function to pass previous merges.\n return function mergedDataFn () {\n return mergeData(\n typeof childVal === 'function' ? childVal.call(this, this) : childVal,\n typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal\n )\n }\n } else {\n return function mergedInstanceDataFn () {\n // instance merge\n var instanceData = typeof childVal === 'function'\n ? childVal.call(vm, vm)\n : childVal;\n var defaultData = typeof parentVal === 'function'\n ? parentVal.call(vm, vm)\n : parentVal;\n if (instanceData) {\n return mergeData(instanceData, defaultData)\n } else {\n return defaultData\n }\n }\n }\n}\n\nstrats.data = function (\n parentVal,\n childVal,\n vm\n) {\n if (!vm) {\n if (childVal && typeof childVal !== 'function') {\n \"production\" !== 'production' && warn(\n 'The \"data\" option should be a function ' +\n 'that returns a per-instance value in component ' +\n 'definitions.',\n vm\n );\n\n return parentVal\n }\n return mergeDataOrFn(parentVal, childVal)\n }\n\n return mergeDataOrFn(parentVal, childVal, vm)\n};\n\n/**\n * Hooks and props are merged as arrays.\n */\nfunction mergeHook (\n parentVal,\n childVal\n) {\n var res = childVal\n ? parentVal\n ? parentVal.concat(childVal)\n : Array.isArray(childVal)\n ? childVal\n : [childVal]\n : parentVal;\n return res\n ? dedupeHooks(res)\n : res\n}\n\nfunction dedupeHooks (hooks) {\n var res = [];\n for (var i = 0; i < hooks.length; i++) {\n if (res.indexOf(hooks[i]) === -1) {\n res.push(hooks[i]);\n }\n }\n return res\n}\n\nLIFECYCLE_HOOKS.forEach(function (hook) {\n strats[hook] = mergeHook;\n});\n\n/**\n * Assets\n *\n * When a vm is present (instance creation), we need to do\n * a three-way merge between constructor options, instance\n * options and parent options.\n */\nfunction mergeAssets (\n parentVal,\n childVal,\n vm,\n key\n) {\n var res = Object.create(parentVal || null);\n if (childVal) {\n \"production\" !== 'production' && assertObjectType(key, childVal, vm);\n return extend(res, childVal)\n } else {\n return res\n }\n}\n\nASSET_TYPES.forEach(function (type) {\n strats[type + 's'] = mergeAssets;\n});\n\n/**\n * Watchers.\n *\n * Watchers hashes should not overwrite one\n * another, so we merge them as arrays.\n */\nstrats.watch = function (\n parentVal,\n childVal,\n vm,\n key\n) {\n // work around Firefox's Object.prototype.watch...\n if (parentVal === nativeWatch) { parentVal = undefined; }\n if (childVal === nativeWatch) { childVal = undefined; }\n /* istanbul ignore if */\n if (!childVal) { return Object.create(parentVal || null) }\n if (false) {\n assertObjectType(key, childVal, vm);\n }\n if (!parentVal) { return childVal }\n var ret = {};\n extend(ret, parentVal);\n for (var key$1 in childVal) {\n var parent = ret[key$1];\n var child = childVal[key$1];\n if (parent && !Array.isArray(parent)) {\n parent = [parent];\n }\n ret[key$1] = parent\n ? parent.concat(child)\n : Array.isArray(child) ? child : [child];\n }\n return ret\n};\n\n/**\n * Other object hashes.\n */\nstrats.props =\nstrats.methods =\nstrats.inject =\nstrats.computed = function (\n parentVal,\n childVal,\n vm,\n key\n) {\n if (childVal && \"production\" !== 'production') {\n assertObjectType(key, childVal, vm);\n }\n if (!parentVal) { return childVal }\n var ret = Object.create(null);\n extend(ret, parentVal);\n if (childVal) { extend(ret, childVal); }\n return ret\n};\nstrats.provide = mergeDataOrFn;\n\n/**\n * Default strategy.\n */\nvar defaultStrat = function (parentVal, childVal) {\n return childVal === undefined\n ? parentVal\n : childVal\n};\n\n/**\n * Validate component names\n */\nfunction checkComponents (options) {\n for (var key in options.components) {\n validateComponentName(key);\n }\n}\n\nfunction validateComponentName (name) {\n if (!new RegExp((\"^[a-zA-Z][\\\\-\\\\.0-9_\" + (unicodeRegExp.source) + \"]*$\")).test(name)) {\n warn(\n 'Invalid component name: \"' + name + '\". Component names ' +\n 'should conform to valid custom element name in html5 specification.'\n );\n }\n if (isBuiltInTag(name) || config.isReservedTag(name)) {\n warn(\n 'Do not use built-in or reserved HTML elements as component ' +\n 'id: ' + name\n );\n }\n}\n\n/**\n * Ensure all props option syntax are normalized into the\n * Object-based format.\n */\nfunction normalizeProps (options, vm) {\n var props = options.props;\n if (!props) { return }\n var res = {};\n var i, val, name;\n if (Array.isArray(props)) {\n i = props.length;\n while (i--) {\n val = props[i];\n if (typeof val === 'string') {\n name = camelize(val);\n res[name] = { type: null };\n } else if (false) {\n warn('props must be strings when using array syntax.');\n }\n }\n } else if (isPlainObject(props)) {\n for (var key in props) {\n val = props[key];\n name = camelize(key);\n res[name] = isPlainObject(val)\n ? val\n : { type: val };\n }\n } else if (false) {\n warn(\n \"Invalid value for option \\\"props\\\": expected an Array or an Object, \" +\n \"but got \" + (toRawType(props)) + \".\",\n vm\n );\n }\n options.props = res;\n}\n\n/**\n * Normalize all injections into Object-based format\n */\nfunction normalizeInject (options, vm) {\n var inject = options.inject;\n if (!inject) { return }\n var normalized = options.inject = {};\n if (Array.isArray(inject)) {\n for (var i = 0; i < inject.length; i++) {\n normalized[inject[i]] = { from: inject[i] };\n }\n } else if (isPlainObject(inject)) {\n for (var key in inject) {\n var val = inject[key];\n normalized[key] = isPlainObject(val)\n ? extend({ from: key }, val)\n : { from: val };\n }\n } else if (false) {\n warn(\n \"Invalid value for option \\\"inject\\\": expected an Array or an Object, \" +\n \"but got \" + (toRawType(inject)) + \".\",\n vm\n );\n }\n}\n\n/**\n * Normalize raw function directives into object format.\n */\nfunction normalizeDirectives (options) {\n var dirs = options.directives;\n if (dirs) {\n for (var key in dirs) {\n var def$$1 = dirs[key];\n if (typeof def$$1 === 'function') {\n dirs[key] = { bind: def$$1, update: def$$1 };\n }\n }\n }\n}\n\nfunction assertObjectType (name, value, vm) {\n if (!isPlainObject(value)) {\n warn(\n \"Invalid value for option \\\"\" + name + \"\\\": expected an Object, \" +\n \"but got \" + (toRawType(value)) + \".\",\n vm\n );\n }\n}\n\n/**\n * Merge two option objects into a new one.\n * Core utility used in both instantiation and inheritance.\n */\nfunction mergeOptions (\n parent,\n child,\n vm\n) {\n if (false) {\n checkComponents(child);\n }\n\n if (typeof child === 'function') {\n child = child.options;\n }\n\n normalizeProps(child, vm);\n normalizeInject(child, vm);\n normalizeDirectives(child);\n\n // Apply extends and mixins on the child options,\n // but only if it is a raw options object that isn't\n // the result of another mergeOptions call.\n // Only merged options has the _base property.\n if (!child._base) {\n if (child.extends) {\n parent = mergeOptions(parent, child.extends, vm);\n }\n if (child.mixins) {\n for (var i = 0, l = child.mixins.length; i < l; i++) {\n parent = mergeOptions(parent, child.mixins[i], vm);\n }\n }\n }\n\n var options = {};\n var key;\n for (key in parent) {\n mergeField(key);\n }\n for (key in child) {\n if (!hasOwn(parent, key)) {\n mergeField(key);\n }\n }\n function mergeField (key) {\n var strat = strats[key] || defaultStrat;\n options[key] = strat(parent[key], child[key], vm, key);\n }\n return options\n}\n\n/**\n * Resolve an asset.\n * This function is used because child instances need access\n * to assets defined in its ancestor chain.\n */\nfunction resolveAsset (\n options,\n type,\n id,\n warnMissing\n) {\n /* istanbul ignore if */\n if (typeof id !== 'string') {\n return\n }\n var assets = options[type];\n // check local registration variations first\n if (hasOwn(assets, id)) { return assets[id] }\n var camelizedId = camelize(id);\n if (hasOwn(assets, camelizedId)) { return assets[camelizedId] }\n var PascalCaseId = capitalize(camelizedId);\n if (hasOwn(assets, PascalCaseId)) { return assets[PascalCaseId] }\n // fallback to prototype chain\n var res = assets[id] || assets[camelizedId] || assets[PascalCaseId];\n if (false) {\n warn(\n 'Failed to resolve ' + type.slice(0, -1) + ': ' + id,\n options\n );\n }\n return res\n}\n\n/* */\n\n\n\nfunction validateProp (\n key,\n propOptions,\n propsData,\n vm\n) {\n var prop = propOptions[key];\n var absent = !hasOwn(propsData, key);\n var value = propsData[key];\n // boolean casting\n var booleanIndex = getTypeIndex(Boolean, prop.type);\n if (booleanIndex > -1) {\n if (absent && !hasOwn(prop, 'default')) {\n value = false;\n } else if (value === '' || value === hyphenate(key)) {\n // only cast empty string / same name to boolean if\n // boolean has higher priority\n var stringIndex = getTypeIndex(String, prop.type);\n if (stringIndex < 0 || booleanIndex < stringIndex) {\n value = true;\n }\n }\n }\n // check default value\n if (value === undefined) {\n value = getPropDefaultValue(vm, prop, key);\n // since the default value is a fresh copy,\n // make sure to observe it.\n var prevShouldObserve = shouldObserve;\n toggleObserving(true);\n observe(value);\n toggleObserving(prevShouldObserve);\n }\n if (\n false\n ) {\n assertProp(prop, key, value, vm, absent);\n }\n return value\n}\n\n/**\n * Get the default value of a prop.\n */\nfunction getPropDefaultValue (vm, prop, key) {\n // no default, return undefined\n if (!hasOwn(prop, 'default')) {\n return undefined\n }\n var def = prop.default;\n // warn against non-factory defaults for Object & Array\n if (false) {\n warn(\n 'Invalid default value for prop \"' + key + '\": ' +\n 'Props with type Object/Array must use a factory function ' +\n 'to return the default value.',\n vm\n );\n }\n // the raw prop value was also undefined from previous render,\n // return previous default value to avoid unnecessary watcher trigger\n if (vm && vm.$options.propsData &&\n vm.$options.propsData[key] === undefined &&\n vm._props[key] !== undefined\n ) {\n return vm._props[key]\n }\n // call factory function for non-Function types\n // a value is Function if its prototype is function even across different execution context\n return typeof def === 'function' && getType(prop.type) !== 'Function'\n ? def.call(vm)\n : def\n}\n\n/**\n * Assert whether a prop is valid.\n */\nfunction assertProp (\n prop,\n name,\n value,\n vm,\n absent\n) {\n if (prop.required && absent) {\n warn(\n 'Missing required prop: \"' + name + '\"',\n vm\n );\n return\n }\n if (value == null && !prop.required) {\n return\n }\n var type = prop.type;\n var valid = !type || type === true;\n var expectedTypes = [];\n if (type) {\n if (!Array.isArray(type)) {\n type = [type];\n }\n for (var i = 0; i < type.length && !valid; i++) {\n var assertedType = assertType(value, type[i]);\n expectedTypes.push(assertedType.expectedType || '');\n valid = assertedType.valid;\n }\n }\n\n if (!valid) {\n warn(\n getInvalidTypeMessage(name, value, expectedTypes),\n vm\n );\n return\n }\n var validator = prop.validator;\n if (validator) {\n if (!validator(value)) {\n warn(\n 'Invalid prop: custom validator check failed for prop \"' + name + '\".',\n vm\n );\n }\n }\n}\n\nvar simpleCheckRE = /^(String|Number|Boolean|Function|Symbol)$/;\n\nfunction assertType (value, type) {\n var valid;\n var expectedType = getType(type);\n if (simpleCheckRE.test(expectedType)) {\n var t = typeof value;\n valid = t === expectedType.toLowerCase();\n // for primitive wrapper objects\n if (!valid && t === 'object') {\n valid = value instanceof type;\n }\n } else if (expectedType === 'Object') {\n valid = isPlainObject(value);\n } else if (expectedType === 'Array') {\n valid = Array.isArray(value);\n } else {\n valid = value instanceof type;\n }\n return {\n valid: valid,\n expectedType: expectedType\n }\n}\n\n/**\n * Use function string name to check built-in types,\n * because a simple equality check will fail when running\n * across different vms / iframes.\n */\nfunction getType (fn) {\n var match = fn && fn.toString().match(/^\\s*function (\\w+)/);\n return match ? match[1] : ''\n}\n\nfunction isSameType (a, b) {\n return getType(a) === getType(b)\n}\n\nfunction getTypeIndex (type, expectedTypes) {\n if (!Array.isArray(expectedTypes)) {\n return isSameType(expectedTypes, type) ? 0 : -1\n }\n for (var i = 0, len = expectedTypes.length; i < len; i++) {\n if (isSameType(expectedTypes[i], type)) {\n return i\n }\n }\n return -1\n}\n\nfunction getInvalidTypeMessage (name, value, expectedTypes) {\n var message = \"Invalid prop: type check failed for prop \\\"\" + name + \"\\\".\" +\n \" Expected \" + (expectedTypes.map(capitalize).join(', '));\n var expectedType = expectedTypes[0];\n var receivedType = toRawType(value);\n var expectedValue = styleValue(value, expectedType);\n var receivedValue = styleValue(value, receivedType);\n // check if we need to specify expected value\n if (expectedTypes.length === 1 &&\n isExplicable(expectedType) &&\n !isBoolean(expectedType, receivedType)) {\n message += \" with value \" + expectedValue;\n }\n message += \", got \" + receivedType + \" \";\n // check if we need to specify received value\n if (isExplicable(receivedType)) {\n message += \"with value \" + receivedValue + \".\";\n }\n return message\n}\n\nfunction styleValue (value, type) {\n if (type === 'String') {\n return (\"\\\"\" + value + \"\\\"\")\n } else if (type === 'Number') {\n return (\"\" + (Number(value)))\n } else {\n return (\"\" + value)\n }\n}\n\nfunction isExplicable (value) {\n var explicitTypes = ['string', 'number', 'boolean'];\n return explicitTypes.some(function (elem) { return value.toLowerCase() === elem; })\n}\n\nfunction isBoolean () {\n var args = [], len = arguments.length;\n while ( len-- ) args[ len ] = arguments[ len ];\n\n return args.some(function (elem) { return elem.toLowerCase() === 'boolean'; })\n}\n\n/* */\n\nfunction handleError (err, vm, info) {\n // Deactivate deps tracking while processing error handler to avoid possible infinite rendering.\n // See: https://github.com/vuejs/vuex/issues/1505\n pushTarget();\n try {\n if (vm) {\n var cur = vm;\n while ((cur = cur.$parent)) {\n var hooks = cur.$options.errorCaptured;\n if (hooks) {\n for (var i = 0; i < hooks.length; i++) {\n try {\n var capture = hooks[i].call(cur, err, vm, info) === false;\n if (capture) { return }\n } catch (e) {\n globalHandleError(e, cur, 'errorCaptured hook');\n }\n }\n }\n }\n }\n globalHandleError(err, vm, info);\n } finally {\n popTarget();\n }\n}\n\nfunction invokeWithErrorHandling (\n handler,\n context,\n args,\n vm,\n info\n) {\n var res;\n try {\n res = args ? handler.apply(context, args) : handler.call(context);\n if (res && !res._isVue && isPromise(res) && !res._handled) {\n res.catch(function (e) { return handleError(e, vm, info + \" (Promise/async)\"); });\n // issue #9511\n // avoid catch triggering multiple times when nested calls\n res._handled = true;\n }\n } catch (e) {\n handleError(e, vm, info);\n }\n return res\n}\n\nfunction globalHandleError (err, vm, info) {\n if (config.errorHandler) {\n try {\n return config.errorHandler.call(null, err, vm, info)\n } catch (e) {\n // if the user intentionally throws the original error in the handler,\n // do not log it twice\n if (e !== err) {\n logError(e, null, 'config.errorHandler');\n }\n }\n }\n logError(err, vm, info);\n}\n\nfunction logError (err, vm, info) {\n if (false) {\n warn((\"Error in \" + info + \": \\\"\" + (err.toString()) + \"\\\"\"), vm);\n }\n /* istanbul ignore else */\n if ((inBrowser || inWeex) && typeof console !== 'undefined') {\n console.error(err);\n } else {\n throw err\n }\n}\n\n/* */\n\nvar isUsingMicroTask = false;\n\nvar callbacks = [];\nvar pending = false;\n\nfunction flushCallbacks () {\n pending = false;\n var copies = callbacks.slice(0);\n callbacks.length = 0;\n for (var i = 0; i < copies.length; i++) {\n copies[i]();\n }\n}\n\n// Here we have async deferring wrappers using microtasks.\n// In 2.5 we used (macro) tasks (in combination with microtasks).\n// However, it has subtle problems when state is changed right before repaint\n// (e.g. #6813, out-in transitions).\n// Also, using (macro) tasks in event handler would cause some weird behaviors\n// that cannot be circumvented (e.g. #7109, #7153, #7546, #7834, #8109).\n// So we now use microtasks everywhere, again.\n// A major drawback of this tradeoff is that there are some scenarios\n// where microtasks have too high a priority and fire in between supposedly\n// sequential events (e.g. #4521, #6690, which have workarounds)\n// or even between bubbling of the same event (#6566).\nvar timerFunc;\n\n// The nextTick behavior leverages the microtask queue, which can be accessed\n// via either native Promise.then or MutationObserver.\n// MutationObserver has wider support, however it is seriously bugged in\n// UIWebView in iOS >= 9.3.3 when triggered in touch event handlers. It\n// completely stops working after triggering a few times... so, if native\n// Promise is available, we will use it:\n/* istanbul ignore next, $flow-disable-line */\nif (typeof Promise !== 'undefined' && isNative(Promise)) {\n var p = Promise.resolve();\n timerFunc = function () {\n p.then(flushCallbacks);\n // In problematic UIWebViews, Promise.then doesn't completely break, but\n // it can get stuck in a weird state where callbacks are pushed into the\n // microtask queue but the queue isn't being flushed, until the browser\n // needs to do some other work, e.g. handle a timer. Therefore we can\n // \"force\" the microtask queue to be flushed by adding an empty timer.\n if (isIOS) { setTimeout(noop); }\n };\n isUsingMicroTask = true;\n} else if (!isIE && typeof MutationObserver !== 'undefined' && (\n isNative(MutationObserver) ||\n // PhantomJS and iOS 7.x\n MutationObserver.toString() === '[object MutationObserverConstructor]'\n)) {\n // Use MutationObserver where native Promise is not available,\n // e.g. PhantomJS, iOS7, Android 4.4\n // (#6466 MutationObserver is unreliable in IE11)\n var counter = 1;\n var observer = new MutationObserver(flushCallbacks);\n var textNode = document.createTextNode(String(counter));\n observer.observe(textNode, {\n characterData: true\n });\n timerFunc = function () {\n counter = (counter + 1) % 2;\n textNode.data = String(counter);\n };\n isUsingMicroTask = true;\n} else if (typeof setImmediate !== 'undefined' && isNative(setImmediate)) {\n // Fallback to setImmediate.\n // Technically it leverages the (macro) task queue,\n // but it is still a better choice than setTimeout.\n timerFunc = function () {\n setImmediate(flushCallbacks);\n };\n} else {\n // Fallback to setTimeout.\n timerFunc = function () {\n setTimeout(flushCallbacks, 0);\n };\n}\n\nfunction nextTick (cb, ctx) {\n var _resolve;\n callbacks.push(function () {\n if (cb) {\n try {\n cb.call(ctx);\n } catch (e) {\n handleError(e, ctx, 'nextTick');\n }\n } else if (_resolve) {\n _resolve(ctx);\n }\n });\n if (!pending) {\n pending = true;\n timerFunc();\n }\n // $flow-disable-line\n if (!cb && typeof Promise !== 'undefined') {\n return new Promise(function (resolve) {\n _resolve = resolve;\n })\n }\n}\n\n/* */\n\nvar mark;\nvar measure;\n\nif (false) {\n var perf = inBrowser && window.performance;\n /* istanbul ignore if */\n if (\n perf &&\n perf.mark &&\n perf.measure &&\n perf.clearMarks &&\n perf.clearMeasures\n ) {\n mark = function (tag) { return perf.mark(tag); };\n measure = function (name, startTag, endTag) {\n perf.measure(name, startTag, endTag);\n perf.clearMarks(startTag);\n perf.clearMarks(endTag);\n // perf.clearMeasures(name)\n };\n }\n}\n\n/* not type checking this file because flow doesn't play well with Proxy */\n\nvar initProxy;\n\nif (false) {\n var allowedGlobals = makeMap(\n 'Infinity,undefined,NaN,isFinite,isNaN,' +\n 'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +\n 'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +\n 'require' // for Webpack/Browserify\n );\n\n var warnNonPresent = function (target, key) {\n warn(\n \"Property or method \\\"\" + key + \"\\\" is not defined on the instance but \" +\n 'referenced during render. Make sure that this property is reactive, ' +\n 'either in the data option, or for class-based components, by ' +\n 'initializing the property. ' +\n 'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',\n target\n );\n };\n\n var warnReservedPrefix = function (target, key) {\n warn(\n \"Property \\\"\" + key + \"\\\" must be accessed with \\\"$data.\" + key + \"\\\" because \" +\n 'properties starting with \"$\" or \"_\" are not proxied in the Vue instance to ' +\n 'prevent conflicts with Vue internals. ' +\n 'See: https://vuejs.org/v2/api/#data',\n target\n );\n };\n\n var hasProxy =\n typeof Proxy !== 'undefined' && isNative(Proxy);\n\n if (hasProxy) {\n var isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact');\n config.keyCodes = new Proxy(config.keyCodes, {\n set: function set (target, key, value) {\n if (isBuiltInModifier(key)) {\n warn((\"Avoid overwriting built-in modifier in config.keyCodes: .\" + key));\n return false\n } else {\n target[key] = value;\n return true\n }\n }\n });\n }\n\n var hasHandler = {\n has: function has (target, key) {\n var has = key in target;\n var isAllowed = allowedGlobals(key) ||\n (typeof key === 'string' && key.charAt(0) === '_' && !(key in target.$data));\n if (!has && !isAllowed) {\n if (key in target.$data) { warnReservedPrefix(target, key); }\n else { warnNonPresent(target, key); }\n }\n return has || !isAllowed\n }\n };\n\n var getHandler = {\n get: function get (target, key) {\n if (typeof key === 'string' && !(key in target)) {\n if (key in target.$data) { warnReservedPrefix(target, key); }\n else { warnNonPresent(target, key); }\n }\n return target[key]\n }\n };\n\n initProxy = function initProxy (vm) {\n if (hasProxy) {\n // determine which proxy handler to use\n var options = vm.$options;\n var handlers = options.render && options.render._withStripped\n ? getHandler\n : hasHandler;\n vm._renderProxy = new Proxy(vm, handlers);\n } else {\n vm._renderProxy = vm;\n }\n };\n}\n\n/* */\n\nvar seenObjects = new _Set();\n\n/**\n * Recursively traverse an object to evoke all converted\n * getters, so that every nested property inside the object\n * is collected as a \"deep\" dependency.\n */\nfunction traverse (val) {\n _traverse(val, seenObjects);\n seenObjects.clear();\n}\n\nfunction _traverse (val, seen) {\n var i, keys;\n var isA = Array.isArray(val);\n if ((!isA && !isObject(val)) || Object.isFrozen(val) || val instanceof VNode) {\n return\n }\n if (val.__ob__) {\n var depId = val.__ob__.dep.id;\n if (seen.has(depId)) {\n return\n }\n seen.add(depId);\n }\n if (isA) {\n i = val.length;\n while (i--) { _traverse(val[i], seen); }\n } else {\n keys = Object.keys(val);\n i = keys.length;\n while (i--) { _traverse(val[keys[i]], seen); }\n }\n}\n\n/* */\n\nvar normalizeEvent = cached(function (name) {\n var passive = name.charAt(0) === '&';\n name = passive ? name.slice(1) : name;\n var once$$1 = name.charAt(0) === '~'; // Prefixed last, checked first\n name = once$$1 ? name.slice(1) : name;\n var capture = name.charAt(0) === '!';\n name = capture ? name.slice(1) : name;\n return {\n name: name,\n once: once$$1,\n capture: capture,\n passive: passive\n }\n});\n\nfunction createFnInvoker (fns, vm) {\n function invoker () {\n var arguments$1 = arguments;\n\n var fns = invoker.fns;\n if (Array.isArray(fns)) {\n var cloned = fns.slice();\n for (var i = 0; i < cloned.length; i++) {\n invokeWithErrorHandling(cloned[i], null, arguments$1, vm, \"v-on handler\");\n }\n } else {\n // return handler return value for single handlers\n return invokeWithErrorHandling(fns, null, arguments, vm, \"v-on handler\")\n }\n }\n invoker.fns = fns;\n return invoker\n}\n\nfunction updateListeners (\n on,\n oldOn,\n add,\n remove$$1,\n createOnceHandler,\n vm\n) {\n var name, def$$1, cur, old, event;\n for (name in on) {\n def$$1 = cur = on[name];\n old = oldOn[name];\n event = normalizeEvent(name);\n if (isUndef(cur)) {\n \"production\" !== 'production' && warn(\n \"Invalid handler for event \\\"\" + (event.name) + \"\\\": got \" + String(cur),\n vm\n );\n } else if (isUndef(old)) {\n if (isUndef(cur.fns)) {\n cur = on[name] = createFnInvoker(cur, vm);\n }\n if (isTrue(event.once)) {\n cur = on[name] = createOnceHandler(event.name, cur, event.capture);\n }\n add(event.name, cur, event.capture, event.passive, event.params);\n } else if (cur !== old) {\n old.fns = cur;\n on[name] = old;\n }\n }\n for (name in oldOn) {\n if (isUndef(on[name])) {\n event = normalizeEvent(name);\n remove$$1(event.name, oldOn[name], event.capture);\n }\n }\n}\n\n/* */\n\nfunction mergeVNodeHook (def, hookKey, hook) {\n if (def instanceof VNode) {\n def = def.data.hook || (def.data.hook = {});\n }\n var invoker;\n var oldHook = def[hookKey];\n\n function wrappedHook () {\n hook.apply(this, arguments);\n // important: remove merged hook to ensure it's called only once\n // and prevent memory leak\n remove(invoker.fns, wrappedHook);\n }\n\n if (isUndef(oldHook)) {\n // no existing hook\n invoker = createFnInvoker([wrappedHook]);\n } else {\n /* istanbul ignore if */\n if (isDef(oldHook.fns) && isTrue(oldHook.merged)) {\n // already a merged invoker\n invoker = oldHook;\n invoker.fns.push(wrappedHook);\n } else {\n // existing plain hook\n invoker = createFnInvoker([oldHook, wrappedHook]);\n }\n }\n\n invoker.merged = true;\n def[hookKey] = invoker;\n}\n\n/* */\n\nfunction extractPropsFromVNodeData (\n data,\n Ctor,\n tag\n) {\n // we are only extracting raw values here.\n // validation and default values are handled in the child\n // component itself.\n var propOptions = Ctor.options.props;\n if (isUndef(propOptions)) {\n return\n }\n var res = {};\n var attrs = data.attrs;\n var props = data.props;\n if (isDef(attrs) || isDef(props)) {\n for (var key in propOptions) {\n var altKey = hyphenate(key);\n if (false) {\n var keyInLowerCase = key.toLowerCase();\n if (\n key !== keyInLowerCase &&\n attrs && hasOwn(attrs, keyInLowerCase)\n ) {\n tip(\n \"Prop \\\"\" + keyInLowerCase + \"\\\" is passed to component \" +\n (formatComponentName(tag || Ctor)) + \", but the declared prop name is\" +\n \" \\\"\" + key + \"\\\". \" +\n \"Note that HTML attributes are case-insensitive and camelCased \" +\n \"props need to use their kebab-case equivalents when using in-DOM \" +\n \"templates. You should probably use \\\"\" + altKey + \"\\\" instead of \\\"\" + key + \"\\\".\"\n );\n }\n }\n checkProp(res, props, key, altKey, true) ||\n checkProp(res, attrs, key, altKey, false);\n }\n }\n return res\n}\n\nfunction checkProp (\n res,\n hash,\n key,\n altKey,\n preserve\n) {\n if (isDef(hash)) {\n if (hasOwn(hash, key)) {\n res[key] = hash[key];\n if (!preserve) {\n delete hash[key];\n }\n return true\n } else if (hasOwn(hash, altKey)) {\n res[key] = hash[altKey];\n if (!preserve) {\n delete hash[altKey];\n }\n return true\n }\n }\n return false\n}\n\n/* */\n\n// The template compiler attempts to minimize the need for normalization by\n// statically analyzing the template at compile time.\n//\n// For plain HTML markup, normalization can be completely skipped because the\n// generated render function is guaranteed to return Array. There are\n// two cases where extra normalization is needed:\n\n// 1. When the children contains components - because a functional component\n// may return an Array instead of a single root. In this case, just a simple\n// normalization is needed - if any child is an Array, we flatten the whole\n// thing with Array.prototype.concat. It is guaranteed to be only 1-level deep\n// because functional components already normalize their own children.\nfunction simpleNormalizeChildren (children) {\n for (var i = 0; i < children.length; i++) {\n if (Array.isArray(children[i])) {\n return Array.prototype.concat.apply([], children)\n }\n }\n return children\n}\n\n// 2. When the children contains constructs that always generated nested Arrays,\n// e.g.