@Mosrod/

Hangman

Python

Advanced, configurable, hangman game created in Python

fork
loading
Files
  • main.py
  • englishwordslowercase.txt
  • hangmanpresets.txt

This Plugin Crashed!

Error: Error: must not create an existing file {"type":"CREATE_FILE","wid":"0.7500430394003206","path":"main.py","file":{"path":"main.py","content":{"asEncoding":{"base64":"IyBDcmVhdGVkIEJ5IE1vc3JvZCAoTmF0aGFuIFIpCiMgKEMpIDIwMTkgTmF0aGFuIFIsIFtBTEwgUklHSFRTIFJFU0VSVkVEXQoKIyBXSVAgU0VUL0FQUEVORCBXT1JETElTVAojIENPTlRBSU5TIEJST0tFTgoKaW1wb3J0IHJhbmRvbSAgIyBJbXBvcnRzIHJhbmRvbSBtb2R1bGUgZm9yIGNob29zaW5nIGEgcmFuZG9tIHdvcmQKaW1wb3J0IHN5cyAgIyBJbXBvcnRzIHN5cyBtb2R1bGUgZm9yIGxvYWRpbmcKaW1wb3J0IG9zICAjIEltcG9ydHMgb3MgbW9kdWxlIGZvciB0ZXN0aW5nIGlmIGEgZmlsZSBleGlzdHMKCndvcmRsaXN0cGF0aCA9ICdlbmdsaXNod29yZHNsb3dlcmNhc2UudHh0JwoKaWYgb3MucGF0aC5pc2ZpbGUod29yZGxpc3RwYXRoKTogICMgSWYgd29yZGxpc3RwYXRoIGlzIGEgZmlsZQogICAgd2l0aCBvcGVuKHdvcmRsaXN0cGF0aCwgJ3InKSBhcyBmOiAgIyBPcGVuIHRleHQgZmlsZSB0aGF0IHN0b3JlcyB0aGUgd29yZHMKICAgICAgICB3b3JkbGlzdCA9IFtsaW5lLnN0cmlwKCkgZm9yIGxpbmUgaW4gZl0gICMgQWRkIGV2ZXJ5IGxpbmUgb2YgdGhlIGZpbGUgdG8gYSBsaXN0CmVsc2U6CiAgICBwcmludCgnV29yZGxpc3QgTm90IEZvdW5kJykgICMgVGVsbCB0aGUgdXNlciB0aGF0IHRoZSB3b3JkbGlzdCBpcyBub3QgZm91bmQKCgppZiBub3Qgb3MucGF0aC5pc2ZpbGUoJ2hhbmdtYW5wcmVzZXRzLnR4dCcpOiAgIyBJZiBoYW5nbWFucHJlc2V0cy50eHQgaXMgbm90IGEgZmlsZQogICAgd2l0aCBvcGVuKCdoYW5nbWFucHJlc2V0cy50eHQnLCAndysnKSBhcyBmOiAgIyBDcmVhdGUgaGFuZ21hbnByZXNldHMudHh0CiAgICAgICAgcGFzcwoKd2l0aCBvcGVuKCdoYW5nbWFucHJlc2V0cy50eHQnLCAncicpIGFzIGY6ICAjIE9wZW4gdGV4dCBmaWxlIHdpdGggcHJlc2V0cwogICAgcHJlc2V0cyA9IFtsaW5lLnN0cmlwKCkgZm9yIGxpbmUgaW4gZl0gICMgQWRkIGV2ZXJ5IGxpbmUgb2YgdGhlIGZpbGUgdG8gYSBsaXN0CgoKcHJpbnQoIiIiCkNPTU1BTkRTOgoxIDogRXhpdHMgdGhlIHByb2dyYW0KMiA6IEdlbmVyYXRlcyBhIG5ldyB3b3JkClBSRVNFVDoKMSA6IFVzZSBhIHByZXNldCBpbiBoYW5nbWFucHJlc2V0cy50eHQKT1BUSU9OUzoKMSA6IEFsbG93IHdvcmRzIHRvIGhhdmUgcGVyaW9kcwoyIDogQWxsb3cgd29yZHMgdG8gaGF2ZSBudW1iZXJzCjMgOiBBbGxvdyB3b3JkcyB0byBoYXZlIHNwYWNlcwo0IDogVHVybiB0aGUgdm93ZWwgcmVxdWlyZWQgdG8gZmFsc2UKNSA6IFR1cm4gb24gbm90aWZpY2F0aW9ucyBpZiBhIHdvcmQgaW4gYSB3b3JkbGlzdCBmYWlscyBhIGNoZWNrCjYgOiBTZXQgdGhlIG1vc3QgcmVwZWF0aW5nIGNoYXJhY3RlcnMgaW4gYSB3b3JkCjcgOiBTZXQgdGhlIG1vc3QgdG90YWwgcmVwZWF0aW5nIGNoYXJhY3RlcnMgaW4gYSB3b3JkCjggOiBTZXQvYXBwZW5kL3R1cm4gb2ZmIHN0cmluZ3MgYWxsb3dlZCBpbiB3b3Jkcwo5IDogU2V0IHRoZSBsZW5ndGgKMTAgOiBTZXQgdGhlIG1pbiBsZW5ndGgKMTEgOiBTZXQgdGhlIG1heCBsZW5ndGgKMTIgOiBNYWtlIHRoZSBmaXJzdCBsZXR0ZXIgb2YgdGhlIHdvcmQgZXF1YWwgdG8gdGhlIHNldCBsZXR0ZXIKMTMgOiBTZXQgdGhlIHdvcmQgbGlzdAoxNCA6IE1ha2Ugc3VyZSBhbGwgd29yZHMgY29udGFpbiB0aGUgbGV0dGVycyBzcGVjaWZpZWQKIiIiKSAgIyBJbmZvcm1zIHRoZSB1c2VyIGFib3V0IHdoYXQgdGhlIG9wdGlvbnMgZG8KCiMgW2EsZCxnLGgsaSxqLGssbSxxLHUsel0KCnByaW50KCIiIgpDT01NQU5EUzoKMSA6IEV4aXQKMiA6IE5ldwpQUkVTRVRTOgoxIDogVXNlIFByZXNldCAoT04pIFstbyhuYW1lKV0KT1BUSU9OUzoKMSA6IFBlcmlvZHMgKE9OKSBbLXBdCjIgOiBOdW1iZXJzIChPTikgWy1uXQozIDogU3BhY2VzIChPTikgWy1zXQo0IDogVm93ZWxzIFJlcXVpcmVkIChPRkYpIFstdl0KNSA6IFdvcmRMaXN0IE5vdGlmaWNhdGlvbnMgKE9OKSBbLXldCjYgOiBNYXggUmVwZWF0aW5nIENoYXJhY3RlcnMgKFNFVCkgWy1yKG51bSldIHs0fQo3IDogTWF4IFRvdGFsIFJlcGVhdGluZyBDaGFyYWN0ZXJzIChTRVQpIFstdChudW0pXSB7MTB9CjggOiBWYWxpZCBTdHJpbmdzIChPRkYvU0VUL0FQUEVORCkgWy14KG8pXSBbLXgoe3MvYX1bc3RyaW5nLHN0cmluZyldCjkgOiBMZW5ndGggKFNFVCkgWy1sKG51bSldIHswfQoxMCA6IE1pbiBMZW5ndGggKFNFVCkgWy1iKG51bSldIHszfQoxMSA6IE1heCBMZW5ndGggKFNFVCkgWy1lKG51bSldIHsxNX0KMTIgOiBGaXJzdCBMZXR0ZXIgKFNFVCkgWy1mKGxldHRlcildCjEzIDogV29yZCBMaXN0IChTRVQpIFstdyhbd29yZCx3b3JkXSldIFstd1sjZmlsZW5hbWUudHh0XSkKMTQgOiBDb250YWlucyAoU0VUKSBbLWMoW2xldHRlcixsZXR0ZXJdKV0KIiIiKSAgIyBJbmZvcm1zIHRoZSB1c2VyIGFib3V0IHRoZSBvcHRpb25zCgoKb3B0aW9ucyA9IGlucHV0KCdPcHRpb25zOiAnKS5sb3dlcigpICAjIFRha2VzIG9wdGlvbnMgZnJvbSB0aGUgdXNlcgoKcHJlc2V0bmFtZSA9ICcnICAjIFNldHMgcHJlc2V0bmFtZSB0byBhbiBlbXB0eSBzdHJpbmcKaWYgb3B0aW9ucyAhPSAnJzogICMgSWYgb3B0aW9ucyBpcyBub3QgZW1wdHkKICAgIHByZXNldG5hbWUgPSBpbnB1dCgnUHJlc2V0OiAnKS5sb3dlcigpICAjIFNldCB1c2VyIGlucHV0IHRvIHRoZSBwcmVzZXQgbmFtZQoKcmVwZWF0ID0gNCAgIyBTZXRzIHJlcGVhdCB0byA0CnJlcGVhdF90b3RhbCA9IDEwICAjIFNldHMgcmVwZWF0X3RvdGFsIHRvIDEwCmxlbmd0aCA9IDAgICMgU2V0cyBsZW5ndGggdG8gMApiZWdpbm5pbmcgPSAzICAjIFNldHMgYmVnaW5uaW5nIHRvIDMKZW5kaW5nID0gMTUgICMgU2V0cyBlbmRpbmcgdG8gMTUKCm9wdGlvbnNsaXN0ID0gb3B0aW9ucy5zcGxpdCgnLScpICAjIFNwbGl0IG9wdGlvbnMgYnkgJy0nCm9wdGlvbnNsaXN0ID0gb3B0aW9uc2xpc3RbMTpdICAjIFJlbW92ZSB0aGUgZmlyc3QgdmFsdWUgZnJvbSBvcHRpb25zbGlzdAoKZm9yIGkgaW4gcmFuZ2UoMCwgbGVuKG9wdGlvbnNsaXN0KSk6ICAjIFJlcGVhdCBmb3IgdGhlIGxlbmd0aCBvZiBvcHRpb25zbGlzdAogICAgb3B0aW9uc2xpc3RbaV0gPSAnLScgKyBvcHRpb25zbGlzdFtpXSAgIyBBZGQgYSAtIGJlZm9yZSBldmVyeSB2YWx1ZSBpbiB0aGUgbGlzdAoKcHJlc2V0dHJ1ZSA9IDEKZm9yIHIgaW4gcmFuZ2UoMCwgbGVuKHByZXNldHMpKTogICMgUmVwZWF0IGZvciB0aGUgbGVuZ3RoIG9mIHByZXNldHMKICAgIHByZXNldCA9IHByZXNldHNbcl0gICMgU2V0IHByZXNldCB0byB0aGUgcHJlc2V0IGluIGxpbmUgcgogICAgdmJhciA9IHByZXNldC5maW5kKCd8JykgICMgRmluZCBhIHBpcGUgaW4gcHJlc2V0CiAgICBuYW1lcHJlc2V0ID0gcHJlc2V0Wzp2YmFyXSAgIyBTcGxpdCBwcmVzZXQgdG8gYmVmb3JlIHRoZSBiYXIgYW5kIHNldCBuYW1lcHJlc2V0IHRvIGl0CgogICAgaWYgcHJlc2V0bmFtZSA9PSBuYW1lcHJlc2V0OiAgIyBJZiB0aGUgcHJlc2V0bmFtZSBpcyBuYW1lcHJlc2V0CiAgICAgICAgcHJpbnQoJ1ByZXNldCBOYW1lIEFscmVhZHkgRXhpc3RzJykgICMgVGVsbCB0aGUgc3VlciB0aGF0IHRoZSBwcmVzZXQgbmFtZSBhbHJlYWR5IGV4aXN0cwogICAgICAgIHByZXNldHRydWUgPSAwICAjIFNldCBwcmVzZXR0cnVlIHRvIDAKCmlmIHByZXNldG5hbWUgIT0gJycgYW5kIHByZXNldHRydWUgPT0gMTogICMgSWYgdGhlIHByZXNldG5hbWUgaXMgbm90IGVtcHR5IGFuZCBwcmVzZXR0cnVlIGlzIDEKICAgIHdpdGggb3BlbignaGFuZ21hbnByZXNldHMudHh0JywgJ2EnKSBhcyBmOiAgIyBPcGVuIHRoZSBwcmVzZXRzIGZpbGUgYXMgYXBwZW5kIG1vZGUKICAgICAgICBmLndyaXRlKCd7fXx7fVxuJy5mb3JtYXQocHJlc2V0bmFtZSwgb3B0aW9ucykpICAjIFdyaXRlIHRoZSBwcmVzZXQgbmFtZSBhbmQgY29kZSB0byBhIG5ld2xpbmUKCm9wdGlvbmxpc3RsZW4gPSBsZW4ob3B0aW9uc2xpc3QpICAjIFNldCBvcHRpb25saXN0bGVuIHRvIHRoZSBsZW5ndGggb2Ygb3B0aW9uc2xpc3QKb3B0aW9ubGlzdGpvaW4gPSAnJy5qb2luKG9wdGlvbnNsaXN0KSAgIyBKb2luIHRoZSBsaXN0IHdpdGggbm8gc2VwZXJhdG9yCgpwcmVzZXRuYW1lY2hlY2sgPSAwICAjIFNldCBwcmVzZXRuYW1lY2hlY2sgdG8gMAoKd2hpbGUgJy1vJyBpbiBvcHRpb25saXN0am9pbjogICMgV2hpbGUgLW8gaXMgaW4gb3B0aW9ubGlzdGpvaW4KICAgIG9wdGlvbmxpc3Rqb2luID0gJycuam9pbihvcHRpb25zbGlzdCkgICMgSm9pbiB0aGUgbGlzdCB3aXRoIG5vIHNlcGVyYXRvcgogICAgb3B0aW9uc2xpc3QgPSBvcHRpb25saXN0am9pbi5zcGxpdCgnLScpICAjIFNwbGl0IHRoZSBsaXN0IHdpdGggYSAtIHNlcGVyYXRvcgogICAgb3B0aW9uc2xpc3QgPSBvcHRpb25zbGlzdFsxOl0gICMgUmVtb3ZlIHRoZSBmaXJzdCBzdHJpbmcgaW4gdGhlIG9wdGlvbnNsaXN0CgogICAgZm9yIGkgaW4gcmFuZ2UoMCwgbGVuKG9wdGlvbnNsaXN0KSk6ICAjIEZvciB0aGUgbGVuZ3RoIG9mIG9wdGlvbnNsaXN0CiAgICAgICAgb3B0aW9uID0gb3B0aW9uc2xpc3RbaV0gICMgU2V0IG9wdGlvbiB0byB0aGUgaXRoIHZhbHVlIG9mIG9wdGlvbnNsaXN0CiAgICAgICAgaWYgb3B0aW9uWzBdICE9ICctJzogICMgSWYgdGhlIGZpcnN0IGNoYXJhY3RlciBvZiBvcHRpb24gaXMgbm90IGEgZGFzaAogICAgICAgICAgICBvcHRpb25zbGlzdFtpXSA9ICctJyArIG9wdGlvbnNsaXN0W2ldICAjIEFkZCBhIGRhc2ggYmVmb3JlIG9wdGlvbgoKICAgIGZvciBpIGluIHJhbmdlKDAsIGxlbihvcHRpb25zbGlzdCkpOiAgIyBGb3IgdGhlIGxlbmd0aCBvZiBvcHRpb25zbGlzdAogICAgICAgIG9wdGlvbiA9IG9wdGlvbnNsaXN0W2ldICAjIFNldCBvcHRpb24gdG8gdGhlIGl0aCB2YWx1ZSBvZiBvcHRpb25zbGlzdAoKICAgICAgICBpZiAnLW8nIGluIG9wdGlvbjogICMgSWYgLW8gaXMgaW4gb3B0aW9uCiAgICAgICAgICAgIG9wdGlvbiA9IG9wdGlvblsyOl0gICMgUmVtb3ZlIHRoZSBmaXJzdCB0d28gY2hhcmFjdGVycwoKICAgICAgICAgICAgZm9yIHIgaW4gcmFuZ2UoMCwgbGVuKHByZXNldHMpKTogICMgUmVwZWF0IGZvciB0aGUgbGVuZ3RoIG9mIHByZXNldHMKICAgICAgICAgICAgICAgIHByZXNldCA9IHByZXNldHNbcl0gICMgU2V0IHByZXNldCB0byB0aGUgcHJlc2V0IGluIGxpbmUgcgogICAgICAgICAgICAgICAgdmJhciA9IHByZXNldC5maW5kKCd8JykgICMgRmluZCBhIHBpcGUgaW4gcHJlc2V0CiAgICAgICAgICAgICAgICBuYW1lcHJlc2V0ID0gcHJlc2V0Wzp2YmFyXSAgIyBTcGxpdCBwcmVzZXQgdG8gYmVmb3JlIHRoZSBiYXIgYW5kIHNldCBuYW1lcHJlc2V0IHRvIGl0CgogICAgICAgICAgICAgICAgaWYgbmFtZXByZXNldCA9PSBvcHRpb246ICAjIElmIHRoZSBjaG9zZW4gcHJlc2V0IG5hbWUgbWF0Y2hlcyB0aGUgb25lIGZvdW5kCiAgICAgICAgICAgICAgICAgICAgb3B0aW9ucHJlc2V0ID0gcHJlc2V0W3ZiYXIgKyAxOl0gICMgU3BsaXQgcHJlc2V0IHRvIGFmdGVyIHRoZSBiYXIgYW5kIHNldCBvcHRpb25wcmVzZXQgdG8gaXQKICAgICAgICAgICAgICAgICAgICBvcHRpb25zbmV3ID0gb3B0aW9ucHJlc2V0LnNwbGl0KCctJykgICMgU3BsaXQgb3B0aW9ucHJlc2V0IGJ5IGEgLQogICAgICAgICAgICAgICAgICAgIG9wdGlvbnNuZXcgPSBvcHRpb25zbmV3WzE6XSAgIyBSZW1vdmUgdGhlIGZpcnN0IGNoYXJhY3RlciBmcm9tIG9wdGlvbnNuZXcKICAgICAgICAgICAgICAgICAgICBvcHRpb25maW5kID0gJy1ve30nLmZvcm1hdChuYW1lcHJlc2V0KSAgIyBTZXQgb3B0aW9uZmluZCB0byAtbyhwcmVzZXQgbmFtZSkKICAgICAgICAgICAgICAgICAgICBvcHRpb25zbGlzdC5wb3AoaSkgICMgUmVtb3ZlIC1vIGZyb20gdGhlIGxpc3QKCiAgICAgICAgICAgICAgICAgICAgZm9yIGQgaW4gcmFuZ2UoMCwgbGVuKG9wdGlvbnNuZXcpKTogICMgRm9yIHRoZSBsZW5ndGggb2Ygb3B0aW9uc25ldwogICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25uZXcgPSBvcHRpb25zbmV3W2RdICAjIFNldCBvcHRpb25uZXcgdG8gdGhlIGQgcGFydCBvZiBvcHRpb25zbmV3CgogICAgICAgICAgICAgICAgICAgICAgICBpZiBvcHRpb25uZXdbMF0gIT0gJy0nOiAgIyBJZiB0aGUgZmlyc3QgY2hhcmFjdGVyIG9mIG9wdGlvbm5ldyBpcyBub3QgYSBkYXNoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25uZXcgPSAnLScgKyBvcHRpb25uZXcgICMgQWRkIGEgZGFzaCBiZWZvcmUgb3B0aW9ubmV3CgogICAgICAgICAgICAgICAgICAgICAgICBvcHRpb25zbGlzdC5pbnNlcnQoaStkLCBvcHRpb25uZXcpICAjIEluc2VydCBvcHRpb25uZXcgdG8gdGhlIG9wdGlvbnNsaXN0IGFmdGVyIHRoZSBwcmV2aW91cwogICAgICAgICAgICAgICAgICAgIHByZXNldG5hbWVjaGVjayA9IDEgICMgU2V0IHByZXNldG5hbWVjaGVjayB0byAxCgogICAgICAgICAgICBpZiBwcmVzZXRuYW1lY2hlY2sgPT0gMDogICMgSWYgcHJlc2V0bmFtZWNoZWNrIGlzIDAKICAgICAgICAgICAgICAgIHByaW50KCdQcmVzZXQgbm90IGZvdW5kJykgICMgVGVsbCB0aGUgdXNlciB0aGF0IHRoZSBwcmVzZXQgaGFzIG5vdCBiZWVuIGZvdW5kCiAgICAgICAgICAgICAgICBvcHRpb25zbGlzdCA9ICcnICAjIFNldCBvcHRpb25zbGlzdCB0byBhbiBlbXB0eSBzdHJpbmcKCm9wdGlvbnMgPSBvcHRpb25saXN0am9pbiAgIyBTZXQgb3B0aW9ucyB0byBvcHRpb25saXN0am9pbgoKY29udGFpbnNsaXN0ID0gJycgICMgU2V0IGNvbnRhaW5saXN0IHRvIGFuIGVtcHR5IHN0cmluZwoKZmlyc3RsZXR0ZXIgPSAnJyAgIyBTZXQgZmlyc3RsZXR0ZXIgdG8gYW4gZW1wdHkgc3RyaW5nCgp2YWxpZG1vZGUgPSAnJyAgICAjIFNldCB2YWxpZG1vZGUgdG8gYW4gZW1wdHkgc3RyaW5nCgp2YWxpZHNsaXN0ID0gJycgICMgU2V0IHZhbGlkc2xpc3QgdG8gYW4gZW1wdHkgc3RyaW5nCgppZiAnLXcnIGluIG9wdGlvbnM6CiAgICB3b3JkbGlzdGFsbCA9IFtdICAjIFNldCB3b3JkbGlzdGFsbCB0byBhbiBlbXB0eSBsaXN0CmVsc2U6CiAgICB3b3JkbGlzdGFsbCA9IHdvcmRsaXN0ICAjIFNldCB3b3JkbGlzdGFsbCB0byB3b3JkbGlzdAoKCmZvciBpIGluIHJhbmdlKDAsIGxlbihvcHRpb25zbGlzdCkpOgogICAgaWYgJy1sJyBpbiBvcHRpb25zbGlzdFtpXTogICMgSWYgdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0IGhhcyAnLWwnIGluIGl0CiAgICAgICAgb3B0aW9ucGljayA9IG9wdGlvbnNsaXN0W2ldICAjIFNldCBvcHRpb25waWNrIHRvIHRoZSB2YWx1ZSBvZiBvcHRpb25zbGlzdAogICAgICAgIG9wdGlvbnNudW0gPSBvcHRpb25waWNrWzI6XSAgIyBSZW1vdmUgdGhlIGZpcnN0LXNlY29uZCB2YWx1ZXMgZnJvbSBvcHRpb25waWNrCiAgICAgICAgbnVtYmVyID0gaW50KG9wdGlvbnNudW0pICAjIFNldCBudW1iZXIgdG8gaW50ZWdlciBvcHRpb25zbnVtCiAgICAgICAgYmVnaW5uaW5nID0gbnVtYmVyICAjIFNldCBiZWdpbm5pbmcgdG8gbnVtYmVyCiAgICAgICAgZW5kaW5nID0gbnVtYmVyICAjIFNldCBlbmRpbmcgdG8gbnVtYmVyCgogICAgZWxpZiAnLWInIGluIG9wdGlvbnNsaXN0W2ldIGFuZCAnLWwnIG5vdCBpbiBvcHRpb25zbGlzdFtpXTogICMgSWYgdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0CiAgICAgICAgIyAgaGFzICctJyBpbiBpdCBhbmQgZG9lcyBub3QgY29udGFpbiAnLWwnCiAgICAgICAgb3B0aW9ucGljayA9IG9wdGlvbnNsaXN0W2ldICAjIFNldCBvcHRpb25waWNrIHRvIHRoZSB2YWx1ZSBvZiBvcHRpb25zbGlzdAogICAgICAgIG9wdGlvbnNudW0gPSBvcHRpb25waWNrWzI6XSAgIyBSZW1vdmUgdGhlIGZpcnN0LXNlY29uZCB2YWx1ZXMgZnJvbSBvcHRpb25waWNrCiAgICAgICAgbnVtYmVyID0gaW50KG9wdGlvbnNudW0pICAjIFNldCBudW1iZXIgdG8gaW50ZWdlciBvcHRpb25zbnVtCiAgICAgICAgYmVnaW5uaW5nID0gbnVtYmVyICAjIFNldCBiZWdpbm5pbmcgdG8gbnVtYmVyCgogICAgZWxpZiAnLWUnIGluIG9wdGlvbnNsaXN0W2ldIGFuZCAnLWwnIG5vdCBpbiBvcHRpb25zbGlzdFtpXTogICMgSWYgdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0CiAgICAgICAgIyAgaGFzICctYicgaW4gaXQgYW5kIGRvZXMgbm90IGNvbnRhaW4gJy1sJwogICAgICAgIG9wdGlvbnBpY2sgPSBvcHRpb25zbGlzdFtpXSAgIyBTZXQgb3B0aW9ucGljayB0byB0aGUgdmFsdWUgb2Ygb3B0aW9uc2xpc3QKICAgICAgICBvcHRpb25zbnVtID0gb3B0aW9ucGlja1syOl0gICMgUmVtb3ZlIHRoZSBmaXJzdC1zZWNvbmQgdmFsdWVzIGZyb20gb3B0aW9ucGljawogICAgICAgIG51bWJlciA9IGludChvcHRpb25zbnVtKSAgIyBTZXQgbnVtYmVyIHRvIGludGVnZXIgb3B0aW9uc251bQogICAgICAgIGVuZGluZyA9IG51bWJlciAgIyBTZXQgZW5kaW5nIHRvIG51bWJlcgoKICAgIGVsaWYgJy1yJyBpbiBvcHRpb25zbGlzdFtpXTogICMgSWYgdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0IGhhcyAtciBpbiBpdAogICAgICAgIG9wdGlvbnBpY2sgPSBvcHRpb25zbGlzdFtpXSAgIyBTZXQgb3B0aW9ucGljayB0byB0aGUgdmFsdWUgb2Ygb3B0aW9uc2xpc3QKICAgICAgICBvcHRpb25zbnVtID0gb3B0aW9ucGlja1syOl0gICMgUmVtb3ZlIHRoZSBmaXJzdC1zZWNvbmQgdmFsdWVzIGZyb20gb3B0aW9ucGljawogICAgICAgIG51bWJlciA9IGludChvcHRpb25zbnVtKSAgIyBTZXQgbnVtYmVyIHRvIGludGVnZXIgb3B0aW9uc251bQogICAgICAgIHJlcGVhdCA9IG51bWJlciAgIyBTZXQgcmVwZWF0IHRvIG51bWJlcgoKICAgIGVsaWYgJy10JyBpbiBvcHRpb25zbGlzdFtpXTogICMgSWYgdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0IGhhcyAtdCBpbiBpdAogICAgICAgIG9wdGlvbnBpY2sgPSBvcHRpb25zbGlzdFtpXSAgIyBTZXQgb3B0aW9ucGljayB0byB0aGUgdmFsdWUgb2Ygb3B0aW9uc2xpc3QKICAgICAgICBvcHRpb25zbnVtID0gb3B0aW9ucGlja1syXSAgIyBSZW1vdmUgdGhlIGZpcnN0LXNlY29uZCB2YWx1ZXMgZnJvbSBvcHRpb25zcGljawogICAgICAgIG51bWJlciA9IGludChvcHRpb25zbnVtKSAgIyBTZXQgbnVtYmVyIHRvIGludGVnZXIgb3B0aW9uc251bQogICAgICAgIHJlcGVhdF90b3RhbCA9IG51bWJlciAgIyBTZXQgcmVwZWF0X3RvdGFsIHRvIG51bWJlcgoKICAgIGVsaWYgJy14JyBpbiBvcHRpb25zbGlzdFtpXTogICMgSWYgdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0IGhhcyAteCBpbiBpdAogICAgICAgIG9wdGlvbnBpY2sgPSBvcHRpb25zbGlzdFtpXSAgIyBTZXQgb3B0aW9ucGljayB0byB0aGUgdmFsdWUgb2Ygb3B0aW9uc2xpc3QKICAgICAgICB2YWxpZG1vZGUgPSBvcHRpb25waWNrWzJdICAjIFJlbW92ZSB0aGUgZmlyc3Qtc2Vjb25kIHZhbHVlcyBmcm9tIG9wdGlvbnBpY2sKICAgICAgICB2YWxpZGxpc3QgPSBvcHRpb25waWNrWzQ6LTFdICAjIFNsaWNlIHRoZSBsaXN0IG9mIGNoYXJhY3RlcnMgZnJvbSBvcHRpb25waWNrCiAgICAgICAgdmFsaWRzbGlzdCA9IHZhbGlkbGlzdC5zcGxpdCgnLCcpICAjIENyZWF0ZSBhIGxpc3QgZnJvbSB2YWxpZGxpc3QKCiAgICBlbGlmICctZicgaW4gb3B0aW9uc2xpc3RbaV06ICAjIElmIHRoZSB2YWx1ZSBvZiBvcHRpb25zbGlzdCBoYXMgLWYgaW4gaXQKICAgICAgICBvcHRpb25waWNrID0gb3B0aW9uc2xpc3RbaV0gICMgU2V0IG9wdGlvbnBpY2sgdG8gdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0CiAgICAgICAgb3B0aW9uc251bSA9IG9wdGlvbnBpY2tbMjpdICAjIFJlbW92ZSB0aGUgZmlyc3Qtc2Vjb25kIHZhbHVlcyBmcm9tIG9wdGlvbnBpY2sKICAgICAgICBsZXR0ZXIgPSBvcHRpb25zbnVtICAjIFNldCBsZXR0ZXIgdG8gaW50ZWdlciBvcHRpb25zbnVtCiAgICAgICAgZmlyc3RsZXR0ZXIgPSBsZXR0ZXIgICMgU2V0IHJlcGVhdF90b3RhbCB0byBsZXR0ZXIKCiAgICBlbGlmICctdycgaW4gb3B0aW9uc2xpc3RbaV06ICAjIElmIHRoZSB2YWx1ZSBvZiBvcHRpb25zbGlzdCBoYXMgLXcgaW4gaXQKICAgICAgICBvcHRpb25waWNrID0gb3B0aW9uc2xpc3RbaV0gICMgU2V0IG9wdGlvbnBpY2sgdG8gdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0CiAgICAgICAgd29yZHMgPSBvcHRpb25waWNrWzM6LTFdICAjIFJlbW92ZSB0aGUgZmlyc3QtdGhpcmQgYW5kIGxhc3QgdmFsdWUgZnJvbSBvcHRpb25waWNrCgogICAgICAgIGlmIHdvcmRzWzBdID09ICcjJzogICMgSWYgdGhlIGZpcnN0IGNoYXJhY3RlciBpcyBhIGhhc2h0YWcKICAgICAgICAgICAgZmlsZW5hbWUgPSB3b3Jkc1sxOl0gICMgUmVtb3ZlIHRoZSBmaXJzdCBjaGFyYWN0ZXIgZnJvbSB3b3JkcyBhbmQgc2V0IHRoYXQgdG8gZmlsZW5hbWUKCiAgICAgICAgICAgIGlmIG9zLnBhdGguaXNmaWxlKGZpbGVuYW1lKTogICMgSWYgdGhlIGZpbGVuYW1lIHNwZWNpZmllZCBpcyBhIHJlYWwgZmlsZQogICAgICAgICAgICAgICAgd2l0aCBvcGVuKGZpbGVuYW1lLCAncicpIGFzIGY6ICAjIE9wZW4gdGV4dCBmaWxlIHRoYXQgc3RvcmVzIHRoZSB3b3JkcwogICAgICAgICAgICAgICAgICAgIHdvcmRsaXN0ID0gW2xpbmUuc3RyaXAoKSBmb3IgbGluZSBpbiBmXSAgIyBBZGQgZXZlcnkgbGluZSBvZiB0aGUgZmlsZSB0byBhIGxpc3QKCiAgICAgICAgICAgIGVsc2U6ICAjIElmIHRoZSBmaWxlbmFtZSBzcGVjaWZpZWQgaXMgbm90IGEgcmVhbCBmaWxlCiAgICAgICAgICAgICAgICBwcmludCgnRmlsZSBEb2VzIE5vdCBFeGlzdCcpICAjIFRlbGwgdGhlIHVzZXIgdGhhdCB0aGUgZmlsZSBkb2VzIG5vdCBleGlzdAoKICAgICAgICBlbHNlOiAgIyBJZiB0aGUgZmlyc3QgY2hhcmFjdGVyIGlzIG5vdCBhIGhhc2h0YWcKICAgICAgICAgICAgd29yZHNsaXN0ID0gd29yZHMuc3BsaXQoJywnKSAgIyBTcGxpdCB3b3JkcyBieSAsCiAgICAgICAgICAgIHdvcmRsaXN0ID0gd29yZHNsaXN0ICAjIFNldCB3b3JkbGlzdCB0byB3b3Jkc2xpc3QKCiAgICAgICAgZm9yIHIgaW4gcmFuZ2UoMCwgbGVuKHdvcmRsaXN0KSk6ICAjIFJlcGVhdCBmb3IgdGhlIGxlbmd0aCBvZiB3b3JkbGlzdAogICAgICAgICAgICB3b3JkbGlzdGFsbC5hcHBlbmQod29yZGxpc3Rbcl0pICAjIEFwcGVuZCB0aGUgd29yZCB0byB3b3JkbGlzdGFsbAoKICAgIGVsaWYgJy1jJyBpbiBvcHRpb25zbGlzdFtpXTogICMgSWYgdGhlIHZhbHVlIG9mIG9wdGlvbnNsaXN0IGhhcyAtdyBpbiBpdAogICAgICAgIG9wdGlvbnBpY2sgPSBvcHRpb25zbGlzdFtpXSAgIyBTZXQgb3B0aW9ucGljayB0byB0aGUgdmFsdWUgb2Ygb3B0aW9uc2xpc3QKICAgICAgICBjb250YWluID0gb3B0aW9ucGlja1szOi0xXSAgIyBSZW1vdmUgdGhlIGZpcnN0IHZhbHVlIGZyb20gb3B0aW9uc3BpY2sKICAgICAgICBjb250YWlubGlzdCA9IGNvbnRhaW4uc3BsaXQoJywnKSAgIyBTcGxpdCBjb250YWluIGJ5ICwKICAgICAgICBjb250YWluc2xpc3QgPSBjb250YWlubGlzdCAgIyBTZXQgY29udGFpbnNsaXN0IHRvIGNvbnRhaW5saXN0Cgp3b3JkbGlzdCA9IHdvcmRsaXN0YWxsICAjIFNldHMgd29yZGxpc3QgdG8gd29yZGxpc3RhbGwKCm9wdGlvbnNsaXN0am9pbiA9ICcsJy5qb2luKG9wdGlvbnNsaXN0KSAgIyBKb2luIG9wdGlvbnNsaXN0IGJ5ICwgYW5kIHNldCBpdCB0byBvcHRpb25zbGlzdGpvaW4KCmxlbmd0aGxpc3QgPSBbXSAgIyBDcmVhdGVzIGEgbGlzdCBmb3IgcHV0dGluZyB0aGUgd29yZHMgdGhhdCBhcmUgdGhlIHNhbWUgbGVuZ3RoIGFzIHJlcXVlc3RlZApjdXN0b21saXN0ID0gW10gICMgQ3JlYXRlcyBhIGxpc3QgZm9yIHB1dHRpbmcgdGhlIHdvcmRzIHRoYXQgZml0IGJldHdlZW4gYmVnaW5uaW5nIGFuZCBlbmRpbmcKdHJ1ZWxpc3QgPSBbXSAgIyBDcmVhdGVzIGEgbGlzdCBmb3IgdHJ1ZSB3b3JkcwoKd29yZGxpc3RhZGQgPSAwICAjIFNldCB3b3JkbGlzdGFkZCB0byAwCndvcmRsaXN0YWRkcm91bmQgPSAwICAjIFNldCB3b3JkbGlzdGFkZHJvdW5kIHRvIDAKd29yZGxpc3Rjb3VudCA9IDAgICMgU2V0IHdvcmRsaXN0Y291bnQgdG8gMAoKdm93ZWxzID0gWydhJywgJ2UnLCAnaScsICdvJywgJ3UnLCAneSddICAjIExpc3Qgb2Ygdm93ZWxzIHRvIGNoZWNrIGluIGEgd29yZAoKdmFsaWRfc3RyaW5nID0gWydhJywgJ2InLCAnYycsICdkJywgJ2UnLCAnZicsICdnJywgJ2gnLCAnaScsICdqJywgJ2snLCAnbCcsICdtJywgJ24nLCAnbycsICdwJywgJ3EnLCAncicsCiAgICAgICAgICAgICAgICAncycsICd0JywgJ3UnLCAndicsICd3JywgJ3gnLCAneScsICd6J10gICMgTGlzdCBvZiB2YWxpZCBzdHJpbmcKCgoKaWYgJy1uJyBpbiBvcHRpb25zOiAgIyBJZiB0aGUgdXNlciBlbmFibGVkIG51bWJlcnMKICAgIHZhbGlkX3N0cmluZy5hcHBlbmQoWycxJywgJzInLCAnMycsICc0JywgJzUnLCAnNicsICc3JywgJzgnLCAnOScsICcwJ10pICAjIEFsbG93IG51bWJlcnMKCmlmICctcCcgaW4gb3B0aW9uczogICMgSWYgdGhlIHVzZXIgZW5hYmxlZCBwZXJpb2RzCiAgICB2YWxpZF9zdHJpbmcuYXBwZW5kKCcuJykgICMgQWxsb3cgcGVyaW9kcwoKaWYgJy1zJyBpbiBvcHRpb25zOiAgIyBJZiB0aGUgdXNlciBlbmFibGVkIHNwYWNlcwogICAgdmFsaWRfc3RyaW5nLmFwcGVuZCgnICcpICAjIEFsbG93IHNwYWNlcwoKaWYgJy14JyBpbiBvcHRpb25zOiAgIyBJZiB0aGUgdXNlciBjb25maWd1cmVkIHZhbGlkIHN0cmluZ3MKICAgIGlmIHZhbGlkbW9kZSA9PSAnYSc6ICAjIElmIHRoZSB2YWxpZG1vZGUgaXMgYQogICAgICAgIHZhbGlkX3N0cmluZyA9IHZhbGlkX3N0cmluZyArIHZhbGlkc2xpc3QKICAgIGVsaWYgdmFsaWRtb2RlID09ICdzJzoKICAgICAgICB2YWxpZF9zdHJpbmcgPSB2YWxpZHNsaXN0CiAgICBlbHNlOgogICAgICAgIHByaW50KCdJbnZhbGlkIE1vZGUnKQoKCmZvciBpIGluIHJhbmdlKDAsIGxlbih3b3JkbGlzdCkpOiAgIyBSZXBlYXRzIHRoaXMgdW50aWwgYXQgdGhlIGVuZCBvZiB3b3JkbGlzdAogICAgdGVzdHNmYWlsZWQgPSBbXSAgIyBMaXN0IG9mIHRlc3RzIGZhaWxlZAoKICAgIHdvcmQgPSB3b3JkbGlzdFtpXSAgIyBTcGxpdHMgdGhlIHdvcmRsaXN0IHRvIGksIGFuZCBhc3NpZ25zIGl0IHRvIHdvcmQKICAgIHdvcmQgPSB3b3JkLmxvd2VyKCkgICMgTWFrZXMgdGhlIHdvcmQgbG93ZXJjYXNlCgogICAgaWYgaSA+IHdvcmRsaXN0YWRkcm91bmQtMSBhbmQgMTAtd29yZGxpc3Rjb3VudCAhPSAwOiAgIyBJZiBpIGlzIGdyZWF0ZXIgdGhhbiB0aGUgdmFsdWUgbmVlZGVkIHRvCiAgICAgICAgIyByZXBsYWNlIGEgLSB3aXRoIGEgKyBhbmQgMTAtdGhlIGFtb3VudCBvZiA9IGlzIG5vdCAwCiAgICAgICAgd29yZGxpc3Rjb3VudCArPSAxICAjIEFkZCAxIHRvIHdvcmRsaXN0Y291bnQKICAgICAgICBwbHVzID0gJysnKndvcmRsaXN0Y291bnQgICMgVGltZXMgKyBieSB0aGUgYW1vdW50IG9mIHRpbWVzIHRoZSBpZiBzdGF0ZW1lbnQgcmFuCiAgICAgICAgbWludXMgPSAnLScqKDEwLXdvcmRsaXN0Y291bnQpICAjIFRpbWVzIC0gYnkgMTAgbWludXMgdGhlIGFtb3VudCBvZiBwbHVzJ3MKICAgICAgICBsb2FkaW5nID0gcGx1cyArIG1pbnVzICAjIENvbWJpbmUgYm90aCBwbHVzIGFuZCBtaW51cyBzdHJpbmdzCiAgICAgICAgc3lzLnN0ZG91dC53cml0ZSgiXHJbe31dIi5mb3JtYXQobG9hZGluZykpICAjIE5vdGlmeSB0aGUgdXNlciBvZiBwcm9ncmVzcwogICAgICAgIHN5cy5zdGRvdXQuZmx1c2goKSAgIyBGbHVzaCB0aGUgYnVmZmVyCiAgICAgICAgd29yZGxpc3RhZGQgKz0gbGVuKHdvcmRsaXN0KS8xMCAgIyBBZGQgdGhlIGxlbmd0aCBvZiB3b3JkbGlzdC8xMCB0byB3b3JkbGlzdGFkZAogICAgICAgIHdvcmRsaXN0YWRkcm91bmQgPSByb3VuZCh3b3JkbGlzdGFkZCkgICMgU2V0IHdvcmRsaXN0YWRkcm91bmQgdG8gd29yZGxpc3RhZGQgcm91bmRlZAoKICAgIHRydWV3b3JkID0gMCAgIyBTZXQgdHJ1ZXdvcmQgdG8gMAoKICAgIGZvciByIGluIHJhbmdlKDAsIGxlbih2b3dlbHMpKTogICMgTG9vcCBmb3IgdGhlIGxlbmd0aCBvZiB0aGUgdm93ZWxzIGxpc3QKCiAgICAgICAgaWYgdm93ZWxzW3JdIGluIHdvcmQgYW5kICctdicgbm90IGluIG9wdGlvbnM6ICAjIElmIHRoZSB2b3dlbCBpcyBub3QgaW4gdGhlIHdvcmQKICAgICAgICAgICAgdHJ1ZXdvcmQgPSAxICAjIFNldCB0cnVld29yZCB0byAxCiAgICAgICAgICAgIGJyZWFrICAjIEJyZWFrIG91dCBvZiB0aGUgZm9yIGxvb3AKCiAgICBpZiB0cnVld29yZCA9PSAwOiAgIyBJZiB0cnVld29yZCBpcyAwCiAgICAgICAgdGVzdHNmYWlsZWQuYXBwZW5kKCd2b3dlbHMnKSAgIyBBcHBlbmQgdm93ZWxzIHRvIHRoZSB0ZXN0c2ZhaWxlZCBsaXN0CgogICAgaWYgJy1uJyBub3QgaW4gc3RyKG9wdGlvbnMpOiAgIyBJZiBudW1iZXJzIGFyZSBvZmYKCiAgICAgICAgZm9yIHIgaW4gcmFuZ2UobGVuKHdvcmQpKTogICMgRm9yIHRoZSBsZW5ndGggb2YgdGhlIHdvcmQKCiAgICAgICAgICAgIGlmIHdvcmRbcl0gaW4gJzEyMzQ1Njc4OTAnOiAgIyBTZWUgaWYgdGhlIHN0cmluZyBpcyBhIG51bWJlcgogICAgICAgICAgICAgICAgdHJ1ZXdvcmQgPSAwICAjIFNldCB0cnVld29yZCB0byAwCiAgICAgICAgICAgICAgICB0ZXN0c2ZhaWxlZC5hcHBlbmQoJ251bWJlcnMnKSAgIyBBcHBlbmQgbnVtYmVycyB0byB0aGUgdGVzdHNmYWlsZWQgbGlzdAogICAgICAgICAgICAgICAgYnJlYWsgICMgQnJlYWsgb3V0IG9mIHRoZSBmb3IgbG9vcAoKICAgIGlmIGxlbih3b3JkKSA8IGJlZ2lubmluZyBvciBsZW4od29yZCkgPiBlbmRpbmc6ICAjIElmIHRoZSB3b3JkIGlzIGxlc3MgdGhhbiBiZWdpbm5pbmcgb3IgZ3JlYXRvciB0aGFuIGVuZGluZwogICAgICAgIHRydWV3b3JkID0gMCAgIyBTZXQgdHJ1ZXdvcmQgdG8gMAogICAgICAgIHRlc3RzZmFpbGVkLmFwcGVuZCgnbGVuZ3RoJykgICAjIEFwcGVuZCBsZW5ndGggdG8gdGhlIHRlc3RzZmFpbGVkIGxpc3QKCiAgICBpZiAnLWYnIGluIG9wdGlvbnMgYW5kIHdvcmRbMF0gIT0gZmlyc3RsZXR0ZXI6ICAjIElmIC1mIGlzIGluIG9wdGlvbnMgYW5kIElmIHRoZSBmaXJzdCBjaGFyYWN0ZXIgb2YgdGhlCiAgICAgICAgIyB3b3JkIGlzIG5vdCBlcXVhbCB0byBmaXJzdGxldHRlcgogICAgICAgIHRydWV3b3JkID0gMCAgIyBTZXQgdHJ1ZXdvcmQgdG8gMAogICAgICAgIHRlc3RzZmFpbGVkLmFwcGVuZCgnZmlyc3RsZXR0ZXInKSAgIyBBcHBlbmQgZmlyc3RsZXR0ZXIgdG8gdGhlIHRlc3RzZmFpbGVkIGxpc3QKCiAgICB0cnVlY29udGFpbnMgPSAwICAjIFNldCB0cnVlY29udGFpbnMgdG8gMAoKICAgIGlmICctYycgaW4gb3B0aW9uczogICMgSWYgdGhlIHVzZXIgY29uZmlndXJlZCBjb250YWlucwoKICAgICAgICBmb3IgciBpbiByYW5nZSgwLCBsZW4od29yZCkpOiAgIyBGb3IgdGhlIGxlbmd0aCBvZiB3b3JkCgogICAgICAgICAgICBpZiB3b3JkW3JdIGluIGNvbnRhaW5zbGlzdDogICMgSWYgd29yZFtyXSBpcyBpbiBjb250YWluc2xpc3QKICAgICAgICAgICAgICAgIHRydWVjb250YWlucyA9IDEgICMgU2V0IHRydWVjb250YWlucyB0byAxCgogICAgICAgIGlmIHRydWVjb250YWlucyA9PSAwOiAgIyBJZiB0cnVlY29udGFpbnMgaXMgMAogICAgICAgICAgICB0cnVld29yZCA9IDAgICMgU2V0IHRydWV3b3JkIHRvIDAKICAgICAgICAgICAgdGVzdHNmYWlsZWQuYXBwZW5kKCdjb25maWd1cmVkJykgICMgQXBwZW5kIGNvbmZpZ3VyZWQgdG8gdGhlIHRlc3RzZmFpbGVkIGxpc3QKCiAgICBpZiB2YWxpZG1vZGUgIT0gJ28nOiAgIyBJZiB2YWxpZG1vZGUgaXMgbm90IG8KICAgICAgICBmb3IgciBpbiByYW5nZSgwLCBsZW4od29yZCkpOiAgIyBGb3IgdGhlIGxlbmd0aCBvZiB3b3JkCiAgICAgICAgICAgIGlmIHdvcmRbcl0gbm90IGluIHZhbGlkX3N0cmluZzogICMgSWYgdGhlIGNoYXJhY3RlciBpcyBub3QgaW4gdGhlIHZhbGlkX3N0cmluZyBsaXN0CiAgICAgICAgICAgICAgICB0cnVld29yZCA9IDAgICMgU2V0IHRydWV3b3JkIHRvIDAKICAgICAgICAgICAgICAgIHRlc3RzZmFpbGVkLmFwcGVuZCgndmFsaWQgc3RyaW5nJykgICMgQXBwZW5kIHZhbGlkIHN0cmluZyB0byB0aGUgdGVzdHNmYWlsZWQgbGlzdAoKICAgIGlmIHRydWV3b3JkID09IDA6ICAjIElmIHRydWV3b3JkIGlzIDAKICAgICAgICBpZiAnLXknIGluIG9wdGlvbnNsaXN0am9pbjogICMgSWYgLXkgaXMgaW4gb3B0aW9ubGlzdGpvaW4KICAgICAgICAgICAgcHJpbnQoJycpICAjIFByaW50IGEgbmV3bGluZQogICAgICAgICAgICBwcmludCgnTk9USUNFOiB7fSBoYXMgZmFpbGVkIHt9IGNoZWNrKHMpJy5mb3JtYXQod29yZCwgdGVzdHNmYWlsZWQpKSAgIyBUZWxsIHRoZSB1c2VyIHRoYXQKICAgICAgICAgICAgIyB0aGUgd29yZCBoYXMgZmFpbGVkIGEgY2hlY2sKICAgICAgICBjb250aW51ZSAgIyBTa2lwIHRoZSByZXN0IG9mIHRoZSBsb29wCgogICAgaWYgJy4nIGluIHdvcmQgYW5kICctcCcgbm90IGluIHN0cihvcHRpb25zKTogICMgSWYgYSBkb3QgaXMgaW4gdGhlIHdvcmQgYW5kIHRoZSBwZXJpb2RzIG9wdGlvbiBpcyB0dXJuZWQgb2ZmCgogICAgICAgIGZvciByIGluIHJhbmdlKDAsIHdvcmQuY291bnQoJy4nKSk6ICAjIFJlcGVhdCBmb3IgdGhlIGFtb3VudCBvZiBwZXJpb2RzIGluIHRoZSB3b3JkCiAgICAgICAgICAgIHVwcGVyID0gd29yZFswOndvcmQuZmluZCgnLicpXSAgIyBTcGxpdCB0aGUgd29yZCBiZWZvcmUgdGhlIHBlcmlvZAogICAgICAgICAgICBsb3dlciA9IHdvcmRbd29yZC5maW5kKCcuJykgKyAxOl0gICMgU3BsaXQgdGhlIHdvcmQgYWZ0ZXIgdGhlIHBlcmlvZAogICAgICAgICAgICB3b3JkID0gdXBwZXIgKyBsb3dlciAgIyBDb21iaW5lIHRoZSB1cHBlciBhbmQgbG93ZXIgcGFydHMKCiAgICBpZiAnICcgaW4gd29yZCBhbmQgJy1zJyBub3QgaW4gc3RyKG9wdGlvbnMpOiAgIyBJZiBhIHNwYWNlIGlzIGluIHRoZSB3b3JkIGFuZCB0aGUgc3BhY2Ugb3B0aW9uIGlzIHR1cm5lZCBvZmYKICAgICAgICBmb3IgciBpbiByYW5nZSgwLCB3b3JkLmNvdW50KCcgJykpOiAgIyBSZXBlYXQgZm9yIHRoZSBhbW91bnQgb2Ygc3BhY2VzIGluIHRoZSB3b3JkCiAgICAgICAgICAgIHVwcGVyID0gd29yZFswOndvcmQuZmluZCgnICcpXSAgIyBTcGxpdCB0aGUgd29yZCBiZWZvcmUgdGhlIHNwYWNlCiAgICAgICAgICAgIGxvd2VyID0gd29yZFt3b3JkLmZpbmQoJyAnKSArIDE6XSAgIyBTcGxpdCB0aGUgd29yZCBhZnRlciB0aGUgc3BhY2UKICAgICAgICAgICAgd29yZCA9IHVwcGVyICsgbG93ZXIgICMgQ29tYmluZSB0aGUgdXBwZXIgYW5kIGxvd2VyIHBhcnRzCgogICAgd29yZGNoYXIgPSBbXSAgIyBDcmVhdGVzIGEgbGlzdCBjYWxsZWQgd29yZGNoYXIKCiAgICBmb3IgciBpbiByYW5nZSgwLCBsZW4od29yZCkpOiAgIyBMb29wIGZvciB0aGUgbGVuZ3RoIG9mIHRoZSB3b3JkCiAgICAgICAgcGFydGxpc3QgPSB3b3JkW3JdICAjIFNwbGl0cyB3b3JkIGludG8gbGV0dGVyCgogICAgICAgIGlmIHIrcmVwZWF0ID4gbGVuKHdvcmQpOiAgIyBJZiB0aGUgc2VjdGlvbiBpdCBpcyBjdXR0aW5nIG91dCBpbnZvbHZlcyBjaGFyYWN0ZXJzCiAgICAgICAgICAgICMgYWZ0ZXIgdGhlIGVuZCBvZiB0aGUgd29yZAogICAgICAgICAgICBicmVhayAgIyBFbmRzIHRoZSBsb29wCgogICAgICAgIHJlcHRlc3QgPSB3b3JkW3I6cityZXBlYXRdICAjIFNwbGl0cyB3b3JkIGZyb20gciB0byByICsgcmVwZWF0CiAgICAgICAgcmVwbGlzdCA9IFtdICAjIENyZWF0ZXMgYSBsaXN0IGNhbGxlZCByZXBsaXN0CgogICAgICAgIGZvciB0IGluIHJhbmdlKDAsIGxlbihyZXB0ZXN0KSk6ICAjIExvb3AgZm9yIHRoZSBsZW5ndGggb2YgcmVwdGVzdAogICAgICAgICAgICByZXBsaXN0LmFwcGVuZChyZXB0ZXN0W3RdKSAgIyBTcGxpdCByZXB0ZXN0IGludG8gYSBjaGFyYWN0ZXIgYW5kIHRoZW4gYXBwZW5kIGl0CgogICAgICAgIHJlcGxpc3RsZW4gPSBsZW4ocmVwbGlzdCkgICMgU2V0IHJlcGxpc3RsZW4gdG8gdGhlIGxlbmd0aCBvZiByZXBsaXN0CiAgICAgICAgcmVwc2V0ID0gc2V0KHJlcGxpc3QpICAjIENyZWF0ZXMgYSBzZXQgZnJvbSByZXBsaXN0CiAgICAgICAgcmVwc2V0bGVuID0gbGVuKHJlcHNldCkgICMgU2V0IHJlcHNldGxlbiB0byB0aGUgbGVuZ3RoIG9mIHJlcHNldAoKICAgICAgICBpZiAocmVwbGlzdGxlbiAtIHJlcHNldGxlbikgKyAxID49IHJlcGVhdDogICMgSWYgdGhlIGRpZmZlcmVuY2UgYmV0d2VlbiByZXBsaXN0bGVuIGFuZCByZXBzZXRsZW4KICAgICAgICAgICAgdHJ1ZXdvcmQgPSAwICAjIFNldHMgdHJ1ZXdvcmQgdG8gMAogICAgICAgICAgICB0ZXN0c2ZhaWxlZC5hcHBlbmQoJ3JlcGVhdCcpICAjIEFwcGVuZCByZXBlYXQgdG8gdGhlIHRlc3RzZmFpbGVkIGxpc3QKCiAgICAgICAgd29yZGNoYXIuYXBwZW5kKHdvcmRbcl0pICAjIEFkZHMgdGhlIGNoYXJhY3RlciB0byB0aGUgd29yZGNoYXIgbGlzdAoKICAgIGxldHRlcnNkb25lID0gW10gICMgQ3JlYXRlcyBhIGxpc3QgY2FsbGVkIGxldHRlcnNkb25lCgogICAgZm9yIHIgaW4gcmFuZ2UoMCwgbGVuKHdvcmRjaGFyKSk6ICAjIExvb3AgZm9yIHRoZSBsZW5ndGggb2Ygd29yZGNoYXIKCiAgICAgICAgaWYgd29yZGNoYXJbcl0gbm90IGluIGxldHRlcnNkb25lOiAgIyBJZiB0aGUgY2hhcmFjdGVyIGlzIG5vdCBpbiBsZXR0ZXJzZG9uZQogICAgICAgICAgICB3b3JkY2hhcmR1cGxpY2F0ZSA9IHdvcmRjaGFyLmNvdW50KHdvcmRjaGFyW3JdKSAgIyBDb3VudCBob3cgbWFueSBvZiB0aGUgY2hhcmFjdGVycyBhcmUgaW4gdGhlIHdvcmQKICAgICAgICAgICAgbGV0dGVyc2RvbmUuYXBwZW5kKHdvcmRjaGFyW3JdKSAgIyBBcHBlbmQgdGhlIGNoYXJhY3RlciB0byBsZXR0ZXJzZG9uZQoKICAgICAgICAgICAgaWYgd29yZGNoYXJkdXBsaWNhdGUgPj0gcmVwZWF0X3RvdGFsOiAgIyBJZiB0aGUgY2hhcmFjdGVyIGNvdW50IGlzIGdyZWF0b3IgdGhhbiByZXBlYXRfdG90YWwKICAgICAgICAgICAgICAgIHRydWV3b3JkID0gMCAgIyBTZXQgdHJ1ZXdvcmQgdG8gMAogICAgICAgICAgICAgICAgdGVzdHNmYWlsZWQuYXBwZW5kKCdyZXBlYXQgdG90YWwnKSAgIyBBcHBlbmQgcmVwZWF0IHRvdGFsIHRvIHRoZSB0ZXN0c2ZhaWxlZCBsaXN0CgogICAgaWYgdHJ1ZXdvcmQgPT0gMDogICMgSWYgdHJ1ZXdvcmQgaXMgMAogICAgICAgIGlmICcteScgaW4gb3B0aW9uc2xpc3Rqb2luOiAgIyBJZiAteSBpcyBpbiBvcHRpb25saXN0am9pbgogICAgICAgICAgICBwcmludCgnJykgICMgUHJpbnQgYSBuZXdsaW5lCiAgICAgICAgICAgIHByaW50KCdOT1RJQ0U6IHt9IGhhcyBmYWlsZWQge30gY2hlY2socyknLmZvcm1hdCh3b3JkLCB0ZXN0c2ZhaWxlZCkpICAjIFRlbGwgdGhlIHVzZXIgdGhhdAogICAgICAgICAgICAjIHRoZSB3b3JkIGhhcyBmYWlsZWQgYSBjaGVjawoKICAgIGlmIGludChiZWdpbm5pbmcpIDw9IGxlbihzdHIod29yZCkpIDw9IGludChlbmRpbmcpIGFuZCB0cnVld29yZCA9PSAxOiAgIyBJZiB0aGUgbGVuZ3RoIG9mIHRoZSB3b3JkIGlzIGJldHdlZW4gdGhlCiAgICAgICAgIyBiZWdpbm5pbmcgYW5kIGVuZGluZwogICAgICAgIGN1c3RvbWxpc3QuYXBwZW5kKHdvcmQpICAjIEFwcGVuZCB0aGUgd29yZCB0byBjdXN0b21saXN0CgoKc3lzLnN0ZG91dC53cml0ZSgiXHJQUk9DRVNTSU5HIERBVEEgQ09NUExFVEUiKSAgIyBOb3RpZmllcyB0aGUgdXNlciB0aGF0IHRoZSBkYXRhIHByb2Nlc3NpbmcgaXMgY29tcGxldGUKc3lzLnN0ZG91dC5mbHVzaCgpICAjIEZsdXNoIHRoZSBidWZmZXIKCmNob29zZWxpc3QgPSBbXSAgIyBDcmVhdGUgYSBsaXN0IGZvciBwaWNraW5nIHJhbmRvbSB3b3JkcyBvdXQgb2YgaXQKCnByaW50KCcnKSAgIyBQcmludCBhIG5ldyBsaW5lCgppZiAnLWInIGluIG9wdGlvbnMgb3IgJy1lJyBpbiBvcHRpb25zIG9yICctbCcgaW4gb3B0aW9uczogICMgSWYgYmVnaW5uaW5nLCBlbmQsIG9yIGxlbmd0aCBjdXN0b21pemVkCiAgICBjaG9vc2VsaXN0ID0gY3VzdG9tbGlzdCAgIyBTZXQgY2hvb3NlbGlzdCBlcXVhbCB0byBjdXN0b21saXN0CgplbHNlOiAgIyBJZiB0aGUgbGVuZ3RoIGlzIDAgb3IgbGVzcwogICAgY2hvb3NlbGlzdCA9IGN1c3RvbWxpc3QgICMgU2V0IGNob29zZWxpc3QgZXF1YWwgdG8gY3VzdG9tbGlzdAoKaWYgbGVuKGNob29zZWxpc3QpID09IDA6ICAjIElmIHRoZSBsaXN0IGhhcyBubyB3b3JkcwogICAgcHJpbnQoJ05vIFdvcmRzIEF2YWxpYWJsZScpICAjIFRlbGwgdGhlIHVzZXIgdGhhdCB0aGVyZSBpcyBubyB3b3JkcyBhdmFsaWFibGUKICAgIGV4aXQoKSAgIyBFeGl0IHRoZSBwcm9ncmFtCgpydW4gPSAwICAjIFNldCBydW4gdG8gMAoKdXNlZG51bXMgPSBbXSAgIyBTZXQgdXNlZG51bXMgdG8gYW4gZW1wdHkgbGlzdAoKd29yZF9waWMgPSAnJyAgIyBTZXQgd29yZF9waWMgdG8gYW4gZW1wdHkgc3RyaW5nCgp3b3JkcmFuZ2UgPSByYW5nZSgwLCBsZW4oY2hvb3NlbGlzdCkpICAjIFNldCB3b3JkcmFuZ2UgdG8gYSByYW5nZSBmcm9tIDAgdG8gdGhlIGxlbmd0aCBvZiBjaG9vc2VsaXN0Cgp3b3JkcmFuZ2UgPSBsaXN0KHdvcmRyYW5nZSkgICMgQ29udmVydCB3b3JkcmFuZ2UgdG8gYSBsaXN0CgoKd2hpbGUgcnVuID09IDA6ICAjIFdoaWxlIHJ1biBpcyAwCgogICAgaWYgbm90IHdvcmRyYW5nZTogICMgSWYgd29yZHJhbmdlIGlzIGVtcHR5CiAgICAgICAgcHJpbnQoJ0FsbCBXb3JkcyBVc2VkJykgICMgVGVsbCB0aGUgdXNlciB0aGF0IGFsbCB3b3JkcyBhcmUgdXNlZAogICAgICAgIHJ1biA9IDEgICMgU2V0IHJ1biB0byAxCiAgICAgICAgYnJlYWsgICMgQnJlYWsgb3V0IG9mIHRoZSB3aGlsZSBsb29wCgogICAgd29yZF9yYW4gPSByYW5kb20uY2hvaWNlKHdvcmRyYW5nZSkgICMgUGlja3MgYSByYW5kb20gbnVtYmVyIGJhc2VkIG9uIHRoZSBmaWxlIGxlbmd0aAoKICAgIHdvcmRyYW5nZS5wb3Aod29yZHJhbmdlLmluZGV4KHdvcmRfcmFuKSkgICMgUmVtb3ZlIHRoZSBudW1iZXIgZnJvbSB0aGUgd29yZHJhbmdlIGxpc3QKCiAgICB3b3JkX3BpYyA9IGNob29zZWxpc3Rbd29yZF9yYW5dICAjIFNsaWNlcyB0aGUgbGlzdCB0byB0aGUgcmFuZG9tIG51bWJlciwgdGh1cyBnZXR0aW5nIGEgcmFuZG9tIHdvcmQKCiAgICBndWVzc2VkID0gMCAgIyBTZXR0aW5nIHRoZSB2YXJpYWJsZSwgdGhhdCBlbmRzIHRoZSB3aGlsZSBsb29wIHdoZW4gdGhlIHdvcmQgaXMgZ3Vlc3NlZAoKICAgIHVzZWRsZXR0ZXJzID0gW10gICMgQ3JlYXRlcyBhIGxpc3QgdG8gc3RvcmUgbGV0dGVycyB0aGF0IGFyZSB1c2VkLCBzbyB0aGUgdHJpZXMgZG9uJ3QgZ28gdXAKCiAgICB3b3JkX3BpY19tb2QgPSAnLScgKiAobGVuKHdvcmRfcGljKSkgICMgVXNlZCB0byBkaXNwbGF5IGd1ZXNzZXMsIGFuZCBhcyBhIHNlcGVyYXRvcgoKICAgIHdvcmRfcGljX2xpc3QgPSBsaXN0KHdvcmRfcGljX21vZCkgICMgQ29udmVydHMgZXZlcnkgY2hhcmFjdGVyIG9mIHdvcmRfcGljX21vZCB0byBhIGxpc3QKCiAgICB3b3JkZ3Vlc3Nqb2luID0gJycuam9pbih3b3JkX3BpY19saXN0KSAgIyBVc2VkIGFzIGEgc2VwZXJhdG9yIGJldHdlZW4gZ3Vlc3NlcwoKICAgIGlmICcgJyBpbiB3b3JkX3BpYyBhbmQgJy1zJyBpbiBvcHRpb25zOiAgIyBJZiBhIHNwYWNlIGlzIGluIHdvcmRfcGljIGFuZCBzcGFjZXMgaXMgdHVybmVkIG9uCiAgICAgICAgdXNlZGxldHRlcnMuYXBwZW5kKCcgJykgICMgQXBwZW5kIGEgc3BhY2UgdG8gdXNlZGxldHRlcnMKICAgICAgICBmb3IgaSBpbiByYW5nZSgwLCB3b3JkX3BpYy5jb3VudCgnICcpKTogICMgUmVwZWF0IGZvciBob3cgbWFueSBzcGFjZXMgaW4gdGhlIHdvcmQgY2hvc2VuCiAgICAgICAgICAgIGVtcHR5aW5kZXggPSB3b3JkX3BpYy5maW5kKCcgJykgICMgU2V0IGVtcHR5aW5kZXggdG8gdGhlIGluZGV4IG9mIHRoZSBmaXJzdCBpbnN0YW5jZSBvZiBhIHNwYWNlIGZvdW5kCiAgICAgICAgICAgIHdvcmRfcGljX2xpc3RbZW1wdHlpbmRleF0gPSAnICcgICMgQ2hhbmdlIHRoZSBkYXNoIHRvIGEgc3BhY2UgaW4gd29yZF9waWNfbGlzdAoKICAgIGlmICctcycgaW4gb3B0aW9uczogICMgSWYgLXMgaXMgaW4gb3B0aW9ucwogICAgICAgIHZhbGlkX3N0cmluZy5wb3AodmFsaWRfc3RyaW5nLmluZGV4KCcgJykpICAjIFJlbW92ZSBzcGFjZSBmcm9tIHRoZSB2YWxpZF9zdHJpbmcgbGlzdAoKICAgIHRyaWVzID0gMCAgIyBTZXQgdGhlIGFtb3VudCBvZiB0cmllcyB0byAwCgogICAgd29yZHByaW50ID0gd29yZF9waWNfbGlzdCAgIyBUaGlzIHZhcmlhYmxlIHNob3dzIHdoYXQgeW91IGd1ZXNzZWQsIGFuZCB3aGF0IGlzIGxlZnQgZXZlcnkgdGltZSB5b3UgZ3Vlc3MKCiAgICB3aGlsZSBndWVzc2VkID09IDA6ICAjIENvZGUgcmVwZWF0cyB1bnRpbCB3b3JkIGlzIGd1ZXNzZWQKCiAgICAgICAgcHJpbnQod29yZGd1ZXNzam9pbikgICMgUHJpbnRzIGEgc2VwZXJhdG9yIHRvIG9yZ2FuaXNlIGVhY2ggYXR0ZW1wdAogICAgICAgIGxldHRlciA9IGlucHV0KCdMZXR0ZXI6ICcpLmxvd2VyKCkgICMgSW5wdXRzIHRoZSBsZXR0ZXIgdGhhdCB5b3UgY2hvb3NlIGFuZCBtYWtlcyBpdCBsb3dlcmNhc2UKCiAgICAgICAgaWYgbGV0dGVyID09ICdleGl0JzogICMgSWYgYSB1c2VyIHB1dHMgZXhpdAogICAgICAgICAgICBleGl0KCkgICMgRXhpdCB0aGUgcHJvZ3JhbQoKICAgICAgICBpZiBsZXR0ZXIgPT0gJ25ldyc6ICAjIElmIGEgdXNlciBwdXRzIG5ldwogICAgICAgICAgICBwcmludCh3b3JkX3BpYykgICMgUHJpbnQgdGhlIHdvcmQKICAgICAgICAgICAgZ3Vlc3NlZCA9IDEgICMgU2V0IGd1ZXNzZWQgdG8gMQogICAgICAgICAgICBicmVhayAgIyBCcmVhayB0aGUgcHJvZ3JhbQoKICAgICAgICBpZiBsZXR0ZXIgbm90IGluIHZhbGlkX3N0cmluZyBhbmQgdmFsaWRtb2RlICE9ICdvJzogICMgSWYgdGhlIGxldHRlciBpcyBub3QgYSB2YWxpZCBzdHJpbmcKICAgICAgICAgICAgcHJpbnQoJ1BsZWFzZSBlbnRlciBhIHZhbGlkIHN0cmluZycpICAjIFRlbGwgdGhlIHVzZXIgdG8gaW5wdXQgYSB2YWxpZCBzdHJpbmcKICAgICAgICAgICAgcHJpbnQoJycuam9pbih3b3JkcHJpbnQpKSAgIyBDb21iaW5lcyB3aGF0IHlvdSBndWVzcyBhbmQgd2hhdCBpcyBsZWZ0IHRvIGd1ZXNzLCBhbmQgcHJpbnRzIGl0CiAgICAgICAgICAgIGNvbnRpbnVlICAjIFNraXBzIHRoZSByZXN0IG9mIHRoZSBsb29wCgogICAgICAgIGlmIGxldHRlciBpbiB1c2VkbGV0dGVyczogICMgSWYgdGhlIGxldHRlciBpcyBhbHJlYWR5IHVzZWQKICAgICAgICAgICAgcHJpbnQoJ0xldHRlciBVc2VkJykgICMgU2VuZHMgYSBtZXNzYWdlIHRoYXQgdGhlIGxldHRlciBpcyB1c2VkCiAgICAgICAgICAgIHByaW50KCcnLmpvaW4od29yZHByaW50KSkgICMgQ29tYmluZXMgd2hhdCB5b3UgZ3Vlc3MgYW5kIHdoYXQgaXMgbGVmdCB0byBndWVzcywgYW5kIHByaW50cyBpdAogICAgICAgICAgICBjb250aW51ZSAgIyBTa2lwcyB0aGUgcmVzdCBvZiB0aGUgbG9vcAoKICAgICAgICBlbGlmIGxldHRlciBub3QgaW4gd29yZF9waWMgYW5kIChsZXR0ZXIgaW4gdmFsaWRfc3RyaW5nIG9yIHZhbGlkbW9kZSA9PSAnbycpOiAgIyBJZiB0aGUgbGV0dGVyCiAgICAgICAgICAgICMgaXMgbm90IGluIHRoZSB3b3JkIGFuZCB0aGUgbGV0dGVyIGlzIG5vdCBhIHZhbGlkIHN0cmluZyBvciB2YWxpZG1vZGUgaXMgbwogICAgICAgICAgICB0cmllcyArPSAxICAjIEFkZCAxIHRvIHRoZSB0cmllcyBjb3VudGVyCiAgICAgICAgICAgIHVzZWRsZXR0ZXJzLmFwcGVuZChsZXR0ZXIpICAjIEFkZHMgdGhlIGxldHRlciB0byB0aGUgdXNlZCBsZXR0ZXJzIGxpc3QKICAgICAgICAgICAgcHJpbnQoJ1RyeSBBZ2FpbicpICAjIFNlbmQgYSBtZXNzYWdlIHRvIHRyeSBhZ2FpbiB3aXRoIGEgZGlmZmVyZW50IGxldHRlcgogICAgICAgICAgICBwcmludCgnJy5qb2luKHdvcmRwcmludCkpICAjIENvbWJpbmVzIHdoYXQgeW91IGd1ZXNzIGFuZCB3aGF0IGlzIGxlZnQgdG8gZ3Vlc3MsIGFuZCBwcmludHMgaXQKCiAgICAgICAgZWxpZiBsZXR0ZXIgaW4gd29yZF9waWMgYW5kIGxldHRlciAhPSAnJzogICMgSWYgbGV0dGVyIGlzIGluIHdvcmRwaWMgYW5kIG5vdCBibGFuawogICAgICAgICAgICB0cmllcyArPSAxICAjIEFkZCAxIHRvIHRoZSB0cmllcyBjb3VudGVyCiAgICAgICAgICAgIHdvcmRjb3VudCA9IHdvcmRfcGljLmNvdW50KGxldHRlcikgICMgRmluZCBob3cgbWFueSB0aW1lcyB0aGUgY2hvc2VuIGxldHRlciBpcyBpbiB0aGUgd29yZAogICAgICAgICAgICBwcmludCgnezB9IGlzIGluIHRoZSB3b3JkIHsxfSB0aW1lcyEnLmZvcm1hdChsZXR0ZXIsIHdvcmRjb3VudCkpICAjIFByaW50cyB0aGUgbGV0dGVyCiAgICAgICAgICAgICMgYW5kIG51bWJlciBvZiB0aW1lcyBpcyBpbiB0aGUgd29yZAogICAgICAgICAgICB1c2VkbGV0dGVycy5hcHBlbmQobGV0dGVyKSAgIyBBZGRzIHRoZSBsZXR0ZXIgdG8gdGhlIHVzZWQgbGV0dGVycyBsaXN0CiAgICAgICAgICAgIGxldHRlcmxvY2F0aW9uID0gd29yZF9waWMuZmluZChsZXR0ZXIpICAjIEZpbmQgd2hlcmUgdGhlIGxldHRlciBpcyBpbiB0aGUgd29yZAogICAgICAgICAgICBhbGxfbWF0Y2ggPSBUcnVlICAjIFNldHMgYWxsX21hdGNoIHRvIFRydWUsIHNvIHRoZSBwbGF5ZXIgbWF0Y2hlcyBhbGwgb2YgdGhlIGxldHRlcnMsIGhlIHdpbnMKICAgICAgICAgICAgd29yZHByaW50ID0gW10gICMgQ2xlYXJzIHRoZSB3b3JkcHJpbnQgbGlzdAoKICAgICAgICAgICAgZm9yIGkgaW4gcmFuZ2UoMCwgbGVuKHdvcmRfcGljKSk6ICAjIFJlcGVhdHMgdGhpcyBmb3IgdGhlIGxlbmd0aCBvZiB0aGUgd29yZAoKICAgICAgICAgICAgICAgIGlmIHdvcmRfcGljW2ldIGluIHVzZWRsZXR0ZXJzOiAgIyBJZiB0aGUgc3BsaXQgY2hhcmFjdGVyIGlzIGFscmVhZHkgZ3Vlc3NlZAogICAgICAgICAgICAgICAgICAgIHByaW50KHdvcmRfcGljW2ldLCBlbmQ9JycpICAjIFByaW50IHRoZSBzcGxpdCBjaGFyYWN0ZXIKICAgICAgICAgICAgICAgICAgICB3b3JkcHJpbnQuYXBwZW5kKHdvcmRfcGljW2ldKSAgIyBBZGQgdGhlIHNwbGl0IGNoYXJhY3RlciB0byB3b3JkcHJpbnQsIHNvIGl0IGlzIHNob3duCiAgICAgICAgICAgICAgICAgICAgIyBpbiBmdXR1cmUgZ3Vlc3NlcwoKICAgICAgICAgICAgICAgIGVsc2U6ICAjIElmIHRoZSBzcGxpdCBjaGFyYWN0ZXIgaXMgbm90IGluIHVzZWQgbGV0dGVycwogICAgICAgICAgICAgICAgICAgIGFsbF9tYXRjaCA9IEZhbHNlICAjIFNldCBhbGxfbWF0Y2ggdG8gZmFsc2UKICAgICAgICAgICAgICAgICAgICBwcmludCgnLScsIGVuZD0nJykgICMgUHJpbnQgYSBwbGFjZWhvbGRlciBkYXNoCiAgICAgICAgICAgICAgICAgICAgd29yZHByaW50LmFwcGVuZCgnLScpICAjIEFkZCB0aGUgc3BsaXQgY2hhcmFjdGVyIHRvIHdvcmRwcmludCwgc28gaXQgaXMgc2hvd24KICAgICAgICAgICAgICAgICAgICAjIGluIGZ1dHVyZSBndWVzc2VzCgogICAgICAgICAgICBwcmludCgnJykgICMgUHJpbnRzIGEgbmV3IGxpbmUKICAgICAgICAgICAgaWYgYWxsX21hdGNoOiAgIyBJZiBhbGwgb2YgdGhlIGNoYXJhY3RlcnMgbWF0Y2gKICAgICAgICAgICAgICAgIHByaW50KCdZb3Ugd29uIGluIHswfSB0cmllcyEnLmZvcm1hdCh0cmllcykpICAjIFRlbGxzIHRoZSB1c2VyIHRoYXQgdGhleSB3b24gd2l0aCB0aGUKICAgICAgICAgICAgICAgIGd1ZXNzZWQgPSAxICAjIFNldHMgZ3Vlc3NlZCB0byAxCgogICAgICAgIGlmIGd1ZXNzZWQgPT0gMTogICMgSWYgZ3Vlc3NlZCBpcyAxCiAgICAgICAgICAgIGdtZSA9IDAgICMgU2V0IGdtZSB0byAwCiAgICAgICAgICAgIHdoaWxlIGdtZSA9PSAwOiAgIyBXaGlsZSBnbWUgaXMgMAogICAgICAgICAgICAgICAgbmV3Z2FtZSA9IGlucHV0KCdOZXcgR2FtZT9beS9uXTogJykubG93ZXIoKSAgIyBBc2sgdGhlIHVzZXIgaWYgdGhleSB3YW50IHRvIHBsYXkgYSBuZXcgZ2FtZQogICAgICAgICAgICAgICAgaWYgbmV3Z2FtZSBpbiBbJ3knLCAneWVzJ106ICAjIElmIHRoZXkgc2F5IHkgb3IgeWVzCiAgICAgICAgICAgICAgICAgICAgZ21lID0gMSAgIyBTZXQgZ21lIHRvIDEKICAgICAgICAgICAgICAgICAgICBydW4gPSAwICAjIFNldCBydW4gdG8gMAogICAgICAgICAgICAgICAgZWxpZiBuZXdnYW1lIGluIFsnbicsICdubyddOiAgIyBJZiB0aGV5IHNheSBuIG9yIG5vCiAgICAgICAgICAgICAgICAgICAgZ21lID0gMSAgIyBTZXQgZ21lIHRvIDEKICAgICAgICAgICAgICAgICAgICBydW4gPSAxICAjIFNldCBydW4gdG8gMAogICAgICAgICAgICAgICAgZWxzZTogICMgSWYgdGhlIGlucHV0IGlzIG5vdCB5LCB5ZXMsIG4sIG9yIG5vCiAgICAgICAgICAgICAgICAgICAgcHJpbnQoJ1RyeSBBZ2FpbicpICAjIFRlbGxzIHRoZSB1c2VyIHRvIHRyeSBhZ2FpbgogICAgICAgICAgICAgICAgICAgIGdtZSA9IDAgICMgU2V0IGdtZSB0byAw"},"asBuffer":null},"loaded":true}}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
# Created By Mosrod (Nathan R)
# (C) 2019 Nathan R, [ALL RIGHTS RESERVED]

