topTenClassify.js 158 KB

1234567891011121314151617181920212223242526272829303132
  1. /*! 版权所有,翻版必究 */
  2. webpackJsonp([4],{
  3. /***/ 1:
  4. /***/ (function(module, exports, __webpack_require__) {
  5. eval("/* WEBPACK VAR INJECTION */(function($) {var Cover = {\r\n show: function (extraClass) {\r\n //$(\"body,html\").addClass(\"no-scroll\");\r\n $(\"body\").addClass(\"no-scroll\");\r\n $('.cover').show();\r\n if (typeof(extraClass) != \"undefined\" && extraClass) {\r\n $('.cover').addClass(extraClass);\r\n }\r\n $('body').on('touchmove', function (e) {\r\n //console.log(e.target);\r\n if ($(e.target).hasClass('cover')){\r\n e.preventDefault();\r\n return false;\r\n }\r\n });\r\n $('.cover').on('touchmove', function (e) {\r\n e.preventDefault();\r\n return false;\r\n });\r\n },\r\n close: function () {\r\n var cover = $('.cover');\r\n if (cover.hasClass('top')) {\r\n cover.removeClass('top');\r\n }\r\n cover.off('click');\r\n cover.off('touchmove');\r\n cover.hide();\r\n //$(\"body,html\").removeClass(\"no-scroll\");\r\n $(\"body\").removeClass(\"no-scroll\");\r\n $('body').off('touchmove');\r\n },\r\n transShow: function () {\r\n $('.cover').addClass('trans');\r\n $('.cover').show();\r\n },\r\n}\r\n\r\nmodule.exports = Cover;\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwX2xzX3dhcC9jb21tb24vY292ZXIuanM/ODRiMiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUEsdUIiLCJmaWxlIjoiMS5qcyIsInNvdXJjZXNDb250ZW50IjpbInZhciBDb3ZlciA9IHtcclxuICAgIHNob3c6IGZ1bmN0aW9uIChleHRyYUNsYXNzKSB7XHJcbiAgICAgICAgLy8kKFwiYm9keSxodG1sXCIpLmFkZENsYXNzKFwibm8tc2Nyb2xsXCIpO1xyXG4gICAgICAgICQoXCJib2R5XCIpLmFkZENsYXNzKFwibm8tc2Nyb2xsXCIpO1xyXG4gICAgICAgICQoJy5jb3ZlcicpLnNob3coKTtcclxuICAgICAgICBpZiAodHlwZW9mKGV4dHJhQ2xhc3MpICE9IFwidW5kZWZpbmVkXCIgJiYgZXh0cmFDbGFzcykge1xyXG4gICAgICAgICAgICAkKCcuY292ZXInKS5hZGRDbGFzcyhleHRyYUNsYXNzKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgJCgnYm9keScpLm9uKCd0b3VjaG1vdmUnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICAvL2NvbnNvbGUubG9nKGUudGFyZ2V0KTtcclxuICAgICAgICAgICAgaWYgKCQoZS50YXJnZXQpLmhhc0NsYXNzKCdjb3ZlcicpKXtcclxuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgICAgICQoJy5jb3ZlcicpLm9uKCd0b3VjaG1vdmUnLCBmdW5jdGlvbiAoZSkge1xyXG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9KTtcclxuICAgIH0sXHJcbiAgICBjbG9zZTogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgIHZhciBjb3ZlciA9ICQoJy5jb3ZlcicpO1xyXG4gICAgICAgIGlmIChjb3Zlci5oYXNDbGFzcygndG9wJykpIHtcclxuICAgICAgICAgICAgY292ZXIucmVtb3ZlQ2xhc3MoJ3RvcCcpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb3Zlci5vZmYoJ2NsaWNrJyk7XHJcbiAgICAgICAgY292ZXIub2ZmKCd0b3VjaG1vdmUnKTtcclxuICAgICAgICBjb3Zlci5oaWRlKCk7XHJcbiAgICAgICAgLy8kKFwiYm9keSxodG1sXCIpLnJlbW92ZUNsYXNzKFwibm8tc2Nyb2xsXCIpO1xyXG4gICAgICAgICQoXCJib2R5XCIpLnJlbW92ZUNsYXNzKFwibm8tc2Nyb2xsXCIpO1xyXG4gICAgICAgICQoJ2JvZHknKS5vZmYoJ3RvdWNobW92ZScpO1xyXG4gICAgfSxcclxuICAgIHRyYW5zU2hvdzogZnVuY3Rpb24gKCkge1xyXG4gICAgICAgICQoJy5jb3ZlcicpLmFkZENsYXNzKCd0cmFucycpO1xyXG4gICAgICAgICQoJy5jb3ZlcicpLnNob3coKTtcclxuICAgIH0sXHJcbn1cclxuXHJcbm1vZHVsZS5leHBvcnRzID0gQ292ZXI7XG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9zcmMvYXBwX2xzX3dhcC9jb21tb24vY292ZXIuanNcbi8vIG1vZHVsZSBpZCA9IDFcbi8vIG1vZHVsZSBjaHVua3MgPSAyIDMgNCJdLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///1\n");
  6. /***/ }),
  7. /***/ 16:
  8. /***/ (function(module, exports, __webpack_require__) {
  9. eval("/* WEBPACK VAR INJECTION */(function($) {__webpack_require__(17);\r\nvar IScroll=__webpack_require__(2);\r\nvar Cover = __webpack_require__(1);\r\n$(function(){\r\n\r\n var activedPacket = $('.scroll-wrap .active');\r\n if (activedPacket.length>0) {\r\n activedPacket[0].scrollIntoView({block: \"start\", behavior: \"smooth\"});\r\n }\r\n\r\n var myScroll = new IScroll('.slot-block-wrap', {\r\n scrollX: false,\r\n scrollY: true, \r\n hScrollbar: false,\r\n click: true,\r\n // disablePointer:true,\r\n // disableTouch:false,\r\n // disableMouse:true,\r\n });\r\n\r\n function dropDownToggle() {\r\n var slot_block=$(\".slot-block\");\r\n if(slot_block.hasClass(\"active\")){\r\n $(\".nav-down\").children().children(\".iconfont\").html(\"\");\r\n $(\".slot-block\").removeClass(\"active\");\r\n \r\n Cover.close();\r\n }\r\n else{\r\n Cover.show();\r\n $(\".nav-down\").children().children(\".iconfont\").html('');\r\n slot_block.addClass('active');\r\n $(\".cover\").click(function (event) {\r\n dropDownToggle();\r\n });\r\n }\r\n }\r\n $(\".nav-down\").click(function(){\r\n dropDownToggle()\r\n });\r\n})\n/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(0)))\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwX2xzX3dhcC90b3BUZW4vdG9wVGVuQ2xhc3NpZnkvdG9wVGVuQ2xhc3NpZnkuanM/OTRmYiJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoieUNBQUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLHlDQUF5QyxtQ0FBbUM7QUFDNUU7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7O0FBRUw7QUFDQTtBQUNBO0FBQ0EsMEVBQTBFO0FBQzFFOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMEVBQTBFO0FBQzFFO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxDQUFDLEMiLCJmaWxlIjoiMTYuanMiLCJzb3VyY2VzQ29udGVudCI6WyJyZXF1aXJlKCcuL3RvcFRlbkNsYXNzaWZ5LnNjc3MnKTtcclxudmFyIElTY3JvbGw9cmVxdWlyZSgnaXNjcm9sbCcpO1xyXG52YXIgQ292ZXIgPSByZXF1aXJlKCcuLi8uLi9jb21tb24vY292ZXIuanMnKTtcclxuJChmdW5jdGlvbigpe1xyXG5cclxuICAgIHZhciBhY3RpdmVkUGFja2V0ID0gJCgnLnNjcm9sbC13cmFwIC5hY3RpdmUnKTtcclxuICAgIGlmIChhY3RpdmVkUGFja2V0Lmxlbmd0aD4wKSB7XHJcbiAgICAgICAgYWN0aXZlZFBhY2tldFswXS5zY3JvbGxJbnRvVmlldyh7YmxvY2s6IFwic3RhcnRcIiwgYmVoYXZpb3I6IFwic21vb3RoXCJ9KTtcclxuICAgIH1cclxuXHJcbiAgICB2YXIgbXlTY3JvbGwgPSBuZXcgSVNjcm9sbCgnLnNsb3QtYmxvY2std3JhcCcsIHtcclxuICAgICAgICBzY3JvbGxYOiBmYWxzZSxcclxuICAgICAgICBzY3JvbGxZOiB0cnVlLCBcclxuICAgICAgICBoU2Nyb2xsYmFyOiBmYWxzZSxcclxuICAgICAgICBjbGljazogdHJ1ZSxcclxuICAgICAgICAvLyBkaXNhYmxlUG9pbnRlcjp0cnVlLFxyXG4gICAgICAgIC8vIGRpc2FibGVUb3VjaDpmYWxzZSxcclxuICAgICAgICAvLyBkaXNhYmxlTW91c2U6dHJ1ZSxcclxuICAgIH0pO1xyXG5cclxuICAgIGZ1bmN0aW9uIGRyb3BEb3duVG9nZ2xlKCkge1xyXG4gICAgICAgIHZhciBzbG90X2Jsb2NrPSQoXCIuc2xvdC1ibG9ja1wiKTtcclxuICAgICAgICBpZihzbG90X2Jsb2NrLmhhc0NsYXNzKFwiYWN0aXZlXCIpKXtcclxuICAgICAgICAgICAgJChcIi5uYXYtZG93blwiKS5jaGlsZHJlbigpLmNoaWxkcmVuKFwiLmljb25mb250XCIpLmh0bWwoXCImI3hlN2E2O1wiKTtcclxuICAgICAgICAgICAgJChcIi5zbG90LWJsb2NrXCIpLnJlbW92ZUNsYXNzKFwiYWN0aXZlXCIpO1xyXG4gICAgICAgICAgIFxyXG4gICAgICAgICAgICBDb3Zlci5jbG9zZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBlbHNle1xyXG4gICAgICAgICAgICBDb3Zlci5zaG93KCk7XHJcbiAgICAgICAgICAgICQoXCIubmF2LWRvd25cIikuY2hpbGRyZW4oKS5jaGlsZHJlbihcIi5pY29uZm9udFwiKS5odG1sKCcmI3hlNjdlOycpO1xyXG4gICAgICAgICAgICBzbG90X2Jsb2NrLmFkZENsYXNzKCdhY3RpdmUnKTtcclxuICAgICAgICAgICAgJChcIi5jb3ZlclwiKS5jbGljayhmdW5jdGlvbiAoZXZlbnQpIHtcclxuICAgICAgICAgICAgICAgIGRyb3BEb3duVG9nZ2xlKCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgICQoXCIubmF2LWRvd25cIikuY2xpY2soZnVuY3Rpb24oKXtcclxuICAgICAgICBkcm9wRG93blRvZ2dsZSgpXHJcbiAgICB9KTtcclxufSlcblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NyYy9hcHBfbHNfd2FwL3RvcFRlbi90b3BUZW5DbGFzc2lmeS90b3BUZW5DbGFzc2lmeS5qc1xuLy8gbW9kdWxlIGlkID0gMTZcbi8vIG1vZHVsZSBjaHVua3MgPSA0Il0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///16\n");
  10. /***/ }),
  11. /***/ 17:
  12. /***/ (function(module, exports) {
  13. eval("// removed by extract-text-webpack-plugin\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvYXBwX2xzX3dhcC90b3BUZW4vdG9wVGVuQ2xhc3NpZnkvdG9wVGVuQ2xhc3NpZnkuc2Nzcz9iZGQ1Il0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBIiwiZmlsZSI6IjE3LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLy8gcmVtb3ZlZCBieSBleHRyYWN0LXRleHQtd2VicGFjay1wbHVnaW5cblxuXG4vLy8vLy8vLy8vLy8vLy8vLy9cbi8vIFdFQlBBQ0sgRk9PVEVSXG4vLyAuL3NyYy9hcHBfbHNfd2FwL3RvcFRlbi90b3BUZW5DbGFzc2lmeS90b3BUZW5DbGFzc2lmeS5zY3NzXG4vLyBtb2R1bGUgaWQgPSAxN1xuLy8gbW9kdWxlIGNodW5rcyA9IDQiXSwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///17\n");
  14. /***/ }),
  15. /***/ 2:
  16. /***/ (function(module, exports, __webpack_require__) {
  17. eval("var __WEBPACK_AMD_DEFINE_RESULT__;/*! iScroll v5.2.0 ~ (c) 2008-2016 Matteo Spinelli ~ http://cubiq.org/license */\n(function (window, document, Math) {\nvar rAF = window.requestAnimationFrame\t||\n\twindow.webkitRequestAnimationFrame\t||\n\twindow.mozRequestAnimationFrame\t\t||\n\twindow.oRequestAnimationFrame\t\t||\n\twindow.msRequestAnimationFrame\t\t||\n\tfunction (callback) { window.setTimeout(callback, 1000 / 60); };\n\nvar utils = (function () {\n\tvar me = {};\n\n\tvar _elementStyle = document.createElement('div').style;\n\tvar _vendor = (function () {\n\t\tvar vendors = ['t', 'webkitT', 'MozT', 'msT', 'OT'],\n\t\t\ttransform,\n\t\t\ti = 0,\n\t\t\tl = vendors.length;\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\ttransform = vendors[i] + 'ransform';\n\t\t\tif ( transform in _elementStyle ) return vendors[i].substr(0, vendors[i].length-1);\n\t\t}\n\n\t\treturn false;\n\t})();\n\n\tfunction _prefixStyle (style) {\n\t\tif ( _vendor === false ) return false;\n\t\tif ( _vendor === '' ) return style;\n\t\treturn _vendor + style.charAt(0).toUpperCase() + style.substr(1);\n\t}\n\n\tme.getTime = Date.now || function getTime () { return new Date().getTime(); };\n\n\tme.extend = function (target, obj) {\n\t\tfor ( var i in obj ) {\n\t\t\ttarget[i] = obj[i];\n\t\t}\n\t};\n\n\tme.addEvent = function (el, type, fn, capture) {\n\t\tel.addEventListener(type, fn, !!capture);\n\t};\n\n\tme.removeEvent = function (el, type, fn, capture) {\n\t\tel.removeEventListener(type, fn, !!capture);\n\t};\n\n\tme.prefixPointerEvent = function (pointerEvent) {\n\t\treturn window.MSPointerEvent ?\n\t\t\t'MSPointer' + pointerEvent.charAt(7).toUpperCase() + pointerEvent.substr(8):\n\t\t\tpointerEvent;\n\t};\n\n\tme.momentum = function (current, start, time, lowerMargin, wrapperSize, deceleration) {\n\t\tvar distance = current - start,\n\t\t\tspeed = Math.abs(distance) / time,\n\t\t\tdestination,\n\t\t\tduration;\n\n\t\tdeceleration = deceleration === undefined ? 0.0006 : deceleration;\n\n\t\tdestination = current + ( speed * speed ) / ( 2 * deceleration ) * ( distance < 0 ? -1 : 1 );\n\t\tduration = speed / deceleration;\n\n\t\tif ( destination < lowerMargin ) {\n\t\t\tdestination = wrapperSize ? lowerMargin - ( wrapperSize / 2.5 * ( speed / 8 ) ) : lowerMargin;\n\t\t\tdistance = Math.abs(destination - current);\n\t\t\tduration = distance / speed;\n\t\t} else if ( destination > 0 ) {\n\t\t\tdestination = wrapperSize ? wrapperSize / 2.5 * ( speed / 8 ) : 0;\n\t\t\tdistance = Math.abs(current) + destination;\n\t\t\tduration = distance / speed;\n\t\t}\n\n\t\treturn {\n\t\t\tdestination: Math.round(destination),\n\t\t\tduration: duration\n\t\t};\n\t};\n\n\tvar _transform = _prefixStyle('transform');\n\n\tme.extend(me, {\n\t\thasTransform: _transform !== false,\n\t\thasPerspective: _prefixStyle('perspective') in _elementStyle,\n\t\thasTouch: 'ontouchstart' in window,\n\t\thasPointer: !!(window.PointerEvent || window.MSPointerEvent), // IE10 is prefixed\n\t\thasTransition: _prefixStyle('transition') in _elementStyle\n\t});\n\n\t/*\n\tThis should find all Android browsers lower than build 535.19 (both stock browser and webview)\n\t- galaxy S2 is ok\n - 2.3.6 : `AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1`\n - 4.0.4 : `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n - galaxy S3 is badAndroid (stock brower, webview)\n `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n - galaxy S4 is badAndroid (stock brower, webview)\n `AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30`\n - galaxy S5 is OK\n `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n - galaxy S6 is OK\n `AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36 (Chrome/)`\n */\n\tme.isBadAndroid = (function() {\n\t\tvar appVersion = window.navigator.appVersion;\n\t\t// Android browser is not a chrome browser.\n\t\tif (/Android/.test(appVersion) && !(/Chrome\\/\\d/.test(appVersion))) {\n\t\t\tvar safariVersion = appVersion.match(/Safari\\/(\\d+.\\d)/);\n\t\t\tif(safariVersion && typeof safariVersion === \"object\" && safariVersion.length >= 2) {\n\t\t\t\treturn parseFloat(safariVersion[1]) < 535.19;\n\t\t\t} else {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t} else {\n\t\t\treturn false;\n\t\t}\n\t})();\n\n\tme.extend(me.style = {}, {\n\t\ttransform: _transform,\n\t\ttransitionTimingFunction: _prefixStyle('transitionTimingFunction'),\n\t\ttransitionDuration: _prefixStyle('transitionDuration'),\n\t\ttransitionDelay: _prefixStyle('transitionDelay'),\n\t\ttransformOrigin: _prefixStyle('transformOrigin')\n\t});\n\n\tme.hasClass = function (e, c) {\n\t\tvar re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\");\n\t\treturn re.test(e.className);\n\t};\n\n\tme.addClass = function (e, c) {\n\t\tif ( me.hasClass(e, c) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar newclass = e.className.split(' ');\n\t\tnewclass.push(c);\n\t\te.className = newclass.join(' ');\n\t};\n\n\tme.removeClass = function (e, c) {\n\t\tif ( !me.hasClass(e, c) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar re = new RegExp(\"(^|\\\\s)\" + c + \"(\\\\s|$)\", 'g');\n\t\te.className = e.className.replace(re, ' ');\n\t};\n\n\tme.offset = function (el) {\n\t\tvar left = -el.offsetLeft,\n\t\t\ttop = -el.offsetTop;\n\n\t\t// jshint -W084\n\t\twhile (el = el.offsetParent) {\n\t\t\tleft -= el.offsetLeft;\n\t\t\ttop -= el.offsetTop;\n\t\t}\n\t\t// jshint +W084\n\n\t\treturn {\n\t\t\tleft: left,\n\t\t\ttop: top\n\t\t};\n\t};\n\n\tme.preventDefaultException = function (el, exceptions) {\n\t\tfor ( var i in exceptions ) {\n\t\t\tif ( exceptions[i].test(el[i]) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t};\n\n\tme.extend(me.eventType = {}, {\n\t\ttouchstart: 1,\n\t\ttouchmove: 1,\n\t\ttouchend: 1,\n\n\t\tmousedown: 2,\n\t\tmousemove: 2,\n\t\tmouseup: 2,\n\n\t\tpointerdown: 3,\n\t\tpointermove: 3,\n\t\tpointerup: 3,\n\n\t\tMSPointerDown: 3,\n\t\tMSPointerMove: 3,\n\t\tMSPointerUp: 3\n\t});\n\n\tme.extend(me.ease = {}, {\n\t\tquadratic: {\n\t\t\tstyle: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',\n\t\t\tfn: function (k) {\n\t\t\t\treturn k * ( 2 - k );\n\t\t\t}\n\t\t},\n\t\tcircular: {\n\t\t\tstyle: 'cubic-bezier(0.1, 0.57, 0.1, 1)',\t// Not properly \"circular\" but this looks better, it should be (0.075, 0.82, 0.165, 1)\n\t\t\tfn: function (k) {\n\t\t\t\treturn Math.sqrt( 1 - ( --k * k ) );\n\t\t\t}\n\t\t},\n\t\tback: {\n\t\t\tstyle: 'cubic-bezier(0.175, 0.885, 0.32, 1.275)',\n\t\t\tfn: function (k) {\n\t\t\t\tvar b = 4;\n\t\t\t\treturn ( k = k - 1 ) * k * ( ( b + 1 ) * k + b ) + 1;\n\t\t\t}\n\t\t},\n\t\tbounce: {\n\t\t\tstyle: '',\n\t\t\tfn: function (k) {\n\t\t\t\tif ( ( k /= 1 ) < ( 1 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * k * k;\n\t\t\t\t} else if ( k < ( 2 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 1.5 / 2.75 ) ) * k + 0.75;\n\t\t\t\t} else if ( k < ( 2.5 / 2.75 ) ) {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 2.25 / 2.75 ) ) * k + 0.9375;\n\t\t\t\t} else {\n\t\t\t\t\treturn 7.5625 * ( k -= ( 2.625 / 2.75 ) ) * k + 0.984375;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\telastic: {\n\t\t\tstyle: '',\n\t\t\tfn: function (k) {\n\t\t\t\tvar f = 0.22,\n\t\t\t\t\te = 0.4;\n\n\t\t\t\tif ( k === 0 ) { return 0; }\n\t\t\t\tif ( k == 1 ) { return 1; }\n\n\t\t\t\treturn ( e * Math.pow( 2, - 10 * k ) * Math.sin( ( k - f / 4 ) * ( 2 * Math.PI ) / f ) + 1 );\n\t\t\t}\n\t\t}\n\t});\n\n\tme.tap = function (e, eventName) {\n\t\tvar ev = document.createEvent('Event');\n\t\tev.initEvent(eventName, true, true);\n\t\tev.pageX = e.pageX;\n\t\tev.pageY = e.pageY;\n\t\te.target.dispatchEvent(ev);\n\t};\n\n\tme.click = function (e) {\n\t\tvar target = e.target,\n\t\t\tev;\n\n\t\tif ( !(/(SELECT|INPUT|TEXTAREA)/i).test(target.tagName) ) {\n\t\t\tev = document.createEvent('MouseEvents');\n\t\t\tev.initMouseEvent('click', true, true, e.view, 1,\n\t\t\t\ttarget.screenX, target.screenY, target.clientX, target.clientY,\n\t\t\t\te.ctrlKey, e.altKey, e.shiftKey, e.metaKey,\n\t\t\t\t0, null);\n\n\t\t\tev._constructed = true;\n\t\t\ttarget.dispatchEvent(ev);\n\t\t}\n\t};\n\n\treturn me;\n})();\nfunction IScroll (el, options) {\n\tthis.wrapper = typeof el == 'string' ? document.querySelector(el) : el;\n\tthis.scroller = this.wrapper.children[0];\n\tthis.scrollerStyle = this.scroller.style;\t\t// cache style for better performance\n\n\tthis.options = {\n\n\t\tresizeScrollbars: true,\n\n\t\tmouseWheelSpeed: 20,\n\n\t\tsnapThreshold: 0.334,\n\n// INSERT POINT: OPTIONS\n\t\tdisablePointer : !utils.hasPointer,\n\t\tdisableTouch : utils.hasPointer || !utils.hasTouch,\n\t\tdisableMouse : utils.hasPointer || utils.hasTouch,\n\t\tstartX: 0,\n\t\tstartY: 0,\n\t\tscrollY: true,\n\t\tdirectionLockThreshold: 5,\n\t\tmomentum: true,\n\n\t\tbounce: true,\n\t\tbounceTime: 600,\n\t\tbounceEasing: '',\n\n\t\tpreventDefault: true,\n\t\tpreventDefaultException: { tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/ },\n\n\t\tHWCompositing: true,\n\t\tuseTransition: true,\n\t\tuseTransform: true,\n\t\tbindToWrapper: typeof window.onmousedown === \"undefined\"\n\t};\n\n\tfor ( var i in options ) {\n\t\tthis.options[i] = options[i];\n\t}\n\n\t// Normalize options\n\tthis.translateZ = this.options.HWCompositing && utils.hasPerspective ? ' translateZ(0)' : '';\n\n\tthis.options.useTransition = utils.hasTransition && this.options.useTransition;\n\tthis.options.useTransform = utils.hasTransform && this.options.useTransform;\n\n\tthis.options.eventPassthrough = this.options.eventPassthrough === true ? 'vertical' : this.options.eventPassthrough;\n\tthis.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;\n\n\t// If you want eventPassthrough I have to lock one of the axes\n\tthis.options.scrollY = this.options.eventPassthrough == 'vertical' ? false : this.options.scrollY;\n\tthis.options.scrollX = this.options.eventPassthrough == 'horizontal' ? false : this.options.scrollX;\n\n\t// With eventPassthrough we also need lockDirection mechanism\n\tthis.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;\n\tthis.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;\n\n\tthis.options.bounceEasing = typeof this.options.bounceEasing == 'string' ? utils.ease[this.options.bounceEasing] || utils.ease.circular : this.options.bounceEasing;\n\n\tthis.options.resizePolling = this.options.resizePolling === undefined ? 60 : this.options.resizePolling;\n\n\tif ( this.options.tap === true ) {\n\t\tthis.options.tap = 'tap';\n\t}\n\n\tif ( this.options.shrinkScrollbars == 'scale' ) {\n\t\tthis.options.useTransition = false;\n\t}\n\n\tthis.options.invertWheelDirection = this.options.invertWheelDirection ? -1 : 1;\n\n// INSERT POINT: NORMALIZATION\n\n\t// Some defaults\n\tthis.x = 0;\n\tthis.y = 0;\n\tthis.directionX = 0;\n\tthis.directionY = 0;\n\tthis._events = {};\n\n// INSERT POINT: DEFAULTS\n\n\tthis._init();\n\tthis.refresh();\n\n\tthis.scrollTo(this.options.startX, this.options.startY);\n\tthis.enable();\n}\n\nIScroll.prototype = {\n\tversion: '5.2.0',\n\n\t_init: function () {\n\t\tthis._initEvents();\n\n\t\tif ( this.options.scrollbars || this.options.indicators ) {\n\t\t\tthis._initIndicators();\n\t\t}\n\n\t\tif ( this.options.mouseWheel ) {\n\t\t\tthis._initWheel();\n\t\t}\n\n\t\tif ( this.options.snap ) {\n\t\t\tthis._initSnap();\n\t\t}\n\n\t\tif ( this.options.keyBindings ) {\n\t\t\tthis._initKeys();\n\t\t}\n\n// INSERT POINT: _init\n\n\t},\n\n\tdestroy: function () {\n\t\tthis._initEvents(true);\n\t\tclearTimeout(this.resizeTimeout);\n \t\tthis.resizeTimeout = null;\n\t\tthis._execEvent('destroy');\n\t},\n\n\t_transitionEnd: function (e) {\n\t\tif ( e.target != this.scroller || !this.isInTransition ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._transitionTime();\n\t\tif ( !this.resetPosition(this.options.bounceTime) ) {\n\t\t\tthis.isInTransition = false;\n\t\t\tthis._execEvent('scrollEnd');\n\t\t}\n\t},\n\n\t_start: function (e) {\n\t\t// React to left mouse button only\n\t\tif ( utils.eventType[e.type] != 1 ) {\n\t\t // for button property\n\t\t // http://unixpapa.com/js/mouse.html\n\t\t var button;\n\t if (!e.which) {\n\t /* IE case */\n\t button = (e.button < 2) ? 0 :\n\t ((e.button == 4) ? 1 : 2);\n\t } else {\n\t /* All others */\n\t button = e.button;\n\t }\n\t\t\tif ( button !== 0 ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tif ( !this.enabled || (this.initiated && utils.eventType[e.type] !== this.initiated) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault && !utils.isBadAndroid && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point = e.touches ? e.touches[0] : e,\n\t\t\tpos;\n\n\t\tthis.initiated\t= utils.eventType[e.type];\n\t\tthis.moved\t\t= false;\n\t\tthis.distX\t\t= 0;\n\t\tthis.distY\t\t= 0;\n\t\tthis.directionX = 0;\n\t\tthis.directionY = 0;\n\t\tthis.directionLocked = 0;\n\n\t\tthis.startTime = utils.getTime();\n\n\t\tif ( this.options.useTransition && this.isInTransition ) {\n\t\t\tthis._transitionTime();\n\t\t\tthis.isInTransition = false;\n\t\t\tpos = this.getComputedPosition();\n\t\t\tthis._translate(Math.round(pos.x), Math.round(pos.y));\n\t\t\tthis._execEvent('scrollEnd');\n\t\t} else if ( !this.options.useTransition && this.isAnimating ) {\n\t\t\tthis.isAnimating = false;\n\t\t\tthis._execEvent('scrollEnd');\n\t\t}\n\n\t\tthis.startX = this.x;\n\t\tthis.startY = this.y;\n\t\tthis.absStartX = this.x;\n\t\tthis.absStartY = this.y;\n\t\tthis.pointX = point.pageX;\n\t\tthis.pointY = point.pageY;\n\n\t\tthis._execEvent('beforeScrollStart');\n\t},\n\n\t_move: function (e) {\n\t\tif ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault ) {\t// increases performance on Android? TODO: check!\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point\t\t= e.touches ? e.touches[0] : e,\n\t\t\tdeltaX\t\t= point.pageX - this.pointX,\n\t\t\tdeltaY\t\t= point.pageY - this.pointY,\n\t\t\ttimestamp\t= utils.getTime(),\n\t\t\tnewX, newY,\n\t\t\tabsDistX, absDistY;\n\n\t\tthis.pointX\t\t= point.pageX;\n\t\tthis.pointY\t\t= point.pageY;\n\n\t\tthis.distX\t\t+= deltaX;\n\t\tthis.distY\t\t+= deltaY;\n\t\tabsDistX\t\t= Math.abs(this.distX);\n\t\tabsDistY\t\t= Math.abs(this.distY);\n\n\t\t// We need to move at least 10 pixels for the scrolling to initiate\n\t\tif ( timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If you are scrolling in one direction lock the other\n\t\tif ( !this.directionLocked && !this.options.freeScroll ) {\n\t\t\tif ( absDistX > absDistY + this.options.directionLockThreshold ) {\n\t\t\t\tthis.directionLocked = 'h';\t\t// lock horizontally\n\t\t\t} else if ( absDistY >= absDistX + this.options.directionLockThreshold ) {\n\t\t\t\tthis.directionLocked = 'v';\t\t// lock vertically\n\t\t\t} else {\n\t\t\t\tthis.directionLocked = 'n';\t\t// no lock\n\t\t\t}\n\t\t}\n\n\t\tif ( this.directionLocked == 'h' ) {\n\t\t\tif ( this.options.eventPassthrough == 'vertical' ) {\n\t\t\t\te.preventDefault();\n\t\t\t} else if ( this.options.eventPassthrough == 'horizontal' ) {\n\t\t\t\tthis.initiated = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdeltaY = 0;\n\t\t} else if ( this.directionLocked == 'v' ) {\n\t\t\tif ( this.options.eventPassthrough == 'horizontal' ) {\n\t\t\t\te.preventDefault();\n\t\t\t} else if ( this.options.eventPassthrough == 'vertical' ) {\n\t\t\t\tthis.initiated = false;\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdeltaX = 0;\n\t\t}\n\n\t\tdeltaX = this.hasHorizontalScroll ? deltaX : 0;\n\t\tdeltaY = this.hasVerticalScroll ? deltaY : 0;\n\n\t\tnewX = this.x + deltaX;\n\t\tnewY = this.y + deltaY;\n\n\t\t// Slow down if outside of the boundaries\n\t\tif ( newX > 0 || newX < this.maxScrollX ) {\n\t\t\tnewX = this.options.bounce ? this.x + deltaX / 3 : newX > 0 ? 0 : this.maxScrollX;\n\t\t}\n\t\tif ( newY > 0 || newY < this.maxScrollY ) {\n\t\t\tnewY = this.options.bounce ? this.y + deltaY / 3 : newY > 0 ? 0 : this.maxScrollY;\n\t\t}\n\n\t\tthis.directionX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;\n\t\tthis.directionY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;\n\n\t\tif ( !this.moved ) {\n\t\t\tthis._execEvent('scrollStart');\n\t\t}\n\n\t\tthis.moved = true;\n\n\t\tthis._translate(newX, newY);\n\n/* REPLACE START: _move */\n\n\t\tif ( timestamp - this.startTime > 300 ) {\n\t\t\tthis.startTime = timestamp;\n\t\t\tthis.startX = this.x;\n\t\t\tthis.startY = this.y;\n\t\t}\n\n/* REPLACE END: _move */\n\n\t},\n\n\t_end: function (e) {\n\t\tif ( !this.enabled || utils.eventType[e.type] !== this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this.options.preventDefault && !utils.preventDefaultException(e.target, this.options.preventDefaultException) ) {\n\t\t\te.preventDefault();\n\t\t}\n\n\t\tvar point = e.changedTouches ? e.changedTouches[0] : e,\n\t\t\tmomentumX,\n\t\t\tmomentumY,\n\t\t\tduration = utils.getTime() - this.startTime,\n\t\t\tnewX = Math.round(this.x),\n\t\t\tnewY = Math.round(this.y),\n\t\t\tdistanceX = Math.abs(newX - this.startX),\n\t\t\tdistanceY = Math.abs(newY - this.startY),\n\t\t\ttime = 0,\n\t\t\teasing = '';\n\n\t\tthis.isInTransition = 0;\n\t\tthis.initiated = 0;\n\t\tthis.endTime = utils.getTime();\n\n\t\t// reset if we are outside of the boundaries\n\t\tif ( this.resetPosition(this.options.bounceTime) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY);\t// ensures that the last position is rounded\n\n\t\t// we scrolled less than 10 pixels\n\t\tif ( !this.moved ) {\n\t\t\tif ( this.options.tap ) {\n\t\t\t\tutils.tap(e, this.options.tap);\n\t\t\t}\n\n\t\t\tif ( this.options.click ) {\n\t\t\t\tutils.click(e);\n\t\t\t}\n\n\t\t\tthis._execEvent('scrollCancel');\n\t\t\treturn;\n\t\t}\n\n\t\tif ( this._events.flick && duration < 200 && distanceX < 100 && distanceY < 100 ) {\n\t\t\tthis._execEvent('flick');\n\t\t\treturn;\n\t\t}\n\n\t\t// start momentum animation if needed\n\t\tif ( this.options.momentum && duration < 300 ) {\n\t\t\tmomentumX = this.hasHorizontalScroll ? utils.momentum(this.x, this.startX, duration, this.maxScrollX, this.options.bounce ? this.wrapperWidth : 0, this.options.deceleration) : { destination: newX, duration: 0 };\n\t\t\tmomentumY = this.hasVerticalScroll ? utils.momentum(this.y, this.startY, duration, this.maxScrollY, this.options.bounce ? this.wrapperHeight : 0, this.options.deceleration) : { destination: newY, duration: 0 };\n\t\t\tnewX = momentumX.destination;\n\t\t\tnewY = momentumY.destination;\n\t\t\ttime = Math.max(momentumX.duration, momentumY.duration);\n\t\t\tthis.isInTransition = 1;\n\t\t}\n\n\n\t\tif ( this.options.snap ) {\n\t\t\tvar snap = this._nearestSnap(newX, newY);\n\t\t\tthis.currentPage = snap;\n\t\t\ttime = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(newX - snap.x), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(newY - snap.y), 1000)\n\t\t\t\t\t), 300);\n\t\t\tnewX = snap.x;\n\t\t\tnewY = snap.y;\n\n\t\t\tthis.directionX = 0;\n\t\t\tthis.directionY = 0;\n\t\t\teasing = this.options.bounceEasing;\n\t\t}\n\n// INSERT POINT: _end\n\n\t\tif ( newX != this.x || newY != this.y ) {\n\t\t\t// change easing function when scroller goes out of the boundaries\n\t\t\tif ( newX > 0 || newX < this.maxScrollX || newY > 0 || newY < this.maxScrollY ) {\n\t\t\t\teasing = utils.ease.quadratic;\n\t\t\t}\n\n\t\t\tthis.scrollTo(newX, newY, time, easing);\n\t\t\treturn;\n\t\t}\n\n\t\tthis._execEvent('scrollEnd');\n\t},\n\n\t_resize: function () {\n\t\tvar that = this;\n\n\t\tclearTimeout(this.resizeTimeout);\n\n\t\tthis.resizeTimeout = setTimeout(function () {\n\t\t\tthat.refresh();\n\t\t}, this.options.resizePolling);\n\t},\n\n\tresetPosition: function (time) {\n\t\tvar x = this.x,\n\t\t\ty = this.y;\n\n\t\ttime = time || 0;\n\n\t\tif ( !this.hasHorizontalScroll || this.x > 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( this.x < this.maxScrollX ) {\n\t\t\tx = this.maxScrollX;\n\t\t}\n\n\t\tif ( !this.hasVerticalScroll || this.y > 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( this.y < this.maxScrollY ) {\n\t\t\ty = this.maxScrollY;\n\t\t}\n\n\t\tif ( x == this.x && y == this.y ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tthis.scrollTo(x, y, time, this.options.bounceEasing);\n\n\t\treturn true;\n\t},\n\n\tdisable: function () {\n\t\tthis.enabled = false;\n\t},\n\n\tenable: function () {\n\t\tthis.enabled = true;\n\t},\n\n\trefresh: function () {\n\t\tvar rf = this.wrapper.offsetHeight;\t\t// Force reflow\n\n\t\tthis.wrapperWidth\t= this.wrapper.clientWidth;\n\t\tthis.wrapperHeight\t= this.wrapper.clientHeight;\n\n/* REPLACE START: refresh */\n\n\t\tthis.scrollerWidth\t= this.scroller.offsetWidth;\n\t\tthis.scrollerHeight\t= this.scroller.offsetHeight;\n\n\t\tthis.maxScrollX\t\t= this.wrapperWidth - this.scrollerWidth;\n\t\tthis.maxScrollY\t\t= this.wrapperHeight - this.scrollerHeight;\n\n/* REPLACE END: refresh */\n\n\t\tthis.hasHorizontalScroll\t= this.options.scrollX && this.maxScrollX < 0;\n\t\tthis.hasVerticalScroll\t\t= this.options.scrollY && this.maxScrollY < 0;\n\n\t\tif ( !this.hasHorizontalScroll ) {\n\t\t\tthis.maxScrollX = 0;\n\t\t\tthis.scrollerWidth = this.wrapperWidth;\n\t\t}\n\n\t\tif ( !this.hasVerticalScroll ) {\n\t\t\tthis.maxScrollY = 0;\n\t\t\tthis.scrollerHeight = this.wrapperHeight;\n\t\t}\n\n\t\tthis.endTime = 0;\n\t\tthis.directionX = 0;\n\t\tthis.directionY = 0;\n\n\t\tthis.wrapperOffset = utils.offset(this.wrapper);\n\n\t\tthis._execEvent('refresh');\n\n\t\tthis.resetPosition();\n\n// INSERT POINT: _refresh\n\n\t},\n\n\ton: function (type, fn) {\n\t\tif ( !this._events[type] ) {\n\t\t\tthis._events[type] = [];\n\t\t}\n\n\t\tthis._events[type].push(fn);\n\t},\n\n\toff: function (type, fn) {\n\t\tif ( !this._events[type] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar index = this._events[type].indexOf(fn);\n\n\t\tif ( index > -1 ) {\n\t\t\tthis._events[type].splice(index, 1);\n\t\t}\n\t},\n\n\t_execEvent: function (type) {\n\t\tif ( !this._events[type] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar i = 0,\n\t\t\tl = this._events[type].length;\n\n\t\tif ( !l ) {\n\t\t\treturn;\n\t\t}\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tthis._events[type][i].apply(this, [].slice.call(arguments, 1));\n\t\t}\n\t},\n\n\tscrollBy: function (x, y, time, easing) {\n\t\tx = this.x + x;\n\t\ty = this.y + y;\n\t\ttime = time || 0;\n\n\t\tthis.scrollTo(x, y, time, easing);\n\t},\n\n\tscrollTo: function (x, y, time, easing) {\n\t\teasing = easing || utils.ease.circular;\n\n\t\tthis.isInTransition = this.options.useTransition && time > 0;\n\t\tvar transitionType = this.options.useTransition && easing.style;\n\t\tif ( !time || transitionType ) {\n\t\t\t\tif(transitionType) {\n\t\t\t\t\tthis._transitionTimingFunction(easing.style);\n\t\t\t\t\tthis._transitionTime(time);\n\t\t\t\t}\n\t\t\tthis._translate(x, y);\n\t\t} else {\n\t\t\tthis._animate(x, y, time, easing.fn);\n\t\t}\n\t},\n\n\tscrollToElement: function (el, time, offsetX, offsetY, easing) {\n\t\tel = el.nodeType ? el : this.scroller.querySelector(el);\n\n\t\tif ( !el ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar pos = utils.offset(el);\n\n\t\tpos.left -= this.wrapperOffset.left;\n\t\tpos.top -= this.wrapperOffset.top;\n\n\t\t// if offsetX/Y are true we center the element to the screen\n\t\tif ( offsetX === true ) {\n\t\t\toffsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);\n\t\t}\n\t\tif ( offsetY === true ) {\n\t\t\toffsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);\n\t\t}\n\n\t\tpos.left -= offsetX || 0;\n\t\tpos.top -= offsetY || 0;\n\n\t\tpos.left = pos.left > 0 ? 0 : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;\n\t\tpos.top = pos.top > 0 ? 0 : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;\n\n\t\ttime = time === undefined || time === null || time === 'auto' ? Math.max(Math.abs(this.x-pos.left), Math.abs(this.y-pos.top)) : time;\n\n\t\tthis.scrollTo(pos.left, pos.top, time, easing);\n\t},\n\n\t_transitionTime: function (time) {\n\t\ttime = time || 0;\n\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tthis.scrollerStyle[durationProp] = time + 'ms';\n\n\t\tif ( !time && utils.isBadAndroid ) {\n\t\t\tthis.scrollerStyle[durationProp] = '0.0001ms';\n\t\t\t// remove 0.0001ms\n\t\t\tvar self = this;\n\t\t\trAF(function() {\n\t\t\t\tif(self.scrollerStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.scrollerStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\n\t\tif ( this.indicators ) {\n\t\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\t\tthis.indicators[i].transitionTime(time);\n\t\t\t}\n\t\t}\n\n\n// INSERT POINT: _transitionTime\n\n\t},\n\n\t_transitionTimingFunction: function (easing) {\n\t\tthis.scrollerStyle[utils.style.transitionTimingFunction] = easing;\n\n\n\t\tif ( this.indicators ) {\n\t\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\t\tthis.indicators[i].transitionTimingFunction(easing);\n\t\t\t}\n\t\t}\n\n\n// INSERT POINT: _transitionTimingFunction\n\n\t},\n\n\t_translate: function (x, y) {\n\t\tif ( this.options.useTransform ) {\n\n/* REPLACE START: _translate */\n\n\t\t\tthis.scrollerStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.translateZ;\n\n/* REPLACE END: _translate */\n\n\t\t} else {\n\t\t\tx = Math.round(x);\n\t\t\ty = Math.round(y);\n\t\t\tthis.scrollerStyle.left = x + 'px';\n\t\t\tthis.scrollerStyle.top = y + 'px';\n\t\t}\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\n\tif ( this.indicators ) {\n\t\tfor ( var i = this.indicators.length; i--; ) {\n\t\t\tthis.indicators[i].updatePosition();\n\t\t}\n\t}\n\n\n// INSERT POINT: _translate\n\n\t},\n\n\t_initEvents: function (remove) {\n\t\tvar eventType = remove ? utils.removeEvent : utils.addEvent,\n\t\t\ttarget = this.options.bindToWrapper ? this.wrapper : window;\n\n\t\teventType(window, 'orientationchange', this);\n\t\teventType(window, 'resize', this);\n\n\t\tif ( this.options.click ) {\n\t\t\teventType(this.wrapper, 'click', this, true);\n\t\t}\n\n\t\tif ( !this.options.disableMouse ) {\n\t\t\teventType(this.wrapper, 'mousedown', this);\n\t\t\teventType(target, 'mousemove', this);\n\t\t\teventType(target, 'mousecancel', this);\n\t\t\teventType(target, 'mouseup', this);\n\t\t}\n\n\t\tif ( utils.hasPointer && !this.options.disablePointer ) {\n\t\t\teventType(this.wrapper, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointermove'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointercancel'), this);\n\t\t\teventType(target, utils.prefixPointerEvent('pointerup'), this);\n\t\t}\n\n\t\tif ( utils.hasTouch && !this.options.disableTouch ) {\n\t\t\teventType(this.wrapper, 'touchstart', this);\n\t\t\teventType(target, 'touchmove', this);\n\t\t\teventType(target, 'touchcancel', this);\n\t\t\teventType(target, 'touchend', this);\n\t\t}\n\n\t\teventType(this.scroller, 'transitionend', this);\n\t\teventType(this.scroller, 'webkitTransitionEnd', this);\n\t\teventType(this.scroller, 'oTransitionEnd', this);\n\t\teventType(this.scroller, 'MSTransitionEnd', this);\n\t},\n\n\tgetComputedPosition: function () {\n\t\tvar matrix = window.getComputedStyle(this.scroller, null),\n\t\t\tx, y;\n\n\t\tif ( this.options.useTransform ) {\n\t\t\tmatrix = matrix[utils.style.transform].split(')')[0].split(', ');\n\t\t\tx = +(matrix[12] || matrix[4]);\n\t\t\ty = +(matrix[13] || matrix[5]);\n\t\t} else {\n\t\t\tx = +matrix.left.replace(/[^-\\d.]/g, '');\n\t\t\ty = +matrix.top.replace(/[^-\\d.]/g, '');\n\t\t}\n\n\t\treturn { x: x, y: y };\n\t},\n\t_initIndicators: function () {\n\t\tvar interactive = this.options.interactiveScrollbars,\n\t\t\tcustomStyle = typeof this.options.scrollbars != 'string',\n\t\t\tindicators = [],\n\t\t\tindicator;\n\n\t\tvar that = this;\n\n\t\tthis.indicators = [];\n\n\t\tif ( this.options.scrollbars ) {\n\t\t\t// Vertical scrollbar\n\t\t\tif ( this.options.scrollY ) {\n\t\t\t\tindicator = {\n\t\t\t\t\tel: createDefaultScrollbar('v', interactive, this.options.scrollbars),\n\t\t\t\t\tinteractive: interactive,\n\t\t\t\t\tdefaultScrollbars: true,\n\t\t\t\t\tcustomStyle: customStyle,\n\t\t\t\t\tresize: this.options.resizeScrollbars,\n\t\t\t\t\tshrink: this.options.shrinkScrollbars,\n\t\t\t\t\tfade: this.options.fadeScrollbars,\n\t\t\t\t\tlistenX: false\n\t\t\t\t};\n\n\t\t\t\tthis.wrapper.appendChild(indicator.el);\n\t\t\t\tindicators.push(indicator);\n\t\t\t}\n\n\t\t\t// Horizontal scrollbar\n\t\t\tif ( this.options.scrollX ) {\n\t\t\t\tindicator = {\n\t\t\t\t\tel: createDefaultScrollbar('h', interactive, this.options.scrollbars),\n\t\t\t\t\tinteractive: interactive,\n\t\t\t\t\tdefaultScrollbars: true,\n\t\t\t\t\tcustomStyle: customStyle,\n\t\t\t\t\tresize: this.options.resizeScrollbars,\n\t\t\t\t\tshrink: this.options.shrinkScrollbars,\n\t\t\t\t\tfade: this.options.fadeScrollbars,\n\t\t\t\t\tlistenY: false\n\t\t\t\t};\n\n\t\t\t\tthis.wrapper.appendChild(indicator.el);\n\t\t\t\tindicators.push(indicator);\n\t\t\t}\n\t\t}\n\n\t\tif ( this.options.indicators ) {\n\t\t\t// TODO: check concat compatibility\n\t\t\tindicators = indicators.concat(this.options.indicators);\n\t\t}\n\n\t\tfor ( var i = indicators.length; i--; ) {\n\t\t\tthis.indicators.push( new Indicator(this, indicators[i]) );\n\t\t}\n\n\t\t// TODO: check if we can use array.map (wide compatibility and performance issues)\n\t\tfunction _indicatorsMap (fn) {\n\t\t\tif (that.indicators) {\n\t\t\t\tfor ( var i = that.indicators.length; i--; ) {\n\t\t\t\t\tfn.call(that.indicators[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( this.options.fadeScrollbars ) {\n\t\t\tthis.on('scrollEnd', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade();\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('scrollCancel', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade();\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('scrollStart', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade(1);\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tthis.on('beforeScrollStart', function () {\n\t\t\t\t_indicatorsMap(function () {\n\t\t\t\t\tthis.fade(1, true);\n\t\t\t\t});\n\t\t\t});\n\t\t}\n\n\n\t\tthis.on('refresh', function () {\n\t\t\t_indicatorsMap(function () {\n\t\t\t\tthis.refresh();\n\t\t\t});\n\t\t});\n\n\t\tthis.on('destroy', function () {\n\t\t\t_indicatorsMap(function () {\n\t\t\t\tthis.destroy();\n\t\t\t});\n\n\t\t\tdelete this.indicators;\n\t\t});\n\t},\n\n\t_initWheel: function () {\n\t\tutils.addEvent(this.wrapper, 'wheel', this);\n\t\tutils.addEvent(this.wrapper, 'mousewheel', this);\n\t\tutils.addEvent(this.wrapper, 'DOMMouseScroll', this);\n\n\t\tthis.on('destroy', function () {\n\t\t\tclearTimeout(this.wheelTimeout);\n\t\t\tthis.wheelTimeout = null;\n\t\t\tutils.removeEvent(this.wrapper, 'wheel', this);\n\t\t\tutils.removeEvent(this.wrapper, 'mousewheel', this);\n\t\t\tutils.removeEvent(this.wrapper, 'DOMMouseScroll', this);\n\t\t});\n\t},\n\n\t_wheel: function (e) {\n\t\tif ( !this.enabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\te.preventDefault();\n\n\t\tvar wheelDeltaX, wheelDeltaY,\n\t\t\tnewX, newY,\n\t\t\tthat = this;\n\n\t\tif ( this.wheelTimeout === undefined ) {\n\t\t\tthat._execEvent('scrollStart');\n\t\t}\n\n\t\t// Execute the scrollEnd event after 400ms the wheel stopped scrolling\n\t\tclearTimeout(this.wheelTimeout);\n\t\tthis.wheelTimeout = setTimeout(function () {\n\t\t\tif(!that.options.snap) {\n\t\t\t\tthat._execEvent('scrollEnd');\n\t\t\t}\n\t\t\tthat.wheelTimeout = undefined;\n\t\t}, 400);\n\n\t\tif ( 'deltaX' in e ) {\n\t\t\tif (e.deltaMode === 1) {\n\t\t\t\twheelDeltaX = -e.deltaX * this.options.mouseWheelSpeed;\n\t\t\t\twheelDeltaY = -e.deltaY * this.options.mouseWheelSpeed;\n\t\t\t} else {\n\t\t\t\twheelDeltaX = -e.deltaX;\n\t\t\t\twheelDeltaY = -e.deltaY;\n\t\t\t}\n\t\t} else if ( 'wheelDeltaX' in e ) {\n\t\t\twheelDeltaX = e.wheelDeltaX / 120 * this.options.mouseWheelSpeed;\n\t\t\twheelDeltaY = e.wheelDeltaY / 120 * this.options.mouseWheelSpeed;\n\t\t} else if ( 'wheelDelta' in e ) {\n\t\t\twheelDeltaX = wheelDeltaY = e.wheelDelta / 120 * this.options.mouseWheelSpeed;\n\t\t} else if ( 'detail' in e ) {\n\t\t\twheelDeltaX = wheelDeltaY = -e.detail / 3 * this.options.mouseWheelSpeed;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\twheelDeltaX *= this.options.invertWheelDirection;\n\t\twheelDeltaY *= this.options.invertWheelDirection;\n\n\t\tif ( !this.hasVerticalScroll ) {\n\t\t\twheelDeltaX = wheelDeltaY;\n\t\t\twheelDeltaY = 0;\n\t\t}\n\n\t\tif ( this.options.snap ) {\n\t\t\tnewX = this.currentPage.pageX;\n\t\t\tnewY = this.currentPage.pageY;\n\n\t\t\tif ( wheelDeltaX > 0 ) {\n\t\t\t\tnewX--;\n\t\t\t} else if ( wheelDeltaX < 0 ) {\n\t\t\t\tnewX++;\n\t\t\t}\n\n\t\t\tif ( wheelDeltaY > 0 ) {\n\t\t\t\tnewY--;\n\t\t\t} else if ( wheelDeltaY < 0 ) {\n\t\t\t\tnewY++;\n\t\t\t}\n\n\t\t\tthis.goToPage(newX, newY);\n\n\t\t\treturn;\n\t\t}\n\n\t\tnewX = this.x + Math.round(this.hasHorizontalScroll ? wheelDeltaX : 0);\n\t\tnewY = this.y + Math.round(this.hasVerticalScroll ? wheelDeltaY : 0);\n\n\t\tthis.directionX = wheelDeltaX > 0 ? -1 : wheelDeltaX < 0 ? 1 : 0;\n\t\tthis.directionY = wheelDeltaY > 0 ? -1 : wheelDeltaY < 0 ? 1 : 0;\n\n\t\tif ( newX > 0 ) {\n\t\t\tnewX = 0;\n\t\t} else if ( newX < this.maxScrollX ) {\n\t\t\tnewX = this.maxScrollX;\n\t\t}\n\n\t\tif ( newY > 0 ) {\n\t\t\tnewY = 0;\n\t\t} else if ( newY < this.maxScrollY ) {\n\t\t\tnewY = this.maxScrollY;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY, 0);\n\n// INSERT POINT: _wheel\n\t},\n\n\t_initSnap: function () {\n\t\tthis.currentPage = {};\n\n\t\tif ( typeof this.options.snap == 'string' ) {\n\t\t\tthis.options.snap = this.scroller.querySelectorAll(this.options.snap);\n\t\t}\n\n\t\tthis.on('refresh', function () {\n\t\t\tvar i = 0, l,\n\t\t\t\tm = 0, n,\n\t\t\t\tcx, cy,\n\t\t\t\tx = 0, y,\n\t\t\t\tstepX = this.options.snapStepX || this.wrapperWidth,\n\t\t\t\tstepY = this.options.snapStepY || this.wrapperHeight,\n\t\t\t\tel;\n\n\t\t\tthis.pages = [];\n\n\t\t\tif ( !this.wrapperWidth || !this.wrapperHeight || !this.scrollerWidth || !this.scrollerHeight ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tif ( this.options.snap === true ) {\n\t\t\t\tcx = Math.round( stepX / 2 );\n\t\t\t\tcy = Math.round( stepY / 2 );\n\n\t\t\t\twhile ( x > -this.scrollerWidth ) {\n\t\t\t\t\tthis.pages[i] = [];\n\t\t\t\t\tl = 0;\n\t\t\t\t\ty = 0;\n\n\t\t\t\t\twhile ( y > -this.scrollerHeight ) {\n\t\t\t\t\t\tthis.pages[i][l] = {\n\t\t\t\t\t\t\tx: Math.max(x, this.maxScrollX),\n\t\t\t\t\t\t\ty: Math.max(y, this.maxScrollY),\n\t\t\t\t\t\t\twidth: stepX,\n\t\t\t\t\t\t\theight: stepY,\n\t\t\t\t\t\t\tcx: x - cx,\n\t\t\t\t\t\t\tcy: y - cy\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\ty -= stepY;\n\t\t\t\t\t\tl++;\n\t\t\t\t\t}\n\n\t\t\t\t\tx -= stepX;\n\t\t\t\t\ti++;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tel = this.options.snap;\n\t\t\t\tl = el.length;\n\t\t\t\tn = -1;\n\n\t\t\t\tfor ( ; i < l; i++ ) {\n\t\t\t\t\tif ( i === 0 || el[i].offsetLeft <= el[i-1].offsetLeft ) {\n\t\t\t\t\t\tm = 0;\n\t\t\t\t\t\tn++;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !this.pages[m] ) {\n\t\t\t\t\t\tthis.pages[m] = [];\n\t\t\t\t\t}\n\n\t\t\t\t\tx = Math.max(-el[i].offsetLeft, this.maxScrollX);\n\t\t\t\t\ty = Math.max(-el[i].offsetTop, this.maxScrollY);\n\t\t\t\t\tcx = x - Math.round(el[i].offsetWidth / 2);\n\t\t\t\t\tcy = y - Math.round(el[i].offsetHeight / 2);\n\n\t\t\t\t\tthis.pages[m][n] = {\n\t\t\t\t\t\tx: x,\n\t\t\t\t\t\ty: y,\n\t\t\t\t\t\twidth: el[i].offsetWidth,\n\t\t\t\t\t\theight: el[i].offsetHeight,\n\t\t\t\t\t\tcx: cx,\n\t\t\t\t\t\tcy: cy\n\t\t\t\t\t};\n\n\t\t\t\t\tif ( x > this.maxScrollX ) {\n\t\t\t\t\t\tm++;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.goToPage(this.currentPage.pageX || 0, this.currentPage.pageY || 0, 0);\n\n\t\t\t// Update snap threshold if needed\n\t\t\tif ( this.options.snapThreshold % 1 === 0 ) {\n\t\t\t\tthis.snapThresholdX = this.options.snapThreshold;\n\t\t\t\tthis.snapThresholdY = this.options.snapThreshold;\n\t\t\t} else {\n\t\t\t\tthis.snapThresholdX = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].width * this.options.snapThreshold);\n\t\t\t\tthis.snapThresholdY = Math.round(this.pages[this.currentPage.pageX][this.currentPage.pageY].height * this.options.snapThreshold);\n\t\t\t}\n\t\t});\n\n\t\tthis.on('flick', function () {\n\t\t\tvar time = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(this.x - this.startX), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(this.y - this.startY), 1000)\n\t\t\t\t\t), 300);\n\n\t\t\tthis.goToPage(\n\t\t\t\tthis.currentPage.pageX + this.directionX,\n\t\t\t\tthis.currentPage.pageY + this.directionY,\n\t\t\t\ttime\n\t\t\t);\n\t\t});\n\t},\n\n\t_nearestSnap: function (x, y) {\n\t\tif ( !this.pages.length ) {\n\t\t\treturn { x: 0, y: 0, pageX: 0, pageY: 0 };\n\t\t}\n\n\t\tvar i = 0,\n\t\t\tl = this.pages.length,\n\t\t\tm = 0;\n\n\t\t// Check if we exceeded the snap threshold\n\t\tif ( Math.abs(x - this.absStartX) < this.snapThresholdX &&\n\t\t\tMath.abs(y - this.absStartY) < this.snapThresholdY ) {\n\t\t\treturn this.currentPage;\n\t\t}\n\n\t\tif ( x > 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( x < this.maxScrollX ) {\n\t\t\tx = this.maxScrollX;\n\t\t}\n\n\t\tif ( y > 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( y < this.maxScrollY ) {\n\t\t\ty = this.maxScrollY;\n\t\t}\n\n\t\tfor ( ; i < l; i++ ) {\n\t\t\tif ( x >= this.pages[i][0].cx ) {\n\t\t\t\tx = this.pages[i][0].x;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tl = this.pages[i].length;\n\n\t\tfor ( ; m < l; m++ ) {\n\t\t\tif ( y >= this.pages[0][m].cy ) {\n\t\t\t\ty = this.pages[0][m].y;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( i == this.currentPage.pageX ) {\n\t\t\ti += this.directionX;\n\n\t\t\tif ( i < 0 ) {\n\t\t\t\ti = 0;\n\t\t\t} else if ( i >= this.pages.length ) {\n\t\t\t\ti = this.pages.length - 1;\n\t\t\t}\n\n\t\t\tx = this.pages[i][0].x;\n\t\t}\n\n\t\tif ( m == this.currentPage.pageY ) {\n\t\t\tm += this.directionY;\n\n\t\t\tif ( m < 0 ) {\n\t\t\t\tm = 0;\n\t\t\t} else if ( m >= this.pages[0].length ) {\n\t\t\t\tm = this.pages[0].length - 1;\n\t\t\t}\n\n\t\t\ty = this.pages[0][m].y;\n\t\t}\n\n\t\treturn {\n\t\t\tx: x,\n\t\t\ty: y,\n\t\t\tpageX: i,\n\t\t\tpageY: m\n\t\t};\n\t},\n\n\tgoToPage: function (x, y, time, easing) {\n\t\teasing = easing || this.options.bounceEasing;\n\n\t\tif ( x >= this.pages.length ) {\n\t\t\tx = this.pages.length - 1;\n\t\t} else if ( x < 0 ) {\n\t\t\tx = 0;\n\t\t}\n\n\t\tif ( y >= this.pages[x].length ) {\n\t\t\ty = this.pages[x].length - 1;\n\t\t} else if ( y < 0 ) {\n\t\t\ty = 0;\n\t\t}\n\n\t\tvar posX = this.pages[x][y].x,\n\t\t\tposY = this.pages[x][y].y;\n\n\t\ttime = time === undefined ? this.options.snapSpeed || Math.max(\n\t\t\tMath.max(\n\t\t\t\tMath.min(Math.abs(posX - this.x), 1000),\n\t\t\t\tMath.min(Math.abs(posY - this.y), 1000)\n\t\t\t), 300) : time;\n\n\t\tthis.currentPage = {\n\t\t\tx: posX,\n\t\t\ty: posY,\n\t\t\tpageX: x,\n\t\t\tpageY: y\n\t\t};\n\n\t\tthis.scrollTo(posX, posY, time, easing);\n\t},\n\n\tnext: function (time, easing) {\n\t\tvar x = this.currentPage.pageX,\n\t\t\ty = this.currentPage.pageY;\n\n\t\tx++;\n\n\t\tif ( x >= this.pages.length && this.hasVerticalScroll ) {\n\t\t\tx = 0;\n\t\t\ty++;\n\t\t}\n\n\t\tthis.goToPage(x, y, time, easing);\n\t},\n\n\tprev: function (time, easing) {\n\t\tvar x = this.currentPage.pageX,\n\t\t\ty = this.currentPage.pageY;\n\n\t\tx--;\n\n\t\tif ( x < 0 && this.hasVerticalScroll ) {\n\t\t\tx = 0;\n\t\t\ty--;\n\t\t}\n\n\t\tthis.goToPage(x, y, time, easing);\n\t},\n\n\t_initKeys: function (e) {\n\t\t// default key bindings\n\t\tvar keys = {\n\t\t\tpageUp: 33,\n\t\t\tpageDown: 34,\n\t\t\tend: 35,\n\t\t\thome: 36,\n\t\t\tleft: 37,\n\t\t\tup: 38,\n\t\t\tright: 39,\n\t\t\tdown: 40\n\t\t};\n\t\tvar i;\n\n\t\t// if you give me characters I give you keycode\n\t\tif ( typeof this.options.keyBindings == 'object' ) {\n\t\t\tfor ( i in this.options.keyBindings ) {\n\t\t\t\tif ( typeof this.options.keyBindings[i] == 'string' ) {\n\t\t\t\t\tthis.options.keyBindings[i] = this.options.keyBindings[i].toUpperCase().charCodeAt(0);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.options.keyBindings = {};\n\t\t}\n\n\t\tfor ( i in keys ) {\n\t\t\tthis.options.keyBindings[i] = this.options.keyBindings[i] || keys[i];\n\t\t}\n\n\t\tutils.addEvent(window, 'keydown', this);\n\n\t\tthis.on('destroy', function () {\n\t\t\tutils.removeEvent(window, 'keydown', this);\n\t\t});\n\t},\n\n\t_key: function (e) {\n\t\tif ( !this.enabled ) {\n\t\t\treturn;\n\t\t}\n\n\t\tvar snap = this.options.snap,\t// we are using this alot, better to cache it\n\t\t\tnewX = snap ? this.currentPage.pageX : this.x,\n\t\t\tnewY = snap ? this.currentPage.pageY : this.y,\n\t\t\tnow = utils.getTime(),\n\t\t\tprevTime = this.keyTime || 0,\n\t\t\tacceleration = 0.250,\n\t\t\tpos;\n\n\t\tif ( this.options.useTransition && this.isInTransition ) {\n\t\t\tpos = this.getComputedPosition();\n\n\t\t\tthis._translate(Math.round(pos.x), Math.round(pos.y));\n\t\t\tthis.isInTransition = false;\n\t\t}\n\n\t\tthis.keyAcceleration = now - prevTime < 200 ? Math.min(this.keyAcceleration + acceleration, 50) : 0;\n\n\t\tswitch ( e.keyCode ) {\n\t\t\tcase this.options.keyBindings.pageUp:\n\t\t\t\tif ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {\n\t\t\t\t\tnewX += snap ? 1 : this.wrapperWidth;\n\t\t\t\t} else {\n\t\t\t\t\tnewY += snap ? 1 : this.wrapperHeight;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.pageDown:\n\t\t\t\tif ( this.hasHorizontalScroll && !this.hasVerticalScroll ) {\n\t\t\t\t\tnewX -= snap ? 1 : this.wrapperWidth;\n\t\t\t\t} else {\n\t\t\t\t\tnewY -= snap ? 1 : this.wrapperHeight;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.end:\n\t\t\t\tnewX = snap ? this.pages.length-1 : this.maxScrollX;\n\t\t\t\tnewY = snap ? this.pages[0].length-1 : this.maxScrollY;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.home:\n\t\t\t\tnewX = 0;\n\t\t\t\tnewY = 0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.left:\n\t\t\t\tnewX += snap ? -1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.up:\n\t\t\t\tnewY += snap ? 1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.right:\n\t\t\t\tnewX -= snap ? -1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tcase this.options.keyBindings.down:\n\t\t\t\tnewY -= snap ? 1 : 5 + this.keyAcceleration>>0;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\tif ( snap ) {\n\t\t\tthis.goToPage(newX, newY);\n\t\t\treturn;\n\t\t}\n\n\t\tif ( newX > 0 ) {\n\t\t\tnewX = 0;\n\t\t\tthis.keyAcceleration = 0;\n\t\t} else if ( newX < this.maxScrollX ) {\n\t\t\tnewX = this.maxScrollX;\n\t\t\tthis.keyAcceleration = 0;\n\t\t}\n\n\t\tif ( newY > 0 ) {\n\t\t\tnewY = 0;\n\t\t\tthis.keyAcceleration = 0;\n\t\t} else if ( newY < this.maxScrollY ) {\n\t\t\tnewY = this.maxScrollY;\n\t\t\tthis.keyAcceleration = 0;\n\t\t}\n\n\t\tthis.scrollTo(newX, newY, 0);\n\n\t\tthis.keyTime = now;\n\t},\n\n\t_animate: function (destX, destY, duration, easingFn) {\n\t\tvar that = this,\n\t\t\tstartX = this.x,\n\t\t\tstartY = this.y,\n\t\t\tstartTime = utils.getTime(),\n\t\t\tdestTime = startTime + duration;\n\n\t\tfunction step () {\n\t\t\tvar now = utils.getTime(),\n\t\t\t\tnewX, newY,\n\t\t\t\teasing;\n\n\t\t\tif ( now >= destTime ) {\n\t\t\t\tthat.isAnimating = false;\n\t\t\t\tthat._translate(destX, destY);\n\n\t\t\t\tif ( !that.resetPosition(that.options.bounceTime) ) {\n\t\t\t\t\tthat._execEvent('scrollEnd');\n\t\t\t\t}\n\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tnow = ( now - startTime ) / duration;\n\t\t\teasing = easingFn(now);\n\t\t\tnewX = ( destX - startX ) * easing + startX;\n\t\t\tnewY = ( destY - startY ) * easing + startY;\n\t\t\tthat._translate(newX, newY);\n\n\t\t\tif ( that.isAnimating ) {\n\t\t\t\trAF(step);\n\t\t\t}\n\t\t}\n\n\t\tthis.isAnimating = true;\n\t\tstep();\n\t},\n\thandleEvent: function (e) {\n\t\tswitch ( e.type ) {\n\t\t\tcase 'touchstart':\n\t\t\tcase 'pointerdown':\n\t\t\tcase 'MSPointerDown':\n\t\t\tcase 'mousedown':\n\t\t\t\tthis._start(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchmove':\n\t\t\tcase 'pointermove':\n\t\t\tcase 'MSPointerMove':\n\t\t\tcase 'mousemove':\n\t\t\t\tthis._move(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchend':\n\t\t\tcase 'pointerup':\n\t\t\tcase 'MSPointerUp':\n\t\t\tcase 'mouseup':\n\t\t\tcase 'touchcancel':\n\t\t\tcase 'pointercancel':\n\t\t\tcase 'MSPointerCancel':\n\t\t\tcase 'mousecancel':\n\t\t\t\tthis._end(e);\n\t\t\t\tbreak;\n\t\t\tcase 'orientationchange':\n\t\t\tcase 'resize':\n\t\t\t\tthis._resize();\n\t\t\t\tbreak;\n\t\t\tcase 'transitionend':\n\t\t\tcase 'webkitTransitionEnd':\n\t\t\tcase 'oTransitionEnd':\n\t\t\tcase 'MSTransitionEnd':\n\t\t\t\tthis._transitionEnd(e);\n\t\t\t\tbreak;\n\t\t\tcase 'wheel':\n\t\t\tcase 'DOMMouseScroll':\n\t\t\tcase 'mousewheel':\n\t\t\t\tthis._wheel(e);\n\t\t\t\tbreak;\n\t\t\tcase 'keydown':\n\t\t\t\tthis._key(e);\n\t\t\t\tbreak;\n\t\t\tcase 'click':\n\t\t\t\tif ( this.enabled && !e._constructed ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\t}\n};\nfunction createDefaultScrollbar (direction, interactive, type) {\n\tvar scrollbar = document.createElement('div'),\n\t\tindicator = document.createElement('div');\n\n\tif ( type === true ) {\n\t\tscrollbar.style.cssText = 'position:absolute;z-index:9999';\n\t\tindicator.style.cssText = '-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px';\n\t}\n\n\tindicator.className = 'iScrollIndicator';\n\n\tif ( direction == 'h' ) {\n\t\tif ( type === true ) {\n\t\t\tscrollbar.style.cssText += ';height:7px;left:2px;right:2px;bottom:0';\n\t\t\tindicator.style.height = '100%';\n\t\t}\n\t\tscrollbar.className = 'iScrollHorizontalScrollbar';\n\t} else {\n\t\tif ( type === true ) {\n\t\t\tscrollbar.style.cssText += ';width:7px;bottom:2px;top:2px;right:1px';\n\t\t\tindicator.style.width = '100%';\n\t\t}\n\t\tscrollbar.className = 'iScrollVerticalScrollbar';\n\t}\n\n\tscrollbar.style.cssText += ';overflow:hidden';\n\n\tif ( !interactive ) {\n\t\tscrollbar.style.pointerEvents = 'none';\n\t}\n\n\tscrollbar.appendChild(indicator);\n\n\treturn scrollbar;\n}\n\nfunction Indicator (scroller, options) {\n\tthis.wrapper = typeof options.el == 'string' ? document.querySelector(options.el) : options.el;\n\tthis.wrapperStyle = this.wrapper.style;\n\tthis.indicator = this.wrapper.children[0];\n\tthis.indicatorStyle = this.indicator.style;\n\tthis.scroller = scroller;\n\n\tthis.options = {\n\t\tlistenX: true,\n\t\tlistenY: true,\n\t\tinteractive: false,\n\t\tresize: true,\n\t\tdefaultScrollbars: false,\n\t\tshrink: false,\n\t\tfade: false,\n\t\tspeedRatioX: 0,\n\t\tspeedRatioY: 0\n\t};\n\n\tfor ( var i in options ) {\n\t\tthis.options[i] = options[i];\n\t}\n\n\tthis.sizeRatioX = 1;\n\tthis.sizeRatioY = 1;\n\tthis.maxPosX = 0;\n\tthis.maxPosY = 0;\n\n\tif ( this.options.interactive ) {\n\t\tif ( !this.options.disableTouch ) {\n\t\t\tutils.addEvent(this.indicator, 'touchstart', this);\n\t\t\tutils.addEvent(window, 'touchend', this);\n\t\t}\n\t\tif ( !this.options.disablePointer ) {\n\t\t\tutils.addEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\tutils.addEvent(window, utils.prefixPointerEvent('pointerup'), this);\n\t\t}\n\t\tif ( !this.options.disableMouse ) {\n\t\t\tutils.addEvent(this.indicator, 'mousedown', this);\n\t\t\tutils.addEvent(window, 'mouseup', this);\n\t\t}\n\t}\n\n\tif ( this.options.fade ) {\n\t\tthis.wrapperStyle[utils.style.transform] = this.scroller.translateZ;\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tthis.wrapperStyle[durationProp] = utils.isBadAndroid ? '0.0001ms' : '0ms';\n\t\t// remove 0.0001ms\n\t\tvar self = this;\n\t\tif(utils.isBadAndroid) {\n\t\t\trAF(function() {\n\t\t\t\tif(self.wrapperStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.wrapperStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\tthis.wrapperStyle.opacity = '0';\n\t}\n}\n\nIndicator.prototype = {\n\thandleEvent: function (e) {\n\t\tswitch ( e.type ) {\n\t\t\tcase 'touchstart':\n\t\t\tcase 'pointerdown':\n\t\t\tcase 'MSPointerDown':\n\t\t\tcase 'mousedown':\n\t\t\t\tthis._start(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchmove':\n\t\t\tcase 'pointermove':\n\t\t\tcase 'MSPointerMove':\n\t\t\tcase 'mousemove':\n\t\t\t\tthis._move(e);\n\t\t\t\tbreak;\n\t\t\tcase 'touchend':\n\t\t\tcase 'pointerup':\n\t\t\tcase 'MSPointerUp':\n\t\t\tcase 'mouseup':\n\t\t\tcase 'touchcancel':\n\t\t\tcase 'pointercancel':\n\t\t\tcase 'MSPointerCancel':\n\t\t\tcase 'mousecancel':\n\t\t\t\tthis._end(e);\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\tdestroy: function () {\n\t\tif ( this.options.fadeScrollbars ) {\n\t\t\tclearTimeout(this.fadeTimeout);\n\t\t\tthis.fadeTimeout = null;\n\t\t}\n\t\tif ( this.options.interactive ) {\n\t\t\tutils.removeEvent(this.indicator, 'touchstart', this);\n\t\t\tutils.removeEvent(this.indicator, utils.prefixPointerEvent('pointerdown'), this);\n\t\t\tutils.removeEvent(this.indicator, 'mousedown', this);\n\n\t\t\tutils.removeEvent(window, 'touchmove', this);\n\t\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\t\tutils.removeEvent(window, 'mousemove', this);\n\n\t\t\tutils.removeEvent(window, 'touchend', this);\n\t\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointerup'), this);\n\t\t\tutils.removeEvent(window, 'mouseup', this);\n\t\t}\n\n\t\tif ( this.options.defaultScrollbars ) {\n\t\t\tthis.wrapper.parentNode.removeChild(this.wrapper);\n\t\t}\n\t},\n\n\t_start: function (e) {\n\t\tvar point = e.touches ? e.touches[0] : e;\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tthis.transitionTime();\n\n\t\tthis.initiated = true;\n\t\tthis.moved = false;\n\t\tthis.lastPointX\t= point.pageX;\n\t\tthis.lastPointY\t= point.pageY;\n\n\t\tthis.startTime\t= utils.getTime();\n\n\t\tif ( !this.options.disableTouch ) {\n\t\t\tutils.addEvent(window, 'touchmove', this);\n\t\t}\n\t\tif ( !this.options.disablePointer ) {\n\t\t\tutils.addEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\t}\n\t\tif ( !this.options.disableMouse ) {\n\t\t\tutils.addEvent(window, 'mousemove', this);\n\t\t}\n\n\t\tthis.scroller._execEvent('beforeScrollStart');\n\t},\n\n\t_move: function (e) {\n\t\tvar point = e.touches ? e.touches[0] : e,\n\t\t\tdeltaX, deltaY,\n\t\t\tnewX, newY,\n\t\t\ttimestamp = utils.getTime();\n\n\t\tif ( !this.moved ) {\n\t\t\tthis.scroller._execEvent('scrollStart');\n\t\t}\n\n\t\tthis.moved = true;\n\n\t\tdeltaX = point.pageX - this.lastPointX;\n\t\tthis.lastPointX = point.pageX;\n\n\t\tdeltaY = point.pageY - this.lastPointY;\n\t\tthis.lastPointY = point.pageY;\n\n\t\tnewX = this.x + deltaX;\n\t\tnewY = this.y + deltaY;\n\n\t\tthis._pos(newX, newY);\n\n// INSERT POINT: indicator._move\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t},\n\n\t_end: function (e) {\n\t\tif ( !this.initiated ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.initiated = false;\n\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\n\t\tutils.removeEvent(window, 'touchmove', this);\n\t\tutils.removeEvent(window, utils.prefixPointerEvent('pointermove'), this);\n\t\tutils.removeEvent(window, 'mousemove', this);\n\n\t\tif ( this.scroller.options.snap ) {\n\t\t\tvar snap = this.scroller._nearestSnap(this.scroller.x, this.scroller.y);\n\n\t\t\tvar time = this.options.snapSpeed || Math.max(\n\t\t\t\t\tMath.max(\n\t\t\t\t\t\tMath.min(Math.abs(this.scroller.x - snap.x), 1000),\n\t\t\t\t\t\tMath.min(Math.abs(this.scroller.y - snap.y), 1000)\n\t\t\t\t\t), 300);\n\n\t\t\tif ( this.scroller.x != snap.x || this.scroller.y != snap.y ) {\n\t\t\t\tthis.scroller.directionX = 0;\n\t\t\t\tthis.scroller.directionY = 0;\n\t\t\t\tthis.scroller.currentPage = snap;\n\t\t\t\tthis.scroller.scrollTo(snap.x, snap.y, time, this.scroller.options.bounceEasing);\n\t\t\t}\n\t\t}\n\n\t\tif ( this.moved ) {\n\t\t\tthis.scroller._execEvent('scrollEnd');\n\t\t}\n\t},\n\n\ttransitionTime: function (time) {\n\t\ttime = time || 0;\n\t\tvar durationProp = utils.style.transitionDuration;\n\t\tthis.indicatorStyle[durationProp] = time + 'ms';\n\n\t\tif ( !time && utils.isBadAndroid ) {\n\t\t\tthis.indicatorStyle[durationProp] = '0.0001ms';\n\t\t\t// remove 0.0001ms\n\t\t\tvar self = this;\n\t\t\trAF(function() {\n\t\t\t\tif(self.indicatorStyle[durationProp] === '0.0001ms') {\n\t\t\t\t\tself.indicatorStyle[durationProp] = '0s';\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t},\n\n\ttransitionTimingFunction: function (easing) {\n\t\tthis.indicatorStyle[utils.style.transitionTimingFunction] = easing;\n\t},\n\n\trefresh: function () {\n\t\tthis.transitionTime();\n\n\t\tif ( this.options.listenX && !this.options.listenY ) {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasHorizontalScroll ? 'block' : 'none';\n\t\t} else if ( this.options.listenY && !this.options.listenX ) {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasVerticalScroll ? 'block' : 'none';\n\t\t} else {\n\t\t\tthis.indicatorStyle.display = this.scroller.hasHorizontalScroll || this.scroller.hasVerticalScroll ? 'block' : 'none';\n\t\t}\n\n\t\tif ( this.scroller.hasHorizontalScroll && this.scroller.hasVerticalScroll ) {\n\t\t\tutils.addClass(this.wrapper, 'iScrollBothScrollbars');\n\t\t\tutils.removeClass(this.wrapper, 'iScrollLoneScrollbar');\n\n\t\t\tif ( this.options.defaultScrollbars && this.options.customStyle ) {\n\t\t\t\tif ( this.options.listenX ) {\n\t\t\t\t\tthis.wrapper.style.right = '8px';\n\t\t\t\t} else {\n\t\t\t\t\tthis.wrapper.style.bottom = '8px';\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tutils.removeClass(this.wrapper, 'iScrollBothScrollbars');\n\t\t\tutils.addClass(this.wrapper, 'iScrollLoneScrollbar');\n\n\t\t\tif ( this.options.defaultScrollbars && this.options.customStyle ) {\n\t\t\t\tif ( this.options.listenX ) {\n\t\t\t\t\tthis.wrapper.style.right = '2px';\n\t\t\t\t} else {\n\t\t\t\t\tthis.wrapper.style.bottom = '2px';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tvar r = this.wrapper.offsetHeight;\t// force refresh\n\n\t\tif ( this.options.listenX ) {\n\t\t\tthis.wrapperWidth = this.wrapper.clientWidth;\n\t\t\tif ( this.options.resize ) {\n\t\t\t\tthis.indicatorWidth = Math.max(Math.round(this.wrapperWidth * this.wrapperWidth / (this.scroller.scrollerWidth || this.wrapperWidth || 1)), 8);\n\t\t\t\tthis.indicatorStyle.width = this.indicatorWidth + 'px';\n\t\t\t} else {\n\t\t\t\tthis.indicatorWidth = this.indicator.clientWidth;\n\t\t\t}\n\n\t\t\tthis.maxPosX = this.wrapperWidth - this.indicatorWidth;\n\n\t\t\tif ( this.options.shrink == 'clip' ) {\n\t\t\t\tthis.minBoundaryX = -this.indicatorWidth + 8;\n\t\t\t\tthis.maxBoundaryX = this.wrapperWidth - 8;\n\t\t\t} else {\n\t\t\t\tthis.minBoundaryX = 0;\n\t\t\t\tthis.maxBoundaryX = this.maxPosX;\n\t\t\t}\n\n\t\t\tthis.sizeRatioX = this.options.speedRatioX || (this.scroller.maxScrollX && (this.maxPosX / this.scroller.maxScrollX));\n\t\t}\n\n\t\tif ( this.options.listenY ) {\n\t\t\tthis.wrapperHeight = this.wrapper.clientHeight;\n\t\t\tif ( this.options.resize ) {\n\t\t\t\tthis.indicatorHeight = Math.max(Math.round(this.wrapperHeight * this.wrapperHeight / (this.scroller.scrollerHeight || this.wrapperHeight || 1)), 8);\n\t\t\t\tthis.indicatorStyle.height = this.indicatorHeight + 'px';\n\t\t\t} else {\n\t\t\t\tthis.indicatorHeight = this.indicator.clientHeight;\n\t\t\t}\n\n\t\t\tthis.maxPosY = this.wrapperHeight - this.indicatorHeight;\n\n\t\t\tif ( this.options.shrink == 'clip' ) {\n\t\t\t\tthis.minBoundaryY = -this.indicatorHeight + 8;\n\t\t\t\tthis.maxBoundaryY = this.wrapperHeight - 8;\n\t\t\t} else {\n\t\t\t\tthis.minBoundaryY = 0;\n\t\t\t\tthis.maxBoundaryY = this.maxPosY;\n\t\t\t}\n\n\t\t\tthis.maxPosY = this.wrapperHeight - this.indicatorHeight;\n\t\t\tthis.sizeRatioY = this.options.speedRatioY || (this.scroller.maxScrollY && (this.maxPosY / this.scroller.maxScrollY));\n\t\t}\n\n\t\tthis.updatePosition();\n\t},\n\n\tupdatePosition: function () {\n\t\tvar x = this.options.listenX && Math.round(this.sizeRatioX * this.scroller.x) || 0,\n\t\t\ty = this.options.listenY && Math.round(this.sizeRatioY * this.scroller.y) || 0;\n\n\t\tif ( !this.options.ignoreBoundaries ) {\n\t\t\tif ( x < this.minBoundaryX ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.width = Math.max(this.indicatorWidth + x, 8);\n\t\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t\t}\n\t\t\t\tx = this.minBoundaryX;\n\t\t\t} else if ( x > this.maxBoundaryX ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.width = Math.max(this.indicatorWidth - (x - this.maxPosX), 8);\n\t\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t\t\tx = this.maxPosX + this.indicatorWidth - this.width;\n\t\t\t\t} else {\n\t\t\t\t\tx = this.maxBoundaryX;\n\t\t\t\t}\n\t\t\t} else if ( this.options.shrink == 'scale' && this.width != this.indicatorWidth ) {\n\t\t\t\tthis.width = this.indicatorWidth;\n\t\t\t\tthis.indicatorStyle.width = this.width + 'px';\n\t\t\t}\n\n\t\t\tif ( y < this.minBoundaryY ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.height = Math.max(this.indicatorHeight + y * 3, 8);\n\t\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t\t}\n\t\t\t\ty = this.minBoundaryY;\n\t\t\t} else if ( y > this.maxBoundaryY ) {\n\t\t\t\tif ( this.options.shrink == 'scale' ) {\n\t\t\t\t\tthis.height = Math.max(this.indicatorHeight - (y - this.maxPosY) * 3, 8);\n\t\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t\t\ty = this.maxPosY + this.indicatorHeight - this.height;\n\t\t\t\t} else {\n\t\t\t\t\ty = this.maxBoundaryY;\n\t\t\t\t}\n\t\t\t} else if ( this.options.shrink == 'scale' && this.height != this.indicatorHeight ) {\n\t\t\t\tthis.height = this.indicatorHeight;\n\t\t\t\tthis.indicatorStyle.height = this.height + 'px';\n\t\t\t}\n\t\t}\n\n\t\tthis.x = x;\n\t\tthis.y = y;\n\n\t\tif ( this.scroller.options.useTransform ) {\n\t\t\tthis.indicatorStyle[utils.style.transform] = 'translate(' + x + 'px,' + y + 'px)' + this.scroller.translateZ;\n\t\t} else {\n\t\t\tthis.indicatorStyle.left = x + 'px';\n\t\t\tthis.indicatorStyle.top = y + 'px';\n\t\t}\n\t},\n\n\t_pos: function (x, y) {\n\t\tif ( x < 0 ) {\n\t\t\tx = 0;\n\t\t} else if ( x > this.maxPosX ) {\n\t\t\tx = this.maxPosX;\n\t\t}\n\n\t\tif ( y < 0 ) {\n\t\t\ty = 0;\n\t\t} else if ( y > this.maxPosY ) {\n\t\t\ty = this.maxPosY;\n\t\t}\n\n\t\tx = this.options.listenX ? Math.round(x / this.sizeRatioX) : this.scroller.x;\n\t\ty = this.options.listenY ? Math.round(y / this.sizeRatioY) : this.scroller.y;\n\n\t\tthis.scroller.scrollTo(x, y);\n\t},\n\n\tfade: function (val, hold) {\n\t\tif ( hold && !this.visible ) {\n\t\t\treturn;\n\t\t}\n\n\t\tclearTimeout(this.fadeTimeout);\n\t\tthis.fadeTimeout = null;\n\n\t\tvar time = val ? 250 : 500,\n\t\t\tdelay = val ? 0 : 300;\n\n\t\tval = val ? '1' : '0';\n\n\t\tthis.wrapperStyle[utils.style.transitionDuration] = time + 'ms';\n\n\t\tthis.fadeTimeout = setTimeout((function (val) {\n\t\t\tthis.wrapperStyle.opacity = val;\n\t\t\tthis.visible = +val;\n\t\t}).bind(this, val), delay);\n\t}\n};\n\nIScroll.utils = utils;\n\nif ( typeof module != 'undefined' && module.exports ) {\n\tmodule.exports = IScroll;\n} else if ( true ) {\n !(__WEBPACK_AMD_DEFINE_RESULT__ = (function () { return IScroll; }).call(exports, __webpack_require__, exports, module),\n\t\t\t\t__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));\n} else {\n\twindow.IScroll = IScroll;\n}\n\n})(window, document, Math);\n\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9ub2RlX21vZHVsZXMvaXNjcm9sbC9idWlsZC9pc2Nyb2xsLmpzPzZjNzciXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxzQkFBc0Isd0NBQXdDOztBQUU5RDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxTQUFTLE9BQU87QUFDaEI7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBLCtDQUErQyw2QkFBNkI7O0FBRTVFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUYsd0JBQXdCO0FBQ3hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUEsNEJBQTRCO0FBQzVCO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUYsdUJBQXVCO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQkFBb0IsVUFBVTtBQUM5QixtQkFBbUIsVUFBVTs7QUFFN0I7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsQ0FBQztBQUNEO0FBQ0E7QUFDQTtBQUNBLDBDQUEwQzs7QUFFMUM7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLDRCQUE0Qiw4Q0FBOEM7O0FBRTFFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsc0NBQXNDO0FBQ3RDO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsK0JBQStCO0FBQy9CLElBQUk7QUFDSiwrQkFBK0I7QUFDL0IsSUFBSTtBQUNKLCtCQUErQjtBQUMvQjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsNEJBQTRCOztBQUU1QjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLG9MQUFvTDtBQUNwTCxtTEFBbUw7QUFDbkw7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQSxxQ0FBcUM7O0FBRXJDO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBOztBQUVBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUEsU0FBUyxPQUFPO0FBQ2hCO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKOzs7QUFHQTtBQUNBLHdDQUF3QyxLQUFLO0FBQzdDO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBOzs7QUFHQTtBQUNBLHdDQUF3QyxLQUFLO0FBQzdDO0FBQ0E7QUFDQTs7O0FBR0E7O0FBRUEsRUFBRTs7QUFFRjtBQUNBOztBQUVBOztBQUVBOztBQUVBOztBQUVBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7OztBQUdBO0FBQ0EsdUNBQXVDLEtBQUs7QUFDNUM7QUFDQTtBQUNBOzs7QUFHQTs7QUFFQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQSxVQUFVO0FBQ1YsRUFBRTtBQUNGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxrQ0FBa0MsS0FBSztBQUN2QztBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLHlDQUF5QyxLQUFLO0FBQzlDO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7O0FBRUo7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUk7QUFDSjs7O0FBR0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0EsSUFBSTs7QUFFSjtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSCxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHOztBQUVIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBLFdBQVcsT0FBTztBQUNsQjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBLEdBQUc7O0FBRUg7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0gsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsV0FBVztBQUNYOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUEsU0FBUyxPQUFPO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUEsU0FBUyxPQUFPO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNILEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEVBQUU7QUFDRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSwrQ0FBK0M7QUFDL0MsMkRBQTJELDJCQUEyQixzQkFBc0Isa0JBQWtCLDJCQUEyQix1Q0FBdUM7QUFDaE07O0FBRUE7O0FBRUE7QUFDQTtBQUNBLGdDQUFnQyxXQUFXLFNBQVMsVUFBVTtBQUM5RDtBQUNBO0FBQ0E7QUFDQSxFQUFFO0FBQ0Y7QUFDQSxnQ0FBZ0MsVUFBVSxXQUFXLFFBQVE7QUFDN0Q7QUFDQTtBQUNBO0FBQ0E7O0FBRUEsOEJBQThCOztBQUU5QjtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBOztBQUVBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTs7QUFFQSxvQ0FBb0M7O0FBRXBDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0EsRUFBRTs7QUFFRjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsSUFBSTtBQUNKO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLEVBQUU7O0FBRUY7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7O0FBRUE7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSxFQUFFOztBQUVGO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0EsQ0FBQztBQUNELHdEQUE2QixnQkFBZ0IsRUFBRTtBQUFBO0FBQy9DLENBQUM7QUFDRDtBQUNBOztBQUVBLENBQUMiLCJmaWxlIjoiMi5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qISBpU2Nyb2xsIHY1LjIuMCB+IChjKSAyMDA4LTIwMTYgTWF0dGVvIFNwaW5lbGxpIH4gaHR0cDovL2N1YmlxLm9yZy9saWNlbnNlICovXG4oZnVuY3Rpb24gKHdpbmRvdywgZG9jdW1lbnQsIE1hdGgpIHtcbnZhciByQUYgPSB3aW5kb3cucmVxdWVzdEFuaW1hdGlvbkZyYW1lXHR8fFxuXHR3aW5kb3cud2Via2l0UmVxdWVzdEFuaW1hdGlvbkZyYW1lXHR8fFxuXHR3aW5kb3cubW96UmVxdWVzdEFuaW1hdGlvbkZyYW1lXHRcdHx8XG5cdHdpbmRvdy5vUmVxdWVzdEFuaW1hdGlvbkZyYW1lXHRcdHx8XG5cdHdpbmRvdy5tc1JlcXVlc3RBbmltYXRpb25GcmFtZVx0XHR8fFxuXHRmdW5jdGlvbiAoY2FsbGJhY2spIHsgd2luZG93LnNldFRpbWVvdXQoY2FsbGJhY2ssIDEwMDAgLyA2MCk7IH07XG5cbnZhciB1dGlscyA9IChmdW5jdGlvbiAoKSB7XG5cdHZhciBtZSA9IHt9O1xuXG5cdHZhciBfZWxlbWVudFN0eWxlID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnZGl2Jykuc3R5bGU7XG5cdHZhciBfdmVuZG9yID0gKGZ1bmN0aW9uICgpIHtcblx0XHR2YXIgdmVuZG9ycyA9IFsndCcsICd3ZWJraXRUJywgJ01velQnLCAnbXNUJywgJ09UJ10sXG5cdFx0XHR0cmFuc2Zvcm0sXG5cdFx0XHRpID0gMCxcblx0XHRcdGwgPSB2ZW5kb3JzLmxlbmd0aDtcblxuXHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdHRyYW5zZm9ybSA9IHZlbmRvcnNbaV0gKyAncmFuc2Zvcm0nO1xuXHRcdFx0aWYgKCB0cmFuc2Zvcm0gaW4gX2VsZW1lbnRTdHlsZSApIHJldHVybiB2ZW5kb3JzW2ldLnN1YnN0cigwLCB2ZW5kb3JzW2ldLmxlbmd0aC0xKTtcblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH0pKCk7XG5cblx0ZnVuY3Rpb24gX3ByZWZpeFN0eWxlIChzdHlsZSkge1xuXHRcdGlmICggX3ZlbmRvciA9PT0gZmFsc2UgKSByZXR1cm4gZmFsc2U7XG5cdFx0aWYgKCBfdmVuZG9yID09PSAnJyApIHJldHVybiBzdHlsZTtcblx0XHRyZXR1cm4gX3ZlbmRvciArIHN0eWxlLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpICsgc3R5bGUuc3Vic3RyKDEpO1xuXHR9XG5cblx0bWUuZ2V0VGltZSA9IERhdGUubm93IHx8IGZ1bmN0aW9uIGdldFRpbWUgKCkgeyByZXR1cm4gbmV3IERhdGUoKS5nZXRUaW1lKCk7IH07XG5cblx0bWUuZXh0ZW5kID0gZnVuY3Rpb24gKHRhcmdldCwgb2JqKSB7XG5cdFx0Zm9yICggdmFyIGkgaW4gb2JqICkge1xuXHRcdFx0dGFyZ2V0W2ldID0gb2JqW2ldO1xuXHRcdH1cblx0fTtcblxuXHRtZS5hZGRFdmVudCA9IGZ1bmN0aW9uIChlbCwgdHlwZSwgZm4sIGNhcHR1cmUpIHtcblx0XHRlbC5hZGRFdmVudExpc3RlbmVyKHR5cGUsIGZuLCAhIWNhcHR1cmUpO1xuXHR9O1xuXG5cdG1lLnJlbW92ZUV2ZW50ID0gZnVuY3Rpb24gKGVsLCB0eXBlLCBmbiwgY2FwdHVyZSkge1xuXHRcdGVsLnJlbW92ZUV2ZW50TGlzdGVuZXIodHlwZSwgZm4sICEhY2FwdHVyZSk7XG5cdH07XG5cblx0bWUucHJlZml4UG9pbnRlckV2ZW50ID0gZnVuY3Rpb24gKHBvaW50ZXJFdmVudCkge1xuXHRcdHJldHVybiB3aW5kb3cuTVNQb2ludGVyRXZlbnQgP1xuXHRcdFx0J01TUG9pbnRlcicgKyBwb2ludGVyRXZlbnQuY2hhckF0KDcpLnRvVXBwZXJDYXNlKCkgKyBwb2ludGVyRXZlbnQuc3Vic3RyKDgpOlxuXHRcdFx0cG9pbnRlckV2ZW50O1xuXHR9O1xuXG5cdG1lLm1vbWVudHVtID0gZnVuY3Rpb24gKGN1cnJlbnQsIHN0YXJ0LCB0aW1lLCBsb3dlck1hcmdpbiwgd3JhcHBlclNpemUsIGRlY2VsZXJhdGlvbikge1xuXHRcdHZhciBkaXN0YW5jZSA9IGN1cnJlbnQgLSBzdGFydCxcblx0XHRcdHNwZWVkID0gTWF0aC5hYnMoZGlzdGFuY2UpIC8gdGltZSxcblx0XHRcdGRlc3RpbmF0aW9uLFxuXHRcdFx0ZHVyYXRpb247XG5cblx0XHRkZWNlbGVyYXRpb24gPSBkZWNlbGVyYXRpb24gPT09IHVuZGVmaW5lZCA/IDAuMDAwNiA6IGRlY2VsZXJhdGlvbjtcblxuXHRcdGRlc3RpbmF0aW9uID0gY3VycmVudCArICggc3BlZWQgKiBzcGVlZCApIC8gKCAyICogZGVjZWxlcmF0aW9uICkgKiAoIGRpc3RhbmNlIDwgMCA/IC0xIDogMSApO1xuXHRcdGR1cmF0aW9uID0gc3BlZWQgLyBkZWNlbGVyYXRpb247XG5cblx0XHRpZiAoIGRlc3RpbmF0aW9uIDwgbG93ZXJNYXJnaW4gKSB7XG5cdFx0XHRkZXN0aW5hdGlvbiA9IHdyYXBwZXJTaXplID8gbG93ZXJNYXJnaW4gLSAoIHdyYXBwZXJTaXplIC8gMi41ICogKCBzcGVlZCAvIDggKSApIDogbG93ZXJNYXJnaW47XG5cdFx0XHRkaXN0YW5jZSA9IE1hdGguYWJzKGRlc3RpbmF0aW9uIC0gY3VycmVudCk7XG5cdFx0XHRkdXJhdGlvbiA9IGRpc3RhbmNlIC8gc3BlZWQ7XG5cdFx0fSBlbHNlIGlmICggZGVzdGluYXRpb24gPiAwICkge1xuXHRcdFx0ZGVzdGluYXRpb24gPSB3cmFwcGVyU2l6ZSA/IHdyYXBwZXJTaXplIC8gMi41ICogKCBzcGVlZCAvIDggKSA6IDA7XG5cdFx0XHRkaXN0YW5jZSA9IE1hdGguYWJzKGN1cnJlbnQpICsgZGVzdGluYXRpb247XG5cdFx0XHRkdXJhdGlvbiA9IGRpc3RhbmNlIC8gc3BlZWQ7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHtcblx0XHRcdGRlc3RpbmF0aW9uOiBNYXRoLnJvdW5kKGRlc3RpbmF0aW9uKSxcblx0XHRcdGR1cmF0aW9uOiBkdXJhdGlvblxuXHRcdH07XG5cdH07XG5cblx0dmFyIF90cmFuc2Zvcm0gPSBfcHJlZml4U3R5bGUoJ3RyYW5zZm9ybScpO1xuXG5cdG1lLmV4dGVuZChtZSwge1xuXHRcdGhhc1RyYW5zZm9ybTogX3RyYW5zZm9ybSAhPT0gZmFsc2UsXG5cdFx0aGFzUGVyc3BlY3RpdmU6IF9wcmVmaXhTdHlsZSgncGVyc3BlY3RpdmUnKSBpbiBfZWxlbWVudFN0eWxlLFxuXHRcdGhhc1RvdWNoOiAnb250b3VjaHN0YXJ0JyBpbiB3aW5kb3csXG5cdFx0aGFzUG9pbnRlcjogISEod2luZG93LlBvaW50ZXJFdmVudCB8fCB3aW5kb3cuTVNQb2ludGVyRXZlbnQpLCAvLyBJRTEwIGlzIHByZWZpeGVkXG5cdFx0aGFzVHJhbnNpdGlvbjogX3ByZWZpeFN0eWxlKCd0cmFuc2l0aW9uJykgaW4gX2VsZW1lbnRTdHlsZVxuXHR9KTtcblxuXHQvKlxuXHRUaGlzIHNob3VsZCBmaW5kIGFsbCBBbmRyb2lkIGJyb3dzZXJzIGxvd2VyIHRoYW4gYnVpbGQgNTM1LjE5IChib3RoIHN0b2NrIGJyb3dzZXIgYW5kIHdlYnZpZXcpXG5cdC0gZ2FsYXh5IFMyIGlzIG9rXG4gICAgLSAyLjMuNiA6IGBBcHBsZVdlYktpdC81MzMuMSAoS0hUTUwsIGxpa2UgR2Vja28pIFZlcnNpb24vNC4wIE1vYmlsZSBTYWZhcmkvNTMzLjFgXG4gICAgLSA0LjAuNCA6IGBBcHBsZVdlYktpdC81MzQuMzAgKEtIVE1MLCBsaWtlIEdlY2tvKSBWZXJzaW9uLzQuMCBNb2JpbGUgU2FmYXJpLzUzNC4zMGBcbiAgIC0gZ2FsYXh5IFMzIGlzIGJhZEFuZHJvaWQgKHN0b2NrIGJyb3dlciwgd2VidmlldylcbiAgICAgYEFwcGxlV2ViS2l0LzUzNC4zMCAoS0hUTUwsIGxpa2UgR2Vja28pIFZlcnNpb24vNC4wIE1vYmlsZSBTYWZhcmkvNTM0LjMwYFxuICAgLSBnYWxheHkgUzQgaXMgYmFkQW5kcm9pZCAoc3RvY2sgYnJvd2VyLCB3ZWJ2aWV3KVxuICAgICBgQXBwbGVXZWJLaXQvNTM0LjMwIChLSFRNTCwgbGlrZSBHZWNrbykgVmVyc2lvbi80LjAgTW9iaWxlIFNhZmFyaS81MzQuMzBgXG4gICAtIGdhbGF4eSBTNSBpcyBPS1xuICAgICBgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgVmVyc2lvbi80LjAgTW9iaWxlIFNhZmFyaS81MzcuMzYgKENocm9tZS8pYFxuICAgLSBnYWxheHkgUzYgaXMgT0tcbiAgICAgYEFwcGxlV2ViS2l0LzUzNy4zNiAoS0hUTUwsIGxpa2UgR2Vja28pIFZlcnNpb24vNC4wIE1vYmlsZSBTYWZhcmkvNTM3LjM2IChDaHJvbWUvKWBcbiAgKi9cblx0bWUuaXNCYWRBbmRyb2lkID0gKGZ1bmN0aW9uKCkge1xuXHRcdHZhciBhcHBWZXJzaW9uID0gd2luZG93Lm5hdmlnYXRvci5hcHBWZXJzaW9uO1xuXHRcdC8vIEFuZHJvaWQgYnJvd3NlciBpcyBub3QgYSBjaHJvbWUgYnJvd3Nlci5cblx0XHRpZiAoL0FuZHJvaWQvLnRlc3QoYXBwVmVyc2lvbikgJiYgISgvQ2hyb21lXFwvXFxkLy50ZXN0KGFwcFZlcnNpb24pKSkge1xuXHRcdFx0dmFyIHNhZmFyaVZlcnNpb24gPSBhcHBWZXJzaW9uLm1hdGNoKC9TYWZhcmlcXC8oXFxkKy5cXGQpLyk7XG5cdFx0XHRpZihzYWZhcmlWZXJzaW9uICYmIHR5cGVvZiBzYWZhcmlWZXJzaW9uID09PSBcIm9iamVjdFwiICYmIHNhZmFyaVZlcnNpb24ubGVuZ3RoID49IDIpIHtcblx0XHRcdFx0cmV0dXJuIHBhcnNlRmxvYXQoc2FmYXJpVmVyc2lvblsxXSkgPCA1MzUuMTk7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0cmV0dXJuIGZhbHNlO1xuXHRcdH1cblx0fSkoKTtcblxuXHRtZS5leHRlbmQobWUuc3R5bGUgPSB7fSwge1xuXHRcdHRyYW5zZm9ybTogX3RyYW5zZm9ybSxcblx0XHR0cmFuc2l0aW9uVGltaW5nRnVuY3Rpb246IF9wcmVmaXhTdHlsZSgndHJhbnNpdGlvblRpbWluZ0Z1bmN0aW9uJyksXG5cdFx0dHJhbnNpdGlvbkR1cmF0aW9uOiBfcHJlZml4U3R5bGUoJ3RyYW5zaXRpb25EdXJhdGlvbicpLFxuXHRcdHRyYW5zaXRpb25EZWxheTogX3ByZWZpeFN0eWxlKCd0cmFuc2l0aW9uRGVsYXknKSxcblx0XHR0cmFuc2Zvcm1PcmlnaW46IF9wcmVmaXhTdHlsZSgndHJhbnNmb3JtT3JpZ2luJylcblx0fSk7XG5cblx0bWUuaGFzQ2xhc3MgPSBmdW5jdGlvbiAoZSwgYykge1xuXHRcdHZhciByZSA9IG5ldyBSZWdFeHAoXCIoXnxcXFxccylcIiArIGMgKyBcIihcXFxcc3wkKVwiKTtcblx0XHRyZXR1cm4gcmUudGVzdChlLmNsYXNzTmFtZSk7XG5cdH07XG5cblx0bWUuYWRkQ2xhc3MgPSBmdW5jdGlvbiAoZSwgYykge1xuXHRcdGlmICggbWUuaGFzQ2xhc3MoZSwgYykgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIG5ld2NsYXNzID0gZS5jbGFzc05hbWUuc3BsaXQoJyAnKTtcblx0XHRuZXdjbGFzcy5wdXNoKGMpO1xuXHRcdGUuY2xhc3NOYW1lID0gbmV3Y2xhc3Muam9pbignICcpO1xuXHR9O1xuXG5cdG1lLnJlbW92ZUNsYXNzID0gZnVuY3Rpb24gKGUsIGMpIHtcblx0XHRpZiAoICFtZS5oYXNDbGFzcyhlLCBjKSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgcmUgPSBuZXcgUmVnRXhwKFwiKF58XFxcXHMpXCIgKyBjICsgXCIoXFxcXHN8JClcIiwgJ2cnKTtcblx0XHRlLmNsYXNzTmFtZSA9IGUuY2xhc3NOYW1lLnJlcGxhY2UocmUsICcgJyk7XG5cdH07XG5cblx0bWUub2Zmc2V0ID0gZnVuY3Rpb24gKGVsKSB7XG5cdFx0dmFyIGxlZnQgPSAtZWwub2Zmc2V0TGVmdCxcblx0XHRcdHRvcCA9IC1lbC5vZmZzZXRUb3A7XG5cblx0XHQvLyBqc2hpbnQgLVcwODRcblx0XHR3aGlsZSAoZWwgPSBlbC5vZmZzZXRQYXJlbnQpIHtcblx0XHRcdGxlZnQgLT0gZWwub2Zmc2V0TGVmdDtcblx0XHRcdHRvcCAtPSBlbC5vZmZzZXRUb3A7XG5cdFx0fVxuXHRcdC8vIGpzaGludCArVzA4NFxuXG5cdFx0cmV0dXJuIHtcblx0XHRcdGxlZnQ6IGxlZnQsXG5cdFx0XHR0b3A6IHRvcFxuXHRcdH07XG5cdH07XG5cblx0bWUucHJldmVudERlZmF1bHRFeGNlcHRpb24gPSBmdW5jdGlvbiAoZWwsIGV4Y2VwdGlvbnMpIHtcblx0XHRmb3IgKCB2YXIgaSBpbiBleGNlcHRpb25zICkge1xuXHRcdFx0aWYgKCBleGNlcHRpb25zW2ldLnRlc3QoZWxbaV0pICkge1xuXHRcdFx0XHRyZXR1cm4gdHJ1ZTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRyZXR1cm4gZmFsc2U7XG5cdH07XG5cblx0bWUuZXh0ZW5kKG1lLmV2ZW50VHlwZSA9IHt9LCB7XG5cdFx0dG91Y2hzdGFydDogMSxcblx0XHR0b3VjaG1vdmU6IDEsXG5cdFx0dG91Y2hlbmQ6IDEsXG5cblx0XHRtb3VzZWRvd246IDIsXG5cdFx0bW91c2Vtb3ZlOiAyLFxuXHRcdG1vdXNldXA6IDIsXG5cblx0XHRwb2ludGVyZG93bjogMyxcblx0XHRwb2ludGVybW92ZTogMyxcblx0XHRwb2ludGVydXA6IDMsXG5cblx0XHRNU1BvaW50ZXJEb3duOiAzLFxuXHRcdE1TUG9pbnRlck1vdmU6IDMsXG5cdFx0TVNQb2ludGVyVXA6IDNcblx0fSk7XG5cblx0bWUuZXh0ZW5kKG1lLmVhc2UgPSB7fSwge1xuXHRcdHF1YWRyYXRpYzoge1xuXHRcdFx0c3R5bGU6ICdjdWJpYy1iZXppZXIoMC4yNSwgMC40NiwgMC40NSwgMC45NCknLFxuXHRcdFx0Zm46IGZ1bmN0aW9uIChrKSB7XG5cdFx0XHRcdHJldHVybiBrICogKCAyIC0gayApO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0Y2lyY3VsYXI6IHtcblx0XHRcdHN0eWxlOiAnY3ViaWMtYmV6aWVyKDAuMSwgMC41NywgMC4xLCAxKScsXHQvLyBOb3QgcHJvcGVybHkgXCJjaXJjdWxhclwiIGJ1dCB0aGlzIGxvb2tzIGJldHRlciwgaXQgc2hvdWxkIGJlICgwLjA3NSwgMC44MiwgMC4xNjUsIDEpXG5cdFx0XHRmbjogZnVuY3Rpb24gKGspIHtcblx0XHRcdFx0cmV0dXJuIE1hdGguc3FydCggMSAtICggLS1rICogayApICk7XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRiYWNrOiB7XG5cdFx0XHRzdHlsZTogJ2N1YmljLWJlemllcigwLjE3NSwgMC44ODUsIDAuMzIsIDEuMjc1KScsXG5cdFx0XHRmbjogZnVuY3Rpb24gKGspIHtcblx0XHRcdFx0dmFyIGIgPSA0O1xuXHRcdFx0XHRyZXR1cm4gKCBrID0gayAtIDEgKSAqIGsgKiAoICggYiArIDEgKSAqIGsgKyBiICkgKyAxO1xuXHRcdFx0fVxuXHRcdH0sXG5cdFx0Ym91bmNlOiB7XG5cdFx0XHRzdHlsZTogJycsXG5cdFx0XHRmbjogZnVuY3Rpb24gKGspIHtcblx0XHRcdFx0aWYgKCAoIGsgLz0gMSApIDwgKCAxIC8gMi43NSApICkge1xuXHRcdFx0XHRcdHJldHVybiA3LjU2MjUgKiBrICogaztcblx0XHRcdFx0fSBlbHNlIGlmICggayA8ICggMiAvIDIuNzUgKSApIHtcblx0XHRcdFx0XHRyZXR1cm4gNy41NjI1ICogKCBrIC09ICggMS41IC8gMi43NSApICkgKiBrICsgMC43NTtcblx0XHRcdFx0fSBlbHNlIGlmICggayA8ICggMi41IC8gMi43NSApICkge1xuXHRcdFx0XHRcdHJldHVybiA3LjU2MjUgKiAoIGsgLT0gKCAyLjI1IC8gMi43NSApICkgKiBrICsgMC45Mzc1O1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHJldHVybiA3LjU2MjUgKiAoIGsgLT0gKCAyLjYyNSAvIDIuNzUgKSApICogayArIDAuOTg0Mzc1O1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fSxcblx0XHRlbGFzdGljOiB7XG5cdFx0XHRzdHlsZTogJycsXG5cdFx0XHRmbjogZnVuY3Rpb24gKGspIHtcblx0XHRcdFx0dmFyIGYgPSAwLjIyLFxuXHRcdFx0XHRcdGUgPSAwLjQ7XG5cblx0XHRcdFx0aWYgKCBrID09PSAwICkgeyByZXR1cm4gMDsgfVxuXHRcdFx0XHRpZiAoIGsgPT0gMSApIHsgcmV0dXJuIDE7IH1cblxuXHRcdFx0XHRyZXR1cm4gKCBlICogTWF0aC5wb3coIDIsIC0gMTAgKiBrICkgKiBNYXRoLnNpbiggKCBrIC0gZiAvIDQgKSAqICggMiAqIE1hdGguUEkgKSAvIGYgKSArIDEgKTtcblx0XHRcdH1cblx0XHR9XG5cdH0pO1xuXG5cdG1lLnRhcCA9IGZ1bmN0aW9uIChlLCBldmVudE5hbWUpIHtcblx0XHR2YXIgZXYgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnRXZlbnQnKTtcblx0XHRldi5pbml0RXZlbnQoZXZlbnROYW1lLCB0cnVlLCB0cnVlKTtcblx0XHRldi5wYWdlWCA9IGUucGFnZVg7XG5cdFx0ZXYucGFnZVkgPSBlLnBhZ2VZO1xuXHRcdGUudGFyZ2V0LmRpc3BhdGNoRXZlbnQoZXYpO1xuXHR9O1xuXG5cdG1lLmNsaWNrID0gZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgdGFyZ2V0ID0gZS50YXJnZXQsXG5cdFx0XHRldjtcblxuXHRcdGlmICggISgvKFNFTEVDVHxJTlBVVHxURVhUQVJFQSkvaSkudGVzdCh0YXJnZXQudGFnTmFtZSkgKSB7XG5cdFx0XHRldiA9IGRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO1xuXHRcdFx0ZXYuaW5pdE1vdXNlRXZlbnQoJ2NsaWNrJywgdHJ1ZSwgdHJ1ZSwgZS52aWV3LCAxLFxuXHRcdFx0XHR0YXJnZXQuc2NyZWVuWCwgdGFyZ2V0LnNjcmVlblksIHRhcmdldC5jbGllbnRYLCB0YXJnZXQuY2xpZW50WSxcblx0XHRcdFx0ZS5jdHJsS2V5LCBlLmFsdEtleSwgZS5zaGlmdEtleSwgZS5tZXRhS2V5LFxuXHRcdFx0XHQwLCBudWxsKTtcblxuXHRcdFx0ZXYuX2NvbnN0cnVjdGVkID0gdHJ1ZTtcblx0XHRcdHRhcmdldC5kaXNwYXRjaEV2ZW50KGV2KTtcblx0XHR9XG5cdH07XG5cblx0cmV0dXJuIG1lO1xufSkoKTtcbmZ1bmN0aW9uIElTY3JvbGwgKGVsLCBvcHRpb25zKSB7XG5cdHRoaXMud3JhcHBlciA9IHR5cGVvZiBlbCA9PSAnc3RyaW5nJyA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoZWwpIDogZWw7XG5cdHRoaXMuc2Nyb2xsZXIgPSB0aGlzLndyYXBwZXIuY2hpbGRyZW5bMF07XG5cdHRoaXMuc2Nyb2xsZXJTdHlsZSA9IHRoaXMuc2Nyb2xsZXIuc3R5bGU7XHRcdC8vIGNhY2hlIHN0eWxlIGZvciBiZXR0ZXIgcGVyZm9ybWFuY2VcblxuXHR0aGlzLm9wdGlvbnMgPSB7XG5cblx0XHRyZXNpemVTY3JvbGxiYXJzOiB0cnVlLFxuXG5cdFx0bW91c2VXaGVlbFNwZWVkOiAyMCxcblxuXHRcdHNuYXBUaHJlc2hvbGQ6IDAuMzM0LFxuXG4vLyBJTlNFUlQgUE9JTlQ6IE9QVElPTlNcblx0XHRkaXNhYmxlUG9pbnRlciA6ICF1dGlscy5oYXNQb2ludGVyLFxuXHRcdGRpc2FibGVUb3VjaCA6IHV0aWxzLmhhc1BvaW50ZXIgfHwgIXV0aWxzLmhhc1RvdWNoLFxuXHRcdGRpc2FibGVNb3VzZSA6IHV0aWxzLmhhc1BvaW50ZXIgfHwgdXRpbHMuaGFzVG91Y2gsXG5cdFx0c3RhcnRYOiAwLFxuXHRcdHN0YXJ0WTogMCxcblx0XHRzY3JvbGxZOiB0cnVlLFxuXHRcdGRpcmVjdGlvbkxvY2tUaHJlc2hvbGQ6IDUsXG5cdFx0bW9tZW50dW06IHRydWUsXG5cblx0XHRib3VuY2U6IHRydWUsXG5cdFx0Ym91bmNlVGltZTogNjAwLFxuXHRcdGJvdW5jZUVhc2luZzogJycsXG5cblx0XHRwcmV2ZW50RGVmYXVsdDogdHJ1ZSxcblx0XHRwcmV2ZW50RGVmYXVsdEV4Y2VwdGlvbjogeyB0YWdOYW1lOiAvXihJTlBVVHxURVhUQVJFQXxCVVRUT058U0VMRUNUKSQvIH0sXG5cblx0XHRIV0NvbXBvc2l0aW5nOiB0cnVlLFxuXHRcdHVzZVRyYW5zaXRpb246IHRydWUsXG5cdFx0dXNlVHJhbnNmb3JtOiB0cnVlLFxuXHRcdGJpbmRUb1dyYXBwZXI6IHR5cGVvZiB3aW5kb3cub25tb3VzZWRvd24gPT09IFwidW5kZWZpbmVkXCJcblx0fTtcblxuXHRmb3IgKCB2YXIgaSBpbiBvcHRpb25zICkge1xuXHRcdHRoaXMub3B0aW9uc1tpXSA9IG9wdGlvbnNbaV07XG5cdH1cblxuXHQvLyBOb3JtYWxpemUgb3B0aW9uc1xuXHR0aGlzLnRyYW5zbGF0ZVogPSB0aGlzLm9wdGlvbnMuSFdDb21wb3NpdGluZyAmJiB1dGlscy5oYXNQZXJzcGVjdGl2ZSA/ICcgdHJhbnNsYXRlWigwKScgOiAnJztcblxuXHR0aGlzLm9wdGlvbnMudXNlVHJhbnNpdGlvbiA9IHV0aWxzLmhhc1RyYW5zaXRpb24gJiYgdGhpcy5vcHRpb25zLnVzZVRyYW5zaXRpb247XG5cdHRoaXMub3B0aW9ucy51c2VUcmFuc2Zvcm0gPSB1dGlscy5oYXNUcmFuc2Zvcm0gJiYgdGhpcy5vcHRpb25zLnVzZVRyYW5zZm9ybTtcblxuXHR0aGlzLm9wdGlvbnMuZXZlbnRQYXNzdGhyb3VnaCA9IHRoaXMub3B0aW9ucy5ldmVudFBhc3N0aHJvdWdoID09PSB0cnVlID8gJ3ZlcnRpY2FsJyA6IHRoaXMub3B0aW9ucy5ldmVudFBhc3N0aHJvdWdoO1xuXHR0aGlzLm9wdGlvbnMucHJldmVudERlZmF1bHQgPSAhdGhpcy5vcHRpb25zLmV2ZW50UGFzc3Rocm91Z2ggJiYgdGhpcy5vcHRpb25zLnByZXZlbnREZWZhdWx0O1xuXG5cdC8vIElmIHlvdSB3YW50IGV2ZW50UGFzc3Rocm91Z2ggSSBoYXZlIHRvIGxvY2sgb25lIG9mIHRoZSBheGVzXG5cdHRoaXMub3B0aW9ucy5zY3JvbGxZID0gdGhpcy5vcHRpb25zLmV2ZW50UGFzc3Rocm91Z2ggPT0gJ3ZlcnRpY2FsJyA/IGZhbHNlIDogdGhpcy5vcHRpb25zLnNjcm9sbFk7XG5cdHRoaXMub3B0aW9ucy5zY3JvbGxYID0gdGhpcy5vcHRpb25zLmV2ZW50UGFzc3Rocm91Z2ggPT0gJ2hvcml6b250YWwnID8gZmFsc2UgOiB0aGlzLm9wdGlvbnMuc2Nyb2xsWDtcblxuXHQvLyBXaXRoIGV2ZW50UGFzc3Rocm91Z2ggd2UgYWxzbyBuZWVkIGxvY2tEaXJlY3Rpb24gbWVjaGFuaXNtXG5cdHRoaXMub3B0aW9ucy5mcmVlU2Nyb2xsID0gdGhpcy5vcHRpb25zLmZyZWVTY3JvbGwgJiYgIXRoaXMub3B0aW9ucy5ldmVudFBhc3N0aHJvdWdoO1xuXHR0aGlzLm9wdGlvbnMuZGlyZWN0aW9uTG9ja1RocmVzaG9sZCA9IHRoaXMub3B0aW9ucy5ldmVudFBhc3N0aHJvdWdoID8gMCA6IHRoaXMub3B0aW9ucy5kaXJlY3Rpb25Mb2NrVGhyZXNob2xkO1xuXG5cdHRoaXMub3B0aW9ucy5ib3VuY2VFYXNpbmcgPSB0eXBlb2YgdGhpcy5vcHRpb25zLmJvdW5jZUVhc2luZyA9PSAnc3RyaW5nJyA/IHV0aWxzLmVhc2VbdGhpcy5vcHRpb25zLmJvdW5jZUVhc2luZ10gfHwgdXRpbHMuZWFzZS5jaXJjdWxhciA6IHRoaXMub3B0aW9ucy5ib3VuY2VFYXNpbmc7XG5cblx0dGhpcy5vcHRpb25zLnJlc2l6ZVBvbGxpbmcgPSB0aGlzLm9wdGlvbnMucmVzaXplUG9sbGluZyA9PT0gdW5kZWZpbmVkID8gNjAgOiB0aGlzLm9wdGlvbnMucmVzaXplUG9sbGluZztcblxuXHRpZiAoIHRoaXMub3B0aW9ucy50YXAgPT09IHRydWUgKSB7XG5cdFx0dGhpcy5vcHRpb25zLnRhcCA9ICd0YXAnO1xuXHR9XG5cblx0aWYgKCB0aGlzLm9wdGlvbnMuc2hyaW5rU2Nyb2xsYmFycyA9PSAnc2NhbGUnICkge1xuXHRcdHRoaXMub3B0aW9ucy51c2VUcmFuc2l0aW9uID0gZmFsc2U7XG5cdH1cblxuXHR0aGlzLm9wdGlvbnMuaW52ZXJ0V2hlZWxEaXJlY3Rpb24gPSB0aGlzLm9wdGlvbnMuaW52ZXJ0V2hlZWxEaXJlY3Rpb24gPyAtMSA6IDE7XG5cbi8vIElOU0VSVCBQT0lOVDogTk9STUFMSVpBVElPTlxuXG5cdC8vIFNvbWUgZGVmYXVsdHNcblx0dGhpcy54ID0gMDtcblx0dGhpcy55ID0gMDtcblx0dGhpcy5kaXJlY3Rpb25YID0gMDtcblx0dGhpcy5kaXJlY3Rpb25ZID0gMDtcblx0dGhpcy5fZXZlbnRzID0ge307XG5cbi8vIElOU0VSVCBQT0lOVDogREVGQVVMVFNcblxuXHR0aGlzLl9pbml0KCk7XG5cdHRoaXMucmVmcmVzaCgpO1xuXG5cdHRoaXMuc2Nyb2xsVG8odGhpcy5vcHRpb25zLnN0YXJ0WCwgdGhpcy5vcHRpb25zLnN0YXJ0WSk7XG5cdHRoaXMuZW5hYmxlKCk7XG59XG5cbklTY3JvbGwucHJvdG90eXBlID0ge1xuXHR2ZXJzaW9uOiAnNS4yLjAnLFxuXG5cdF9pbml0OiBmdW5jdGlvbiAoKSB7XG5cdFx0dGhpcy5faW5pdEV2ZW50cygpO1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuc2Nyb2xsYmFycyB8fCB0aGlzLm9wdGlvbnMuaW5kaWNhdG9ycyApIHtcblx0XHRcdHRoaXMuX2luaXRJbmRpY2F0b3JzKCk7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMubW91c2VXaGVlbCApIHtcblx0XHRcdHRoaXMuX2luaXRXaGVlbCgpO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5vcHRpb25zLnNuYXAgKSB7XG5cdFx0XHR0aGlzLl9pbml0U25hcCgpO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5vcHRpb25zLmtleUJpbmRpbmdzICkge1xuXHRcdFx0dGhpcy5faW5pdEtleXMoKTtcblx0XHR9XG5cbi8vIElOU0VSVCBQT0lOVDogX2luaXRcblxuXHR9LFxuXG5cdGRlc3Ryb3k6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLl9pbml0RXZlbnRzKHRydWUpO1xuXHRcdGNsZWFyVGltZW91dCh0aGlzLnJlc2l6ZVRpbWVvdXQpO1xuIFx0XHR0aGlzLnJlc2l6ZVRpbWVvdXQgPSBudWxsO1xuXHRcdHRoaXMuX2V4ZWNFdmVudCgnZGVzdHJveScpO1xuXHR9LFxuXG5cdF90cmFuc2l0aW9uRW5kOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICggZS50YXJnZXQgIT0gdGhpcy5zY3JvbGxlciB8fCAhdGhpcy5pc0luVHJhbnNpdGlvbiApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR0aGlzLl90cmFuc2l0aW9uVGltZSgpO1xuXHRcdGlmICggIXRoaXMucmVzZXRQb3NpdGlvbih0aGlzLm9wdGlvbnMuYm91bmNlVGltZSkgKSB7XG5cdFx0XHR0aGlzLmlzSW5UcmFuc2l0aW9uID0gZmFsc2U7XG5cdFx0XHR0aGlzLl9leGVjRXZlbnQoJ3Njcm9sbEVuZCcpO1xuXHRcdH1cblx0fSxcblxuXHRfc3RhcnQ6IGZ1bmN0aW9uIChlKSB7XG5cdFx0Ly8gUmVhY3QgdG8gbGVmdCBtb3VzZSBidXR0b24gb25seVxuXHRcdGlmICggdXRpbHMuZXZlbnRUeXBlW2UudHlwZV0gIT0gMSApIHtcblx0XHQgIC8vIGZvciBidXR0b24gcHJvcGVydHlcblx0XHQgIC8vIGh0dHA6Ly91bml4cGFwYS5jb20vanMvbW91c2UuaHRtbFxuXHRcdCAgdmFyIGJ1dHRvbjtcblx0ICAgIGlmICghZS53aGljaCkge1xuXHQgICAgICAvKiBJRSBjYXNlICovXG5cdCAgICAgIGJ1dHRvbiA9IChlLmJ1dHRvbiA8IDIpID8gMCA6XG5cdCAgICAgICAgICAgICAgICgoZS5idXR0b24gPT0gNCkgPyAxIDogMik7XG5cdCAgICB9IGVsc2Uge1xuXHQgICAgICAvKiBBbGwgb3RoZXJzICovXG5cdCAgICAgIGJ1dHRvbiA9IGUuYnV0dG9uO1xuXHQgICAgfVxuXHRcdFx0aWYgKCBidXR0b24gIT09IDAgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoICF0aGlzLmVuYWJsZWQgfHwgKHRoaXMuaW5pdGlhdGVkICYmIHV0aWxzLmV2ZW50VHlwZVtlLnR5cGVdICE9PSB0aGlzLmluaXRpYXRlZCkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMucHJldmVudERlZmF1bHQgJiYgIXV0aWxzLmlzQmFkQW5kcm9pZCAmJiAhdXRpbHMucHJldmVudERlZmF1bHRFeGNlcHRpb24oZS50YXJnZXQsIHRoaXMub3B0aW9ucy5wcmV2ZW50RGVmYXVsdEV4Y2VwdGlvbikgKSB7XG5cdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0fVxuXG5cdFx0dmFyIHBvaW50ID0gZS50b3VjaGVzID8gZS50b3VjaGVzWzBdIDogZSxcblx0XHRcdHBvcztcblxuXHRcdHRoaXMuaW5pdGlhdGVkXHQ9IHV0aWxzLmV2ZW50VHlwZVtlLnR5cGVdO1xuXHRcdHRoaXMubW92ZWRcdFx0PSBmYWxzZTtcblx0XHR0aGlzLmRpc3RYXHRcdD0gMDtcblx0XHR0aGlzLmRpc3RZXHRcdD0gMDtcblx0XHR0aGlzLmRpcmVjdGlvblggPSAwO1xuXHRcdHRoaXMuZGlyZWN0aW9uWSA9IDA7XG5cdFx0dGhpcy5kaXJlY3Rpb25Mb2NrZWQgPSAwO1xuXG5cdFx0dGhpcy5zdGFydFRpbWUgPSB1dGlscy5nZXRUaW1lKCk7XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy51c2VUcmFuc2l0aW9uICYmIHRoaXMuaXNJblRyYW5zaXRpb24gKSB7XG5cdFx0XHR0aGlzLl90cmFuc2l0aW9uVGltZSgpO1xuXHRcdFx0dGhpcy5pc0luVHJhbnNpdGlvbiA9IGZhbHNlO1xuXHRcdFx0cG9zID0gdGhpcy5nZXRDb21wdXRlZFBvc2l0aW9uKCk7XG5cdFx0XHR0aGlzLl90cmFuc2xhdGUoTWF0aC5yb3VuZChwb3MueCksIE1hdGgucm91bmQocG9zLnkpKTtcblx0XHRcdHRoaXMuX2V4ZWNFdmVudCgnc2Nyb2xsRW5kJyk7XG5cdFx0fSBlbHNlIGlmICggIXRoaXMub3B0aW9ucy51c2VUcmFuc2l0aW9uICYmIHRoaXMuaXNBbmltYXRpbmcgKSB7XG5cdFx0XHR0aGlzLmlzQW5pbWF0aW5nID0gZmFsc2U7XG5cdFx0XHR0aGlzLl9leGVjRXZlbnQoJ3Njcm9sbEVuZCcpO1xuXHRcdH1cblxuXHRcdHRoaXMuc3RhcnRYICAgID0gdGhpcy54O1xuXHRcdHRoaXMuc3RhcnRZICAgID0gdGhpcy55O1xuXHRcdHRoaXMuYWJzU3RhcnRYID0gdGhpcy54O1xuXHRcdHRoaXMuYWJzU3RhcnRZID0gdGhpcy55O1xuXHRcdHRoaXMucG9pbnRYICAgID0gcG9pbnQucGFnZVg7XG5cdFx0dGhpcy5wb2ludFkgICAgPSBwb2ludC5wYWdlWTtcblxuXHRcdHRoaXMuX2V4ZWNFdmVudCgnYmVmb3JlU2Nyb2xsU3RhcnQnKTtcblx0fSxcblxuXHRfbW92ZTogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAoICF0aGlzLmVuYWJsZWQgfHwgdXRpbHMuZXZlbnRUeXBlW2UudHlwZV0gIT09IHRoaXMuaW5pdGlhdGVkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5vcHRpb25zLnByZXZlbnREZWZhdWx0ICkge1x0Ly8gaW5jcmVhc2VzIHBlcmZvcm1hbmNlIG9uIEFuZHJvaWQ/IFRPRE86IGNoZWNrIVxuXHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdH1cblxuXHRcdHZhciBwb2ludFx0XHQ9IGUudG91Y2hlcyA/IGUudG91Y2hlc1swXSA6IGUsXG5cdFx0XHRkZWx0YVhcdFx0PSBwb2ludC5wYWdlWCAtIHRoaXMucG9pbnRYLFxuXHRcdFx0ZGVsdGFZXHRcdD0gcG9pbnQucGFnZVkgLSB0aGlzLnBvaW50WSxcblx0XHRcdHRpbWVzdGFtcFx0PSB1dGlscy5nZXRUaW1lKCksXG5cdFx0XHRuZXdYLCBuZXdZLFxuXHRcdFx0YWJzRGlzdFgsIGFic0Rpc3RZO1xuXG5cdFx0dGhpcy5wb2ludFhcdFx0PSBwb2ludC5wYWdlWDtcblx0XHR0aGlzLnBvaW50WVx0XHQ9IHBvaW50LnBhZ2VZO1xuXG5cdFx0dGhpcy5kaXN0WFx0XHQrPSBkZWx0YVg7XG5cdFx0dGhpcy5kaXN0WVx0XHQrPSBkZWx0YVk7XG5cdFx0YWJzRGlzdFhcdFx0PSBNYXRoLmFicyh0aGlzLmRpc3RYKTtcblx0XHRhYnNEaXN0WVx0XHQ9IE1hdGguYWJzKHRoaXMuZGlzdFkpO1xuXG5cdFx0Ly8gV2UgbmVlZCB0byBtb3ZlIGF0IGxlYXN0IDEwIHBpeGVscyBmb3IgdGhlIHNjcm9sbGluZyB0byBpbml0aWF0ZVxuXHRcdGlmICggdGltZXN0YW1wIC0gdGhpcy5lbmRUaW1lID4gMzAwICYmIChhYnNEaXN0WCA8IDEwICYmIGFic0Rpc3RZIDwgMTApICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdC8vIElmIHlvdSBhcmUgc2Nyb2xsaW5nIGluIG9uZSBkaXJlY3Rpb24gbG9jayB0aGUgb3RoZXJcblx0XHRpZiAoICF0aGlzLmRpcmVjdGlvbkxvY2tlZCAmJiAhdGhpcy5vcHRpb25zLmZyZWVTY3JvbGwgKSB7XG5cdFx0XHRpZiAoIGFic0Rpc3RYID4gYWJzRGlzdFkgKyB0aGlzLm9wdGlvbnMuZGlyZWN0aW9uTG9ja1RocmVzaG9sZCApIHtcblx0XHRcdFx0dGhpcy5kaXJlY3Rpb25Mb2NrZWQgPSAnaCc7XHRcdC8vIGxvY2sgaG9yaXpvbnRhbGx5XG5cdFx0XHR9IGVsc2UgaWYgKCBhYnNEaXN0WSA+PSBhYnNEaXN0WCArIHRoaXMub3B0aW9ucy5kaXJlY3Rpb25Mb2NrVGhyZXNob2xkICkge1xuXHRcdFx0XHR0aGlzLmRpcmVjdGlvbkxvY2tlZCA9ICd2JztcdFx0Ly8gbG9jayB2ZXJ0aWNhbGx5XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmRpcmVjdGlvbkxvY2tlZCA9ICduJztcdFx0Ly8gbm8gbG9ja1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggdGhpcy5kaXJlY3Rpb25Mb2NrZWQgPT0gJ2gnICkge1xuXHRcdFx0aWYgKCB0aGlzLm9wdGlvbnMuZXZlbnRQYXNzdGhyb3VnaCA9PSAndmVydGljYWwnICkge1xuXHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHR9IGVsc2UgaWYgKCB0aGlzLm9wdGlvbnMuZXZlbnRQYXNzdGhyb3VnaCA9PSAnaG9yaXpvbnRhbCcgKSB7XG5cdFx0XHRcdHRoaXMuaW5pdGlhdGVkID0gZmFsc2U7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0ZGVsdGFZID0gMDtcblx0XHR9IGVsc2UgaWYgKCB0aGlzLmRpcmVjdGlvbkxvY2tlZCA9PSAndicgKSB7XG5cdFx0XHRpZiAoIHRoaXMub3B0aW9ucy5ldmVudFBhc3N0aHJvdWdoID09ICdob3Jpem9udGFsJyApIHtcblx0XHRcdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdFx0fSBlbHNlIGlmICggdGhpcy5vcHRpb25zLmV2ZW50UGFzc3Rocm91Z2ggPT0gJ3ZlcnRpY2FsJyApIHtcblx0XHRcdFx0dGhpcy5pbml0aWF0ZWQgPSBmYWxzZTtcblx0XHRcdFx0cmV0dXJuO1xuXHRcdFx0fVxuXG5cdFx0XHRkZWx0YVggPSAwO1xuXHRcdH1cblxuXHRcdGRlbHRhWCA9IHRoaXMuaGFzSG9yaXpvbnRhbFNjcm9sbCA/IGRlbHRhWCA6IDA7XG5cdFx0ZGVsdGFZID0gdGhpcy5oYXNWZXJ0aWNhbFNjcm9sbCA/IGRlbHRhWSA6IDA7XG5cblx0XHRuZXdYID0gdGhpcy54ICsgZGVsdGFYO1xuXHRcdG5ld1kgPSB0aGlzLnkgKyBkZWx0YVk7XG5cblx0XHQvLyBTbG93IGRvd24gaWYgb3V0c2lkZSBvZiB0aGUgYm91bmRhcmllc1xuXHRcdGlmICggbmV3WCA+IDAgfHwgbmV3WCA8IHRoaXMubWF4U2Nyb2xsWCApIHtcblx0XHRcdG5ld1ggPSB0aGlzLm9wdGlvbnMuYm91bmNlID8gdGhpcy54ICsgZGVsdGFYIC8gMyA6IG5ld1ggPiAwID8gMCA6IHRoaXMubWF4U2Nyb2xsWDtcblx0XHR9XG5cdFx0aWYgKCBuZXdZID4gMCB8fCBuZXdZIDwgdGhpcy5tYXhTY3JvbGxZICkge1xuXHRcdFx0bmV3WSA9IHRoaXMub3B0aW9ucy5ib3VuY2UgPyB0aGlzLnkgKyBkZWx0YVkgLyAzIDogbmV3WSA+IDAgPyAwIDogdGhpcy5tYXhTY3JvbGxZO1xuXHRcdH1cblxuXHRcdHRoaXMuZGlyZWN0aW9uWCA9IGRlbHRhWCA+IDAgPyAtMSA6IGRlbHRhWCA8IDAgPyAxIDogMDtcblx0XHR0aGlzLmRpcmVjdGlvblkgPSBkZWx0YVkgPiAwID8gLTEgOiBkZWx0YVkgPCAwID8gMSA6IDA7XG5cblx0XHRpZiAoICF0aGlzLm1vdmVkICkge1xuXHRcdFx0dGhpcy5fZXhlY0V2ZW50KCdzY3JvbGxTdGFydCcpO1xuXHRcdH1cblxuXHRcdHRoaXMubW92ZWQgPSB0cnVlO1xuXG5cdFx0dGhpcy5fdHJhbnNsYXRlKG5ld1gsIG5ld1kpO1xuXG4vKiBSRVBMQUNFIFNUQVJUOiBfbW92ZSAqL1xuXG5cdFx0aWYgKCB0aW1lc3RhbXAgLSB0aGlzLnN0YXJ0VGltZSA+IDMwMCApIHtcblx0XHRcdHRoaXMuc3RhcnRUaW1lID0gdGltZXN0YW1wO1xuXHRcdFx0dGhpcy5zdGFydFggPSB0aGlzLng7XG5cdFx0XHR0aGlzLnN0YXJ0WSA9IHRoaXMueTtcblx0XHR9XG5cbi8qIFJFUExBQ0UgRU5EOiBfbW92ZSAqL1xuXG5cdH0sXG5cblx0X2VuZDogZnVuY3Rpb24gKGUpIHtcblx0XHRpZiAoICF0aGlzLmVuYWJsZWQgfHwgdXRpbHMuZXZlbnRUeXBlW2UudHlwZV0gIT09IHRoaXMuaW5pdGlhdGVkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5vcHRpb25zLnByZXZlbnREZWZhdWx0ICYmICF1dGlscy5wcmV2ZW50RGVmYXVsdEV4Y2VwdGlvbihlLnRhcmdldCwgdGhpcy5vcHRpb25zLnByZXZlbnREZWZhdWx0RXhjZXB0aW9uKSApIHtcblx0XHRcdGUucHJldmVudERlZmF1bHQoKTtcblx0XHR9XG5cblx0XHR2YXIgcG9pbnQgPSBlLmNoYW5nZWRUb3VjaGVzID8gZS5jaGFuZ2VkVG91Y2hlc1swXSA6IGUsXG5cdFx0XHRtb21lbnR1bVgsXG5cdFx0XHRtb21lbnR1bVksXG5cdFx0XHRkdXJhdGlvbiA9IHV0aWxzLmdldFRpbWUoKSAtIHRoaXMuc3RhcnRUaW1lLFxuXHRcdFx0bmV3WCA9IE1hdGgucm91bmQodGhpcy54KSxcblx0XHRcdG5ld1kgPSBNYXRoLnJvdW5kKHRoaXMueSksXG5cdFx0XHRkaXN0YW5jZVggPSBNYXRoLmFicyhuZXdYIC0gdGhpcy5zdGFydFgpLFxuXHRcdFx0ZGlzdGFuY2VZID0gTWF0aC5hYnMobmV3WSAtIHRoaXMuc3RhcnRZKSxcblx0XHRcdHRpbWUgPSAwLFxuXHRcdFx0ZWFzaW5nID0gJyc7XG5cblx0XHR0aGlzLmlzSW5UcmFuc2l0aW9uID0gMDtcblx0XHR0aGlzLmluaXRpYXRlZCA9IDA7XG5cdFx0dGhpcy5lbmRUaW1lID0gdXRpbHMuZ2V0VGltZSgpO1xuXG5cdFx0Ly8gcmVzZXQgaWYgd2UgYXJlIG91dHNpZGUgb2YgdGhlIGJvdW5kYXJpZXNcblx0XHRpZiAoIHRoaXMucmVzZXRQb3NpdGlvbih0aGlzLm9wdGlvbnMuYm91bmNlVGltZSkgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dGhpcy5zY3JvbGxUbyhuZXdYLCBuZXdZKTtcdC8vIGVuc3VyZXMgdGhhdCB0aGUgbGFzdCBwb3NpdGlvbiBpcyByb3VuZGVkXG5cblx0XHQvLyB3ZSBzY3JvbGxlZCBsZXNzIHRoYW4gMTAgcGl4ZWxzXG5cdFx0aWYgKCAhdGhpcy5tb3ZlZCApIHtcblx0XHRcdGlmICggdGhpcy5vcHRpb25zLnRhcCApIHtcblx0XHRcdFx0dXRpbHMudGFwKGUsIHRoaXMub3B0aW9ucy50YXApO1xuXHRcdFx0fVxuXG5cdFx0XHRpZiAoIHRoaXMub3B0aW9ucy5jbGljayApIHtcblx0XHRcdFx0dXRpbHMuY2xpY2soZSk7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMuX2V4ZWNFdmVudCgnc2Nyb2xsQ2FuY2VsJyk7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLl9ldmVudHMuZmxpY2sgJiYgZHVyYXRpb24gPCAyMDAgJiYgZGlzdGFuY2VYIDwgMTAwICYmIGRpc3RhbmNlWSA8IDEwMCApIHtcblx0XHRcdHRoaXMuX2V4ZWNFdmVudCgnZmxpY2snKTtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHQvLyBzdGFydCBtb21lbnR1bSBhbmltYXRpb24gaWYgbmVlZGVkXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMubW9tZW50dW0gJiYgZHVyYXRpb24gPCAzMDAgKSB7XG5cdFx0XHRtb21lbnR1bVggPSB0aGlzLmhhc0hvcml6b250YWxTY3JvbGwgPyB1dGlscy5tb21lbnR1bSh0aGlzLngsIHRoaXMuc3RhcnRYLCBkdXJhdGlvbiwgdGhpcy5tYXhTY3JvbGxYLCB0aGlzLm9wdGlvbnMuYm91bmNlID8gdGhpcy53cmFwcGVyV2lkdGggOiAwLCB0aGlzLm9wdGlvbnMuZGVjZWxlcmF0aW9uKSA6IHsgZGVzdGluYXRpb246IG5ld1gsIGR1cmF0aW9uOiAwIH07XG5cdFx0XHRtb21lbnR1bVkgPSB0aGlzLmhhc1ZlcnRpY2FsU2Nyb2xsID8gdXRpbHMubW9tZW50dW0odGhpcy55LCB0aGlzLnN0YXJ0WSwgZHVyYXRpb24sIHRoaXMubWF4U2Nyb2xsWSwgdGhpcy5vcHRpb25zLmJvdW5jZSA/IHRoaXMud3JhcHBlckhlaWdodCA6IDAsIHRoaXMub3B0aW9ucy5kZWNlbGVyYXRpb24pIDogeyBkZXN0aW5hdGlvbjogbmV3WSwgZHVyYXRpb246IDAgfTtcblx0XHRcdG5ld1ggPSBtb21lbnR1bVguZGVzdGluYXRpb247XG5cdFx0XHRuZXdZID0gbW9tZW50dW1ZLmRlc3RpbmF0aW9uO1xuXHRcdFx0dGltZSA9IE1hdGgubWF4KG1vbWVudHVtWC5kdXJhdGlvbiwgbW9tZW50dW1ZLmR1cmF0aW9uKTtcblx0XHRcdHRoaXMuaXNJblRyYW5zaXRpb24gPSAxO1xuXHRcdH1cblxuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuc25hcCApIHtcblx0XHRcdHZhciBzbmFwID0gdGhpcy5fbmVhcmVzdFNuYXAobmV3WCwgbmV3WSk7XG5cdFx0XHR0aGlzLmN1cnJlbnRQYWdlID0gc25hcDtcblx0XHRcdHRpbWUgPSB0aGlzLm9wdGlvbnMuc25hcFNwZWVkIHx8IE1hdGgubWF4KFxuXHRcdFx0XHRcdE1hdGgubWF4KFxuXHRcdFx0XHRcdFx0TWF0aC5taW4oTWF0aC5hYnMobmV3WCAtIHNuYXAueCksIDEwMDApLFxuXHRcdFx0XHRcdFx0TWF0aC5taW4oTWF0aC5hYnMobmV3WSAtIHNuYXAueSksIDEwMDApXG5cdFx0XHRcdFx0KSwgMzAwKTtcblx0XHRcdG5ld1ggPSBzbmFwLng7XG5cdFx0XHRuZXdZID0gc25hcC55O1xuXG5cdFx0XHR0aGlzLmRpcmVjdGlvblggPSAwO1xuXHRcdFx0dGhpcy5kaXJlY3Rpb25ZID0gMDtcblx0XHRcdGVhc2luZyA9IHRoaXMub3B0aW9ucy5ib3VuY2VFYXNpbmc7XG5cdFx0fVxuXG4vLyBJTlNFUlQgUE9JTlQ6IF9lbmRcblxuXHRcdGlmICggbmV3WCAhPSB0aGlzLnggfHwgbmV3WSAhPSB0aGlzLnkgKSB7XG5cdFx0XHQvLyBjaGFuZ2UgZWFzaW5nIGZ1bmN0aW9uIHdoZW4gc2Nyb2xsZXIgZ29lcyBvdXQgb2YgdGhlIGJvdW5kYXJpZXNcblx0XHRcdGlmICggbmV3WCA+IDAgfHwgbmV3WCA8IHRoaXMubWF4U2Nyb2xsWCB8fCBuZXdZID4gMCB8fCBuZXdZIDwgdGhpcy5tYXhTY3JvbGxZICkge1xuXHRcdFx0XHRlYXNpbmcgPSB1dGlscy5lYXNlLnF1YWRyYXRpYztcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5zY3JvbGxUbyhuZXdYLCBuZXdZLCB0aW1lLCBlYXNpbmcpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMuX2V4ZWNFdmVudCgnc2Nyb2xsRW5kJyk7XG5cdH0sXG5cblx0X3Jlc2l6ZTogZnVuY3Rpb24gKCkge1xuXHRcdHZhciB0aGF0ID0gdGhpcztcblxuXHRcdGNsZWFyVGltZW91dCh0aGlzLnJlc2l6ZVRpbWVvdXQpO1xuXG5cdFx0dGhpcy5yZXNpemVUaW1lb3V0ID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHR0aGF0LnJlZnJlc2goKTtcblx0XHR9LCB0aGlzLm9wdGlvbnMucmVzaXplUG9sbGluZyk7XG5cdH0sXG5cblx0cmVzZXRQb3NpdGlvbjogZnVuY3Rpb24gKHRpbWUpIHtcblx0XHR2YXIgeCA9IHRoaXMueCxcblx0XHRcdHkgPSB0aGlzLnk7XG5cblx0XHR0aW1lID0gdGltZSB8fCAwO1xuXG5cdFx0aWYgKCAhdGhpcy5oYXNIb3Jpem9udGFsU2Nyb2xsIHx8IHRoaXMueCA+IDAgKSB7XG5cdFx0XHR4ID0gMDtcblx0XHR9IGVsc2UgaWYgKCB0aGlzLnggPCB0aGlzLm1heFNjcm9sbFggKSB7XG5cdFx0XHR4ID0gdGhpcy5tYXhTY3JvbGxYO1xuXHRcdH1cblxuXHRcdGlmICggIXRoaXMuaGFzVmVydGljYWxTY3JvbGwgfHwgdGhpcy55ID4gMCApIHtcblx0XHRcdHkgPSAwO1xuXHRcdH0gZWxzZSBpZiAoIHRoaXMueSA8IHRoaXMubWF4U2Nyb2xsWSApIHtcblx0XHRcdHkgPSB0aGlzLm1heFNjcm9sbFk7XG5cdFx0fVxuXG5cdFx0aWYgKCB4ID09IHRoaXMueCAmJiB5ID09IHRoaXMueSApIHtcblx0XHRcdHJldHVybiBmYWxzZTtcblx0XHR9XG5cblx0XHR0aGlzLnNjcm9sbFRvKHgsIHksIHRpbWUsIHRoaXMub3B0aW9ucy5ib3VuY2VFYXNpbmcpO1xuXG5cdFx0cmV0dXJuIHRydWU7XG5cdH0sXG5cblx0ZGlzYWJsZTogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuZW5hYmxlZCA9IGZhbHNlO1xuXHR9LFxuXG5cdGVuYWJsZTogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMuZW5hYmxlZCA9IHRydWU7XG5cdH0sXG5cblx0cmVmcmVzaDogZnVuY3Rpb24gKCkge1xuXHRcdHZhciByZiA9IHRoaXMud3JhcHBlci5vZmZzZXRIZWlnaHQ7XHRcdC8vIEZvcmNlIHJlZmxvd1xuXG5cdFx0dGhpcy53cmFwcGVyV2lkdGhcdD0gdGhpcy53cmFwcGVyLmNsaWVudFdpZHRoO1xuXHRcdHRoaXMud3JhcHBlckhlaWdodFx0PSB0aGlzLndyYXBwZXIuY2xpZW50SGVpZ2h0O1xuXG4vKiBSRVBMQUNFIFNUQVJUOiByZWZyZXNoICovXG5cblx0XHR0aGlzLnNjcm9sbGVyV2lkdGhcdD0gdGhpcy5zY3JvbGxlci5vZmZzZXRXaWR0aDtcblx0XHR0aGlzLnNjcm9sbGVySGVpZ2h0XHQ9IHRoaXMuc2Nyb2xsZXIub2Zmc2V0SGVpZ2h0O1xuXG5cdFx0dGhpcy5tYXhTY3JvbGxYXHRcdD0gdGhpcy53cmFwcGVyV2lkdGggLSB0aGlzLnNjcm9sbGVyV2lkdGg7XG5cdFx0dGhpcy5tYXhTY3JvbGxZXHRcdD0gdGhpcy53cmFwcGVySGVpZ2h0IC0gdGhpcy5zY3JvbGxlckhlaWdodDtcblxuLyogUkVQTEFDRSBFTkQ6IHJlZnJlc2ggKi9cblxuXHRcdHRoaXMuaGFzSG9yaXpvbnRhbFNjcm9sbFx0PSB0aGlzLm9wdGlvbnMuc2Nyb2xsWCAmJiB0aGlzLm1heFNjcm9sbFggPCAwO1xuXHRcdHRoaXMuaGFzVmVydGljYWxTY3JvbGxcdFx0PSB0aGlzLm9wdGlvbnMuc2Nyb2xsWSAmJiB0aGlzLm1heFNjcm9sbFkgPCAwO1xuXG5cdFx0aWYgKCAhdGhpcy5oYXNIb3Jpem9udGFsU2Nyb2xsICkge1xuXHRcdFx0dGhpcy5tYXhTY3JvbGxYID0gMDtcblx0XHRcdHRoaXMuc2Nyb2xsZXJXaWR0aCA9IHRoaXMud3JhcHBlcldpZHRoO1xuXHRcdH1cblxuXHRcdGlmICggIXRoaXMuaGFzVmVydGljYWxTY3JvbGwgKSB7XG5cdFx0XHR0aGlzLm1heFNjcm9sbFkgPSAwO1xuXHRcdFx0dGhpcy5zY3JvbGxlckhlaWdodCA9IHRoaXMud3JhcHBlckhlaWdodDtcblx0XHR9XG5cblx0XHR0aGlzLmVuZFRpbWUgPSAwO1xuXHRcdHRoaXMuZGlyZWN0aW9uWCA9IDA7XG5cdFx0dGhpcy5kaXJlY3Rpb25ZID0gMDtcblxuXHRcdHRoaXMud3JhcHBlck9mZnNldCA9IHV0aWxzLm9mZnNldCh0aGlzLndyYXBwZXIpO1xuXG5cdFx0dGhpcy5fZXhlY0V2ZW50KCdyZWZyZXNoJyk7XG5cblx0XHR0aGlzLnJlc2V0UG9zaXRpb24oKTtcblxuLy8gSU5TRVJUIFBPSU5UOiBfcmVmcmVzaFxuXG5cdH0sXG5cblx0b246IGZ1bmN0aW9uICh0eXBlLCBmbikge1xuXHRcdGlmICggIXRoaXMuX2V2ZW50c1t0eXBlXSApIHtcblx0XHRcdHRoaXMuX2V2ZW50c1t0eXBlXSA9IFtdO1xuXHRcdH1cblxuXHRcdHRoaXMuX2V2ZW50c1t0eXBlXS5wdXNoKGZuKTtcblx0fSxcblxuXHRvZmY6IGZ1bmN0aW9uICh0eXBlLCBmbikge1xuXHRcdGlmICggIXRoaXMuX2V2ZW50c1t0eXBlXSApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgaW5kZXggPSB0aGlzLl9ldmVudHNbdHlwZV0uaW5kZXhPZihmbik7XG5cblx0XHRpZiAoIGluZGV4ID4gLTEgKSB7XG5cdFx0XHR0aGlzLl9ldmVudHNbdHlwZV0uc3BsaWNlKGluZGV4LCAxKTtcblx0XHR9XG5cdH0sXG5cblx0X2V4ZWNFdmVudDogZnVuY3Rpb24gKHR5cGUpIHtcblx0XHRpZiAoICF0aGlzLl9ldmVudHNbdHlwZV0gKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIGkgPSAwLFxuXHRcdFx0bCA9IHRoaXMuX2V2ZW50c1t0eXBlXS5sZW5ndGg7XG5cblx0XHRpZiAoICFsICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGZvciAoIDsgaSA8IGw7IGkrKyApIHtcblx0XHRcdHRoaXMuX2V2ZW50c1t0eXBlXVtpXS5hcHBseSh0aGlzLCBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cywgMSkpO1xuXHRcdH1cblx0fSxcblxuXHRzY3JvbGxCeTogZnVuY3Rpb24gKHgsIHksIHRpbWUsIGVhc2luZykge1xuXHRcdHggPSB0aGlzLnggKyB4O1xuXHRcdHkgPSB0aGlzLnkgKyB5O1xuXHRcdHRpbWUgPSB0aW1lIHx8IDA7XG5cblx0XHR0aGlzLnNjcm9sbFRvKHgsIHksIHRpbWUsIGVhc2luZyk7XG5cdH0sXG5cblx0c2Nyb2xsVG86IGZ1bmN0aW9uICh4LCB5LCB0aW1lLCBlYXNpbmcpIHtcblx0XHRlYXNpbmcgPSBlYXNpbmcgfHwgdXRpbHMuZWFzZS5jaXJjdWxhcjtcblxuXHRcdHRoaXMuaXNJblRyYW5zaXRpb24gPSB0aGlzLm9wdGlvbnMudXNlVHJhbnNpdGlvbiAmJiB0aW1lID4gMDtcblx0XHR2YXIgdHJhbnNpdGlvblR5cGUgPSB0aGlzLm9wdGlvbnMudXNlVHJhbnNpdGlvbiAmJiBlYXNpbmcuc3R5bGU7XG5cdFx0aWYgKCAhdGltZSB8fCB0cmFuc2l0aW9uVHlwZSApIHtcblx0XHRcdFx0aWYodHJhbnNpdGlvblR5cGUpIHtcblx0XHRcdFx0XHR0aGlzLl90cmFuc2l0aW9uVGltaW5nRnVuY3Rpb24oZWFzaW5nLnN0eWxlKTtcblx0XHRcdFx0XHR0aGlzLl90cmFuc2l0aW9uVGltZSh0aW1lKTtcblx0XHRcdFx0fVxuXHRcdFx0dGhpcy5fdHJhbnNsYXRlKHgsIHkpO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHR0aGlzLl9hbmltYXRlKHgsIHksIHRpbWUsIGVhc2luZy5mbik7XG5cdFx0fVxuXHR9LFxuXG5cdHNjcm9sbFRvRWxlbWVudDogZnVuY3Rpb24gKGVsLCB0aW1lLCBvZmZzZXRYLCBvZmZzZXRZLCBlYXNpbmcpIHtcblx0XHRlbCA9IGVsLm5vZGVUeXBlID8gZWwgOiB0aGlzLnNjcm9sbGVyLnF1ZXJ5U2VsZWN0b3IoZWwpO1xuXG5cdFx0aWYgKCAhZWwgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0dmFyIHBvcyA9IHV0aWxzLm9mZnNldChlbCk7XG5cblx0XHRwb3MubGVmdCAtPSB0aGlzLndyYXBwZXJPZmZzZXQubGVmdDtcblx0XHRwb3MudG9wICAtPSB0aGlzLndyYXBwZXJPZmZzZXQudG9wO1xuXG5cdFx0Ly8gaWYgb2Zmc2V0WC9ZIGFyZSB0cnVlIHdlIGNlbnRlciB0aGUgZWxlbWVudCB0byB0aGUgc2NyZWVuXG5cdFx0aWYgKCBvZmZzZXRYID09PSB0cnVlICkge1xuXHRcdFx0b2Zmc2V0WCA9IE1hdGgucm91bmQoZWwub2Zmc2V0V2lkdGggLyAyIC0gdGhpcy53cmFwcGVyLm9mZnNldFdpZHRoIC8gMik7XG5cdFx0fVxuXHRcdGlmICggb2Zmc2V0WSA9PT0gdHJ1ZSApIHtcblx0XHRcdG9mZnNldFkgPSBNYXRoLnJvdW5kKGVsLm9mZnNldEhlaWdodCAvIDIgLSB0aGlzLndyYXBwZXIub2Zmc2V0SGVpZ2h0IC8gMik7XG5cdFx0fVxuXG5cdFx0cG9zLmxlZnQgLT0gb2Zmc2V0WCB8fCAwO1xuXHRcdHBvcy50b3AgIC09IG9mZnNldFkgfHwgMDtcblxuXHRcdHBvcy5sZWZ0ID0gcG9zLmxlZnQgPiAwID8gMCA6IHBvcy5sZWZ0IDwgdGhpcy5tYXhTY3JvbGxYID8gdGhpcy5tYXhTY3JvbGxYIDogcG9zLmxlZnQ7XG5cdFx0cG9zLnRvcCAgPSBwb3MudG9wICA+IDAgPyAwIDogcG9zLnRvcCAgPCB0aGlzLm1heFNjcm9sbFkgPyB0aGlzLm1heFNjcm9sbFkgOiBwb3MudG9wO1xuXG5cdFx0dGltZSA9IHRpbWUgPT09IHVuZGVmaW5lZCB8fCB0aW1lID09PSBudWxsIHx8IHRpbWUgPT09ICdhdXRvJyA/IE1hdGgubWF4KE1hdGguYWJzKHRoaXMueC1wb3MubGVmdCksIE1hdGguYWJzKHRoaXMueS1wb3MudG9wKSkgOiB0aW1lO1xuXG5cdFx0dGhpcy5zY3JvbGxUbyhwb3MubGVmdCwgcG9zLnRvcCwgdGltZSwgZWFzaW5nKTtcblx0fSxcblxuXHRfdHJhbnNpdGlvblRpbWU6IGZ1bmN0aW9uICh0aW1lKSB7XG5cdFx0dGltZSA9IHRpbWUgfHwgMDtcblxuXHRcdHZhciBkdXJhdGlvblByb3AgPSB1dGlscy5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb247XG5cdFx0dGhpcy5zY3JvbGxlclN0eWxlW2R1cmF0aW9uUHJvcF0gPSB0aW1lICsgJ21zJztcblxuXHRcdGlmICggIXRpbWUgJiYgdXRpbHMuaXNCYWRBbmRyb2lkICkge1xuXHRcdFx0dGhpcy5zY3JvbGxlclN0eWxlW2R1cmF0aW9uUHJvcF0gPSAnMC4wMDAxbXMnO1xuXHRcdFx0Ly8gcmVtb3ZlIDAuMDAwMW1zXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0XHRyQUYoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmKHNlbGYuc2Nyb2xsZXJTdHlsZVtkdXJhdGlvblByb3BdID09PSAnMC4wMDAxbXMnKSB7XG5cdFx0XHRcdFx0c2VsZi5zY3JvbGxlclN0eWxlW2R1cmF0aW9uUHJvcF0gPSAnMHMnO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cblxuXHRcdGlmICggdGhpcy5pbmRpY2F0b3JzICkge1xuXHRcdFx0Zm9yICggdmFyIGkgPSB0aGlzLmluZGljYXRvcnMubGVuZ3RoOyBpLS07ICkge1xuXHRcdFx0XHR0aGlzLmluZGljYXRvcnNbaV0udHJhbnNpdGlvblRpbWUodGltZSk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cbi8vIElOU0VSVCBQT0lOVDogX3RyYW5zaXRpb25UaW1lXG5cblx0fSxcblxuXHRfdHJhbnNpdGlvblRpbWluZ0Z1bmN0aW9uOiBmdW5jdGlvbiAoZWFzaW5nKSB7XG5cdFx0dGhpcy5zY3JvbGxlclN0eWxlW3V0aWxzLnN0eWxlLnRyYW5zaXRpb25UaW1pbmdGdW5jdGlvbl0gPSBlYXNpbmc7XG5cblxuXHRcdGlmICggdGhpcy5pbmRpY2F0b3JzICkge1xuXHRcdFx0Zm9yICggdmFyIGkgPSB0aGlzLmluZGljYXRvcnMubGVuZ3RoOyBpLS07ICkge1xuXHRcdFx0XHR0aGlzLmluZGljYXRvcnNbaV0udHJhbnNpdGlvblRpbWluZ0Z1bmN0aW9uKGVhc2luZyk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cbi8vIElOU0VSVCBQT0lOVDogX3RyYW5zaXRpb25UaW1pbmdGdW5jdGlvblxuXG5cdH0sXG5cblx0X3RyYW5zbGF0ZTogZnVuY3Rpb24gKHgsIHkpIHtcblx0XHRpZiAoIHRoaXMub3B0aW9ucy51c2VUcmFuc2Zvcm0gKSB7XG5cbi8qIFJFUExBQ0UgU1RBUlQ6IF90cmFuc2xhdGUgKi9cblxuXHRcdFx0dGhpcy5zY3JvbGxlclN0eWxlW3V0aWxzLnN0eWxlLnRyYW5zZm9ybV0gPSAndHJhbnNsYXRlKCcgKyB4ICsgJ3B4LCcgKyB5ICsgJ3B4KScgKyB0aGlzLnRyYW5zbGF0ZVo7XG5cbi8qIFJFUExBQ0UgRU5EOiBfdHJhbnNsYXRlICovXG5cblx0XHR9IGVsc2Uge1xuXHRcdFx0eCA9IE1hdGgucm91bmQoeCk7XG5cdFx0XHR5ID0gTWF0aC5yb3VuZCh5KTtcblx0XHRcdHRoaXMuc2Nyb2xsZXJTdHlsZS5sZWZ0ID0geCArICdweCc7XG5cdFx0XHR0aGlzLnNjcm9sbGVyU3R5bGUudG9wID0geSArICdweCc7XG5cdFx0fVxuXG5cdFx0dGhpcy54ID0geDtcblx0XHR0aGlzLnkgPSB5O1xuXG5cblx0aWYgKCB0aGlzLmluZGljYXRvcnMgKSB7XG5cdFx0Zm9yICggdmFyIGkgPSB0aGlzLmluZGljYXRvcnMubGVuZ3RoOyBpLS07ICkge1xuXHRcdFx0dGhpcy5pbmRpY2F0b3JzW2ldLnVwZGF0ZVBvc2l0aW9uKCk7XG5cdFx0fVxuXHR9XG5cblxuLy8gSU5TRVJUIFBPSU5UOiBfdHJhbnNsYXRlXG5cblx0fSxcblxuXHRfaW5pdEV2ZW50czogZnVuY3Rpb24gKHJlbW92ZSkge1xuXHRcdHZhciBldmVudFR5cGUgPSByZW1vdmUgPyB1dGlscy5yZW1vdmVFdmVudCA6IHV0aWxzLmFkZEV2ZW50LFxuXHRcdFx0dGFyZ2V0ID0gdGhpcy5vcHRpb25zLmJpbmRUb1dyYXBwZXIgPyB0aGlzLndyYXBwZXIgOiB3aW5kb3c7XG5cblx0XHRldmVudFR5cGUod2luZG93LCAnb3JpZW50YXRpb25jaGFuZ2UnLCB0aGlzKTtcblx0XHRldmVudFR5cGUod2luZG93LCAncmVzaXplJywgdGhpcyk7XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy5jbGljayApIHtcblx0XHRcdGV2ZW50VHlwZSh0aGlzLndyYXBwZXIsICdjbGljaycsIHRoaXMsIHRydWUpO1xuXHRcdH1cblxuXHRcdGlmICggIXRoaXMub3B0aW9ucy5kaXNhYmxlTW91c2UgKSB7XG5cdFx0XHRldmVudFR5cGUodGhpcy53cmFwcGVyLCAnbW91c2Vkb3duJywgdGhpcyk7XG5cdFx0XHRldmVudFR5cGUodGFyZ2V0LCAnbW91c2Vtb3ZlJywgdGhpcyk7XG5cdFx0XHRldmVudFR5cGUodGFyZ2V0LCAnbW91c2VjYW5jZWwnLCB0aGlzKTtcblx0XHRcdGV2ZW50VHlwZSh0YXJnZXQsICdtb3VzZXVwJywgdGhpcyk7XG5cdFx0fVxuXG5cdFx0aWYgKCB1dGlscy5oYXNQb2ludGVyICYmICF0aGlzLm9wdGlvbnMuZGlzYWJsZVBvaW50ZXIgKSB7XG5cdFx0XHRldmVudFR5cGUodGhpcy53cmFwcGVyLCB1dGlscy5wcmVmaXhQb2ludGVyRXZlbnQoJ3BvaW50ZXJkb3duJyksIHRoaXMpO1xuXHRcdFx0ZXZlbnRUeXBlKHRhcmdldCwgdXRpbHMucHJlZml4UG9pbnRlckV2ZW50KCdwb2ludGVybW92ZScpLCB0aGlzKTtcblx0XHRcdGV2ZW50VHlwZSh0YXJnZXQsIHV0aWxzLnByZWZpeFBvaW50ZXJFdmVudCgncG9pbnRlcmNhbmNlbCcpLCB0aGlzKTtcblx0XHRcdGV2ZW50VHlwZSh0YXJnZXQsIHV0aWxzLnByZWZpeFBvaW50ZXJFdmVudCgncG9pbnRlcnVwJyksIHRoaXMpO1xuXHRcdH1cblxuXHRcdGlmICggdXRpbHMuaGFzVG91Y2ggJiYgIXRoaXMub3B0aW9ucy5kaXNhYmxlVG91Y2ggKSB7XG5cdFx0XHRldmVudFR5cGUodGhpcy53cmFwcGVyLCAndG91Y2hzdGFydCcsIHRoaXMpO1xuXHRcdFx0ZXZlbnRUeXBlKHRhcmdldCwgJ3RvdWNobW92ZScsIHRoaXMpO1xuXHRcdFx0ZXZlbnRUeXBlKHRhcmdldCwgJ3RvdWNoY2FuY2VsJywgdGhpcyk7XG5cdFx0XHRldmVudFR5cGUodGFyZ2V0LCAndG91Y2hlbmQnLCB0aGlzKTtcblx0XHR9XG5cblx0XHRldmVudFR5cGUodGhpcy5zY3JvbGxlciwgJ3RyYW5zaXRpb25lbmQnLCB0aGlzKTtcblx0XHRldmVudFR5cGUodGhpcy5zY3JvbGxlciwgJ3dlYmtpdFRyYW5zaXRpb25FbmQnLCB0aGlzKTtcblx0XHRldmVudFR5cGUodGhpcy5zY3JvbGxlciwgJ29UcmFuc2l0aW9uRW5kJywgdGhpcyk7XG5cdFx0ZXZlbnRUeXBlKHRoaXMuc2Nyb2xsZXIsICdNU1RyYW5zaXRpb25FbmQnLCB0aGlzKTtcblx0fSxcblxuXHRnZXRDb21wdXRlZFBvc2l0aW9uOiBmdW5jdGlvbiAoKSB7XG5cdFx0dmFyIG1hdHJpeCA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRoaXMuc2Nyb2xsZXIsIG51bGwpLFxuXHRcdFx0eCwgeTtcblxuXHRcdGlmICggdGhpcy5vcHRpb25zLnVzZVRyYW5zZm9ybSApIHtcblx0XHRcdG1hdHJpeCA9IG1hdHJpeFt1dGlscy5zdHlsZS50cmFuc2Zvcm1dLnNwbGl0KCcpJylbMF0uc3BsaXQoJywgJyk7XG5cdFx0XHR4ID0gKyhtYXRyaXhbMTJdIHx8IG1hdHJpeFs0XSk7XG5cdFx0XHR5ID0gKyhtYXRyaXhbMTNdIHx8IG1hdHJpeFs1XSk7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHggPSArbWF0cml4LmxlZnQucmVwbGFjZSgvW14tXFxkLl0vZywgJycpO1xuXHRcdFx0eSA9ICttYXRyaXgudG9wLnJlcGxhY2UoL1teLVxcZC5dL2csICcnKTtcblx0XHR9XG5cblx0XHRyZXR1cm4geyB4OiB4LCB5OiB5IH07XG5cdH0sXG5cdF9pbml0SW5kaWNhdG9yczogZnVuY3Rpb24gKCkge1xuXHRcdHZhciBpbnRlcmFjdGl2ZSA9IHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZVNjcm9sbGJhcnMsXG5cdFx0XHRjdXN0b21TdHlsZSA9IHR5cGVvZiB0aGlzLm9wdGlvbnMuc2Nyb2xsYmFycyAhPSAnc3RyaW5nJyxcblx0XHRcdGluZGljYXRvcnMgPSBbXSxcblx0XHRcdGluZGljYXRvcjtcblxuXHRcdHZhciB0aGF0ID0gdGhpcztcblxuXHRcdHRoaXMuaW5kaWNhdG9ycyA9IFtdO1xuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuc2Nyb2xsYmFycyApIHtcblx0XHRcdC8vIFZlcnRpY2FsIHNjcm9sbGJhclxuXHRcdFx0aWYgKCB0aGlzLm9wdGlvbnMuc2Nyb2xsWSApIHtcblx0XHRcdFx0aW5kaWNhdG9yID0ge1xuXHRcdFx0XHRcdGVsOiBjcmVhdGVEZWZhdWx0U2Nyb2xsYmFyKCd2JywgaW50ZXJhY3RpdmUsIHRoaXMub3B0aW9ucy5zY3JvbGxiYXJzKSxcblx0XHRcdFx0XHRpbnRlcmFjdGl2ZTogaW50ZXJhY3RpdmUsXG5cdFx0XHRcdFx0ZGVmYXVsdFNjcm9sbGJhcnM6IHRydWUsXG5cdFx0XHRcdFx0Y3VzdG9tU3R5bGU6IGN1c3RvbVN0eWxlLFxuXHRcdFx0XHRcdHJlc2l6ZTogdGhpcy5vcHRpb25zLnJlc2l6ZVNjcm9sbGJhcnMsXG5cdFx0XHRcdFx0c2hyaW5rOiB0aGlzLm9wdGlvbnMuc2hyaW5rU2Nyb2xsYmFycyxcblx0XHRcdFx0XHRmYWRlOiB0aGlzLm9wdGlvbnMuZmFkZVNjcm9sbGJhcnMsXG5cdFx0XHRcdFx0bGlzdGVuWDogZmFsc2Vcblx0XHRcdFx0fTtcblxuXHRcdFx0XHR0aGlzLndyYXBwZXIuYXBwZW5kQ2hpbGQoaW5kaWNhdG9yLmVsKTtcblx0XHRcdFx0aW5kaWNhdG9ycy5wdXNoKGluZGljYXRvcik7XG5cdFx0XHR9XG5cblx0XHRcdC8vIEhvcml6b250YWwgc2Nyb2xsYmFyXG5cdFx0XHRpZiAoIHRoaXMub3B0aW9ucy5zY3JvbGxYICkge1xuXHRcdFx0XHRpbmRpY2F0b3IgPSB7XG5cdFx0XHRcdFx0ZWw6IGNyZWF0ZURlZmF1bHRTY3JvbGxiYXIoJ2gnLCBpbnRlcmFjdGl2ZSwgdGhpcy5vcHRpb25zLnNjcm9sbGJhcnMpLFxuXHRcdFx0XHRcdGludGVyYWN0aXZlOiBpbnRlcmFjdGl2ZSxcblx0XHRcdFx0XHRkZWZhdWx0U2Nyb2xsYmFyczogdHJ1ZSxcblx0XHRcdFx0XHRjdXN0b21TdHlsZTogY3VzdG9tU3R5bGUsXG5cdFx0XHRcdFx0cmVzaXplOiB0aGlzLm9wdGlvbnMucmVzaXplU2Nyb2xsYmFycyxcblx0XHRcdFx0XHRzaHJpbms6IHRoaXMub3B0aW9ucy5zaHJpbmtTY3JvbGxiYXJzLFxuXHRcdFx0XHRcdGZhZGU6IHRoaXMub3B0aW9ucy5mYWRlU2Nyb2xsYmFycyxcblx0XHRcdFx0XHRsaXN0ZW5ZOiBmYWxzZVxuXHRcdFx0XHR9O1xuXG5cdFx0XHRcdHRoaXMud3JhcHBlci5hcHBlbmRDaGlsZChpbmRpY2F0b3IuZWwpO1xuXHRcdFx0XHRpbmRpY2F0b3JzLnB1c2goaW5kaWNhdG9yKTtcblx0XHRcdH1cblx0XHR9XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy5pbmRpY2F0b3JzICkge1xuXHRcdFx0Ly8gVE9ETzogY2hlY2sgY29uY2F0IGNvbXBhdGliaWxpdHlcblx0XHRcdGluZGljYXRvcnMgPSBpbmRpY2F0b3JzLmNvbmNhdCh0aGlzLm9wdGlvbnMuaW5kaWNhdG9ycyk7XG5cdFx0fVxuXG5cdFx0Zm9yICggdmFyIGkgPSBpbmRpY2F0b3JzLmxlbmd0aDsgaS0tOyApIHtcblx0XHRcdHRoaXMuaW5kaWNhdG9ycy5wdXNoKCBuZXcgSW5kaWNhdG9yKHRoaXMsIGluZGljYXRvcnNbaV0pICk7XG5cdFx0fVxuXG5cdFx0Ly8gVE9ETzogY2hlY2sgaWYgd2UgY2FuIHVzZSBhcnJheS5tYXAgKHdpZGUgY29tcGF0aWJpbGl0eSBhbmQgcGVyZm9ybWFuY2UgaXNzdWVzKVxuXHRcdGZ1bmN0aW9uIF9pbmRpY2F0b3JzTWFwIChmbikge1xuXHRcdFx0aWYgKHRoYXQuaW5kaWNhdG9ycykge1xuXHRcdFx0XHRmb3IgKCB2YXIgaSA9IHRoYXQuaW5kaWNhdG9ycy5sZW5ndGg7IGktLTsgKSB7XG5cdFx0XHRcdFx0Zm4uY2FsbCh0aGF0LmluZGljYXRvcnNbaV0pO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuZmFkZVNjcm9sbGJhcnMgKSB7XG5cdFx0XHR0aGlzLm9uKCdzY3JvbGxFbmQnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdF9pbmRpY2F0b3JzTWFwKGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0XHR0aGlzLmZhZGUoKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblxuXHRcdFx0dGhpcy5vbignc2Nyb2xsQ2FuY2VsJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRfaW5kaWNhdG9yc01hcChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0dGhpcy5mYWRlKCk7XG5cdFx0XHRcdH0pO1xuXHRcdFx0fSk7XG5cblx0XHRcdHRoaXMub24oJ3Njcm9sbFN0YXJ0JywgZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRfaW5kaWNhdG9yc01hcChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0dGhpcy5mYWRlKDEpO1xuXHRcdFx0XHR9KTtcblx0XHRcdH0pO1xuXG5cdFx0XHR0aGlzLm9uKCdiZWZvcmVTY3JvbGxTdGFydCcsIGZ1bmN0aW9uICgpIHtcblx0XHRcdFx0X2luZGljYXRvcnNNYXAoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHRcdHRoaXMuZmFkZSgxLCB0cnVlKTtcblx0XHRcdFx0fSk7XG5cdFx0XHR9KTtcblx0XHR9XG5cblxuXHRcdHRoaXMub24oJ3JlZnJlc2gnLCBmdW5jdGlvbiAoKSB7XG5cdFx0XHRfaW5kaWNhdG9yc01hcChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHRoaXMucmVmcmVzaCgpO1xuXHRcdFx0fSk7XG5cdFx0fSk7XG5cblx0XHR0aGlzLm9uKCdkZXN0cm95JywgZnVuY3Rpb24gKCkge1xuXHRcdFx0X2luZGljYXRvcnNNYXAoZnVuY3Rpb24gKCkge1xuXHRcdFx0XHR0aGlzLmRlc3Ryb3koKTtcblx0XHRcdH0pO1xuXG5cdFx0XHRkZWxldGUgdGhpcy5pbmRpY2F0b3JzO1xuXHRcdH0pO1xuXHR9LFxuXG5cdF9pbml0V2hlZWw6IGZ1bmN0aW9uICgpIHtcblx0XHR1dGlscy5hZGRFdmVudCh0aGlzLndyYXBwZXIsICd3aGVlbCcsIHRoaXMpO1xuXHRcdHV0aWxzLmFkZEV2ZW50KHRoaXMud3JhcHBlciwgJ21vdXNld2hlZWwnLCB0aGlzKTtcblx0XHR1dGlscy5hZGRFdmVudCh0aGlzLndyYXBwZXIsICdET01Nb3VzZVNjcm9sbCcsIHRoaXMpO1xuXG5cdFx0dGhpcy5vbignZGVzdHJveScsIGZ1bmN0aW9uICgpIHtcblx0XHRcdGNsZWFyVGltZW91dCh0aGlzLndoZWVsVGltZW91dCk7XG5cdFx0XHR0aGlzLndoZWVsVGltZW91dCA9IG51bGw7XG5cdFx0XHR1dGlscy5yZW1vdmVFdmVudCh0aGlzLndyYXBwZXIsICd3aGVlbCcsIHRoaXMpO1xuXHRcdFx0dXRpbHMucmVtb3ZlRXZlbnQodGhpcy53cmFwcGVyLCAnbW91c2V3aGVlbCcsIHRoaXMpO1xuXHRcdFx0dXRpbHMucmVtb3ZlRXZlbnQodGhpcy53cmFwcGVyLCAnRE9NTW91c2VTY3JvbGwnLCB0aGlzKTtcblx0XHR9KTtcblx0fSxcblxuXHRfd2hlZWw6IGZ1bmN0aW9uIChlKSB7XG5cdFx0aWYgKCAhdGhpcy5lbmFibGVkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGUucHJldmVudERlZmF1bHQoKTtcblxuXHRcdHZhciB3aGVlbERlbHRhWCwgd2hlZWxEZWx0YVksXG5cdFx0XHRuZXdYLCBuZXdZLFxuXHRcdFx0dGhhdCA9IHRoaXM7XG5cblx0XHRpZiAoIHRoaXMud2hlZWxUaW1lb3V0ID09PSB1bmRlZmluZWQgKSB7XG5cdFx0XHR0aGF0Ll9leGVjRXZlbnQoJ3Njcm9sbFN0YXJ0Jyk7XG5cdFx0fVxuXG5cdFx0Ly8gRXhlY3V0ZSB0aGUgc2Nyb2xsRW5kIGV2ZW50IGFmdGVyIDQwMG1zIHRoZSB3aGVlbCBzdG9wcGVkIHNjcm9sbGluZ1xuXHRcdGNsZWFyVGltZW91dCh0aGlzLndoZWVsVGltZW91dCk7XG5cdFx0dGhpcy53aGVlbFRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcblx0XHRcdGlmKCF0aGF0Lm9wdGlvbnMuc25hcCkge1xuXHRcdFx0XHR0aGF0Ll9leGVjRXZlbnQoJ3Njcm9sbEVuZCcpO1xuXHRcdFx0fVxuXHRcdFx0dGhhdC53aGVlbFRpbWVvdXQgPSB1bmRlZmluZWQ7XG5cdFx0fSwgNDAwKTtcblxuXHRcdGlmICggJ2RlbHRhWCcgaW4gZSApIHtcblx0XHRcdGlmIChlLmRlbHRhTW9kZSA9PT0gMSkge1xuXHRcdFx0XHR3aGVlbERlbHRhWCA9IC1lLmRlbHRhWCAqIHRoaXMub3B0aW9ucy5tb3VzZVdoZWVsU3BlZWQ7XG5cdFx0XHRcdHdoZWVsRGVsdGFZID0gLWUuZGVsdGFZICogdGhpcy5vcHRpb25zLm1vdXNlV2hlZWxTcGVlZDtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHdoZWVsRGVsdGFYID0gLWUuZGVsdGFYO1xuXHRcdFx0XHR3aGVlbERlbHRhWSA9IC1lLmRlbHRhWTtcblx0XHRcdH1cblx0XHR9IGVsc2UgaWYgKCAnd2hlZWxEZWx0YVgnIGluIGUgKSB7XG5cdFx0XHR3aGVlbERlbHRhWCA9IGUud2hlZWxEZWx0YVggLyAxMjAgKiB0aGlzLm9wdGlvbnMubW91c2VXaGVlbFNwZWVkO1xuXHRcdFx0d2hlZWxEZWx0YVkgPSBlLndoZWVsRGVsdGFZIC8gMTIwICogdGhpcy5vcHRpb25zLm1vdXNlV2hlZWxTcGVlZDtcblx0XHR9IGVsc2UgaWYgKCAnd2hlZWxEZWx0YScgaW4gZSApIHtcblx0XHRcdHdoZWVsRGVsdGFYID0gd2hlZWxEZWx0YVkgPSBlLndoZWVsRGVsdGEgLyAxMjAgKiB0aGlzLm9wdGlvbnMubW91c2VXaGVlbFNwZWVkO1xuXHRcdH0gZWxzZSBpZiAoICdkZXRhaWwnIGluIGUgKSB7XG5cdFx0XHR3aGVlbERlbHRhWCA9IHdoZWVsRGVsdGFZID0gLWUuZGV0YWlsIC8gMyAqIHRoaXMub3B0aW9ucy5tb3VzZVdoZWVsU3BlZWQ7XG5cdFx0fSBlbHNlIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR3aGVlbERlbHRhWCAqPSB0aGlzLm9wdGlvbnMuaW52ZXJ0V2hlZWxEaXJlY3Rpb247XG5cdFx0d2hlZWxEZWx0YVkgKj0gdGhpcy5vcHRpb25zLmludmVydFdoZWVsRGlyZWN0aW9uO1xuXG5cdFx0aWYgKCAhdGhpcy5oYXNWZXJ0aWNhbFNjcm9sbCApIHtcblx0XHRcdHdoZWVsRGVsdGFYID0gd2hlZWxEZWx0YVk7XG5cdFx0XHR3aGVlbERlbHRhWSA9IDA7XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMuc25hcCApIHtcblx0XHRcdG5ld1ggPSB0aGlzLmN1cnJlbnRQYWdlLnBhZ2VYO1xuXHRcdFx0bmV3WSA9IHRoaXMuY3VycmVudFBhZ2UucGFnZVk7XG5cblx0XHRcdGlmICggd2hlZWxEZWx0YVggPiAwICkge1xuXHRcdFx0XHRuZXdYLS07XG5cdFx0XHR9IGVsc2UgaWYgKCB3aGVlbERlbHRhWCA8IDAgKSB7XG5cdFx0XHRcdG5ld1grKztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB3aGVlbERlbHRhWSA+IDAgKSB7XG5cdFx0XHRcdG5ld1ktLTtcblx0XHRcdH0gZWxzZSBpZiAoIHdoZWVsRGVsdGFZIDwgMCApIHtcblx0XHRcdFx0bmV3WSsrO1xuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmdvVG9QYWdlKG5ld1gsIG5ld1kpO1xuXG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0bmV3WCA9IHRoaXMueCArIE1hdGgucm91bmQodGhpcy5oYXNIb3Jpem9udGFsU2Nyb2xsID8gd2hlZWxEZWx0YVggOiAwKTtcblx0XHRuZXdZID0gdGhpcy55ICsgTWF0aC5yb3VuZCh0aGlzLmhhc1ZlcnRpY2FsU2Nyb2xsID8gd2hlZWxEZWx0YVkgOiAwKTtcblxuXHRcdHRoaXMuZGlyZWN0aW9uWCA9IHdoZWVsRGVsdGFYID4gMCA/IC0xIDogd2hlZWxEZWx0YVggPCAwID8gMSA6IDA7XG5cdFx0dGhpcy5kaXJlY3Rpb25ZID0gd2hlZWxEZWx0YVkgPiAwID8gLTEgOiB3aGVlbERlbHRhWSA8IDAgPyAxIDogMDtcblxuXHRcdGlmICggbmV3WCA+IDAgKSB7XG5cdFx0XHRuZXdYID0gMDtcblx0XHR9IGVsc2UgaWYgKCBuZXdYIDwgdGhpcy5tYXhTY3JvbGxYICkge1xuXHRcdFx0bmV3WCA9IHRoaXMubWF4U2Nyb2xsWDtcblx0XHR9XG5cblx0XHRpZiAoIG5ld1kgPiAwICkge1xuXHRcdFx0bmV3WSA9IDA7XG5cdFx0fSBlbHNlIGlmICggbmV3WSA8IHRoaXMubWF4U2Nyb2xsWSApIHtcblx0XHRcdG5ld1kgPSB0aGlzLm1heFNjcm9sbFk7XG5cdFx0fVxuXG5cdFx0dGhpcy5zY3JvbGxUbyhuZXdYLCBuZXdZLCAwKTtcblxuLy8gSU5TRVJUIFBPSU5UOiBfd2hlZWxcblx0fSxcblxuXHRfaW5pdFNuYXA6IGZ1bmN0aW9uICgpIHtcblx0XHR0aGlzLmN1cnJlbnRQYWdlID0ge307XG5cblx0XHRpZiAoIHR5cGVvZiB0aGlzLm9wdGlvbnMuc25hcCA9PSAnc3RyaW5nJyApIHtcblx0XHRcdHRoaXMub3B0aW9ucy5zbmFwID0gdGhpcy5zY3JvbGxlci5xdWVyeVNlbGVjdG9yQWxsKHRoaXMub3B0aW9ucy5zbmFwKTtcblx0XHR9XG5cblx0XHR0aGlzLm9uKCdyZWZyZXNoJywgZnVuY3Rpb24gKCkge1xuXHRcdFx0dmFyIGkgPSAwLCBsLFxuXHRcdFx0XHRtID0gMCwgbixcblx0XHRcdFx0Y3gsIGN5LFxuXHRcdFx0XHR4ID0gMCwgeSxcblx0XHRcdFx0c3RlcFggPSB0aGlzLm9wdGlvbnMuc25hcFN0ZXBYIHx8IHRoaXMud3JhcHBlcldpZHRoLFxuXHRcdFx0XHRzdGVwWSA9IHRoaXMub3B0aW9ucy5zbmFwU3RlcFkgfHwgdGhpcy53cmFwcGVySGVpZ2h0LFxuXHRcdFx0XHRlbDtcblxuXHRcdFx0dGhpcy5wYWdlcyA9IFtdO1xuXG5cdFx0XHRpZiAoICF0aGlzLndyYXBwZXJXaWR0aCB8fCAhdGhpcy53cmFwcGVySGVpZ2h0IHx8ICF0aGlzLnNjcm9sbGVyV2lkdGggfHwgIXRoaXMuc2Nyb2xsZXJIZWlnaHQgKSB7XG5cdFx0XHRcdHJldHVybjtcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB0aGlzLm9wdGlvbnMuc25hcCA9PT0gdHJ1ZSApIHtcblx0XHRcdFx0Y3ggPSBNYXRoLnJvdW5kKCBzdGVwWCAvIDIgKTtcblx0XHRcdFx0Y3kgPSBNYXRoLnJvdW5kKCBzdGVwWSAvIDIgKTtcblxuXHRcdFx0XHR3aGlsZSAoIHggPiAtdGhpcy5zY3JvbGxlcldpZHRoICkge1xuXHRcdFx0XHRcdHRoaXMucGFnZXNbaV0gPSBbXTtcblx0XHRcdFx0XHRsID0gMDtcblx0XHRcdFx0XHR5ID0gMDtcblxuXHRcdFx0XHRcdHdoaWxlICggeSA+IC10aGlzLnNjcm9sbGVySGVpZ2h0ICkge1xuXHRcdFx0XHRcdFx0dGhpcy5wYWdlc1tpXVtsXSA9IHtcblx0XHRcdFx0XHRcdFx0eDogTWF0aC5tYXgoeCwgdGhpcy5tYXhTY3JvbGxYKSxcblx0XHRcdFx0XHRcdFx0eTogTWF0aC5tYXgoeSwgdGhpcy5tYXhTY3JvbGxZKSxcblx0XHRcdFx0XHRcdFx0d2lkdGg6IHN0ZXBYLFxuXHRcdFx0XHRcdFx0XHRoZWlnaHQ6IHN0ZXBZLFxuXHRcdFx0XHRcdFx0XHRjeDogeCAtIGN4LFxuXHRcdFx0XHRcdFx0XHRjeTogeSAtIGN5XG5cdFx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0XHR5IC09IHN0ZXBZO1xuXHRcdFx0XHRcdFx0bCsrO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdHggLT0gc3RlcFg7XG5cdFx0XHRcdFx0aSsrO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRlbCA9IHRoaXMub3B0aW9ucy5zbmFwO1xuXHRcdFx0XHRsID0gZWwubGVuZ3RoO1xuXHRcdFx0XHRuID0gLTE7XG5cblx0XHRcdFx0Zm9yICggOyBpIDwgbDsgaSsrICkge1xuXHRcdFx0XHRcdGlmICggaSA9PT0gMCB8fCBlbFtpXS5vZmZzZXRMZWZ0IDw9IGVsW2ktMV0ub2Zmc2V0TGVmdCApIHtcblx0XHRcdFx0XHRcdG0gPSAwO1xuXHRcdFx0XHRcdFx0bisrO1xuXHRcdFx0XHRcdH1cblxuXHRcdFx0XHRcdGlmICggIXRoaXMucGFnZXNbbV0gKSB7XG5cdFx0XHRcdFx0XHR0aGlzLnBhZ2VzW21dID0gW107XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0eCA9IE1hdGgubWF4KC1lbFtpXS5vZmZzZXRMZWZ0LCB0aGlzLm1heFNjcm9sbFgpO1xuXHRcdFx0XHRcdHkgPSBNYXRoLm1heCgtZWxbaV0ub2Zmc2V0VG9wLCB0aGlzLm1heFNjcm9sbFkpO1xuXHRcdFx0XHRcdGN4ID0geCAtIE1hdGgucm91bmQoZWxbaV0ub2Zmc2V0V2lkdGggLyAyKTtcblx0XHRcdFx0XHRjeSA9IHkgLSBNYXRoLnJvdW5kKGVsW2ldLm9mZnNldEhlaWdodCAvIDIpO1xuXG5cdFx0XHRcdFx0dGhpcy5wYWdlc1ttXVtuXSA9IHtcblx0XHRcdFx0XHRcdHg6IHgsXG5cdFx0XHRcdFx0XHR5OiB5LFxuXHRcdFx0XHRcdFx0d2lkdGg6IGVsW2ldLm9mZnNldFdpZHRoLFxuXHRcdFx0XHRcdFx0aGVpZ2h0OiBlbFtpXS5vZmZzZXRIZWlnaHQsXG5cdFx0XHRcdFx0XHRjeDogY3gsXG5cdFx0XHRcdFx0XHRjeTogY3lcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0aWYgKCB4ID4gdGhpcy5tYXhTY3JvbGxYICkge1xuXHRcdFx0XHRcdFx0bSsrO1xuXHRcdFx0XHRcdH1cblx0XHRcdFx0fVxuXHRcdFx0fVxuXG5cdFx0XHR0aGlzLmdvVG9QYWdlKHRoaXMuY3VycmVudFBhZ2UucGFnZVggfHwgMCwgdGhpcy5jdXJyZW50UGFnZS5wYWdlWSB8fCAwLCAwKTtcblxuXHRcdFx0Ly8gVXBkYXRlIHNuYXAgdGhyZXNob2xkIGlmIG5lZWRlZFxuXHRcdFx0aWYgKCB0aGlzLm9wdGlvbnMuc25hcFRocmVzaG9sZCAlIDEgPT09IDAgKSB7XG5cdFx0XHRcdHRoaXMuc25hcFRocmVzaG9sZFggPSB0aGlzLm9wdGlvbnMuc25hcFRocmVzaG9sZDtcblx0XHRcdFx0dGhpcy5zbmFwVGhyZXNob2xkWSA9IHRoaXMub3B0aW9ucy5zbmFwVGhyZXNob2xkO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5zbmFwVGhyZXNob2xkWCA9IE1hdGgucm91bmQodGhpcy5wYWdlc1t0aGlzLmN1cnJlbnRQYWdlLnBhZ2VYXVt0aGlzLmN1cnJlbnRQYWdlLnBhZ2VZXS53aWR0aCAqIHRoaXMub3B0aW9ucy5zbmFwVGhyZXNob2xkKTtcblx0XHRcdFx0dGhpcy5zbmFwVGhyZXNob2xkWSA9IE1hdGgucm91bmQodGhpcy5wYWdlc1t0aGlzLmN1cnJlbnRQYWdlLnBhZ2VYXVt0aGlzLmN1cnJlbnRQYWdlLnBhZ2VZXS5oZWlnaHQgKiB0aGlzLm9wdGlvbnMuc25hcFRocmVzaG9sZCk7XG5cdFx0XHR9XG5cdFx0fSk7XG5cblx0XHR0aGlzLm9uKCdmbGljaycsIGZ1bmN0aW9uICgpIHtcblx0XHRcdHZhciB0aW1lID0gdGhpcy5vcHRpb25zLnNuYXBTcGVlZCB8fCBNYXRoLm1heChcblx0XHRcdFx0XHRNYXRoLm1heChcblx0XHRcdFx0XHRcdE1hdGgubWluKE1hdGguYWJzKHRoaXMueCAtIHRoaXMuc3RhcnRYKSwgMTAwMCksXG5cdFx0XHRcdFx0XHRNYXRoLm1pbihNYXRoLmFicyh0aGlzLnkgLSB0aGlzLnN0YXJ0WSksIDEwMDApXG5cdFx0XHRcdFx0KSwgMzAwKTtcblxuXHRcdFx0dGhpcy5nb1RvUGFnZShcblx0XHRcdFx0dGhpcy5jdXJyZW50UGFnZS5wYWdlWCArIHRoaXMuZGlyZWN0aW9uWCxcblx0XHRcdFx0dGhpcy5jdXJyZW50UGFnZS5wYWdlWSArIHRoaXMuZGlyZWN0aW9uWSxcblx0XHRcdFx0dGltZVxuXHRcdFx0KTtcblx0XHR9KTtcblx0fSxcblxuXHRfbmVhcmVzdFNuYXA6IGZ1bmN0aW9uICh4LCB5KSB7XG5cdFx0aWYgKCAhdGhpcy5wYWdlcy5sZW5ndGggKSB7XG5cdFx0XHRyZXR1cm4geyB4OiAwLCB5OiAwLCBwYWdlWDogMCwgcGFnZVk6IDAgfTtcblx0XHR9XG5cblx0XHR2YXIgaSA9IDAsXG5cdFx0XHRsID0gdGhpcy5wYWdlcy5sZW5ndGgsXG5cdFx0XHRtID0gMDtcblxuXHRcdC8vIENoZWNrIGlmIHdlIGV4Y2VlZGVkIHRoZSBzbmFwIHRocmVzaG9sZFxuXHRcdGlmICggTWF0aC5hYnMoeCAtIHRoaXMuYWJzU3RhcnRYKSA8IHRoaXMuc25hcFRocmVzaG9sZFggJiZcblx0XHRcdE1hdGguYWJzKHkgLSB0aGlzLmFic1N0YXJ0WSkgPCB0aGlzLnNuYXBUaHJlc2hvbGRZICkge1xuXHRcdFx0cmV0dXJuIHRoaXMuY3VycmVudFBhZ2U7XG5cdFx0fVxuXG5cdFx0aWYgKCB4ID4gMCApIHtcblx0XHRcdHggPSAwO1xuXHRcdH0gZWxzZSBpZiAoIHggPCB0aGlzLm1heFNjcm9sbFggKSB7XG5cdFx0XHR4ID0gdGhpcy5tYXhTY3JvbGxYO1xuXHRcdH1cblxuXHRcdGlmICggeSA+IDAgKSB7XG5cdFx0XHR5ID0gMDtcblx0XHR9IGVsc2UgaWYgKCB5IDwgdGhpcy5tYXhTY3JvbGxZICkge1xuXHRcdFx0eSA9IHRoaXMubWF4U2Nyb2xsWTtcblx0XHR9XG5cblx0XHRmb3IgKCA7IGkgPCBsOyBpKysgKSB7XG5cdFx0XHRpZiAoIHggPj0gdGhpcy5wYWdlc1tpXVswXS5jeCApIHtcblx0XHRcdFx0eCA9IHRoaXMucGFnZXNbaV1bMF0ueDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0bCA9IHRoaXMucGFnZXNbaV0ubGVuZ3RoO1xuXG5cdFx0Zm9yICggOyBtIDwgbDsgbSsrICkge1xuXHRcdFx0aWYgKCB5ID49IHRoaXMucGFnZXNbMF1bbV0uY3kgKSB7XG5cdFx0XHRcdHkgPSB0aGlzLnBhZ2VzWzBdW21dLnk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdGlmICggaSA9PSB0aGlzLmN1cnJlbnRQYWdlLnBhZ2VYICkge1xuXHRcdFx0aSArPSB0aGlzLmRpcmVjdGlvblg7XG5cblx0XHRcdGlmICggaSA8IDAgKSB7XG5cdFx0XHRcdGkgPSAwO1xuXHRcdFx0fSBlbHNlIGlmICggaSA+PSB0aGlzLnBhZ2VzLmxlbmd0aCApIHtcblx0XHRcdFx0aSA9IHRoaXMucGFnZXMubGVuZ3RoIC0gMTtcblx0XHRcdH1cblxuXHRcdFx0eCA9IHRoaXMucGFnZXNbaV1bMF0ueDtcblx0XHR9XG5cblx0XHRpZiAoIG0gPT0gdGhpcy5jdXJyZW50UGFnZS5wYWdlWSApIHtcblx0XHRcdG0gKz0gdGhpcy5kaXJlY3Rpb25ZO1xuXG5cdFx0XHRpZiAoIG0gPCAwICkge1xuXHRcdFx0XHRtID0gMDtcblx0XHRcdH0gZWxzZSBpZiAoIG0gPj0gdGhpcy5wYWdlc1swXS5sZW5ndGggKSB7XG5cdFx0XHRcdG0gPSB0aGlzLnBhZ2VzWzBdLmxlbmd0aCAtIDE7XG5cdFx0XHR9XG5cblx0XHRcdHkgPSB0aGlzLnBhZ2VzWzBdW21dLnk7XG5cdFx0fVxuXG5cdFx0cmV0dXJuIHtcblx0XHRcdHg6IHgsXG5cdFx0XHR5OiB5LFxuXHRcdFx0cGFnZVg6IGksXG5cdFx0XHRwYWdlWTogbVxuXHRcdH07XG5cdH0sXG5cblx0Z29Ub1BhZ2U6IGZ1bmN0aW9uICh4LCB5LCB0aW1lLCBlYXNpbmcpIHtcblx0XHRlYXNpbmcgPSBlYXNpbmcgfHwgdGhpcy5vcHRpb25zLmJvdW5jZUVhc2luZztcblxuXHRcdGlmICggeCA+PSB0aGlzLnBhZ2VzLmxlbmd0aCApIHtcblx0XHRcdHggPSB0aGlzLnBhZ2VzLmxlbmd0aCAtIDE7XG5cdFx0fSBlbHNlIGlmICggeCA8IDAgKSB7XG5cdFx0XHR4ID0gMDtcblx0XHR9XG5cblx0XHRpZiAoIHkgPj0gdGhpcy5wYWdlc1t4XS5sZW5ndGggKSB7XG5cdFx0XHR5ID0gdGhpcy5wYWdlc1t4XS5sZW5ndGggLSAxO1xuXHRcdH0gZWxzZSBpZiAoIHkgPCAwICkge1xuXHRcdFx0eSA9IDA7XG5cdFx0fVxuXG5cdFx0dmFyIHBvc1ggPSB0aGlzLnBhZ2VzW3hdW3ldLngsXG5cdFx0XHRwb3NZID0gdGhpcy5wYWdlc1t4XVt5XS55O1xuXG5cdFx0dGltZSA9IHRpbWUgPT09IHVuZGVmaW5lZCA/IHRoaXMub3B0aW9ucy5zbmFwU3BlZWQgfHwgTWF0aC5tYXgoXG5cdFx0XHRNYXRoLm1heChcblx0XHRcdFx0TWF0aC5taW4oTWF0aC5hYnMocG9zWCAtIHRoaXMueCksIDEwMDApLFxuXHRcdFx0XHRNYXRoLm1pbihNYXRoLmFicyhwb3NZIC0gdGhpcy55KSwgMTAwMClcblx0XHRcdCksIDMwMCkgOiB0aW1lO1xuXG5cdFx0dGhpcy5jdXJyZW50UGFnZSA9IHtcblx0XHRcdHg6IHBvc1gsXG5cdFx0XHR5OiBwb3NZLFxuXHRcdFx0cGFnZVg6IHgsXG5cdFx0XHRwYWdlWTogeVxuXHRcdH07XG5cblx0XHR0aGlzLnNjcm9sbFRvKHBvc1gsIHBvc1ksIHRpbWUsIGVhc2luZyk7XG5cdH0sXG5cblx0bmV4dDogZnVuY3Rpb24gKHRpbWUsIGVhc2luZykge1xuXHRcdHZhciB4ID0gdGhpcy5jdXJyZW50UGFnZS5wYWdlWCxcblx0XHRcdHkgPSB0aGlzLmN1cnJlbnRQYWdlLnBhZ2VZO1xuXG5cdFx0eCsrO1xuXG5cdFx0aWYgKCB4ID49IHRoaXMucGFnZXMubGVuZ3RoICYmIHRoaXMuaGFzVmVydGljYWxTY3JvbGwgKSB7XG5cdFx0XHR4ID0gMDtcblx0XHRcdHkrKztcblx0XHR9XG5cblx0XHR0aGlzLmdvVG9QYWdlKHgsIHksIHRpbWUsIGVhc2luZyk7XG5cdH0sXG5cblx0cHJldjogZnVuY3Rpb24gKHRpbWUsIGVhc2luZykge1xuXHRcdHZhciB4ID0gdGhpcy5jdXJyZW50UGFnZS5wYWdlWCxcblx0XHRcdHkgPSB0aGlzLmN1cnJlbnRQYWdlLnBhZ2VZO1xuXG5cdFx0eC0tO1xuXG5cdFx0aWYgKCB4IDwgMCAmJiB0aGlzLmhhc1ZlcnRpY2FsU2Nyb2xsICkge1xuXHRcdFx0eCA9IDA7XG5cdFx0XHR5LS07XG5cdFx0fVxuXG5cdFx0dGhpcy5nb1RvUGFnZSh4LCB5LCB0aW1lLCBlYXNpbmcpO1xuXHR9LFxuXG5cdF9pbml0S2V5czogZnVuY3Rpb24gKGUpIHtcblx0XHQvLyBkZWZhdWx0IGtleSBiaW5kaW5nc1xuXHRcdHZhciBrZXlzID0ge1xuXHRcdFx0cGFnZVVwOiAzMyxcblx0XHRcdHBhZ2VEb3duOiAzNCxcblx0XHRcdGVuZDogMzUsXG5cdFx0XHRob21lOiAzNixcblx0XHRcdGxlZnQ6IDM3LFxuXHRcdFx0dXA6IDM4LFxuXHRcdFx0cmlnaHQ6IDM5LFxuXHRcdFx0ZG93bjogNDBcblx0XHR9O1xuXHRcdHZhciBpO1xuXG5cdFx0Ly8gaWYgeW91IGdpdmUgbWUgY2hhcmFjdGVycyBJIGdpdmUgeW91IGtleWNvZGVcblx0XHRpZiAoIHR5cGVvZiB0aGlzLm9wdGlvbnMua2V5QmluZGluZ3MgPT0gJ29iamVjdCcgKSB7XG5cdFx0XHRmb3IgKCBpIGluIHRoaXMub3B0aW9ucy5rZXlCaW5kaW5ncyApIHtcblx0XHRcdFx0aWYgKCB0eXBlb2YgdGhpcy5vcHRpb25zLmtleUJpbmRpbmdzW2ldID09ICdzdHJpbmcnICkge1xuXHRcdFx0XHRcdHRoaXMub3B0aW9ucy5rZXlCaW5kaW5nc1tpXSA9IHRoaXMub3B0aW9ucy5rZXlCaW5kaW5nc1tpXS50b1VwcGVyQ2FzZSgpLmNoYXJDb2RlQXQoMCk7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5vcHRpb25zLmtleUJpbmRpbmdzID0ge307XG5cdFx0fVxuXG5cdFx0Zm9yICggaSBpbiBrZXlzICkge1xuXHRcdFx0dGhpcy5vcHRpb25zLmtleUJpbmRpbmdzW2ldID0gdGhpcy5vcHRpb25zLmtleUJpbmRpbmdzW2ldIHx8IGtleXNbaV07XG5cdFx0fVxuXG5cdFx0dXRpbHMuYWRkRXZlbnQod2luZG93LCAna2V5ZG93bicsIHRoaXMpO1xuXG5cdFx0dGhpcy5vbignZGVzdHJveScsIGZ1bmN0aW9uICgpIHtcblx0XHRcdHV0aWxzLnJlbW92ZUV2ZW50KHdpbmRvdywgJ2tleWRvd24nLCB0aGlzKTtcblx0XHR9KTtcblx0fSxcblxuXHRfa2V5OiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICggIXRoaXMuZW5hYmxlZCApIHtcblx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHR2YXIgc25hcCA9IHRoaXMub3B0aW9ucy5zbmFwLFx0Ly8gd2UgYXJlIHVzaW5nIHRoaXMgYWxvdCwgYmV0dGVyIHRvIGNhY2hlIGl0XG5cdFx0XHRuZXdYID0gc25hcCA/IHRoaXMuY3VycmVudFBhZ2UucGFnZVggOiB0aGlzLngsXG5cdFx0XHRuZXdZID0gc25hcCA/IHRoaXMuY3VycmVudFBhZ2UucGFnZVkgOiB0aGlzLnksXG5cdFx0XHRub3cgPSB1dGlscy5nZXRUaW1lKCksXG5cdFx0XHRwcmV2VGltZSA9IHRoaXMua2V5VGltZSB8fCAwLFxuXHRcdFx0YWNjZWxlcmF0aW9uID0gMC4yNTAsXG5cdFx0XHRwb3M7XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy51c2VUcmFuc2l0aW9uICYmIHRoaXMuaXNJblRyYW5zaXRpb24gKSB7XG5cdFx0XHRwb3MgPSB0aGlzLmdldENvbXB1dGVkUG9zaXRpb24oKTtcblxuXHRcdFx0dGhpcy5fdHJhbnNsYXRlKE1hdGgucm91bmQocG9zLngpLCBNYXRoLnJvdW5kKHBvcy55KSk7XG5cdFx0XHR0aGlzLmlzSW5UcmFuc2l0aW9uID0gZmFsc2U7XG5cdFx0fVxuXG5cdFx0dGhpcy5rZXlBY2NlbGVyYXRpb24gPSBub3cgLSBwcmV2VGltZSA8IDIwMCA/IE1hdGgubWluKHRoaXMua2V5QWNjZWxlcmF0aW9uICsgYWNjZWxlcmF0aW9uLCA1MCkgOiAwO1xuXG5cdFx0c3dpdGNoICggZS5rZXlDb2RlICkge1xuXHRcdFx0Y2FzZSB0aGlzLm9wdGlvbnMua2V5QmluZGluZ3MucGFnZVVwOlxuXHRcdFx0XHRpZiAoIHRoaXMuaGFzSG9yaXpvbnRhbFNjcm9sbCAmJiAhdGhpcy5oYXNWZXJ0aWNhbFNjcm9sbCApIHtcblx0XHRcdFx0XHRuZXdYICs9IHNuYXAgPyAxIDogdGhpcy53cmFwcGVyV2lkdGg7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bmV3WSArPSBzbmFwID8gMSA6IHRoaXMud3JhcHBlckhlaWdodDtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgdGhpcy5vcHRpb25zLmtleUJpbmRpbmdzLnBhZ2VEb3duOlxuXHRcdFx0XHRpZiAoIHRoaXMuaGFzSG9yaXpvbnRhbFNjcm9sbCAmJiAhdGhpcy5oYXNWZXJ0aWNhbFNjcm9sbCApIHtcblx0XHRcdFx0XHRuZXdYIC09IHNuYXAgPyAxIDogdGhpcy53cmFwcGVyV2lkdGg7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0bmV3WSAtPSBzbmFwID8gMSA6IHRoaXMud3JhcHBlckhlaWdodDtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgdGhpcy5vcHRpb25zLmtleUJpbmRpbmdzLmVuZDpcblx0XHRcdFx0bmV3WCA9IHNuYXAgPyB0aGlzLnBhZ2VzLmxlbmd0aC0xIDogdGhpcy5tYXhTY3JvbGxYO1xuXHRcdFx0XHRuZXdZID0gc25hcCA/IHRoaXMucGFnZXNbMF0ubGVuZ3RoLTEgOiB0aGlzLm1heFNjcm9sbFk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSB0aGlzLm9wdGlvbnMua2V5QmluZGluZ3MuaG9tZTpcblx0XHRcdFx0bmV3WCA9IDA7XG5cdFx0XHRcdG5ld1kgPSAwO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgdGhpcy5vcHRpb25zLmtleUJpbmRpbmdzLmxlZnQ6XG5cdFx0XHRcdG5ld1ggKz0gc25hcCA/IC0xIDogNSArIHRoaXMua2V5QWNjZWxlcmF0aW9uPj4wO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgdGhpcy5vcHRpb25zLmtleUJpbmRpbmdzLnVwOlxuXHRcdFx0XHRuZXdZICs9IHNuYXAgPyAxIDogNSArIHRoaXMua2V5QWNjZWxlcmF0aW9uPj4wO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGNhc2UgdGhpcy5vcHRpb25zLmtleUJpbmRpbmdzLnJpZ2h0OlxuXHRcdFx0XHRuZXdYIC09IHNuYXAgPyAtMSA6IDUgKyB0aGlzLmtleUFjY2VsZXJhdGlvbj4+MDtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlIHRoaXMub3B0aW9ucy5rZXlCaW5kaW5ncy5kb3duOlxuXHRcdFx0XHRuZXdZIC09IHNuYXAgPyAxIDogNSArIHRoaXMua2V5QWNjZWxlcmF0aW9uPj4wO1xuXHRcdFx0XHRicmVhaztcblx0XHRcdGRlZmF1bHQ6XG5cdFx0XHRcdHJldHVybjtcblx0XHR9XG5cblx0XHRpZiAoIHNuYXAgKSB7XG5cdFx0XHR0aGlzLmdvVG9QYWdlKG5ld1gsIG5ld1kpO1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdGlmICggbmV3WCA+IDAgKSB7XG5cdFx0XHRuZXdYID0gMDtcblx0XHRcdHRoaXMua2V5QWNjZWxlcmF0aW9uID0gMDtcblx0XHR9IGVsc2UgaWYgKCBuZXdYIDwgdGhpcy5tYXhTY3JvbGxYICkge1xuXHRcdFx0bmV3WCA9IHRoaXMubWF4U2Nyb2xsWDtcblx0XHRcdHRoaXMua2V5QWNjZWxlcmF0aW9uID0gMDtcblx0XHR9XG5cblx0XHRpZiAoIG5ld1kgPiAwICkge1xuXHRcdFx0bmV3WSA9IDA7XG5cdFx0XHR0aGlzLmtleUFjY2VsZXJhdGlvbiA9IDA7XG5cdFx0fSBlbHNlIGlmICggbmV3WSA8IHRoaXMubWF4U2Nyb2xsWSApIHtcblx0XHRcdG5ld1kgPSB0aGlzLm1heFNjcm9sbFk7XG5cdFx0XHR0aGlzLmtleUFjY2VsZXJhdGlvbiA9IDA7XG5cdFx0fVxuXG5cdFx0dGhpcy5zY3JvbGxUbyhuZXdYLCBuZXdZLCAwKTtcblxuXHRcdHRoaXMua2V5VGltZSA9IG5vdztcblx0fSxcblxuXHRfYW5pbWF0ZTogZnVuY3Rpb24gKGRlc3RYLCBkZXN0WSwgZHVyYXRpb24sIGVhc2luZ0ZuKSB7XG5cdFx0dmFyIHRoYXQgPSB0aGlzLFxuXHRcdFx0c3RhcnRYID0gdGhpcy54LFxuXHRcdFx0c3RhcnRZID0gdGhpcy55LFxuXHRcdFx0c3RhcnRUaW1lID0gdXRpbHMuZ2V0VGltZSgpLFxuXHRcdFx0ZGVzdFRpbWUgPSBzdGFydFRpbWUgKyBkdXJhdGlvbjtcblxuXHRcdGZ1bmN0aW9uIHN0ZXAgKCkge1xuXHRcdFx0dmFyIG5vdyA9IHV0aWxzLmdldFRpbWUoKSxcblx0XHRcdFx0bmV3WCwgbmV3WSxcblx0XHRcdFx0ZWFzaW5nO1xuXG5cdFx0XHRpZiAoIG5vdyA+PSBkZXN0VGltZSApIHtcblx0XHRcdFx0dGhhdC5pc0FuaW1hdGluZyA9IGZhbHNlO1xuXHRcdFx0XHR0aGF0Ll90cmFuc2xhdGUoZGVzdFgsIGRlc3RZKTtcblxuXHRcdFx0XHRpZiAoICF0aGF0LnJlc2V0UG9zaXRpb24odGhhdC5vcHRpb25zLmJvdW5jZVRpbWUpICkge1xuXHRcdFx0XHRcdHRoYXQuX2V4ZWNFdmVudCgnc2Nyb2xsRW5kJyk7XG5cdFx0XHRcdH1cblxuXHRcdFx0XHRyZXR1cm47XG5cdFx0XHR9XG5cblx0XHRcdG5vdyA9ICggbm93IC0gc3RhcnRUaW1lICkgLyBkdXJhdGlvbjtcblx0XHRcdGVhc2luZyA9IGVhc2luZ0ZuKG5vdyk7XG5cdFx0XHRuZXdYID0gKCBkZXN0WCAtIHN0YXJ0WCApICogZWFzaW5nICsgc3RhcnRYO1xuXHRcdFx0bmV3WSA9ICggZGVzdFkgLSBzdGFydFkgKSAqIGVhc2luZyArIHN0YXJ0WTtcblx0XHRcdHRoYXQuX3RyYW5zbGF0ZShuZXdYLCBuZXdZKTtcblxuXHRcdFx0aWYgKCB0aGF0LmlzQW5pbWF0aW5nICkge1xuXHRcdFx0XHRyQUYoc3RlcCk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dGhpcy5pc0FuaW1hdGluZyA9IHRydWU7XG5cdFx0c3RlcCgpO1xuXHR9LFxuXHRoYW5kbGVFdmVudDogZnVuY3Rpb24gKGUpIHtcblx0XHRzd2l0Y2ggKCBlLnR5cGUgKSB7XG5cdFx0XHRjYXNlICd0b3VjaHN0YXJ0Jzpcblx0XHRcdGNhc2UgJ3BvaW50ZXJkb3duJzpcblx0XHRcdGNhc2UgJ01TUG9pbnRlckRvd24nOlxuXHRcdFx0Y2FzZSAnbW91c2Vkb3duJzpcblx0XHRcdFx0dGhpcy5fc3RhcnQoZSk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAndG91Y2htb3ZlJzpcblx0XHRcdGNhc2UgJ3BvaW50ZXJtb3ZlJzpcblx0XHRcdGNhc2UgJ01TUG9pbnRlck1vdmUnOlxuXHRcdFx0Y2FzZSAnbW91c2Vtb3ZlJzpcblx0XHRcdFx0dGhpcy5fbW92ZShlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICd0b3VjaGVuZCc6XG5cdFx0XHRjYXNlICdwb2ludGVydXAnOlxuXHRcdFx0Y2FzZSAnTVNQb2ludGVyVXAnOlxuXHRcdFx0Y2FzZSAnbW91c2V1cCc6XG5cdFx0XHRjYXNlICd0b3VjaGNhbmNlbCc6XG5cdFx0XHRjYXNlICdwb2ludGVyY2FuY2VsJzpcblx0XHRcdGNhc2UgJ01TUG9pbnRlckNhbmNlbCc6XG5cdFx0XHRjYXNlICdtb3VzZWNhbmNlbCc6XG5cdFx0XHRcdHRoaXMuX2VuZChlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdvcmllbnRhdGlvbmNoYW5nZSc6XG5cdFx0XHRjYXNlICdyZXNpemUnOlxuXHRcdFx0XHR0aGlzLl9yZXNpemUoKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICd0cmFuc2l0aW9uZW5kJzpcblx0XHRcdGNhc2UgJ3dlYmtpdFRyYW5zaXRpb25FbmQnOlxuXHRcdFx0Y2FzZSAnb1RyYW5zaXRpb25FbmQnOlxuXHRcdFx0Y2FzZSAnTVNUcmFuc2l0aW9uRW5kJzpcblx0XHRcdFx0dGhpcy5fdHJhbnNpdGlvbkVuZChlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICd3aGVlbCc6XG5cdFx0XHRjYXNlICdET01Nb3VzZVNjcm9sbCc6XG5cdFx0XHRjYXNlICdtb3VzZXdoZWVsJzpcblx0XHRcdFx0dGhpcy5fd2hlZWwoZSk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAna2V5ZG93bic6XG5cdFx0XHRcdHRoaXMuX2tleShlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICdjbGljayc6XG5cdFx0XHRcdGlmICggdGhpcy5lbmFibGVkICYmICFlLl9jb25zdHJ1Y3RlZCApIHtcblx0XHRcdFx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0XHRcdFx0ZS5zdG9wUHJvcGFnYXRpb24oKTtcblx0XHRcdFx0fVxuXHRcdFx0XHRicmVhaztcblx0XHR9XG5cdH1cbn07XG5mdW5jdGlvbiBjcmVhdGVEZWZhdWx0U2Nyb2xsYmFyIChkaXJlY3Rpb24sIGludGVyYWN0aXZlLCB0eXBlKSB7XG5cdHZhciBzY3JvbGxiYXIgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKSxcblx0XHRpbmRpY2F0b3IgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcblxuXHRpZiAoIHR5cGUgPT09IHRydWUgKSB7XG5cdFx0c2Nyb2xsYmFyLnN0eWxlLmNzc1RleHQgPSAncG9zaXRpb246YWJzb2x1dGU7ei1pbmRleDo5OTk5Jztcblx0XHRpbmRpY2F0b3Iuc3R5bGUuY3NzVGV4dCA9ICctd2Via2l0LWJveC1zaXppbmc6Ym9yZGVyLWJveDstbW96LWJveC1zaXppbmc6Ym9yZGVyLWJveDtib3gtc2l6aW5nOmJvcmRlci1ib3g7cG9zaXRpb246YWJzb2x1dGU7YmFja2dyb3VuZDpyZ2JhKDAsMCwwLDAuNSk7Ym9yZGVyOjFweCBzb2xpZCByZ2JhKDI1NSwyNTUsMjU1LDAuOSk7Ym9yZGVyLXJhZGl1czozcHgnO1xuXHR9XG5cblx0aW5kaWNhdG9yLmNsYXNzTmFtZSA9ICdpU2Nyb2xsSW5kaWNhdG9yJztcblxuXHRpZiAoIGRpcmVjdGlvbiA9PSAnaCcgKSB7XG5cdFx0aWYgKCB0eXBlID09PSB0cnVlICkge1xuXHRcdFx0c2Nyb2xsYmFyLnN0eWxlLmNzc1RleHQgKz0gJztoZWlnaHQ6N3B4O2xlZnQ6MnB4O3JpZ2h0OjJweDtib3R0b206MCc7XG5cdFx0XHRpbmRpY2F0b3Iuc3R5bGUuaGVpZ2h0ID0gJzEwMCUnO1xuXHRcdH1cblx0XHRzY3JvbGxiYXIuY2xhc3NOYW1lID0gJ2lTY3JvbGxIb3Jpem9udGFsU2Nyb2xsYmFyJztcblx0fSBlbHNlIHtcblx0XHRpZiAoIHR5cGUgPT09IHRydWUgKSB7XG5cdFx0XHRzY3JvbGxiYXIuc3R5bGUuY3NzVGV4dCArPSAnO3dpZHRoOjdweDtib3R0b206MnB4O3RvcDoycHg7cmlnaHQ6MXB4Jztcblx0XHRcdGluZGljYXRvci5zdHlsZS53aWR0aCA9ICcxMDAlJztcblx0XHR9XG5cdFx0c2Nyb2xsYmFyLmNsYXNzTmFtZSA9ICdpU2Nyb2xsVmVydGljYWxTY3JvbGxiYXInO1xuXHR9XG5cblx0c2Nyb2xsYmFyLnN0eWxlLmNzc1RleHQgKz0gJztvdmVyZmxvdzpoaWRkZW4nO1xuXG5cdGlmICggIWludGVyYWN0aXZlICkge1xuXHRcdHNjcm9sbGJhci5zdHlsZS5wb2ludGVyRXZlbnRzID0gJ25vbmUnO1xuXHR9XG5cblx0c2Nyb2xsYmFyLmFwcGVuZENoaWxkKGluZGljYXRvcik7XG5cblx0cmV0dXJuIHNjcm9sbGJhcjtcbn1cblxuZnVuY3Rpb24gSW5kaWNhdG9yIChzY3JvbGxlciwgb3B0aW9ucykge1xuXHR0aGlzLndyYXBwZXIgPSB0eXBlb2Ygb3B0aW9ucy5lbCA9PSAnc3RyaW5nJyA/IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3Iob3B0aW9ucy5lbCkgOiBvcHRpb25zLmVsO1xuXHR0aGlzLndyYXBwZXJTdHlsZSA9IHRoaXMud3JhcHBlci5zdHlsZTtcblx0dGhpcy5pbmRpY2F0b3IgPSB0aGlzLndyYXBwZXIuY2hpbGRyZW5bMF07XG5cdHRoaXMuaW5kaWNhdG9yU3R5bGUgPSB0aGlzLmluZGljYXRvci5zdHlsZTtcblx0dGhpcy5zY3JvbGxlciA9IHNjcm9sbGVyO1xuXG5cdHRoaXMub3B0aW9ucyA9IHtcblx0XHRsaXN0ZW5YOiB0cnVlLFxuXHRcdGxpc3Rlblk6IHRydWUsXG5cdFx0aW50ZXJhY3RpdmU6IGZhbHNlLFxuXHRcdHJlc2l6ZTogdHJ1ZSxcblx0XHRkZWZhdWx0U2Nyb2xsYmFyczogZmFsc2UsXG5cdFx0c2hyaW5rOiBmYWxzZSxcblx0XHRmYWRlOiBmYWxzZSxcblx0XHRzcGVlZFJhdGlvWDogMCxcblx0XHRzcGVlZFJhdGlvWTogMFxuXHR9O1xuXG5cdGZvciAoIHZhciBpIGluIG9wdGlvbnMgKSB7XG5cdFx0dGhpcy5vcHRpb25zW2ldID0gb3B0aW9uc1tpXTtcblx0fVxuXG5cdHRoaXMuc2l6ZVJhdGlvWCA9IDE7XG5cdHRoaXMuc2l6ZVJhdGlvWSA9IDE7XG5cdHRoaXMubWF4UG9zWCA9IDA7XG5cdHRoaXMubWF4UG9zWSA9IDA7XG5cblx0aWYgKCB0aGlzLm9wdGlvbnMuaW50ZXJhY3RpdmUgKSB7XG5cdFx0aWYgKCAhdGhpcy5vcHRpb25zLmRpc2FibGVUb3VjaCApIHtcblx0XHRcdHV0aWxzLmFkZEV2ZW50KHRoaXMuaW5kaWNhdG9yLCAndG91Y2hzdGFydCcsIHRoaXMpO1xuXHRcdFx0dXRpbHMuYWRkRXZlbnQod2luZG93LCAndG91Y2hlbmQnLCB0aGlzKTtcblx0XHR9XG5cdFx0aWYgKCAhdGhpcy5vcHRpb25zLmRpc2FibGVQb2ludGVyICkge1xuXHRcdFx0dXRpbHMuYWRkRXZlbnQodGhpcy5pbmRpY2F0b3IsIHV0aWxzLnByZWZpeFBvaW50ZXJFdmVudCgncG9pbnRlcmRvd24nKSwgdGhpcyk7XG5cdFx0XHR1dGlscy5hZGRFdmVudCh3aW5kb3csIHV0aWxzLnByZWZpeFBvaW50ZXJFdmVudCgncG9pbnRlcnVwJyksIHRoaXMpO1xuXHRcdH1cblx0XHRpZiAoICF0aGlzLm9wdGlvbnMuZGlzYWJsZU1vdXNlICkge1xuXHRcdFx0dXRpbHMuYWRkRXZlbnQodGhpcy5pbmRpY2F0b3IsICdtb3VzZWRvd24nLCB0aGlzKTtcblx0XHRcdHV0aWxzLmFkZEV2ZW50KHdpbmRvdywgJ21vdXNldXAnLCB0aGlzKTtcblx0XHR9XG5cdH1cblxuXHRpZiAoIHRoaXMub3B0aW9ucy5mYWRlICkge1xuXHRcdHRoaXMud3JhcHBlclN0eWxlW3V0aWxzLnN0eWxlLnRyYW5zZm9ybV0gPSB0aGlzLnNjcm9sbGVyLnRyYW5zbGF0ZVo7XG5cdFx0dmFyIGR1cmF0aW9uUHJvcCA9IHV0aWxzLnN0eWxlLnRyYW5zaXRpb25EdXJhdGlvbjtcblx0XHR0aGlzLndyYXBwZXJTdHlsZVtkdXJhdGlvblByb3BdID0gdXRpbHMuaXNCYWRBbmRyb2lkID8gJzAuMDAwMW1zJyA6ICcwbXMnO1xuXHRcdC8vIHJlbW92ZSAwLjAwMDFtc1xuXHRcdHZhciBzZWxmID0gdGhpcztcblx0XHRpZih1dGlscy5pc0JhZEFuZHJvaWQpIHtcblx0XHRcdHJBRihmdW5jdGlvbigpIHtcblx0XHRcdFx0aWYoc2VsZi53cmFwcGVyU3R5bGVbZHVyYXRpb25Qcm9wXSA9PT0gJzAuMDAwMW1zJykge1xuXHRcdFx0XHRcdHNlbGYud3JhcHBlclN0eWxlW2R1cmF0aW9uUHJvcF0gPSAnMHMnO1xuXHRcdFx0XHR9XG5cdFx0XHR9KTtcblx0XHR9XG5cdFx0dGhpcy53cmFwcGVyU3R5bGUub3BhY2l0eSA9ICcwJztcblx0fVxufVxuXG5JbmRpY2F0b3IucHJvdG90eXBlID0ge1xuXHRoYW5kbGVFdmVudDogZnVuY3Rpb24gKGUpIHtcblx0XHRzd2l0Y2ggKCBlLnR5cGUgKSB7XG5cdFx0XHRjYXNlICd0b3VjaHN0YXJ0Jzpcblx0XHRcdGNhc2UgJ3BvaW50ZXJkb3duJzpcblx0XHRcdGNhc2UgJ01TUG9pbnRlckRvd24nOlxuXHRcdFx0Y2FzZSAnbW91c2Vkb3duJzpcblx0XHRcdFx0dGhpcy5fc3RhcnQoZSk7XG5cdFx0XHRcdGJyZWFrO1xuXHRcdFx0Y2FzZSAndG91Y2htb3ZlJzpcblx0XHRcdGNhc2UgJ3BvaW50ZXJtb3ZlJzpcblx0XHRcdGNhc2UgJ01TUG9pbnRlck1vdmUnOlxuXHRcdFx0Y2FzZSAnbW91c2Vtb3ZlJzpcblx0XHRcdFx0dGhpcy5fbW92ZShlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0XHRjYXNlICd0b3VjaGVuZCc6XG5cdFx0XHRjYXNlICdwb2ludGVydXAnOlxuXHRcdFx0Y2FzZSAnTVNQb2ludGVyVXAnOlxuXHRcdFx0Y2FzZSAnbW91c2V1cCc6XG5cdFx0XHRjYXNlICd0b3VjaGNhbmNlbCc6XG5cdFx0XHRjYXNlICdwb2ludGVyY2FuY2VsJzpcblx0XHRcdGNhc2UgJ01TUG9pbnRlckNhbmNlbCc6XG5cdFx0XHRjYXNlICdtb3VzZWNhbmNlbCc6XG5cdFx0XHRcdHRoaXMuX2VuZChlKTtcblx0XHRcdFx0YnJlYWs7XG5cdFx0fVxuXHR9LFxuXG5cdGRlc3Ryb3k6IGZ1bmN0aW9uICgpIHtcblx0XHRpZiAoIHRoaXMub3B0aW9ucy5mYWRlU2Nyb2xsYmFycyApIHtcblx0XHRcdGNsZWFyVGltZW91dCh0aGlzLmZhZGVUaW1lb3V0KTtcblx0XHRcdHRoaXMuZmFkZVRpbWVvdXQgPSBudWxsO1xuXHRcdH1cblx0XHRpZiAoIHRoaXMub3B0aW9ucy5pbnRlcmFjdGl2ZSApIHtcblx0XHRcdHV0aWxzLnJlbW92ZUV2ZW50KHRoaXMuaW5kaWNhdG9yLCAndG91Y2hzdGFydCcsIHRoaXMpO1xuXHRcdFx0dXRpbHMucmVtb3ZlRXZlbnQodGhpcy5pbmRpY2F0b3IsIHV0aWxzLnByZWZpeFBvaW50ZXJFdmVudCgncG9pbnRlcmRvd24nKSwgdGhpcyk7XG5cdFx0XHR1dGlscy5yZW1vdmVFdmVudCh0aGlzLmluZGljYXRvciwgJ21vdXNlZG93bicsIHRoaXMpO1xuXG5cdFx0XHR1dGlscy5yZW1vdmVFdmVudCh3aW5kb3csICd0b3VjaG1vdmUnLCB0aGlzKTtcblx0XHRcdHV0aWxzLnJlbW92ZUV2ZW50KHdpbmRvdywgdXRpbHMucHJlZml4UG9pbnRlckV2ZW50KCdwb2ludGVybW92ZScpLCB0aGlzKTtcblx0XHRcdHV0aWxzLnJlbW92ZUV2ZW50KHdpbmRvdywgJ21vdXNlbW92ZScsIHRoaXMpO1xuXG5cdFx0XHR1dGlscy5yZW1vdmVFdmVudCh3aW5kb3csICd0b3VjaGVuZCcsIHRoaXMpO1xuXHRcdFx0dXRpbHMucmVtb3ZlRXZlbnQod2luZG93LCB1dGlscy5wcmVmaXhQb2ludGVyRXZlbnQoJ3BvaW50ZXJ1cCcpLCB0aGlzKTtcblx0XHRcdHV0aWxzLnJlbW92ZUV2ZW50KHdpbmRvdywgJ21vdXNldXAnLCB0aGlzKTtcblx0XHR9XG5cblx0XHRpZiAoIHRoaXMub3B0aW9ucy5kZWZhdWx0U2Nyb2xsYmFycyApIHtcblx0XHRcdHRoaXMud3JhcHBlci5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKHRoaXMud3JhcHBlcik7XG5cdFx0fVxuXHR9LFxuXG5cdF9zdGFydDogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgcG9pbnQgPSBlLnRvdWNoZXMgPyBlLnRvdWNoZXNbMF0gOiBlO1xuXG5cdFx0ZS5wcmV2ZW50RGVmYXVsdCgpO1xuXHRcdGUuc3RvcFByb3BhZ2F0aW9uKCk7XG5cblx0XHR0aGlzLnRyYW5zaXRpb25UaW1lKCk7XG5cblx0XHR0aGlzLmluaXRpYXRlZCA9IHRydWU7XG5cdFx0dGhpcy5tb3ZlZCA9IGZhbHNlO1xuXHRcdHRoaXMubGFzdFBvaW50WFx0PSBwb2ludC5wYWdlWDtcblx0XHR0aGlzLmxhc3RQb2ludFlcdD0gcG9pbnQucGFnZVk7XG5cblx0XHR0aGlzLnN0YXJ0VGltZVx0PSB1dGlscy5nZXRUaW1lKCk7XG5cblx0XHRpZiAoICF0aGlzLm9wdGlvbnMuZGlzYWJsZVRvdWNoICkge1xuXHRcdFx0dXRpbHMuYWRkRXZlbnQod2luZG93LCAndG91Y2htb3ZlJywgdGhpcyk7XG5cdFx0fVxuXHRcdGlmICggIXRoaXMub3B0aW9ucy5kaXNhYmxlUG9pbnRlciApIHtcblx0XHRcdHV0aWxzLmFkZEV2ZW50KHdpbmRvdywgdXRpbHMucHJlZml4UG9pbnRlckV2ZW50KCdwb2ludGVybW92ZScpLCB0aGlzKTtcblx0XHR9XG5cdFx0aWYgKCAhdGhpcy5vcHRpb25zLmRpc2FibGVNb3VzZSApIHtcblx0XHRcdHV0aWxzLmFkZEV2ZW50KHdpbmRvdywgJ21vdXNlbW92ZScsIHRoaXMpO1xuXHRcdH1cblxuXHRcdHRoaXMuc2Nyb2xsZXIuX2V4ZWNFdmVudCgnYmVmb3JlU2Nyb2xsU3RhcnQnKTtcblx0fSxcblxuXHRfbW92ZTogZnVuY3Rpb24gKGUpIHtcblx0XHR2YXIgcG9pbnQgPSBlLnRvdWNoZXMgPyBlLnRvdWNoZXNbMF0gOiBlLFxuXHRcdFx0ZGVsdGFYLCBkZWx0YVksXG5cdFx0XHRuZXdYLCBuZXdZLFxuXHRcdFx0dGltZXN0YW1wID0gdXRpbHMuZ2V0VGltZSgpO1xuXG5cdFx0aWYgKCAhdGhpcy5tb3ZlZCApIHtcblx0XHRcdHRoaXMuc2Nyb2xsZXIuX2V4ZWNFdmVudCgnc2Nyb2xsU3RhcnQnKTtcblx0XHR9XG5cblx0XHR0aGlzLm1vdmVkID0gdHJ1ZTtcblxuXHRcdGRlbHRhWCA9IHBvaW50LnBhZ2VYIC0gdGhpcy5sYXN0UG9pbnRYO1xuXHRcdHRoaXMubGFzdFBvaW50WCA9IHBvaW50LnBhZ2VYO1xuXG5cdFx0ZGVsdGFZID0gcG9pbnQucGFnZVkgLSB0aGlzLmxhc3RQb2ludFk7XG5cdFx0dGhpcy5sYXN0UG9pbnRZID0gcG9pbnQucGFnZVk7XG5cblx0XHRuZXdYID0gdGhpcy54ICsgZGVsdGFYO1xuXHRcdG5ld1kgPSB0aGlzLnkgKyBkZWx0YVk7XG5cblx0XHR0aGlzLl9wb3MobmV3WCwgbmV3WSk7XG5cbi8vIElOU0VSVCBQT0lOVDogaW5kaWNhdG9yLl9tb3ZlXG5cblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ZS5zdG9wUHJvcGFnYXRpb24oKTtcblx0fSxcblxuXHRfZW5kOiBmdW5jdGlvbiAoZSkge1xuXHRcdGlmICggIXRoaXMuaW5pdGlhdGVkICkge1xuXHRcdFx0cmV0dXJuO1xuXHRcdH1cblxuXHRcdHRoaXMuaW5pdGlhdGVkID0gZmFsc2U7XG5cblx0XHRlLnByZXZlbnREZWZhdWx0KCk7XG5cdFx0ZS5zdG9wUHJvcGFnYXRpb24oKTtcblxuXHRcdHV0aWxzLnJlbW92ZUV2ZW50KHdpbmRvdywgJ3RvdWNobW92ZScsIHRoaXMpO1xuXHRcdHV0aWxzLnJlbW92ZUV2ZW50KHdpbmRvdywgdXRpbHMucHJlZml4UG9pbnRlckV2ZW50KCdwb2ludGVybW92ZScpLCB0aGlzKTtcblx0XHR1dGlscy5yZW1vdmVFdmVudCh3aW5kb3csICdtb3VzZW1vdmUnLCB0aGlzKTtcblxuXHRcdGlmICggdGhpcy5zY3JvbGxlci5vcHRpb25zLnNuYXAgKSB7XG5cdFx0XHR2YXIgc25hcCA9IHRoaXMuc2Nyb2xsZXIuX25lYXJlc3RTbmFwKHRoaXMuc2Nyb2xsZXIueCwgdGhpcy5zY3JvbGxlci55KTtcblxuXHRcdFx0dmFyIHRpbWUgPSB0aGlzLm9wdGlvbnMuc25hcFNwZWVkIHx8IE1hdGgubWF4KFxuXHRcdFx0XHRcdE1hdGgubWF4KFxuXHRcdFx0XHRcdFx0TWF0aC5taW4oTWF0aC5hYnModGhpcy5zY3JvbGxlci54IC0gc25hcC54KSwgMTAwMCksXG5cdFx0XHRcdFx0XHRNYXRoLm1pbihNYXRoLmFicyh0aGlzLnNjcm9sbGVyLnkgLSBzbmFwLnkpLCAxMDAwKVxuXHRcdFx0XHRcdCksIDMwMCk7XG5cblx0XHRcdGlmICggdGhpcy5zY3JvbGxlci54ICE9IHNuYXAueCB8fCB0aGlzLnNjcm9sbGVyLnkgIT0gc25hcC55ICkge1xuXHRcdFx0XHR0aGlzLnNjcm9sbGVyLmRpcmVjdGlvblggPSAwO1xuXHRcdFx0XHR0aGlzLnNjcm9sbGVyLmRpcmVjdGlvblkgPSAwO1xuXHRcdFx0XHR0aGlzLnNjcm9sbGVyLmN1cnJlbnRQYWdlID0gc25hcDtcblx0XHRcdFx0dGhpcy5zY3JvbGxlci5zY3JvbGxUbyhzbmFwLngsIHNuYXAueSwgdGltZSwgdGhpcy5zY3JvbGxlci5vcHRpb25zLmJvdW5jZUVhc2luZyk7XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0aWYgKCB0aGlzLm1vdmVkICkge1xuXHRcdFx0dGhpcy5zY3JvbGxlci5fZXhlY0V2ZW50KCdzY3JvbGxFbmQnKTtcblx0XHR9XG5cdH0sXG5cblx0dHJhbnNpdGlvblRpbWU6IGZ1bmN0aW9uICh0aW1lKSB7XG5cdFx0dGltZSA9IHRpbWUgfHwgMDtcblx0XHR2YXIgZHVyYXRpb25Qcm9wID0gdXRpbHMuc3R5bGUudHJhbnNpdGlvbkR1cmF0aW9uO1xuXHRcdHRoaXMuaW5kaWNhdG9yU3R5bGVbZHVyYXRpb25Qcm9wXSA9IHRpbWUgKyAnbXMnO1xuXG5cdFx0aWYgKCAhdGltZSAmJiB1dGlscy5pc0JhZEFuZHJvaWQgKSB7XG5cdFx0XHR0aGlzLmluZGljYXRvclN0eWxlW2R1cmF0aW9uUHJvcF0gPSAnMC4wMDAxbXMnO1xuXHRcdFx0Ly8gcmVtb3ZlIDAuMDAwMW1zXG5cdFx0XHR2YXIgc2VsZiA9IHRoaXM7XG5cdFx0XHRyQUYoZnVuY3Rpb24oKSB7XG5cdFx0XHRcdGlmKHNlbGYuaW5kaWNhdG9yU3R5bGVbZHVyYXRpb25Qcm9wXSA9PT0gJzAuMDAwMW1zJykge1xuXHRcdFx0XHRcdHNlbGYuaW5kaWNhdG9yU3R5bGVbZHVyYXRpb25Qcm9wXSA9ICcwcyc7XG5cdFx0XHRcdH1cblx0XHRcdH0pO1xuXHRcdH1cblx0fSxcblxuXHR0cmFuc2l0aW9uVGltaW5nRnVuY3Rpb246IGZ1bmN0aW9uIChlYXNpbmcpIHtcblx0XHR0aGlzLmluZGljYXRvclN0eWxlW3V0aWxzLnN0eWxlLnRyYW5zaXRpb25UaW1pbmdGdW5jdGlvbl0gPSBlYXNpbmc7XG5cdH0sXG5cblx0cmVmcmVzaDogZnVuY3Rpb24gKCkge1xuXHRcdHRoaXMudHJhbnNpdGlvblRpbWUoKTtcblxuXHRcdGlmICggdGhpcy5vcHRpb25zLmxpc3RlblggJiYgIXRoaXMub3B0aW9ucy5saXN0ZW5ZICkge1xuXHRcdFx0dGhpcy5pbmRpY2F0b3JTdHlsZS5kaXNwbGF5ID0gdGhpcy5zY3JvbGxlci5oYXNIb3Jpem9udGFsU2Nyb2xsID8gJ2Jsb2NrJyA6ICdub25lJztcblx0XHR9IGVsc2UgaWYgKCB0aGlzLm9wdGlvbnMubGlzdGVuWSAmJiAhdGhpcy5vcHRpb25zLmxpc3RlblggKSB7XG5cdFx0XHR0aGlzLmluZGljYXRvclN0eWxlLmRpc3BsYXkgPSB0aGlzLnNjcm9sbGVyLmhhc1ZlcnRpY2FsU2Nyb2xsID8gJ2Jsb2NrJyA6ICdub25lJztcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5pbmRpY2F0b3JTdHlsZS5kaXNwbGF5ID0gdGhpcy5zY3JvbGxlci5oYXNIb3Jpem9udGFsU2Nyb2xsIHx8IHRoaXMuc2Nyb2xsZXIuaGFzVmVydGljYWxTY3JvbGwgPyAnYmxvY2snIDogJ25vbmUnO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5zY3JvbGxlci5oYXNIb3Jpem9udGFsU2Nyb2xsICYmIHRoaXMuc2Nyb2xsZXIuaGFzVmVydGljYWxTY3JvbGwgKSB7XG5cdFx0XHR1dGlscy5hZGRDbGFzcyh0aGlzLndyYXBwZXIsICdpU2Nyb2xsQm90aFNjcm9sbGJhcnMnKTtcblx0XHRcdHV0aWxzLnJlbW92ZUNsYXNzKHRoaXMud3JhcHBlciwgJ2lTY3JvbGxMb25lU2Nyb2xsYmFyJyk7XG5cblx0XHRcdGlmICggdGhpcy5vcHRpb25zLmRlZmF1bHRTY3JvbGxiYXJzICYmIHRoaXMub3B0aW9ucy5jdXN0b21TdHlsZSApIHtcblx0XHRcdFx0aWYgKCB0aGlzLm9wdGlvbnMubGlzdGVuWCApIHtcblx0XHRcdFx0XHR0aGlzLndyYXBwZXIuc3R5bGUucmlnaHQgPSAnOHB4Jztcblx0XHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0XHR0aGlzLndyYXBwZXIuc3R5bGUuYm90dG9tID0gJzhweCc7XG5cdFx0XHRcdH1cblx0XHRcdH1cblx0XHR9IGVsc2Uge1xuXHRcdFx0dXRpbHMucmVtb3ZlQ2xhc3ModGhpcy53cmFwcGVyLCAnaVNjcm9sbEJvdGhTY3JvbGxiYXJzJyk7XG5cdFx0XHR1dGlscy5hZGRDbGFzcyh0aGlzLndyYXBwZXIsICdpU2Nyb2xsTG9uZVNjcm9sbGJhcicpO1xuXG5cdFx0XHRpZiAoIHRoaXMub3B0aW9ucy5kZWZhdWx0U2Nyb2xsYmFycyAmJiB0aGlzLm9wdGlvbnMuY3VzdG9tU3R5bGUgKSB7XG5cdFx0XHRcdGlmICggdGhpcy5vcHRpb25zLmxpc3RlblggKSB7XG5cdFx0XHRcdFx0dGhpcy53cmFwcGVyLnN0eWxlLnJpZ2h0ID0gJzJweCc7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0dGhpcy53cmFwcGVyLnN0eWxlLmJvdHRvbSA9ICcycHgnO1xuXHRcdFx0XHR9XG5cdFx0XHR9XG5cdFx0fVxuXG5cdFx0dmFyIHIgPSB0aGlzLndyYXBwZXIub2Zmc2V0SGVpZ2h0O1x0Ly8gZm9yY2UgcmVmcmVzaFxuXG5cdFx0aWYgKCB0aGlzLm9wdGlvbnMubGlzdGVuWCApIHtcblx0XHRcdHRoaXMud3JhcHBlcldpZHRoID0gdGhpcy53cmFwcGVyLmNsaWVudFdpZHRoO1xuXHRcdFx0aWYgKCB0aGlzLm9wdGlvbnMucmVzaXplICkge1xuXHRcdFx0XHR0aGlzLmluZGljYXRvcldpZHRoID0gTWF0aC5tYXgoTWF0aC5yb3VuZCh0aGlzLndyYXBwZXJXaWR0aCAqIHRoaXMud3JhcHBlcldpZHRoIC8gKHRoaXMuc2Nyb2xsZXIuc2Nyb2xsZXJXaWR0aCB8fCB0aGlzLndyYXBwZXJXaWR0aCB8fCAxKSksIDgpO1xuXHRcdFx0XHR0aGlzLmluZGljYXRvclN0eWxlLndpZHRoID0gdGhpcy5pbmRpY2F0b3JXaWR0aCArICdweCc7XG5cdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHR0aGlzLmluZGljYXRvcldpZHRoID0gdGhpcy5pbmRpY2F0b3IuY2xpZW50V2lkdGg7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMubWF4UG9zWCA9IHRoaXMud3JhcHBlcldpZHRoIC0gdGhpcy5pbmRpY2F0b3JXaWR0aDtcblxuXHRcdFx0aWYgKCB0aGlzLm9wdGlvbnMuc2hyaW5rID09ICdjbGlwJyApIHtcblx0XHRcdFx0dGhpcy5taW5Cb3VuZGFyeVggPSAtdGhpcy5pbmRpY2F0b3JXaWR0aCArIDg7XG5cdFx0XHRcdHRoaXMubWF4Qm91bmRhcnlYID0gdGhpcy53cmFwcGVyV2lkdGggLSA4O1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5taW5Cb3VuZGFyeVggPSAwO1xuXHRcdFx0XHR0aGlzLm1heEJvdW5kYXJ5WCA9IHRoaXMubWF4UG9zWDtcblx0XHRcdH1cblxuXHRcdFx0dGhpcy5zaXplUmF0aW9YID0gdGhpcy5vcHRpb25zLnNwZWVkUmF0aW9YIHx8ICh0aGlzLnNjcm9sbGVyLm1heFNjcm9sbFggJiYgKHRoaXMubWF4UG9zWCAvIHRoaXMuc2Nyb2xsZXIubWF4U2Nyb2xsWCkpO1xuXHRcdH1cblxuXHRcdGlmICggdGhpcy5vcHRpb25zLmxpc3RlblkgKSB7XG5cdFx0XHR0aGlzLndyYXBwZXJIZWlnaHQgPSB0aGlzLndyYXBwZXIuY2xpZW50SGVpZ2h0O1xuXHRcdFx0aWYgKCB0aGlzLm9wdGlvbnMucmVzaXplICkge1xuXHRcdFx0XHR0aGlzLmluZGljYXRvckhlaWdodCA9IE1hdGgubWF4KE1hdGgucm91bmQodGhpcy53cmFwcGVySGVpZ2h0ICogdGhpcy53cmFwcGVySGVpZ2h0IC8gKHRoaXMuc2Nyb2xsZXIuc2Nyb2xsZXJIZWlnaHQgfHwgdGhpcy53cmFwcGVySGVpZ2h0IHx8IDEpKSwgOCk7XG5cdFx0XHRcdHRoaXMuaW5kaWNhdG9yU3R5bGUuaGVpZ2h0ID0gdGhpcy5pbmRpY2F0b3JIZWlnaHQgKyAncHgnO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0dGhpcy5pbmRpY2F0b3JIZWlnaHQgPSB0aGlzLmluZGljYXRvci5jbGllbnRIZWlnaHQ7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMubWF4UG9zWSA9IHRoaXMud3JhcHBlckhlaWdodCAtIHRoaXMuaW5kaWNhdG9ySGVpZ2h0O1xuXG5cdFx0XHRpZiAoIHRoaXMub3B0aW9ucy5zaHJpbmsgPT0gJ2NsaXAnICkge1xuXHRcdFx0XHR0aGlzLm1pbkJvdW5kYXJ5WSA9IC10aGlzLmluZGljYXRvckhlaWdodCArIDg7XG5cdFx0XHRcdHRoaXMubWF4Qm91bmRhcnlZID0gdGhpcy53cmFwcGVySGVpZ2h0IC0gODtcblx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdHRoaXMubWluQm91bmRhcnlZID0gMDtcblx0XHRcdFx0dGhpcy5tYXhCb3VuZGFyeVkgPSB0aGlzLm1heFBvc1k7XG5cdFx0XHR9XG5cblx0XHRcdHRoaXMubWF4UG9zWSA9IHRoaXMud3JhcHBlckhlaWdodCAtIHRoaXMuaW5kaWNhdG9ySGVpZ2h0O1xuXHRcdFx0dGhpcy5zaXplUmF0aW9ZID0gdGhpcy5vcHRpb25zLnNwZWVkUmF0aW9ZIHx8ICh0aGlzLnNjcm9sbGVyLm1heFNjcm9sbFkgJiYgKHRoaXMubWF4UG9zWSAvIHRoaXMuc2Nyb2xsZXIubWF4U2Nyb2xsWSkpO1xuXHRcdH1cblxuXHRcdHRoaXMudXBkYXRlUG9zaXRpb24oKTtcblx0fSxcblxuXHR1cGRhdGVQb3NpdGlvbjogZnVuY3Rpb24gKCkge1xuXHRcdHZhciB4ID0gdGhpcy5vcHRpb25zLmxpc3RlblggJiYgTWF0aC5yb3VuZCh0aGlzLnNpemVSYXRpb1ggKiB0aGlzLnNjcm9sbGVyLngpIHx8IDAsXG5cdFx0XHR5ID0gdGhpcy5vcHRpb25zLmxpc3RlblkgJiYgTWF0aC5yb3VuZCh0aGlzLnNpemVSYXRpb1kgKiB0aGlzLnNjcm9sbGVyLnkpIHx8IDA7XG5cblx0XHRpZiAoICF0aGlzLm9wdGlvbnMuaWdub3JlQm91bmRhcmllcyApIHtcblx0XHRcdGlmICggeCA8IHRoaXMubWluQm91bmRhcnlYICkge1xuXHRcdFx0XHRpZiAoIHRoaXMub3B0aW9ucy5zaHJpbmsgPT0gJ3NjYWxlJyApIHtcblx0XHRcdFx0XHR0aGlzLndpZHRoID0gTWF0aC5tYXgodGhpcy5pbmRpY2F0b3JXaWR0aCArIHgsIDgpO1xuXHRcdFx0XHRcdHRoaXMuaW5kaWNhdG9yU3R5bGUud2lkdGggPSB0aGlzLndpZHRoICsgJ3B4Jztcblx0XHRcdFx0fVxuXHRcdFx0XHR4ID0gdGhpcy5taW5Cb3VuZGFyeVg7XG5cdFx0XHR9IGVsc2UgaWYgKCB4ID4gdGhpcy5tYXhCb3VuZGFyeVggKSB7XG5cdFx0XHRcdGlmICggdGhpcy5vcHRpb25zLnNocmluayA9PSAnc2NhbGUnICkge1xuXHRcdFx0XHRcdHRoaXMud2lkdGggPSBNYXRoLm1heCh0aGlzLmluZGljYXRvcldpZHRoIC0gKHggLSB0aGlzLm1heFBvc1gpLCA4KTtcblx0XHRcdFx0XHR0aGlzLmluZGljYXRvclN0eWxlLndpZHRoID0gdGhpcy53aWR0aCArICdweCc7XG5cdFx0XHRcdFx0eCA9IHRoaXMubWF4UG9zWCArIHRoaXMuaW5kaWNhdG9yV2lkdGggLSB0aGlzLndpZHRoO1xuXHRcdFx0XHR9IGVsc2Uge1xuXHRcdFx0XHRcdHggPSB0aGlzLm1heEJvdW5kYXJ5WDtcblx0XHRcdFx0fVxuXHRcdFx0fSBlbHNlIGlmICggdGhpcy5vcHRpb25zLnNocmluayA9PSAnc2NhbGUnICYmIHRoaXMud2lkdGggIT0gdGhpcy5pbmRpY2F0b3JXaWR0aCApIHtcblx0XHRcdFx0dGhpcy53aWR0aCA9IHRoaXMuaW5kaWNhdG9yV2lkdGg7XG5cdFx0XHRcdHRoaXMuaW5kaWNhdG9yU3R5bGUud2lkdGggPSB0aGlzLndpZHRoICsgJ3B4Jztcblx0XHRcdH1cblxuXHRcdFx0aWYgKCB5IDwgdGhpcy5taW5Cb3VuZGFyeVkgKSB7XG5cdFx0XHRcdGlmICggdGhpcy5vcHRpb25zLnNocmluayA9PSAnc2NhbGUnICkge1xuXHRcdFx0XHRcdHRoaXMuaGVpZ2h0ID0gTWF0aC5tYXgodGhpcy5pbmRpY2F0b3JIZWlnaHQgKyB5ICogMywgOCk7XG5cdFx0XHRcdFx0dGhpcy5pbmRpY2F0b3JTdHlsZS5oZWlnaHQgPSB0aGlzLmhlaWdodCArICdweCc7XG5cdFx0XHRcdH1cblx0XHRcdFx0eSA9IHRoaXMubWluQm91bmRhcnlZO1xuXHRcdFx0fSBlbHNlIGlmICggeSA+IHRoaXMubWF4Qm91bmRhcnlZICkge1xuXHRcdFx0XHRpZiAoIHRoaXMub3B0aW9ucy5zaHJpbmsgPT0gJ3NjYWxlJyApIHtcblx0XHRcdFx0XHR0aGlzLmhlaWdodCA9IE1hdGgubWF4KHRoaXMuaW5kaWNhdG9ySGVpZ2h0IC0gKHkgLSB0aGlzLm1heFBvc1kpICogMywgOCk7XG5cdFx0XHRcdFx0dGhpcy5pbmRpY2F0b3JTdHlsZS5oZWlnaHQgPSB0aGlzLmhlaWdodCArICdweCc7XG5cdFx0XHRcdFx0eSA9IHRoaXMubWF4UG9zWSArIHRoaXMuaW5kaWNhdG9ySGVpZ2h0IC0gdGhpcy5oZWlnaHQ7XG5cdFx0XHRcdH0gZWxzZSB7XG5cdFx0XHRcdFx0eSA9IHRoaXMubWF4Qm91bmRhcnlZO1xuXHRcdFx0XHR9XG5cdFx0XHR9IGVsc2UgaWYgKCB0aGlzLm9wdGlvbnMuc2hyaW5rID09ICdzY2FsZScgJiYgdGhpcy5oZWlnaHQgIT0gdGhpcy5pbmRpY2F0b3JIZWlnaHQgKSB7XG5cdFx0XHRcdHRoaXMuaGVpZ2h0ID0gdGhpcy5pbmRpY2F0b3JIZWlnaHQ7XG5cdFx0XHRcdHRoaXMuaW5kaWNhdG9yU3R5bGUuaGVpZ2h0ID0gdGhpcy5oZWlnaHQgKyAncHgnO1xuXHRcdFx0fVxuXHRcdH1cblxuXHRcdHRoaXMueCA9IHg7XG5cdFx0dGhpcy55ID0geTtcblxuXHRcdGlmICggdGhpcy5zY3JvbGxlci5vcHRpb25zLnVzZVRyYW5zZm9ybSApIHtcblx0XHRcdHRoaXMuaW5kaWNhdG9yU3R5bGVbdXRpbHMuc3R5bGUudHJhbnNmb3JtXSA9ICd0cmFuc2xhdGUoJyArIHggKyAncHgsJyArIHkgKyAncHgpJyArIHRoaXMuc2Nyb2xsZXIudHJhbnNsYXRlWjtcblx0XHR9IGVsc2Uge1xuXHRcdFx0dGhpcy5pbmRpY2F0b3JTdHlsZS5sZWZ0ID0geCArICdweCc7XG5cdFx0XHR0aGlzLmluZGljYXRvclN0eWxlLnRvcCA9IHkgKyAncHgnO1xuXHRcdH1cblx0fSxcblxuXHRfcG9zOiBmdW5jdGlvbiAoeCwgeSkge1xuXHRcdGlmICggeCA8IDAgKSB7XG5cdFx0XHR4ID0gMDtcblx0XHR9IGVsc2UgaWYgKCB4ID4gdGhpcy5tYXhQb3NYICkge1xuXHRcdFx0eCA9IHRoaXMubWF4UG9zWDtcblx0XHR9XG5cblx0XHRpZiAoIHkgPCAwICkge1xuXHRcdFx0eSA9IDA7XG5cdFx0fSBlbHNlIGlmICggeSA+IHRoaXMubWF4UG9zWSApIHtcblx0XHRcdHkgPSB0aGlzLm1heFBvc1k7XG5cdFx0fVxuXG5cdFx0eCA9IHRoaXMub3B0aW9ucy5saXN0ZW5YID8gTWF0aC5yb3VuZCh4IC8gdGhpcy5zaXplUmF0aW9YKSA6IHRoaXMuc2Nyb2xsZXIueDtcblx0XHR5ID0gdGhpcy5vcHRpb25zLmxpc3RlblkgPyBNYXRoLnJvdW5kKHkgLyB0aGlzLnNpemVSYXRpb1kpIDogdGhpcy5zY3JvbGxlci55O1xuXG5cdFx0dGhpcy5zY3JvbGxlci5zY3JvbGxUbyh4LCB5KTtcblx0fSxcblxuXHRmYWRlOiBmdW5jdGlvbiAodmFsLCBob2xkKSB7XG5cdFx0aWYgKCBob2xkICYmICF0aGlzLnZpc2libGUgKSB7XG5cdFx0XHRyZXR1cm47XG5cdFx0fVxuXG5cdFx0Y2xlYXJUaW1lb3V0KHRoaXMuZmFkZVRpbWVvdXQpO1xuXHRcdHRoaXMuZmFkZVRpbWVvdXQgPSBudWxsO1xuXG5cdFx0dmFyIHRpbWUgPSB2YWwgPyAyNTAgOiA1MDAsXG5cdFx0XHRkZWxheSA9IHZhbCA/IDAgOiAzMDA7XG5cblx0XHR2YWwgPSB2YWwgPyAnMScgOiAnMCc7XG5cblx0XHR0aGlzLndyYXBwZXJTdHlsZVt1dGlscy5zdHlsZS50cmFuc2l0aW9uRHVyYXRpb25dID0gdGltZSArICdtcyc7XG5cblx0XHR0aGlzLmZhZGVUaW1lb3V0ID0gc2V0VGltZW91dCgoZnVuY3Rpb24gKHZhbCkge1xuXHRcdFx0dGhpcy53cmFwcGVyU3R5bGUub3BhY2l0eSA9IHZhbDtcblx0XHRcdHRoaXMudmlzaWJsZSA9ICt2YWw7XG5cdFx0fSkuYmluZCh0aGlzLCB2YWwpLCBkZWxheSk7XG5cdH1cbn07XG5cbklTY3JvbGwudXRpbHMgPSB1dGlscztcblxuaWYgKCB0eXBlb2YgbW9kdWxlICE9ICd1bmRlZmluZWQnICYmIG1vZHVsZS5leHBvcnRzICkge1xuXHRtb2R1bGUuZXhwb3J0cyA9IElTY3JvbGw7XG59IGVsc2UgaWYgKCB0eXBlb2YgZGVmaW5lID09ICdmdW5jdGlvbicgJiYgZGVmaW5lLmFtZCApIHtcbiAgICAgICAgZGVmaW5lKCBmdW5jdGlvbiAoKSB7IHJldHVybiBJU2Nyb2xsOyB9ICk7XG59IGVsc2Uge1xuXHR3aW5kb3cuSVNjcm9sbCA9IElTY3JvbGw7XG59XG5cbn0pKHdpbmRvdywgZG9jdW1lbnQsIE1hdGgpO1xuXG5cblxuLy8vLy8vLy8vLy8vLy8vLy8vXG4vLyBXRUJQQUNLIEZPT1RFUlxuLy8gLi9ub2RlX21vZHVsZXMvaXNjcm9sbC9idWlsZC9pc2Nyb2xsLmpzXG4vLyBtb2R1bGUgaWQgPSAyXG4vLyBtb2R1bGUgY2h1bmtzID0gMiA0Il0sInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///2\n");
  18. /***/ })
  19. },[16]);