# react-best-practices > A comprehensive collection of React best practices and performance optimization techniques from Vercel, including rules for eliminating waterfalls, bundle size optimization, server-side performance, and more. - Author: kihiku - Repository: kimjuyoung1127/signalcraftWebApp - Version: 20260130190105 - Stars: 0 - Forks: 0 - Last Updated: 2026-02-06 - Source: https://github.com/kimjuyoung1127/signalcraftWebApp - Web: https://mule.run/skillshub/@@kimjuyoung1127/signalcraftWebApp~react-best-practices:20260130190105 --- LS0tCm5hbWU6IHJlYWN0LWJlc3QtcHJhY3RpY2VzCmRlc2NyaXB0aW9uOiBBIGNvbXByZWhlbnNpdmUgY29sbGVjdGlvbiBvZiBSZWFjdCBiZXN0IHByYWN0aWNlcyBhbmQgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uIHRlY2huaXF1ZXMgZnJvbSBWZXJjZWwsIGluY2x1ZGluZyBydWxlcyBmb3IgZWxpbWluYXRpbmcgd2F0ZXJmYWxscywgYnVuZGxlIHNpemUgb3B0aW1pemF0aW9uLCBzZXJ2ZXItc2lkZSBwZXJmb3JtYW5jZSwgYW5kIG1vcmUuCi0tLQoKIyBSZWFjdCBCZXN0IFByYWN0aWNlcwoKVGhpcyBza2lsbCBwcm92aWRlcyBhIHNldCBvZiBydWxlcyBhbmQgYmVzdCBwcmFjdGljZXMgZm9yIGRldmVsb3BpbmcgaGlnaC1wZXJmb3JtYW5jZSBSZWFjdCBhcHBsaWNhdGlvbnMuCiMgUmVhY3QgQmVzdCBQcmFjdGljZXMKCioqVmVyc2lvbiAxLjAuMCoqICAKVmVyY2VsIEVuZ2luZWVyaW5nICAKSmFudWFyeSAyMDI2Cgo+ICoqTm90ZToqKiAgCj4gVGhpcyBkb2N1bWVudCBpcyBtYWlubHkgZm9yIGFnZW50cyBhbmQgTExNcyB0byBmb2xsb3cgd2hlbiBtYWludGFpbmluZywgIAo+IGdlbmVyYXRpbmcsIG9yIHJlZmFjdG9yaW5nIFJlYWN0IGFuZCBOZXh0LmpzIGNvZGViYXNlcyBhdCBWZXJjZWwuIEh1bWFucyAgCj4gbWF5IGFsc28gZmluZCBpdCB1c2VmdWwsIGJ1dCBndWlkYW5jZSBoZXJlIGlzIG9wdGltaXplZCBmb3IgYXV0b21hdGlvbiAgCj4gYW5kIGNvbnNpc3RlbmN5IGJ5IEFJLWFzc2lzdGVkIHdvcmtmbG93cy4KCi0tLQoKIyMgQWJzdHJhY3QKCkNvbXByZWhlbnNpdmUgcGVyZm9ybWFuY2Ugb3B0aW1pemF0aW9uIGd1aWRlIGZvciBSZWFjdCBhbmQgTmV4dC5qcyBhcHBsaWNhdGlvbnMsIGRlc2lnbmVkIGZvciBBSSBhZ2VudHMgYW5kIExMTXMuIENvbnRhaW5zIDQwKyBydWxlcyBhY3Jvc3MgOCBjYXRlZ29yaWVzLCBwcmlvcml0aXplZCBieSBpbXBhY3QgZnJvbSBjcml0aWNhbCAoZWxpbWluYXRpbmcgd2F0ZXJmYWxscywgcmVkdWNpbmcgYnVuZGxlIHNpemUpIHRvIGluY3JlbWVudGFsIChhZHZhbmNlZCBwYXR0ZXJucykuIEVhY2ggcnVsZSBpbmNsdWRlcyBkZXRhaWxlZCBleHBsYW5hdGlvbnMsIHJlYWwtd29ybGQgZXhhbXBsZXMgY29tcGFyaW5nIGluY29ycmVjdCB2cy4gY29ycmVjdCBpbXBsZW1lbnRhdGlvbnMsIGFuZCBzcGVjaWZpYyBpbXBhY3QgbWV0cmljcyB0byBndWlkZSBhdXRvbWF0ZWQgcmVmYWN0b3JpbmcgYW5kIGNvZGUgZ2VuZXJhdGlvbi4KCi0tLQoKIyMgVGFibGUgb2YgQ29udGVudHMKCjEuIFtFbGltaW5hdGluZyBXYXRlcmZhbGxzXSgjMS1lbGltaW5hdGluZy13YXRlcmZhbGxzKSA/PyoqQ1JJVElDQUwqKgogICAtIDEuMSBbRGVmZXIgQXdhaXQgVW50aWwgTmVlZGVkXSgjMTEtZGVmZXItYXdhaXQtdW50aWwtbmVlZGVkKQogICAtIDEuMiBbRGVwZW5kZW5jeS1CYXNlZCBQYXJhbGxlbGl6YXRpb25dKCMxMi1kZXBlbmRlbmN5LWJhc2VkLXBhcmFsbGVsaXphdGlvbikKICAgLSAxLjMgW1ByZXZlbnQgV2F0ZXJmYWxsIENoYWlucyBpbiBBUEkgUm91dGVzXSgjMTMtcHJldmVudC13YXRlcmZhbGwtY2hhaW5zLWluLWFwaS1yb3V0ZXMpCiAgIC0gMS40IFtQcm9taXNlLmFsbCgpIGZvciBJbmRlcGVuZGVudCBPcGVyYXRpb25zXSgjMTQtcHJvbWlzZWFsbC1mb3ItaW5kZXBlbmRlbnQtb3BlcmF0aW9ucykKICAgLSAxLjUgW1N0cmF0ZWdpYyBTdXNwZW5zZSBCb3VuZGFyaWVzXSgjMTUtc3RyYXRlZ2ljLXN1c3BlbnNlLWJvdW5kYXJpZXMpCjIuIFtCdW5kbGUgU2l6ZSBPcHRpbWl6YXRpb25dKCMyLWJ1bmRsZS1zaXplLW9wdGltaXphdGlvbikgPz8qKkNSSVRJQ0FMKioKICAgLSAyLjEgW0F2b2lkIEJhcnJlbCBGaWxlIEltcG9ydHNdKCMyMS1hdm9pZC1iYXJyZWwtZmlsZS1pbXBvcnRzKQogICAtIDIuMiBbQ29uZGl0aW9uYWwgTW9kdWxlIExvYWRpbmddKCMyMi1jb25kaXRpb25hbC1tb2R1bGUtbG9hZGluZykKICAgLSAyLjMgW0RlZmVyIE5vbi1Dcml0aWNhbCBUaGlyZC1QYXJ0eSBMaWJyYXJpZXNdKCMyMy1kZWZlci1ub24tY3JpdGljYWwtdGhpcmQtcGFydHktbGlicmFyaWVzKQogICAtIDIuNCBbRHluYW1pYyBJbXBvcnRzIGZvciBIZWF2eSBDb21wb25lbnRzXSgjMjQtZHluYW1pYy1pbXBvcnRzLWZvci1oZWF2eS1jb21wb25lbnRzKQogICAtIDIuNSBbUHJlbG9hZCBCYXNlZCBvbiBVc2VyIEludGVudF0oIzI1LXByZWxvYWQtYmFzZWQtb24tdXNlci1pbnRlbnQpCjMuIFtTZXJ2ZXItU2lkZSBQZXJmb3JtYW5jZV0oIzMtc2VydmVyLXNpZGUtcGVyZm9ybWFuY2UpID8/KipISUdIKioKICAgLSAzLjEgW0F1dGhlbnRpY2F0ZSBTZXJ2ZXIgQWN0aW9ucyBMaWtlIEFQSSBSb3V0ZXNdKCMzMS1hdXRoZW50aWNhdGUtc2VydmVyLWFjdGlvbnMtbGlrZS1hcGktcm91dGVzKQogICAtIDMuMiBbQXZvaWQgRHVwbGljYXRlIFNlcmlhbGl6YXRpb24gaW4gUlNDIFByb3BzXSgjMzItYXZvaWQtZHVwbGljYXRlLXNlcmlhbGl6YXRpb24taW4tcnNjLXByb3BzKQogICAtIDMuMyBbQ3Jvc3MtUmVxdWVzdCBMUlUgQ2FjaGluZ10oIzMzLWNyb3NzLXJlcXVlc3QtbHJ1LWNhY2hpbmcpCiAgIC0gMy40IFtNaW5pbWl6ZSBTZXJpYWxpemF0aW9uIGF0IFJTQyBCb3VuZGFyaWVzXSgjMzQtbWluaW1pemUtc2VyaWFsaXphdGlvbi1hdC1yc2MtYm91bmRhcmllcykKICAgLSAzLjUgW1BhcmFsbGVsIERhdGEgRmV0Y2hpbmcgd2l0aCBDb21wb25lbnQgQ29tcG9zaXRpb25dKCMzNS1wYXJhbGxlbC1kYXRhLWZldGNoaW5nLXdpdGgtY29tcG9uZW50LWNvbXBvc2l0aW9uKQogICAtIDMuNiBbUGVyLVJlcXVlc3QgRGVkdXBsaWNhdGlvbiB3aXRoIFJlYWN0LmNhY2hlKCldKCMzNi1wZXItcmVxdWVzdC1kZWR1cGxpY2F0aW9uLXdpdGgtcmVhY3RjYWNoZSkKICAgLSAzLjcgW1VzZSBhZnRlcigpIGZvciBOb24tQmxvY2tpbmcgT3BlcmF0aW9uc10oIzM3LXVzZS1hZnRlci1mb3Itbm9uLWJsb2NraW5nLW9wZXJhdGlvbnMpCjQuIFtDbGllbnQtU2lkZSBEYXRhIEZldGNoaW5nXSgjNC1jbGllbnQtc2lkZS1kYXRhLWZldGNoaW5nKSA/PyoqTUVESVVNLUhJR0gqKgogICAtIDQuMSBbRGVkdXBsaWNhdGUgR2xvYmFsIEV2ZW50IExpc3RlbmVyc10oIzQxLWRlZHVwbGljYXRlLWdsb2JhbC1ldmVudC1saXN0ZW5lcnMpCiAgIC0gNC4yIFtVc2UgUGFzc2l2ZSBFdmVudCBMaXN0ZW5lcnMgZm9yIFNjcm9sbGluZyBQZXJmb3JtYW5jZV0oIzQyLXVzZS1wYXNzaXZlLWV2ZW50LWxpc3RlbmVycy1mb3Itc2Nyb2xsaW5nLXBlcmZvcm1hbmNlKQogICAtIDQuMyBbVXNlIFNXUiBmb3IgQXV0b21hdGljIERlZHVwbGljYXRpb25dKCM0My11c2Utc3dyLWZvci1hdXRvbWF0aWMtZGVkdXBsaWNhdGlvbikKICAgLSA0LjQgW1ZlcnNpb24gYW5kIE1pbmltaXplIGxvY2FsU3RvcmFnZSBEYXRhXSgjNDQtdmVyc2lvbi1hbmQtbWluaW1pemUtbG9jYWxzdG9yYWdlLWRhdGEpCjUuIFtSZS1yZW5kZXIgT3B0aW1pemF0aW9uXSgjNS1yZS1yZW5kZXItb3B0aW1pemF0aW9uKSA/PyoqTUVESVVNKioKICAgLSA1LjEgW0RlZmVyIFN0YXRlIFJlYWRzIHRvIFVzYWdlIFBvaW50XSgjNTEtZGVmZXItc3RhdGUtcmVhZHMtdG8tdXNhZ2UtcG9pbnQpCiAgIC0gNS4yIFtEbyBub3Qgd3JhcCBhIHNpbXBsZSBleHByZXNzaW9uIHdpdGggYSBwcmltaXRpdmUgcmVzdWx0IHR5cGUgaW4gdXNlTWVtb10oIzUyLWRvLW5vdC13cmFwLWEtc2ltcGxlLWV4cHJlc3Npb24td2l0aC1hLXByaW1pdGl2ZS1yZXN1bHQtdHlwZS1pbi11c2VtZW1vKQogICAtIDUuMyBbRXh0cmFjdCBEZWZhdWx0IE5vbi1wcmltaXRpdmUgUGFyYW1ldGVyIFZhbHVlIGZyb20gTWVtb2l6ZWQgQ29tcG9uZW50IHRvIENvbnN0YW50XSgjNTMtZXh0cmFjdC1kZWZhdWx0LW5vbi1wcmltaXRpdmUtcGFyYW1ldGVyLXZhbHVlLWZyb20tbWVtb2l6ZWQtY29tcG9uZW50LXRvLWNvbnN0YW50KQogICAtIDUuNCBbRXh0cmFjdCB0byBNZW1vaXplZCBDb21wb25lbnRzXSgjNTQtZXh0cmFjdC10by1tZW1vaXplZC1jb21wb25lbnRzKQogICAtIDUuNSBbTmFycm93IEVmZmVjdCBEZXBlbmRlbmNpZXNdKCM1NS1uYXJyb3ctZWZmZWN0LWRlcGVuZGVuY2llcykKICAgLSA1LjYgW1N1YnNjcmliZSB0byBEZXJpdmVkIFN0YXRlXSgjNTYtc3Vic2NyaWJlLXRvLWRlcml2ZWQtc3RhdGUpCiAgIC0gNS43IFtVc2UgRnVuY3Rpb25hbCBzZXRTdGF0ZSBVcGRhdGVzXSgjNTctdXNlLWZ1bmN0aW9uYWwtc2V0c3RhdGUtdXBkYXRlcykKICAgLSA1LjggW1VzZSBMYXp5IFN0YXRlIEluaXRpYWxpemF0aW9uXSgjNTgtdXNlLWxhenktc3RhdGUtaW5pdGlhbGl6YXRpb24pCiAgIC0gNS45IFtVc2UgVHJhbnNpdGlvbnMgZm9yIE5vbi1VcmdlbnQgVXBkYXRlc10oIzU5LXVzZS10cmFuc2l0aW9ucy1mb3Itbm9uLXVyZ2VudC11cGRhdGVzKQo2LiBbUmVuZGVyaW5nIFBlcmZvcm1hbmNlXSgjNi1yZW5kZXJpbmctcGVyZm9ybWFuY2UpID8/KipNRURJVU0qKgogICAtIDYuMSBbQW5pbWF0ZSBTVkcgV3JhcHBlciBJbnN0ZWFkIG9mIFNWRyBFbGVtZW50XSgjNjEtYW5pbWF0ZS1zdmctd3JhcHBlci1pbnN0ZWFkLW9mLXN2Zy1lbGVtZW50KQogICAtIDYuMiBbQ1NTIGNvbnRlbnQtdmlzaWJpbGl0eSBmb3IgTG9uZyBMaXN0c10oIzYyLWNzcy1jb250ZW50LXZpc2liaWxpdHktZm9yLWxvbmctbGlzdHMpCiAgIC0gNi4zIFtIb2lzdCBTdGF0aWMgSlNYIEVsZW1lbnRzXSgjNjMtaG9pc3Qtc3RhdGljLWpzeC1lbGVtZW50cykKICAgLSA2LjQgW09wdGltaXplIFNWRyBQcmVjaXNpb25dKCM2NC1vcHRpbWl6ZS1zdmctcHJlY2lzaW9uKQogICAtIDYuNSBbUHJldmVudCBIeWRyYXRpb24gTWlzbWF0Y2ggV2l0aG91dCBGbGlja2VyaW5nXSgjNjUtcHJldmVudC1oeWRyYXRpb24tbWlzbWF0Y2gtd2l0aG91dC1mbGlja2VyaW5nKQogICAtIDYuNiBbVXNlIEFjdGl2aXR5IENvbXBvbmVudCBmb3IgU2hvdy9IaWRlXSgjNjYtdXNlLWFjdGl2aXR5LWNvbXBvbmVudC1mb3Itc2hvd2hpZGUpCiAgIC0gNi43IFtVc2UgRXhwbGljaXQgQ29uZGl0aW9uYWwgUmVuZGVyaW5nXSgjNjctdXNlLWV4cGxpY2l0LWNvbmRpdGlvbmFsLXJlbmRlcmluZykKICAgLSA2LjggW1VzZSB1c2VUcmFuc2l0aW9uIE92ZXIgTWFudWFsIExvYWRpbmcgU3RhdGVzXSgjNjgtdXNlLXVzZXRyYW5zaXRpb24tb3Zlci1tYW51YWwtbG9hZGluZy1zdGF0ZXMpCjcuIFtKYXZhU2NyaXB0IFBlcmZvcm1hbmNlXSgjNy1qYXZhc2NyaXB0LXBlcmZvcm1hbmNlKSA/PyoqTE9XLU1FRElVTSoqCiAgIC0gNy4xIFtBdm9pZCBMYXlvdXQgVGhyYXNoaW5nXSgjNzEtYXZvaWQtbGF5b3V0LXRocmFzaGluZykKICAgLSA3LjIgW0J1aWxkIEluZGV4IE1hcHMgZm9yIFJlcGVhdGVkIExvb2t1cHNdKCM3Mi1idWlsZC1pbmRleC1tYXBzLWZvci1yZXBlYXRlZC1sb29rdXBzKQogICAtIDcuMyBbQ2FjaGUgUHJvcGVydHkgQWNjZXNzIGluIExvb3BzXSgjNzMtY2FjaGUtcHJvcGVydHktYWNjZXNzLWluLWxvb3BzKQogICAtIDcuNCBbQ2FjaGUgUmVwZWF0ZWQgRnVuY3Rpb24gQ2FsbHNdKCM3NC1jYWNoZS1yZXBlYXRlZC1mdW5jdGlvbi1jYWxscykKICAgLSA3LjUgW0NhY2hlIFN0b3JhZ2UgQVBJIENhbGxzXSgjNzUtY2FjaGUtc3RvcmFnZS1hcGktY2FsbHMpCiAgIC0gNy42IFtDb21iaW5lIE11bHRpcGxlIEFycmF5IEl0ZXJhdGlvbnNdKCM3Ni1jb21iaW5lLW11bHRpcGxlLWFycmF5LWl0ZXJhdGlvbnMpCiAgIC0gNy43IFtFYXJseSBMZW5ndGggQ2hlY2sgZm9yIEFycmF5IENvbXBhcmlzb25zXSgjNzctZWFybHktbGVuZ3RoLWNoZWNrLWZvci1hcnJheS1jb21wYXJpc29ucykKICAgLSA3LjggW0Vhcmx5IFJldHVybiBmcm9tIEZ1bmN0aW9uc10oIzc4LWVhcmx5LXJldHVybi1mcm9tLWZ1bmN0aW9ucykKICAgLSA3LjkgW0hvaXN0IFJlZ0V4cCBDcmVhdGlvbl0oIzc5LWhvaXN0LXJlZ2V4cC1jcmVhdGlvbikKICAgLSA3LjEwIFtVc2UgTG9vcCBmb3IgTWluL01heCBJbnN0ZWFkIG9mIFNvcnRdKCM3MTAtdXNlLWxvb3AtZm9yLW1pbm1heC1pbnN0ZWFkLW9mLXNvcnQpCiAgIC0gNy4xMSBbVXNlIFNldC9NYXAgZm9yIE8oMSkgTG9va3Vwc10oIzcxMS11c2Utc2V0bWFwLWZvci1vMS1sb29rdXBzKQogICAtIDcuMTIgW1VzZSB0b1NvcnRlZCgpIEluc3RlYWQgb2Ygc29ydCgpIGZvciBJbW11dGFiaWxpdHldKCM3MTItdXNlLXRvc29ydGVkLWluc3RlYWQtb2Ytc29ydC1mb3ItaW1tdXRhYmlsaXR5KQo4LiBbQWR2YW5jZWQgUGF0dGVybnNdKCM4LWFkdmFuY2VkLXBhdHRlcm5zKSA/PyoqTE9XKioKICAgLSA4LjEgW1N0b3JlIEV2ZW50IEhhbmRsZXJzIGluIFJlZnNdKCM4MS1zdG9yZS1ldmVudC1oYW5kbGVycy1pbi1yZWZzKQogICAtIDguMiBbdXNlRWZmZWN0RXZlbnQgZm9yIFN0YWJsZSBDYWxsYmFjayBSZWZzXSgjODItdXNlZWZmZWN0ZXZlbnQtZm9yLXN0YWJsZS1jYWxsYmFjay1yZWZzKQoKLS0tCgojIyAxLiBFbGltaW5hdGluZyBXYXRlcmZhbGxzCgoqKkltcGFjdDogQ1JJVElDQUwqKgoKV2F0ZXJmYWxscyBhcmUgdGhlICMxIHBlcmZvcm1hbmNlIGtpbGxlci4gRWFjaCBzZXF1ZW50aWFsIGF3YWl0IGFkZHMgZnVsbCBuZXR3b3JrIGxhdGVuY3kuIEVsaW1pbmF0aW5nIHRoZW0geWllbGRzIHRoZSBsYXJnZXN0IGdhaW5zLgoKIyMjIDEuMSBEZWZlciBBd2FpdCBVbnRpbCBOZWVkZWQKCioqSW1wYWN0OiBISUdIIChhdm9pZHMgYmxvY2tpbmcgdW51c2VkIGNvZGUgcGF0aHMpKioKCk1vdmUgYGF3YWl0YCBvcGVyYXRpb25zIGludG8gdGhlIGJyYW5jaGVzIHdoZXJlIHRoZXkncmUgYWN0dWFsbHkgdXNlZCB0byBhdm9pZCBibG9ja2luZyBjb2RlIHBhdGhzIHRoYXQgZG9uJ3QgbmVlZCB0aGVtLgoKKipJbmNvcnJlY3Q6IGJsb2NrcyBib3RoIGJyYW5jaGVzKioKCmBgYHR5cGVzY3JpcHQKYXN5bmMgZnVuY3Rpb24gaGFuZGxlUmVxdWVzdCh1c2VySWQ6IHN0cmluZywgc2tpcFByb2Nlc3Npbmc6IGJvb2xlYW4pIHsKICBjb25zdCB1c2VyRGF0YSA9IGF3YWl0IGZldGNoVXNlckRhdGEodXNlcklkKQogIAogIGlmIChza2lwUHJvY2Vzc2luZykgewogICAgLy8gUmV0dXJucyBpbW1lZGlhdGVseSBidXQgc3RpbGwgd2FpdGVkIGZvciB1c2VyRGF0YQogICAgcmV0dXJuIHsgc2tpcHBlZDogdHJ1ZSB9CiAgfQogIAogIC8vIE9ubHkgdGhpcyBicmFuY2ggdXNlcyB1c2VyRGF0YQogIHJldHVybiBwcm9jZXNzVXNlckRhdGEodXNlckRhdGEpCn0KYGBgCgoqKkNvcnJlY3Q6IG9ubHkgYmxvY2tzIHdoZW4gbmVlZGVkKioKCmBgYHR5cGVzY3JpcHQKYXN5bmMgZnVuY3Rpb24gaGFuZGxlUmVxdWVzdCh1c2VySWQ6IHN0cmluZywgc2tpcFByb2Nlc3Npbmc6IGJvb2xlYW4pIHsKICBpZiAoc2tpcFByb2Nlc3NpbmcpIHsKICAgIC8vIFJldHVybnMgaW1tZWRpYXRlbHkgd2l0aG91dCB3YWl0aW5nCiAgICByZXR1cm4geyBza2lwcGVkOiB0cnVlIH0KICB9CiAgCiAgLy8gRmV0Y2ggb25seSB3aGVuIG5lZWRlZAogIGNvbnN0IHVzZXJEYXRhID0gYXdhaXQgZmV0Y2hVc2VyRGF0YSh1c2VySWQpCiAgcmV0dXJuIHByb2Nlc3NVc2VyRGF0YSh1c2VyRGF0YSkKfQpgYGAKCioqQW5vdGhlciBleGFtcGxlOiBlYXJseSByZXR1cm4gb3B0aW1pemF0aW9uKioKCmBgYHR5cGVzY3JpcHQKLy8gSW5jb3JyZWN0OiBhbHdheXMgZmV0Y2hlcyBwZXJtaXNzaW9ucwphc3luYyBmdW5jdGlvbiB1cGRhdGVSZXNvdXJjZShyZXNvdXJjZUlkOiBzdHJpbmcsIHVzZXJJZDogc3RyaW5nKSB7CiAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCBmZXRjaFBlcm1pc3Npb25zKHVzZXJJZCkKICBjb25zdCByZXNvdXJjZSA9IGF3YWl0IGdldFJlc291cmNlKHJlc291cmNlSWQpCiAgCiAgaWYgKCFyZXNvdXJjZSkgewogICAgcmV0dXJuIHsgZXJyb3I6ICdOb3QgZm91bmQnIH0KICB9CiAgCiAgaWYgKCFwZXJtaXNzaW9ucy5jYW5FZGl0KSB7CiAgICByZXR1cm4geyBlcnJvcjogJ0ZvcmJpZGRlbicgfQogIH0KICAKICByZXR1cm4gYXdhaXQgdXBkYXRlUmVzb3VyY2VEYXRhKHJlc291cmNlLCBwZXJtaXNzaW9ucykKfQoKLy8gQ29ycmVjdDogZmV0Y2hlcyBvbmx5IHdoZW4gbmVlZGVkCmFzeW5jIGZ1bmN0aW9uIHVwZGF0ZVJlc291cmNlKHJlc291cmNlSWQ6IHN0cmluZywgdXNlcklkOiBzdHJpbmcpIHsKICBjb25zdCByZXNvdXJjZSA9IGF3YWl0IGdldFJlc291cmNlKHJlc291cmNlSWQpCiAgCiAgaWYgKCFyZXNvdXJjZSkgewogICAgcmV0dXJuIHsgZXJyb3I6ICdOb3QgZm91bmQnIH0KICB9CiAgCiAgY29uc3QgcGVybWlzc2lvbnMgPSBhd2FpdCBmZXRjaFBlcm1pc3Npb25zKHVzZXJJZCkKICAKICBpZiAoIXBlcm1pc3Npb25zLmNhbkVkaXQpIHsKICAgIHJldHVybiB7IGVycm9yOiAnRm9yYmlkZGVuJyB9CiAgfQogIAogIHJldHVybiBhd2FpdCB1cGRhdGVSZXNvdXJjZURhdGEocmVzb3VyY2UsIHBlcm1pc3Npb25zKQp9CmBgYAoKVGhpcyBvcHRpbWl6YXRpb24gaXMgZXNwZWNpYWxseSB2YWx1YWJsZSB3aGVuIHRoZSBza2lwcGVkIGJyYW5jaCBpcyBmcmVxdWVudGx5IHRha2VuLCBvciB3aGVuIHRoZSBkZWZlcnJlZCBvcGVyYXRpb24gaXMgZXhwZW5zaXZlLgoKIyMjIDEuMiBEZXBlbmRlbmN5LUJhc2VkIFBhcmFsbGVsaXphdGlvbgoKKipJbXBhY3Q6IENSSVRJQ0FMICgyLTEww5cgaW1wcm92ZW1lbnQpKioKCkZvciBvcGVyYXRpb25zIHdpdGggcGFydGlhbCBkZXBlbmRlbmNpZXMsIHVzZSBgYmV0dGVyLWFsbGAgdG8gbWF4aW1pemUgcGFyYWxsZWxpc20uIEl0IGF1dG9tYXRpY2FsbHkgc3RhcnRzIGVhY2ggdGFzayBhdCB0aGUgZWFybGllc3QgcG9zc2libGUgbW9tZW50LgoKKipJbmNvcnJlY3Q6IHByb2ZpbGUgd2FpdHMgZm9yIGNvbmZpZyB1bm5lY2Vzc2FyaWx5KioKCmBgYHR5cGVzY3JpcHQKY29uc3QgW3VzZXIsIGNvbmZpZ10gPSBhd2FpdCBQcm9taXNlLmFsbChbCiAgZmV0Y2hVc2VyKCksCiAgZmV0Y2hDb25maWcoKQpdKQpjb25zdCBwcm9maWxlID0gYXdhaXQgZmV0Y2hQcm9maWxlKHVzZXIuaWQpCmBgYAoKKipDb3JyZWN0OiBjb25maWcgYW5kIHByb2ZpbGUgcnVuIGluIHBhcmFsbGVsKioKCmBgYHR5cGVzY3JpcHQKaW1wb3J0IHsgYWxsIH0gZnJvbSAnYmV0dGVyLWFsbCcKCmNvbnN0IHsgdXNlciwgY29uZmlnLCBwcm9maWxlIH0gPSBhd2FpdCBhbGwoewogIGFzeW5jIHVzZXIoKSB7IHJldHVybiBmZXRjaFVzZXIoKSB9LAogIGFzeW5jIGNvbmZpZygpIHsgcmV0dXJuIGZldGNoQ29uZmlnKCkgfSwKICBhc3luYyBwcm9maWxlKCkgewogICAgcmV0dXJuIGZldGNoUHJvZmlsZSgoYXdhaXQgdGhpcy4kLnVzZXIpLmlkKQogIH0KfSkKYGBgCgoqKkFsdGVybmF0aXZlIHdpdGhvdXQgZXh0cmEgZGVwZW5kZW5jaWVzOioqCgpgYGB0eXBlc2NyaXB0CmNvbnN0IHVzZXJQcm9taXNlID0gZmV0Y2hVc2VyKCkKY29uc3QgcHJvZmlsZVByb21pc2UgPSB1c2VyUHJvbWlzZS50aGVuKHVzZXIgPT4gZmV0Y2hQcm9maWxlKHVzZXIuaWQpKQoKY29uc3QgW3VzZXIsIGNvbmZpZywgcHJvZmlsZV0gPSBhd2FpdCBQcm9taXNlLmFsbChbCiAgdXNlclByb21pc2UsCiAgZmV0Y2hDb25maWcoKSwKICBwcm9maWxlUHJvbWlzZQpdKQpgYGAKCldlIGNhbiBhbHNvIGNyZWF0ZSBhbGwgdGhlIHByb21pc2VzIGZpcnN0LCBhbmQgZG8gYFByb21pc2UuYWxsKClgIGF0IHRoZSBlbmQuCgpSZWZlcmVuY2U6IFtodHRwczovL2dpdGh1Yi5jb20vc2h1ZGluZy9iZXR0ZXItYWxsXShodHRwczovL2dpdGh1Yi5jb20vc2h1ZGluZy9iZXR0ZXItYWxsKQoKIyMjIDEuMyBQcmV2ZW50IFdhdGVyZmFsbCBDaGFpbnMgaW4gQVBJIFJvdXRlcwoKKipJbXBhY3Q6IENSSVRJQ0FMICgyLTEww5cgaW1wcm92ZW1lbnQpKioKCkluIEFQSSByb3V0ZXMgYW5kIFNlcnZlciBBY3Rpb25zLCBzdGFydCBpbmRlcGVuZGVudCBvcGVyYXRpb25zIGltbWVkaWF0ZWx5LCBldmVuIGlmIHlvdSBkb24ndCBhd2FpdCB0aGVtIHlldC4KCioqSW5jb3JyZWN0OiBjb25maWcgd2FpdHMgZm9yIGF1dGgsIGRhdGEgd2FpdHMgZm9yIGJvdGgqKgoKYGBgdHlwZXNjcmlwdApleHBvcnQgYXN5bmMgZnVuY3Rpb24gR0VUKHJlcXVlc3Q6IFJlcXVlc3QpIHsKICBjb25zdCBzZXNzaW9uID0gYXdhaXQgYXV0aCgpCiAgY29uc3QgY29uZmlnID0gYXdhaXQgZmV0Y2hDb25maWcoKQogIGNvbnN0IGRhdGEgPSBhd2FpdCBmZXRjaERhdGEoc2Vzc2lvbi51c2VyLmlkKQogIHJldHVybiBSZXNwb25zZS5qc29uKHsgZGF0YSwgY29uZmlnIH0pCn0KYGBgCgoqKkNvcnJlY3Q6IGF1dGggYW5kIGNvbmZpZyBzdGFydCBpbW1lZGlhdGVseSoqCgpgYGB0eXBlc2NyaXB0CmV4cG9ydCBhc3luYyBmdW5jdGlvbiBHRVQocmVxdWVzdDogUmVxdWVzdCkgewogIGNvbnN0IHNlc3Npb25Qcm9taXNlID0gYXV0aCgpCiAgY29uc3QgY29uZmlnUHJvbWlzZSA9IGZldGNoQ29uZmlnKCkKICBjb25zdCBzZXNzaW9uID0gYXdhaXQgc2Vzc2lvblByb21pc2UKICBjb25zdCBbY29uZmlnLCBkYXRhXSA9IGF3YWl0IFByb21pc2UuYWxsKFsKICAgIGNvbmZpZ1Byb21pc2UsCiAgICBmZXRjaERhdGEoc2Vzc2lvbi51c2VyLmlkKQogIF0pCiAgcmV0dXJuIFJlc3BvbnNlLmpzb24oeyBkYXRhLCBjb25maWcgfSkKfQpgYGAKCkZvciBvcGVyYXRpb25zIHdpdGggbW9yZSBjb21wbGV4IGRlcGVuZGVuY3kgY2hhaW5zLCB1c2UgYGJldHRlci1hbGxgIHRvIGF1dG9tYXRpY2FsbHkgbWF4aW1pemUgcGFyYWxsZWxpc20gKHNlZSBEZXBlbmRlbmN5LUJhc2VkIFBhcmFsbGVsaXphdGlvbikuCgojIyMgMS40IFByb21pc2UuYWxsKCkgZm9yIEluZGVwZW5kZW50IE9wZXJhdGlvbnMKCioqSW1wYWN0OiBDUklUSUNBTCAoMi0xMMOXIGltcHJvdmVtZW50KSoqCgpXaGVuIGFzeW5jIG9wZXJhdGlvbnMgaGF2ZSBubyBpbnRlcmRlcGVuZGVuY2llcywgZXhlY3V0ZSB0aGVtIGNvbmN1cnJlbnRseSB1c2luZyBgUHJvbWlzZS5hbGwoKWAuCgoqKkluY29ycmVjdDogc2VxdWVudGlhbCBleGVjdXRpb24sIDMgcm91bmQgdHJpcHMqKgoKYGBgdHlwZXNjcmlwdApjb25zdCB1c2VyID0gYXdhaXQgZmV0Y2hVc2VyKCkKY29uc3QgcG9zdHMgPSBhd2FpdCBmZXRjaFBvc3RzKCkKY29uc3QgY29tbWVudHMgPSBhd2FpdCBmZXRjaENvbW1lbnRzKCkKYGBgCgoqKkNvcnJlY3Q6IHBhcmFsbGVsIGV4ZWN1dGlvbiwgMSByb3VuZCB0cmlwKioKCmBgYHR5cGVzY3JpcHQKY29uc3QgW3VzZXIsIHBvc3RzLCBjb21tZW50c10gPSBhd2FpdCBQcm9taXNlLmFsbChbCiAgZmV0Y2hVc2VyKCksCiAgZmV0Y2hQb3N0cygpLAogIGZldGNoQ29tbWVudHMoKQpdKQpgYGAKCiMjIyAxLjUgU3RyYXRlZ2ljIFN1c3BlbnNlIEJvdW5kYXJpZXMKCioqSW1wYWN0OiBISUdIIChmYXN0ZXIgaW5pdGlhbCBwYWludCkqKgoKSW5zdGVhZCBvZiBhd2FpdGluZyBkYXRhIGluIGFzeW5jIGNvbXBvbmVudHMgYmVmb3JlIHJldHVybmluZyBKU1gsIHVzZSBTdXNwZW5zZSBib3VuZGFyaWVzIHRvIHNob3cgdGhlIHdyYXBwZXIgVUkgZmFzdGVyIHdoaWxlIGRhdGEgbG9hZHMuCgoqKkluY29ycmVjdDogd3JhcHBlciBibG9ja2VkIGJ5IGRhdGEgZmV0Y2hpbmcqKgoKYGBgdHN4CmFzeW5jIGZ1bmN0aW9uIFBhZ2UoKSB7CiAgY29uc3QgZGF0YSA9IGF3YWl0IGZldGNoRGF0YSgpIC8vIEJsb2NrcyBlbnRpcmUgcGFnZQogIAogIHJldHVybiAoCiAgICA8ZGl2PgogICAgICA8ZGl2PlNpZGViYXI8L2Rpdj4KICAgICAgPGRpdj5IZWFkZXI8L2Rpdj4KICAgICAgPGRpdj4KICAgICAgICA8RGF0YURpc3BsYXkgZGF0YT17ZGF0YX0gLz4KICAgICAgPC9kaXY+CiAgICAgIDxkaXY+Rm9vdGVyPC9kaXY+CiAgICA8L2Rpdj4KICApCn0KYGBgCgpUaGUgZW50aXJlIGxheW91dCB3YWl0cyBmb3IgZGF0YSBldmVuIHRob3VnaCBvbmx5IHRoZSBtaWRkbGUgc2VjdGlvbiBuZWVkcyBpdC4KCioqQ29ycmVjdDogd3JhcHBlciBzaG93cyBpbW1lZGlhdGVseSwgZGF0YSBzdHJlYW1zIGluKioKCmBgYHRzeApmdW5jdGlvbiBQYWdlKCkgewogIHJldHVybiAoCiAgICA8ZGl2PgogICAgICA8ZGl2PlNpZGViYXI8L2Rpdj4KICAgICAgPGRpdj5IZWFkZXI8L2Rpdj4KICAgICAgPGRpdj4KICAgICAgICA8U3VzcGVuc2UgZmFsbGJhY2s9ezxTa2VsZXRvbiAvPn0+CiAgICAgICAgICA8RGF0YURpc3BsYXkgLz4KICAgICAgICA8L1N1c3BlbnNlPgogICAgICA8L2Rpdj4KICAgICAgPGRpdj5Gb290ZXI8L2Rpdj4KICAgIDwvZGl2PgogICkKfQoKYXN5bmMgZnVuY3Rpb24gRGF0YURpc3BsYXkoKSB7CiAgY29uc3QgZGF0YSA9IGF3YWl0IGZldGNoRGF0YSgpIC8vIE9ubHkgYmxvY2tzIHRoaXMgY29tcG9uZW50CiAgcmV0dXJuIDxkaXY+e2RhdGEuY29udGVudH08L2Rpdj4KfQpgYGAKClNpZGViYXIsIEhlYWRlciwgYW5kIEZvb3RlciByZW5kZXIgaW1tZWRpYXRlbHkuIE9ubHkgRGF0YURpc3BsYXkgd2FpdHMgZm9yIGRhdGEuCgoqKkFsdGVybmF0aXZlOiBzaGFyZSBwcm9taXNlIGFjcm9zcyBjb21wb25lbnRzKioKCmBgYHRzeApmdW5jdGlvbiBQYWdlKCkgewogIC8vIFN0YXJ0IGZldGNoIGltbWVkaWF0ZWx5LCBidXQgZG9uJ3QgYXdhaXQKICBjb25zdCBkYXRhUHJvbWlzZSA9IGZldGNoRGF0YSgpCiAgCiAgcmV0dXJuICgKICAgIDxkaXY+CiAgICAgIDxkaXY+U2lkZWJhcjwvZGl2PgogICAgICA8ZGl2PkhlYWRlcjwvZGl2PgogICAgICA8U3VzcGVuc2UgZmFsbGJhY2s9ezxTa2VsZXRvbiAvPn0+CiAgICAgICAgPERhdGFEaXNwbGF5IGRhdGFQcm9taXNlPXtkYXRhUHJvbWlzZX0gLz4KICAgICAgICA8RGF0YVN1bW1hcnkgZGF0YVByb21pc2U9e2RhdGFQcm9taXNlfSAvPgogICAgICA8L1N1c3BlbnNlPgogICAgICA8ZGl2PkZvb3RlcjwvZGl2PgogICAgPC9kaXY+CiAgKQp9CgpmdW5jdGlvbiBEYXRhRGlzcGxheSh7IGRhdGFQcm9taXNlIH06IHsgZGF0YVByb21pc2U6IFByb21pc2U8RGF0YT4gfSkgewogIGNvbnN0IGRhdGEgPSB1c2UoZGF0YVByb21pc2UpIC8vIFVud3JhcHMgdGhlIHByb21pc2UKICByZXR1cm4gPGRpdj57ZGF0YS5jb250ZW50fTwvZGl2Pgp9CgpmdW5jdGlvbiBEYXRhU3VtbWFyeSh7IGRhdGFQcm9taXNlIH06IHsgZGF0YVByb21pc2U6IFByb21pc2U8RGF0YT4gfSkgewogIGNvbnN0IGRhdGEgPSB1c2UoZGF0YVByb21pc2UpIC8vIFJldXNlcyB0aGUgc2FtZSBwcm9taXNlCiAgcmV0dXJuIDxkaXY+e2RhdGEuc3VtbWFyeX08L2Rpdj4KfQpgYGAKCkJvdGggY29tcG9uZW50cyBzaGFyZSB0aGUgc2FtZSBwcm9taXNlLCBzbyBvbmx5IG9uZSBmZXRjaCBvY2N1cnMuIExheW91dCByZW5kZXJzIGltbWVkaWF0ZWx5IHdoaWxlIGJvdGggY29tcG9uZW50cyB3YWl0IHRvZ2V0aGVyLgoKKipXaGVuIE5PVCB0byB1c2UgdGhpcyBwYXR0ZXJuOioqCgotIENyaXRpY2FsIGRhdGEgbmVlZGVkIGZvciBsYXlvdXQgZGVjaXNpb25zIChhZmZlY3RzIHBvc2l0aW9uaW5nKQoKLSBTRU8tY3JpdGljYWwgY29udGVudCBhYm92ZSB0aGUgZm9sZAoKLSBTbWFsbCwgZmFzdCBxdWVyaWVzIHdoZXJlIHN1c3BlbnNlIG92ZXJoZWFkIGlzbid0IHdvcnRoIGl0CgotIFdoZW4geW91IHdhbnQgdG8gYXZvaWQgbGF5b3V0IHNoaWZ0IChsb2FkaW5nID8/Y29udGVudCBqdW1wKQoKKipUcmFkZS1vZmY6KiogRmFzdGVyIGluaXRpYWwgcGFpbnQgdnMgcG90ZW50aWFsIGxheW91dCBzaGlmdC4gQ2hvb3NlIGJhc2VkIG9uIHlvdXIgVVggcHJpb3JpdGllcy4KCi0tLQoKIyMgMi4gQnVuZGxlIFNpemUgT3B0aW1pemF0aW9uCgoqKkltcGFjdDogQ1JJVElDQUwqKgoKUmVkdWNpbmcgaW5pdGlhbCBidW5kbGUgc2l6ZSBpbXByb3ZlcyBUaW1lIHRvIEludGVyYWN0aXZlIGFuZCBMYXJnZXN0IENvbnRlbnRmdWwgUGFpbnQuCgojIyMgMi4xIEF2b2lkIEJhcnJlbCBGaWxlIEltcG9ydHMKCioqSW1wYWN0OiBDUklUSUNBTCAoMjAwLTgwMG1zIGltcG9ydCBjb3N0LCBzbG93IGJ1aWxkcykqKgoKSW1wb3J0IGRpcmVjdGx5IGZyb20gc291cmNlIGZpbGVzIGluc3RlYWQgb2YgYmFycmVsIGZpbGVzIHRvIGF2b2lkIGxvYWRpbmcgdGhvdXNhbmRzIG9mIHVudXNlZCBtb2R1bGVzLiAqKkJhcnJlbCBmaWxlcyoqIGFyZSBlbnRyeSBwb2ludHMgdGhhdCByZS1leHBvcnQgbXVsdGlwbGUgbW9kdWxlcyAoZS5nLiwgYGluZGV4LmpzYCB0aGF0IGRvZXMgYGV4cG9ydCAqIGZyb20gJy4vbW9kdWxlJ2ApLgoKUG9wdWxhciBpY29uIGFuZCBjb21wb25lbnQgbGlicmFyaWVzIGNhbiBoYXZlICoqdXAgdG8gMTAsMDAwIHJlLWV4cG9ydHMqKiBpbiB0aGVpciBlbnRyeSBmaWxlLiBGb3IgbWFueSBSZWFjdCBwYWNrYWdlcywgKippdCB0YWtlcyAyMDAtODAwbXMganVzdCB0byBpbXBvcnQgdGhlbSoqLCBhZmZlY3RpbmcgYm90aCBkZXZlbG9wbWVudCBzcGVlZCBhbmQgcHJvZHVjdGlvbiBjb2xkIHN0YXJ0cy4KCioqV2h5IHRyZWUtc2hha2luZyBkb2Vzbid0IGhlbHA6KiogV2hlbiBhIGxpYnJhcnkgaXMgbWFya2VkIGFzIGV4dGVybmFsIChub3QgYnVuZGxlZCksIHRoZSBidW5kbGVyIGNhbid0IG9wdGltaXplIGl0LiBJZiB5b3UgYnVuZGxlIGl0IHRvIGVuYWJsZSB0cmVlLXNoYWtpbmcsIGJ1aWxkcyBiZWNvbWUgc3Vic3RhbnRpYWxseSBzbG93ZXIgYW5hbHl6aW5nIHRoZSBlbnRpcmUgbW9kdWxlIGdyYXBoLgoKKipJbmNvcnJlY3Q6IGltcG9ydHMgZW50aXJlIGxpYnJhcnkqKgoKYGBgdHN4CmltcG9ydCB7IENoZWNrLCBYLCBNZW51IH0gZnJvbSAnbHVjaWRlLXJlYWN0JwovLyBMb2FkcyAxLDU4MyBtb2R1bGVzLCB0YWtlcyB+Mi44cyBleHRyYSBpbiBkZXYKLy8gUnVudGltZSBjb3N0OiAyMDAtODAwbXMgb24gZXZlcnkgY29sZCBzdGFydAoKaW1wb3J0IHsgQnV0dG9uLCBUZXh0RmllbGQgfSBmcm9tICdAbXVpL21hdGVyaWFsJwovLyBMb2FkcyAyLDIyNSBtb2R1bGVzLCB0YWtlcyB+NC4ycyBleHRyYSBpbiBkZXYKYGBgCgoqKkNvcnJlY3Q6IGltcG9ydHMgb25seSB3aGF0IHlvdSBuZWVkKioKCmBgYHRzeAppbXBvcnQgQ2hlY2sgZnJvbSAnbHVjaWRlLXJlYWN0L2Rpc3QvZXNtL2ljb25zL2NoZWNrJwppbXBvcnQgWCBmcm9tICdsdWNpZGUtcmVhY3QvZGlzdC9lc20vaWNvbnMveCcKaW1wb3J0IE1lbnUgZnJvbSAnbHVjaWRlLXJlYWN0L2Rpc3QvZXNtL2ljb25zL21lbnUnCi8vIExvYWRzIG9ubHkgMyBtb2R1bGVzICh+MktCIHZzIH4xTUIpCgppbXBvcnQgQnV0dG9uIGZyb20gJ0BtdWkvbWF0ZXJpYWwvQnV0dG9uJwppbXBvcnQgVGV4dEZpZWxkIGZyb20gJ0BtdWkvbWF0ZXJpYWwvVGV4dEZpZWxkJwovLyBMb2FkcyBvbmx5IHdoYXQgeW91IHVzZQpgYGAKCioqQWx0ZXJuYXRpdmU6IE5leHQuanMgMTMuNSsqKgoKYGBganMKLy8gbmV4dC5jb25maWcuanMgLSB1c2Ugb3B0aW1pemVQYWNrYWdlSW1wb3J0cwptb2R1bGUuZXhwb3J0cyA9IHsKICBleHBlcmltZW50YWw6IHsKICAgIG9wdGltaXplUGFja2FnZUltcG9ydHM6IFsnbHVjaWRlLXJlYWN0JywgJ0BtdWkvbWF0ZXJpYWwnXQogIH0KfQoKLy8gVGhlbiB5b3UgY2FuIGtlZXAgdGhlIGVyZ29ub21pYyBiYXJyZWwgaW1wb3J0czoKaW1wb3J0IHsgQ2hlY2ssIFgsIE1lbnUgfSBmcm9tICdsdWNpZGUtcmVhY3QnCi8vIEF1dG9tYXRpY2FsbHkgdHJhbnNmb3JtZWQgdG8gZGlyZWN0IGltcG9ydHMgYXQgYnVpbGQgdGltZQpgYGAKCkRpcmVjdCBpbXBvcnRzIHByb3ZpZGUgMTUtNzAlIGZhc3RlciBkZXYgYm9vdCwgMjglIGZhc3RlciBidWlsZHMsIDQwJSBmYXN0ZXIgY29sZCBzdGFydHMsIGFuZCBzaWduaWZpY2FudGx5IGZhc3RlciBITVIuCgpMaWJyYXJpZXMgY29tbW9ubHkgYWZmZWN0ZWQ6IGBsdWNpZGUtcmVhY3RgLCBgQG11aS9tYXRlcmlhbGAsIGBAbXVpL2ljb25zLW1hdGVyaWFsYCwgYEB0YWJsZXIvaWNvbnMtcmVhY3RgLCBgcmVhY3QtaWNvbnNgLCBgQGhlYWRsZXNzdWkvcmVhY3RgLCBgQHJhZGl4LXVpL3JlYWN0LSpgLCBgbG9kYXNoYCwgYHJhbWRhYCwgYGRhdGUtZm5zYCwgYHJ4anNgLCBgcmVhY3QtdXNlYC4KClJlZmVyZW5jZTogW2h0dHBzOi8vdmVyY2VsLmNvbS9ibG9nL2hvdy13ZS1vcHRpbWl6ZWQtcGFja2FnZS1pbXBvcnRzLWluLW5leHQtanNdKGh0dHBzOi8vdmVyY2VsLmNvbS9ibG9nL2hvdy13ZS1vcHRpbWl6ZWQtcGFja2FnZS1pbXBvcnRzLWluLW5leHQtanMpCgojIyMgMi4yIENvbmRpdGlvbmFsIE1vZHVsZSBMb2FkaW5nCgoqKkltcGFjdDogSElHSCAobG9hZHMgbGFyZ2UgZGF0YSBvbmx5IHdoZW4gbmVlZGVkKSoqCgpMb2FkIGxhcmdlIGRhdGEgb3IgbW9kdWxlcyBvbmx5IHdoZW4gYSBmZWF0dXJlIGlzIGFjdGl2YXRlZC4KCioqRXhhbXBsZTogbGF6eS1sb2FkIGFuaW1hdGlvbiBmcmFtZXMqKgoKYGBgdHN4CmZ1bmN0aW9uIEFuaW1hdGlvblBsYXllcih7IGVuYWJsZWQsIHNldEVuYWJsZWQgfTogeyBlbmFibGVkOiBib29sZWFuOyBzZXRFbmFibGVkOiBSZWFjdC5EaXNwYXRjaDxSZWFjdC5TZXRTdGF0ZUFjdGlvbjxib29sZWFuPj4gfSkgewogIGNvbnN0IFtmcmFtZXMsIHNldEZyYW1lc10gPSB1c2VTdGF0ZTxGcmFtZVtdIHwgbnVsbD4obnVsbCkKCiAgdXNlRWZmZWN0KCgpID0+IHsKICAgIGlmIChlbmFibGVkICYmICFmcmFtZXMgJiYgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCcpIHsKICAgICAgaW1wb3J0KCcuL2FuaW1hdGlvbi1mcmFtZXMuanMnKQogICAgICAgIC50aGVuKG1vZCA9PiBzZXRGcmFtZXMobW9kLmZyYW1lcykpCiAgICAgICAgLmNhdGNoKCgpID0+IHNldEVuYWJsZWQoZmFsc2UpKQogICAgfQogIH0sIFtlbmFibGVkLCBmcmFtZXMsIHNldEVuYWJsZWRdKQoKICBpZiAoIWZyYW1lcykgcmV0dXJuIDxTa2VsZXRvbiAvPgogIHJldHVybiA8Q2FudmFzIGZyYW1lcz17ZnJhbWVzfSAvPgp9CmBgYAoKVGhlIGB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJ2AgY2hlY2sgcHJldmVudHMgYnVuZGxpbmcgdGhpcyBtb2R1bGUgZm9yIFNTUiwgb3B0aW1pemluZyBzZXJ2ZXIgYnVuZGxlIHNpemUgYW5kIGJ1aWxkIHNwZWVkLgoKIyMjIDIuMyBEZWZlciBOb24tQ3JpdGljYWwgVGhpcmQtUGFydHkgTGlicmFyaWVzCgoqKkltcGFjdDogTUVESVVNIChsb2FkcyBhZnRlciBoeWRyYXRpb24pKioKCkFuYWx5dGljcywgbG9nZ2luZywgYW5kIGVycm9yIHRyYWNraW5nIGRvbid0IGJsb2NrIHVzZXIgaW50ZXJhY3Rpb24uIExvYWQgdGhlbSBhZnRlciBoeWRyYXRpb24uCgoqKkluY29ycmVjdDogYmxvY2tzIGluaXRpYWwgYnVuZGxlKioKCmBgYHRzeAppbXBvcnQgeyBBbmFseXRpY3MgfSBmcm9tICdAdmVyY2VsL2FuYWx5dGljcy9yZWFjdCcKCmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIFJvb3RMYXlvdXQoeyBjaGlsZHJlbiB9KSB7CiAgcmV0dXJuICgKICAgIDxodG1sPgogICAgICA8Ym9keT4KICAgICAgICB7Y2hpbGRyZW59CiAgICAgICAgPEFuYWx5dGljcyAvPgogICAgICA8L2JvZHk+CiAgICA8L2h0bWw+CiAgKQp9CmBgYAoKKipDb3JyZWN0OiBsb2FkcyBhZnRlciBoeWRyYXRpb24qKgoKYGBgdHN4CmltcG9ydCBkeW5hbWljIGZyb20gJ25leHQvZHluYW1pYycKCmNvbnN0IEFuYWx5dGljcyA9IGR5bmFtaWMoCiAgKCkgPT4gaW1wb3J0KCdAdmVyY2VsL2FuYWx5dGljcy9yZWFjdCcpLnRoZW4obSA9PiBtLkFuYWx5dGljcyksCiAgeyBzc3I6IGZhbHNlIH0KKQoKZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24gUm9vdExheW91dCh7IGNoaWxkcmVuIH0pIHsKICByZXR1cm4gKAogICAgPGh0bWw+CiAgICAgIDxib2R5PgogICAgICAgIHtjaGlsZHJlbn0KICAgICAgICA8QW5hbHl0aWNzIC8+CiAgICAgIDwvYm9keT4KICAgIDwvaHRtbD4KICApCn0KYGBgCgojIyMgMi40IER5bmFtaWMgSW1wb3J0cyBmb3IgSGVhdnkgQ29tcG9uZW50cwoKKipJbXBhY3Q6IENSSVRJQ0FMIChkaXJlY3RseSBhZmZlY3RzIFRUSSBhbmQgTENQKSoqCgpVc2UgYG5leHQvZHluYW1pY2AgdG8gbGF6eS1sb2FkIGxhcmdlIGNvbXBvbmVudHMgbm90IG5lZWRlZCBvbiBpbml0aWFsIHJlbmRlci4KCioqSW5jb3JyZWN0OiBNb25hY28gYnVuZGxlcyB3aXRoIG1haW4gY2h1bmsgfjMwMEtCKioKCmBgYHRzeAppbXBvcnQgeyBNb25hY29FZGl0b3IgfSBmcm9tICcuL21vbmFjby1lZGl0b3InCgpmdW5jdGlvbiBDb2RlUGFuZWwoeyBjb2RlIH06IHsgY29kZTogc3RyaW5nIH0pIHsKICByZXR1cm4gPE1vbmFjb0VkaXRvciB2YWx1ZT17Y29kZX0gLz4KfQpgYGAKCioqQ29ycmVjdDogTW9uYWNvIGxvYWRzIG9uIGRlbWFuZCoqCgpgYGB0c3gKaW1wb3J0IGR5bmFtaWMgZnJvbSAnbmV4dC9keW5hbWljJwoKY29uc3QgTW9uYWNvRWRpdG9yID0gZHluYW1pYygKICAoKSA9PiBpbXBvcnQoJy4vbW9uYWNvLWVkaXRvcicpLnRoZW4obSA9PiBtLk1vbmFjb0VkaXRvciksCiAgeyBzc3I6IGZhbHNlIH0KKQoKZnVuY3Rpb24gQ29kZVBhbmVsKHsgY29kZSB9OiB7IGNvZGU6IHN0cmluZyB9KSB7CiAgcmV0dXJuIDxNb25hY29FZGl0b3IgdmFsdWU9e2NvZGV9IC8+Cn0KYGBgCgojIyMgMi41IFByZWxvYWQgQmFzZWQgb24gVXNlciBJbnRlbnQKCioqSW1wYWN0OiBNRURJVU0gKHJlZHVjZXMgcGVyY2VpdmVkIGxhdGVuY3kpKioKClByZWxvYWQgaGVhdnkgYnVuZGxlcyBiZWZvcmUgdGhleSdyZSBuZWVkZWQgdG8gcmVkdWNlIHBlcmNlaXZlZCBsYXRlbmN5LgoKKipFeGFtcGxlOiBwcmVsb2FkIG9uIGhvdmVyL2ZvY3VzKioKCmBgYHRzeApmdW5jdGlvbiBFZGl0b3JCdXR0b24oeyBvbkNsaWNrIH06IHsgb25DbGljazogKCkgPT4gdm9pZCB9KSB7CiAgY29uc3QgcHJlbG9hZCA9ICgpID0+IHsKICAgIGlmICh0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJykgewogICAgICB2b2lkIGltcG9ydCgnLi9tb25hY28tZWRpdG9yJykKICAgIH0KICB9CgogIHJldHVybiAoCiAgICA8YnV0dG9uCiAgICAgIG9uTW91c2VFbnRlcj17cHJlbG9hZH0KICAgICAgb25Gb2N1cz17cHJlbG9hZH0KICAgICAgb25DbGljaz17b25DbGlja30KICAgID4KICAgICAgT3BlbiBFZGl0b3IKICAgIDwvYnV0dG9uPgogICkKfQpgYGAKCioqRXhhbXBsZTogcHJlbG9hZCB3aGVuIGZlYXR1cmUgZmxhZyBpcyBlbmFibGVkKioKCmBgYHRzeApmdW5jdGlvbiBGbGFnc1Byb3ZpZGVyKHsgY2hpbGRyZW4sIGZsYWdzIH06IFByb3BzKSB7CiAgdXNlRWZmZWN0KCgpID0+IHsKICAgIGlmIChmbGFncy5lZGl0b3JFbmFibGVkICYmIHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnKSB7CiAgICAgIHZvaWQgaW1wb3J0KCcuL21vbmFjby1lZGl0b3InKS50aGVuKG1vZCA9PiBtb2QuaW5pdCgpKQogICAgfQogIH0sIFtmbGFncy5lZGl0b3JFbmFibGVkXSkKCiAgcmV0dXJuIDxGbGFnc0NvbnRleHQuUHJvdmlkZXIgdmFsdWU9e2ZsYWdzfT4KICAgIHtjaGlsZHJlbn0KICA8L0ZsYWdzQ29udGV4dC5Qcm92aWRlcj4KfQpgYGAKClRoZSBgdHlwZW9mIHdpbmRvdyAhPT0gJ3VuZGVmaW5lZCdgIGNoZWNrIHByZXZlbnRzIGJ1bmRsaW5nIHByZWxvYWRlZCBtb2R1bGVzIGZvciBTU1IsIG9wdGltaXppbmcgc2VydmVyIGJ1bmRsZSBzaXplIGFuZCBidWlsZCBzcGVlZC4KCi0tLQoKIyMgMy4gU2VydmVyLVNpZGUgUGVyZm9ybWFuY2UKCioqSW1wYWN0OiBISUdIKioKCk9wdGltaXppbmcgc2VydmVyLXNpZGUgcmVuZGVyaW5nIGFuZCBkYXRhIGZldGNoaW5nIGVsaW1pbmF0ZXMgc2VydmVyLXNpZGUgd2F0ZXJmYWxscyBhbmQgcmVkdWNlcyByZXNwb25zZSB0aW1lcy4KCiMjIyAzLjEgQXV0aGVudGljYXRlIFNlcnZlciBBY3Rpb25zIExpa2UgQVBJIFJvdXRlcwoKKipJbXBhY3Q6IENSSVRJQ0FMIChwcmV2ZW50cyB1bmF1dGhvcml6ZWQgYWNjZXNzIHRvIHNlcnZlciBtdXRhdGlvbnMpKioKClNlcnZlciBBY3Rpb25zIChmdW5jdGlvbnMgd2l0aCBgInVzZSBzZXJ2ZXIiYCkgYXJlIGV4cG9zZWQgYXMgcHVibGljIGVuZHBvaW50cywganVzdCBsaWtlIEFQSSByb3V0ZXMuIEFsd2F5cyB2ZXJpZnkgYXV0aGVudGljYXRpb24gYW5kIGF1dGhvcml6YXRpb24gKippbnNpZGUqKiBlYWNoIFNlcnZlciBBY3Rpb24/lGRvIG5vdCByZWx5IHNvbGVseSBvbiBtaWRkbGV3YXJlLCBsYXlvdXQgZ3VhcmRzLCBvciBwYWdlLWxldmVsIGNoZWNrcywgYXMgU2VydmVyIEFjdGlvbnMgY2FuIGJlIGludm9rZWQgZGlyZWN0bHkuCgpOZXh0LmpzIGRvY3VtZW50YXRpb24gZXhwbGljaXRseSBzdGF0ZXM6ICJUcmVhdCBTZXJ2ZXIgQWN0aW9ucyB3aXRoIHRoZSBzYW1lIHNlY3VyaXR5IGNvbnNpZGVyYXRpb25zIGFzIHB1YmxpYy1mYWNpbmcgQVBJIGVuZHBvaW50cywgYW5kIHZlcmlmeSBpZiB0aGUgdXNlciBpcyBhbGxvd2VkIHRvIHBlcmZvcm0gYSBtdXRhdGlvbi4iCgoqKkluY29ycmVjdDogbm8gYXV0aGVudGljYXRpb24gY2hlY2sqKgoKYGBgdHlwZXNjcmlwdAondXNlIHNlcnZlcicKCmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVVc2VyKHVzZXJJZDogc3RyaW5nKSB7CiAgLy8gQW55b25lIGNhbiBjYWxsIHRoaXMhIE5vIGF1dGggY2hlY2sKICBhd2FpdCBkYi51c2VyLmRlbGV0ZSh7IHdoZXJlOiB7IGlkOiB1c2VySWQgfSB9KQogIHJldHVybiB7IHN1Y2Nlc3M6IHRydWUgfQp9CmBgYAoKKipDb3JyZWN0OiBhdXRoZW50aWNhdGlvbiBpbnNpZGUgdGhlIGFjdGlvbioqCgpgYGB0eXBlc2NyaXB0Cid1c2Ugc2VydmVyJwoKaW1wb3J0IHsgdmVyaWZ5U2Vzc2lvbiB9IGZyb20gJ0AvbGliL2F1dGgnCmltcG9ydCB7IHVuYXV0aG9yaXplZCB9IGZyb20gJ0AvbGliL2Vycm9ycycKCmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVVc2VyKHVzZXJJZDogc3RyaW5nKSB7CiAgLy8gQWx3YXlzIGNoZWNrIGF1dGggaW5zaWRlIHRoZSBhY3Rpb24KICBjb25zdCBzZXNzaW9uID0gYXdhaXQgdmVyaWZ5U2Vzc2lvbigpCiAgCiAgaWYgKCFzZXNzaW9uKSB7CiAgICB0aHJvdyB1bmF1dGhvcml6ZWQoJ011c3QgYmUgbG9nZ2VkIGluJykKICB9CiAgCiAgLy8gQ2hlY2sgYXV0aG9yaXphdGlvbiB0b28KICBpZiAoc2Vzc2lvbi51c2VyLnJvbGUgIT09ICdhZG1pbicgJiYgc2Vzc2lvbi51c2VyLmlkICE9PSB1c2VySWQpIHsKICAgIHRocm93IHVuYXV0aG9yaXplZCgnQ2Fubm90IGRlbGV0ZSBvdGhlciB1c2VycycpCiAgfQogIAogIGF3YWl0IGRiLnVzZXIuZGVsZXRlKHsgd2hlcmU6IHsgaWQ6IHVzZXJJZCB9IH0pCiAgcmV0dXJuIHsgc3VjY2VzczogdHJ1ZSB9Cn0KYGBgCgoqKldpdGggaW5wdXQgdmFsaWRhdGlvbjoqKgoKYGBgdHlwZXNjcmlwdAondXNlIHNlcnZlcicKCmltcG9ydCB7IHZlcmlmeVNlc3Npb24gfSBmcm9tICdAL2xpYi9hdXRoJwppbXBvcnQgeyB6IH0gZnJvbSAnem9kJwoKY29uc3QgdXBkYXRlUHJvZmlsZVNjaGVtYSA9IHoub2JqZWN0KHsKICB1c2VySWQ6IHouc3RyaW5nKCkudXVpZCgpLAogIG5hbWU6IHouc3RyaW5nKCkubWluKDEpLm1heCgxMDApLAogIGVtYWlsOiB6LnN0cmluZygpLmVtYWlsKCkKfSkKCmV4cG9ydCBhc3luYyBmdW5jdGlvbiB1cGRhdGVQcm9maWxlKGRhdGE6IHVua25vd24pIHsKICAvLyBWYWxpZGF0ZSBpbnB1dCBmaXJzdAogIGNvbnN0IHZhbGlkYXRlZCA9IHVwZGF0ZVByb2ZpbGVTY2hlbWEucGFyc2UoZGF0YSkKICAKICAvLyBUaGVuIGF1dGhlbnRpY2F0ZQogIGNvbnN0IHNlc3Npb24gPSBhd2FpdCB2ZXJpZnlTZXNzaW9uKCkKICBpZiAoIXNlc3Npb24pIHsKICAgIHRocm93IG5ldyBFcnJvcignVW5hdXRob3JpemVkJykKICB9CiAgCiAgLy8gVGhlbiBhdXRob3JpemUKICBpZiAoc2Vzc2lvbi51c2VyLmlkICE9PSB2YWxpZGF0ZWQudXNlcklkKSB7CiAgICB0aHJvdyBuZXcgRXJyb3IoJ0NhbiBvbmx5IHVwZGF0ZSBvd24gcHJvZmlsZScpCiAgfQogIAogIC8vIEZpbmFsbHkgcGVyZm9ybSB0aGUgbXV0YXRpb24KICBhd2FpdCBkYi51c2VyLnVwZGF0ZSh7CiAgICB3aGVyZTogeyBpZDogdmFsaWRhdGVkLnVzZXJJZCB9LAogICAgZGF0YTogewogICAgICBuYW1lOiB2YWxpZGF0ZWQubmFtZSwKICAgICAgZW1haWw6IHZhbGlkYXRlZC5lbWFpbAogICAgfQogIH0pCiAgCiAgcmV0dXJuIHsgc3VjY2VzczogdHJ1ZSB9Cn0KYGBgCgpSZWZlcmVuY2U6IFtodHRwczovL25leHRqcy5vcmcvZG9jcy9hcHAvZ3VpZGVzL2F1dGhlbnRpY2F0aW9uXShodHRwczovL25leHRqcy5vcmcvZG9jcy9hcHAvZ3VpZGVzL2F1dGhlbnRpY2F0aW9uKQoKIyMjIDMuMiBBdm9pZCBEdXBsaWNhdGUgU2VyaWFsaXphdGlvbiBpbiBSU0MgUHJvcHMKCioqSW1wYWN0OiBMT1cgKHJlZHVjZXMgbmV0d29yayBwYXlsb2FkIGJ5IGF2b2lkaW5nIGR1cGxpY2F0ZSBzZXJpYWxpemF0aW9uKSoqCgpSU0M/kmNsaWVudCBzZXJpYWxpemF0aW9uIGRlZHVwbGljYXRlcyBieSBvYmplY3QgcmVmZXJlbmNlLCBub3QgdmFsdWUuIFNhbWUgcmVmZXJlbmNlID0gc2VyaWFsaXplZCBvbmNlOyBuZXcgcmVmZXJlbmNlID0gc2VyaWFsaXplZCBhZ2Fpbi4gRG8gdHJhbnNmb3JtYXRpb25zIChgLnRvU29ydGVkKClgLCBgLmZpbHRlcigpYCwgYC5tYXAoKWApIGluIGNsaWVudCwgbm90IHNlcnZlci4KCioqSW5jb3JyZWN0OiBkdXBsaWNhdGVzIGFycmF5KioKCmBgYHRzeAovLyBSU0M6IHNlbmRzIDYgc3RyaW5ncyAoMiBhcnJheXMgw5cgMyBpdGVtcykKPENsaWVudExpc3QgdXNlcm5hbWVzPXt1c2VybmFtZXN9IHVzZXJuYW1lc09yZGVyZWQ9e3VzZXJuYW1lcy50b1NvcnRlZCgpfSAvPgpgYGAKCioqQ29ycmVjdDogc2VuZHMgMyBzdHJpbmdzKioKCmBgYHRzeAovLyBSU0M6IHNlbmQgb25jZQo8Q2xpZW50TGlzdCB1c2VybmFtZXM9e3VzZXJuYW1lc30gLz4KCi8vIENsaWVudDogdHJhbnNmb3JtIHRoZXJlCid1c2UgY2xpZW50Jwpjb25zdCBzb3J0ZWQgPSB1c2VNZW1vKCgpID0+IFsuLi51c2VybmFtZXNdLnNvcnQoKSwgW3VzZXJuYW1lc10pCmBgYAoKKipOZXN0ZWQgZGVkdXBsaWNhdGlvbiBiZWhhdmlvcjoqKgoKYGBgdHN4Ci8vIHN0cmluZ1tdIC0gZHVwbGljYXRlcyBldmVyeXRoaW5nCnVzZXJuYW1lcz17WydhJywnYiddfSBzb3J0ZWQ9e3VzZXJuYW1lcy50b1NvcnRlZCgpfSAvLyBzZW5kcyA0IHN0cmluZ3MKCi8vIG9iamVjdFtdIC0gZHVwbGljYXRlcyBhcnJheSBzdHJ1Y3R1cmUgb25seQp1c2Vycz17W3tpZDoxfSx7aWQ6Mn1dfSBzb3J0ZWQ9e3VzZXJzLnRvU29ydGVkKCl9IC8vIHNlbmRzIDIgYXJyYXlzICsgMiB1bmlxdWUgb2JqZWN0cyAobm90IDQpCmBgYAoKRGVkdXBsaWNhdGlvbiB3b3JrcyByZWN1cnNpdmVseS4gSW1wYWN0IHZhcmllcyBieSBkYXRhIHR5cGU6CgotIGBzdHJpbmdbXWAsIGBudW1iZXJbXWAsIGBib29sZWFuW11gOiAqKkhJR0ggaW1wYWN0KiogLSBhcnJheSArIGFsbCBwcmltaXRpdmVzIGZ1bGx5IGR1cGxpY2F0ZWQKCi0gYG9iamVjdFtdYDogKipMT1cgaW1wYWN0KiogLSBhcnJheSBkdXBsaWNhdGVkLCBidXQgbmVzdGVkIG9iamVjdHMgZGVkdXBsaWNhdGVkIGJ5IHJlZmVyZW5jZQoKKipPcGVyYXRpb25zIGJyZWFraW5nIGRlZHVwbGljYXRpb246IGNyZWF0ZSBuZXcgcmVmZXJlbmNlcyoqCgotIEFycmF5czogYC50b1NvcnRlZCgpYCwgYC5maWx0ZXIoKWAsIGAubWFwKClgLCBgLnNsaWNlKClgLCBgWy4uLmFycl1gCgotIE9iamVjdHM6IGB7Li4ub2JqfWAsIGBPYmplY3QuYXNzaWduKClgLCBgc3RydWN0dXJlZENsb25lKClgLCBgSlNPTi5wYXJzZShKU09OLnN0cmluZ2lmeSgpKWAKCioqTW9yZSBleGFtcGxlczoqKgoKYGBgdHN4Ci8vID8/QmFkCjxDIHVzZXJzPXt1c2Vyc30gYWN0aXZlPXt1c2Vycy5maWx0ZXIodSA9PiB1LmFjdGl2ZSl9IC8+CjxDIHByb2R1Y3Q9e3Byb2R1Y3R9IHByb2R1Y3ROYW1lPXtwcm9kdWN0Lm5hbWV9IC8+CgovLyA/P0dvb2QKPEMgdXNlcnM9e3VzZXJzfSAvPgo8QyBwcm9kdWN0PXtwcm9kdWN0fSAvPgovLyBEbyBmaWx0ZXJpbmcvZGVzdHJ1Y3R1cmluZyBpbiBjbGllbnQKYGBgCgoqKkV4Y2VwdGlvbjoqKiBQYXNzIGRlcml2ZWQgZGF0YSB3aGVuIHRyYW5zZm9ybWF0aW9uIGlzIGV4cGVuc2l2ZSBvciBjbGllbnQgZG9lc24ndCBuZWVkIG9yaWdpbmFsLgoKIyMjIDMuMyBDcm9zcy1SZXF1ZXN0IExSVSBDYWNoaW5nCgoqKkltcGFjdDogSElHSCAoY2FjaGVzIGFjcm9zcyByZXF1ZXN0cykqKgoKYFJlYWN0LmNhY2hlKClgIG9ubHkgd29ya3Mgd2l0aGluIG9uZSByZXF1ZXN0LiBGb3IgZGF0YSBzaGFyZWQgYWNyb3NzIHNlcXVlbnRpYWwgcmVxdWVzdHMgKHVzZXIgY2xpY2tzIGJ1dHRvbiBBIHRoZW4gYnV0dG9uIEIpLCB1c2UgYW4gTFJVIGNhY2hlLgoKKipJbXBsZW1lbnRhdGlvbjoqKgoKYGBgdHlwZXNjcmlwdAppbXBvcnQgeyBMUlVDYWNoZSB9IGZyb20gJ2xydS1jYWNoZScKCmNvbnN0IGNhY2hlID0gbmV3IExSVUNhY2hlPHN0cmluZywgYW55Pih7CiAgbWF4OiAxMDAwLAogIHR0bDogNSAqIDYwICogMTAwMCAgLy8gNSBtaW51dGVzCn0pCgpleHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0VXNlcihpZDogc3RyaW5nKSB7CiAgY29uc3QgY2FjaGVkID0gY2FjaGUuZ2V0KGlkKQogIGlmIChjYWNoZWQpIHJldHVybiBjYWNoZWQKCiAgY29uc3QgdXNlciA9IGF3YWl0IGRiLnVzZXIuZmluZFVuaXF1ZSh7IHdoZXJlOiB7IGlkIH0gfSkKICBjYWNoZS5zZXQoaWQsIHVzZXIpCiAgcmV0dXJuIHVzZXIKfQoKLy8gUmVxdWVzdCAxOiBEQiBxdWVyeSwgcmVzdWx0IGNhY2hlZAovLyBSZXF1ZXN0IDI6IGNhY2hlIGhpdCwgbm8gREIgcXVlcnkKYGBgCgpVc2Ugd2hlbiBzZXF1ZW50aWFsIHVzZXIgYWN0aW9ucyBoaXQgbXVsdGlwbGUgZW5kcG9pbnRzIG5lZWRpbmcgdGhlIHNhbWUgZGF0YSB3aXRoaW4gc2Vjb25kcy4KCioqV2l0aCBWZXJjZWwncyBbRmx1aWQgQ29tcHV0ZV0oaHR0cHM6Ly92ZXJjZWwuY29tL2RvY3MvZmx1aWQtY29tcHV0ZSk6KiogTFJVIGNhY2hpbmcgaXMgZXNwZWNpYWxseSBlZmZlY3RpdmUgYmVjYXVzZSBtdWx0aXBsZSBjb25jdXJyZW50IHJlcXVlc3RzIGNhbiBzaGFyZSB0aGUgc2FtZSBmdW5jdGlvbiBpbnN0YW5jZSBhbmQgY2FjaGUuIFRoaXMgbWVhbnMgdGhlIGNhY2hlIHBlcnNpc3RzIGFjcm9zcyByZXF1ZXN0cyB3aXRob3V0IG5lZWRpbmcgZXh0ZXJuYWwgc3RvcmFnZSBsaWtlIFJlZGlzLgoKKipJbiB0cmFkaXRpb25hbCBzZXJ2ZXJsZXNzOioqIEVhY2ggaW52b2NhdGlvbiBydW5zIGluIGlzb2xhdGlvbiwgc28gY29uc2lkZXIgUmVkaXMgZm9yIGNyb3NzLXByb2Nlc3MgY2FjaGluZy4KClJlZmVyZW5jZTogW2h0dHBzOi8vZ2l0aHViLmNvbS9pc2FhY3Mvbm9kZS1scnUtY2FjaGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9pc2FhY3Mvbm9kZS1scnUtY2FjaGUpCgojIyMgMy40IE1pbmltaXplIFNlcmlhbGl6YXRpb24gYXQgUlNDIEJvdW5kYXJpZXMKCioqSW1wYWN0OiBISUdIIChyZWR1Y2VzIGRhdGEgdHJhbnNmZXIgc2l6ZSkqKgoKVGhlIFJlYWN0IFNlcnZlci9DbGllbnQgYm91bmRhcnkgc2VyaWFsaXplcyBhbGwgb2JqZWN0IHByb3BlcnRpZXMgaW50byBzdHJpbmdzIGFuZCBlbWJlZHMgdGhlbSBpbiB0aGUgSFRNTCByZXNwb25zZSBhbmQgc3Vic2VxdWVudCBSU0MgcmVxdWVzdHMuIFRoaXMgc2VyaWFsaXplZCBkYXRhIGRpcmVjdGx5IGltcGFjdHMgcGFnZSB3ZWlnaHQgYW5kIGxvYWQgdGltZSwgc28gKipzaXplIG1hdHRlcnMgYSBsb3QqKi4gT25seSBwYXNzIGZpZWxkcyB0aGF0IHRoZSBjbGllbnQgYWN0dWFsbHkgdXNlcy4KCioqSW5jb3JyZWN0OiBzZXJpYWxpemVzIGFsbCA1MCBmaWVsZHMqKgoKYGBgdHN4CmFzeW5jIGZ1bmN0aW9uIFBhZ2UoKSB7CiAgY29uc3QgdXNlciA9IGF3YWl0IGZldGNoVXNlcigpICAvLyA1MCBmaWVsZHMKICByZXR1cm4gPFByb2ZpbGUgdXNlcj17dXNlcn0gLz4KfQoKJ3VzZSBjbGllbnQnCmZ1bmN0aW9uIFByb2ZpbGUoeyB1c2VyIH06IHsgdXNlcjogVXNlciB9KSB7CiAgcmV0dXJuIDxkaXY+e3VzZXIubmFtZX08L2Rpdj4gIC8vIHVzZXMgMSBmaWVsZAp9CmBgYAoKKipDb3JyZWN0OiBzZXJpYWxpemVzIG9ubHkgMSBmaWVsZCoqCgpgYGB0c3gKYXN5bmMgZnVuY3Rpb24gUGFnZSgpIHsKICBjb25zdCB1c2VyID0gYXdhaXQgZmV0Y2hVc2VyKCkKICByZXR1cm4gPFByb2ZpbGUgbmFtZT17dXNlci5uYW1lfSAvPgp9CgondXNlIGNsaWVudCcKZnVuY3Rpb24gUHJvZmlsZSh7IG5hbWUgfTogeyBuYW1lOiBzdHJpbmcgfSkgewogIHJldHVybiA8ZGl2PntuYW1lfTwvZGl2Pgp9CmBgYAoKIyMjIDMuNSBQYXJhbGxlbCBEYXRhIEZldGNoaW5nIHdpdGggQ29tcG9uZW50IENvbXBvc2l0aW9uCgoqKkltcGFjdDogQ1JJVElDQUwgKGVsaW1pbmF0ZXMgc2VydmVyLXNpZGUgd2F0ZXJmYWxscykqKgoKUmVhY3QgU2VydmVyIENvbXBvbmVudHMgZXhlY3V0ZSBzZXF1ZW50aWFsbHkgd2l0aGluIGEgdHJlZS4gUmVzdHJ1Y3R1cmUgd2l0aCBjb21wb3NpdGlvbiB0byBwYXJhbGxlbGl6ZSBkYXRhIGZldGNoaW5nLgoKKipJbmNvcnJlY3Q6IFNpZGViYXIgd2FpdHMgZm9yIFBhZ2UncyBmZXRjaCB0byBjb21wbGV0ZSoqCgpgYGB0c3gKZXhwb3J0IGRlZmF1bHQgYXN5bmMgZnVuY3Rpb24gUGFnZSgpIHsKICBjb25zdCBoZWFkZXIgPSBhd2FpdCBmZXRjaEhlYWRlcigpCiAgcmV0dXJuICgKICAgIDxkaXY+CiAgICAgIDxkaXY+e2hlYWRlcn08L2Rpdj4KICAgICAgPFNpZGViYXIgLz4KICAgIDwvZGl2PgogICkKfQoKYXN5bmMgZnVuY3Rpb24gU2lkZWJhcigpIHsKICBjb25zdCBpdGVtcyA9IGF3YWl0IGZldGNoU2lkZWJhckl0ZW1zKCkKICByZXR1cm4gPG5hdj57aXRlbXMubWFwKHJlbmRlckl0ZW0pfTwvbmF2Pgp9CmBgYAoKKipDb3JyZWN0OiBib3RoIGZldGNoIHNpbXVsdGFuZW91c2x5KioKCmBgYHRzeAphc3luYyBmdW5jdGlvbiBIZWFkZXIoKSB7CiAgY29uc3QgZGF0YSA9IGF3YWl0IGZldGNoSGVhZGVyKCkKICByZXR1cm4gPGRpdj57ZGF0YX08L2Rpdj4KfQoKYXN5bmMgZnVuY3Rpb24gU2lkZWJhcigpIHsKICBjb25zdCBpdGVtcyA9IGF3YWl0IGZldGNoU2lkZWJhckl0ZW1zKCkKICByZXR1cm4gPG5hdj57aXRlbXMubWFwKHJlbmRlckl0ZW0pfTwvbmF2Pgp9CgpleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBQYWdlKCkgewogIHJldHVybiAoCiAgICA8ZGl2PgogICAgICA8SGVhZGVyIC8+CiAgICAgIDxTaWRlYmFyIC8+CiAgICA8L2Rpdj4KICApCn0KYGBgCgoqKkFsdGVybmF0aXZlIHdpdGggY2hpbGRyZW4gcHJvcDoqKgoKYGBgdHN4CmFzeW5jIGZ1bmN0aW9uIEhlYWRlcigpIHsKICBjb25zdCBkYXRhID0gYXdhaXQgZmV0Y2hIZWFkZXIoKQogIHJldHVybiA8ZGl2PntkYXRhfTwvZGl2Pgp9Cgphc3luYyBmdW5jdGlvbiBTaWRlYmFyKCkgewogIGNvbnN0IGl0ZW1zID0gYXdhaXQgZmV0Y2hTaWRlYmFySXRlbXMoKQogIHJldHVybiA8bmF2PntpdGVtcy5tYXAocmVuZGVySXRlbSl9PC9uYXY+Cn0KCmZ1bmN0aW9uIExheW91dCh7IGNoaWxkcmVuIH06IHsgY2hpbGRyZW46IFJlYWN0Tm9kZSB9KSB7CiAgcmV0dXJuICgKICAgIDxkaXY+CiAgICAgIDxIZWFkZXIgLz4KICAgICAge2NoaWxkcmVufQogICAgPC9kaXY+CiAgKQp9CgpleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBQYWdlKCkgewogIHJldHVybiAoCiAgICA8TGF5b3V0PgogICAgICA8U2lkZWJhciAvPgogICAgPC9MYXlvdXQ+CiAgKQp9CmBgYAoKIyMjIDMuNiBQZXItUmVxdWVzdCBEZWR1cGxpY2F0aW9uIHdpdGggUmVhY3QuY2FjaGUoKQoKKipJbXBhY3Q6IE1FRElVTSAoZGVkdXBsaWNhdGVzIHdpdGhpbiByZXF1ZXN0KSoqCgpVc2UgYFJlYWN0LmNhY2hlKClgIGZvciBzZXJ2ZXItc2lkZSByZXF1ZXN0IGRlZHVwbGljYXRpb24uIEF1dGhlbnRpY2F0aW9uIGFuZCBkYXRhYmFzZSBxdWVyaWVzIGJlbmVmaXQgbW9zdC4KCioqVXNhZ2U6KioKCmBgYHR5cGVzY3JpcHQKaW1wb3J0IHsgY2FjaGUgfSBmcm9tICdyZWFjdCcKCmV4cG9ydCBjb25zdCBnZXRDdXJyZW50VXNlciA9IGNhY2hlKGFzeW5jICgpID0+IHsKICBjb25zdCBzZXNzaW9uID0gYXdhaXQgYXV0aCgpCiAgaWYgKCFzZXNzaW9uPy51c2VyPy5pZCkgcmV0dXJuIG51bGwKICByZXR1cm4gYXdhaXQgZGIudXNlci5maW5kVW5pcXVlKHsKICAgIHdoZXJlOiB7IGlkOiBzZXNzaW9uLnVzZXIuaWQgfQogIH0pCn0pCmBgYAoKV2l0aGluIGEgc2luZ2xlIHJlcXVlc3QsIG11bHRpcGxlIGNhbGxzIHRvIGBnZXRDdXJyZW50VXNlcigpYCBleGVjdXRlIHRoZSBxdWVyeSBvbmx5IG9uY2UuCgoqKkF2b2lkIGlubGluZSBvYmplY3RzIGFzIGFyZ3VtZW50czoqKgoKYFJlYWN0LmNhY2hlKClgIHVzZXMgc2hhbGxvdyBlcXVhbGl0eSAoYE9iamVjdC5pc2ApIHRvIGRldGVybWluZSBjYWNoZSBoaXRzLiBJbmxpbmUgb2JqZWN0cyBjcmVhdGUgbmV3IHJlZmVyZW5jZXMgZWFjaCBjYWxsLCBwcmV2ZW50aW5nIGNhY2hlIGhpdHMuCgoqKkluY29ycmVjdDogYWx3YXlzIGNhY2hlIG1pc3MqKgoKYGBgdHlwZXNjcmlwdApjb25zdCBnZXRVc2VyID0gY2FjaGUoYXN5bmMgKHBhcmFtczogeyB1aWQ6IG51bWJlciB9KSA9PiB7CiAgcmV0dXJuIGF3YWl0IGRiLnVzZXIuZmluZFVuaXF1ZSh7IHdoZXJlOiB7IGlkOiBwYXJhbXMudWlkIH0gfSkKfSkKCi8vIEVhY2ggY2FsbCBjcmVhdGVzIG5ldyBvYmplY3QsIG5ldmVyIGhpdHMgY2FjaGUKZ2V0VXNlcih7IHVpZDogMSB9KQpnZXRVc2VyKHsgdWlkOiAxIH0pICAvLyBDYWNoZSBtaXNzLCBydW5zIHF1ZXJ5IGFnYWluCmBgYAoKKipDb3JyZWN0OiBjYWNoZSBoaXQqKgoKYGBgdHlwZXNjcmlwdApjb25zdCBwYXJhbXMgPSB7IHVpZDogMSB9CmdldFVzZXIocGFyYW1zKSAgLy8gUXVlcnkgcnVucwpnZXRVc2VyKHBhcmFtcykgIC8vIENhY2hlIGhpdCAoc2FtZSByZWZlcmVuY2UpCmBgYAoKSWYgeW91IG11c3QgcGFzcyBvYmplY3RzLCBwYXNzIHRoZSBzYW1lIHJlZmVyZW5jZToKCioqTmV4dC5qcy1TcGVjaWZpYyBOb3RlOioqCgpJbiBOZXh0LmpzLCB0aGUgYGZldGNoYCBBUEkgaXMgYXV0b21hdGljYWxseSBleHRlbmRlZCB3aXRoIHJlcXVlc3QgbWVtb2l6YXRpb24uIFJlcXVlc3RzIHdpdGggdGhlIHNhbWUgVVJMIGFuZCBvcHRpb25zIGFyZSBhdXRvbWF0aWNhbGx5IGRlZHVwbGljYXRlZCB3aXRoaW4gYSBzaW5nbGUgcmVxdWVzdCwgc28geW91IGRvbid0IG5lZWQgYFJlYWN0LmNhY2hlKClgIGZvciBgZmV0Y2hgIGNhbGxzLiBIb3dldmVyLCBgUmVhY3QuY2FjaGUoKWAgaXMgc3RpbGwgZXNzZW50aWFsIGZvciBvdGhlciBhc3luYyB0YXNrczoKCi0gRGF0YWJhc2UgcXVlcmllcyAoUHJpc21hLCBEcml6emxlLCBldGMuKQoKLSBIZWF2eSBjb21wdXRhdGlvbnMKCi0gQXV0aGVudGljYXRpb24gY2hlY2tzCgotIEZpbGUgc3lzdGVtIG9wZXJhdGlvbnMKCi0gQW55IG5vbi1mZXRjaCBhc3luYyB3b3JrCgpVc2UgYFJlYWN0LmNhY2hlKClgIHRvIGRlZHVwbGljYXRlIHRoZXNlIG9wZXJhdGlvbnMgYWNyb3NzIHlvdXIgY29tcG9uZW50IHRyZWUuCgpSZWZlcmVuY2U6IFtodHRwczovL3JlYWN0LmRldi9yZWZlcmVuY2UvcmVhY3QvY2FjaGVdKGh0dHBzOi8vcmVhY3QuZGV2L3JlZmVyZW5jZS9yZWFjdC9jYWNoZSkKCiMjIyAzLjcgVXNlIGFmdGVyKCkgZm9yIE5vbi1CbG9ja2luZyBPcGVyYXRpb25zCgoqKkltcGFjdDogTUVESVVNIChmYXN0ZXIgcmVzcG9uc2UgdGltZXMpKioKClVzZSBOZXh0LmpzJ3MgYGFmdGVyKClgIHRvIHNjaGVkdWxlIHdvcmsgdGhhdCBzaG91bGQgZXhlY3V0ZSBhZnRlciBhIHJlc3BvbnNlIGlzIHNlbnQuIFRoaXMgcHJldmVudHMgbG9nZ2luZywgYW5hbHl0aWNzLCBhbmQgb3RoZXIgc2lkZSBlZmZlY3RzIGZyb20gYmxvY2tpbmcgdGhlIHJlc3BvbnNlLgoKKipJbmNvcnJlY3Q6IGJsb2NrcyByZXNwb25zZSoqCgpgYGB0c3gKaW1wb3J0IHsgbG9nVXNlckFjdGlvbiB9IGZyb20gJ0AvYXBwL3V0aWxzJwoKZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIFBPU1QocmVxdWVzdDogUmVxdWVzdCkgewogIC8vIFBlcmZvcm0gbXV0YXRpb24KICBhd2FpdCB1cGRhdGVEYXRhYmFzZShyZXF1ZXN0KQogIAogIC8vIExvZ2dpbmcgYmxvY2tzIHRoZSByZXNwb25zZQogIGNvbnN0IHVzZXJBZ2VudCA9IHJlcXVlc3QuaGVhZGVycy5nZXQoJ3VzZXItYWdlbnQnKSB8fCAndW5rbm93bicKICBhd2FpdCBsb2dVc2VyQWN0aW9uKHsgdXNlckFnZW50IH0pCiAgCiAgcmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeSh7IHN0YXR1czogJ3N1Y2Nlc3MnIH0pLCB7CiAgICBzdGF0dXM6IDIwMCwKICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9CiAgfSkKfQpgYGAKCioqQ29ycmVjdDogbm9uLWJsb2NraW5nKioKCmBgYHRzeAppbXBvcnQgeyBhZnRlciB9IGZyb20gJ25leHQvc2VydmVyJwppbXBvcnQgeyBoZWFkZXJzLCBjb29raWVzIH0gZnJvbSAnbmV4dC9oZWFkZXJzJwppbXBvcnQgeyBsb2dVc2VyQWN0aW9uIH0gZnJvbSAnQC9hcHAvdXRpbHMnCgpleHBvcnQgYXN5bmMgZnVuY3Rpb24gUE9TVChyZXF1ZXN0OiBSZXF1ZXN0KSB7CiAgLy8gUGVyZm9ybSBtdXRhdGlvbgogIGF3YWl0IHVwZGF0ZURhdGFiYXNlKHJlcXVlc3QpCiAgCiAgLy8gTG9nIGFmdGVyIHJlc3BvbnNlIGlzIHNlbnQKICBhZnRlcihhc3luYyAoKSA9PiB7CiAgICBjb25zdCB1c2VyQWdlbnQgPSAoYXdhaXQgaGVhZGVycygpKS5nZXQoJ3VzZXItYWdlbnQnKSB8fCAndW5rbm93bicKICAgIGNvbnN0IHNlc3Npb25Db29raWUgPSAoYXdhaXQgY29va2llcygpKS5nZXQoJ3Nlc3Npb24taWQnKT8udmFsdWUgfHwgJ2Fub255bW91cycKICAgIAogICAgbG9nVXNlckFjdGlvbih7IHNlc3Npb25Db29raWUsIHVzZXJBZ2VudCB9KQogIH0pCiAgCiAgcmV0dXJuIG5ldyBSZXNwb25zZShKU09OLnN0cmluZ2lmeSh7IHN0YXR1czogJ3N1Y2Nlc3MnIH0pLCB7CiAgICBzdGF0dXM6IDIwMCwKICAgIGhlYWRlcnM6IHsgJ0NvbnRlbnQtVHlwZSc6ICdhcHBsaWNhdGlvbi9qc29uJyB9CiAgfSkKfQpgYGAKClRoZSByZXNwb25zZSBpcyBzZW50IGltbWVkaWF0ZWx5IHdoaWxlIGxvZ2dpbmcgaGFwcGVucyBpbiB0aGUgYmFja2dyb3VuZC4KCioqQ29tbW9uIHVzZSBjYXNlczoqKgoKLSBBbmFseXRpY3MgdHJhY2tpbmcKCi0gQXVkaXQgbG9nZ2luZwoKLSBTZW5kaW5nIG5vdGlmaWNhdGlvbnMKCi0gQ2FjaGUgaW52YWxpZGF0aW9uCgotIENsZWFudXAgdGFza3MKCioqSW1wb3J0YW50IG5vdGVzOioqCgotIGBhZnRlcigpYCBydW5zIGV2ZW4gaWYgdGhlIHJlc3BvbnNlIGZhaWxzIG9yIHJlZGlyZWN0cwoKLSBXb3JrcyBpbiBTZXJ2ZXIgQWN0aW9ucywgUm91dGUgSGFuZGxlcnMsIGFuZCBTZXJ2ZXIgQ29tcG9uZW50cwoKUmVmZXJlbmNlOiBbaHR0cHM6Ly9uZXh0anMub3JnL2RvY3MvYXBwL2FwaS1yZWZlcmVuY2UvZnVuY3Rpb25zL2FmdGVyXShodHRwczovL25leHRqcy5vcmcvZG9jcy9hcHAvYXBpLXJlZmVyZW5jZS9mdW5jdGlvbnMvYWZ0ZXIpCgotLS0KCiMjIDQuIENsaWVudC1TaWRlIERhdGEgRmV0Y2hpbmcKCioqSW1wYWN0OiBNRURJVU0tSElHSCoqCgpBdXRvbWF0aWMgZGVkdXBsaWNhdGlvbiBhbmQgZWZmaWNpZW50IGRhdGEgZmV0Y2hpbmcgcGF0dGVybnMgcmVkdWNlIHJlZHVuZGFudCBuZXR3b3JrIHJlcXVlc3RzLgoKIyMjIDQuMSBEZWR1cGxpY2F0ZSBHbG9iYWwgRXZlbnQgTGlzdGVuZXJzCgoqKkltcGFjdDogTE9XIChzaW5nbGUgbGlzdGVuZXIgZm9yIE4gY29tcG9uZW50cykqKgoKVXNlIGB1c2VTV1JTdWJzY3JpcHRpb24oKWAgdG8gc2hhcmUgZ2xvYmFsIGV2ZW50IGxpc3RlbmVycyBhY3Jvc3MgY29tcG9uZW50IGluc3RhbmNlcy4KCioqSW5jb3JyZWN0OiBOIGluc3RhbmNlcyA9IE4gbGlzdGVuZXJzKioKCmBgYHRzeApmdW5jdGlvbiB1c2VLZXlib2FyZFNob3J0Y3V0KGtleTogc3RyaW5nLCBjYWxsYmFjazogKCkgPT4gdm9pZCkgewogIHVzZUVmZmVjdCgoKSA9PiB7CiAgICBjb25zdCBoYW5kbGVyID0gKGU6IEtleWJvYXJkRXZlbnQpID0+IHsKICAgICAgaWYgKGUubWV0YUtleSAmJiBlLmtleSA9PT0ga2V5KSB7CiAgICAgICAgY2FsbGJhY2soKQogICAgICB9CiAgICB9CiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGhhbmRsZXIpCiAgICByZXR1cm4gKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCBoYW5kbGVyKQogIH0sIFtrZXksIGNhbGxiYWNrXSkKfQpgYGAKCldoZW4gdXNpbmcgdGhlIGB1c2VLZXlib2FyZFNob3J0Y3V0YCBob29rIG11bHRpcGxlIHRpbWVzLCBlYWNoIGluc3RhbmNlIHdpbGwgcmVnaXN0ZXIgYSBuZXcgbGlzdGVuZXIuCgoqKkNvcnJlY3Q6IE4gaW5zdGFuY2VzID0gMSBsaXN0ZW5lcioqCgpgYGB0c3gKaW1wb3J0IHVzZVNXUlN1YnNjcmlwdGlvbiBmcm9tICdzd3Ivc3Vic2NyaXB0aW9uJwoKLy8gTW9kdWxlLWxldmVsIE1hcCB0byB0cmFjayBjYWxsYmFja3MgcGVyIGtleQpjb25zdCBrZXlDYWxsYmFja3MgPSBuZXcgTWFwPHN0cmluZywgU2V0PCgpID0+IHZvaWQ+PigpCgpmdW5jdGlvbiB1c2VLZXlib2FyZFNob3J0Y3V0KGtleTogc3RyaW5nLCBjYWxsYmFjazogKCkgPT4gdm9pZCkgewogIC8vIFJlZ2lzdGVyIHRoaXMgY2FsbGJhY2sgaW4gdGhlIE1hcAogIHVzZUVmZmVjdCgoKSA9PiB7CiAgICBpZiAoIWtleUNhbGxiYWNrcy5oYXMoa2V5KSkgewogICAgICBrZXlDYWxsYmFja3Muc2V0KGtleSwgbmV3IFNldCgpKQogICAgfQogICAga2V5Q2FsbGJhY2tzLmdldChrZXkpIS5hZGQoY2FsbGJhY2spCgogICAgcmV0dXJuICgpID0+IHsKICAgICAgY29uc3Qgc2V0ID0ga2V5Q2FsbGJhY2tzLmdldChrZXkpCiAgICAgIGlmIChzZXQpIHsKICAgICAgICBzZXQuZGVsZXRlKGNhbGxiYWNrKQogICAgICAgIGlmIChzZXQuc2l6ZSA9PT0gMCkgewogICAgICAgICAga2V5Q2FsbGJhY2tzLmRlbGV0ZShrZXkpCiAgICAgICAgfQogICAgICB9CiAgICB9CiAgfSwgW2tleSwgY2FsbGJhY2tdKQoKICB1c2VTV1JTdWJzY3JpcHRpb24oJ2dsb2JhbC1rZXlkb3duJywgKCkgPT4gewogICAgY29uc3QgaGFuZGxlciA9IChlOiBLZXlib2FyZEV2ZW50KSA9PiB7CiAgICAgIGlmIChlLm1ldGFLZXkgJiYga2V5Q2FsbGJhY2tzLmhhcyhlLmtleSkpIHsKICAgICAgICBrZXlDYWxsYmFja3MuZ2V0KGUua2V5KSEuZm9yRWFjaChjYiA9PiBjYigpKQogICAgICB9CiAgICB9CiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIGhhbmRsZXIpCiAgICByZXR1cm4gKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCBoYW5kbGVyKQogIH0pCn0KCmZ1bmN0aW9uIFByb2ZpbGUoKSB7CiAgLy8gTXVsdGlwbGUgc2hvcnRjdXRzIHdpbGwgc2hhcmUgdGhlIHNhbWUgbGlzdGVuZXIKICB1c2VLZXlib2FyZFNob3J0Y3V0KCdwJywgKCkgPT4geyAvKiAuLi4gKi8gfSkgCiAgdXNlS2V5Ym9hcmRTaG9ydGN1dCgnaycsICgpID0+IHsgLyogLi4uICovIH0pCiAgLy8gLi4uCn0KYGBgCgojIyMgNC4yIFVzZSBQYXNzaXZlIEV2ZW50IExpc3RlbmVycyBmb3IgU2Nyb2xsaW5nIFBlcmZvcm1hbmNlCgoqKkltcGFjdDogTUVESVVNIChlbGltaW5hdGVzIHNjcm9sbCBkZWxheSBjYXVzZWQgYnkgZXZlbnQgbGlzdGVuZXJzKSoqCgpBZGQgYHsgcGFzc2l2ZTogdHJ1ZSB9YCB0byB0b3VjaCBhbmQgd2hlZWwgZXZlbnQgbGlzdGVuZXJzIHRvIGVuYWJsZSBpbW1lZGlhdGUgc2Nyb2xsaW5nLiBCcm93c2VycyBub3JtYWxseSB3YWl0IGZvciBsaXN0ZW5lcnMgdG8gZmluaXNoIHRvIGNoZWNrIGlmIGBwcmV2ZW50RGVmYXVsdCgpYCBpcyBjYWxsZWQsIGNhdXNpbmcgc2Nyb2xsIGRlbGF5LgoKKipJbmNvcnJlY3Q6KioKCmBgYHR5cGVzY3JpcHQKdXNlRWZmZWN0KCgpID0+IHsKICBjb25zdCBoYW5kbGVUb3VjaCA9IChlOiBUb3VjaEV2ZW50KSA9PiBjb25zb2xlLmxvZyhlLnRvdWNoZXNbMF0uY2xpZW50WCkKICBjb25zdCBoYW5kbGVXaGVlbCA9IChlOiBXaGVlbEV2ZW50KSA9PiBjb25zb2xlLmxvZyhlLmRlbHRhWSkKICAKICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd0b3VjaHN0YXJ0JywgaGFuZGxlVG91Y2gpCiAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBoYW5kbGVXaGVlbCkKICAKICByZXR1cm4gKCkgPT4gewogICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigndG91Y2hzdGFydCcsIGhhbmRsZVRvdWNoKQogICAgZG9jdW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBoYW5kbGVXaGVlbCkKICB9Cn0sIFtdKQpgYGAKCioqQ29ycmVjdDoqKgoKYGBgdHlwZXNjcmlwdAp1c2VFZmZlY3QoKCkgPT4gewogIGNvbnN0IGhhbmRsZVRvdWNoID0gKGU6IFRvdWNoRXZlbnQpID0+IGNvbnNvbGUubG9nKGUudG91Y2hlc1swXS5jbGllbnRYKQogIGNvbnN0IGhhbmRsZVdoZWVsID0gKGU6IFdoZWVsRXZlbnQpID0+IGNvbnNvbGUubG9nKGUuZGVsdGFZKQogIAogIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBoYW5kbGVUb3VjaCwgeyBwYXNzaXZlOiB0cnVlIH0pCiAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLCBoYW5kbGVXaGVlbCwgeyBwYXNzaXZlOiB0cnVlIH0pCiAgCiAgcmV0dXJuICgpID0+IHsKICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3RvdWNoc3RhcnQnLCBoYW5kbGVUb3VjaCkKICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3doZWVsJywgaGFuZGxlV2hlZWwpCiAgfQp9LCBbXSkKYGBgCgoqKlVzZSBwYXNzaXZlIHdoZW46KiogdHJhY2tpbmcvYW5hbHl0aWNzLCBsb2dnaW5nLCBhbnkgbGlzdGVuZXIgdGhhdCBkb2Vzbid0IGNhbGwgYHByZXZlbnREZWZhdWx0KClgLgoKKipEb24ndCB1c2UgcGFzc2l2ZSB3aGVuOioqIGltcGxlbWVudGluZyBjdXN0b20gc3dpcGUgZ2VzdHVyZXMsIGN1c3RvbSB6b29tIGNvbnRyb2xzLCBvciBhbnkgbGlzdGVuZXIgdGhhdCBuZWVkcyBgcHJldmVudERlZmF1bHQoKWAuCgojIyMgNC4zIFVzZSBTV1IgZm9yIEF1dG9tYXRpYyBEZWR1cGxpY2F0aW9uCgoqKkltcGFjdDogTUVESVVNLUhJR0ggKGF1dG9tYXRpYyBkZWR1cGxpY2F0aW9uKSoqCgpTV1IgZW5hYmxlcyByZXF1ZXN0IGRlZHVwbGljYXRpb24sIGNhY2hpbmcsIGFuZCByZXZhbGlkYXRpb24gYWNyb3NzIGNvbXBvbmVudCBpbnN0YW5jZXMuCgoqKkluY29ycmVjdDogbm8gZGVkdXBsaWNhdGlvbiwgZWFjaCBpbnN0YW5jZSBmZXRjaGVzKioKCmBgYHRzeApmdW5jdGlvbiBVc2VyTGlzdCgpIHsKICBjb25zdCBbdXNlcnMsIHNldFVzZXJzXSA9IHVzZVN0YXRlKFtdKQogIHVzZUVmZmVjdCgoKSA9PiB7CiAgICBmZXRjaCgnL2FwaS91c2VycycpCiAgICAgIC50aGVuKHIgPT4gci5qc29uKCkpCiAgICAgIC50aGVuKHNldFVzZXJzKQogIH0sIFtdKQp9CmBgYAoKKipDb3JyZWN0OiBtdWx0aXBsZSBpbnN0YW5jZXMgc2hhcmUgb25lIHJlcXVlc3QqKgoKYGBgdHN4CmltcG9ydCB1c2VTV1IgZnJvbSAnc3dyJwoKZnVuY3Rpb24gVXNlckxpc3QoKSB7CiAgY29uc3QgeyBkYXRhOiB1c2VycyB9ID0gdXNlU1dSKCcvYXBpL3VzZXJzJywgZmV0Y2hlcikKfQpgYGAKCioqRm9yIGltbXV0YWJsZSBkYXRhOioqCgpgYGB0c3gKaW1wb3J0IHsgdXNlSW1tdXRhYmxlU1dSIH0gZnJvbSAnQC9saWIvc3dyJwoKZnVuY3Rpb24gU3RhdGljQ29udGVudCgpIHsKICBjb25zdCB7IGRhdGEgfSA9IHVzZUltbXV0YWJsZVNXUignL2FwaS9jb25maWcnLCBmZXRjaGVyKQp9CmBgYAoKKipGb3IgbXV0YXRpb25zOioqCgpgYGB0c3gKaW1wb3J0IHsgdXNlU1dSTXV0YXRpb24gfSBmcm9tICdzd3IvbXV0YXRpb24nCgpmdW5jdGlvbiBVcGRhdGVCdXR0b24oKSB7CiAgY29uc3QgeyB0cmlnZ2VyIH0gPSB1c2VTV1JNdXRhdGlvbignL2FwaS91c2VyJywgdXBkYXRlVXNlcikKICByZXR1cm4gPGJ1dHRvbiBvbkNsaWNrPXsoKSA9PiB0cmlnZ2VyKCl9PlVwZGF0ZTwvYnV0dG9uPgp9CmBgYAoKUmVmZXJlbmNlOiBbaHR0cHM6Ly9zd3IudmVyY2VsLmFwcF0oaHR0cHM6Ly9zd3IudmVyY2VsLmFwcCkKCiMjIyA0LjQgVmVyc2lvbiBhbmQgTWluaW1pemUgbG9jYWxTdG9yYWdlIERhdGEKCioqSW1wYWN0OiBNRURJVU0gKHByZXZlbnRzIHNjaGVtYSBjb25mbGljdHMsIHJlZHVjZXMgc3RvcmFnZSBzaXplKSoqCgpBZGQgdmVyc2lvbiBwcmVmaXggdG8ga2V5cyBhbmQgc3RvcmUgb25seSBuZWVkZWQgZmllbGRzLiBQcmV2ZW50cyBzY2hlbWEgY29uZmxpY3RzIGFuZCBhY2NpZGVudGFsIHN0b3JhZ2Ugb2Ygc2Vuc2l0aXZlIGRhdGEuCgoqKkluY29ycmVjdDoqKgoKYGBgdHlwZXNjcmlwdAovLyBObyB2ZXJzaW9uLCBzdG9yZXMgZXZlcnl0aGluZywgbm8gZXJyb3IgaGFuZGxpbmcKbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ3VzZXJDb25maWcnLCBKU09OLnN0cmluZ2lmeShmdWxsVXNlck9iamVjdCkpCmNvbnN0IGRhdGEgPSBsb2NhbFN0b3JhZ2UuZ2V0SXRlbSgndXNlckNvbmZpZycpCmBgYAoKKipDb3JyZWN0OioqCgpgYGB0eXBlc2NyaXB0CmNvbnN0IFZFUlNJT04gPSAndjInCgpmdW5jdGlvbiBzYXZlQ29uZmlnKGNvbmZpZzogeyB0aGVtZTogc3RyaW5nOyBsYW5ndWFnZTogc3RyaW5nIH0pIHsKICB0cnkgewogICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oYHVzZXJDb25maWc6JHtWRVJTSU9OfWAsIEpTT04uc3RyaW5naWZ5KGNvbmZpZykpCiAgfSBjYXRjaCB7CiAgICAvLyBUaHJvd3MgaW4gaW5jb2duaXRvL3ByaXZhdGUgYnJvd3NpbmcsIHF1b3RhIGV4Y2VlZGVkLCBvciBkaXNhYmxlZAogIH0KfQoKZnVuY3Rpb24gbG9hZENvbmZpZygpIHsKICB0cnkgewogICAgY29uc3QgZGF0YSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKGB1c2VyQ29uZmlnOiR7VkVSU0lPTn1gKQogICAgcmV0dXJuIGRhdGEgPyBKU09OLnBhcnNlKGRhdGEpIDogbnVsbAogIH0gY2F0Y2ggewogICAgcmV0dXJuIG51bGwKICB9Cn0KCi8vIE1pZ3JhdGlvbiBmcm9tIHYxIHRvIHYyCmZ1bmN0aW9uIG1pZ3JhdGUoKSB7CiAgdHJ5IHsKICAgIGNvbnN0IHYxID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3VzZXJDb25maWc6djEnKQogICAgaWYgKHYxKSB7CiAgICAgIGNvbnN0IG9sZCA9IEpTT04ucGFyc2UodjEpCiAgICAgIHNhdmVDb25maWcoeyB0aGVtZTogb2xkLmRhcmtNb2RlID8gJ2RhcmsnIDogJ2xpZ2h0JywgbGFuZ3VhZ2U6IG9sZC5sYW5nIH0pCiAgICAgIGxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKCd1c2VyQ29uZmlnOnYxJykKICAgIH0KICB9IGNhdGNoIHt9Cn0KYGBgCgoqKlN0b3JlIG1pbmltYWwgZmllbGRzIGZyb20gc2VydmVyIHJlc3BvbnNlczoqKgoKYGBgdHlwZXNjcmlwdAovLyBVc2VyIG9iamVjdCBoYXMgMjArIGZpZWxkcywgb25seSBzdG9yZSB3aGF0IFVJIG5lZWRzCmZ1bmN0aW9uIGNhY2hlUHJlZnModXNlcjogRnVsbFVzZXIpIHsKICB0cnkgewogICAgbG9jYWxTdG9yYWdlLnNldEl0ZW0oJ3ByZWZzOnYxJywgSlNPTi5zdHJpbmdpZnkoewogICAgICB0aGVtZTogdXNlci5wcmVmZXJlbmNlcy50aGVtZSwKICAgICAgbm90aWZpY2F0aW9uczogdXNlci5wcmVmZXJlbmNlcy5ub3RpZmljYXRpb25zCiAgICB9KSkKICB9IGNhdGNoIHt9Cn0KYGBgCgoqKkFsd2F5cyB3cmFwIGluIHRyeS1jYXRjaDoqKiBgZ2V0SXRlbSgpYCBhbmQgYHNldEl0ZW0oKWAgdGhyb3cgaW4gaW5jb2duaXRvL3ByaXZhdGUgYnJvd3NpbmcgKFNhZmFyaSwgRmlyZWZveCksIHdoZW4gcXVvdGEgZXhjZWVkZWQsIG9yIHdoZW4gZGlzYWJsZWQuCgoqKkJlbmVmaXRzOioqIFNjaGVtYSBldm9sdXRpb24gdmlhIHZlcnNpb25pbmcsIHJlZHVjZWQgc3RvcmFnZSBzaXplLCBwcmV2ZW50cyBzdG9yaW5nIHRva2Vucy9QSUkvaW50ZXJuYWwgZmxhZ3MuCgotLS0KCiMjIDUuIFJlLXJlbmRlciBPcHRpbWl6YXRpb24KCioqSW1wYWN0OiBNRURJVU0qKgoKUmVkdWNpbmcgdW5uZWNlc3NhcnkgcmUtcmVuZGVycyBtaW5pbWl6ZXMgd2FzdGVkIGNvbXB1dGF0aW9uIGFuZCBpbXByb3ZlcyBVSSByZXNwb25zaXZlbmVzcy4KCiMjIyA1LjEgRGVmZXIgU3RhdGUgUmVhZHMgdG8gVXNhZ2UgUG9pbnQKCioqSW1wYWN0OiBNRURJVU0gKGF2b2lkcyB1bm5lY2Vzc2FyeSBzdWJzY3JpcHRpb25zKSoqCgpEb24ndCBzdWJzY3JpYmUgdG8gZHluYW1pYyBzdGF0ZSAoc2VhcmNoUGFyYW1zLCBsb2NhbFN0b3JhZ2UpIGlmIHlvdSBvbmx5IHJlYWQgaXQgaW5zaWRlIGNhbGxiYWNrcy4KCioqSW5jb3JyZWN0OiBzdWJzY3JpYmVzIHRvIGFsbCBzZWFyY2hQYXJhbXMgY2hhbmdlcyoqCgpgYGB0c3gKZnVuY3Rpb24gU2hhcmVCdXR0b24oeyBjaGF0SWQgfTogeyBjaGF0SWQ6IHN0cmluZyB9KSB7CiAgY29uc3Qgc2VhcmNoUGFyYW1zID0gdXNlU2VhcmNoUGFyYW1zKCkKCiAgY29uc3QgaGFuZGxlU2hhcmUgPSAoKSA9PiB7CiAgICBjb25zdCByZWYgPSBzZWFyY2hQYXJhbXMuZ2V0KCdyZWYnKQogICAgc2hhcmVDaGF0KGNoYXRJZCwgeyByZWYgfSkKICB9CgogIHJldHVybiA8YnV0dG9uIG9uQ2xpY2s9e2hhbmRsZVNoYXJlfT5TaGFyZTwvYnV0dG9uPgp9CmBgYAoKKipDb3JyZWN0OiByZWFkcyBvbiBkZW1hbmQsIG5vIHN1YnNjcmlwdGlvbioqCgpgYGB0c3gKZnVuY3Rpb24gU2hhcmVCdXR0b24oeyBjaGF0SWQgfTogeyBjaGF0SWQ6IHN0cmluZyB9KSB7CiAgY29uc3QgaGFuZGxlU2hhcmUgPSAoKSA9PiB7CiAgICBjb25zdCBwYXJhbXMgPSBuZXcgVVJMU2VhcmNoUGFyYW1zKHdpbmRvdy5sb2NhdGlvbi5zZWFyY2gpCiAgICBjb25zdCByZWYgPSBwYXJhbXMuZ2V0KCdyZWYnKQogICAgc2hhcmVDaGF0KGNoYXRJZCwgeyByZWYgfSkKICB9CgogIHJldHVybiA8YnV0dG9uIG9uQ2xpY2s9e2hhbmRsZVNoYXJlfT5TaGFyZTwvYnV0dG9uPgp9CmBgYAoKIyMjIDUuMiBEbyBub3Qgd3JhcCBhIHNpbXBsZSBleHByZXNzaW9uIHdpdGggYSBwcmltaXRpdmUgcmVzdWx0IHR5cGUgaW4gdXNlTWVtbwoKKipJbXBhY3Q6IExPVy1NRURJVU0gKHdhc3RlZCBjb21wdXRhdGlvbiBvbiBldmVyeSByZW5kZXIpKioKCldoZW4gYW4gZXhwcmVzc2lvbiBpcyBzaW1wbGUgKGZldyBsb2dpY2FsIG9yIGFyaXRobWV0aWNhbCBvcGVyYXRvcnMpIGFuZCBoYXMgYSBwcmltaXRpdmUgcmVzdWx0IHR5cGUgKGJvb2xlYW4sIG51bWJlciwgc3RyaW5nKSwgZG8gbm90IHdyYXAgaXQgaW4gYHVzZU1lbW9gLgoKQ2FsbGluZyBgdXNlTWVtb2AgYW5kIGNvbXBhcmluZyBob29rIGRlcGVuZGVuY2llcyBtYXkgY29uc3VtZSBtb3JlIHJlc291cmNlcyB0aGFuIHRoZSBleHByZXNzaW9uIGl0c2VsZi4KCioqSW5jb3JyZWN0OioqCgpgYGB0c3gKZnVuY3Rpb24gSGVhZGVyKHsgdXNlciwgbm90aWZpY2F0aW9ucyB9OiBQcm9wcykgewogIGNvbnN0IGlzTG9hZGluZyA9IHVzZU1lbW8oKCkgPT4gewogICAgcmV0dXJuIHVzZXIuaXNMb2FkaW5nIHx8IG5vdGlmaWNhdGlvbnMuaXNMb2FkaW5nCiAgfSwgW3VzZXIuaXNMb2FkaW5nLCBub3RpZmljYXRpb25zLmlzTG9hZGluZ10pCgogIGlmIChpc0xvYWRpbmcpIHJldHVybiA8U2tlbGV0b24gLz4KICAvLyByZXR1cm4gc29tZSBtYXJrdXAKfQpgYGAKCioqQ29ycmVjdDoqKgoKYGBgdHN4CmZ1bmN0aW9uIEhlYWRlcih7IHVzZXIsIG5vdGlmaWNhdGlvbnMgfTogUHJvcHMpIHsKICBjb25zdCBpc0xvYWRpbmcgPSB1c2VyLmlzTG9hZGluZyB8fCBub3RpZmljYXRpb25zLmlzTG9hZGluZwoKICBpZiAoaXNMb2FkaW5nKSByZXR1cm4gPFNrZWxldG9uIC8+CiAgLy8gcmV0dXJuIHNvbWUgbWFya3VwCn0KYGBgCgojIyMgNS4zIEV4dHJhY3QgRGVmYXVsdCBOb24tcHJpbWl0aXZlIFBhcmFtZXRlciBWYWx1ZSBmcm9tIE1lbW9pemVkIENvbXBvbmVudCB0byBDb25zdGFudAoKKipJbXBhY3Q6IE1FRElVTSAocmVzdG9yZXMgbWVtb2l6YXRpb24gYnkgdXNpbmcgYSBjb25zdGFudCBmb3IgZGVmYXVsdCB2YWx1ZSkqKgoKV2hlbiBtZW1vaXplZCBjb21wb25lbnQgaGFzIGEgZGVmYXVsdCB2YWx1ZSBmb3Igc29tZSBub24tcHJpbWl0aXZlIG9wdGlvbmFsIHBhcmFtZXRlciwgc3VjaCBhcyBhbiBhcnJheSwgZnVuY3Rpb24sIG9yIG9iamVjdCwgY2FsbGluZyB0aGUgY29tcG9uZW50IHdpdGhvdXQgdGhhdCBwYXJhbWV0ZXIgcmVzdWx0cyBpbiBicm9rZW4gbWVtb2l6YXRpb24uIFRoaXMgaXMgYmVjYXVzZSBuZXcgdmFsdWUgaW5zdGFuY2VzIGFyZSBjcmVhdGVkIG9uIGV2ZXJ5IHJlcmVuZGVyLCBhbmQgdGhleSBkbyBub3QgcGFzcyBzdHJpY3QgZXF1YWxpdHkgY29tcGFyaXNvbiBpbiBgbWVtbygpYC4KClRvIGFkZHJlc3MgdGhpcyBpc3N1ZSwgZXh0cmFjdCB0aGUgZGVmYXVsdCB2YWx1ZSBpbnRvIGEgY29uc3RhbnQuCgoqKkluY29ycmVjdDogYG9uQ2xpY2tgIGhhcyBkaWZmZXJlbnQgdmFsdWVzIG9uIGV2ZXJ5IHJlcmVuZGVyKioKCmBgYHRzeApjb25zdCBVc2VyQXZhdGFyID0gbWVtbyhmdW5jdGlvbiBVc2VyQXZhdGFyKHsgb25DbGljayA9ICgpID0+IHt9IH06IHsgb25DbGljaz86ICgpID0+IHZvaWQgfSkgewogIC8vIC4uLgp9KQoKLy8gVXNlZCB3aXRob3V0IG9wdGlvbmFsIG9uQ2xpY2sKPFVzZXJBdmF0YXIgLz4KYGBgCgoqKkNvcnJlY3Q6IHN0YWJsZSBkZWZhdWx0IHZhbHVlKioKCmBgYHRzeApjb25zdCBOT09QID0gKCkgPT4ge307Cgpjb25zdCBVc2VyQXZhdGFyID0gbWVtbyhmdW5jdGlvbiBVc2VyQXZhdGFyKHsgb25DbGljayA9IE5PT1AgfTogeyBvbkNsaWNrPzogKCkgPT4gdm9pZCB9KSB7CiAgLy8gLi4uCn0pCgovLyBVc2VkIHdpdGhvdXQgb3B0aW9uYWwgb25DbGljawo8VXNlckF2YXRhciAvPgpgYGAKCiMjIyA1LjQgRXh0cmFjdCB0byBNZW1vaXplZCBDb21wb25lbnRzCgoqKkltcGFjdDogTUVESVVNIChlbmFibGVzIGVhcmx5IHJldHVybnMpKioKCkV4dHJhY3QgZXhwZW5zaXZlIHdvcmsgaW50byBtZW1vaXplZCBjb21wb25lbnRzIHRvIGVuYWJsZSBlYXJseSByZXR1cm5zIGJlZm9yZSBjb21wdXRhdGlvbi4KCioqSW5jb3JyZWN0OiBjb21wdXRlcyBhdmF0YXIgZXZlbiB3aGVuIGxvYWRpbmcqKgoKYGBgdHN4CmZ1bmN0aW9uIFByb2ZpbGUoeyB1c2VyLCBsb2FkaW5nIH06IFByb3BzKSB7CiAgY29uc3QgYXZhdGFyID0gdXNlTWVtbygoKSA9PiB7CiAgICBjb25zdCBpZCA9IGNvbXB1dGVBdmF0YXJJZCh1c2VyKQogICAgcmV0dXJuIDxBdmF0YXIgaWQ9e2lkfSAvPgogIH0sIFt1c2VyXSkKCiAgaWYgKGxvYWRpbmcpIHJldHVybiA8U2tlbGV0b24gLz4KICByZXR1cm4gPGRpdj57YXZhdGFyfTwvZGl2Pgp9CmBgYAoKKipDb3JyZWN0OiBza2lwcyBjb21wdXRhdGlvbiB3aGVuIGxvYWRpbmcqKgoKYGBgdHN4CmNvbnN0IFVzZXJBdmF0YXIgPSBtZW1vKGZ1bmN0aW9uIFVzZXJBdmF0YXIoeyB1c2VyIH06IHsgdXNlcjogVXNlciB9KSB7CiAgY29uc3QgaWQgPSB1c2VNZW1vKCgpID0+IGNvbXB1dGVBdmF0YXJJZCh1c2VyKSwgW3VzZXJdKQogIHJldHVybiA8QXZhdGFyIGlkPXtpZH0gLz4KfSkKCmZ1bmN0aW9uIFByb2ZpbGUoeyB1c2VyLCBsb2FkaW5nIH06IFByb3BzKSB7CiAgaWYgKGxvYWRpbmcpIHJldHVybiA8U2tlbGV0b24gLz4KICByZXR1cm4gKAogICAgPGRpdj4KICAgICAgPFVzZXJBdmF0YXIgdXNlcj17dXNlcn0gLz4KICAgIDwvZGl2PgogICkKfQpgYGAKCioqTm90ZToqKiBJZiB5b3VyIHByb2plY3QgaGFzIFtSZWFjdCBDb21waWxlcl0oaHR0cHM6Ly9yZWFjdC5kZXYvbGVhcm4vcmVhY3QtY29tcGlsZXIpIGVuYWJsZWQsIG1hbnVhbCBtZW1vaXphdGlvbiB3aXRoIGBtZW1vKClgIGFuZCBgdXNlTWVtbygpYCBpcyBub3QgbmVjZXNzYXJ5LiBUaGUgY29tcGlsZXIgYXV0b21hdGljYWxseSBvcHRpbWl6ZXMgcmUtcmVuZGVycy4KCiMjIyA1LjUgTmFycm93IEVmZmVjdCBEZXBlbmRlbmNpZXMKCioqSW1wYWN0OiBMT1cgKG1pbmltaXplcyBlZmZlY3QgcmUtcnVucykqKgoKU3BlY2lmeSBwcmltaXRpdmUgZGVwZW5kZW5jaWVzIGluc3RlYWQgb2Ygb2JqZWN0cyB0byBtaW5pbWl6ZSBlZmZlY3QgcmUtcnVucy4KCioqSW5jb3JyZWN0OiByZS1ydW5zIG9uIGFueSB1c2VyIGZpZWxkIGNoYW5nZSoqCgpgYGB0c3gKdXNlRWZmZWN0KCgpID0+IHsKICBjb25zb2xlLmxvZyh1c2VyLmlkKQp9LCBbdXNlcl0pCmBgYAoKKipDb3JyZWN0OiByZS1ydW5zIG9ubHkgd2hlbiBpZCBjaGFuZ2VzKioKCmBgYHRzeAp1c2VFZmZlY3QoKCkgPT4gewogIGNvbnNvbGUubG9nKHVzZXIuaWQpCn0sIFt1c2VyLmlkXSkKYGBgCgoqKkZvciBkZXJpdmVkIHN0YXRlLCBjb21wdXRlIG91dHNpZGUgZWZmZWN0OioqCgpgYGB0c3gKLy8gSW5jb3JyZWN0OiBydW5zIG9uIHdpZHRoPTc2NywgNzY2LCA3NjUuLi4KdXNlRWZmZWN0KCgpID0+IHsKICBpZiAod2lkdGggPCA3NjgpIHsKICAgIGVuYWJsZU1vYmlsZU1vZGUoKQogIH0KfSwgW3dpZHRoXSkKCi8vIENvcnJlY3Q6IHJ1bnMgb25seSBvbiBib29sZWFuIHRyYW5zaXRpb24KY29uc3QgaXNNb2JpbGUgPSB3aWR0aCA8IDc2OAp1c2VFZmZlY3QoKCkgPT4gewogIGlmIChpc01vYmlsZSkgewogICAgZW5hYmxlTW9iaWxlTW9kZSgpCiAgfQp9LCBbaXNNb2JpbGVdKQpgYGAKCiMjIyA1LjYgU3Vic2NyaWJlIHRvIERlcml2ZWQgU3RhdGUKCioqSW1wYWN0OiBNRURJVU0gKHJlZHVjZXMgcmUtcmVuZGVyIGZyZXF1ZW5jeSkqKgoKU3Vic2NyaWJlIHRvIGRlcml2ZWQgYm9vbGVhbiBzdGF0ZSBpbnN0ZWFkIG9mIGNvbnRpbnVvdXMgdmFsdWVzIHRvIHJlZHVjZSByZS1yZW5kZXIgZnJlcXVlbmN5LgoKKipJbmNvcnJlY3Q6IHJlLXJlbmRlcnMgb24gZXZlcnkgcGl4ZWwgY2hhbmdlKioKCmBgYHRzeApmdW5jdGlvbiBTaWRlYmFyKCkgewogIGNvbnN0IHdpZHRoID0gdXNlV2luZG93V2lkdGgoKSAgLy8gdXBkYXRlcyBjb250aW51b3VzbHkKICBjb25zdCBpc01vYmlsZSA9IHdpZHRoIDwgNzY4CiAgcmV0dXJuIDxuYXYgY2xhc3NOYW1lPXtpc01vYmlsZSA/ICdtb2JpbGUnIDogJ2Rlc2t0b3AnfSAvPgp9CmBgYAoKKipDb3JyZWN0OiByZS1yZW5kZXJzIG9ubHkgd2hlbiBib29sZWFuIGNoYW5nZXMqKgoKYGBgdHN4CmZ1bmN0aW9uIFNpZGViYXIoKSB7CiAgY29uc3QgaXNNb2JpbGUgPSB1c2VNZWRpYVF1ZXJ5KCcobWF4LXdpZHRoOiA3NjdweCknKQogIHJldHVybiA8bmF2IGNsYXNzTmFtZT17aXNNb2JpbGUgPyAnbW9iaWxlJyA6ICdkZXNrdG9wJ30gLz4KfQpgYGAKCiMjIyA1LjcgVXNlIEZ1bmN0aW9uYWwgc2V0U3RhdGUgVXBkYXRlcwoKKipJbXBhY3Q6IE1FRElVTSAocHJldmVudHMgc3RhbGUgY2xvc3VyZXMgYW5kIHVubmVjZXNzYXJ5IGNhbGxiYWNrIHJlY3JlYXRpb25zKSoqCgpXaGVuIHVwZGF0aW5nIHN0YXRlIGJhc2VkIG9uIHRoZSBjdXJyZW50IHN0YXRlIHZhbHVlLCB1c2UgdGhlIGZ1bmN0aW9uYWwgdXBkYXRlIGZvcm0gb2Ygc2V0U3RhdGUgaW5zdGVhZCBvZiBkaXJlY3RseSByZWZlcmVuY2luZyB0aGUgc3RhdGUgdmFyaWFibGUuIFRoaXMgcHJldmVudHMgc3RhbGUgY2xvc3VyZXMsIGVsaW1pbmF0ZXMgdW5uZWNlc3NhcnkgZGVwZW5kZW5jaWVzLCBhbmQgY3JlYXRlcyBzdGFibGUgY2FsbGJhY2sgcmVmZXJlbmNlcy4KCioqSW5jb3JyZWN0OiByZXF1aXJlcyBzdGF0ZSBhcyBkZXBlbmRlbmN5KioKCmBgYHRzeApmdW5jdGlvbiBUb2RvTGlzdCgpIHsKICBjb25zdCBbaXRlbXMsIHNldEl0ZW1zXSA9IHVzZVN0YXRlKGluaXRpYWxJdGVtcykKICAKICAvLyBDYWxsYmFjayBtdXN0IGRlcGVuZCBvbiBpdGVtcywgcmVjcmVhdGVkIG9uIGV2ZXJ5IGl0ZW1zIGNoYW5nZQogIGNvbnN0IGFkZEl0ZW1zID0gdXNlQ2FsbGJhY2soKG5ld0l0ZW1zOiBJdGVtW10pID0+IHsKICAgIHNldEl0ZW1zKFsuLi5pdGVtcywgLi4ubmV3SXRlbXNdKQogIH0sIFtpdGVtc10pICAvLyA/P2l0ZW1zIGRlcGVuZGVuY3kgY2F1c2VzIHJlY3JlYXRpb25zCiAgCiAgLy8gUmlzayBvZiBzdGFsZSBjbG9zdXJlIGlmIGRlcGVuZGVuY3kgaXMgZm9yZ290dGVuCiAgY29uc3QgcmVtb3ZlSXRlbSA9IHVzZUNhbGxiYWNrKChpZDogc3RyaW5nKSA9PiB7CiAgICBzZXRJdGVtcyhpdGVtcy5maWx0ZXIoaXRlbSA9PiBpdGVtLmlkICE9PSBpZCkpCiAgfSwgW10pICAvLyA/P01pc3NpbmcgaXRlbXMgZGVwZW5kZW5jeSAtIHdpbGwgdXNlIHN0YWxlIGl0ZW1zIQogIAogIHJldHVybiA8SXRlbXNFZGl0b3IgaXRlbXM9e2l0ZW1zfSBvbkFkZD17YWRkSXRlbXN9IG9uUmVtb3ZlPXtyZW1vdmVJdGVtfSAvPgp9CmBgYAoKVGhlIGZpcnN0IGNhbGxiYWNrIGlzIHJlY3JlYXRlZCBldmVyeSB0aW1lIGBpdGVtc2AgY2hhbmdlcywgd2hpY2ggY2FuIGNhdXNlIGNoaWxkIGNvbXBvbmVudHMgdG8gcmUtcmVuZGVyIHVubmVjZXNzYXJpbHkuIFRoZSBzZWNvbmQgY2FsbGJhY2sgaGFzIGEgc3RhbGUgY2xvc3VyZSBidWc/lGl0IHdpbGwgYWx3YXlzIHJlZmVyZW5jZSB0aGUgaW5pdGlhbCBgaXRlbXNgIHZhbHVlLgoKKipDb3JyZWN0OiBzdGFibGUgY2FsbGJhY2tzLCBubyBzdGFsZSBjbG9zdXJlcyoqCgpgYGB0c3gKZnVuY3Rpb24gVG9kb0xpc3QoKSB7CiAgY29uc3QgW2l0ZW1zLCBzZXRJdGVtc10gPSB1c2VTdGF0ZShpbml0aWFsSXRlbXMpCiAgCiAgLy8gU3RhYmxlIGNhbGxiYWNrLCBuZXZlciByZWNyZWF0ZWQKICBjb25zdCBhZGRJdGVtcyA9IHVzZUNhbGxiYWNrKChuZXdJdGVtczogSXRlbVtdKSA9PiB7CiAgICBzZXRJdGVtcyhjdXJyID0+IFsuLi5jdXJyLCAuLi5uZXdJdGVtc10pCiAgfSwgW10pICAvLyA/P05vIGRlcGVuZGVuY2llcyBuZWVkZWQKICAKICAvLyBBbHdheXMgdXNlcyBsYXRlc3Qgc3RhdGUsIG5vIHN0YWxlIGNsb3N1cmUgcmlzawogIGNvbnN0IHJlbW92ZUl0ZW0gPSB1c2VDYWxsYmFjaygoaWQ6IHN0cmluZykgPT4gewogICAgc2V0SXRlbXMoY3VyciA9PiBjdXJyLmZpbHRlcihpdGVtID0+IGl0ZW0uaWQgIT09IGlkKSkKICB9LCBbXSkgIC8vID8/U2FmZSBhbmQgc3RhYmxlCiAgCiAgcmV0dXJuIDxJdGVtc0VkaXRvciBpdGVtcz17aXRlbXN9IG9uQWRkPXthZGRJdGVtc30gb25SZW1vdmU9e3JlbW92ZUl0ZW19IC8+Cn0KYGBgCgoqKkJlbmVmaXRzOioqCgoxLiAqKlN0YWJsZSBjYWxsYmFjayByZWZlcmVuY2VzKiogLSBDYWxsYmFja3MgZG9uJ3QgbmVlZCB0byBiZSByZWNyZWF0ZWQgd2hlbiBzdGF0ZSBjaGFuZ2VzCgoyLiAqKk5vIHN0YWxlIGNsb3N1cmVzKiogLSBBbHdheXMgb3BlcmF0ZXMgb24gdGhlIGxhdGVzdCBzdGF0ZSB2YWx1ZQoKMy4gKipGZXdlciBkZXBlbmRlbmNpZXMqKiAtIFNpbXBsaWZpZXMgZGVwZW5kZW5jeSBhcnJheXMgYW5kIHJlZHVjZXMgbWVtb3J5IGxlYWtzCgo0LiAqKlByZXZlbnRzIGJ1Z3MqKiAtIEVsaW1pbmF0ZXMgdGhlIG1vc3QgY29tbW9uIHNvdXJjZSBvZiBSZWFjdCBjbG9zdXJlIGJ1Z3MKCioqV2hlbiB0byB1c2UgZnVuY3Rpb25hbCB1cGRhdGVzOioqCgotIEFueSBzZXRTdGF0ZSB0aGF0IGRlcGVuZHMgb24gdGhlIGN1cnJlbnQgc3RhdGUgdmFsdWUKCi0gSW5zaWRlIHVzZUNhbGxiYWNrL3VzZU1lbW8gd2hlbiBzdGF0ZSBpcyBuZWVkZWQKCi0gRXZlbnQgaGFuZGxlcnMgdGhhdCByZWZlcmVuY2Ugc3RhdGUKCi0gQXN5bmMgb3BlcmF0aW9ucyB0aGF0IHVwZGF0ZSBzdGF0ZQoKKipXaGVuIGRpcmVjdCB1cGRhdGVzIGFyZSBmaW5lOioqCgotIFNldHRpbmcgc3RhdGUgdG8gYSBzdGF0aWMgdmFsdWU6IGBzZXRDb3VudCgwKWAKCi0gU2V0dGluZyBzdGF0ZSBmcm9tIHByb3BzL2FyZ3VtZW50cyBvbmx5OiBgc2V0TmFtZShuZXdOYW1lKWAKCi0gU3RhdGUgZG9lc24ndCBkZXBlbmQgb24gcHJldmlvdXMgdmFsdWUKCioqTm90ZToqKiBJZiB5b3VyIHByb2plY3QgaGFzIFtSZWFjdCBDb21waWxlcl0oaHR0cHM6Ly9yZWFjdC5kZXYvbGVhcm4vcmVhY3QtY29tcGlsZXIpIGVuYWJsZWQsIHRoZSBjb21waWxlciBjYW4gYXV0b21hdGljYWxseSBvcHRpbWl6ZSBzb21lIGNhc2VzLCBidXQgZnVuY3Rpb25hbCB1cGRhdGVzIGFyZSBzdGlsbCByZWNvbW1lbmRlZCBmb3IgY29ycmVjdG5lc3MgYW5kIHRvIHByZXZlbnQgc3RhbGUgY2xvc3VyZSBidWdzLgoKIyMjIDUuOCBVc2UgTGF6eSBTdGF0ZSBJbml0aWFsaXphdGlvbgoKKipJbXBhY3Q6IE1FRElVTSAod2FzdGVkIGNvbXB1dGF0aW9uIG9uIGV2ZXJ5IHJlbmRlcikqKgoKUGFzcyBhIGZ1bmN0aW9uIHRvIGB1c2VTdGF0ZWAgZm9yIGV4cGVuc2l2ZSBpbml0aWFsIHZhbHVlcy4gV2l0aG91dCB0aGUgZnVuY3Rpb24gZm9ybSwgdGhlIGluaXRpYWxpemVyIHJ1bnMgb24gZXZlcnkgcmVuZGVyIGV2ZW4gdGhvdWdoIHRoZSB2YWx1ZSBpcyBvbmx5IHVzZWQgb25jZS4KCioqSW5jb3JyZWN0OiBydW5zIG9uIGV2ZXJ5IHJlbmRlcioqCgpgYGB0c3gKZnVuY3Rpb24gRmlsdGVyZWRMaXN0KHsgaXRlbXMgfTogeyBpdGVtczogSXRlbVtdIH0pIHsKICAvLyBidWlsZFNlYXJjaEluZGV4KCkgcnVucyBvbiBFVkVSWSByZW5kZXIsIGV2ZW4gYWZ0ZXIgaW5pdGlhbGl6YXRpb24KICBjb25zdCBbc2VhcmNoSW5kZXgsIHNldFNlYXJjaEluZGV4XSA9IHVzZVN0YXRlKGJ1aWxkU2VhcmNoSW5kZXgoaXRlbXMpKQogIGNvbnN0IFtxdWVyeSwgc2V0UXVlcnldID0gdXNlU3RhdGUoJycpCiAgCiAgLy8gV2hlbiBxdWVyeSBjaGFuZ2VzLCBidWlsZFNlYXJjaEluZGV4IHJ1bnMgYWdhaW4gdW5uZWNlc3NhcmlseQogIHJldHVybiA8U2VhcmNoUmVzdWx0cyBpbmRleD17c2VhcmNoSW5kZXh9IHF1ZXJ5PXtxdWVyeX0gLz4KfQoKZnVuY3Rpb24gVXNlclByb2ZpbGUoKSB7CiAgLy8gSlNPTi5wYXJzZSBydW5zIG9uIGV2ZXJ5IHJlbmRlcgogIGNvbnN0IFtzZXR0aW5ncywgc2V0U2V0dGluZ3NdID0gdXNlU3RhdGUoCiAgICBKU09OLnBhcnNlKGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdzZXR0aW5ncycpIHx8ICd7fScpCiAgKQogIAogIHJldHVybiA8U2V0dGluZ3NGb3JtIHNldHRpbmdzPXtzZXR0aW5nc30gb25DaGFuZ2U9e3NldFNldHRpbmdzfSAvPgp9CmBgYAoKKipDb3JyZWN0OiBydW5zIG9ubHkgb25jZSoqCgpgYGB0c3gKZnVuY3Rpb24gRmlsdGVyZWRMaXN0KHsgaXRlbXMgfTogeyBpdGVtczogSXRlbVtdIH0pIHsKICAvLyBidWlsZFNlYXJjaEluZGV4KCkgcnVucyBPTkxZIG9uIGluaXRpYWwgcmVuZGVyCiAgY29uc3QgW3NlYXJjaEluZGV4LCBzZXRTZWFyY2hJbmRleF0gPSB1c2VTdGF0ZSgoKSA9PiBidWlsZFNlYXJjaEluZGV4KGl0ZW1zKSkKICBjb25zdCBbcXVlcnksIHNldFF1ZXJ5XSA9IHVzZVN0YXRlKCcnKQogIAogIHJldHVybiA8U2VhcmNoUmVzdWx0cyBpbmRleD17c2VhcmNoSW5kZXh9IHF1ZXJ5PXtxdWVyeX0gLz4KfQoKZnVuY3Rpb24gVXNlclByb2ZpbGUoKSB7CiAgLy8gSlNPTi5wYXJzZSBydW5zIG9ubHkgb24gaW5pdGlhbCByZW5kZXIKICBjb25zdCBbc2V0dGluZ3MsIHNldFNldHRpbmdzXSA9IHVzZVN0YXRlKCgpID0+IHsKICAgIGNvbnN0IHN0b3JlZCA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCdzZXR0aW5ncycpCiAgICByZXR1cm4gc3RvcmVkID8gSlNPTi5wYXJzZShzdG9yZWQpIDoge30KICB9KQogIAogIHJldHVybiA8U2V0dGluZ3NGb3JtIHNldHRpbmdzPXtzZXR0aW5nc30gb25DaGFuZ2U9e3NldFNldHRpbmdzfSAvPgp9CmBgYAoKVXNlIGxhenkgaW5pdGlhbGl6YXRpb24gd2hlbiBjb21wdXRpbmcgaW5pdGlhbCB2YWx1ZXMgZnJvbSBsb2NhbFN0b3JhZ2Uvc2Vzc2lvblN0b3JhZ2UsIGJ1aWxkaW5nIGRhdGEgc3RydWN0dXJlcyAoaW5kZXhlcywgbWFwcyksIHJlYWRpbmcgZnJvbSB0aGUgRE9NLCBvciBwZXJmb3JtaW5nIGhlYXZ5IHRyYW5zZm9ybWF0aW9ucy4KCkZvciBzaW1wbGUgcHJpbWl0aXZlcyAoYHVzZVN0YXRlKDApYCksIGRpcmVjdCByZWZlcmVuY2VzIChgdXNlU3RhdGUocHJvcHMudmFsdWUpYCksIG9yIGNoZWFwIGxpdGVyYWxzIChgdXNlU3RhdGUoe30pYCksIHRoZSBmdW5jdGlvbiBmb3JtIGlzIHVubmVjZXNzYXJ5LgoKIyMjIDUuOSBVc2UgVHJhbnNpdGlvbnMgZm9yIE5vbi1VcmdlbnQgVXBkYXRlcwoKKipJbXBhY3Q6IE1FRElVTSAobWFpbnRhaW5zIFVJIHJlc3BvbnNpdmVuZXNzKSoqCgpNYXJrIGZyZXF1ZW50LCBub24tdXJnZW50IHN0YXRlIHVwZGF0ZXMgYXMgdHJhbnNpdGlvbnMgdG8gbWFpbnRhaW4gVUkgcmVzcG9uc2l2ZW5lc3MuCgoqKkluY29ycmVjdDogYmxvY2tzIFVJIG9uIGV2ZXJ5IHNjcm9sbCoqCgpgYGB0c3gKZnVuY3Rpb24gU2Nyb2xsVHJhY2tlcigpIHsKICBjb25zdCBbc2Nyb2xsWSwgc2V0U2Nyb2xsWV0gPSB1c2VTdGF0ZSgwKQogIHVzZUVmZmVjdCgoKSA9PiB7CiAgICBjb25zdCBoYW5kbGVyID0gKCkgPT4gc2V0U2Nyb2xsWSh3aW5kb3cuc2Nyb2xsWSkKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdzY3JvbGwnLCBoYW5kbGVyLCB7IHBhc3NpdmU6IHRydWUgfSkKICAgIHJldHVybiAoKSA9PiB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgaGFuZGxlcikKICB9LCBbXSkKfQpgYGAKCioqQ29ycmVjdDogbm9uLWJsb2NraW5nIHVwZGF0ZXMqKgoKYGBgdHN4CmltcG9ydCB7IHN0YXJ0VHJhbnNpdGlvbiB9IGZyb20gJ3JlYWN0JwoKZnVuY3Rpb24gU2Nyb2xsVHJhY2tlcigpIHsKICBjb25zdCBbc2Nyb2xsWSwgc2V0U2Nyb2xsWV0gPSB1c2VTdGF0ZSgwKQogIHVzZUVmZmVjdCgoKSA9PiB7CiAgICBjb25zdCBoYW5kbGVyID0gKCkgPT4gewogICAgICBzdGFydFRyYW5zaXRpb24oKCkgPT4gc2V0U2Nyb2xsWSh3aW5kb3cuc2Nyb2xsWSkpCiAgICB9CiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignc2Nyb2xsJywgaGFuZGxlciwgeyBwYXNzaXZlOiB0cnVlIH0pCiAgICByZXR1cm4gKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ3Njcm9sbCcsIGhhbmRsZXIpCiAgfSwgW10pCn0KYGBgCgotLS0KCiMjIDYuIFJlbmRlcmluZyBQZXJmb3JtYW5jZQoKKipJbXBhY3Q6IE1FRElVTSoqCgpPcHRpbWl6aW5nIHRoZSByZW5kZXJpbmcgcHJvY2VzcyByZWR1Y2VzIHRoZSB3b3JrIHRoZSBicm93c2VyIG5lZWRzIHRvIGRvLgoKIyMjIDYuMSBBbmltYXRlIFNWRyBXcmFwcGVyIEluc3RlYWQgb2YgU1ZHIEVsZW1lbnQKCioqSW1wYWN0OiBMT1cgKGVuYWJsZXMgaGFyZHdhcmUgYWNjZWxlcmF0aW9uKSoqCgpNYW55IGJyb3dzZXJzIGRvbid0IGhhdmUgaGFyZHdhcmUgYWNjZWxlcmF0aW9uIGZvciBDU1MzIGFuaW1hdGlvbnMgb24gU1ZHIGVsZW1lbnRzLiBXcmFwIFNWRyBpbiBhIGA8ZGl2PmAgYW5kIGFuaW1hdGUgdGhlIHdyYXBwZXIgaW5zdGVhZC4KCioqSW5jb3JyZWN0OiBhbmltYXRpbmcgU1ZHIGRpcmVjdGx5IC0gbm8gaGFyZHdhcmUgYWNjZWxlcmF0aW9uKioKCmBgYHRzeApmdW5jdGlvbiBMb2FkaW5nU3Bpbm5lcigpIHsKICByZXR1cm4gKAogICAgPHN2ZyAKICAgICAgY2xhc3NOYW1lPSJhbmltYXRlLXNwaW4iCiAgICAgIHdpZHRoPSIyNCIgCiAgICAgIGhlaWdodD0iMjQiIAogICAgICB2aWV3Qm94PSIwIDAgMjQgMjQiCiAgICA+CiAgICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEwIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgLz4KICAgIDwvc3ZnPgogICkKfQpgYGAKCioqQ29ycmVjdDogYW5pbWF0aW5nIHdyYXBwZXIgZGl2IC0gaGFyZHdhcmUgYWNjZWxlcmF0ZWQqKgoKYGBgdHN4CmZ1bmN0aW9uIExvYWRpbmdTcGlubmVyKCkgewogIHJldHVybiAoCiAgICA8ZGl2IGNsYXNzTmFtZT0iYW5pbWF0ZS1zcGluIj4KICAgICAgPHN2ZyAKICAgICAgICB3aWR0aD0iMjQiIAogICAgICAgIGhlaWdodD0iMjQiIAogICAgICAgIHZpZXdCb3g9IjAgMCAyNCAyNCIKICAgICAgPgogICAgICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjEwIiBzdHJva2U9ImN1cnJlbnRDb2xvciIgLz4KICAgICAgPC9zdmc+CiAgICA8L2Rpdj4KICApCn0KYGBgCgpUaGlzIGFwcGxpZXMgdG8gYWxsIENTUyB0cmFuc2Zvcm1zIGFuZCB0cmFuc2l0aW9ucyAoYHRyYW5zZm9ybWAsIGBvcGFjaXR5YCwgYHRyYW5zbGF0ZWAsIGBzY2FsZWAsIGByb3RhdGVgKS4gVGhlIHdyYXBwZXIgZGl2IGFsbG93cyBicm93c2VycyB0byB1c2UgR1BVIGFjY2VsZXJhdGlvbiBmb3Igc21vb3RoZXIgYW5pbWF0aW9ucy4KCiMjIyA2LjIgQ1NTIGNvbnRlbnQtdmlzaWJpbGl0eSBmb3IgTG9uZyBMaXN0cwoKKipJbXBhY3Q6IEhJR0ggKGZhc3RlciBpbml0aWFsIHJlbmRlcikqKgoKQXBwbHkgYGNvbnRlbnQtdmlzaWJpbGl0eTogYXV0b2AgdG8gZGVmZXIgb2ZmLXNjcmVlbiByZW5kZXJpbmcuCgoqKkNTUzoqKgoKYGBgY3NzCi5tZXNzYWdlLWl0ZW0gewogIGNvbnRlbnQtdmlzaWJpbGl0eTogYXV0bzsKICBjb250YWluLWludHJpbnNpYy1zaXplOiAwIDgwcHg7Cn0KYGBgCgoqKkV4YW1wbGU6KioKCmBgYHRzeApmdW5jdGlvbiBNZXNzYWdlTGlzdCh7IG1lc3NhZ2VzIH06IHsgbWVzc2FnZXM6IE1lc3NhZ2VbXSB9KSB7CiAgcmV0dXJuICgKICAgIDxkaXYgY2xhc3NOYW1lPSJvdmVyZmxvdy15LWF1dG8gaC1zY3JlZW4iPgogICAgICB7bWVzc2FnZXMubWFwKG1zZyA9PiAoCiAgICAgICAgPGRpdiBrZXk9e21zZy5pZH0gY2xhc3NOYW1lPSJtZXNzYWdlLWl0ZW0iPgogICAgICAgICAgPEF2YXRhciB1c2VyPXttc2cuYXV0aG9yfSAvPgogICAgICAgICAgPGRpdj57bXNnLmNvbnRlbnR9PC9kaXY+CiAgICAgICAgPC9kaXY+CiAgICAgICkpfQogICAgPC9kaXY+CiAgKQp9CmBgYAoKRm9yIDEwMDAgbWVzc2FnZXMsIGJyb3dzZXIgc2tpcHMgbGF5b3V0L3BhaW50IGZvciB+OTkwIG9mZi1zY3JlZW4gaXRlbXMgKDEww5cgZmFzdGVyIGluaXRpYWwgcmVuZGVyKS4KCiMjIyA2LjMgSG9pc3QgU3RhdGljIEpTWCBFbGVtZW50cwoKKipJbXBhY3Q6IExPVyAoYXZvaWRzIHJlLWNyZWF0aW9uKSoqCgpFeHRyYWN0IHN0YXRpYyBKU1ggb3V0c2lkZSBjb21wb25lbnRzIHRvIGF2b2lkIHJlLWNyZWF0aW9uLgoKKipJbmNvcnJlY3Q6IHJlY3JlYXRlcyBlbGVtZW50IGV2ZXJ5IHJlbmRlcioqCgpgYGB0c3gKZnVuY3Rpb24gTG9hZGluZ1NrZWxldG9uKCkgewogIHJldHVybiA8ZGl2IGNsYXNzTmFtZT0iYW5pbWF0ZS1wdWxzZSBoLTIwIGJnLWdyYXktMjAwIiAvPgp9CgpmdW5jdGlvbiBDb250YWluZXIoKSB7CiAgcmV0dXJuICgKICAgIDxkaXY+CiAgICAgIHtsb2FkaW5nICYmIDxMb2FkaW5nU2tlbGV0b24gLz59CiAgICA8L2Rpdj4KICApCn0KYGBgCgoqKkNvcnJlY3Q6IHJldXNlcyBzYW1lIGVsZW1lbnQqKgoKYGBgdHN4CmNvbnN0IGxvYWRpbmdTa2VsZXRvbiA9ICgKICA8ZGl2IGNsYXNzTmFtZT0iYW5pbWF0ZS1wdWxzZSBoLTIwIGJnLWdyYXktMjAwIiAvPgopCgpmdW5jdGlvbiBDb250YWluZXIoKSB7CiAgcmV0dXJuICgKICAgIDxkaXY+CiAgICAgIHtsb2FkaW5nICYmIGxvYWRpbmdTa2VsZXRvbn0KICAgIDwvZGl2PgogICkKfQpgYGAKClRoaXMgaXMgZXNwZWNpYWxseSBoZWxwZnVsIGZvciBsYXJnZSBhbmQgc3RhdGljIFNWRyBub2Rlcywgd2hpY2ggY2FuIGJlIGV4cGVuc2l2ZSB0byByZWNyZWF0ZSBvbiBldmVyeSByZW5kZXIuCgoqKk5vdGU6KiogSWYgeW91ciBwcm9qZWN0IGhhcyBbUmVhY3QgQ29tcGlsZXJdKGh0dHBzOi8vcmVhY3QuZGV2L2xlYXJuL3JlYWN0LWNvbXBpbGVyKSBlbmFibGVkLCB0aGUgY29tcGlsZXIgYXV0b21hdGljYWxseSBob2lzdHMgc3RhdGljIEpTWCBlbGVtZW50cyBhbmQgb3B0aW1pemVzIGNvbXBvbmVudCByZS1yZW5kZXJzLCBtYWtpbmcgbWFudWFsIGhvaXN0aW5nIHVubmVjZXNzYXJ5LgoKIyMjIDYuNCBPcHRpbWl6ZSBTVkcgUHJlY2lzaW9uCgoqKkltcGFjdDogTE9XIChyZWR1Y2VzIGZpbGUgc2l6ZSkqKgoKUmVkdWNlIFNWRyBjb29yZGluYXRlIHByZWNpc2lvbiB0byBkZWNyZWFzZSBmaWxlIHNpemUuIFRoZSBvcHRpbWFsIHByZWNpc2lvbiBkZXBlbmRzIG9uIHRoZSB2aWV3Qm94IHNpemUsIGJ1dCBpbiBnZW5lcmFsIHJlZHVjaW5nIHByZWNpc2lvbiBzaG91bGQgYmUgY29uc2lkZXJlZC4KCioqSW5jb3JyZWN0OiBleGNlc3NpdmUgcHJlY2lzaW9uKioKCmBgYHN2Zwo8cGF0aCBkPSJNIDEwLjI5Mzg0NyAyMC44NDczNjIgTCAzMC45Mzg0NzIgNDAuMTkyODM3IiAvPgpgYGAKCioqQ29ycmVjdDogMSBkZWNpbWFsIHBsYWNlKioKCmBgYHN2Zwo8cGF0aCBkPSJNIDEwLjMgMjAuOCBMIDMwLjkgNDAuMiIgLz4KYGBgCgoqKkF1dG9tYXRlIHdpdGggU1ZHTzoqKgoKYGBgYmFzaApucHggc3ZnbyAtLXByZWNpc2lvbj0xIC0tbXVsdGlwYXNzIGljb24uc3ZnCmBgYAoKIyMjIDYuNSBQcmV2ZW50IEh5ZHJhdGlvbiBNaXNtYXRjaCBXaXRob3V0IEZsaWNrZXJpbmcKCioqSW1wYWN0OiBNRURJVU0gKGF2b2lkcyB2aXN1YWwgZmxpY2tlciBhbmQgaHlkcmF0aW9uIGVycm9ycykqKgoKV2hlbiByZW5kZXJpbmcgY29udGVudCB0aGF0IGRlcGVuZHMgb24gY2xpZW50LXNpZGUgc3RvcmFnZSAobG9jYWxTdG9yYWdlLCBjb29raWVzKSwgYXZvaWQgYm90aCBTU1IgYnJlYWthZ2UgYW5kIHBvc3QtaHlkcmF0aW9uIGZsaWNrZXJpbmcgYnkgaW5qZWN0aW5nIGEgc3luY2hyb25vdXMgc2NyaXB0IHRoYXQgdXBkYXRlcyB0aGUgRE9NIGJlZm9yZSBSZWFjdCBoeWRyYXRlcy4KCioqSW5jb3JyZWN0OiBicmVha3MgU1NSKioKCmBgYHRzeApmdW5jdGlvbiBUaGVtZVdyYXBwZXIoeyBjaGlsZHJlbiB9OiB7IGNoaWxkcmVuOiBSZWFjdE5vZGUgfSkgewogIC8vIGxvY2FsU3RvcmFnZSBpcyBub3QgYXZhaWxhYmxlIG9uIHNlcnZlciAtIHRocm93cyBlcnJvcgogIGNvbnN0IHRoZW1lID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3RoZW1lJykgfHwgJ2xpZ2h0JwogIAogIHJldHVybiAoCiAgICA8ZGl2IGNsYXNzTmFtZT17dGhlbWV9PgogICAgICB7Y2hpbGRyZW59CiAgICA8L2Rpdj4KICApCn0KYGBgCgpTZXJ2ZXItc2lkZSByZW5kZXJpbmcgd2lsbCBmYWlsIGJlY2F1c2UgYGxvY2FsU3RvcmFnZWAgaXMgdW5kZWZpbmVkLgoKKipJbmNvcnJlY3Q6IHZpc3VhbCBmbGlja2VyaW5nKioKCmBgYHRzeApmdW5jdGlvbiBUaGVtZVdyYXBwZXIoeyBjaGlsZHJlbiB9OiB7IGNoaWxkcmVuOiBSZWFjdE5vZGUgfSkgewogIGNvbnN0IFt0aGVtZSwgc2V0VGhlbWVdID0gdXNlU3RhdGUoJ2xpZ2h0JykKICAKICB1c2VFZmZlY3QoKCkgPT4gewogICAgLy8gUnVucyBhZnRlciBoeWRyYXRpb24gLSBjYXVzZXMgdmlzaWJsZSBmbGFzaAogICAgY29uc3Qgc3RvcmVkID0gbG9jYWxTdG9yYWdlLmdldEl0ZW0oJ3RoZW1lJykKICAgIGlmIChzdG9yZWQpIHsKICAgICAgc2V0VGhlbWUoc3RvcmVkKQogICAgfQogIH0sIFtdKQogIAogIHJldHVybiAoCiAgICA8ZGl2IGNsYXNzTmFtZT17dGhlbWV9PgogICAgICB7Y2hpbGRyZW59CiAgICA8L2Rpdj4KICApCn0KYGBgCgpDb21wb25lbnQgZmlyc3QgcmVuZGVycyB3aXRoIGRlZmF1bHQgdmFsdWUgKGBsaWdodGApLCB0aGVuIHVwZGF0ZXMgYWZ0ZXIgaHlkcmF0aW9uLCBjYXVzaW5nIGEgdmlzaWJsZSBmbGFzaCBvZiBpbmNvcnJlY3QgY29udGVudC4KCioqQ29ycmVjdDogbm8gZmxpY2tlciwgbm8gaHlkcmF0aW9uIG1pc21hdGNoKioKCmBgYHRzeApmdW5jdGlvbiBUaGVtZVdyYXBwZXIoeyBjaGlsZHJlbiB9OiB7IGNoaWxkcmVuOiBSZWFjdE5vZGUgfSkgewogIHJldHVybiAoCiAgICA8PgogICAgICA8ZGl2IGlkPSJ0aGVtZS13cmFwcGVyIj4KICAgICAgICB7Y2hpbGRyZW59CiAgICAgIDwvZGl2PgogICAgICA8c2NyaXB0CiAgICAgICAgZGFuZ2Vyb3VzbHlTZXRJbm5lckhUTUw9e3sKICAgICAgICAgIF9faHRtbDogYAogICAgICAgICAgICAoZnVuY3Rpb24oKSB7CiAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgIHZhciB0aGVtZSA9IGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd0aGVtZScpIHx8ICdsaWdodCc7CiAgICAgICAgICAgICAgICB2YXIgZWwgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgndGhlbWUtd3JhcHBlcicpOwogICAgICAgICAgICAgICAgaWYgKGVsKSBlbC5jbGFzc05hbWUgPSB0aGVtZTsKICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7fQogICAgICAgICAgICB9KSgpOwogICAgICAgICAgYCwKICAgICAgICB9fQogICAgICAvPgogICAgPC8+CiAgKQp9CmBgYAoKVGhlIGlubGluZSBzY3JpcHQgZXhlY3V0ZXMgc3luY2hyb25vdXNseSBiZWZvcmUgc2hvd2luZyB0aGUgZWxlbWVudCwgZW5zdXJpbmcgdGhlIERPTSBhbHJlYWR5IGhhcyB0aGUgY29ycmVjdCB2YWx1ZS4gTm8gZmxpY2tlcmluZywgbm8gaHlkcmF0aW9uIG1pc21hdGNoLgoKVGhpcyBwYXR0ZXJuIGlzIGVzcGVjaWFsbHkgdXNlZnVsIGZvciB0aGVtZSB0b2dnbGVzLCB1c2VyIHByZWZlcmVuY2VzLCBhdXRoZW50aWNhdGlvbiBzdGF0ZXMsIGFuZCBhbnkgY2xpZW50LW9ubHkgZGF0YSB0aGF0IHNob3VsZCByZW5kZXIgaW1tZWRpYXRlbHkgd2l0aG91dCBmbGFzaGluZyBkZWZhdWx0IHZhbHVlcy4KCiMjIyA2LjYgVXNlIEFjdGl2aXR5IENvbXBvbmVudCBmb3IgU2hvdy9IaWRlCgoqKkltcGFjdDogTUVESVVNIChwcmVzZXJ2ZXMgc3RhdGUvRE9NKSoqCgpVc2UgUmVhY3QncyBgPEFjdGl2aXR5PmAgdG8gcHJlc2VydmUgc3RhdGUvRE9NIGZvciBleHBlbnNpdmUgY29tcG9uZW50cyB0aGF0IGZyZXF1ZW50bHkgdG9nZ2xlIHZpc2liaWxpdHkuCgoqKlVzYWdlOioqCgpgYGB0c3gKaW1wb3J0IHsgQWN0aXZpdHkgfSBmcm9tICdyZWFjdCcKCmZ1bmN0aW9uIERyb3Bkb3duKHsgaXNPcGVuIH06IFByb3BzKSB7CiAgcmV0dXJuICgKICAgIDxBY3Rpdml0eSBtb2RlPXtpc09wZW4gPyAndmlzaWJsZScgOiAnaGlkZGVuJ30+CiAgICAgIDxFeHBlbnNpdmVNZW51IC8+CiAgICA8L0FjdGl2aXR5PgogICkKfQpgYGAKCkF2b2lkcyBleHBlbnNpdmUgcmUtcmVuZGVycyBhbmQgc3RhdGUgbG9zcy4KCiMjIyA2LjcgVXNlIEV4cGxpY2l0IENvbmRpdGlvbmFsIFJlbmRlcmluZwoKKipJbXBhY3Q6IExPVyAocHJldmVudHMgcmVuZGVyaW5nIDAgb3IgTmFOKSoqCgpVc2UgZXhwbGljaXQgdGVybmFyeSBvcGVyYXRvcnMgKGA/IDpgKSBpbnN0ZWFkIG9mIGAmJmAgZm9yIGNvbmRpdGlvbmFsIHJlbmRlcmluZyB3aGVuIHRoZSBjb25kaXRpb24gY2FuIGJlIGAwYCwgYE5hTmAsIG9yIG90aGVyIGZhbHN5IHZhbHVlcyB0aGF0IHJlbmRlci4KCioqSW5jb3JyZWN0OiByZW5kZXJzICIwIiB3aGVuIGNvdW50IGlzIDAqKgoKYGBgdHN4CmZ1bmN0aW9uIEJhZGdlKHsgY291bnQgfTogeyBjb3VudDogbnVtYmVyIH0pIHsKICByZXR1cm4gKAogICAgPGRpdj4KICAgICAge2NvdW50ICYmIDxzcGFuIGNsYXNzTmFtZT0iYmFkZ2UiPntjb3VudH08L3NwYW4+fQogICAgPC9kaXY+CiAgKQp9CgovLyBXaGVuIGNvdW50ID0gMCwgcmVuZGVyczogPGRpdj4wPC9kaXY+Ci8vIFdoZW4gY291bnQgPSA1LCByZW5kZXJzOiA8ZGl2PjxzcGFuIGNsYXNzPSJiYWRnZSI+NTwvc3Bhbj48L2Rpdj4KYGBgCgoqKkNvcnJlY3Q6IHJlbmRlcnMgbm90aGluZyB3aGVuIGNvdW50IGlzIDAqKgoKYGBgdHN4CmZ1bmN0aW9uIEJhZGdlKHsgY291bnQgfTogeyBjb3VudDogbnVtYmVyIH0pIHsKICByZXR1cm4gKAogICAgPGRpdj4KICAgICAge2NvdW50ID4gMCA/IDxzcGFuIGNsYXNzTmFtZT0iYmFkZ2UiPntjb3VudH08L3NwYW4+IDogbnVsbH0KICAgIDwvZGl2PgogICkKfQoKLy8gV2hlbiBjb3VudCA9IDAsIHJlbmRlcnM6IDxkaXY+PC9kaXY+Ci8vIFdoZW4gY291bnQgPSA1LCByZW5kZXJzOiA8ZGl2PjxzcGFuIGNsYXNzPSJiYWRnZSI+NTwvc3Bhbj48L2Rpdj4KYGBgCgojIyMgNi44IFVzZSB1c2VUcmFuc2l0aW9uIE92ZXIgTWFudWFsIExvYWRpbmcgU3RhdGVzCgoqKkltcGFjdDogTE9XIChyZWR1Y2VzIHJlLXJlbmRlcnMgYW5kIGltcHJvdmVzIGNvZGUgY2xhcml0eSkqKgoKVXNlIGB1c2VUcmFuc2l0aW9uYCBpbnN0ZWFkIG9mIG1hbnVhbCBgdXNlU3RhdGVgIGZvciBsb2FkaW5nIHN0YXRlcy4gVGhpcyBwcm92aWRlcyBidWlsdC1pbiBgaXNQZW5kaW5nYCBzdGF0ZSBhbmQgYXV0b21hdGljYWxseSBtYW5hZ2VzIHRyYW5zaXRpb25zLgoKKipJbmNvcnJlY3Q6IG1hbnVhbCBsb2FkaW5nIHN0YXRlKioKCmBgYHRzeApmdW5jdGlvbiBTZWFyY2hSZXN1bHRzKCkgewogIGNvbnN0IFtxdWVyeSwgc2V0UXVlcnldID0gdXNlU3RhdGUoJycpCiAgY29uc3QgW3Jlc3VsdHMsIHNldFJlc3VsdHNdID0gdXNlU3RhdGUoW10pCiAgY29uc3QgW2lzTG9hZGluZywgc2V0SXNMb2FkaW5nXSA9IHVzZVN0YXRlKGZhbHNlKQoKICBjb25zdCBoYW5kbGVTZWFyY2ggPSBhc3luYyAodmFsdWU6IHN0cmluZykgPT4gewogICAgc2V0SXNMb2FkaW5nKHRydWUpCiAgICBzZXRRdWVyeSh2YWx1ZSkKICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBmZXRjaFJlc3VsdHModmFsdWUpCiAgICBzZXRSZXN1bHRzKGRhdGEpCiAgICBzZXRJc0xvYWRpbmcoZmFsc2UpCiAgfQoKICByZXR1cm4gKAogICAgPD4KICAgICAgPGlucHV0IG9uQ2hhbmdlPXsoZSkgPT4gaGFuZGxlU2VhcmNoKGUudGFyZ2V0LnZhbHVlKX0gLz4KICAgICAge2lzTG9hZGluZyAmJiA8U3Bpbm5lciAvPn0KICAgICAgPFJlc3VsdHNMaXN0IHJlc3VsdHM9e3Jlc3VsdHN9IC8+CiAgICA8Lz4KICApCn0KYGBgCgoqKkNvcnJlY3Q6IHVzZVRyYW5zaXRpb24gd2l0aCBidWlsdC1pbiBwZW5kaW5nIHN0YXRlKioKCmBgYHRzeAppbXBvcnQgeyB1c2VUcmFuc2l0aW9uLCB1c2VTdGF0ZSB9IGZyb20gJ3JlYWN0JwoKZnVuY3Rpb24gU2VhcmNoUmVzdWx0cygpIHsKICBjb25zdCBbcXVlcnksIHNldFF1ZXJ5XSA9IHVzZVN0YXRlKCcnKQogIGNvbnN0IFtyZXN1bHRzLCBzZXRSZXN1bHRzXSA9IHVzZVN0YXRlKFtdKQogIGNvbnN0IFtpc1BlbmRpbmcsIHN0YXJ0VHJhbnNpdGlvbl0gPSB1c2VUcmFuc2l0aW9uKCkKCiAgY29uc3QgaGFuZGxlU2VhcmNoID0gKHZhbHVlOiBzdHJpbmcpID0+IHsKICAgIHNldFF1ZXJ5KHZhbHVlKSAvLyBVcGRhdGUgaW5wdXQgaW1tZWRpYXRlbHkKICAgIAogICAgc3RhcnRUcmFuc2l0aW9uKGFzeW5jICgpID0+IHsKICAgICAgLy8gRmV0Y2ggYW5kIHVwZGF0ZSByZXN1bHRzCiAgICAgIGNvbnN0IGRhdGEgPSBhd2FpdCBmZXRjaFJlc3VsdHModmFsdWUpCiAgICAgIHNldFJlc3VsdHMoZGF0YSkKICAgIH0pCiAgfQoKICByZXR1cm4gKAogICAgPD4KICAgICAgPGlucHV0IG9uQ2hhbmdlPXsoZSkgPT4gaGFuZGxlU2VhcmNoKGUudGFyZ2V0LnZhbHVlKX0gLz4KICAgICAge2lzUGVuZGluZyAmJiA8U3Bpbm5lciAvPn0KICAgICAgPFJlc3VsdHNMaXN0IHJlc3VsdHM9e3Jlc3VsdHN9IC8+CiAgICA8Lz4KICApCn0KYGBgCgoqKkJlbmVmaXRzOioqCgotICoqQXV0b21hdGljIHBlbmRpbmcgc3RhdGUqKjogTm8gbmVlZCB0byBtYW51YWxseSBtYW5hZ2UgYHNldElzTG9hZGluZyh0cnVlL2ZhbHNlKWAKCi0gKipFcnJvciByZXNpbGllbmNlKio6IFBlbmRpbmcgc3RhdGUgY29ycmVjdGx5IHJlc2V0cyBldmVuIGlmIHRoZSB0cmFuc2l0aW9uIHRocm93cwoKLSAqKkJldHRlciByZXNwb25zaXZlbmVzcyoqOiBLZWVwcyB0aGUgVUkgcmVzcG9uc2l2ZSBkdXJpbmcgdXBkYXRlcwoKLSAqKkludGVycnVwdCBoYW5kbGluZyoqOiBOZXcgdHJhbnNpdGlvbnMgYXV0b21hdGljYWxseSBjYW5jZWwgcGVuZGluZyBvbmVzCgpSZWZlcmVuY2U6IFtodHRwczovL3JlYWN0LmRldi9yZWZlcmVuY2UvcmVhY3QvdXNlVHJhbnNpdGlvbl0oaHR0cHM6Ly9yZWFjdC5kZXYvcmVmZXJlbmNlL3JlYWN0L3VzZVRyYW5zaXRpb24pCgotLS0KCiMjIDcuIEphdmFTY3JpcHQgUGVyZm9ybWFuY2UKCioqSW1wYWN0OiBMT1ctTUVESVVNKioKCk1pY3JvLW9wdGltaXphdGlvbnMgZm9yIGhvdCBwYXRocyBjYW4gYWRkIHVwIHRvIG1lYW5pbmdmdWwgaW1wcm92ZW1lbnRzLgoKIyMjIDcuMSBBdm9pZCBMYXlvdXQgVGhyYXNoaW5nCgoqKkltcGFjdDogTUVESVVNIChwcmV2ZW50cyBmb3JjZWQgc3luY2hyb25vdXMgbGF5b3V0cyBhbmQgcmVkdWNlcyBwZXJmb3JtYW5jZSBib3R0bGVuZWNrcykqKgoKQXZvaWQgaW50ZXJsZWF2aW5nIHN0eWxlIHdyaXRlcyB3aXRoIGxheW91dCByZWFkcy4gV2hlbiB5b3UgcmVhZCBhIGxheW91dCBwcm9wZXJ0eSAobGlrZSBgb2Zmc2V0V2lkdGhgLCBgZ2V0Qm91bmRpbmdDbGllbnRSZWN0KClgLCBvciBgZ2V0Q29tcHV0ZWRTdHlsZSgpYCkgYmV0d2VlbiBzdHlsZSBjaGFuZ2VzLCB0aGUgYnJvd3NlciBpcyBmb3JjZWQgdG8gdHJpZ2dlciBhIHN5bmNocm9ub3VzIHJlZmxvdy4KCioqVGhpcyBpcyBPSzogYnJvd3NlciBiYXRjaGVzIHN0eWxlIGNoYW5nZXMqKgoKYGBgdHlwZXNjcmlwdApmdW5jdGlvbiB1cGRhdGVFbGVtZW50U3R5bGVzKGVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7CiAgLy8gRWFjaCBsaW5lIGludmFsaWRhdGVzIHN0eWxlLCBidXQgYnJvd3NlciBiYXRjaGVzIHRoZSByZWNhbGN1bGF0aW9uCiAgZWxlbWVudC5zdHlsZS53aWR0aCA9ICcxMDBweCcKICBlbGVtZW50LnN0eWxlLmhlaWdodCA9ICcyMDBweCcKICBlbGVtZW50LnN0eWxlLmJhY2tncm91bmRDb2xvciA9ICdibHVlJwogIGVsZW1lbnQuc3R5bGUuYm9yZGVyID0gJzFweCBzb2xpZCBibGFjaycKfQpgYGAKCioqSW5jb3JyZWN0OiBpbnRlcmxlYXZlZCByZWFkcyBhbmQgd3JpdGVzIGZvcmNlIHJlZmxvd3MqKgoKYGBgdHlwZXNjcmlwdApmdW5jdGlvbiBsYXlvdXRUaHJhc2hpbmcoZWxlbWVudDogSFRNTEVsZW1lbnQpIHsKICBlbGVtZW50LnN0eWxlLndpZHRoID0gJzEwMHB4JwogIGNvbnN0IHdpZHRoID0gZWxlbWVudC5vZmZzZXRXaWR0aCAgLy8gRm9yY2VzIHJlZmxvdwogIGVsZW1lbnQuc3R5bGUuaGVpZ2h0ID0gJzIwMHB4JwogIGNvbnN0IGhlaWdodCA9IGVsZW1lbnQub2Zmc2V0SGVpZ2h0ICAvLyBGb3JjZXMgYW5vdGhlciByZWZsb3cKfQpgYGAKCioqQ29ycmVjdDogYmF0Y2ggd3JpdGVzLCB0aGVuIHJlYWQgb25jZSoqCgpgYGB0eXBlc2NyaXB0CmZ1bmN0aW9uIHVwZGF0ZUVsZW1lbnRTdHlsZXMoZWxlbWVudDogSFRNTEVsZW1lbnQpIHsKICAvLyBCYXRjaCBhbGwgd3JpdGVzIHRvZ2V0aGVyCiAgZWxlbWVudC5zdHlsZS53aWR0aCA9ICcxMDBweCcKICBlbGVtZW50LnN0eWxlLmhlaWdodCA9ICcyMDBweCcKICBlbGVtZW50LnN0eWxlLmJhY2tncm91bmRDb2xvciA9ICdibHVlJwogIGVsZW1lbnQuc3R5bGUuYm9yZGVyID0gJzFweCBzb2xpZCBibGFjaycKICAKICAvLyBSZWFkIGFmdGVyIGFsbCB3cml0ZXMgYXJlIGRvbmUgKHNpbmdsZSByZWZsb3cpCiAgY29uc3QgeyB3aWR0aCwgaGVpZ2h0IH0gPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpCn0KYGBgCgoqKkNvcnJlY3Q6IGJhdGNoIHJlYWRzLCB0aGVuIHdyaXRlcyoqCgpgYGB0eXBlc2NyaXB0CmZ1bmN0aW9uIHVwZGF0ZUVsZW1lbnRTdHlsZXMoZWxlbWVudDogSFRNTEVsZW1lbnQpIHsKICBlbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2hpZ2hsaWdodGVkLWJveCcpCiAgCiAgY29uc3QgeyB3aWR0aCwgaGVpZ2h0IH0gPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpCn0KYGBgCgoqKkJldHRlcjogdXNlIENTUyBjbGFzc2VzKioKCioqUmVhY3QgZXhhbXBsZToqKgoKYGBgdHN4Ci8vIEluY29ycmVjdDogaW50ZXJsZWF2aW5nIHN0eWxlIGNoYW5nZXMgd2l0aCBsYXlvdXQgcXVlcmllcwpmdW5jdGlvbiBCb3goeyBpc0hpZ2hsaWdodGVkIH06IHsgaXNIaWdobGlnaHRlZDogYm9vbGVhbiB9KSB7CiAgY29uc3QgcmVmID0gdXNlUmVmPEhUTUxEaXZFbGVtZW50PihudWxsKQogIAogIHVzZUVmZmVjdCgoKSA9PiB7CiAgICBpZiAocmVmLmN1cnJlbnQgJiYgaXNIaWdobGlnaHRlZCkgewogICAgICByZWYuY3VycmVudC5zdHlsZS53aWR0aCA9ICcxMDBweCcKICAgICAgY29uc3Qgd2lkdGggPSByZWYuY3VycmVudC5vZmZzZXRXaWR0aCAvLyBGb3JjZXMgbGF5b3V0CiAgICAgIHJlZi5jdXJyZW50LnN0eWxlLmhlaWdodCA9ICcyMDBweCcKICAgIH0KICB9LCBbaXNIaWdobGlnaHRlZF0pCiAgCiAgcmV0dXJuIDxkaXYgcmVmPXtyZWZ9PkNvbnRlbnQ8L2Rpdj4KfQoKLy8gQ29ycmVjdDogdG9nZ2xlIGNsYXNzCmZ1bmN0aW9uIEJveCh7IGlzSGlnaGxpZ2h0ZWQgfTogeyBpc0hpZ2hsaWdodGVkOiBib29sZWFuIH0pIHsKICByZXR1cm4gKAogICAgPGRpdiBjbGFzc05hbWU9e2lzSGlnaGxpZ2h0ZWQgPyAnaGlnaGxpZ2h0ZWQtYm94JyA6ICcnfT4KICAgICAgQ29udGVudAogICAgPC9kaXY+CiAgKQp9CmBgYAoKUHJlZmVyIENTUyBjbGFzc2VzIG92ZXIgaW5saW5lIHN0eWxlcyB3aGVuIHBvc3NpYmxlLiBDU1MgZmlsZXMgYXJlIGNhY2hlZCBieSB0aGUgYnJvd3NlciwgYW5kIGNsYXNzZXMgcHJvdmlkZSBiZXR0ZXIgc2VwYXJhdGlvbiBvZiBjb25jZXJucyBhbmQgYXJlIGVhc2llciB0byBtYWludGFpbi4KClNlZSBbdGhpcyBnaXN0XShodHRwczovL2dpc3QuZ2l0aHViLmNvbS9wYXVsaXJpc2gvNWQ1MmZiMDgxYjM1NzBjODFlM2EpIGFuZCBbQ1NTIFRyaWdnZXJzXShodHRwczovL2Nzc3RyaWdnZXJzLmNvbS8pIGZvciBtb3JlIGluZm9ybWF0aW9uIG9uIGxheW91dC1mb3JjaW5nIG9wZXJhdGlvbnMuCgojIyMgNy4yIEJ1aWxkIEluZGV4IE1hcHMgZm9yIFJlcGVhdGVkIExvb2t1cHMKCioqSW1wYWN0OiBMT1ctTUVESVVNICgxTSBvcHMgdG8gMksgb3BzKSoqCgpNdWx0aXBsZSBgLmZpbmQoKWAgY2FsbHMgYnkgdGhlIHNhbWUga2V5IHNob3VsZCB1c2UgYSBNYXAuCgoqKkluY29ycmVjdCAoTyhuKSBwZXIgbG9va3VwKToqKgoKYGBgdHlwZXNjcmlwdApmdW5jdGlvbiBwcm9jZXNzT3JkZXJzKG9yZGVyczogT3JkZXJbXSwgdXNlcnM6IFVzZXJbXSkgewogIHJldHVybiBvcmRlcnMubWFwKG9yZGVyID0+ICh7CiAgICAuLi5vcmRlciwKICAgIHVzZXI6IHVzZXJzLmZpbmQodSA9PiB1LmlkID09PSBvcmRlci51c2VySWQpCiAgfSkpCn0KYGBgCgoqKkNvcnJlY3QgKE8oMSkgcGVyIGxvb2t1cCk6KioKCmBgYHR5cGVzY3JpcHQKZnVuY3Rpb24gcHJvY2Vzc09yZGVycyhvcmRlcnM6IE9yZGVyW10sIHVzZXJzOiBVc2VyW10pIHsKICBjb25zdCB1c2VyQnlJZCA9IG5ldyBNYXAodXNlcnMubWFwKHUgPT4gW3UuaWQsIHVdKSkKCiAgcmV0dXJuIG9yZGVycy5tYXAob3JkZXIgPT4gKHsKICAgIC4uLm9yZGVyLAogICAgdXNlcjogdXNlckJ5SWQuZ2V0KG9yZGVyLnVzZXJJZCkKICB9KSkKfQpgYGAKCkJ1aWxkIG1hcCBvbmNlIChPKG4pKSwgdGhlbiBhbGwgbG9va3VwcyBhcmUgTygxKS4KCkZvciAxMDAwIG9yZGVycyDDlyAxMDAwIHVzZXJzOiAxTSBvcHMgPz8ySyBvcHMuCgojIyMgNy4zIENhY2hlIFByb3BlcnR5IEFjY2VzcyBpbiBMb29wcwoKKipJbXBhY3Q6IExPVy1NRURJVU0gKHJlZHVjZXMgbG9va3VwcykqKgoKQ2FjaGUgb2JqZWN0IHByb3BlcnR5IGxvb2t1cHMgaW4gaG90IHBhdGhzLgoKKipJbmNvcnJlY3Q6IDMgbG9va3VwcyDDlyBOIGl0ZXJhdGlvbnMqKgoKYGBgdHlwZXNjcmlwdApmb3IgKGxldCBpID0gMDsgaSA8IGFyci5sZW5ndGg7IGkrKykgewogIHByb2Nlc3Mob2JqLmNvbmZpZy5zZXR0aW5ncy52YWx1ZSkKfQpgYGAKCioqQ29ycmVjdDogMSBsb29rdXAgdG90YWwqKgoKYGBgdHlwZXNjcmlwdApjb25zdCB2YWx1ZSA9IG9iai5jb25maWcuc2V0dGluZ3MudmFsdWUKY29uc3QgbGVuID0gYXJyLmxlbmd0aApmb3IgKGxldCBpID0gMDsgaSA8IGxlbjsgaSsrKSB7CiAgcHJvY2Vzcyh2YWx1ZSkKfQpgYGAKCiMjIyA3LjQgQ2FjaGUgUmVwZWF0ZWQgRnVuY3Rpb24gQ2FsbHMKCioqSW1wYWN0OiBNRURJVU0gKGF2b2lkIHJlZHVuZGFudCBjb21wdXRhdGlvbikqKgoKVXNlIGEgbW9kdWxlLWxldmVsIE1hcCB0byBjYWNoZSBmdW5jdGlvbiByZXN1bHRzIHdoZW4gdGhlIHNhbWUgZnVuY3Rpb24gaXMgY2FsbGVkIHJlcGVhdGVkbHkgd2l0aCB0aGUgc2FtZSBpbnB1dHMgZHVyaW5nIHJlbmRlci4KCioqSW5jb3JyZWN0OiByZWR1bmRhbnQgY29tcHV0YXRpb24qKgoKYGBgdHlwZXNjcmlwdApmdW5jdGlvbiBQcm9qZWN0TGlzdCh7IHByb2plY3RzIH06IHsgcHJvamVjdHM6IFByb2plY3RbXSB9KSB7CiAgcmV0dXJuICgKICAgIDxkaXY+CiAgICAgIHtwcm9qZWN0cy5tYXAocHJvamVjdCA9PiB7CiAgICAgICAgLy8gc2x1Z2lmeSgpIGNhbGxlZCAxMDArIHRpbWVzIGZvciBzYW1lIHByb2plY3QgbmFtZXMKICAgICAgICBjb25zdCBzbHVnID0gc2x1Z2lmeShwcm9qZWN0Lm5hbWUpCiAgICAgICAgCiAgICAgICAgcmV0dXJuIDxQcm9qZWN0Q2FyZCBrZXk9e3Byb2plY3QuaWR9IHNsdWc9e3NsdWd9IC8+CiAgICAgIH0pfQogICAgPC9kaXY+CiAgKQp9CmBgYAoKKipDb3JyZWN0OiBjYWNoZWQgcmVzdWx0cyoqCgpgYGB0eXBlc2NyaXB0Ci8vIE1vZHVsZS1sZXZlbCBjYWNoZQpjb25zdCBzbHVnaWZ5Q2FjaGUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpCgpmdW5jdGlvbiBjYWNoZWRTbHVnaWZ5KHRleHQ6IHN0cmluZyk6IHN0cmluZyB7CiAgaWYgKHNsdWdpZnlDYWNoZS5oYXModGV4dCkpIHsKICAgIHJldHVybiBzbHVnaWZ5Q2FjaGUuZ2V0KHRleHQpIQogIH0KICBjb25zdCByZXN1bHQgPSBzbHVnaWZ5KHRleHQpCiAgc2x1Z2lmeUNhY2hlLnNldCh0ZXh0LCByZXN1bHQpCiAgcmV0dXJuIHJlc3VsdAp9CgpmdW5jdGlvbiBQcm9qZWN0TGlzdCh7IHByb2plY3RzIH06IHsgcHJvamVjdHM6IFByb2plY3RbXSB9KSB7CiAgcmV0dXJuICgKICAgIDxkaXY+CiAgICAgIHtwcm9qZWN0cy5tYXAocHJvamVjdCA9PiB7CiAgICAgICAgLy8gQ29tcHV0ZWQgb25seSBvbmNlIHBlciB1bmlxdWUgcHJvamVjdCBuYW1lCiAgICAgICAgY29uc3Qgc2x1ZyA9IGNhY2hlZFNsdWdpZnkocHJvamVjdC5uYW1lKQogICAgICAgIAogICAgICAgIHJldHVybiA8UHJvamVjdENhcmQga2V5PXtwcm9qZWN0LmlkfSBzbHVnPXtzbHVnfSAvPgogICAgICB9KX0KICAgIDwvZGl2PgogICkKfQpgYGAKCioqU2ltcGxlciBwYXR0ZXJuIGZvciBzaW5nbGUtdmFsdWUgZnVuY3Rpb25zOioqCgpgYGB0eXBlc2NyaXB0CmxldCBpc0xvZ2dlZEluQ2FjaGU6IGJvb2xlYW4gfCBudWxsID0gbnVsbAoKZnVuY3Rpb24gaXNMb2dnZWRJbigpOiBib29sZWFuIHsKICBpZiAoaXNMb2dnZWRJbkNhY2hlICE9PSBudWxsKSB7CiAgICByZXR1cm4gaXNMb2dnZWRJbkNhY2hlCiAgfQogIAogIGlzTG9nZ2VkSW5DYWNoZSA9IGRvY3VtZW50LmNvb2tpZS5pbmNsdWRlcygnYXV0aD0nKQogIHJldHVybiBpc0xvZ2dlZEluQ2FjaGUKfQoKLy8gQ2xlYXIgY2FjaGUgd2hlbiBhdXRoIGNoYW5nZXMKZnVuY3Rpb24gb25BdXRoQ2hhbmdlKCkgewogIGlzTG9nZ2VkSW5DYWNoZSA9IG51bGwKfQpgYGAKClVzZSBhIE1hcCAobm90IGEgaG9vaykgc28gaXQgd29ya3MgZXZlcnl3aGVyZTogdXRpbGl0aWVzLCBldmVudCBoYW5kbGVycywgbm90IGp1c3QgUmVhY3QgY29tcG9uZW50cy4KClJlZmVyZW5jZTogW2h0dHBzOi8vdmVyY2VsLmNvbS9ibG9nL2hvdy13ZS1tYWRlLXRoZS12ZXJjZWwtZGFzaGJvYXJkLXR3aWNlLWFzLWZhc3RdKGh0dHBzOi8vdmVyY2VsLmNvbS9ibG9nL2hvdy13ZS1tYWRlLXRoZS12ZXJjZWwtZGFzaGJvYXJkLXR3aWNlLWFzLWZhc3QpCgojIyMgNy41IENhY2hlIFN0b3JhZ2UgQVBJIENhbGxzCgoqKkltcGFjdDogTE9XLU1FRElVTSAocmVkdWNlcyBleHBlbnNpdmUgSS9PKSoqCgpgbG9jYWxTdG9yYWdlYCwgYHNlc3Npb25TdG9yYWdlYCwgYW5kIGBkb2N1bWVudC5jb29raWVgIGFyZSBzeW5jaHJvbm91cyBhbmQgZXhwZW5zaXZlLiBDYWNoZSByZWFkcyBpbiBtZW1vcnkuCgoqKkluY29ycmVjdDogcmVhZHMgc3RvcmFnZSBvbiBldmVyeSBjYWxsKioKCmBgYHR5cGVzY3JpcHQKZnVuY3Rpb24gZ2V0VGhlbWUoKSB7CiAgcmV0dXJuIGxvY2FsU3RvcmFnZS5nZXRJdGVtKCd0aGVtZScpID8/ICdsaWdodCcKfQovLyBDYWxsZWQgMTAgdGltZXMgPSAxMCBzdG9yYWdlIHJlYWRzCmBgYAoKKipDb3JyZWN0OiBNYXAgY2FjaGUqKgoKYGBgdHlwZXNjcmlwdApjb25zdCBzdG9yYWdlQ2FjaGUgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nIHwgbnVsbD4oKQoKZnVuY3Rpb24gZ2V0TG9jYWxTdG9yYWdlKGtleTogc3RyaW5nKSB7CiAgaWYgKCFzdG9yYWdlQ2FjaGUuaGFzKGtleSkpIHsKICAgIHN0b3JhZ2VDYWNoZS5zZXQoa2V5LCBsb2NhbFN0b3JhZ2UuZ2V0SXRlbShrZXkpKQogIH0KICByZXR1cm4gc3RvcmFnZUNhY2hlLmdldChrZXkpCn0KCmZ1bmN0aW9uIHNldExvY2FsU3RvcmFnZShrZXk6IHN0cmluZywgdmFsdWU6IHN0cmluZykgewogIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGtleSwgdmFsdWUpCiAgc3RvcmFnZUNhY2hlLnNldChrZXksIHZhbHVlKSAgLy8ga2VlcCBjYWNoZSBpbiBzeW5jCn0KYGBgCgpVc2UgYSBNYXAgKG5vdCBhIGhvb2spIHNvIGl0IHdvcmtzIGV2ZXJ5d2hlcmU6IHV0aWxpdGllcywgZXZlbnQgaGFuZGxlcnMsIG5vdCBqdXN0IFJlYWN0IGNvbXBvbmVudHMuCgoqKkNvb2tpZSBjYWNoaW5nOioqCgpgYGB0eXBlc2NyaXB0CmxldCBjb29raWVDYWNoZTogUmVjb3JkPHN0cmluZywgc3RyaW5nPiB8IG51bGwgPSBudWxsCgpmdW5jdGlvbiBnZXRDb29raWUobmFtZTogc3RyaW5nKSB7CiAgaWYgKCFjb29raWVDYWNoZSkgewogICAgY29va2llQ2FjaGUgPSBPYmplY3QuZnJvbUVudHJpZXMoCiAgICAgIGRvY3VtZW50LmNvb2tpZS5zcGxpdCgnOyAnKS5tYXAoYyA9PiBjLnNwbGl0KCc9JykpCiAgICApCiAgfQogIHJldHVybiBjb29raWVDYWNoZVtuYW1lXQp9CmBgYAoKKipJbXBvcnRhbnQ6IGludmFsaWRhdGUgb24gZXh0ZXJuYWwgY2hhbmdlcyoqCgpgYGB0eXBlc2NyaXB0CndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdzdG9yYWdlJywgKGUpID0+IHsKICBpZiAoZS5rZXkpIHN0b3JhZ2VDYWNoZS5kZWxldGUoZS5rZXkpCn0pCgpkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCd2aXNpYmlsaXR5Y2hhbmdlJywgKCkgPT4gewogIGlmIChkb2N1bWVudC52aXNpYmlsaXR5U3RhdGUgPT09ICd2aXNpYmxlJykgewogICAgc3RvcmFnZUNhY2hlLmNsZWFyKCkKICB9Cn0pCmBgYAoKSWYgc3RvcmFnZSBjYW4gY2hhbmdlIGV4dGVybmFsbHkgKGFub3RoZXIgdGFiLCBzZXJ2ZXItc2V0IGNvb2tpZXMpLCBpbnZhbGlkYXRlIGNhY2hlOgoKIyMjIDcuNiBDb21iaW5lIE11bHRpcGxlIEFycmF5IEl0ZXJhdGlvbnMKCioqSW1wYWN0OiBMT1ctTUVESVVNIChyZWR1Y2VzIGl0ZXJhdGlvbnMpKioKCk11bHRpcGxlIGAuZmlsdGVyKClgIG9yIGAubWFwKClgIGNhbGxzIGl0ZXJhdGUgdGhlIGFycmF5IG11bHRpcGxlIHRpbWVzLiBDb21iaW5lIGludG8gb25lIGxvb3AuCgoqKkluY29ycmVjdDogMyBpdGVyYXRpb25zKioKCmBgYHR5cGVzY3JpcHQKY29uc3QgYWRtaW5zID0gdXNlcnMuZmlsdGVyKHUgPT4gdS5pc0FkbWluKQpjb25zdCB0ZXN0ZXJzID0gdXNlcnMuZmlsdGVyKHUgPT4gdS5pc1Rlc3RlcikKY29uc3QgaW5hY3RpdmUgPSB1c2Vycy5maWx0ZXIodSA9PiAhdS5pc0FjdGl2ZSkKYGBgCgoqKkNvcnJlY3Q6IDEgaXRlcmF0aW9uKioKCmBgYHR5cGVzY3JpcHQKY29uc3QgYWRtaW5zOiBVc2VyW10gPSBbXQpjb25zdCB0ZXN0ZXJzOiBVc2VyW10gPSBbXQpjb25zdCBpbmFjdGl2ZTogVXNlcltdID0gW10KCmZvciAoY29uc3QgdXNlciBvZiB1c2VycykgewogIGlmICh1c2VyLmlzQWRtaW4pIGFkbWlucy5wdXNoKHVzZXIpCiAgaWYgKHVzZXIuaXNUZXN0ZXIpIHRlc3RlcnMucHVzaCh1c2VyKQogIGlmICghdXNlci5pc0FjdGl2ZSkgaW5hY3RpdmUucHVzaCh1c2VyKQp9CmBgYAoKIyMjIDcuNyBFYXJseSBMZW5ndGggQ2hlY2sgZm9yIEFycmF5IENvbXBhcmlzb25zCgoqKkltcGFjdDogTUVESVVNLUhJR0ggKGF2b2lkcyBleHBlbnNpdmUgb3BlcmF0aW9ucyB3aGVuIGxlbmd0aHMgZGlmZmVyKSoqCgpXaGVuIGNvbXBhcmluZyBhcnJheXMgd2l0aCBleHBlbnNpdmUgb3BlcmF0aW9ucyAoc29ydGluZywgZGVlcCBlcXVhbGl0eSwgc2VyaWFsaXphdGlvbiksIGNoZWNrIGxlbmd0aHMgZmlyc3QuIElmIGxlbmd0aHMgZGlmZmVyLCB0aGUgYXJyYXlzIGNhbm5vdCBiZSBlcXVhbC4KCkluIHJlYWwtd29ybGQgYXBwbGljYXRpb25zLCB0aGlzIG9wdGltaXphdGlvbiBpcyBlc3BlY2lhbGx5IHZhbHVhYmxlIHdoZW4gdGhlIGNvbXBhcmlzb24gcnVucyBpbiBob3QgcGF0aHMgKGV2ZW50IGhhbmRsZXJzLCByZW5kZXIgbG9vcHMpLgoKKipJbmNvcnJlY3Q6IGFsd2F5cyBydW5zIGV4cGVuc2l2ZSBjb21wYXJpc29uKioKCmBgYHR5cGVzY3JpcHQKZnVuY3Rpb24gaGFzQ2hhbmdlcyhjdXJyZW50OiBzdHJpbmdbXSwgb3JpZ2luYWw6IHN0cmluZ1tdKSB7CiAgLy8gQWx3YXlzIHNvcnRzIGFuZCBqb2lucywgZXZlbiB3aGVuIGxlbmd0aHMgZGlmZmVyCiAgcmV0dXJuIGN1cnJlbnQuc29ydCgpLmpvaW4oKSAhPT0gb3JpZ2luYWwuc29ydCgpLmpvaW4oKQp9CmBgYAoKVHdvIE8obiBsb2cgbikgc29ydHMgcnVuIGV2ZW4gd2hlbiBgY3VycmVudC5sZW5ndGhgIGlzIDUgYW5kIGBvcmlnaW5hbC5sZW5ndGhgIGlzIDEwMC4gVGhlcmUgaXMgYWxzbyBvdmVyaGVhZCBvZiBqb2luaW5nIHRoZSBhcnJheXMgYW5kIGNvbXBhcmluZyB0aGUgc3RyaW5ncy4KCioqQ29ycmVjdCAoTygxKSBsZW5ndGggY2hlY2sgZmlyc3QpOioqCgpgYGB0eXBlc2NyaXB0CmZ1bmN0aW9uIGhhc0NoYW5nZXMoY3VycmVudDogc3RyaW5nW10sIG9yaWdpbmFsOiBzdHJpbmdbXSkgewogIC8vIEVhcmx5IHJldHVybiBpZiBsZW5ndGhzIGRpZmZlcgogIGlmIChjdXJyZW50Lmxlbmd0aCAhPT0gb3JpZ2luYWwubGVuZ3RoKSB7CiAgICByZXR1cm4gdHJ1ZQogIH0KICAvLyBPbmx5IHNvcnQgd2hlbiBsZW5ndGhzIG1hdGNoCiAgY29uc3QgY3VycmVudFNvcnRlZCA9IGN1cnJlbnQudG9Tb3J0ZWQoKQogIGNvbnN0IG9yaWdpbmFsU29ydGVkID0gb3JpZ2luYWwudG9Tb3J0ZWQoKQogIGZvciAobGV0IGkgPSAwOyBpIDwgY3VycmVudFNvcnRlZC5sZW5ndGg7IGkrKykgewogICAgaWYgKGN1cnJlbnRTb3J0ZWRbaV0gIT09IG9yaWdpbmFsU29ydGVkW2ldKSB7CiAgICAgIHJldHVybiB0cnVlCiAgICB9CiAgfQogIHJldHVybiBmYWxzZQp9CmBgYAoKVGhpcyBuZXcgYXBwcm9hY2ggaXMgbW9yZSBlZmZpY2llbnQgYmVjYXVzZToKCi0gSXQgYXZvaWRzIHRoZSBvdmVyaGVhZCBvZiBzb3J0aW5nIGFuZCBqb2luaW5nIHRoZSBhcnJheXMgd2hlbiBsZW5ndGhzIGRpZmZlcgoKLSBJdCBhdm9pZHMgY29uc3VtaW5nIG1lbW9yeSBmb3IgdGhlIGpvaW5lZCBzdHJpbmdzIChlc3BlY2lhbGx5IGltcG9ydGFudCBmb3IgbGFyZ2UgYXJyYXlzKQoKLSBJdCBhdm9pZHMgbXV0YXRpbmcgdGhlIG9yaWdpbmFsIGFycmF5cwoKLSBJdCByZXR1cm5zIGVhcmx5IHdoZW4gYSBkaWZmZXJlbmNlIGlzIGZvdW5kCgojIyMgNy44IEVhcmx5IFJldHVybiBmcm9tIEZ1bmN0aW9ucwoKKipJbXBhY3Q6IExPVy1NRURJVU0gKGF2b2lkcyB1bm5lY2Vzc2FyeSBjb21wdXRhdGlvbikqKgoKUmV0dXJuIGVhcmx5IHdoZW4gcmVzdWx0IGlzIGRldGVybWluZWQgdG8gc2tpcCB1bm5lY2Vzc2FyeSBwcm9jZXNzaW5nLgoKKipJbmNvcnJlY3Q6IHByb2Nlc3NlcyBhbGwgaXRlbXMgZXZlbiBhZnRlciBmaW5kaW5nIGFuc3dlcioqCgpgYGB0eXBlc2NyaXB0CmZ1bmN0aW9uIHZhbGlkYXRlVXNlcnModXNlcnM6IFVzZXJbXSkgewogIGxldCBoYXNFcnJvciA9IGZhbHNlCiAgbGV0IGVycm9yTWVzc2FnZSA9ICcnCiAgCiAgZm9yIChjb25zdCB1c2VyIG9mIHVzZXJzKSB7CiAgICBpZiAoIXVzZXIuZW1haWwpIHsKICAgICAgaGFzRXJyb3IgPSB0cnVlCiAgICAgIGVycm9yTWVzc2FnZSA9ICdFbWFpbCByZXF1aXJlZCcKICAgIH0KICAgIGlmICghdXNlci5uYW1lKSB7CiAgICAgIGhhc0Vycm9yID0gdHJ1ZQogICAgICBlcnJvck1lc3NhZ2UgPSAnTmFtZSByZXF1aXJlZCcKICAgIH0KICAgIC8vIENvbnRpbnVlcyBjaGVja2luZyBhbGwgdXNlcnMgZXZlbiBhZnRlciBlcnJvciBmb3VuZAogIH0KICAKICByZXR1cm4gaGFzRXJyb3IgPyB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6IGVycm9yTWVzc2FnZSB9IDogeyB2YWxpZDogdHJ1ZSB9Cn0KYGBgCgoqKkNvcnJlY3Q6IHJldHVybnMgaW1tZWRpYXRlbHkgb24gZmlyc3QgZXJyb3IqKgoKYGBgdHlwZXNjcmlwdApmdW5jdGlvbiB2YWxpZGF0ZVVzZXJzKHVzZXJzOiBVc2VyW10pIHsKICBmb3IgKGNvbnN0IHVzZXIgb2YgdXNlcnMpIHsKICAgIGlmICghdXNlci5lbWFpbCkgewogICAgICByZXR1cm4geyB2YWxpZDogZmFsc2UsIGVycm9yOiAnRW1haWwgcmVxdWlyZWQnIH0KICAgIH0KICAgIGlmICghdXNlci5uYW1lKSB7CiAgICAgIHJldHVybiB7IHZhbGlkOiBmYWxzZSwgZXJyb3I6ICdOYW1lIHJlcXVpcmVkJyB9CiAgICB9CiAgfQoKICByZXR1cm4geyB2YWxpZDogdHJ1ZSB9Cn0KYGBgCgojIyMgNy45IEhvaXN0IFJlZ0V4cCBDcmVhdGlvbgoKKipJbXBhY3Q6IExPVy1NRURJVU0gKGF2b2lkcyByZWNyZWF0aW9uKSoqCgpEb24ndCBjcmVhdGUgUmVnRXhwIGluc2lkZSByZW5kZXIuIEhvaXN0IHRvIG1vZHVsZSBzY29wZSBvciBtZW1vaXplIHdpdGggYHVzZU1lbW8oKWAuCgoqKkluY29ycmVjdDogbmV3IFJlZ0V4cCBldmVyeSByZW5kZXIqKgoKYGBgdHN4CmZ1bmN0aW9uIEhpZ2hsaWdodGVyKHsgdGV4dCwgcXVlcnkgfTogUHJvcHMpIHsKICBjb25zdCByZWdleCA9IG5ldyBSZWdFeHAoYCgke3F1ZXJ5fSlgLCAnZ2knKQogIGNvbnN0IHBhcnRzID0gdGV4dC5zcGxpdChyZWdleCkKICByZXR1cm4gPD57cGFydHMubWFwKChwYXJ0LCBpKSA9PiAuLi4pfTwvPgp9CmBgYAoKKipDb3JyZWN0OiBtZW1vaXplIG9yIGhvaXN0KioKCmBgYHRzeApjb25zdCBFTUFJTF9SRUdFWCA9IC9eW15cc0BdK0BbXlxzQF0rXC5bXlxzQF0rJC8KCmZ1bmN0aW9uIEhpZ2hsaWdodGVyKHsgdGV4dCwgcXVlcnkgfTogUHJvcHMpIHsKICBjb25zdCByZWdleCA9IHVzZU1lbW8oCiAgICAoKSA9PiBuZXcgUmVnRXhwKGAoJHtlc2NhcGVSZWdleChxdWVyeSl9KWAsICdnaScpLAogICAgW3F1ZXJ5XQogICkKICBjb25zdCBwYXJ0cyA9IHRleHQuc3BsaXQocmVnZXgpCiAgcmV0dXJuIDw+e3BhcnRzLm1hcCgocGFydCwgaSkgPT4gLi4uKX08Lz4KfQpgYGAKCioqV2FybmluZzogZ2xvYmFsIHJlZ2V4IGhhcyBtdXRhYmxlIHN0YXRlKioKCmBgYHR5cGVzY3JpcHQKY29uc3QgcmVnZXggPSAvZm9vL2cKcmVnZXgudGVzdCgnZm9vJykgIC8vIHRydWUsIGxhc3RJbmRleCA9IDMKcmVnZXgudGVzdCgnZm9vJykgIC8vIGZhbHNlLCBsYXN0SW5kZXggPSAwCmBgYAoKR2xvYmFsIHJlZ2V4IChgL2dgKSBoYXMgbXV0YWJsZSBgbGFzdEluZGV4YCBzdGF0ZToKCiMjIyA3LjEwIFVzZSBMb29wIGZvciBNaW4vTWF4IEluc3RlYWQgb2YgU29ydAoKKipJbXBhY3Q6IExPVyAoTyhuKSBpbnN0ZWFkIG9mIE8obiBsb2cgbikpKioKCkZpbmRpbmcgdGhlIHNtYWxsZXN0IG9yIGxhcmdlc3QgZWxlbWVudCBvbmx5IHJlcXVpcmVzIGEgc2luZ2xlIHBhc3MgdGhyb3VnaCB0aGUgYXJyYXkuIFNvcnRpbmcgaXMgd2FzdGVmdWwgYW5kIHNsb3dlci4KCioqSW5jb3JyZWN0IChPKG4gbG9nIG4pIC0gc29ydCB0byBmaW5kIGxhdGVzdCk6KioKCmBgYHR5cGVzY3JpcHQKaW50ZXJmYWNlIFByb2plY3QgewogIGlkOiBzdHJpbmcKICBuYW1lOiBzdHJpbmcKICB1cGRhdGVkQXQ6IG51bWJlcgp9CgpmdW5jdGlvbiBnZXRMYXRlc3RQcm9qZWN0KHByb2plY3RzOiBQcm9qZWN0W10pIHsKICBjb25zdCBzb3J0ZWQgPSBbLi4ucHJvamVjdHNdLnNvcnQoKGEsIGIpID0+IGIudXBkYXRlZEF0IC0gYS51cGRhdGVkQXQpCiAgcmV0dXJuIHNvcnRlZFswXQp9CmBgYAoKU29ydHMgdGhlIGVudGlyZSBhcnJheSBqdXN0IHRvIGZpbmQgdGhlIG1heGltdW0gdmFsdWUuCgoqKkluY29ycmVjdCAoTyhuIGxvZyBuKSAtIHNvcnQgZm9yIG9sZGVzdCBhbmQgbmV3ZXN0KToqKgoKYGBgdHlwZXNjcmlwdApmdW5jdGlvbiBnZXRPbGRlc3RBbmROZXdlc3QocHJvamVjdHM6IFByb2plY3RbXSkgewogIGNvbnN0IHNvcnRlZCA9IFsuLi5wcm9qZWN0c10uc29ydCgoYSwgYikgPT4gYS51cGRhdGVkQXQgLSBiLnVwZGF0ZWRBdCkKICByZXR1cm4geyBvbGRlc3Q6IHNvcnRlZFswXSwgbmV3ZXN0OiBzb3J0ZWRbc29ydGVkLmxlbmd0aCAtIDFdIH0KfQpgYGAKClN0aWxsIHNvcnRzIHVubmVjZXNzYXJpbHkgd2hlbiBvbmx5IG1pbi9tYXggYXJlIG5lZWRlZC4KCioqQ29ycmVjdCAoTyhuKSAtIHNpbmdsZSBsb29wKToqKgoKYGBgdHlwZXNjcmlwdApmdW5jdGlvbiBnZXRMYXRlc3RQcm9qZWN0KHByb2plY3RzOiBQcm9qZWN0W10pIHsKICBpZiAocHJvamVjdHMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbAogIAogIGxldCBsYXRlc3QgPSBwcm9qZWN0c1swXQogIAogIGZvciAobGV0IGkgPSAxOyBpIDwgcHJvamVjdHMubGVuZ3RoOyBpKyspIHsKICAgIGlmIChwcm9qZWN0c1tpXS51cGRhdGVkQXQgPiBsYXRlc3QudXBkYXRlZEF0KSB7CiAgICAgIGxhdGVzdCA9IHByb2plY3RzW2ldCiAgICB9CiAgfQogIAogIHJldHVybiBsYXRlc3QKfQoKZnVuY3Rpb24gZ2V0T2xkZXN0QW5kTmV3ZXN0KHByb2plY3RzOiBQcm9qZWN0W10pIHsKICBpZiAocHJvamVjdHMubGVuZ3RoID09PSAwKSByZXR1cm4geyBvbGRlc3Q6IG51bGwsIG5ld2VzdDogbnVsbCB9CiAgCiAgbGV0IG9sZGVzdCA9IHByb2plY3RzWzBdCiAgbGV0IG5ld2VzdCA9IHByb2plY3RzWzBdCiAgCiAgZm9yIChsZXQgaSA9IDE7IGkgPCBwcm9qZWN0cy5sZW5ndGg7IGkrKykgewogICAgaWYgKHByb2plY3RzW2ldLnVwZGF0ZWRBdCA8IG9sZGVzdC51cGRhdGVkQXQpIG9sZGVzdCA9IHByb2plY3RzW2ldCiAgICBpZiAocHJvamVjdHNbaV0udXBkYXRlZEF0ID4gbmV3ZXN0LnVwZGF0ZWRBdCkgbmV3ZXN0ID0gcHJvamVjdHNbaV0KICB9CiAgCiAgcmV0dXJuIHsgb2xkZXN0LCBuZXdlc3QgfQp9CmBgYAoKU2luZ2xlIHBhc3MgdGhyb3VnaCB0aGUgYXJyYXksIG5vIGNvcHlpbmcsIG5vIHNvcnRpbmcuCgoqKkFsdGVybmF0aXZlOiBNYXRoLm1pbi9NYXRoLm1heCBmb3Igc21hbGwgYXJyYXlzKioKCmBgYHR5cGVzY3JpcHQKY29uc3QgbnVtYmVycyA9IFs1LCAyLCA4LCAxLCA5XQpjb25zdCBtaW4gPSBNYXRoLm1pbiguLi5udW1iZXJzKQpjb25zdCBtYXggPSBNYXRoLm1heCguLi5udW1iZXJzKQpgYGAKClRoaXMgd29ya3MgZm9yIHNtYWxsIGFycmF5cywgYnV0IGNhbiBiZSBzbG93ZXIgb3IganVzdCB0aHJvdyBhbiBlcnJvciBmb3IgdmVyeSBsYXJnZSBhcnJheXMgZHVlIHRvIHNwcmVhZCBvcGVyYXRvciBsaW1pdGF0aW9ucy4gTWF4aW1hbCBhcnJheSBsZW5ndGggaXMgYXBwcm94aW1hdGVseSAxMjQwMDAgaW4gQ2hyb21lIDE0MyBhbmQgNjM4MDAwIGluIFNhZmFyaSAxODsgZXhhY3QgbnVtYmVycyBtYXkgdmFyeSAtIHNlZSBbdGhlIGZpZGRsZV0oaHR0cHM6Ly9qc2ZpZGRsZS5uZXQvcXcxamFic3gvNC8pLiBVc2UgdGhlIGxvb3AgYXBwcm9hY2ggZm9yIHJlbGlhYmlsaXR5LgoKIyMjIDcuMTEgVXNlIFNldC9NYXAgZm9yIE8oMSkgTG9va3VwcwoKKipJbXBhY3Q6IExPVy1NRURJVU0gKE8obikgdG8gTygxKSkqKgoKQ29udmVydCBhcnJheXMgdG8gU2V0L01hcCBmb3IgcmVwZWF0ZWQgbWVtYmVyc2hpcCBjaGVja3MuCgoqKkluY29ycmVjdCAoTyhuKSBwZXIgY2hlY2spOioqCgpgYGB0eXBlc2NyaXB0CmNvbnN0IGFsbG93ZWRJZHMgPSBbJ2EnLCAnYicsICdjJywgLi4uXQppdGVtcy5maWx0ZXIoaXRlbSA9PiBhbGxvd2VkSWRzLmluY2x1ZGVzKGl0ZW0uaWQpKQpgYGAKCioqQ29ycmVjdCAoTygxKSBwZXIgY2hlY2spOioqCgpgYGB0eXBlc2NyaXB0CmNvbnN0IGFsbG93ZWRJZHMgPSBuZXcgU2V0KFsnYScsICdiJywgJ2MnLCAuLi5dKQppdGVtcy5maWx0ZXIoaXRlbSA9PiBhbGxvd2VkSWRzLmhhcyhpdGVtLmlkKSkKYGBgCgojIyMgNy4xMiBVc2UgdG9Tb3J0ZWQoKSBJbnN0ZWFkIG9mIHNvcnQoKSBmb3IgSW1tdXRhYmlsaXR5CgoqKkltcGFjdDogTUVESVVNLUhJR0ggKHByZXZlbnRzIG11dGF0aW9uIGJ1Z3MgaW4gUmVhY3Qgc3RhdGUpKioKCmAuc29ydCgpYCBtdXRhdGVzIHRoZSBhcnJheSBpbiBwbGFjZSwgd2hpY2ggY2FuIGNhdXNlIGJ1Z3Mgd2l0aCBSZWFjdCBzdGF0ZSBhbmQgcHJvcHMuIFVzZSBgLnRvU29ydGVkKClgIHRvIGNyZWF0ZSBhIG5ldyBzb3J0ZWQgYXJyYXkgd2l0aG91dCBtdXRhdGlvbi4KCioqSW5jb3JyZWN0OiBtdXRhdGVzIG9yaWdpbmFsIGFycmF5KioKCmBgYHR5cGVzY3JpcHQKZnVuY3Rpb24gVXNlckxpc3QoeyB1c2VycyB9OiB7IHVzZXJzOiBVc2VyW10gfSkgewogIC8vIE11dGF0ZXMgdGhlIHVzZXJzIHByb3AgYXJyYXkhCiAgY29uc3Qgc29ydGVkID0gdXNlTWVtbygKICAgICgpID0+IHVzZXJzLnNvcnQoKGEsIGIpID0+IGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSkpLAogICAgW3VzZXJzXQogICkKICByZXR1cm4gPGRpdj57c29ydGVkLm1hcChyZW5kZXJVc2VyKX08L2Rpdj4KfQpgYGAKCioqQ29ycmVjdDogY3JlYXRlcyBuZXcgYXJyYXkqKgoKYGBgdHlwZXNjcmlwdApmdW5jdGlvbiBVc2VyTGlzdCh7IHVzZXJzIH06IHsgdXNlcnM6IFVzZXJbXSB9KSB7CiAgLy8gQ3JlYXRlcyBuZXcgc29ydGVkIGFycmF5LCBvcmlnaW5hbCB1bmNoYW5nZWQKICBjb25zdCBzb3J0ZWQgPSB1c2VNZW1vKAogICAgKCkgPT4gdXNlcnMudG9Tb3J0ZWQoKGEsIGIpID0+IGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSkpLAogICAgW3VzZXJzXQogICkKICByZXR1cm4gPGRpdj57c29ydGVkLm1hcChyZW5kZXJVc2VyKX08L2Rpdj4KfQpgYGAKCioqV2h5IHRoaXMgbWF0dGVycyBpbiBSZWFjdDoqKgoKMS4gUHJvcHMvc3RhdGUgbXV0YXRpb25zIGJyZWFrIFJlYWN0J3MgaW1tdXRhYmlsaXR5IG1vZGVsIC0gUmVhY3QgZXhwZWN0cyBwcm9wcyBhbmQgc3RhdGUgdG8gYmUgdHJlYXRlZCBhcyByZWFkLW9ubHkKCjIuIENhdXNlcyBzdGFsZSBjbG9zdXJlIGJ1Z3MgLSBNdXRhdGluZyBhcnJheXMgaW5zaWRlIGNsb3N1cmVzIChjYWxsYmFja3MsIGVmZmVjdHMpIGNhbiBsZWFkIHRvIHVuZXhwZWN0ZWQgYmVoYXZpb3IKCioqQnJvd3NlciBzdXBwb3J0OiBmYWxsYmFjayBmb3Igb2xkZXIgYnJvd3NlcnMqKgoKYGBgdHlwZXNjcmlwdAovLyBGYWxsYmFjayBmb3Igb2xkZXIgYnJvd3NlcnMKY29uc3Qgc29ydGVkID0gWy4uLml0ZW1zXS5zb3J0KChhLCBiKSA9PiBhLnZhbHVlIC0gYi52YWx1ZSkKYGBgCgpgLnRvU29ydGVkKClgIGlzIGF2YWlsYWJsZSBpbiBhbGwgbW9kZXJuIGJyb3dzZXJzIChDaHJvbWUgMTEwKywgU2FmYXJpIDE2KywgRmlyZWZveCAxMTUrLCBOb2RlLmpzIDIwKykuIEZvciBvbGRlciBlbnZpcm9ubWVudHMsIHVzZSBzcHJlYWQgb3BlcmF0b3I6CgoqKk90aGVyIGltbXV0YWJsZSBhcnJheSBtZXRob2RzOioqCgotIGAudG9Tb3J0ZWQoKWAgLSBpbW11dGFibGUgc29ydAoKLSBgLnRvUmV2ZXJzZWQoKWAgLSBpbW11dGFibGUgcmV2ZXJzZQoKLSBgLnRvU3BsaWNlZCgpYCAtIGltbXV0YWJsZSBzcGxpY2UKCi0gYC53aXRoKClgIC0gaW1tdXRhYmxlIGVsZW1lbnQgcmVwbGFjZW1lbnQKCi0tLQoKIyMgOC4gQWR2YW5jZWQgUGF0dGVybnMKCioqSW1wYWN0OiBMT1cqKgoKQWR2YW5jZWQgcGF0dGVybnMgZm9yIHNwZWNpZmljIGNhc2VzIHRoYXQgcmVxdWlyZSBjYXJlZnVsIGltcGxlbWVudGF0aW9uLgoKIyMjIDguMSBTdG9yZSBFdmVudCBIYW5kbGVycyBpbiBSZWZzCgoqKkltcGFjdDogTE9XIChzdGFibGUgc3Vic2NyaXB0aW9ucykqKgoKU3RvcmUgY2FsbGJhY2tzIGluIHJlZnMgd2hlbiB1c2VkIGluIGVmZmVjdHMgdGhhdCBzaG91bGRuJ3QgcmUtc3Vic2NyaWJlIG9uIGNhbGxiYWNrIGNoYW5nZXMuCgoqKkluY29ycmVjdDogcmUtc3Vic2NyaWJlcyBvbiBldmVyeSByZW5kZXIqKgoKYGBgdHN4CmZ1bmN0aW9uIHVzZVdpbmRvd0V2ZW50KGV2ZW50OiBzdHJpbmcsIGhhbmRsZXI6IChlKSA9PiB2b2lkKSB7CiAgdXNlRWZmZWN0KCgpID0+IHsKICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyKQogICAgcmV0dXJuICgpID0+IHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKGV2ZW50LCBoYW5kbGVyKQogIH0sIFtldmVudCwgaGFuZGxlcl0pCn0KYGBgCgoqKkNvcnJlY3Q6IHN0YWJsZSBzdWJzY3JpcHRpb24qKgoKYGBgdHN4CmltcG9ydCB7IHVzZUVmZmVjdEV2ZW50IH0gZnJvbSAncmVhY3QnCgpmdW5jdGlvbiB1c2VXaW5kb3dFdmVudChldmVudDogc3RyaW5nLCBoYW5kbGVyOiAoZSkgPT4gdm9pZCkgewogIGNvbnN0IG9uRXZlbnQgPSB1c2VFZmZlY3RFdmVudChoYW5kbGVyKQoKICB1c2VFZmZlY3QoKCkgPT4gewogICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoZXZlbnQsIG9uRXZlbnQpCiAgICByZXR1cm4gKCkgPT4gd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnQsIG9uRXZlbnQpCiAgfSwgW2V2ZW50XSkKfQpgYGAKCioqQWx0ZXJuYXRpdmU6IHVzZSBgdXNlRWZmZWN0RXZlbnRgIGlmIHlvdSdyZSBvbiBsYXRlc3QgUmVhY3Q6KioKCmB1c2VFZmZlY3RFdmVudGAgcHJvdmlkZXMgYSBjbGVhbmVyIEFQSSBmb3IgdGhlIHNhbWUgcGF0dGVybjogaXQgY3JlYXRlcyBhIHN0YWJsZSBmdW5jdGlvbiByZWZlcmVuY2UgdGhhdCBhbHdheXMgY2FsbHMgdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIHRoZSBoYW5kbGVyLgoKIyMjIDguMiB1c2VFZmZlY3RFdmVudCBmb3IgU3RhYmxlIENhbGxiYWNrIFJlZnMKCioqSW1wYWN0OiBMT1cgKHByZXZlbnRzIGVmZmVjdCByZS1ydW5zKSoqCgpBY2Nlc3MgbGF0ZXN0IHZhbHVlcyBpbiBjYWxsYmFja3Mgd2l0aG91dCBhZGRpbmcgdGhlbSB0byBkZXBlbmRlbmN5IGFycmF5cy4gUHJldmVudHMgZWZmZWN0IHJlLXJ1bnMgd2hpbGUgYXZvaWRpbmcgc3RhbGUgY2xvc3VyZXMuCgoqKkluY29ycmVjdDogZWZmZWN0IHJlLXJ1bnMgb24gZXZlcnkgY2FsbGJhY2sgY2hhbmdlKioKCmBgYHRzeApmdW5jdGlvbiBTZWFyY2hJbnB1dCh7IG9uU2VhcmNoIH06IHsgb25TZWFyY2g6IChxOiBzdHJpbmcpID0+IHZvaWQgfSkgewogIGNvbnN0IFtxdWVyeSwgc2V0UXVlcnldID0gdXNlU3RhdGUoJycpCgogIHVzZUVmZmVjdCgoKSA9PiB7CiAgICBjb25zdCB0aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiBvblNlYXJjaChxdWVyeSksIDMwMCkKICAgIHJldHVybiAoKSA9PiBjbGVhclRpbWVvdXQodGltZW91dCkKICB9LCBbcXVlcnksIG9uU2VhcmNoXSkKfQpgYGAKCioqQ29ycmVjdDogdXNpbmcgUmVhY3QncyB1c2VFZmZlY3RFdmVudCoqCgpgYGB0c3gKaW1wb3J0IHsgdXNlRWZmZWN0RXZlbnQgfSBmcm9tICdyZWFjdCc7CgpmdW5jdGlvbiBTZWFyY2hJbnB1dCh7IG9uU2VhcmNoIH06IHsgb25TZWFyY2g6IChxOiBzdHJpbmcpID0+IHZvaWQgfSkgewogIGNvbnN0IFtxdWVyeSwgc2V0UXVlcnldID0gdXNlU3RhdGUoJycpCiAgY29uc3Qgb25TZWFyY2hFdmVudCA9IHVzZUVmZmVjdEV2ZW50KG9uU2VhcmNoKQoKICB1c2VFZmZlY3QoKCkgPT4gewogICAgY29uc3QgdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4gb25TZWFyY2hFdmVudChxdWVyeSksIDMwMCkKICAgIHJldHVybiAoKSA9PiBjbGVhclRpbWVvdXQodGltZW91dCkKICB9LCBbcXVlcnldKQp9CmBgYAoKLS0tCgojIyBSZWZlcmVuY2VzCgoxLiBbaHR0cHM6Ly9yZWFjdC5kZXZdKGh0dHBzOi8vcmVhY3QuZGV2KQoyLiBbaHR0cHM6Ly9uZXh0anMub3JnXShodHRwczovL25leHRqcy5vcmcpCjMuIFtodHRwczovL3N3ci52ZXJjZWwuYXBwXShodHRwczovL3N3ci52ZXJjZWwuYXBwKQo0LiBbaHR0cHM6Ly9naXRodWIuY29tL3NodWRpbmcvYmV0dGVyLWFsbF0oaHR0cHM6Ly9naXRodWIuY29tL3NodWRpbmcvYmV0dGVyLWFsbCkKNS4gW2h0dHBzOi8vZ2l0aHViLmNvbS9pc2FhY3Mvbm9kZS1scnUtY2FjaGVdKGh0dHBzOi8vZ2l0aHViLmNvbS9pc2FhY3Mvbm9kZS1scnUtY2FjaGUpCjYuIFtodHRwczovL3ZlcmNlbC5jb20vYmxvZy9ob3ctd2Utb3B0aW1pemVkLXBhY2thZ2UtaW1wb3J0cy1pbi1uZXh0LWpzXShodHRwczovL3ZlcmNlbC5jb20vYmxvZy9ob3ctd2Utb3B0aW1pemVkLXBhY2thZ2UtaW1wb3J0cy1pbi1uZXh0LWpzKQo3LiBbaHR0cHM6Ly92ZXJjZWwuY29tL2Jsb2cvaG93LXdlLW1hZGUtdGhlLXZlcmNlbC1kYXNoYm9hcmQtdHdpY2UtYXMtZmFzdF0oaHR0cHM6Ly92ZXJjZWwuY29tL2Jsb2cvaG93LXdlLW1hZGUtdGhlLXZlcmNlbC1kYXNoYm9hcmQtdHdpY2UtYXMtZmFzdCkK