# WIP SET/APPEND WORDLIST
# CONTAINS BROKEN

import random  # Imports random module for choosing a random word
import sys  # Imports sys module for loading
import os  # Imports os module for testing if a file exists

wordlistpath = 'englishwordslowercase.txt'

if os.path.isfile(wordlistpath):  # If wordlistpath is a file
    with open(wordlistpath, 'r') as f:  # Open text file that stores the words
        wordlist = [line.strip() for line in f]  # Add every line of the file to a list
else:
    print('Wordlist Not Found')  # Tell the user that the wordlist is not found


if not os.path.isfile('hangmanpresets.txt'):  # If hangmanpresets.txt is not a file
    with open('hangmanpresets.txt', 'w+') as f:  # Create hangmanpresets.txt
        pass

with open('hangmanpresets.txt', 'r') as f:  # Open text file with presets
    presets = [line.strip() for line in f]  # Add every line of the file to a list


print("""
COMMANDS:
1 : Exits the program
2 : Generates a new word
PRESET:
1 : Use a preset in hangmanpresets.txt
OPTIONS:
1 : Allow words to have periods
2 : Allow words to have numbers
3 : Allow words to have spaces
4 : Turn the vowel required to false
5 : Turn on notifications if a word in a wordlist fails a check
6 : Set the most repeating characters in a word
7 : Set the most total repeating characters in a word
8 : Set/append/turn off strings allowed in words
9 : Set the length
10 : Set the min length
11 : Set the max length
12 : Make the first letter of the word equal to the set letter
13 : Set the word list
14 : Make sure all words contain the letters specified
""")  # Informs the user about what the options do

