Files
newbury-nights/public/js/game.js
T
jessikitty ec4442d4ce Add WebM (VP9+alpha) VideoTexture ghost billboards with GIF/WebP fallback
- Detect VP9-alpha WebM support once at load; iOS Safari falls back to <img>
- addGhost prefers data.webm via THREE.VideoTexture (browser-decoded, no
  per-frame needsUpdate pump) when supported
- On video error, gracefully swap the billboard to the GIF/image texture
- Pause + release ghost <video> elements on capture and on hunt teardown to
  avoid leaking decoders
2026-06-18 13:15:54 +10:00

1 line
31 KiB
JavaScript

aW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnOwoKLyogPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09CiAgIE5ld2J1cnkgTmlnaHRzIOKAlCBjbGllbnQgZ2FtZSBsb2dpYwogICAtIFNjcmVlbiByb3V0aW5nICh0aXRsZSAvIHNjYW4gLyBodW50IC8gcm9zdGVyKQogICAtIFFSIHNjYW4gdmlhIEJhcmNvZGVEZXRlY3RvciAobWFudWFsIGNvZGUgZmFsbGJhY2spCiAgIC0gQVIgaHVudDogY2FtZXJhIHBhc3N0aHJvdWdoICsgRGV2aWNlT3JpZW50YXRpb24gZ3lybyBsb29rLAogICAgIGNvbG9yLXdoZWVsIGdsb29tIGRldGVjdGlvbiwgYmxhc3RlciB3aXRoIG92ZXJoZWF0LAogICAgIHByb2NlZHVyYWwgd2lzcCBtZXNoZXMgKyBhbmltYXRlZC1HSUYgYmlsbGJvYXJkcy4KICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09ICovCgpjb25zdCAkID0gKHMsIHIgPSBkb2N1bWVudCkgPT4gci5xdWVyeVNlbGVjdG9yKHMpOwpjb25zdCAkJCA9IChzLCByID0gZG9jdW1lbnQpID0+IFsuLi5yLnF1ZXJ5U2VsZWN0b3JBbGwocyldOwoKY29uc3Qgc2NyZWVucyA9IHsKICB0aXRsZTogJCgnI3NjcmVlbi10aXRsZScpLAogIHNjYW46ICQoJyNzY3JlZW4tc2NhbicpLAogIGh1bnQ6ICQoJyNzY3JlZW4taHVudCcpLAogIHJvc3RlcjogJCgnI3NjcmVlbi1yb3N0ZXInKSwKICBhYm91dDogJCgnI3NjcmVlbi1hYm91dCcpLAp9OwpmdW5jdGlvbiBzaG93KG5hbWUpIHsKICBPYmplY3QudmFsdWVzKHNjcmVlbnMpLmZvckVhY2goKHMpID0+IHMuY2xhc3NMaXN0LmFkZCgnaGlkZGVuJykpOwogIHNjcmVlbnNbbmFtZV0uY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuJyk7Cn0KCi8qIC0tLS0tLS0tLS0gVGl0bGUgbmF2IC0tLS0tLS0tLS0gKi8KJCgnI2J0bi1zY2FuLXNldCcpLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gc3RhcnRTY2FuKCkpOwokKCcjYnRuLWZyZWVodW50JykuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiBzdGFydEh1bnQoeyBmcmVlSHVudDogdHJ1ZSB9KSk7CiQoJyNidG4tcm9zdGVyJykuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiBvcGVuUm9zdGVyKCkpOwokKCcjYnRuLWFib3V0JykuYWRkRXZlbnRMaXN0ZW5lcignY2xpY2snLCAoKSA9PiBzaG93KCdhYm91dCcpKTsKJCQoJ1tkYXRhLWJhY2tdJykuZm9yRWFjaCgoYikgPT4gYi5hZGRFdmVudExpc3RlbmVyKCdjbGljaycsICgpID0+IHJldHVybkhvbWUoKSkpOwoKZnVuY3Rpb24gcmV0dXJuSG9tZSgpIHsKICBzdG9wU2NhbigpOwogIGh1bnQuc3RvcCgpOwogIHNob3coJ3RpdGxlJyk7Cn0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBTQ0FOCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpsZXQgc2NhblN0cmVhbSA9IG51bGw7CmxldCBzY2FuTG9vcCA9IG51bGw7CmxldCBkZXRlY3RvciA9IG51bGw7Cgphc3luYyBmdW5jdGlvbiBzdGFydFNjYW4oKSB7CiAgc2hvdygnc2NhbicpOwogICQoJyNzY2FuLWVycm9yJykuY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7CiAgY29uc3Qgc3RhdHVzID0gJCgnI3NjYW4tc3RhdHVzJyk7CiAgY29uc3QgdmlkZW8gPSAkKCcjc2Nhbi12aWRlbycpOwoKICBpZiAoJ0JhcmNvZGVEZXRlY3RvcicgaW4gd2luZG93KSB7CiAgICB0cnkgewogICAgICBjb25zdCBmb3JtYXRzID0gYXdhaXQgd2luZG93LkJhcmNvZGVEZXRlY3Rvci5nZXRTdXBwb3J0ZWRGb3JtYXRzKCk7CiAgICAgIGlmIChmb3JtYXRzLmluY2x1ZGVzKCdxcl9jb2RlJykpIHsKICAgICAgICBkZXRlY3RvciA9IG5ldyB3aW5kb3cuQmFyY29kZURldGVjdG9yKHsgZm9ybWF0czogWydxcl9jb2RlJ10gfSk7CiAgICAgIH0KICAgIH0gY2F0Y2ggeyBkZXRlY3RvciA9IG51bGw7IH0KICB9CgogIHRyeSB7CiAgICBzY2FuU3RyZWFtID0gYXdhaXQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoewogICAgICB2aWRlbzogeyBmYWNpbmdNb2RlOiAnZW52aXJvbm1lbnQnIH0sIGF1ZGlvOiBmYWxzZSwKICAgIH0pOwogICAgdmlkZW8uc3JjT2JqZWN0ID0gc2NhblN0cmVhbTsKICAgIGF3YWl0IHZpZGVvLnBsYXkoKTsKICAgIHN0YXR1cy50ZXh0Q29udGVudCA9IGRldGVjdG9yID8gJ0xvb2tpbmcgZm9yIGEgc2V0IGNvZGXigKYnIDogJ0NhbWVyYSBvbiDigJQgZW50ZXIgY29kZSBiZWxvdyc7CiAgICBpZiAoZGV0ZWN0b3IpIHRpY2tTY2FuKHZpZGVvKTsKICB9IGNhdGNoIChlKSB7CiAgICBzdGF0dXMudGV4dENvbnRlbnQgPSAnQ2FtZXJhIHVuYXZhaWxhYmxlIOKAlCBlbnRlciB0aGUgY29kZSBiZWxvdyc7CiAgfQp9Cgphc3luYyBmdW5jdGlvbiB0aWNrU2Nhbih2aWRlbykgewogIGlmICghZGV0ZWN0b3IgfHwgIXNjYW5TdHJlYW0pIHJldHVybjsKICB0cnkgewogICAgY29uc3QgY29kZXMgPSBhd2FpdCBkZXRlY3Rvci5kZXRlY3QodmlkZW8pOwogICAgaWYgKGNvZGVzLmxlbmd0aCkgewogICAgICBjb25zdCByYXcgPSBjb2Rlc1swXS5yYXdWYWx1ZT8udHJpbSgpOwogICAgICBpZiAocmF3KSB7IHJlc29sdmVDb2RlKHJhdyk7IHJldHVybjsgfQogICAgfQogIH0gY2F0Y2ggeyAvKiBrZWVwIHRyeWluZyAqLyB9CiAgc2Nhbkxvb3AgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gdGlja1NjYW4odmlkZW8pKTsKfQoKZnVuY3Rpb24gc3RvcFNjYW4oKSB7CiAgaWYgKHNjYW5Mb29wKSBjYW5jZWxBbmltYXRpb25GcmFtZShzY2FuTG9vcCksIChzY2FuTG9vcCA9IG51bGwpOwogIGlmIChzY2FuU3RyZWFtKSB7IHNjYW5TdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCgodCkgPT4gdC5zdG9wKCkpOyBzY2FuU3RyZWFtID0gbnVsbDsgfQp9CgokKCcjYnRuLW1hbnVhbC1nbycpLmFkZEV2ZW50TGlzdGVuZXIoJ2NsaWNrJywgKCkgPT4gewogIGNvbnN0IGNvZGUgPSAkKCcjbWFudWFsLWNvZGUnKS52YWx1ZS50cmltKCk7CiAgaWYgKGNvZGUpIHJlc29sdmVDb2RlKGNvZGUpOwp9KTsKJCgnI21hbnVhbC1jb2RlJykuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIChlKSA9PiB7CiAgaWYgKGUua2V5ID09PSAnRW50ZXInKSAkKCcjYnRuLW1hbnVhbC1nbycpLmNsaWNrKCk7Cn0pOwoKYXN5bmMgZnVuY3Rpb24gcmVzb2x2ZUNvZGUoY29kZSkgewogIC8vIEFjY2VwdCBlaXRoZXIgYSBiYXJlIGNvZGUgb3IgYSBVUkwgd2hvc2UgbGFzdCBwYXRoL3F1ZXJ5IHNlZ21lbnQgaXMgdGhlIGNvZGUuCiAgY29uc3QgY2xlYW5lZCA9IGNvZGUuaW5jbHVkZXMoJy8nKSA/IGNvZGUuc3BsaXQoL1tcLz89XS8pLmZpbHRlcihCb29sZWFuKS5wb3AoKSA6IGNvZGU7CiAgdHJ5IHsKICAgIGNvbnN0IHJlcyA9IGF3YWl0IGZldGNoKGAvYXBpL3NjYW4vJHtlbmNvZGVVUklDb21wb25lbnQoY2xlYW5lZCl9YCk7CiAgICBpZiAoIXJlcy5vaykgdGhyb3cgbmV3IEVycm9yKCdVbmtub3duIHNldCBjb2RlJyk7CiAgICBjb25zdCBkYXRhID0gYXdhaXQgcmVzLmpzb24oKTsKICAgIHN0b3BTY2FuKCk7CiAgICBzdGFydEh1bnQoeyBzZXREYXRhOiBkYXRhIH0pOwogIH0gY2F0Y2ggKGUpIHsKICAgIGNvbnN0IGVyciA9ICQoJyNzY2FuLWVycm9yJyk7CiAgICBlcnIudGV4dENvbnRlbnQgPSBgQ291bGRuJ3QgZmluZCBhIHNldCBmb3IgIiR7Y2xlYW5lZH0iLiBDaGVjayB0aGUgY29kZSBhbmQgdHJ5IGFnYWluLmA7CiAgICBlcnIuY2xhc3NMaXN0LnJlbW92ZSgnaGlkZGVuJyk7CiAgfQp9CgovKiA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgSFVOVCAoQVIpCiAgID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwpjb25zdCBUWVBFX0NPTE9SUyA9IHsgcmVkOiAweGZmM2I1YywgeWVsbG93OiAweGZmYzIzYiwgYmx1ZTogMHgzYmI2ZmYgfTsKCi8vIERldGVjdCBWUDktd2l0aC1hbHBoYSBXZWJNIHN1cHBvcnQgb25jZS4gaU9TIFNhZmFyaSBoaXN0b3JpY2FsbHkgbGFja3MKLy8gcmVsaWFibGUgVlA5LWFscGhhLCBzbyB0aG9zZSBkZXZpY2VzIGZhbGwgYmFjayB0byB0aGUgR0lGL1dlYlAgPGltZz4gcGF0aC4KY29uc3QgU1VQUE9SVFNfV0VCTV9BTFBIQSA9ICgoKSA9PiB7CiAgdHJ5IHsKICAgIGNvbnN0IHYgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCd2aWRlbycpOwogICAgcmV0dXJuICEhdi5jYW5QbGF5VHlwZSAmJiB2LmNhblBsYXlUeXBlKCd2aWRlby93ZWJtOyBjb2RlY3M9InZwOSInKSAhPT0gJyc7CiAgfSBjYXRjaCB7CiAgICByZXR1cm4gZmFsc2U7CiAgfQp9KSgpOwoKY29uc3QgaHVudCA9IHsKICBydW5uaW5nOiBmYWxzZSwKICBzY2VuZTogbnVsbCwgY2FtZXJhOiBudWxsLCByZW5kZXJlcjogbnVsbCwgcmFmOiBudWxsLAogIHN0cmVhbTogbnVsbCwgdmlkZW86IG51bGwsCiAgZ2hvc3RzOiBbXSwgICAgICAgICAgLy8gYWN0aXZlIGdob3N0IG9iamVjdHMgaW4gdGhlIHNjZW5lCiAgdGFyZ2V0OiBudWxsLCAgICAgICAgLy8gY3VycmVudGx5IGxvY2tlZCBnaG9zdAogIGFybWVkVHlwZTogbnVsbCwgICAgIC8vIGNvbG9yLXdoZWVsIGFybWVkIHR5cGUKICBiYXR0ZXJ5OiAxMDAsCiAgZ2xvb206IDAsCiAgb3ZlcmhlYXQ6IDAsCiAgYmxhc3Rpbmc6IGZhbHNlLAogIG9yaWVudGF0aW9uOiB7IGFscGhhOiAwLCBiZXRhOiAwLCBnYW1tYTogMCwgYWN0aXZlOiBmYWxzZSB9LAogIHBvb2w6IFtdLCAgICAgICAgICAgIC8vIGdob3N0cyBhdmFpbGFibGUgdG8gc3Bhd24gKGZyb20gc2V0IHJvc3RlciBvciBmcmVlaHVudCkKICBib3NzOiBudWxsLAogIHJlbWFpbmluZzogMCwgICAgICAgIC8vIHNwb3RzIGxlZnQgdG8gY2xlYXIgKHNldCBtb2RlKQogIGZyZWVIdW50OiBmYWxzZSwKCiAgYXN5bmMgc3RhcnQoeyBzZXREYXRhLCBmcmVlSHVudCB9KSB7CiAgICBzaG93KCdodW50Jyk7CiAgICB0aGlzLnJ1bm5pbmcgPSB0cnVlOwogICAgdGhpcy5mcmVlSHVudCA9ICEhZnJlZUh1bnQ7CiAgICB0aGlzLmJhdHRlcnkgPSAxMDA7IHRoaXMuZ2xvb20gPSAwOyB0aGlzLm92ZXJoZWF0ID0gMDsgdGhpcy50YXJnZXQgPSBudWxsOyB0aGlzLmFybWVkVHlwZSA9IG51bGw7CiAgICB0aGlzLmdob3N0cyA9IFtdOwogICAgJCgnI3Jlc3VsdCcpLmNsYXNzTGlzdC5hZGQoJ2hpZGRlbicpOwogICAgJCgnI2xvY2tvbicpLmNsYXNzTGlzdC5hZGQoJ2hpZGRlbicpOwogICAgdGhpcy51cGRhdGVCYXR0ZXJ5KCk7IHRoaXMudXBkYXRlR2xvb20oKTsKCiAgICBpZiAoZnJlZUh1bnQpIHsKICAgICAgY29uc3QgcmVzID0gYXdhaXQgZmV0Y2goJy9hcGkvZnJlZWh1bnQ/bj02Jyk7CiAgICAgIHRoaXMucG9vbCA9IChhd2FpdCByZXMuanNvbigpKS5zcGF3bnM7CiAgICAgIHRoaXMuYm9zcyA9IG51bGw7CiAgICAgIHRoaXMucmVtYWluaW5nID0gSW5maW5pdHk7CiAgICB9IGVsc2UgewogICAgICB0aGlzLnBvb2wgPSBzZXREYXRhLnJvc3Rlci5maWx0ZXIoKGcpID0+ICFnLmlzQm9zcyk7CiAgICAgIHRoaXMuYm9zcyA9IHNldERhdGEuYm9zczsKICAgICAgdGhpcy5yZW1haW5pbmcgPSBNYXRoLm1pbig1LCB0aGlzLnBvb2wubGVuZ3RoKTsgLy8gc3BvdHMgdG8gY2xlYXIgYmVmb3JlIGJvc3MKICAgIH0KCiAgICBhd2FpdCB0aGlzLmluaXRDYW1lcmEoKTsKICAgIHRoaXMuaW5pdFNjZW5lKCk7CiAgICB0aGlzLmJpbmRDb250cm9scygpOwogICAgdGhpcy5tYXliZVByb21wdE1vdGlvbigpOwogICAgdGhpcy5zcGF3bk5leHQoKTsKICAgIHRoaXMubG9vcCgpOwogIH0sCgogIC8vIE9uIGlPUywgc3VyZmFjZSBhbiBleHBsaWNpdCAiRW5hYmxlIE1vdGlvbiIgYnV0dG9uLiBUYXBwaW5nIGl0IGlzIHRoZSBjbGVhbgogIC8vIHVzZXIgZ2VzdHVyZSBpT1MgbmVlZHMgdG8gc2hvdyBpdHMgTW90aW9uICYgT3JpZW50YXRpb24gQWNjZXNzIHByb21wdC4KICBtYXliZVByb21wdE1vdGlvbigpIHsKICAgIGNvbnN0IG92ZXJsYXkgPSAkKCcjbW90aW9uLWdhdGUnKTsKICAgIGlmICghdGhpcy5neXJvTmVlZHNQZXJtaXNzaW9uKCkpIHsgb3ZlcmxheS5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTsgcmV0dXJuOyB9CiAgICBvdmVybGF5LmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpOwogICAgY29uc3QgYnRuID0gJCgnI21vdGlvbi1lbmFibGUnKTsKICAgIGNvbnN0IG9uVGFwID0gYXN5bmMgKCkgPT4gewogICAgICBjb25zdCBvayA9IGF3YWl0IHRoaXMucmVxdWVzdEd5cm8oKTsKICAgICAgb3ZlcmxheS5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKTsKICAgICAgaWYgKCFvaykgdGhpcy50b2FzdCgnTW90aW9uIGJsb2NrZWQg4oCUIGVuYWJsZSBpdCBpbiBTZXR0aW5ncyDigLogU2FmYXJpJywgMjIwMCk7CiAgICB9OwogICAgYnRuLm9uY2xpY2sgPSBvblRhcDsKICAgIHRoaXMuX21vdGlvbkVscyA9IHsgb3ZlcmxheSwgYnRuIH07CiAgfSwKCiAgYXN5bmMgaW5pdENhbWVyYSgpIHsKICAgIHRoaXMudmlkZW8gPSAkKCcjYXItdmlkZW8nKTsKICAgIHRyeSB7CiAgICAgIHRoaXMuc3RyZWFtID0gYXdhaXQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoewogICAgICAgIHZpZGVvOiB7IGZhY2luZ01vZGU6ICdlbnZpcm9ubWVudCcgfSwgYXVkaW86IGZhbHNlLAogICAgICB9KTsKICAgICAgdGhpcy52aWRlby5zcmNPYmplY3QgPSB0aGlzLnN0cmVhbTsKICAgICAgYXdhaXQgdGhpcy52aWRlby5wbGF5KCk7CiAgICB9IGNhdGNoIHsgLyogbm8gY2FtZXJhIOKGkiBkYXJrIGJhY2tkcm9wLCBneXJvIHN0aWxsIHdvcmtzICovIH0KICB9LAoKICBpbml0U2NlbmUoKSB7CiAgICBjb25zdCBjYW52YXMgPSAkKCcjYXItY2FudmFzJyk7CiAgICB0aGlzLnJlbmRlcmVyID0gbmV3IFRIUkVFLldlYkdMUmVuZGVyZXIoeyBjYW52YXMsIGFscGhhOiB0cnVlLCBhbnRpYWxpYXM6IHRydWUgfSk7CiAgICB0aGlzLnJlbmRlcmVyLnNldFBpeGVsUmF0aW8oTWF0aC5taW4oZGV2aWNlUGl4ZWxSYXRpbywgMikpOwogICAgdGhpcy5yZW5kZXJlci5zZXRTaXplKGlubmVyV2lkdGgsIGlubmVySGVpZ2h0KTsKCiAgICB0aGlzLnNjZW5lID0gbmV3IFRIUkVFLlNjZW5lKCk7CiAgICB0aGlzLmNhbWVyYSA9IG5ldyBUSFJFRS5QZXJzcGVjdGl2ZUNhbWVyYSg3MCwgaW5uZXJXaWR0aCAvIGlubmVySGVpZ2h0LCAwLjEsIDEwMCk7CiAgICB0aGlzLmNhbWVyYS5wb3NpdGlvbi5zZXQoMCwgMCwgMCk7CgogICAgdGhpcy5zY2VuZS5hZGQobmV3IFRIUkVFLkFtYmllbnRMaWdodCgweGZmZmZmZiwgMC44KSk7CiAgICBjb25zdCBwID0gbmV3IFRIUkVFLlBvaW50TGlnaHQoMHg4OGFhZmYsIDEuMiwgNTApOwogICAgcC5wb3NpdGlvbi5zZXQoMCwgMiwgMik7CiAgICB0aGlzLnNjZW5lLmFkZChwKTsKCiAgICB0aGlzLl9vblJlc2l6ZSA9ICgpID0+IHsKICAgICAgdGhpcy5jYW1lcmEuYXNwZWN0ID0gaW5uZXJXaWR0aCAvIGlubmVySGVpZ2h0OwogICAgICB0aGlzLmNhbWVyYS51cGRhdGVQcm9qZWN0aW9uTWF0cml4KCk7CiAgICAgIHRoaXMucmVuZGVyZXIuc2V0U2l6ZShpbm5lcldpZHRoLCBpbm5lckhlaWdodCk7CiAgICB9OwogICAgYWRkRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fb25SZXNpemUpOwoKICAgIC8vIEd5cm8gbG9vay4gaU9TIFNhZmFyaSByZXF1aXJlcyBEZXZpY2VPcmllbnRhdGlvbkV2ZW50LnJlcXVlc3RQZXJtaXNzaW9uKCkKICAgIC8vIGZyb20gYW4gZXhwbGljaXQgdXNlciBnZXN0dXJlIChoYW5kbGVkIGJ5IHRoZSAiRW5hYmxlIE1vdGlvbiIgYnV0dG9uIGluCiAgICAvLyBzdGFydCgpKS4gT3RoZXIgYnJvd3NlcnMgY2FuIGF0dGFjaCB0aGUgbGlzdGVuZXIgaW1tZWRpYXRlbHkuCiAgICB0aGlzLl9vbk9yaWVudCA9IChlKSA9PiB7CiAgICAgIGlmIChlLmFscGhhID09IG51bGwpIHJldHVybjsKICAgICAgdGhpcy5vcmllbnRhdGlvbiA9IHsgYWxwaGE6IGUuYWxwaGEsIGJldGE6IGUuYmV0YSwgZ2FtbWE6IGUuZ2FtbWEsIGFjdGl2ZTogdHJ1ZSB9OwogICAgfTsKICAgIGlmICghdGhpcy5neXJvTmVlZHNQZXJtaXNzaW9uKCkpIHsKICAgICAgYWRkRXZlbnRMaXN0ZW5lcignZGV2aWNlb3JpZW50YXRpb24nLCB0aGlzLl9vbk9yaWVudCk7CiAgICAgIHRoaXMuX2d5cm9BdHRhY2hlZCA9IHRydWU7CiAgICB9CiAgfSwKCiAgZ3lyb05lZWRzUGVybWlzc2lvbigpIHsKICAgIGNvbnN0IERPRSA9IHdpbmRvdy5EZXZpY2VPcmllbnRhdGlvbkV2ZW50OwogICAgcmV0dXJuICEhKERPRSAmJiB0eXBlb2YgRE9FLnJlcXVlc3RQZXJtaXNzaW9uID09PSAnZnVuY3Rpb24nKTsKICB9LAoKICAvLyBDYWxsZWQgZnJvbSBhIGNsZWFuIHRhcCAodGhlIEVuYWJsZSBNb3Rpb24gb3ZlcmxheSkuIE9uIGlPUyB0aGlzIHRyaWdnZXJzCiAgLy8gdGhlIHN5c3RlbSAiTW90aW9uICYgT3JpZW50YXRpb24gQWNjZXNzIiBwcm9tcHQ7IG9uY2UgZ3JhbnRlZCB3ZSBhdHRhY2ggdGhlCiAgLy8gbGlzdGVuZXIuIFNhZmUgdG8gY2FsbCBtb3JlIHRoYW4gb25jZS4KICBhc3luYyByZXF1ZXN0R3lybygpIHsKICAgIGlmICh0aGlzLl9neXJvQXR0YWNoZWQpIHJldHVybiB0cnVlOwogICAgY29uc3QgRE9FID0gd2luZG93LkRldmljZU9yaWVudGF0aW9uRXZlbnQ7CiAgICB0cnkgewogICAgICBpZiAoRE9FICYmIHR5cGVvZiBET0UucmVxdWVzdFBlcm1pc3Npb24gPT09ICdmdW5jdGlvbicpIHsKICAgICAgICBjb25zdCByZXMgPSBhd2FpdCBET0UucmVxdWVzdFBlcm1pc3Npb24oKTsKICAgICAgICBpZiAocmVzICE9PSAnZ3JhbnRlZCcpIHJldHVybiBmYWxzZTsKICAgICAgfQogICAgICBhZGRFdmVudExpc3RlbmVyKCdkZXZpY2VvcmllbnRhdGlvbicsIHRoaXMuX29uT3JpZW50KTsKICAgICAgdGhpcy5fZ3lyb0F0dGFjaGVkID0gdHJ1ZTsKICAgICAgcmV0dXJuIHRydWU7CiAgICB9IGNhdGNoIHsKICAgICAgcmV0dXJuIGZhbHNlOwogICAgfQogIH0sCgogIGJpbmRDb250cm9scygpIHsKICAgIC8vIGNvbG9yIHdoZWVsCiAgICAkJCgnLndoZWVsLXNlZycpLmZvckVhY2goKHNlZykgPT4gewogICAgICBzZWcub25jbGljayA9ICgpID0+IHsKICAgICAgICBjb25zdCB0eXBlID0gc2VnLmRhdGFzZXQudHlwZTsKICAgICAgICB0aGlzLmFybWVkVHlwZSA9IHR5cGU7CiAgICAgICAgJCQoJy53aGVlbC1zZWcnKS5mb3JFYWNoKChzKSA9PiBzLmNsYXNzTGlzdC5yZW1vdmUoJ2FybWVkJykpOwogICAgICAgIHNlZy5jbGFzc0xpc3QuYWRkKCdhcm1lZCcpOwogICAgICAgICQoJyN3aGVlbC1jb3JlJykudGV4dENvbnRlbnQgPSB0eXBlLnRvVXBwZXJDYXNlKCk7CiAgICAgICAgdGhpcy5zY2FuR2xvb20odHlwZSk7CiAgICAgIH07CiAgICB9KTsKCiAgICBjb25zdCBibGFzdCA9ICQoJyNidG4tYmxhc3QnKTsKICAgIGNvbnN0IHN0YXJ0Qmxhc3QgPSAoZSkgPT4gewogICAgICBlLnByZXZlbnREZWZhdWx0KCk7CiAgICAgIHRoaXMuYmxhc3RpbmcgPSB0cnVlOwogICAgfTsKICAgIGNvbnN0IGVuZEJsYXN0ID0gKCkgPT4geyB0aGlzLmJsYXN0aW5nID0gZmFsc2U7IH07CiAgICBibGFzdC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0Jywgc3RhcnRCbGFzdCwgeyBwYXNzaXZlOiBmYWxzZSB9KTsKICAgIGJsYXN0LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlZG93bicsIHN0YXJ0Qmxhc3QpOwogICAgYWRkRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCBlbmRCbGFzdCk7CiAgICBhZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgZW5kQmxhc3QpOwogICAgdGhpcy5fYmxhc3RFbHMgPSB7IGJsYXN0LCBzdGFydEJsYXN0LCBlbmRCbGFzdCB9OwogIH0sCgogIC8qIHNwYXduIGEgd2lzcC9iaWxsYm9hcmQgZ2hvc3QgYXQgYSByYW5kb20gc3BvdCBhcm91bmQgdGhlIHBsYXllciAqLwogIHNwYXduTmV4dCgpIHsKICAgIGlmICghdGhpcy5wb29sLmxlbmd0aCkgcmV0dXJuOwogICAgY29uc3QgZGF0YSA9IHRoaXMucG9vbFtNYXRoLmZsb29yKE1hdGgucmFuZG9tKCkgKiB0aGlzLnBvb2wubGVuZ3RoKV07CiAgICB0aGlzLmFkZEdob3N0KGRhdGEpOwogIH0sCgogIGFkZEdob3N0KGRhdGEsIGlzQm9zcyA9IGZhbHNlKSB7CiAgICBjb25zdCBncm91cCA9IG5ldyBUSFJFRS5Hcm91cCgpOwogICAgY29uc3QgY29sb3IgPSBUWVBFX0NPTE9SU1tkYXRhLnR5cGVdID8/IDB4ZmZmZmZmOwoKICAgIGxldCBtZXNoOwogICAgbGV0IHRleHR1cmUgPSBudWxsOwogICAgaWYgKGRhdGEud2VibSAmJiBTVVBQT1JUU19XRUJNX0FMUEhBKSB7CiAgICAgIC8vIFdlYk0gKFZQOSthbHBoYSkgYmlsbGJvYXJkIHZpYSBWaWRlb1RleHR1cmUuIFRoZSBicm93c2VyIGRlY29kZXMgYW5kCiAgICAgIC8vIHVwZGF0ZXMgdGhlIHRleHR1cmUgaXRzZWxmIOKAlCBubyBwZXItZnJhbWUgbmVlZHNVcGRhdGUgcHVtcGluZyBuZWVkZWQuCiAgICAgIGNvbnN0IHZpZCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ3ZpZGVvJyk7CiAgICAgIHZpZC5jcm9zc09yaWdpbiA9ICdhbm9ueW1vdXMnOwogICAgICB2aWQubXV0ZWQgPSB0cnVlOyAgICAgICAgLy8gcmVxdWlyZWQgZm9yIGF1dG9wbGF5CiAgICAgIHZpZC5sb29wID0gdHJ1ZTsKICAgICAgdmlkLnBsYXlzSW5saW5lID0gdHJ1ZTsgIC8vIGlPUzogc3RheSBpbmxpbmUsIGRvbid0IGZ1bGxzY3JlZW4KICAgICAgdmlkLmF1dG9wbGF5ID0gdHJ1ZTsKICAgICAgdmlkLnByZWxvYWQgPSAnYXV0byc7CiAgICAgIHZpZC5zcmMgPSBkYXRhLndlYm07CiAgICAgIHRleHR1cmUgPSBuZXcgVEhSRUUuVmlkZW9UZXh0dXJlKHZpZCk7CiAgICAgIHRleHR1cmUuY29sb3JTcGFjZSA9IFRIUkVFLlNSR0JDb2xvclNwYWNlOwogICAgICB0ZXh0dXJlLm1pbkZpbHRlciA9IFRIUkVFLkxpbmVhckZpbHRlcjsKICAgICAgdGV4dHVyZS5tYWdGaWx0ZXIgPSBUSFJFRS5MaW5lYXJGaWx0ZXI7CiAgICAgIHRleHR1cmUuZ2VuZXJhdGVNaXBtYXBzID0gZmFsc2U7CiAgICAgIGNvbnN0IG1hdCA9IG5ldyBUSFJFRS5NZXNoQmFzaWNNYXRlcmlhbCh7IG1hcDogdGV4dHVyZSwgdHJhbnNwYXJlbnQ6IHRydWUsIHNpZGU6IFRIUkVFLkRvdWJsZVNpZGUsIGRlcHRoV3JpdGU6IGZhbHNlIH0pOwogICAgICBtZXNoID0gbmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLlBsYW5lR2VvbWV0cnkoMS4yLCAxLjIpLCBtYXQpOwogICAgICAvLyBJZiB0aGUgdmlkZW8gZXJyb3JzIChlLmcuIGFscGhhIHVuc3VwcG9ydGVkIGRlc3BpdGUgY2FuUGxheVR5cGUpLCBzd2FwCiAgICAgIC8vIHRvIHRoZSBHSUYvaW1hZ2UgYmlsbGJvYXJkIGlmIHdlIGhhdmUgb25lLgogICAgICB2aWQub25lcnJvciA9ICgpID0+IHsKICAgICAgICBpZiAoZ3JvdXAudXNlckRhdGEudmlkZW9GZWxsQmFjaykgcmV0dXJuOwogICAgICAgIGdyb3VwLnVzZXJEYXRhLnZpZGVvRmVsbEJhY2sgPSB0cnVlOwogICAgICAgIGlmIChkYXRhLmltYWdlKSB7CiAgICAgICAgICBjb25zdCBpbWcgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdpbWcnKTsKICAgICAgICAgIGltZy5jcm9zc09yaWdpbiA9ICdhbm9ueW1vdXMnOwogICAgICAgICAgaW1nLnNyYyA9IGRhdGEuaW1hZ2U7CiAgICAgICAgICBjb25zdCB0MiA9IG5ldyBUSFJFRS5UZXh0dXJlKGltZyk7CiAgICAgICAgICBpbWcub25sb2FkID0gKCkgPT4geyB0Mi5uZWVkc1VwZGF0ZSA9IHRydWU7IH07CiAgICAgICAgICBtZXNoLm1hdGVyaWFsLm1hcCA9IHQyOwogICAgICAgICAgbWVzaC5tYXRlcmlhbC5uZWVkc1VwZGF0ZSA9IHRydWU7CiAgICAgICAgICBncm91cC51c2VyRGF0YS5naWZJbWcgPSBpbWc7CiAgICAgICAgICBncm91cC51c2VyRGF0YS5naWZUZXggPSB0MjsKICAgICAgICAgIGdyb3VwLnVzZXJEYXRhLnZpZEVsID0gbnVsbDsKICAgICAgICB9CiAgICAgIH07CiAgICAgIGNvbnN0IHByID0gdmlkLnBsYXkoKTsKICAgICAgaWYgKHByICYmIHByLmNhdGNoKSBwci5jYXRjaCgoKSA9PiB7fSk7CiAgICAgIGdyb3VwLnVzZXJEYXRhLnZpZEVsID0gdmlkOwogICAgfSBlbHNlIGlmIChkYXRhLmltYWdlKSB7CiAgICAgIC8vIGFuaW1hdGVkIEdJRiBiaWxsYm9hcmQg4oCUIHRleHR1cmUubmVlZHNVcGRhdGUgcHVtcGVkIGVhY2ggZnJhbWUKICAgICAgY29uc3QgaW1nID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnaW1nJyk7CiAgICAgIGltZy5jcm9zc09yaWdpbiA9ICdhbm9ueW1vdXMnOwogICAgICBpbWcuc3JjID0gZGF0YS5pbWFnZTsKICAgICAgdGV4dHVyZSA9IG5ldyBUSFJFRS5UZXh0dXJlKGltZyk7CiAgICAgIGltZy5vbmxvYWQgPSAoKSA9PiB7IHRleHR1cmUubmVlZHNVcGRhdGUgPSB0cnVlOyB9OwogICAgICBjb25zdCBtYXQgPSBuZXcgVEhSRUUuTWVzaEJhc2ljTWF0ZXJpYWwoeyBtYXA6IHRleHR1cmUsIHRyYW5zcGFyZW50OiB0cnVlLCBzaWRlOiBUSFJFRS5Eb3VibGVTaWRlIH0pOwogICAgICBtZXNoID0gbmV3IFRIUkVFLk1lc2gobmV3IFRIUkVFLlBsYW5lR2VvbWV0cnkoMS4yLCAxLjIpLCBtYXQpOwogICAgICBncm91cC51c2VyRGF0YS5naWZJbWcgPSBpbWc7CiAgICAgIGdyb3VwLnVzZXJEYXRhLmdpZlRleCA9IHRleHR1cmU7CiAgICB9IGVsc2UgewogICAgICAvLyBwcm9jZWR1cmFsIHdpc3A6IGdsb3dpbmcgc3BoZXJlICsgaGFsbwogICAgICBjb25zdCBnZW8gPSBuZXcgVEhSRUUuU3BoZXJlR2VvbWV0cnkoMC40NSwgMjQsIDI0KTsKICAgICAgY29uc3QgbWF0ID0gbmV3IFRIUkVFLk1lc2hTdGFuZGFyZE1hdGVyaWFsKHsKICAgICAgICBjb2xvciwgZW1pc3NpdmU6IGNvbG9yLCBlbWlzc2l2ZUludGVuc2l0eTogMS40LCByb3VnaG5lc3M6IDAuNCwKICAgICAgICB0cmFuc3BhcmVudDogdHJ1ZSwgb3BhY2l0eTogMC45MiwKICAgICAgfSk7CiAgICAgIG1lc2ggPSBuZXcgVEhSRUUuTWVzaChnZW8sIG1hdCk7CiAgICAgIGNvbnN0IGhhbG8gPSBuZXcgVEhSRUUuTWVzaCgKICAgICAgICBuZXcgVEhSRUUuU3BoZXJlR2VvbWV0cnkoMC42MiwgMjQsIDI0KSwKICAgICAgICBuZXcgVEhSRUUuTWVzaEJhc2ljTWF0ZXJpYWwoeyBjb2xvciwgdHJhbnNwYXJlbnQ6IHRydWUsIG9wYWNpdHk6IDAuMTYsIHNpZGU6IFRIUkVFLkJhY2tTaWRlIH0pCiAgICAgICk7CiAgICAgIGdyb3VwLmFkZChoYWxvKTsKICAgIH0KICAgIGdyb3VwLmFkZChtZXNoKTsKCiAgICAvLyBQbGFjZSBpbiBhIGZvcndhcmQtZmFjaW5nIGFyYyBzbyBnaG9zdHMgYXJlIGZpbmRhYmxlIHdpdGhvdXQgcGVyZmVjdAogICAgLy8gYWltaW5nOiB5YXcgd2l0aGluIMKxNjDCsCBvZiBzdHJhaWdodCBhaGVhZCwgbW9kZXN0IHBpdGNoLCBjbG9zZXIgaW4uCiAgICBjb25zdCB5YXcgPSAoTWF0aC5yYW5kb20oKSAtIDAuNSkgKiAoTWF0aC5QSSAqIDIgLyAzKTsKICAgIGNvbnN0IHBpdGNoID0gKE1hdGgucmFuZG9tKCkgLSAwLjUpICogMC41OwogICAgY29uc3QgZGlzdCA9IDMgKyBNYXRoLnJhbmRvbSgpICogMS41OwogICAgZ3JvdXAucG9zaXRpb24uc2V0KAogICAgICBNYXRoLnNpbih5YXcpICogZGlzdCwKICAgICAgTWF0aC5zaW4ocGl0Y2gpICogZGlzdCwKICAgICAgLU1hdGguY29zKHlhdykgKiBkaXN0CiAgICApOwoKICAgIGdyb3VwLnVzZXJEYXRhID0gewogICAgICAuLi5ncm91cC51c2VyRGF0YSwKICAgICAgZGF0YSwgaXNCb3NzLAogICAgICBocDogZGF0YS5oZWFsdGgsIG1heEhwOiBkYXRhLmhlYWx0aCwKICAgICAgYm9iUGhhc2U6IE1hdGgucmFuZG9tKCkgKiBNYXRoLlBJICogMiwKICAgICAgcmV2ZWFsZWQ6IHRydWUsIC8vIHZpc2libGUgb24gc3Bhd247IHRoZSB3aGVlbCBub3cgYWdncm9zL3RpbnRzIHJhdGhlciB0aGFuIHVuY2xvYWtzCiAgICB9OwogICAgdGhpcy5zY2VuZS5hZGQoZ3JvdXApOwogICAgdGhpcy5naG9zdHMucHVzaChncm91cCk7CiAgfSwKCiAgc2Nhbkdsb29tKHR5cGUpIHsKICAgIC8vIEdob3N0cyBhcmUgdmlzaWJsZSBvbiBzcGF3biBub3csIHNvIHRoZSB3aGVlbCBhY3RzIGFzIGEgImx1cmUiOiBzY2FubmluZyBhCiAgICAvLyBjb2xvdXIgcHVsbHMgdGhlIG5lYXJlc3QgbWF0Y2hpbmcgZ2hvc3QgdG93YXJkIHlvdXIgYWltIGFuZCBjaGFyZ2VzIGdsb29tLgogICAgLy8gTWlzbWF0Y2hlZCBjb2xvdXIgcmlza3MgYSBqdW1wc2NhcmUuCiAgICBjb25zdCBtYXRjaGVzID0gdGhpcy5naG9zdHMuZmlsdGVyKChnKSA9PiBnLnVzZXJEYXRhLmRhdGEudHlwZSA9PT0gdHlwZSk7CiAgICBpZiAobWF0Y2hlcy5sZW5ndGgpIHsKICAgICAgLy8gcHVsbCB0aGUgbmVhcmVzdCBtYXRjaCBpbnRvIGEgZm9yd2FyZCwgZWFzeS10by1haW0gcG9zaXRpb24KICAgICAgY29uc3QgZyA9IG1hdGNoZXNbMF07CiAgICAgIGNvbnN0IGRpc3QgPSAzOwogICAgICBnLnBvc2l0aW9uLnNldCgoTWF0aC5yYW5kb20oKSAtIDAuNSkgKiAxLjIsIChNYXRoLnJhbmRvbSgpIC0gMC4zKSAqIDAuOCwgLWRpc3QpOwogICAgICBnLnVzZXJEYXRhLmx1cmVkID0gdHJ1ZTsKICAgICAgdGhpcy5nbG9vbSArPSA1OyB0aGlzLnVwZGF0ZUdsb29tKCk7CiAgICAgIHRoaXMudG9hc3QoYCR7dHlwZS50b1VwcGVyQ2FzZSgpfSBnaG9zdCBsdXJlZCBpbmAsIDgwMCk7CiAgICB9IGVsc2UgewogICAgICAvLyBubyBnaG9zdCBvZiB0aGF0IGNvbG91ciBwcmVzZW50IOKAlCBzbWFsbCBjaGFuY2Ugb2YgYSBqdW1wc2NhcmUKICAgICAgaWYgKE1hdGgucmFuZG9tKCkgPCAwLjEyKSB0aGlzLmp1bXBzY2FyZSgpOwogICAgICBlbHNlIHsgdGhpcy5nbG9vbSArPSAyOyB0aGlzLnVwZGF0ZUdsb29tKCk7IHRoaXMudG9hc3QoJysyIGdsb29tJywgNjAwKTsgfQogICAgfQogIH0sCgogIGxvb3AoKSB7CiAgICBpZiAoIXRoaXMucnVubmluZykgcmV0dXJuOwogICAgdGhpcy5yYWYgPSByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gdGhpcy5sb29wKCkpOwogICAgY29uc3QgdCA9IHBlcmZvcm1hbmNlLm5vdygpIC8gMTAwMDsKCiAgICAvLyBjYW1lcmEgeWF3L3BpdGNoIGZyb20gZ3lybwogICAgaWYgKHRoaXMub3JpZW50YXRpb24uYWN0aXZlKSB7CiAgICAgIGNvbnN0IHsgYWxwaGEsIGJldGEsIGdhbW1hIH0gPSB0aGlzLm9yaWVudGF0aW9uOwogICAgICAvLyBzaW1wbGUgbWFwcGluZzsgZ29vZCBlbm91Z2ggZm9yIGxvb2stYXJvdW5kIGFpbWluZwogICAgICB0aGlzLmNhbWVyYS5yb3RhdGlvbi5zZXQoCiAgICAgICAgVEhSRUUuTWF0aFV0aWxzLmRlZ1RvUmFkKChiZXRhID8/IDApIC0gOTApLAogICAgICAgIFRIUkVFLk1hdGhVdGlscy5kZWdUb1JhZChhbHBoYSA/PyAwKSwKICAgICAgICBUSFJFRS5NYXRoVXRpbHMuZGVnVG9SYWQoLShnYW1tYSA/PyAwKSksCiAgICAgICAgJ1lYWicKICAgICAgKTsKICAgIH0KCiAgICAvLyBhbmltYXRlIGdob3N0czogYm9iICsgZmFjZSBjYW1lcmEgKyBwdW1wIEdJRiB0ZXh0dXJlcwogICAgZm9yIChjb25zdCBnIG9mIHRoaXMuZ2hvc3RzKSB7CiAgICAgIGcucG9zaXRpb24ueSArPSBNYXRoLnNpbih0ICogMS41ICsgZy51c2VyRGF0YS5ib2JQaGFzZSkgKiAwLjAwMjU7CiAgICAgIGcubG9va0F0KHRoaXMuY2FtZXJhLnBvc2l0aW9uKTsKICAgICAgaWYgKGcudXNlckRhdGEuZ2lmVGV4ICYmIGcudXNlckRhdGEuZ2lmSW1nPy5jb21wbGV0ZSkgZy51c2VyRGF0YS5naWZUZXgubmVlZHNVcGRhdGUgPSB0cnVlOwogICAgfQoKICAgIC8vIHRhcmdldGluZzogZ2hvc3QgbmVhcmVzdCBzY3JlZW4tY2VudGVyIChhbmQgcmV2ZWFsZWQpIGJlY29tZXMgdGhlIGxvY2stb24KICAgIHRoaXMudXBkYXRlVGFyZ2V0KCk7CgogICAgLy8gYmxhc3RlcgogICAgaWYgKHRoaXMuYmxhc3RpbmcgJiYgdGhpcy5vdmVyaGVhdCA8IDEwMCAmJiB0aGlzLnRhcmdldCkgewogICAgICBjb25zdCBkbWcgPSAwLjk7IC8vIHBlci1mcmFtZSBjaGlwIGRhbWFnZQogICAgICB0aGlzLnRhcmdldC51c2VyRGF0YS5ocCAtPSBkbWc7CiAgICAgIHRoaXMub3ZlcmhlYXQgPSBNYXRoLm1pbigxMDAsIHRoaXMub3ZlcmhlYXQgKyAwLjgpOwogICAgICB0aGlzLnVwZGF0ZUdob3N0SHAoKTsKICAgICAgaWYgKHRoaXMudGFyZ2V0LnVzZXJEYXRhLmhwIDw9IDApIHRoaXMuY2FwdHVyZVRhcmdldCgpOwogICAgfSBlbHNlIGlmICghdGhpcy5ibGFzdGluZyAmJiB0aGlzLm92ZXJoZWF0ID4gMCkgewogICAgICB0aGlzLm92ZXJoZWF0ID0gTWF0aC5tYXgoMCwgdGhpcy5vdmVyaGVhdCAtIDEuMik7IC8vIGNvb2wgZG93bgogICAgfQogICAgaWYgKHRoaXMub3ZlcmhlYXQgPj0gMTAwKSB0aGlzLmJsYXN0aW5nID0gZmFsc2U7CiAgICB0aGlzLnVwZGF0ZU92ZXJoZWF0KCk7CgogICAgLy8gZ2hvc3RzIGF0dGFjazogZHJhaW4gYmF0dGVyeSBpZiBhIHJldmVhbGVkIGdob3N0IGlzIGluIGZyb250IG9mIHlvdQogICAgdGhpcy5tYXliZVRha2VEYW1hZ2UoKTsKCiAgICB0aGlzLnJlbmRlcmVyLnJlbmRlcih0aGlzLnNjZW5lLCB0aGlzLmNhbWVyYSk7CiAgfSwKCiAgdXBkYXRlVGFyZ2V0KCkgewogICAgY29uc3QgY2VudGVyID0gbmV3IFRIUkVFLlZlY3RvcjIoMCwgMCk7CiAgICBsZXQgYmVzdCA9IG51bGwsIGJlc3REaXN0ID0gMC41OyAvLyB3aXRoaW4gfmhhbGYtc2NyZWVuIG9mIGNlbnRlcgogICAgY29uc3QgdiA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7CiAgICBmb3IgKGNvbnN0IGcgb2YgdGhpcy5naG9zdHMpIHsKICAgICAgaWYgKCFnLnVzZXJEYXRhLnJldmVhbGVkKSBjb250aW51ZTsKICAgICAgdi5jb3B5KGcucG9zaXRpb24pLnByb2plY3QodGhpcy5jYW1lcmEpOwogICAgICBpZiAodi56ID4gMSkgY29udGludWU7IC8vIGJlaGluZCBjYW1lcmEKICAgICAgY29uc3QgZCA9IE1hdGguaHlwb3Qodi54IC0gY2VudGVyLngsIHYueSAtIGNlbnRlci55KTsKICAgICAgaWYgKGQgPCBiZXN0RGlzdCkgeyBiZXN0RGlzdCA9IGQ7IGJlc3QgPSBnOyB9CiAgICB9CiAgICBpZiAoYmVzdCAhPT0gdGhpcy50YXJnZXQpIHsKICAgICAgdGhpcy50YXJnZXQgPSBiZXN0OwogICAgICB0aGlzLnJlbmRlckxvY2tvbigpOwogICAgfQogIH0sCgogIHJlbmRlckxvY2tvbigpIHsKICAgIGNvbnN0IGxvY2sgPSAkKCcjbG9ja29uJyk7CiAgICBpZiAoIXRoaXMudGFyZ2V0KSB7IGxvY2suY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7IHJldHVybjsgfQogICAgY29uc3QgZCA9IHRoaXMudGFyZ2V0LnVzZXJEYXRhLmRhdGE7CiAgICBsb2NrLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpOwogICAgLy8gSU1QT1JUQU5UOiBsYWJlbCByZWFkcyBkaXNwbGF5TmFtZSwgbm90IGEgaGFyZGNvZGVkIHRpbnQgbmFtZQogICAgJCgnI2xvY2tvbi1uYW1lJykudGV4dENvbnRlbnQgPSBkLmRpc3BsYXlOYW1lIHx8IGQubmFtZTsKICAgICQoJyNsb2Nrb24tbmFtZScpLmNsYXNzTmFtZSA9IGBsb2Nrb24tbmFtZSBkaXNwbGF5IHR5cGUtJHtkLnR5cGV9YDsKICAgICQoJyNsb2Nrb24tdHlwZScpLnRleHRDb250ZW50ID0gZC50eXBlOwogICAgJCgnI2xvY2tvbi1yYXJpdHknKS50ZXh0Q29udGVudCA9ICfimIUnLnJlcGVhdChkLnJhcml0eSk7CiAgICAkKCcjbG9ja29uLWFiaWxpdHknKS50ZXh0Q29udGVudCA9IGQuYWJpbGl0eSB8fCAn4oCUJzsKICAgIHRoaXMudXBkYXRlR2hvc3RIcCgpOwogIH0sCgogIHVwZGF0ZUdob3N0SHAoKSB7CiAgICBpZiAoIXRoaXMudGFyZ2V0KSByZXR1cm47CiAgICBjb25zdCBwY3QgPSBNYXRoLm1heCgwLCAodGhpcy50YXJnZXQudXNlckRhdGEuaHAgLyB0aGlzLnRhcmdldC51c2VyRGF0YS5tYXhIcCkgKiAxMDApOwogICAgJCgnI2dob3N0LWhwLWZpbGwnKS5zdHlsZS53aWR0aCA9IGAke3BjdH0lYDsKICB9LAoKICBjYXB0dXJlVGFyZ2V0KCkgewogICAgY29uc3QgZyA9IHRoaXMudGFyZ2V0OwogICAgY29uc3QgZCA9IGcudXNlckRhdGEuZGF0YTsKICAgIGlmIChnLnVzZXJEYXRhLnZpZEVsKSB7IHRyeSB7IGcudXNlckRhdGEudmlkRWwucGF1c2UoKTsgZy51c2VyRGF0YS52aWRFbC5zcmMgPSAnJzsgfSBjYXRjaCB7fSBnLnVzZXJEYXRhLnZpZEVsID0gbnVsbDsgfQogICAgdGhpcy5zY2VuZS5yZW1vdmUoZyk7CiAgICB0aGlzLmdob3N0cyA9IHRoaXMuZ2hvc3RzLmZpbHRlcigoeCkgPT4geCAhPT0gZyk7CiAgICB0aGlzLnRhcmdldCA9IG51bGw7CiAgICAkKCcjbG9ja29uJykuY2xhc3NMaXN0LmFkZCgnaGlkZGVuJyk7CiAgICB0aGlzLmdsb29tICs9IDEwICsgZC5yYXJpdHkgKiA1OwogICAgdGhpcy51cGRhdGVHbG9vbSgpOwogICAgdGhpcy50b2FzdChgQ2FwdHVyZWQgJHtkLmRpc3BsYXlOYW1lIHx8IGQubmFtZX0hYCwgOTAwKTsKCiAgICBpZiAoZy51c2VyRGF0YS5pc0Jvc3MpIHsgdGhpcy53aW4oZCk7IHJldHVybjsgfQoKICAgIGlmICghdGhpcy5mcmVlSHVudCkgewogICAgICB0aGlzLnJlbWFpbmluZyAtPSAxOwogICAgICBpZiAodGhpcy5yZW1haW5pbmcgPD0gMCAmJiB0aGlzLmJvc3MpIHsKICAgICAgICAvLyBzb3VsIGFydGlmYWN0IOKGkiBib3NzIGFwcGVhcnMKICAgICAgICB0aGlzLnRvYXN0KCdBIFNvdWwgQXJ0aWZhY3QgcHVsc2Vz4oCmJywgMTEwMCk7CiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLmFkZEdob3N0KHRoaXMuYm9zcywgdHJ1ZSksIDExMDApOwogICAgICAgIHJldHVybjsKICAgICAgfQogICAgfQogICAgLy8gcmVzcGF3biBhbm90aGVyIGdob3N0IHRvIGtlZXAgdGhlIGh1bnQgZ29pbmcKICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5zcGF3bk5leHQoKSwgNjAwKTsKICB9LAoKICBtYXliZVRha2VEYW1hZ2UoKSB7CiAgICAvLyBhIHJldmVhbGVkIGdob3N0IHJvdWdobHkgY2VudGVyZWQgKyB3ZSdyZSBub3QgYmxhc3Rpbmcg4oaSIGl0IGdsb29tcyB1cwogICAgaWYgKHRoaXMuYmxhc3RpbmcpIHJldHVybjsKICAgIGlmICghdGhpcy50YXJnZXQpIHJldHVybjsKICAgIGlmIChNYXRoLnJhbmRvbSgpIDwgMC4wMDQpIHsKICAgICAgY29uc3QgZG1nID0gdGhpcy50YXJnZXQudXNlckRhdGEuZGF0YS5yYXJpdHkgKiAxLjU7IC8vIDTimIUgaHVydHMgbW9zdAogICAgICB0aGlzLmJhdHRlcnkgPSBNYXRoLm1heCgwLCB0aGlzLmJhdHRlcnkgLSBkbWcpOwogICAgICB0aGlzLnVwZGF0ZUJhdHRlcnkoKTsKICAgICAgdGhpcy5mbGFzaERhbWFnZSgpOwogICAgICBpZiAodGhpcy5iYXR0ZXJ5IDw9IDApIHRoaXMubG9zZSgpOwogICAgfQogIH0sCgogIC8qIC0tLS0gSFVEIHVwZGF0ZXMgLS0tLSAqLwogIHVwZGF0ZUJhdHRlcnkoKSB7CiAgICBjb25zdCBmaWxsID0gJCgnI2JhdHRlcnktZmlsbCcpOwogICAgZmlsbC5zdHlsZS53aWR0aCA9IGAke3RoaXMuYmF0dGVyeX0lYDsKICAgIGZpbGwuY2xhc3NMaXN0LnRvZ2dsZSgnbG93JywgdGhpcy5iYXR0ZXJ5IDw9IDMwKTsKICAgICQoJyNiYXR0ZXJ5LXBjdCcpLnRleHRDb250ZW50ID0gYCR7TWF0aC5yb3VuZCh0aGlzLmJhdHRlcnkpfSVgOwogIH0sCiAgdXBkYXRlR2xvb20oKSB7ICQoJyNnbG9vbS1jb3VudCcpLnRleHRDb250ZW50ID0gdGhpcy5nbG9vbTsgfSwKICB1cGRhdGVPdmVyaGVhdCgpIHsKICAgICQoJyNvdmVyaGVhdC1maWxsJykuc3R5bGUud2lkdGggPSBgJHt0aGlzLm92ZXJoZWF0fSVgOwogICAgJCgnI2J0bi1ibGFzdCcpLmNsYXNzTGlzdC50b2dnbGUoJ292ZXJoZWF0ZWQnLCB0aGlzLm92ZXJoZWF0ID49IDEwMCk7CiAgICAkKCcjYnRuLWJsYXN0JykudGV4dENvbnRlbnQgPSB0aGlzLm92ZXJoZWF0ID49IDEwMCA/ICdPVkVSSEVBVEVEJyA6ICdIT0xEIFRPIEJMQVNUJzsKICB9LAoKICB0b2FzdChtc2csIG1zID0gODAwLCBqdW1wID0gZmFsc2UpIHsKICAgIGNvbnN0IHQgPSAkKCcjdG9hc3QnKTsKICAgIHQudGV4dENvbnRlbnQgPSBtc2c7CiAgICB0LmNsYXNzTmFtZSA9IGB0b2FzdCR7anVtcCA/ICcganVtcHNjYXJlJyA6ICcnfWA7CiAgICBjbGVhclRpbWVvdXQodGhpcy5fdG9hc3RUKTsKICAgIHRoaXMuX3RvYXN0VCA9IHNldFRpbWVvdXQoKCkgPT4gdC5jbGFzc0xpc3QuYWRkKCdoaWRkZW4nKSwgbXMpOwogIH0sCiAganVtcHNjYXJlKCkgewogICAgdGhpcy50b2FzdCgnQk9PIScsIDcwMCwgdHJ1ZSk7CiAgICB0aGlzLmJhdHRlcnkgPSBNYXRoLm1heCgwLCB0aGlzLmJhdHRlcnkgLSA0KTsKICAgIHRoaXMudXBkYXRlQmF0dGVyeSgpOwogICAgaWYgKG5hdmlnYXRvci52aWJyYXRlKSBuYXZpZ2F0b3IudmlicmF0ZSgxMjApOwogIH0sCiAgZmxhc2hEYW1hZ2UoKSB7CiAgICBpZiAobmF2aWdhdG9yLnZpYnJhdGUpIG5hdmlnYXRvci52aWJyYXRlKDQwKTsKICAgIGRvY3VtZW50LmJvZHkuYW5pbWF0ZSgKICAgICAgW3sgYm94U2hhZG93OiAnaW5zZXQgMCAwIDAgOTk5OXB4IHJnYmEoMjU1LDU5LDkyLC4yNSknIH0sIHsgYm94U2hhZG93OiAnaW5zZXQgMCAwIDAgOTk5OXB4IHJnYmEoMjU1LDU5LDkyLDApJyB9XSwKICAgICAgeyBkdXJhdGlvbjogMjUwIH0KICAgICk7CiAgfSwKCiAgd2luKGJvc3MpIHsKICAgICQoJyNyZXN1bHQtdGl0bGUnKS50ZXh0Q29udGVudCA9ICdTZXQgQ2xlYXJlZCc7CiAgICAkKCcjcmVzdWx0LWJvZHknKS50ZXh0Q29udGVudCA9IGBZb3UgY2FwdHVyZWQgJHtib3NzLmRpc3BsYXlOYW1lIHx8IGJvc3MubmFtZX0gYW5kIGRyb3ZlIHRoZSBnbG9vbSBvdXQuIEdsb29tIGJhbmtlZDogJHt0aGlzLmdsb29tfS5gOwogICAgJCgnI3Jlc3VsdCcpLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpOwogICAgdGhpcy5ydW5uaW5nID0gZmFsc2U7CiAgfSwKICBsb3NlKCkgewogICAgJCgnI3Jlc3VsdC10aXRsZScpLnRleHRDb250ZW50ID0gJ0JhdHRlcnkgRGVhZCc7CiAgICAkKCcjcmVzdWx0LWJvZHknKS50ZXh0Q29udGVudCA9ICdUaGUgZGV0ZWN0b3Igd2VudCBkYXJrIGFuZCB0aGUgZ2hvc3RzIHNsaXBwZWQgYXdheS4gUmVjaGFyZ2UgYW5kIHRyeSBhZ2Fpbi4nOwogICAgJCgnI3Jlc3VsdCcpLmNsYXNzTGlzdC5yZW1vdmUoJ2hpZGRlbicpOwogICAgdGhpcy5ydW5uaW5nID0gZmFsc2U7CiAgfSwKCiAgc3RvcCgpIHsKICAgIHRoaXMucnVubmluZyA9IGZhbHNlOwogICAgaWYgKHRoaXMucmFmKSBjYW5jZWxBbmltYXRpb25GcmFtZSh0aGlzLnJhZik7CiAgICBpZiAodGhpcy5zdHJlYW0pIHsgdGhpcy5zdHJlYW0uZ2V0VHJhY2tzKCkuZm9yRWFjaCgodCkgPT4gdC5zdG9wKCkpOyB0aGlzLnN0cmVhbSA9IG51bGw7IH0KICAgIGlmICh0aGlzLl9vblJlc2l6ZSkgcmVtb3ZlRXZlbnRMaXN0ZW5lcigncmVzaXplJywgdGhpcy5fb25SZXNpemUpOwogICAgaWYgKHRoaXMuX29uT3JpZW50ICYmIHRoaXMuX2d5cm9BdHRhY2hlZCkgewogICAgICByZW1vdmVFdmVudExpc3RlbmVyKCdkZXZpY2VvcmllbnRhdGlvbicsIHRoaXMuX29uT3JpZW50KTsKICAgICAgdGhpcy5fZ3lyb0F0dGFjaGVkID0gZmFsc2U7CiAgICB9CiAgICBpZiAodGhpcy5fbW90aW9uRWxzKSB7IHRoaXMuX21vdGlvbkVscy5vdmVybGF5LmNsYXNzTGlzdC5hZGQoJ2hpZGRlbicpOyB9CiAgICBpZiAodGhpcy5fYmxhc3RFbHMpIHsKICAgICAgcmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hlbmQnLCB0aGlzLl9ibGFzdEVscy5lbmRCbGFzdCk7CiAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLl9ibGFzdEVscy5lbmRCbGFzdCk7CiAgICB9CiAgICBpZiAodGhpcy5yZW5kZXJlcikgeyB0aGlzLnJlbmRlcmVyLmRpc3Bvc2U/LigpOyB9CiAgICBmb3IgKGNvbnN0IGcgb2YgdGhpcy5naG9zdHMpIHsKICAgICAgaWYgKGcudXNlckRhdGEudmlkRWwpIHsgdHJ5IHsgZy51c2VyRGF0YS52aWRFbC5wYXVzZSgpOyBnLnVzZXJEYXRhLnZpZEVsLnNyYyA9ICcnOyB9IGNhdGNoIHt9IGcudXNlckRhdGEudmlkRWwgPSBudWxsOyB9CiAgICB9CiAgICB0aGlzLmdob3N0cyA9IFtdOyB0aGlzLnRhcmdldCA9IG51bGw7CiAgfSwKfTsKCmZ1bmN0aW9uIHN0YXJ0SHVudChvcHRzKSB7IGh1bnQuc3RhcnQob3B0cyk7IH0KCi8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQogICBST1NURVIgLyBHSE9TVCBJTkRFWAogICA9PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0gKi8KYXN5bmMgZnVuY3Rpb24gb3BlblJvc3RlcigpIHsKICBzaG93KCdyb3N0ZXInKTsKICBhd2FpdCBsb2FkUm9zdGVyKCk7Cn0KWycjZmlsdGVyLXR5cGUnLCAnI2ZpbHRlci1yYXJpdHknLCAnI2ZpbHRlci1ib3NzJ10uZm9yRWFjaCgoc2VsKSA9PgogICQoc2VsKS5hZGRFdmVudExpc3RlbmVyKCdjaGFuZ2UnLCBsb2FkUm9zdGVyKQopOwoKYXN5bmMgZnVuY3Rpb24gbG9hZFJvc3RlcigpIHsKICBjb25zdCB0eXBlID0gJCgnI2ZpbHRlci10eXBlJykudmFsdWU7CiAgY29uc3QgcmFyaXR5ID0gJCgnI2ZpbHRlci1yYXJpdHknKS52YWx1ZTsKICBjb25zdCBib3NzID0gJCgnI2ZpbHRlci1ib3NzJykuY2hlY2tlZCA/ICcxJyA6ICcnOwogIGNvbnN0IHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMoKTsKICBpZiAodHlwZSkgcGFyYW1zLnNldCgndHlwZScsIHR5cGUpOwogIGlmIChyYXJpdHkpIHBhcmFtcy5zZXQoJ3Jhcml0eScsIHJhcml0eSk7CiAgaWYgKGJvc3MpIHBhcmFtcy5zZXQoJ2Jvc3MnLCBib3NzKTsKICBjb25zdCByZXMgPSBhd2FpdCBmZXRjaChgL2FwaS9naG9zdHM/JHtwYXJhbXN9YCk7CiAgY29uc3QgeyBnaG9zdHMgfSA9IGF3YWl0IHJlcy5qc29uKCk7CiAgY29uc3QgZ3JpZCA9ICQoJyNyb3N0ZXItZ3JpZCcpOwogIGdyaWQuaW5uZXJIVE1MID0gZ2hvc3RzLm1hcChnaG9zdENhcmQpLmpvaW4oJycpIHx8CiAgICAnPHAgY2xhc3M9Im11dGVkIj5ObyBnaG9zdHMgbWF0Y2ggdGhvc2UgZmlsdGVycy48L3A+JzsKfQoKZnVuY3Rpb24gZ2hvc3RDYXJkKGcpIHsKICBjb25zdCBjb2xvclZhciA9IGB2YXIoLS0ke2cudHlwZX0pYDsKICBjb25zdCB0aHVtYiA9IGcuaW1hZ2UKICAgID8gYDxpbWcgY2xhc3M9Imdob3N0LXRodW1iIiBzcmM9IiR7Zy5pbWFnZX0iIGFsdD0iJHtlc2NhcGVIdG1sKGcuZGlzcGxheU5hbWUpfSIgbG9hZGluZz0ibGF6eSI+YAogICAgOiAnJzsKICBjb25zdCBzZXRSZWYgPSBnLnNldE51bWJlciA/IGA8ZGl2IGNsYXNzPSJzZXQtcmVmIj5TZXQgJHtnLnNldE51bWJlcn0gwrcgJHtlc2NhcGVIdG1sKGcuc2V0TmFtZSB8fCAnJyl9PC9kaXY+YCA6ICcnOwogIHJldHVybiBgCiAgICA8ZGl2IGNsYXNzPSJnaG9zdC1jYXJkICR7Zy5pc0Jvc3MgPyAnYm9zcycgOiAnJ30iPgogICAgICA8ZGl2IGNsYXNzPSJhY2NlbnQiIHN0eWxlPSJiYWNrZ3JvdW5kOiR7Y29sb3JWYXJ9Ij48L2Rpdj4KICAgICAgJHt0aHVtYn0KICAgICAgPGRpdiBjbGFzcz0iZ25hbWUiPiR7ZXNjYXBlSHRtbChnLmRpc3BsYXlOYW1lKX0gJHtnLmlzQm9zcyA/ICc8c3BhbiBjbGFzcz0iYm9zcy1iYWRnZSI+Qk9TUzwvc3Bhbj4nIDogJyd9PC9kaXY+CiAgICAgIDxkaXYgY2xhc3M9Im1ldGEiPjxzcGFuIGNsYXNzPSJkb3QgJHtnLnR5cGV9Ij48L3NwYW4+IDxzcGFuIGNsYXNzPSJzdGFycyI+JHsn4piFJy5yZXBlYXQoZy5yYXJpdHkpfTwvc3Bhbj48L2Rpdj4KICAgICAgPGRpdiBjbGFzcz0ic3RhdGxpbmUiPjxzcGFuPkhQICR7Zy5oZWFsdGh9PC9zcGFuPjxzcGFuPkRNRyAke2cuZGFtYWdlfTwvc3Bhbj48L2Rpdj4KICAgICAgPGRpdiBjbGFzcz0ic3RhdGxpbmUiPjxzcGFuPlNQRCAke2cuc3BlZWR9PC9zcGFuPjxzcGFuPlJORyAke2cucmFuZ2V9PC9zcGFuPjwvZGl2PgogICAgICAke2cuYWJpbGl0eSA/IGA8ZGl2IGNsYXNzPSJzZXQtcmVmIiBzdHlsZT0ibWFyZ2luLXRvcDo2cHgiPuKaoSAke2VzY2FwZUh0bWwoZy5hYmlsaXR5KX08L2Rpdj5gIDogJyd9CiAgICAgICR7c2V0UmVmfQogICAgPC9kaXY+YDsKfQoKZnVuY3Rpb24gZXNjYXBlSHRtbChzKSB7CiAgcmV0dXJuIFN0cmluZyhzID8/ICcnKS5yZXBsYWNlKC9bJjw+IiddL2csIChjKSA9PgogICAgKHsgJyYnOiAnJmFtcDsnLCAnPCc6ICcmbHQ7JywgJz4nOiAnJmd0OycsICciJzogJyZxdW90OycsICInIjogJyYjMzk7JyB9W2NdKSk7Cn0K