From cd97aab9d5cb27ec899a39b7112981988bdcefc7 Mon Sep 17 00:00:00 2001 From: Kingbro6 <99345187+MrHyplex9511@users.noreply.github.com> Date: Mon, 14 Sep 2026 14:33:55 +0530 Subject: [PATCH] Bounty #1600: Add RustChain stats dashboard --- explorer/stats-dashboard.html | 1 + explorer/stats_server.py | 1 + 2 files changed, 2 insertions(+) create mode 100644 explorer/stats-dashboard.html create mode 100644 explorer/stats_server.py diff --git a/explorer/stats-dashboard.html b/explorer/stats-dashboard.html new file mode 100644 index 000000000..cff45f8ab --- /dev/null +++ b/explorer/stats-dashboard.html @@ -0,0 +1 @@ +PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+CiAgICA8bWV0YSBuYW1lPSJ2aWV3cG9ydCIgY29udGVudD0id2lkdGg9ZGV2aWNlLXdpZHRoLCBpbml0aWFsLXNjYWxlPTEuMCI+CiAgICA8bWV0YSBuYW1lPSJkZXNjcmlwdGlvbiIgY29udGVudD0iUnVzdENoYWluIE5ldHdvcmsgU3RhdGlzdGljcyBEYXNoYm9hcmQg4oCUIGxpdmUgZXBvY2gsIG1pbmVycywgc3VwcGx5LCBhbmQgdHJhbnNhY3Rpb24gZGF0YS4iPgogICAgPG1ldGEgbmFtZT0idGhlbWUtY29sb3IiIGNvbnRlbnQ9IiM4YjVjZjYiPgogICAgPHRpdGxlPlJ1c3RDaGFpbiBTdGF0cyBEYXNoYm9hcmQ8L3RpdGxlPgoKICAgIDwhLS0KICAgICAgICBCb3VudHkgIzE2MDAg4oCUIFJ1c3RDaGFpbiBTdGF0cyBEYXNoYm9hcmQKICAgICAgICBTdGFuZGFsb25lIFNQQSAobm8gYnVpbGQgc3RlcCwgbm8gZXh0ZXJuYWwgZGVwcykuCgogICAgICAgIFJ1biB2aWEgdGhlIGNvbXBhbmlvbiBQeXRob24gc2VydmVyOgogICAgICAgICAgICBjZCBleHBsb3JlciAmJiBweXRob24zIHN0YXRzX3NlcnZlci5weSAgICAgICAgIyBwb3J0IDkwOTAKCiAgICAgICAgT3Igc2VydmUgc3RhdGljYWxseSB3aXRoIGFueSBzZXJ2ZXI6CiAgICAgICAgICAgIHB5dGhvbjMgLW0gaHR0cC5zZXJ2ZXIgOTA5MCAgICMgaW5zaWRlIGV4cGxvcmVyLwoKICAgICAgICBPciBvcGVuIGRpcmVjdGx5IGluIGEgYnJvd3NlciAobmV0d29yayBjYWxscyBhcmUgcHJveGllZCBvbmx5CiAgICAgICAgYnkgc3RhdHNfc2VydmVyLnB5OyBkaXJlY3QgZmlsZTovLyB1c2UgZmV0Y2hlcyB0aGUgUnVzdENoYWluCiAgICAgICAgQVBJIGRpcmVjdGx5IGZyb20gdGhlIGNvbmZpZ3VyZWQgQVBJX0JBU0UpLgogICAgLS0+CgogICAgPGxpbmsgcmVsPSJpY29uIiB0eXBlPSJpbWFnZS9zdmcreG1sIiBocmVmPSJkYXRhOmltYWdlL3N2Zyt4bWwsPHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxMDAgMTAwJz48dGV4dCB5PScuOWVtJyBmb250LXNpemU9JzkwJz7wn6aAPC90ZXh0Pjwvc3ZnPiI+CgogICAgPHN0eWxlPgogICAgICAgIDpyb290IHsKICAgICAgICAgICAgLS1iZzogIzBmMGYxYTsKICAgICAgICAgICAgLS1zdXJmYWNlOiAjMWExYTJlOwogICAgICAgICAgICAtLXN1cmZhY2UtMjogIzIzMjM0MDsKICAgICAgICAgICAgLS1ib3JkZXI6ICMyZDJkNGE7CiAgICAgICAgICAgIC0tdGV4dDogI2U0ZTRmMDsKICAgICAgICAgICAgLS10ZXh0LWRpbTogIzk4OThiYjsKICAgICAgICAgICAgLS1hY2NlbnQ6ICM4YjVjZjY7CiAgICAgICAgICAgIC0tYWNjZW50LWdsb3c6IHJnYmEoMTM5LDkyLDI0NiwwLjE1KTsKICAgICAgICAgICAgLS1ncmVlbjogIzIyYzU1ZTsKICAgICAgICAgICAgLS1yZWQ6ICNlZjQ0NDQ7CiAgICAgICAgICAgIC0teWVsbG93OiAjZWFiMzA4OwogICAgICAgIH0KCiAgICAgICAgKiB7IG1hcmdpbjogMDsgcGFkZGluZzogMDsgYm94LXNpemluZzogYm9yZGVyLWJveDsgfQoKICAgICAgICBib2R5IHsKICAgICAgICAgICAgZm9udC1mYW1pbHk6ICdTRiBNb25vJywgJ0ZpcmEgQ29kZScsICdDb25zb2xhcycsICdDb3VyaWVyIE5ldycsIG1vbm9zcGFjZTsKICAgICAgICAgICAgYmFja2dyb3VuZDogdmFyKC0tYmcpOwogICAgICAgICAgICBjb2xvcjogdmFyKC0tdGV4dCk7CiAgICAgICAgICAgIG1pbi1oZWlnaHQ6IDEwMHZoOwogICAgICAgIH0KCiAgICAgICAgLyogQWNjZXNzaWJpbGl0eSAqLwogICAgICAgIC5za2lwLWxpbmsgewogICAgICAgICAgICBwb3NpdGlvbjogYWJzb2x1dGU7IHRvcDogLTEwMCU7IGxlZnQ6IDA7CiAgICAgICAgICAgIGJhY2tncm91bmQ6IHZhcigtLWFjY2VudCk7IGNvbG9yOiAjZmZmOwogICAgICAgICAgICBwYWRkaW5nOiAuNXJlbSAxcmVtOyB6LWluZGV4OiAxMDAwOyBmb250LXdlaWdodDogNjAwOyB0ZXh0LWRlY29yYXRpb246IG5vbmU7CiAgICAgICAgfQogICAgICAgIC5za2lwLWxpbms6Zm9jdXMgeyB0b3A6IDA7IH0KICAgICAgICAuc3Itb25seSB7CiAgICAgICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTsgd2lkdGg6IDFweDsgaGVpZ2h0OiAxcHg7IHBhZGRpbmc6IDA7IG1hcmdpbjogLTFweDsKICAgICAgICAgICAgb3ZlcmZsb3c6IGhpZGRlbjsgY2xpcDogcmVjdCgwLDAsMCwwKTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsgYm9yZGVyOiAwOwogICAgICAgIH0KICAgICAgICA6Zm9jdXMtdmlzaWJsZSB7IG91dGxpbmU6IDJweCBzb2xpZCB2YXIoLS1hY2NlbnQpOyBvdXRsaW5lLW9mZnNldDogMnB4OyB9CgogICAgICAgIC8qIEhlYWRlciAqLwogICAgICAgIC5oZWFkZXIgewogICAgICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1zdXJmYWNlKTsKICAgICAgICAgICAgYm9yZGVyLWJvdHRvbTogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7CiAgICAgICAgICAgIHBhZGRpbmc6IDFyZW0gMS41cmVtOwogICAgICAgICAgICBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogY2VudGVyOyBqdXN0aWZ5LWNvbnRlbnQ6IHNwYWNlLWJldHdlZW47CiAgICAgICAgICAgIGZsZXgtd3JhcDogd3JhcDsgZ2FwOiAuNzVyZW07CiAgICAgICAgfQogICAgICAgIC5sb2dvIHsgZm9udC1zaXplOiAxLjE1cmVtOyBmb250LXdlaWdodDogNzAwOyBjb2xvcjogdmFyKC0tYWNjZW50KTsgdGV4dC1kZWNvcmF0aW9uOiBub25lOyBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogY2VudGVyOyBnYXA6IC41cmVtOyB9CiAgICAgICAgLmhlYWRlci1yaWdodCB7IGRpc3BsYXk6IGZsZXg7IGFsaWduLWl0ZW1zOiBjZW50ZXI7IGdhcDogMXJlbTsgfQogICAgICAgIC5yZWZyZXNoLWJhZGdlIHsKICAgICAgICAgICAgZm9udC1zaXplOiAuNzVyZW07IHBhZGRpbmc6IC4yNXJlbSAuNnJlbTsgYm9yZGVyLXJhZGl1czogOTk5cHg7CiAgICAgICAgICAgIGJhY2tncm91bmQ6IHZhcigtLXN1cmZhY2UtMik7IGJvcmRlcjogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7IGNvbG9yOiB2YXIoLS10ZXh0LWRpbSk7CiAgICAgICAgfQogICAgICAgIC5yZWZyZXNoLWJhZGdlLmxpdmUgeyBib3JkZXItY29sb3I6IHZhcigtLWdyZWVuKTsgY29sb3I6IHZhcigtLWdyZWVuKTsgfQogICAgICAgIC5zdGF0dXMtZG90IHsKICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOyB3aWR0aDogOHB4OyBoZWlnaHQ6IDhweDsgYm9yZGVyLXJhZGl1czogNTAlOyBtYXJnaW4tcmlnaHQ6IC4zNXJlbTsKICAgICAgICB9CiAgICAgICAgLnN0YXR1cy1kb3Qub24geyBiYWNrZ3JvdW5kOiB2YXIoLS1ncmVlbik7IGJveC1zaGFkb3c6IDAgMCA2cHggdmFyKC0tZ3JlZW4pOyB9CiAgICAgICAgLnN0YXR1cy1kb3Qub2ZmIHsgYmFja2dyb3VuZDogdmFyKC0tcmVkKTsgfQoKICAgICAgICAvKiBDYXJkcyBncmlkICovCiAgICAgICAgLmNhcmRzIHsgZGlzcGxheTogZ3JpZDsgZ3JpZC10ZW1wbGF0ZS1jb2x1bW5zOiByZXBlYXQoYXV0by1maWxsLG1pbm1heCgyMjBweCwxZnIpKTsgZ2FwOiAxcmVtOyBwYWRkaW5nOiAxLjVyZW07IG1heC13aWR0aDogMTQwMHB4OyBtYXJnaW46IDAgYXV0bzsgfQogICAgICAgIC5jYXJkIHsKICAgICAgICAgICAgYmFja2dyb3VuZDogdmFyKC0tc3VyZmFjZSk7IGJvcmRlcjogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7IGJvcmRlci1yYWRpdXM6IDEwcHg7CiAgICAgICAgICAgIHBhZGRpbmc6IDEuMjVyZW0gMS41cmVtOyBwb3NpdGlvbjogcmVsYXRpdmU7IG92ZXJmbG93OiBoaWRkZW47CiAgICAgICAgfQogICAgICAgIC5jYXJkOjpiZWZvcmUgewogICAgICAgICAgICBjb250ZW50OiAnJzsgcG9zaXRpb246IGFic29sdXRlOyBpbnNldDogMDsgcG9pbnRlci1ldmVudHM6IG5vbmU7CiAgICAgICAgICAgIGJhY2tncm91bmQ6IHZhcigtLWFjY2VudC1nbG93KTsgb3BhY2l0eTogMDsgdHJhbnNpdGlvbjogb3BhY2l0eSAuMjVzOwogICAgICAgIH0KICAgICAgICAuY2FyZDpob3Zlcjo6YmVmb3JlIHsgb3BhY2l0eTogMTsgfQogICAgICAgIC5jYXJkLWxhYmVsIHsgZm9udC1zaXplOiAuNzVyZW07IGNvbG9yOiB2YXIoLS10ZXh0LWRpbSk7IHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7IGxldHRlci1zcGFjaW5nOiAuMDZlbTsgbWFyZ2luLWJvdHRvbTogLjVyZW07IH0KICAgICAgICAuY2FyZC12YWx1ZSB7IGZvbnQtc2l6ZTogMS44NXJlbTsgZm9udC13ZWlnaHQ6IDcwMDsgbGluZS1oZWlnaHQ6IDEuMjsgfQogICAgICAgIC5jYXJkLXN1YiB7IGZvbnQtc2l6ZTogLjdyZW07IGNvbG9yOiB2YXIoLS10ZXh0LWRpbSk7IG1hcmdpbi10b3A6IC4zNXJlbTsgfQoKICAgICAgICAudGV4dC1ncmVlbiB7IGNvbG9yOiB2YXIoLS1ncmVlbik7IH0KICAgICAgICAudGV4dC15ZWxsb3cgeyBjb2xvcjogdmFyKC0teWVsbG93KTsgfQogICAgICAgIC50ZXh0LXJlZCB7IGNvbG9yOiB2YXIoLS1yZWQpOyB9CiAgICAgICAgLnRleHQtYWNjZW50IHsgY29sb3I6IHZhcigtLWFjY2VudCk7IH0KCiAgICAgICAgLyogU2VjdGlvbnMgKi8KICAgICAgICAuc2VjdGlvbiB7IHBhZGRpbmc6IDAgMS41cmVtIDEuNXJlbTsgbWF4LXdpZHRoOiAxNDAwcHg7IG1hcmdpbjogMCBhdXRvOyB9CiAgICAgICAgLnNlY3Rpb24tdGl0bGUgeyBmb250LXNpemU6IC44NXJlbTsgY29sb3I6IHZhcigtLXRleHQtZGltKTsgdGV4dC10cmFuc2Zvcm06IHVwcGVyY2FzZTsgbGV0dGVyLXNwYWNpbmc6IC4wNWVtOyBtYXJnaW4tYm90dG9tOiAuNzVyZW07IH0KCiAgICAgICAgLyogTWluZXIgdGFibGUgKi8KICAgICAgICAudGFibGUtd3JhcCB7IG92ZXJmbG93LXg6IGF1dG87IGJvcmRlcjogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7IGJvcmRlci1yYWRpdXM6IDEwcHg7IGJhY2tncm91bmQ6IHZhcigtLXN1cmZhY2UpOyB9CiAgICAgICAgdGFibGUgeyB3aWR0aDogMTAwJTsgYm9yZGVyLWNvbGxhcHNlOiBjb2xsYXBzZTsgZm9udC1zaXplOiAuOHJlbTsgfQogICAgICAgIHRoIHsgYmFja2dyb3VuZDogdmFyKC0tc3VyZmFjZS0yKTsgdGV4dC1hbGlnbjogbGVmdDsgcGFkZGluZzogLjY1cmVtIDFyZW07IGZvbnQtd2VpZ2h0OiA2MDA7IGNvbG9yOiB2YXIoLS10ZXh0LWRpbSk7IHRleHQtdHJhbnNmb3JtOiB1cHBlcmNhc2U7IGZvbnQtc2l6ZTogLjdyZW07IGxldHRlci1zcGFjaW5nOiAuMDRlbTsgd2hpdGUtc3BhY2U6IG5vd3JhcDsgfQogICAgICAgIHRkIHsgcGFkZGluZzogLjU1cmVtIDFyZW07IGJvcmRlci10b3A6IDFweCBzb2xpZCB2YXIoLS1ib3JkZXIpOyB3aGl0ZS1zcGFjZTogbm93cmFwOyB9CiAgICAgICAgdHI6aG92ZXIgdGQgeyBiYWNrZ3JvdW5kOiB2YXIoLS1hY2NlbnQtZ2xvdyk7IH0KICAgICAgICAubW9ubyB7IGZvbnQtZmFtaWx5OiBpbmhlcml0OyB9CiAgICAgICAgLmJhZGdlIHsKICAgICAgICAgICAgZGlzcGxheTogaW5saW5lLWJsb2NrOyBwYWRkaW5nOiAuMTVyZW0gLjVyZW07IGJvcmRlci1yYWRpdXM6IDRweDsgZm9udC1zaXplOiAuN3JlbTsgZm9udC13ZWlnaHQ6IDYwMDsKICAgICAgICB9CiAgICAgICAgLmJhZGdlLWdyZWVuIHsgYmFja2dyb3VuZDogcmdiYSgzNCwxOTcsOTQsLjE1KTsgY29sb3I6IHZhcigtLWdyZWVuKTsgfQogICAgICAgIC5iYWRnZS15ZWxsb3cgeyBiYWNrZ3JvdW5kOiByZ2JhKDIzNCwxNzksOCwuMTUpOyBjb2xvcjogdmFyKC0teWVsbG93KTsgfQogICAgICAgIC5iYWRnZS1yZWQgeyBiYWNrZ3JvdW5kOiByZ2JhKDIzOSw2OCw2OCwuMTUpOyBjb2xvcjogdmFyKC0tcmVkKTsgfQogICAgICAgIC5iYWRnZS1hY2NlbnQgeyBiYWNrZ3JvdW5kOiB2YXIoLS1hY2NlbnQtZ2xvdyk7IGNvbG9yOiB2YXIoLS1hY2NlbnQpOyB9CgogICAgICAgIC8qIEFyY2hpdGVjdHVyZSBiYXIgY2hhcnQgKi8KICAgICAgICAuYXJjaC1iYXJzIHsgZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsgZ2FwOiAuNXJlbTsgcGFkZGluZzogMXJlbSAxLjVyZW07IH0KICAgICAgICAuYXJjaC1yb3cgeyBkaXNwbGF5OiBmbGV4OyBhbGlnbi1pdGVtczogY2VudGVyOyBnYXA6IC43NXJlbTsgfQogICAgICAgIC5hcmNoLWxhYmVsIHsgd2lkdGg6IDkwcHg7IGZvbnQtc2l6ZTogLjc1cmVtOyBjb2xvcjogdmFyKC0tdGV4dC1kaW0pOyB0ZXh0LWFsaWduOiByaWdodDsgZmxleC1zaHJpbms6IDA7IH0KICAgICAgICAuYXJjaC1iYXItdHJhY2sgeyBmbGV4OiAxOyBoZWlnaHQ6IDE4cHg7IGJhY2tncm91bmQ6IHZhcigtLXN1cmZhY2UtMik7IGJvcmRlci1yYWRpdXM6IDRweDsgb3ZlcmZsb3c6IGhpZGRlbjsgfQogICAgICAgIC5hcmNoLWJhci1maWxsIHsgaGVpZ2h0OiAxMDAlOyBib3JkZXItcmFkaXVzOiA0cHg7IGJhY2tncm91bmQ6IHZhcigtLWFjY2VudCk7IHRyYW5zaXRpb246IHdpZHRoIC40cyBlYXNlOyBtaW4td2lkdGg6IDJweDsgfQogICAgICAgIC5hcmNoLWNvdW50IHsgd2lkdGg6IDQwcHg7IGZvbnQtc2l6ZTogLjc1cmVtOyBjb2xvcjogdmFyKC0tdGV4dC1kaW0pOyB9CgogICAgICAgIC8qIEVtcHR5IHN0YXRlICovCiAgICAgICAgLmVtcHR5IHsgdGV4dC1hbGlnbjogY2VudGVyOyBwYWRkaW5nOiAzcmVtIDFyZW07IGNvbG9yOiB2YXIoLS10ZXh0LWRpbSk7IH0KICAgICAgICAuZW1wdHktaWNvbiB7IGZvbnQtc2l6ZTogMnJlbTsgbWFyZ2luLWJvdHRvbTogLjc1cmVtOyB9CgogICAgICAgIC8qIEZvb3RlciAqLwogICAgICAgIC5mb290ZXIgeyB0ZXh0LWFsaWduOiBjZW50ZXI7IHBhZGRpbmc6IDJyZW0gMXJlbTsgZm9udC1zaXplOiAuN3JlbTsgY29sb3I6IHZhcigtLXRleHQtZGltKTsgYm9yZGVyLXRvcDogMXB4IHNvbGlkIHZhcigtLWJvcmRlcik7IG1hcmdpbi10b3A6IDJyZW07IH0KCiAgICAgICAgLyogUmVzcG9uc2l2ZSAqLwogICAgICAgIEBtZWRpYSAobWF4LXdpZHRoOiA2MDBweCkgewogICAgICAgICAgICAuY2FyZHMgeyBncmlkLXRlbXBsYXRlLWNvbHVtbnM6IDFmciAxZnI7IGdhcDogLjc1cmVtOyBwYWRkaW5nOiAxcmVtOyB9CiAgICAgICAgICAgIC5jYXJkLXZhbHVlIHsgZm9udC1zaXplOiAxLjRyZW07IH0KICAgICAgICAgICAgLmhlYWRlciB7IHBhZGRpbmc6IC43NXJlbSAxcmVtOyB9CiAgICAgICAgICAgIC5zZWN0aW9uIHsgcGFkZGluZzogMCAxcmVtIDFyZW07IH0KICAgICAgICAgICAgdGgsIHRkIHsgcGFkZGluZzogLjQ1cmVtIC42cmVtOyB9CiAgICAgICAgICAgIC5hcmNoLWxhYmVsIHsgd2lkdGg6IDY1cHg7IGZvbnQtc2l6ZTogLjY1cmVtOyB9CiAgICAgICAgfQogICAgPC9zdHlsZT4KPC9oZWFkPgo8Ym9keT4KICAgIDxhIGhyZWY9IiNtYWluIiBjbGFzcz0ic2tpcC1saW5rIj5Ta2lwIHRvIG1haW4gY29udGVudDwvYT4KCiAgICA8aGVhZGVyIGNsYXNzPSJoZWFkZXIiPgogICAgICAgIDxhIGhyZWY9Ii8iIGNsYXNzPSJsb2dvIj48c3BhbiBhcmlhLWhpZGRlbj0idHJ1ZSI+8J+mgDwvc3Bhbj4gUnVzdENoYWluIFN0YXRzPC9hPgogICAgICAgIDxkaXYgY2xhc3M9ImhlYWRlci1yaWdodCI+CiAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJyZWZyZXNoLWJhZGdlIGxpdmUiIGlkPSJyZWZyZXNoLWJhZGdlIiByb2xlPSJzdGF0dXMiIGFyaWEtbGl2ZT0icG9saXRlIj4KICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPSJzdGF0dXMtZG90IG9uIiBpZD0ic3RhdHVzLWRvdCIgYXJpYS1oaWRkZW49InRydWUiPjwvc3Bhbj4gQXV0by1yZWZyZXNoIDEwIHMKICAgICAgICAgICAgPC9zcGFuPgogICAgICAgICAgICA8c3BhbiBzdHlsZT0iZm9udC1zaXplOi43NXJlbTtjb2xvcjp2YXIoLS10ZXh0LWRpbSkiIGlkPSJsYXN0LXVwZGF0ZSI+LS08L3NwYW4+CiAgICAgICAgPC9kaXY+CiAgICA8L2hlYWRlcj4KCiAgICA8bWFpbiBpZD0ibWFpbiIgcm9sZT0ibWFpbiI+CiAgICAgICAgPCEtLSBTdW1tYXJ5IGNhcmRzIC0tPgogICAgICAgIDxkaXYgY2xhc3M9ImNhcmRzIiBpZD0ic3VtbWFyeS1jYXJkcyI+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQiIGFyaWEtbGFiZWw9Ik5ldHdvcmsgc3RhdHVzIj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtbGFiZWwiPk5ldHdvcms8L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtdmFsdWUiIGlkPSJ2LW5ldHdvcmsiIGFyaWEtbGl2ZT0icG9saXRlIj4tLTwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1zdWIiIGlkPSJ2LW5ldHdvcmstc3ViIj48L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQiIGFyaWEtbGFiZWw9IkN1cnJlbnQgZXBvY2giPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1sYWJlbCI+RXBvY2g8L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtdmFsdWUgdGV4dC1hY2NlbnQiIGlkPSJ2LWVwb2NoIiBhcmlhLWxpdmU9InBvbGl0ZSI+LS08L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtc3ViIiBpZD0idi1lcG9jaC1zdWIiPjwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZCIgYXJpYS1sYWJlbD0iQWN0aXZlIG1pbmVycyI+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWxhYmVsIj5BY3RpdmUgTWluZXJzPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLXZhbHVlIiBpZD0idi1taW5lcnMiIGFyaWEtbGl2ZT0icG9saXRlIj4tLTwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1zdWIiIGlkPSJ2LW1pbmVycy1zdWIiPjwvZGl2PgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZCIgYXJpYS1sYWJlbD0iRXBvY2ggcG90Ij4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtbGFiZWwiPkVwb2NoIFBvdDwvZGl2PgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC12YWx1ZSB0ZXh0LXllbGxvdyIgaWQ9InYtcG90IiBhcmlhLWxpdmU9InBvbGl0ZSI+LS08L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtc3ViIj5SVEM8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQiIGFyaWEtbGFiZWw9IlRvdGFsIHN1cHBseSI+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLWxhYmVsIj5Ub3RhbCBTdXBwbHk8L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtdmFsdWUiIGlkPSJ2LXN1cHBseSI+LS08L2Rpdj4KICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQtc3ViIj5SVEM8L2Rpdj4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgICAgIDxkaXYgY2xhc3M9ImNhcmQiIGFyaWEtbGFiZWw9IlJlY2VudCB0cmFuc2FjdGlvbnMiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iY2FyZC1sYWJlbCI+VHJhbnNhY3Rpb25zPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLXZhbHVlIHRleHQtZ3JlZW4iIGlkPSJ2LXR4cyIgYXJpYS1saXZlPSJwb2xpdGUiPi0tPC9kaXY+CiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPSJjYXJkLXN1YiIgaWQ9InYtdHhzLXN1YiI+PC9kaXY+CiAgICAgICAgICAgIDwvZGl2PgogICAgICAgIDwvZGl2PgoKICAgICAgICA8IS0tIEFyY2hpdGVjdHVyZSBicmVha2Rvd24gLS0+CiAgICAgICAgPGRpdiBjbGFzcz0ic2VjdGlvbiI+CiAgICAgICAgICAgIDxoMiBjbGFzcz0ic2VjdGlvbi10aXRsZSI+QXJjaGl0ZWN0dXJlIEJyZWFrZG93bjwvaDI+CiAgICAgICAgICAgIDxkaXYgaWQ9ImFyY2gtY29udGFpbmVyIiBjbGFzcz0iZW1wdHkiPgogICAgICAgICAgICAgICAgPGRpdiBjbGFzcz0iZW1wdHktaWNvbiIgYXJpYS1oaWRkZW49InRydWUiPuKame+4jzwvZGl2PgogICAgICAgICAgICAgICAgV2FpdGluZyBmb3IgZGF0YS4uLgogICAgICAgICAgICA8L2Rpdj4KICAgICAgICA8L2Rpdj4KCiAgICAgICAgPCEtLSBNaW5lciBsZWFkZXJib2FyZCAtLT4KICAgICAgICA8ZGl2IGNsYXNzPSJzZWN0aW9uIj4KICAgICAgICAgICAgPGgyIGNsYXNzPSJzZWN0aW9uLXRpdGxlIj5Ub3AgTWluZXJzIChieSBzY29yZSk8L2gyPgogICAgICAgICAgICA8ZGl2IGNsYXNzPSJ0YWJsZS13cmFwIj4KICAgICAgICAgICAgICAgIDx0YWJsZT4KICAgICAgICAgICAgICAgICAgICA8dGhlYWQ+CiAgICAgICAgICAgICAgICAgICAgICAgIDx0cj4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBzY29wZT0iY29sIj4jPC90aD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBzY29wZT0iY29sIj5NaW5lcjwvdGg+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc2NvcGU9ImNvbCI+QXJjaGl0ZWN0dXJlPC90aD4KICAgICAgICAgICAgICAgICAgICAgICAgICAgIDx0aCBzY29wZT0iY29sIj5TY29yZTwvdGg+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc2NvcGU9ImNvbCI+TXVsdGlwbGllcjwvdGg+CiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8dGggc2NvcGU9ImNvbCI+U3RhdHVzPC90aD4KICAgICAgICAgICAgICAgICAgICAgICAgPC90cj4KICAgICAgICAgICAgICAgICAgICA8L3RoZWFkPgogICAgICAgICAgICAgICAgICAgIDx0Ym9keSBpZD0ibWluZXItdGJvZHkiPgogICAgICAgICAgICAgICAgICAgICAgICA8dHI+PHRkIGNvbHNwYW49IjYiIGNsYXNzPSJlbXB0eSI+TG9hZGluZy4uLjwvdGQ+PC90cj4KICAgICAgICAgICAgICAgICAgICA8L3Rib2R5PgogICAgICAgICAgICAgICAgPC90YWJsZT4KICAgICAgICAgICAgPC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICA8L21haW4+CgogICAgPGZvb3RlciBjbGFzcz0iZm9vdGVyIj4KICAgICAgICBSdXN0Q2hhaW4gU3RhdHMgRGFzaGJvYXJkIOKAlCBCb3VudHkgIzE2MDAgJm1pZGRvdDsgUHJvb2Ytb2YtQW50aXF1aXR5ICZtaWRkb3Q7IFRvdGFsIHN1cHBseTogOCwzODgsNjA4IFJUQwogICAgPC9mb290ZXI+CgogICAgPHNjcmlwdD4KICAgIC8qID09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0KICAgICAgIFJ1c3RDaGFpbiBTdGF0cyBEYXNoYm9hcmQg4oCUIHZhbmlsbGEgSlMsIHplcm8gZGVwcy4KICAgICAgIEZldGNoZXMgL2hlYWx0aCwgL2Vwb2NoLCAvYXBpL21pbmVycywgL2FwaS90cmFuc2FjdGlvbnMgdmlhCiAgICAgICB0aGUgY29tcGFuaW9uIHN0YXRzX3NlcnZlci5weSBwcm94eSAob3IgQ09SUy1lbmFibGVkIG5vZGUpLgogICAgICAgPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PSAqLwogICAgKGZ1bmN0aW9uICgpIHsKICAgICAgICAndXNlIHN0cmljdCc7CgogICAgICAgIC8qIC0tLS0tLS0tLS0gQ29uZmlndXJhdGlvbiAtLS0tLS0tLS0tICovCiAgICAgICAgY29uc3QgQVBJX0JBU0UgPSAoZnVuY3Rpb24gKCkgewogICAgICAgICAgICAvKiBJZiBzZXJ2ZWQgYnkgc3RhdHNfc2VydmVyLnB5IHRoZSBvcmlnaW4gaXMgdGhlIHByb3h5OwogICAgICAgICAgICAgICBvdGhlcndpc2UgZmFsbCBiYWNrIHRvIHRoZSBSdXN0Q2hhaW4gcHVibGljIEFQSS4gKi8KICAgICAgICAgICAgdmFyIHBhcmFtcyA9IG5ldyBVUkxTZWFyY2hQYXJhbXMobG9jYXRpb24uc2VhcmNoKTsKICAgICAgICAgICAgaWYgKHBhcmFtcy5oYXMoJ2FwaScpKSByZXR1cm4gcGFyYW1zLmdldCgnYXBpJykucmVwbGFjZSgvXC8kLywgJycpOwogICAgICAgICAgICBpZiAobG9jYXRpb24ucG9ydCA9PT0gJzkwOTAnKSByZXR1cm4gJyc7ICAgICAgICAgICAgLy8gcHJveHkgbW9kZSAoc2FtZSBvcmlnaW4pCiAgICAgICAgICAgIHJldHVybiAnaHR0cHM6Ly9ydXN0Y2hhaW4ub3JnJzsKICAgICAgICB9KSgpOwoKICAgICAgICBjb25zdCBUT1RBTF9TVVBQTFkgPSA4Mzg4NjA4OyAgIC8vIDJeMjMgUlRDCiAgICAgICAgY29uc3QgUkVGUkVTSF9NUyAgID0gMTAwMDA7CiAgICAgICAgY29uc3QgTUFYX01JTkVSUyAgID0gNTA7CgogICAgICAgIC8qIC0tLS0tLS0tLS0gSGVscGVycyAtLS0tLS0tLS0tICovCiAgICAgICAgZnVuY3Rpb24gZXNjKHMpIHsgICAgICAgICAgICAgICAgICAgIC8vIFhTUy1zYWZlIHRleHQgaW5qZWN0aW9uCiAgICAgICAgICAgIHZhciBkID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpOwogICAgICAgICAgICBkLnRleHRDb250ZW50ID0gcyA9PSBudWxsID8gJycgOiBTdHJpbmcocyk7CiAgICAgICAgICAgIHJldHVybiBkLmlubmVySFRNTDsKICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIGZtdChuKSB7ICAgICAgICAgICAgICAgICAgIC8vIGxvY2FsZS1hd2FyZSBudW1iZXIKICAgICAgICAgICAgcmV0dXJuIG4gPT0gbnVsbCA/ICctLScgOiBOdW1iZXIobikudG9Mb2NhbGVTdHJpbmcoKTsKICAgICAgICB9CgogICAgICAgIGZ1bmN0aW9uIHNob3J0QWRkcihhLCBuKSB7CiAgICAgICAgICAgIG4gPSBuIHx8IDY7CiAgICAgICAgICAgIGlmICghYSB8fCBhLmxlbmd0aCA8IG4gKiAyICsgMikgcmV0dXJuIGVzYyhhIHx8ICc/Jyk7CiAgICAgICAgICAgIHJldHVybiBlc2MoYS5zbGljZSgwLCBuICsgMikpICsgJyZoZWxsaXA7JyArIGVzYyhhLnNsaWNlKC1uKSk7CiAgICAgICAgfQoKICAgICAgICBmdW5jdGlvbiBzdGF0dXNCYWRnZShzKSB7CiAgICAgICAgICAgIGlmIChzID09PSAnb25saW5lJykgcmV0dXJuICc8c3BhbiBjbGFzcz0iYmFkZ2UgYmFkZ2UtZ3JlZW4iPm9ubGluZTwvc3Bhbj4nOwogICAgICAgICAgICBpZiAocyA9PT0gJ2lkbGUnKSAgIHJldHVybiAnPHNwYW4gY2xhc3M9ImJhZGdlIGJhZGdlLXllbGxvdyI+aWRsZTwvc3Bhbj4nOwogICAgICAgICAgICByZXR1cm4gJzxzcGFuIGNsYXNzPSJiYWRnZSBiYWRnZS1yZWQiPicgKyBlc2MocyB8fCAndW5rbm93bicpICsgJzwvc3Bhbj4nOwogICAgICAgIH0KCiAgICAgICAgZnVuY3Rpb24gdGllckJhZGdlKGFyY2gpIHsKICAgICAgICAgICAgdmFyIHYgPSBTdHJpbmcoYXJjaCkudG9Mb3dlckNhc2UoKTsKICAgICAgICAgICAgaWYgKHYuaW5kZXhPZignYW5jaWVudCcpICE9PSAtMSB8fCB2LmluZGV4T2YoJ3NhY3JlZCcpICE9PSAtMSkKICAgICAgICAgICAgICAgIHJldHVybiAnPHNwYW4gY2xhc3M9ImJhZGdlIGJhZGdlLWFjY2VudCI+JyArIGVzYyhhcmNoKSArICc8L3NwYW4+JzsKICAgICAgICAgICAgaWYgKHYuaW5kZXhPZigndmludGFnZScpICE9PSAtMSB8fCB2LmluZGV4T2YoJ2NsYXNzaWMnKSAhPT0gLTEpCiAgICAgICAgICAgICAgICByZXR1cm4gJzxzcGFuIGNsYXNzPSJiYWRnZSBiYWRnZS15ZWxsb3ciPicgKyBlc2MoYXJjaCkgKyAnPC9zcGFuPic7CiAgICAgICAgICAgIHJldHVybiAnPHNwYW4gY2xhc3M9ImJhZGdlIj4nICsgZXNjKGFyY2ggfHwgJz8nKSArICc8L3NwYW4+JzsKICAgICAgICB9CgogICAgICAgIC8qIC0tLS0tLS0tLS0gRmV0Y2ggd3JhcHBlciAtLS0tLS0tLS0tICovCiAgICAgICAgZnVuY3Rpb24gYXBpKHBhdGgpIHsKICAgICAgICAgICAgcmV0dXJuIGZldGNoKEFQSV9CQVNFICsgcGF0aCwgeyBtb2RlOiAnY29ycycsIGNhY2hlOiAnbm8tc3RvcmUnIH0pCiAgICAgICAgICAgICAgICAudGhlbihmdW5jdGlvbiAocikgeyByZXR1cm4gci5vayA/IHIuanNvbigpIDogbnVsbDsgfSkKICAgICAgICAgICAgICAgIC5jYXRjaChmdW5jdGlvbiAoKSB7IHJldHVybiBudWxsOyB9KTsKICAgICAgICB9CgogICAgICAgIC8qIC0tLS0tLS0tLS0gU3RhdGUgLS0tLS0tLS0tLSAqLwogICAgICAgIHZhciBtaW5lcnMgICA9IFtdOwogICAgICAgIHZhciBlcG9jaCAgICA9IHt9OwogICAgICAgIHZhciB0eHMgICAgICA9IFtdOwogICAgICAgIHZhciBsYXN0T2sgICA9IGZhbHNlOwoKICAgICAgICAvKiAtLS0tLS0tLS0tIEZldGNoIGFsbCBkYXRhIGluIHBhcmFsbGVsIC0tLS0tLS0tLS0gKi8KICAgICAgICBmdW5jdGlvbiByZWZyZXNoKCkgewogICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwoWwogICAgICAgICAgICAgICAgYXBpKCcvaGVhbHRoJyksCiAgICAgICAgICAgICAgICBhcGkoJy9lcG9jaCcpLAogICAgICAgICAgICAgICAgYXBpKCcvYXBpL21pbmVycycpLAogICAgICAgICAgICAgICAgYXBpKCcvYXBpL3RyYW5zYWN0aW9ucycpLAogICAgICAgICAgICBdKS50aGVuKGZ1bmN0aW9uIChyZXN1bHRzKSB7CiAgICAgICAgICAgICAgICB2YXIgaGVhbHRoICA9IHJlc3VsdHNbMF07CiAgICAgICAgICAgICAgICB2YXIgZSAgICAgICA9IHJlc3VsdHNbMV07CiAgICAgICAgICAgICAgICB2YXIgbSAgICAgICA9IHJlc3VsdHNbMl07CiAgICAgICAgICAgICAgICB2YXIgdCAgICAgICA9IHJlc3VsdHNbM107CgogICAgICAgICAgICAgICAgaWYgKGhlYWx0aCkgbGFzdE9rID0gdHJ1ZTsKCiAgICAgICAgICAgICAgICAvKiBNaW5lcnMgKi8KICAgICAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KG0pKSBtaW5lcnMgPSBtOwogICAgICAgICAgICAgICAgZWxzZSBpZiAobSAmJiBBcnJheS5pc0FycmF5KG0ubWluZXJzKSkgbWluZXJzID0gbS5taW5lcnM7CgogICAgICAgICAgICAgICAgLyogRXBvY2ggKi8KICAgICAgICAgICAgICAgIGlmIChlICYmIHR5cGVvZiBlID09PSAnb2JqZWN0JykgZXBvY2ggPSBlOwoKICAgICAgICAgICAgICAgIC8qIFRyYW5zYWN0aW9ucyAqLwogICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkodCkpIHR4cyA9IHQ7CiAgICAgICAgICAgICAgICBlbHNlIGlmICh0ICYmIEFycmF5LmlzQXJyYXkodC50cmFuc2FjdGlvbnMpKSB0eHMgPSB0LnRyYW5zYWN0aW9uczsKCiAgICAgICAgICAgICAgICByZW5kZXIoaGVhbHRoKTsKICAgICAgICAgICAgfSk7CiAgICAgICAgfQoKICAgICAgICAvKiAtLS0tLS0tLS0tIFJlbmRlciAtLS0tLS0tLS0tICovCiAgICAgICAgZnVuY3Rpb24gcmVuZGVyKGhlYWx0aCkgewogICAgICAgICAgICAvKiBOZXR3b3JrIHN0YXR1cyAqLwogICAgICAgICAgICB2YXIgdm4gPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndi1uZXR3b3JrJyk7CiAgICAgICAgICAgIHZhciB2bnMgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndi1uZXR3b3JrLXN1YicpOwogICAgICAgICAgICB2YXIgZG90ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3N0YXR1cy1kb3QnKTsKICAgICAgICAgICAgaWYgKGhlYWx0aCAmJiAoaGVhbHRoLnN0YXR1cyA9PT0gJ29rJyB8fCBoZWFsdGguc3RhdHVzID09PSAnaGVhbHRoeScgfHwgaGVhbHRoLnN0YXR1cyA9PT0gJ2RlbW8nKSkgewogICAgICAgICAgICAgICAgdm4udGV4dENvbnRlbnQgPSAnT25saW5lJzsKICAgICAgICAgICAgICAgIHZuLmNsYXNzTmFtZSA9ICdjYXJkLXZhbHVlIHRleHQtZ3JlZW4nOwogICAgICAgICAgICAgICAgZG90LmNsYXNzTmFtZSA9ICdzdGF0dXMtZG90IG9uJzsKICAgICAgICAgICAgICAgIHZucy50ZXh0Q29udGVudCA9IGhlYWx0aC52ZXJzaW9uID8gJ3YnICsgZXNjKGhlYWx0aC52ZXJzaW9uKSA6ICcnOwogICAgICAgICAgICB9IGVsc2UgaWYgKGhlYWx0aCAmJiBoZWFsdGguc3RhdHVzKSB7CiAgICAgICAgICAgICAgICB2bi50ZXh0Q29udGVudCA9IGVzYyhoZWFsdGguc3RhdHVzKTsKICAgICAgICAgICAgICAgIHZuLmNsYXNzTmFtZSA9ICdjYXJkLXZhbHVlIHRleHQteWVsbG93JzsKICAgICAgICAgICAgICAgIGRvdC5jbGFzc05hbWUgPSAnc3RhdHVzLWRvdCBvZmYnOwogICAgICAgICAgICAgICAgdm5zLnRleHRDb250ZW50ID0gJyc7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICB2bi50ZXh0Q29udGVudCA9ICdVbnJlYWNoYWJsZSc7CiAgICAgICAgICAgICAgICB2bi5jbGFzc05hbWUgPSAnY2FyZC12YWx1ZSB0ZXh0LXJlZCc7CiAgICAgICAgICAgICAgICBkb3QuY2xhc3NOYW1lID0gJ3N0YXR1cy1kb3Qgb2ZmJzsKICAgICAgICAgICAgICAgIHZucy50ZXh0Q29udGVudCA9ICdDb3VsZCBub3QgcmVhY2ggbm9kZSc7CiAgICAgICAgICAgIH0KCiAgICAgICAgICAgIC8qIEVwb2NoICovCiAgICAgICAgICAgIHZhciB2ZSAgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndi1lcG9jaCcpOwogICAgICAgICAgICB2YXIgdmVzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3YtZXBvY2gtc3ViJyk7CiAgICAgICAgICAgIHZlLnRleHRDb250ZW50ID0gZXBvY2guZXBvY2ggIT0gbnVsbCA/ICcjJyArIGZtdChlcG9jaC5lcG9jaCkgOiAnLS0nOwogICAgICAgICAgICB2ZXMudGV4dENvbnRlbnQgPSBlcG9jaC5zbG90ICE9IG51bGwgPyAnU2xvdCAnICsgZm10KGVwb2NoLnNsb3QpIDogJyc7CgogICAgICAgICAgICAvKiBNaW5lcnMgKi8KICAgICAgICAgICAgdmFyIHZtICA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2LW1pbmVycycpOwogICAgICAgICAgICB2YXIgdm1zID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3YtbWluZXJzLXN1YicpOwogICAgICAgICAgICB2YXIgb25saW5lQ291bnQgPSBtaW5lcnMuZmlsdGVyKGZ1bmN0aW9uIChtKSB7IHJldHVybiBtLnN0YXR1cyA9PT0gJ29ubGluZSc7IH0pLmxlbmd0aDsKICAgICAgICAgICAgdm0udGV4dENvbnRlbnQgPSBmbXQobWluZXJzLmxlbmd0aCk7CiAgICAgICAgICAgIHZtLmNsYXNzTmFtZSA9ICdjYXJkLXZhbHVlJzsKICAgICAgICAgICAgaWYgKG9ubGluZUNvdW50ID4gMCkgewogICAgICAgICAgICAgICAgdm0udGV4dENvbnRlbnQgPSBmbXQob25saW5lQ291bnQpICsgJyAvICcgKyBmbXQobWluZXJzLmxlbmd0aCk7CiAgICAgICAgICAgICAgICB2bXMudGV4dENvbnRlbnQgPSBmbXQob25saW5lQ291bnQpICsgJyBvbmxpbmUnOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgdm1zLnRleHRDb250ZW50ID0gbWluZXJzLmxlbmd0aCA/ICdubyBvbmxpbmUgbWluZXJzJyA6ICcnOwogICAgICAgICAgICB9CgogICAgICAgICAgICAvKiBQb3QgKi8KICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3YtcG90JykudGV4dENvbnRlbnQgPSBmbXQoZXBvY2gucG90KTsKCiAgICAgICAgICAgIC8qIFN1cHBseSAqLwogICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndi1zdXBwbHknKS50ZXh0Q29udGVudCA9IGZtdChUT1RBTF9TVVBQTFkpOwoKICAgICAgICAgICAgLyogVHJhbnNhY3Rpb25zICovCiAgICAgICAgICAgIHZhciB2dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCd2LXR4cycpOwogICAgICAgICAgICB2YXIgdnRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3YtdHhzLXN1YicpOwogICAgICAgICAgICB2dC50ZXh0Q29udGVudCA9IGZtdCh0eHMubGVuZ3RoKTsKICAgICAgICAgICAgdnRzLnRleHRDb250ZW50ID0gdHhzLmxlbmd0aCA/ICdpbiBjdXJyZW50IHdpbmRvdycgOiAnJzsKCiAgICAgICAgICAgIC8qIEFyY2hpdGVjdHVyZSBjaGFydCAqLwogICAgICAgICAgICByZW5kZXJBcmNoQ2hhcnQoKTsKCiAgICAgICAgICAgIC8qIE1pbmVyIHRhYmxlICovCiAgICAgICAgICAgIHJlbmRlck1pbmVyVGFibGUoKTsKCiAgICAgICAgICAgIC8qIFRpbWVzdGFtcCAqLwogICAgICAgICAgICBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgnbGFzdC11cGRhdGUnKS50ZXh0Q29udGVudCA9CiAgICAgICAgICAgICAgICBuZXcgRGF0ZSgpLnRvTG9jYWxlVGltZVN0cmluZygpOwogICAgICAgIH0KCiAgICAgICAgLyogLS0tLS0tLS0tLSBBcmNoaXRlY3R1cmUgYmFyIGNoYXJ0IC0tLS0tLS0tLS0gKi8KICAgICAgICBmdW5jdGlvbiByZW5kZXJBcmNoQ2hhcnQoKSB7CiAgICAgICAgICAgIHZhciBjb3VudHMgPSB7fTsKICAgICAgICAgICAgbWluZXJzLmZvckVhY2goZnVuY3Rpb24gKG0pIHsKICAgICAgICAgICAgICAgIHZhciBhcmNoID0gbS5hcmNoaXRlY3R1cmUgfHwgbS50aWVyIHx8ICdVbmtub3duJzsKICAgICAgICAgICAgICAgIGNvdW50c1thcmNoXSA9IChjb3VudHNbYXJjaF0gfHwgMCkgKyAxOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgdmFyIGVudHJpZXMgPSBPYmplY3Qua2V5cyhjb3VudHMpLm1hcChmdW5jdGlvbiAoaykgewogICAgICAgICAgICAgICAgcmV0dXJuIHsgYXJjaDogaywgY291bnQ6IGNvdW50c1trXSB9OwogICAgICAgICAgICB9KS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7IHJldHVybiBiLmNvdW50IC0gYS5jb3VudDsgfSk7CgogICAgICAgICAgICBpZiAoZW50cmllcy5sZW5ndGggPT09IDApIHsKICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdhcmNoLWNvbnRhaW5lcicpLmlubmVySFRNTCA9CiAgICAgICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9ImVtcHR5Ij48ZGl2IGNsYXNzPSJlbXB0eS1pY29uIiBhcmlhLWhpZGRlbj0idHJ1ZSI+4pqZ77iPPC9kaXY+Tm8gbWluZXIgZGF0YSBhdmFpbGFibGU8L2Rpdj4nOwogICAgICAgICAgICAgICAgcmV0dXJuOwogICAgICAgICAgICB9CiAgICAgICAgICAgIHZhciBtYXggPSBlbnRyaWVzWzBdLmNvdW50OwogICAgICAgICAgICB2YXIgaHRtbCA9ICcnOwogICAgICAgICAgICBlbnRyaWVzLmZvckVhY2goZnVuY3Rpb24gKGUpIHsKICAgICAgICAgICAgICAgIHZhciBwY3QgPSBNYXRoLnJvdW5kKChlLmNvdW50IC8gbWF4KSAqIDEwMCk7CiAgICAgICAgICAgICAgICBodG1sICs9ICc8ZGl2IGNsYXNzPSJhcmNoLXJvdyI+JyArCiAgICAgICAgICAgICAgICAgICAgJzxkaXYgY2xhc3M9ImFyY2gtbGFiZWwiPicgKyBlc2MoZS5hcmNoKSArICc8L2Rpdj4nICsKICAgICAgICAgICAgICAgICAgICAnPGRpdiBjbGFzcz0iYXJjaC1iYXItdHJhY2siPjxkaXYgY2xhc3M9ImFyY2gtYmFyLWZpbGwiIHN0eWxlPSJ3aWR0aDonICsgcGN0ICsgJyUiPjwvZGl2PjwvZGl2PicgKwogICAgICAgICAgICAgICAgICAgICc8ZGl2IGNsYXNzPSJhcmNoLWNvdW50Ij4nICsgZS5jb3VudCArICc8L2Rpdj48L2Rpdj4nOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ2FyY2gtY29udGFpbmVyJykuaW5uZXJIVE1MID0gaHRtbDsKICAgICAgICB9CgogICAgICAgIC8qIC0tLS0tLS0tLS0gTWluZXIgdGFibGUgLS0tLS0tLS0tLSAqLwogICAgICAgIGZ1bmN0aW9uIHJlbmRlck1pbmVyVGFibGUoKSB7CiAgICAgICAgICAgIHZhciBzb3J0ZWQgPSBtaW5lcnMuc2xpY2UoKS5zb3J0KGZ1bmN0aW9uIChhLCBiKSB7CiAgICAgICAgICAgICAgICByZXR1cm4gKGIuc2NvcmUgfHwgYi5ydXN0X3Njb3JlIHx8IDApIC0gKGEuc2NvcmUgfHwgYS5ydXN0X3Njb3JlIHx8IDApOwogICAgICAgICAgICB9KS5zbGljZSgwLCBNQVhfTUlORVJTKTsKCiAgICAgICAgICAgIHZhciB0Ym9keSA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdtaW5lci10Ym9keScpOwogICAgICAgICAgICBpZiAoc29ydGVkLmxlbmd0aCA9PT0gMCkgewogICAgICAgICAgICAgICAgdGJvZHkuaW5uZXJIVE1MID0gJzx0cj48dGQgY29sc3Bhbj0iNiIgY2xhc3M9ImVtcHR5Ij5ObyBtaW5lcnMgZm91bmQ8L3RkPjwvdHI+JzsKICAgICAgICAgICAgICAgIHJldHVybjsKICAgICAgICAgICAgfQoKICAgICAgICAgICAgdmFyIGh0bWwgPSAnJzsKICAgICAgICAgICAgc29ydGVkLmZvckVhY2goZnVuY3Rpb24gKG0sIGkpIHsKICAgICAgICAgICAgICAgIHZhciBpZCAgID0gbS5taW5lcl9pZCB8fCBtLmlkIHx8IG0ud2FsbGV0IHx8ICcnOwogICAgICAgICAgICAgICAgdmFyIGFyY2ggPSBtLmFyY2hpdGVjdHVyZSB8fCBtLnRpZXIgfHwgJz8nOwogICAgICAgICAgICAgICAgdmFyIHNjb3JlID0gbS5zY29yZSB8fCBtLnJ1c3Rfc2NvcmUgfHwgMDsKICAgICAgICAgICAgICAgIHZhciBtdWx0ICA9IG0ubXVsdGlwbGllciAhPSBudWxsID8gbS5tdWx0aXBsaWVyICsgJ3gnIDogJy0tJzsKICAgICAgICAgICAgICAgIHZhciBzdCAgICA9IG0uc3RhdHVzIHx8ICd1bmtub3duJzsKICAgICAgICAgICAgICAgIGh0bWwgKz0gJzx0cj4nICsKICAgICAgICAgICAgICAgICAgICAnPHRkPicgKyAoaSArIDEpICsgJzwvdGQ+JyArCiAgICAgICAgICAgICAgICAgICAgJzx0ZCBjbGFzcz0ibW9ubyIgdGl0bGU9IicgKyBlc2MoaWQpICsgJyI+JyArIHNob3J0QWRkcihpZCwgNCkgKyAnPC90ZD4nICsKICAgICAgICAgICAgICAgICAgICAnPHRkPicgKyB0aWVyQmFkZ2UoYXJjaCkgKyAnPC90ZD4nICsKICAgICAgICAgICAgICAgICAgICAnPHRkPicgKyBmbXQoc2NvcmUpICsgJzwvdGQ+JyArCiAgICAgICAgICAgICAgICAgICAgJzx0ZD4nICsgZXNjKG11bHQpICsgJzwvdGQ+JyArCiAgICAgICAgICAgICAgICAgICAgJzx0ZD4nICsgc3RhdHVzQmFkZ2Uoc3QpICsgJzwvdGQ+PC90cj4nOwogICAgICAgICAgICB9KTsKICAgICAgICAgICAgdGJvZHkuaW5uZXJIVE1MID0gaHRtbDsKICAgICAgICB9CgogICAgICAgIC8qIC0tLS0tLS0tLS0gQXV0by1yZWZyZXNoIC0tLS0tLS0tLS0gKi8KICAgICAgICByZWZyZXNoKCk7CiAgICAgICAgc2V0SW50ZXJ2YWwocmVmcmVzaCwgUkVGUkVTSF9NUyk7CgogICAgICAgIC8qIFZpc2liaWxpdHkgQVBJOiBza2lwIHJlZnJlc2ggd2hlbiB0YWIgaGlkZGVuICovCiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigndmlzaWJpbGl0eWNoYW5nZScsIGZ1bmN0aW9uICgpIHsKICAgICAgICAgICAgLyogbm8tb3A6IHdlIGFsd2F5cyByZWZyZXNoLCBidXQgY291bGQgYWRkIHBhdXNlIGxvZ2ljICovCiAgICAgICAgfSk7CiAgICB9KSgpOwogICAgPC9zY3JpcHQ+CjwvYm9keT4KPC9odG1sPgo= \ No newline at end of file diff --git a/explorer/stats_server.py b/explorer/stats_server.py new file mode 100644 index 000000000..445d97e31 --- /dev/null +++ b/explorer/stats_server.py @@ -0,0 +1 @@ +IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwojIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBNSVQKIiIiClJ1c3RDaGFpbiBTdGF0cyBEYXNoYm9hcmQg4oCUIGxpZ2h0d2VpZ2h0IFB5dGhvbiBwcm94eSBzZXJ2ZXIuCgpTZXJ2ZXMgc3RhdHMtZGFzaGJvYXJkLmh0bWwgYW5kIHByb3hpZXMgcmVxdWVzdHMgdG8gYSBSdXN0Q2hhaW4gbm9kZS4KWmVybyBleHRlcm5hbCBkZXBlbmRlbmNpZXMgKHN0ZGxpYiBvbmx5KS4KClVzYWdlOgogICAgcHl0aG9uMyBzdGF0c19zZXJ2ZXIucHkgICAgICAgICAgICAgICAgICAgICAgICAgIyBkZWZhdWx0czogcG9ydCA5MDkwLCBub2RlIGF0IHJ1c3RjaGFpbi5vcmcKICAgIHB5dGhvbjMgc3RhdHNfc2VydmVyLnB5IC0tcG9ydCA4MDgwIC0tbm9kZSBodHRwOi8vbG9jYWxob3N0OjgwMDAKICAgIHB5dGhvbjMgc3RhdHNfc2VydmVyLnB5IC0tdGVzdCAgICAgICAgICAgICAgICAgICMgcnVuIG9mZmxpbmUgc2VsZi10ZXN0cwoKRW52aXJvbm1lbnQgdmFyaWFibGVzICh0YWtlIHByZWNlZGVuY2Ugb3ZlciBDTEkgZmxhZ3MpOgogICAgU1RBVFNfUE9SVCAgICAgICAgICBTZXJ2ZXIgcG9ydCAgICAgICAgKGRlZmF1bHQgOTA5MCkKICAgIFJVU1RDSEFJTl9BUElfQkFTRSAgVXBzdHJlYW0gbm9kZSBVUkwgIChkZWZhdWx0IGh0dHBzOi8vcnVzdGNoYWluLm9yZykKIiIiCgppbXBvcnQgYXJncGFyc2UKaW1wb3J0IGpzb24KaW1wb3J0IG9zCmltcG9ydCBzeXMKaW1wb3J0IHRpbWUKaW1wb3J0IHVuaXR0ZXN0CmZyb20gaHR0cC5zZXJ2ZXIgaW1wb3J0IEhUVFBTZXJ2ZXIsIFNpbXBsZUhUVFBSZXF1ZXN0SGFuZGxlcgpmcm9tIHVybGxpYi5wYXJzZSBpbXBvcnQgdXJscGFyc2UsIHBhcnNlX3FzCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIENvbmZpZ3VyYXRpb24gaGVscGVycwojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQoKUFJPWFlfRU5EUE9JTlRTID0gZnJvemVuc2V0KHsiaGVhbHRoIiwgImVwb2NoIiwgImFwaS9taW5lcnMiLCAiYXBpL3RyYW5zYWN0aW9ucyIsICJhcGkvc3RhdHMifSkKCgpkZWYgX3ZhbGlkYXRlX2VuZHBvaW50KHJhdzogc3RyKSAtPiBzdHIgfCBOb25lOgogICAgIiIiUmV0dXJuIGEgc2FmZSB1cHN0cmVhbSBwYXRoIGlmICpyYXcqIGlzIGluIHRoZSBhbGxvdy1saXN0LCBlbHNlIE5vbmUuIiIiCiAgICBpZiBub3QgcmF3IG9yIHJhdy5zdGFydHN3aXRoKCIvIikgb3IgcmF3LmVuZHN3aXRoKCIvIik6CiAgICAgICAgcmV0dXJuIE5vbmUKICAgIGlmICIuLiIgaW4gcmF3IG9yIHJhdyBpbiAoIi4iLCAiIik6CiAgICAgICAgcmV0dXJuIE5vbmUKICAgICMgT25seSBhbGxvdyBzZWdtZW50cyBvZiB0aGUgc2FmZSBhbHBoYWJldCAoYS16LCBBLVosIDAtOSwgLykg4oCUCiAgICAjIHJlamVjdCBhbnl0aGluZyB3aXRoIHNwYWNlcywgcXVlcnkgc3RyaW5ncywgb3Igc3VzcGljaW91cyBjaGFycy4KICAgIGltcG9ydCByZQogICAgaWYgbm90IHJlLmZ1bGxtYXRjaChyIlthLXpBLVowLTkvXSsiLCByYXcpOgogICAgICAgIHJldHVybiBOb25lCiAgICByZXR1cm4gcmF3IGlmIHJhdyBpbiBQUk9YWV9FTkRQT0lOVFMgZWxzZSBOb25lCgoKZGVmIF9mZXRjaF9qc29uKGJhc2U6IHN0ciwgZW5kcG9pbnQ6IHN0ciwgdGltZW91dDogZmxvYXQgPSA4LjApIC0+IGRpY3QgfCBOb25lOgogICAgIiIiRmV0Y2ggYSBKU09OIHJlc291cmNlIGZyb20gdGhlIHVwc3RyZWFtIG5vZGUuIFJldHVybnMgTm9uZSBvbiBmYWlsdXJlLiIiIgogICAgaW1wb3J0IHVybGxpYi5yZXF1ZXN0CiAgICBpbXBvcnQgdXJsbGliLmVycm9yCgogICAgdXJsID0gZiJ7YmFzZS5yc3RyaXAoJy8nKX0ve2VuZHBvaW50fSIKICAgIHRyeToKICAgICAgICB3aXRoIHVybGxpYi5yZXF1ZXN0LnVybG9wZW4odXJsLCB0aW1lb3V0PXRpbWVvdXQpIGFzIHJlc3A6CiAgICAgICAgICAgIHJldHVybiBqc29uLmxvYWRzKHJlc3AucmVhZCgpLmRlY29kZSgpKQogICAgZXhjZXB0ICh1cmxsaWIuZXJyb3IuVVJMRXJyb3IsIE9TRXJyb3IsIGpzb24uSlNPTkRlY29kZUVycm9yKToKICAgICAgICByZXR1cm4gTm9uZQoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgSFRUUCBoYW5kbGVyCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpjbGFzcyBfSGFuZGxlcihTaW1wbGVIVFRQUmVxdWVzdEhhbmRsZXIpOgogICAgIiIiU2VydmVzIHRoZSBkYXNoYm9hcmQgSFRNTCBhbmQgcHJveGllcyAvcHJveHkvPGVuZHBvaW50PiB0byB0aGUgbm9kZS4iIiIKCiAgICBhcGlfYmFzZTogc3RyICAjIHNldCBieSB0aGUgc2VydmVyIGNsYXNzIGJlZm9yZSBiaW5kaW5nCgogICAgZGVmIGRvX0dFVChzZWxmKToKICAgICAgICBwYXJzZWQgPSB1cmxwYXJzZShzZWxmLnBhdGgpCiAgICAgICAgcGF0aCA9IHBhcnNlZC5wYXRoCgogICAgICAgICMgLS0tIFByb3h5IHJvdXRlIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgICAgIGlmIHBhdGguc3RhcnRzd2l0aCgiL3Byb3h5LyIpOgogICAgICAgICAgICBlbmRwb2ludCA9IHBhdGguc3BsaXQoIi9wcm94eS8iLCAxKVsxXQogICAgICAgICAgICBzYWZlID0gX3ZhbGlkYXRlX2VuZHBvaW50KGVuZHBvaW50KQogICAgICAgICAgICBpZiBzYWZlIGlzIE5vbmU6CiAgICAgICAgICAgICAgICBzZWxmLl9qc29uX3JlcGx5KDQwMCwgeyJlcnJvciI6ICJFbmRwb2ludCBub3QgYWxsb3dlZCJ9KQogICAgICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgICAgIGRhdGEgPSBfZmV0Y2hfanNvbihzZWxmLmFwaV9iYXNlLCBzYWZlKQogICAgICAgICAgICBpZiBkYXRhIGlzIE5vbmU6CiAgICAgICAgICAgICAgICBzZWxmLl9qc29uX3JlcGx5KDUwMiwgeyJlcnJvciI6ICJVcHN0cmVhbSB1bmF2YWlsYWJsZSJ9KQogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgc2VsZi5fanNvbl9yZXBseSgyMDAsIGRhdGEpCiAgICAgICAgICAgIHJldHVybgoKICAgICAgICAjIC0tLSBIZWFsdGggb2YgdGhpcyBzZXJ2ZXIgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgICAgIGlmIHBhdGggPT0gIi9zZXJ2ZXItaGVhbHRoIjoKICAgICAgICAgICAgc2VsZi5fanNvbl9yZXBseSgyMDAsIHsic3RhdHVzIjogIm9rIiwgInZlcnNpb24iOiAiMS4wLjAifSkKICAgICAgICAgICAgcmV0dXJuCgogICAgICAgICMgLS0tIFNlcnZlIGRhc2hib2FyZCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQogICAgICAgIGlmIHBhdGggaW4gKCIvIiwgIi9zdGF0cy1kYXNoYm9hcmQuaHRtbCIpOgogICAgICAgICAgICBzZWxmLnBhdGggPSAiL3N0YXRzLWRhc2hib2FyZC5odG1sIgogICAgICAgIHJldHVybiBzdXBlcigpLmRvX0dFVCgpCgogICAgZGVmIGRvX09QVElPTlMoc2VsZik6CiAgICAgICAgc2VsZi5zZW5kX3Jlc3BvbnNlKDIwMCkKICAgICAgICBzZWxmLnNlbmRfaGVhZGVyKCJBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4iLCAiKiIpCiAgICAgICAgc2VsZi5zZW5kX2hlYWRlcigiQWNjZXNzLUNvbnRyb2wtQWxsb3ctTWV0aG9kcyIsICJHRVQsIE9QVElPTlMiKQogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkFjY2Vzcy1Db250cm9sLUFsbG93LUhlYWRlcnMiLCAiQ29udGVudC1UeXBlIikKICAgICAgICBzZWxmLnNlbmRfaGVhZGVyKCJBY2Nlc3MtQ29udHJvbC1NYXgtQWdlIiwgIjg2NDAwIikKICAgICAgICBzZWxmLmVuZF9oZWFkZXJzKCkKCiAgICBkZWYgX2pzb25fcmVwbHkoc2VsZiwgY29kZTogaW50LCBib2R5OiBkaWN0KToKICAgICAgICBwYXlsb2FkID0ganNvbi5kdW1wcyhib2R5KS5lbmNvZGUoKQogICAgICAgIHNlbGYuc2VuZF9yZXNwb25zZShjb2RlKQogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkNvbnRlbnQtVHlwZSIsICJhcHBsaWNhdGlvbi9qc29uIikKICAgICAgICBzZWxmLnNlbmRfaGVhZGVyKCJBY2Nlc3MtQ29udHJvbC1BbGxvdy1PcmlnaW4iLCAiKiIpCiAgICAgICAgc2VsZi5zZW5kX2hlYWRlcigiQ29udGVudC1MZW5ndGgiLCBzdHIobGVuKHBheWxvYWQpKSkKICAgICAgICBzZWxmLmVuZF9oZWFkZXJzKCkKICAgICAgICBzZWxmLndmaWxlLndyaXRlKHBheWxvYWQpCgogICAgZGVmIGxvZ19tZXNzYWdlKHNlbGYsIGZtdCwgKmFyZ3MpOgogICAgICAgIHRzID0gdGltZS5zdHJmdGltZSgiJVktJW0tJWQgJUg6JU06JVMiKQogICAgICAgIHN5cy5zdGRlcnIud3JpdGUoZiJbe3RzfV0ge2FyZ3NbMF19XG4iKQoKCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCiMgT2ZmbGluZSBzZWxmLXRlc3RzCiMgLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tCgpjbGFzcyBUZXN0VmFsaWRhdGVFbmRwb2ludCh1bml0dGVzdC5UZXN0Q2FzZSk6CiAgICBkZWYgdGVzdF92YWxpZChzZWxmKToKICAgICAgICBmb3IgZXAgaW4gUFJPWFlfRU5EUE9JTlRTOgogICAgICAgICAgICBzZWxmLmFzc2VydEVxdWFsKF92YWxpZGF0ZV9lbmRwb2ludChlcCksIGVwKQoKICAgIGRlZiB0ZXN0X3JlamVjdF9wYXRoX3NlZ21lbnRzKHNlbGYpOgogICAgICAgIHNlbGYuYXNzZXJ0SXNOb25lKF92YWxpZGF0ZV9lbmRwb2ludCgiaGVhbHRoLy4uLy4uL2V0Yy9wYXNzd2QiKSkKCiAgICBkZWYgdGVzdF9yZWplY3RfdW5saXN0ZWQoc2VsZik6CiAgICAgICAgc2VsZi5hc3NlcnRJc05vbmUoX3ZhbGlkYXRlX2VuZHBvaW50KCJhZG1pbiIpKQogICAgICAgIHNlbGYuYXNzZXJ0SXNOb25lKF92YWxpZGF0ZV9lbmRwb2ludCgiIikpCgogICAgZGVmIHRlc3RfcmVqZWN0X2RvdF9zZWdtZW50cyhzZWxmKToKICAgICAgICBzZWxmLmFzc2VydElzTm9uZShfdmFsaWRhdGVfZW5kcG9pbnQoIi4iKSkKCgpjbGFzcyBUZXN0RmV0Y2hKc29uKHVuaXR0ZXN0LlRlc3RDYXNlKToKICAgICIiIlVzZXMgYSB0aW55IHRocmVhZGVkIEhUVFAgc2VydmVyIGFzIGEgZmFrZSB1cHN0cmVhbS4iIiIKCiAgICBkZWYgX3N0YXJ0X2Zha2Vfc2VydmVyKHNlbGYpIC0+IHR1cGxlW0hUVFBTZXJ2ZXIsIGludF06CiAgICAgICAgZmFrZSA9IEhUVFBTZXJ2ZXIoKCIxMjcuMC4wLjEiLCAwKSwgX0Zha2VIYW5kbGVyKQogICAgICAgIGltcG9ydCB0aHJlYWRpbmcKICAgICAgICB0ID0gdGhyZWFkaW5nLlRocmVhZCh0YXJnZXQ9ZmFrZS5zZXJ2ZV9mb3JldmVyLCBkYWVtb249VHJ1ZSkKICAgICAgICB0LnN0YXJ0KCkKICAgICAgICByZXR1cm4gZmFrZSwgZmFrZS5zZXJ2ZXJfYWRkcmVzc1sxXQoKICAgIGRlZiB0ZXN0X2ZldGNoX29rKHNlbGYpOgogICAgICAgIHNydiwgcG9ydCA9IHNlbGYuX3N0YXJ0X2Zha2Vfc2VydmVyKCkKICAgICAgICB0cnk6CiAgICAgICAgICAgIHJlc3VsdCA9IF9mZXRjaF9qc29uKGYiaHR0cDovLzEyNy4wLjAuMTp7cG9ydH0iLCAiaGVhbHRoIiwgdGltZW91dD0zKQogICAgICAgICAgICBzZWxmLmFzc2VydEVxdWFsKHJlc3VsdCwgeyJzdGF0dXMiOiAib2sifSkKICAgICAgICBmaW5hbGx5OgogICAgICAgICAgICBzcnYuc2h1dGRvd24oKQoKICAgIGRlZiB0ZXN0X2ZldGNoX2JhZF9ob3N0KHNlbGYpOgogICAgICAgIHJlc3VsdCA9IF9mZXRjaF9qc29uKCJodHRwOi8vMTI3LjAuMC4xOjEiLCAiaGVhbHRoIiwgdGltZW91dD0xKQogICAgICAgIHNlbGYuYXNzZXJ0SXNOb25lKHJlc3VsdCkKCgpjbGFzcyBfRmFrZUhhbmRsZXIoU2ltcGxlSFRUUFJlcXVlc3RIYW5kbGVyKToKICAgICIiIk1pbmltYWwgaGFuZGxlciB0aGF0IHJlc3BvbmRzIHRvIEdFVCAvaGVhbHRoIHdpdGggSlNPTi4iIiIKCiAgICBkZWYgZG9fR0VUKHNlbGYpOgogICAgICAgIGJvZHkgPSBiJ3sic3RhdHVzIjoib2sifScKICAgICAgICBzZWxmLnNlbmRfcmVzcG9uc2UoMjAwKQogICAgICAgIHNlbGYuc2VuZF9oZWFkZXIoIkNvbnRlbnQtVHlwZSIsICJhcHBsaWNhdGlvbi9qc29uIikKICAgICAgICBzZWxmLnNlbmRfaGVhZGVyKCJDb250ZW50LUxlbmd0aCIsIHN0cihsZW4oYm9keSkpKQogICAgICAgIHNlbGYuZW5kX2hlYWRlcnMoKQogICAgICAgIHNlbGYud2ZpbGUud3JpdGUoYm9keSkKCiAgICBkZWYgbG9nX21lc3NhZ2Uoc2VsZiwgKl9hKToKICAgICAgICBwYXNzICAjIHNpbGVuY2UKCgpjbGFzcyBUZXN0U2VydmVEYXNoYm9hcmQodW5pdHRlc3QuVGVzdENhc2UpOgogICAgIiIiVmVyaWZ5IHRoZSBzZXJ2ZXIgYWN0dWFsbHkgc2VydmVzIHRoZSBIVE1MIGZpbGUuIiIiCgogICAgZGVmIHRlc3Rfc2VydmVfaW5kZXgoc2VsZik6CiAgICAgICAgIyBCaW5kIGluIHRoZSBkaXJlY3RvcnkgY29udGFpbmluZyBzdGF0cy1kYXNoYm9hcmQuaHRtbAogICAgICAgIG9yaWdpbmFsX2RpciA9IG9zLmdldGN3ZCgpCiAgICAgICAgdGVzdF9kaXIgPSBvcy5wYXRoLmRpcm5hbWUob3MucGF0aC5hYnNwYXRoKF9fZmlsZV9fKSkKICAgICAgICBvcy5jaGRpcih0ZXN0X2RpcikKICAgICAgICB0cnk6CiAgICAgICAgICAgIHNydiA9IEhUVFBTZXJ2ZXIoKCIxMjcuMC4wLjEiLCAwKSwgX0hhbmRsZXIpCiAgICAgICAgICAgIGltcG9ydCB0aHJlYWRpbmcKICAgICAgICAgICAgdCA9IHRocmVhZGluZy5UaHJlYWQodGFyZ2V0PXNydi5zZXJ2ZV9mb3JldmVyLCBkYWVtb249VHJ1ZSkKICAgICAgICAgICAgdC5zdGFydCgpCiAgICAgICAgICAgIGltcG9ydCB1cmxsaWIucmVxdWVzdAogICAgICAgICAgICBwb3J0ID0gc3J2LnNlcnZlcl9hZGRyZXNzWzFdCiAgICAgICAgICAgIHJlc3AgPSB1cmxsaWIucmVxdWVzdC51cmxvcGVuKGYiaHR0cDovLzEyNy4wLjAuMTp7cG9ydH0vIiwgdGltZW91dD01KQogICAgICAgICAgICBodG1sID0gcmVzcC5yZWFkKCkuZGVjb2RlKCkKICAgICAgICAgICAgc2VsZi5hc3NlcnRJbigiUnVzdENoYWluIFN0YXRzIERhc2hib2FyZCIsIGh0bWwpCiAgICAgICAgICAgIHNydi5zaHV0ZG93bigpCiAgICAgICAgZmluYWxseToKICAgICAgICAgICAgb3MuY2hkaXIob3JpZ2luYWxfZGlyKQoKCmRlZiBydW5fdGVzdHMoKToKICAgICIiIlJ1biBhbGwgb2ZmbGluZSBzZWxmLXRlc3RzLiIiIgogICAgbG9hZGVyID0gdW5pdHRlc3QuVGVzdExvYWRlcigpCiAgICBzdWl0ZSAgPSB1bml0dGVzdC5UZXN0U3VpdGUoKQogICAgc3VpdGUuYWRkVGVzdHMobG9hZGVyLmxvYWRUZXN0c0Zyb21UZXN0Q2FzZShUZXN0VmFsaWRhdGVFbmRwb2ludCkpCiAgICBzdWl0ZS5hZGRUZXN0cyhsb2FkZXIubG9hZFRlc3RzRnJvbVRlc3RDYXNlKFRlc3RGZXRjaEpzb24pKQogICAgc3VpdGUuYWRkVGVzdHMobG9hZGVyLmxvYWRUZXN0c0Zyb21UZXN0Q2FzZShUZXN0U2VydmVEYXNoYm9hcmQpKQogICAgcnVubmVyID0gdW5pdHRlc3QuVGV4dFRlc3RSdW5uZXIodmVyYm9zaXR5PTIpCiAgICByZXN1bHQgPSBydW5uZXIucnVuKHN1aXRlKQogICAgcmV0dXJuIDAgaWYgcmVzdWx0Lndhc1N1Y2Nlc3NmdWwoKSBlbHNlIDEKCgojIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQojIE1haW4KIyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0KCmRlZiBtYWluKCk6CiAgICBwYXJzZXIgPSBhcmdwYXJzZS5Bcmd1bWVudFBhcnNlcihkZXNjcmlwdGlvbj0iUnVzdENoYWluIFN0YXRzIERhc2hib2FyZCBTZXJ2ZXIiKQogICAgcGFyc2VyLmFkZF9hcmd1bWVudCgiLS1wb3J0IiwgIHR5cGU9aW50LCBkZWZhdWx0PWludChvcy5lbnZpcm9uLmdldCgiU1RBVFNfUE9SVCIsIDkwOTApKSkKICAgIHBhcnNlci5hZGRfYXJndW1lbnQoIi0tbm9kZSIsICB0eXBlPXN0ciwgZGVmYXVsdD1vcy5lbnZpcm9uLmdldCgiUlVTVENIQUlOX0FQSV9CQVNFIiwgImh0dHBzOi8vcnVzdGNoYWluLm9yZyIpKQogICAgcGFyc2VyLmFkZF9hcmd1bWVudCgiLS10ZXN0IiwgIGFjdGlvbj0ic3RvcmVfdHJ1ZSIsIGhlbHA9IlJ1biBvZmZsaW5lIHNlbGYtdGVzdHMgYW5kIGV4aXQiKQogICAgYXJncyA9IHBhcnNlci5wYXJzZV9hcmdzKCkKCiAgICBpZiBhcmdzLnRlc3Q6CiAgICAgICAgc3lzLmV4aXQocnVuX3Rlc3RzKCkpCgogICAgIyBTZXJ2ZSB0aGUgZGlyZWN0b3J5IHRoaXMgc2NyaXB0IGxpdmVzIGluCiAgICBvcy5jaGRpcihvcy5wYXRoLmRpcm5hbWUob3MucGF0aC5hYnNwYXRoKF9fZmlsZV9fKSkpCgogICAgX0hhbmRsZXIuYXBpX2Jhc2UgPSBhcmdzLm5vZGUKICAgIHNydiA9IEhUVFBTZXJ2ZXIoKCIiLCBhcmdzLnBvcnQpLCBfSGFuZGxlcikKCiAgICBwcmludChmIvCfpoAgUnVzdENoYWluIFN0YXRzIERhc2hib2FyZCBsaXN0ZW5pbmcgb24gaHR0cDovL2xvY2FsaG9zdDp7YXJncy5wb3J0fSIpCiAgICBwcmludChmIiAgIFVwc3RyZWFtIG5vZGU6IHthcmdzLm5vZGV9IikKICAgIHByaW50KGYiICAgUHJlc3MgQ3RybCtDIHRvIHN0b3BcbiIpCgogICAgdHJ5OgogICAgICAgIHNydi5zZXJ2ZV9mb3JldmVyKCkKICAgIGV4Y2VwdCBLZXlib2FyZEludGVycnVwdDoKICAgICAgICBwcmludCgiXG5TaHV0dGluZyBkb3duLi4uIikKICAgICAgICBzcnYuc2h1dGRvd24oKQoKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBtYWluKCkK \ No newline at end of file