# [a,d,g,h,i,j,k,m,q,u,z]

print("""
COMMANDS:
1 : Exit
2 : New
PRESETS:
1 : Use Preset (ON) [-o(name)]
OPTIONS:
1 : Periods (ON) [-p]
2 : Numbers (ON) [-n]
3 : Spaces (ON) [-s]
4 : Vowels Required (OFF) [-v]
5 : WordList Notifications (ON) [-y]
6 : Max Repeating Characters (SET) [-r(num)] {4}
7 : Max Total Repeating Characters (SET) [-t(num)] {10}
8 : Valid Strings (OFF/SET/APPEND) [-x(o)] [-x({s/a}[string,string)]
9 : Length (SET) [-l(num)] {0}
10 : Min Length (SET) [-b(num)] {3}
11 : Max Length (SET) [-e(num)] {15}
12 : First Letter (SET) [-f(letter)]
13 : Word List (SET) [-w([word,word])] [-w[#filename.txt])
14 : Contains (SET) [-c([letter,letter])]
""")  # Informs the user about the options


options = input('Options: ').lower()  # Takes options from the user

presetname = ''  # Sets presetname to an empty string
if options != '':  # If options is not empty
    presetname = input('Preset: ').lower()  # Set user input to the preset name

repeat = 4  # Sets repeat to 4
repeat_total = 10  # Sets repeat_total to 10
length = 0  # Sets length to 0
beginning = 3  # Sets beginning to 3
ending = 15  # Sets ending to 15

