Skip to content

Instantly share code, notes, and snippets.

@dev-jaydeep
Created August 25, 2023 12:28
Show Gist options
  • Save dev-jaydeep/b2b50ea8266045149e0a9a38550fa0ae to your computer and use it in GitHub Desktop.
Save dev-jaydeep/b2b50ea8266045149e0a9a38550fa0ae to your computer and use it in GitHub Desktop.
PDF Reader react native [rn-pdf-reader-js]
import { Base64 } from 'js-base64';
const bundle = 'IWZ1bmN0aW9uKGUpe3ZhciB0PXt9O2Z1bmN0aW9uIG4ocil7aWYodFtyXSlyZXR1cm4gdFtyXS5leHBvcnRzO3ZhciBhPXRbcl09e2k6cixsOiExLGV4cG9ydHM6e319O3JldHVybiBlW3JdLmNhbGwoYS5leHBvcnRzLGEsYS5leHBvcnRzLG4pLGEubD0hMCxhLmV4cG9ydHN9bi5tPWUsbi5jPXQsbi5kPWZ1bmN0aW9uKGUsdCxyKXtuLm8oZSx0KXx8T2JqZWN0LmRlZmluZVByb3BlcnR5KGUsdCx7ZW51bWVyYWJsZTohMCxnZXQ6cn0pfSxuLnI9ZnVuY3Rpb24oZSl7InVuZGVmaW5lZCIhPXR5cGVvZiBTeW1ib2wmJlN5bWJvbC50b1N0cmluZ1RhZyYmT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsU3ltYm9sLnRvU3RyaW5nVGFnLHt2YWx1ZToiTW9kdWxlIn0pLE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlLCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KX0sbi50PWZ1bmN0aW9uKGUsdCl7aWYoMSZ0JiYoZT1uKGUpKSw4JnQpcmV0dXJuIGU7aWYoNCZ0JiYib2JqZWN0Ij09dHlwZW9mIGUmJmUmJmUuX19lc01vZHVsZSlyZXR1cm4gZTt2YXIgcj1PYmplY3QuY3JlYXRlKG51bGwpO2lmKG4ucihyKSxPYmplY3QuZGVmaW5lUHJvcGVydHkociwiZGVmYXVsdCIse2VudW1lcmFibGU6ITAsdmFsdWU6ZX0pLDImdCYmInN0cmluZyIhPXR5cGVvZiBlKWZvcih2YXIgYSBpbiBlKW4uZChyLGEsZnVuY3Rpb24odCl7cmV0dXJuIGVbdF19LmJpbmQobnVsbCxhKSk7cmV0dXJuIHJ9LG4ubj1mdW5jdGlvbihlKXt2YXIgdD1lJiZlLl9fZXNNb2R1bGU/ZnVuY3Rpb24oKXtyZXR1cm4gZS5kZWZhdWx0fTpmdW5jdGlvbigpe3JldHVybiBlfTtyZXR1cm4gbi5kKHQsImEiLHQpLHR9LG4ubz1mdW5jdGlvbihlLHQpe3JldHVybiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwoZSx0KX0sbi5wPSIiLG4obi5zPTMwKX0oW2Z1bmN0aW9uKGUsdCl7ZS5leHBvcnRzPVJlYWN0fSxmdW5jdGlvbihlLHQpe2UuZXhwb3J0cz1mdW5jdGlvbihlKXtyZXR1cm4gZSYmZS5fX2VzTW9kdWxlP2U6e2RlZmF1bHQ6ZX19fSxmdW5jdGlvbihlLHQpe2Z1bmN0aW9uIG4odCl7cmV0dXJuIGUuZXhwb3J0cz1uPU9iamVjdC5zZXRQcm90b3R5cGVPZj9PYmplY3QuZ2V0UHJvdG90eXBlT2Y6ZnVuY3Rpb24oZSl7cmV0dXJuIGUuX19wcm90b19ffHxPYmplY3QuZ2V0UHJvdG90eXBlT2YoZSl9LG4odCl9ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsdCxuKXtlLmV4cG9ydHM9bigzNCkoKX0sZnVuY3Rpb24oZSx0KXtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LG4pe3JldHVybiB0IGluIGU/T2JqZWN0LmRlZmluZVByb3BlcnR5KGUsdCx7dmFsdWU6bixlbnVtZXJhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMCx3cml0YWJsZTohMH0pOmVbdF09bixlfX0sZnVuY3Rpb24oZSx0KXtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXtpZighKGUgaW5zdGFuY2VvZiB0KSl0aHJvdyBuZXcgVHlwZUVycm9yKCJDYW5ub3QgY2FsbCBhIGNsYXNzIGFzIGEgZnVuY3Rpb24iKX19LGZ1bmN0aW9uKGUsdCxuKXt2YXIgcj1uKDE4KSxhPW4oNyk7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIXR8fCJvYmplY3QiIT09cih0KSYmImZ1bmN0aW9uIiE9dHlwZW9mIHQ/YShlKTp0fX0sZnVuY3Rpb24oZSx0KXtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7aWYodm9pZCAwPT09ZSl0aHJvdyBuZXcgUmVmZXJlbmNlRXJyb3IoInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZCIpO3JldHVybiBlfX0sZnVuY3Rpb24oZSx0LG4pe3ZhciByPW4oMTkpO2UuZXhwb3J0cz1mdW5jdGlvbihlLHQpe2lmKCJmdW5jdGlvbiIhPXR5cGVvZiB0JiZudWxsIT09dCl0aHJvdyBuZXcgVHlwZUVycm9yKCJTdXBlciBleHByZXNzaW9uIG11c3QgZWl0aGVyIGJlIG51bGwgb3IgYSBmdW5jdGlvbiIpO2UucHJvdG90eXBlPU9iamVjdC5jcmVhdGUodCYmdC5wcm90b3R5cGUse2NvbnN0cnVjdG9yOnt2YWx1ZTplLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH19KSx0JiZyKGUsdCl9fSxmdW5jdGlvbihlLHQsbil7dmFyIHI9bigxOCk7ZnVuY3Rpb24gYSgpe2lmKCJmdW5jdGlvbiIhPXR5cGVvZiBXZWFrTWFwKXJldHVybiBudWxsO3ZhciBlPW5ldyBXZWFrTWFwO3JldHVybiBhPWZ1bmN0aW9uKCl7cmV0dXJuIGV9LGV9ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKGUmJmUuX19lc01vZHVsZSlyZXR1cm4gZTtpZihudWxsPT09ZXx8Im9iamVjdCIhPT1yKGUpJiYiZnVuY3Rpb24iIT10eXBlb2YgZSlyZXR1cm57ZGVmYXVsdDplfTt2YXIgdD1hKCk7aWYodCYmdC5oYXMoZSkpcmV0dXJuIHQuZ2V0KGUpO3ZhciBuPXt9LG89T2JqZWN0LmRlZmluZVByb3BlcnR5JiZPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yO2Zvcih2YXIgaSBpbiBlKWlmKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChlLGkpKXt2YXIgdT1vP09iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoZSxpKTpudWxsO3UmJih1LmdldHx8dS5zZXQpP09iamVjdC5kZWZpbmVQcm9wZXJ0eShuLGksdSk6bltpXT1lW2ldfXJldHVybiBuLmRlZmF1bHQ9ZSx0JiZ0LnNldChlLG4pLG59fSxmdW5jdGlvbihlLHQpe2Z1bmN0aW9uIG4oKXtyZXR1cm4gZS5leHBvcnRzPW49T2JqZWN0LmFzc2lnbnx8ZnVuY3Rpb24oZSl7Zm9yKHZhciB0PTE7dDxhcmd1bWVudHMubGVuZ3RoO3QrKyl7dmFyIG49YXJndW1lbnRzW3RdO2Zvcih2YXIgciBpbiBuKU9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChuLHIpJiYoZVtyXT1uW3JdKX1yZXR1cm4gZX0sbi5hcHBseSh0aGlzLGFyZ3VtZW50cyl9ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsdCl7ZnVuY3Rpb24gbihlLHQpe2Zvcih2YXIgbj0wO248dC5sZW5ndGg7bisrKXt2YXIgcj10W25dO3IuZW51bWVyYWJsZT1yLmVudW1lcmFibGV8fCExLHIuY29uZmlndXJhYmxlPSEwLCJ2YWx1ZSJpbiByJiYoci53cml0YWJsZT0hMCksT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsci5rZXkscil9fWUuZXhwb3J0cz1mdW5jdGlvbihlLHQscil7cmV0dXJuIHQmJm4oZS5wcm90b3R5cGUsdCksciYmbihlLHIpLGV9fSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO3ZhciByPW4oMSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsIl9fZXNNb2R1bGUiLHt2YWx1ZTohMH0pLHQubG9hZEZyb21GaWxlPXQuaXNDYW5jZWxFeGNlcHRpb249dC5tYWtlUGFnZUNhbGxiYWNrPXQuY2FuY2VsUnVubmluZ1Rhc2s9dC5tYWtlQ2FuY2VsbGFibGU9dC5kaXNwbGF5Q09SU1dhcm5pbmc9dC5lcnJvck9uRGV2PXQud2Fybk9uRGV2PXQuZ2V0UGl4ZWxSYXRpbz10LmNhbGxJZkRlZmluZWQ9dC5kYXRhVVJJdG9VaW50OEFycmF5PXQuaXNEYXRhVVJJPXQuaXNGaWxlPXQuaXNCbG9iPXQuaXNBcnJheUJ1ZmZlcj10LmlzU3RyaW5nPXQuaXNQcm92aWRlZD10LmlzRGVmaW5lZD10LmlzUHJvZHVjdGlvbj10LmlzTG9jYWxGaWxlU3lzdGVtPXQuaXNCcm93c2VyPXZvaWQgMDt2YXIgYT1yKG4oNSkpLG89cihuKDYpKSxpPXIobigyKSksdT1yKG4oOCkpLGM9cihuKDM4KSkscz0idW5kZWZpbmVkIiE9dHlwZW9mIHdpbmRvdzt0LmlzQnJvd3Nlcj1zO3ZhciBsPXMmJiJmaWxlOiI9PT13aW5kb3cubG9jYXRpb24ucHJvdG9jb2w7dC5pc0xvY2FsRmlsZVN5c3RlbT1sO3QuaXNQcm9kdWN0aW9uPSEwO3ZhciBmPWZ1bmN0aW9uKGUpe3JldHVybiB2b2lkIDAhPT1lfTt0LmlzRGVmaW5lZD1mO3QuaXNQcm92aWRlZD1mdW5jdGlvbihlKXtyZXR1cm4gZihlKSYmbnVsbCE9PWV9O3ZhciBkPWZ1bmN0aW9uKGUpe3JldHVybiJzdHJpbmciPT10eXBlb2YgZX07dC5pc1N0cmluZz1kO3QuaXNBcnJheUJ1ZmZlcj1mdW5jdGlvbihlKXtyZXR1cm4gZSBpbnN0YW5jZW9mIEFycmF5QnVmZmVyfTt0LmlzQmxvYj1mdW5jdGlvbihlKXtpZighcyl0aHJvdyBuZXcgRXJyb3IoIkF0dGVtcHRlZCB0byBjaGVjayBpZiBhIHZhcmlhYmxlIGlzIGEgQmxvYiBvbiBhIG5vbi1icm93c2VyIGVudmlyb25tZW50LiIpO3JldHVybiBlIGluc3RhbmNlb2YgQmxvYn07dC5pc0ZpbGU9ZnVuY3Rpb24oZSl7aWYoIXMpdGhyb3cgbmV3IEVycm9yKCJBdHRlbXB0ZWQgdG8gY2hlY2sgaWYgYSB2YXJpYWJsZSBpcyBhIEZpbGUgb24gYSBub24tYnJvd3NlciBlbnZpcm9ubWVudC4iKTtyZXR1cm4gZSBpbnN0YW5jZW9mIEZpbGV9O3ZhciBwPWZ1bmN0aW9uKGUpe3JldHVybiBkKGUpJiYvXmRhdGE6Ly50ZXN0KGUpfTt0LmlzRGF0YVVSST1wO3QuZGF0YVVSSXRvVWludDhBcnJheT1mdW5jdGlvbihlKXtpZighcChlKSl0aHJvdyBuZXcgRXJyb3IoImRhdGFVUkl0b1VpbnQ4QXJyYXkgd2FzIHByb3ZpZGVkIHdpdGggYW4gYXJndW1lbnQgd2hpY2ggaXMgbm90IGEgdmFsaWQgZGF0YSBVUkkuIik7dmFyIHQ7dD1lLnNwbGl0KCIsIilbMF0uaW5kZXhPZigiYmFzZTY0Iik+PTA/YXRvYihlLnNwbGl0KCIsIilbMV0pOnVuZXNjYXBlKGUuc3BsaXQoIiwiKVsxXSk7Zm9yKHZhciBuPW5ldyBVaW50OEFycmF5KHQubGVuZ3RoKSxyPTA7cjx0Lmxlbmd0aDtyKz0xKW5bcl09dC5jaGFyQ29kZUF0KHIpO3JldHVybiBufTt0LmNhbGxJZkRlZmluZWQ9ZnVuY3Rpb24oZSl7aWYoZSYmImZ1bmN0aW9uIj09dHlwZW9mIGUpe2Zvcih2YXIgdD1hcmd1bWVudHMubGVuZ3RoLG49bmV3IEFycmF5KHQ+MT90LTE6MCkscj0xO3I8dDtyKyspbltyLTFdPWFyZ3VtZW50c1tyXTtlLmFwcGx5KHZvaWQgMCxuKX19O3QuZ2V0UGl4ZWxSYXRpbz1mdW5jdGlvbigpe3JldHVybiBzJiZ3aW5kb3cuZGV2aWNlUGl4ZWxSYXRpb3x8MX07dmFyIGg9ZnVuY3Rpb24oZSl7fSx2PWZ1bmN0aW9uKCl7Zm9yKHZhciBlPWFyZ3VtZW50cy5sZW5ndGgsdD1uZXcgQXJyYXkoZSksbj0wO248ZTtuKyspdFtuXT1hcmd1bWVudHNbbl07cmV0dXJuIGguYXBwbHkodm9pZCAwLFsid2FybiJdLmNvbmNhdCh0KSl9O3Qud2Fybk9uRGV2PXY7dC5lcnJvck9uRGV2PWZ1bmN0aW9uKCl7Zm9yKHZhciBlPWFyZ3VtZW50cy5sZW5ndGgsdD1uZXcgQXJyYXkoZSksbj0wO248ZTtuKyspdFtuXT1hcmd1bWVudHNbbl07cmV0dXJuIGguYXBwbHkodm9pZCAwLFsiZXJyb3IiXS5jb25jYXQodCkpfTt0LmRpc3BsYXlDT1JTV2FybmluZz1mdW5jdGlvbigpe2wmJnYoIkxvYWRpbmcgUERGIGFzIGJhc2U2NCBzdHJpbmdzL1VSTHMgbWlnaHQgbm90IHdvcmsgb24gcHJvdG9jb2xzIG90aGVyIHRoYW4gSFRUUC9IVFRQUy4gT24gR29vZ2xlIENocm9tZSwgeW91IGNhbiB1c2UgLS1hbGxvdy1maWxlLWFjY2Vzcy1mcm9tLWZpbGVzIGZsYWcgZm9yIGRlYnVnZ2luZyBwdXJwb3Nlcy4iKX07dmFyIGc9ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gdChlLG4pe3ZhciByO3JldHVybigwLGEuZGVmYXVsdCkodGhpcyx0KSwocj0oMCxvLmRlZmF1bHQpKHRoaXMsKDAsaS5kZWZhdWx0KSh0KS5jYWxsKHRoaXMsZSxuKSkpLm5hbWU9IlByb21pc2VDYW5jZWxsZWRFeGNlcHRpb24iLHIubWVzc2FnZT1lLHIudHlwZT1uLHJ9cmV0dXJuKDAsdS5kZWZhdWx0KSh0LGUpLHR9KCgwLGMuZGVmYXVsdCkoRXJyb3IpKTt0Lm1ha2VDYW5jZWxsYWJsZT1mdW5jdGlvbihlKXt2YXIgdD0hMTtyZXR1cm57cHJvbWlzZTpuZXcgUHJvbWlzZSgoZnVuY3Rpb24obixyKXtlLnRoZW4oKGZ1bmN0aW9uKCl7cmV0dXJuIHQ/cihuZXcgZygiUHJvbWlzZSBjYW5jZWxsZWQiKSk6bi5hcHBseSh2b2lkIDAsYXJndW1lbnRzKX0pLChmdW5jdGlvbihlKXtyZXR1cm4gcih0P25ldyBnKCJQcm9taXNlIGNhbmNlbGxlZCIpOmUpfSkpfSkpLGNhbmNlbDpmdW5jdGlvbigpe3Q9ITB9fX07dC5jYW5jZWxSdW5uaW5nVGFzaz1mdW5jdGlvbihlKXtlJiZlLmNhbmNlbCYmZS5jYW5jZWwoKX07dC5tYWtlUGFnZUNhbGxiYWNrPWZ1bmN0aW9uKGUsdCl7cmV0dXJuIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShlLCJ3aWR0aCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnZpZXdbMl0qdH0sY29uZmlndXJhYmxlOiEwfSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsImhlaWdodCIse2dldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnZpZXdbM10qdH0sY29uZmlndXJhYmxlOiEwfSksT2JqZWN0LmRlZmluZVByb3BlcnR5KGUsIm9yaWdpbmFsV2lkdGgiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy52aWV3WzJdfSxjb25maWd1cmFibGU6ITB9KSxPYmplY3QuZGVmaW5lUHJvcGVydHkoZSwib3JpZ2luYWxIZWlnaHQiLHtnZXQ6ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy52aWV3WzNdfSxjb25maWd1cmFibGU6ITB9KSxlfTt0LmlzQ2FuY2VsRXhjZXB0aW9uPWZ1bmN0aW9uKGUpe3JldHVybiJSZW5kZXJpbmdDYW5jZWxsZWRFeGNlcHRpb24iPT09ZS5uYW1lfHwiUHJvbWlzZUNhbmNlbGxlZEV4Y2VwdGlvbiI9PT1lLm5hbWV9O3QubG9hZEZyb21GaWxlPWZ1bmN0aW9uKGUpe3JldHVybiBuZXcgUHJvbWlzZSgoZnVuY3Rpb24odCxuKXt2YXIgcj1uZXcgRmlsZVJlYWRlcjtyZXR1cm4gci5vbmxvYWQ9ZnVuY3Rpb24oKXtyZXR1cm4gdChuZXcgVWludDhBcnJheShyLnJlc3VsdCkpfSxyLm9uZXJyb3I9ZnVuY3Rpb24oZSl7c3dpdGNoKGUudGFyZ2V0LmVycm9yLmNvZGUpe2Nhc2UgZS50YXJnZXQuZXJyb3IuTk9UX0ZPVU5EX0VSUjpyZXR1cm4gbihuZXcgRXJyb3IoIkVycm9yIHdoaWxlIHJlYWRpbmcgYSBmaWxlOiBGaWxlIG5vdCBmb3VuZC4iKSk7Y2FzZSBlLnRhcmdldC5lcnJvci5OT1RfUkVBREFCTEVfRVJSOnJldHVybiBuKG5ldyBFcnJvcigiRXJyb3Igd2hpbGUgcmVhZGluZyBhIGZpbGU6IEZpbGUgbm90IHJlYWRhYmxlLiIpKTtjYXNlIGUudGFyZ2V0LmVycm9yLlNFQ1VSSVRZX0VSUjpyZXR1cm4gbihuZXcgRXJyb3IoIkVycm9yIHdoaWxlIHJlYWRpbmcgYSBmaWxlOiBTZWN1cml0eSBlcnJvci4iKSk7Y2FzZSBlLnRhcmdldC5lcnJvci5BQk9SVF9FUlI6cmV0dXJuIG4obmV3IEVycm9yKCJFcnJvciB3aGlsZSByZWFkaW5nIGEgZmlsZTogQWJvcnRlZC4iKSk7ZGVmYXVsdDpyZXR1cm4gbihuZXcgRXJyb3IoIkVycm9yIHdoaWxlIHJlYWRpbmcgYSBmaWxlLiIpKX19LHIucmVhZEFzQXJyYXlCdWZmZXIoZSksbnVsbH0pKX19LGZ1bmN0aW9uKGUsdCxuKXsidXNlIHN0cmljdCI7dmFyIHI9bigxKTtPYmplY3QuZGVmaW5lUHJvcGVydHkodCwiX19lc01vZHVsZSIse3ZhbHVlOiEwfSksdC5pc1JvdGF0ZT10LmlzUmVuZGVyTW9kZT10LmlzUGRmPXQuaXNQYWdlTnVtYmVyPXQuaXNQYWdlSW5kZXg9dC5pc1BhZ2U9dC5pc0xpbmtUYXJnZXQ9dC5pc0xpbmtTZXJ2aWNlPXQuaXNGaWxlPXQuaXNDbGFzc05hbWU9dC5ldmVudHNQcm9wcz12b2lkIDA7dmFyIGE9cihuKDE4KSksbz1yKG4oNDEpKSxpPXIobigzKSksdT1yKG4oNDUpKSxjPW4oMjApLHM9bigxMiksbD1yKG4oMjYpKSxmPSgwLHUuZGVmYXVsdCkoKGZ1bmN0aW9uKCl7dmFyIGU9e307cmV0dXJuW10uY29uY2F0KCgwLG8uZGVmYXVsdCkoYy5tb3VzZUV2ZW50cyksKDAsby5kZWZhdWx0KShjLnRvdWNoRXZlbnRzKSwoMCxvLmRlZmF1bHQpKGMua2V5Ym9hcmRFdmVudHMpKS5mb3JFYWNoKChmdW5jdGlvbih0KXtlW3RdPWkuZGVmYXVsdC5mdW5jfSkpLGV9KSk7dC5ldmVudHNQcm9wcz1mO3ZhciBkPVtpLmRlZmF1bHQuc3RyaW5nLGkuZGVmYXVsdC5pbnN0YW5jZU9mKEFycmF5QnVmZmVyKSxpLmRlZmF1bHQuc2hhcGUoe2RhdGE6aS5kZWZhdWx0Lm9iamVjdCxodHRwSGVhZGVyczppLmRlZmF1bHQub2JqZWN0LHJhbmdlOmkuZGVmYXVsdC5vYmplY3QsdXJsOmkuZGVmYXVsdC5zdHJpbmcsd2l0aENyZWRlbnRpYWxzOmkuZGVmYXVsdC5ib29sfSldOyJ1bmRlZmluZWQiIT10eXBlb2YgRmlsZSYmZC5wdXNoKGkuZGVmYXVsdC5pbnN0YW5jZU9mKEZpbGUpKSwidW5kZWZpbmVkIiE9dHlwZW9mIEJsb2ImJmQucHVzaChpLmRlZmF1bHQuaW5zdGFuY2VPZihCbG9iKSk7dmFyIHA9aS5kZWZhdWx0Lm9uZU9mVHlwZShbaS5kZWZhdWx0LnN0cmluZyxpLmRlZmF1bHQuYXJyYXlPZihpLmRlZmF1bHQuc3RyaW5nKV0pO3QuaXNDbGFzc05hbWU9cDt2YXIgaD1pLmRlZmF1bHQub25lT2ZUeXBlKGQpO3QuaXNGaWxlPWg7dmFyIHY9aS5kZWZhdWx0Lmluc3RhbmNlT2YobC5kZWZhdWx0KTt0LmlzTGlua1NlcnZpY2U9djt2YXIgZz1pLmRlZmF1bHQub25lT2YoWyJfc2VsZiIsIl9ibGFuayIsIl9wYXJlbnQiLCJfdG9wIl0pO3QuaXNMaW5rVGFyZ2V0PWc7dmFyIG09aS5kZWZhdWx0LnNoYXBlKHtfdHJhbnNwb3J0OmkuZGVmYXVsdC5zaGFwZSh7Zm9udExvYWRlcjppLmRlZmF1bHQub2JqZWN0LmlzUmVxdWlyZWR9KS5pc1JlcXVpcmVkLGNvbW1vbk9ianM6aS5kZWZhdWx0LnNoYXBlKHtfb2JqczppLmRlZmF1bHQub2JqZWN0LmlzUmVxdWlyZWR9KS5pc1JlcXVpcmVkLGdldEFubm90YXRpb25zOmkuZGVmYXVsdC5mdW5jLmlzUmVxdWlyZWQsZ2V0VGV4dENvbnRlbnQ6aS5kZWZhdWx0LmZ1bmMuaXNSZXF1aXJlZCxnZXRWaWV3cG9ydDppLmRlZmF1bHQuZnVuYy5pc1JlcXVpcmVkLHJlbmRlcjppLmRlZmF1bHQuZnVuYy5pc1JlcXVpcmVkfSk7dC5pc1BhZ2U9bTt0LmlzUGFnZUluZGV4PWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj1lW3RdLG89ZS5wYWdlTnVtYmVyLGk9ZS5wZGY7aWYoISgwLHMuaXNEZWZpbmVkKShpKSlyZXR1cm4gbnVsbDtpZigoMCxzLmlzRGVmaW5lZCkocikpe2lmKCJudW1iZXIiIT10eXBlb2YgcilyZXR1cm4gbmV3IEVycm9yKCJgIi5jb25jYXQodCwiYCBvZiB0eXBlIGAiKS5jb25jYXQoKDAsYS5kZWZhdWx0KShyKSwiYCBzdXBwbGllZCB0byBgIikuY29uY2F0KG4sImAsIGV4cGVjdGVkIGBudW1iZXJgLiIpKTtpZihyPDApcmV0dXJuIG5ldyBFcnJvcigiRXhwZWN0ZWQgYCIuY29uY2F0KHQsImAgdG8gYmUgZ3JlYXRlciBvciBlcXVhbCB0byAwLiIpKTt2YXIgdT1pLm51bVBhZ2VzO2lmKHIrMT51KXJldHVybiBuZXcgRXJyb3IoIkV4cGVjdGVkIGAiLmNvbmNhdCh0LCJgIHRvIGJlIGxlc3Mgb3IgZXF1YWwgdG8gIikuY29uY2F0KHUtMSwiLiIpKX1lbHNlIGlmKCEoMCxzLmlzRGVmaW5lZCkobykpcmV0dXJuIG5ldyBFcnJvcigiYCIuY29uY2F0KHQsImAgbm90IHN1cHBsaWVkLiBFaXRoZXIgcGFnZUluZGV4IG9yIHBhZ2VOdW1iZXIgbXVzdCBiZSBzdXBwbGllZCB0byBgIikuY29uY2F0KG4sImAuIikpO3JldHVybiBudWxsfTt0LmlzUGFnZU51bWJlcj1mdW5jdGlvbihlLHQsbil7dmFyIHI9ZVt0XSxvPWUucGFnZUluZGV4LGk9ZS5wZGY7aWYoISgwLHMuaXNEZWZpbmVkKShpKSlyZXR1cm4gbnVsbDtpZigoMCxzLmlzRGVmaW5lZCkocikpe2lmKCJudW1iZXIiIT10eXBlb2YgcilyZXR1cm4gbmV3IEVycm9yKCJgIi5jb25jYXQodCwiYCBvZiB0eXBlIGAiKS5jb25jYXQoKDAsYS5kZWZhdWx0KShyKSwiYCBzdXBwbGllZCB0byBgIikuY29uY2F0KG4sImAsIGV4cGVjdGVkIGBudW1iZXJgLiIpKTtpZihyPDEpcmV0dXJuIG5ldyBFcnJvcigiRXhwZWN0ZWQgYCIuY29uY2F0KHQsImAgdG8gYmUgZ3JlYXRlciBvciBlcXVhbCB0byAxLiIpKTt2YXIgdT1pLm51bVBhZ2VzO2lmKHI+dSlyZXR1cm4gbmV3IEVycm9yKCJFeHBlY3RlZCBgIi5jb25jYXQodCwiYCB0byBiZSBsZXNzIG9yIGVxdWFsIHRvICIpLmNvbmNhdCh1LCIuIikpfWVsc2UgaWYoISgwLHMuaXNEZWZpbmVkKShvKSlyZXR1cm4gbmV3IEVycm9yKCJgIi5jb25jYXQodCwiYCBub3Qgc3VwcGxpZWQuIEVpdGhlciBwYWdlSW5kZXggb3IgcGFnZU51bWJlciBtdXN0IGJlIHN1cHBsaWVkIHRvIGAiKS5jb25jYXQobiwiYC4iKSk7cmV0dXJuIG51bGx9O3ZhciB5PWkuZGVmYXVsdC5vbmVPZlR5cGUoW2kuZGVmYXVsdC5zaGFwZSh7Z2V0RGVzdGluYXRpb246aS5kZWZhdWx0LmZ1bmMuaXNSZXF1aXJlZCxnZXRPdXRsaW5lOmkuZGVmYXVsdC5mdW5jLmlzUmVxdWlyZWQsZ2V0UGFnZTppLmRlZmF1bHQuZnVuYy5pc1JlcXVpcmVkLG51bVBhZ2VzOmkuZGVmYXVsdC5udW1iZXIuaXNSZXF1aXJlZH0pLGkuZGVmYXVsdC5ib29sXSk7dC5pc1BkZj15O3ZhciBiPWkuZGVmYXVsdC5vbmVPZihbImNhbnZhcyIsIm5vbmUiLCJzdmciXSk7dC5pc1JlbmRlck1vZGU9Yjt2YXIgdz1pLmRlZmF1bHQub25lT2YoWzAsOTAsMTgwLDI3MF0pO3QuaXNSb3RhdGU9d30sZnVuY3Rpb24oZSx0LG4peyhmdW5jdGlvbih0KXtmb3IodmFyIHI9big1NiksYT0idW5kZWZpbmVkIj09dHlwZW9mIHdpbmRvdz90OndpbmRvdyxvPVsibW96Iiwid2Via2l0Il0saT0iQW5pbWF0aW9uRnJhbWUiLHU9YVsicmVxdWVzdCIraV0sYz1hWyJjYW5jZWwiK2ldfHxhWyJjYW5jZWxSZXF1ZXN0IitpXSxzPTA7IXUmJnM8by5sZW5ndGg7cysrKXU9YVtvW3NdKyJSZXF1ZXN0IitpXSxjPWFbb1tzXSsiQ2FuY2VsIitpXXx8YVtvW3NdKyJDYW5jZWxSZXF1ZXN0IitpXTtpZighdXx8IWMpe3ZhciBsPTAsZj0wLGQ9W107dT1mdW5jdGlvbihlKXtpZigwPT09ZC5sZW5ndGgpe3ZhciB0PXIoKSxuPU1hdGgubWF4KDAsMWUzLzYwLSh0LWwpKTtsPW4rdCxzZXRUaW1lb3V0KChmdW5jdGlvbigpe3ZhciBlPWQuc2xpY2UoMCk7ZC5sZW5ndGg9MDtmb3IodmFyIHQ9MDt0PGUubGVuZ3RoO3QrKylpZighZVt0XS5jYW5jZWxsZWQpdHJ5e2VbdF0uY2FsbGJhY2sobCl9Y2F0Y2goZSl7c2V0VGltZW91dCgoZnVuY3Rpb24oKXt0aHJvdyBlfSksMCl9fSksTWF0aC5yb3VuZChuKSl9cmV0dXJuIGQucHVzaCh7aGFuZGxlOisrZixjYWxsYmFjazplLGNhbmNlbGxlZDohMX0pLGZ9LGM9ZnVuY3Rpb24oZSl7Zm9yKHZhciB0PTA7dDxkLmxlbmd0aDt0KyspZFt0XS5oYW5kbGU9PT1lJiYoZFt0XS5jYW5jZWxsZWQ9ITApfX1lLmV4cG9ydHM9ZnVuY3Rpb24oZSl7cmV0dXJuIHUuY2FsbChhLGUpfSxlLmV4cG9ydHMuY2FuY2VsPWZ1bmN0aW9uKCl7Yy5hcHBseShhLGFyZ3VtZW50cyl9LGUuZXhwb3J0cy5wb2x5ZmlsbD1mdW5jdGlvbihlKXtlfHwoZT1hKSxlLnJlcXVlc3RBbmltYXRpb25GcmFtZT11LGUuY2FuY2VsQW5pbWF0aW9uRnJhbWU9Y319KS5jYWxsKHRoaXMsbig1NSkpfSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSx0LmRlZmF1bHQ9dm9pZCAwO3ZhciByPSgwLG4oMCkuY3JlYXRlQ29udGV4dCkobnVsbCk7dC5kZWZhdWx0PXJ9LGZ1bmN0aW9uKGUsdCxuKXtlLmV4cG9ydHM9bigzMyl9LGZ1bmN0aW9uKGUsdCl7ZnVuY3Rpb24gbihlLHQsbixyLGEsbyxpKXt0cnl7dmFyIHU9ZVtvXShpKSxjPXUudmFsdWV9Y2F0Y2goZSl7cmV0dXJuIHZvaWQgbihlKX11LmRvbmU/dChjKTpQcm9taXNlLnJlc29sdmUoYykudGhlbihyLGEpfWUuZXhwb3J0cz1mdW5jdGlvbihlKXtyZXR1cm4gZnVuY3Rpb24oKXt2YXIgdD10aGlzLHI9YXJndW1lbnRzO3JldHVybiBuZXcgUHJvbWlzZSgoZnVuY3Rpb24oYSxvKXt2YXIgaT1lLmFwcGx5KHQscik7ZnVuY3Rpb24gdShlKXtuKGksYSxvLHUsYywibmV4dCIsZSl9ZnVuY3Rpb24gYyhlKXtuKGksYSxvLHUsYywidGhyb3ciLGUpfXUodm9pZCAwKX0pKX19fSxmdW5jdGlvbihlLHQpe2Z1bmN0aW9uIG4odCl7cmV0dXJuImZ1bmN0aW9uIj09dHlwZW9mIFN5bWJvbCYmInN5bWJvbCI9PXR5cGVvZiBTeW1ib2wuaXRlcmF0b3I/ZS5leHBvcnRzPW49ZnVuY3Rpb24oZSl7cmV0dXJuIHR5cGVvZiBlfTplLmV4cG9ydHM9bj1mdW5jdGlvbihlKXtyZXR1cm4gZSYmImZ1bmN0aW9uIj09dHlwZW9mIFN5bWJvbCYmZS5jb25zdHJ1Y3Rvcj09PVN5bWJvbCYmZSE9PVN5bWJvbC5wcm90b3R5cGU/InN5bWJvbCI6dHlwZW9mIGV9LG4odCl9ZS5leHBvcnRzPW59LGZ1bmN0aW9uKGUsdCl7ZnVuY3Rpb24gbih0LHIpe3JldHVybiBlLmV4cG9ydHM9bj1PYmplY3Quc2V0UHJvdG90eXBlT2Z8fGZ1bmN0aW9uKGUsdCl7cmV0dXJuIGUuX19wcm90b19fPXQsZX0sbih0LHIpfWUuZXhwb3J0cz1ufSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSx0LmRlZmF1bHQ9dC5mb2N1c0V2ZW50cz10LmtleWJvYXJkRXZlbnRzPXQudG91Y2hFdmVudHM9dC5tb3VzZUV2ZW50cz12b2lkIDA7dmFyIHI9WyJvbkNsaWNrIiwib25Db250ZXh0TWVudSIsIm9uRG91YmxlQ2xpY2siLCJvbkRyYWciLCJvbkRyYWdFbmQiLCJvbkRyYWdFbnRlciIsIm9uRHJhZ0V4aXQiLCJvbkRyYWdMZWF2ZSIsIm9uRHJhZ092ZXIiLCJvbkRyYWdTdGFydCIsIm9uRHJvcCIsIm9uTW91c2VEb3duIiwib25Nb3VzZUVudGVyIiwib25Nb3VzZUxlYXZlIiwib25Nb3VzZU1vdmUiLCJvbk1vdXNlT3V0Iiwib25Nb3VzZU92ZXIiLCJvbk1vdXNlVXAiXTt0Lm1vdXNlRXZlbnRzPXI7dmFyIGE9WyJvblRvdWNoQ2FuY2VsIiwib25Ub3VjaEVuZCIsIm9uVG91Y2hNb3ZlIiwib25Ub3VjaFN0YXJ0Il07dC50b3VjaEV2ZW50cz1hO3ZhciBvPVsib25LZXlEb3duIiwib25LZXlQcmVzcyIsIm9uS2V5VXAiXTt0LmtleWJvYXJkRXZlbnRzPW87dmFyIGk9WyJvbkZvY3VzIiwib25CbHVyIl07dC5mb2N1c0V2ZW50cz1pO3ZhciB1PWZ1bmN0aW9uKGUsdCl7dmFyIG49e307cmV0dXJuW10uY29uY2F0KHIsYSxvLGkpLmZvckVhY2goKGZ1bmN0aW9uKHIpe2Vbcl0mJihuW3JdPWZ1bmN0aW9uKG4pe3JldHVybiB0P2Vbcl0obix0KHIpKTplW3JdKG4pfSl9KSksbn07dC5kZWZhdWx0PXV9LGZ1bmN0aW9uKGUsdCl7ZS5leHBvcnRzPXBkZmpzTGlifSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSx0LmRlZmF1bHQ9dm9pZCAwO3ZhciByPSgwLG4oMCkuY3JlYXRlQ29udGV4dCkobnVsbCk7dC5kZWZhdWx0PXJ9LGZ1bmN0aW9uKGUsdCxuKXt2YXIgcj1uKDQpO2UuZXhwb3J0cz1mdW5jdGlvbihlKXtmb3IodmFyIHQ9MTt0PGFyZ3VtZW50cy5sZW5ndGg7dCsrKXt2YXIgbj1udWxsIT1hcmd1bWVudHNbdF0/YXJndW1lbnRzW3RdOnt9LGE9T2JqZWN0LmtleXMoT2JqZWN0KG4pKTsiZnVuY3Rpb24iPT10eXBlb2YgT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyYmKGE9YS5jb25jYXQoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhuKS5maWx0ZXIoKGZ1bmN0aW9uKGUpe3JldHVybiBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKG4sZSkuZW51bWVyYWJsZX0pKSkpLGEuZm9yRWFjaCgoZnVuY3Rpb24odCl7cihlLHQsblt0XSl9KSl9cmV0dXJuIGV9fSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KTt0LmRlZmF1bHQ9ZnVuY3Rpb24oKXtmb3IodmFyIGU9YXJndW1lbnRzLmxlbmd0aCx0PUFycmF5KGUpLG49MDtuPGU7bisrKXRbbl09YXJndW1lbnRzW25dO3JldHVybiB0LnJlZHVjZSgoZnVuY3Rpb24oZSx0KXtyZXR1cm4ic3RyaW5nIj09dHlwZW9mIHR8fHQgaW5zdGFuY2VvZiBBcnJheT9lLmNvbmNhdCh0KTplfSksW10pLmZpbHRlcigoZnVuY3Rpb24oZSl7cmV0dXJuIGV9KSkuam9pbigiICIpfX0sZnVuY3Rpb24oZSx0LG4peyJ1c2Ugc3RyaWN0Ijt2YXIgcj1uKDEpO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSx0LmRlZmF1bHQ9dm9pZCAwO3ZhciBhPXIobigwKSksbz1yKG4oMykpLGk9ZnVuY3Rpb24oZSl7dmFyIHQ9ZS5jaGlsZHJlbixuPWUudHlwZTtyZXR1cm4gYS5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoImRpdiIse2NsYXNzTmFtZToicmVhY3QtcGRmX19tZXNzYWdlIHJlYWN0LXBkZl9fbWVzc2FnZS0tIi5jb25jYXQobil9LHQpfTtpLnByb3BUeXBlcz17Y2hpbGRyZW46by5kZWZhdWx0Lm5vZGUsdHlwZTpvLmRlZmF1bHQub25lT2YoWyJlcnJvciIsImxvYWRpbmciLCJuby1kYXRhIl0pLmlzUmVxdWlyZWR9O3ZhciB1PWk7dC5kZWZhdWx0PXV9LGZ1bmN0aW9uKGUsdCxuKXsidXNlIHN0cmljdCI7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsIl9fZXNNb2R1bGUiLHt2YWx1ZTohMH0pLHQuZGVmYXVsdD12b2lkIDA7dmFyIHI9bigzNikuUERGTGlua1NlcnZpY2U7dC5kZWZhdWx0PXJ9LGZ1bmN0aW9uKGUsdCl7ZS5leHBvcnRzPVJlYWN0RE9NfSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO3ZhciByPW4oOSksYT1uKDEpO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSx0LmRlZmF1bHQ9dm9pZCAwO3ZhciBvPWEobigxMCkpLGk9YShuKDMxKSksdT1hKG4oMTgpKSxjPWEobigxNikpLHM9YShuKDIzKSksbD1hKG4oMTcpKSxmPWEobig1KSksZD1hKG4oMTEpKSxwPWEobig2KSksaD1hKG4oMikpLHY9YShuKDgpKSxnPWEobig3KSksbT1hKG4oNCkpLHk9cihuKDApKSxiPWEobigzKSksdz1hKG4oMjApKSx4PWEobigyNCkpLEU9cihuKDIxKSksXz1hKG4oMjIpKSxrPWEobigyNSkpLFA9YShuKDI2KSksUz1hKG4oMzcpKSxSPW4oMTIpLE89bigxMyksTD1mdW5jdGlvbihlKXtmdW5jdGlvbiB0KCl7dmFyIGUsbjsoMCxmLmRlZmF1bHQpKHRoaXMsdCk7Zm9yKHZhciByPWFyZ3VtZW50cy5sZW5ndGgsYT1uZXcgQXJyYXkociksbz0wO288cjtvKyspYVtvXT1hcmd1bWVudHNbb107cmV0dXJuIG49KDAscC5kZWZhdWx0KSh0aGlzLChlPSgwLGguZGVmYXVsdCkodCkpLmNhbGwuYXBwbHkoZSxbdGhpc10uY29uY2F0KGEpKSksKDAsbS5kZWZhdWx0KSgoMCxnLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkobikpLCJzdGF0ZSIse3BkZjpudWxsfSksKDAsbS5kZWZhdWx0KSgoMCxnLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkobikpLCJ2aWV3ZXIiLHtzY3JvbGxQYWdlSW50b1ZpZXc6ZnVuY3Rpb24oZSl7dmFyIHQ9ZS5wYWdlTnVtYmVyLHI9bi5wcm9wcy5vbkl0ZW1DbGljaztpZihyKXIoe3BhZ2VOdW1iZXI6dH0pO2Vsc2V7dmFyIGE9bi5wYWdlc1t0LTFdO2E/YS5zY3JvbGxJbnRvVmlldygpOigwLFIud2Fybk9uRGV2KSgiV2FybmluZzogQW4gaW50ZXJuYWwgbGluayBsZWFkaW5nIHRvIHBhZ2UgIi5jb25jYXQodCwiIHdhcyBjbGlja2VkLCBidXQgbmVpdGhlciA8RG9jdW1lbnQ+IHdhcyBwcm92aWRlZCB3aXRoIG9uSXRlbUNsaWNrIG5vciBpdCB3YXMgYWJsZSB0byBmaW5kIHRoZSBwYWdlIHdpdGhpbiBpdHNlbGYuIEVpdGhlciBwcm92aWRlIG9uSXRlbUNsaWNrIHRvIDxEb2N1bWVudD4gYW5kIGhhbmRsZSBuYXZpZ2F0aW5nIGJ5IHlvdXJzZWxmIG9yIGVuc3VyZSB0aGF0IGFsbCBwYWdlcyBhcmUgcmVuZGVyZWQgd2l0aGluIDxEb2N1bWVudD4uIikpfX19KSwoMCxtLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkoKDAsZy5kZWZhdWx0KShuKSksImxpbmtTZXJ2aWNlIixuZXcgUC5kZWZhdWx0KSwoMCxtLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkoKDAsZy5kZWZhdWx0KShuKSksImxvYWREb2N1bWVudCIsKDAsbC5kZWZhdWx0KShjLmRlZmF1bHQubWFyaygoZnVuY3Rpb24gZSgpe3ZhciB0LHIsYSxvLGksdSxsLGY7cmV0dXJuIGMuZGVmYXVsdC53cmFwKChmdW5jdGlvbihlKXtmb3IoOzspc3dpdGNoKGUucHJldj1lLm5leHQpe2Nhc2UgMDpyZXR1cm4gdD1udWxsLGUucHJldj0xLGUubmV4dD00LG4uZmluZERvY3VtZW50U291cmNlKCk7Y2FzZSA0OnQ9ZS5zZW50LG4ub25Tb3VyY2VTdWNjZXNzKCksZS5uZXh0PTExO2JyZWFrO2Nhc2UgODplLnByZXY9OCxlLnQwPWUuY2F0Y2goMSksbi5vblNvdXJjZUVycm9yKGUudDApO2Nhc2UgMTE6aWYodCl7ZS5uZXh0PTEzO2JyZWFrfXJldHVybiBlLmFicnVwdCgicmV0dXJuIik7Y2FzZSAxMzpyZXR1cm4gbi5zZXRTdGF0ZSgoZnVuY3Rpb24oZSl7cmV0dXJuIGUucGRmP3twZGY6bnVsbH06bnVsbH0pKSxyPW4ucHJvcHMsYT1yLm9wdGlvbnMsbz1yLm9uTG9hZFByb2dyZXNzLGk9ci5vblBhc3N3b3JkLGUucHJldj0xNSwoMCxSLmNhbmNlbFJ1bm5pbmdUYXNrKShuLnJ1bm5pbmdUYXNrKSwodT1FLmRlZmF1bHQuZ2V0RG9jdW1lbnQoKDAscy5kZWZhdWx0KSh7fSx0LGEpKSkub25QYXNzd29yZD1pLG8mJih1Lm9uUHJvZ3Jlc3M9byksbD0oMCxSLm1ha2VDYW5jZWxsYWJsZSkodS5wcm9taXNlKSxuLnJ1bm5pbmdUYXNrPWwsZS5uZXh0PTI0LGwucHJvbWlzZTtjYXNlIDI0OmY9ZS5zZW50LG4uc2V0U3RhdGUoKGZ1bmN0aW9uKGUpe3JldHVybiBlLnBkZiYmZS5wZGYuZmluZ2VycHJpbnQ9PT1mLmZpbmdlcnByaW50P251bGw6e3BkZjpmfX0pLG4ub25Mb2FkU3VjY2VzcyksZS5uZXh0PTMxO2JyZWFrO2Nhc2UgMjg6ZS5wcmV2PTI4LGUudDE9ZS5jYXRjaCgxNSksbi5vbkxvYWRFcnJvcihlLnQxKTtjYXNlIDMxOmNhc2UiZW5kIjpyZXR1cm4gZS5zdG9wKCl9fSksZSx0aGlzLFtbMSw4XSxbMTUsMjhdXSl9KSkpKSwoMCxtLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkoKDAsZy5kZWZhdWx0KShuKSksInNldHVwTGlua1NlcnZpY2UiLChmdW5jdGlvbigpe24ubGlua1NlcnZpY2Uuc2V0Vmlld2VyKG4udmlld2VyKTt2YXIgZT0oMCxnLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkobikpO09iamVjdC5kZWZpbmVQcm9wZXJ0eShuLmxpbmtTZXJ2aWNlLCJleHRlcm5hbExpbmtUYXJnZXQiLHtnZXQ6ZnVuY3Rpb24oKXtzd2l0Y2goZS5wcm9wcy5leHRlcm5hbExpbmtUYXJnZXQpe2Nhc2UiX3NlbGYiOnJldHVybiAxO2Nhc2UiX2JsYW5rIjpyZXR1cm4gMjtjYXNlIl9wYXJlbnQiOnJldHVybiAzO2Nhc2UiX3RvcCI6cmV0dXJuIDQ7ZGVmYXVsdDpyZXR1cm4gMH19fSl9KSksKDAsbS5kZWZhdWx0KSgoMCxnLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkobikpLCJvblNvdXJjZVN1Y2Nlc3MiLChmdW5jdGlvbigpe3ZhciBlPW4ucHJvcHMub25Tb3VyY2VTdWNjZXNzOygwLFIuY2FsbElmRGVmaW5lZCkoZSl9KSksKDAsbS5kZWZhdWx0KSgoMCxnLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkobikpLCJvblNvdXJjZUVycm9yIiwoZnVuY3Rpb24oZSl7aWYoISgwLFIuaXNDYW5jZWxFeGNlcHRpb24pKGUpKXsoMCxSLmVycm9yT25EZXYpKGUpO3ZhciB0PW4ucHJvcHMub25Tb3VyY2VFcnJvcjsoMCxSLmNhbGxJZkRlZmluZWQpKHQsZSl9fSkpLCgwLG0uZGVmYXVsdCkoKDAsZy5kZWZhdWx0KSgoMCxnLmRlZmF1bHQpKG4pKSwib25Mb2FkU3VjY2VzcyIsKGZ1bmN0aW9uKCl7dmFyIGU9bi5wcm9wcy5vbkxvYWRTdWNjZXNzLHQ9bi5zdGF0ZS5wZGY7KDAsUi5jYWxsSWZEZWZpbmVkKShlLHQpLG4ucGFnZXM9bmV3IEFycmF5KHQubnVtUGFnZXMpLG4ubGlua1NlcnZpY2Uuc2V0RG9jdW1lbnQodCl9KSksKDAsbS5kZWZhdWx0KSgoMCxnLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkobikpLCJvbkxvYWRFcnJvciIsKGZ1bmN0aW9uKGUpe2lmKCEoMCxSLmlzQ2FuY2VsRXhjZXB0aW9uKShlKSl7bi5zZXRTdGF0ZSh7cGRmOiExfSksKDAsUi5lcnJvck9uRGV2KShlKTt2YXIgdD1uLnByb3BzLm9uTG9hZEVycm9yOygwLFIuY2FsbElmRGVmaW5lZCkodCxlKX19KSksKDAsbS5kZWZhdWx0KSgoMCxnLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkobikpLCJmaW5kRG9jdW1lbnRTb3VyY2UiLCgwLGwuZGVmYXVsdCkoYy5kZWZhdWx0Lm1hcmsoKGZ1bmN0aW9uIGUoKXt2YXIgdCxyLGEsbyxsO3JldHVybiBjLmRlZmF1bHQud3JhcCgoZnVuY3Rpb24oZSl7Zm9yKDs7KXN3aXRjaChlLnByZXY9ZS5uZXh0KXtjYXNlIDA6aWYodD1uLnByb3BzLmZpbGUpe2UubmV4dD0zO2JyZWFrfXJldHVybiBlLmFicnVwdCgicmV0dXJuIixudWxsKTtjYXNlIDM6aWYoInN0cmluZyIhPXR5cGVvZiB0KXtlLm5leHQ9OTticmVha31pZighKDAsUi5pc0RhdGFVUkkpKHQpKXtlLm5leHQ9NzticmVha31yZXR1cm4gcj0oMCxSLmRhdGFVUkl0b1VpbnQ4QXJyYXkpKHQpLGUuYWJydXB0KCJyZXR1cm4iLHtkYXRhOnJ9KTtjYXNlIDc6cmV0dXJuKDAsUi5kaXNwbGF5Q09SU1dhcm5pbmcpKCksZS5hYnJ1cHQoInJldHVybiIse3VybDp0fSk7Y2FzZSA5OmlmKCEodCBpbnN0YW5jZW9mIEUuUERGRGF0YVJhbmdlVHJhbnNwb3J0KSl7ZS5uZXh0PTExO2JyZWFrfXJldHVybiBlLmFicnVwdCgicmV0dXJuIix7cmFuZ2U6dH0pO2Nhc2UgMTE6aWYoISgwLFIuaXNBcnJheUJ1ZmZlcikodCkpe2UubmV4dD0xMzticmVha31yZXR1cm4gZS5hYnJ1cHQoInJldHVybiIse2RhdGE6dH0pO2Nhc2UgMTM6aWYoIVIuaXNCcm93c2VyKXtlLm5leHQ9MTk7YnJlYWt9aWYoISgwLFIuaXNCbG9iKSh0KSYmISgwLFIuaXNGaWxlKSh0KSl7ZS5uZXh0PTE5O2JyZWFrfXJldHVybiBlLm5leHQ9MTcsKDAsUi5sb2FkRnJvbUZpbGUpKHQpO2Nhc2UgMTc6cmV0dXJuIGUudDA9ZS5zZW50LGUuYWJydXB0KCJyZXR1cm4iLHtkYXRhOmUudDB9KTtjYXNlIDE5OmlmKCJvYmplY3QiPT09KDAsdS5kZWZhdWx0KSh0KSl7ZS5uZXh0PTIxO2JyZWFrfXRocm93IG5ldyBFcnJvcigiSW52YWxpZCBwYXJhbWV0ZXIgaW4gZmlsZSwgbmVlZCBlaXRoZXIgVWludDhBcnJheSwgc3RyaW5nIG9yIGEgcGFyYW1ldGVyIG9iamVjdCIpO2Nhc2UgMjE6aWYodC51cmx8fHQuZGF0YXx8dC5yYW5nZSl7ZS5uZXh0PTIzO2JyZWFrfXRocm93IG5ldyBFcnJvcigiSW52YWxpZCBwYXJhbWV0ZXIgb2JqZWN0OiBuZWVkIGVpdGhlciAuZGF0YSwgLnJhbmdlIG9yIC51cmwiKTtjYXNlIDIzOmlmKCJzdHJpbmciIT10eXBlb2YgdC51cmwpe2UubmV4dD0yOTticmVha31pZighKDAsUi5pc0RhdGFVUkkpKHQudXJsKSl7ZS5uZXh0PTI4O2JyZWFrfXJldHVybiBhPXQudXJsLG89KDAsaS5kZWZhdWx0KSh0LFsidXJsIl0pLGw9KDAsUi5kYXRhVVJJdG9VaW50OEFycmF5KShhKSxlLmFicnVwdCgicmV0dXJuIiwoMCxzLmRlZmF1bHQpKHtkYXRhOmx9LG8pKTtjYXNlIDI4OigwLFIuZGlzcGxheUNPUlNXYXJuaW5nKSgpO2Nhc2UgMjk6cmV0dXJuIGUuYWJydXB0KCJyZXR1cm4iLHQpO2Nhc2UgMzA6Y2FzZSJlbmQiOnJldHVybiBlLnN0b3AoKX19KSxlLHRoaXMpfSkpKSksKDAsbS5kZWZhdWx0KSgoMCxnLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkobikpLCJyZWdpc3RlclBhZ2UiLChmdW5jdGlvbihlLHQpe24ucGFnZXNbZV09dH0pKSwoMCxtLmRlZmF1bHQpKCgwLGcuZGVmYXVsdCkoKDAsZy5kZWZhdWx0KShuKSksInVucmVnaXN0ZXJQYWdlIiwoZnVuY3Rpb24oZSl7ZGVsZXRlIG4ucGFnZXNbZV19KSksbn1yZXR1cm4oMCx2LmRlZmF1bHQpKHQsZSksKDAsZC5kZWZhdWx0KSh0LFt7a2V5OiJjb21wb25lbnREaWRNb3VudCIsdmFsdWU6ZnVuY3Rpb24oKXt0aGlzLmxvYWREb2N1bWVudCgpLHRoaXMuc2V0dXBMaW5rU2VydmljZSgpfX0se2tleToiY29tcG9uZW50RGlkVXBkYXRlIix2YWx1ZTpmdW5jdGlvbihlKXt0aGlzLnByb3BzLmZpbGUhPT1lLmZpbGUmJnRoaXMubG9hZERvY3VtZW50KCl9fSx7a2V5OiJjb21wb25lbnRXaWxsVW5tb3VudCIsdmFsdWU6ZnVuY3Rpb24oKXsoMCxSLmNhbmNlbFJ1bm5pbmdUYXNrKSh0aGlzLnJ1bm5pbmdUYXNrKX19LHtrZXk6InJlbmRlckNoaWxkcmVuIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMuY2hpbGRyZW47cmV0dXJuIHkuZGVmYXVsdC5jcmVhdGVFbGVtZW50KF8uZGVmYXVsdC5Qcm92aWRlcix7dmFsdWU6dGhpcy5jaGlsZENvbnRleHR9LGUpfX0se2tleToicmVuZGVyQ29udGVudCIsdmFsdWU6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnByb3BzLmZpbGUsdD10aGlzLnN0YXRlLnBkZjtpZighZSl7dmFyIG49dGhpcy5wcm9wcy5ub0RhdGE7cmV0dXJuIHkuZGVmYXVsdC5jcmVhdGVFbGVtZW50KGsuZGVmYXVsdCx7dHlwZToibm8tZGF0YSJ9LCJmdW5jdGlvbiI9PXR5cGVvZiBuP24oKTpuKX1pZihudWxsPT09dCl7dmFyIHI9dGhpcy5wcm9wcy5sb2FkaW5nO3JldHVybiB5LmRlZmF1bHQuY3JlYXRlRWxlbWVudChrLmRlZmF1bHQse3R5cGU6ImxvYWRpbmcifSwiZnVuY3Rpb24iPT10eXBlb2Ygcj9yKCk6cil9aWYoITE9PT10KXt2YXIgYT10aGlzLnByb3BzLmVycm9yO3JldHVybiB5LmRlZmF1bHQuY3JlYXRlRWxlbWVudChrLmRlZmF1bHQse3R5cGU6ImVycm9yIn0sImZ1bmN0aW9uIj09dHlwZW9mIGE/YSgpOmEpfXJldHVybiB0aGlzLnJlbmRlckNoaWxkcmVuKCl9fSx7a2V5OiJyZW5kZXIiLHZhbHVlOmZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5wcm9wcyx0PWUuY2xhc3NOYW1lLG49ZS5pbnB1dFJlZjtyZXR1cm4geS5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoImRpdiIsKDAsby5kZWZhdWx0KSh7Y2xhc3NOYW1lOigwLHguZGVmYXVsdCkoInJlYWN0LXBkZl9fRG9jdW1lbnQiLHQpLHJlZjpufSx0aGlzLmV2ZW50UHJvcHMpLHRoaXMucmVuZGVyQ29udGVudCgpKX19LHtrZXk6ImNoaWxkQ29udGV4dCIsZ2V0OmZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5saW5rU2VydmljZSx0PXRoaXMucmVnaXN0ZXJQYWdlLG49dGhpcy51bnJlZ2lzdGVyUGFnZSxyPXRoaXMucHJvcHMsYT1yLnJlbmRlck1vZGUsbz1yLnJvdGF0ZTtyZXR1cm57bGlua1NlcnZpY2U6ZSxwZGY6dGhpcy5zdGF0ZS5wZGYscmVnaXN0ZXJQYWdlOnQscmVuZGVyTW9kZTphLHJvdGF0ZTpvLHVucmVnaXN0ZXJQYWdlOm59fX0se2tleToiZXZlbnRQcm9wcyIsZ2V0OmZ1bmN0aW9uKCl7dmFyIGU9dGhpcztyZXR1cm4oMCx3LmRlZmF1bHQpKHRoaXMucHJvcHMsKGZ1bmN0aW9uKCl7cmV0dXJuIGUuc3RhdGUucGRmfSkpfX1dKSx0fSh5LlB1cmVDb21wb25lbnQpO3QuZGVmYXVsdD1MLEwuZGVmYXVsdFByb3BzPXtlcnJvcjoiRmFpbGVkIHRvIGxvYWQgUERGIGZpbGUuIixsb2FkaW5nOiJMb2FkaW5nIFBERuKApiIsbm9EYXRhOiJObyBQREYgZmlsZSBzcGVjaWZpZWQuIixvblBhc3N3b3JkOmZ1bmN0aW9uKGUsdCl7c3dpdGNoKHQpe2Nhc2UgUy5kZWZhdWx0Lk5FRURfUEFTU1dPUkQ6ZShwcm9tcHQoIkVudGVyIHRoZSBwYXNzd29yZCB0byBvcGVuIHRoaXMgUERGIGZpbGUuIikpO2JyZWFrO2Nhc2UgUy5kZWZhdWx0LklOQ09SUkVDVF9QQVNTV09SRDplKHByb21wdCgiSW52YWxpZCBwYXNzd29yZC4gUGxlYXNlIHRyeSBhZ2Fpbi4iKSl9fX0sTC5wcm9wVHlwZXM9KDAscy5kZWZhdWx0KSh7Y2hpbGRyZW46Yi5kZWZhdWx0Lm5vZGUsY2xhc3NOYW1lOk8uaXNDbGFzc05hbWUsZXJyb3I6Yi5kZWZhdWx0Lm5vZGUsZmlsZTpSLmlzRmlsZSxpbnB1dFJlZjpiLmRlZmF1bHQuZnVuYyxsb2FkaW5nOmIuZGVmYXVsdC5ub2RlLG5vRGF0YTpiLmRlZmF1bHQubm9kZSxvbkl0ZW1DbGljazpiLmRlZmF1bHQuZnVuYyxvbkxvYWRFcnJvcjpiLmRlZmF1bHQuZnVuYyxvbkxvYWRQcm9ncmVzczpiLmRlZmF1bHQuZnVuYyxvbkxvYWRTdWNjZXNzOmIuZGVmYXVsdC5mdW5jLG9uUGFzc3dvcmQ6Yi5kZWZhdWx0LmZ1bmMsb25Tb3VyY2VFcnJvcjpiLmRlZmF1bHQuZnVuYyxvblNvdXJjZVN1Y2Nlc3M6Yi5kZWZhdWx0LmZ1bmMscm90YXRlOmIuZGVmYXVsdC5udW1iZXJ9LCgwLE8uZXZlbnRzUHJvcHMpKCkpfSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO3ZhciByPW4oOSksYT1uKDEpO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSx0LmRlZmF1bHQ9dC5QYWdlSW50ZXJuYWw9dm9pZCAwO3ZhciBvPWEobigyMykpLGk9YShuKDEwKSksdT1hKG4oMTYpKSxjPWEobigxNykpLHM9YShuKDUpKSxsPWEobigxMSkpLGY9YShuKDYpKSxkPWEobigyKSkscD1hKG4oOCkpLGg9YShuKDcpKSx2PWEobig0KSksZz1yKG4oMCkpLG09YShuKDMpKSx5PWEobigyMCkpLGI9YShuKDI0KSksdz1hKG4oMjIpKSx4PWEobigxNSkpLEU9YShuKDI1KSksXz1hKG4oNDYpKSxrPWEobig0NykpLFA9YShuKDQ4KSksUz1hKG4oNTQpKSxSPW4oMTIpLE89bigxMyksTD1mdW5jdGlvbihlKXtmdW5jdGlvbiB0KCl7dmFyIGUsbjsoMCxzLmRlZmF1bHQpKHRoaXMsdCk7Zm9yKHZhciByPWFyZ3VtZW50cy5sZW5ndGgsYT1uZXcgQXJyYXkociksbz0wO288cjtvKyspYVtvXT1hcmd1bWVudHNbb107cmV0dXJuIG49KDAsZi5kZWZhdWx0KSh0aGlzLChlPSgwLGQuZGVmYXVsdCkodCkpLmNhbGwuYXBwbHkoZSxbdGhpc10uY29uY2F0KGEpKSksKDAsdi5kZWZhdWx0KSgoMCxoLmRlZmF1bHQpKCgwLGguZGVmYXVsdCkobikpLCJzdGF0ZSIse3BhZ2U6bnVsbH0pLCgwLHYuZGVmYXVsdCkoKDAsaC5kZWZhdWx0KSgoMCxoLmRlZmF1bHQpKG4pKSwib25Mb2FkU3VjY2VzcyIsKGZ1bmN0aW9uKCl7dmFyIGU9bi5wcm9wcyx0PWUub25Mb2FkU3VjY2VzcyxyPWUucmVnaXN0ZXJQYWdlLGE9bi5zdGF0ZS5wYWdlOygwLFIuY2FsbElmRGVmaW5lZCkodCwoMCxSLm1ha2VQYWdlQ2FsbGJhY2spKGEsbi5zY2FsZSkpLCgwLFIuY2FsbElmRGVmaW5lZCkocixuLnBhZ2VJbmRleCxuLnJlZil9KSksKDAsdi5kZWZhdWx0KSgoMCxoLmRlZmF1bHQpKCgwLGguZGVmYXVsdCkobikpLCJvbkxvYWRFcnJvciIsKGZ1bmN0aW9uKGUpe2lmKCEoMCxSLmlzQ2FuY2VsRXhjZXB0aW9uKShlKSl7KDAsUi5lcnJvck9uRGV2KShlKTt2YXIgdD1uLnByb3BzLm9uTG9hZEVycm9yOygwLFIuY2FsbElmRGVmaW5lZCkodCxlKX19KSksKDAsdi5kZWZhdWx0KSgoMCxoLmRlZmF1bHQpKCgwLGguZGVmYXVsdCkobikpLCJsb2FkUGFnZSIsKDAsYy5kZWZhdWx0KSh1LmRlZmF1bHQubWFyaygoZnVuY3Rpb24gZSgpe3ZhciB0LHIsYSxvO3JldHVybiB1LmRlZmF1bHQud3JhcCgoZnVuY3Rpb24oZSl7Zm9yKDs7KXN3aXRjaChlLnByZXY9ZS5uZXh0KXtjYXNlIDA6aWYodD1uLnByb3BzLnBkZixyPW4uZ2V0UGFnZU51bWJlcigpKXtlLm5leHQ9NDticmVha31yZXR1cm4gZS5hYnJ1cHQoInJldHVybiIpO2Nhc2UgNDpyZXR1cm4gbi5zZXRTdGF0ZSgoZnVuY3Rpb24oZSl7cmV0dXJuIGUucGFnZT97cGFnZTpudWxsfTpudWxsfSkpLGUucHJldj01LGE9KDAsUi5tYWtlQ2FuY2VsbGFibGUpKHQuZ2V0UGFnZShyKSksbi5ydW5uaW5nVGFzaz1hLGUubmV4dD0xMCxhLnByb21pc2U7Y2FzZSAxMDpvPWUuc2VudCxuLnNldFN0YXRlKHtwYWdlOm99LG4ub25Mb2FkU3VjY2VzcyksZS5uZXh0PTE4O2JyZWFrO2Nhc2UgMTQ6ZS5wcmV2PTE0LGUudDA9ZS5jYXRjaCg1KSxuLnNldFN0YXRlKHtwYWdlOiExfSksbi5vbkxvYWRFcnJvcihlLnQwKTtjYXNlIDE4OmNhc2UiZW5kIjpyZXR1cm4gZS5zdG9wKCl9fSksZSx0aGlzLFtbNSwxNF1dKX0pKSkpLG59cmV0dXJuKDAscC5kZWZhdWx0KSh0LGUpLCgwLGwuZGVmYXVsdCkodCxbe2tleToiY29tcG9uZW50RGlkTW91bnQiLHZhbHVlOmZ1bmN0aW9uKCl7aWYoIXRoaXMucHJvcHMucGRmKXRocm93IG5ldyBFcnJvcigiQXR0ZW1wdGVkIHRvIGxvYWQgYSBwYWdlLCBidXQgbm8gZG9jdW1lbnQgd2FzIHNwZWNpZmllZC4iKTt0aGlzLmxvYWRQYWdlKCl9fSx7a2V5OiJjb21wb25lbnREaWRVcGRhdGUiLHZhbHVlOmZ1bmN0aW9uKGUpe3ZhciB0PXRoaXMucHJvcHMucGRmO2lmKGUucGRmJiZ0IT09ZS5wZGZ8fHRoaXMuZ2V0UGFnZU51bWJlcigpIT09dGhpcy5nZXRQYWdlTnVtYmVyKGUpKXt2YXIgbj10aGlzLnByb3BzLnVucmVnaXN0ZXJQYWdlOygwLFIuY2FsbElmRGVmaW5lZCkobix0aGlzLmdldFBhZ2VJbmRleChlKSksdGhpcy5sb2FkUGFnZSgpfX19LHtrZXk6ImNvbXBvbmVudFdpbGxVbm1vdW50Iix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMudW5yZWdpc3RlclBhZ2U7KDAsUi5jYWxsSWZEZWZpbmVkKShlLHRoaXMucGFnZUluZGV4KSwoMCxSLmNhbmNlbFJ1bm5pbmdUYXNrKSh0aGlzLnJ1bm5pbmdUYXNrKX19LHtrZXk6ImdldFBhZ2VJbmRleCIsdmFsdWU6ZnVuY3Rpb24oKXt2YXIgZT1hcmd1bWVudHMubGVuZ3RoPjAmJnZvaWQgMCE9PWFyZ3VtZW50c1swXT9hcmd1bWVudHNbMF06dGhpcy5wcm9wcztyZXR1cm4oMCxSLmlzUHJvdmlkZWQpKGUucGFnZU51bWJlcik/ZS5wYWdlTnVtYmVyLTE6KDAsUi5pc1Byb3ZpZGVkKShlLnBhZ2VJbmRleCk/ZS5wYWdlSW5kZXg6bnVsbH19LHtrZXk6ImdldFBhZ2VOdW1iZXIiLHZhbHVlOmZ1bmN0aW9uKCl7dmFyIGU9YXJndW1lbnRzLmxlbmd0aD4wJiZ2b2lkIDAhPT1hcmd1bWVudHNbMF0/YXJndW1lbnRzWzBdOnRoaXMucHJvcHM7cmV0dXJuKDAsUi5pc1Byb3ZpZGVkKShlLnBhZ2VOdW1iZXIpP2UucGFnZU51bWJlcjooMCxSLmlzUHJvdmlkZWQpKGUucGFnZUluZGV4KT9lLnBhZ2VJbmRleCsxOm51bGx9fSx7a2V5OiJyZW5kZXJNYWluTGF5ZXIiLHZhbHVlOmZ1bmN0aW9uKCl7c3dpdGNoKHRoaXMucHJvcHMucmVuZGVyTW9kZSl7Y2FzZSJub25lIjpyZXR1cm4gbnVsbDtjYXNlInN2ZyI6cmV0dXJuIGcuZGVmYXVsdC5jcmVhdGVFbGVtZW50KGsuZGVmYXVsdCx7a2V5OiIiLmNvbmNhdCh0aGlzLnBhZ2VLZXlOb1NjYWxlLCJfc3ZnIil9KTtjYXNlImNhbnZhcyI6ZGVmYXVsdDpyZXR1cm4gZy5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoXy5kZWZhdWx0LHtrZXk6IiIuY29uY2F0KHRoaXMucGFnZUtleSwiX2NhbnZhcyIpfSl9fX0se2tleToicmVuZGVyVGV4dExheWVyIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMucmVuZGVyVGV4dExheWVyO3JldHVybiBlP2cuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFAuZGVmYXVsdCx7a2V5OiIiLmNvbmNhdCh0aGlzLnBhZ2VLZXksIl90ZXh0Iil9KTpudWxsfX0se2tleToicmVuZGVyQW5ub3RhdGlvbkxheWVyIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMucmVuZGVyQW5ub3RhdGlvbkxheWVyO3JldHVybiBlP2cuZGVmYXVsdC5jcmVhdGVFbGVtZW50KFMuZGVmYXVsdCx7a2V5OiIiLmNvbmNhdCh0aGlzLnBhZ2VLZXksIl9hbm5vdGF0aW9ucyIpfSk6bnVsbH19LHtrZXk6InJlbmRlckNoaWxkcmVuIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMuY2hpbGRyZW47cmV0dXJuIGcuZGVmYXVsdC5jcmVhdGVFbGVtZW50KHguZGVmYXVsdC5Qcm92aWRlcix7dmFsdWU6dGhpcy5jaGlsZENvbnRleHR9LHRoaXMucmVuZGVyTWFpbkxheWVyKCksdGhpcy5yZW5kZXJUZXh0TGF5ZXIoKSx0aGlzLnJlbmRlckFubm90YXRpb25MYXllcigpLGUpfX0se2tleToicmVuZGVyQ29udGVudCIsdmFsdWU6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnBhZ2VOdW1iZXIsdD10aGlzLnByb3BzLnBkZixuPXRoaXMuc3RhdGUucGFnZTtpZighZSl7dmFyIHI9dGhpcy5wcm9wcy5ub0RhdGE7cmV0dXJuIGcuZGVmYXVsdC5jcmVhdGVFbGVtZW50KEUuZGVmYXVsdCx7dHlwZToibm8tZGF0YSJ9LCJmdW5jdGlvbiI9PXR5cGVvZiByP3IoKTpyKX1pZihudWxsPT09dHx8bnVsbD09PW4pe3ZhciBhPXRoaXMucHJvcHMubG9hZGluZztyZXR1cm4gZy5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoRS5kZWZhdWx0LHt0eXBlOiJsb2FkaW5nIn0sImZ1bmN0aW9uIj09dHlwZW9mIGE/YSgpOmEpfWlmKCExPT09dHx8ITE9PT1uKXt2YXIgbz10aGlzLnByb3BzLmVycm9yO3JldHVybiBnLmRlZmF1bHQuY3JlYXRlRWxlbWVudChFLmRlZmF1bHQse3R5cGU6ImVycm9yIn0sImZ1bmN0aW9uIj09dHlwZW9mIG8/bygpOm8pfXJldHVybiB0aGlzLnJlbmRlckNoaWxkcmVuKCl9fSx7a2V5OiJyZW5kZXIiLHZhbHVlOmZ1bmN0aW9uKCl7dmFyIGU9dGhpcyx0PXRoaXMucGFnZU51bWJlcixuPXRoaXMucHJvcHMuY2xhc3NOYW1lO3JldHVybiBnLmRlZmF1bHQuY3JlYXRlRWxlbWVudCgiZGl2IiwoMCxpLmRlZmF1bHQpKHtjbGFzc05hbWU6KDAsYi5kZWZhdWx0KSgicmVhY3QtcGRmX19QYWdlIixuKSxyZWY6ZnVuY3Rpb24odCl7dmFyIG49ZS5wcm9wcy5pbnB1dFJlZjtuJiZuKHQpLGUucmVmPXR9LHN0eWxlOntwb3NpdGlvbjoicmVsYXRpdmUifSwiZGF0YS1wYWdlLW51bWJlciI6dH0sdGhpcy5ldmVudFByb3BzKSx0aGlzLnJlbmRlckNvbnRlbnQoKSl9fSx7a2V5OiJjaGlsZENvbnRleHQiLGdldDpmdW5jdGlvbigpe3ZhciBlPXRoaXMuc3RhdGUucGFnZTtpZighZSlyZXR1cm57fTt2YXIgdD10aGlzLnByb3BzO3JldHVybntjdXN0b21UZXh0UmVuZGVyZXI6dC5jdXN0b21UZXh0UmVuZGVyZXIsb25HZXRBbm5vdGF0aW9uc0Vycm9yOnQub25HZXRBbm5vdGF0aW9uc0Vycm9yLG9uR2V0QW5ub3RhdGlvbnNTdWNjZXNzOnQub25HZXRBbm5vdGF0aW9uc1N1Y2Nlc3Msb25HZXRUZXh0RXJyb3I6dC5vbkdldFRleHRFcnJvcixvbkdldFRleHRTdWNjZXNzOnQub25HZXRUZXh0U3VjY2VzcyxvblJlbmRlckFubm90YXRpb25MYXllckVycm9yOnQub25SZW5kZXJBbm5vdGF0aW9uTGF5ZXJFcnJvcixvblJlbmRlckFubm90YXRpb25MYXllclN1Y2Nlc3M6dC5vblJlbmRlckFubm90YXRpb25MYXllclN1Y2Nlc3Msb25SZW5kZXJFcnJvcjp0Lm9uUmVuZGVyRXJyb3Isb25SZW5kZXJTdWNjZXNzOnQub25SZW5kZXJTdWNjZXNzLHBhZ2U6ZSxyZW5kZXJJbnRlcmFjdGl2ZUZvcm1zOnQucmVuZGVySW50ZXJhY3RpdmVGb3Jtcyxyb3RhdGU6dGhpcy5yb3RhdGUsc2NhbGU6dGhpcy5zY2FsZX19fSx7a2V5OiJwYWdlSW5kZXgiLGdldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLmdldFBhZ2VJbmRleCgpfX0se2tleToicGFnZU51bWJlciIsZ2V0OmZ1bmN0aW9uKCl7cmV0dXJuIHRoaXMuZ2V0UGFnZU51bWJlcigpfX0se2tleToicm90YXRlIixnZXQ6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnByb3BzLnJvdGF0ZTtpZigoMCxSLmlzUHJvdmlkZWQpKGUpKXJldHVybiBlO3ZhciB0PXRoaXMuc3RhdGUucGFnZTtyZXR1cm4gdD90LnJvdGF0ZTpudWxsfX0se2tleToic2NhbGUiLGdldDpmdW5jdGlvbigpe3ZhciBlPXRoaXMuc3RhdGUucGFnZTtpZighZSlyZXR1cm4gbnVsbDt2YXIgdD10aGlzLnByb3BzLG49dC5zY2FsZSxyPXQud2lkdGgsYT10LmhlaWdodCxvPXRoaXMucm90YXRlLGk9MSx1PW51bGw9PT1uPzE6bjtpZihyfHxhKXt2YXIgYz1lLmdldFZpZXdwb3J0KHtzY2FsZToxLHJvdGF0aW9uOm99KTtpPXI/ci9jLndpZHRoOmEvYy5oZWlnaHR9cmV0dXJuIHUqaX19LHtrZXk6ImV2ZW50UHJvcHMiLGdldDpmdW5jdGlvbigpe3ZhciBlPXRoaXM7cmV0dXJuKDAseS5kZWZhdWx0KSh0aGlzLnByb3BzLChmdW5jdGlvbigpe3ZhciB0PWUuc3RhdGUucGFnZTtyZXR1cm4gdD8oMCxSLm1ha2VQYWdlQ2FsbGJhY2spKHQsZS5zY2FsZSk6dH0pKX19LHtrZXk6InBhZ2VLZXkiLGdldDpmdW5jdGlvbigpe3ZhciBlPXRoaXMuc3RhdGUucGFnZTtyZXR1cm4iIi5jb25jYXQoZS5wYWdlSW5kZXgsIkAiKS5jb25jYXQodGhpcy5zY2FsZSwiLyIpLmNvbmNhdCh0aGlzLnJvdGF0ZSl9fSx7a2V5OiJwYWdlS2V5Tm9TY2FsZSIsZ2V0OmZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5zdGF0ZS5wYWdlO3JldHVybiIiLmNvbmNhdChlLnBhZ2VJbmRleCwiLyIpLmNvbmNhdCh0aGlzLnJvdGF0ZSl9fV0pLHR9KGcuUHVyZUNvbXBvbmVudCk7dC5QYWdlSW50ZXJuYWw9TCxMLmRlZmF1bHRQcm9wcz17ZXJyb3I6IkZhaWxlZCB0byBsb2FkIHRoZSBwYWdlLiIsbG9hZGluZzoiTG9hZGluZyBwYWdl4oCmIixub0RhdGE6Ik5vIHBhZ2Ugc3BlY2lmaWVkLiIscmVuZGVyQW5ub3RhdGlvbkxheWVyOiEwLHJlbmRlckludGVyYWN0aXZlRm9ybXM6ITEscmVuZGVyTW9kZToiY2FudmFzIixyZW5kZXJUZXh0TGF5ZXI6ITAsc2NhbGU6MX0sTC5wcm9wVHlwZXM9KDAsby5kZWZhdWx0KSh7Y2hpbGRyZW46bS5kZWZhdWx0Lm5vZGUsY2xhc3NOYW1lOk8uaXNDbGFzc05hbWUsY3VzdG9tVGV4dFJlbmRlcmVyOm0uZGVmYXVsdC5mdW5jLGVycm9yOm0uZGVmYXVsdC5ub2RlLGhlaWdodDptLmRlZmF1bHQubnVtYmVyLGlucHV0UmVmOm0uZGVmYXVsdC5mdW5jLGxvYWRpbmc6bS5kZWZhdWx0Lm5vZGUsbm9EYXRhOm0uZGVmYXVsdC5ub2RlLG9uR2V0VGV4dEVycm9yOm0uZGVmYXVsdC5mdW5jLG9uR2V0VGV4dFN1Y2Nlc3M6bS5kZWZhdWx0LmZ1bmMsb25Mb2FkRXJyb3I6bS5kZWZhdWx0LmZ1bmMsb25Mb2FkU3VjY2VzczptLmRlZmF1bHQuZnVuYyxvblJlbmRlckVycm9yOm0uZGVmYXVsdC5mdW5jLG9uUmVuZGVyU3VjY2VzczptLmRlZmF1bHQuZnVuYyxwYWdlSW5kZXg6Ty5pc1BhZ2VJbmRleCxwYWdlTnVtYmVyOk8uaXNQYWdlTnVtYmVyLHBkZjpPLmlzUGRmLHJlZ2lzdGVyUGFnZTptLmRlZmF1bHQuZnVuYyxyZW5kZXJBbm5vdGF0aW9uTGF5ZXI6bS5kZWZhdWx0LmJvb2wscmVuZGVySW50ZXJhY3RpdmVGb3JtczptLmRlZmF1bHQuYm9vbCxyZW5kZXJNb2RlOk8uaXNSZW5kZXJNb2RlLHJlbmRlclRleHRMYXllcjptLmRlZmF1bHQuYm9vbCxyb3RhdGU6Ty5pc1JvdGF0ZSxzY2FsZTptLmRlZmF1bHQubnVtYmVyLHVucmVnaXN0ZXJQYWdlOm0uZGVmYXVsdC5mdW5jLHdpZHRoOm0uZGVmYXVsdC5udW1iZXJ9LCgwLE8uZXZlbnRzUHJvcHMpKCkpO3ZhciBUPWcuZGVmYXVsdC5mb3J3YXJkUmVmKChmdW5jdGlvbihlLHQpe3JldHVybiBnLmRlZmF1bHQuY3JlYXRlRWxlbWVudCh3LmRlZmF1bHQuQ29uc3VtZXIsbnVsbCwoZnVuY3Rpb24obil7cmV0dXJuIGcuZGVmYXVsdC5jcmVhdGVFbGVtZW50KEwsKDAsaS5kZWZhdWx0KSh7cmVmOnR9LG4sZSx7cmVuZGVyQW5ub3RhdGlvbkxheWVyOnZvaWQgMCE9PWUucmVuZGVyQW5ub3RhdGlvbkxheWVyP2UucmVuZGVyQW5ub3RhdGlvbkxheWVyOmUucmVuZGVyQW5ub3RhdGlvbnN9KSl9KSl9KSk7dC5kZWZhdWx0PVR9LGZ1bmN0aW9uKGUsdCxuKXtlLmV4cG9ydHM9big2Mil9LGZ1bmN0aW9uKGUsdCxuKXt2YXIgcj1uKDMyKTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSx0KXtpZihudWxsPT1lKXJldHVybnt9O3ZhciBuLGEsbz1yKGUsdCk7aWYoT2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyl7dmFyIGk9T2JqZWN0LmdldE93blByb3BlcnR5U3ltYm9scyhlKTtmb3IoYT0wO2E8aS5sZW5ndGg7YSsrKW49aVthXSx0LmluZGV4T2Yobik+PTB8fE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChlLG4pJiYob1tuXT1lW25dKX1yZXR1cm4gb319LGZ1bmN0aW9uKGUsdCl7ZS5leHBvcnRzPWZ1bmN0aW9uKGUsdCl7aWYobnVsbD09ZSlyZXR1cm57fTt2YXIgbixyLGE9e30sbz1PYmplY3Qua2V5cyhlKTtmb3Iocj0wO3I8by5sZW5ndGg7cisrKW49b1tyXSx0LmluZGV4T2Yobik+PTB8fChhW25dPWVbbl0pO3JldHVybiBhfX0sZnVuY3Rpb24oZSx0LG4pe3ZhciByPWZ1bmN0aW9uKGUpeyJ1c2Ugc3RyaWN0Ijt2YXIgdD1PYmplY3QucHJvdG90eXBlLG49dC5oYXNPd25Qcm9wZXJ0eSxyPSJmdW5jdGlvbiI9PXR5cGVvZiBTeW1ib2w/U3ltYm9sOnt9LGE9ci5pdGVyYXRvcnx8IkBAaXRlcmF0b3IiLG89ci5hc3luY0l0ZXJhdG9yfHwiQEBhc3luY0l0ZXJhdG9yIixpPXIudG9TdHJpbmdUYWd8fCJAQHRvU3RyaW5nVGFnIjtmdW5jdGlvbiB1KGUsdCxuLHIpe3ZhciBhPXQmJnQucHJvdG90eXBlIGluc3RhbmNlb2YgbD90Omwsbz1PYmplY3QuY3JlYXRlKGEucHJvdG90eXBlKSxpPW5ldyBFKHJ8fFtdKTtyZXR1cm4gby5faW52b2tlPWZ1bmN0aW9uKGUsdCxuKXt2YXIgcj0ic3VzcGVuZGVkU3RhcnQiO3JldHVybiBmdW5jdGlvbihhLG8pe2lmKCJleGVjdXRpbmciPT09cil0aHJvdyBuZXcgRXJyb3IoIkdlbmVyYXRvciBpcyBhbHJlYWR5IHJ1bm5pbmciKTtpZigiY29tcGxldGVkIj09PXIpe2lmKCJ0aHJvdyI9PT1hKXRocm93IG87cmV0dXJuIGsoKX1mb3Iobi5tZXRob2Q9YSxuLmFyZz1vOzspe3ZhciBpPW4uZGVsZWdhdGU7aWYoaSl7dmFyIHU9YihpLG4pO2lmKHUpe2lmKHU9PT1zKWNvbnRpbnVlO3JldHVybiB1fX1pZigibmV4dCI9PT1uLm1ldGhvZCluLnNlbnQ9bi5fc2VudD1uLmFyZztlbHNlIGlmKCJ0aHJvdyI9PT1uLm1ldGhvZCl7aWYoInN1c3BlbmRlZFN0YXJ0Ij09PXIpdGhyb3cgcj0iY29tcGxldGVkIixuLmFyZztuLmRpc3BhdGNoRXhjZXB0aW9uKG4uYXJnKX1lbHNlInJldHVybiI9PT1uLm1ldGhvZCYmbi5hYnJ1cHQoInJldHVybiIsbi5hcmcpO3I9ImV4ZWN1dGluZyI7dmFyIGw9YyhlLHQsbik7aWYoIm5vcm1hbCI9PT1sLnR5cGUpe2lmKHI9bi5kb25lPyJjb21wbGV0ZWQiOiJzdXNwZW5kZWRZaWVsZCIsbC5hcmc9PT1zKWNvbnRpbnVlO3JldHVybnt2YWx1ZTpsLmFyZyxkb25lOm4uZG9uZX19InRocm93Ij09PWwudHlwZSYmKHI9ImNvbXBsZXRlZCIsbi5tZXRob2Q9InRocm93IixuLmFyZz1sLmFyZyl9fX0oZSxuLGkpLG99ZnVuY3Rpb24gYyhlLHQsbil7dHJ5e3JldHVybnt0eXBlOiJub3JtYWwiLGFyZzplLmNhbGwodCxuKX19Y2F0Y2goZSl7cmV0dXJue3R5cGU6InRocm93Iixhcmc6ZX19fWUud3JhcD11O3ZhciBzPXt9O2Z1bmN0aW9uIGwoKXt9ZnVuY3Rpb24gZigpe31mdW5jdGlvbiBkKCl7fXZhciBwPXt9O3BbYV09ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc307dmFyIGg9T2JqZWN0LmdldFByb3RvdHlwZU9mLHY9aCYmaChoKF8oW10pKSk7diYmdiE9PXQmJm4uY2FsbCh2LGEpJiYocD12KTt2YXIgZz1kLnByb3RvdHlwZT1sLnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKHApO2Z1bmN0aW9uIG0oZSl7WyJuZXh0IiwidGhyb3ciLCJyZXR1cm4iXS5mb3JFYWNoKChmdW5jdGlvbih0KXtlW3RdPWZ1bmN0aW9uKGUpe3JldHVybiB0aGlzLl9pbnZva2UodCxlKX19KSl9ZnVuY3Rpb24geShlKXt2YXIgdDt0aGlzLl9pbnZva2U9ZnVuY3Rpb24ocixhKXtmdW5jdGlvbiBvKCl7cmV0dXJuIG5ldyBQcm9taXNlKChmdW5jdGlvbih0LG8peyFmdW5jdGlvbiB0KHIsYSxvLGkpe3ZhciB1PWMoZVtyXSxlLGEpO2lmKCJ0aHJvdyIhPT11LnR5cGUpe3ZhciBzPXUuYXJnLGw9cy52YWx1ZTtyZXR1cm4gbCYmIm9iamVjdCI9PXR5cGVvZiBsJiZuLmNhbGwobCwiX19hd2FpdCIpP1Byb21pc2UucmVzb2x2ZShsLl9fYXdhaXQpLnRoZW4oKGZ1bmN0aW9uKGUpe3QoIm5leHQiLGUsbyxpKX0pLChmdW5jdGlvbihlKXt0KCJ0aHJvdyIsZSxvLGkpfSkpOlByb21pc2UucmVzb2x2ZShsKS50aGVuKChmdW5jdGlvbihlKXtzLnZhbHVlPWUsbyhzKX0pLChmdW5jdGlvbihlKXtyZXR1cm4gdCgidGhyb3ciLGUsbyxpKX0pKX1pKHUuYXJnKX0ocixhLHQsbyl9KSl9cmV0dXJuIHQ9dD90LnRoZW4obyxvKTpvKCl9fWZ1bmN0aW9uIGIoZSx0KXt2YXIgbj1lLml0ZXJhdG9yW3QubWV0aG9kXTtpZih2b2lkIDA9PT1uKXtpZih0LmRlbGVnYXRlPW51bGwsInRocm93Ij09PXQubWV0aG9kKXtpZihlLml0ZXJhdG9yLnJldHVybiYmKHQubWV0aG9kPSJyZXR1cm4iLHQuYXJnPXZvaWQgMCxiKGUsdCksInRocm93Ij09PXQubWV0aG9kKSlyZXR1cm4gczt0Lm1ldGhvZD0idGhyb3ciLHQuYXJnPW5ldyBUeXBlRXJyb3IoIlRoZSBpdGVyYXRvciBkb2VzIG5vdCBwcm92aWRlIGEgJ3Rocm93JyBtZXRob2QiKX1yZXR1cm4gc312YXIgcj1jKG4sZS5pdGVyYXRvcix0LmFyZyk7aWYoInRocm93Ij09PXIudHlwZSlyZXR1cm4gdC5tZXRob2Q9InRocm93Iix0LmFyZz1yLmFyZyx0LmRlbGVnYXRlPW51bGwsczt2YXIgYT1yLmFyZztyZXR1cm4gYT9hLmRvbmU/KHRbZS5yZXN1bHROYW1lXT1hLnZhbHVlLHQubmV4dD1lLm5leHRMb2MsInJldHVybiIhPT10Lm1ldGhvZCYmKHQubWV0aG9kPSJuZXh0Iix0LmFyZz12b2lkIDApLHQuZGVsZWdhdGU9bnVsbCxzKTphOih0Lm1ldGhvZD0idGhyb3ciLHQuYXJnPW5ldyBUeXBlRXJyb3IoIml0ZXJhdG9yIHJlc3VsdCBpcyBub3QgYW4gb2JqZWN0IiksdC5kZWxlZ2F0ZT1udWxsLHMpfWZ1bmN0aW9uIHcoZSl7dmFyIHQ9e3RyeUxvYzplWzBdfTsxIGluIGUmJih0LmNhdGNoTG9jPWVbMV0pLDIgaW4gZSYmKHQuZmluYWxseUxvYz1lWzJdLHQuYWZ0ZXJMb2M9ZVszXSksdGhpcy50cnlFbnRyaWVzLnB1c2godCl9ZnVuY3Rpb24geChlKXt2YXIgdD1lLmNvbXBsZXRpb258fHt9O3QudHlwZT0ibm9ybWFsIixkZWxldGUgdC5hcmcsZS5jb21wbGV0aW9uPXR9ZnVuY3Rpb24gRShlKXt0aGlzLnRyeUVudHJpZXM9W3t0cnlMb2M6InJvb3QifV0sZS5mb3JFYWNoKHcsdGhpcyksdGhpcy5yZXNldCghMCl9ZnVuY3Rpb24gXyhlKXtpZihlKXt2YXIgdD1lW2FdO2lmKHQpcmV0dXJuIHQuY2FsbChlKTtpZigiZnVuY3Rpb24iPT10eXBlb2YgZS5uZXh0KXJldHVybiBlO2lmKCFpc05hTihlLmxlbmd0aCkpe3ZhciByPS0xLG89ZnVuY3Rpb24gdCgpe2Zvcig7KytyPGUubGVuZ3RoOylpZihuLmNhbGwoZSxyKSlyZXR1cm4gdC52YWx1ZT1lW3JdLHQuZG9uZT0hMSx0O3JldHVybiB0LnZhbHVlPXZvaWQgMCx0LmRvbmU9ITAsdH07cmV0dXJuIG8ubmV4dD1vfX1yZXR1cm57bmV4dDprfX1mdW5jdGlvbiBrKCl7cmV0dXJue3ZhbHVlOnZvaWQgMCxkb25lOiEwfX1yZXR1cm4gZi5wcm90b3R5cGU9Zy5jb25zdHJ1Y3Rvcj1kLGQuY29uc3RydWN0b3I9ZixkW2ldPWYuZGlzcGxheU5hbWU9IkdlbmVyYXRvckZ1bmN0aW9uIixlLmlzR2VuZXJhdG9yRnVuY3Rpb249ZnVuY3Rpb24oZSl7dmFyIHQ9ImZ1bmN0aW9uIj09dHlwZW9mIGUmJmUuY29uc3RydWN0b3I7cmV0dXJuISF0JiYodD09PWZ8fCJHZW5lcmF0b3JGdW5jdGlvbiI9PT0odC5kaXNwbGF5TmFtZXx8dC5uYW1lKSl9LGUubWFyaz1mdW5jdGlvbihlKXtyZXR1cm4gT2JqZWN0LnNldFByb3RvdHlwZU9mP09iamVjdC5zZXRQcm90b3R5cGVPZihlLGQpOihlLl9fcHJvdG9fXz1kLGkgaW4gZXx8KGVbaV09IkdlbmVyYXRvckZ1bmN0aW9uIikpLGUucHJvdG90eXBlPU9iamVjdC5jcmVhdGUoZyksZX0sZS5hd3JhcD1mdW5jdGlvbihlKXtyZXR1cm57X19hd2FpdDplfX0sbSh5LnByb3RvdHlwZSkseS5wcm90b3R5cGVbb109ZnVuY3Rpb24oKXtyZXR1cm4gdGhpc30sZS5Bc3luY0l0ZXJhdG9yPXksZS5hc3luYz1mdW5jdGlvbih0LG4scixhKXt2YXIgbz1uZXcgeSh1KHQsbixyLGEpKTtyZXR1cm4gZS5pc0dlbmVyYXRvckZ1bmN0aW9uKG4pP286by5uZXh0KCkudGhlbigoZnVuY3Rpb24oZSl7cmV0dXJuIGUuZG9uZT9lLnZhbHVlOm8ubmV4dCgpfSkpfSxtKGcpLGdbaV09IkdlbmVyYXRvciIsZ1thXT1mdW5jdGlvbigpe3JldHVybiB0aGlzfSxnLnRvU3RyaW5nPWZ1bmN0aW9uKCl7cmV0dXJuIltvYmplY3QgR2VuZXJhdG9yXSJ9LGUua2V5cz1mdW5jdGlvbihlKXt2YXIgdD1bXTtmb3IodmFyIG4gaW4gZSl0LnB1c2gobik7cmV0dXJuIHQucmV2ZXJzZSgpLGZ1bmN0aW9uIG4oKXtmb3IoO3QubGVuZ3RoOyl7dmFyIHI9dC5wb3AoKTtpZihyIGluIGUpcmV0dXJuIG4udmFsdWU9cixuLmRvbmU9ITEsbn1yZXR1cm4gbi5kb25lPSEwLG59fSxlLnZhbHVlcz1fLEUucHJvdG90eXBlPXtjb25zdHJ1Y3RvcjpFLHJlc2V0OmZ1bmN0aW9uKGUpe2lmKHRoaXMucHJldj0wLHRoaXMubmV4dD0wLHRoaXMuc2VudD10aGlzLl9zZW50PXZvaWQgMCx0aGlzLmRvbmU9ITEsdGhpcy5kZWxlZ2F0ZT1udWxsLHRoaXMubWV0aG9kPSJuZXh0Iix0aGlzLmFyZz12b2lkIDAsdGhpcy50cnlFbnRyaWVzLmZvckVhY2goeCksIWUpZm9yKHZhciB0IGluIHRoaXMpInQiPT09dC5jaGFyQXQoMCkmJm4uY2FsbCh0aGlzLHQpJiYhaXNOYU4oK3Quc2xpY2UoMSkpJiYodGhpc1t0XT12b2lkIDApfSxzdG9wOmZ1bmN0aW9uKCl7dGhpcy5kb25lPSEwO3ZhciBlPXRoaXMudHJ5RW50cmllc1swXS5jb21wbGV0aW9uO2lmKCJ0aHJvdyI9PT1lLnR5cGUpdGhyb3cgZS5hcmc7cmV0dXJuIHRoaXMucnZhbH0sZGlzcGF0Y2hFeGNlcHRpb246ZnVuY3Rpb24oZSl7aWYodGhpcy5kb25lKXRocm93IGU7dmFyIHQ9dGhpcztmdW5jdGlvbiByKG4scil7cmV0dXJuIGkudHlwZT0idGhyb3ciLGkuYXJnPWUsdC5uZXh0PW4sciYmKHQubWV0aG9kPSJuZXh0Iix0LmFyZz12b2lkIDApLCEhcn1mb3IodmFyIGE9dGhpcy50cnlFbnRyaWVzLmxlbmd0aC0xO2E+PTA7LS1hKXt2YXIgbz10aGlzLnRyeUVudHJpZXNbYV0saT1vLmNvbXBsZXRpb247aWYoInJvb3QiPT09by50cnlMb2MpcmV0dXJuIHIoImVuZCIpO2lmKG8udHJ5TG9jPD10aGlzLnByZXYpe3ZhciB1PW4uY2FsbChvLCJjYXRjaExvYyIpLGM9bi5jYWxsKG8sImZpbmFsbHlMb2MiKTtpZih1JiZjKXtpZih0aGlzLnByZXY8by5jYXRjaExvYylyZXR1cm4gcihvLmNhdGNoTG9jLCEwKTtpZih0aGlzLnByZXY8by5maW5hbGx5TG9jKXJldHVybiByKG8uZmluYWxseUxvYyl9ZWxzZSBpZih1KXtpZih0aGlzLnByZXY8by5jYXRjaExvYylyZXR1cm4gcihvLmNhdGNoTG9jLCEwKX1lbHNle2lmKCFjKXRocm93IG5ldyBFcnJvcigidHJ5IHN0YXRlbWVudCB3aXRob3V0IGNhdGNoIG9yIGZpbmFsbHkiKTtpZih0aGlzLnByZXY8by5maW5hbGx5TG9jKXJldHVybiByKG8uZmluYWxseUxvYyl9fX19LGFicnVwdDpmdW5jdGlvbihlLHQpe2Zvcih2YXIgcj10aGlzLnRyeUVudHJpZXMubGVuZ3RoLTE7cj49MDstLXIpe3ZhciBhPXRoaXMudHJ5RW50cmllc1tyXTtpZihhLnRyeUxvYzw9dGhpcy5wcmV2JiZuLmNhbGwoYSwiZmluYWxseUxvYyIpJiZ0aGlzLnByZXY8YS5maW5hbGx5TG9jKXt2YXIgbz1hO2JyZWFrfX1vJiYoImJyZWFrIj09PWV8fCJjb250aW51ZSI9PT1lKSYmby50cnlMb2M8PXQmJnQ8PW8uZmluYWxseUxvYyYmKG89bnVsbCk7dmFyIGk9bz9vLmNvbXBsZXRpb246e307cmV0dXJuIGkudHlwZT1lLGkuYXJnPXQsbz8odGhpcy5tZXRob2Q9Im5leHQiLHRoaXMubmV4dD1vLmZpbmFsbHlMb2Mscyk6dGhpcy5jb21wbGV0ZShpKX0sY29tcGxldGU6ZnVuY3Rpb24oZSx0KXtpZigidGhyb3ciPT09ZS50eXBlKXRocm93IGUuYXJnO3JldHVybiJicmVhayI9PT1lLnR5cGV8fCJjb250aW51ZSI9PT1lLnR5cGU/dGhpcy5uZXh0PWUuYXJnOiJyZXR1cm4iPT09ZS50eXBlPyh0aGlzLnJ2YWw9dGhpcy5hcmc9ZS5hcmcsdGhpcy5tZXRob2Q9InJldHVybiIsdGhpcy5uZXh0PSJlbmQiKToibm9ybWFsIj09PWUudHlwZSYmdCYmKHRoaXMubmV4dD10KSxzfSxmaW5pc2g6ZnVuY3Rpb24oZSl7Zm9yKHZhciB0PXRoaXMudHJ5RW50cmllcy5sZW5ndGgtMTt0Pj0wOy0tdCl7dmFyIG49dGhpcy50cnlFbnRyaWVzW3RdO2lmKG4uZmluYWxseUxvYz09PWUpcmV0dXJuIHRoaXMuY29tcGxldGUobi5jb21wbGV0aW9uLG4uYWZ0ZXJMb2MpLHgobiksc319LGNhdGNoOmZ1bmN0aW9uKGUpe2Zvcih2YXIgdD10aGlzLnRyeUVudHJpZXMubGVuZ3RoLTE7dD49MDstLXQpe3ZhciBuPXRoaXMudHJ5RW50cmllc1t0XTtpZihuLnRyeUxvYz09PWUpe3ZhciByPW4uY29tcGxldGlvbjtpZigidGhyb3ciPT09ci50eXBlKXt2YXIgYT1yLmFyZzt4KG4pfXJldHVybiBhfX10aHJvdyBuZXcgRXJyb3IoImlsbGVnYWwgY2F0Y2ggYXR0ZW1wdCIpfSxkZWxlZ2F0ZVlpZWxkOmZ1bmN0aW9uKGUsdCxuKXtyZXR1cm4gdGhpcy5kZWxlZ2F0ZT17aXRlcmF0b3I6XyhlKSxyZXN1bHROYW1lOnQsbmV4dExvYzpufSwibmV4dCI9PT10aGlzLm1ldGhvZCYmKHRoaXMuYXJnPXZvaWQgMCksc319LGV9KGUuZXhwb3J0cyk7dHJ5e3JlZ2VuZXJhdG9yUnVudGltZT1yfWNhdGNoKGUpe0Z1bmN0aW9uKCJyIiwicmVnZW5lcmF0b3JSdW50aW1lID0gciIpKHIpfX0sZnVuY3Rpb24oZSx0LG4peyJ1c2Ugc3RyaWN0Ijt2YXIgcj1uKDM1KTtmdW5jdGlvbiBhKCl7fWZ1bmN0aW9uIG8oKXt9by5yZXNldFdhcm5pbmdDYWNoZT1hLGUuZXhwb3J0cz1mdW5jdGlvbigpe2Z1bmN0aW9uIGUoZSx0LG4sYSxvLGkpe2lmKGkhPT1yKXt2YXIgdT1uZXcgRXJyb3IoIkNhbGxpbmcgUHJvcFR5cGVzIHZhbGlkYXRvcnMgZGlyZWN0bHkgaXMgbm90IHN1cHBvcnRlZCBieSB0aGUgYHByb3AtdHlwZXNgIHBhY2thZ2UuIFVzZSBQcm9wVHlwZXMuY2hlY2tQcm9wVHlwZXMoKSB0byBjYWxsIHRoZW0uIFJlYWQgbW9yZSBhdCBodHRwOi8vZmIubWUvdXNlLWNoZWNrLXByb3AtdHlwZXMiKTt0aHJvdyB1Lm5hbWU9IkludmFyaWFudCBWaW9sYXRpb24iLHV9fWZ1bmN0aW9uIHQoKXtyZXR1cm4gZX1lLmlzUmVxdWlyZWQ9ZTt2YXIgbj17YXJyYXk6ZSxib29sOmUsZnVuYzplLG51bWJlcjplLG9iamVjdDplLHN0cmluZzplLHN5bWJvbDplLGFueTplLGFycmF5T2Y6dCxlbGVtZW50OmUsZWxlbWVudFR5cGU6ZSxpbnN0YW5jZU9mOnQsbm9kZTplLG9iamVjdE9mOnQsb25lT2Y6dCxvbmVPZlR5cGU6dCxzaGFwZTp0LGV4YWN0OnQsY2hlY2tQcm9wVHlwZXM6byxyZXNldFdhcm5pbmdDYWNoZTphfTtyZXR1cm4gbi5Qcm9wVHlwZXM9bixufX0sZnVuY3Rpb24oZSx0LG4peyJ1c2Ugc3RyaWN0IjtlLmV4cG9ydHM9IlNFQ1JFVF9ET19OT1RfUEFTU19USElTX09SX1lPVV9XSUxMX0JFX0ZJUkVEIn0sZnVuY3Rpb24oZSx0KXtlLmV4cG9ydHM9cGRmanNWaWV3ZXJ9LGZ1bmN0aW9uKGUsdCxuKXsidXNlIHN0cmljdCI7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsIl9fZXNNb2R1bGUiLHt2YWx1ZTohMH0pLHQuZGVmYXVsdD12b2lkIDA7dmFyIHI9e05FRURfUEFTU1dPUkQ6MSxJTkNPUlJFQ1RfUEFTU1dPUkQ6Mn07dC5kZWZhdWx0PXJ9LGZ1bmN0aW9uKGUsdCxuKXt2YXIgcj1uKDIpLGE9bigxOSksbz1uKDM5KSxpPW4oNDApO2Z1bmN0aW9uIHUodCl7dmFyIG49ImZ1bmN0aW9uIj09dHlwZW9mIE1hcD9uZXcgTWFwOnZvaWQgMDtyZXR1cm4gZS5leHBvcnRzPXU9ZnVuY3Rpb24oZSl7aWYobnVsbD09PWV8fCFvKGUpKXJldHVybiBlO2lmKCJmdW5jdGlvbiIhPXR5cGVvZiBlKXRocm93IG5ldyBUeXBlRXJyb3IoIlN1cGVyIGV4cHJlc3Npb24gbXVzdCBlaXRoZXIgYmUgbnVsbCBvciBhIGZ1bmN0aW9uIik7aWYodm9pZCAwIT09bil7aWYobi5oYXMoZSkpcmV0dXJuIG4uZ2V0KGUpO24uc2V0KGUsdCl9ZnVuY3Rpb24gdCgpe3JldHVybiBpKGUsYXJndW1lbnRzLHIodGhpcykuY29uc3RydWN0b3IpfXJldHVybiB0LnByb3RvdHlwZT1PYmplY3QuY3JlYXRlKGUucHJvdG90eXBlLHtjb25zdHJ1Y3Rvcjp7dmFsdWU6dCxlbnVtZXJhYmxlOiExLHdyaXRhYmxlOiEwLGNvbmZpZ3VyYWJsZTohMH19KSxhKHQsZSl9LHUodCl9ZS5leHBvcnRzPXV9LGZ1bmN0aW9uKGUsdCl7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybi0xIT09RnVuY3Rpb24udG9TdHJpbmcuY2FsbChlKS5pbmRleE9mKCJbbmF0aXZlIGNvZGVdIil9fSxmdW5jdGlvbihlLHQsbil7dmFyIHI9bigxOSk7ZnVuY3Rpb24gYSgpe2lmKCJ1bmRlZmluZWQiPT10eXBlb2YgUmVmbGVjdHx8IVJlZmxlY3QuY29uc3RydWN0KXJldHVybiExO2lmKFJlZmxlY3QuY29uc3RydWN0LnNoYW0pcmV0dXJuITE7aWYoImZ1bmN0aW9uIj09dHlwZW9mIFByb3h5KXJldHVybiEwO3RyeXtyZXR1cm4gRGF0ZS5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChSZWZsZWN0LmNvbnN0cnVjdChEYXRlLFtdLChmdW5jdGlvbigpe30pKSksITB9Y2F0Y2goZSl7cmV0dXJuITF9fWZ1bmN0aW9uIG8odCxuLGkpe3JldHVybiBhKCk/ZS5leHBvcnRzPW89UmVmbGVjdC5jb25zdHJ1Y3Q6ZS5leHBvcnRzPW89ZnVuY3Rpb24oZSx0LG4pe3ZhciBhPVtudWxsXTthLnB1c2guYXBwbHkoYSx0KTt2YXIgbz1uZXcoRnVuY3Rpb24uYmluZC5hcHBseShlLGEpKTtyZXR1cm4gbiYmcihvLG4ucHJvdG90eXBlKSxvfSxvLmFwcGx5KG51bGwsYXJndW1lbnRzKX1lLmV4cG9ydHM9b30sZnVuY3Rpb24oZSx0LG4pe3ZhciByPW4oNDIpLGE9big0Myksbz1uKDQ0KTtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7cmV0dXJuIHIoZSl8fGEoZSl8fG8oKX19LGZ1bmN0aW9uKGUsdCl7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKEFycmF5LmlzQXJyYXkoZSkpe2Zvcih2YXIgdD0wLG49bmV3IEFycmF5KGUubGVuZ3RoKTt0PGUubGVuZ3RoO3QrKyluW3RdPWVbdF07cmV0dXJuIG59fX0sZnVuY3Rpb24oZSx0KXtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7aWYoU3ltYm9sLml0ZXJhdG9yIGluIE9iamVjdChlKXx8IltvYmplY3QgQXJndW1lbnRzXSI9PT1PYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZSkpcmV0dXJuIEFycmF5LmZyb20oZSl9fSxmdW5jdGlvbihlLHQpe2UuZXhwb3J0cz1mdW5jdGlvbigpe3Rocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgYXR0ZW1wdCB0byBzcHJlYWQgbm9uLWl0ZXJhYmxlIGluc3RhbmNlIil9fSxmdW5jdGlvbihlLHQpe3ZhciBuPS9eXHMrfFxzKyQvZyxyPS9eWy0rXTB4WzAtOWEtZl0rJC9pLGE9L14wYlswMV0rJC9pLG89L14wb1swLTddKyQvaSxpPXBhcnNlSW50LHU9T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZztmdW5jdGlvbiBjKGUsdCl7dmFyIGM7aWYoImZ1bmN0aW9uIiE9dHlwZW9mIHQpdGhyb3cgbmV3IFR5cGVFcnJvcigiRXhwZWN0ZWQgYSBmdW5jdGlvbiIpO3JldHVybiBlPWZ1bmN0aW9uKGUpe3ZhciB0PWZ1bmN0aW9uKGUpe2lmKCFlKXJldHVybiAwPT09ZT9lOjA7aWYoKGU9ZnVuY3Rpb24oZSl7aWYoIm51bWJlciI9PXR5cGVvZiBlKXJldHVybiBlO2lmKGZ1bmN0aW9uKGUpe3JldHVybiJzeW1ib2wiPT10eXBlb2YgZXx8ZnVuY3Rpb24oZSl7cmV0dXJuISFlJiYib2JqZWN0Ij09dHlwZW9mIGV9KGUpJiYiW29iamVjdCBTeW1ib2xdIj09dS5jYWxsKGUpfShlKSlyZXR1cm4gTmFOO2lmKHMoZSkpe3ZhciB0PSJmdW5jdGlvbiI9PXR5cGVvZiBlLnZhbHVlT2Y/ZS52YWx1ZU9mKCk6ZTtlPXModCk/dCsiIjp0fWlmKCJzdHJpbmciIT10eXBlb2YgZSlyZXR1cm4gMD09PWU/ZTorZTtlPWUucmVwbGFjZShuLCIiKTt2YXIgYz1hLnRlc3QoZSk7cmV0dXJuIGN8fG8udGVzdChlKT9pKGUuc2xpY2UoMiksYz8yOjgpOnIudGVzdChlKT9OYU46K2V9KGUpKT09PTEvMHx8ZT09PS0xLzApe3JldHVybiAxNzk3NjkzMTM0ODYyMzE1N2UyOTIqKGU8MD8tMToxKX1yZXR1cm4gZT09ZT9lOjB9KGUpLGM9dCUxO3JldHVybiB0PT10P2M/dC1jOnQ6MH0oZSksZnVuY3Rpb24oKXtyZXR1cm4tLWU+MCYmKGM9dC5hcHBseSh0aGlzLGFyZ3VtZW50cykpLGU8PTEmJih0PXZvaWQgMCksY319ZnVuY3Rpb24gcyhlKXt2YXIgdD10eXBlb2YgZTtyZXR1cm4hIWUmJigib2JqZWN0Ij09dHx8ImZ1bmN0aW9uIj09dCl9ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe3JldHVybiBjKDIsZSl9fSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO3ZhciByPW4oOSksYT1uKDEpO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSx0LmRlZmF1bHQ9ZnVuY3Rpb24oZSl7cmV0dXJuIHAuZGVmYXVsdC5jcmVhdGVFbGVtZW50KHYuZGVmYXVsdC5Db25zdW1lcixudWxsLChmdW5jdGlvbih0KXtyZXR1cm4gcC5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoeSwoMCxvLmRlZmF1bHQpKHt9LHQsZSkpfSkpfSx0LlBhZ2VDYW52YXNJbnRlcm5hbD12b2lkIDA7dmFyIG89YShuKDEwKSksaT1hKG4oNSkpLHU9YShuKDExKSksYz1hKG4oNikpLHM9YShuKDIpKSxsPWEobig4KSksZj1hKG4oNykpLGQ9YShuKDQpKSxwPXIobigwKSksaD1hKG4oMykpLHY9YShuKDE1KSksZz1uKDEyKSxtPW4oMTMpLHk9ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gdCgpe3ZhciBlLG47KDAsaS5kZWZhdWx0KSh0aGlzLHQpO2Zvcih2YXIgcj1hcmd1bWVudHMubGVuZ3RoLGE9bmV3IEFycmF5KHIpLG89MDtvPHI7bysrKWFbb109YXJndW1lbnRzW29dO3JldHVybiBuPSgwLGMuZGVmYXVsdCkodGhpcywoZT0oMCxzLmRlZmF1bHQpKHQpKS5jYWxsLmFwcGx5KGUsW3RoaXNdLmNvbmNhdChhKSkpLCgwLGQuZGVmYXVsdCkoKDAsZi5kZWZhdWx0KSgoMCxmLmRlZmF1bHQpKG4pKSwib25SZW5kZXJTdWNjZXNzIiwoZnVuY3Rpb24oKXtuLnJlbmRlcmVyPW51bGw7dmFyIGU9bi5wcm9wcyx0PWUub25SZW5kZXJTdWNjZXNzLHI9ZS5wYWdlLGE9ZS5zY2FsZTsoMCxnLmNhbGxJZkRlZmluZWQpKHQsKDAsZy5tYWtlUGFnZUNhbGxiYWNrKShyLGEpKX0pKSwoMCxkLmRlZmF1bHQpKCgwLGYuZGVmYXVsdCkoKDAsZi5kZWZhdWx0KShuKSksIm9uUmVuZGVyRXJyb3IiLChmdW5jdGlvbihlKXtpZighKDAsZy5pc0NhbmNlbEV4Y2VwdGlvbikoZSkpeygwLGcuZXJyb3JPbkRldikoZSk7dmFyIHQ9bi5wcm9wcy5vblJlbmRlckVycm9yOygwLGcuY2FsbElmRGVmaW5lZCkodCxlKX19KSksKDAsZC5kZWZhdWx0KSgoMCxmLmRlZmF1bHQpKCgwLGYuZGVmYXVsdCkobikpLCJkcmF3UGFnZU9uQ2FudmFzIiwoZnVuY3Rpb24oKXt2YXIgZT0oMCxmLmRlZmF1bHQpKCgwLGYuZGVmYXVsdCkobikpLmNhbnZhc0xheWVyO2lmKCFlKXJldHVybiBudWxsO3ZhciB0PSgwLGYuZGVmYXVsdCkoKDAsZi5kZWZhdWx0KShuKSkscj10LnJlbmRlclZpZXdwb3J0LGE9dC52aWV3cG9ydCxvPW4ucHJvcHMsaT1vLnBhZ2UsdT1vLnJlbmRlckludGVyYWN0aXZlRm9ybXM7ZS53aWR0aD1yLndpZHRoLGUuaGVpZ2h0PXIuaGVpZ2h0LGUuc3R5bGUud2lkdGg9IiIuY29uY2F0KE1hdGguZmxvb3IoYS53aWR0aCksInB4IiksZS5zdHlsZS5oZWlnaHQ9IiIuY29uY2F0KE1hdGguZmxvb3IoYS5oZWlnaHQpLCJweCIpO3ZhciBjPXtnZXQgY2FudmFzQ29udGV4dCgpe3JldHVybiBlLmdldENvbnRleHQoIjJkIil9LHZpZXdwb3J0OnIscmVuZGVySW50ZXJhY3RpdmVGb3Jtczp1fTtyZXR1cm4gbi5jYW5jZWxSZW5kZXJpbmdUYXNrKCksbi5yZW5kZXJlcj1pLnJlbmRlcihjKSxuLnJlbmRlcmVyLnByb21pc2UudGhlbihuLm9uUmVuZGVyU3VjY2VzcykuY2F0Y2gobi5vblJlbmRlckVycm9yKX0pKSxufXJldHVybigwLGwuZGVmYXVsdCkodCxlKSwoMCx1LmRlZmF1bHQpKHQsW3trZXk6ImNvbXBvbmVudERpZE1vdW50Iix2YWx1ZTpmdW5jdGlvbigpe3RoaXMuZHJhd1BhZ2VPbkNhbnZhcygpfX0se2tleToiY29tcG9uZW50RGlkVXBkYXRlIix2YWx1ZTpmdW5jdGlvbihlKXt2YXIgdD10aGlzLnByb3BzLG49dC5wYWdlO3QucmVuZGVySW50ZXJhY3RpdmVGb3JtcyE9PWUucmVuZGVySW50ZXJhY3RpdmVGb3JtcyYmKG4uY2xlYW51cCgpLHRoaXMuZHJhd1BhZ2VPbkNhbnZhcygpKX19LHtrZXk6ImNvbXBvbmVudFdpbGxVbm1vdW50Iix2YWx1ZTpmdW5jdGlvbigpe3RoaXMuY2FuY2VsUmVuZGVyaW5nVGFzaygpLHRoaXMuY2FudmFzTGF5ZXImJih0aGlzLmNhbnZhc0xheWVyLndpZHRoPTAsdGhpcy5jYW52YXNMYXllci5oZWlnaHQ9MCx0aGlzLmNhbnZhc0xheWVyPW51bGwpfX0se2tleToiY2FuY2VsUmVuZGVyaW5nVGFzayIsdmFsdWU6ZnVuY3Rpb24oKXt0aGlzLnJlbmRlcmVyJiZ0aGlzLnJlbmRlcmVyLl9pbnRlcm5hbFJlbmRlclRhc2sucnVubmluZyYmdGhpcy5yZW5kZXJlci5faW50ZXJuYWxSZW5kZXJUYXNrLmNhbmNlbCgpfX0se2tleToicmVuZGVyIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXM7cmV0dXJuIHAuZGVmYXVsdC5jcmVhdGVFbGVtZW50KCJjYW52YXMiLHtjbGFzc05hbWU6InJlYWN0LXBkZl9fUGFnZV9fY2FudmFzIixzdHlsZTp7ZGlzcGxheToiYmxvY2siLHVzZXJTZWxlY3Q6Im5vbmUifSxyZWY6ZnVuY3Rpb24odCl7ZS5jYW52YXNMYXllcj10fX0pfX0se2tleToicmVuZGVyVmlld3BvcnQiLGdldDpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMsdD1lLnBhZ2Usbj1lLnJvdGF0ZSxyPWUuc2NhbGUsYT0oMCxnLmdldFBpeGVsUmF0aW8pKCk7cmV0dXJuIHQuZ2V0Vmlld3BvcnQoe3NjYWxlOnIqYSxyb3RhdGlvbjpufSl9fSx7a2V5OiJ2aWV3cG9ydCIsZ2V0OmZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5wcm9wcyx0PWUucGFnZSxuPWUucm90YXRlLHI9ZS5zY2FsZTtyZXR1cm4gdC5nZXRWaWV3cG9ydCh7c2NhbGU6cixyb3RhdGlvbjpufSl9fV0pLHR9KHAuUHVyZUNvbXBvbmVudCk7dC5QYWdlQ2FudmFzSW50ZXJuYWw9eSx5LnByb3BUeXBlcz17b25SZW5kZXJFcnJvcjpoLmRlZmF1bHQuZnVuYyxvblJlbmRlclN1Y2Nlc3M6aC5kZWZhdWx0LmZ1bmMscGFnZTptLmlzUGFnZS5pc1JlcXVpcmVkLHJlbmRlckludGVyYWN0aXZlRm9ybXM6aC5kZWZhdWx0LmJvb2wscm90YXRlOm0uaXNSb3RhdGUsc2NhbGU6aC5kZWZhdWx0Lm51bWJlcn19LGZ1bmN0aW9uKGUsdCxuKXsidXNlIHN0cmljdCI7dmFyIHI9big5KSxhPW4oMSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsIl9fZXNNb2R1bGUiLHt2YWx1ZTohMH0pLHQuZGVmYXVsdD1mdW5jdGlvbihlKXtyZXR1cm4gcC5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoZy5kZWZhdWx0LkNvbnN1bWVyLG51bGwsKGZ1bmN0aW9uKHQpe3JldHVybiBwLmRlZmF1bHQuY3JlYXRlRWxlbWVudChiLCgwLG8uZGVmYXVsdCkoe30sdCxlKSl9KSl9LHQuUGFnZVNWR0ludGVybmFsPXZvaWQgMDt2YXIgbz1hKG4oMTApKSxpPWEobig1KSksdT1hKG4oMTEpKSxjPWEobig2KSkscz1hKG4oMikpLGw9YShuKDgpKSxmPWEobig3KSksZD1hKG4oNCkpLHA9cihuKDApKSxoPWEobigzKSksdj1hKG4oMjEpKSxnPWEobigxNSkpLG09bigxMikseT1uKDEzKSxiPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHQoKXt2YXIgZSxuOygwLGkuZGVmYXVsdCkodGhpcyx0KTtmb3IodmFyIHI9YXJndW1lbnRzLmxlbmd0aCxhPW5ldyBBcnJheShyKSxvPTA7bzxyO28rKylhW29dPWFyZ3VtZW50c1tvXTtyZXR1cm4gbj0oMCxjLmRlZmF1bHQpKHRoaXMsKGU9KDAscy5kZWZhdWx0KSh0KSkuY2FsbC5hcHBseShlLFt0aGlzXS5jb25jYXQoYSkpKSwoMCxkLmRlZmF1bHQpKCgwLGYuZGVmYXVsdCkoKDAsZi5kZWZhdWx0KShuKSksInN0YXRlIix7c3ZnOm51bGx9KSwoMCxkLmRlZmF1bHQpKCgwLGYuZGVmYXVsdCkoKDAsZi5kZWZhdWx0KShuKSksIm9uUmVuZGVyU3VjY2VzcyIsKGZ1bmN0aW9uKCl7bi5yZW5kZXJlcj1udWxsO3ZhciBlPW4ucHJvcHMsdD1lLm9uUmVuZGVyU3VjY2VzcyxyPWUucGFnZSxhPWUuc2NhbGU7KDAsbS5jYWxsSWZEZWZpbmVkKSh0LCgwLG0ubWFrZVBhZ2VDYWxsYmFjaykocixhKSl9KSksKDAsZC5kZWZhdWx0KSgoMCxmLmRlZmF1bHQpKCgwLGYuZGVmYXVsdCkobikpLCJvblJlbmRlckVycm9yIiwoZnVuY3Rpb24oZSl7aWYoISgwLG0uaXNDYW5jZWxFeGNlcHRpb24pKGUpKXsoMCxtLmVycm9yT25EZXYpKGUpO3ZhciB0PW4ucHJvcHMub25SZW5kZXJFcnJvcjsoMCxtLmNhbGxJZkRlZmluZWQpKHQsZSl9fSkpLCgwLGQuZGVmYXVsdCkoKDAsZi5kZWZhdWx0KSgoMCxmLmRlZmF1bHQpKG4pKSwicmVuZGVyU1ZHIiwoZnVuY3Rpb24oKXt2YXIgZT1uLnByb3BzLnBhZ2U7cmV0dXJuIG4ucmVuZGVyZXI9ZS5nZXRPcGVyYXRvckxpc3QoKSxuLnJlbmRlcmVyLnRoZW4oKGZ1bmN0aW9uKHQpe3ZhciByPW5ldyB2LmRlZmF1bHQuU1ZHR3JhcGhpY3MoZS5jb21tb25PYmpzLGUub2Jqcyk7bi5yZW5kZXJlcj1yLmdldFNWRyh0LG4udmlld3BvcnQpLnRoZW4oKGZ1bmN0aW9uKGUpe24uc2V0U3RhdGUoe3N2ZzplfSxuLm9uUmVuZGVyU3VjY2Vzcyl9KSkuY2F0Y2gobi5vblJlbmRlckVycm9yKX0pKS5jYXRjaChuLm9uUmVuZGVyRXJyb3IpfSkpLCgwLGQuZGVmYXVsdCkoKDAsZi5kZWZhdWx0KSgoMCxmLmRlZmF1bHQpKG4pKSwiZHJhd1BhZ2VPbkNvbnRhaW5lciIsKGZ1bmN0aW9uKGUpe3ZhciB0PW4uc3RhdGUuc3ZnO2lmKGUmJnQpe2UuZmlyc3RFbGVtZW50Q2hpbGR8fGUuYXBwZW5kQ2hpbGQodCk7dmFyIHI9bi52aWV3cG9ydCxhPXIud2lkdGgsbz1yLmhlaWdodDt0LnNldEF0dHJpYnV0ZSgid2lkdGgiLGEpLHQuc2V0QXR0cmlidXRlKCJoZWlnaHQiLG8pfX0pKSxufXJldHVybigwLGwuZGVmYXVsdCkodCxlKSwoMCx1LmRlZmF1bHQpKHQsW3trZXk6ImNvbXBvbmVudERpZE1vdW50Iix2YWx1ZTpmdW5jdGlvbigpe3RoaXMucmVuZGVyU1ZHKCl9fSx7a2V5OiJyZW5kZXIiLHZhbHVlOmZ1bmN0aW9uKCl7dmFyIGU9dGhpcyx0PXRoaXMudmlld3BvcnQsbj10LndpZHRoLHI9dC5oZWlnaHQ7cmV0dXJuIHAuZGVmYXVsdC5jcmVhdGVFbGVtZW50KCJkaXYiLHtjbGFzc05hbWU6InJlYWN0LXBkZl9fUGFnZV9fc3ZnIixzdHlsZTp7ZGlzcGxheToiYmxvY2siLGJhY2tncm91bmRDb2xvcjoid2hpdGUiLG92ZXJmbG93OiJoaWRkZW4iLHdpZHRoOm4saGVpZ2h0OnIsdXNlclNlbGVjdDoibm9uZSJ9LHJlZjpmdW5jdGlvbih0KXtyZXR1cm4gZS5kcmF3UGFnZU9uQ29udGFpbmVyKHQpfX0pfX0se2tleToidmlld3BvcnQiLGdldDpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMsdD1lLnBhZ2Usbj1lLnJvdGF0ZSxyPWUuc2NhbGU7cmV0dXJuIHQuZ2V0Vmlld3BvcnQoe3NjYWxlOnIscm90YXRpb246bn0pfX1dKSx0fShwLlB1cmVDb21wb25lbnQpO3QuUGFnZVNWR0ludGVybmFsPWIsYi5wcm9wVHlwZXM9e29uUmVuZGVyRXJyb3I6aC5kZWZhdWx0LmZ1bmMsb25SZW5kZXJTdWNjZXNzOmguZGVmYXVsdC5mdW5jLHBhZ2U6eS5pc1BhZ2UuaXNSZXF1aXJlZCxyb3RhdGU6eS5pc1JvdGF0ZSxzY2FsZTpoLmRlZmF1bHQubnVtYmVyfX0sZnVuY3Rpb24oZSx0LG4peyJ1c2Ugc3RyaWN0Ijt2YXIgcj1uKDkpLGE9bigxKTtPYmplY3QuZGVmaW5lUHJvcGVydHkodCwiX19lc01vZHVsZSIse3ZhbHVlOiEwfSksdC5kZWZhdWx0PWZ1bmN0aW9uKGUpe3JldHVybiB2LmRlZmF1bHQuY3JlYXRlRWxlbWVudChtLmRlZmF1bHQuQ29uc3VtZXIsbnVsbCwoZnVuY3Rpb24odCl7cmV0dXJuIHYuZGVmYXVsdC5jcmVhdGVFbGVtZW50KHgsKDAsby5kZWZhdWx0KSh7fSx0LGUpKX0pKX0sdC5UZXh0TGF5ZXJJbnRlcm5hbD12b2lkIDA7dmFyIG89YShuKDEwKSksaT1hKG4oMTYpKSx1PWEobigxNykpLGM9YShuKDUpKSxzPWEobigxMSkpLGw9YShuKDYpKSxmPWEobigyKSksZD1hKG4oOCkpLHA9YShuKDcpKSxoPWEobig0KSksdj1yKG4oMCkpLGc9YShuKDMpKSxtPWEobigxNSkpLHk9YShuKDQ5KSksYj1uKDEyKSx3PW4oMTMpLHg9ZnVuY3Rpb24oZSl7ZnVuY3Rpb24gdCgpe3ZhciBlLG47KDAsYy5kZWZhdWx0KSh0aGlzLHQpO2Zvcih2YXIgcj1hcmd1bWVudHMubGVuZ3RoLGE9bmV3IEFycmF5KHIpLG89MDtvPHI7bysrKWFbb109YXJndW1lbnRzW29dO3JldHVybiBuPSgwLGwuZGVmYXVsdCkodGhpcywoZT0oMCxmLmRlZmF1bHQpKHQpKS5jYWxsLmFwcGx5KGUsW3RoaXNdLmNvbmNhdChhKSkpLCgwLGguZGVmYXVsdCkoKDAscC5kZWZhdWx0KSgoMCxwLmRlZmF1bHQpKG4pKSwic3RhdGUiLHt0ZXh0SXRlbXM6bnVsbH0pLCgwLGguZGVmYXVsdCkoKDAscC5kZWZhdWx0KSgoMCxwLmRlZmF1bHQpKG4pKSwibG9hZFRleHRJdGVtcyIsKDAsdS5kZWZhdWx0KShpLmRlZmF1bHQubWFyaygoZnVuY3Rpb24gZSgpe3ZhciB0LHIsYSxvO3JldHVybiBpLmRlZmF1bHQud3JhcCgoZnVuY3Rpb24oZSl7Zm9yKDs7KXN3aXRjaChlLnByZXY9ZS5uZXh0KXtjYXNlIDA6cmV0dXJuIHQ9bi5wcm9wcy5wYWdlLGUucHJldj0xLHI9KDAsYi5tYWtlQ2FuY2VsbGFibGUpKHQuZ2V0VGV4dENvbnRlbnQoKSksbi5ydW5uaW5nVGFzaz1yLGUubmV4dD02LHIucHJvbWlzZTtjYXNlIDY6YT1lLnNlbnQsbz1hLml0ZW1zLG4uc2V0U3RhdGUoe3RleHRJdGVtczpvfSxuLm9uTG9hZFN1Y2Nlc3MpLGUubmV4dD0xNDticmVhaztjYXNlIDExOmUucHJldj0xMSxlLnQwPWUuY2F0Y2goMSksbi5vbkxvYWRFcnJvcihlLnQwKTtjYXNlIDE0OmNhc2UiZW5kIjpyZXR1cm4gZS5zdG9wKCl9fSksZSx0aGlzLFtbMSwxMV1dKX0pKSkpLCgwLGguZGVmYXVsdCkoKDAscC5kZWZhdWx0KSgoMCxwLmRlZmF1bHQpKG4pKSwib25Mb2FkU3VjY2VzcyIsKGZ1bmN0aW9uKCl7dmFyIGU9bi5wcm9wcy5vbkdldFRleHRTdWNjZXNzLHQ9bi5zdGF0ZS50ZXh0SXRlbXM7KDAsYi5jYWxsSWZEZWZpbmVkKShlLHQpfSkpLCgwLGguZGVmYXVsdCkoKDAscC5kZWZhdWx0KSgoMCxwLmRlZmF1bHQpKG4pKSwib25Mb2FkRXJyb3IiLChmdW5jdGlvbihlKXtpZighKDAsYi5pc0NhbmNlbEV4Y2VwdGlvbikoZSkpe24uc2V0U3RhdGUoe3RleHRJdGVtczohMX0pLCgwLGIuZXJyb3JPbkRldikoZSk7dmFyIHQ9bi5wcm9wcy5vbkdldFRleHRFcnJvcjsoMCxiLmNhbGxJZkRlZmluZWQpKHQsZSl9fSkpLG59cmV0dXJuKDAsZC5kZWZhdWx0KSh0LGUpLCgwLHMuZGVmYXVsdCkodCxbe2tleToiY29tcG9uZW50RGlkTW91bnQiLHZhbHVlOmZ1bmN0aW9uKCl7aWYoIXRoaXMucHJvcHMucGFnZSl0aHJvdyBuZXcgRXJyb3IoIkF0dGVtcHRlZCB0byBsb2FkIHBhZ2UgdGV4dCBjb250ZW50LCBidXQgbm8gcGFnZSB3YXMgc3BlY2lmaWVkLiIpO3RoaXMubG9hZFRleHRJdGVtcygpfX0se2tleToiY29tcG9uZW50RGlkVXBkYXRlIix2YWx1ZTpmdW5jdGlvbihlKXt2YXIgdD10aGlzLnByb3BzLnBhZ2U7ZS5wYWdlJiZ0IT09ZS5wYWdlJiZ0aGlzLmxvYWRUZXh0SXRlbXMoKX19LHtrZXk6ImNvbXBvbmVudFdpbGxVbm1vdW50Iix2YWx1ZTpmdW5jdGlvbigpeygwLGIuY2FuY2VsUnVubmluZ1Rhc2spKHRoaXMucnVubmluZ1Rhc2spfX0se2tleToicmVuZGVyVGV4dEl0ZW1zIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMuc3RhdGUudGV4dEl0ZW1zO3JldHVybiBlP2UubWFwKChmdW5jdGlvbihlLHQpe3JldHVybiB2LmRlZmF1bHQuY3JlYXRlRWxlbWVudCh5LmRlZmF1bHQsKDAsby5kZWZhdWx0KSh7a2V5OnQsaXRlbUluZGV4OnR9LGUpKX0pKTpudWxsfX0se2tleToicmVuZGVyIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMudW5yb3RhdGVkVmlld3BvcnQsdD10aGlzLnJvdGF0ZTtyZXR1cm4gdi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoImRpdiIse2NsYXNzTmFtZToicmVhY3QtcGRmX19QYWdlX190ZXh0Q29udGVudCIsc3R5bGU6e3Bvc2l0aW9uOiJhYnNvbHV0ZSIsdG9wOiI1MCUiLGxlZnQ6IjUwJSIsd2lkdGg6IiIuY29uY2F0KGUud2lkdGgsInB4IiksaGVpZ2h0OiIiLmNvbmNhdChlLmhlaWdodCwicHgiKSxjb2xvcjoidHJhbnNwYXJlbnQiLHRyYW5zZm9ybToidHJhbnNsYXRlKC01MCUsIC01MCUpIHJvdGF0ZSgiLmNvbmNhdCh0LCJkZWcpIikscG9pbnRlckV2ZW50czoibm9uZSJ9fSx0aGlzLnJlbmRlclRleHRJdGVtcygpKX19LHtrZXk6InVucm90YXRlZFZpZXdwb3J0IixnZXQ6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnByb3BzLHQ9ZS5wYWdlLG49ZS5zY2FsZTtyZXR1cm4gdC5nZXRWaWV3cG9ydCh7c2NhbGU6bn0pfX0se2tleToicm90YXRlIixnZXQ6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnByb3BzLHQ9ZS5wYWdlO3JldHVybiBlLnJvdGF0ZS10LnJvdGF0ZX19XSksdH0odi5QdXJlQ29tcG9uZW50KTt0LlRleHRMYXllckludGVybmFsPXgseC5wcm9wVHlwZXM9e29uR2V0VGV4dEVycm9yOmcuZGVmYXVsdC5mdW5jLG9uR2V0VGV4dFN1Y2Nlc3M6Zy5kZWZhdWx0LmZ1bmMscGFnZTp3LmlzUGFnZS5pc1JlcXVpcmVkLHJvdGF0ZTp3LmlzUm90YXRlLHNjYWxlOmcuZGVmYXVsdC5udW1iZXJ9fSxmdW5jdGlvbihlLHQsbil7InVzZSBzdHJpY3QiO3ZhciByPW4oOSksYT1uKDEpO09iamVjdC5kZWZpbmVQcm9wZXJ0eSh0LCJfX2VzTW9kdWxlIix7dmFsdWU6ITB9KSx0LmRlZmF1bHQ9ZnVuY3Rpb24oZSl7cmV0dXJuIGcuZGVmYXVsdC5jcmVhdGVFbGVtZW50KHkuZGVmYXVsdC5Db25zdW1lcixudWxsLChmdW5jdGlvbih0KXtyZXR1cm4gZy5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQodywoMCxvLmRlZmF1bHQpKHt9LHQsZSkpfSkpfSx0LlRleHRMYXllckl0ZW1JbnRlcm5hbD12b2lkIDA7dmFyIG89YShuKDEwKSksaT1hKG4oNTApKSx1PWEobigxNikpLGM9YShuKDE3KSkscz1hKG4oNSkpLGw9YShuKDExKSksZj1hKG4oNikpLGQ9YShuKDIpKSxwPWEobig4KSksaD1hKG4oNykpLHY9YShuKDQpKSxnPXIobigwKSksbT1hKG4oMykpLHk9YShuKDE1KSksYj1uKDEzKSx3PWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHQoKXt2YXIgZSxuOygwLHMuZGVmYXVsdCkodGhpcyx0KTtmb3IodmFyIHI9YXJndW1lbnRzLmxlbmd0aCxhPW5ldyBBcnJheShyKSxvPTA7bzxyO28rKylhW29dPWFyZ3VtZW50c1tvXTtyZXR1cm4gbj0oMCxmLmRlZmF1bHQpKHRoaXMsKGU9KDAsZC5kZWZhdWx0KSh0KSkuY2FsbC5hcHBseShlLFt0aGlzXS5jb25jYXQoYSkpKSwoMCx2LmRlZmF1bHQpKCgwLGguZGVmYXVsdCkoKDAsaC5kZWZhdWx0KShuKSksImdldEVsZW1lbnRXaWR0aCIsKGZ1bmN0aW9uKGUpe3ZhciB0PSgwLGguZGVmYXVsdCkoKDAsaC5kZWZhdWx0KShuKSkuc2lkZXdheXM7cmV0dXJuIGUuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClbdD8iaGVpZ2h0Ijoid2lkdGgiXX0pKSxufXZhciBuLHI7cmV0dXJuKDAscC5kZWZhdWx0KSh0LGUpLCgwLGwuZGVmYXVsdCkodCxbe2tleToiY29tcG9uZW50RGlkTW91bnQiLHZhbHVlOmZ1bmN0aW9uKCl7dGhpcy5hbGlnblRleHRJdGVtKCl9fSx7a2V5OiJjb21wb25lbnREaWRVcGRhdGUiLHZhbHVlOmZ1bmN0aW9uKCl7dGhpcy5hbGlnblRleHRJdGVtKCl9fSx7a2V5OiJnZXRGb250RGF0YSIsdmFsdWU6KHI9KDAsYy5kZWZhdWx0KSh1LmRlZmF1bHQubWFyaygoZnVuY3Rpb24gZSh0KXt2YXIgbixyO3JldHVybiB1LmRlZmF1bHQud3JhcCgoZnVuY3Rpb24oZSl7Zm9yKDs7KXN3aXRjaChlLnByZXY9ZS5uZXh0KXtjYXNlIDA6cmV0dXJuIG49dGhpcy5wcm9wcy5wYWdlLGUubmV4dD0zLG5ldyBQcm9taXNlKChmdW5jdGlvbihlKXtuLmNvbW1vbk9ianMuZ2V0KHQsZSl9KSk7Y2FzZSAzOnJldHVybiByPWUuc2VudCxlLmFicnVwdCgicmV0dXJuIixyKTtjYXNlIDU6Y2FzZSJlbmQiOnJldHVybiBlLnN0b3AoKX19KSxlLHRoaXMpfSkpKSxmdW5jdGlvbihlKXtyZXR1cm4gci5hcHBseSh0aGlzLGFyZ3VtZW50cyl9KX0se2tleToiYWxpZ25UZXh0SXRlbSIsdmFsdWU6KG49KDAsYy5kZWZhdWx0KSh1LmRlZmF1bHQubWFyaygoZnVuY3Rpb24gZSgpe3ZhciB0LG4scixhLG8saSxjLHMsbCxmLGQ7cmV0dXJuIHUuZGVmYXVsdC53cmFwKChmdW5jdGlvbihlKXtmb3IoOzspc3dpdGNoKGUucHJldj1lLm5leHQpe2Nhc2UgMDppZih0PXRoaXMuaXRlbSl7ZS5uZXh0PTM7YnJlYWt9cmV0dXJuIGUuYWJydXB0KCJyZXR1cm4iKTtjYXNlIDM6cmV0dXJuIHQuc3R5bGUudHJhbnNmb3JtPSIiLG49dGhpcy5wcm9wcyxyPW4uZm9udE5hbWUsYT1uLnNjYWxlLG89bi53aWR0aCx0LnN0eWxlLmZvbnRGYW1pbHk9IiIuY29uY2F0KHIsIiwgc2Fucy1zZXJpZiIpLGUubmV4dD04LHRoaXMuZ2V0Rm9udERhdGEocik7Y2FzZSA4Omk9ZS5zZW50LGM9aT9pLmZhbGxiYWNrTmFtZToic2Fucy1zZXJpZiIsdC5zdHlsZS5mb250RmFtaWx5PSIiLmNvbmNhdChyLCIsICIpLmNvbmNhdChjKSxzPW8qYSxsPXRoaXMuZ2V0RWxlbWVudFdpZHRoKHQpLGY9InNjYWxlWCgiLmNvbmNhdChzL2wsIikiKSwoZD1pP2kuYXNjZW50OjApJiYoZis9IiB0cmFuc2xhdGVZKCIuY29uY2F0KDEwMCooMS1kKSwiJSkiKSksdC5zdHlsZS50cmFuc2Zvcm09ZjtjYXNlIDE3OmNhc2UiZW5kIjpyZXR1cm4gZS5zdG9wKCl9fSksZSx0aGlzKX0pKSksZnVuY3Rpb24oKXtyZXR1cm4gbi5hcHBseSh0aGlzLGFyZ3VtZW50cyl9KX0se2tleToicmVuZGVyIix2YWx1ZTpmdW5jdGlvbigpe3ZhciBlPXRoaXMsdD10aGlzLmZvbnRTaXplLG49dGhpcy50b3Ascj10aGlzLmxlZnQsYT10aGlzLnByb3BzLG89YS5jdXN0b21UZXh0UmVuZGVyZXIsaT1hLnNjYWxlLHU9YS5zdHI7cmV0dXJuIGcuZGVmYXVsdC5jcmVhdGVFbGVtZW50KCJzcGFuIix7c3R5bGU6e2hlaWdodDoiMWVtIixmb250RmFtaWx5OiJzYW5zLXNlcmlmIixmb250U2l6ZToiIi5jb25jYXQodCppLCJweCIpLHBvc2l0aW9uOiJhYnNvbHV0ZSIsdG9wOiIiLmNvbmNhdChuKmksInB4IiksbGVmdDoiIi5jb25jYXQocippLCJweCIpLHRyYW5zZm9ybU9yaWdpbjoibGVmdCBib3R0b20iLHdoaXRlU3BhY2U6InByZSIscG9pbnRlckV2ZW50czoiYWxsIn0scmVmOmZ1bmN0aW9uKHQpe2UuaXRlbT10fX0sbz9vKHRoaXMucHJvcHMpOnUpfX0se2tleToidW5yb3RhdGVkVmlld3BvcnQiLGdldDpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMsdD1lLnBhZ2Usbj1lLnNjYWxlO3JldHVybiB0LmdldFZpZXdwb3J0KHtzY2FsZTpufSl9fSx7a2V5OiJyb3RhdGUiLGdldDpmdW5jdGlvbigpe3ZhciBlPXRoaXMucHJvcHMsdD1lLnBhZ2U7cmV0dXJuIGUucm90YXRlLXQucm90YXRlfX0se2tleToic2lkZXdheXMiLGdldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnJvdGF0ZSUxODAhPTB9fSx7a2V5OiJkZWZhdWx0U2lkZXdheXMiLGdldDpmdW5jdGlvbigpe3JldHVybiB0aGlzLnVucm90YXRlZFZpZXdwb3J0LnJvdGF0aW9uJTE4MCE9MH19LHtrZXk6ImZvbnRTaXplIixnZXQ6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnByb3BzLnRyYW5zZm9ybSx0PXRoaXMuZGVmYXVsdFNpZGV3YXlzLG49KDAsaS5kZWZhdWx0KShlLDIpLHI9blswXSxhPW5bMV07cmV0dXJuIHQ/YTpyfX0se2tleToidG9wIixnZXQ6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnByb3BzLnRyYW5zZm9ybSx0PXRoaXMudW5yb3RhdGVkVmlld3BvcnQsbj10aGlzLmRlZmF1bHRTaWRld2F5cyxyPSgwLGkuZGVmYXVsdCkoZSw2KSxhPXJbMl0sbz1yWzNdLHU9cls0XSxjPXJbNV0scz0oMCxpLmRlZmF1bHQpKHQudmlld0JveCw0KSxsPXNbMV0sZj1zWzNdO3JldHVybiBuP3UrYStsOmYtKGMrbyl9fSx7a2V5OiJsZWZ0IixnZXQ6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnByb3BzLnRyYW5zZm9ybSx0PXRoaXMudW5yb3RhdGVkVmlld3BvcnQsbj10aGlzLmRlZmF1bHRTaWRld2F5cyxyPSgwLGkuZGVmYXVsdCkoZSw2KSxhPXJbNF0sbz1yWzVdLHU9KDAsaS5kZWZhdWx0KSh0LnZpZXdCb3gsMSlbMF07cmV0dXJuIG4/by11OmEtdX19XSksdH0oZy5QdXJlQ29tcG9uZW50KTt0LlRleHRMYXllckl0ZW1JbnRlcm5hbD13LHcucHJvcFR5cGVzPXtjdXN0b21UZXh0UmVuZGVyZXI6bS5kZWZhdWx0LmZ1bmMsZm9udE5hbWU6bS5kZWZhdWx0LnN0cmluZy5pc1JlcXVpcmVkLGl0ZW1JbmRleDptLmRlZmF1bHQubnVtYmVyLmlzUmVxdWlyZWQscGFnZTpiLmlzUGFnZS5pc1JlcXVpcmVkLHJvdGF0ZTpiLmlzUm90YXRlLHNjYWxlOm0uZGVmYXVsdC5udW1iZXIsc3RyOm0uZGVmYXVsdC5zdHJpbmcuaXNSZXF1aXJlZCx0cmFuc2Zvcm06bS5kZWZhdWx0LmFycmF5T2YobS5kZWZhdWx0Lm51bWJlcikuaXNSZXF1aXJlZCx3aWR0aDptLmRlZmF1bHQubnVtYmVyLmlzUmVxdWlyZWR9fSxmdW5jdGlvbihlLHQsbil7dmFyIHI9big1MSksYT1uKDUyKSxvPW4oNTMpO2UuZXhwb3J0cz1mdW5jdGlvbihlLHQpe3JldHVybiByKGUpfHxhKGUsdCl8fG8oKX19LGZ1bmN0aW9uKGUsdCl7ZS5leHBvcnRzPWZ1bmN0aW9uKGUpe2lmKEFycmF5LmlzQXJyYXkoZSkpcmV0dXJuIGV9fSxmdW5jdGlvbihlLHQpe2UuZXhwb3J0cz1mdW5jdGlvbihlLHQpe2lmKFN5bWJvbC5pdGVyYXRvciBpbiBPYmplY3QoZSl8fCJbb2JqZWN0IEFyZ3VtZW50c10iPT09T2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGUpKXt2YXIgbj1bXSxyPSEwLGE9ITEsbz12b2lkIDA7dHJ5e2Zvcih2YXIgaSx1PWVbU3ltYm9sLml0ZXJhdG9yXSgpOyEocj0oaT11Lm5leHQoKSkuZG9uZSkmJihuLnB1c2goaS52YWx1ZSksIXR8fG4ubGVuZ3RoIT09dCk7cj0hMCk7fWNhdGNoKGUpe2E9ITAsbz1lfWZpbmFsbHl7dHJ5e3J8fG51bGw9PXUucmV0dXJufHx1LnJldHVybigpfWZpbmFsbHl7aWYoYSl0aHJvdyBvfX1yZXR1cm4gbn19fSxmdW5jdGlvbihlLHQpe2UuZXhwb3J0cz1mdW5jdGlvbigpe3Rocm93IG5ldyBUeXBlRXJyb3IoIkludmFsaWQgYXR0ZW1wdCB0byBkZXN0cnVjdHVyZSBub24taXRlcmFibGUgaW5zdGFuY2UiKX19LGZ1bmN0aW9uKGUsdCxuKXsidXNlIHN0cmljdCI7dmFyIHI9big5KSxhPW4oMSk7T2JqZWN0LmRlZmluZVByb3BlcnR5KHQsIl9fZXNNb2R1bGUiLHt2YWx1ZTohMH0pLHQuZGVmYXVsdD10LkFubm90YXRpb25MYXllckludGVybmFsPXZvaWQgMDt2YXIgbz1hKG4oMTApKSxpPWEobigxNikpLHU9YShuKDE3KSksYz1hKG4oNSkpLHM9YShuKDExKSksbD1hKG4oNikpLGY9YShuKDIpKSxkPWEobig4KSkscD1hKG4oNykpLGg9YShuKDQpKSx2PXIobigwKSksZz1hKG4oMykpLG09YShuKDIxKSkseT1hKG4oMjIpKSxiPWEobigxNSkpLHc9bigxMikseD1uKDEzKSxFPWZ1bmN0aW9uKGUpe2Z1bmN0aW9uIHQoKXt2YXIgZSxuOygwLGMuZGVmYXVsdCkodGhpcyx0KTtmb3IodmFyIHI9YXJndW1lbnRzLmxlbmd0aCxhPW5ldyBBcnJheShyKSxvPTA7bzxyO28rKylhW29dPWFyZ3VtZW50c1tvXTtyZXR1cm4gbj0oMCxsLmRlZmF1bHQpKHRoaXMsKGU9KDAsZi5kZWZhdWx0KSh0KSkuY2FsbC5hcHBseShlLFt0aGlzXS5jb25jYXQoYSkpKSwoMCxoLmRlZmF1bHQpKCgwLHAuZGVmYXVsdCkoKDAscC5kZWZhdWx0KShuKSksInN0YXRlIix7YW5ub3RhdGlvbnM6bnVsbH0pLCgwLGguZGVmYXVsdCkoKDAscC5kZWZhdWx0KSgoMCxwLmRlZmF1bHQpKG4pKSwibG9hZEFubm90YXRpb25zIiwoMCx1LmRlZmF1bHQpKGkuZGVmYXVsdC5tYXJrKChmdW5jdGlvbiBlKCl7dmFyIHQscixhO3JldHVybiBpLmRlZmF1bHQud3JhcCgoZnVuY3Rpb24oZSl7Zm9yKDs7KXN3aXRjaChlLnByZXY9ZS5uZXh0KXtjYXNlIDA6cmV0dXJuIHQ9bi5wcm9wcy5wYWdlLGUucHJldj0xLHI9KDAsdy5tYWtlQ2FuY2VsbGFibGUpKHQuZ2V0QW5ub3RhdGlvbnMoKSksbi5ydW5uaW5nVGFzaz1yLGUubmV4dD02LHIucHJvbWlzZTtjYXNlIDY6YT1lLnNlbnQsbi5zZXRTdGF0ZSh7YW5ub3RhdGlvbnM6YX0sbi5vbkxvYWRTdWNjZXNzKSxlLm5leHQ9MTM7YnJlYWs7Y2FzZSAxMDplLnByZXY9MTAsZS50MD1lLmNhdGNoKDEpLG4ub25Mb2FkRXJyb3IoZS50MCk7Y2FzZSAxMzpjYXNlImVuZCI6cmV0dXJuIGUuc3RvcCgpfX0pLGUsdGhpcyxbWzEsMTBdXSl9KSkpKSwoMCxoLmRlZmF1bHQpKCgwLHAuZGVmYXVsdCkoKDAscC5kZWZhdWx0KShuKSksIm9uTG9hZFN1Y2Nlc3MiLChmdW5jdGlvbigpe3ZhciBlPW4ucHJvcHMub25HZXRBbm5vdGF0aW9uc1N1Y2Nlc3MsdD1uLnN0YXRlLmFubm90YXRpb25zOygwLHcuY2FsbElmRGVmaW5lZCkoZSx0KX0pKSwoMCxoLmRlZmF1bHQpKCgwLHAuZGVmYXVsdCkoKDAscC5kZWZhdWx0KShuKSksIm9uTG9hZEVycm9yIiwoZnVuY3Rpb24oZSl7aWYoISgwLHcuaXNDYW5jZWxFeGNlcHRpb24pKGUpKXtuLnNldFN0YXRlKHthbm5vdGF0aW9uczohMX0pLCgwLHcuZXJyb3JPbkRldikoZSk7dmFyIHQ9bi5wcm9wcy5vbkdldEFubm90YXRpb25zRXJyb3I7KDAsdy5jYWxsSWZEZWZpbmVkKSh0LGUpfX0pKSwoMCxoLmRlZmF1bHQpKCgwLHAuZGVmYXVsdCkoKDAscC5kZWZhdWx0KShuKSksIm9uUmVuZGVyU3VjY2VzcyIsKGZ1bmN0aW9uKCl7dmFyIGU9bi5wcm9wcy5vblJlbmRlckFubm90YXRpb25MYXllclN1Y2Nlc3M7KDAsdy5jYWxsSWZEZWZpbmVkKShlKX0pKSwoMCxoLmRlZmF1bHQpKCgwLHAuZGVmYXVsdCkoKDAscC5kZWZhdWx0KShuKSksIm9uUmVuZGVyRXJyb3IiLChmdW5jdGlvbihlKXtpZighKDAsdy5pc0NhbmNlbEV4Y2VwdGlvbikoZSkpeygwLHcuZXJyb3JPbkRldikoZSk7dmFyIHQ9bi5wcm9wcy5vblJlbmRlckFubm90YXRpb25MYXllckVycm9yOygwLHcuY2FsbElmRGVmaW5lZCkodCxlKX19KSksbn1yZXR1cm4oMCxkLmRlZmF1bHQpKHQsZSksKDAscy5kZWZhdWx0KSh0LFt7a2V5OiJjb21wb25lbnREaWRNb3VudCIsdmFsdWU6ZnVuY3Rpb24oKXtpZighdGhpcy5wcm9wcy5wYWdlKXRocm93IG5ldyBFcnJvcigiQXR0ZW1wdGVkIHRvIGxvYWQgcGFnZSBhbm5vdGF0aW9ucywgYnV0IG5vIHBhZ2Ugd2FzIHNwZWNpZmllZC4iKTt0aGlzLmxvYWRBbm5vdGF0aW9ucygpfX0se2tleToiY29tcG9uZW50RGlkVXBkYXRlIix2YWx1ZTpmdW5jdGlvbihlKXt2YXIgdD10aGlzLnByb3BzLG49dC5wYWdlLHI9dC5yZW5kZXJJbnRlcmFjdGl2ZUZvcm1zOyhlLnBhZ2UmJm4hPT1lLnBhZ2V8fHIhPT1lLnJlbmRlckludGVyYWN0aXZlRm9ybXMpJiZ0aGlzLmxvYWRBbm5vdGF0aW9ucygpfX0se2tleToiY29tcG9uZW50V2lsbFVubW91bnQiLHZhbHVlOmZ1bmN0aW9uKCl7KDAsdy5jYW5jZWxSdW5uaW5nVGFzaykodGhpcy5ydW5uaW5nVGFzayl9fSx7a2V5OiJyZW5kZXJBbm5vdGF0aW9uTGF5ZXIiLHZhbHVlOmZ1bmN0aW9uKCl7dmFyIGU9dGhpcy5zdGF0ZS5hbm5vdGF0aW9ucztpZihlKXt2YXIgdD10aGlzLnByb3BzLG49dC5saW5rU2VydmljZSxyPXQucGFnZSxhPXQucmVuZGVySW50ZXJhY3RpdmVGb3JtcyxvPXRoaXMudmlld3BvcnQuY2xvbmUoe2RvbnRGbGlwOiEwfSksaT17YW5ub3RhdGlvbnM6ZSxkaXY6dGhpcy5hbm5vdGF0aW9uTGF5ZXIsbGlua1NlcnZpY2U6bixwYWdlOnIscmVuZGVySW50ZXJhY3RpdmVGb3JtczphLHZpZXdwb3J0Om99O3RoaXMuYW5ub3RhdGlvbkxheWVyLmlubmVySFRNTD0iIjt0cnl7bS5kZWZhdWx0LkFubm90YXRpb25MYXllci5yZW5kZXIoaSksdGhpcy5vblJlbmRlclN1Y2Nlc3MoKX1jYXRjaChlKXt0aGlzLm9uUmVuZGVyRXJyb3IoZSl9fX19LHtrZXk6InJlbmRlciIsdmFsdWU6ZnVuY3Rpb24oKXt2YXIgZT10aGlzO3JldHVybiB2LmRlZmF1bHQuY3JlYXRlRWxlbWVudCgiZGl2Iix7Y2xhc3NOYW1lOiJyZWFjdC1wZGZfX1BhZ2VfX2Fubm90YXRpb25zIGFubm90YXRpb25MYXllciIscmVmOmZ1bmN0aW9uKHQpe2UuYW5ub3RhdGlvbkxheWVyPXR9fSx0aGlzLnJlbmRlckFubm90YXRpb25MYXllcigpKX19LHtrZXk6InZpZXdwb3J0IixnZXQ6ZnVuY3Rpb24oKXt2YXIgZT10aGlzLnByb3BzLHQ9ZS5wYWdlLG49ZS5yb3RhdGUscj1lLnNjYWxlO3JldHVybiB0LmdldFZpZXdwb3J0KHtzY2FsZTpyLHJvdGF0aW9uOm59KX19XSksdH0odi5QdXJlQ29tcG9uZW50KTt0LkFubm90YXRpb25MYXllckludGVybmFsPUUsRS5wcm9wVHlwZXM9e2xpbmtTZXJ2aWNlOnguaXNMaW5rU2VydmljZS5pc1JlcXVpcmVkLG9uR2V0QW5ub3RhdGlvbnNFcnJvcjpnLmRlZmF1bHQuZnVuYyxvbkdldEFubm90YXRpb25zU3VjY2VzczpnLmRlZmF1bHQuZnVuYyxvblJlbmRlckFubm90YXRpb25MYXllckVycm9yOmcuZGVmYXVsdC5mdW5jLG9uUmVuZGVyQW5ub3RhdGlvbkxheWVyU3VjY2VzczpnLmRlZmF1bHQuZnVuYyxwYWdlOnguaXNQYWdlLHJlbmRlckludGVyYWN0aXZlRm9ybXM6Zy5kZWZhdWx0LmJvb2wscm90YXRlOnguaXNSb3RhdGUsc2NhbGU6Zy5kZWZhdWx0Lm51bWJlcn07dmFyIF89ZnVuY3Rpb24oZSl7cmV0dXJuIHYuZGVmYXVsdC5jcmVhdGVFbGVtZW50KHkuZGVmYXVsdC5Db25zdW1lcixudWxsLChmdW5jdGlvbih0KXtyZXR1cm4gdi5kZWZhdWx0LmNyZWF0ZUVsZW1lbnQoYi5kZWZhdWx0LkNvbnN1bWVyLG51bGwsKGZ1bmN0aW9uKG4pe3JldHVybiB2LmRlZmF1bHQuY3JlYXRlRWxlbWVudChFLCgwLG8uZGVmYXVsdCkoe30sdCxuLGUpKX0pKX0pKX07dC5kZWZhdWx0PV99LGZ1bmN0aW9uKGUsdCl7dmFyIG47bj1mdW5jdGlvbigpe3JldHVybiB0aGlzfSgpO3RyeXtuPW58fG5ldyBGdW5jdGlvbigicmV0dXJuIHRoaXMiKSgpfWNhdGNoKGUpeyJvYmplY3QiPT10eXBlb2Ygd2luZG93JiYobj13aW5kb3cpfWUuZXhwb3J0cz1ufSxmdW5jdGlvbihlLHQsbil7KGZ1bmN0aW9uKHQpeyhmdW5jdGlvbigpe3ZhciBuLHIsYSxvLGksdTsidW5kZWZpbmVkIiE9dHlwZW9mIHBlcmZvcm1hbmNlJiZudWxsIT09cGVyZm9ybWFuY2UmJnBlcmZvcm1hbmNlLm5vdz9lLmV4cG9ydHM9ZnVuY3Rpb24oKXtyZXR1cm4gcGVyZm9ybWFuY2Uubm93KCl9Om51bGwhPXQmJnQuaHJ0aW1lPyhlLmV4cG9ydHM9ZnVuY3Rpb24oKXtyZXR1cm4obigpLWkpLzFlNn0scj10LmhydGltZSxvPShuPWZ1bmN0aW9uKCl7dmFyIGU7cmV0dXJuIDFlOSooZT1yKCkpWzBdK2VbMV19KSgpLHU9MWU5KnQudXB0aW1lKCksaT1vLXUpOkRhdGUubm93PyhlLmV4cG9ydHM9ZnVuY3Rpb24oKXtyZXR1cm4gRGF0ZS5ub3coKS1hfSxhPURhdGUubm93KCkpOihlLmV4cG9ydHM9ZnVuY3Rpb24oKXtyZXR1cm4obmV3IERhdGUpLmdldFRpbWUoKS1hfSxhPShuZXcgRGF0ZSkuZ2V0VGltZSgpKX0pLmNhbGwodGhpcyl9KS5jYWxsKHRoaXMsbig1NykpfSxmdW5jdGlvbihlLHQpe3ZhciBuLHIsYT1lLmV4cG9ydHM9e307ZnVuY3Rpb24gbygpe3Rocm93IG5ldyBFcnJvcigic2V0VGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCIpfWZ1bmN0aW9uIGkoKXt0aHJvdyBuZXcgRXJyb3IoImNsZWFyVGltZW91dCBoYXMgbm90IGJlZW4gZGVmaW5lZCIpfWZ1bmN0aW9uIHUoZSl7aWYobj09PXNldFRpbWVvdXQpcmV0dXJuIHNldFRpbWVvdXQoZSwwKTtpZigobj09PW98fCFuKSYmc2V0VGltZW91dClyZXR1cm4gbj1zZXRUaW1lb3V0LHNldFRpbWVvdXQoZSwwKTt0cnl7cmV0dXJuIG4oZSwwKX1jYXRjaCh0KXt0cnl7cmV0dXJuIG4uY2FsbChudWxsLGUsMCl9Y2F0Y2godCl7cmV0dXJuIG4uY2FsbCh0aGlzLGUsMCl9fX0hZnVuY3Rpb24oKXt0cnl7bj0iZnVuY3Rpb24iPT10eXBlb2Ygc2V0VGltZW91dD9zZXRUaW1lb3V0Om99Y2F0Y2goZSl7bj1vfXRyeXtyPSJmdW5jdGlvbiI9PXR5cGVvZiBjbGVhclRpbWVvdXQ/Y2xlYXJUaW1lb3V0Oml9Y2F0Y2goZSl7cj1pfX0oKTt2YXIgYyxzPVtdLGw9ITEsZj0tMTtmdW5jdGlvbiBkKCl7bCYmYyYmKGw9ITEsYy5sZW5ndGg/cz1jLmNvbmNhdChzKTpmPS0xLHMubGVuZ3RoJiZwKCkpfWZ1bmN0aW9uIHAoKXtpZighbCl7dmFyIGU9dShkKTtsPSEwO2Zvcih2YXIgdD1zLmxlbmd0aDt0Oyl7Zm9yKGM9cyxzPVtdOysrZjx0OyljJiZjW2ZdLnJ1bigpO2Y9LTEsdD1zLmxlbmd0aH1jPW51bGwsbD0hMSxmdW5jdGlvbihlKXtpZihyPT09Y2xlYXJUaW1lb3V0KXJldHVybiBjbGVhclRpbWVvdXQoZSk7aWYoKHI9PT1pfHwhcikmJmNsZWFyVGltZW91dClyZXR1cm4gcj1jbGVhclRpbWVvdXQsY2xlYXJUaW1lb3V0KGUpO3RyeXtyKGUpfWNhdGNoKHQpe3RyeXtyZXR1cm4gci5jYWxsKG51bGwsZSl9Y2F0Y2godCl7cmV0dXJuIHIuY2FsbCh0aGlzLGUpfX19KGUpfX1mdW5jdGlvbiBoKGUsdCl7dGhpcy5mdW49ZSx0aGlzLmFycmF5PXR9ZnVuY3Rpb24gdigpe31hLm5leHRUaWNrPWZ1bmN0aW9uKGUpe3ZhciB0PW5ldyBBcnJheShhcmd1bWVudHMubGVuZ3RoLTEpO2lmKGFyZ3VtZW50cy5sZW5ndGg+MSlmb3IodmFyIG49MTtuPGFyZ3VtZW50cy5sZW5ndGg7bisrKXRbbi0xXT1hcmd1bWVudHNbbl07cy5wdXNoKG5ldyBoKGUsdCkpLDEhPT1zLmxlbmd0aHx8bHx8dShwKX0saC5wcm90b3R5cGUucnVuPWZ1bmN0aW9uKCl7dGhpcy5mdW4uYXBwbHkobnVsbCx0aGlzLmFycmF5KX0sYS50aXRsZT0iYnJvd3NlciIsYS5icm93c2VyPSEwLGEuZW52PXt9LGEuYXJndj1bXSxhLnZlcnNpb249IiIsYS52ZXJzaW9ucz17fSxhLm9uPXYsYS5hZGRMaXN0ZW5lcj12LGEub25jZT12LGEub2ZmPXYsYS5yZW1vdmVMaXN0ZW5lcj12LGEucmVtb3ZlQWxsTGlzdGVuZXJzPXYsYS5lbWl0PXYsYS5wcmVwZW5kTGlzdGVuZXI9dixhLnByZXBlbmRPbmNlTGlzdGVuZXI9dixhLmxpc3RlbmVycz1mdW5jdGlvbihlKXtyZXR1cm5bXX0sYS5iaW5kaW5nPWZ1bmN0aW9uKGUpe3Rocm93IG5ldyBFcnJvcigicHJvY2Vzcy5iaW5kaW5nIGlzIG5vdCBzdXBwb3J0ZWQiKX0sYS5jd2Q9ZnVuY3Rpb24oKXtyZXR1cm4iLyJ9LGEuY2hkaXI9ZnVuY3Rpb24oZSl7dGhyb3cgbmV3IEVycm9yKCJwcm9jZXNzLmNoZGlyIGlzIG5vdCBzdXBwb3J0ZWQiKX0sYS51bWFzaz1mdW5jdGlvbigpe3JldHVybiAwfX0sZnVuY3Rpb24oZSx0LG4pe3ZhciByPW4oNTkpLGE9big2MCk7InN0cmluZyI9PXR5cGVvZihhPWEuX19lc01vZHVsZT9hLmRlZmF1bHQ6YSkmJihhPVtbZS5pLGEsIiJdXSk7dmFyIG89e2luc2VydDoiaGVhZCIsc2luZ2xldG9uOiExfSxpPShyKGUuaSxhLG8pLGEubG9jYWxzP2EubG9jYWxzOnt9KTtlLmV4cG9ydHM9aX0sZnVuY3Rpb24oZSx0LG4peyJ1c2Ugc3RyaWN0Ijt2YXIgcixhPWZ1bmN0aW9uKCl7cmV0dXJuIHZvaWQgMD09PXImJihyPUJvb2xlYW4od2luZG93JiZkb2N1bWVudCYmZG9jdW1lbnQuYWxsJiYhd2luZG93LmF0b2IpKSxyfSxvPWZ1bmN0aW9uKCl7dmFyIGU9e307cmV0dXJuIGZ1bmN0aW9uKHQpe2lmKHZvaWQgMD09PWVbdF0pe3ZhciBuPWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IodCk7aWYod2luZG93LkhUTUxJRnJhbWVFbGVtZW50JiZuIGluc3RhbmNlb2Ygd2luZG93LkhUTUxJRnJhbWVFbGVtZW50KXRyeXtuPW4uY29udGVudERvY3VtZW50LmhlYWR9Y2F0Y2goZSl7bj1udWxsfWVbdF09bn1yZXR1cm4gZVt0XX19KCksaT17fTtmdW5jdGlvbiB1KGUsdCxuKXtmb3IodmFyIHI9MDtyPHQubGVuZ3RoO3IrKyl7dmFyIGE9e2Nzczp0W3JdWzFdLG1lZGlhOnRbcl1bMl0sc291cmNlTWFwOnRbcl1bM119O2lbZV1bcl0/aVtlXVtyXShhKTppW2VdLnB1c2godihhLG4pKX19ZnVuY3Rpb24gYyhlKXt2YXIgdD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJzdHlsZSIpLHI9ZS5hdHRyaWJ1dGVzfHx7fTtpZih2b2lkIDA9PT1yLm5vbmNlKXt2YXIgYT1uLm5jO2EmJihyLm5vbmNlPWEpfWlmKE9iamVjdC5rZXlzKHIpLmZvckVhY2goKGZ1bmN0aW9uKGUpe3Quc2V0QXR0cmlidXRlKGUscltlXSl9KSksImZ1bmN0aW9uIj09dHlwZW9mIGUuaW5zZXJ0KWUuaW5zZXJ0KHQpO2Vsc2V7dmFyIGk9byhlLmluc2VydHx8ImhlYWQiKTtpZighaSl0aHJvdyBuZXcgRXJyb3IoIkNvdWxkbid0IGZpbmQgYSBzdHlsZSB0YXJnZXQuIFRoaXMgcHJvYmFibHkgbWVhbnMgdGhhdCB0aGUgdmFsdWUgZm9yIHRoZSAnaW5zZXJ0JyBwYXJhbWV0ZXIgaXMgaW52YWxpZC4iKTtpLmFwcGVuZENoaWxkKHQpfXJldHVybiB0fXZhciBzLGw9KHM9W10sZnVuY3Rpb24oZSx0KXtyZXR1cm4gc1tlXT10LHMuZmlsdGVyKEJvb2xlYW4pLmpvaW4oIlxuIil9KTtmdW5jdGlvbiBmKGUsdCxuLHIpe3ZhciBhPW4/IiI6ci5jc3M7aWYoZS5zdHlsZVNoZWV0KWUuc3R5bGVTaGVldC5jc3NUZXh0PWwodCxhKTtlbHNle3ZhciBvPWRvY3VtZW50LmNyZWF0ZVRleHROb2RlKGEpLGk9ZS5jaGlsZE5vZGVzO2lbdF0mJmUucmVtb3ZlQ2hpbGQoaVt0XSksaS5sZW5ndGg/ZS5pbnNlcnRCZWZvcmUobyxpW3RdKTplLmFwcGVuZENoaWxkKG8pfX1mdW5jdGlvbiBkKGUsdCxuKXt2YXIgcj1uLmNzcyxhPW4ubWVkaWEsbz1uLnNvdXJjZU1hcDtpZihhP2Uuc2V0QXR0cmlidXRlKCJtZWRpYSIsYSk6ZS5yZW1vdmVBdHRyaWJ1dGUoIm1lZGlhIiksbyYmYnRvYSYmKHIrPSJcbi8qIyBzb3VyY2VNYXBwaW5nVVJMPWRhdGE6YXBwbGljYXRpb24vanNvbjtiYXNlNjQsIi5jb25jYXQoYnRvYSh1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkobykpKSksIiAqLyIpKSxlLnN0eWxlU2hlZXQpZS5zdHlsZVNoZWV0LmNzc1RleHQ9cjtlbHNle2Zvcig7ZS5maXJzdENoaWxkOyllLnJlbW92ZUNoaWxkKGUuZmlyc3RDaGlsZCk7ZS5hcHBlbmRDaGlsZChkb2N1bWVudC5jcmVhdGVUZXh0Tm9kZShyKSl9fXZhciBwPW51bGwsaD0wO2Z1bmN0aW9uIHYoZSx0KXt2YXIgbixyLGE7aWYodC5zaW5nbGV0b24pe3ZhciBvPWgrKztuPXB8fChwPWModCkpLHI9Zi5iaW5kKG51bGwsbixvLCExKSxhPWYuYmluZChudWxsLG4sbywhMCl9ZWxzZSBuPWModCkscj1kLmJpbmQobnVsbCxuLHQpLGE9ZnVuY3Rpb24oKXshZnVuY3Rpb24oZSl7aWYobnVsbD09PWUucGFyZW50Tm9kZSlyZXR1cm4hMTtlLnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQoZSl9KG4pfTtyZXR1cm4gcihlKSxmdW5jdGlvbih0KXtpZih0KXtpZih0LmNzcz09PWUuY3NzJiZ0Lm1lZGlhPT09ZS5tZWRpYSYmdC5zb3VyY2VNYXA9PT1lLnNvdXJjZU1hcClyZXR1cm47cihlPXQpfWVsc2UgYSgpfX1lLmV4cG9ydHM9ZnVuY3Rpb24oZSx0LG4pe3JldHVybihuPW58fHt9KS5zaW5nbGV0b258fCJib29sZWFuIj09dHlwZW9mIG4uc2luZ2xldG9ufHwobi5zaW5nbGV0b249YSgpKSxlPW4uYmFzZT9lK24uYmFzZTplLHQ9dHx8W10saVtlXXx8KGlbZV09W10pLHUoZSx0LG4pLGZ1bmN0aW9uKHQpe2lmKHQ9dHx8W10sIltvYmplY3QgQXJyYXldIj09PU9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbCh0KSl7aVtlXXx8KGlbZV09W10pLHUoZSx0LG4pO2Zvcih2YXIgcj10Lmxlbmd0aDtyPGlbZV0ubGVuZ3RoO3IrKylpW2VdW3JdKCk7aVtlXS5sZW5ndGg9dC5sZW5ndGgsMD09PWlbZV0ubGVuZ3RoJiZkZWxldGUgaVtlXX19fX0sZnVuY3Rpb24oZSx0LG4peyh0PW4oNjEpKCExKSkucHVzaChbZS5pLCJib2R5IHtcbiAgbWFyZ2luOiAwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNTI1NjU5O1xuICBjb2xvcjogI2ZmZjtcbiAgZm9udC1mYW1pbHk6IEhlbHZldGljYSwgQXJpYWwsIHNhbnMtc2VyaWY7XG59XG4uUmVhZGVyIHtcbiAgaGVpZ2h0OiAxMDB2aDtcbn1cbi5SZWFkZXJfX2NvbnRhaW5lcl9fbnVtYmVycyB7XG4gIHBvc2l0aW9uOiBmaXhlZDtcbiAgdG9wOiAwcHg7XG4gIHdpZHRoOiAxMDAlO1xuICBtYXJnaW46IGF1dG87XG4gIHBhZGRpbmc6IDVweDtcbiAgYmFja2dyb3VuZC1jb2xvcjogIzU2NTc1OTtcbiAgei1pbmRleDogMTAwO1xufVxuLlJlYWRlcl9fY29udGFpbmVyX19udW1iZXJzX19jb250ZW50IHtcbiAgZm9udC1zaXplOiAwLjY1cmVtO1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG4gIHBhZGRpbmc6IDVweDtcbiAgYm9yZGVyLXJhZGl1czogNHB4O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDI1NSwgMjU1LCAyNTUsIDAuMTQ0KTtcbiAgd2lkdGg6IDUwcHg7XG4gIG1hcmdpbjogYXV0bztcbn1cbi5SZWFkZXJfX2NvbnRhaW5lcl9fbmF2aWdhdGUge1xuICBwb3NpdGlvbjogZml4ZWQ7XG4gIGJvdHRvbTogMHB4O1xuICB3aWR0aDogMTAwJTtcbiAgbWFyZ2luOiBhdXRvO1xuICBkaXNwbGF5OiBmbGV4O1xuICBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWFyb3VuZDtcbiAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgei1pbmRleDogMTAwO1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjNDA1YTY1O1xufVxuLlJlYWRlcl9fY29udGFpbmVyX19uYXZpZ2F0ZV9fYXJyb3cge1xuICBmb250LXNpemU6IDIuNWVtO1xuICBtYXJnaW46IDEwcHg7XG4gIHdpZHRoOiAxMDBweDtcbiAgbWFyZ2luOiBhdXRvO1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG59XG4uUmVhZGVyX19jb250YWluZXJfX3pvb21fY29udGFpbmVyIHtcbiAgcG9zaXRpb246IGZpeGVkO1xuICBib3R0b206IDYwcHg7XG4gIHJpZ2h0OiAxNXB4O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiByZ2JhKDAsIDAsIDAsIDAuOSk7XG4gIHotaW5kZXg6IDEwMTtcbiAgZmxleDogMTtcbiAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG59XG4uUmVhZGVyX19jb250YWluZXJfX3pvb21fY29udGFpbmVyX19idXR0b24ge1xuICBmb250LXNpemU6IDIuNWVtO1xuICBtYXJnaW46IDU7XG4gIHdpZHRoOiA1MHB4O1xuICB0ZXh0LWFsaWduOiBjZW50ZXI7XG59XG4uUmVhZGVyX19jb250YWluZXJfX2xvYWQge1xuICBtYXJnaW4tdG9wOiAxZW07XG4gIGNvbG9yOiB3aGl0ZTtcbn1cbi5SZWFkZXJfX2NvbnRhaW5lcl9fZG9jdW1lbnQge1xuICBtYXJnaW46IGF1dG87XG4gIHBhZGRpbmctdG9wOiA0MHB4O1xuICBwYWRkaW5nLWJvdHRvbTogNTBweDtcbn1cbi5SZWFkZXJfX2NvbnRhaW5lcl9fZG9jdW1lbnQgLnJlYWN0LXBkZl9fRG9jdW1lbnQgc3BhbiB7XG4gIGRpc3BsYXk6IGZsZXg7XG4gIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG59XG4uUmVhZGVyX19jb250YWluZXJfX2RvY3VtZW50IC5yZWFjdC1wZGZfX1BhZ2Uge1xuICBkaXNwbGF5OiBibG9jaztcbn1cbi5SZWFkZXJfX2NvbnRhaW5lcl9fZG9jdW1lbnQgLnJlYWN0LXBkZl9fUGFnZSBjYW52YXMge1xuICBtYXJnaW46IGF1dG87XG59XG4uUmVhZGVyX19jb250YWluZXJfX2RvY3VtZW50IC5yZWFjdC1wZGZfX1BhZ2VfX2Fubm90YXRpb25zIHtcbiAgZGlzcGxheTogbm9uZTtcbn1cbiIsIiJdKSxlLmV4cG9ydHM9dH0sZnVuY3Rpb24oZSx0LG4peyJ1c2Ugc3RyaWN0IjtlLmV4cG9ydHM9ZnVuY3Rpb24oZSl7dmFyIHQ9W107cmV0dXJuIHQudG9TdHJpbmc9ZnVuY3Rpb24oKXtyZXR1cm4gdGhpcy5tYXAoKGZ1bmN0aW9uKHQpe3ZhciBuPWZ1bmN0aW9uKGUsdCl7dmFyIG49ZVsxXXx8IiIscj1lWzNdO2lmKCFyKXJldHVybiBuO2lmKHQmJiJmdW5jdGlvbiI9PXR5cGVvZiBidG9hKXt2YXIgYT0oaT1yLHU9YnRvYSh1bmVzY2FwZShlbmNvZGVVUklDb21wb25lbnQoSlNPTi5zdHJpbmdpZnkoaSkpKSksYz0ic291cmNlTWFwcGluZ1VSTD1kYXRhOmFwcGxpY2F0aW9uL2pzb247Y2hhcnNldD11dGYtODtiYXNlNjQsIi5jb25jYXQodSksIi8qIyAiLmNvbmNhdChjLCIgKi8iKSksbz1yLnNvdXJjZXMubWFwKChmdW5jdGlvbihlKXtyZXR1cm4iLyojIHNvdXJjZVVSTD0iLmNvbmNhdChyLnNvdXJjZVJvb3R8fCIiKS5jb25jYXQoZSwiICovIil9KSk7cmV0dXJuW25dLmNvbmNhdChvKS5jb25jYXQoW2FdKS5qb2luKCJcbiIpfXZhciBpLHUsYztyZXR1cm5bbl0uam9pbigiXG4iKX0odCxlKTtyZXR1cm4gdFsyXT8iQG1lZGlhICIuY29uY2F0KHRbMl0sIiB7IikuY29uY2F0KG4sIn0iKTpufSkpLmpvaW4oIiIpfSx0Lmk9ZnVuY3Rpb24oZSxuKXsic3RyaW5nIj09dHlwZW9mIGUmJihlPVtbbnVsbCxlLCIiXV0pO2Zvcih2YXIgcj0wO3I8ZS5sZW5ndGg7cisrKXt2YXIgYT1bXS5jb25jYXQoZVtyXSk7biYmKGFbMl0/YVsyXT0iIi5jb25jYXQobiwiIGFuZCAiKS5jb25jYXQoYVsyXSk6YVsyXT1uKSx0LnB1c2goYSl9fSx0fX0sZnVuY3Rpb24oZSx0LG4peyJ1c2Ugc3RyaWN0IjtuLnIodCk7dmFyIHI9bigwKSxhPW4oMjcpLG89bigyOCksaT1uLm4obyksdT1uKDI5KSxjPW4ubih1KSxzPW4oMTQpLGw9bi5uKHMpLGY9KCk9PnIuY3JlYXRlRWxlbWVudCgic3ZnIix7eG1sbnM6Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIix3aWR0aDoiMjQiLGhlaWdodDoiMjQiLHZpZXdCb3g6IjAgMCAyNCAyNCIsZmlsbDoibm9uZSIsc3Ryb2tlOiJjdXJyZW50Q29sb3IiLHN0cm9rZVdpZHRoOiIyIixzdHJva2VMaW5lY2FwOiJyb3VuZCIsc3Ryb2tlTGluZWpvaW46InJvdW5kIixjbGFzc05hbWU6ImZlYXRoZXIgZmVhdGhlci1hcnJvdy1kb3duIn0sci5jcmVhdGVFbGVtZW50KCJsaW5lIix7eDE6IjEyIix5MToiNSIseDI6IjEyIix5MjoiMTkifSksci5jcmVhdGVFbGVtZW50KCJwb2x5bGluZSIse3BvaW50czoiMTkgMTIgMTIgMTkgNSAxMiJ9KSksZD0oKT0+ci5jcmVhdGVFbGVtZW50KCJzdmciLHt4bWxuczoiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLHdpZHRoOiIyNCIsaGVpZ2h0OiIyNCIsdmlld0JveDoiMCAwIDI0IDI0IixmaWxsOiJub25lIixzdHJva2U6ImN1cnJlbnRDb2xvciIsc3Ryb2tlV2lkdGg6IjIiLHN0cm9rZUxpbmVjYXA6InJvdW5kIixzdHJva2VMaW5lam9pbjoicm91bmQiLGNsYXNzTmFtZToiIn0sci5jcmVhdGVFbGVtZW50KCJwb2x5bGluZSIse3BvaW50czoiNSAxMiAxOSAxMiJ9KSxyLmNyZWF0ZUVsZW1lbnQoInBvbHlsaW5lIix7cG9pbnRzOiIxMiA1IDEyIDE5In0pKSxwPSgpPT5yLmNyZWF0ZUVsZW1lbnQoInN2ZyIse3htbG5zOiJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIsd2lkdGg6IjI0IixoZWlnaHQ6IjI0Iix2aWV3Qm94OiIwIDAgMjQgMjQiLGZpbGw6Im5vbmUiLHN0cm9rZToiY3VycmVudENvbG9yIixzdHJva2VXaWR0aDoiMiIsc3Ryb2tlTGluZWNhcDoicm91bmQiLHN0cm9rZUxpbmVqb2luOiJyb3VuZCIsY2xhc3NOYW1lOiIifSxyLmNyZWF0ZUVsZW1lbnQoImxpbmUiLHt4MToiNSIseTE6IjEyIix4MjoiMTkiLHkyOiIxMiJ9KSksaD0oKT0+ci5jcmVhdGVFbGVtZW50KCJzdmciLHt4bWxuczoiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciLHdpZHRoOiIyNCIsaGVpZ2h0OiIyNCIsdmlld0JveDoiMCAwIDI0IDI0IixmaWxsOiJub25lIixzdHJva2U6ImN1cnJlbnRDb2xvciIsc3Ryb2tlV2lkdGg6IjIiLHN0cm9rZUxpbmVjYXA6InJvdW5kIixzdHJva2VMaW5lam9pbjoicm91bmQiLGNsYXNzTmFtZToiZmVhdGhlciBmZWF0aGVyLWFycm93LXVwIn0sci5jcmVhdGVFbGVtZW50KCJsaW5lIix7eDE6IjEyIix5MToiMTkiLHgyOiIxMiIseTI6IjUifSksci5jcmVhdGVFbGVtZW50KCJwb2x5bGluZSIse3BvaW50czoiNSAxMiAxMiA1IDE5IDEyIn0pKTtuKDU4KTtjb25zdCB2PWRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoIiNyZWFjdC1jb250YWluZXIiKSxnPXtjTWFwVXJsOiIvL2Nkbi5qc2RlbGl2ci5uZXQvbnBtL3BkZmpzLWRpc3RAMi4xLjI2Ni9jbWFwcy8iLGNNYXBQYWNrZWQ6ITB9O2NsYXNzIG0gZXh0ZW5kcyByLkNvbXBvbmVudHtjb25zdHJ1Y3Rvcigpe3N1cGVyKC4uLmFyZ3VtZW50cyksdGhpcy5zdGF0ZT17bnVtUGFnZXM6bnVsbCxjdXJyZW50UGFnZToxLHJlYWR5OiEwLHBhZ2VMb2FkZWQ6ITEsc2NhbGU6MSxlcnJvcjp2b2lkIDB9LHRoaXMuTUFYX1NDQUxFPTQsdGhpcy5fX3pvb21FdmVudD0hMSx0aGlzLm9uRG9jdW1lbnRMb2FkU3VjY2Vzcz0oe251bVBhZ2VzOmV9KT0+e3RoaXMuc2V0U3RhdGUoe251bVBhZ2VzOmV9KX0sdGhpcy5vbkVycm9yPWU9Pntjb25zb2xlLmVycm9yKGUpLHRoaXMuc2V0U3RhdGUoe2Vycm9yOmV9KX0sdGhpcy56b29tT3V0PWU9PntlLnByZXZlbnREZWZhdWx0KCksdGhpcy5fX3pvb21FdmVudHx8bCgpKHRoaXMuek91dCl9LHRoaXMuem9vbUluPWU9PntlLnByZXZlbnREZWZhdWx0KCksdGhpcy5fX3pvb21FdmVudHx8bCgpKHRoaXMuekluKX0sdGhpcy56SW49KCk9Pnt0aGlzLnN0YXRlLnNjYWxlPD10aGlzLk1BWF9TQ0FMRS0uMjUmJih0aGlzLl9fem9vbUV2ZW50PSEwLHRoaXMuc2V0U3RhdGUoZT0+KHtzY2FsZTplLnNjYWxlKy4yNX0pKSl9LHRoaXMuek91dD0oKT0+e3RoaXMuc3RhdGUuc2NhbGU+PS43NSYmKHRoaXMuX196b29tRXZlbnQ9ITAsdGhpcy5zZXRTdGF0ZShlPT4oe3NjYWxlOmUuc2NhbGUtLjI1fSkpKX0sdGhpcy51cD0oKT0+e2NvbnN0e2N1cnJlbnRQYWdlOmV9PXRoaXMuc3RhdGU7aWYoZT4xKXtjb25zdCB0PWUtMTt0aGlzLnNldFN0YXRlKHtjdXJyZW50UGFnZTp0fSl9T2JqZWN0KHMuY2FuY2VsKSh0aGlzLnVwKX0sdGhpcy5kb3duPSgpPT57Y29uc3R7Y3VycmVudFBhZ2U6ZSxudW1QYWdlczp0fT10aGlzLnN0YXRlO2lmKGU8dCl7Y29uc3QgdD1lKzE7dGhpcy5zZXRTdGF0ZSh7Y3VycmVudFBhZ2U6dH0pfU9iamVjdChzLmNhbmNlbCkodGhpcy5kb3duKX0sdGhpcy5nb1VwPWU9PntlLnByZXZlbnREZWZhdWx0KCksbCgpKHRoaXMudXApfSx0aGlzLmdvRG93bj1lPT57ZS5wcmV2ZW50RGVmYXVsdCgpLGwoKSh0aGlzLmRvd24pfSx0aGlzLnJlbmRlclBhZ2U9ZT0+ci5jcmVhdGVFbGVtZW50KGMuYSx7bG9hZGluZzoiICIsa2V5OmBwYWdlXyR7ZX1gLHBhZ2VOdW1iZXI6ZSxvbkxvYWRFcnJvcjp0aGlzLm9uRXJyb3Isb25SZW5kZXJFcnJvcjp0aGlzLm9uRXJyb3Isb25HZXRUZXh0RXJyb3I6dGhpcy5vbkVycm9yLG9uR2V0QW5ub3RhdGlvbnNFcnJvcjp0aGlzLm9uRXJyb3Isd2lkdGg6OTAqZG9jdW1lbnQuYm9keS5jbGllbnRXaWR0aC8xMDAsb25SZW5kZXJTdWNjZXNzOigpPT57dGhpcy5fX3pvb21FdmVudD0hMX0sc2NhbGU6dGhpcy5zdGF0ZS5zY2FsZX0pLHRoaXMucmVuZGVyUGFnZXM9KCk9PkFycmF5LmZyb20oQXJyYXkodGhpcy5zdGF0ZS5udW1QYWdlcykua2V5cygpKS5tYXAoZT0+ci5jcmVhdGVFbGVtZW50KCJkaXYiLHtrZXk6YHBhZ2UtJHtlLnRvU3RyaW5nKCl9YCxzdHlsZTp7bWFyZ2luQm90dG9tOjEwfX0sdGhpcy5yZW5kZXJQYWdlKGUrMSkpKX1zdGF0aWMgZ2V0RGVyaXZlZFN0YXRlRnJvbUVycm9yKGUpe3JldHVybntlcnJvcjplfX1yZW5kZXIoKXt2YXIgZSx0LG4sYSxvLHUsYyxzLGwsdjtjb25zdHtudW1QYWdlczptLGN1cnJlbnRQYWdlOmIsZXJyb3I6eH09dGhpcy5zdGF0ZSx7Y3VzdG9tU3R5bGU6RX09dGhpcy5wcm9wcztyZXR1cm4geD9yLmNyZWF0ZUVsZW1lbnQoInAiLG51bGwseC5tZXNzYWdlP3gubWVzc2FnZToiU29ycnkgYW4gZXJyb3Igb2NjdXJyZWQhIik6ci5jcmVhdGVFbGVtZW50KCJkaXYiLHtjbGFzc05hbWU6IlJlYWRlciJ9LHIuY3JlYXRlRWxlbWVudCgiZGl2Iix7Y2xhc3NOYW1lOiJSZWFkZXJfX2NvbnRhaW5lciIsc3R5bGU6bnVsbD09PShlPUUpfHx2b2lkIDA9PT1lP3ZvaWQgMDplLnJlYWRlckNvbnRhaW5lcn0sci5jcmVhdGVFbGVtZW50KCJkaXYiLHtjbGFzc05hbWU6IlJlYWRlcl9fY29udGFpbmVyX19kb2N1bWVudCIsc3R5bGU6bnVsbD09PSh0PUUpfHx2b2lkIDA9PT10P3ZvaWQgMDp0LnJlYWRlckNvbnRhaW5lckRvY3VtZW50fSxyLmNyZWF0ZUVsZW1lbnQoaS5hLE9iamVjdC5hc3NpZ24oe2xvYWRpbmc6IiAiLG9uTG9hZFN1Y2Nlc3M6dGhpcy5vbkRvY3VtZW50TG9hZFN1Y2Nlc3Msb25Mb2FkRXJyb3I6dGhpcy5vbkVycm9yLG9uU291cmNlRXJyb3I6dGhpcy5vbkVycm9yfSx7b3B0aW9uczpnLGZpbGU6eX0pLHc/dGhpcy5yZW5kZXJQYWdlcygpOnRoaXMucmVuZGVyUGFnZShiKSkpLG0mJiF3JiZyLmNyZWF0ZUVsZW1lbnQoImRpdiIse2NsYXNzTmFtZToiUmVhZGVyX19jb250YWluZXJfX251bWJlcnMiLHN0eWxlOm51bGw9PT0obj1FKXx8dm9pZCAwPT09bj92b2lkIDA6bi5yZWFkZXJDb250YWluZXJOdW1iZXJzfSxyLmNyZWF0ZUVsZW1lbnQoImRpdiIse2NsYXNzTmFtZToiUmVhZGVyX19jb250YWluZXJfX251bWJlcnNfX2NvbnRlbnQiLHN0eWxlOm51bGw9PT0oYT1FKXx8dm9pZCAwPT09YT92b2lkIDA6YS5yZWFkZXJDb250YWluZXJOdW1iZXJzQ29udGVudH0sYiwiIC8gIixtKSksci5jcmVhdGVFbGVtZW50KCJkaXYiLHtjbGFzc05hbWU6IlJlYWRlcl9fY29udGFpbmVyX196b29tX2NvbnRhaW5lciIsc3R5bGU6bnVsbD09PShvPUUpfHx2b2lkIDA9PT1vP3ZvaWQgMDpvLnJlYWRlckNvbnRhaW5lclpvb21Db250YWluZXJ9LHIuY3JlYXRlRWxlbWVudCgiZGl2Iix7Y2xhc3NOYW1lOiJSZWFkZXJfX2NvbnRhaW5lcl9fem9vbV9jb250YWluZXJfX2J1dHRvbiIsc3R5bGU6bnVsbD09PSh1PUUpfHx2b2lkIDA9PT11P3ZvaWQgMDp1LnJlYWRlckNvbnRhaW5lclpvb21Db250YWluZXJCdXR0b24sb25DbGljazp0aGlzLnpvb21Jbn0sci5jcmVhdGVFbGVtZW50KGQsbnVsbCkpLHIuY3JlYXRlRWxlbWVudCgiZGl2Iix7Y2xhc3NOYW1lOiJSZWFkZXJfX2NvbnRhaW5lcl9fem9vbV9jb250YWluZXJfX2J1dHRvbiIsc3R5bGU6bnVsbD09PShjPUUpfHx2b2lkIDA9PT1jP3ZvaWQgMDpjLnJlYWRlckNvbnRhaW5lclpvb21Db250YWluZXJCdXR0b24sb25DbGljazp0aGlzLnpvb21PdXR9LHIuY3JlYXRlRWxlbWVudChwLG51bGwpKSksbT4xJiYhdyYmci5jcmVhdGVFbGVtZW50KCJkaXYiLHtjbGFzc05hbWU6IlJlYWRlcl9fY29udGFpbmVyX19uYXZpZ2F0ZSIsc3R5bGU6bnVsbD09PShzPUUpfHx2b2lkIDA9PT1zP3ZvaWQgMDpzLnJlYWRlckNvbnRhaW5lck5hdmlnYXRlfSxyLmNyZWF0ZUVsZW1lbnQoImRpdiIse2NsYXNzTmFtZToiUmVhZGVyX19jb250YWluZXJfX25hdmlnYXRlX19hcnJvdyIsc3R5bGU6T2JqZWN0LmFzc2lnbihPYmplY3QuYXNzaWduKHt9LDE9PT1iP3tjb2xvcjoicmdiYSgyNTUsMjU1LDI1NSwwLjQpIn06e30pLG51bGw9PT0obD1FKXx8dm9pZCAwPT09bD92b2lkIDA6bC5yZWFkZXJDb250YWluZXJOYXZpZ2F0ZUFycm93KSxvbkNsaWNrOnRoaXMuZ29VcH0sci5jcmVhdGVFbGVtZW50KGgsbnVsbCkpLHIuY3JlYXRlRWxlbWVudCgiZGl2Iix7Y2xhc3NOYW1lOiJSZWFkZXJfX2NvbnRhaW5lcl9fbmF2aWdhdGVfX2Fycm93IixzdHlsZTpPYmplY3QuYXNzaWduKE9iamVjdC5hc3NpZ24oe30sYj09PW0/e2NvbG9yOiJyZ2JhKDI1NSwyNTUsMjU1LDAuNCkifTp7fSksbnVsbD09PSh2PUUpfHx2b2lkIDA9PT12P3ZvaWQgMDp2LnJlYWRlckNvbnRhaW5lck5hdmlnYXRlQXJyb3cpLG9uQ2xpY2s6dGhpcy5nb0Rvd259LHIuY3JlYXRlRWxlbWVudChmLG51bGwpKSkpKX19Y29uc3QgeT1kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCIjZmlsZSIpLmdldEF0dHJpYnV0ZSgiZGF0YS1maWxlIiksYj13aW5kb3cuQ1VTVE9NX1NUWUxFLHc9d2luZG93LldJVEhfU0NST0xMO09iamVjdChhLnJlbmRlcikoci5jcmVhdGVFbGVtZW50KG0sT2JqZWN0LmFzc2lnbih7fSx7ZmlsZTp5LGN1c3RvbVN0eWxlOmIsd2l0aFNjcm9sbDp3fSkpLHYpfV0pOw==';
export function getBundle() {
return Base64.decode(bundle);
}
export function getBundleMd5() {
return 'd8beb4926a47d917200dd2d1bdc77595';
}
import * as React from 'react';
import { View, ActivityIndicator, Platform, StyleSheet } from 'react-native';
import { WebView } from 'react-native-webview';
import * as FileSystem from 'expo-file-system';
const { cacheDirectory, writeAsStringAsync, deleteAsync, getInfoAsync, EncodingType, } = FileSystem;
function viewerHtml(base64, customStyle, withScroll = false, withPinchZoom = false, maximumPinchZoomScale = 5) {
return `
<!DOCTYPE html>
<html>
<head>
<title>PDF reader</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, maximum-scale=${withPinchZoom ? `${maximumPinchZoomScale}.0` : '1.0'}, user-scalable=${withPinchZoom ? 'yes' : 'no'}" />
<script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@2.1.266/build/pdf.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pdfjs-dist@2.1.266/web/pdf_viewer.min.js"></script>
<script
crossorigin
src="https://unpkg.com/react@16/umd/react.production.min.js"
></script>
<script
crossorigin
src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"
></script>
<script>
pdfjsLib.GlobalWorkerOptions.workerSrc =
'https://cdn.jsdelivr.net/npm/pdfjs-dist@2.1.266/build/pdf.worker.min.js'
</script>
<script type="application/javascript">
try {
window.CUSTOM_STYLE = JSON.parse('${JSON.stringify((customStyle !== null && customStyle !== void 0 ? customStyle : {}))}');
} catch (error) {
window.CUSTOM_STYLE = {}
}
try {
window.WITH_SCROLL = JSON.parse('${JSON.stringify(withScroll)}');
} catch (error) {
window.WITH_SCROLL = {}
}
</script>
</head>
<body>
<div id="file" data-file="${base64}"></div>
<div id="react-container"></div>
<script type="text/javascript" src="bundle.js"></script>
</body>
</html>
`;
}
const bundleJsPath = `${cacheDirectory}bundle.js`;
const htmlPath = `${cacheDirectory}index.html`;
const pdfPath = `${cacheDirectory}file.pdf`;
async function writeWebViewReaderFileAsync(data, customStyle, withScroll, withPinchZoom, maximumPinchZoomScale) {
const { exists, md5 } = await getInfoAsync(bundleJsPath, { md5: true });
const bundleContainer = require('./bundleContainer');
if (__DEV__ || !exists || bundleContainer.getBundleMd5() !== md5) {
await writeAsStringAsync(bundleJsPath, bundleContainer.getBundle());
}
await writeAsStringAsync(htmlPath, viewerHtml(data, customStyle, withScroll, withPinchZoom, maximumPinchZoomScale));
}
async function writePDFAsync(base64) {
await writeAsStringAsync(pdfPath, base64.replace('data:application/pdf;base64,', ''), { encoding: EncodingType.Base64 });
}
export async function removeFilesAsync() {
const { exists: htmlPathExist } = await getInfoAsync(htmlPath);
if (htmlPathExist) {
await deleteAsync(htmlPath, { idempotent: true });
}
const { exists: pdfPathExist } = await getInfoAsync(pdfPath);
if (pdfPathExist) {
await deleteAsync(pdfPath, { idempotent: true });
}
}
function readAsTextAsync(mediaBlob) {
return new Promise((resolve, reject) => {
try {
const reader = new FileReader();
reader.onloadend = (_e) => {
if (typeof reader.result === 'string') {
return resolve(reader.result);
}
return reject(`Unable to get result of file due to bad type, waiting string and getting ${typeof reader.result}.`);
};
reader.readAsDataURL(mediaBlob);
}
catch (error) {
reject(error);
}
});
}
async function fetchPdfAsync(source) {
const mediaBlob = await urlToBlob(source);
if (mediaBlob) {
return readAsTextAsync(mediaBlob);
}
return undefined;
}
async function urlToBlob(source) {
if (!source.uri) {
return undefined;
}
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onerror = reject;
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
resolve(xhr.response);
}
};
xhr.open('GET', source.uri);
if (source.headers && Object.keys(source.headers).length > 0) {
Object.keys(source.headers).forEach((key) => {
xhr.setRequestHeader(key, source.headers[key]);
});
}
xhr.responseType = 'blob';
xhr.send();
});
}
const getGoogleReaderUrl = (url) => `https://docs.google.com/viewer?url=${url}`;
const Loader = () => (React.createElement(View, { style: {
...StyleSheet.absoluteFillObject,
justifyContent: 'center',
alignItems: 'center',
} },
React.createElement(ActivityIndicator, { size: 'large' })));
class PdfReader extends React.Component {
constructor() {
super(...arguments);
this.state = {
renderType: undefined,
ready: false,
data: undefined,
renderedOnce: false,
};
this.validate = () => {
const { onError: propOnError, source } = this.props;
const { renderType } = this.state;
const onError = propOnError !== undefined ? propOnError : console.error;
if (!renderType || !source) {
onError('source is undefined');
}
else if ((renderType === 'DIRECT_URL' ||
renderType === 'GOOGLE_READER' ||
renderType === 'URL_TO_BASE64') &&
(!source.uri ||
!(source.uri.startsWith('http') ||
source.uri.startsWith('file') ||
source.uri.startsWith('content')))) {
onError(`source.uri is undefined or not started with http, file or content source.uri = ${source.uri}`);
}
else if ((renderType === 'BASE64_TO_LOCAL_PDF' ||
renderType === 'DIRECT_BASE64') &&
(!source.base64 ||
!source.base64.startsWith('data:application/pdf;base64,'))) {
onError('Base64 is not correct (ie. start with data:application/pdf;base64,)');
}
};
this.init = async () => {
try {
const { source, customStyle, withScroll, withPinchZoom, maximumPinchZoomScale, } = this.props;
const { renderType } = this.state;
switch (renderType) {
case 'URL_TO_BASE64': {
const data = await fetchPdfAsync(source);
await writeWebViewReaderFileAsync(data, customStyle, withScroll, withPinchZoom, maximumPinchZoomScale);
break;
}
case 'DIRECT_BASE64': {
await writeWebViewReaderFileAsync(source.base64, customStyle, withScroll, withPinchZoom, maximumPinchZoomScale);
break;
}
case 'BASE64_TO_LOCAL_PDF': {
await writePDFAsync(source.base64);
break;
}
default:
break;
}
this.setState({ ready: true });
}
catch (error) {
alert(`Sorry, an error occurred. ${error.message}`);
console.error(error);
}
};
this.getRenderType = () => {
const { useGoogleReader, source: { uri, base64 }, } = this.props;
if (useGoogleReader) {
return 'GOOGLE_READER';
}
if (Platform.OS === 'ios') {
if (uri !== undefined) {
return 'DIRECT_URL';
}
if (base64 !== undefined) {
return 'BASE64_TO_LOCAL_PDF';
}
}
if (base64 !== undefined) {
return 'DIRECT_BASE64';
}
if (uri !== undefined) {
return 'URL_TO_BASE64';
}
return undefined;
};
this.getWebviewSource = () => {
const { renderType } = this.state;
const { source: { uri, headers }, onError, } = this.props;
switch (renderType) {
case 'GOOGLE_READER':
return { uri: getGoogleReaderUrl(uri) };
case 'DIRECT_BASE64':
case 'URL_TO_BASE64':
return { uri: htmlPath };
case 'DIRECT_URL':
return { uri: uri, headers };
case 'BASE64_TO_LOCAL_PDF':
return { uri: pdfPath };
default: {
onError('Unknown RenderType');
return undefined;
}
}
};
}
componentDidMount() {
this.setState({ renderType: this.getRenderType() }, () => {
console.debug(this.state.renderType);
this.validate();
this.init();
});
}
componentDidUpdate(prevProps) {
if (prevProps.source.uri !== this.props.source.uri ||
prevProps.source.base64 !== this.props.source.base64) {
this.setState({ ready: false, renderType: this.getRenderType() });
this.validate();
this.init();
}
}
componentWillUnmount() {
const { renderType } = this.state;
if (renderType === 'DIRECT_BASE64' ||
renderType === 'URL_TO_BASE64' ||
renderType === 'BASE64_TO_LOCAL_PDF') {
try {
removeFilesAsync();
}
catch (error) {
alert(`Error on removing file. ${error.message}`);
console.error(error);
}
}
}
render() {
const { ready, renderedOnce } = this.state;
const { style: containerStyle, webviewStyle, onLoad, noLoader, onLoadEnd, onError, webviewProps, } = this.props;
const originWhitelist = [
'http://*',
'https://*',
'file://*',
'data:*',
'content:*',
];
const style = [styles.webview, webviewStyle];
const isAndroid = Platform.OS === 'android';
if (ready) {
const source = this.getWebviewSource();
return (React.createElement(View, { style: [styles.container, containerStyle] },
React.createElement(WebView, Object.assign({}, {
originWhitelist,
onLoad: (event) => {
console.log('renderedOnce', )
this.setState({ renderedOnce: true });
if (onLoad) {
onLoad(event);
}
},
onLoadEnd,
onError,
onHttpError: onError,
style,
source: renderedOnce || !isAndroid ? source : { uri: undefined },
}, { allowFileAccess: isAndroid, allowFileAccessFromFileURLs: isAndroid, allowUniversalAccessFromFileURLs: isAndroid, scalesPageToFit: Platform.select({ android: false }), mixedContentMode: isAndroid ? 'always' : undefined, sharedCookiesEnabled: false, startInLoadingState: !noLoader, renderLoading: () => (noLoader ? React.createElement(View, null) : React.createElement(Loader, null)) }, webviewProps))));
}
return !noLoader && !ready && React.createElement(Loader, null);
}
}
PdfReader.defaultProps = {
withScroll: false,
noLoader: false,
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
webview: {
flex: 1,
},
});
export default PdfReader;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment