I2luY2x1ZGUgJmx0O2lvc3RyZWFtJmd0OwojaW5jbHVkZSAmbHQ7ZnN0cmVhbSZndDsKI2luY2x1ZGUgJmx0O2lvbWFuaXAmZ3Q7CiNpbmNsdWRlICZsdDtzdHJpbmcmZ3Q7CiNpbmNsdWRlICZsdDt2ZWN0b3ImZ3Q7CiNpbmNsdWRlICZsdDtjc3RyaW5nJmd0OwoKdXNpbmcgbmFtZXNwYWNlIHN0ZDsKCi8vIC0tLS0tLS0tLS0tLS0tLS0gVHJhaW4gQ2xhc3MgLS0tLS0tLS0tLS0tLS0tLQpjbGFzcyBUcmFpbiB7CnB1YmxpYzoKICAgIGludCB0cmFpbk5vOwogICAgc3RyaW5nIHRyYWluTmFtZTsKICAgIHN0cmluZyBzb3VyY2U7CiAgICBzdHJpbmcgZGVzdGluYXRpb247CiAgICBpbnQgdG90YWxTZWF0czsKICAgIGludCBib29rZWRTZWF0czsKICAgIGZsb2F0IGZhcmU7CgogICAgVHJhaW4oKSA6IHRyYWluTm8oMCksIHRvdGFsU2VhdHMoMCksIGJvb2tlZFNlYXRzKDApLCBmYXJlKDApIHt9CgogICAgVHJhaW4oaW50IG5vLCBzdHJpbmcgbmFtZSwgc3RyaW5nIHNyYywgc3RyaW5nIGRlc3QsIGludCBzZWF0cywgZmxvYXQgZikKICAgICAgICA6IHRyYWluTm8obm8pLCB0cmFpbk5hbWUobmFtZSksIHNvdXJjZShzcmMpLAogICAgICAgICAgZGVzdGluYXRpb24oZGVzdCksIHRvdGFsU2VhdHMoc2VhdHMpLCBib29rZWRTZWF0cygwKSwgZmFyZShmKSB7fQoKICAgIGludCBhdmFpbGFibGVTZWF0cygpIGNvbnN0IHsgcmV0dXJuIHRvdGFsU2VhdHMgLSBib29rZWRTZWF0czsgfQp9OwoKLy8gLS0tLS0tLS0tLS0tLS0tLSBQYXNzZW5nZXIgQ2xhc3MgLS0tLS0tLS0tLS0tLS0tLQpjbGFzcyBQYXNzZW5nZXIgewpwdWJsaWM6CiAgICBpbnQgcG5yOwogICAgc3RyaW5nIG5hbWU7CiAgICBpbnQgYWdlOwogICAgY2hhciBnZW5kZXI7CiAgICBzdHJpbmcgcGhvbmU7CiAgICBpbnQgdHJhaW5ObzsKICAgIHN0cmluZyB0cmFpbk5hbWU7CiAgICBzdHJpbmcgc291cmNlOwogICAgc3RyaW5nIGRlc3RpbmF0aW9uOwogICAgZmxvYXQgZmFyZTsKICAgIGludCBzZWF0Tm87CgogICAgUGFzc2VuZ2VyKCkgOiBwbnIoMCksIGFnZSgwKSwgZ2VuZGVyKCdNJyksIHRyYWluTm8oMCksIGZhcmUoMCksIHNlYXRObygwKSB7fQp9OwoKLy8gLS0tLS0tLS0tLS0tLS0tLSBSYWlsd2F5IFN5c3RlbSAtLS0tLS0tLS0tLS0tLS0tCmNsYXNzIFJhaWx3YXlTeXN0ZW0gewpwcml2YXRlOgogICAgdmVjdG9yJmx0O1RyYWluJmd0OyB0cmFpbnM7CiAgICBjb25zdCBzdHJpbmcgdHJhaW5GaWxlID0gJnF1b3Q7dHJhaW5zLmRhdCZxdW90OzsKICAgIGNvbnN0IHN0cmluZyBib29raW5nRmlsZSA9ICZxdW90O2Jvb2tpbmdzLmRhdCZxdW90OzsKICAgIGludCBuZXh0UE5SOwoKcHVibGljOgogICAgUmFpbHdheVN5c3RlbSgpIHsKICAgICAgICBsb2FkVHJhaW5zKCk7CiAgICAgICAgaWYgKHRyYWlucy5lbXB0eSgpKSB7CiAgICAgICAgICAgIGluaXRpYWxpemVUcmFpbnMoKTsKICAgICAgICB9CiAgICAgICAgbG9hZE5leHRQTlIoKTsKICAgIH0KCiAgICAvLyBJbml0aWFsaXplIGRlZmF1bHQgdHJhaW5zCiAgICB2b2lkIGluaXRpYWxpemVUcmFpbnMoKSB7CiAgICAgICAgdHJhaW5zLnB1c2hfYmFjayhUcmFpbigxMjM0NSwgJnF1b3Q7UmFqZGhhbmkgRXhwcmVzcyZxdW90OywgJnF1b3Q7RGVsaGkmcXVvdDssICZxdW90O011bWJhaSZxdW90OywgMTAwLCAyNTAwLjApKTsKICAgICAgICB0cmFpbnMucHVzaF9iYWNrKFRyYWluKDEyMzQ2LCAmcXVvdDtTaGF0YWJkaSBFeHByZXNzJnF1b3Q7LCAmcXVvdDtEZWxoaSZxdW90OywgJnF1b3Q7QmhvcGFsJnF1b3Q7LCA4MCwgMTIwMC4wKSk7CiAgICAgICAgdHJhaW5zLnB1c2hfYmFjayhUcmFpbigxMjM0NywgJnF1b3Q7RHVyb250byBFeHByZXNzJnF1b3Q7LCAmcXVvdDtNdW1iYWkmcXVvdDssICZxdW90O0NoZW5uYWkmcXVvdDssIDEyMCwgMTgwMC4wKSk7CiAgICAgICAgdHJhaW5zLnB1c2hfYmFjayhUcmFpbigxMjM0OCwgJnF1b3Q7R2FyaWIgUmF0aCZxdW90OywgJnF1b3Q7S29sa2F0YSZxdW90OywgJnF1b3Q7RGVsaGkmcXVvdDssIDE1MCwgOTAwLjApKTsKICAgICAgICB0cmFpbnMucHVzaF9iYWNrKFRyYWluKDEyMzQ5LCAmcXVvdDtDaGVubmFpIEV4cHJlc3MmcXVvdDssICZxdW90O0NoZW5uYWkmcXVvdDssICZxdW90O011bWJhaSZxdW90OywgMTEwLCAxNTAwLjApKTsKICAgICAgICBzYXZlVHJhaW5zKCk7CiAgICB9CgogICAgLy8gLS0tLS0tLS0tLSBGaWxlIEhhbmRsaW5nIC0tLS0tLS0tLS0KICAgIHZvaWQgc2F2ZVRyYWlucygpIHsKICAgICAgICBvZnN0cmVhbSBmb3V0KHRyYWluRmlsZSwgaW9zOjpiaW5hcnkpOwogICAgICAgIHNpemVfdCBzaXplID0gdHJhaW5zLnNpemUoKTsKICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO3NpemUsIHNpemVvZihzaXplKSk7CiAgICAgICAgZm9yIChhdXRvICZhbXA7dCA6IHRyYWlucykgewogICAgICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO3QudHJhaW5Obywgc2l6ZW9mKHQudHJhaW5ObykpOwogICAgICAgICAgICBzaXplX3QgbGVuID0gdC50cmFpbk5hbWUuc2l6ZSgpOwogICAgICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOwogICAgICAgICAgICBmb3V0LndyaXRlKHQudHJhaW5OYW1lLmNfc3RyKCksIGxlbik7CiAgICAgICAgICAgIGxlbiA9IHQuc291cmNlLnNpemUoKTsKICAgICAgICAgICAgZm91dC53cml0ZSgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsKICAgICAgICAgICAgZm91dC53cml0ZSh0LnNvdXJjZS5jX3N0cigpLCBsZW4pOwogICAgICAgICAgICBsZW4gPSB0LmRlc3RpbmF0aW9uLnNpemUoKTsKICAgICAgICAgICAgZm91dC53cml0ZSgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsKICAgICAgICAgICAgZm91dC53cml0ZSh0LmRlc3RpbmF0aW9uLmNfc3RyKCksIGxlbik7CiAgICAgICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7dC50b3RhbFNlYXRzLCBzaXplb2YodC50b3RhbFNlYXRzKSk7CiAgICAgICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7dC5ib29rZWRTZWF0cywgc2l6ZW9mKHQuYm9va2VkU2VhdHMpKTsKICAgICAgICAgICAgZm91dC53cml0ZSgoY2hhciopJmFtcDt0LmZhcmUsIHNpemVvZih0LmZhcmUpKTsKICAgICAgICB9CiAgICAgICAgZm91dC5jbG9zZSgpOwogICAgfQoKICAgIHZvaWQgbG9hZFRyYWlucygpIHsKICAgICAgICBpZnN0cmVhbSBmaW4odHJhaW5GaWxlLCBpb3M6OmJpbmFyeSk7CiAgICAgICAgaWYgKCFmaW4pIHJldHVybjsKICAgICAgICBzaXplX3Qgc2l6ZTsKICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtzaXplLCBzaXplb2Yoc2l6ZSkpOwogICAgICAgIGZvciAoc2l6ZV90IGkgPSAwOyBpICZsdDsgc2l6ZTsgaSsrKSB7CiAgICAgICAgICAgIFRyYWluIHQ7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3QudHJhaW5Obywgc2l6ZW9mKHQudHJhaW5ObykpOwogICAgICAgICAgICBzaXplX3QgbGVuOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsKICAgICAgICAgICAgdC50cmFpbk5hbWUucmVzaXplKGxlbik7CiAgICAgICAgICAgIGZpbi5yZWFkKCZhbXA7dC50cmFpbk5hbWVbMF0sIGxlbik7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOwogICAgICAgICAgICB0LnNvdXJjZS5yZXNpemUobGVuKTsKICAgICAgICAgICAgZmluLnJlYWQoJmFtcDt0LnNvdXJjZVswXSwgbGVuKTsKICAgICAgICAgICAgZmluLnJlYWQoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7CiAgICAgICAgICAgIHQuZGVzdGluYXRpb24ucmVzaXplKGxlbik7CiAgICAgICAgICAgIGZpbi5yZWFkKCZhbXA7dC5kZXN0aW5hdGlvblswXSwgbGVuKTsKICAgICAgICAgICAgZmluLnJlYWQoKGNoYXIqKSZhbXA7dC50b3RhbFNlYXRzLCBzaXplb2YodC50b3RhbFNlYXRzKSk7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3QuYm9va2VkU2VhdHMsIHNpemVvZih0LmJvb2tlZFNlYXRzKSk7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3QuZmFyZSwgc2l6ZW9mKHQuZmFyZSkpOwogICAgICAgICAgICB0cmFpbnMucHVzaF9iYWNrKHQpOwogICAgICAgIH0KICAgICAgICBmaW4uY2xvc2UoKTsKICAgIH0KCiAgICB2b2lkIGxvYWROZXh0UE5SKCkgewogICAgICAgIGlmc3RyZWFtIGZpbihib29raW5nRmlsZSwgaW9zOjpiaW5hcnkpOwogICAgICAgIG5leHRQTlIgPSAxMDAwOwogICAgICAgIGlmICghZmluKSByZXR1cm47CiAgICAgICAgZmluLnNlZWtnKDAsIGlvczo6ZW5kKTsKICAgICAgICBpZiAoZmluLnRlbGxnKCkgPT0gMCkgeyBmaW4uY2xvc2UoKTsgcmV0dXJuOyB9CiAgICAgICAgZmluLnNlZWtnKDApOwogICAgICAgIHdoaWxlIChmaW4ucGVlaygpICE9IEVPRikgewogICAgICAgICAgICBpbnQgcG5yOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtwbnIsIHNpemVvZihwbnIpKTsKICAgICAgICAgICAgaWYgKGZpbi5nY291bnQoKSA9PSAwKSBicmVhazsKICAgICAgICAgICAgbmV4dFBOUiA9IHBuciArIDE7CiAgICAgICAgICAgIC8vIHNraXAgcmVtYWluaW5nIHBhc3NlbmdlciBkYXRhCiAgICAgICAgICAgIGludCBhZ2UsIHRyYWluTm8sIHNlYXRObzsKICAgICAgICAgICAgY2hhciBnZW5kZXI7CiAgICAgICAgICAgIGZsb2F0IGZhcmU7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO2FnZSwgc2l6ZW9mKGFnZSkpOwogICAgICAgICAgICBmaW4ucmVhZCgmYW1wO2dlbmRlciwgc2l6ZW9mKGdlbmRlcikpOwogICAgICAgICAgICBzaXplX3QgbGVuOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsgZmluLnNlZWtnKGxlbiwgaW9zOjpjdXIpOyAvLyBuYW1lCiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOyBmaW4uc2Vla2cobGVuLCBpb3M6OmN1cik7IC8vIHBob25lCiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3RyYWluTm8sIHNpemVvZih0cmFpbk5vKSk7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOyBmaW4uc2Vla2cobGVuLCBpb3M6OmN1cik7IC8vIHRyYWluTmFtZQogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsgZmluLnNlZWtnKGxlbiwgaW9zOjpjdXIpOyAvLyBzb3VyY2UKICAgICAgICAgICAgZmluLnJlYWQoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7IGZpbi5zZWVrZyhsZW4sIGlvczo6Y3VyKTsgLy8gZGVzdAogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtmYXJlLCBzaXplb2YoZmFyZSkpOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtzZWF0Tm8sIHNpemVvZihzZWF0Tm8pKTsKICAgICAgICB9CiAgICAgICAgZmluLmNsb3NlKCk7CiAgICB9CgogICAgdm9pZCBhcHBlbmRCb29raW5nKGNvbnN0IFBhc3NlbmdlciAmYW1wO3ApIHsKICAgICAgICBvZnN0cmVhbSBmb3V0KGJvb2tpbmdGaWxlLCBpb3M6OmJpbmFyeSB8IGlvczo6YXBwKTsKICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO3AucG5yLCBzaXplb2YocC5wbnIpKTsKICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO3AuYWdlLCBzaXplb2YocC5hZ2UpKTsKICAgICAgICBmb3V0LndyaXRlKCZhbXA7cC5nZW5kZXIsIHNpemVvZihwLmdlbmRlcikpOwogICAgICAgIHNpemVfdCBsZW4gPSBwLm5hbWUuc2l6ZSgpOwogICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7CiAgICAgICAgZm91dC53cml0ZShwLm5hbWUuY19zdHIoKSwgbGVuKTsKICAgICAgICBsZW4gPSBwLnBob25lLnNpemUoKTsKICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOwogICAgICAgIGZvdXQud3JpdGUocC5waG9uZS5jX3N0cigpLCBsZW4pOwogICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7cC50cmFpbk5vLCBzaXplb2YocC50cmFpbk5vKSk7CiAgICAgICAgbGVuID0gcC50cmFpbk5hbWUuc2l6ZSgpOwogICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7CiAgICAgICAgZm91dC53cml0ZShwLnRyYWluTmFtZS5jX3N0cigpLCBsZW4pOwogICAgICAgIGxlbiA9IHAuc291cmNlLnNpemUoKTsKICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOwogICAgICAgIGZvdXQud3JpdGUocC5zb3VyY2UuY19zdHIoKSwgbGVuKTsKICAgICAgICBsZW4gPSBwLmRlc3RpbmF0aW9uLnNpemUoKTsKICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOwogICAgICAgIGZvdXQud3JpdGUocC5kZXN0aW5hdGlvbi5jX3N0cigpLCBsZW4pOwogICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7cC5mYXJlLCBzaXplb2YocC5mYXJlKSk7CiAgICAgICAgZm91dC53cml0ZSgoY2hhciopJmFtcDtwLnNlYXRObywgc2l6ZW9mKHAuc2VhdE5vKSk7CiAgICAgICAgZm91dC5jbG9zZSgpOwogICAgfQoKICAgIC8vIC0tLS0tLS0tLS0gQ29yZSBGdW5jdGlvbnMgLS0tLS0tLS0tLQogICAgdm9pZCBkaXNwbGF5QWxsVHJhaW5zKCkgewogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7XG49PT09PT09PT09IEF2YWlsYWJsZSBUcmFpbnMgPT09PT09PT09PVxuJnF1b3Q7OwogICAgICAgIGNvdXQgJmx0OyZsdDsgbGVmdCAmbHQ7Jmx0OyBzZXR3KDEwKSAmbHQ7Jmx0OyAmcXVvdDtUcmFpbk5vJnF1b3Q7CiAgICAgICAgICAgICAmbHQ7Jmx0OyBzZXR3KDIyKSAmbHQ7Jmx0OyAmcXVvdDtUcmFpbiBOYW1lJnF1b3Q7CiAgICAgICAgICAgICAmbHQ7Jmx0OyBzZXR3KDEyKSAmbHQ7Jmx0OyAmcXVvdDtTb3VyY2UmcXVvdDsKICAgICAgICAgICAgICZsdDsmbHQ7IHNldHcoMTIpICZsdDsmbHQ7ICZxdW90O0Rlc3QmcXVvdDsKICAgICAgICAgICAgICZsdDsmbHQ7IHNldHcoMTApICZsdDsmbHQ7ICZxdW90O1NlYXRzJnF1b3Q7CiAgICAgICAgICAgICAmbHQ7Jmx0OyBzZXR3KDEwKSAmbHQ7Jmx0OyAmcXVvdDtGYXJlJnF1b3Q7ICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7OwogICAgICAgIGNvdXQgJmx0OyZsdDsgc3RyaW5nKDc2LCAnLScpICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7OwogICAgICAgIGZvciAoYXV0byAmYW1wO3QgOiB0cmFpbnMpIHsKICAgICAgICAgICAgY291dCAmbHQ7Jmx0OyBsZWZ0ICZsdDsmbHQ7IHNldHcoMTApICZsdDsmbHQ7IHQudHJhaW5ObwogICAgICAgICAgICAgICAgICZsdDsmbHQ7IHNldHcoMjIpICZsdDsmbHQ7IHQudHJhaW5OYW1lCiAgICAgICAgICAgICAgICAgJmx0OyZsdDsgc2V0dygxMikgJmx0OyZsdDsgdC5zb3VyY2UKICAgICAgICAgICAgICAgICAmbHQ7Jmx0OyBzZXR3KDEyKSAmbHQ7Jmx0OyB0LmRlc3RpbmF0aW9uCiAgICAgICAgICAgICAgICAgJmx0OyZsdDsgc2V0dygxMCkgJmx0OyZsdDsgdC5hdmFpbGFibGVTZWF0cygpCiAgICAgICAgICAgICAgICAgJmx0OyZsdDsgc2V0dygxMCkgJmx0OyZsdDsgdC5mYXJlICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7OwogICAgICAgIH0KICAgIH0KCiAgICBUcmFpbiogZmluZFRyYWluKGludCBubykgewogICAgICAgIGZvciAoYXV0byAmYW1wO3QgOiB0cmFpbnMpCiAgICAgICAgICAgIGlmICh0LnRyYWluTm8gPT0gbm8pIHJldHVybiAmYW1wO3Q7CiAgICAgICAgcmV0dXJuIG51bGxwdHI7CiAgICB9CgogICAgdm9pZCBib29rVGlja2V0KCkgewogICAgICAgIGRpc3BsYXlBbGxUcmFpbnMoKTsKICAgICAgICBpbnQgbm87CiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtcbkVudGVyIFRyYWluIE51bWJlciB0byBib29rOiAmcXVvdDs7CiAgICAgICAgY2luICZndDsmZ3Q7IG5vOwogICAgICAgIFRyYWluICp0ID0gZmluZFRyYWluKG5vKTsKICAgICAgICBpZiAoIXQpIHsgY291dCAmbHQ7Jmx0OyAmcXVvdDtUcmFpbiBub3QgZm91bmQhXG4mcXVvdDs7IHJldHVybjsgfQogICAgICAgIGlmICh0LSZndDthdmFpbGFibGVTZWF0cygpICZsdDs9IDApIHsKICAgICAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtTb3JyeSEgTm8gc2VhdHMgYXZhaWxhYmxlLlxuJnF1b3Q7OwogICAgICAgICAgICByZXR1cm47CiAgICAgICAgfQoKICAgICAgICBQYXNzZW5nZXIgcDsKICAgICAgICBwLnBuciA9IG5leHRQTlIrKzsKICAgICAgICBwLnRyYWluTm8gPSB0LSZndDt0cmFpbk5vOwogICAgICAgIHAudHJhaW5OYW1lID0gdC0mZ3Q7dHJhaW5OYW1lOwogICAgICAgIHAuc291cmNlID0gdC0mZ3Q7c291cmNlOwogICAgICAgIHAuZGVzdGluYXRpb24gPSB0LSZndDtkZXN0aW5hdGlvbjsKICAgICAgICBwLmZhcmUgPSB0LSZndDtmYXJlOwoKICAgICAgICBjaW4uaWdub3JlKCk7CiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtFbnRlciBOYW1lOiAmcXVvdDs7CiAgICAgICAgZ2V0bGluZShjaW4sIHAubmFtZSk7CiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtFbnRlciBBZ2U6ICZxdW90OzsKICAgICAgICBjaW4gJmd0OyZndDsgcC5hZ2U7CiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtFbnRlciBHZW5kZXIgKE0vRik6ICZxdW90OzsKICAgICAgICBjaW4gJmd0OyZndDsgcC5nZW5kZXI7CiAgICAgICAgY2luLmlnbm9yZSgpOwogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7RW50ZXIgUGhvbmU6ICZxdW90OzsKICAgICAgICBnZXRsaW5lKGNpbiwgcC5waG9uZSk7CgogICAgICAgIHQtJmd0O2Jvb2tlZFNlYXRzKys7CiAgICAgICAgcC5zZWF0Tm8gPSB0LSZndDtib29rZWRTZWF0czsKCiAgICAgICAgYXBwZW5kQm9va2luZyhwKTsKICAgICAgICBzYXZlVHJhaW5zKCk7CgogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7XG49PT09PSBCb29raW5nIENvbmZpcm1lZCA9PT09PVxuJnF1b3Q7OwogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7UE5SICAgICAgIDogJnF1b3Q7ICZsdDsmbHQ7IHAucG5yICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7OwogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7TmFtZSAgICAgIDogJnF1b3Q7ICZsdDsmbHQ7IHAubmFtZSAmbHQ7Jmx0OyAmcXVvdDtcbiZxdW90OzsKICAgICAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O1RyYWluICAgICA6ICZxdW90OyAmbHQ7Jmx0OyBwLnRyYWluTmFtZSAmbHQ7Jmx0OyAmcXVvdDsgKCZxdW90OyAmbHQ7Jmx0OyBwLnRyYWluTm8gJmx0OyZsdDsgJnF1b3Q7KVxuJnF1b3Q7OwogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7Um91dGUgICAgIDogJnF1b3Q7ICZsdDsmbHQ7IHAuc291cmNlICZsdDsmbHQ7ICZxdW90OyAtJmd0OyAmcXVvdDsgJmx0OyZsdDsgcC5kZXN0aW5hdGlvbiAmbHQ7Jmx0OyAmcXVvdDtcbiZxdW90OzsKICAgICAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O1NlYXQgTm8gICA6ICZxdW90OyAmbHQ7Jmx0OyBwLnNlYXRObyAmbHQ7Jmx0OyAmcXVvdDtcbiZxdW90OzsKICAgICAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O0ZhcmUgICAgICA6IFJzLiAmcXVvdDsgJmx0OyZsdDsgcC5mYXJlICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7OwogICAgfQoKICAgIHZvaWQgY2FuY2VsVGlja2V0KCkgewogICAgICAgIGludCBwbnI7CiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtcbkVudGVyIFBOUiB0byBjYW5jZWw6ICZxdW90OzsKICAgICAgICBjaW4gJmd0OyZndDsgcG5yOwoKICAgICAgICBpZnN0cmVhbSBmaW4oYm9va2luZ0ZpbGUsIGlvczo6YmluYXJ5KTsKICAgICAgICBpZiAoIWZpbikgeyBjb3V0ICZsdDsmbHQ7ICZxdW90O05vIGJvb2tpbmdzIGZvdW5kLlxuJnF1b3Q7OyByZXR1cm47IH0KCiAgICAgICAgdmVjdG9yJmx0O1Bhc3NlbmdlciZndDsgYWxsOwogICAgICAgIGJvb2wgZm91bmQgPSBmYWxzZTsKICAgICAgICBQYXNzZW5nZXIgdGFyZ2V0OwoKICAgICAgICB3aGlsZSAoZmluLnBlZWsoKSAhPSBFT0YpIHsKICAgICAgICAgICAgUGFzc2VuZ2VyIHA7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3AucG5yLCBzaXplb2YocC5wbnIpKTsKICAgICAgICAgICAgaWYgKGZpbi5nY291bnQoKSA9PSAwKSBicmVhazsKICAgICAgICAgICAgZmluLnJlYWQoKGNoYXIqKSZhbXA7cC5hZ2UsIHNpemVvZihwLmFnZSkpOwogICAgICAgICAgICBmaW4ucmVhZCgmYW1wO3AuZ2VuZGVyLCBzaXplb2YocC5nZW5kZXIpKTsKICAgICAgICAgICAgc2l6ZV90IGxlbjsKICAgICAgICAgICAgZmluLnJlYWQoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7IHAubmFtZS5yZXNpemUobGVuKTsgZmluLnJlYWQoJmFtcDtwLm5hbWVbMF0sIGxlbik7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOyBwLnBob25lLnJlc2l6ZShsZW4pOyBmaW4ucmVhZCgmYW1wO3AucGhvbmVbMF0sIGxlbik7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3AudHJhaW5Obywgc2l6ZW9mKHAudHJhaW5ObykpOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsgcC50cmFpbk5hbWUucmVzaXplKGxlbik7IGZpbi5yZWFkKCZhbXA7cC50cmFpbk5hbWVbMF0sIGxlbik7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOyBwLnNvdXJjZS5yZXNpemUobGVuKTsgZmluLnJlYWQoJmFtcDtwLnNvdXJjZVswXSwgbGVuKTsKICAgICAgICAgICAgZmluLnJlYWQoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7IHAuZGVzdGluYXRpb24ucmVzaXplKGxlbik7IGZpbi5yZWFkKCZhbXA7cC5kZXN0aW5hdGlvblswXSwgbGVuKTsKICAgICAgICAgICAgZmluLnJlYWQoKGNoYXIqKSZhbXA7cC5mYXJlLCBzaXplb2YocC5mYXJlKSk7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3Auc2VhdE5vLCBzaXplb2YocC5zZWF0Tm8pKTsKCiAgICAgICAgICAgIGlmIChwLnBuciA9PSBwbnIgJmFtcDsmYW1wOyAhZm91bmQpIHsKICAgICAgICAgICAgICAgIGZvdW5kID0gdHJ1ZTsKICAgICAgICAgICAgICAgIHRhcmdldCA9IHA7CiAgICAgICAgICAgIH0gZWxzZSB7CiAgICAgICAgICAgICAgICBhbGwucHVzaF9iYWNrKHApOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZpbi5jbG9zZSgpOwoKICAgICAgICBpZiAoIWZvdW5kKSB7IGNvdXQgJmx0OyZsdDsgJnF1b3Q7UE5SIG5vdCBmb3VuZCFcbiZxdW90OzsgcmV0dXJuOyB9CgogICAgICAgIC8vIFJld3JpdGUgYm9va2luZ3MgZmlsZQogICAgICAgIG9mc3RyZWFtIGZvdXQoYm9va2luZ0ZpbGUsIGlvczo6YmluYXJ5IHwgaW9zOjp0cnVuYyk7CiAgICAgICAgZm9yIChhdXRvICZhbXA7cCA6IGFsbCkgewogICAgICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO3AucG5yLCBzaXplb2YocC5wbnIpKTsKICAgICAgICAgICAgZm91dC53cml0ZSgoY2hhciopJmFtcDtwLmFnZSwgc2l6ZW9mKHAuYWdlKSk7CiAgICAgICAgICAgIGZvdXQud3JpdGUoJmFtcDtwLmdlbmRlciwgc2l6ZW9mKHAuZ2VuZGVyKSk7CiAgICAgICAgICAgIHNpemVfdCBsZW4gPSBwLm5hbWUuc2l6ZSgpOwogICAgICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOyBmb3V0LndyaXRlKHAubmFtZS5jX3N0cigpLCBsZW4pOwogICAgICAgICAgICBsZW4gPSBwLnBob25lLnNpemUoKTsKICAgICAgICAgICAgZm91dC53cml0ZSgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsgZm91dC53cml0ZShwLnBob25lLmNfc3RyKCksIGxlbik7CiAgICAgICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7cC50cmFpbk5vLCBzaXplb2YocC50cmFpbk5vKSk7CiAgICAgICAgICAgIGxlbiA9IHAudHJhaW5OYW1lLnNpemUoKTsKICAgICAgICAgICAgZm91dC53cml0ZSgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsgZm91dC53cml0ZShwLnRyYWluTmFtZS5jX3N0cigpLCBsZW4pOwogICAgICAgICAgICBsZW4gPSBwLnNvdXJjZS5zaXplKCk7CiAgICAgICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7IGZvdXQud3JpdGUocC5zb3VyY2UuY19zdHIoKSwgbGVuKTsKICAgICAgICAgICAgbGVuID0gcC5kZXN0aW5hdGlvbi5zaXplKCk7CiAgICAgICAgICAgIGZvdXQud3JpdGUoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7IGZvdXQud3JpdGUocC5kZXN0aW5hdGlvbi5jX3N0cigpLCBsZW4pOwogICAgICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO3AuZmFyZSwgc2l6ZW9mKHAuZmFyZSkpOwogICAgICAgICAgICBmb3V0LndyaXRlKChjaGFyKikmYW1wO3Auc2VhdE5vLCBzaXplb2YocC5zZWF0Tm8pKTsKICAgICAgICB9CiAgICAgICAgZm91dC5jbG9zZSgpOwoKICAgICAgICAvLyBVcGRhdGUgdHJhaW4gYm9va2VkIHNlYXRzCiAgICAgICAgVHJhaW4gKnQgPSBmaW5kVHJhaW4odGFyZ2V0LnRyYWluTm8pOwogICAgICAgIGlmICh0ICZhbXA7JmFtcDsgdC0mZ3Q7Ym9va2VkU2VhdHMgJmd0OyAwKSB0LSZndDtib29rZWRTZWF0cy0tOwogICAgICAgIHNhdmVUcmFpbnMoKTsKCiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtcblRpY2tldCBDYW5jZWxsZWQgU3VjY2Vzc2Z1bGx5IVxuJnF1b3Q7OwogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7UmVmdW5kIEFtb3VudDogUnMuICZxdW90OyAmbHQ7Jmx0OyAodGFyZ2V0LmZhcmUgKiAwLjkpICZsdDsmbHQ7ICZxdW90OyAoMTAlIGNhbmNlbGxhdGlvbiBjaGFyZ2UpXG4mcXVvdDs7CiAgICB9CgogICAgdm9pZCB2aWV3Qm9va2luZ3MoKSB7CiAgICAgICAgaWZzdHJlYW0gZmluKGJvb2tpbmdGaWxlLCBpb3M6OmJpbmFyeSk7CiAgICAgICAgaWYgKCFmaW4pIHsgY291dCAmbHQ7Jmx0OyAmcXVvdDtcbk5vIGJvb2tpbmdzIHlldC5cbiZxdW90OzsgcmV0dXJuOyB9CgogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7XG49PT09PT09PT09IEFsbCBCb29raW5ncyA9PT09PT09PT09XG4mcXVvdDs7CiAgICAgICAgY291dCAmbHQ7Jmx0OyBsZWZ0ICZsdDsmbHQ7IHNldHcoOCkgJmx0OyZsdDsgJnF1b3Q7UE5SJnF1b3Q7CiAgICAgICAgICAgICAmbHQ7Jmx0OyBzZXR3KDE4KSAmbHQ7Jmx0OyAmcXVvdDtOYW1lJnF1b3Q7CiAgICAgICAgICAgICAmbHQ7Jmx0OyBzZXR3KDgpICZsdDsmbHQ7ICZxdW90O0FnZSZxdW90OwogICAgICAgICAgICAgJmx0OyZsdDsgc2V0dyg2KSAmbHQ7Jmx0OyAmcXVvdDtHZW4mcXVvdDsKICAgICAgICAgICAgICZsdDsmbHQ7IHNldHcoMjIpICZsdDsmbHQ7ICZxdW90O1RyYWluJnF1b3Q7CiAgICAgICAgICAgICAmbHQ7Jmx0OyBzZXR3KDgpICZsdDsmbHQ7ICZxdW90O1NlYXQmcXVvdDsKICAgICAgICAgICAgICZsdDsmbHQ7IHNldHcoMTApICZsdDsmbHQ7ICZxdW90O0ZhcmUmcXVvdDsgJmx0OyZsdDsgJnF1b3Q7XG4mcXVvdDs7CiAgICAgICAgY291dCAmbHQ7Jmx0OyBzdHJpbmcoODAsICctJykgJmx0OyZsdDsgJnF1b3Q7XG4mcXVvdDs7CgogICAgICAgIGJvb2wgYW55ID0gZmFsc2U7CiAgICAgICAgd2hpbGUgKGZpbi5wZWVrKCkgIT0gRU9GKSB7CiAgICAgICAgICAgIFBhc3NlbmdlciBwOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtwLnBuciwgc2l6ZW9mKHAucG5yKSk7CiAgICAgICAgICAgIGlmIChmaW4uZ2NvdW50KCkgPT0gMCkgYnJlYWs7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3AuYWdlLCBzaXplb2YocC5hZ2UpKTsKICAgICAgICAgICAgZmluLnJlYWQoJmFtcDtwLmdlbmRlciwgc2l6ZW9mKHAuZ2VuZGVyKSk7CiAgICAgICAgICAgIHNpemVfdCBsZW47CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOyBwLm5hbWUucmVzaXplKGxlbik7IGZpbi5yZWFkKCZhbXA7cC5uYW1lWzBdLCBsZW4pOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsgcC5waG9uZS5yZXNpemUobGVuKTsgZmluLnJlYWQoJmFtcDtwLnBob25lWzBdLCBsZW4pOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtwLnRyYWluTm8sIHNpemVvZihwLnRyYWluTm8pKTsKICAgICAgICAgICAgZmluLnJlYWQoKGNoYXIqKSZhbXA7bGVuLCBzaXplb2YobGVuKSk7IHAudHJhaW5OYW1lLnJlc2l6ZShsZW4pOyBmaW4ucmVhZCgmYW1wO3AudHJhaW5OYW1lWzBdLCBsZW4pOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtsZW4sIHNpemVvZihsZW4pKTsgcC5zb3VyY2UucmVzaXplKGxlbik7IGZpbi5yZWFkKCZhbXA7cC5zb3VyY2VbMF0sIGxlbik7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO2xlbiwgc2l6ZW9mKGxlbikpOyBwLmRlc3RpbmF0aW9uLnJlc2l6ZShsZW4pOyBmaW4ucmVhZCgmYW1wO3AuZGVzdGluYXRpb25bMF0sIGxlbik7CiAgICAgICAgICAgIGZpbi5yZWFkKChjaGFyKikmYW1wO3AuZmFyZSwgc2l6ZW9mKHAuZmFyZSkpOwogICAgICAgICAgICBmaW4ucmVhZCgoY2hhciopJmFtcDtwLnNlYXRObywgc2l6ZW9mKHAuc2VhdE5vKSk7CgogICAgICAgICAgICBjb3V0ICZsdDsmbHQ7IGxlZnQgJmx0OyZsdDsgc2V0dyg4KSAmbHQ7Jmx0OyBwLnBucgogICAgICAgICAgICAgICAgICZsdDsmbHQ7IHNldHcoMTgpICZsdDsmbHQ7IHAubmFtZQogICAgICAgICAgICAgICAgICZsdDsmbHQ7IHNldHcoOCkgJmx0OyZsdDsgcC5hZ2UKICAgICAgICAgICAgICAgICAmbHQ7Jmx0OyBzZXR3KDYpICZsdDsmbHQ7IHAuZ2VuZGVyCiAgICAgICAgICAgICAgICAgJmx0OyZsdDsgc2V0dygyMikgJmx0OyZsdDsgKHAudHJhaW5OYW1lICsgJnF1b3Q7ICgmcXVvdDsgKyB0b19zdHJpbmcocC50cmFpbk5vKSArICZxdW90OykmcXVvdDspCiAgICAgICAgICAgICAgICAgJmx0OyZsdDsgc2V0dyg4KSAmbHQ7Jmx0OyBwLnNlYXRObwogICAgICAgICAgICAgICAgICZsdDsmbHQ7IHNldHcoMTApICZsdDsmbHQ7IHAuZmFyZSAmbHQ7Jmx0OyAmcXVvdDtcbiZxdW90OzsKICAgICAgICAgICAgYW55ID0gdHJ1ZTsKICAgICAgICB9CiAgICAgICAgZmluLmNsb3NlKCk7CiAgICAgICAgaWYgKCFhbnkpIGNvdXQgJmx0OyZsdDsgJnF1b3Q7Tm8gYm9va2luZ3MgZm91bmQuXG4mcXVvdDs7CiAgICB9CgogICAgdm9pZCBjaGVja0F2YWlsYWJpbGl0eSgpIHsKICAgICAgICBpbnQgbm87CiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtcbkVudGVyIFRyYWluIE51bWJlcjogJnF1b3Q7OwogICAgICAgIGNpbiAmZ3Q7Jmd0OyBubzsKICAgICAgICBUcmFpbiAqdCA9IGZpbmRUcmFpbihubyk7CiAgICAgICAgaWYgKCF0KSB7IGNvdXQgJmx0OyZsdDsgJnF1b3Q7VHJhaW4gbm90IGZvdW5kIVxuJnF1b3Q7OyByZXR1cm47IH0KICAgICAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O1xuVHJhaW4gICA6ICZxdW90OyAmbHQ7Jmx0OyB0LSZndDt0cmFpbk5hbWUgJmx0OyZsdDsgJnF1b3Q7XG4mcXVvdDs7CiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtSb3V0ZSAgIDogJnF1b3Q7ICZsdDsmbHQ7IHQtJmd0O3NvdXJjZSAmbHQ7Jmx0OyAmcXVvdDsgLSZndDsgJnF1b3Q7ICZsdDsmbHQ7IHQtJmd0O2Rlc3RpbmF0aW9uICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7OwogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7VG90YWwgICA6ICZxdW90OyAmbHQ7Jmx0OyB0LSZndDt0b3RhbFNlYXRzICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7OwogICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7Qm9va2VkICA6ICZxdW90OyAmbHQ7Jmx0OyB0LSZndDtib29rZWRTZWF0cyAmbHQ7Jmx0OyAmcXVvdDtcbiZxdW90OzsKICAgICAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O0F2YWlsYWJsZTogJnF1b3Q7ICZsdDsmbHQ7IHQtJmd0O2F2YWlsYWJsZVNlYXRzKCkgJmx0OyZsdDsgJnF1b3Q7XG4mcXVvdDs7CiAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtGYXJlICAgIDogUnMuICZxdW90OyAmbHQ7Jmx0OyB0LSZndDtmYXJlICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7OwogICAgfQp9OwoKLy8gLS0tLS0tLS0tLS0tLS0tLSBNZW51IC0tLS0tLS0tLS0tLS0tLS0Kdm9pZCBzaG93TWVudSgpIHsKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7XG7ilZTilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZdcbiZxdW90OzsKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q74pWRICAgIFJBSUxXQVkgUkVTRVJWQVRJT04gU1lTVEVNICAgICAgICAgIOKVkVxuJnF1b3Q7OwogICAgY291dCAmbHQ7Jmx0OyAmcXVvdDvilaDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilZDilaNcbiZxdW90OzsKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q74pWRICAxLiBWaWV3IEFsbCBUcmFpbnMgICAgICAgICAgICAgICAgICAgIOKVkVxuJnF1b3Q7OwogICAgY291dCAmbHQ7Jmx0OyAmcXVvdDvilZEgIDIuIEJvb2sgVGlja2V0ICAgICAgICAgICAgICAgICAgICAgICAg4pWRXG4mcXVvdDs7CiAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O+KVkSAgMy4gQ2FuY2VsIFRpY2tldCAgICAgICAgICAgICAgICAgICAgICDilZFcbiZxdW90OzsKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q74pWRICA0LiBDaGVjayBTZWF0IEF2YWlsYWJpbGl0eSAgICAgICAgICAgIOKVkVxuJnF1b3Q7OwogICAgY291dCAmbHQ7Jmx0OyAmcXVvdDvilZEgIDUuIFZpZXcgQWxsIEJvb2tpbmdzICAgICAgICAgICAgICAgICAg4pWRXG4mcXVvdDs7CiAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O+KVkSAgNi4gRXhpdCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDilZFcbiZxdW90OzsKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q74pWa4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWQ4pWdXG4mcXVvdDs7CiAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O0VudGVyIHlvdXIgY2hvaWNlOiAmcXVvdDs7Cn0KCmludCBtYWluKCkgewogICAgUmFpbHdheVN5c3RlbSBzeXN0ZW07CiAgICBpbnQgY2hvaWNlOwoKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7XG49PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4mcXVvdDs7CiAgICBjb3V0ICZsdDsmbHQ7ICZxdW90OyBXZWxjb21lIHRvIFJhaWx3YXkgUmVzZXJ2YXRpb24gU3lzdGVtICBcbiZxdW90OzsKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuJnF1b3Q7OwoKICAgIGRvIHsKICAgICAgICBzaG93TWVudSgpOwogICAgICAgIGNpbiAmZ3Q7Jmd0OyBjaG9pY2U7CgogICAgICAgIHN3aXRjaCAoY2hvaWNlKSB7CiAgICAgICAgICAgIGNhc2UgMTogc3lzdGVtLmRpc3BsYXlBbGxUcmFpbnMoKTsgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMjogc3lzdGVtLmJvb2tUaWNrZXQoKTsgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgMzogc3lzdGVtLmNhbmNlbFRpY2tldCgpOyBicmVhazsKICAgICAgICAgICAgY2FzZSA0OiBzeXN0ZW0uY2hlY2tBdmFpbGFiaWxpdHkoKTsgYnJlYWs7CiAgICAgICAgICAgIGNhc2UgNTogc3lzdGVtLnZpZXdCb29raW5ncygpOyBicmVhazsKICAgICAgICAgICAgY2FzZSA2OgogICAgICAgICAgICAgICAgY291dCAmbHQ7Jmx0OyAmcXVvdDtcblRoYW5rIHlvdSBmb3IgdXNpbmcgUmFpbHdheSBSZXNlcnZhdGlvbiBTeXN0ZW0hXG4mcXVvdDs7CiAgICAgICAgICAgICAgICBicmVhazsKICAgICAgICAgICAgZGVmYXVsdDoKICAgICAgICAgICAgICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7XG5JbnZhbGlkIGNob2ljZSEgVHJ5IGFnYWluLlxuJnF1b3Q7OwogICAgICAgIH0KICAgIH0gd2hpbGUgKGNob2ljZSAhPSA2KTsKCiAgICByZXR1cm4gMDsKfQ==
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <vector>
#include <cstring>
using namespace std;
// ---------------- Train Class ----------------
class Train {
public:
int trainNo;
string trainName;
string source;
string destination;
int totalSeats;
int bookedSeats;
float fare;
Train() : trainNo(0), totalSeats(0), bookedSeats(0), fare(0) {}
Train(int no, string name, string src, string dest, int seats, float f)
: trainNo(no), trainName(name), source(src),
destination(dest), totalSeats(seats), bookedSeats(0), fare(f) {}
int availableSeats() const { return totalSeats - bookedSeats; }
};
// ---------------- Passenger Class ----------------
class Passenger {
public:
int pnr;
string name;
int age;
char gender;
string phone;
int trainNo;
string trainName;
string source;
string destination;
float fare;
int seatNo;
Passenger() : pnr(0), age(0), gender('M'), trainNo(0), fare(0), seatNo(0) {}
};
// ---------------- Railway System ----------------
class RailwaySystem {
private:
vector<Train> trains;
const string trainFile = "trains.dat";
const string bookingFile = "bookings.dat";
int nextPNR;
public:
RailwaySystem() {
loadTrains();
if (trains.empty()) {
initializeTrains();
}
loadNextPNR();
}
// Initialize default trains
void initializeTrains() {
trains.push_back(Train(12345, "Rajdhani Express", "Delhi", "Mumbai", 100, 2500.0));
trains.push_back(Train(12346, "Shatabdi Express", "Delhi", "Bhopal", 80, 1200.0));
trains.push_back(Train(12347, "Duronto Express", "Mumbai", "Chennai", 120, 1800.0));
trains.push_back(Train(12348, "Garib Rath", "Kolkata", "Delhi", 150, 900.0));
trains.push_back(Train(12349, "Chennai Express", "Chennai", "Mumbai", 110, 1500.0));
saveTrains();
}
// ---------- File Handling ----------
void saveTrains() {
ofstream fout(trainFile, ios::binary);
size_t size = trains.size();
fout.write((char*)&size, sizeof(size));
for (auto &t : trains) {
fout.write((char*)&t.trainNo, sizeof(t.trainNo));
size_t len = t.trainName.size();
fout.write((char*)&len, sizeof(len));
fout.write(t.trainName.c_str(), len);
len = t.source.size();
fout.write((char*)&len, sizeof(len));
fout.write(t.source.c_str(), len);
len = t.destination.size();
fout.write((char*)&len, sizeof(len));
fout.write(t.destination.c_str(), len);
fout.write((char*)&t.totalSeats, sizeof(t.totalSeats));
fout.write((char*)&t.bookedSeats, sizeof(t.bookedSeats));
fout.write((char*)&t.fare, sizeof(t.fare));
}
fout.close();
}
void loadTrains() {
ifstream fin(trainFile, ios::binary);
if (!fin) return;
size_t size;
fin.read((char*)&size, sizeof(size));
for (size_t i = 0; i < size; i++) {
Train t;
fin.read((char*)&t.trainNo, sizeof(t.trainNo));
size_t len;
fin.read((char*)&len, sizeof(len));
t.trainName.resize(len);
fin.read(&t.trainName[0], len);
fin.read((char*)&len, sizeof(len));
t.source.resize(len);
fin.read(&t.source[0], len);
fin.read((char*)&len, sizeof(len));
t.destination.resize(len);
fin.read(&t.destination[0], len);
fin.read((char*)&t.totalSeats, sizeof(t.totalSeats));
fin.read((char*)&t.bookedSeats, sizeof(t.bookedSeats));
fin.read((char*)&t.fare, sizeof(t.fare));
trains.push_back(t);
}
fin.close();
}
void loadNextPNR() {
ifstream fin(bookingFile, ios::binary);
nextPNR = 1000;
if (!fin) return;
fin.seekg(0, ios::end);
if (fin.tellg() == 0) { fin.close(); return; }
fin.seekg(0);
while (fin.peek() != EOF) {
int pnr;
fin.read((char*)&pnr, sizeof(pnr));
if (fin.gcount() == 0) break;
nextPNR = pnr + 1;
// skip remaining passenger data
int age, trainNo, seatNo;
char gender;
float fare;
fin.read((char*)&age, sizeof(age));
fin.read(&gender, sizeof(gender));
size_t len;
fin.read((char*)&len, sizeof(len)); fin.seekg(len, ios::cur); // name
fin.read((char*)&len, sizeof(len)); fin.seekg(len, ios::cur); // phone
fin.read((char*)&trainNo, sizeof(trainNo));
fin.read((char*)&len, sizeof(len)); fin.seekg(len, ios::cur); // trainName
fin.read((char*)&len, sizeof(len)); fin.seekg(len, ios::cur); // source
fin.read((char*)&len, sizeof(len)); fin.seekg(len, ios::cur); // dest
fin.read((char*)&fare, sizeof(fare));
fin.read((char*)&seatNo, sizeof(seatNo));
}
fin.close();
}
void appendBooking(const Passenger &p) {
ofstream fout(bookingFile, ios::binary | ios::app);
fout.write((char*)&p.pnr, sizeof(p.pnr));
fout.write((char*)&p.age, sizeof(p.age));
fout.write(&p.gender, sizeof(p.gender));
size_t len = p.name.size();
fout.write((char*)&len, sizeof(len));
fout.write(p.name.c_str(), len);
len = p.phone.size();
fout.write((char*)&len, sizeof(len));
fout.write(p.phone.c_str(), len);
fout.write((char*)&p.trainNo, sizeof(p.trainNo));
len = p.trainName.size();
fout.write((char*)&len, sizeof(len));
fout.write(p.trainName.c_str(), len);
len = p.source.size();
fout.write((char*)&len, sizeof(len));
fout.write(p.source.c_str(), len);
len = p.destination.size();
fout.write((char*)&len, sizeof(len));
fout.write(p.destination.c_str(), len);
fout.write((char*)&p.fare, sizeof(p.fare));
fout.write((char*)&p.seatNo, sizeof(p.seatNo));
fout.close();
}
// ---------- Core Functions ----------
void displayAllTrains() {
cout << "\n========== Available Trains ==========\n";
cout << left << setw(10) << "TrainNo"
<< setw(22) << "Train Name"
<< setw(12) << "Source"
<< setw(12) << "Dest"
<< setw(10) << "Seats"
<< setw(10) << "Fare" << "\n";
cout << string(76, '-') << "\n";
for (auto &t : trains) {
cout << left << setw(10) << t.trainNo
<< setw(22) << t.trainName
<< setw(12) << t.source
<< setw(12) << t.destination
<< setw(10) << t.availableSeats()
<< setw(10) << t.fare << "\n";
}
}
Train* findTrain(int no) {
for (auto &t : trains)
if (t.trainNo == no) return &t;
return nullptr;
}
void bookTicket() {
displayAllTrains();
int no;
cout << "\nEnter Train Number to book: ";
cin >> no;
Train *t = findTrain(no);
if (!t) { cout << "Train not found!\n"; return; }
if (t->availableSeats() <= 0) {
cout << "Sorry! No seats available.\n";
return;
}
Passenger p;
p.pnr = nextPNR++;
p.trainNo = t->trainNo;
p.trainName = t->trainName;
p.source = t->source;
p.destination = t->destination;
p.fare = t->fare;
cin.ignore();
cout << "Enter Name: ";
getline(cin, p.name);
cout << "Enter Age: ";
cin >> p.age;
cout << "Enter Gender (M/F): ";
cin >> p.gender;
cin.ignore();
cout << "Enter Phone: ";
getline(cin, p.phone);
t->bookedSeats++;
p.seatNo = t->bookedSeats;
appendBooking(p);
saveTrains();
cout << "\n===== Booking Confirmed =====\n";
cout << "PNR : " << p.pnr << "\n";
cout << "Name : " << p.name << "\n";
cout << "Train : " << p.trainName << " (" << p.trainNo << ")\n";
cout << "Route : " << p.source << " -> " << p.destination << "\n";
cout << "Seat No : " << p.seatNo << "\n";
cout << "Fare : Rs. " << p.fare << "\n";
}
void cancelTicket() {
int pnr;
cout << "\nEnter PNR to cancel: ";
cin >> pnr;
ifstream fin(bookingFile, ios::binary);
if (!fin) { cout << "No bookings found.\n"; return; }
vector<Passenger> all;
bool found = false;
Passenger target;
while (fin.peek() != EOF) {
Passenger p;
fin.read((char*)&p.pnr, sizeof(p.pnr));
if (fin.gcount() == 0) break;
fin.read((char*)&p.age, sizeof(p.age));
fin.read(&p.gender, sizeof(p.gender));
size_t len;
fin.read((char*)&len, sizeof(len)); p.name.resize(len); fin.read(&p.name[0], len);
fin.read((char*)&len, sizeof(len)); p.phone.resize(len); fin.read(&p.phone[0], len);
fin.read((char*)&p.trainNo, sizeof(p.trainNo));
fin.read((char*)&len, sizeof(len)); p.trainName.resize(len); fin.read(&p.trainName[0], len);
fin.read((char*)&len, sizeof(len)); p.source.resize(len); fin.read(&p.source[0], len);
fin.read((char*)&len, sizeof(len)); p.destination.resize(len); fin.read(&p.destination[0], len);
fin.read((char*)&p.fare, sizeof(p.fare));
fin.read((char*)&p.seatNo, sizeof(p.seatNo));
if (p.pnr == pnr && !found) {
found = true;
target = p;
} else {
all.push_back(p);
}
}
fin.close();
if (!found) { cout << "PNR not found!\n"; return; }
// Rewrite bookings file
ofstream fout(bookingFile, ios::binary | ios::trunc);
for (auto &p : all) {
fout.write((char*)&p.pnr, sizeof(p.pnr));
fout.write((char*)&p.age, sizeof(p.age));
fout.write(&p.gender, sizeof(p.gender));
size_t len = p.name.size();
fout.write((char*)&len, sizeof(len)); fout.write(p.name.c_str(), len);
len = p.phone.size();
fout.write((char*)&len, sizeof(len)); fout.write(p.phone.c_str(), len);
fout.write((char*)&p.trainNo, sizeof(p.trainNo));
len = p.trainName.size();
fout.write((char*)&len, sizeof(len)); fout.write(p.trainName.c_str(), len);
len = p.source.size();
fout.write((char*)&len, sizeof(len)); fout.write(p.source.c_str(), len);
len = p.destination.size();
fout.write((char*)&len, sizeof(len)); fout.write(p.destination.c_str(), len);
fout.write((char*)&p.fare, sizeof(p.fare));
fout.write((char*)&p.seatNo, sizeof(p.seatNo));
}
fout.close();
// Update train booked seats
Train *t = findTrain(target.trainNo);
if (t && t->bookedSeats > 0) t->bookedSeats--;
saveTrains();
cout << "\nTicket Cancelled Successfully!\n";
cout << "Refund Amount: Rs. " << (target.fare * 0.9) << " (10% cancellation charge)\n";
}
void viewBookings() {
ifstream fin(bookingFile, ios::binary);
if (!fin) { cout << "\nNo bookings yet.\n"; return; }
cout << "\n========== All Bookings ==========\n";
cout << left << setw(8) << "PNR"
<< setw(18) << "Name"
<< setw(8) << "Age"
<< setw(6) << "Gen"
<< setw(22) << "Train"
<< setw(8) << "Seat"
<< setw(10) << "Fare" << "\n";
cout << string(80, '-') << "\n";
bool any = false;
while (fin.peek() != EOF) {
Passenger p;
fin.read((char*)&p.pnr, sizeof(p.pnr));
if (fin.gcount() == 0) break;
fin.read((char*)&p.age, sizeof(p.age));
fin.read(&p.gender, sizeof(p.gender));
size_t len;
fin.read((char*)&len, sizeof(len)); p.name.resize(len); fin.read(&p.name[0], len);
fin.read((char*)&len, sizeof(len)); p.phone.resize(len); fin.read(&p.phone[0], len);
fin.read((char*)&p.trainNo, sizeof(p.trainNo));
fin.read((char*)&len, sizeof(len)); p.trainName.resize(len); fin.read(&p.trainName[0], len);
fin.read((char*)&len, sizeof(len)); p.source.resize(len); fin.read(&p.source[0], len);
fin.read((char*)&len, sizeof(len)); p.destination.resize(len); fin.read(&p.destination[0], len);
fin.read((char*)&p.fare, sizeof(p.fare));
fin.read((char*)&p.seatNo, sizeof(p.seatNo));
cout << left << setw(8) << p.pnr
<< setw(18) << p.name
<< setw(8) << p.age
<< setw(6) << p.gender
<< setw(22) << (p.trainName + " (" + to_string(p.trainNo) + ")")
<< setw(8) << p.seatNo
<< setw(10) << p.fare << "\n";
any = true;
}
fin.close();
if (!any) cout << "No bookings found.\n";
}
void checkAvailability() {
int no;
cout << "\nEnter Train Number: ";
cin >> no;
Train *t = findTrain(no);
if (!t) { cout << "Train not found!\n"; return; }
cout << "\nTrain : " << t->trainName << "\n";
cout << "Route : " << t->source << " -> " << t->destination << "\n";
cout << "Total : " << t->totalSeats << "\n";
cout << "Booked : " << t->bookedSeats << "\n";
cout << "Available: " << t->availableSeats() << "\n";
cout << "Fare : Rs. " << t->fare << "\n";
}
};
// ---------------- Menu ----------------
void showMenu() {
cout << "\n╔════════════════════════════════════════╗\n";
cout << "║ RAILWAY RESERVATION SYSTEM ║\n";
cout << "╠════════════════════════════════════════╣\n";
cout << "║ 1. View All Trains ║\n";
cout << "║ 2. Book Ticket ║\n";
cout << "║ 3. Cancel Ticket ║\n";
cout << "║ 4. Check Seat Availability ║\n";
cout << "║ 5. View All Bookings ║\n";
cout << "║ 6. Exit ║\n";
cout << "╚════════════════════════════════════════╝\n";
cout << "Enter your choice: ";
}
int main() {
RailwaySystem system;
int choice;
cout << "\n========================================\n";
cout << " Welcome to Railway Reservation System \n";
cout << "========================================\n";
do {
showMenu();
cin >> choice;
switch (choice) {
case 1: system.displayAllTrains(); break;
case 2: system.bookTicket(); break;
case 3: system.cancelTicket(); break;
case 4: system.checkAvailability(); break;
case 5: system.viewBookings(); break;
case 6:
cout << "\nThank you for using Railway Reservation System!\n";
break;
default:
cout << "\nInvalid choice! Try again.\n";
}
} while (choice != 6);
return 0;
}