optionslist = options.split('-')  # Split options by '-'
optionslist = optionslist[1:]  # Remove the first value from optionslist

for i in range(0, len(optionslist)):  # Repeat for the length of optionslist
    optionslist[i] = '-' + optionslist[i]  # Add a - before every value in the list

presettrue = 1
for r in range(0, len(presets)):  # Repeat for the length of presets
    preset = presets[r]  # Set preset to the preset in line r
    vbar = preset.find('|')  # Find a pipe in preset
    namepreset = preset[:vbar]  # Split preset to before the bar and set namepreset to it

    if presetname == namepreset:  # If the presetname is namepreset
        print('Preset Name Already Exists')  # Tell the suer that the preset name already exists
        presettrue = 0  # Set presettrue to 0

if presetname != '' and presettrue == 1:  # If the presetname is not empty and presettrue is 1
    with open('hangmanpresets.txt', 'a') as f:  # Open the presets file as append mode
        f.write('{}|{}\n'.format(presetname, options))  # Write the preset name and code to a newline

optionlistlen = len(optionslist)  # Set optionlistlen to the length of optionslist
optionlistjoin = ''.join(optionslist)  # Join the list with no seperator

presetnamecheck = 0  # Set presetnamecheck to 0

while '-o' in optionlistjoin:  # While -o is in optionlistjoin
    optionlistjoin = ''.join(optionslist)  # Join the list with no seperator
    optionslist = optionlistjoin.split('-')  # Split the list with a - seperator
    optionslist = optionslist[1:]  # Remove the first string in the optionslist

    for i in range(0, len(optionslist)):  # For the length of optionslist
        option = optionslist[i]  # Set option to the ith value of optionslist
        if option[0] != '-':  # If the first character of option is not a dash
            optionslist[i] = '-' + optionslist[i]  # Add a dash before option

    for i in range(0, len(optionslist)):  # For the length of optionslist
        option = optionslist[i]  # Set option to the ith value of optionslist

        if '-o' in option:  # If -o is in option
            option = option[2:]  # Remove the first two characters

            for r in range(0, len(presets)):  # Repeat for the length of presets
                preset = presets[r]  # Set preset to the preset in line r
                vbar = preset.find('|')  # Find a pipe in preset
                namepreset = preset[:vbar]  # Split preset to before the bar and set namepreset to it

                if namepreset == option:  # If the chosen preset name matches the one found
                    optionpreset = preset[vbar + 1:]  # Split preset to after the bar and set optionpreset to it
                    optionsnew = optionpreset.split('-')  # Split optionpreset by a -
                    optionsnew = optionsnew[1:]  # Remove the first character from optionsnew
                    optionfind = '-o{}'.format(namepreset)  # Set optionfind to -o(preset name)
                    optionslist.pop(i)  # Remove -o from the list

                    for d in range(0, len(optionsnew)):  # For the length of optionsnew
                        optionnew = optionsnew[d]  # Set optionnew to the d part of optionsnew

                        if optionnew[0] != '-':  # If the first character of optionnew is not a dash
                            optionnew = '-' + optionnew  # Add a dash before optionnew

                        optionslist.insert(i+d, optionnew)  # Insert optionnew to the optionslist after the previous
                    presetnamecheck = 1  # Set presetnamecheck to 1

            if presetnamecheck == 0:  # If presetnamecheck is 0
                print('Preset not found')  # Tell the user that the preset has not been found
                optionslist = ''  # Set optionslist to an empty string

