I2luY2x1ZGUgJmx0O2JpdHMvc3RkYysrLmgmZ3Q7CnVzaW5nIG5hbWVzcGFjZSBzdGQ7CgplbnVtIFN0YXR1cyB7IEFUX09SSUdJTiwgSU5fVFJBTlNJVCwgT1VUX0ZPUl9ERUxJVkVSWSwgREVMSVZFUkVEIH07CgpzdHJ1Y3QgUGFyY2VsIHsKICAgIHN0cmluZyB0cmFja2luZzsKICAgIHN0cmluZyBzZW5kZXIsIHJlY2VpdmVyOwogICAgc3RyaW5nIG9yaWdpbiwgZGVzdGluYXRpb247CiAgICBkb3VibGUgd2VpZ2h0S2d7fTsKICAgIGludCBwb3N0YWdle307CiAgICBpbnQgZGVjbGFyZWRWYWx1ZXt9OwogICAgU3RhdHVzIHN0YXR1c3t9OwogICAgc3RyaW5nIGFjY2VwdERhdGU7CiAgICBzdHJpbmcgZGVsaXZlckRhdGU7IC8vIOC4reC4suC4iOC4p+C5iOC4suC4h+C4luC5ieC4suC4ouC4seC4h+C5hOC4oeC5iOC4quC5iOC4h+C4quC4s+C5gOC4o+C5h+C4iAp9OwoKLyogLS0tLS0tLS0tLSBVdGlsaXRpZXMgLS0tLS0tLS0tLSAqLwpzdHJpbmcgc3RhdHVzTmFtZShTdGF0dXMgcyl7CiAgICBzd2l0Y2gocyl7CiAgICAgICAgY2FzZSBBVF9PUklHSU46IHJldHVybiAmcXVvdDtBVF9PUklHSU4mcXVvdDs7CiAgICAgICAgY2FzZSBJTl9UUkFOU0lUOiByZXR1cm4gJnF1b3Q7SU5fVFJBTlNJVCZxdW90OzsKICAgICAgICBjYXNlIE9VVF9GT1JfREVMSVZFUlk6IHJldHVybiAmcXVvdDtPVVRfRk9SX0RFTElWRVJZJnF1b3Q7OwogICAgICAgIGNhc2UgREVMSVZFUkVEOiByZXR1cm4gJnF1b3Q7REVMSVZFUkVEJnF1b3Q7OwogICAgfQogICAgcmV0dXJuICZxdW90Oz8mcXVvdDs7Cn0KCnZvaWQgcHJpbnRSb3coY29uc3QgUGFyY2VsJmFtcDsgcCl7CiAgICBjb3V0ICZsdDsmbHQ7IGxlZnQKICAgICAgICAgJmx0OyZsdDsgc2V0dygxMykgJmx0OyZsdDsgcC50cmFja2luZwogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDEyKSAmbHQ7Jmx0OyBwLnNlbmRlci5zdWJzdHIoMCwxMCkKICAgICAgICAgJmx0OyZsdDsgc2V0dygxMikgJmx0OyZsdDsgcC5yZWNlaXZlci5zdWJzdHIoMCwxMCkKICAgICAgICAgJmx0OyZsdDsgc2V0dyg4KSAgJmx0OyZsdDsgcC5vcmlnaW4KICAgICAgICAgJmx0OyZsdDsgc2V0dyg4KSAgJmx0OyZsdDsgcC5kZXN0aW5hdGlvbgogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDYpICAmbHQ7Jmx0OyBmaXhlZCAmbHQ7Jmx0OyBzZXRwcmVjaXNpb24oMSkgJmx0OyZsdDsgcC53ZWlnaHRLZwogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDcpICAmbHQ7Jmx0OyBwLnBvc3RhZ2UKICAgICAgICAgJmx0OyZsdDsgc2V0dyg4KSAgJmx0OyZsdDsgcC5kZWNsYXJlZFZhbHVlCiAgICAgICAgICZsdDsmbHQ7IHNldHcoMTkpICZsdDsmbHQ7IHN0YXR1c05hbWUocC5zdGF0dXMpCiAgICAgICAgICZsdDsmbHQ7IHNldHcoMTIpICZsdDsmbHQ7IHAuYWNjZXB0RGF0ZQogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDEyKSAmbHQ7Jmx0OyAocC5kZWxpdmVyRGF0ZS5lbXB0eSgpID8gJnF1b3Q7LSZxdW90OyA6IHAuZGVsaXZlckRhdGUpCiAgICAgICAgICZsdDsmbHQ7ICZxdW90O1xuJnF1b3Q7Owp9Cgp2b2lkIHByaW50VGFibGUoY29uc3QgdmVjdG9yJmx0O1BhcmNlbCZndDsmYW1wOyB2KXsKICAgIGNvdXQgJmx0OyZsdDsgbGVmdAogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDEzKSAmbHQ7Jmx0OyAmcXVvdDtUcmFja2luZyZxdW90OwogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDEyKSAmbHQ7Jmx0OyAmcXVvdDtTZW5kZXImcXVvdDsKICAgICAgICAgJmx0OyZsdDsgc2V0dygxMikgJmx0OyZsdDsgJnF1b3Q7UmVjZWl2ZXImcXVvdDsKICAgICAgICAgJmx0OyZsdDsgc2V0dyg4KSAgJmx0OyZsdDsgJnF1b3Q7RnJvbSZxdW90OwogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDgpICAmbHQ7Jmx0OyAmcXVvdDtUbyZxdW90OwogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDYpICAmbHQ7Jmx0OyAmcXVvdDtLZyZxdW90OwogICAgICAgICAmbHQ7Jmx0OyBzZXR3KDcpICAmbHQ7Jmx0OyAmcXVvdDtGZWUmcXVvdDsKICAgICAgICAgJmx0OyZsdDsgc2V0dyg4KSAgJmx0OyZsdDsgJnF1b3Q7VmFsdWUmcXVvdDsKICAgICAgICAgJmx0OyZsdDsgc2V0dygxOSkgJmx0OyZsdDsgJnF1b3Q7U3RhdHVzJnF1b3Q7CiAgICAgICAgICZsdDsmbHQ7IHNldHcoMTIpICZsdDsmbHQ7ICZxdW90O0FjY2VwdERhdGUmcXVvdDsKICAgICAgICAgJmx0OyZsdDsgc2V0dygxMikgJmx0OyZsdDsgJnF1b3Q7RGVsaXZlckRhdGUmcXVvdDsgJmx0OyZsdDsgJnF1b3Q7XG4mcXVvdDs7CiAgICBjb3V0ICZsdDsmbHQ7IHN0cmluZygxMTcsJy0nKSAmbHQ7Jmx0OyAmcXVvdDtcbiZxdW90OzsKICAgIGZvciAoYXV0byAmYW1wO3AgOiB2KSBwcmludFJvdyhwKTsKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7XG4mcXVvdDs7Cn0KCi8qIC0tLS0tLS0tLS0gU2FtcGxlIERhdGEgKDEwIOC4o+C4suC4ouC4geC4suC4oykgLS0tLS0tLS0tLSAqLwp2ZWN0b3ImbHQ7UGFyY2VsJmd0OyBzYW1wbGVEYXRhKCl7CiAgICByZXR1cm4gewogICAgICAgIHsmcXVvdDtUSDAxMDAwMSZxdW90OywgJnF1b3Q7U29tY2hhaSZxdW90OywgICZxdW90O0FvciZxdW90OywgICAgICAmcXVvdDtCS0smcXVvdDssJnF1b3Q7Q05YJnF1b3Q7LCAxLjIsICA2MCwgMzAwMCwgSU5fVFJBTlNJVCwgICAgICAgICZxdW90OzIwMjUtMTAtMjAmcXVvdDssICZxdW90OyZxdW90O30sCiAgICAgICAgeyZxdW90O1RIMDEwMDA5JnF1b3Q7LCAmcXVvdDtNYXkmcXVvdDssICAgICAgJnF1b3Q7VG9uJnF1b3Q7LCAgICAgICZxdW90O0JLSyZxdW90OywmcXVvdDtIS1QmcXVvdDssIDIuMCwgMTEwLCAyNTAwLCBBVF9PUklHSU4sICAgICAgICAgJnF1b3Q7MjAyNS0xMC0yMiZxdW90OywgJnF1b3Q7JnF1b3Q7fSwKICAgICAgICB7JnF1b3Q7VEgwMTAwMDQmcXVvdDssICZxdW90O0phbmUmcXVvdDssICAgICAmcXVvdDtCZWFtJnF1b3Q7LCAgICAgJnF1b3Q7Q05YJnF1b3Q7LCZxdW90O0JLSyZxdW90OywgMC41LCAgNDUsIDEyMDAsIE9VVF9GT1JfREVMSVZFUlksICAmcXVvdDsyMDI1LTEwLTE4JnF1b3Q7LCAmcXVvdDsmcXVvdDt9LAogICAgICAgIHsmcXVvdDtUSDAxMDAwMiZxdW90OywgJnF1b3Q7UG9uZCZxdW90OywgICAgICZxdW90O01pbnQmcXVvdDssICAgICAmcXVvdDtCS0smcXVvdDssJnF1b3Q7S0tOJnF1b3Q7LCAzLjQsIDE2MCwgNDUwMCwgSU5fVFJBTlNJVCwgICAgICAgICZxdW90OzIwMjUtMTAtMTkmcXVvdDssICZxdW90OyZxdW90O30sCiAgICAgICAgeyZxdW90O1RIMDEwMDA2JnF1b3Q7LCAmcXVvdDtWaWV3JnF1b3Q7LCAgICAgJnF1b3Q7TGlubiZxdW90OywgICAgICZxdW90O0hLVCZxdW90OywmcXVvdDtCS0smcXVvdDssIDAuOCwgIDU1LCAgODAwLCBERUxJVkVSRUQsICAgICAgICAgJnF1b3Q7MjAyNS0xMC0xMCZxdW90OywgJnF1b3Q7MjAyNS0xMC0xMyZxdW90O30sCiAgICAgICAgeyZxdW90O1RIMDEwMDA3JnF1b3Q7LCAmcXVvdDtCYW5rJnF1b3Q7LCAgICAgJnF1b3Q7R2FtZSZxdW90OywgICAgICZxdW90O0tLTiZxdW90OywmcXVvdDtCS0smcXVvdDssIDEuMCwgIDYwLCAyMDAwLCBJTl9UUkFOU0lULCAgICAgICAgJnF1b3Q7MjAyNS0xMC0yMSZxdW90OywgJnF1b3Q7JnF1b3Q7fSwKICAgICAgICB7JnF1b3Q7VEgwMTAwMDMmcXVvdDssICZxdW90O05vb24mcXVvdDssICAgICAmcXVvdDtNaGVlJnF1b3Q7LCAgICAgJnF1b3Q7QktLJnF1b3Q7LCZxdW90O0NUSSZxdW90OywgNS4yLCAyMjAsIDcwMDAsIEFUX09SSUdJTiwgICAgICAgICAmcXVvdDsyMDI1LTEwLTIzJnF1b3Q7LCAmcXVvdDsmcXVvdDt9LAogICAgICAgIHsmcXVvdDtUSDAxMDAxMCZxdW90OywgJnF1b3Q7UG9wJnF1b3Q7LCAgICAgICZxdW90O0ZvbiZxdW90OywgICAgICAmcXVvdDtDTlgmcXVvdDssJnF1b3Q7Q1RJJnF1b3Q7LCAwLjQsICA0MCwgIDUwMCwgREVMSVZFUkVELCAgICAgICAgICZxdW90OzIwMjUtMTAtMDgmcXVvdDssICZxdW90OzIwMjUtMTAtMTEmcXVvdDt9LAogICAgICAgIHsmcXVvdDtUSDAxMDAwOCZxdW90OywgJnF1b3Q7VGxlJnF1b3Q7LCAgICAgICZxdW90O051bmUmcXVvdDssICAgICAmcXVvdDtDVEkmcXVvdDssJnF1b3Q7Q05YJnF1b3Q7LCAxLjcsICA5MCwgMTgwMCwgT1VUX0ZPUl9ERUxJVkVSWSwgICZxdW90OzIwMjUtMTAtMjImcXVvdDssICZxdW90OyZxdW90O30sCiAgICAgICAgeyZxdW90O1RIMDEwMDA1JnF1b3Q7LCAmcXVvdDtGaXJzdCZxdW90OywgICAgJnF1b3Q7Qm9hdCZxdW90OywgICAgICZxdW90O0JLSyZxdW90OywmcXVvdDtDTlgmcXVvdDssIDIuOCwgMTUwLCAzMjAwLCBJTl9UUkFOU0lULCAgICAgICAgJnF1b3Q7MjAyNS0xMC0xNyZxdW90OywgJnF1b3Q7JnF1b3Q7fQogICAgfTsKfQoKLyogLS0tLS0tLS0tLSDguIHguLLguKPguYDguKPguLXguKLguIfguKXguLPguJTguLHguJo6IFNlbGVjdGlvbiBTb3J0IOC4leC4suC4oSB0cmFja2luZyAtLS0tLS0tLS0tICovCnZvaWQgc2VsZWN0aW9uU29ydEJ5VHJhY2tpbmcodmVjdG9yJmx0O1BhcmNlbCZndDsmYW1wOyBhKXsKICAgIGludCBuID0gKGludClhLnNpemUoKTsKICAgIGZvcihpbnQgaT0wO2kmbHQ7bi0xO2krKyl7CiAgICAgICAgaW50IG1pbklkeCA9IGk7CiAgICAgICAgZm9yKGludCBqPWkrMTtqJmx0O247aisrKQogICAgICAgICAgICBpZiAoYVtqXS50cmFja2luZyAmbHQ7IGFbbWluSWR4XS50cmFja2luZykgbWluSWR4ID0gajsKICAgICAgICBpZiAobWluSWR4ICE9IGkpIHN3YXAoYVtpXSwgYVttaW5JZHhdKTsKICAgIH0KfQoKLyogLS0tLS0tLS0tLSDguITguYnguJnguKvguLLguYHguJrguJrguYTguJrguJnguLLguKPguLUgKOC4leC5ieC4reC4h+C5gOC4o+C4teC4ouC4h+C5geC4peC5ieC4pykgLS0tLS0tLS0tLSAqLwppbnQgYmluYXJ5U2VhcmNoVHJhY2tpbmcoY29uc3QgdmVjdG9yJmx0O1BhcmNlbCZndDsmYW1wOyBhLCBjb25zdCBzdHJpbmcmYW1wOyBrZXkpewogICAgaW50IEwgPSAwLCBSID0gKGludClhLnNpemUoKS0xOwogICAgd2hpbGUgKEwgJmx0Oz0gUil7CiAgICAgICAgaW50IE0gPSAoTCtSKS8yOwogICAgICAgIGlmIChhW01dLnRyYWNraW5nID09IGtleSkgcmV0dXJuIE07CiAgICAgICAgaWYgKGFbTV0udHJhY2tpbmcgJmx0OyBrZXkpICBMID0gTSsxOwogICAgICAgIGVsc2UgICAgICAgICAgICAgICAgICAgICAgUiA9IE0tMTsKICAgIH0KICAgIHJldHVybiAtMTsKfQoKLyogLS0tLS0tLS0tLSDguIHguLLguKPguYHguIHguYnguYTguIIv4Lil4LiaL+C5gOC4nuC4tOC5iOC4oSAtLS0tLS0tLS0tICovCmJvb2wgdXBkYXRlU3RhdHVzKHZlY3RvciZsdDtQYXJjZWwmZ3Q7JmFtcDsgYSwgY29uc3Qgc3RyaW5nJmFtcDsga2V5LCBTdGF0dXMgcywgY29uc3Qgc3RyaW5nJmFtcDsgZGVsaXZlckRhdGU9JnF1b3Q7JnF1b3Q7KXsKICAgIGludCBpZHggPSBiaW5hcnlTZWFyY2hUcmFja2luZyhhLCBrZXkpOwogICAgaWYgKGlkeCAmbHQ7IDApIHJldHVybiBmYWxzZTsKICAgIGFbaWR4XS5zdGF0dXMgPSBzOwogICAgaWYgKHMgPT0gREVMSVZFUkVEICZhbXA7JmFtcDsgIWRlbGl2ZXJEYXRlLmVtcHR5KCkpCiAgICAgICAgYVtpZHhdLmRlbGl2ZXJEYXRlID0gZGVsaXZlckRhdGU7CiAgICByZXR1cm4gdHJ1ZTsKfQoKYm9vbCByZW1vdmVCeVRyYWNraW5nKHZlY3RvciZsdDtQYXJjZWwmZ3Q7JmFtcDsgYSwgY29uc3Qgc3RyaW5nJmFtcDsga2V5KXsKICAgIGludCBpZHggPSBiaW5hcnlTZWFyY2hUcmFja2luZyhhLCBrZXkpOwogICAgaWYgKGlkeCAmbHQ7IDApIHJldHVybiBmYWxzZTsKICAgIGEuZXJhc2UoYS5iZWdpbigpK2lkeCk7CiAgICByZXR1cm4gdHJ1ZTsKfQoKdm9pZCBhZGRQYXJjZWwodmVjdG9yJmx0O1BhcmNlbCZndDsmYW1wOyBhLCBjb25zdCBQYXJjZWwmYW1wOyBwKXsKICAgIC8vIOC5geC4l+C4o+C4geC5geC4peC5ieC4p+C5gOC4o+C4teC4ouC4h+C5g+C4q+C4oeC5iOC4h+C5iOC4suC4ouC4l+C4teC5iOC4quC4uOC4lOC4quC4s+C4q+C4o+C4seC4muC4h+C4suC4meC4meC4teC5iSAobiDguYDguKXguYfguIEpCiAgICBhLnB1c2hfYmFjayhwKTsKICAgIHNlbGVjdGlvblNvcnRCeVRyYWNraW5nKGEpOwp9CgovKiAtLS0tLS0tLS0tIOC4geC4o+C4reC4h+C4leC4suC4oeC4quC4luC4suC4meC4sCAtLS0tLS0tLS0tICovCnZlY3RvciZsdDtQYXJjZWwmZ3Q7IGZpbHRlckJ5U3RhdHVzKGNvbnN0IHZlY3RvciZsdDtQYXJjZWwmZ3Q7JmFtcDsgYSwgU3RhdHVzIHMpewogICAgdmVjdG9yJmx0O1BhcmNlbCZndDsgb3V0OwogICAgZm9yIChhdXRvICZhbXA7cCA6IGEpIGlmIChwLnN0YXR1cyA9PSBzKSBvdXQucHVzaF9iYWNrKHApOwogICAgcmV0dXJuIG91dDsKfQoKLyogLS0tLS0tLS0tLSDguYDguJTguYLguKHguIHguLLguKPguYPguIrguYnguIfguLLguJnguJXguLLguKHguYPguJrguIfguLLguJkgLS0tLS0tLS0tLSAqLwppbnQgbWFpbigpewogICAgaW9zOjpzeW5jX3dpdGhfc3RkaW8oZmFsc2UpOwogICAgY2luLnRpZShudWxscHRyKTsKCiAgICAvLyAxKSDguYLguKvguKXguJTguILguYnguK3guKHguLnguKXguJXguLHguKfguK3guKLguYjguLLguIcgKyDguYHguKrguJTguIcKICAgIGF1dG8gZGIgPSBzYW1wbGVEYXRhKCk7CiAgICBjb3V0ICZsdDsmbHQ7ICZxdW90Oz09PSDguILguYnguK3guKHguLnguKXguYDguKPguLTguYjguKHguJXguYnguJkgKDEwIOC4o+C4suC4ouC4geC4suC4oykgPT09XG4mcXVvdDs7CiAgICBwcmludFRhYmxlKGRiKTsKCiAgICAvLyAyKSDguYDguKPguLXguKLguIfguKXguLPguJTguLHguJrguJXguLLguKEgdHJhY2tpbmcgKFNlbGVjdGlvbiBTb3J0KSDguYHguKXguYnguKfguYHguKrguJTguIcKICAgIHNlbGVjdGlvblNvcnRCeVRyYWNraW5nKGRiKTsKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7PT09IOC4q+C4peC4seC4h+C5gOC4o+C4teC4ouC4h+C4peC4s+C4lOC4seC4muC4lOC5ieC4p+C4oiBTZWxlY3Rpb24gU29ydCAodHJhY2tpbmcpID09PVxuJnF1b3Q7OwogICAgcHJpbnRUYWJsZShkYik7CgogICAgLy8gMykg4LiE4LmJ4LiZ4Lir4Liy4LmA4Lil4LiC4Lie4Lix4Liq4LiU4Li4IChCaW5hcnkgU2VhcmNoKSAmbmRhc2g7IOC4leC4seC4p+C4reC4ouC5iOC4suC4hzog4LmA4LiI4LitIOC5geC4peC4sCDguYTguKHguYjguYDguIjguK0KICAgIHN0cmluZyBrMSA9ICZxdW90O1RIMDEwMDA2JnF1b3Q7LCBrMiA9ICZxdW90O1RIOTk5OTk5JnF1b3Q7OwogICAgaW50IGlkeDEgPSBiaW5hcnlTZWFyY2hUcmFja2luZyhkYiwgazEpOwogICAgaW50IGlkeDIgPSBiaW5hcnlTZWFyY2hUcmFja2luZyhkYiwgazIpOwogICAgY291dCAmbHQ7Jmx0OyAmcXVvdDvguITguYnguJnguKvguLIgJnF1b3Q7ICZsdDsmbHQ7IGsxICZsdDsmbHQ7ICZxdW90OyAtJmd0OyAmcXVvdDsgJmx0OyZsdDsgKGlkeDEmZ3Q7PTAgPyAmcXVvdDvguJ7guJrguJfguLXguYggaW5kZXggJnF1b3Q7K3RvX3N0cmluZyhpZHgxKSA6ICZxdW90O+C5hOC4oeC5iOC4nuC4miZxdW90OykgJmx0OyZsdDsgJnF1b3Q7XG4mcXVvdDs7CiAgICBjb3V0ICZsdDsmbHQ7ICZxdW90O+C4hOC5ieC4meC4q+C4siAmcXVvdDsgJmx0OyZsdDsgazIgJmx0OyZsdDsgJnF1b3Q7IC0mZ3Q7ICZxdW90OyAmbHQ7Jmx0OyAoaWR4MiZndDs9MCA/ICZxdW90O+C4nuC4miZxdW90OyA6ICZxdW90O+C5hOC4oeC5iOC4nuC4miZxdW90OykgJmx0OyZsdDsgJnF1b3Q7XG5cbiZxdW90OzsKCiAgICAvLyA0KSDguK3guLHguJvguYDguJTguJXguKrguJbguLLguJnguLA6IOC4quC5iOC4h+C4quC4s+C5gOC4o+C5h+C4iAogICAgY291dCAmbHQ7Jmx0OyAmcXVvdDs9PT0g4Lit4Lix4Lib4LmA4LiU4LiV4Liq4LiW4Liy4LiZ4LiwICZxdW90OyAmbHQ7Jmx0OyBrMSAmbHQ7Jmx0OyAmcXVvdDsg4LmA4Lib4LmH4LiZIERFTElWRVJFRCA9PT1cbiZxdW90OzsKICAgIGlmICh1cGRhdGVTdGF0dXMoZGIsIGsxLCBERUxJVkVSRUQsICZxdW90OzIwMjUtMTAtMjMmcXVvdDspKSBwcmludFRhYmxlKGRiKTsKCiAgICAvLyA1KSDguKXguJrguJ7guLHguKrguJTguLjguJTguYnguKfguKIgdHJhY2tpbmcKICAgIGNvdXQgJmx0OyZsdDsgJnF1b3Q7PT09IOC4peC4muC4nuC4seC4quC4lOC4uCBUSDAxMDAwMyA9PT1cbiZxdW90OzsKICAgIHJlbW92ZUJ5VHJhY2tpbmcoZGIsICZxdW90O1RIMDEwMDAzJnF1b3Q7KTsKICAgIHByaW50VGFibGUoZGIpOwoKICAgIC8vIDYpIOC4geC4o+C4reC4h+C5geC4quC4lOC4h+C5gOC4ieC4nuC4suC4sOC4quC4luC4suC4meC4sCBPVVRfRk9SX0RFTElWRVJZCiAgICBjb3V0ICZsdDsmbHQ7ICZxdW90Oz09PSDguIHguKPguK3guIfguKrguJbguLLguJnguLAgT1VUX0ZPUl9ERUxJVkVSWSA9PT1cbiZxdW90OzsKICAgIGF1dG8gb2ZkID0gZmlsdGVyQnlTdGF0dXMoZGIsIE9VVF9GT1JfREVMSVZFUlkpOwogICAgcHJpbnRUYWJsZShvZmQpOwoKICAgIC8vIDcpIOC5gOC4nuC4tOC5iOC4oeC4o+C4suC4ouC4geC4suC4o+C5g+C4q+C4oeC5iAogICAgY291dCAmbHQ7Jmx0OyAmcXVvdDs9PT0g4LmA4Lie4Li04LmI4Lih4Lij4Liy4Lii4LiB4Liy4Lij4LmD4Lir4Lih4LmIIOC5geC4peC4sOC5gOC4o+C4teC4ouC4h+C4reC4seC4leC5guC4meC4oeC4seC4leC4tCA9PT1cbiZxdW90OzsKICAgIGFkZFBhcmNlbChkYiwgeyZxdW90O1RIMDEwMDAwJnF1b3Q7LCAmcXVvdDtBcnQmcXVvdDssICZxdW90O09tJnF1b3Q7LCAmcXVvdDtCS0smcXVvdDssJnF1b3Q7Q05YJnF1b3Q7LDAuNyw1MCw1MDAsIEFUX09SSUdJTiwgJnF1b3Q7MjAyNS0xMC0yNCZxdW90OywmcXVvdDsmcXVvdDt9KTsKICAgIHByaW50VGFibGUoZGIpOwoKICAgIHJldHVybiAwOwp9
#include <bits/stdc++.h>
using namespace std;
enum Status { AT_ORIGIN, IN_TRANSIT, OUT_FOR_DELIVERY, DELIVERED };
struct Parcel {
string tracking;
string sender, receiver;
string origin, destination;
double weightKg{};
int postage{};
int declaredValue{};
Status status{};
string acceptDate;
string deliverDate; // อาจว่างถ้ายังไม่ส่งสำเร็จ
};
/* ---------- Utilities ---------- */
string statusName(Status s){
switch(s){
case AT_ORIGIN: return "AT_ORIGIN";
case IN_TRANSIT: return "IN_TRANSIT";
case OUT_FOR_DELIVERY: return "OUT_FOR_DELIVERY";
case DELIVERED: return "DELIVERED";
}
return "?";
}
void printRow(const Parcel& p){
cout << left
<< setw(13) << p.tracking
<< setw(12) << p.sender.substr(0,10)
<< setw(12) << p.receiver.substr(0,10)
<< setw(8) << p.origin
<< setw(8) << p.destination
<< setw(6) << fixed << setprecision(1) << p.weightKg
<< setw(7) << p.postage
<< setw(8) << p.declaredValue
<< setw(19) << statusName(p.status)
<< setw(12) << p.acceptDate
<< setw(12) << (p.deliverDate.empty() ? "-" : p.deliverDate)
<< "\n";
}
void printTable(const vector<Parcel>& v){
cout << left
<< setw(13) << "Tracking"
<< setw(12) << "Sender"
<< setw(12) << "Receiver"
<< setw(8) << "From"
<< setw(8) << "To"
<< setw(6) << "Kg"
<< setw(7) << "Fee"
<< setw(8) << "Value"
<< setw(19) << "Status"
<< setw(12) << "AcceptDate"
<< setw(12) << "DeliverDate" << "\n";
cout << string(117,'-') << "\n";
for (auto &p : v) printRow(p);
cout << "\n";
}
/* ---------- Sample Data (10 รายการ) ---------- */
vector<Parcel> sampleData(){
return {
{"TH010001", "Somchai", "Aor", "BKK","CNX", 1.2, 60, 3000, IN_TRANSIT, "2025-10-20", ""},
{"TH010009", "May", "Ton", "BKK","HKT", 2.0, 110, 2500, AT_ORIGIN, "2025-10-22", ""},
{"TH010004", "Jane", "Beam", "CNX","BKK", 0.5, 45, 1200, OUT_FOR_DELIVERY, "2025-10-18", ""},
{"TH010002", "Pond", "Mint", "BKK","KKN", 3.4, 160, 4500, IN_TRANSIT, "2025-10-19", ""},
{"TH010006", "View", "Linn", "HKT","BKK", 0.8, 55, 800, DELIVERED, "2025-10-10", "2025-10-13"},
{"TH010007", "Bank", "Game", "KKN","BKK", 1.0, 60, 2000, IN_TRANSIT, "2025-10-21", ""},
{"TH010003", "Noon", "Mhee", "BKK","CTI", 5.2, 220, 7000, AT_ORIGIN, "2025-10-23", ""},
{"TH010010", "Pop", "Fon", "CNX","CTI", 0.4, 40, 500, DELIVERED, "2025-10-08", "2025-10-11"},
{"TH010008", "Tle", "Nune", "CTI","CNX", 1.7, 90, 1800, OUT_FOR_DELIVERY, "2025-10-22", ""},
{"TH010005", "First", "Boat", "BKK","CNX", 2.8, 150, 3200, IN_TRANSIT, "2025-10-17", ""}
};
}
/* ---------- การเรียงลำดับ: Selection Sort ตาม tracking ---------- */
void selectionSortByTracking(vector<Parcel>& a){
int n = (int)a.size();
for(int i=0;i<n-1;i++){
int minIdx = i;
for(int j=i+1;j<n;j++)
if (a[j].tracking < a[minIdx].tracking) minIdx = j;
if (minIdx != i) swap(a[i], a[minIdx]);
}
}
/* ---------- ค้นหาแบบไบนารี (ต้องเรียงแล้ว) ---------- */
int binarySearchTracking(const vector<Parcel>& a, const string& key){
int L = 0, R = (int)a.size()-1;
while (L <= R){
int M = (L+R)/2;
if (a[M].tracking == key) return M;
if (a[M].tracking < key) L = M+1;
else R = M-1;
}
return -1;
}
/* ---------- การแก้ไข/ลบ/เพิ่ม ---------- */
bool updateStatus(vector<Parcel>& a, const string& key, Status s, const string& deliverDate=""){
int idx = binarySearchTracking(a, key);
if (idx < 0) return false;
a[idx].status = s;
if (s == DELIVERED && !deliverDate.empty())
a[idx].deliverDate = deliverDate;
return true;
}
bool removeByTracking(vector<Parcel>& a, const string& key){
int idx = binarySearchTracking(a, key);
if (idx < 0) return false;
a.erase(a.begin()+idx);
return true;
}
void addParcel(vector<Parcel>& a, const Parcel& p){
// แทรกแล้วเรียงใหม่ง่ายที่สุดสำหรับงานนี้ (n เล็ก)
a.push_back(p);
selectionSortByTracking(a);
}
/* ---------- กรองตามสถานะ ---------- */
vector<Parcel> filterByStatus(const vector<Parcel>& a, Status s){
vector<Parcel> out;
for (auto &p : a) if (p.status == s) out.push_back(p);
return out;
}
/* ---------- เดโมการใช้งานตามใบงาน ---------- */
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
// 1) โหลดข้อมูลตัวอย่าง + แสดง
auto db = sampleData();
cout << "=== ข้อมูลเริ่มต้น (10 รายการ) ===\n";
printTable(db);
// 2) เรียงลำดับตาม tracking (Selection Sort) แล้วแสดง
selectionSortByTracking(db);
cout << "=== หลังเรียงลำดับด้วย Selection Sort (tracking) ===\n";
printTable(db);
// 3) ค้นหาเลขพัสดุ (Binary Search) – ตัวอย่าง: เจอ และ ไม่เจอ
string k1 = "TH010006", k2 = "TH999999";
int idx1 = binarySearchTracking(db, k1);
int idx2 = binarySearchTracking(db, k2);
cout << "ค้นหา " << k1 << " -> " << (idx1>=0 ? "พบที่ index "+to_string(idx1) : "ไม่พบ") << "\n";
cout << "ค้นหา " << k2 << " -> " << (idx2>=0 ? "พบ" : "ไม่พบ") << "\n\n";
// 4) อัปเดตสถานะ: ส่งสำเร็จ
cout << "=== อัปเดตสถานะ " << k1 << " เป็น DELIVERED ===\n";
if (updateStatus(db, k1, DELIVERED, "2025-10-23")) printTable(db);
// 5) ลบพัสดุด้วย tracking
cout << "=== ลบพัสดุ TH010003 ===\n";
removeByTracking(db, "TH010003");
printTable(db);
// 6) กรองแสดงเฉพาะสถานะ OUT_FOR_DELIVERY
cout << "=== กรองสถานะ OUT_FOR_DELIVERY ===\n";
auto ofd = filterByStatus(db, OUT_FOR_DELIVERY);
printTable(ofd);
// 7) เพิ่มรายการใหม่
cout << "=== เพิ่มรายการใหม่ และเรียงอัตโนมัติ ===\n";
addParcel(db, {"TH010000", "Art", "Om", "BKK","CNX",0.7,50,500, AT_ORIGIN, "2025-10-24",""});
printTable(db);
return 0;
}