Tshas1 / Capstone

Capstone project

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Capstone

Capstone project

<title>Next Word Prediction App</title> <script type="text/javascript"> var SLIDE_CONFIG = { // Slide settings settings: { title: 'Next Word Prediction App', useBuilds: true, usePrettify: true, enableSlideAreas: true, enableTouch: true, }, // Author information presenters: [ { name: 'Amber Wang' , company: '', gplus: '', twitter: '', www: '', github: '' }, ] }; </script> <script src="data:application/x-javascript;base64,LyogTW9kZXJuaXpyIDIuNS4zIChDdXN0b20gQnVpbGQpIHwgTUlUICYgQlNECiAqIEJ1aWxkOiBodHRwOi8vd3d3Lm1vZGVybml6ci5jb20vZG93bmxvYWQvIy1mb250ZmFjZS1iYWNrZ3JvdW5kc2l6ZS1ib3JkZXJpbWFnZS1ib3JkZXJyYWRpdXMtYm94c2hhZG93LWZsZXhib3gtZmxleGJveF9sZWdhY3ktaHNsYS1tdWx0aXBsZWJncy1vcGFjaXR5LXJnYmEtdGV4dHNoYWRvdy1jc3NhbmltYXRpb25zLWNzc2NvbHVtbnMtZ2VuZXJhdGVkY29udGVudC1jc3NncmFkaWVudHMtY3NzcmVmbGVjdGlvbnMtY3NzdHJhbnNmb3Jtcy1jc3N0cmFuc2Zvcm1zM2QtY3NzdHJhbnNpdGlvbnMtYXBwbGljYXRpb25jYWNoZS1jYW52YXMtY2FudmFzdGV4dC1kcmFnYW5kZHJvcC1oYXNoY2hhbmdlLWhpc3RvcnktYXVkaW8tdmlkZW8taW5kZXhlZGRiLWlucHV0LWlucHV0dHlwZXMtbG9jYWxzdG9yYWdlLXBvc3RtZXNzYWdlLXNlc3Npb25zdG9yYWdlLXdlYnNvY2tldHMtd2Vic3FsZGF0YWJhc2Utd2Vid29ya2Vycy1nZW9sb2NhdGlvbi1pbmxpbmVzdmctc21pbC1zdmctc3ZnY2xpcHBhdGhzLXRvdWNoLXdlYmdsLW1xLXByZWZpeGVkLXRlc3RzdHlsZXMtdGVzdHByb3AtdGVzdGFsbHByb3BzLWhhc2V2ZW50LXByZWZpeGVzLWRvbXByZWZpeGVzLWxvYWQKICovCjt3aW5kb3cuTW9kZXJuaXpyPWZ1bmN0aW9uKGEsYixjKXtmdW5jdGlvbiBDKGEpe2kuY3NzVGV4dD1hfWZ1bmN0aW9uIEQoYSxiKXtyZXR1cm4gQyhtLmpvaW4oYSsiOyIpKyhifHwiIikpfWZ1bmN0aW9uIEUoYSxiKXtyZXR1cm4gdHlwZW9mIGE9PT1ifWZ1bmN0aW9uIEYoYSxiKXtyZXR1cm4hIX4oIiIrYSkuaW5kZXhPZihiKX1mdW5jdGlvbiBHKGEsYil7Zm9yKHZhciBkIGluIGEpaWYoaVthW2RdXSE9PWMpcmV0dXJuIGI9PSJwZngiP2FbZF06ITA7cmV0dXJuITF9ZnVuY3Rpb24gSChhLGIsZCl7Zm9yKHZhciBlIGluIGEpe3ZhciBmPWJbYVtlXV07aWYoZiE9PWMpcmV0dXJuIGQ9PT0hMT9hW2VdOkUoZiwiZnVuY3Rpb24iKT9mLmJpbmQoZHx8Yik6Zn1yZXR1cm4hMX1mdW5jdGlvbiBJKGEsYixjKXt2YXIgZD1hLmNoYXJBdCgwKS50b1VwcGVyQ2FzZSgpK2Euc3Vic3RyKDEpLGU9KGErIiAiK28uam9pbihkKyIgIikrZCkuc3BsaXQoIiAiKTtyZXR1cm4gRShiLCJzdHJpbmciKXx8RShiLCJ1bmRlZmluZWQiKT9HKGUsYik6KGU9KGErIiAiK3Auam9pbihkKyIgIikrZCkuc3BsaXQoIiAiKSxIKGUsYixjKSl9ZnVuY3Rpb24gSygpe2UuaW5wdXQ9ZnVuY3Rpb24oYyl7Zm9yKHZhciBkPTAsZT1jLmxlbmd0aDtkPGU7ZCsrKXRbY1tkXV09Y1tkXWluIGo7cmV0dXJuIHQubGlzdCYmKHQubGlzdD0hIWIuY3JlYXRlRWxlbWVudCgiZGF0YWxpc3QiKSYmISFhLkhUTUxEYXRhTGlzdEVsZW1lbnQpLHR9KCJhdXRvY29tcGxldGUgYXV0b2ZvY3VzIGxpc3QgcGxhY2Vob2xkZXIgbWF4IG1pbiBtdWx0aXBsZSBwYXR0ZXJuIHJlcXVpcmVkIHN0ZXAiLnNwbGl0KCIgIikpLGUuaW5wdXR0eXBlcz1mdW5jdGlvbihhKXtmb3IodmFyIGQ9MCxlLGcsaCxpPWEubGVuZ3RoO2Q8aTtkKyspai5zZXRBdHRyaWJ1dGUoInR5cGUiLGc9YVtkXSksZT1qLnR5cGUhPT0idGV4dCIsZSYmKGoudmFsdWU9ayxqLnN0eWxlLmNzc1RleHQ9InBvc2l0aW9uOmFic29sdXRlO3Zpc2liaWxpdHk6aGlkZGVuOyIsL15yYW5nZSQvLnRlc3QoZykmJmouc3R5bGUuV2Via2l0QXBwZWFyYW5jZSE9PWM/KGYuYXBwZW5kQ2hpbGQoaiksaD1iLmRlZmF1bHRWaWV3LGU9aC5nZXRDb21wdXRlZFN0eWxlJiZoLmdldENvbXB1dGVkU3R5bGUoaixudWxsKS5XZWJraXRBcHBlYXJhbmNlIT09InRleHRmaWVsZCImJmoub2Zmc2V0SGVpZ2h0IT09MCxmLnJlbW92ZUNoaWxkKGopKTovXihzZWFyY2h8dGVsKSQvLnRlc3QoZyl8fCgvXih1cmx8ZW1haWwpJC8udGVzdChnKT9lPWouY2hlY2tWYWxpZGl0eSYmai5jaGVja1ZhbGlkaXR5KCk9PT0hMTovXmNvbG9yJC8udGVzdChnKT8oZi5hcHBlbmRDaGlsZChqKSxmLm9mZnNldFdpZHRoLGU9ai52YWx1ZSE9ayxmLnJlbW92ZUNoaWxkKGopKTplPWoudmFsdWUhPWspKSxzW2FbZF1dPSEhZTtyZXR1cm4gc30oInNlYXJjaCB0ZWwgdXJsIGVtYWlsIGRhdGV0aW1lIGRhdGUgbW9udGggd2VlayB0aW1lIGRhdGV0aW1lLWxvY2FsIG51bWJlciByYW5nZSBjb2xvciIuc3BsaXQoIiAiKSl9dmFyIGQ9IjIuNS4zIixlPXt9LGY9Yi5kb2N1bWVudEVsZW1lbnQsZz0ibW9kZXJuaXpyIixoPWIuY3JlYXRlRWxlbWVudChnKSxpPWguc3R5bGUsaj1iLmNyZWF0ZUVsZW1lbnQoImlucHV0Iiksaz0iOikiLGw9e30udG9TdHJpbmcsbT0iIC13ZWJraXQtIC1tb3otIC1vLSAtbXMtICIuc3BsaXQoIiAiKSxuPSJXZWJraXQgTW96IE8gbXMiLG89bi5zcGxpdCgiICIpLHA9bi50b0xvd2VyQ2FzZSgpLnNwbGl0KCIgIikscT17c3ZnOiJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyJ9LHI9e30scz17fSx0PXt9LHU9W10sdj11LnNsaWNlLHcseD1mdW5jdGlvbihhLGMsZCxlKXt2YXIgaCxpLGosaz1iLmNyZWF0ZUVsZW1lbnQoImRpdiIpLGw9Yi5ib2R5LG09bD9sOmIuY3JlYXRlRWxlbWVudCgiYm9keSIpO2lmKHBhcnNlSW50KGQsMTApKXdoaWxlKGQtLSlqPWIuY3JlYXRlRWxlbWVudCgiZGl2Iiksai5pZD1lP2VbZF06ZysoZCsxKSxrLmFwcGVuZENoaWxkKGopO3JldHVybiBoPVsiJiMxNzM7IiwiPHN0eWxlPiIsYSwiPC9zdHlsZT4iXS5qb2luKCIiKSxrLmlkPWcsKGw/azptKS5pbm5lckhUTUwrPWgsbS5hcHBlbmRDaGlsZChrKSxsfHwobS5zdHlsZS5iYWNrZ3JvdW5kPSIiLGYuYXBwZW5kQ2hpbGQobSkpLGk9YyhrLGEpLGw/ay5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGspOm0ucGFyZW50Tm9kZS5yZW1vdmVDaGlsZChtKSwhIWl9LHk9ZnVuY3Rpb24oYil7dmFyIGM9YS5tYXRjaE1lZGlhfHxhLm1zTWF0Y2hNZWRpYTtpZihjKXJldHVybiBjKGIpLm1hdGNoZXM7dmFyIGQ7cmV0dXJuIHgoIkBtZWRpYSAiK2IrIiB7ICMiK2crIiB7IHBvc2l0aW9uOiBhYnNvbHV0ZTsgfSB9IixmdW5jdGlvbihiKXtkPShhLmdldENvbXB1dGVkU3R5bGU/Z2V0Q29tcHV0ZWRTdHlsZShiLG51bGwpOmIuY3VycmVudFN0eWxlKVsicG9zaXRpb24iXT09ImFic29sdXRlIn0pLGR9LHo9ZnVuY3Rpb24oKXtmdW5jdGlvbiBkKGQsZSl7ZT1lfHxiLmNyZWF0ZUVsZW1lbnQoYVtkXXx8ImRpdiIpLGQ9Im9uIitkO3ZhciBmPWQgaW4gZTtyZXR1cm4gZnx8KGUuc2V0QXR0cmlidXRlfHwoZT1iLmNyZWF0ZUVsZW1lbnQoImRpdiIpKSxlLnNldEF0dHJpYnV0ZSYmZS5yZW1vdmVBdHRyaWJ1dGUmJihlLnNldEF0dHJpYnV0ZShkLCIiKSxmPUUoZVtkXSwiZnVuY3Rpb24iKSxFKGVbZF0sInVuZGVmaW5lZCIpfHwoZVtkXT1jKSxlLnJlbW92ZUF0dHJpYnV0ZShkKSkpLGU9bnVsbCxmfXZhciBhPXtzZWxlY3Q6ImlucHV0IixjaGFuZ2U6ImlucHV0IixzdWJtaXQ6ImZvcm0iLHJlc2V0OiJmb3JtIixlcnJvcjoiaW1nIixsb2FkOiJpbWciLGFib3J0OiJpbWcifTtyZXR1cm4gZH0oKSxBPXt9Lmhhc093blByb3BlcnR5LEI7IUUoQSwidW5kZWZpbmVkIikmJiFFKEEuY2FsbCwidW5kZWZpbmVkIik/Qj1mdW5jdGlvbihhLGIpe3JldHVybiBBLmNhbGwoYSxiKX06Qj1mdW5jdGlvbihhLGIpe3JldHVybiBiIGluIGEmJkUoYS5jb25zdHJ1Y3Rvci5wcm90b3R5cGVbYl0sInVuZGVmaW5lZCIpfSxGdW5jdGlvbi5wcm90b3R5cGUuYmluZHx8KEZ1bmN0aW9uLnByb3RvdHlwZS5iaW5kPWZ1bmN0aW9uKGIpe3ZhciBjPXRoaXM7aWYodHlwZW9mIGMhPSJmdW5jdGlvbiIpdGhyb3cgbmV3IFR5cGVFcnJvcjt2YXIgZD12LmNhbGwoYXJndW1lbnRzLDEpLGU9ZnVuY3Rpb24oKXtpZih0aGlzIGluc3RhbmNlb2YgZSl7dmFyIGE9ZnVuY3Rpb24oKXt9O2EucHJvdG90eXBlPWMucHJvdG90eXBlO3ZhciBmPW5ldyBhLGc9Yy5hcHBseShmLGQuY29uY2F0KHYuY2FsbChhcmd1bWVudHMpKSk7cmV0dXJuIE9iamVjdChnKT09PWc/ZzpmfXJldHVybiBjLmFwcGx5KGIsZC5jb25jYXQodi5jYWxsKGFyZ3VtZW50cykpKX07cmV0dXJuIGV9KTt2YXIgSj1mdW5jdGlvbihjLGQpe3ZhciBmPWMuam9pbigiIiksZz1kLmxlbmd0aDt4KGYsZnVuY3Rpb24oYyxkKXt2YXIgZj1iLnN0eWxlU2hlZXRzW2Iuc3R5bGVTaGVldHMubGVuZ3RoLTFdLGg9Zj9mLmNzc1J1bGVzJiZmLmNzc1J1bGVzWzBdP2YuY3NzUnVsZXNbMF0uY3NzVGV4dDpmLmNzc1RleHR8fCIiOiIiLGk9Yy5jaGlsZE5vZGVzLGo9e307d2hpbGUoZy0tKWpbaVtnXS5pZF09aVtnXTtlLnRvdWNoPSJvbnRvdWNoc3RhcnQiaW4gYXx8YS5Eb2N1bWVudFRvdWNoJiZiIGluc3RhbmNlb2YgRG9jdW1lbnRUb3VjaHx8KGoudG91Y2gmJmoudG91Y2gub2Zmc2V0VG9wKT09PTksZS5jc3N0cmFuc2Zvcm1zM2Q9KGouY3NzdHJhbnNmb3JtczNkJiZqLmNzc3RyYW5zZm9ybXMzZC5vZmZzZXRMZWZ0KT09PTkmJmouY3NzdHJhbnNmb3JtczNkLm9mZnNldEhlaWdodD09PTMsZS5nZW5lcmF0ZWRjb250ZW50PShqLmdlbmVyYXRlZGNvbnRlbnQmJmouZ2VuZXJhdGVkY29udGVudC5vZmZzZXRIZWlnaHQpPj0xLGUuZm9udGZhY2U9L3NyYy9pLnRlc3QoaCkmJmguaW5kZXhPZihkLnNwbGl0KCIgIilbMF0pPT09MH0sZyxkKX0oWydAZm9udC1mYWNlIHtmb250LWZhbWlseToiZm9udCI7c3JjOnVybCgiaHR0cHM6Ly8iKX0nLFsiQG1lZGlhICgiLG0uam9pbigidG91Y2gtZW5hYmxlZCksKCIpLGcsIikiLCJ7I3RvdWNoe3RvcDo5cHg7cG9zaXRpb246YWJzb2x1dGV9fSJdLmpvaW4oIiIpLFsiQG1lZGlhICgiLG0uam9pbigidHJhbnNmb3JtLTNkKSwoIiksZywiKSIsInsjY3NzdHJhbnNmb3JtczNke2xlZnQ6OXB4O3Bvc2l0aW9uOmFic29sdXRlO2hlaWdodDozcHg7fX0iXS5qb2luKCIiKSxbJyNnZW5lcmF0ZWRjb250ZW50OmFmdGVye2NvbnRlbnQ6IicsaywnIjt2aXNpYmlsaXR5OmhpZGRlbn0nXS5qb2luKCIiKV0sWyJmb250ZmFjZSIsInRvdWNoIiwiY3NzdHJhbnNmb3JtczNkIiwiZ2VuZXJhdGVkY29udGVudCJdKTtyLmZsZXhib3g9ZnVuY3Rpb24oKXtyZXR1cm4gSSgiZmxleE9yZGVyIil9LHJbImZsZXhib3gtbGVnYWN5Il09ZnVuY3Rpb24oKXtyZXR1cm4gSSgiYm94RGlyZWN0aW9uIil9LHIuY2FudmFzPWZ1bmN0aW9uKCl7dmFyIGE9Yi5jcmVhdGVFbGVtZW50KCJjYW52YXMiKTtyZXR1cm4hIWEuZ2V0Q29udGV4dCYmISFhLmdldENvbnRleHQoIjJkIil9LHIuY2FudmFzdGV4dD1mdW5jdGlvbigpe3JldHVybiEhZS5jYW52YXMmJiEhRShiLmNyZWF0ZUVsZW1lbnQoImNhbnZhcyIpLmdldENvbnRleHQoIjJkIikuZmlsbFRleHQsImZ1bmN0aW9uIil9LHIud2ViZ2w9ZnVuY3Rpb24oKXt0cnl7dmFyIGQ9Yi5jcmVhdGVFbGVtZW50KCJjYW52YXMiKSxlO2U9ISghYS5XZWJHTFJlbmRlcmluZ0NvbnRleHR8fCFkLmdldENvbnRleHQoImV4cGVyaW1lbnRhbC13ZWJnbCIpJiYhZC5nZXRDb250ZXh0KCJ3ZWJnbCIpKSxkPWN9Y2F0Y2goZil7ZT0hMX1yZXR1cm4gZX0sci50b3VjaD1mdW5jdGlvbigpe3JldHVybiBlLnRvdWNofSxyLmdlb2xvY2F0aW9uPWZ1bmN0aW9uKCl7cmV0dXJuISFuYXZpZ2F0b3IuZ2VvbG9jYXRpb259LHIucG9zdG1lc3NhZ2U9ZnVuY3Rpb24oKXtyZXR1cm4hIWEucG9zdE1lc3NhZ2V9LHIud2Vic3FsZGF0YWJhc2U9ZnVuY3Rpb24oKXtyZXR1cm4hIWEub3BlbkRhdGFiYXNlfSxyLmluZGV4ZWREQj1mdW5jdGlvbigpe3JldHVybiEhSSgiaW5kZXhlZERCIixhKX0sci5oYXNoY2hhbmdlPWZ1bmN0aW9uKCl7cmV0dXJuIHooImhhc2hjaGFuZ2UiLGEpJiYoYi5kb2N1bWVudE1vZGU9PT1jfHxiLmRvY3VtZW50TW9kZT43KX0sci5oaXN0b3J5PWZ1bmN0aW9uKCl7cmV0dXJuISFhLmhpc3RvcnkmJiEhaGlzdG9yeS5wdXNoU3RhdGV9LHIuZHJhZ2FuZGRyb3A9ZnVuY3Rpb24oKXt2YXIgYT1iLmNyZWF0ZUVsZW1lbnQoImRpdiIpO3JldHVybiJkcmFnZ2FibGUiaW4gYXx8Im9uZHJhZ3N0YXJ0ImluIGEmJiJvbmRyb3AiaW4gYX0sci53ZWJzb2NrZXRzPWZ1bmN0aW9uKCl7Zm9yKHZhciBiPS0xLGM9by5sZW5ndGg7KytiPGM7KWlmKGFbb1tiXSsiV2ViU29ja2V0Il0pcmV0dXJuITA7cmV0dXJuIldlYlNvY2tldCJpbiBhfSxyLnJnYmE9ZnVuY3Rpb24oKXtyZXR1cm4gQygiYmFja2dyb3VuZC1jb2xvcjpyZ2JhKDE1MCwyNTUsMTUwLC41KSIpLEYoaS5iYWNrZ3JvdW5kQ29sb3IsInJnYmEiKX0sci5oc2xhPWZ1bmN0aW9uKCl7cmV0dXJuIEMoImJhY2tncm91bmQtY29sb3I6aHNsYSgxMjAsNDAlLDEwMCUsLjUpIiksRihpLmJhY2tncm91bmRDb2xvciwicmdiYSIpfHxGKGkuYmFja2dyb3VuZENvbG9yLCJoc2xhIil9LHIubXVsdGlwbGViZ3M9ZnVuY3Rpb24oKXtyZXR1cm4gQygiYmFja2dyb3VuZDp1cmwoaHR0cHM6Ly8pLHVybChodHRwczovLykscmVkIHVybChodHRwczovLykiKSwvKHVybFxzKlwoLio/KXszfS8udGVzdChpLmJhY2tncm91bmQpfSxyLmJhY2tncm91bmRzaXplPWZ1bmN0aW9uKCl7cmV0dXJuIEkoImJhY2tncm91bmRTaXplIil9LHIuYm9yZGVyaW1hZ2U9ZnVuY3Rpb24oKXtyZXR1cm4gSSgiYm9yZGVySW1hZ2UiKX0sci5ib3JkZXJyYWRpdXM9ZnVuY3Rpb24oKXtyZXR1cm4gSSgiYm9yZGVyUmFkaXVzIil9LHIuYm94c2hhZG93PWZ1bmN0aW9uKCl7cmV0dXJuIEkoImJveFNoYWRvdyIpfSxyLnRleHRzaGFkb3c9ZnVuY3Rpb24oKXtyZXR1cm4gYi5jcmVhdGVFbGVtZW50KCJkaXYiKS5zdHlsZS50ZXh0U2hhZG93PT09IiJ9LHIub3BhY2l0eT1mdW5jdGlvbigpe3JldHVybiBEKCJvcGFjaXR5Oi41NSIpLC9eMC41NSQvLnRlc3QoaS5vcGFjaXR5KX0sci5jc3NhbmltYXRpb25zPWZ1bmN0aW9uKCl7cmV0dXJuIEkoImFuaW1hdGlvbk5hbWUiKX0sci5jc3Njb2x1bW5zPWZ1bmN0aW9uKCl7cmV0dXJuIEkoImNvbHVtbkNvdW50Iil9LHIuY3NzZ3JhZGllbnRzPWZ1bmN0aW9uKCl7dmFyIGE9ImJhY2tncm91bmQtaW1hZ2U6IixiPSJncmFkaWVudChsaW5lYXIsbGVmdCB0b3AscmlnaHQgYm90dG9tLGZyb20oIzlmOSksdG8od2hpdGUpKTsiLGM9ImxpbmVhci1ncmFkaWVudChsZWZ0IHRvcCwjOWY5LCB3aGl0ZSk7IjtyZXR1cm4gQygoYSsiLXdlYmtpdC0gIi5zcGxpdCgiICIpLmpvaW4oYithKSttLmpvaW4oYythKSkuc2xpY2UoMCwtYS5sZW5ndGgpKSxGKGkuYmFja2dyb3VuZEltYWdlLCJncmFkaWVudCIpfSxyLmNzc3JlZmxlY3Rpb25zPWZ1bmN0aW9uKCl7cmV0dXJuIEkoImJveFJlZmxlY3QiKX0sci5jc3N0cmFuc2Zvcm1zPWZ1bmN0aW9uKCl7cmV0dXJuISFJKCJ0cmFuc2Zvcm0iKX0sci5jc3N0cmFuc2Zvcm1zM2Q9ZnVuY3Rpb24oKXt2YXIgYT0hIUkoInBlcnNwZWN0aXZlIik7cmV0dXJuIGEmJiJ3ZWJraXRQZXJzcGVjdGl2ZSJpbiBmLnN0eWxlJiYoYT1lLmNzc3RyYW5zZm9ybXMzZCksYX0sci5jc3N0cmFuc2l0aW9ucz1mdW5jdGlvbigpe3JldHVybiBJKCJ0cmFuc2l0aW9uIil9LHIuZm9udGZhY2U9ZnVuY3Rpb24oKXtyZXR1cm4gZS5mb250ZmFjZX0sci5nZW5lcmF0ZWRjb250ZW50PWZ1bmN0aW9uKCl7cmV0dXJuIGUuZ2VuZXJhdGVkY29udGVudH0sci52aWRlbz1mdW5jdGlvbigpe3ZhciBhPWIuY3JlYXRlRWxlbWVudCgidmlkZW8iKSxjPSExO3RyeXtpZihjPSEhYS5jYW5QbGF5VHlwZSljPW5ldyBCb29sZWFuKGMpLGMub2dnPWEuY2FuUGxheVR5cGUoJ3ZpZGVvL29nZzsgY29kZWNzPSJ0aGVvcmEiJykucmVwbGFjZSgvXm5vJC8sIiIpLGMuaDI2ND1hLmNhblBsYXlUeXBlKCd2aWRlby9tcDQ7IGNvZGVjcz0iYXZjMS40MkUwMUUiJykucmVwbGFjZSgvXm5vJC8sIiIpLGMud2VibT1hLmNhblBsYXlUeXBlKCd2aWRlby93ZWJtOyBjb2RlY3M9InZwOCwgdm9yYmlzIicpLnJlcGxhY2UoL15ubyQvLCIiKX1jYXRjaChkKXt9cmV0dXJuIGN9LHIuYXVkaW89ZnVuY3Rpb24oKXt2YXIgYT1iLmNyZWF0ZUVsZW1lbnQoImF1ZGlvIiksYz0hMTt0cnl7aWYoYz0hIWEuY2FuUGxheVR5cGUpYz1uZXcgQm9vbGVhbihjKSxjLm9nZz1hLmNhblBsYXlUeXBlKCdhdWRpby9vZ2c7IGNvZGVjcz0idm9yYmlzIicpLnJlcGxhY2UoL15ubyQvLCIiKSxjLm1wMz1hLmNhblBsYXlUeXBlKCJhdWRpby9tcGVnOyIpLnJlcGxhY2UoL15ubyQvLCIiKSxjLndhdj1hLmNhblBsYXlUeXBlKCdhdWRpby93YXY7IGNvZGVjcz0iMSInKS5yZXBsYWNlKC9ebm8kLywiIiksYy5tNGE9KGEuY2FuUGxheVR5cGUoImF1ZGlvL3gtbTRhOyIpfHxhLmNhblBsYXlUeXBlKCJhdWRpby9hYWM7IikpLnJlcGxhY2UoL15ubyQvLCIiKX1jYXRjaChkKXt9cmV0dXJuIGN9LHIubG9jYWxzdG9yYWdlPWZ1bmN0aW9uKCl7dHJ5e3JldHVybiBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShnLGcpLGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKGcpLCEwfWNhdGNoKGEpe3JldHVybiExfX0sci5zZXNzaW9uc3RvcmFnZT1mdW5jdGlvbigpe3RyeXtyZXR1cm4gc2Vzc2lvblN0b3JhZ2Uuc2V0SXRlbShnLGcpLHNlc3Npb25TdG9yYWdlLnJlbW92ZUl0ZW0oZyksITB9Y2F0Y2goYSl7cmV0dXJuITF9fSxyLndlYndvcmtlcnM9ZnVuY3Rpb24oKXtyZXR1cm4hIWEuV29ya2VyfSxyLmFwcGxpY2F0aW9uY2FjaGU9ZnVuY3Rpb24oKXtyZXR1cm4hIWEuYXBwbGljYXRpb25DYWNoZX0sci5zdmc9ZnVuY3Rpb24oKXtyZXR1cm4hIWIuY3JlYXRlRWxlbWVudE5TJiYhIWIuY3JlYXRlRWxlbWVudE5TKHEuc3ZnLCJzdmciKS5jcmVhdGVTVkdSZWN0fSxyLmlubGluZXN2Zz1mdW5jdGlvbigpe3ZhciBhPWIuY3JlYXRlRWxlbWVudCgiZGl2Iik7cmV0dXJuIGEuaW5uZXJIVE1MPSI8c3ZnLz4iLChhLmZpcnN0Q2hpbGQmJmEuZmlyc3RDaGlsZC5uYW1lc3BhY2VVUkkpPT1xLnN2Z30sci5zbWlsPWZ1bmN0aW9uKCl7cmV0dXJuISFiLmNyZWF0ZUVsZW1lbnROUyYmL1NWR0FuaW1hdGUvLnRlc3QobC5jYWxsKGIuY3JlYXRlRWxlbWVudE5TKHEuc3ZnLCJhbmltYXRlIikpKX0sci5zdmdjbGlwcGF0aHM9ZnVuY3Rpb24oKXtyZXR1cm4hIWIuY3JlYXRlRWxlbWVudE5TJiYvU1ZHQ2xpcFBhdGgvLnRlc3QobC5jYWxsKGIuY3JlYXRlRWxlbWVudE5TKHEuc3ZnLCJjbGlwUGF0aCIpKSl9O2Zvcih2YXIgTCBpbiByKUIocixMKSYmKHc9TC50b0xvd2VyQ2FzZSgpLGVbd109cltMXSgpLHUucHVzaCgoZVt3XT8iIjoibm8tIikrdykpO3JldHVybiBlLmlucHV0fHxLKCksQygiIiksaD1qPW51bGwsZS5fdmVyc2lvbj1kLGUuX3ByZWZpeGVzPW0sZS5fZG9tUHJlZml4ZXM9cCxlLl9jc3NvbVByZWZpeGVzPW8sZS5tcT15LGUuaGFzRXZlbnQ9eixlLnRlc3RQcm9wPWZ1bmN0aW9uKGEpe3JldHVybiBHKFthXSl9LGUudGVzdEFsbFByb3BzPUksZS50ZXN0U3R5bGVzPXgsZS5wcmVmaXhlZD1mdW5jdGlvbihhLGIsYyl7cmV0dXJuIGI/SShhLGIsYyk6SShhLCJwZngiKX0sZX0odGhpcyx0aGlzLmRvY3VtZW50KSxmdW5jdGlvbihhLGIsYyl7ZnVuY3Rpb24gZChhKXtyZXR1cm4gby5jYWxsKGEpPT0iW29iamVjdCBGdW5jdGlvbl0ifWZ1bmN0aW9uIGUoYSl7cmV0dXJuIHR5cGVvZiBhPT0ic3RyaW5nIn1mdW5jdGlvbiBmKCl7fWZ1bmN0aW9uIGcoYSl7cmV0dXJuIWF8fGE9PSJsb2FkZWQifHxhPT0iY29tcGxldGUifHxhPT0idW5pbml0aWFsaXplZCJ9ZnVuY3Rpb24gaCgpe3ZhciBhPXAuc2hpZnQoKTtxPTEsYT9hLnQ/bShmdW5jdGlvbigpeyhhLnQ9PSJjIj9CLmluamVjdENzczpCLmluamVjdEpzKShhLnMsMCxhLmEsYS54LGEuZSwxKX0sMCk6KGEoKSxoKCkpOnE9MH1mdW5jdGlvbiBpKGEsYyxkLGUsZixpLGope2Z1bmN0aW9uIGsoYil7aWYoIW8mJmcobC5yZWFkeVN0YXRlKSYmKHUucj1vPTEsIXEmJmgoKSxsLm9ubG9hZD1sLm9ucmVhZHlzdGF0ZWNoYW5nZT1udWxsLGIpKXthIT0iaW1nIiYmbShmdW5jdGlvbigpe3QucmVtb3ZlQ2hpbGQobCl9LDUwKTtmb3IodmFyIGQgaW4geVtjXSl5W2NdLmhhc093blByb3BlcnR5KGQpJiZ5W2NdW2RdLm9ubG9hZCgpfX12YXIgaj1qfHxCLmVycm9yVGltZW91dCxsPXt9LG89MCxyPTAsdT17dDpkLHM6YyxlOmYsYTppLHg6an07eVtjXT09PTEmJihyPTEseVtjXT1bXSxsPWIuY3JlYXRlRWxlbWVudChhKSksYT09Im9iamVjdCI/bC5kYXRhPWM6KGwuc3JjPWMsbC50eXBlPWEpLGwud2lkdGg9bC5oZWlnaHQ9IjAiLGwub25lcnJvcj1sLm9ubG9hZD1sLm9ucmVhZHlzdGF0ZWNoYW5nZT1mdW5jdGlvbigpe2suY2FsbCh0aGlzLHIpfSxwLnNwbGljZShlLDAsdSksYSE9ImltZyImJihyfHx5W2NdPT09Mj8odC5pbnNlcnRCZWZvcmUobCxzP251bGw6biksbShrLGopKTp5W2NdLnB1c2gobCkpfWZ1bmN0aW9uIGooYSxiLGMsZCxmKXtyZXR1cm4gcT0wLGI9Ynx8ImoiLGUoYSk/aShiPT0iYyI/djp1LGEsYix0aGlzLmkrKyxjLGQsZik6KHAuc3BsaWNlKHRoaXMuaSsrLDAsYSkscC5sZW5ndGg9PTEmJmgoKSksdGhpc31mdW5jdGlvbiBrKCl7dmFyIGE9QjtyZXR1cm4gYS5sb2FkZXI9e2xvYWQ6aixpOjB9LGF9dmFyIGw9Yi5kb2N1bWVudEVsZW1lbnQsbT1hLnNldFRpbWVvdXQsbj1iLmdldEVsZW1lbnRzQnlUYWdOYW1lKCJzY3JpcHQiKVswXSxvPXt9LnRvU3RyaW5nLHA9W10scT0wLHI9Ik1vekFwcGVhcmFuY2UiaW4gbC5zdHlsZSxzPXImJiEhYi5jcmVhdGVSYW5nZSgpLmNvbXBhcmVOb2RlLHQ9cz9sOm4ucGFyZW50Tm9kZSxsPWEub3BlcmEmJm8uY2FsbChhLm9wZXJhKT09IltvYmplY3QgT3BlcmFdIixsPSEhYi5hdHRhY2hFdmVudCYmIWwsdT1yPyJvYmplY3QiOmw/InNjcmlwdCI6ImltZyIsdj1sPyJzY3JpcHQiOnUsdz1BcnJheS5pc0FycmF5fHxmdW5jdGlvbihhKXtyZXR1cm4gby5jYWxsKGEpPT0iW29iamVjdCBBcnJheV0ifSx4PVtdLHk9e30sej17dGltZW91dDpmdW5jdGlvbihhLGIpe3JldHVybiBiLmxlbmd0aCYmKGEudGltZW91dD1iWzBdKSxhfX0sQSxCO0I9ZnVuY3Rpb24oYSl7ZnVuY3Rpb24gYihhKXt2YXIgYT1hLnNwbGl0KCIhIiksYj14Lmxlbmd0aCxjPWEucG9wKCksZD1hLmxlbmd0aCxjPXt1cmw6YyxvcmlnVXJsOmMscHJlZml4ZXM6YX0sZSxmLGc7Zm9yKGY9MDtmPGQ7ZisrKWc9YVtmXS5zcGxpdCgiPSIpLChlPXpbZy5zaGlmdCgpXSkmJihjPWUoYyxnKSk7Zm9yKGY9MDtmPGI7ZisrKWM9eFtmXShjKTtyZXR1cm4gY31mdW5jdGlvbiBnKGEsZSxmLGcsaSl7dmFyIGo9YihhKSxsPWouYXV0b0NhbGxiYWNrO2oudXJsLnNwbGl0KCIuIikucG9wKCkuc3BsaXQoIj8iKS5zaGlmdCgpLGouYnlwYXNzfHwoZSYmKGU9ZChlKT9lOmVbYV18fGVbZ118fGVbYS5zcGxpdCgiLyIpLnBvcCgpLnNwbGl0KCI/IilbMF1dfHxoKSxqLmluc3RlYWQ/ai5pbnN0ZWFkKGEsZSxmLGcsaSk6KHlbai51cmxdP2oubm9leGVjPSEwOnlbai51cmxdPTEsZi5sb2FkKGoudXJsLGouZm9yY2VDU1N8fCFqLmZvcmNlSlMmJiJjc3MiPT1qLnVybC5zcGxpdCgiLiIpLnBvcCgpLnNwbGl0KCI/Iikuc2hpZnQoKT8iYyI6YyxqLm5vZXhlYyxqLmF0dHJzLGoudGltZW91dCksKGQoZSl8fGQobCkpJiZmLmxvYWQoZnVuY3Rpb24oKXtrKCksZSYmZShqLm9yaWdVcmwsaSxnKSxsJiZsKGoub3JpZ1VybCxpLGcpLHlbai51cmxdPTJ9KSkpfWZ1bmN0aW9uIGkoYSxiKXtmdW5jdGlvbiBjKGEsYyl7aWYoYSl7aWYoZShhKSljfHwoaj1mdW5jdGlvbigpe3ZhciBhPVtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtrLmFwcGx5KHRoaXMsYSksbCgpfSksZyhhLGosYiwwLGgpO2Vsc2UgaWYoT2JqZWN0KGEpPT09YSlmb3IobiBpbiBtPWZ1bmN0aW9uKCl7dmFyIGI9MCxjO2ZvcihjIGluIGEpYS5oYXNPd25Qcm9wZXJ0eShjKSYmYisrO3JldHVybiBifSgpLGEpYS5oYXNPd25Qcm9wZXJ0eShuKSYmKCFjJiYhLS1tJiYoZChqKT9qPWZ1bmN0aW9uKCl7dmFyIGE9W10uc2xpY2UuY2FsbChhcmd1bWVudHMpO2suYXBwbHkodGhpcyxhKSxsKCl9Ompbbl09ZnVuY3Rpb24oYSl7cmV0dXJuIGZ1bmN0aW9uKCl7dmFyIGI9W10uc2xpY2UuY2FsbChhcmd1bWVudHMpO2EmJmEuYXBwbHkodGhpcyxiKSxsKCl9fShrW25dKSksZyhhW25dLGosYixuLGgpKX1lbHNlIWMmJmwoKX12YXIgaD0hIWEudGVzdCxpPWEubG9hZHx8YS5ib3RoLGo9YS5jYWxsYmFja3x8ZixrPWosbD1hLmNvbXBsZXRlfHxmLG0sbjtjKGg/YS55ZXA6YS5ub3BlLCEhaSksaSYmYyhpKX12YXIgaixsLG09dGhpcy55ZXBub3BlLmxvYWRlcjtpZihlKGEpKWcoYSwwLG0sMCk7ZWxzZSBpZih3KGEpKWZvcihqPTA7ajxhLmxlbmd0aDtqKyspbD1hW2pdLGUobCk/ZyhsLDAsbSwwKTp3KGwpP0IobCk6T2JqZWN0KGwpPT09bCYmaShsLG0pO2Vsc2UgT2JqZWN0KGEpPT09YSYmaShhLG0pfSxCLmFkZFByZWZpeD1mdW5jdGlvbihhLGIpe3pbYV09Yn0sQi5hZGRGaWx0ZXI9ZnVuY3Rpb24oYSl7eC5wdXNoKGEpfSxCLmVycm9yVGltZW91dD0xZTQsYi5yZWFkeVN0YXRlPT1udWxsJiZiLmFkZEV2ZW50TGlzdGVuZXImJihiLnJlYWR5U3RhdGU9ImxvYWRpbmciLGIuYWRkRXZlbnRMaXN0ZW5lcigiRE9NQ29udGVudExvYWRlZCIsQT1mdW5jdGlvbigpe2IucmVtb3ZlRXZlbnRMaXN0ZW5lcigiRE9NQ29udGVudExvYWRlZCIsQSwwKSxiLnJlYWR5U3RhdGU9ImNvbXBsZXRlIn0sMCkpLGEueWVwbm9wZT1rKCksYS55ZXBub3BlLmV4ZWN1dGVTdGFjaz1oLGEueWVwbm9wZS5pbmplY3RKcz1mdW5jdGlvbihhLGMsZCxlLGksail7dmFyIGs9Yi5jcmVhdGVFbGVtZW50KCJzY3JpcHQiKSxsLG8sZT1lfHxCLmVycm9yVGltZW91dDtrLnNyYz1hO2ZvcihvIGluIGQpay5zZXRBdHRyaWJ1dGUobyxkW29dKTtjPWo/aDpjfHxmLGsub25yZWFkeXN0YXRlY2hhbmdlPWsub25sb2FkPWZ1bmN0aW9uKCl7IWwmJmcoay5yZWFkeVN0YXRlKSYmKGw9MSxjKCksay5vbmxvYWQ9ay5vbnJlYWR5c3RhdGVjaGFuZ2U9bnVsbCl9LG0oZnVuY3Rpb24oKXtsfHwobD0xLGMoMSkpfSxlKSxpP2sub25sb2FkKCk6bi5wYXJlbnROb2RlLmluc2VydEJlZm9yZShrLG4pfSxhLnllcG5vcGUuaW5qZWN0Q3NzPWZ1bmN0aW9uKGEsYyxkLGUsZyxpKXt2YXIgZT1iLmNyZWF0ZUVsZW1lbnQoImxpbmsiKSxqLGM9aT9oOmN8fGY7ZS5ocmVmPWEsZS5yZWw9InN0eWxlc2hlZXQiLGUudHlwZT0idGV4dC9jc3MiO2ZvcihqIGluIGQpZS5zZXRBdHRyaWJ1dGUoaixkW2pdKTtnfHwobi5wYXJlbnROb2RlLmluc2VydEJlZm9yZShlLG4pLG0oYywwKSl9fSh0aGlzLGRvY3VtZW50KSxNb2Rlcm5penIubG9hZD1mdW5jdGlvbigpe3llcG5vcGUuYXBwbHkod2luZG93LFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzLDApKX07"></script> <script src="data:application/x-javascript;base64,dmFyIHE9bnVsbDt3aW5kb3cuUFJfU0hPVUxEX1VTRV9DT05USU5VQVRJT049ITA7CihmdW5jdGlvbigpe2Z1bmN0aW9uIEwoYSl7ZnVuY3Rpb24gbShhKXt2YXIgZj1hLmNoYXJDb2RlQXQoMCk7aWYoZiE9PTkyKXJldHVybiBmO3ZhciBiPWEuY2hhckF0KDEpO3JldHVybihmPXJbYl0pP2Y6IjAiPD1iJiZiPD0iNyI/cGFyc2VJbnQoYS5zdWJzdHJpbmcoMSksOCk6Yj09PSJ1Inx8Yj09PSJ4Ij9wYXJzZUludChhLnN1YnN0cmluZygyKSwxNik6YS5jaGFyQ29kZUF0KDEpfWZ1bmN0aW9uIGUoYSl7aWYoYTwzMilyZXR1cm4oYTwxNj8iXFx4MCI6IlxceCIpK2EudG9TdHJpbmcoMTYpO2E9U3RyaW5nLmZyb21DaGFyQ29kZShhKTtpZihhPT09IlxcInx8YT09PSItInx8YT09PSJbInx8YT09PSJdIilhPSJcXCIrYTtyZXR1cm4gYX1mdW5jdGlvbiBoKGEpe2Zvcih2YXIgZj1hLnN1YnN0cmluZygxLGEubGVuZ3RoLTEpLm1hdGNoKC9cXHVbXGRBLUZhLWZdezR9fFxceFtcZEEtRmEtZl17Mn18XFxbMC0zXVswLTddezAsMn18XFxbMC03XXsxLDJ9fFxcW1xTXHNdfFteXFxdL2cpLGE9CltdLGI9W10sbz1mWzBdPT09Il4iLGM9bz8xOjAsaT1mLmxlbmd0aDtjPGk7KytjKXt2YXIgaj1mW2NdO2lmKC9cXFtiZHN3XS9pLnRlc3QoaikpYS5wdXNoKGopO2Vsc2V7dmFyIGo9bShqKSxkO2MrMjxpJiYiLSI9PT1mW2MrMV0/KGQ9bShmW2MrMl0pLGMrPTIpOmQ9ajtiLnB1c2goW2osZF0pO2Q8NjV8fGo+MTIyfHwoZDw2NXx8aj45MHx8Yi5wdXNoKFtNYXRoLm1heCg2NSxqKXwzMixNYXRoLm1pbihkLDkwKXwzMl0pLGQ8OTd8fGo+MTIyfHxiLnB1c2goW01hdGgubWF4KDk3LGopJi0zMyxNYXRoLm1pbihkLDEyMikmLTMzXSkpfX1iLnNvcnQoZnVuY3Rpb24oYSxmKXtyZXR1cm4gYVswXS1mWzBdfHxmWzFdLWFbMV19KTtmPVtdO2o9W05hTixOYU5dO2ZvcihjPTA7YzxiLmxlbmd0aDsrK2MpaT1iW2NdLGlbMF08PWpbMV0rMT9qWzFdPU1hdGgubWF4KGpbMV0saVsxXSk6Zi5wdXNoKGo9aSk7Yj1bIlsiXTtvJiZiLnB1c2goIl4iKTtiLnB1c2guYXBwbHkoYixhKTtmb3IoYz0wO2M8CmYubGVuZ3RoOysrYylpPWZbY10sYi5wdXNoKGUoaVswXSkpLGlbMV0+aVswXSYmKGlbMV0rMT5pWzBdJiZiLnB1c2goIi0iKSxiLnB1c2goZShpWzFdKSkpO2IucHVzaCgiXSIpO3JldHVybiBiLmpvaW4oIiIpfWZ1bmN0aW9uIHkoYSl7Zm9yKHZhciBmPWEuc291cmNlLm1hdGNoKC9cWyg/OlteXFxcXV18XFxbXFNcc10pKl18XFx1W1xkQS1GYS1mXXs0fXxcXHhbXGRBLUZhLWZdezJ9fFxcXGQrfFxcW15cZHV4XXxcKFw/WyE6PV18WygpXl18W14oKVtcXF5dKy9nKSxiPWYubGVuZ3RoLGQ9W10sYz0wLGk9MDtjPGI7KytjKXt2YXIgaj1mW2NdO2o9PT0iKCI/KytpOiJcXCI9PT1qLmNoYXJBdCgwKSYmKGo9K2ouc3Vic3RyaW5nKDEpKSYmajw9aSYmKGRbal09LTEpfWZvcihjPTE7YzxkLmxlbmd0aDsrK2MpLTE9PT1kW2NdJiYoZFtjXT0rK3QpO2ZvcihpPWM9MDtjPGI7KytjKWo9ZltjXSxqPT09IigiPygrK2ksZFtpXT09PXZvaWQgMCYmKGZbY109Iig/OiIpKToiXFwiPT09ai5jaGFyQXQoMCkmJgooaj0rai5zdWJzdHJpbmcoMSkpJiZqPD1pJiYoZltjXT0iXFwiK2RbaV0pO2ZvcihpPWM9MDtjPGI7KytjKSJeIj09PWZbY10mJiJeIiE9PWZbYysxXSYmKGZbY109IiIpO2lmKGEuaWdub3JlQ2FzZSYmcylmb3IoYz0wO2M8YjsrK2Mpaj1mW2NdLGE9ai5jaGFyQXQoMCksai5sZW5ndGg+PTImJmE9PT0iWyI/ZltjXT1oKGopOmEhPT0iXFwiJiYoZltjXT1qLnJlcGxhY2UoL1tBLVphLXpdL2csZnVuY3Rpb24oYSl7YT1hLmNoYXJDb2RlQXQoMCk7cmV0dXJuIlsiK1N0cmluZy5mcm9tQ2hhckNvZGUoYSYtMzMsYXwzMikrIl0ifSkpO3JldHVybiBmLmpvaW4oIiIpfWZvcih2YXIgdD0wLHM9ITEsbD0hMSxwPTAsZD1hLmxlbmd0aDtwPGQ7KytwKXt2YXIgZz1hW3BdO2lmKGcuaWdub3JlQ2FzZSlsPSEwO2Vsc2UgaWYoL1thLXpdL2kudGVzdChnLnNvdXJjZS5yZXBsYWNlKC9cXHVbXGRhLWZdezR9fFxceFtcZGEtZl17Mn18XFxbXlVYdXhdL2dpLCIiKSkpe3M9ITA7bD0hMTticmVha319Zm9yKHZhciByPQp7Yjo4LHQ6OSxuOjEwLHY6MTEsZjoxMixyOjEzfSxuPVtdLHA9MCxkPWEubGVuZ3RoO3A8ZDsrK3Ape2c9YVtwXTtpZihnLmdsb2JhbHx8Zy5tdWx0aWxpbmUpdGhyb3cgRXJyb3IoIiIrZyk7bi5wdXNoKCIoPzoiK3koZykrIikiKX1yZXR1cm4gUmVnRXhwKG4uam9pbigifCIpLGw/ImdpIjoiZyIpfWZ1bmN0aW9uIE0oYSl7ZnVuY3Rpb24gbShhKXtzd2l0Y2goYS5ub2RlVHlwZSl7Y2FzZSAxOmlmKGUudGVzdChhLmNsYXNzTmFtZSkpYnJlYWs7Zm9yKHZhciBnPWEuZmlyc3RDaGlsZDtnO2c9Zy5uZXh0U2libGluZyltKGcpO2c9YS5ub2RlTmFtZTtpZigiQlIiPT09Z3x8IkxJIj09PWcpaFtzXT0iXG4iLHRbczw8MV09eSsrLHRbcysrPDwxfDFdPWE7YnJlYWs7Y2FzZSAzOmNhc2UgNDpnPWEubm9kZVZhbHVlLGcubGVuZ3RoJiYoZz1wP2cucmVwbGFjZSgvXHJcbj8vZywiXG4iKTpnLnJlcGxhY2UoL1tcdFxuXHIgXSsvZywiICIpLGhbc109Zyx0W3M8PDFdPXkseSs9Zy5sZW5ndGgsCnRbcysrPDwxfDFdPWEpfX12YXIgZT0vKD86Xnxccylub2NvZGUoPzpcc3wkKS8saD1bXSx5PTAsdD1bXSxzPTAsbDthLmN1cnJlbnRTdHlsZT9sPWEuY3VycmVudFN0eWxlLndoaXRlU3BhY2U6d2luZG93LmdldENvbXB1dGVkU3R5bGUmJihsPWRvY3VtZW50LmRlZmF1bHRWaWV3LmdldENvbXB1dGVkU3R5bGUoYSxxKS5nZXRQcm9wZXJ0eVZhbHVlKCJ3aGl0ZS1zcGFjZSIpKTt2YXIgcD1sJiYicHJlIj09PWwuc3Vic3RyaW5nKDAsMyk7bShhKTtyZXR1cm57YTpoLmpvaW4oIiIpLnJlcGxhY2UoL1xuJC8sIiIpLGM6dH19ZnVuY3Rpb24gQihhLG0sZSxoKXttJiYoYT17YTptLGQ6YX0sZShhKSxoLnB1c2guYXBwbHkoaCxhLmUpKX1mdW5jdGlvbiB4KGEsbSl7ZnVuY3Rpb24gZShhKXtmb3IodmFyIGw9YS5kLHA9W2wsInBsbiJdLGQ9MCxnPWEuYS5tYXRjaCh5KXx8W10scj17fSxuPTAsej1nLmxlbmd0aDtuPHo7KytuKXt2YXIgZj1nW25dLGI9cltmXSxvPXZvaWQgMCxjO2lmKHR5cGVvZiBiPT09CiJzdHJpbmciKWM9ITE7ZWxzZXt2YXIgaT1oW2YuY2hhckF0KDApXTtpZihpKW89Zi5tYXRjaChpWzFdKSxiPWlbMF07ZWxzZXtmb3IoYz0wO2M8dDsrK2MpaWYoaT1tW2NdLG89Zi5tYXRjaChpWzFdKSl7Yj1pWzBdO2JyZWFrfW98fChiPSJwbG4iKX1pZigoYz1iLmxlbmd0aD49NSYmImxhbmctIj09PWIuc3Vic3RyaW5nKDAsNSkpJiYhKG8mJnR5cGVvZiBvWzFdPT09InN0cmluZyIpKWM9ITEsYj0ic3JjIjtjfHwocltmXT1iKX1pPWQ7ZCs9Zi5sZW5ndGg7aWYoYyl7Yz1vWzFdO3ZhciBqPWYuaW5kZXhPZihjKSxrPWorYy5sZW5ndGg7b1syXSYmKGs9Zi5sZW5ndGgtb1syXS5sZW5ndGgsaj1rLWMubGVuZ3RoKTtiPWIuc3Vic3RyaW5nKDUpO0IobCtpLGYuc3Vic3RyaW5nKDAsaiksZSxwKTtCKGwraStqLGMsQyhiLGMpLHApO0IobCtpK2ssZi5zdWJzdHJpbmcoayksZSxwKX1lbHNlIHAucHVzaChsK2ksYil9YS5lPXB9dmFyIGg9e30seTsoZnVuY3Rpb24oKXtmb3IodmFyIGU9YS5jb25jYXQobSksCmw9W10scD17fSxkPTAsZz1lLmxlbmd0aDtkPGc7KytkKXt2YXIgcj1lW2RdLG49clszXTtpZihuKWZvcih2YXIgaz1uLmxlbmd0aDstLWs+PTA7KWhbbi5jaGFyQXQoayldPXI7cj1yWzFdO249IiIrcjtwLmhhc093blByb3BlcnR5KG4pfHwobC5wdXNoKHIpLHBbbl09cSl9bC5wdXNoKC9bXFNcc10vKTt5PUwobCl9KSgpO3ZhciB0PW0ubGVuZ3RoO3JldHVybiBlfWZ1bmN0aW9uIHUoYSl7dmFyIG09W10sZT1bXTthLnRyaXBsZVF1b3RlZFN0cmluZ3M/bS5wdXNoKFsic3RyIiwvXig/OicnJyg/OlteJ1xcXXxcXFtcU1xzXXwnJz8oPz1bXiddKSkqKD86JycnfCQpfCIiIig/OlteIlxcXXxcXFtcU1xzXXwiIj8oPz1bXiJdKSkqKD86IiIifCQpfCcoPzpbXidcXF18XFxbXFNcc10pKig/Oid8JCl8Iig/OlteIlxcXXxcXFtcU1xzXSkqKD86InwkKSkvLHEsIidcIiJdKTphLm11bHRpTGluZVN0cmluZ3M/bS5wdXNoKFsic3RyIiwvXig/OicoPzpbXidcXF18XFxbXFNcc10pKig/Oid8JCl8Iig/OlteIlxcXXxcXFtcU1xzXSkqKD86InwkKXxgKD86W15cXGBdfFxcW1xTXHNdKSooPzpgfCQpKS8sCnEsIidcImAiXSk6bS5wdXNoKFsic3RyIiwvXig/OicoPzpbXlxuXHInXFxdfFxcLikqKD86J3wkKXwiKD86W15cblxyIlxcXXxcXC4pKig/OiJ8JCkpLyxxLCJcIiciXSk7YS52ZXJiYXRpbVN0cmluZ3MmJmUucHVzaChbInN0ciIsL15AIig/OlteIl18IiIpKig/OiJ8JCkvLHFdKTt2YXIgaD1hLmhhc2hDb21tZW50cztoJiYoYS5jU3R5bGVDb21tZW50cz8oaD4xP20ucHVzaChbImNvbSIsL14jKD86IyMoPzpbXiNdfCMoPyEjIykpKig/OiMjI3wkKXwuKikvLHEsIiMiXSk6bS5wdXNoKFsiY29tIiwvXiMoPzooPzpkZWZpbmV8ZWxpZnxlbHNlfGVuZGlmfGVycm9yfGlmZGVmfGluY2x1ZGV8aWZuZGVmfGxpbmV8cHJhZ21hfHVuZGVmfHdhcm5pbmcpXGJ8W15cblxyXSopLyxxLCIjIl0pLGUucHVzaChbInN0ciIsL148KD86KD86KD86XC5cLlwvKSp8XC8/KSg/Oltcdy1dKyg/OlwvW1x3LV0rKSspP1tcdy1dK1wuaHxbYS16XVx3Kik+LyxxXSkpOm0ucHVzaChbImNvbSIsL14jW15cblxyXSovLApxLCIjIl0pKTthLmNTdHlsZUNvbW1lbnRzJiYoZS5wdXNoKFsiY29tIiwvXlwvXC9bXlxuXHJdKi8scV0pLGUucHVzaChbImNvbSIsL15cL1wqW1xTXHNdKj8oPzpcKlwvfCQpLyxxXSkpO2EucmVnZXhMaXRlcmFscyYmZS5wdXNoKFsibGFuZy1yZWdleCIsL14oPzpeXlwuP3xbISstXXwhPXwhPT18I3wlfCU9fCZ8JiZ8JiY9fCY9fFwofFwqfFwqPXxcKz18LHwtPXwtPnxcL3xcLz18Onw6Onw7fDx8PDx8PDw9fDw9fD18PT18PT09fD58Pj18Pj58Pj49fD4+Pnw+Pj49fFs/QFteXXxcXj18XF5cXnxcXlxePXx7fFx8fFx8PXxcfFx8fFx8XHw9fH58YnJlYWt8Y2FzZXxjb250aW51ZXxkZWxldGV8ZG98ZWxzZXxmaW5hbGx5fGluc3RhbmNlb2Z8cmV0dXJufHRocm93fHRyeXx0eXBlb2YpXHMqKFwvKD89W14qL10pKD86W14vW1xcXXxcXFtcU1xzXXxcWyg/OlteXFxcXV18XFxbXFNcc10pKig/Ol18JCkpK1wvKS9dKTsoaD1hLnR5cGVzKSYmZS5wdXNoKFsidHlwIixoXSk7YT0oIiIrYS5rZXl3b3JkcykucmVwbGFjZSgvXiB8ICQvZywKIiIpO2EubGVuZ3RoJiZlLnB1c2goWyJrd2QiLFJlZ0V4cCgiXig/OiIrYS5yZXBsYWNlKC9bXHMsXSsvZywifCIpKyIpXFxiIikscV0pO20ucHVzaChbInBsbiIsL15ccysvLHEsIiBcclxuXHRceGEwIl0pO2UucHVzaChbImxpdCIsL15AWyRfYS16XVtcdyRAXSovaSxxXSxbInR5cCIsL14oPzpbQF9dP1tBLVpdK1thLXpdW1x3JEBdKnxcdytfdFxiKS8scV0sWyJwbG4iLC9eWyRfYS16XVtcdyRAXSovaSxxXSxbImxpdCIsL14oPzoweFtcZGEtZl0rfCg/OlxkKD86X1xkKykqXGQqKD86XC5cZCopP3xcLlxkXCspKD86ZVsrLV0/XGQrKT8pW2Etel0qL2kscSwiMDEyMzQ1Njc4OSJdLFsicGxuIiwvXlxcW1xTXHNdPy8scV0sWyJwdW4iLC9eLlteXHNcdyItJCcuL0BcXGBdKi8scV0pO3JldHVybiB4KG0sZSl9ZnVuY3Rpb24gRChhLG0pe2Z1bmN0aW9uIGUoYSl7c3dpdGNoKGEubm9kZVR5cGUpe2Nhc2UgMTppZihrLnRlc3QoYS5jbGFzc05hbWUpKWJyZWFrO2lmKCJCUiI9PT1hLm5vZGVOYW1lKWgoYSksCmEucGFyZW50Tm9kZSYmYS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGEpO2Vsc2UgZm9yKGE9YS5maXJzdENoaWxkO2E7YT1hLm5leHRTaWJsaW5nKWUoYSk7YnJlYWs7Y2FzZSAzOmNhc2UgNDppZihwKXt2YXIgYj1hLm5vZGVWYWx1ZSxkPWIubWF0Y2godCk7aWYoZCl7dmFyIGM9Yi5zdWJzdHJpbmcoMCxkLmluZGV4KTthLm5vZGVWYWx1ZT1jOyhiPWIuc3Vic3RyaW5nKGQuaW5kZXgrZFswXS5sZW5ndGgpKSYmYS5wYXJlbnROb2RlLmluc2VydEJlZm9yZShzLmNyZWF0ZVRleHROb2RlKGIpLGEubmV4dFNpYmxpbmcpO2goYSk7Y3x8YS5wYXJlbnROb2RlLnJlbW92ZUNoaWxkKGEpfX19fWZ1bmN0aW9uIGgoYSl7ZnVuY3Rpb24gYihhLGQpe3ZhciBlPWQ/YS5jbG9uZU5vZGUoITEpOmEsZj1hLnBhcmVudE5vZGU7aWYoZil7dmFyIGY9YihmLDEpLGc9YS5uZXh0U2libGluZztmLmFwcGVuZENoaWxkKGUpO2Zvcih2YXIgaD1nO2g7aD1nKWc9aC5uZXh0U2libGluZyxmLmFwcGVuZENoaWxkKGgpfXJldHVybiBlfQpmb3IoOyFhLm5leHRTaWJsaW5nOylpZihhPWEucGFyZW50Tm9kZSwhYSlyZXR1cm47Zm9yKHZhciBhPWIoYS5uZXh0U2libGluZywwKSxlOyhlPWEucGFyZW50Tm9kZSkmJmUubm9kZVR5cGU9PT0xOylhPWU7ZC5wdXNoKGEpfXZhciBrPS8oPzpefFxzKW5vY29kZSg/OlxzfCQpLyx0PS9cclxuP3xcbi8scz1hLm93bmVyRG9jdW1lbnQsbDthLmN1cnJlbnRTdHlsZT9sPWEuY3VycmVudFN0eWxlLndoaXRlU3BhY2U6d2luZG93LmdldENvbXB1dGVkU3R5bGUmJihsPXMuZGVmYXVsdFZpZXcuZ2V0Q29tcHV0ZWRTdHlsZShhLHEpLmdldFByb3BlcnR5VmFsdWUoIndoaXRlLXNwYWNlIikpO3ZhciBwPWwmJiJwcmUiPT09bC5zdWJzdHJpbmcoMCwzKTtmb3IobD1zLmNyZWF0ZUVsZW1lbnQoIkxJIik7YS5maXJzdENoaWxkOylsLmFwcGVuZENoaWxkKGEuZmlyc3RDaGlsZCk7Zm9yKHZhciBkPVtsXSxnPTA7ZzxkLmxlbmd0aDsrK2cpZShkW2ddKTttPT09KG18MCkmJmRbMF0uc2V0QXR0cmlidXRlKCJ2YWx1ZSIsCm0pO3ZhciByPXMuY3JlYXRlRWxlbWVudCgiT0wiKTtyLmNsYXNzTmFtZT0ibGluZW51bXMiO2Zvcih2YXIgbj1NYXRoLm1heCgwLG0tMXwwKXx8MCxnPTAsej1kLmxlbmd0aDtnPHo7KytnKWw9ZFtnXSxsLmNsYXNzTmFtZT0iTCIrKGcrbiklMTAsbC5maXJzdENoaWxkfHxsLmFwcGVuZENoaWxkKHMuY3JlYXRlVGV4dE5vZGUoIlx4YTAiKSksci5hcHBlbmRDaGlsZChsKTthLmFwcGVuZENoaWxkKHIpfWZ1bmN0aW9uIGsoYSxtKXtmb3IodmFyIGU9bS5sZW5ndGg7LS1lPj0wOyl7dmFyIGg9bVtlXTtBLmhhc093blByb3BlcnR5KGgpP3dpbmRvdy5jb25zb2xlJiZjb25zb2xlLndhcm4oImNhbm5vdCBvdmVycmlkZSBsYW5ndWFnZSBoYW5kbGVyICVzIixoKTpBW2hdPWF9fWZ1bmN0aW9uIEMoYSxtKXtpZighYXx8IUEuaGFzT3duUHJvcGVydHkoYSkpYT0vXlxzKjwvLnRlc3QobSk/ImRlZmF1bHQtbWFya3VwIjoiZGVmYXVsdC1jb2RlIjtyZXR1cm4gQVthXX1mdW5jdGlvbiBFKGEpe3ZhciBtPQphLmc7dHJ5e3ZhciBlPU0oYS5oKSxoPWUuYTthLmE9aDthLmM9ZS5jO2EuZD0wO0MobSxoKShhKTt2YXIgaz0vXGJNU0lFXGIvLnRlc3QobmF2aWdhdG9yLnVzZXJBZ2VudCksbT0vXG4vZyx0PWEuYSxzPXQubGVuZ3RoLGU9MCxsPWEuYyxwPWwubGVuZ3RoLGg9MCxkPWEuZSxnPWQubGVuZ3RoLGE9MDtkW2ddPXM7dmFyIHIsbjtmb3Iobj1yPTA7bjxnOylkW25dIT09ZFtuKzJdPyhkW3IrK109ZFtuKytdLGRbcisrXT1kW24rK10pOm4rPTI7Zz1yO2ZvcihuPXI9MDtuPGc7KXtmb3IodmFyIHo9ZFtuXSxmPWRbbisxXSxiPW4rMjtiKzI8PWcmJmRbYisxXT09PWY7KWIrPTI7ZFtyKytdPXo7ZFtyKytdPWY7bj1ifWZvcihkLmxlbmd0aD1yO2g8cDspe3ZhciBvPWxbaCsyXXx8cyxjPWRbYSsyXXx8cyxiPU1hdGgubWluKG8sYyksaT1sW2grMV0sajtpZihpLm5vZGVUeXBlIT09MSYmKGo9dC5zdWJzdHJpbmcoZSxiKSkpe2smJihqPWoucmVwbGFjZShtLCJcciIpKTtpLm5vZGVWYWx1ZT0Kajt2YXIgdT1pLm93bmVyRG9jdW1lbnQsdj11LmNyZWF0ZUVsZW1lbnQoIlNQQU4iKTt2LmNsYXNzTmFtZT1kW2ErMV07dmFyIHg9aS5wYXJlbnROb2RlO3gucmVwbGFjZUNoaWxkKHYsaSk7di5hcHBlbmRDaGlsZChpKTtlPG8mJihsW2grMV09aT11LmNyZWF0ZVRleHROb2RlKHQuc3Vic3RyaW5nKGIsbykpLHguaW5zZXJ0QmVmb3JlKGksdi5uZXh0U2libGluZykpfWU9YjtlPj1vJiYoaCs9Mik7ZT49YyYmKGErPTIpfX1jYXRjaCh3KXsiY29uc29sZSJpbiB3aW5kb3cmJmNvbnNvbGUubG9nKHcmJncuc3RhY2s/dy5zdGFjazp3KX19dmFyIHY9WyJicmVhayxjb250aW51ZSxkbyxlbHNlLGZvcixpZixyZXR1cm4sd2hpbGUiXSx3PVtbdiwiYXV0byxjYXNlLGNoYXIsY29uc3QsZGVmYXVsdCxkb3VibGUsZW51bSxleHRlcm4sZmxvYXQsZ290byxpbnQsbG9uZyxyZWdpc3RlcixzaG9ydCxzaWduZWQsc2l6ZW9mLHN0YXRpYyxzdHJ1Y3Qsc3dpdGNoLHR5cGVkZWYsdW5pb24sdW5zaWduZWQsdm9pZCx2b2xhdGlsZSJdLAoiY2F0Y2gsY2xhc3MsZGVsZXRlLGZhbHNlLGltcG9ydCxuZXcsb3BlcmF0b3IscHJpdmF0ZSxwcm90ZWN0ZWQscHVibGljLHRoaXMsdGhyb3csdHJ1ZSx0cnksdHlwZW9mIl0sRj1bdywiYWxpZ25vZixhbGlnbl91bmlvbixhc20sYXhpb20sYm9vbCxjb25jZXB0LGNvbmNlcHRfbWFwLGNvbnN0X2Nhc3QsY29uc3RleHByLGRlY2x0eXBlLGR5bmFtaWNfY2FzdCxleHBsaWNpdCxleHBvcnQsZnJpZW5kLGlubGluZSxsYXRlX2NoZWNrLG11dGFibGUsbmFtZXNwYWNlLG51bGxwdHIscmVpbnRlcnByZXRfY2FzdCxzdGF0aWNfYXNzZXJ0LHN0YXRpY19jYXN0LHRlbXBsYXRlLHR5cGVpZCx0eXBlbmFtZSx1c2luZyx2aXJ0dWFsLHdoZXJlIl0sRz1bdywiYWJzdHJhY3QsYm9vbGVhbixieXRlLGV4dGVuZHMsZmluYWwsZmluYWxseSxpbXBsZW1lbnRzLGltcG9ydCxpbnN0YW5jZW9mLG51bGwsbmF0aXZlLHBhY2thZ2Usc3RyaWN0ZnAsc3VwZXIsc3luY2hyb25pemVkLHRocm93cyx0cmFuc2llbnQiXSwKSD1bRywiYXMsYmFzZSxieSxjaGVja2VkLGRlY2ltYWwsZGVsZWdhdGUsZGVzY2VuZGluZyxkeW5hbWljLGV2ZW50LGZpeGVkLGZvcmVhY2gsZnJvbSxncm91cCxpbXBsaWNpdCxpbixpbnRlcmZhY2UsaW50ZXJuYWwsaW50byxpcyxsb2NrLG9iamVjdCxvdXQsb3ZlcnJpZGUsb3JkZXJieSxwYXJhbXMscGFydGlhbCxyZWFkb25seSxyZWYsc2J5dGUsc2VhbGVkLHN0YWNrYWxsb2Msc3RyaW5nLHNlbGVjdCx1aW50LHVsb25nLHVuY2hlY2tlZCx1bnNhZmUsdXNob3J0LHZhciJdLHc9W3csImRlYnVnZ2VyLGV2YWwsZXhwb3J0LGZ1bmN0aW9uLGdldCxudWxsLHNldCx1bmRlZmluZWQsdmFyLHdpdGgsSW5maW5pdHksTmFOIl0sST1bdiwiYW5kLGFzLGFzc2VydCxjbGFzcyxkZWYsZGVsLGVsaWYsZXhjZXB0LGV4ZWMsZmluYWxseSxmcm9tLGdsb2JhbCxpbXBvcnQsaW4saXMsbGFtYmRhLG5vbmxvY2FsLG5vdCxvcixwYXNzLHByaW50LHJhaXNlLHRyeSx3aXRoLHlpZWxkLEZhbHNlLFRydWUsTm9uZSJdLApKPVt2LCJhbGlhcyxhbmQsYmVnaW4sY2FzZSxjbGFzcyxkZWYsZGVmaW5lZCxlbHNpZixlbmQsZW5zdXJlLGZhbHNlLGluLG1vZHVsZSxuZXh0LG5pbCxub3Qsb3IscmVkbyxyZXNjdWUscmV0cnksc2VsZixzdXBlcix0aGVuLHRydWUsdW5kZWYsdW5sZXNzLHVudGlsLHdoZW4seWllbGQsQkVHSU4sRU5EIl0sdj1bdiwiY2FzZSxkb25lLGVsaWYsZXNhYyxldmFsLGZpLGZ1bmN0aW9uLGluLGxvY2FsLHNldCx0aGVuLHVudGlsIl0sSz0vXihESVJ8RklMRXx2ZWN0b3J8KGRlfHByaW9yaXR5Xyk/cXVldWV8bGlzdHxzdGFja3woY29uc3RfKT9pdGVyYXRvcnwobXVsdGkpPyhzZXR8bWFwKXxiaXRzZXR8dT8oaW50fGZsb2F0KVxkKikvLE49L1xTLyxPPXUoe2tleXdvcmRzOltGLEgsdywiY2FsbGVyLGRlbGV0ZSxkaWUsZG8sZHVtcCxlbHNpZixldmFsLGV4aXQsZm9yZWFjaCxmb3IsZ290byxpZixpbXBvcnQsbGFzdCxsb2NhbCxteSxuZXh0LG5vLG91cixwcmludCxwYWNrYWdlLHJlZG8scmVxdWlyZSxzdWIsdW5kZWYsdW5sZXNzLHVudGlsLHVzZSx3YW50YXJyYXksd2hpbGUsQkVHSU4sRU5EIisKSSxKLHZdLGhhc2hDb21tZW50czohMCxjU3R5bGVDb21tZW50czohMCxtdWx0aUxpbmVTdHJpbmdzOiEwLHJlZ2V4TGl0ZXJhbHM6ITB9KSxBPXt9O2soTyxbImRlZmF1bHQtY29kZSJdKTtrKHgoW10sW1sicGxuIiwvXltePD9dKy9dLFsiZGVjIiwvXjwhXHdbXj5dKig/Oj58JCkvXSxbImNvbSIsL148XCEtLVtcU1xzXSo/KD86LS1cPnwkKS9dLFsibGFuZy0iLC9ePFw/KFtcU1xzXSs/KSg/Olw/PnwkKS9dLFsibGFuZy0iLC9ePCUoW1xTXHNdKz8pKD86JT58JCkvXSxbInB1biIsL14oPzo8WyU/XXxbJT9dPikvXSxbImxhbmctIiwvXjx4bXBcYltePl0qPihbXFNcc10rPyk8XC94bXBcYltePl0qPi9pXSxbImxhbmctanMiLC9ePHNjcmlwdFxiW14+XSo+KFtcU1xzXSo/KSg8XC9zY3JpcHRcYltePl0qPikvaV0sWyJsYW5nLWNzcyIsL148c3R5bGVcYltePl0qPihbXFNcc10qPykoPFwvc3R5bGVcYltePl0qPikvaV0sWyJsYW5nLWluLnRhZyIsL14oPFwvP1thLXpdW148Pl0qPikvaV1dKSwKWyJkZWZhdWx0LW1hcmt1cCIsImh0bSIsImh0bWwiLCJteG1sIiwieGh0bWwiLCJ4bWwiLCJ4c2wiXSk7ayh4KFtbInBsbiIsL15ccysvLHEsIiBcdFxyXG4iXSxbImF0diIsL14oPzoiW14iXSoiP3wnW14nXSonPykvLHEsIlwiJyJdXSxbWyJ0YWciLC9eXjxcLz9bYS16XSg/Oltcdy0uOl0qXHcpP3xcLz8+JC9pXSxbImF0biIsL14oPyFzdHlsZVtccz1dfG9uKVthLXpdKD86W1x3Oi1dKlx3KT8vaV0sWyJsYW5nLXVxLnZhbCIsL149XHMqKFteXHMiJz5dKig/OlteXHMiJy8+XXxcLyg/PVxzKSkpL10sWyJwdW4iLC9eWy88LT5dKy9dLFsibGFuZy1qcyIsL15vblx3K1xzKj1ccyoiKFteIl0rKSIvaV0sWyJsYW5nLWpzIiwvXm9uXHcrXHMqPVxzKicoW14nXSspJy9pXSxbImxhbmctanMiLC9eb25cdytccyo9XHMqKFteXHMiJz5dKykvaV0sWyJsYW5nLWNzcyIsL15zdHlsZVxzKj1ccyoiKFteIl0rKSIvaV0sWyJsYW5nLWNzcyIsL15zdHlsZVxzKj1ccyonKFteJ10rKScvaV0sWyJsYW5nLWNzcyIsCi9ec3R5bGVccyo9XHMqKFteXHMiJz5dKykvaV1dKSxbImluLnRhZyJdKTtrKHgoW10sW1siYXR2IiwvXltcU1xzXSsvXV0pLFsidXEudmFsIl0pO2sodSh7a2V5d29yZHM6RixoYXNoQ29tbWVudHM6ITAsY1N0eWxlQ29tbWVudHM6ITAsdHlwZXM6S30pLFsiYyIsImNjIiwiY3BwIiwiY3h4IiwiY3ljIiwibSJdKTtrKHUoe2tleXdvcmRzOiJudWxsLHRydWUsZmFsc2UifSksWyJqc29uIl0pO2sodSh7a2V5d29yZHM6SCxoYXNoQ29tbWVudHM6ITAsY1N0eWxlQ29tbWVudHM6ITAsdmVyYmF0aW1TdHJpbmdzOiEwLHR5cGVzOkt9KSxbImNzIl0pO2sodSh7a2V5d29yZHM6RyxjU3R5bGVDb21tZW50czohMH0pLFsiamF2YSJdKTtrKHUoe2tleXdvcmRzOnYsaGFzaENvbW1lbnRzOiEwLG11bHRpTGluZVN0cmluZ3M6ITB9KSxbImJzaCIsImNzaCIsInNoIl0pO2sodSh7a2V5d29yZHM6SSxoYXNoQ29tbWVudHM6ITAsbXVsdGlMaW5lU3RyaW5nczohMCx0cmlwbGVRdW90ZWRTdHJpbmdzOiEwfSksClsiY3YiLCJweSJdKTtrKHUoe2tleXdvcmRzOiJjYWxsZXIsZGVsZXRlLGRpZSxkbyxkdW1wLGVsc2lmLGV2YWwsZXhpdCxmb3JlYWNoLGZvcixnb3RvLGlmLGltcG9ydCxsYXN0LGxvY2FsLG15LG5leHQsbm8sb3VyLHByaW50LHBhY2thZ2UscmVkbyxyZXF1aXJlLHN1Yix1bmRlZix1bmxlc3MsdW50aWwsdXNlLHdhbnRhcnJheSx3aGlsZSxCRUdJTixFTkQiLGhhc2hDb21tZW50czohMCxtdWx0aUxpbmVTdHJpbmdzOiEwLHJlZ2V4TGl0ZXJhbHM6ITB9KSxbInBlcmwiLCJwbCIsInBtIl0pO2sodSh7a2V5d29yZHM6SixoYXNoQ29tbWVudHM6ITAsbXVsdGlMaW5lU3RyaW5nczohMCxyZWdleExpdGVyYWxzOiEwfSksWyJyYiJdKTtrKHUoe2tleXdvcmRzOncsY1N0eWxlQ29tbWVudHM6ITAscmVnZXhMaXRlcmFsczohMH0pLFsianMiXSk7ayh1KHtrZXl3b3JkczoiYWxsLGFuZCxieSxjYXRjaCxjbGFzcyxlbHNlLGV4dGVuZHMsZmFsc2UsZmluYWxseSxmb3IsaWYsaW4saXMsaXNudCxsb29wLG5ldyxubyxub3QsbnVsbCxvZixvZmYsb24sb3IscmV0dXJuLHN1cGVyLHRoZW4sdHJ1ZSx0cnksdW5sZXNzLHVudGlsLHdoZW4sd2hpbGUseWVzIiwKaGFzaENvbW1lbnRzOjMsY1N0eWxlQ29tbWVudHM6ITAsbXVsdGlsaW5lU3RyaW5nczohMCx0cmlwbGVRdW90ZWRTdHJpbmdzOiEwLHJlZ2V4TGl0ZXJhbHM6ITB9KSxbImNvZmZlZSJdKTtrKHgoW10sW1sic3RyIiwvXltcU1xzXSsvXV0pLFsicmVnZXgiXSk7d2luZG93LnByZXR0eVByaW50T25lPWZ1bmN0aW9uKGEsbSxlKXt2YXIgaD1kb2N1bWVudC5jcmVhdGVFbGVtZW50KCJQUkUiKTtoLmlubmVySFRNTD1hO2UmJkQoaCxlKTtFKHtnOm0saTplLGg6aH0pO3JldHVybiBoLmlubmVySFRNTH07d2luZG93LnByZXR0eVByaW50PWZ1bmN0aW9uKGEpe2Z1bmN0aW9uIG0oKXtmb3IodmFyIGU9d2luZG93LlBSX1NIT1VMRF9VU0VfQ09OVElOVUFUSU9OP2wubm93KCkrMjUwOkluZmluaXR5O3A8aC5sZW5ndGgmJmwubm93KCk8ZTtwKyspe3ZhciBuPWhbcF0saz1uLmNsYXNzTmFtZTtpZihrLmluZGV4T2YoInByZXR0eXByaW50Iik+PTApe3ZhciBrPWsubWF0Y2goZyksZixiO2lmKGI9CiFrKXtiPW47Zm9yKHZhciBvPXZvaWQgMCxjPWIuZmlyc3RDaGlsZDtjO2M9Yy5uZXh0U2libGluZyl2YXIgaT1jLm5vZGVUeXBlLG89aT09PTE/bz9iOmM6aT09PTM/Ti50ZXN0KGMubm9kZVZhbHVlKT9iOm86bztiPShmPW89PT1iP3ZvaWQgMDpvKSYmIkNPREUiPT09Zi50YWdOYW1lfWImJihrPWYuY2xhc3NOYW1lLm1hdGNoKGcpKTtrJiYoaz1rWzFdKTtiPSExO2ZvcihvPW4ucGFyZW50Tm9kZTtvO289by5wYXJlbnROb2RlKWlmKChvLnRhZ05hbWU9PT0icHJlInx8by50YWdOYW1lPT09ImNvZGUifHxvLnRhZ05hbWU9PT0ieG1wIikmJm8uY2xhc3NOYW1lJiZvLmNsYXNzTmFtZS5pbmRleE9mKCJwcmV0dHlwcmludCIpPj0wKXtiPSEwO2JyZWFrfWJ8fCgoYj0oYj1uLmNsYXNzTmFtZS5tYXRjaCgvXGJsaW5lbnVtc1xiKD86OihcZCspKT8vKSk/YlsxXSYmYlsxXS5sZW5ndGg/K2JbMV06ITA6ITEpJiZEKG4sYiksZD17ZzprLGg6bixpOmJ9LEUoZCkpfX1wPGgubGVuZ3RoP3NldFRpbWVvdXQobSwKMjUwKTphJiZhKCl9Zm9yKHZhciBlPVtkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgicHJlIiksZG9jdW1lbnQuZ2V0RWxlbWVudHNCeVRhZ05hbWUoImNvZGUiKSxkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgieG1wIildLGg9W10saz0wO2s8ZS5sZW5ndGg7KytrKWZvcih2YXIgdD0wLHM9ZVtrXS5sZW5ndGg7dDxzOysrdCloLnB1c2goZVtrXVt0XSk7dmFyIGU9cSxsPURhdGU7bC5ub3d8fChsPXtub3c6ZnVuY3Rpb24oKXtyZXR1cm4rbmV3IERhdGV9fSk7dmFyIHA9MCxkLGc9L1xibGFuZyg/OnVhZ2UpPy0oW1x3Ll0rKSg/IVxTKS87bSgpfTt3aW5kb3cuUFI9e2NyZWF0ZVNpbXBsZUxleGVyOngscmVnaXN0ZXJMYW5nSGFuZGxlcjprLHNvdXJjZURlY29yYXRvcjp1LFBSX0FUVFJJQl9OQU1FOiJhdG4iLFBSX0FUVFJJQl9WQUxVRToiYXR2IixQUl9DT01NRU5UOiJjb20iLFBSX0RFQ0xBUkFUSU9OOiJkZWMiLFBSX0tFWVdPUkQ6Imt3ZCIsUFJfTElURVJBTDoibGl0IiwKUFJfTk9DT0RFOiJub2NvZGUiLFBSX1BMQUlOOiJwbG4iLFBSX1BVTkNUVUFUSU9OOiJwdW4iLFBSX1NPVVJDRToic3JjIixQUl9TVFJJTkc6InN0ciIsUFJfVEFHOiJ0YWciLFBSX1RZUEU6InR5cCJ9fSkoKTsK"></script> <script src="data:application/x-javascript;base64,Ly8gQ29weXJpZ2h0IChDKSAyMDEyIEplZmZyZXkgQi4gQXJub2xkCi8vCi8vIExpY2Vuc2VkIHVuZGVyIHRoZSBBcGFjaGUgTGljZW5zZSwgVmVyc2lvbiAyLjAgKHRoZSAiTGljZW5zZSIpOwovLyB5b3UgbWF5IG5vdCB1c2UgdGhpcyBmaWxlIGV4Y2VwdCBpbiBjb21wbGlhbmNlIHdpdGggdGhlIExpY2Vuc2UuCi8vIFlvdSBtYXkgb2J0YWluIGEgY29weSBvZiB0aGUgTGljZW5zZSBhdAovLwovLyAgICAgIGh0dHA6Ly93d3cuYXBhY2hlLm9yZy9saWNlbnNlcy9MSUNFTlNFLTIuMAovLwovLyBVbmxlc3MgcmVxdWlyZWQgYnkgYXBwbGljYWJsZSBsYXcgb3IgYWdyZWVkIHRvIGluIHdyaXRpbmcsIHNvZnR3YXJlCi8vIGRpc3RyaWJ1dGVkIHVuZGVyIHRoZSBMaWNlbnNlIGlzIGRpc3RyaWJ1dGVkIG9uIGFuICJBUyBJUyIgQkFTSVMsCi8vIFdJVEhPVVQgV0FSUkFOVElFUyBPUiBDT05ESVRJT05TIE9GIEFOWSBLSU5ELCBlaXRoZXIgZXhwcmVzcyBvciBpbXBsaWVkLgovLyBTZWUgdGhlIExpY2Vuc2UgZm9yIHRoZSBzcGVjaWZpYyBsYW5ndWFnZSBnb3Zlcm5pbmcgcGVybWlzc2lvbnMgYW5kCi8vIGxpbWl0YXRpb25zIHVuZGVyIHRoZSBMaWNlbnNlLgoKCi8qKgogKiBAZmlsZW92ZXJ2aWV3CiAqIFJlZ2lzdGVycyBhIGxhbmd1YWdlIGhhbmRsZXIgZm9yIFMsIFMtcGx1cywgYW5kIFIgc291cmNlIGNvZGUuCiAqCiAqCiAqIFRvIHVzZSwgaW5jbHVkZSBwcmV0dGlmeS5qcyBhbmQgdGhpcyBmaWxlIGluIHlvdXIgSFRNTCBwYWdlLgogKiBUaGVuIHB1dCB5b3VyIGNvZGUgaW4gYW4gSFRNTCB0YWcgbGlrZQogKiAgICAgIDxwcmUgY2xhc3M9InByZXR0eXByaW50IGxhbmctciI+IGNvZGUgPC9wcmU+CiAqCiAqIExhbmd1YWdlIGRlZmluaXRpb24gZnJvbQogKiBodHRwOi8vY3Jhbi5yLXByb2plY3Qub3JnL2RvYy9tYW51YWxzL1ItbGFuZy5odG1sLgogKiBNYW55IG9mIHRoZSByZWdleGVzIGFyZSBzaGFyZWQgIHdpdGggdGhlIHB5Z21lbnRzIFNMZXhlciwKICogaHR0cDovL3B5Z21lbnRzLm9yZy8uCiAqCiAqIE9yaWdpbmFsOiBodHRwczovL3Jhdy5naXRodWIuY29tL2pybm9sZC9wcmV0dGlmeS1sYW5nLXItYnVncy9tYXN0ZXIvbGFuZy1yLmpzCiAqCiAqIEBhdXRob3IgamVmZnJleS5hcm5vbGRAZ21haWwuY29tCiAqLwpQUlsncmVnaXN0ZXJMYW5nSGFuZGxlciddKAogICAgUFJbJ2NyZWF0ZVNpbXBsZUxleGVyJ10oCiAgICAgICAgWwogICAgICAgICAgICBbUFJbJ1BSX1BMQUlOJ10sICAgICAgIC9eW1x0XG5cciBceEEwXSsvLCBudWxsLCAnXHRcblxyIFx4QTAnXSwKCSAgICBbUFJbJ1BSX1NUUklORyddLCAgICAgIC9eXCIoPzpbXlwiXFxdfFxcW1xzXFNdKSooPzpcInwkKS8sIG51bGwsICciJ10sCgkgICAgW1BSWydQUl9TVFJJTkcnXSwgICAgICAvXlwnKD86W15cJ1xcXXxcXFtcc1xTXSkqKD86XCd8JCkvLCBudWxsLCAiJyJdCiAgICAgICAgXSwKICAgICAgICBbCiAgICAgICAgICAgIFtQUlsnUFJfQ09NTUVOVCddLCAgICAgL14jLiovXSwKCSAgICBbUFJbJ1BSX0tFWVdPUkQnXSwgICAgIC9eKD86aWZ8ZWxzZXxmb3J8d2hpbGV8cmVwZWF0fGlufG5leHR8YnJlYWt8cmV0dXJufHN3aXRjaHxmdW5jdGlvbikoPyFbQS1aYS16MC05Xy5dKS9dLAoJICAgIC8vIGhleCBudW1iZXMKCSAgICBbUFJbJ1BSX0xJVEVSQUwnXSwgL14wW3hYXVthLWZBLUYwLTldKyhbcFBdWzAtOV0rKT9bTGldPy9dLAoJICAgIC8vIERlY2ltYWwgbnVtYmVycwogICAgICAgICAgICBbUFJbJ1BSX0xJVEVSQUwnXSwgL15bKy1dPyhbMC05XSsoXC5bMC05XSspP3xcLlswLTldKykoW2VFXVsrLV0/WzAtOV0rKT9bTGldPy9dLAoJICAgIC8vIGJ1aWx0aW4gc3ltYm9scwoJICAgIFtQUlsnUFJfTElURVJBTCddLCAvXig/Ok5VTEx8TkEoPzpfKD86aW50ZWdlcnxyZWFsfGNvbXBsZXh8Y2hhcmFjdGVyKV8pP3xJbmZ8VFJVRXxGQUxTRXxOYU58XC5cLig/OlwufFswLTldKykpKD8hW0EtWmEtejAtOV8uXSkvXSwKCSAgICAvLyBhc3NpZ25tZW50LCBvcGVyYXRvcnMsIGFuZCBwYXJlbnMsIGV0Yy4KCSAgICBbUFJbJ1BSX1BVTkNUVUFUSU9OJ10sIC9eKD86PDw/LXwtPj4/fC18PT18PD18Pj18PHw+fCYmP3whPXxcfFx8P3xcKnxcK3xcXnxcL3whfCUuKj8lfD18fnxcJHxAfDp7MSwzfXxbXFtcXSgpe307LD9dKS9dLAoJICAgIC8vIHZhbGlkIHZhcmlhYmxlIG5hbWVzCgkgICAgW1BSWydQUl9QTEFJTiddLCAvXig/OltBLVphLXpdK1tBLVphLXowLTlfLl0qfFwuW2EtekEtWl9dWzAtOWEtekEtWlwuX10qKSg/IVtBLVphLXowLTlfLl0pL10sCgkgICAgLy8gc3RyaW5nIGJhY2t0aWNrCgkgICAgW1BSWydQUl9TVFJJTkcnXSwgL15gLitgL10KICAgICAgICBdKSwKICAgIFsncicsICdzJywgJ1InLCAnUycsICdTcGx1cyddKTsK"></script> <script src="data:application/x-javascript;base64,dmFyIGE9bnVsbDsKUFIucmVnaXN0ZXJMYW5nSGFuZGxlcihQUi5jcmVhdGVTaW1wbGVMZXhlcihbWyJwdW4iLC9eWzo+P3xdKy8sYSwiOnw+PyJdLFsiZGVjIiwvXiUoPzpZQU1MfFRBRylbXlxuXHIjXSsvLGEsIiUiXSxbInR5cCIsL14mXFMrLyxhLCImIl0sWyJ0eXAiLC9eIVxTKi8sYSwiISJdLFsic3RyIiwvXiIoPzpbXiJcXF18XFwuKSooPzoifCQpLyxhLCciJ10sWyJzdHIiLC9eJyg/OlteJ118JycpKig/Oid8JCkvLGEsIiciXSxbImNvbSIsL14jW15cblxyXSovLGEsIiMiXSxbInBsbiIsL15ccysvLGEsIiBcdFxyXG4iXV0sW1siZGVjIiwvXig/Oi0tLXxcLlwuXC4pKD86W1xuXHJdfCQpL10sWyJwdW4iLC9eLS9dLFsia3dkIiwvXlx3KzpbXG5cciBdL10sWyJwbG4iLC9eXHcrL11dKSxbInlhbWwiLCJ5bWwiXSk7Cg=="></script> <script src="data:application/x-javascript;base64,LyoKICogSGFtbWVyLkpTCiAqIHZlcnNpb24gMC40CiAqIGF1dGhvcjogRWlnaHQgTWVkaWEKICogaHR0cHM6Ly9naXRodWIuY29tL0VpZ2h0TWVkaWEvaGFtbWVyLmpzCiAqLwpmdW5jdGlvbiBIYW1tZXIoZWxlbWVudCwgb3B0aW9ucywgdW5kZWZpbmVkKQp7CiAgICB2YXIgc2VsZiA9IHRoaXM7CgogICAgdmFyIGRlZmF1bHRzID0gewogICAgICAgIC8vIHByZXZlbnQgdGhlIGRlZmF1bHQgZXZlbnQgb3Igbm90Li4uIG1pZ2h0IGJlIGJ1Z2d5IHdoZW4gZmFsc2UKICAgICAgICBwcmV2ZW50X2RlZmF1bHQgICAgOiBmYWxzZSwKICAgICAgICBjc3NfaGFja3MgICAgICAgICAgOiB0cnVlLAoKICAgICAgICBkcmFnICAgICAgICAgICAgICAgOiB0cnVlLAogICAgICAgIGRyYWdfdmVydGljYWwgICAgICA6IHRydWUsCiAgICAgICAgZHJhZ19ob3Jpem9udGFsICAgIDogdHJ1ZSwKICAgICAgICAvLyBtaW5pbXVtIGRpc3RhbmNlIGJlZm9yZSB0aGUgZHJhZyBldmVudCBzdGFydHMKICAgICAgICBkcmFnX21pbl9kaXN0YW5jZSAgOiAyMCwgLy8gcGl4ZWxzCgogICAgICAgIC8vIHBpbmNoIHpvb20gYW5kIHJvdGF0aW9uCiAgICAgICAgdHJhbnNmb3JtICAgICAgICAgIDogdHJ1ZSwKICAgICAgICBzY2FsZV90cmVzaG9sZCAgICAgOiAwLjEsCiAgICAgICAgcm90YXRpb25fdHJlc2hvbGQgIDogMTUsIC8vIGRlZ3JlZXMKCiAgICAgICAgdGFwICAgICAgICAgICAgICAgIDogdHJ1ZSwKICAgICAgICB0YXBfZG91YmxlICAgICAgICAgOiB0cnVlLAogICAgICAgIHRhcF9tYXhfaW50ZXJ2YWwgICA6IDMwMCwKICAgICAgICB0YXBfZG91YmxlX2Rpc3RhbmNlOiAyMCwKCiAgICAgICAgaG9sZCAgICAgICAgICAgICAgIDogdHJ1ZSwKICAgICAgICBob2xkX3RpbWVvdXQgICAgICAgOiA1MDAKICAgIH07CiAgICBvcHRpb25zID0gbWVyZ2VPYmplY3QoZGVmYXVsdHMsIG9wdGlvbnMpOwoKICAgIC8vIHNvbWUgY3NzIGhhY2tzCiAgICAoZnVuY3Rpb24oKSB7CiAgICAgICAgaWYoIW9wdGlvbnMuY3NzX2hhY2tzKSB7CiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9CgogICAgICAgIHZhciB2ZW5kb3JzID0gWyd3ZWJraXQnLCdtb3onLCdtcycsJ28nLCcnXTsKICAgICAgICB2YXIgY3NzX3Byb3BzID0gewogICAgICAgICAgICAidXNlclNlbGVjdCI6ICJub25lIiwKICAgICAgICAgICAgInRvdWNoQ2FsbG91dCI6ICJub25lIiwKICAgICAgICAgICAgInVzZXJEcmFnIjogIm5vbmUiLAogICAgICAgICAgICAidGFwSGlnaGxpZ2h0Q29sb3IiOiAicmdiYSgwLDAsMCwwKSIKICAgICAgICB9OwoKICAgICAgICB2YXIgcHJvcCA9ICcnOwogICAgICAgIGZvcih2YXIgaSA9IDA7IGkgPCB2ZW5kb3JzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgIGZvcih2YXIgcCBpbiBjc3NfcHJvcHMpIHsKICAgICAgICAgICAgICAgIHByb3AgPSBwOwogICAgICAgICAgICAgICAgaWYodmVuZG9yc1tpXSkgewogICAgICAgICAgICAgICAgICAgIHByb3AgPSB2ZW5kb3JzW2ldICsgcHJvcC5zdWJzdHJpbmcoMCwgMSkudG9VcHBlckNhc2UoKSArIHByb3Auc3Vic3RyaW5nKDEpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgZWxlbWVudC5zdHlsZVsgcHJvcCBdID0gY3NzX3Byb3BzW3BdOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfSkoKTsKCiAgICAvLyBob2xkcyB0aGUgZGlzdGFuY2UgdGhhdCBoYXMgYmVlbiBtb3ZlZAogICAgdmFyIF9kaXN0YW5jZSA9IDA7CgogICAgLy8gaG9sZHMgdGhlIGV4YWN0IGFuZ2xlIHRoYXQgaGFzIGJlZW4gbW92ZWQKICAgIHZhciBfYW5nbGUgPSAwOwoKICAgIC8vIGhvbGRzIHRoZSBkaXJhY3Rpb24gdGhhdCBoYXMgYmVlbiBtb3ZlZAogICAgdmFyIF9kaXJlY3Rpb24gPSAwOwoKICAgIC8vIGhvbGRzIHBvc2l0aW9uIG1vdmVtZW50IGZvciBzbGlkaW5nCiAgICB2YXIgX3BvcyA9IHsgfTsKCiAgICAvLyBob3cgbWFueSBmaW5nZXJzIGFyZSBvbiB0aGUgc2NyZWVuCiAgICB2YXIgX2ZpbmdlcnMgPSAwOwoKICAgIHZhciBfZmlyc3QgPSBmYWxzZTsKCiAgICB2YXIgX2dlc3R1cmUgPSBudWxsOwogICAgdmFyIF9wcmV2X2dlc3R1cmUgPSBudWxsOwoKICAgIHZhciBfdG91Y2hfc3RhcnRfdGltZSA9IG51bGw7CiAgICB2YXIgX3ByZXZfdGFwX3BvcyA9IHt4OiAwLCB5OiAwfTsKICAgIHZhciBfcHJldl90YXBfZW5kX3RpbWUgPSBudWxsOwoKICAgIHZhciBfaG9sZF90aW1lciA9IG51bGw7CgogICAgdmFyIF9vZmZzZXQgPSB7fTsKCiAgICAvLyBrZWVwIHRyYWNrIG9mIHRoZSBtb3VzZSBzdGF0dXMKICAgIHZhciBfbW91c2Vkb3duID0gZmFsc2U7CgogICAgdmFyIF9ldmVudF9zdGFydDsKICAgIHZhciBfZXZlbnRfbW92ZTsKICAgIHZhciBfZXZlbnRfZW5kOwoKCiAgICAvKioKICAgICAqIGFuZ2xlIHRvIGRpcmVjdGlvbiBkZWZpbmUKICAgICAqIEBwYXJhbSAgZmxvYXQgICAgYW5nbGUKICAgICAqIEByZXR1cm4gc3RyaW5nICAgZGlyZWN0aW9uCiAgICAgKi8KICAgIHRoaXMuZ2V0RGlyZWN0aW9uRnJvbUFuZ2xlID0gZnVuY3Rpb24oIGFuZ2xlICkKICAgIHsKICAgICAgICB2YXIgZGlyZWN0aW9ucyA9IHsKICAgICAgICAgICAgZG93bjogYW5nbGUgPj0gNDUgJiYgYW5nbGUgPCAxMzUsIC8vOTAKICAgICAgICAgICAgbGVmdDogYW5nbGUgPj0gMTM1IHx8IGFuZ2xlIDw9IC0xMzUsIC8vMTgwCiAgICAgICAgICAgIHVwOiBhbmdsZSA8IC00NSAmJiBhbmdsZSA+IC0xMzUsIC8vMjcwCiAgICAgICAgICAgIHJpZ2h0OiBhbmdsZSA+PSAtNDUgJiYgYW5nbGUgPD0gNDUgLy8wCiAgICAgICAgfTsKCiAgICAgICAgdmFyIGRpcmVjdGlvbiwga2V5OwogICAgICAgIGZvcihrZXkgaW4gZGlyZWN0aW9ucyl7CiAgICAgICAgICAgIGlmKGRpcmVjdGlvbnNba2V5XSl7CiAgICAgICAgICAgICAgICBkaXJlY3Rpb24gPSBrZXk7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgfQogICAgICAgIH0KICAgICAgICByZXR1cm4gZGlyZWN0aW9uOwogICAgfTsKCgogICAgLyoqCiAgICAgKiBjb3VudCB0aGUgbnVtYmVyIG9mIGZpbmdlcnMgaW4gdGhlIGV2ZW50CiAgICAgKiB3aGVuIG5vIGZpbmdlcnMgYXJlIGRldGVjdGVkLCBvbmUgZmluZ2VyIGlzIHJldHVybmVkIChtb3VzZSBwb2ludGVyKQogICAgICogQHBhcmFtICBldmVudAogICAgICogQHJldHVybiBpbnQgIGZpbmdlcnMKICAgICAqLwogICAgZnVuY3Rpb24gY291bnRGaW5nZXJzKCBldmVudCApCiAgICB7CiAgICAgICAgLy8gdGhlcmUgaXMgYSBidWcgb24gYW5kcm9pZCAodW50aWwgdjQ/KSB0aGF0IHRvdWNoZXMgaXMgYWx3YXlzIDEsCiAgICAgICAgLy8gc28gbm8gbXVsdGl0b3VjaCBpcyBzdXBwb3J0ZWQsIGUuZy4gbm8sIHpvb20gYW5kIHJvdGF0aW9uLi4uCiAgICAgICAgcmV0dXJuIGV2ZW50LnRvdWNoZXMgPyBldmVudC50b3VjaGVzLmxlbmd0aCA6IDE7CiAgICB9CgoKICAgIC8qKgogICAgICogZ2V0IHRoZSB4IGFuZCB5IHBvc2l0aW9ucyBmcm9tIHRoZSBldmVudCBvYmplY3QKICAgICAqIEBwYXJhbSAgZXZlbnQKICAgICAqIEByZXR1cm4gYXJyYXkgIFt7IHg6IGludCwgeTogaW50IH1dCiAgICAgKi8KICAgIGZ1bmN0aW9uIGdldFhZZnJvbUV2ZW50KCBldmVudCApCiAgICB7CiAgICAgICAgZXZlbnQgPSBldmVudCB8fCB3aW5kb3cuZXZlbnQ7CgogICAgICAgIC8vIG5vIHRvdWNoZXMsIHVzZSB0aGUgZXZlbnQgcGFnZVggYW5kIHBhZ2VZCiAgICAgICAgaWYoIWV2ZW50LnRvdWNoZXMpIHsKICAgICAgICAgICAgdmFyIGRvYyA9IGRvY3VtZW50LAogICAgICAgICAgICAgICAgYm9keSA9IGRvYy5ib2R5OwoKICAgICAgICAgICAgcmV0dXJuIFt7CiAgICAgICAgICAgICAgICB4OiBldmVudC5wYWdlWCB8fCBldmVudC5jbGllbnRYICsgKCBkb2MgJiYgZG9jLnNjcm9sbExlZnQgfHwgYm9keSAmJiBib2R5LnNjcm9sbExlZnQgfHwgMCApIC0gKCBkb2MgJiYgZG9jLmNsaWVudExlZnQgfHwgYm9keSAmJiBkb2MuY2xpZW50TGVmdCB8fCAwICksCiAgICAgICAgICAgICAgICB5OiBldmVudC5wYWdlWSB8fCBldmVudC5jbGllbnRZICsgKCBkb2MgJiYgZG9jLnNjcm9sbFRvcCB8fCBib2R5ICYmIGJvZHkuc2Nyb2xsVG9wIHx8IDAgKSAtICggZG9jICYmIGRvYy5jbGllbnRUb3AgfHwgYm9keSAmJiBkb2MuY2xpZW50VG9wIHx8IDAgKQogICAgICAgICAgICB9XTsKICAgICAgICB9CiAgICAgICAgLy8gbXVsdGl0b3VjaCwgcmV0dXJuIGFycmF5IHdpdGggcG9zaXRpb25zCiAgICAgICAgZWxzZSB7CiAgICAgICAgICAgIHZhciBwb3MgPSBbXSwgc3JjOwogICAgICAgICAgICBmb3IodmFyIHQ9MCwgbGVuPWV2ZW50LnRvdWNoZXMubGVuZ3RoOyB0PGxlbjsgdCsrKSB7CiAgICAgICAgICAgICAgICBzcmMgPSBldmVudC50b3VjaGVzW3RdOwogICAgICAgICAgICAgICAgcG9zLnB1c2goeyB4OiBzcmMucGFnZVgsIHk6IHNyYy5wYWdlWSB9KTsKICAgICAgICAgICAgfQogICAgICAgICAgICByZXR1cm4gcG9zOwogICAgICAgIH0KICAgIH0KCgogICAgLyoqCiAgICAgKiBjYWxjdWxhdGUgdGhlIGFuZ2xlIGJldHdlZW4gdHdvIHBvaW50cwogICAgICogQHBhcmFtIG9iamVjdCBwb3MxIHsgeDogaW50LCB5OiBpbnQgfQogICAgICogQHBhcmFtIG9iamVjdCBwb3MyIHsgeDogaW50LCB5OiBpbnQgfQogICAgICovCiAgICBmdW5jdGlvbiBnZXRBbmdsZSggcG9zMSwgcG9zMiApCiAgICB7CiAgICAgICAgcmV0dXJuIE1hdGguYXRhbjIocG9zMi55IC0gcG9zMS55LCBwb3MyLnggLSBwb3MxLngpICogMTgwIC8gTWF0aC5QSTsKICAgIH0KCiAgICAvKioKICAgICAqIHRyaWdnZXIgYW4gZXZlbnQvY2FsbGJhY2sgYnkgbmFtZSB3aXRoIHBhcmFtcwogICAgICogQHBhcmFtIHN0cmluZyBuYW1lCiAgICAgKiBAcGFyYW0gYXJyYXkgIHBhcmFtcwogICAgICovCiAgICBmdW5jdGlvbiB0cmlnZ2VyRXZlbnQoIGV2ZW50TmFtZSwgcGFyYW1zICkKICAgIHsKICAgICAgICAvLyByZXR1cm4gdG91Y2hlcyBvYmplY3QKICAgICAgICBwYXJhbXMudG91Y2hlcyA9IGdldFhZZnJvbUV2ZW50KHBhcmFtcy5vcmlnaW5hbEV2ZW50KTsKICAgICAgICBwYXJhbXMudHlwZSA9IGV2ZW50TmFtZTsKCiAgICAgICAgLy8gdHJpZ2dlciBjYWxsYmFjawogICAgICAgIGlmKGlzRnVuY3Rpb24oc2VsZlsib24iKyBldmVudE5hbWVdKSkgewogICAgICAgICAgICBzZWxmWyJvbiIrIGV2ZW50TmFtZV0uY2FsbChzZWxmLCBwYXJhbXMpOwogICAgICAgIH0KICAgIH0KCgogICAgLyoqCiAgICAgKiBjYW5jZWwgZXZlbnQKICAgICAqIEBwYXJhbSAgIG9iamVjdCAgZXZlbnQKICAgICAqIEByZXR1cm4gIHZvaWQKICAgICAqLwoKICAgIGZ1bmN0aW9uIGNhbmNlbEV2ZW50KGV2ZW50KXsKICAgICAgICBldmVudCA9IGV2ZW50IHx8IHdpbmRvdy5ldmVudDsKICAgICAgICBpZihldmVudC5wcmV2ZW50RGVmYXVsdCl7CiAgICAgICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7CiAgICAgICAgfWVsc2V7CiAgICAgICAgICAgIGV2ZW50LnJldHVyblZhbHVlID0gZmFsc2U7CiAgICAgICAgICAgIGV2ZW50LmNhbmNlbEJ1YmJsZSA9IHRydWU7CiAgICAgICAgfQogICAgfQoKCiAgICAvKioKICAgICAqIHJlc2V0IHRoZSBpbnRlcm5hbCB2YXJzIHRvIHRoZSBzdGFydCB2YWx1ZXMKICAgICAqLwogICAgZnVuY3Rpb24gcmVzZXQoKQogICAgewogICAgICAgIF9wb3MgPSB7fTsKICAgICAgICBfZmlyc3QgPSBmYWxzZTsKICAgICAgICBfZmluZ2VycyA9IDA7CiAgICAgICAgX2Rpc3RhbmNlID0gMDsKICAgICAgICBfYW5nbGUgPSAwOwogICAgICAgIF9nZXN0dXJlID0gbnVsbDsKICAgIH0KCgogICAgdmFyIGdlc3R1cmVzID0gewogICAgICAgIC8vIGhvbGQgZ2VzdHVyZQogICAgICAgIC8vIGZpcmVkIG9uIHRvdWNoc3RhcnQKICAgICAgICBob2xkIDogZnVuY3Rpb24oZXZlbnQpCiAgICAgICAgewogICAgICAgICAgICAvLyBvbmx5IHdoZW4gb25lIGZpbmdlciBpcyBvbiB0aGUgc2NyZWVuCiAgICAgICAgICAgIGlmKG9wdGlvbnMuaG9sZCkgewogICAgICAgICAgICAgICAgX2dlc3R1cmUgPSAnaG9sZCc7CiAgICAgICAgICAgICAgICBjbGVhclRpbWVvdXQoX2hvbGRfdGltZXIpOwoKICAgICAgICAgICAgICAgIF9ob2xkX3RpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbigpIHsKICAgICAgICAgICAgICAgICAgICBpZihfZ2VzdHVyZSA9PSAnaG9sZCcpIHsKICAgICAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckV2ZW50KCJob2xkIiwgewogICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudCAgIDogZXZlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiAgICAgICAgOiBfcG9zLnN0YXJ0CiAgICAgICAgICAgICAgICAgICAgICAgIH0pOwogICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIH0sIG9wdGlvbnMuaG9sZF90aW1lb3V0KTsKICAgICAgICAgICAgfQogICAgICAgIH0sCgoKICAgICAgICAvLyBkcmFnIGdlc3R1cmUKICAgICAgICAvLyBmaXJlZCBvbiBtb3VzZW1vdmUKICAgICAgICBkcmFnIDogZnVuY3Rpb24oZXZlbnQpCiAgICAgICAgewogICAgICAgICAgICAvLyBnZXQgdGhlIGRpc3RhbmNlIHdlIG1vdmVkCiAgICAgICAgICAgIHZhciBfZGlzdGFuY2VfeCA9IF9wb3MubW92ZVswXS54IC0gX3Bvcy5zdGFydFswXS54OwogICAgICAgICAgICB2YXIgX2Rpc3RhbmNlX3kgPSBfcG9zLm1vdmVbMF0ueSAtIF9wb3Muc3RhcnRbMF0ueTsKICAgICAgICAgICAgX2Rpc3RhbmNlID0gTWF0aC5zcXJ0KF9kaXN0YW5jZV94ICogX2Rpc3RhbmNlX3ggKyBfZGlzdGFuY2VfeSAqIF9kaXN0YW5jZV95KTsKCiAgICAgICAgICAgIC8vIGRyYWcKICAgICAgICAgICAgLy8gbWluaW1hbCBtb3ZlbWVudCByZXF1aXJlZAogICAgICAgICAgICBpZihvcHRpb25zLmRyYWcgJiYgKF9kaXN0YW5jZSA+IG9wdGlvbnMuZHJhZ19taW5fZGlzdGFuY2UpIHx8IF9nZXN0dXJlID09ICdkcmFnJykgewogICAgICAgICAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBhbmdsZQogICAgICAgICAgICAgICAgX2FuZ2xlID0gZ2V0QW5nbGUoX3Bvcy5zdGFydFswXSwgX3Bvcy5tb3ZlWzBdKTsKICAgICAgICAgICAgICAgIF9kaXJlY3Rpb24gPSBzZWxmLmdldERpcmVjdGlvbkZyb21BbmdsZShfYW5nbGUpOwoKICAgICAgICAgICAgICAgIC8vIGNoZWNrIHRoZSBtb3ZlbWVudCBhbmQgc3RvcCBpZiB3ZSBnbyBpbiB0aGUgd3JvbmcgZGlyZWN0aW9uCiAgICAgICAgICAgICAgICB2YXIgaXNfdmVydGljYWwgPSAoX2RpcmVjdGlvbiA9PSAndXAnIHx8IF9kaXJlY3Rpb24gPT0gJ2Rvd24nKTsKICAgICAgICAgICAgICAgIGlmKCgoaXNfdmVydGljYWwgJiYgIW9wdGlvbnMuZHJhZ192ZXJ0aWNhbCkgfHwgKCFpc192ZXJ0aWNhbCAmJiAhb3B0aW9ucy5kcmFnX2hvcml6b250YWwpKQogICAgICAgICAgICAgICAgICAgICYmIChfZGlzdGFuY2UgPiBvcHRpb25zLmRyYWdfbWluX2Rpc3RhbmNlKSkgewogICAgICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICBfZ2VzdHVyZSA9ICdkcmFnJzsKCiAgICAgICAgICAgICAgICB2YXIgcG9zaXRpb24gPSB7IHg6IF9wb3MubW92ZVswXS54IC0gX29mZnNldC5sZWZ0LAogICAgICAgICAgICAgICAgICAgIHk6IF9wb3MubW92ZVswXS55IC0gX29mZnNldC50b3AgfTsKCiAgICAgICAgICAgICAgICB2YXIgZXZlbnRfb2JqID0gewogICAgICAgICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQgICA6IGV2ZW50LAogICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uICAgICAgICA6IHBvc2l0aW9uLAogICAgICAgICAgICAgICAgICAgIGRpcmVjdGlvbiAgICAgICA6IF9kaXJlY3Rpb24sCiAgICAgICAgICAgICAgICAgICAgZGlzdGFuY2UgICAgICAgIDogX2Rpc3RhbmNlLAogICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlWCAgICAgICA6IF9kaXN0YW5jZV94LAogICAgICAgICAgICAgICAgICAgIGRpc3RhbmNlWSAgICAgICA6IF9kaXN0YW5jZV95LAogICAgICAgICAgICAgICAgICAgIGFuZ2xlICAgICAgICAgICA6IF9hbmdsZQogICAgICAgICAgICAgICAgfTsKCiAgICAgICAgICAgICAgICAvLyBvbiB0aGUgZmlyc3QgdGltZSB0cmlnZ2VyIHRoZSBzdGFydCBldmVudAogICAgICAgICAgICAgICAgaWYoX2ZpcnN0KSB7CiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckV2ZW50KCJkcmFnc3RhcnQiLCBldmVudF9vYmopOwoKICAgICAgICAgICAgICAgICAgICBfZmlyc3QgPSBmYWxzZTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyBub3JtYWwgc2xpZGUgZXZlbnQKICAgICAgICAgICAgICAgIHRyaWdnZXJFdmVudCgiZHJhZyIsIGV2ZW50X29iaik7CgogICAgICAgICAgICAgICAgY2FuY2VsRXZlbnQoZXZlbnQpOwogICAgICAgICAgICB9CiAgICAgICAgfSwKCgogICAgICAgIC8vIHRyYW5zZm9ybSBnZXN0dXJlCiAgICAgICAgLy8gZmlyZWQgb24gdG91Y2htb3ZlCiAgICAgICAgdHJhbnNmb3JtIDogZnVuY3Rpb24oZXZlbnQpCiAgICAgICAgewogICAgICAgICAgICBpZihvcHRpb25zLnRyYW5zZm9ybSkgewogICAgICAgICAgICAgICAgdmFyIHNjYWxlID0gZXZlbnQuc2NhbGUgfHwgMTsKICAgICAgICAgICAgICAgIHZhciByb3RhdGlvbiA9IGV2ZW50LnJvdGF0aW9uIHx8IDA7CgogICAgICAgICAgICAgICAgaWYoY291bnRGaW5nZXJzKGV2ZW50KSAhPSAyKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIGlmKF9nZXN0dXJlICE9ICdkcmFnJyAmJgogICAgICAgICAgICAgICAgICAgIChfZ2VzdHVyZSA9PSAndHJhbnNmb3JtJyB8fCBNYXRoLmFicygxLXNjYWxlKSA+IG9wdGlvbnMuc2NhbGVfdHJlc2hvbGQKICAgICAgICAgICAgICAgICAgICAgICAgfHwgTWF0aC5hYnMocm90YXRpb24pID4gb3B0aW9ucy5yb3RhdGlvbl90cmVzaG9sZCkpIHsKICAgICAgICAgICAgICAgICAgICBfZ2VzdHVyZSA9ICd0cmFuc2Zvcm0nOwoKICAgICAgICAgICAgICAgICAgICBfcG9zLmNlbnRlciA9IHsgIHg6ICgoX3Bvcy5tb3ZlWzBdLnggKyBfcG9zLm1vdmVbMV0ueCkgLyAyKSAtIF9vZmZzZXQubGVmdCwKICAgICAgICAgICAgICAgICAgICAgICAgeTogKChfcG9zLm1vdmVbMF0ueSArIF9wb3MubW92ZVsxXS55KSAvIDIpIC0gX29mZnNldC50b3AgfTsKCiAgICAgICAgICAgICAgICAgICAgdmFyIGV2ZW50X29iaiA9IHsKICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudCAgIDogZXZlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uICAgICAgICA6IF9wb3MuY2VudGVyLAogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSAgICAgICAgICAgOiBzY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb24gICAgICAgIDogcm90YXRpb24KICAgICAgICAgICAgICAgICAgICB9OwoKICAgICAgICAgICAgICAgICAgICAvLyBvbiB0aGUgZmlyc3QgdGltZSB0cmlnZ2VyIHRoZSBzdGFydCBldmVudAogICAgICAgICAgICAgICAgICAgIGlmKF9maXJzdCkgewogICAgICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyRXZlbnQoInRyYW5zZm9ybXN0YXJ0IiwgZXZlbnRfb2JqKTsKICAgICAgICAgICAgICAgICAgICAgICAgX2ZpcnN0ID0gZmFsc2U7CiAgICAgICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyRXZlbnQoInRyYW5zZm9ybSIsIGV2ZW50X29iaik7CgogICAgICAgICAgICAgICAgICAgIGNhbmNlbEV2ZW50KGV2ZW50KTsKCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIHJldHVybiBmYWxzZTsKICAgICAgICB9LAoKCiAgICAgICAgLy8gdGFwIGFuZCBkb3VibGUgdGFwIGdlc3R1cmUKICAgICAgICAvLyBmaXJlZCBvbiB0b3VjaGVuZAogICAgICAgIHRhcCA6IGZ1bmN0aW9uKGV2ZW50KQogICAgICAgIHsKICAgICAgICAgICAgLy8gY29tcGFyZSB0aGUga2luZCBvZiBnZXN0dXJlIGJ5IHRpbWUKICAgICAgICAgICAgdmFyIG5vdyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpOwogICAgICAgICAgICB2YXIgdG91Y2hfdGltZSA9IG5vdyAtIF90b3VjaF9zdGFydF90aW1lOwoKICAgICAgICAgICAgLy8gZG9udCBmaXJlIHdoZW4gaG9sZCBpcyBmaXJlZAogICAgICAgICAgICBpZihvcHRpb25zLmhvbGQgJiYgIShvcHRpb25zLmhvbGQgJiYgb3B0aW9ucy5ob2xkX3RpbWVvdXQgPiB0b3VjaF90aW1lKSkgewogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvLyB3aGVuIHByZXZpb3VzIGV2ZW50IHdhcyB0YXAgYW5kIHRoZSB0YXAgd2FzIG1heF9pbnRlcnZhbCBtcyBhZ28KICAgICAgICAgICAgdmFyIGlzX2RvdWJsZV90YXAgPSAoZnVuY3Rpb24oKXsKICAgICAgICAgICAgICAgIGlmIChfcHJldl90YXBfcG9zICYmIG9wdGlvbnMudGFwX2RvdWJsZSAmJiBfcHJldl9nZXN0dXJlID09ICd0YXAnICYmIChfdG91Y2hfc3RhcnRfdGltZSAtIF9wcmV2X3RhcF9lbmRfdGltZSkgPCBvcHRpb25zLnRhcF9tYXhfaW50ZXJ2YWwpIHsKICAgICAgICAgICAgICAgICAgICB2YXIgeF9kaXN0YW5jZSA9IE1hdGguYWJzKF9wcmV2X3RhcF9wb3NbMF0ueCAtIF9wb3Muc3RhcnRbMF0ueCk7CiAgICAgICAgICAgICAgICAgICAgdmFyIHlfZGlzdGFuY2UgPSBNYXRoLmFicyhfcHJldl90YXBfcG9zWzBdLnkgLSBfcG9zLnN0YXJ0WzBdLnkpOwogICAgICAgICAgICAgICAgICAgIHJldHVybiAoX3ByZXZfdGFwX3BvcyAmJiBfcG9zLnN0YXJ0ICYmIE1hdGgubWF4KHhfZGlzdGFuY2UsIHlfZGlzdGFuY2UpIDwgb3B0aW9ucy50YXBfZG91YmxlX2Rpc3RhbmNlKTsKCiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgIH0pKCk7CgogICAgICAgICAgICBpZihpc19kb3VibGVfdGFwKSB7CiAgICAgICAgICAgICAgICBfZ2VzdHVyZSA9ICdkb3VibGVfdGFwJzsKICAgICAgICAgICAgICAgIF9wcmV2X3RhcF9lbmRfdGltZSA9IG51bGw7CgogICAgICAgICAgICAgICAgdHJpZ2dlckV2ZW50KCJkb3VibGV0YXAiLCB7CiAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudCAgIDogZXZlbnQsCiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gICAgICAgIDogX3Bvcy5zdGFydAogICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICBjYW5jZWxFdmVudChldmVudCk7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8vIHNpbmdsZSB0YXAgaXMgc2luZ2xlIHRvdWNoCiAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgX2dlc3R1cmUgPSAndGFwJzsKICAgICAgICAgICAgICAgIF9wcmV2X3RhcF9lbmRfdGltZSA9IG5vdzsKICAgICAgICAgICAgICAgIF9wcmV2X3RhcF9wb3MgPSBfcG9zLnN0YXJ0OwoKICAgICAgICAgICAgICAgIGlmKG9wdGlvbnMudGFwKSB7CiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckV2ZW50KCJ0YXAiLCB7CiAgICAgICAgICAgICAgICAgICAgICAgIG9yaWdpbmFsRXZlbnQgICA6IGV2ZW50LAogICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiAgICAgICAgOiBfcG9zLnN0YXJ0CiAgICAgICAgICAgICAgICAgICAgfSk7CiAgICAgICAgICAgICAgICAgICAgY2FuY2VsRXZlbnQoZXZlbnQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICB9CgogICAgICAgIH0KCiAgICB9OwoKCiAgICBmdW5jdGlvbiBoYW5kbGVFdmVudHMoZXZlbnQpCiAgICB7CiAgICAgICAgc3dpdGNoKGV2ZW50LnR5cGUpCiAgICAgICAgewogICAgICAgICAgICBjYXNlICdtb3VzZWRvd24nOgogICAgICAgICAgICBjYXNlICd0b3VjaHN0YXJ0JzoKICAgICAgICAgICAgICAgIF9wb3Muc3RhcnQgPSBnZXRYWWZyb21FdmVudChldmVudCk7CiAgICAgICAgICAgICAgICBfdG91Y2hfc3RhcnRfdGltZSA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpOwogICAgICAgICAgICAgICAgX2ZpbmdlcnMgPSBjb3VudEZpbmdlcnMoZXZlbnQpOwogICAgICAgICAgICAgICAgX2ZpcnN0ID0gdHJ1ZTsKICAgICAgICAgICAgICAgIF9ldmVudF9zdGFydCA9IGV2ZW50OwoKICAgICAgICAgICAgICAgIC8vIGJvcnJvd2VkIGZyb20ganF1ZXJ5IG9mZnNldCBodHRwczovL2dpdGh1Yi5jb20vanF1ZXJ5L2pxdWVyeS9ibG9iL21hc3Rlci9zcmMvb2Zmc2V0LmpzCiAgICAgICAgICAgICAgICB2YXIgYm94ID0gZWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTsKICAgICAgICAgICAgICAgIHZhciBjbGllbnRUb3AgID0gZWxlbWVudC5jbGllbnRUb3AgIHx8IGRvY3VtZW50LmJvZHkuY2xpZW50VG9wICB8fCAwOwogICAgICAgICAgICAgICAgdmFyIGNsaWVudExlZnQgPSBlbGVtZW50LmNsaWVudExlZnQgfHwgZG9jdW1lbnQuYm9keS5jbGllbnRMZWZ0IHx8IDA7CiAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsVG9wICA9IHdpbmRvdy5wYWdlWU9mZnNldCB8fCBlbGVtZW50LnNjcm9sbFRvcCAgfHwgZG9jdW1lbnQuYm9keS5zY3JvbGxUb3A7CiAgICAgICAgICAgICAgICB2YXIgc2Nyb2xsTGVmdCA9IHdpbmRvdy5wYWdlWE9mZnNldCB8fCBlbGVtZW50LnNjcm9sbExlZnQgfHwgZG9jdW1lbnQuYm9keS5zY3JvbGxMZWZ0OwoKICAgICAgICAgICAgICAgIF9vZmZzZXQgPSB7CiAgICAgICAgICAgICAgICAgICAgdG9wOiBib3gudG9wICsgc2Nyb2xsVG9wIC0gY2xpZW50VG9wLAogICAgICAgICAgICAgICAgICAgIGxlZnQ6IGJveC5sZWZ0ICsgc2Nyb2xsTGVmdCAtIGNsaWVudExlZnQKICAgICAgICAgICAgICAgIH07CgogICAgICAgICAgICAgICAgX21vdXNlZG93biA9IHRydWU7CgogICAgICAgICAgICAgICAgLy8gaG9sZCBnZXN0dXJlCiAgICAgICAgICAgICAgICBnZXN0dXJlcy5ob2xkKGV2ZW50KTsKCiAgICAgICAgICAgICAgICBpZihvcHRpb25zLnByZXZlbnRfZGVmYXVsdCkgewogICAgICAgICAgICAgICAgICAgIGNhbmNlbEV2ZW50KGV2ZW50KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGJyZWFrOwoKICAgICAgICAgICAgY2FzZSAnbW91c2Vtb3ZlJzoKICAgICAgICAgICAgY2FzZSAndG91Y2htb3ZlJzoKICAgICAgICAgICAgICAgIGlmKCFfbW91c2Vkb3duKSB7CiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgX2V2ZW50X21vdmUgPSBldmVudDsKICAgICAgICAgICAgICAgIF9wb3MubW92ZSA9IGdldFhZZnJvbUV2ZW50KGV2ZW50KTsKCiAgICAgICAgICAgICAgICBpZighZ2VzdHVyZXMudHJhbnNmb3JtKGV2ZW50KSkgewogICAgICAgICAgICAgICAgICAgIGdlc3R1cmVzLmRyYWcoZXZlbnQpOwogICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgYnJlYWs7CgogICAgICAgICAgICBjYXNlICdtb3VzZXVwJzoKICAgICAgICAgICAgY2FzZSAnbW91c2VvdXQnOgogICAgICAgICAgICBjYXNlICd0b3VjaGNhbmNlbCc6CiAgICAgICAgICAgIGNhc2UgJ3RvdWNoZW5kJzoKICAgICAgICAgICAgICAgIGlmKCFfbW91c2Vkb3duIHx8IChfZ2VzdHVyZSAhPSAndHJhbnNmb3JtJyAmJiBldmVudC50b3VjaGVzICYmIGV2ZW50LnRvdWNoZXMubGVuZ3RoID4gMCkpIHsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7CiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgX21vdXNlZG93biA9IGZhbHNlOwogICAgICAgICAgICAgICAgX2V2ZW50X2VuZCA9IGV2ZW50OwoKICAgICAgICAgICAgICAgIC8vIGRyYWcgZ2VzdHVyZQogICAgICAgICAgICAgICAgLy8gZHJhZ3N0YXJ0IGlzIHRyaWdnZXJlZCwgc28gZHJhZ2VuZCBpcyBwb3NzaWJsZQogICAgICAgICAgICAgICAgaWYoX2dlc3R1cmUgPT0gJ2RyYWcnKSB7CiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlckV2ZW50KCJkcmFnZW5kIiwgewogICAgICAgICAgICAgICAgICAgICAgICBvcmlnaW5hbEV2ZW50ICAgOiBldmVudCwKICAgICAgICAgICAgICAgICAgICAgICAgZGlyZWN0aW9uICAgICAgIDogX2RpcmVjdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgZGlzdGFuY2UgICAgICAgIDogX2Rpc3RhbmNlLAogICAgICAgICAgICAgICAgICAgICAgICBhbmdsZSAgICAgICAgICAgOiBfYW5nbGUKICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KCiAgICAgICAgICAgICAgICAvLyB0cmFuc2Zvcm0KICAgICAgICAgICAgICAgIC8vIHRyYW5zZm9ybXN0YXJ0IGlzIHRyaWdnZXJlZCwgc28gdHJhbnNmb3JtZWQgaXMgcG9zc2libGUKICAgICAgICAgICAgICAgIGVsc2UgaWYoX2dlc3R1cmUgPT0gJ3RyYW5zZm9ybScpIHsKICAgICAgICAgICAgICAgICAgICB0cmlnZ2VyRXZlbnQoInRyYW5zZm9ybWVuZCIsIHsKICAgICAgICAgICAgICAgICAgICAgICAgb3JpZ2luYWxFdmVudCAgIDogZXZlbnQsCiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uICAgICAgICA6IF9wb3MuY2VudGVyLAogICAgICAgICAgICAgICAgICAgICAgICBzY2FsZSAgICAgICAgICAgOiBldmVudC5zY2FsZSwKICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb24gICAgICAgIDogZXZlbnQucm90YXRpb24KICAgICAgICAgICAgICAgICAgICB9KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgIGVsc2UgewogICAgICAgICAgICAgICAgICAgIGdlc3R1cmVzLnRhcChfZXZlbnRfc3RhcnQpOwogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIF9wcmV2X2dlc3R1cmUgPSBfZ2VzdHVyZTsKCiAgICAgICAgICAgICAgICAvLyByZXNldCB2YXJzCiAgICAgICAgICAgICAgICByZXNldCgpOwogICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgfQogICAgfQoKCiAgICAvLyBiaW5kIGV2ZW50cyBmb3IgdG91Y2ggZGV2aWNlcwogICAgLy8gZXhjZXB0IGZvciB3aW5kb3dzIHBob25lIDcuNSwgaXQgZG9lc250IHN1cHBvcnQgdG91Y2ggZXZlbnRzLi4hCiAgICBpZignb250b3VjaHN0YXJ0JyBpbiB3aW5kb3cpIHsKICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoInRvdWNoc3RhcnQiLCBoYW5kbGVFdmVudHMsIGZhbHNlKTsKICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoInRvdWNobW92ZSIsIGhhbmRsZUV2ZW50cywgZmFsc2UpOwogICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigidG91Y2hlbmQiLCBoYW5kbGVFdmVudHMsIGZhbHNlKTsKICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoInRvdWNoY2FuY2VsIiwgaGFuZGxlRXZlbnRzLCBmYWxzZSk7CiAgICB9CiAgICAvLyBmb3Igbm9uLXRvdWNoCiAgICBlbHNlIHsKCiAgICAgICAgaWYoZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKXsgLy8gcHJldmVudCBvbGQgSUUgZXJyb3JzCiAgICAgICAgICAgIGVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigibW91c2VvdXQiLCBmdW5jdGlvbihldmVudCkgewogICAgICAgICAgICAgICAgaWYoIWlzSW5zaWRlSGFtbWVyKGVsZW1lbnQsIGV2ZW50LnJlbGF0ZWRUYXJnZXQpKSB7CiAgICAgICAgICAgICAgICAgICAgaGFuZGxlRXZlbnRzKGV2ZW50KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwgZmFsc2UpOwogICAgICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoIm1vdXNldXAiLCBoYW5kbGVFdmVudHMsIGZhbHNlKTsKICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJtb3VzZWRvd24iLCBoYW5kbGVFdmVudHMsIGZhbHNlKTsKICAgICAgICAgICAgZWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCJtb3VzZW1vdmUiLCBoYW5kbGVFdmVudHMsIGZhbHNlKTsKCiAgICAgICAgICAgIC8vIGV2ZW50cyBmb3Igb2xkZXIgSUUKICAgICAgICB9ZWxzZSBpZihkb2N1bWVudC5hdHRhY2hFdmVudCl7CiAgICAgICAgICAgIGVsZW1lbnQuYXR0YWNoRXZlbnQoIm9ubW91c2VvdXQiLCBmdW5jdGlvbihldmVudCkgewogICAgICAgICAgICAgICAgaWYoIWlzSW5zaWRlSGFtbWVyKGVsZW1lbnQsIGV2ZW50LnJlbGF0ZWRUYXJnZXQpKSB7CiAgICAgICAgICAgICAgICAgICAgaGFuZGxlRXZlbnRzKGV2ZW50KTsKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfSwgZmFsc2UpOwogICAgICAgICAgICBlbGVtZW50LmF0dGFjaEV2ZW50KCJvbm1vdXNldXAiLCBoYW5kbGVFdmVudHMpOwogICAgICAgICAgICBlbGVtZW50LmF0dGFjaEV2ZW50KCJvbm1vdXNlZG93biIsIGhhbmRsZUV2ZW50cyk7CiAgICAgICAgICAgIGVsZW1lbnQuYXR0YWNoRXZlbnQoIm9ubW91c2Vtb3ZlIiwgaGFuZGxlRXZlbnRzKTsKICAgICAgICB9CiAgICB9CgoKICAgIC8qKgogICAgICogZmluZCBpZiBlbGVtZW50IGlzIChpbnNpZGUpIGdpdmVuIHBhcmVudCBlbGVtZW50CiAgICAgKiBAcGFyYW0gICBvYmplY3QgIGVsZW1lbnQKICAgICAqIEBwYXJhbSAgIG9iamVjdCAgcGFyZW50CiAgICAgKiBAcmV0dXJuICBib29sICAgIGluc2lkZQogICAgICovCiAgICBmdW5jdGlvbiBpc0luc2lkZUhhbW1lcihwYXJlbnQsIGNoaWxkKSB7CiAgICAgICAgLy8gZ2V0IHJlbGF0ZWQgdGFyZ2V0IGZvciBJRQogICAgICAgIGlmKCFjaGlsZCAmJiB3aW5kb3cuZXZlbnQgJiYgd2luZG93LmV2ZW50LnRvRWxlbWVudCl7CiAgICAgICAgICAgIGNoaWxkID0gd2luZG93LmV2ZW50LnRvRWxlbWVudDsKICAgICAgICB9CgogICAgICAgIGlmKHBhcmVudCA9PT0gY2hpbGQpewogICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICB9CgogICAgICAgIC8vIGxvb3Agb3ZlciBwYXJlbnROb2RlcyBvZiBjaGlsZCB1bnRpbCB3ZSBmaW5kIGhhbW1lciBlbGVtZW50CiAgICAgICAgaWYoY2hpbGQpewogICAgICAgICAgICB2YXIgbm9kZSA9IGNoaWxkLnBhcmVudE5vZGU7CiAgICAgICAgICAgIHdoaWxlKG5vZGUgIT09IG51bGwpewogICAgICAgICAgICAgICAgaWYobm9kZSA9PT0gcGFyZW50KXsKICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTsKICAgICAgICAgICAgICAgIH07CiAgICAgICAgICAgICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIHJldHVybiBmYWxzZTsKICAgIH0KCgogICAgLyoqCiAgICAgKiBtZXJnZSAyIG9iamVjdHMgaW50byBhIG5ldyBvYmplY3QKICAgICAqIEBwYXJhbSAgIG9iamVjdCAgb2JqMQogICAgICogQHBhcmFtICAgb2JqZWN0ICBvYmoyCiAgICAgKiBAcmV0dXJuICBvYmplY3QgIG1lcmdlZCBvYmplY3QKICAgICAqLwogICAgZnVuY3Rpb24gbWVyZ2VPYmplY3Qob2JqMSwgb2JqMikgewogICAgICAgIHZhciBvdXRwdXQgPSB7fTsKCiAgICAgICAgaWYoIW9iajIpIHsKICAgICAgICAgICAgcmV0dXJuIG9iajE7CiAgICAgICAgfQoKICAgICAgICBmb3IgKHZhciBwcm9wIGluIG9iajEpIHsKICAgICAgICAgICAgaWYgKHByb3AgaW4gb2JqMikgewogICAgICAgICAgICAgICAgb3V0cHV0W3Byb3BdID0gb2JqMltwcm9wXTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIG91dHB1dFtwcm9wXSA9IG9iajFbcHJvcF07CiAgICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgcmV0dXJuIG91dHB1dDsKICAgIH0KCiAgICBmdW5jdGlvbiBpc0Z1bmN0aW9uKCBvYmogKXsKICAgICAgICByZXR1cm4gT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKCBvYmogKSA9PSAiW29iamVjdCBGdW5jdGlvbl0iOwogICAgfQp9"></script> <script src="data:application/x-javascript;base64,KGZ1bmN0aW9uKHdpbmRvdykgewoKdmFyIE9SSUdJTl8gPSBsb2NhdGlvbi5wcm90b2NvbCArICcvLycgKyBsb2NhdGlvbi5ob3N0OwoKLy8gY2hlY2sgZm9yIGxvY2FsIHN0b3JhZ2UKdmFyIGhhdmVMb2NhbFN0b3JhZ2UgPSAoZnVuY3Rpb24oKSB7CiAgdmFyIG1vZCA9ICdtb2QnOwogIHRyeSB7CiAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShtb2QsIG1vZCk7CiAgICBsb2NhbFN0b3JhZ2UucmVtb3ZlSXRlbShtb2QpOwogICAgcmV0dXJuIHRydWU7CiAgfSBjYXRjaChlKSB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9KCkpOwoKZnVuY3Rpb24gU2xpZGVDb250cm9sbGVyKCkgewogIHRoaXMucG9wdXAgPSBudWxsOwogIHRoaXMuaXNQb3B1cCA9IHdpbmRvdy5vcGVuZXI7CgogIGlmICh0aGlzLnNldHVwRG9uZSgpKSB7CiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbWVzc2FnZScsIHRoaXMub25NZXNzYWdlXy5iaW5kKHRoaXMpLCBmYWxzZSk7CgogICAgLy8gQ2xvc2UgcG9wdXBzIGlmIHdlIHJlbG9hZCB0aGUgbWFpbiB3aW5kb3cuCiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignYmVmb3JldW5sb2FkJywgZnVuY3Rpb24oZSkgewogICAgICBpZiAodGhpcy5wb3B1cCkgewogICAgICAgIHRoaXMucG9wdXAuY2xvc2UoKTsKICAgICAgfQogICAgfS5iaW5kKHRoaXMpLCBmYWxzZSk7CiAgfQp9CgpTbGlkZUNvbnRyb2xsZXIuUFJFU0VOVEVSX01PREVfUEFSQU0gPSAncHJlc2VudG1lJzsKClNsaWRlQ29udHJvbGxlci5wcm90b3R5cGUuc2V0dXBEb25lID0gZnVuY3Rpb24oKSB7CiAgdmFyIHBhcmFtcyA9IGxvY2F0aW9uLnNlYXJjaC5zdWJzdHJpbmcoMSkuc3BsaXQoJyYnKS5tYXAoZnVuY3Rpb24oZWwpIHsKICAgIHJldHVybiBlbC5zcGxpdCgnPScpOwogIH0pOwoKICB2YXIgcHJlc2VudE1lID0gbnVsbDsKICBmb3IgKHZhciBpID0gMCwgcGFyYW07IHBhcmFtID0gcGFyYW1zW2ldOyArK2kpIHsKICAgIGlmIChwYXJhbVswXS50b0xvd2VyQ2FzZSgpID09IFNsaWRlQ29udHJvbGxlci5QUkVTRU5URVJfTU9ERV9QQVJBTSkgewogICAgICBwcmVzZW50TWUgPSBwYXJhbVsxXSA9PSAndHJ1ZSc7CiAgICAgIGJyZWFrOwogICAgfQogIH0KCiAgaWYgKHByZXNlbnRNZSAhPT0gbnVsbCkgewogICAgaWYgKGhhdmVMb2NhbFN0b3JhZ2UpCiAgICAgIGxvY2FsU3RvcmFnZS5FTkFCTEVfUFJFU0VOVE9SX01PREUgPSBwcmVzZW50TWU7CiAgICAvLyBUT0RPOiB1c2Ugd2luZG93Lmhpc3RvcnkucHVzaFN0YXRlIHRvIHVwZGF0ZSBVUkwgaW5zdGVhZCBvZiB0aGUgcmVkaXJlY3QuCiAgICBpZiAod2luZG93Lmhpc3RvcnkucmVwbGFjZVN0YXRlKSB7CiAgICAgIHdpbmRvdy5oaXN0b3J5LnJlcGxhY2VTdGF0ZSh7fSwgJycsIGxvY2F0aW9uLnBhdGhuYW1lKTsKICAgIH0gZWxzZSB7CiAgICAgIGxvY2F0aW9uLnJlcGxhY2UobG9jYXRpb24ucGF0aG5hbWUpOwogICAgICByZXR1cm4gZmFsc2U7CiAgICB9CiAgfQoKICB2YXIgZW5hYmxlUHJlc2VudGVyTW9kZSA9IGhhdmVMb2NhbFN0b3JhZ2UgJiYgbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ0VOQUJMRV9QUkVTRU5UT1JfTU9ERScpOwogIGlmIChlbmFibGVQcmVzZW50ZXJNb2RlICYmIEpTT04ucGFyc2UoZW5hYmxlUHJlc2VudGVyTW9kZSkpIHsKICAgIC8vIE9ubHkgb3BlbiBwb3B1cCBmcm9tIG1haW4gZGVjay4gRG9uJ3Qgd2FudCByZWN1cnNpdmUgcG9wdXAgb3BlbmluZyEKICAgIGlmICghdGhpcy5pc1BvcHVwKSB7CiAgICAgIHZhciBvcHRzID0gJ21lbnViYXI9bm8sbG9jYXRpb249eWVzLHJlc2l6YWJsZT15ZXMsc2Nyb2xsYmFycz1ubyxzdGF0dXM9bm8nOwogICAgICB0aGlzLnBvcHVwID0gd2luZG93Lm9wZW4obG9jYXRpb24uaHJlZiwgJ215d2luZG93Jywgb3B0cyk7CgogICAgICAvLyBMb2FkaW5nIGluIHRoZSBwb3B1cD8gVHJpZ2dlciB0aGUgaG90a2V5IGZvciB0dXJuaW5nIHByZXNlbnRlciBtb2RlIG9uLgogICAgICB0aGlzLnBvcHVwLmFkZEV2ZW50TGlzdGVuZXIoJ2xvYWQnLCBmdW5jdGlvbihlKSB7CiAgICAgICAgdmFyIGV2dCA9IHRoaXMucG9wdXAuZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7CiAgICAgICAgZXZ0LmluaXRFdmVudCgna2V5ZG93bicsIHRydWUsIHRydWUpOwogICAgICAgIGV2dC5rZXlDb2RlID0gJ1AnLmNoYXJDb2RlQXQoMCk7CiAgICAgICAgdGhpcy5wb3B1cC5kb2N1bWVudC5kaXNwYXRjaEV2ZW50KGV2dCk7CiAgICAgICAgLy8gdGhpcy5wb3B1cC5kb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ3dpdGgtbm90ZXMnKTsKICAgICAgICAvLyBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5hZGQoJ3BvcHVwJyk7CiAgICAgIH0uYmluZCh0aGlzKSwgZmFsc2UpOwogICAgfQogIH0KCiAgcmV0dXJuIHRydWU7Cn0KClNsaWRlQ29udHJvbGxlci5wcm90b3R5cGUub25NZXNzYWdlXyA9IGZ1bmN0aW9uKGUpIHsKICB2YXIgZGF0YSA9IGUuZGF0YTsKCiAgLy8gUmVzdHJpY3QgbWVzc2FnZXMgdG8gYmVpbmcgZnJvbSB0aGlzIG9yaWdpbi4gQWxsb3cgbG9jYWwgZGV2ZWxvcG1ldAogIC8vIGZyb20gZmlsZTovLyB0aG91Z2guCiAgLy8gVE9ETzogSXQgd291bGQgYmUgZG9wZSBpZiBGRiBpbXBsZW1lbnRlZCBsb2NhdGlvbi5vcmlnaW4hCiAgaWYgKGUub3JpZ2luICE9IE9SSUdJTl8gJiYgT1JJR0lOXy5pbmRleE9mKCdmaWxlOi8vJykgIT0gMCkgewogICAgLy8gSWdub3JlIG1lc3NhZ2VzIGZyb20gdW5yZWNvZ25pemVkIG9yaWdpbnMKICAgIHJldHVybjsKICB9CgogIC8vIGlmIChlLnNvdXJjZS5sb2NhdGlvbi5ob3N0bmFtZSAhPSAnbG9jYWxob3N0JykgewogIC8vICAgYWxlcnQoJ1NvbWVvbmUgdHJpZWQgdG8gcG9zdE1lc3NhZ2UgZnJvbSBhbiB1bmtub3duIG9yaWdpbicpOwogIC8vICAgcmV0dXJuOwogIC8vIH0KCiAgaWYgKCdrZXlDb2RlJyBpbiBkYXRhKSB7CiAgICB2YXIgZXZ0ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0V2ZW50Jyk7CiAgICBldnQuaW5pdEV2ZW50KCdrZXlkb3duJywgdHJ1ZSwgdHJ1ZSk7CiAgICBldnQua2V5Q29kZSA9IGRhdGEua2V5Q29kZTsKICAgIGRvY3VtZW50LmRpc3BhdGNoRXZlbnQoZXZ0KTsKICB9Cn07CgpTbGlkZUNvbnRyb2xsZXIucHJvdG90eXBlLnNlbmRNc2cgPSBmdW5jdGlvbihtc2cpIHsKICAvLyAvLyBTZW5kIG1lc3NhZ2UgdG8gcG9wdXAgd2luZG93LgogIC8vIGlmICh0aGlzLnBvcHVwKSB7CiAgLy8gICB0aGlzLnBvcHVwLnBvc3RNZXNzYWdlKG1zZywgT1JJR0lOXyk7CiAgLy8gfQoKICAvLyBTZW5kIG1lc3NhZ2UgdG8gbWFpbiB3aW5kb3cuCiAgaWYgKHRoaXMuaXNQb3B1cCkgewogICAgLy8gVE9ETzogSXQgd291bGQgYmUgZG9wZSBpZiBGRiBpbXBsZW1lbnRlZCBsb2NhdGlvbi5vcmlnaW4uCiAgICB3aW5kb3cub3BlbmVyLnBvc3RNZXNzYWdlKG1zZywgJyonKTsKICB9Cn07Cgp3aW5kb3cuU2xpZGVDb250cm9sbGVyID0gU2xpZGVDb250cm9sbGVyOwoKfSkod2luZG93KTsKCg=="></script> <script src="data:application/x-javascript;base64,LyoqCiAqIEBhdXRob3JzIEx1a2UgTWFoZQogKiBAYXV0aG9ycyBFcmljIEJpZGVsbWFuCiAqIEBmaWxlb3ZlcnZpZXcgVE9ETwogKi8KZG9jdW1lbnQuY2FuY2VsRnVsbFNjcmVlbiA9IGRvY3VtZW50LndlYmtpdENhbmNlbEZ1bGxTY3JlZW4gfHwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvY3VtZW50Lm1vekNhbmNlbEZ1bGxTY3JlZW47CgovKioKICogQGNvbnN0cnVjdG9yCiAqLwpmdW5jdGlvbiBTbGlkZURlY2soZWwpIHsKICB0aGlzLmN1clNsaWRlXyA9IDA7CiAgdGhpcy5wcmV2U2xpZGVfID0gMDsKICB0aGlzLmNvbmZpZ18gPSBudWxsOwogIHRoaXMuY29udGFpbmVyID0gZWwgfHwgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignc2xpZGVzJyk7CiAgdGhpcy5zbGlkZXMgPSBbXTsKICB0aGlzLmNvbnRyb2xsZXIgPSBudWxsOwoKICB0aGlzLmdldEN1cnJlbnRTbGlkZUZyb21IYXNoXygpOwoKICAvLyBDYWxsIHRoaXMgZXhwbGljaXRseS4gTW9kZXJuaXpyLmxvYWQgd29uJ3QgYmUgZG9uZSB1bnRpbCBhZnRlciBET00gbG9hZC4KICB0aGlzLm9uRG9tTG9hZGVkXy5iaW5kKHRoaXMpKCk7Cn0KCi8qKgogKiBAY29uc3QKICogQHByaXZhdGUKICovClNsaWRlRGVjay5wcm90b3R5cGUuU0xJREVfQ0xBU1NFU18gPSBbCiAgJ2Zhci1wYXN0JywgJ3Bhc3QnLCAnY3VycmVudCcsICduZXh0JywgJ2Zhci1uZXh0J107CgovKioKICogQGNvbnN0CiAqIEBwcml2YXRlCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLkNTU19ESVJfID0gJ3RoZW1lL2Nzcy8nOwoKLyoqCiAqIEBwcml2YXRlCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLmdldEN1cnJlbnRTbGlkZUZyb21IYXNoXyA9IGZ1bmN0aW9uKCkgewogIHZhciBzbGlkZU5vID0gcGFyc2VJbnQoZG9jdW1lbnQubG9jYXRpb24uaGFzaC5zdWJzdHIoMSkpOwoKICBpZiAoc2xpZGVObykgewogICAgdGhpcy5jdXJTbGlkZV8gPSBzbGlkZU5vIC0gMTsKICB9IGVsc2UgewogICAgdGhpcy5jdXJTbGlkZV8gPSAwOwogIH0KfTsKCi8qKgogKiBAcGFyYW0ge251bWJlcn0gc2xpZGVObwogKi8KU2xpZGVEZWNrLnByb3RvdHlwZS5sb2FkU2xpZGUgPSBmdW5jdGlvbihzbGlkZU5vKSB7CiAgaWYgKHNsaWRlTm8pIHsKICAgIHRoaXMuY3VyU2xpZGVfID0gc2xpZGVObyAtIDE7CiAgICB0aGlzLnVwZGF0ZVNsaWRlc18oKTsKICB9Cn07CgovKioKICogQHByaXZhdGUKICovClNsaWRlRGVjay5wcm90b3R5cGUub25Eb21Mb2FkZWRfID0gZnVuY3Rpb24oZSkgewogIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LmFkZCgnbG9hZGVkJyk7IC8vIEFkZCBsb2FkZWQgY2xhc3MgZm9yIHRlbXBsYXRlcyB0byB1c2UuCgogIHRoaXMuc2xpZGVzID0gdGhpcy5jb250YWluZXIucXVlcnlTZWxlY3RvckFsbCgnc2xpZGU6bm90KFtoaWRkZW5dKTpub3QoLmhpZGRlbik6bm90KC5iYWNrZHJvcCknKTsKCiAgLy8gSWYgd2UncmUgb24gYSBzbWFydHBob25lLCBhcHBseSBzcGVjaWFsIHNhdWNlLgogIGlmIChNb2Rlcm5penIubXEoJ29ubHkgc2NyZWVuIGFuZCAobWF4LWRldmljZS13aWR0aDogNDgwcHgpJykpIHsKICAgIC8vIHZhciBzdHlsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTsKICAgIC8vIHN0eWxlLnJlbCA9ICdzdHlsZXNoZWV0JzsKICAgIC8vIHN0eWxlLnR5cGUgPSAndGV4dC9jc3MnOwogICAgLy8gc3R5bGUuaHJlZiA9IHRoaXMuQ1NTX0RJUl8gKyAncGhvbmUuY3NzJzsKICAgIC8vIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2hlYWQnKS5hcHBlbmRDaGlsZChzdHlsZSk7CgogICAgLy8gTm8gbmVlZCBmb3Igd2lkZXNjcmVlbiBsYXlvdXQgb24gYSBwaG9uZS4KICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC5yZW1vdmUoJ2xheW91dC13aWRlc2NyZWVuJyk7CiAgfQoKICB0aGlzLmxvYWRDb25maWdfKFNMSURFX0NPTkZJRyk7CiAgdGhpcy5hZGRFdmVudExpc3RlbmVyc18oKTsKICB0aGlzLnVwZGF0ZVNsaWRlc18oKTsKCiAgLy8gQWRkIHNsaWRlIG51bWJlcnMgYW5kIHRvdGFsIHNsaWRlIGNvdW50IG1ldGFkYXRhIHRvIGVhY2ggc2xpZGUuCiAgdmFyIHRoYXQgPSB0aGlzOwogIGZvciAodmFyIGkgPSAwLCBzbGlkZTsgc2xpZGUgPSB0aGlzLnNsaWRlc1tpXTsgKytpKSB7CiAgICBzbGlkZS5kYXRhc2V0LnNsaWRlTnVtID0gaSArIDE7CiAgICBzbGlkZS5kYXRhc2V0LnRvdGFsU2xpZGVzID0gdGhpcy5zbGlkZXMubGVuZ3RoOwoKICAgIHNsaWRlLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgZnVuY3Rpb24oZSkgewogICAgICBpZiAoZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuY29udGFpbnMoJ292ZXJ2aWV3JykpIHsKICAgICAgICB0aGF0LmxvYWRTbGlkZSh0aGlzLmRhdGFzZXQuc2xpZGVOdW0pOwogICAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgICB3aW5kb3cuc2V0VGltZW91dChmdW5jdGlvbigpIHsKICAgICAgICAgIHRoYXQudG9nZ2xlT3ZlcnZpZXcoKTsKICAgICAgICB9LCA1MDApOwogICAgICB9CiAgICB9LCBmYWxzZSk7CiAgfQoKICAvLyBOb3RlOiB0aGlzIG5lZWRzIHRvIGNvbWUgYWZ0ZXIgYWRkRXZlbnRMaXN0ZW5lcnNfKCksIHdoaWNoIGFkZHMgYQogIC8vICdrZXlkb3duJyBsaXN0ZW5lciB0aGF0IHRoaXMgY29udHJvbGxlciByZWxpZXMgb24uCgogIC8vIE1vZGVybml6ci50b3VjaCBpc24ndCBhIHN1ZmZpY2llbnQgY2hlY2sgZm9yIGRldmljZXMgdGhhdCBzdXBwb3J0IGJvdGgKICAvLyB0b3VjaCBhbmQgbW91c2UuIENyZWF0ZSB0aGUgY29udHJvbGxlciBpbiBhbGwgY2FzZXMuCiAgLy8gLy8gQWxzbywgbm8gbmVlZCB0byBzZXQgdGhpcyB1cCBpZiB3ZSdyZSBvbiBtb2JpbGUuCiAgLy8gaWYgKCFNb2Rlcm5penIudG91Y2gpIHsKICAgIHRoaXMuY29udHJvbGxlciA9IG5ldyBTbGlkZUNvbnRyb2xsZXIodGhpcyk7CiAgICBpZiAodGhpcy5jb250cm9sbGVyLmlzUG9wdXApIHsKICAgICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuYWRkKCdwb3B1cCcpOwogICAgfQogIC8vfQp9OwoKLyoqCiAqIEBwcml2YXRlCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLmFkZEV2ZW50TGlzdGVuZXJzXyA9IGZ1bmN0aW9uKCkgewogIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLm9uQm9keUtleURvd25fLmJpbmQodGhpcyksIHRydWUpOwogIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdwb3BzdGF0ZScsIHRoaXMub25Qb3BTdGF0ZV8uYmluZCh0aGlzKSwgZmFsc2UpOwoKICAvLyB2YXIgdHJhbnNFbmRFdmVudE5hbWVzID0gewogIC8vICAgJ1dlYmtpdFRyYW5zaXRpb24nOiAnd2Via2l0VHJhbnNpdGlvbkVuZCcsCiAgLy8gICAnTW96VHJhbnNpdGlvbic6ICd0cmFuc2l0aW9uZW5kJywKICAvLyAgICdPVHJhbnNpdGlvbic6ICdvVHJhbnNpdGlvbkVuZCcsCiAgLy8gICAnbXNUcmFuc2l0aW9uJzogJ01TVHJhbnNpdGlvbkVuZCcsCiAgLy8gICAndHJhbnNpdGlvbic6ICd0cmFuc2l0aW9uZW5kJwogIC8vIH07CiAgLy8KICAvLyAvLyBGaW5kIHRoZSBjb3JyZWN0IHRyYW5zaXRpb25FbmQgdmVuZG9yIHByZWZpeC4KICAvLyB3aW5kb3cudHJhbnNFbmRFdmVudE5hbWUgPSB0cmFuc0VuZEV2ZW50TmFtZXNbCiAgLy8gICAgIE1vZGVybml6ci5wcmVmaXhlZCgndHJhbnNpdGlvbicpXTsKICAvLwogIC8vIC8vIFdoZW4gc2xpZGVzIGFyZSBkb25lIHRyYW5zaXRpb25pbmcsIGtpY2tvZmYgbG9hZGluZyBpZnJhbWVzLgogIC8vIC8vIE5vdGU6IHdlJ3JlIG9ubHkgbG9va2luZyBhdCBhIHNpbmdsZSB0cmFuc2l0aW9uIChvbiB0aGUgc2xpZGUpLiBUaGlzCiAgLy8gLy8gZG9lc24ndCBpbmNsdWRlIGF1dG9idWlsZHMgdGhlIHNsaWRlcyBtYXkgaGF2ZS4gQWxzbywgaWYgdGhlIHNsaWRlCiAgLy8gLy8gdHJhbnNpdGlvbnMgb24gbXVsdGlwbGUgcHJvcGVydGllcyAoZS5nLiBub3QganVzdCAnYWxsJyksIHRoaXMgZG9lc24ndAogIC8vIC8vIGhhbmRsZSB0aGF0IGNhc2UuCiAgLy8gdGhpcy5jb250YWluZXIuYWRkRXZlbnRMaXN0ZW5lcih0cmFuc0VuZEV2ZW50TmFtZSwgZnVuY3Rpb24oZSkgewogIC8vICAgICB0aGlzLmVuYWJsZVNsaWRlRnJhbWVzXyh0aGlzLmN1clNsaWRlXyk7CiAgLy8gfS5iaW5kKHRoaXMpLCBmYWxzZSk7CgogIC8vIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3NsaWRlZW50ZXInLCBmdW5jdGlvbihlKSB7CiAgLy8gICB2YXIgc2xpZGUgPSBlLnRhcmdldDsKICAvLyAgIHdpbmRvdy5zZXRUaW1lb3V0KGZ1bmN0aW9uKCkgewogIC8vICAgICB0aGlzLmVuYWJsZVNsaWRlRnJhbWVzXyhlLnNsaWRlTnVtYmVyKTsKICAvLyAgICAgdGhpcy5lbmFibGVTbGlkZUZyYW1lc18oZS5zbGlkZU51bWJlciArIDEpOwogIC8vICAgfS5iaW5kKHRoaXMpLCAzMDApOwogIC8vIH0uYmluZCh0aGlzKSwgZmFsc2UpOwp9OwoKLyoqCiAqIEBwcml2YXRlCiAqIEBwYXJhbSB7RXZlbnR9IGUgVGhlIHBvcCBldmVudC4KICovClNsaWRlRGVjay5wcm90b3R5cGUub25Qb3BTdGF0ZV8gPSBmdW5jdGlvbihlKSB7CiAgaWYgKGUuc3RhdGUgIT0gbnVsbCkgewogICAgdGhpcy5jdXJTbGlkZV8gPSBlLnN0YXRlOwogICAgdGhpcy51cGRhdGVTbGlkZXNfKHRydWUpOwogIH0KfTsKCi8qKgogKiBAcGFyYW0ge0V2ZW50fSBlCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLm9uQm9keUtleURvd25fID0gZnVuY3Rpb24oZSkgewoKICAvLyBEb24ndCBoYW5kbGUga2V5cyBpZiBhbiBpbnB1dCBvciB0ZXh0IGFyZWEgaXMgYWN0aXZlLiBEbyBzcGVjaWFsIGhhbmRsaW5nCiAgLy8gZm9yIHNlbGVjdGl6ZSBiZWNhdXNlIGl0IGtlZXBzIGZvY3VzIHdpdGhpbiBhbiBvZmZzY3JlZW4gdGV4dGJveCBldmVuCiAgLy8gd2hlbiBqdXN0IHRoZSBzZWxlY3QgY29udHJvbCBpcyBzaG93aW5nIC0tIGZvciBzZWxlY3RpemUgd2UgcmVmcmFpbiBmcm9tCiAgLy8gaGFuZGxpbmcga2V5cyBvbmx5IHdoZW4gdGhlIHRleHQgaW5wdXQgaXMgYWN0aXZlIG9yIHdoZW4gdGhlIHVwIG9yIGRvd24KICAvLyBhcnJvdyBrZXkgaXMgcHJlc3NlZCAod2hpY2ggaXMgdXNlZCB0byBvcGVuIHRoZSBsaXN0IGZyb20gdGhlIGtleWJvYXJkKQogIHZhciBwYXJlbnROb2RlID0gZS50YXJnZXQucGFyZW50Tm9kZSB8fCBlLnRhcmdldDsgLy8gaGFuZGxlIG5vIHBhcmVudAogIGlmIChwYXJlbnROb2RlLmNsYXNzTGlzdCAmJiBwYXJlbnROb2RlLmNsYXNzTGlzdC5jb250YWlucygnc2VsZWN0aXplLWlucHV0JykpIHsKICAgIGlmIChwYXJlbnROb2RlLmNsYXNzTGlzdC5jb250YWlucygnaW5wdXQtYWN0aXZlJykgfHwgIC8vIHRleHQgaW5wdXQgaXMgYWN0aXZlCiAgICAgICAoZS5rZXlDb2RlID09IDM4KSB8fCAoZS5rZXlDb2RlID09IDQwKSkgICAgICAgICAgICAvLyB1cCBvciBkb3duIGFycm93CiAgICAgIHJldHVybjsKICB9IGVsc2UgaWYgKC9eKGlucHV0fHRleHRhcmVhKSQvaS50ZXN0KGUudGFyZ2V0Lm5vZGVOYW1lKSB8fAogICAgICBlLnRhcmdldC5pc0NvbnRlbnRFZGl0YWJsZSkgewogICAgcmV0dXJuOwogIH0KCiAgLy8gRm9yd2FyZCBrZXlkb3ducyB0byB0aGUgbWFpbiBzbGlkZXMgaWYgd2UncmUgdGhlIHBvcHVwLgogIGlmICh0aGlzLmNvbnRyb2xsZXIgJiYgdGhpcy5jb250cm9sbGVyLmlzUG9wdXApIHsKICAgIHRoaXMuY29udHJvbGxlci5zZW5kTXNnKHtrZXlDb2RlOiBlLmtleUNvZGV9KTsKICB9CgogIHN3aXRjaCAoZS5rZXlDb2RlKSB7CiAgICBjYXNlIDEzOiAvLyBFbnRlcgogICAgICBpZiAoZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuY29udGFpbnMoJ292ZXJ2aWV3JykpIHsKICAgICAgICB0aGlzLnRvZ2dsZU92ZXJ2aWV3KCk7CiAgICAgIH0KICAgICAgYnJlYWs7CgogICAgY2FzZSAzOTogLy8gcmlnaHQgYXJyb3cKICAgIGNhc2UgMzI6IC8vIHNwYWNlCiAgICBjYXNlIDM0OiAvLyBQZ0RuCiAgICAgIHRoaXMubmV4dFNsaWRlKCk7CiAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgYnJlYWs7CgogICAgY2FzZSAzNzogLy8gbGVmdCBhcnJvdwogICAgY2FzZSA4OiAvLyBCYWNrc3BhY2UKICAgIGNhc2UgMzM6IC8vIFBnVXAKICAgICAgdGhpcy5wcmV2U2xpZGUoKTsKICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICBicmVhazsKCiAgICBjYXNlIDQwOiAvLyBkb3duIGFycm93CiAgICAgIHRoaXMubmV4dFNsaWRlKCk7CiAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgICAgYnJlYWs7CgogICAgY2FzZSAzODogLy8gdXAgYXJyb3cKICAgICAgdGhpcy5wcmV2U2xpZGUoKTsKICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOwogICAgICBicmVhazsKCiAgICBjYXNlIDcyOiAvLyBIOiBUb2dnbGUgY29kZSBoaWdobGlnaHRpbmcKICAgICAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QudG9nZ2xlKCdoaWdobGlnaHQtY29kZScpOwogICAgICBicmVhazsKCiAgICBjYXNlIDc5OiAvLyBPOiBUb2dnbGUgb3ZlcnZpZXcKICAgICAgdGhpcy50b2dnbGVPdmVydmlldygpOwogICAgICBicmVhazsKCiAgICBjYXNlIDgwOiAvLyBQCiAgICAgIGlmICh0aGlzLmNvbnRyb2xsZXIgJiYgdGhpcy5jb250cm9sbGVyLmlzUG9wdXApIHsKICAgICAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC50b2dnbGUoJ3dpdGgtbm90ZXMnKTsKICAgICAgfSBlbHNlIGlmICh0aGlzLmNvbnRyb2xsZXIgJiYgIXRoaXMuY29udHJvbGxlci5wb3B1cCkgewogICAgICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnRvZ2dsZSgnd2l0aC1ub3RlcycpOwogICAgICB9CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgODI6IC8vIFIKICAgICAgLy8gVE9ETzogaW1wbGVtZW50IHJlZnJlc2ggb24gbWFpbiBzbGlkZXMgd2hlbiBwb3B1cCBpcyByZWZyZXNoZWQuCiAgICAgIGJyZWFrOwoKICAgIGNhc2UgMjc6IC8vIEVTQzogSGlkZSBub3RlcyBhbmQgaGlnaGxpZ2h0aW5nCiAgICAgIGRvY3VtZW50LmJvZHkuY2xhc3NMaXN0LnJlbW92ZSgnd2l0aC1ub3RlcycpOwogICAgICBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5yZW1vdmUoJ2hpZ2hsaWdodC1jb2RlJyk7CgogICAgICBpZiAoZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuY29udGFpbnMoJ292ZXJ2aWV3JykpIHsKICAgICAgICB0aGlzLnRvZ2dsZU92ZXJ2aWV3KCk7CiAgICAgIH0KICAgICAgYnJlYWs7CgogICAgY2FzZSA3MDogLy8gRjogVG9nZ2xlIGZ1bGxzY3JlZW4KICAgICAgIC8vIE9ubHkgcmVzcGVjdCAnZicgb24gYm9keS4gRG9uJ3Qgd2FudCB0byBjYXB0dXJlIGtleXMgZnJvbSBhbiA8aW5wdXQ+LgogICAgICAgLy8gQWxzbywgaWdub3JlIGJyb3dzZXIncyBmdWxsc2NyZWVuIHNob3J0Y3V0IChjbWQrc2hpZnQrZikgc28gd2UgZG9uJ3QKICAgICAgIC8vIGdldCB0cmFwcGVkIGluIGZ1bGxzY3JlZW4hCiAgICAgIGlmIChkb2N1bWVudC5jYW5jZWxGdWxsU2NyZWVuICE9PSB1bmRlZmluZWQgJiYgZS50YXJnZXQgPT0gZG9jdW1lbnQuYm9keSAmJiAhKGUuc2hpZnRLZXkgJiYgZS5tZXRhS2V5KSkgewogICAgICAgIGlmIChkb2N1bWVudC5tb3pGdWxsU2NyZWVuICE9PSB1bmRlZmluZWQgJiYgIWRvY3VtZW50Lm1vekZ1bGxTY3JlZW4pIHsKICAgICAgICAgIGRvY3VtZW50LmJvZHkubW96UmVxdWVzdEZ1bGxTY3JlZW4oRWxlbWVudC5BTExPV19LRVlCT0FSRF9JTlBVVCk7CiAgICAgICAgfSBlbHNlIGlmIChkb2N1bWVudC53ZWJraXRJc0Z1bGxTY3JlZW4gIT09IHVuZGVmaW5lZCAmJiAhZG9jdW1lbnQud2Via2l0SXNGdWxsU2NyZWVuKSB7CiAgICAgICAgICBkb2N1bWVudC5ib2R5LndlYmtpdFJlcXVlc3RGdWxsU2NyZWVuKEVsZW1lbnQuQUxMT1dfS0VZQk9BUkRfSU5QVVQpOwogICAgICAgIH0gZWxzZSB7CiAgICAgICAgICBkb2N1bWVudC5jYW5jZWxGdWxsU2NyZWVuKCk7CiAgICAgICAgfQogICAgICB9CiAgICAgIGJyZWFrOwoKICAgIGNhc2UgODc6IC8vIFc6IFRvZ2dsZSB3aWRlc2NyZWVuCiAgICAgIC8vIE9ubHkgcmVzcGVjdCAndycgb24gYm9keS4gRG9uJ3Qgd2FudCB0byBjYXB0dXJlIGtleXMgZnJvbSBhbiA8aW5wdXQ+LgogICAgICBpZiAoZS50YXJnZXQgPT0gZG9jdW1lbnQuYm9keSAmJiAhKGUuc2hpZnRLZXkgJiYgZS5tZXRhS2V5KSkgewogICAgICAgIHRoaXMuY29udGFpbmVyLmNsYXNzTGlzdC50b2dnbGUoJ2xheW91dC13aWRlc2NyZWVuJyk7CiAgICAgIH0KICAgICAgYnJlYWs7CiAgfQp9OwoKLyoqCiAqCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLmZvY3VzT3ZlcnZpZXdfID0gZnVuY3Rpb24oKSB7CiAgdmFyIG92ZXJ2aWV3ID0gZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuY29udGFpbnMoJ292ZXJ2aWV3Jyk7CgogIGZvciAodmFyIGkgPSAwLCBzbGlkZTsgc2xpZGUgPSB0aGlzLnNsaWRlc1tpXTsgaSsrKSB7CiAgICBzbGlkZS5zdHlsZVtNb2Rlcm5penIucHJlZml4ZWQoJ3RyYW5zZm9ybScpXSA9IG92ZXJ2aWV3ID8KICAgICAgICAndHJhbnNsYXRlWigtMjUwMHB4KSB0cmFuc2xhdGUoJyArICgoIGkgLSB0aGlzLmN1clNsaWRlXyApICogMTA1KSArCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICclLCAwJSknIDogJyc7CiAgfQp9OwoKLyoqCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLnRvZ2dsZU92ZXJ2aWV3ID0gZnVuY3Rpb24oKSB7CiAgZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QudG9nZ2xlKCdvdmVydmlldycpOwoKICB0aGlzLmZvY3VzT3ZlcnZpZXdfKCk7Cn07CgovKioKICogQHByaXZhdGUKICovClNsaWRlRGVjay5wcm90b3R5cGUubG9hZENvbmZpZ18gPSBmdW5jdGlvbihjb25maWcpIHsKICBpZiAoIWNvbmZpZykgewogICAgcmV0dXJuOwogIH0KCiAgdGhpcy5jb25maWdfID0gY29uZmlnOwoKICB2YXIgc2V0dGluZ3MgPSB0aGlzLmNvbmZpZ18uc2V0dGluZ3M7CgogIHRoaXMubG9hZFRoZW1lXyhzZXR0aW5ncy50aGVtZSB8fCBbXSk7CgogIGlmIChzZXR0aW5ncy5mYXZJY29uKSB7CiAgICB0aGlzLmFkZEZhdkljb25fKHNldHRpbmdzLmZhdkljb24pOwogIH0KCiAgLy8gUHJldHR5cHJpbnQuIERlZmF1bHQgdG8gb24uCiAgaWYgKCEhISgndXNlUHJldHRpZnknIGluIHNldHRpbmdzKSB8fCBzZXR0aW5ncy51c2VQcmV0dGlmeSkgewogICAgcHJldHR5UHJpbnQoKTsKICB9CgogIGlmIChzZXR0aW5ncy5hbmFseXRpY3MpIHsKICAgIHRoaXMubG9hZEFuYWx5dGljc18oKTsKICB9CgogIGlmIChzZXR0aW5ncy5mb250cykgewogICAgdGhpcy5hZGRGb250c18oc2V0dGluZ3MuZm9udHMpOwogIH0KCiAgLy8gQnVpbGRzLiBEZWZhdWx0IHRvIG9uLgogIGlmICghISEoJ3VzZUJ1aWxkcycgaW4gc2V0dGluZ3MpIHx8IHNldHRpbmdzLnVzZUJ1aWxkcykgewogICAgdGhpcy5tYWtlQnVpbGRMaXN0c18oKTsKICB9CgogIGlmIChzZXR0aW5ncy50aXRsZSkgewogICAgZG9jdW1lbnQudGl0bGUgPSBzZXR0aW5ncy50aXRsZS5yZXBsYWNlKC88YnJcLz8+LywgJyAnKTsKICAgIGlmIChzZXR0aW5ncy5ldmVudEluZm8gJiYgc2V0dGluZ3MuZXZlbnRJbmZvLnRpdGxlKSB7CiAgICAgIGRvY3VtZW50LnRpdGxlICs9ICAnIC0gJyArIHNldHRpbmdzLmV2ZW50SW5mby50aXRsZTsKICAgIH0KICAgIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLWNvbmZpZy10aXRsZV0nKS5pbm5lckhUTUwgPSBzZXR0aW5ncy50aXRsZTsKICB9CgogIGlmIChzZXR0aW5ncy5zdWJ0aXRsZSkgewogICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW2RhdGEtY29uZmlnLXN1YnRpdGxlXScpLmlubmVySFRNTCA9IHNldHRpbmdzLnN1YnRpdGxlOwogIH0KCiAgaWYgKHRoaXMuY29uZmlnXy5wcmVzZW50ZXJzKSB7CiAgICB2YXIgcHJlc2VudGVycyA9IHRoaXMuY29uZmlnXy5wcmVzZW50ZXJzOwogICAgdmFyIGRhdGFDb25maWdDb250YWN0ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignW2RhdGEtY29uZmlnLWNvbnRhY3RdJyk7CgogICAgdmFyIGh0bWwgPSBbXTsKICAgIGlmIChwcmVzZW50ZXJzLmxlbmd0aCA9PSAxKSB7CiAgICAgIHZhciBwID0gcHJlc2VudGVyc1swXTsKCiAgICAgIHZhciBwcmVzZW50ZXJUaXRsZSA9IFtwLm5hbWVdOwogICAgICBpZiAocC5jb21wYW55KSB7CiAgICAgICAgcHJlc2VudGVyVGl0bGUucHVzaChwLmNvbXBhbnkpOwogICAgICB9CiAgICAgIGh0bWwgPSBwcmVzZW50ZXJUaXRsZS5qb2luKCcgLSAnKSArICc8YnI+JzsKCiAgICAgIHZhciBncGx1cyA9IHAuZ3BsdXMgPyAnPHNwYW4+Zys8L3NwYW4+PGEgaHJlZj0iJyArIHAuZ3BsdXMgKwogICAgICAgICAgJyI+JyArIHAuZ3BsdXMucmVwbGFjZSgvaHR0cHM/OlwvXC8vLCAnJykgKyAnPC9hPicgOiAnJzsKCiAgICAgIHZhciB0d2l0dGVyID0gcC50d2l0dGVyID8gJzxzcGFuPnR3aXR0ZXI8L3NwYW4+JyArCiAgICAgICAgICAnPGEgaHJlZj0iaHR0cDovL3R3aXR0ZXIuY29tLycgKyBwLnR3aXR0ZXIgKyAnIj4nICsKICAgICAgICAgIHAudHdpdHRlciArICc8L2E+JyA6ICcnOwoKICAgICAgdmFyIHd3dyA9IHAud3d3ID8gJzxzcGFuPnd3dzwvc3Bhbj48YSBocmVmPSInICsgcC53d3cgKwogICAgICAgICAgICAgICAgICAgICAgICAnIj4nICsgcC53d3cucmVwbGFjZSgvaHR0cHM/OlwvXC8vLCAnJykgKyAnPC9hPicgOiAnJzsKCiAgICAgIHZhciBnaXRodWIgPSBwLmdpdGh1YiA/ICc8c3Bhbj5naXRodWI8L3NwYW4+PGEgaHJlZj0iJyArIHAuZ2l0aHViICsKICAgICAgICAgICciPicgKyBwLmdpdGh1Yi5yZXBsYWNlKC9odHRwcz86XC9cLy8sICcnKSArICc8L2E+JyA6ICcnOwoKICAgICAgdmFyIGh0bWwyID0gW2dwbHVzLCB0d2l0dGVyLCB3d3csIGdpdGh1Yl0uam9pbignPGJyPicpOwoKICAgICAgaWYgKGRhdGFDb25maWdDb250YWN0KSB7CiAgICAgICAgZGF0YUNvbmZpZ0NvbnRhY3QuaW5uZXJIVE1MID0gaHRtbDI7CiAgICAgIH0KICAgIH0gZWxzZSB7CiAgICAgIGZvciAodmFyIGkgPSAwLCBwOyBwID0gcHJlc2VudGVyc1tpXTsgKytpKSB7CiAgICAgICAgaHRtbC5wdXNoKHAubmFtZSArICcgLSAnICsgcC5jb21wYW55KTsKICAgICAgfQogICAgICBodG1sID0gaHRtbC5qb2luKCc8YnI+Jyk7CiAgICAgIGlmIChkYXRhQ29uZmlnQ29udGFjdCkgewogICAgICAgIGRhdGFDb25maWdDb250YWN0LmlubmVySFRNTCA9IGh0bWw7CiAgICAgIH0KICAgIH0KCiAgICB2YXIgZGF0YUNvbmZpZ1ByZXNlbnRlciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ1tkYXRhLWNvbmZpZy1wcmVzZW50ZXJdJyk7CiAgICBpZiAoZGF0YUNvbmZpZ1ByZXNlbnRlcikgewogICAgICBkYXRhQ29uZmlnUHJlc2VudGVyLmlubmVySFRNTCA9IGh0bWw7CiAgICAgIGlmIChzZXR0aW5ncy5ldmVudEluZm8pIHsKICAgICAgICB2YXIgZGF0ZSA9IHNldHRpbmdzLmV2ZW50SW5mby5kYXRlOwogICAgICAgIHZhciBkYXRlSW5mbyA9IGRhdGUgPyAnIC0gPHRpbWU+JyArIGRhdGUgKyAnPC90aW1lPicgOiAnJzsKICAgICAgICBkYXRhQ29uZmlnUHJlc2VudGVyLmlubmVySFRNTCArPSBzZXR0aW5ncy5ldmVudEluZm8udGl0bGUgKyBkYXRlSW5mbzsKICAgICAgfQogICAgfQogIH0KCiAgLyogTGVmdC9SaWdodCB0YXAgYXJlYXMuIERlZmF1bHQgdG8gaW5jbHVkaW5nLiAqLwogIGlmICghISEoJ2VuYWJsZVNsaWRlQXJlYXMnIGluIHNldHRpbmdzKSB8fCBzZXR0aW5ncy5lbmFibGVTbGlkZUFyZWFzKSB7CiAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgIGVsLmNsYXNzTGlzdC5hZGQoJ3NsaWRlLWFyZWEnKTsKICAgIGVsLmlkID0gJ3ByZXYtc2xpZGUtYXJlYSc7CiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMucHJldlNsaWRlLmJpbmQodGhpcyksIGZhbHNlKTsKICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZENoaWxkKGVsKTsKCiAgICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTsKICAgIGVsLmNsYXNzTGlzdC5hZGQoJ3NsaWRlLWFyZWEnKTsKICAgIGVsLmlkID0gJ25leHQtc2xpZGUtYXJlYSc7CiAgICBlbC5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsIHRoaXMubmV4dFNsaWRlLmJpbmQodGhpcyksIGZhbHNlKTsKICAgIHRoaXMuY29udGFpbmVyLmFwcGVuZENoaWxkKGVsKTsKICB9CgogIGlmIChNb2Rlcm5penIudG91Y2ggJiYgKCEhISgnZW5hYmxlVG91Y2gnIGluIHNldHRpbmdzKSB8fAogICAgICBzZXR0aW5ncy5lbmFibGVUb3VjaCkpIHsKICAgIHZhciBzZWxmID0gdGhpczsKCiAgICAvLyBOb3RlOiB0aGlzIHByZXZlbnRzIG1vYmlsZSB6b29tIGluL291dCBidXQgcHJldmVudHMgaU9TIGZyb20gZG9pbmcKICAgIC8vIGl0J3MgY3Jhenkgc2Nyb2xsIG92ZXIgZWZmZWN0IGFuZCBkaXNhbGlnbmluZyB0aGUgc2xpZGVzLgogICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBmdW5jdGlvbihlKSB7CiAgICAgIGUucHJldmVudERlZmF1bHQoKTsKICAgIH0sIGZhbHNlKTsKCiAgICB2YXIgaGFtbWVyID0gbmV3IEhhbW1lcih0aGlzLmNvbnRhaW5lcik7CiAgICBoYW1tZXIub25kcmFnZW5kID0gZnVuY3Rpb24oZSkgewogICAgICBpZiAoZS5kaXJlY3Rpb24gPT0gJ3JpZ2h0JyB8fCBlLmRpcmVjdGlvbiA9PSAnZG93bicpIHsKICAgICAgICBzZWxmLnByZXZTbGlkZSgpOwogICAgICB9IGVsc2UgaWYgKGUuZGlyZWN0aW9uID09ICdsZWZ0JyB8fCBlLmRpcmVjdGlvbiA9PSAndXAnKSB7CiAgICAgICAgc2VsZi5uZXh0U2xpZGUoKTsKICAgICAgfQogICAgfTsKICB9Cn07CgovKioKICogQHByaXZhdGUKICogQHBhcmFtIHtBcnJheS48c3RyaW5nPn0gZm9udHMKICovClNsaWRlRGVjay5wcm90b3R5cGUuYWRkRm9udHNfID0gZnVuY3Rpb24oZm9udHMpIHsKICB2YXIgZWwgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdsaW5rJyk7CiAgZWwucmVsID0gJ3N0eWxlc2hlZXQnOwogIGVsLmhyZWYgPSAoJ2h0dHBzOicgPT0gZG9jdW1lbnQubG9jYXRpb24ucHJvdG9jb2wgPyAnaHR0cHMnIDogJ2h0dHAnKSArCiAgICAgICc6Ly9mb250cy5nb29nbGVhcGlzLmNvbS9jc3M/ZmFtaWx5PScgKyBmb250cy5qb2luKCd8JykgKyAnJnYyJzsKICBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCdoZWFkJykuYXBwZW5kQ2hpbGQoZWwpOwp9OwoKLyoqCiAqIEBwcml2YXRlCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLmJ1aWxkTmV4dEl0ZW1fID0gZnVuY3Rpb24oKSB7CiAgdmFyIHNsaWRlID0gdGhpcy5zbGlkZXNbdGhpcy5jdXJTbGlkZV9dOwogIHZhciB0b0J1aWxkID0gc2xpZGUucXVlcnlTZWxlY3RvcignLnRvLWJ1aWxkJyk7CiAgdmFyIGJ1aWx0ID0gc2xpZGUucXVlcnlTZWxlY3RvcignLmJ1aWxkLWN1cnJlbnQnKTsKCiAgaWYgKGJ1aWx0KSB7CiAgICBidWlsdC5jbGFzc0xpc3QucmVtb3ZlKCdidWlsZC1jdXJyZW50Jyk7CiAgICBpZiAoYnVpbHQuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYWRlJykpIHsKICAgICAgYnVpbHQuY2xhc3NMaXN0LmFkZCgnYnVpbGQtZmFkZScpOwogICAgfQogIH0KCiAgaWYgKCF0b0J1aWxkKSB7CiAgICB2YXIgaXRlbXMgPSBzbGlkZS5xdWVyeVNlbGVjdG9yQWxsKCcuYnVpbGQtZmFkZScpOwogICAgZm9yICh2YXIgaiA9IDAsIGl0ZW07IGl0ZW0gPSBpdGVtc1tqXTsgaisrKSB7CiAgICAgIGl0ZW0uY2xhc3NMaXN0LnJlbW92ZSgnYnVpbGQtZmFkZScpOwogICAgfQogICAgcmV0dXJuIGZhbHNlOwogIH0KCiAgdG9CdWlsZC5jbGFzc0xpc3QucmVtb3ZlKCd0by1idWlsZCcpOwogIHRvQnVpbGQuY2xhc3NMaXN0LmFkZCgnYnVpbGQtY3VycmVudCcpOwoKICByZXR1cm4gdHJ1ZTsKfTsKCi8qKgogKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfZG9udFB1c2gKICovClNsaWRlRGVjay5wcm90b3R5cGUucHJldlNsaWRlID0gZnVuY3Rpb24ob3B0X2RvbnRQdXNoKSB7CiAgaWYgKHRoaXMuY3VyU2xpZGVfID4gMCkgewogICAgdmFyIGJvZHlDbGFzc0xpc3QgPSBkb2N1bWVudC5ib2R5LmNsYXNzTGlzdDsKICAgIGJvZHlDbGFzc0xpc3QucmVtb3ZlKCdoaWdobGlnaHQtY29kZScpOwoKICAgIC8vIFRvZ2dsZSBvZmYgc3BlYWtlciBub3RlcyBpZiB0aGV5J3JlIHNob3dpbmcgd2hlbiB3ZSBtb3ZlIGJhY2t3YXJkcyBvbiB0aGUKICAgIC8vIG1haW4gc2xpZGVzLiBJZiB3ZSdyZSB0aGUgc3BlYWtlciBub3RlcyBwb3B1cCwgbGVhdmUgdGhlbSB1cC4KICAgIGlmICh0aGlzLmNvbnRyb2xsZXIgJiYgIXRoaXMuY29udHJvbGxlci5pc1BvcHVwKSB7CiAgICAgIGJvZHlDbGFzc0xpc3QucmVtb3ZlKCd3aXRoLW5vdGVzJyk7CiAgICB9IGVsc2UgaWYgKCF0aGlzLmNvbnRyb2xsZXIpIHsKICAgICAgYm9keUNsYXNzTGlzdC5yZW1vdmUoJ3dpdGgtbm90ZXMnKTsKICAgIH0KCiAgICB0aGlzLnByZXZTbGlkZV8gPSB0aGlzLmN1clNsaWRlXy0tOwoKICAgIHRoaXMudXBkYXRlU2xpZGVzXyhvcHRfZG9udFB1c2gpOwogIH0KfTsKCi8qKgogKiBAcGFyYW0ge2Jvb2xlYW49fSBvcHRfZG9udFB1c2gKICovClNsaWRlRGVjay5wcm90b3R5cGUubmV4dFNsaWRlID0gZnVuY3Rpb24ob3B0X2RvbnRQdXNoKSB7CiAgaWYgKCFkb2N1bWVudC5ib2R5LmNsYXNzTGlzdC5jb250YWlucygnb3ZlcnZpZXcnKSAmJiB0aGlzLmJ1aWxkTmV4dEl0ZW1fKCkpIHsKICAgIHJldHVybjsKICB9CgogIGlmICh0aGlzLmN1clNsaWRlXyA8IHRoaXMuc2xpZGVzLmxlbmd0aCAtIDEpIHsKICAgIHZhciBib2R5Q2xhc3NMaXN0ID0gZG9jdW1lbnQuYm9keS5jbGFzc0xpc3Q7CiAgICBib2R5Q2xhc3NMaXN0LnJlbW92ZSgnaGlnaGxpZ2h0LWNvZGUnKTsKCiAgICAvLyBUb2dnbGUgb2ZmIHNwZWFrZXIgbm90ZXMgaWYgdGhleSdyZSBzaG93aW5nIHdoZW4gd2UgYWR2YW5jZWQgb24gdGhlIG1haW4KICAgIC8vIHNsaWRlcy4gSWYgd2UncmUgdGhlIHNwZWFrZXIgbm90ZXMgcG9wdXAsIGxlYXZlIHRoZW0gdXAuCiAgICBpZiAodGhpcy5jb250cm9sbGVyICYmICF0aGlzLmNvbnRyb2xsZXIuaXNQb3B1cCkgewogICAgICBib2R5Q2xhc3NMaXN0LnJlbW92ZSgnd2l0aC1ub3RlcycpOwogICAgfSBlbHNlIGlmICghdGhpcy5jb250cm9sbGVyKSB7CiAgICAgIGJvZHlDbGFzc0xpc3QucmVtb3ZlKCd3aXRoLW5vdGVzJyk7CiAgICB9CgogICAgdGhpcy5wcmV2U2xpZGVfID0gdGhpcy5jdXJTbGlkZV8rKzsKCiAgICB0aGlzLnVwZGF0ZVNsaWRlc18ob3B0X2RvbnRQdXNoKTsKICB9Cn07CgovKiBTbGlkZSBldmVudHMgKi8KCi8qKgogKiBUcmlnZ2VyZWQgd2hlbiBhIHNsaWRlIGVudGVyL2xlYXZlIGV2ZW50IHNob3VsZCBiZSBkaXNwYXRjaGVkLgogKgogKiBAcGFyYW0ge3N0cmluZ30gdHlwZSBUaGUgdHlwZSBvZiBldmVudCB0byB0cmlnZ2VyCiAqICAgICAoZS5nLiAnc2xpZGVlbnRlcicsICdzbGlkZWxlYXZlJykuCiAqIEBwYXJhbSB7bnVtYmVyfSBzbGlkZU5vIFRoZSBpbmRleCBvZiB0aGUgc2xpZGUgdGhhdCBpcyBiZWluZyBsZWZ0LgogKi8KU2xpZGVEZWNrLnByb3RvdHlwZS50cmlnZ2VyU2xpZGVFdmVudCA9IGZ1bmN0aW9uKHR5cGUsIHNsaWRlTm8pIHsKICB2YXIgZWwgPSB0aGlzLmdldFNsaWRlRWxfKHNsaWRlTm8pOwogIGlmICghZWwpIHsKICAgIHJldHVybjsKICB9CgogIC8vIENhbGwgb25zbGlkZWVudGVyL29uc2xpZGVsZWF2ZSBpZiB0aGUgYXR0cmlidXRlIGlzIGRlZmluZWQgb24gdGhpcyBzbGlkZS4KICB2YXIgZnVuYyA9IGVsLmdldEF0dHJpYnV0ZSh0eXBlKTsKICBpZiAoZnVuYykgewogICAgbmV3IEZ1bmN0aW9uKGZ1bmMpLmNhbGwoZWwpOyAvLyBUT0RPOiBEb24ndCB1c2UgbmV3IEZ1bmN0aW9uKCkgOigKICB9CgogIC8vIERpc3BhdGNoIGV2ZW50IHRvIGxpc3RlbmVycyBzZXR1cCB1c2luZyBhZGRFdmVudExpc3RlbmVyLgogIHZhciBldnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnRXZlbnQnKTsKICBldnQuaW5pdEV2ZW50KHR5cGUsIHRydWUsIHRydWUpOwogIGV2dC5zbGlkZU51bWJlciA9IHNsaWRlTm8gKyAxOyAvLyBNYWtlIGl0IHJlYWRhYmxlCiAgZXZ0LnNsaWRlID0gZWw7CgogIGVsLmRpc3BhdGNoRXZlbnQoZXZ0KTsKfTsKCi8qKgogKiBAcHJpdmF0ZQogKi8KU2xpZGVEZWNrLnByb3RvdHlwZS51cGRhdGVTbGlkZXNfID0gZnVuY3Rpb24ob3B0X2RvbnRQdXNoKSB7CiAgdmFyIGRvbnRQdXNoID0gb3B0X2RvbnRQdXNoIHx8IGZhbHNlOwoKICB2YXIgY3VyU2xpZGUgPSB0aGlzLmN1clNsaWRlXzsKICBmb3IgKHZhciBpID0gMDsgaSA8IHRoaXMuc2xpZGVzLmxlbmd0aDsgKytpKSB7CiAgICBzd2l0Y2ggKGkpIHsKICAgICAgY2FzZSBjdXJTbGlkZSAtIDI6CiAgICAgICAgdGhpcy51cGRhdGVTbGlkZUNsYXNzXyhpLCAnZmFyLXBhc3QnKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBjdXJTbGlkZSAtIDE6CiAgICAgICAgdGhpcy51cGRhdGVTbGlkZUNsYXNzXyhpLCAncGFzdCcpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIGN1clNsaWRlOgogICAgICAgIHRoaXMudXBkYXRlU2xpZGVDbGFzc18oaSwgJ2N1cnJlbnQnKTsKICAgICAgICBicmVhazsKICAgICAgY2FzZSBjdXJTbGlkZSArIDE6CiAgICAgICAgdGhpcy51cGRhdGVTbGlkZUNsYXNzXyhpLCAnbmV4dCcpOwogICAgICAgIGJyZWFrOwogICAgICBjYXNlIGN1clNsaWRlICsgMjoKICAgICAgICB0aGlzLnVwZGF0ZVNsaWRlQ2xhc3NfKGksICdmYXItbmV4dCcpOwogICAgICAgIGJyZWFrOwogICAgICBkZWZhdWx0OgogICAgICAgIHRoaXMudXBkYXRlU2xpZGVDbGFzc18oaSk7CiAgICAgICAgYnJlYWs7CiAgICB9CiAgfTsKCiAgdGhpcy50cmlnZ2VyU2xpZGVFdmVudCgnc2xpZGVsZWF2ZScsIHRoaXMucHJldlNsaWRlXyk7CiAgdGhpcy50cmlnZ2VyU2xpZGVFdmVudCgnc2xpZGVlbnRlcicsIGN1clNsaWRlKTsKCi8vIHdpbmRvdy5zZXRUaW1lb3V0KHRoaXMuZGlzYWJsZVNsaWRlRnJhbWVzXy5iaW5kKHRoaXMsIGN1clNsaWRlIC0gMiksIDMwMSk7Ci8vCi8vIHRoaXMuZW5hYmxlU2xpZGVGcmFtZXNfKGN1clNsaWRlIC0gMSk7IC8vIFByZXZpb3VzIHNsaWRlLgovLyB0aGlzLmVuYWJsZVNsaWRlRnJhbWVzXyhjdXJTbGlkZSArIDEpOyAvLyBDdXJyZW50IHNsaWRlLgovLyB0aGlzLmVuYWJsZVNsaWRlRnJhbWVzXyhjdXJTbGlkZSArIDIpOyAvLyBOZXh0IHNsaWRlLgoKICAgLy8gRW5hYmxlIGN1cnJlbnQgc2xpZGUncyBpZnJhbWVzIChuZWVkZWQgZm9yIHBhZ2UgbG9hdCBhdCBjdXJyZW50IHNsaWRlKS4KICAgdGhpcy5lbmFibGVTbGlkZUZyYW1lc18oY3VyU2xpZGUgKyAxKTsKCiAgIC8vIE5vIHdheSB0byB0ZWxsIHdoZW4gYWxsIHNsaWRlIHRyYW5zaXRpb25zICsgYXV0byBidWlsZHMgYXJlIGRvbmUuCiAgIC8vIEdpdmUgb3Vyc2VsdmVzIGEgZ29vZCBidWZmZXIgdG8gcHJlbG9hZCB0aGUgbmV4dCBzbGlkZSdzIGlmcmFtZXMuCiAgIHdpbmRvdy5zZXRUaW1lb3V0KHRoaXMuZW5hYmxlU2xpZGVGcmFtZXNfLmJpbmQodGhpcywgY3VyU2xpZGUgKyAyKSwgMTAwMCk7CgogIHRoaXMudXBkYXRlSGFzaF8oZG9udFB1c2gpOwoKICBpZiAoZG9jdW1lbnQuYm9keS5jbGFzc0xpc3QuY29udGFpbnMoJ292ZXJ2aWV3JykpIHsKICAgIHRoaXMuZm9jdXNPdmVydmlld18oKTsKICAgIHJldHVybjsKICB9Cgp9OwoKLyoqCiAqIEBwcml2YXRlCiAqIEBwYXJhbSB7bnVtYmVyfSBzbGlkZU5vCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLmVuYWJsZVNsaWRlRnJhbWVzXyA9IGZ1bmN0aW9uKHNsaWRlTm8pIHsKICB2YXIgZWwgPSB0aGlzLnNsaWRlc1tzbGlkZU5vIC0gMV07CiAgaWYgKCFlbCkgewogICAgcmV0dXJuOwogIH0KCiAgdmFyIGZyYW1lcyA9IGVsLnF1ZXJ5U2VsZWN0b3JBbGwoJ2lmcmFtZScpOwogIGZvciAodmFyIGkgPSAwLCBmcmFtZTsgZnJhbWUgPSBmcmFtZXNbaV07IGkrKykgewogICAgdGhpcy5lbmFibGVGcmFtZV8oZnJhbWUpOwogIH0KfTsKCi8qKgogKiBAcHJpdmF0ZQogKiBAcGFyYW0ge251bWJlcn0gc2xpZGVObwogKi8KU2xpZGVEZWNrLnByb3RvdHlwZS5lbmFibGVGcmFtZV8gPSBmdW5jdGlvbihmcmFtZSkgewogIHZhciBzcmMgPSBmcmFtZS5kYXRhc2V0LnNyYzsKICBpZiAoc3JjICYmIGZyYW1lLnNyYyAhPSBzcmMpIHsKICAgIGZyYW1lLnNyYyA9IHNyYzsKICB9Cn07CgovKioKICogQHByaXZhdGUKICogQHBhcmFtIHtudW1iZXJ9IHNsaWRlTm8KICovClNsaWRlRGVjay5wcm90b3R5cGUuZGlzYWJsZVNsaWRlRnJhbWVzXyA9IGZ1bmN0aW9uKHNsaWRlTm8pIHsKICB2YXIgZWwgPSB0aGlzLnNsaWRlc1tzbGlkZU5vIC0gMV07CiAgaWYgKCFlbCkgewogICAgcmV0dXJuOwogIH0KCiAgdmFyIGZyYW1lcyA9IGVsLnF1ZXJ5U2VsZWN0b3JBbGwoJ2lmcmFtZScpOwogIGZvciAodmFyIGkgPSAwLCBmcmFtZTsgZnJhbWUgPSBmcmFtZXNbaV07IGkrKykgewogICAgdGhpcy5kaXNhYmxlRnJhbWVfKGZyYW1lKTsKICB9Cn07CgovKioKICogQHByaXZhdGUKICogQHBhcmFtIHtOb2RlfSBmcmFtZQogKi8KU2xpZGVEZWNrLnByb3RvdHlwZS5kaXNhYmxlRnJhbWVfID0gZnVuY3Rpb24oZnJhbWUpIHsKICBmcmFtZS5zcmMgPSAnYWJvdXQ6YmxhbmsnOwp9OwoKLyoqCiAqIEBwcml2YXRlCiAqIEBwYXJhbSB7bnVtYmVyfSBzbGlkZU5vCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLmdldFNsaWRlRWxfID0gZnVuY3Rpb24obm8pIHsKICBpZiAoKG5vIDwgMCkgfHwgKG5vID49IHRoaXMuc2xpZGVzLmxlbmd0aCkpIHsKICAgIHJldHVybiBudWxsOwogIH0gZWxzZSB7CiAgICByZXR1cm4gdGhpcy5zbGlkZXNbbm9dOwogIH0KfTsKCi8qKgogKiBAcHJpdmF0ZQogKiBAcGFyYW0ge251bWJlcn0gc2xpZGVObwogKiBAcGFyYW0ge3N0cmluZ30gY2xhc3NOYW1lCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLnVwZGF0ZVNsaWRlQ2xhc3NfID0gZnVuY3Rpb24oc2xpZGVObywgY2xhc3NOYW1lKSB7CiAgdmFyIGVsID0gdGhpcy5nZXRTbGlkZUVsXyhzbGlkZU5vKTsKCiAgaWYgKCFlbCkgewogICAgcmV0dXJuOwogIH0KCiAgaWYgKGNsYXNzTmFtZSkgewogICAgZWwuY2xhc3NMaXN0LmFkZChjbGFzc05hbWUpOwogIH0KCiAgZm9yICh2YXIgaSA9IDAsIHNsaWRlQ2xhc3M7IHNsaWRlQ2xhc3MgPSB0aGlzLlNMSURFX0NMQVNTRVNfW2ldOyArK2kpIHsKICAgIGlmIChjbGFzc05hbWUgIT0gc2xpZGVDbGFzcykgewogICAgICBlbC5jbGFzc0xpc3QucmVtb3ZlKHNsaWRlQ2xhc3MpOwogICAgfQogIH0KfTsKCi8qKgogKiBAcHJpdmF0ZQogKi8KU2xpZGVEZWNrLnByb3RvdHlwZS5tYWtlQnVpbGRMaXN0c18gPSBmdW5jdGlvbiAoKSB7CiAgZm9yICh2YXIgaSA9IHRoaXMuY3VyU2xpZGVfLCBzbGlkZTsgc2xpZGUgPSB0aGlzLnNsaWRlc1tpXTsgKytpKSB7CiAgICB2YXIgaXRlbXMgPSBzbGlkZS5xdWVyeVNlbGVjdG9yQWxsKCcuYnVpbGQgPiAqJyk7CiAgICBmb3IgKHZhciBqID0gMCwgaXRlbTsgaXRlbSA9IGl0ZW1zW2pdOyArK2opIHsKICAgICAgaWYgKGl0ZW0uY2xhc3NMaXN0KSB7CiAgICAgICAgaXRlbS5jbGFzc0xpc3QuYWRkKCd0by1idWlsZCcpOwogICAgICAgIGlmIChpdGVtLnBhcmVudE5vZGUuY2xhc3NMaXN0LmNvbnRhaW5zKCdmYWRlJykpIHsKICAgICAgICAgIGl0ZW0uY2xhc3NMaXN0LmFkZCgnZmFkZScpOwogICAgICAgIH0KICAgICAgfQogICAgfQogIH0KfTsKCi8qKgogKiBAcHJpdmF0ZQogKiBAcGFyYW0ge2Jvb2xlYW59IGRvbnRQdXNoCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLnVwZGF0ZUhhc2hfID0gZnVuY3Rpb24oZG9udFB1c2gpIHsKICBpZiAoIWRvbnRQdXNoKSB7CiAgICB2YXIgc2xpZGVObyA9IHRoaXMuY3VyU2xpZGVfICsgMTsKICAgIC8vIEFkZCBldmVyeXRoaW5nIGV4Y2VwdCB0aGUgaGFzaC4KICAgIHZhciBsb2MgPSBsb2NhdGlvbi5wcm90b2NvbCsnLy8nK2xvY2F0aW9uLmhvc3QrbG9jYXRpb24ucGF0aG5hbWUrKGxvY2F0aW9uLnNlYXJjaD9sb2NhdGlvbi5zZWFyY2g6IiIpOwogICAgdmFyIGhhc2ggPSAnIycgKyBzbGlkZU5vOwogICAgaWYgKHdpbmRvdy5oaXN0b3J5LnB1c2hTdGF0ZSAmJiAobG9jYXRpb24ucHJvdG9jb2wgIT09ICJmaWxlOiIpKSB7CiAgICAgIHdpbmRvdy5oaXN0b3J5LnB1c2hTdGF0ZSh0aGlzLmN1clNsaWRlXywgJ1NsaWRlICcgKyBzbGlkZU5vLCBsb2MgKyBoYXNoKTsKICAgIH0gZWxzZSB7CiAgICAgIHdpbmRvdy5sb2NhdGlvbi5yZXBsYWNlKGxvYyArIGhhc2gpOwogICAgfQoKICAgIC8vIFJlY29yZCBHQSBoaXQgb24gdGhpcyBzbGlkZS4KICAgIGlmKHR5cGVvZiB3aW5kb3cuZ2EgPT09ICdmdW5jdGlvbicpIHsKICAgICAgZ2EoJ3NldCcsICdwYWdlJywgaGFzaCkKICAgICAgZ2EoJ3NlbmQnLCAncGFnZXZpZXcnKTsKICAgIH0KICB9Cn07CgoKLyoqCiAqIEBwcml2YXRlCiAqIEBwYXJhbSB7c3RyaW5nfSBmYXZJY29uCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLmFkZEZhdkljb25fID0gZnVuY3Rpb24oZmF2SWNvbikgewogIHZhciBlbCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTsKICBlbC5yZWwgPSAnaWNvbic7CiAgZWwudHlwZSA9ICdpbWFnZS9wbmcnOwogIGVsLmhyZWYgPSBmYXZJY29uOwogIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ2hlYWQnKS5hcHBlbmRDaGlsZChlbCk7Cn07CgovKioKICogQHByaXZhdGUKICogQHBhcmFtIHtzdHJpbmd9IHRoZW1lCiAqLwpTbGlkZURlY2sucHJvdG90eXBlLmxvYWRUaGVtZV8gPSBmdW5jdGlvbih0aGVtZSkgewogIHZhciBzdHlsZXMgPSBbXTsKICBpZiAodGhlbWUuY29uc3RydWN0b3IubmFtZSA9PT0gJ1N0cmluZycpIHsKICAgIHN0eWxlcy5wdXNoKHRoZW1lKTsKICB9IGVsc2UgewogICAgc3R5bGVzID0gdGhlbWU7CiAgfQoKICBmb3IgKHZhciBpID0gMCwgc3R5bGU7IHRoZW1lVXJsID0gc3R5bGVzW2ldOyBpKyspIHsKICAgIHZhciBzdHlsZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpbmsnKTsKICAgIHN0eWxlLnJlbCA9ICdzdHlsZXNoZWV0JzsKICAgIHN0eWxlLnR5cGUgPSAndGV4dC9jc3MnOwogICAgaWYgKHRoZW1lVXJsLmluZGV4T2YoJ2h0dHAnKSA9PSAtMSkgewogICAgICBzdHlsZS5ocmVmID0gdGhpcy5DU1NfRElSXyArIHRoZW1lVXJsICsgJy5jc3MnOwogICAgfSBlbHNlIHsKICAgICAgc3R5bGUuaHJlZiA9IHRoZW1lVXJsOwogICAgfQogICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvcignaGVhZCcpLmFwcGVuZENoaWxkKHN0eWxlKTsKICB9Cn07CgovKioKICogQHByaXZhdGUKICovClNsaWRlRGVjay5wcm90b3R5cGUubG9hZEFuYWx5dGljc18gPSBmdW5jdGlvbigpIHsKICAoZnVuY3Rpb24oaSxzLG8sZyxyLGEsbSl7aVsnR29vZ2xlQW5hbHl0aWNzT2JqZWN0J109cjtpW3JdPWlbcl18fGZ1bmN0aW9uKCl7CiAgICAoaVtyXS5xPWlbcl0ucXx8W10pLnB1c2goYXJndW1lbnRzKX0saVtyXS5sPTEqbmV3IERhdGUoKTthPXMuY3JlYXRlRWxlbWVudChvKSwKICAgIG09cy5nZXRFbGVtZW50c0J5VGFnTmFtZShvKVswXTthLmFzeW5jPTE7YS5zcmM9ZzttLnBhcmVudE5vZGUuaW5zZXJ0QmVmb3JlKGEsbSkKICB9KSh3aW5kb3csZG9jdW1lbnQsJ3NjcmlwdCcsJy8vd3d3Lmdvb2dsZS1hbmFseXRpY3MuY29tL2FuYWx5dGljcy5qcycsJ2dhJyk7CgogIGdhKCdjcmVhdGUnLCB0aGlzLmNvbmZpZ18uc2V0dGluZ3MuYW5hbHl0aWNzLCAnYXV0bycpOwogIGdhKCdzZW5kJywgJ3BhZ2V2aWV3Jyk7Cn07CgoKdmFyIGxvYWREZWNrID0gZnVuY3Rpb24oZXZlbnQpIHsKICAvLyBQb2x5ZmlsbCBtaXNzaW5nIEFQSXMgKGlmIHdlIG5lZWQgdG8pLCB0aGVuIGNyZWF0ZSB0aGUgc2xpZGUgZGVjay4KICAvLyBpT1MgPCA1IG5lZWRzIGNsYXNzTGlzdCwgZGF0YXNldCwgYW5kIHdpbmRvdy5tYXRjaE1lZGlhLiBNb2Rlcm5penIgY29udGFpbnMKICAvLyB0aGUgbGFzdCBvbmUuCiAgTW9kZXJuaXpyLmxvYWQoewogICAgY29tcGxldGU6IGZ1bmN0aW9uKCkgewogICAgICB3aW5kb3cuc2xpZGVkZWNrID0gbmV3IFNsaWRlRGVjaygpOwogICAgfQogIH0pOwp9OwoKaWYgKGRvY3VtZW50LnJlYWR5U3RhdGUgIT09ICJsb2FkaW5nIiAmJgogICAgZG9jdW1lbnQucXVlcnlTZWxlY3Rvcignc2xpZGVzJykgPT09IG51bGwpIHsgCiAgLy8gaWYgdGhlIGRvY3VtZW50IGlzIGRvbmUgbG9hZGluZyBidXQgb3VyIGVsZW1lbnQgaGFzbid0IHlldCBhcHBlYXJlZCwgZGVmZXIKICAvLyBsb2FkaW5nIG9mIHRoZSBkZWNrCiAgd2luZG93LnNldFRpbWVvdXQoZnVuY3Rpb24oKSB7CiAgICBsb2FkRGVjayhudWxsKTsKICB9LCAwKTsKfSBlbHNlIHsKICAvLyBzdGlsbCBsb2FkaW5nIHRoZSBET00sIHNvIHdhaXQgdW50aWwgaXQncyBmaW5pc2hlZAogIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoIkRPTUNvbnRlbnRMb2FkZWQiLCBsb2FkRGVjayk7Cn0KCgoK"></script> <style type="text/css"> b, strong { font-weight: bold; } em { font-style: italic; } slides > slide { -webkit-transition: all 0.4s ease-in-out; -moz-transition: all 0.4s ease-in-out; -o-transition: all 0.4s ease-in-out; transition: all 0.4s ease-in-out; } .auto-fadein { -webkit-transition: opacity 0.6s ease-in; -webkit-transition-delay: 0.4s; -moz-transition: opacity 0.6s ease-in 0.4s; -o-transition: opacity 0.6s ease-in 0.4s; transition: opacity 0.6s ease-in 0.4s; opacity: 0; } </style>

3/31/2018

Introduction

  • This is the tenth course of the Coursera Data Science Specialization, Data Science Capstone. This course focuses on analyzing a large corpus of text documents to discover the structure in the data and how words are put together to build a predictive text model.
  • Contents
    • Text data analysis: analysis of the corpus to understand the relationship of words and word pairs
    • Predictive modeling: build basice n-gram models and develop algorithms to facilitate text prediction
    • Shiny app development: produce a web-based Shiny app interphase to predict next words

Modeling

  1. Getting and cleaning the data: profanity was first removed and words tokenized
  2. Exploratory data analysis: the frequencies of words and word paris were calculated
  3. Modeling: 2-7 gram models were built to facilitate word prediction
  4. Prediciton model:
    • Katz's back-off model was used to predict the next word
    • The model iterates from 7-gram to 2-gram to find matches in the last n-1 words
    • In the case of unseen n-gram, the most frequent word, 'the', is returned
    • To improve efficiency, word pairs that appear less than 5 times in the corpus were removed

Results

  • The data analysis and model building writeups can be found on GitHub
  • The Shiny app for prediction can be found here
  • The app takes in the following inputs:
    1. query word/phrase that the user inputs
    2. number of predicted next word
  • The predicted next word(s) will show up in the order of most frequently used to less frequently used

Reference

<script> (function () { var script = document.createElement("script"); script.type = "text/javascript"; script.src = "https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"; document.getElementsByTagName("head")[0].appendChild(script); })(); </script> <script> (function() { if (window.jQuery) { window.jQuery(document).on('slideleave', function(e) { window.jQuery(e.target).trigger('hidden'); }); window.jQuery(document).on('slideenter', function(e) { window.jQuery(e.target).trigger('shown'); }); } })(); </script>

About

Capstone project