options = optionlistjoin  # Set options to optionlistjoin

containslist = ''  # Set containlist to an empty string

firstletter = ''  # Set firstletter to an empty string

validmode = ''    # Set validmode to an empty string

validslist = ''  # Set validslist to an empty string

if '-w' in options:
    wordlistall = []  # Set wordlistall to an empty list
else:
    wordlistall = wordlist  # Set wordlistall to wordlist


for i in range(0, len(optionslist)):
    if '-l' in optionslist[i]:  # If the value of optionslist has '-l' in it
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        optionsnum = optionpick[2:]  # Remove the first-second values from optionpick
        number = int(optionsnum)  # Set number to integer optionsnum
        beginning = number  # Set beginning to number
        ending = number  # Set ending to number

    elif '-b' in optionslist[i] and '-l' not in optionslist[i]:  # If the value of optionslist
        #  has '-' in it and does not contain '-l'
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        optionsnum = optionpick[2:]  # Remove the first-second values from optionpick
        number = int(optionsnum)  # Set number to integer optionsnum
        beginning = number  # Set beginning to number

    elif '-e' in optionslist[i] and '-l' not in optionslist[i]:  # If the value of optionslist
        #  has '-b' in it and does not contain '-l'
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        optionsnum = optionpick[2:]  # Remove the first-second values from optionpick
        number = int(optionsnum)  # Set number to integer optionsnum
        ending = number  # Set ending to number

    elif '-r' in optionslist[i]:  # If the value of optionslist has -r in it
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        optionsnum = optionpick[2:]  # Remove the first-second values from optionpick
        number = int(optionsnum)  # Set number to integer optionsnum
        repeat = number  # Set repeat to number

    elif '-t' in optionslist[i]:  # If the value of optionslist has -t in it
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        optionsnum = optionpick[2]  # Remove the first-second values from optionspick
        number = int(optionsnum)  # Set number to integer optionsnum
        repeat_total = number  # Set repeat_total to number

    elif '-x' in optionslist[i]:  # If the value of optionslist has -x in it
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        validmode = optionpick[2]  # Remove the first-second values from optionpick
        validlist = optionpick[4:-1]  # Slice the list of characters from optionpick
        validslist = validlist.split(',')  # Create a list from validlist

    elif '-f' in optionslist[i]:  # If the value of optionslist has -f in it
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        optionsnum = optionpick[2:]  # Remove the first-second values from optionpick
        letter = optionsnum  # Set letter to integer optionsnum
        firstletter = letter  # Set repeat_total to letter

    elif '-w' in optionslist[i]:  # If the value of optionslist has -w in it
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        words = optionpick[3:-1]  # Remove the first-third and last value from optionpick

        if words[0] == '#':  # If the first character is a hashtag
            filename = words[1:]  # Remove the first character from words and set that to filename

            if os.path.isfile(filename):  # If the filename specified is a real file
                with open(filename, 'r') as f:  # Open text file that stores the words
                    wordlist = [line.strip() for line in f]  # Add every line of the file to a list

            else:  # If the filename specified is not a real file
                print('File Does Not Exist')  # Tell the user that the file does not exist

        else:  # If the first character is not a hashtag
            wordslist = words.split(',')  # Split words by ,
            wordlist = wordslist  # Set wordlist to wordslist

        for r in range(0, len(wordlist)):  # Repeat for the length of wordlist
            wordlistall.append(wordlist[r])  # Append the word to wordlistall

    elif '-c' in optionslist[i]:  # If the value of optionslist has -w in it
        optionpick = optionslist[i]  # Set optionpick to the value of optionslist
        contain = optionpick[3:-1]  # Remove the first value from optionspick
        containlist = contain.split(',')  # Split contain by ,
        containslist = containlist  # Set containslist to containlist

