aW1wb3J0IFJlYWN0LCB7IHVzZVN0YXRlLCB1c2VFZmZlY3QgfSBmcm9tICdyZWFjdCc7CmltcG9ydCB7IAogIENyZWRpdENhcmQsIAogIFNlbmQsIAogIFFyQ29kZSwgCiAgVXNlciwgCiAgSGlzdG9yeSwgCiAgRXllLCAKICBFeWVPZmYsCiAgQXJyb3dMZWZ0LAogIENoZWNrLAogIFgsCiAgU21hcnRwaG9uZSwKICBTaGllbGQsCiAgWmFwCn0gZnJvbSAnbHVjaWRlLXJlYWN0JzsKCmNvbnN0IFVQSVBheW1lbnRBcHAgPSAoKSA9Jmd0OyB7CiAgY29uc3QgW2N1cnJlbnRTY3JlZW4sIHNldEN1cnJlbnRTY3JlZW5dID0gdXNlU3RhdGUoJ2hvbWUnKTsKICBjb25zdCBbc2hvd0JhbGFuY2UsIHNldFNob3dCYWxhbmNlXSA9IHVzZVN0YXRlKGZhbHNlKTsKICBjb25zdCBbYmFsYW5jZSwgc2V0QmFsYW5jZV0gPSB1c2VTdGF0ZSgyNTQzMC41MCk7CiAgY29uc3QgW3Bpbiwgc2V0UGluXSA9IHVzZVN0YXRlKCcnKTsKICBjb25zdCBbcGF5bWVudEFtb3VudCwgc2V0UGF5bWVudEFtb3VudF0gPSB1c2VTdGF0ZSgnJyk7CiAgY29uc3QgW3JlY2lwaWVudCwgc2V0UmVjaXBpZW50XSA9IHVzZVN0YXRlKCcnKTsKICBjb25zdCBbaXNQcm9jZXNzaW5nLCBzZXRJc1Byb2Nlc3NpbmddID0gdXNlU3RhdGUoZmFsc2UpOwogIGNvbnN0IFtzaG93U3VjY2Vzcywgc2V0U2hvd1N1Y2Nlc3NdID0gdXNlU3RhdGUoZmFsc2UpOwogIGNvbnN0IFtjYW1lcmFBY3RpdmUsIHNldENhbWVyYUFjdGl2ZV0gPSB1c2VTdGF0ZShmYWxzZSk7CiAgY29uc3QgW3NjYW5uZWREYXRhLCBzZXRTY2FubmVkRGF0YV0gPSB1c2VTdGF0ZShudWxsKTsKICBjb25zdCBbc3RyZWFtLCBzZXRTdHJlYW1dID0gdXNlU3RhdGUobnVsbCk7CiAgY29uc3QgW3NjYW5FcnJvciwgc2V0U2NhbkVycm9yXSA9IHVzZVN0YXRlKCcnKTsKCiAgY29uc3QgW3RyYW5zYWN0aW9uc10gPSB1c2VTdGF0ZShbCiAgICB7IGlkOiAxLCB0eXBlOiAnc2VudCcsIGFtb3VudDogNTAwLCByZWNpcGllbnQ6ICdKb2huIERvZScsIHRpbWU6ICcxMDozMCBBTScsIHN0YXR1czogJ3N1Y2Nlc3MnIH0sCiAgICB7IGlkOiAyLCB0eXBlOiAncmVjZWl2ZWQnLCBhbW91bnQ6IDEyMDAsIHNlbmRlcjogJ1NhcmFoIFdpbHNvbicsIHRpbWU6ICc5OjE1IEFNJywgc3RhdHVzOiAnc3VjY2VzcycgfSwKICAgIHsgaWQ6IDMsIHR5cGU6ICdzZW50JywgYW1vdW50OiAzMDAsIHJlY2lwaWVudDogJ0NvZmZlZSBTaG9wJywgdGltZTogJ1llc3RlcmRheScsIHN0YXR1czogJ3N1Y2Nlc3MnIH0sCiAgICB7IGlkOiA0LCB0eXBlOiAncmVjZWl2ZWQnLCBhbW91bnQ6IDI1MDAsIHNlbmRlcjogJ0ZyZWVsYW5jZSBQYXltZW50JywgdGltZTogJzIgZGF5cyBhZ28nLCBzdGF0dXM6ICdzdWNjZXNzJyB9CiAgXSk7CgogIGNvbnN0IGhhbmRsZVBheW1lbnQgPSAoKSA9Jmd0OyB7CiAgICBpZiAocGF5bWVudEFtb3VudCAmYW1wOyZhbXA7IHJlY2lwaWVudCAmYW1wOyZhbXA7IHBpbiA9PT0gJzEyMzQnKSB7CiAgICAgIHNldElzUHJvY2Vzc2luZyh0cnVlKTsKICAgICAgc2V0VGltZW91dCgoKSA9Jmd0OyB7CiAgICAgICAgc2V0QmFsYW5jZShwcmV2ID0mZ3Q7IHByZXYgLSBwYXJzZUZsb2F0KHBheW1lbnRBbW91bnQpKTsKICAgICAgICBzZXRJc1Byb2Nlc3NpbmcoZmFsc2UpOwogICAgICAgIHNldFNob3dTdWNjZXNzKHRydWUpOwogICAgICAgIHNldFRpbWVvdXQoKCkgPSZndDsgewogICAgICAgICAgc2V0U2hvd1N1Y2Nlc3MoZmFsc2UpOwogICAgICAgICAgc2V0Q3VycmVudFNjcmVlbignaG9tZScpOwogICAgICAgICAgc2V0UGF5bWVudEFtb3VudCgnJyk7CiAgICAgICAgICBzZXRSZWNpcGllbnQoJycpOwogICAgICAgICAgc2V0UGluKCcnKTsKICAgICAgICB9LCAyMDAwKTsKICAgICAgfSwgMjAwMCk7CiAgICB9CiAgfTsKCiAgY29uc3QgSG9tZVNjcmVlbiA9ICgpID0mZ3Q7ICgKICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O21pbi1oLXNjcmVlbiBiZy1ncmFkaWVudC10by1iciBmcm9tLWJsdWUtNTAgdG8taW5kaWdvLTEwMCZxdW90OyZndDsKICAgICAgey8qIEhlYWRlciAqL30KICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7YmctZ3JhZGllbnQtdG8tciBmcm9tLWJsdWUtNjAwIHRvLWluZGlnby03MDAgdGV4dC13aGl0ZSBwLTYgcGItOCZxdW90OyZndDsKICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDtmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gbWItNiZxdW90OyZndDsKICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2ZsZXggaXRlbXMtY2VudGVyIHNwYWNlLXgtMyZxdW90OyZndDsKICAgICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7dy0xMCBoLTEwIGJnLXdoaXRlLzIwIHJvdW5kZWQtZnVsbCBmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWNlbnRlciZxdW90OyZndDsKICAgICAgICAgICAgICAmbHQ7WmFwIGNsYXNzTmFtZT0mcXVvdDt3LTYgaC02JnF1b3Q7IC8mZ3Q7CiAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgICAmbHQ7ZGl2Jmd0OwogICAgICAgICAgICAgICZsdDtoMSBjbGFzc05hbWU9JnF1b3Q7dGV4dC14bCBmb250LWJvbGQmcXVvdDsmZ3Q7UGF5RWFzeSZsdDsvaDEmZ3Q7CiAgICAgICAgICAgICAgJmx0O3AgY2xhc3NOYW1lPSZxdW90O3RleHQtYmx1ZS0xMDAgdGV4dC1zbSZxdW90OyZndDtZb3VyIFVQSSBXYWxsZXQmbHQ7L3AmZ3Q7CiAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDt3LTEwIGgtMTAgYmctd2hpdGUvMjAgcm91bmRlZC1mdWxsIGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyJnF1b3Q7Jmd0OwogICAgICAgICAgICAmbHQ7VXNlciBjbGFzc05hbWU9JnF1b3Q7dy02IGgtNiZxdW90OyAvJmd0OwogICAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICAgJmx0Oy9kaXYmZ3Q7CgogICAgICAgIHsvKiBCYWxhbmNlIENhcmQgKi99CiAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7Ymctd2hpdGUvMTAgYmFja2Ryb3AtYmx1ci1zbSByb3VuZGVkLXhsIHAtNCBib3JkZXIgYm9yZGVyLXdoaXRlLzIwJnF1b3Q7Jmd0OwogICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7ZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1iZXR3ZWVuJnF1b3Q7Jmd0OwogICAgICAgICAgICAmbHQ7ZGl2Jmd0OwogICAgICAgICAgICAgICZsdDtwIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWJsdWUtMTAwIHRleHQtc20gbWItMSZxdW90OyZndDtUb3RhbCBCYWxhbmNlJmx0Oy9wJmd0OwogICAgICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2ZsZXggaXRlbXMtY2VudGVyIHNwYWNlLXgtMiZxdW90OyZndDsKICAgICAgICAgICAgICAgICZsdDtzcGFuIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LTJ4bCBmb250LWJvbGQmcXVvdDsmZ3Q7CiAgICAgICAgICAgICAgICAgIHtzaG93QmFsYW5jZSA/IGDigrkke2JhbGFuY2UudG9Mb2NhbGVTdHJpbmcoKX1gIDogJ+KCuSZidWxsOyZidWxsOyZidWxsOyZidWxsOyZidWxsOyZidWxsOyd9CiAgICAgICAgICAgICAgICAmbHQ7L3NwYW4mZ3Q7CiAgICAgICAgICAgICAgICAmbHQ7YnV0dG9uCiAgICAgICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0mZ3Q7IHNldFNob3dCYWxhbmNlKCFzaG93QmFsYW5jZSl9CiAgICAgICAgICAgICAgICAgIGNsYXNzTmFtZT0mcXVvdDtwLTEgaG92ZXI6Ymctd2hpdGUvMTAgcm91bmRlZCZxdW90OwogICAgICAgICAgICAgICAgJmd0OwogICAgICAgICAgICAgICAgICB7c2hvd0JhbGFuY2UgPyAmbHQ7RXllT2ZmIGNsYXNzTmFtZT0mcXVvdDt3LTQgaC00JnF1b3Q7IC8mZ3Q7IDogJmx0O0V5ZSBjbGFzc05hbWU9JnF1b3Q7dy00IGgtNCZxdW90OyAvJmd0O30KICAgICAgICAgICAgICAgICZsdDsvYnV0dG9uJmd0OwogICAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7dy0xMiBoLTEyIGJnLWdyYWRpZW50LXRvLWJyIGZyb20tZ3JlZW4tNDAwIHRvLWVtZXJhbGQtNTAwIHJvdW5kZWQteGwgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXImcXVvdDsmZ3Q7CiAgICAgICAgICAgICAgJmx0O0NyZWRpdENhcmQgY2xhc3NOYW1lPSZxdW90O3ctNiBoLTYgdGV4dC13aGl0ZSZxdW90OyAvJmd0OwogICAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAmbHQ7L2RpdiZndDsKCiAgICAgIHsvKiBRdWljayBBY3Rpb25zICovfQogICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDtweC02IC1tdC00IG1iLTYmcXVvdDsmZ3Q7CiAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7Ymctd2hpdGUgcm91bmRlZC14bCBzaGFkb3ctbGcgcC02JnF1b3Q7Jmd0OwogICAgICAgICAgJmx0O2gzIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWxnIGZvbnQtc2VtaWJvbGQgbWItNCB0ZXh0LWdyYXktODAwJnF1b3Q7Jmd0O1F1aWNrIEFjdGlvbnMmbHQ7L2gzJmd0OwogICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7Z3JpZCBncmlkLWNvbHMtMiBnYXAtNCZxdW90OyZndDsKICAgICAgICAgICAgJmx0O2J1dHRvbgogICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0mZ3Q7IHNldEN1cnJlbnRTY3JlZW4oJ3NlbmQnKX0KICAgICAgICAgICAgICBjbGFzc05hbWU9JnF1b3Q7ZmxleCBmbGV4LWNvbCBpdGVtcy1jZW50ZXIgcC00IGJnLWdyYWRpZW50LXRvLWJyIGZyb20tYmx1ZS01MCB0by1ibHVlLTEwMCByb3VuZGVkLXhsIGhvdmVyOnNoYWRvdy1tZCB0cmFuc2l0aW9uLWFsbCBkdXJhdGlvbi0yMDAgZ3JvdXAmcXVvdDsKICAgICAgICAgICAgJmd0OwogICAgICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O3ctMTIgaC0xMiBiZy1ibHVlLTUwMCByb3VuZGVkLXhsIGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIG1iLTIgZ3JvdXAtaG92ZXI6c2NhbGUtMTEwIHRyYW5zaXRpb24tdHJhbnNmb3JtJnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgJmx0O1NlbmQgY2xhc3NOYW1lPSZxdW90O3ctNiBoLTYgdGV4dC13aGl0ZSZxdW90OyAvJmd0OwogICAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgICAgICZsdDtzcGFuIGNsYXNzTmFtZT0mcXVvdDtmb250LW1lZGl1bSB0ZXh0LWdyYXktODAwJnF1b3Q7Jmd0O1NlbmQgTW9uZXkmbHQ7L3NwYW4mZ3Q7CiAgICAgICAgICAgICZsdDsvYnV0dG9uJmd0OwogICAgICAgICAgICAmbHQ7YnV0dG9uCiAgICAgICAgICAgICAgb25DbGljaz17KCkgPSZndDsgc2V0Q3VycmVudFNjcmVlbignc2NhbicpfQogICAgICAgICAgICAgIGNsYXNzTmFtZT0mcXVvdDtmbGV4IGZsZXgtY29sIGl0ZW1zLWNlbnRlciBwLTQgYmctZ3JhZGllbnQtdG8tYnIgZnJvbS1wdXJwbGUtNTAgdG8tcHVycGxlLTEwMCByb3VuZGVkLXhsIGhvdmVyOnNoYWRvdy1tZCB0cmFuc2l0aW9uLWFsbCBkdXJhdGlvbi0yMDAgZ3JvdXAmcXVvdDsKICAgICAgICAgICAgJmd0OwogICAgICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O3ctMTIgaC0xMiBiZy1wdXJwbGUtNTAwIHJvdW5kZWQteGwgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgbWItMiBncm91cC1ob3ZlcjpzY2FsZS0xMTAgdHJhbnNpdGlvbi10cmFuc2Zvcm0mcXVvdDsmZ3Q7CiAgICAgICAgICAgICAgICAmbHQ7UXJDb2RlIGNsYXNzTmFtZT0mcXVvdDt3LTYgaC02IHRleHQtd2hpdGUmcXVvdDsgLyZndDsKICAgICAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAgICAgICAmbHQ7c3BhbiBjbGFzc05hbWU9JnF1b3Q7Zm9udC1tZWRpdW0gdGV4dC1ncmF5LTgwMCZxdW90OyZndDtTY2FuICZhbXA7IFBheSZsdDsvc3BhbiZndDsKICAgICAgICAgICAgJmx0Oy9idXR0b24mZ3Q7CiAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgJmx0Oy9kaXYmZ3Q7CgogICAgICB7LyogUmVjZW50IFRyYW5zYWN0aW9ucyAqL30KICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7cHgtNiZxdW90OyZndDsKICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDtiZy13aGl0ZSByb3VuZGVkLXhsIHNoYWRvdy1sZyBwLTYmcXVvdDsmZ3Q7CiAgICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDtmbGV4IGl0ZW1zLWNlbnRlciBqdXN0aWZ5LWJldHdlZW4gbWItNCZxdW90OyZndDsKICAgICAgICAgICAgJmx0O2gzIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWxnIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTgwMCZxdW90OyZndDtSZWNlbnQgVHJhbnNhY3Rpb25zJmx0Oy9oMyZndDsKICAgICAgICAgICAgJmx0O2J1dHRvbgogICAgICAgICAgICAgIG9uQ2xpY2s9eygpID0mZ3Q7IHNldEN1cnJlbnRTY3JlZW4oJ2hpc3RvcnknKX0KICAgICAgICAgICAgICBjbGFzc05hbWU9JnF1b3Q7dGV4dC1ibHVlLTYwMCB0ZXh0LXNtIGZvbnQtbWVkaXVtIGhvdmVyOnRleHQtYmx1ZS03MDAmcXVvdDsKICAgICAgICAgICAgJmd0OwogICAgICAgICAgICAgIFZpZXcgQWxsCiAgICAgICAgICAgICZsdDsvYnV0dG9uJmd0OwogICAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDtzcGFjZS15LTMmcXVvdDsmZ3Q7CiAgICAgICAgICAgIHt0cmFuc2FjdGlvbnMuc2xpY2UoMCwgMykubWFwKCh0cmFuc2FjdGlvbikgPSZndDsgKAogICAgICAgICAgICAgICZsdDtkaXYga2V5PXt0cmFuc2FjdGlvbi5pZH0gY2xhc3NOYW1lPSZxdW90O2ZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiBwLTMgYmctZ3JheS01MCByb3VuZGVkLWxnJnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7ZmxleCBpdGVtcy1jZW50ZXIgc3BhY2UteC0zJnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT17YHctMTAgaC0xMCByb3VuZGVkLWZ1bGwgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgJHsKICAgICAgICAgICAgICAgICAgICB0cmFuc2FjdGlvbi50eXBlID09PSAnc2VudCcgPyAnYmctcmVkLTEwMCcgOiAnYmctZ3JlZW4tMTAwJwogICAgICAgICAgICAgICAgICB9YH0mZ3Q7CiAgICAgICAgICAgICAgICAgICAgJmx0O1NlbmQgY2xhc3NOYW1lPXtgdy01IGgtNSAkewogICAgICAgICAgICAgICAgICAgICAgdHJhbnNhY3Rpb24udHlwZSA9PT0gJ3NlbnQnID8gJ3RleHQtcmVkLTYwMCByb3RhdGUtNDUnIDogJ3RleHQtZ3JlZW4tNjAwIC1yb3RhdGUtNDUnCiAgICAgICAgICAgICAgICAgICAgfWB9IC8mZ3Q7CiAgICAgICAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgICAgICAgICAmbHQ7ZGl2Jmd0OwogICAgICAgICAgICAgICAgICAgICZsdDtwIGNsYXNzTmFtZT0mcXVvdDtmb250LW1lZGl1bSB0ZXh0LWdyYXktODAwJnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgICAgICAge3RyYW5zYWN0aW9uLnR5cGUgPT09ICdzZW50JyA/IHRyYW5zYWN0aW9uLnJlY2lwaWVudCA6IHRyYW5zYWN0aW9uLnNlbmRlcn0KICAgICAgICAgICAgICAgICAgICAmbHQ7L3AmZ3Q7CiAgICAgICAgICAgICAgICAgICAgJmx0O3AgY2xhc3NOYW1lPSZxdW90O3RleHQtc20gdGV4dC1ncmF5LTUwMCZxdW90OyZndDt7dHJhbnNhY3Rpb24udGltZX0mbHQ7L3AmZ3Q7CiAgICAgICAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICAgICAgICAgICAmbHQ7c3BhbiBjbGFzc05hbWU9e2Bmb250LXNlbWlib2xkICR7CiAgICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uLnR5cGUgPT09ICdzZW50JyA/ICd0ZXh0LXJlZC02MDAnIDogJ3RleHQtZ3JlZW4tNjAwJwogICAgICAgICAgICAgICAgfWB9Jmd0OwogICAgICAgICAgICAgICAgICB7dHJhbnNhY3Rpb24udHlwZSA9PT0gJ3NlbnQnID8gJy0nIDogJysnfeKCuXt0cmFuc2FjdGlvbi5hbW91bnR9CiAgICAgICAgICAgICAgICAmbHQ7L3NwYW4mZ3Q7CiAgICAgICAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICAgICAgICkpfQogICAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICZsdDsvZGl2Jmd0OwogICAgJmx0Oy9kaXYmZ3Q7CiAgKTsKCiAgY29uc3QgU2VuZE1vbmV5U2NyZWVuID0gKCkgPSZndDsgKAogICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7bWluLWgtc2NyZWVuIGJnLWdyYXktNTAmcXVvdDsmZ3Q7CiAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2JnLXdoaXRlIHNoYWRvdy1zbSBwLTQgZmxleCBpdGVtcy1jZW50ZXIgc3BhY2UteC00JnF1b3Q7Jmd0OwogICAgICAgICZsdDtidXR0b24KICAgICAgICAgIG9uQ2xpY2s9eygpID0mZ3Q7IHNldEN1cnJlbnRTY3JlZW4oJ2hvbWUnKX0KICAgICAgICAgIGNsYXNzTmFtZT0mcXVvdDtwLTIgaG92ZXI6YmctZ3JheS0xMDAgcm91bmRlZC1mdWxsJnF1b3Q7CiAgICAgICAgJmd0OwogICAgICAgICAgJmx0O0Fycm93TGVmdCBjbGFzc05hbWU9JnF1b3Q7dy02IGgtNiZxdW90OyAvJmd0OwogICAgICAgICZsdDsvYnV0dG9uJmd0OwogICAgICAgICZsdDtoMiBjbGFzc05hbWU9JnF1b3Q7dGV4dC1sZyBmb250LXNlbWlib2xkJnF1b3Q7Jmd0O1NlbmQgTW9uZXkmbHQ7L2gyJmd0OwogICAgICAmbHQ7L2RpdiZndDsKCiAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O3AtNiBzcGFjZS15LTYmcXVvdDsmZ3Q7CiAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7Ymctd2hpdGUgcm91bmRlZC14bCBzaGFkb3ctc20gcC02JnF1b3Q7Jmd0OwogICAgICAgICAgJmx0O2gzIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWxnIGZvbnQtc2VtaWJvbGQgbWItNCZxdW90OyZndDtFbnRlciBEZXRhaWxzJmx0Oy9oMyZndDsKICAgICAgICAgIAogICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7c3BhY2UteS00JnF1b3Q7Jmd0OwogICAgICAgICAgICAmbHQ7ZGl2Jmd0OwogICAgICAgICAgICAgICZsdDtsYWJlbCBjbGFzc05hbWU9JnF1b3Q7YmxvY2sgdGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LWdyYXktNzAwIG1iLTImcXVvdDsmZ3Q7CiAgICAgICAgICAgICAgICBSZWNpcGllbnQgKFVQSSBJRCBvciBQaG9uZSkKICAgICAgICAgICAgICAmbHQ7L2xhYmVsJmd0OwogICAgICAgICAgICAgICZsdDtpbnB1dAogICAgICAgICAgICAgICAgdHlwZT0mcXVvdDt0ZXh0JnF1b3Q7CiAgICAgICAgICAgICAgICB2YWx1ZT17cmVjaXBpZW50fQogICAgICAgICAgICAgICAgb25DaGFuZ2U9eyhlKSA9Jmd0OyBzZXRSZWNpcGllbnQoZS50YXJnZXQudmFsdWUpfQogICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9JnF1b3Q7am9obkBwYXl0bSBvciA5ODc2NTQzMjEwJnF1b3Q7CiAgICAgICAgICAgICAgICBjbGFzc05hbWU9JnF1b3Q7dy1mdWxsIHAtMyBib3JkZXIgYm9yZGVyLWdyYXktMzAwIHJvdW5kZWQtbGcgZm9jdXM6cmluZy0yIGZvY3VzOnJpbmctYmx1ZS01MDAgZm9jdXM6Ym9yZGVyLXRyYW5zcGFyZW50JnF1b3Q7CiAgICAgICAgICAgICAgLyZndDsKICAgICAgICAgICAgJmx0Oy9kaXYmZ3Q7CgogICAgICAgICAgICAmbHQ7ZGl2Jmd0OwogICAgICAgICAgICAgICZsdDtsYWJlbCBjbGFzc05hbWU9JnF1b3Q7YmxvY2sgdGV4dC1zbSBmb250LW1lZGl1bSB0ZXh0LWdyYXktNzAwIG1iLTImcXVvdDsmZ3Q7CiAgICAgICAgICAgICAgICBBbW91bnQgKOKCuSkKICAgICAgICAgICAgICAmbHQ7L2xhYmVsJmd0OwogICAgICAgICAgICAgICZsdDtpbnB1dAogICAgICAgICAgICAgICAgdHlwZT0mcXVvdDtudW1iZXImcXVvdDsKICAgICAgICAgICAgICAgIHZhbHVlPXtwYXltZW50QW1vdW50fQogICAgICAgICAgICAgICAgb25DaGFuZ2U9eyhlKSA9Jmd0OyBzZXRQYXltZW50QW1vdW50KGUudGFyZ2V0LnZhbHVlKX0KICAgICAgICAgICAgICAgIHBsYWNlaG9sZGVyPSZxdW90O0VudGVyIGFtb3VudCZxdW90OwogICAgICAgICAgICAgICAgY2xhc3NOYW1lPSZxdW90O3ctZnVsbCBwLTMgYm9yZGVyIGJvcmRlci1ncmF5LTMwMCByb3VuZGVkLWxnIGZvY3VzOnJpbmctMiBmb2N1czpyaW5nLWJsdWUtNTAwIGZvY3VzOmJvcmRlci10cmFuc3BhcmVudCZxdW90OwogICAgICAgICAgICAgIC8mZ3Q7CiAgICAgICAgICAgICZsdDsvZGl2Jmd0OwoKICAgICAgICAgICAgJmx0O2RpdiZndDsKICAgICAgICAgICAgICAmbHQ7bGFiZWwgY2xhc3NOYW1lPSZxdW90O2Jsb2NrIHRleHQtc20gZm9udC1tZWRpdW0gdGV4dC1ncmF5LTcwMCBtYi0yJnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgVVBJIFBJTgogICAgICAgICAgICAgICZsdDsvbGFiZWwmZ3Q7CiAgICAgICAgICAgICAgJmx0O2lucHV0CiAgICAgICAgICAgICAgICB0eXBlPSZxdW90O3Bhc3N3b3JkJnF1b3Q7CiAgICAgICAgICAgICAgICB2YWx1ZT17cGlufQogICAgICAgICAgICAgICAgb25DaGFuZ2U9eyhlKSA9Jmd0OyBzZXRQaW4oZS50YXJnZXQudmFsdWUpfQogICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9JnF1b3Q7RW50ZXIgNC1kaWdpdCBQSU4mcXVvdDsKICAgICAgICAgICAgICAgIG1heExlbmd0aD0mcXVvdDs0JnF1b3Q7CiAgICAgICAgICAgICAgICBjbGFzc05hbWU9JnF1b3Q7dy1mdWxsIHAtMyBib3JkZXIgYm9yZGVyLWdyYXktMzAwIHJvdW5kZWQtbGcgZm9jdXM6cmluZy0yIGZvY3VzOnJpbmctYmx1ZS01MDAgZm9jdXM6Ym9yZGVyLXRyYW5zcGFyZW50JnF1b3Q7CiAgICAgICAgICAgICAgLyZndDsKICAgICAgICAgICAgICAmbHQ7cCBjbGFzc05hbWU9JnF1b3Q7dGV4dC14cyB0ZXh0LWdyYXktNTAwIG10LTEmcXVvdDsmZ3Q7RGVtbyBQSU46IDEyMzQmbHQ7L3AmZ3Q7CiAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgJmx0Oy9kaXYmZ3Q7CgogICAgICAgICAgJmx0O2J1dHRvbgogICAgICAgICAgICBvbkNsaWNrPXtoYW5kbGVQYXltZW50fQogICAgICAgICAgICBkaXNhYmxlZD17IXBheW1lbnRBbW91bnQgfHwgIXJlY2lwaWVudCB8fCAhcGluIHx8IGlzUHJvY2Vzc2luZ30KICAgICAgICAgICAgY2xhc3NOYW1lPSZxdW90O3ctZnVsbCBtdC02IGJnLWdyYWRpZW50LXRvLXIgZnJvbS1ibHVlLTYwMCB0by1pbmRpZ28tNjAwIHRleHQtd2hpdGUgcHktMyByb3VuZGVkLWxnIGZvbnQtc2VtaWJvbGQgaG92ZXI6ZnJvbS1ibHVlLTcwMCBob3Zlcjp0by1pbmRpZ28tNzAwIGRpc2FibGVkOm9wYWNpdHktNTAgZGlzYWJsZWQ6Y3Vyc29yLW5vdC1hbGxvd2VkIGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHNwYWNlLXgtMiZxdW90OwogICAgICAgICAgJmd0OwogICAgICAgICAgICB7aXNQcm9jZXNzaW5nID8gKAogICAgICAgICAgICAgICZsdDsmZ3Q7CiAgICAgICAgICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDt3LTUgaC01IGJvcmRlci0yIGJvcmRlci13aGl0ZSBib3JkZXItdC10cmFuc3BhcmVudCByb3VuZGVkLWZ1bGwgYW5pbWF0ZS1zcGluJnF1b3Q7Jmd0OyZsdDsvZGl2Jmd0OwogICAgICAgICAgICAgICAgJmx0O3NwYW4mZ3Q7UHJvY2Vzc2luZy4uLiZsdDsvc3BhbiZndDsKICAgICAgICAgICAgICAmbHQ7LyZndDsKICAgICAgICAgICAgKSA6ICgKICAgICAgICAgICAgICAmbHQ7Jmd0OwogICAgICAgICAgICAgICAgJmx0O1NlbmQgY2xhc3NOYW1lPSZxdW90O3ctNSBoLTUmcXVvdDsgLyZndDsKICAgICAgICAgICAgICAgICZsdDtzcGFuJmd0O1NlbmQgTW9uZXkmbHQ7L3NwYW4mZ3Q7CiAgICAgICAgICAgICAgJmx0Oy8mZ3Q7CiAgICAgICAgICAgICl9CiAgICAgICAgICAmbHQ7L2J1dHRvbiZndDsKICAgICAgICAmbHQ7L2RpdiZndDsKCiAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7YmctYmx1ZS01MCBib3JkZXIgYm9yZGVyLWJsdWUtMjAwIHJvdW5kZWQteGwgcC00JnF1b3Q7Jmd0OwogICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7ZmxleCBpdGVtcy1zdGFydCBzcGFjZS14LTMmcXVvdDsmZ3Q7CiAgICAgICAgICAgICZsdDtTaGllbGQgY2xhc3NOYW1lPSZxdW90O3ctNSBoLTUgdGV4dC1ibHVlLTYwMCBtdC0wLjUmcXVvdDsgLyZndDsKICAgICAgICAgICAgJmx0O2RpdiZndDsKICAgICAgICAgICAgICAmbHQ7aDQgY2xhc3NOYW1lPSZxdW90O2ZvbnQtbWVkaXVtIHRleHQtYmx1ZS05MDAmcXVvdDsmZ3Q7U2VjdXJlIFRyYW5zYWN0aW9uJmx0Oy9oNCZndDsKICAgICAgICAgICAgICAmbHQ7cCBjbGFzc05hbWU9JnF1b3Q7dGV4dC1zbSB0ZXh0LWJsdWUtNzAwJnF1b3Q7Jmd0O1lvdXIgcGF5bWVudCBpcyBwcm90ZWN0ZWQgd2l0aCBiYW5rLWdyYWRlIHNlY3VyaXR5Jmx0Oy9wJmd0OwogICAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAmbHQ7L2RpdiZndDsKICAgICZsdDsvZGl2Jmd0OwogICk7CgogIGNvbnN0IHNpbXVsYXRlUVJTY2FuID0gKCkgPSZndDsgewogICAgLy8gU2ltdWxhdGUgUVIgY29kZSBkZXRlY3Rpb24KICAgIGNvbnN0IG1vY2tRUkRhdGEgPSB7CiAgICAgIG1lcmNoYW50TmFtZTogJnF1b3Q7Q29mZmVlIEhvdXNlJnF1b3Q7LAogICAgICB1cGlJZDogJnF1b3Q7Y29mZmVob3VzZUBwYXl0bSZxdW90OywKICAgICAgYW1vdW50OiAxNTAKICAgIH07CiAgICAKICAgIHNldENhbWVyYUFjdGl2ZSh0cnVlKTsKICAgIHNldFRpbWVvdXQoKCkgPSZndDsgewogICAgICBzZXRTY2FubmVkRGF0YShtb2NrUVJEYXRhKTsKICAgICAgc2V0Q2FtZXJhQWN0aXZlKGZhbHNlKTsKICAgIH0sIDMwMDApOwogIH07CgogIGNvbnN0IFNjYW5QYXlTY3JlZW4gPSAoKSA9Jmd0OyB7CiAgICBpZiAoc2Nhbm5lZERhdGEpIHsKICAgICAgcmV0dXJuICgKICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDttaW4taC1zY3JlZW4gYmctZ3JheS01MCZxdW90OyZndDsKICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2JnLXdoaXRlIHNoYWRvdy1zbSBwLTQgZmxleCBpdGVtcy1jZW50ZXIgc3BhY2UteC00JnF1b3Q7Jmd0OwogICAgICAgICAgICAmbHQ7YnV0dG9uCiAgICAgICAgICAgICAgb25DbGljaz17KCkgPSZndDsgewogICAgICAgICAgICAgICAgc2V0U2Nhbm5lZERhdGEobnVsbCk7CiAgICAgICAgICAgICAgICBzZXRDdXJyZW50U2NyZWVuKCdob21lJyk7CiAgICAgICAgICAgICAgfX0KICAgICAgICAgICAgICBjbGFzc05hbWU9JnF1b3Q7cC0yIGhvdmVyOmJnLWdyYXktMTAwIHJvdW5kZWQtZnVsbCZxdW90OwogICAgICAgICAgICAmZ3Q7CiAgICAgICAgICAgICAgJmx0O0Fycm93TGVmdCBjbGFzc05hbWU9JnF1b3Q7dy02IGgtNiZxdW90OyAvJmd0OwogICAgICAgICAgICAmbHQ7L2J1dHRvbiZndDsKICAgICAgICAgICAgJmx0O2gyIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWxnIGZvbnQtc2VtaWJvbGQmcXVvdDsmZ3Q7UGF5bWVudCBEZXRhaWxzJmx0Oy9oMiZndDsKICAgICAgICAgICZsdDsvZGl2Jmd0OwoKICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O3AtNiBzcGFjZS15LTYmcXVvdDsmZ3Q7CiAgICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2JnLXdoaXRlIHJvdW5kZWQteGwgc2hhZG93LXNtIHAtNiZxdW90OyZndDsKICAgICAgICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWNlbnRlciBtYi02JnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7dy0xNiBoLTE2IGJnLWdyZWVuLTEwMCByb3VuZGVkLWZ1bGwgZmxleCBpdGVtcy1jZW50ZXIganVzdGlmeS1jZW50ZXIgbXgtYXV0byBtYi00JnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgICAmbHQ7Q2hlY2sgY2xhc3NOYW1lPSZxdW90O3ctOCBoLTggdGV4dC1ncmVlbi02MDAmcXVvdDsgLyZndDsKICAgICAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgICAgICAgJmx0O2gzIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWxnIGZvbnQtc2VtaWJvbGQgdGV4dC1ncmF5LTgwMCZxdW90OyZndDtRUiBDb2RlIFNjYW5uZWQgU3VjY2Vzc2Z1bGx5Jmx0Oy9oMyZndDsKICAgICAgICAgICAgICAmbHQ7L2RpdiZndDsKCiAgICAgICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7YmctZ3JheS01MCByb3VuZGVkLWxnIHAtNCBtYi02JnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7ZmxleCBqdXN0aWZ5LWJldHdlZW4gaXRlbXMtY2VudGVyIG1iLTImcXVvdDsmZ3Q7CiAgICAgICAgICAgICAgICAgICZsdDtzcGFuIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWdyYXktNjAwJnF1b3Q7Jmd0O01lcmNoYW50OiZsdDsvc3BhbiZndDsKICAgICAgICAgICAgICAgICAgJmx0O3NwYW4gY2xhc3NOYW1lPSZxdW90O2ZvbnQtc2VtaWJvbGQmcXVvdDsmZ3Q7e3NjYW5uZWREYXRhLm1lcmNoYW50TmFtZX0mbHQ7L3NwYW4mZ3Q7CiAgICAgICAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2ZsZXgganVzdGlmeS1iZXR3ZWVuIGl0ZW1zLWNlbnRlcgoKICBjb25zdCBUcmFuc2FjdGlvbkhpc3RvcnkgPSAoKSA9Jmd0OyAoCiAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDttaW4taC1zY3JlZW4gYmctZ3JheS01MCZxdW90OyZndDsKICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7Ymctd2hpdGUgc2hhZG93LXNtIHAtNCBmbGV4IGl0ZW1zLWNlbnRlciBzcGFjZS14LTQmcXVvdDsmZ3Q7CiAgICAgICAgJmx0O2J1dHRvbgogICAgICAgICAgb25DbGljaz17KCkgPSZndDsgc2V0Q3VycmVudFNjcmVlbignaG9tZScpfQogICAgICAgICAgY2xhc3NOYW1lPSZxdW90O3AtMiBob3ZlcjpiZy1ncmF5LTEwMCByb3VuZGVkLWZ1bGwmcXVvdDsKICAgICAgICAmZ3Q7CiAgICAgICAgICAmbHQ7QXJyb3dMZWZ0IGNsYXNzTmFtZT0mcXVvdDt3LTYgaC02JnF1b3Q7IC8mZ3Q7CiAgICAgICAgJmx0Oy9idXR0b24mZ3Q7CiAgICAgICAgJmx0O2gyIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWxnIGZvbnQtc2VtaWJvbGQmcXVvdDsmZ3Q7VHJhbnNhY3Rpb24gSGlzdG9yeSZsdDsvaDImZ3Q7CiAgICAgICZsdDsvZGl2Jmd0OwoKICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7cC02JnF1b3Q7Jmd0OwogICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2JnLXdoaXRlIHJvdW5kZWQteGwgc2hhZG93LXNtJnF1b3Q7Jmd0OwogICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7cC02IGJvcmRlci1iIGJvcmRlci1ncmF5LTIwMCZxdW90OyZndDsKICAgICAgICAgICAgJmx0O2gzIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LWxnIGZvbnQtc2VtaWJvbGQmcXVvdDsmZ3Q7QWxsIFRyYW5zYWN0aW9ucyZsdDsvaDMmZ3Q7CiAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2RpdmlkZS15IGRpdmlkZS1ncmF5LTIwMCZxdW90OyZndDsKICAgICAgICAgICAge3RyYW5zYWN0aW9ucy5tYXAoKHRyYW5zYWN0aW9uKSA9Jmd0OyAoCiAgICAgICAgICAgICAgJmx0O2RpdiBrZXk9e3RyYW5zYWN0aW9uLmlkfSBjbGFzc05hbWU9JnF1b3Q7cC02IGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktYmV0d2VlbiZxdW90OyZndDsKICAgICAgICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2ZsZXggaXRlbXMtY2VudGVyIHNwYWNlLXgtNCZxdW90OyZndDsKICAgICAgICAgICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9e2B3LTEyIGgtMTIgcm91bmRlZC1mdWxsIGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyICR7CiAgICAgICAgICAgICAgICAgICAgdHJhbnNhY3Rpb24udHlwZSA9PT0gJ3NlbnQnID8gJ2JnLXJlZC0xMDAnIDogJ2JnLWdyZWVuLTEwMCcKICAgICAgICAgICAgICAgICAgfWB9Jmd0OwogICAgICAgICAgICAgICAgICAgICZsdDtTZW5kIGNsYXNzTmFtZT17YHctNiBoLTYgJHsKICAgICAgICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uLnR5cGUgPT09ICdzZW50JyA/ICd0ZXh0LXJlZC02MDAgcm90YXRlLTQ1JyA6ICd0ZXh0LWdyZWVuLTYwMCAtcm90YXRlLTQ1JwogICAgICAgICAgICAgICAgICAgIH1gfSAvJmd0OwogICAgICAgICAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAgICAgICAgICAgJmx0O2RpdiZndDsKICAgICAgICAgICAgICAgICAgICAmbHQ7cCBjbGFzc05hbWU9JnF1b3Q7Zm9udC1tZWRpdW0gdGV4dC1ncmF5LTgwMCZxdW90OyZndDsKICAgICAgICAgICAgICAgICAgICAgIHt0cmFuc2FjdGlvbi50eXBlID09PSAnc2VudCcgPyBgVG8gJHt0cmFuc2FjdGlvbi5yZWNpcGllbnR9YCA6IGBGcm9tICR7dHJhbnNhY3Rpb24uc2VuZGVyfWB9CiAgICAgICAgICAgICAgICAgICAgJmx0Oy9wJmd0OwogICAgICAgICAgICAgICAgICAgICZsdDtwIGNsYXNzTmFtZT0mcXVvdDt0ZXh0LXNtIHRleHQtZ3JheS01MDAmcXVvdDsmZ3Q7e3RyYW5zYWN0aW9uLnRpbWV9Jmx0Oy9wJmd0OwogICAgICAgICAgICAgICAgICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O2ZsZXggaXRlbXMtY2VudGVyIHNwYWNlLXgtMSBtdC0xJnF1b3Q7Jmd0OwogICAgICAgICAgICAgICAgICAgICAgJmx0O0NoZWNrIGNsYXNzTmFtZT0mcXVvdDt3LTMgaC0zIHRleHQtZ3JlZW4tNTAwJnF1b3Q7IC8mZ3Q7CiAgICAgICAgICAgICAgICAgICAgICAmbHQ7c3BhbiBjbGFzc05hbWU9JnF1b3Q7dGV4dC14cyB0ZXh0LWdyZWVuLTYwMCZxdW90OyZndDtTdWNjZXNzJmx0Oy9zcGFuJmd0OwogICAgICAgICAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAgICAgICAgICZsdDsvZGl2Jmd0OwogICAgICAgICAgICAgICAgJmx0O3NwYW4gY2xhc3NOYW1lPXtgdGV4dC1sZyBmb250LXNlbWlib2xkICR7CiAgICAgICAgICAgICAgICAgIHRyYW5zYWN0aW9uLnR5cGUgPT09ICdzZW50JyA/ICd0ZXh0LXJlZC02MDAnIDogJ3RleHQtZ3JlZW4tNjAwJwogICAgICAgICAgICAgICAgfWB9Jmd0OwogICAgICAgICAgICAgICAgICB7dHJhbnNhY3Rpb24udHlwZSA9PT0gJ3NlbnQnID8gJy0nIDogJysnfeKCuXt0cmFuc2FjdGlvbi5hbW91bnR9CiAgICAgICAgICAgICAgICAmbHQ7L3NwYW4mZ3Q7CiAgICAgICAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICAgICAgICkpfQogICAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAgICZsdDsvZGl2Jmd0OwogICAgJmx0Oy9kaXYmZ3Q7CiAgKTsKCiAgY29uc3QgU3VjY2Vzc1NjcmVlbiA9ICgpID0mZ3Q7ICgKICAgICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O21pbi1oLXNjcmVlbiBiZy1ncmFkaWVudC10by1iciBmcm9tLWdyZWVuLTUwIHRvLWVtZXJhbGQtMTAwIGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIHAtNiZxdW90OyZndDsKICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7Ymctd2hpdGUgcm91bmRlZC14bCBzaGFkb3ctbGcgcC04IHRleHQtY2VudGVyIG1heC13LXNtIHctZnVsbCZxdW90OyZndDsKICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDt3LTIwIGgtMjAgYmctZ3JhZGllbnQtdG8tYnIgZnJvbS1ncmVlbi01MDAgdG8tZW1lcmFsZC01MDAgcm91bmRlZC1mdWxsIGZsZXggaXRlbXMtY2VudGVyIGp1c3RpZnktY2VudGVyIG14LWF1dG8gbWItNiZxdW90OyZndDsKICAgICAgICAgICZsdDtDaGVjayBjbGFzc05hbWU9JnF1b3Q7dy0xMCBoLTEwIHRleHQtd2hpdGUmcXVvdDsgLyZndDsKICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAKICAgICAgICAmbHQ7aDMgY2xhc3NOYW1lPSZxdW90O3RleHQtMnhsIGZvbnQtYm9sZCB0ZXh0LWdyYXktODAwIG1iLTImcXVvdDsmZ3Q7UGF5bWVudCBTdWNjZXNzZnVsISZsdDsvaDMmZ3Q7CiAgICAgICAgJmx0O3AgY2xhc3NOYW1lPSZxdW90O3RleHQtZ3JheS02MDAgbWItNCZxdW90OyZndDvigrl7cGF5bWVudEFtb3VudH0gc2VudCB0byB7cmVjaXBpZW50fSZsdDsvcCZndDsKICAgICAgICAKICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDtiZy1ncmF5LTUwIHJvdW5kZWQtbGcgcC00IG1iLTYmcXVvdDsmZ3Q7CiAgICAgICAgICAmbHQ7cCBjbGFzc05hbWU9JnF1b3Q7dGV4dC1zbSB0ZXh0LWdyYXktNTAwJnF1b3Q7Jmd0O1RyYW5zYWN0aW9uIElEJmx0Oy9wJmd0OwogICAgICAgICAgJmx0O3AgY2xhc3NOYW1lPSZxdW90O2ZvbnQtbW9ubyB0ZXh0LXNtIGZvbnQtbWVkaXVtJnF1b3Q7Jmd0O1VQSXtEYXRlLm5vdygpfSZsdDsvcCZndDsKICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgICAKICAgICAgICAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDt3LWZ1bGwgaC0xIGJnLWdyZWVuLTIwMCByb3VuZGVkLWZ1bGwgb3ZlcmZsb3ctaGlkZGVuJnF1b3Q7Jmd0OwogICAgICAgICAgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7aC1mdWxsIGJnLWdyZWVuLTUwMCByb3VuZGVkLWZ1bGwgYW5pbWF0ZS1wdWxzZSZxdW90OyZndDsmbHQ7L2RpdiZndDsKICAgICAgICAmbHQ7L2RpdiZndDsKICAgICAgJmx0Oy9kaXYmZ3Q7CiAgICAmbHQ7L2RpdiZndDsKICApOwoKICBpZiAoc2hvd1N1Y2Nlc3MpIHJldHVybiAmbHQ7U3VjY2Vzc1NjcmVlbiAvJmd0OzsKCiAgc3dpdGNoIChjdXJyZW50U2NyZWVuKSB7CiAgICBjYXNlICdob21lJzoKICAgICAgcmV0dXJuICZsdDtIb21lU2NyZWVuIC8mZ3Q7OwogICAgY2FzZSAnc2VuZCc6CiAgICAgIHJldHVybiAmbHQ7U2VuZE1vbmV5U2NyZWVuIC8mZ3Q7OwogICAgY2FzZSAnc2Nhbic6CiAgICAgIHJldHVybiAmbHQ7U2NhblBheVNjcmVlbiAvJmd0OzsKICAgIGNhc2UgJ2hpc3RvcnknOgogICAgICByZXR1cm4gJmx0O1RyYW5zYWN0aW9uSGlzdG9yeSAvJmd0OzsKICAgIGRlZmF1bHQ6CiAgICAgIHJldHVybiAmbHQ7SG9tZVNjcmVlbiAvJmd0OzsKICB9Cn07CgpleHBvcnQgZGVmYXVsdCBVUElQYXltZW50QXBwOw==
import React, { useState, useEffect } from 'react';
import {
CreditCard,
Send,
QrCode,
User,
History,
Eye,
EyeOff,
ArrowLeft,
Check,
X,
Smartphone,
Shield,
Zap
} from 'lucide-react';
const UPIPaymentApp = () => {
const [currentScreen, setCurrentScreen] = useState('home');
const [showBalance, setShowBalance] = useState(false);
const [balance, setBalance] = useState(25430.50);
const [pin, setPin] = useState('');
const [paymentAmount, setPaymentAmount] = useState('');
const [recipient, setRecipient] = useState('');
const [isProcessing, setIsProcessing] = useState(false);
const [showSuccess, setShowSuccess] = useState(false);
const [cameraActive, setCameraActive] = useState(false);
const [scannedData, setScannedData] = useState(null);
const [stream, setStream] = useState(null);
const [scanError, setScanError] = useState('');
const [transactions] = useState([
{ id: 1, type: 'sent', amount: 500, recipient: 'John Doe', time: '10:30 AM', status: 'success' },
{ id: 2, type: 'received', amount: 1200, sender: 'Sarah Wilson', time: '9:15 AM', status: 'success' },
{ id: 3, type: 'sent', amount: 300, recipient: 'Coffee Shop', time: 'Yesterday', status: 'success' },
{ id: 4, type: 'received', amount: 2500, sender: 'Freelance Payment', time: '2 days ago', status: 'success' }
]);
const handlePayment = () => {
if (paymentAmount && recipient && pin === '1234') {
setIsProcessing(true);
setTimeout(() => {
setBalance(prev => prev - parseFloat(paymentAmount));
setIsProcessing(false);
setShowSuccess(true);
setTimeout(() => {
setShowSuccess(false);
setCurrentScreen('home');
setPaymentAmount('');
setRecipient('');
setPin('');
}, 2000);
}, 2000);
}
};
const HomeScreen = () => (
<div className="min-h-screen bg-gradient-to-br from-blue-50 to-indigo-100">
{/* Header */}
<div className="bg-gradient-to-r from-blue-600 to-indigo-700 text-white p-6 pb-8">
<div className="flex items-center justify-between mb-6">
<div className="flex items-center space-x-3">
<div className="w-10 h-10 bg-white/20 rounded-full flex items-center justify-center">
<Zap className="w-6 h-6" />
</div>
<div>
<h1 className="text-xl font-bold">PayEasy</h1>
<p className="text-blue-100 text-sm">Your UPI Wallet</p>
</div>
</div>
<div className="w-10 h-10 bg-white/20 rounded-full flex items-center justify-center">
<User className="w-6 h-6" />
</div>
</div>
{/* Balance Card */}
<div className="bg-white/10 backdrop-blur-sm rounded-xl p-4 border border-white/20">
<div className="flex items-center justify-between">
<div>
<p className="text-blue-100 text-sm mb-1">Total Balance</p>
<div className="flex items-center space-x-2">
<span className="text-2xl font-bold">
{showBalance ? `₹${balance.toLocaleString()}` : '₹••••••'}
</span>
<button
onClick={() => setShowBalance(!showBalance)}
className="p-1 hover:bg-white/10 rounded"
>
{showBalance ? <EyeOff className="w-4 h-4" /> : <Eye className="w-4 h-4" />}
</button>
</div>
</div>
<div className="w-12 h-12 bg-gradient-to-br from-green-400 to-emerald-500 rounded-xl flex items-center justify-center">
<CreditCard className="w-6 h-6 text-white" />
</div>
</div>
</div>
</div>
{/* Quick Actions */}
<div className="px-6 -mt-4 mb-6">
<div className="bg-white rounded-xl shadow-lg p-6">
<h3 className="text-lg font-semibold mb-4 text-gray-800">Quick Actions</h3>
<div className="grid grid-cols-2 gap-4">
<button
onClick={() => setCurrentScreen('send')}
className="flex flex-col items-center p-4 bg-gradient-to-br from-blue-50 to-blue-100 rounded-xl hover:shadow-md transition-all duration-200 group"
>
<div className="w-12 h-12 bg-blue-500 rounded-xl flex items-center justify-center mb-2 group-hover:scale-110 transition-transform">
<Send className="w-6 h-6 text-white" />
</div>
<span className="font-medium text-gray-800">Send Money</span>
</button>
<button
onClick={() => setCurrentScreen('scan')}
className="flex flex-col items-center p-4 bg-gradient-to-br from-purple-50 to-purple-100 rounded-xl hover:shadow-md transition-all duration-200 group"
>
<div className="w-12 h-12 bg-purple-500 rounded-xl flex items-center justify-center mb-2 group-hover:scale-110 transition-transform">
<QrCode className="w-6 h-6 text-white" />
</div>
<span className="font-medium text-gray-800">Scan & Pay</span>
</button>
</div>
</div>
</div>
{/* Recent Transactions */}
<div className="px-6">
<div className="bg-white rounded-xl shadow-lg p-6">
<div className="flex items-center justify-between mb-4">
<h3 className="text-lg font-semibold text-gray-800">Recent Transactions</h3>
<button
onClick={() => setCurrentScreen('history')}
className="text-blue-600 text-sm font-medium hover:text-blue-700"
>
View All
</button>
</div>
<div className="space-y-3">
{transactions.slice(0, 3).map((transaction) => (
<div key={transaction.id} className="flex items-center justify-between p-3 bg-gray-50 rounded-lg">
<div className="flex items-center space-x-3">
<div className={`w-10 h-10 rounded-full flex items-center justify-center ${
transaction.type === 'sent' ? 'bg-red-100' : 'bg-green-100'
}`}>
<Send className={`w-5 h-5 ${
transaction.type === 'sent' ? 'text-red-600 rotate-45' : 'text-green-600 -rotate-45'
}`} />
</div>
<div>
<p className="font-medium text-gray-800">
{transaction.type === 'sent' ? transaction.recipient : transaction.sender}
</p>
<p className="text-sm text-gray-500">{transaction.time}</p>
</div>
</div>
<span className={`font-semibold ${
transaction.type === 'sent' ? 'text-red-600' : 'text-green-600'
}`}>
{transaction.type === 'sent' ? '-' : '+'}₹{transaction.amount}
</span>
</div>
))}
</div>
</div>
</div>
</div>
);
const SendMoneyScreen = () => (
<div className="min-h-screen bg-gray-50">
<div className="bg-white shadow-sm p-4 flex items-center space-x-4">
<button
onClick={() => setCurrentScreen('home')}
className="p-2 hover:bg-gray-100 rounded-full"
>
<ArrowLeft className="w-6 h-6" />
</button>
<h2 className="text-lg font-semibold">Send Money</h2>
</div>
<div className="p-6 space-y-6">
<div className="bg-white rounded-xl shadow-sm p-6">
<h3 className="text-lg font-semibold mb-4">Enter Details</h3>
<div className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Recipient (UPI ID or Phone)
</label>
<input
type="text"
value={recipient}
onChange={(e) => setRecipient(e.target.value)}
placeholder="john@paytm or 9876543210"
className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
Amount (₹)
</label>
<input
type="number"
value={paymentAmount}
onChange={(e) => setPaymentAmount(e.target.value)}
placeholder="Enter amount"
className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">
UPI PIN
</label>
<input
type="password"
value={pin}
onChange={(e) => setPin(e.target.value)}
placeholder="Enter 4-digit PIN"
maxLength="4"
className="w-full p-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
<p className="text-xs text-gray-500 mt-1">Demo PIN: 1234</p>
</div>
</div>
<button
onClick={handlePayment}
disabled={!paymentAmount || !recipient || !pin || isProcessing}
className="w-full mt-6 bg-gradient-to-r from-blue-600 to-indigo-600 text-white py-3 rounded-lg font-semibold hover:from-blue-700 hover:to-indigo-700 disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center space-x-2"
>
{isProcessing ? (
<>
<div className="w-5 h-5 border-2 border-white border-t-transparent rounded-full animate-spin"></div>
<span>Processing...</span>
</>
) : (
<>
<Send className="w-5 h-5" />
<span>Send Money</span>
</>
)}
</button>
</div>
<div className="bg-blue-50 border border-blue-200 rounded-xl p-4">
<div className="flex items-start space-x-3">
<Shield className="w-5 h-5 text-blue-600 mt-0.5" />
<div>
<h4 className="font-medium text-blue-900">Secure Transaction</h4>
<p className="text-sm text-blue-700">Your payment is protected with bank-grade security</p>
</div>
</div>
</div>
</div>
</div>
);
const simulateQRScan = () => {
// Simulate QR code detection
const mockQRData = {
merchantName: "Coffee House",
upiId: "coffehouse@paytm",
amount: 150
};
setCameraActive(true);
setTimeout(() => {
setScannedData(mockQRData);
setCameraActive(false);
}, 3000);
};
const ScanPayScreen = () => {
if (scannedData) {
return (
<div className="min-h-screen bg-gray-50">
<div className="bg-white shadow-sm p-4 flex items-center space-x-4">
<button
onClick={() => {
setScannedData(null);
setCurrentScreen('home');
}}
className="p-2 hover:bg-gray-100 rounded-full"
>
<ArrowLeft className="w-6 h-6" />
</button>
<h2 className="text-lg font-semibold">Payment Details</h2>
</div>
<div className="p-6 space-y-6">
<div className="bg-white rounded-xl shadow-sm p-6">
<div className="text-center mb-6">
<div className="w-16 h-16 bg-green-100 rounded-full flex items-center justify-center mx-auto mb-4">
<Check className="w-8 h-8 text-green-600" />
</div>
<h3 className="text-lg font-semibold text-gray-800">QR Code Scanned Successfully</h3>
</div>
<div className="bg-gray-50 rounded-lg p-4 mb-6">
<div className="flex justify-between items-center mb-2">
<span className="text-gray-600">Merchant:</span>
<span className="font-semibold">{scannedData.merchantName}</span>
</div>
<div className="flex justify-between items-center
const TransactionHistory = () => (
<div className="min-h-screen bg-gray-50">
<div className="bg-white shadow-sm p-4 flex items-center space-x-4">
<button
onClick={() => setCurrentScreen('home')}
className="p-2 hover:bg-gray-100 rounded-full"
>
<ArrowLeft className="w-6 h-6" />
</button>
<h2 className="text-lg font-semibold">Transaction History</h2>
</div>
<div className="p-6">
<div className="bg-white rounded-xl shadow-sm">
<div className="p-6 border-b border-gray-200">
<h3 className="text-lg font-semibold">All Transactions</h3>
</div>
<div className="divide-y divide-gray-200">
{transactions.map((transaction) => (
<div key={transaction.id} className="p-6 flex items-center justify-between">
<div className="flex items-center space-x-4">
<div className={`w-12 h-12 rounded-full flex items-center justify-center ${
transaction.type === 'sent' ? 'bg-red-100' : 'bg-green-100'
}`}>
<Send className={`w-6 h-6 ${
transaction.type === 'sent' ? 'text-red-600 rotate-45' : 'text-green-600 -rotate-45'
}`} />
</div>
<div>
<p className="font-medium text-gray-800">
{transaction.type === 'sent' ? `To ${transaction.recipient}` : `From ${transaction.sender}`}
</p>
<p className="text-sm text-gray-500">{transaction.time}</p>
<div className="flex items-center space-x-1 mt-1">
<Check className="w-3 h-3 text-green-500" />
<span className="text-xs text-green-600">Success</span>
</div>
</div>
</div>
<span className={`text-lg font-semibold ${
transaction.type === 'sent' ? 'text-red-600' : 'text-green-600'
}`}>
{transaction.type === 'sent' ? '-' : '+'}₹{transaction.amount}
</span>
</div>
))}
</div>
</div>
</div>
</div>
);
const SuccessScreen = () => (
<div className="min-h-screen bg-gradient-to-br from-green-50 to-emerald-100 flex items-center justify-center p-6">
<div className="bg-white rounded-xl shadow-lg p-8 text-center max-w-sm w-full">
<div className="w-20 h-20 bg-gradient-to-br from-green-500 to-emerald-500 rounded-full flex items-center justify-center mx-auto mb-6">
<Check className="w-10 h-10 text-white" />
</div>
<h3 className="text-2xl font-bold text-gray-800 mb-2">Payment Successful!</h3>
<p className="text-gray-600 mb-4">₹{paymentAmount} sent to {recipient}</p>
<div className="bg-gray-50 rounded-lg p-4 mb-6">
<p className="text-sm text-gray-500">Transaction ID</p>
<p className="font-mono text-sm font-medium">UPI{Date.now()}</p>
</div>
<div className="w-full h-1 bg-green-200 rounded-full overflow-hidden">
<div className="h-full bg-green-500 rounded-full animate-pulse"></div>
</div>
</div>
</div>
);
if (showSuccess) return <SuccessScreen />;
switch (currentScreen) {
case 'home':
return <HomeScreen />;
case 'send':
return <SendMoneyScreen />;
case 'scan':
return <ScanPayScreen />;
case 'history':
return <TransactionHistory />;
default:
return <HomeScreen />;
}
};
export default UPIPaymentApp;