wordlist = wordlistall  # Sets wordlist to wordlistall

optionslistjoin = ','.join(optionslist)  # Join optionslist by , and set it to optionslistjoin

lengthlist = []  # Creates a list for putting the words that are the same length as requested
customlist = []  # Creates a list for putting the words that fit between beginning and ending
truelist = []  # Creates a list for true words

wordlistadd = 0  # Set wordlistadd to 0
wordlistaddround = 0  # Set wordlistaddround to 0
wordlistcount = 0  # Set wordlistcount to 0

vowels = ['a', 'e', 'i', 'o', 'u', 'y']  # List of vowels to check in a word

valid_string = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r',
                's', 't', 'u', 'v', 'w', 'x', 'y', 'z']  # List of valid string



if '-n' in options:  # If the user enabled numbers
    valid_string.append(['1', '2', '3', '4', '5', '6', '7', '8', '9', '0'])  # Allow numbers

if '-p' in options:  # If the user enabled periods
    valid_string.append('.')  # Allow periods

if '-s' in options:  # If the user enabled spaces
    valid_string.append(' ')  # Allow spaces

if '-x' in options:  # If the user configured valid strings
    if validmode == 'a':  # If the validmode is a
        valid_string = valid_string + validslist
    elif validmode == 's':
        valid_string = validslist
    else:
        print('Invalid Mode')


for i in range(0, len(wordlist)):  # Repeats this until at the end of wordlist
    testsfailed = []  # List of tests failed

    word = wordlist[i]  # Splits the wordlist to i, and assigns it to word
    word = word.lower()  # Makes the word lowercase

    if i > wordlistaddround-1 and 10-wordlistcount != 0:  # If i is greater than the value needed to
        # replace a - with a + and 10-the amount of = is not 0
        wordlistcount += 1  # Add 1 to wordlistcount
        plus = '+'*wordlistcount  # Times + by the amount of times the if statement ran
        minus = '-'*(10-wordlistcount)  # Times - by 10 minus the amount of plus's
        loading = plus + minus  # Combine both plus and minus strings
        sys.stdout.write("\r[{}]".format(loading))  # Notify the user of progress
        sys.stdout.flush()  # Flush the buffer
        wordlistadd += len(wordlist)/10  # Add the length of wordlist/10 to wordlistadd
        wordlistaddround = round(wordlistadd)  # Set wordlistaddround to wordlistadd rounded

    trueword = 0  # Set trueword to 0

    for r in range(0, len(vowels)):  # Loop for the length of the vowels list

        if vowels[r] in word and '-v' not in options:  # If the vowel is not in the word
            trueword = 1  # Set trueword to 1
            break  # Break out of the for loop

    if trueword == 0:  # If trueword is 0
        testsfailed.append('vowels')  # Append vowels to the testsfailed list

    if '-n' not in str(options):  # If numbers are off

        for r in range(len(word)):  # For the length of the word

            if word[r] in '1234567890':  # See if the string is a number
                trueword = 0  # Set trueword to 0
                testsfailed.append('numbers')  # Append numbers to the testsfailed list
                break  # Break out of the for loop

    if len(word) < beginning or len(word) > ending:  # If the word is less than beginning or greator than ending
        trueword = 0  # Set trueword to 0
        testsfailed.append('length')   # Append length to the testsfailed list

    if '-f' in options and word[0] != firstletter:  # If -f is in options and If the first character of the
        # word is not equal to firstletter
        trueword = 0  # Set trueword to 0
        testsfailed.append('firstletter')  # Append firstletter to the testsfailed list

    truecontains = 0  # Set truecontains to 0

    if '-c' in options:  # If the user configured contains

        for r in range(0, len(word)):  # For the length of word

            if word[r] in containslist:  # If word[r] is in containslist
                truecontains = 1  # Set truecontains to 1

        if truecontains == 0:  # If truecontains is 0
            trueword = 0  # Set trueword to 0
            testsfailed.append('configured')  # Append configured to the testsfailed list

    if validmode != 'o':  # If validmode is not o
        for r in range(0, len(word)):  # For the length of word
            if word[r] not in valid_string:  # If the character is not in the valid_string list
                trueword = 0  # Set trueword to 0
                testsfailed.append('valid string')  # Append valid string to the testsfailed list

    if trueword == 0:  # If trueword is 0
        if '-y' in optionslistjoin:  # If -y is in optionlistjoin
            print('')  # Print a newline
            print('NOTICE: {} has failed {} check(s)'.format(word, testsfailed))  # Tell the user that
            # the word has failed a check
        continue  # Skip the rest of the loop

    if '.' in word and '-p' not in str(options):  # If a dot is in the word and the periods option is turned off

        for r in range(0, word.count('.')):  # Repeat for the amount of periods in the word
            upper = word[0:word.find('.')]  # Split the word before the period
            lower = word[word.find('.') + 1:]  # Split the word after the period
            word = upper + lower  # Combine the upper and lower parts

    if ' ' in word and '-s' not in str(options):  # If a space is in the word and the space option is turned off
        for r in range(0, word.count(' ')):  # Repeat for the amount of spaces in the word
            upper = word[0:word.find(' ')]  # Split the word before the space
            lower = word[word.find(' ') + 1:]  # Split the word after the space
            word = upper + lower  # Combine the upper and lower parts

    wordchar = []  # Creates a list called wordchar

    for r in range(0, len(word)):  # Loop for the length of the word
        partlist = word[r]  # Splits word into letter

        if r+repeat > len(word):  # If the section it is cutting out involves characters
            # after the end of the word
            break  # Ends the loop

        reptest = word[r:r+repeat]  # Splits word from r to r + repeat
        replist = []  # Creates a list called replist

        for t in range(0, len(reptest)):  # Loop for the length of reptest
            replist.append(reptest[t])  # Split reptest into a character and then append it

        replistlen = len(replist)  # Set replistlen to the length of replist
        repset = set(replist)  # Creates a set from replist
        repsetlen = len(repset)  # Set repsetlen to the length of repset

        if (replistlen - repsetlen) + 1 >= repeat:  # If the difference between replistlen and repsetlen
            trueword = 0  # Sets trueword to 0
            testsfailed.append('repeat')  # Append repeat to the testsfailed list

        wordchar.append(word[r])  # Adds the character to the wordchar list

    lettersdone = []  # Creates a list called lettersdone

    for r in range(0, len(wordchar)):  # Loop for the length of wordchar

        if wordchar[r] not in lettersdone:  # If the character is not in lettersdone
            wordcharduplicate = wordchar.count(wordchar[r])  # Count how many of the characters are in the word
            lettersdone.append(wordchar[r])  # Append the character to lettersdone

            if wordcharduplicate >= repeat_total:  # If the character count is greator than repeat_total
                trueword = 0  # Set trueword to 0
                testsfailed.append('repeat total')  # Append repeat total to the testsfailed list

    if trueword == 0:  # If trueword is 0
        if '-y' in optionslistjoin:  # If -y is in optionlistjoin
            print('')  # Print a newline
            print('NOTICE: {} has failed {} check(s)'.format(word, testsfailed))  # Tell the user that
            # the word has failed a check

    if int(beginning) <= len(str(word)) <= int(ending) and trueword == 1:  # If the length of the word is between the
        # beginning and ending
        customlist.append(word)  # Append the word to customlist


sys.stdout.write("\rPROCESSING DATA COMPLETE")  # Notifies the user that the data processing is complete
sys.stdout.flush()  # Flush the buffer

chooselist = []  # Create a list for picking random words out of it

print('')  # Print a new line

if '-b' in options or '-e' in options or '-l' in options:  # If beginning, end, or length customized
    chooselist = customlist  # Set chooselist equal to customlist

else:  # If the length is 0 or less
    chooselist = customlist  # Set chooselist equal to customlist

if len(chooselist) == 0:  # If the list has no words
    print('No Words Avaliable')  # Tell the user that there is no words avaliable
    exit()  # Exit the program

run = 0  # Set run to 0

usednums = []  # Set usednums to an empty list

word_pic = ''  # Set word_pic to an empty string

wordrange = range(0, len(chooselist))  # Set wordrange to a range from 0 to the length of chooselist

wordrange = list(wordrange)  # Convert wordrange to a list


while run == 0:  # While run is 0

    if not wordrange:  # If wordrange is empty
        print('All Words Used')  # Tell the user that all words are used
        run = 1  # Set run to 1
        break  # Break out of the while loop

    word_ran = random.choice(wordrange)  # Picks a random number based on the file length

    wordrange.pop(wordrange.index(word_ran))  # Remove the number from the wordrange list

    word_pic = chooselist[word_ran]  # Slices the list to the random number, thus getting a random word

    guessed = 0  # Setting the variable, that ends the while loop when the word is guessed

    usedletters = []  # Creates a list to store letters that are used, so the tries don't go up

    word_pic_mod = '-' * (len(word_pic))  # Used to display guesses, and as a seperator

    word_pic_list = list(word_pic_mod)  # Converts every character of word_pic_mod to a list

    wordguessjoin = ''.join(word_pic_list)  # Used as a seperator between guesses

    if ' ' in word_pic and '-s' in options:  # If a space is in word_pic and spaces is turned on
        usedletters.append(' ')  # Append a space to usedletters
        for i in range(0, word_pic.count(' ')):  # Repeat for how many spaces in the word chosen
            emptyindex = word_pic.find(' ')  # Set emptyindex to the index of the first instance of a space found
            word_pic_list[emptyindex] = ' '  # Change the dash to a space in word_pic_list

    if '-s' in options:  # If -s is in options
        valid_string.pop(valid_string.index(' '))  # Remove space from the valid_string list

    tries = 0  # Set the amount of tries to 0

    wordprint = word_pic_list  # This variable shows what you guessed, and what is left every time you guess

    while guessed == 0:  # Code repeats until word is guessed

        print(wordguessjoin)  # Prints a seperator to organise each attempt
        letter = input('Letter: ').lower()  # Inputs the letter that you choose and makes it lowercase

        if letter == 'exit':  # If a user puts exit
            exit()  # Exit the program

        if letter == 'new':  # If a user puts new
            print(word_pic)  # Print the word
            guessed = 1  # Set guessed to 1
            break  # Break the program

        if letter not in valid_string and validmode != 'o':  # If the letter is not a valid string
            print('Please enter a valid string')  # Tell the user to input a valid string
            print(''.join(wordprint))  # Combines what you guess and what is left to guess, and prints it
            continue  # Skips the rest of the loop

        if letter in usedletters:  # If the letter is already used
            print('Letter Used')  # Sends a message that the letter is used
            print(''.join(wordprint))  # Combines what you guess and what is left to guess, and prints it
            continue  # Skips the rest of the loop

        elif letter not in word_pic and (letter in valid_string or validmode == 'o'):  # If the letter
            # is not in the word and the letter is not a valid string or validmode is o
            tries += 1  # Add 1 to the tries counter
            usedletters.append(letter)  # Adds the letter to the used letters list
            print('Try Again')  # Send a message to try again with a different letter
            print(''.join(wordprint))  # Combines what you guess and what is left to guess, and prints it

        elif letter in word_pic and letter != '':  # If letter is in wordpic and not blank
            tries += 1  # Add 1 to the tries counter
            wordcount = word_pic.count(letter)  # Find how many times the chosen letter is in the word
            print('{0} is in the word {1} times!'.format(letter, wordcount))  # Prints the letter
            # and number of times is in the word
            usedletters.append(letter)  # Adds the letter to the used letters list
            letterlocation = word_pic.find(letter)  # Find where the letter is in the word
            all_match = True  # Sets all_match to True, so the player matches all of the letters, he wins
            wordprint = []  # Clears the wordprint list

            for i in range(0, len(word_pic)):  # Repeats this for the length of the word

                if word_pic[i] in usedletters:  # If the split character is already guessed
                    print(word_pic[i], end='')  # Print the split character
                    wordprint.append(word_pic[i])  # Add the split character to wordprint, so it is shown
                    # in future guesses

                else:  # If the split character is not in used letters
                    all_match = False  # Set all_match to false
                    print('-', end='')  # Print a placeholder dash
                    wordprint.append('-')  # Add the split character to wordprint, so it is shown
                    # in future guesses

            print('')  # Prints a new line
            if all_match:  # If all of the characters match
                print('You won in {0} tries!'.format(tries))  # Tells the user that they won with the
                guessed = 1  # Sets guessed to 1

        if guessed == 1:  # If guessed is 1
            gme = 0  # Set gme to 0
            while gme == 0:  # While gme is 0
                newgame = input('New Game?[y/n]: ').lower()  # Ask the user if they want to play a new game
                if newgame in ['y', 'yes']:  # If they say y or yes
                    gme = 1  # Set gme to 1
                    run = 0  # Set run to 0
                elif newgame in ['n', 'no']:  # If they say n or no
                    gme = 1  # Set gme to 1
                    run = 1  # Set run to 0
                else:  # If the input is not y, yes, n, or no
                    print('Try Again')  # Tells the user to try again
                    gme = 0  # Set gme to 0