aW1wb3J0IFJlYWN0LCB7IHVzZUVmZmVjdCwgdXNlTWVtbywgdXNlUmVmLCB1c2VTdGF0ZSB9IGZyb20gJnF1b3Q7cmVhY3QmcXVvdDs7IGltcG9ydCB7IG1vdGlvbiwgQW5pbWF0ZVByZXNlbmNlIH0gZnJvbSAmcXVvdDtmcmFtZXItbW90aW9uJnF1b3Q7OyBpbXBvcnQgeyBTaHVmZmxlLCBUcm9waHksIFNwYXJrbGVzLCBWb2x1bWUyLCBWb2x1bWVYLCBGbGFtZSwgU2hpZWxkLCBTdGFyLCBSZXBlYXQyLCBHaWZ0LCBXYW5kMiwgTG9jaywgU2hhcmUyLCBIZWFydCwgSGlzdG9yeSwgQmFkZ2VJbmZvLCBNZWdhcGhvbmUsIH0gZnJvbSAmcXVvdDtsdWNpZGUtcmVhY3QmcXVvdDs7Cgpjb25zdCBDTFVCUyA9IFsgeyBpZDogJnF1b3Q7bWNpJnF1b3Q7LCBuYW1lOiAmcXVvdDtNYW5jaGVzdGVyIENpdHkmcXVvdDssIHR5cGU6ICZxdW90O2NsdWImcXVvdDssIGxlYWd1ZTogJnF1b3Q7UHJlbWllciBMZWFndWUmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogOTUsIGxvZ286ICZxdW90O/CflLUmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1za3ktNTAwIHRvLWJsdWUtNzAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2xpdiZxdW90OywgbmFtZTogJnF1b3Q7TGl2ZXJwb29sJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O1ByZW1pZXIgTGVhZ3VlJnF1b3Q7LCByZWdpb246ICZxdW90O0V1cm9wZSZxdW90Oywgc3RyZW5ndGg6IDkyLCBsb2dvOiAmcXVvdDvwn5S0JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tcmVkLTUwMCB0by1yb3NlLTcwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDthcnMmcXVvdDssIG5hbWU6ICZxdW90O0Fyc2VuYWwmcXVvdDssIHR5cGU6ICZxdW90O2NsdWImcXVvdDssIGxlYWd1ZTogJnF1b3Q7UHJlbWllciBMZWFndWUmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogOTAsIGxvZ286ICZxdW90O/CflLQmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1yb3NlLTUwMCB0by1vcmFuZ2UtNjAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O3JtYSZxdW90OywgbmFtZTogJnF1b3Q7UmVhbCBNYWRyaWQmcXVvdDssIHR5cGU6ICZxdW90O2NsdWImcXVvdDssIGxlYWd1ZTogJnF1b3Q7TGEgTGlnYSZxdW90OywgcmVnaW9uOiAmcXVvdDtFdXJvcGUmcXVvdDssIHN0cmVuZ3RoOiA5NiwgbG9nbzogJnF1b3Q78J+RkSZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXppbmMtMTAwIHRvLXppbmMtNDAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2JhciZxdW90OywgbmFtZTogJnF1b3Q7RkMgQmFyY2Vsb25hJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O0xhIExpZ2EmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogOTQsIGxvZ286ICZxdW90O/CflLUmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1ibHVlLTYwMCB0by1yZWQtNjAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2F0bSZxdW90OywgbmFtZTogJnF1b3Q7QXRsJmVhY3V0ZTt0aWNvIE1hZHJpZCZxdW90OywgdHlwZTogJnF1b3Q7Y2x1YiZxdW90OywgbGVhZ3VlOiAmcXVvdDtMYSBMaWdhJnF1b3Q7LCByZWdpb246ICZxdW90O0V1cm9wZSZxdW90Oywgc3RyZW5ndGg6IDg5LCBsb2dvOiAmcXVvdDvimqomcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1yZWQtNzAwIHRvLXNsYXRlLTkwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtqdXYmcXVvdDssIG5hbWU6ICZxdW90O0p1dmVudHVzJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O1NlcmllIEEmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogODgsIGxvZ286ICZxdW90O+KaqyZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXNsYXRlLTkwMCB0by1zbGF0ZS03MDAmcXVvdDsgfSwgeyBpZDogJnF1b3Q7bWlsJnF1b3Q7LCBuYW1lOiAmcXVvdDtBQyBNaWxhbiZxdW90OywgdHlwZTogJnF1b3Q7Y2x1YiZxdW90OywgbGVhZ3VlOiAmcXVvdDtTZXJpZSBBJnF1b3Q7LCByZWdpb246ICZxdW90O0V1cm9wZSZxdW90Oywgc3RyZW5ndGg6IDg5LCBsb2dvOiAmcXVvdDvwn5S0JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tcmVkLTYwMCB0by1ibGFjayZxdW90OyB9LCB7IGlkOiAmcXVvdDtpbnQmcXVvdDssIG5hbWU6ICZxdW90O0ludGVyJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O1NlcmllIEEmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogOTEsIGxvZ286ICZxdW90O/CflLUmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1za3ktNzAwIHRvLWJsYWNrJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2J2YiZxdW90OywgbmFtZTogJnF1b3Q7Qm9ydXNzaWEgRG9ydG11bmQmcXVvdDssIHR5cGU6ICZxdW90O2NsdWImcXVvdDssIGxlYWd1ZTogJnF1b3Q7QnVuZGVzbGlnYSZxdW90OywgcmVnaW9uOiAmcXVvdDtFdXJvcGUmcXVvdDssIHN0cmVuZ3RoOiA4NywgbG9nbzogJnF1b3Q78J+foSZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXllbGxvdy00MDAgdG8tYmxhY2smcXVvdDsgfSwgeyBpZDogJnF1b3Q7YmF5JnF1b3Q7LCBuYW1lOiAmcXVvdDtCYXllcm4gTXVuaWNoJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O0J1bmRlc2xpZ2EmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogOTUsIGxvZ286ICZxdW90O/CflLQmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1yZWQtNjAwIHRvLXJvc2UtODAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O3BzZyZxdW90OywgbmFtZTogJnF1b3Q7UFNHJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O0xpZ3VlIDEmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogOTMsIGxvZ286ICZxdW90O/CflLUmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1ibHVlLTgwMCB0by1waW5rLTYwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDttb24mcXVvdDssIG5hbWU6ICZxdW90O01vbmFjbyZxdW90OywgdHlwZTogJnF1b3Q7Y2x1YiZxdW90OywgbGVhZ3VlOiAmcXVvdDtMaWd1ZSAxJnF1b3Q7LCByZWdpb246ICZxdW90O0V1cm9wZSZxdW90Oywgc3RyZW5ndGg6IDg0LCBsb2dvOiAmcXVvdDvwn5S0JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tcmVkLTYwMCB0by13aGl0ZSZxdW90OyB9LCB7IGlkOiAmcXVvdDtwb3ImcXVvdDssIG5hbWU6ICZxdW90O0ZDIFBvcnRvJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O1ByaW1laXJhIExpZ2EmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogODUsIGxvZ286ICZxdW90O/CfkIkmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1ibHVlLTcwMCB0by1za3ktNDAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2FqYSZxdW90OywgbmFtZTogJnF1b3Q7QWpheCZxdW90OywgdHlwZTogJnF1b3Q7Y2x1YiZxdW90OywgbGVhZ3VlOiAmcXVvdDtFcmVkaXZpc2llJnF1b3Q7LCByZWdpb246ICZxdW90O0V1cm9wZSZxdW90Oywgc3RyZW5ndGg6IDgzLCBsb2dvOiAmcXVvdDvirZAmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1yZWQtNTAwIHRvLXdoaXRlJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2FsbiZxdW90OywgbmFtZTogJnF1b3Q7QWwgTmFzc3ImcXVvdDssIHR5cGU6ICZxdW90O2NsdWImcXVvdDssIGxlYWd1ZTogJnF1b3Q7U2F1ZGkgUHJvIExlYWd1ZSZxdW90OywgcmVnaW9uOiAmcXVvdDtBc2lhJnF1b3Q7LCBzdHJlbmd0aDogODQsIGxvZ286ICZxdW90O/Cfn6EmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS15ZWxsb3ctNDAwIHRvLWFtYmVyLTcwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtoaWwmcXVvdDssIG5hbWU6ICZxdW90O0FsIEhpbGFsJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O1NhdWRpIFBybyBMZWFndWUmcXVvdDssIHJlZ2lvbjogJnF1b3Q7QXNpYSZxdW90Oywgc3RyZW5ndGg6IDg2LCBsb2dvOiAmcXVvdDvwn5S3JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tc2t5LTUwMCB0by1ibHVlLTkwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtVbHMmcXVvdDssIG5hbWU6ICZxdW90O1Vsc2FuIEhEJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O0sgTGVhZ3VlJnF1b3Q7LCByZWdpb246ICZxdW90O0FzaWEmcXVvdDssIHN0cmVuZ3RoOiA3OCwgbG9nbzogJnF1b3Q78J+fpiZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLWJsdWUtNTAwIHRvLXNsYXRlLTgwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtiZmMmcXVvdDssIG5hbWU6ICZxdW90O0JlaWppbmcgR3VvYW4mcXVvdDssIHR5cGU6ICZxdW90O2NsdWImcXVvdDssIGxlYWd1ZTogJnF1b3Q7Q2hpbmVzZSBTdXBlciBMZWFndWUmcXVvdDssIHJlZ2lvbjogJnF1b3Q7QXNpYSZxdW90Oywgc3RyZW5ndGg6IDc2LCBsb2dvOiAmcXVvdDvwn5+pJnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tZW1lcmFsZC01MDAgdG8tZ3JlZW4tODAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O3NhbiZxdW90OywgbmFtZTogJnF1b3Q7U2FudG9zJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O0JyYXNpbGVpciZhdGlsZGU7byZxdW90OywgcmVnaW9uOiAmcXVvdDtTb3V0aCBBbWVyaWNhJnF1b3Q7LCBzdHJlbmd0aDogNzksIGxvZ286ICZxdW90O+KaqiZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXdoaXRlIHRvLWJsYWNrJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O3BhbCZxdW90OywgbmFtZTogJnF1b3Q7UGFsbWVpcmFzJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O0JyYXNpbGVpciZhdGlsZGU7byZxdW90OywgcmVnaW9uOiAmcXVvdDtTb3V0aCBBbWVyaWNhJnF1b3Q7LCBzdHJlbmd0aDogODcsIGxvZ286ICZxdW90O/Cfn6ImcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1lbWVyYWxkLTUwMCB0by1ncmVlbi05MDAmcXVvdDsgfSwgeyBpZDogJnF1b3Q7cmlvJnF1b3Q7LCBuYW1lOiAmcXVvdDtSaXZlciBQbGF0ZSZxdW90OywgdHlwZTogJnF1b3Q7Y2x1YiZxdW90OywgbGVhZ3VlOiAmcXVvdDtMaWdhIEFyZ2VudGluYSZxdW90OywgcmVnaW9uOiAmcXVvdDtTb3V0aCBBbWVyaWNhJnF1b3Q7LCBzdHJlbmd0aDogODgsIGxvZ286ICZxdW90O/CflLQmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1yZWQtNjAwIHRvLXdoaXRlJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2JvbyZxdW90OywgbmFtZTogJnF1b3Q7Qm9jYSBKdW5pb3JzJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O0xpZ2EgQXJnZW50aW5hJnF1b3Q7LCByZWdpb246ICZxdW90O1NvdXRoIEFtZXJpY2EmcXVvdDssIHN0cmVuZ3RoOiA4NiwgbG9nbzogJnF1b3Q78J+SmSZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLWJsdWUtNzAwIHRvLXllbGxvdy00MDAmcXVvdDsgfSwgeyBpZDogJnF1b3Q7YWZyMSZxdW90OywgbmFtZTogJnF1b3Q7QWwgQWhseSZxdW90OywgdHlwZTogJnF1b3Q7Y2x1YiZxdW90OywgbGVhZ3VlOiAmcXVvdDtFZ3lwdCBQcmVtaWVyIExlYWd1ZSZxdW90OywgcmVnaW9uOiAmcXVvdDtBZnJpY2EmcXVvdDssIHN0cmVuZ3RoOiA4MCwgbG9nbzogJnF1b3Q78J+fpSZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXJlZC03MDAgdG8tYW1iZXItNzAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2FmcjImcXVvdDssIG5hbWU6ICZxdW90O1d5ZGFkIEFDJnF1b3Q7LCB0eXBlOiAmcXVvdDtjbHViJnF1b3Q7LCBsZWFndWU6ICZxdW90O0JvdG9sYSBQcm8mcXVvdDssIHJlZ2lvbjogJnF1b3Q7QWZyaWNhJnF1b3Q7LCBzdHJlbmd0aDogNzcsIGxvZ286ICZxdW90O+KsmyZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXJlZC04MDAgdG8tYmxhY2smcXVvdDsgfSwgeyBpZDogJnF1b3Q7Z2FsJnF1b3Q7LCBuYW1lOiAmcXVvdDtHYWxhdGFzYXJheSZxdW90OywgdHlwZTogJnF1b3Q7Y2x1YiZxdW90OywgbGVhZ3VlOiAmcXVvdDtTJnV1bWw7cGVyIExpZyZxdW90OywgcmVnaW9uOiAmcXVvdDtFdXJvcGUmcXVvdDssIHN0cmVuZ3RoOiA4NCwgbG9nbzogJnF1b3Q78J+foCZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLW9yYW5nZS01MDAgdG8tcmVkLTcwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtuZXcmcXVvdDssIG5hbWU6ICZxdW90O05ld2Nhc3RsZSBVbml0ZWQmcXVvdDssIHR5cGU6ICZxdW90O2NsdWImcXVvdDssIGxlYWd1ZTogJnF1b3Q7UHJlbWllciBMZWFndWUmcXVvdDssIHJlZ2lvbjogJnF1b3Q7RXVyb3BlJnF1b3Q7LCBzdHJlbmd0aDogODMsIGxvZ286ICZxdW90O+KaqyZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXppbmMtOTAwIHRvLWVtZXJhbGQtNzAwJnF1b3Q7IH0sIF07Cgpjb25zdCBOQVRJT05BTFMgPSBbIHsgaWQ6ICZxdW90O2ZyYSZxdW90OywgbmFtZTogJnF1b3Q7RnJhbmNlJnF1b3Q7LCB0eXBlOiAmcXVvdDtuYXRpb25hbCZxdW90OywgbGVhZ3VlOiAmcXVvdDtOYXRpb25hbCBUZWFtJnF1b3Q7LCByZWdpb246ICZxdW90O0V1cm9wZSZxdW90Oywgc3RyZW5ndGg6IDk1LCBsb2dvOiAmcXVvdDvwn4er8J+HtyZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLWJsdWUtNzAwIHRvLXJlZC02MDAmcXVvdDsgfSwgeyBpZDogJnF1b3Q7c3BhJnF1b3Q7LCBuYW1lOiAmcXVvdDtTcGFpbiZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtFdXJvcGUmcXVvdDssIHN0cmVuZ3RoOiA5MSwgbG9nbzogJnF1b3Q78J+HqvCfh7gmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1yZWQtNjAwIHRvLXllbGxvdy00MDAmcXVvdDsgfSwgeyBpZDogJnF1b3Q7Z2VyJnF1b3Q7LCBuYW1lOiAmcXVvdDtHZXJtYW55JnF1b3Q7LCB0eXBlOiAmcXVvdDtuYXRpb25hbCZxdW90OywgbGVhZ3VlOiAmcXVvdDtOYXRpb25hbCBUZWFtJnF1b3Q7LCByZWdpb246ICZxdW90O0V1cm9wZSZxdW90Oywgc3RyZW5ndGg6IDkwLCBsb2dvOiAmcXVvdDvwn4ep8J+HqiZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLWJsYWNrIHRvLXJlZC02MDAmcXVvdDsgfSwgeyBpZDogJnF1b3Q7aXRhJnF1b3Q7LCBuYW1lOiAmcXVvdDtJdGFseSZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtFdXJvcGUmcXVvdDssIHN0cmVuZ3RoOiA4OSwgbG9nbzogJnF1b3Q78J+HrvCfh7kmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1ncmVlbi02MDAgdG8tYmx1ZS02MDAmcXVvdDsgfSwgeyBpZDogJnF1b3Q7ZW5nJnF1b3Q7LCBuYW1lOiAmcXVvdDtFbmdsYW5kJnF1b3Q7LCB0eXBlOiAmcXVvdDtuYXRpb25hbCZxdW90OywgbGVhZ3VlOiAmcXVvdDtOYXRpb25hbCBUZWFtJnF1b3Q7LCByZWdpb246ICZxdW90O0V1cm9wZSZxdW90Oywgc3RyZW5ndGg6IDkwLCBsb2dvOiAmcXVvdDvwn4+0JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tc2xhdGUtODAwIHRvLXNsYXRlLTUwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtwb3JOJnF1b3Q7LCBuYW1lOiAmcXVvdDtQb3J0dWdhbCZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtFdXJvcGUmcXVvdDssIHN0cmVuZ3RoOiA4OCwgbG9nbzogJnF1b3Q78J+HtfCfh7kmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1lbWVyYWxkLTYwMCB0by1yZWQtNzAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2pwbiZxdW90OywgbmFtZTogJnF1b3Q7SmFwYW4mcXVvdDssIHR5cGU6ICZxdW90O25hdGlvbmFsJnF1b3Q7LCBsZWFndWU6ICZxdW90O05hdGlvbmFsIFRlYW0mcXVvdDssIHJlZ2lvbjogJnF1b3Q7QXNpYSZxdW90Oywgc3RyZW5ndGg6IDg1LCBsb2dvOiAmcXVvdDvwn4ev8J+HtSZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXJvc2UtNTAwIHRvLXdoaXRlJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2tvciZxdW90OywgbmFtZTogJnF1b3Q7U291dGggS29yZWEmcXVvdDssIHR5cGU6ICZxdW90O25hdGlvbmFsJnF1b3Q7LCBsZWFndWU6ICZxdW90O05hdGlvbmFsIFRlYW0mcXVvdDssIHJlZ2lvbjogJnF1b3Q7QXNpYSZxdW90Oywgc3RyZW5ndGg6IDg0LCBsb2dvOiAmcXVvdDvwn4ew8J+HtyZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXJlZC02MDAgdG8tc2t5LTYwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtzYXUmcXVvdDssIG5hbWU6ICZxdW90O1NhdWRpIEFyYWJpYSZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtBc2lhJnF1b3Q7LCBzdHJlbmd0aDogNzksIGxvZ286ICZxdW90O/Cfh7jwn4emJnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tZ3JlZW4tNzAwIHRvLWVtZXJhbGQtNTAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2F1cyZxdW90OywgbmFtZTogJnF1b3Q7QXVzdHJhbGlhJnF1b3Q7LCB0eXBlOiAmcXVvdDtuYXRpb25hbCZxdW90OywgbGVhZ3VlOiAmcXVvdDtOYXRpb25hbCBUZWFtJnF1b3Q7LCByZWdpb246ICZxdW90O0FzaWEmcXVvdDssIHN0cmVuZ3RoOiA3OCwgbG9nbzogJnF1b3Q78J+HpvCfh7omcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1za3ktNzAwIHRvLWFtYmVyLTUwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtuZ2EmcXVvdDssIG5hbWU6ICZxdW90O05pZ2VyaWEmcXVvdDssIHR5cGU6ICZxdW90O25hdGlvbmFsJnF1b3Q7LCBsZWFndWU6ICZxdW90O05hdGlvbmFsIFRlYW0mcXVvdDssIHJlZ2lvbjogJnF1b3Q7QWZyaWNhJnF1b3Q7LCBzdHJlbmd0aDogODIsIGxvZ286ICZxdW90O/Cfh7Pwn4esJnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tZ3JlZW4tNzAwIHRvLWJsYWNrJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O21hciZxdW90OywgbmFtZTogJnF1b3Q7TW9yb2NjbyZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtBZnJpY2EmcXVvdDssIHN0cmVuZ3RoOiA4NCwgbG9nbzogJnF1b3Q78J+HsvCfh6YmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1yZWQtNzAwIHRvLWdyZWVuLTcwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDtnaGEmcXVvdDssIG5hbWU6ICZxdW90O0doYW5hJnF1b3Q7LCB0eXBlOiAmcXVvdDtuYXRpb25hbCZxdW90OywgbGVhZ3VlOiAmcXVvdDtOYXRpb25hbCBUZWFtJnF1b3Q7LCByZWdpb246ICZxdW90O0FmcmljYSZxdW90Oywgc3RyZW5ndGg6IDc4LCBsb2dvOiAmcXVvdDvwn4es8J+HrSZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXJlZC02MDAgdG8tZ3JlZW4tNjAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O3NlbiZxdW90OywgbmFtZTogJnF1b3Q7U2VuZWdhbCZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtBZnJpY2EmcXVvdDssIHN0cmVuZ3RoOiA4MSwgbG9nbzogJnF1b3Q78J+HuPCfh7MmcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1ncmVlbi03MDAgdG8teWVsbG93LTQwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDticmEmcXVvdDssIG5hbWU6ICZxdW90O0JyYXppbCZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtTb3V0aCBBbWVyaWNhJnF1b3Q7LCBzdHJlbmd0aDogOTQsIGxvZ286ICZxdW90O/Cfh6fwn4e3JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tZW1lcmFsZC01MDAgdG8teWVsbG93LTQwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDthcmcmcXVvdDssIG5hbWU6ICZxdW90O0FyZ2VudGluYSZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtTb3V0aCBBbWVyaWNhJnF1b3Q7LCBzdHJlbmd0aDogOTMsIGxvZ286ICZxdW90O/Cfh6bwn4e3JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tc2t5LTUwMCB0by13aGl0ZSZxdW90OyB9LCB7IGlkOiAmcXVvdDt1cnUmcXVvdDssIG5hbWU6ICZxdW90O1VydWd1YXkmcXVvdDssIHR5cGU6ICZxdW90O25hdGlvbmFsJnF1b3Q7LCBsZWFndWU6ICZxdW90O05hdGlvbmFsIFRlYW0mcXVvdDssIHJlZ2lvbjogJnF1b3Q7U291dGggQW1lcmljYSZxdW90Oywgc3RyZW5ndGg6IDg3LCBsb2dvOiAmcXVvdDvwn4e68J+HviZxdW90OywgY29sb3JzOiAmcXVvdDtmcm9tLXNreS02MDAgdG8td2hpdGUmcXVvdDsgfSwgeyBpZDogJnF1b3Q7Y29sJnF1b3Q7LCBuYW1lOiAmcXVvdDtDb2xvbWJpYSZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtTb3V0aCBBbWVyaWNhJnF1b3Q7LCBzdHJlbmd0aDogODQsIGxvZ286ICZxdW90O/Cfh6jwn4e0JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20teWVsbG93LTQwMCB0by1yZWQtNjAwJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O21leCZxdW90OywgbmFtZTogJnF1b3Q7TWV4aWNvJnF1b3Q7LCB0eXBlOiAmcXVvdDtuYXRpb25hbCZxdW90OywgbGVhZ3VlOiAmcXVvdDtOYXRpb25hbCBUZWFtJnF1b3Q7LCByZWdpb246ICZxdW90O05vcnRoIEFtZXJpY2EmcXVvdDssIHN0cmVuZ3RoOiA4MiwgbG9nbzogJnF1b3Q78J+HsvCfh70mcXVvdDssIGNvbG9yczogJnF1b3Q7ZnJvbS1ncmVlbi03MDAgdG8tcmVkLTcwMCZxdW90OyB9LCB7IGlkOiAmcXVvdDt1c2EmcXVvdDssIG5hbWU6ICZxdW90O1VTQSZxdW90OywgdHlwZTogJnF1b3Q7bmF0aW9uYWwmcXVvdDssIGxlYWd1ZTogJnF1b3Q7TmF0aW9uYWwgVGVhbSZxdW90OywgcmVnaW9uOiAmcXVvdDtOb3J0aCBBbWVyaWNhJnF1b3Q7LCBzdHJlbmd0aDogODMsIGxvZ286ICZxdW90O/Cfh7rwn4e4JnF1b3Q7LCBjb2xvcnM6ICZxdW90O2Zyb20tYmx1ZS03MDAgdG8tcmVkLTcwMCZxdW90OyB9LCBdOwoKY29uc3QgTEVBR1VFUyA9IFsgJnF1b3Q7UHJlbWllciBMZWFndWUmcXVvdDssICZxdW90O0xhIExpZ2EmcXVvdDssICZxdW90O1NlcmllIEEmcXVvdDssICZxdW90O0J1bmRlc2xpZ2EmcXVvdDssICZxdW90O0xpZ3VlIDEmcXVvdDssICZxdW90O1ByaW1laXJhIExpZ2EmcXVvdDssICZxdW90O0VyZWRpdmlzaWUmcXVvdDssICZxdW90O1NhdWRpIFBybyBMZWFndWUmcXVvdDssICZxdW90O0sgTGVhZ3VlJnF1b3Q7LCAmcXVvdDtDaGluZXNlIFN1cGVyIExlYWd1ZSZxdW90OywgJnF1b3Q7QnJhc2lsZWlyJmF0aWxkZTtvJnF1b3Q7LCAmcXVvdDtMaWdhIEFyZ2VudGluYSZxdW90OywgJnF1b3Q7RWd5cHQgUHJlbWllciBMZWFndWUmcXVvdDssICZxdW90O0JvdG9sYSBQcm8mcXVvdDssICZxdW90O1MmdXVtbDtwZXIgTGlnJnF1b3Q7LCBdOwoKY29uc3QgTkFUSU9OQUxfUkVHSU9OUyA9IFsmcXVvdDtFdXJvcGUmcXVvdDssICZxdW90O0FzaWEmcXVvdDssICZxdW90O0FmcmljYSZxdW90OywgJnF1b3Q7Tm9ydGggQW1lcmljYSZxdW90OywgJnF1b3Q7U291dGggQW1lcmljYSZxdW90O107Cgpjb25zdCBFRkZFQ1RTID0gWyB7IGlkOiAmcXVvdDt3aGVlbCZxdW90OywgbGFiZWw6ICZxdW90O1Ymb2dyYXZlO25nIHF1YXkgbWF5IG3huq9uJnF1b3Q7LCBpY29uOiAmcXVvdDvwn46hJnF1b3Q7IH0sIHsgaWQ6ICZxdW90O2NhcmRzJnF1b3Q7LCBsYWJlbDogJnF1b3Q7QuG7kWMgbCZhYWN1dGU7IGImYWdyYXZlO2kmcXVvdDssIGljb246ICZxdW90O/Cfg48mcXVvdDsgfSwgeyBpZDogJnF1b3Q7Z2lmdCZxdW90OywgbGFiZWw6ICZxdW90O0Lhu5FjIGjhu5lwIHF1JmFncmF2ZTsmcXVvdDssIGljb246ICZxdW90O/CfjoEmcXVvdDsgfSwgeyBpZDogJnF1b3Q7ZmxpcCZxdW90OywgbGFiZWw6ICZxdW90O0zhuq10IHRo4bq7JnF1b3Q7LCBpY29uOiAmcXVvdDvwn6qZJnF1b3Q7IH0sIF07Cgpjb25zdCBTUEVDSUFMX0NBUkRTID0gWyB7IGlkOiAmcXVvdDtvcHBvbmVudCZxdW90OywgbGFiZWw6ICZxdW90O0No4buNbiDEkeG7mWkgY2hvIMSR4buRaSBwaMawxqFuZyZxdW90OywgaWNvbjogJmx0O01lZ2FwaG9uZSBjbGFzc05hbWU9JnF1b3Q7aC00IHctNCZxdW90OyAvJmd0OyB9LCB7IGlkOiAmcXVvdDtzd2FwJnF1b3Q7LCBsYWJlbDogJnF1b3Q7xJDhu5VpIMSR4buZaSZxdW90OywgaWNvbjogJmx0O1JlcGVhdDIgY2xhc3NOYW1lPSZxdW90O2gtNCB3LTQmcXVvdDsgLyZndDsgfSwgeyBpZDogJnF1b3Q7c3Ryb25nV2VhayZxdW90OywgbGFiZWw6ICZxdW90O0No4buNbiDEkeG7mWkgbeG6oW5oL3nhur91JnF1b3Q7LCBpY29uOiAmbHQ7RmxhbWUgY2xhc3NOYW1lPSZxdW90O2gtNCB3LTQmcXVvdDsgLyZndDsgfSwgeyBpZDogJnF1b3Q7cmVyb2xsJnF1b3Q7LCBsYWJlbDogJnF1b3Q7UmFuZG9tIGzhuqFpJnF1b3Q7LCBpY29uOiAmbHQ7U2h1ZmZsZSBjbGFzc05hbWU9JnF1b3Q7aC00IHctNCZxdW90OyAvJmd0OyB9LCB7IGlkOiAmcXVvdDtleHRyYSZxdW90OywgbGFiZWw6ICZxdW90O0Lhu5FjIHRoJmVjaXJjO20gMSBsxrDhu6N0JnF1b3Q7LCBpY29uOiAmbHQ7R2lmdCBjbGFzc05hbWU9JnF1b3Q7aC00IHctNCZxdW90OyAvJmd0OyB9LCB7IGlkOiAmcXVvdDtiYW5MZWFndWUmcXVvdDssIGxhYmVsOiAmcXVvdDtD4bqlbSBjaOG7jW4gbeG7mXQgZ2nhuqNpIMSR4bqldSZxdW90OywgaWNvbjogJmx0O0xvY2sgY2xhc3NOYW1lPSZxdW90O2gtNCB3LTQmcXVvdDsgLyZndDsgfSwgXTsKCmZ1bmN0aW9uIGNsYW1wKG1pbiwgbWF4LCB2YWx1ZSkgeyByZXR1cm4gTWF0aC5tYXgobWluLCBNYXRoLm1pbihtYXgsIHZhbHVlKSk7IH0KCmZ1bmN0aW9uIHBpY2tSYW5kb20oYXJyKSB7IHJldHVybiBhcnJbTWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogYXJyLmxlbmd0aCldOyB9CgpmdW5jdGlvbiBzaHVmZmxlKGFycikgeyByZXR1cm4gWy4uLmFycl0uc29ydCgoKSA9Jmd0OyBNYXRoLnJhbmRvbSgpIC0gMC41KTsgfQoKZnVuY3Rpb24gZ2V0RGF0YXNldChtb2RlKSB7IGlmIChtb2RlID09PSAmcXVvdDtuYXRpb25hbCZxdW90OykgcmV0dXJuIE5BVElPTkFMUzsgaWYgKG1vZGUgPT09ICZxdW90O2Zhdm9yaXRlcyZxdW90OykgcmV0dXJuIFsuLi5DTFVCUywgLi4uTkFUSU9OQUxTXTsgcmV0dXJuIENMVUJTOyB9CgpmdW5jdGlvbiBub3JtYWxpemUoc3RyKSB7IHJldHVybiBTdHJpbmcoc3RyIHx8ICZxdW90OyZxdW90OykudG9Mb3dlckNhc2UoKTsgfQoKZnVuY3Rpb24gdXNlTG9jYWxTdG9yYWdlKGtleSwgaW5pdGlhbFZhbHVlKSB7IGNvbnN0IFt2YWx1ZSwgc2V0VmFsdWVdID0gdXNlU3RhdGUoKCkgPSZndDsgeyBpZiAodHlwZW9mIHdpbmRvdyA9PT0gJnF1b3Q7dW5kZWZpbmVkJnF1b3Q7KSByZXR1cm4gaW5pdGlhbFZhbHVlOyB0cnkgeyBjb25zdCBzYXZlZCA9IHdpbmRvdy5sb2NhbFN0b3JhZ2UuZ2V0SXRlbShrZXkpOyByZXR1cm4gc2F2ZWQgPyBKU09OLnBhcnNlKHNhdmVkKSA6IGluaXRpYWxWYWx1ZTsgfSBjYXRjaCB7IHJldHVybiBpbml0aWFsVmFsdWU7IH0gfSk7Cgp1c2VFZmZlY3QoKCkgPSZndDsgeyB0cnkgeyB3aW5kb3cubG9jYWxTdG9yYWdlLnNldEl0ZW0oa2V5LCBKU09OLnN0cmluZ2lmeSh2YWx1ZSkpOyB9IGNhdGNoIHsgLy8gaWdub3JlIH0gfSwgW2tleSwgdmFsdWVdKTsKCnJldHVybiBbdmFsdWUsIHNldFZhbHVlXTsgfQoKZnVuY3Rpb24gbWFrZUNvbmZldHRpKGNvdW50ID0gNDgpIHsgcmV0dXJuIEFycmF5LmZyb20oeyBsZW5ndGg6IGNvdW50IH0pLm1hcCgoXywgaSkgPSZndDsgKHsgaWQ6ICR7RGF0ZS5ub3coKX0tJHtpfSwgbGVmdDogTWF0aC5yYW5kb20oKSAqIDEwMCwgZGVsYXk6IE1hdGgucmFuZG9tKCkgKiAwLjM1LCBzaXplOiA4ICsgTWF0aC5yYW5kb20oKSAqIDEyLCByb3RhdGU6IE1hdGgucmFuZG9tKCkgKiAzNjAsIGR1cmF0aW9uOiAxLjggKyBNYXRoLnJhbmRvbSgpICogMS44LCB9KSk7IH0KCmZ1bmN0aW9uIHN0cmVuZ3RoTGFiZWwobikgeyBpZiAobiAmZ3Q7PSA5MikgcmV0dXJuICZxdW90O0VsaXRlJnF1b3Q7OyBpZiAobiAmZ3Q7PSA4NykgcmV0dXJuICZxdW90O03huqFuaCZxdW90OzsgaWYgKG4gJmd0Oz0gODApIHJldHVybiAmcXVvdDtU4buRdCZxdW90OzsgaWYgKG4gJmd0Oz0gNzIpIHJldHVybiAmcXVvdDtLaCZhYWN1dGU7JnF1b3Q7OyByZXR1cm4gJnF1b3Q7VnVpJnF1b3Q7OyB9CgpmdW5jdGlvbiBwbGF5QmVlcCh0eXBlID0gJnF1b3Q7d2luJnF1b3Q7KSB7IHRyeSB7IGNvbnN0IEF1ZGlvQ3R4ID0gd2luZG93LkF1ZGlvQ29udGV4dCB8fCB3aW5kb3cud2Via2l0QXVkaW9Db250ZXh0OyBpZiAoIUF1ZGlvQ3R4KSByZXR1cm47IGNvbnN0IGN0eCA9IG5ldyBBdWRpb0N0eCgpOyBjb25zdCBub3cgPSBjdHguY3VycmVudFRpbWU7IGNvbnN0IHRvbmVzID0gdHlwZSA9PT0gJnF1b3Q7d2luJnF1b3Q7ID8gWzM5MiwgNTIzLjI1LCA2NTkuMjVdIDogWzIyMCwgMjc3LjE4XTsgdG9uZXMuZm9yRWFjaCgoZnJlcSwgaWR4KSA9Jmd0OyB7IGNvbnN0IG9zYyA9IGN0eC5jcmVhdGVPc2NpbGxhdG9yKCk7IGNvbnN0IGdhaW4gPSBjdHguY3JlYXRlR2FpbigpOyBvc2MudHlwZSA9ICZxdW90O3NpbmUmcXVvdDs7IG9zYy5mcmVxdWVuY3kudmFsdWUgPSBmcmVxOyBnYWluLmdhaW4udmFsdWUgPSAwLjAwMDE7IG9zYy5jb25uZWN0KGdhaW4pOyBnYWluLmNvbm5lY3QoY3R4LmRlc3RpbmF0aW9uKTsgb3NjLnN0YXJ0KG5vdyArIGlkeCAqIDAuMDgpOyBnYWluLmdhaW4uZXhwb25lbnRpYWxSYW1wVG9WYWx1ZUF0VGltZSgwLjIsIG5vdyArIGlkeCAqIDAuMDggKyAwLjAxKTsgZ2Fpbi5nYWluLmV4cG9uZW50aWFsUmFtcFRvVmFsdWVBdFRpbWUoMC4wMDAxLCBub3cgKyBpZHggKiAwLjA4ICsgMC4yMik7IG9zYy5zdG9wKG5vdyArIGlkeCAqIDAuMDggKyAwLjI0KTsgfSk7IHNldFRpbWVvdXQoKCkgPSZndDsgY3R4LmNsb3NlKCkuY2F0Y2goKCkgPSZndDsge30pLCAxMDAwKTsgfSBjYXRjaCB7IC8vIGlnbm9yZSBhdWRpbyBlcnJvcnMgfSB9CgpmdW5jdGlvbiBDYXJkKHsgdGl0bGUsIGljb24sIGNoaWxkcmVuLCBjbGFzc05hbWUgPSAmcXVvdDsmcXVvdDsgfSkgeyByZXR1cm4gKCAmbHQ7ZGl2IGNsYXNzTmFtZT17cm91bmRlZC0zeGwgYm9yZGVyIGJvcmRlci13aGl0ZS8xMCBiZy13aGl0ZS81IGJhY2tkcm9wLWJsdXIteGwgc2hhZG93LTJ4bCBzaGFkb3ctYmxhY2svMjAgJHtjbGFzc05hbWV9fSZndDsgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7ZmxleCBpdGVtcy1jZW50ZXIgZ2FwLTIgYm9yZGVyLWIgYm9yZGVyLXdoaXRlLzEwIHB4LTQgcHktMyB0ZXh0LXdoaXRlLzkwJnF1b3Q7Jmd0OyAmbHQ7ZGl2IGNsYXNzTmFtZT0mcXVvdDtyb3VuZGVkLTJ4bCBiZy13aGl0ZS8xMCBwLTImcXVvdDsmZ3Q7e2ljb259Jmx0Oy9kaXYmZ3Q7ICZsdDtoMyBjbGFzc05hbWU9JnF1b3Q7Zm9udC1zZW1pYm9sZCZxdW90OyZndDt7dGl0bGV9Jmx0Oy9oMyZndDsgJmx0Oy9kaXYmZ3Q7ICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O3AtNCZxdW90OyZndDt7Y2hpbGRyZW59Jmx0Oy9kaXYmZ3Q7ICZsdDsvZGl2Jmd0OyApOyB9CgpmdW5jdGlvbiBUZWFtQ2hpcCh7IHRlYW0sIG9uVG9nZ2xlRmF2b3JpdGUsIGZhdm9yaXRlIH0pIHsgcmV0dXJuICggJmx0O2RpdiBjbGFzc05hbWU9e3JvdW5kZWQtMnhsIGJvcmRlciBib3JkZXItd2hpdGUvMTAgYmctZ3JhZGllbnQtdG8tYnIgJHt0ZWFtLmNvbG9yc30gcC1bMXB4XX0mZ3Q7ICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O3JvdW5kZWQtMnhsIGJnLXNsYXRlLTk1MC85MCBwLTMgdGV4dC13aGl0ZSZxdW90OyZndDsgJmx0O2RpdiBjbGFzc05hbWU9JnF1b3Q7ZmxleCBpdGVtcy1zdGFydCBqdXN0aWZ5LWJldHdlZW4gZ2FwLTMmcXVvdDsmZ3Q7ICZsdDtkaXYmZ3Q7ICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O3RleHQtMnhsJnF1b3Q7Jmd0O3t0ZWFtLmxvZ299Jmx0Oy9kaXYmZ3Q7ICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O210LTIgZm9udC1zZW1pYm9sZCBsZWFkaW5nLXRpZ2h0JnF1b3Q7Jmd0O3t0ZWFtLm5hbWV9Jmx0Oy9kaXYmZ3Q7ICZsdDtkaXYgY2xhc3NOYW1lPSZxdW90O210LTEgdGV4dC14cyB0ZXh0LXdoaXRlLzY1JnF1b3Q7Jmd0O3t0ZWFtLnR5cGUgPT09ICZxdW90O2NsdWImcXVvdDsgPyB0ZWFtLmxlYWd1ZSA6IHRlYW0ucmVnaW9ufSAmbWlkZG90OyB7c3RyZW5ndGhMYWJlbCh0ZWFtLnN0cmVuZ3RoKX0mbHQ7L2RpdiZndDsgJmx0Oy9kaXYmZ3Q7ICZsdDtidXR0b24gb25DbGljaz17KCkgPSZndDsgb25Ub2dnbGVGYXZvcml0ZSh0ZWFtLmlkKX0gY2xhc3NOYW1lPXtyb3VuZGVkLWZ1bGwgcC0yIHRyYW5zaXRpb24gJHtmYXZvcml0ZSA/ICZxdW90O2JnLXBpbmstNTAwLzIwIHRleHQtcGluay0zMDAmcXVvdDsgOiAmcXVvdDtiZy13aGl0ZS84IHRleHQtd2hpdGUvNjAgaG92ZXI6Ymctd2hpdGUvMTImcXVvdDt9fSBhcmlhLWxhYmVsPSZxdW90O2Zhdm9yaXRlJnF1b3Q7ICZndDsgJmx0O0hlYXJ0IGNsYXNzTmFtZT17aC00IHctNCAke2Zhdm9yaXRlID8gJnF1b3Q7ZmlsbC1waW5rLTQwMCZxdW90OyA6ICZxdW90OyZxdW90O319IC8mZ3Q7ICZsdDsvYnV0dG9uJmd0OyAmbHQ7L2RpdiZndDsgJmx0Oy9kaXYmZ3Q7ICZsdDsvZGl2Jmd0OyApOyB9CgpleHBvcnQgZGVmYXVsdCBmdW5jdGlvbiBQZXNSYW5kb21pemVyV2Vic2l0ZSgpIHsgY29uc3QgW21vZGUsIHNldE1vZGVdID0gdXNlU3RhdGUoJnF1b3Q7MnAmcXVvdDspOyBjb25zdCBbZWZmZWN0LCBzZXRFZmZlY3RdID0gdXNlU3RhdGUoJnF1b3Q7d2hlZWwmcXVvdDspOyBjb25zdCBbc291bmRPbiwgc2V0U291bmRPbl0gPSB1c2VTdGF0ZSh0cnVlKTsgY29uc3QgW3BhcnR5TW9kZSwgc2V0UGFydHlNb2RlXSA9IHVzZVN0YXRlKHRydWUpOyBjb25zdCBbdW5pcXVlVGVhbXMsIHNldFVuaXF1ZVRlYW1zXSA9IHVzZVN0YXRlKHRydWUpOyBjb25zdCBbc2VsZWN0ZWRMZWFndWUsIHNldFNlbGVjdGVkTGVhZ3VlXSA9IHVzZVN0YXRlKCZxdW90O0FsbCZxdW90Oyk7IGNvbnN0IFtzZWxlY3RlZFJlZ2lvbiwgc2V0U2VsZWN0ZWRSZWdpb25dID0gdXNlU3RhdGUoJnF1b3Q7QWxsJnF1b3Q7KTsgY29uc3QgW2Jhbm5lZExlYWd1ZSwgc2V0QmFubmVkTGVhZ3VlXSA9IHVzZVN0YXRlKCZxdW90O05vbmUmcXVvdDspOyBjb25zdCBbZmF2b3JpdGVJZHMsIHNldEZhdm9yaXRlSWRzXSA9IHVzZUxvY2FsU3RvcmFnZSgmcXVvdDtwZXMtZmF2b3JpdGVzJnF1b3Q7LCBbJnF1b3Q7bWNpJnF1b3Q7LCAmcXVvdDtybWEmcXVvdDssICZxdW90O2JhciZxdW90OywgJnF1b3Q7ZnJhJnF1b3Q7LCAmcXVvdDthcmcmcXVvdDssICZxdW90O2JyYSZxdW90O10pOyBjb25zdCBbaGlzdG9yeSwgc2V0SGlzdG9yeV0gPSB1c2VMb2NhbFN0b3JhZ2UoJnF1b3Q7cGVzLWhpc3RvcnkmcXVvdDssIFtdKTsgY29uc3QgW3Jlc3VsdCwgc2V0UmVzdWx0XSA9IHVzZVN0YXRlKG51bGwpOyBjb25zdCBbY29uZmV0dGksIHNldENvbmZldHRpXSA9IHVzZVN0YXRlKFtdKTsgY29uc3QgW2FuaW1hdGluZywgc2V0QW5pbWF0aW5nXSA9IHVzZVN0YXRlKGZhbHNlKTsgY29uc3QgW3NwZWNpYWxDYXJkLCBzZXRTcGVjaWFsQ2FyZF0gPSB1c2VTdGF0ZShudWxsKTsgY29uc3QgW2ZvcmNlZE1vZGUsIHNldEZvcmNlZE1vZGVdID0gdXNlU3RhdGUobnVsbCk7IGNvbnN0IFtwYXJ0eU1lc3NhZ2UsIHNldFBhcnR5TWVzc2FnZV0gPSB1c2VTdGF0ZSgmcXVvdDtT4bq1biBzJmFncmF2ZTtuZyByYW5kb20gY2jGsGE/IE5o4bqlbiBuJnVhY3V0ZTt0IGzhu5tuIGImZWNpcmM7biBkxrDhu5tpISZxdW90Oyk7IGNvbnN0IHJlc3VsdFJlZiA9IHVzZVJlZihudWxsKTsKCmNvbnN0IGFsbFRlYW1zID0gdXNlTWVtbygoKSA9Jmd0OyB7IGlmIChtb2RlID09PSAmcXVvdDtuYXRpb25hbCZxdW90OykgcmV0dXJuIE5BVElPTkFMUzsgaWYgKG1vZGUgPT09ICZxdW90O2Zhdm9yaXRlcyZxdW90OykgeyBjb25zdCBmYXYgPSBbLi4uQ0xVQlMsIC4uLk5BVElPTkFMU10uZmlsdGVyKCh0KSA9Jmd0OyBmYXZvcml0ZUlkcy5pbmNsdWRlcyh0LmlkKSk7IHJldHVybiBmYXYubGVuZ3RoID8gZmF2IDogWy4uLkNMVUJTLCAuLi5OQVRJT05BTFNdOyB9IHJldHVybiBDTFVCUzsgfSwgW21vZGUsIGZhdm9yaXRlSWRzXSk7Cgpjb25zdCBmaWx0ZXJlZFRlYW1zID0gdXNlTWVtbygoKSA9Jmd0OyB7IGxldCBsaXN0ID0gWy4uLmFsbFRlYW1zXTsgaWYgKG1vZGUgPT09ICZxdW90O2NsdWImcXVvdDsgfHwgbW9kZSA9PT0gJnF1b3Q7MnAmcXVvdDsgfHwgbW9kZSA9PT0gJnF1b3Q7cGFydHkmcXVvdDspIHsgaWYgKHNlbGVjdGVkTGVhZ3VlICE9PSAmcXVvdDtBbGwmcXVvdDspIGxpc3QgPSBsaXN0LmZpbHRlcigodCkgPSZndDsgdC50eXBlID09PSAmcXVvdDtjbHViJnF1b3Q7ICZhbXA7JmFtcDsgdC5sZWFndWUgPT09IHNlbGVjdGVkTGVhZ3VlKTsgaWYgKGJhbm5lZExlYWd1ZSAhPT0gJnF1b3Q7Tm9uZSZxdW90OykgbGlzdCA9IGxpc3QuZmlsdGVyKCh0KSA9Jmd0OyB0LmxlYWd1ZSAhPT0gYmFubmVkTGVhZ3VlKTsgfSBpZiAobW9kZSA9PT0gJnF1b3Q7bmF0aW9uYWwmcXVvdDspIHsgaWYgKHNlbGVjdGVkUmVnaW9uICE9PSAmcXVvdDtBbGwmcXVvdDspIGxpc3QgPSBsaXN0LmZpbHRlcigodCkgPSZndDsgdC5yZWdpb24gPT09IHNlbGVjdGVkUmVnaW9uKTsgfSBpZiAoZm9yY2VkTW9kZSA9PT0gJnF1b3Q7c3Ryb25nJnF1b3Q7KSBsaXN0ID0gWy4uLmxpc3RdLnNvcnQoKGEsIGIpID0mZ3Q7IGIuc3RyZW5ndGggLSBhLnN0cmVuZ3RoKTsgaWYgKGZvcmNlZE1vZGUgPT09ICZxdW90O3dlYWsmcXVvdDspIGxpc3QgPSBbLi4ubGlzdF0uc29ydCgoYSwgYikgPSZndDsgYS5zdHJlbmd0aCAtIGIuc3RyZW5ndGgpOyByZXR1cm4gbGlzdDsgfSwgW2FsbFRlYW1zLCBtb2RlLCBzZWxlY3RlZExlYWd1ZSwgc2VsZWN0ZWRSZWdpb24sIGJhbm5lZExlYWd1ZSwgZm9yY2VkTW9kZV0pOwoKY29uc3QgZmF2b3JpdGVUZWFtcyA9IHVzZU1lbW8oKCkgPSZndDsgWy4uLkNMVUJTLCAuLi5OQVRJT05BTFNdLmZpbHRlcigodCkgPSZndDsgZmF2b3JpdGVJZHMuaW5jbHVkZXModC5pZCkpLCBbZmF2b3JpdGVJZHNdKTsKCmNvbnN0IHN0YXRzID0gdXNlTWVtbygoKSA9Jmd0OyB7IGNvbnN0IGxlYWd1ZXMgPSBuZXcgU2V0KGZpbHRlcmVkVGVhbXMuZmlsdGVyKCh0KSA9Jmd0OyB0LnR5cGUgPT09ICZxdW90O2NsdWImcXVvdDspLm1hcCgodCkgPSZndDsgdC5sZWFndWUpKTsgY29uc3QgcmVnaW9ucyA9IG5ldyBTZXQoZmlsdGVyZWRUZWFtcy5maWx0ZXIoKHQpID0mZ3Q7IHQudHlwZSA9PT0gJnF1b3Q7bmF0aW9uYWwmcXVvdDspLm1hcCgodCkgPSZndDsgdC5yZWdpb24pKTsgcmV0dXJuIHsgdGVhbXM6IGZpbHRlcmVkVGVhbXMubGVuZ3RoLCBsZWFndWVzOiBsZWFndWVzLnNpemUsIHJlZ2lvbnM6IHJlZ2lvbnMuc2l6ZSB9OyB9LCBbZmlsdGVyZWRUZWFtc10pOwoKdXNlRWZmZWN0KCgpID0mZ3Q7IHsgaWYgKHJlc3VsdFJlZi5jdXJyZW50ICZhbXA7JmFtcDsgcmVzdWx0KSB7IHJlc3VsdFJlZi5jdXJyZW50LnNjcm9sbEludG9WaWV3KHsgYmVoYXZpb3I6ICZxdW90O3Ntb290aCZxdW90OywgYmxvY2s6ICZxdW90O2NlbnRlciZxdW90OyB9KTsgfSB9LCBbcmVzdWx0XSk7CgpmdW5jdGlvbiBzYXZlSGlzdG9yeShlbnRyeSkgeyBzZXRIaXN0b3J5KChwcmV2KSA9Jmd0OyBbZW50cnksIC4uLnByZXZdLnNsaWNlKDAsIDgpKTsgfQoKZnVuY3Rpb24gdG9nZ2xlRmF2b3JpdGUoaWQpIHsgc2V0RmF2b3JpdGVJZHMoKHByZXYpID0mZ3Q7IHByZXYuaW5jbHVkZXMoaWQpID8gcHJldi5maWx0ZXIoKHgpID0mZ3Q7IHggIT09IGlkKSA6IFtpZCwgLi4ucHJldl0uc2xpY2UoMCwgMTgpICk7IH0KCmZ1bmN0aW9uIGFubm91bmNlKHRleHQpIHsgc2V0UGFydHlNZXNzYWdlKHRleHQpOyB9CgpmdW5jdGlvbiBjaG9vc2VXaXRoQ29uc3RyYWludHMoc291cmNlLCB7IGRpZmZlcmVudCA9IHRydWUgfSA9IHt9KSB7IGlmICghc291cmNlLmxlbmd0aCkgcmV0dXJuIG51bGw7IGNvbnN0IHBvb2wgPSBzaHVmZmxlKHNvdXJjZSk7IHJldHVybiBwb29sWzBdIHx8IG51bGw7IH0KCmZ1bmN0aW9uIHBpY2tUd29UZWFtcyhzb3VyY2UpIHsgaWYgKCFzb3VyY2UubGVuZ3RoKSByZXR1cm4gbnVsbDsgY29uc3QgcG9vbCA9IFsuLi5zb3VyY2VdOyBpZiAocG9vbC5sZW5ndGggPT09IDEpIHsgcmV0dXJuIHVuaXF1ZVRlYW1zID8gbnVsbCA6IHsgYTogcG9vbFswXSwgYjogcG9vbFswXSB9OyB9Cgpjb25zdCBhID0gcGlja1JhbmRvbShwb29sKTsKbGV0IHJlbWFpbmluZyA9IHBvb2wuZmlsdGVyKCh0KSA9Jmd0OyB0LmlkICE9PSBhLmlkKTsKaWYgKCF1bmlxdWVUZWFtcyAmYW1wOyZhbXA7IE1hdGgucmFuZG9tKCkgJmd0OyAwLjcpIHJlbWFpbmluZyA9IFsuLi5wb29sXTsKY29uc3QgYiA9IHJlbWFpbmluZy5sZW5ndGggPyBwaWNrUmFuZG9tKHJlbWFpbmluZykgOiBudWxsOwpyZXR1cm4gYiA/IHsgYSwgYiB9IDogbnVsbDsKCn0KCmZ1bmN0aW9uIHJ1blJhbmRvbSh7IGZyb21TcGVjaWFsID0gZmFsc2UgfSA9IHt9KSB7IGNvbnN0IHNvdXJjZSA9IGZpbHRlcmVkVGVhbXM7IGlmICghc291cmNlLmxlbmd0aCkgeyBzZXRSZXN1bHQoeyBlcnJvcjogJnF1b3Q7S2gmb2NpcmM7bmcgYyZvYWN1dGU7IMSR4buZaSBuJmFncmF2ZTtvIHBoJnVncmF2ZTsgaOG7o3AgduG7m2kgYuG7mSBs4buNYyBoaeG7h24gdOG6oWkuJnF1b3Q7IH0pOyByZXR1cm47IH0KCnNldEFuaW1hdGluZyh0cnVlKTsKc2V0UmVzdWx0KG51bGwpOwppZiAoc291bmRPbikgcGxheUJlZXAoJnF1b3Q7c3BpbiZxdW90Oyk7Cgpjb25zdCBkZWxheSA9IGVmZmVjdCA9PT0gJnF1b3Q7d2hlZWwmcXVvdDsgPyAxMDUwIDogZWZmZWN0ID09PSAmcXVvdDtnaWZ0JnF1b3Q7ID8gOTAwIDogZWZmZWN0ID09PSAmcXVvdDtjYXJkcyZxdW90OyA/IDc4MCA6IDY4MDsKc2V0VGltZW91dCgoKSA9Jmd0OyB7CiAgbGV0IG5leHRSZXN1bHQ7CiAgaWYgKG1vZGUgPT09ICZxdW90OzJwJnF1b3Q7IHx8IG1vZGUgPT09ICZxdW90O3BhcnR5JnF1b3Q7KSB7CiAgICBjb25zdCBwaWNrZWQgPSBwaWNrVHdvVGVhbXMoc291cmNlKTsKICAgIGlmICghcGlja2VkKSB7CiAgICAgIG5leHRSZXN1bHQgPSB7IGVycm9yOiB1bmlxdWVUZWFtcyA/ICZxdW90O0RhbmggcyZhYWN1dGU7Y2ggaGnhu4duIHThuqFpIGtoJm9jaXJjO25nIMSR4bunIMSR4buZaSDEkeG7gyBjaOG7jW4gMiDEkeG7mWkga2gmYWFjdXRlO2MgbmhhdS4mcXVvdDsgOiAmcXVvdDtLaCZvY2lyYztuZyB0aOG7gyByYW5kb20uJnF1b3Q7IH07CiAgICB9IGVsc2UgewogICAgICBuZXh0UmVzdWx0ID0geyB0eXBlOiAmcXVvdDtwYWlyJnF1b3Q7LCBhOiBwaWNrZWQuYSwgYjogcGlja2VkLmIgfTsKICAgIH0KICB9IGVsc2UgaWYgKG1vZGUgPT09ICZxdW90O25hdGlvbmFsJnF1b3Q7KSB7CiAgICBuZXh0UmVzdWx0ID0geyB0eXBlOiAmcXVvdDtzaW5nbGUmcXVvdDssIGE6IGNob29zZVdpdGhDb25zdHJhaW50cyhzb3VyY2UpIH07CiAgfSBlbHNlIGlmIChtb2RlID09PSAmcXVvdDtmYXZvcml0ZXMmcXVvdDspIHsKICAgIGNvbnN0IHBpY2tlZCA9IHBpY2tUd29UZWFtcyhzb3VyY2UpOwogICAgbmV4dFJlc3VsdCA9IHBpY2tlZCA/IHsgdHlwZTogJnF1b3Q7cGFpciZxdW90OywgYTogcGlja2VkLmEsIGI6IHBpY2tlZC5iIH0gOiB7IGVycm9yOiAmcXVvdDtEYW5oIHMmYWFjdXRlO2NoIHkmZWNpcmM7dSB0aCZpYWN1dGU7Y2ggcXUmYWFjdXRlOyAmaWFjdXRlO3QgxJHhu4MgcmFuZG9tLiZxdW90OyB9OwogIH0gZWxzZSB7CiAgICBjb25zdCBwaWNrZWQgPSBwaWNrVHdvVGVhbXMoc291cmNlKTsKICAgIG5leHRSZXN1bHQgPSBwaWNrZWQgPyB7IHR5cGU6ICZxdW90O3BhaXImcXVvdDssIGE6IHBpY2tlZC5hLCBiOiBwaWNrZWQuYiB9IDogeyBlcnJvcjogJnF1b3Q7S2gmb2NpcmM7bmcgxJHhu6cgZOG7ryBsaeG7h3UuJnF1b3Q7IH07CiAgfQoKICBpZiAobmV4dFJlc3VsdD8uZXJyb3IpIHsKICAgIHNldFJlc3VsdChuZXh0UmVzdWx0KTsKICAgIGFubm91bmNlKG5leHRSZXN1bHQuZXJyb3IpOwogICAgc2V0QW5pbWF0aW5nKGZhbHNlKTsKICAgIHJldHVybjsKICB9CgogIGlmIChwYXJ0eU1vZGUgJmFtcDsmYW1wOyBtb2RlID09PSAmcXVvdDtwYXJ0eSZxdW90OyAmYW1wOyZhbXA7ICFmcm9tU3BlY2lhbCkgewogICAgY29uc3QgcGFydHlSb2xsID0gTWF0aC5yYW5kb20oKTsKICAgIGlmIChwYXJ0eVJvbGwgJmx0OyAwLjIpIHsKICAgICAgc2V0U3BlY2lhbENhcmQoeyBpZDogJnF1b3Q7b3Bwb25lbnQmcXVvdDssIGxhYmVsOiAmcXVvdDtUaOG6uyDEkeG6t2MgYmnhu4d0OiBDaOG7jW4gxJHhu5lpIGNobyDEkeG7kWkgcGjGsMahbmcmcXVvdDsgfSk7CiAgICAgIGFubm91bmNlKCZxdW90O1BhcnR5IG1vZGU6IMSR4buRaSBwaMawxqFuZyBi4buLIGNo4buNbiDEkeG7mWkgYuG6pXQgbmfhu50hJnF1b3Q7KTsKICAgIH0gZWxzZSBpZiAocGFydHlSb2xsICZsdDsgMC4zNSkgewogICAgICBzZXRTcGVjaWFsQ2FyZCh7IGlkOiAmcXVvdDtzdHJvbmdXZWFrJnF1b3Q7LCBsYWJlbDogJnF1b3Q7VGjhursgxJHhurdjIGJp4buHdDogQ2jhu41uIMSR4buZaSBt4bqhbmgveeG6v3UmcXVvdDsgfSk7CiAgICB9IGVsc2UgaWYgKHBhcnR5Um9sbCAmbHQ7IDAuNDgpIHsKICAgICAgc2V0U3BlY2lhbENhcmQoeyBpZDogJnF1b3Q7ZXh0cmEmcXVvdDssIGxhYmVsOiAmcXVvdDtUaOG6uyDEkeG6t2MgYmnhu4d0OiBC4buRYyB0aCZlY2lyYzttIDEgbMaw4bujdCZxdW90OyB9KTsKICAgIH0gZWxzZSBpZiAocGFydHlSb2xsICZsdDsgMC41OCkgewogICAgICBzZXRTcGVjaWFsQ2FyZCh7IGlkOiAmcXVvdDtzd2FwJnF1b3Q7LCBsYWJlbDogJnF1b3Q7VGjhursgxJHhurdjIGJp4buHdDogxJDhu5VpIMSR4buZaSZxdW90OyB9KTsKICAgIH0gZWxzZSB7CiAgICAgIHNldFNwZWNpYWxDYXJkKG51bGwpOwogICAgfQogIH0KCiAgaWYgKHNvdW5kT24pIHBsYXlCZWVwKCZxdW90O3dpbiZxdW90Oyk7CiAgY29uc3QgZW50cnkgPSB7IC4uLm5leHRSZXN1bHQsIG1vZGUsIGVmZmVjdCwgY3JlYXRlZEF0OiBuZXcgRGF0ZSgpLnRvSVNPU3RyaW5nKCkgfTsKICBzZXRSZXN1bHQobmV4dFJlc3VsdCk7CiAgc2F2ZUhpc3RvcnkoZW50cnkpOwogIHNldENvbmZldHRpKG1ha2VDb25mZXR0aShlZmZlY3QgPT09ICZxdW90O2dpZnQmcXVvdDsgPyA3MiA6IDU0KSk7CiAgYW5ub3VuY2UoCiAgICBuZXh0UmVzdWx0LnR5cGUgPT09ICZxdW90O3BhaXImcXVvdDsKICAgICAgPyBgJHtuZXh0UmVzdWx0LmEubmFtZX0gdnMgJHtuZXh0UmVzdWx0LmIubmFtZX1gCiAgICAgIDogYELhuqFuIG5o4bqtbiDEkcaw4bujYyAke25leHRSZXN1bHQuYS5uYW1lfWAKICApOwogIHNldEFuaW1hdGluZyhmYWxzZSk7CiAgc2V0VGltZW91dCgoKSA9Jmd0OyBzZXRDb25mZXR0aShbXSksIDIyMDApOwp9LCBkZWxheSk7Cgp9CgpmdW5jdGlvbiByZXJvbGwoKSB7IHJ1blJhbmRvbSh7IGZyb21TcGVjaWFsOiBmYWxzZSB9KTsgfQoKZnVuY3Rpb24gc3dhcFRlYW1zKCkgeyBpZiAoIXJlc3VsdCB8fCByZXN1bHQudHlwZSAhPT0gJnF1b3Q7cGFpciZxdW90OykgcmV0dXJuOyBzZXRSZXN1bHQoeyAuLi5yZXN1bHQsIGE6IHJlc3VsdC5iLCBiOiByZXN1bHQuYSB9KTsgY29uc3Qgc3dhcHBlZCA9IHsgLi4ucmVzdWx0LCBhOiByZXN1bHQuYiwgYjogcmVzdWx0LmEsIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLCBtb2RlLCBlZmZlY3QgfTsgc2F2ZUhpc3Rvcnkoc3dhcHBlZCk7IHNldENvbmZldHRpKG1ha2VDb25mZXR0aSgzNCkpOyBpZiAoc291bmRPbikgcGxheUJlZXAoJnF1b3Q7d2luJnF1b3Q7KTsgfQoKZnVuY3Rpb24gY2hvb3NlU3Ryb25nV2VhayhraW5kKSB7IGNvbnN0IHNvdXJjZSA9IGZpbHRlcmVkVGVhbXM7IGlmICghc291cmNlLmxlbmd0aCkgcmV0dXJuOyBjb25zdCBvcmRlcmVkID0gWy4uLnNvdXJjZV0uc29ydCgoYSwgYikgPSZndDsgKGtpbmQgPT09ICZxdW90O3N0cm9uZyZxdW90OyA/IGIuc3RyZW5ndGggLSBhLnN0cmVuZ3RoIDogYS5zdHJlbmd0aCAtIGIuc3RyZW5ndGgpKTsgY29uc3QgdG9wID0gb3JkZXJlZC5zbGljZSgwLCBNYXRoLm1heCgyLCBNYXRoLmNlaWwob3JkZXJlZC5sZW5ndGggKiAwLjMpKSk7IGNvbnN0IHBpY2tlZCA9IHBpY2tUd29UZWFtcyh0b3ApOyBpZiAoIXBpY2tlZCkgcmV0dXJuOyBzZXRGb3JjZWRNb2RlKGtpbmQpOyBzZXRSZXN1bHQoeyB0eXBlOiAmcXVvdDtwYWlyJnF1b3Q7LCBhOiBwaWNrZWQuYSwgYjogcGlja2VkLmIgfSk7IHNhdmVIaXN0b3J5KHsgdHlwZTogJnF1b3Q7cGFpciZxdW90OywgYTogcGlja2VkLmEsIGI6IHBpY2tlZC5iLCBtb2RlLCBlZmZlY3QsIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLCBzcGVjaWFsOiBraW5kIH0pOyBzZXRDb25mZXR0aShtYWtlQ29uZmV0dGkoNjApKTsgYW5ub3VuY2Uoa2luZCA9PT0gJnF1b3Q7c3Ryb25nJnF1b3Q7ID8gJnF1b3Q7xJAmYXRpbGRlOyBjaOG7jW4gY+G6t3AgxJHhu5lpIG3huqFuaCEmcXVvdDsgOiAmcXVvdDvEkCZhdGlsZGU7IGNo4buNbiBj4bq3cCDEkeG7mWkgeeG6v3UgaMahbiBjaG8gcGFydHkgbW9kZSEmcXVvdDspOyB9CgpmdW5jdGlvbiBjaG9vc2VGb3JPcHBvbmVudCgpIHsgY29uc3Qgc291cmNlID0gZmlsdGVyZWRUZWFtczsgaWYgKCFzb3VyY2UubGVuZ3RoKSByZXR1cm47IGNvbnN0IG90aGVyID0gcGlja1JhbmRvbShzb3VyY2UpOyBzZXRSZXN1bHQoeyB0eXBlOiAmcXVvdDtzaW5nbGUmcXVvdDssIGE6IG90aGVyLCBub3RlOiAmcXVvdDvEkOG7mWkgZCZhZ3JhdmU7bmggY2hvIMSR4buRaSBwaMawxqFuZyZxdW90OyB9KTsgc2F2ZUhpc3RvcnkoeyB0eXBlOiAmcXVvdDtzaW5nbGUmcXVvdDssIGE6IG90aGVyLCBtb2RlLCBlZmZlY3QsIGNyZWF0ZWRBdDogbmV3IERhdGUoKS50b0lTT1N0cmluZygpLCBzcGVjaWFsOiAmcXVvdDtvcHBvbmVudCZxdW90OyB9KTsgc2V0Q29uZmV0dGkobWFrZUNvbmZldHRpKDQ0KSk7IH0KCmZ1bmN0aW9uIGV4dHJhRHJhdygpIHsgcnVuUmFuZG9tKHsgZnJvbVNwZWNpYWw6IHRydWUgfSk7IHNldFRpbWVvdXQoKCkgPSZndDsgcnVuUmFuZG9tKHsgZnJvbVNwZWNpYWw6IHRydWUgfSksIDI1MCk7IH0KCmZ1bmN0aW9uIGJhbkxlYWd1ZVJhbmRvbSgpIHsgc2V0QmFubmVkTGVhZ3VlKHBpY2tSYW5kb20oTEVBR1VFUykpOyBzZXRQYXJ0eU1lc3NhZ2UoJnF1b3Q7TeG7mXQgZ2nhuqNpIMSR4bqldSDEkSZhdGlsZGU7IGLhu4sgY+G6pW0gbmfhuqt1IG5oaSZlY2lyYztuLiZxdW90Oyk7IH0KCmZ1bmN0aW9uIHNoYXJlUmVzdWx0KCkgeyBpZiAoIXJlc3VsdCkgcmV0dXJuOyBjb25zdCB0ZXh0ID0gcmVzdWx0LnR5cGUgPT09ICZxdW90O3BhaXImcXVvdDsgPyBQRVMvZUZvb3RiYWxsIFJhbmRvbTogJHtyZXN1bHQuYS5uYW1lfSB2cyAke3Jlc3VsdC5iLm5hbWV9IDogUEVTL2VGb290YmFsbCBSYW5kb206ICR7cmVzdWx0LmEubmFtZX07IGlmIChuYXZpZ2F0b3Iuc2hhcmUpIHsgbmF2aWdhdG9yLnNoYXJlKHsgdGl0bGU6ICZxdW90O1BFUyBSYW5kb20mcXVvdDssIHRleHQgfSkuY2F0Y2goKCkgPSZndDsge30pOyB9IGVsc2UgaWYgKG5hdmlnYXRvci5jbGlwYm9hcmQpIHsgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQodGV4dCkuY2F0Y2goKCkgPSZndDsge30pOyBhbm4=
import React, { useEffect, useMemo, useRef, useState } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { Shuffle, Trophy, Sparkles, Volume2, VolumeX, Flame, Shield, Star, Repeat2, Gift, Wand2, Lock, Share2, Heart, History, BadgeInfo, Megaphone, } from "lucide-react";
const CLUBS = [ { id: "mci", name: "Manchester City", type: "club", league: "Premier League", region: "Europe", strength: 95, logo: "🔵", colors: "from-sky-500 to-blue-700" }, { id: "liv", name: "Liverpool", type: "club", league: "Premier League", region: "Europe", strength: 92, logo: "🔴", colors: "from-red-500 to-rose-700" }, { id: "ars", name: "Arsenal", type: "club", league: "Premier League", region: "Europe", strength: 90, logo: "🔴", colors: "from-rose-500 to-orange-600" }, { id: "rma", name: "Real Madrid", type: "club", league: "La Liga", region: "Europe", strength: 96, logo: "👑", colors: "from-zinc-100 to-zinc-400" }, { id: "bar", name: "FC Barcelona", type: "club", league: "La Liga", region: "Europe", strength: 94, logo: "🔵", colors: "from-blue-600 to-red-600" }, { id: "atm", name: "Atlético Madrid", type: "club", league: "La Liga", region: "Europe", strength: 89, logo: "⚪", colors: "from-red-700 to-slate-900" }, { id: "juv", name: "Juventus", type: "club", league: "Serie A", region: "Europe", strength: 88, logo: "⚫", colors: "from-slate-900 to-slate-700" }, { id: "mil", name: "AC Milan", type: "club", league: "Serie A", region: "Europe", strength: 89, logo: "🔴", colors: "from-red-600 to-black" }, { id: "int", name: "Inter", type: "club", league: "Serie A", region: "Europe", strength: 91, logo: "🔵", colors: "from-sky-700 to-black" }, { id: "bvb", name: "Borussia Dortmund", type: "club", league: "Bundesliga", region: "Europe", strength: 87, logo: "🟡", colors: "from-yellow-400 to-black" }, { id: "bay", name: "Bayern Munich", type: "club", league: "Bundesliga", region: "Europe", strength: 95, logo: "🔴", colors: "from-red-600 to-rose-800" }, { id: "psg", name: "PSG", type: "club", league: "Ligue 1", region: "Europe", strength: 93, logo: "🔵", colors: "from-blue-800 to-pink-600" }, { id: "mon", name: "Monaco", type: "club", league: "Ligue 1", region: "Europe", strength: 84, logo: "🔴", colors: "from-red-600 to-white" }, { id: "por", name: "FC Porto", type: "club", league: "Primeira Liga", region: "Europe", strength: 85, logo: "🐉", colors: "from-blue-700 to-sky-400" }, { id: "aja", name: "Ajax", type: "club", league: "Eredivisie", region: "Europe", strength: 83, logo: "⭐", colors: "from-red-500 to-white" }, { id: "aln", name: "Al Nassr", type: "club", league: "Saudi Pro League", region: "Asia", strength: 84, logo: "🟡", colors: "from-yellow-400 to-amber-700" }, { id: "hil", name: "Al Hilal", type: "club", league: "Saudi Pro League", region: "Asia", strength: 86, logo: "🔷", colors: "from-sky-500 to-blue-900" }, { id: "Uls", name: "Ulsan HD", type: "club", league: "K League", region: "Asia", strength: 78, logo: "🟦", colors: "from-blue-500 to-slate-800" }, { id: "bfc", name: "Beijing Guoan", type: "club", league: "Chinese Super League", region: "Asia", strength: 76, logo: "🟩", colors: "from-emerald-500 to-green-800" }, { id: "san", name: "Santos", type: "club", league: "Brasileirão", region: "South America", strength: 79, logo: "⚪", colors: "from-white to-black" }, { id: "pal", name: "Palmeiras", type: "club", league: "Brasileirão", region: "South America", strength: 87, logo: "🟢", colors: "from-emerald-500 to-green-900" }, { id: "rio", name: "River Plate", type: "club", league: "Liga Argentina", region: "South America", strength: 88, logo: "🔴", colors: "from-red-600 to-white" }, { id: "boo", name: "Boca Juniors", type: "club", league: "Liga Argentina", region: "South America", strength: 86, logo: "💙", colors: "from-blue-700 to-yellow-400" }, { id: "afr1", name: "Al Ahly", type: "club", league: "Egypt Premier League", region: "Africa", strength: 80, logo: "🟥", colors: "from-red-700 to-amber-700" }, { id: "afr2", name: "Wydad AC", type: "club", league: "Botola Pro", region: "Africa", strength: 77, logo: "⬛", colors: "from-red-800 to-black" }, { id: "gal", name: "Galatasaray", type: "club", league: "Süper Lig", region: "Europe", strength: 84, logo: "🟠", colors: "from-orange-500 to-red-700" }, { id: "new", name: "Newcastle United", type: "club", league: "Premier League", region: "Europe", strength: 83, logo: "⚫", colors: "from-zinc-900 to-emerald-700" }, ];
const NATIONALS = [ { id: "fra", name: "France", type: "national", league: "National Team", region: "Europe", strength: 95, logo: "🇫🇷", colors: "from-blue-700 to-red-600" }, { id: "spa", name: "Spain", type: "national", league: "National Team", region: "Europe", strength: 91, logo: "🇪🇸", colors: "from-red-600 to-yellow-400" }, { id: "ger", name: "Germany", type: "national", league: "National Team", region: "Europe", strength: 90, logo: "🇩🇪", colors: "from-black to-red-600" }, { id: "ita", name: "Italy", type: "national", league: "National Team", region: "Europe", strength: 89, logo: "🇮🇹", colors: "from-green-600 to-blue-600" }, { id: "eng", name: "England", type: "national", league: "National Team", region: "Europe", strength: 90, logo: "🏴", colors: "from-slate-800 to-slate-500" }, { id: "porN", name: "Portugal", type: "national", league: "National Team", region: "Europe", strength: 88, logo: "🇵🇹", colors: "from-emerald-600 to-red-700" }, { id: "jpn", name: "Japan", type: "national", league: "National Team", region: "Asia", strength: 85, logo: "🇯🇵", colors: "from-rose-500 to-white" }, { id: "kor", name: "South Korea", type: "national", league: "National Team", region: "Asia", strength: 84, logo: "🇰🇷", colors: "from-red-600 to-sky-600" }, { id: "sau", name: "Saudi Arabia", type: "national", league: "National Team", region: "Asia", strength: 79, logo: "🇸🇦", colors: "from-green-700 to-emerald-500" }, { id: "aus", name: "Australia", type: "national", league: "National Team", region: "Asia", strength: 78, logo: "🇦🇺", colors: "from-sky-700 to-amber-500" }, { id: "nga", name: "Nigeria", type: "national", league: "National Team", region: "Africa", strength: 82, logo: "🇳🇬", colors: "from-green-700 to-black" }, { id: "mar", name: "Morocco", type: "national", league: "National Team", region: "Africa", strength: 84, logo: "🇲🇦", colors: "from-red-700 to-green-700" }, { id: "gha", name: "Ghana", type: "national", league: "National Team", region: "Africa", strength: 78, logo: "🇬🇭", colors: "from-red-600 to-green-600" }, { id: "sen", name: "Senegal", type: "national", league: "National Team", region: "Africa", strength: 81, logo: "🇸🇳", colors: "from-green-700 to-yellow-400" }, { id: "bra", name: "Brazil", type: "national", league: "National Team", region: "South America", strength: 94, logo: "🇧🇷", colors: "from-emerald-500 to-yellow-400" }, { id: "arg", name: "Argentina", type: "national", league: "National Team", region: "South America", strength: 93, logo: "🇦🇷", colors: "from-sky-500 to-white" }, { id: "uru", name: "Uruguay", type: "national", league: "National Team", region: "South America", strength: 87, logo: "🇺🇾", colors: "from-sky-600 to-white" }, { id: "col", name: "Colombia", type: "national", league: "National Team", region: "South America", strength: 84, logo: "🇨🇴", colors: "from-yellow-400 to-red-600" }, { id: "mex", name: "Mexico", type: "national", league: "National Team", region: "North America", strength: 82, logo: "🇲🇽", colors: "from-green-700 to-red-700" }, { id: "usa", name: "USA", type: "national", league: "National Team", region: "North America", strength: 83, logo: "🇺🇸", colors: "from-blue-700 to-red-700" }, ];
const LEAGUES = [ "Premier League", "La Liga", "Serie A", "Bundesliga", "Ligue 1", "Primeira Liga", "Eredivisie", "Saudi Pro League", "K League", "Chinese Super League", "Brasileirão", "Liga Argentina", "Egypt Premier League", "Botola Pro", "Süper Lig", ];
const NATIONAL_REGIONS = ["Europe", "Asia", "Africa", "North America", "South America"];
const EFFECTS = [ { id: "wheel", label: "Vòng quay may mắn", icon: "🎡" }, { id: "cards", label: "Bốc lá bài", icon: "🃏" }, { id: "gift", label: "Bốc hộp quà", icon: "🎁" }, { id: "flip", label: "Lật thẻ", icon: "🪙" }, ];
const SPECIAL_CARDS = [ { id: "opponent", label: "Chọn đội cho đối phương", icon: <Megaphone className="h-4 w-4" /> }, { id: "swap", label: "Đổi đội", icon: <Repeat2 className="h-4 w-4" /> }, { id: "strongWeak", label: "Chọn đội mạnh/yếu", icon: <Flame className="h-4 w-4" /> }, { id: "reroll", label: "Random lại", icon: <Shuffle className="h-4 w-4" /> }, { id: "extra", label: "Bốc thêm 1 lượt", icon: <Gift className="h-4 w-4" /> }, { id: "banLeague", label: "Cấm chọn một giải đấu", icon: <Lock className="h-4 w-4" /> }, ];
function clamp(min, max, value) { return Math.max(min, Math.min(max, value)); }
function pickRandom(arr) { return arr[Math.floor(Math.random() * arr.length)]; }
function shuffle(arr) { return [...arr].sort(() => Math.random() - 0.5); }
function getDataset(mode) { if (mode === "national") return NATIONALS; if (mode === "favorites") return [...CLUBS, ...NATIONALS]; return CLUBS; }
function normalize(str) { return String(str || "").toLowerCase(); }
function useLocalStorage(key, initialValue) { const [value, setValue] = useState(() => { if (typeof window === "undefined") return initialValue; try { const saved = window.localStorage.getItem(key); return saved ? JSON.parse(saved) : initialValue; } catch { return initialValue; } });
useEffect(() => { try { window.localStorage.setItem(key, JSON.stringify(value)); } catch { // ignore } }, [key, value]);
return [value, setValue]; }
function makeConfetti(count = 48) { return Array.from({ length: count }).map((_, i) => ({ id: ${Date.now()}-${i}, left: Math.random() * 100, delay: Math.random() * 0.35, size: 8 + Math.random() * 12, rotate: Math.random() * 360, duration: 1.8 + Math.random() * 1.8, })); }
function strengthLabel(n) { if (n >= 92) return "Elite"; if (n >= 87) return "Mạnh"; if (n >= 80) return "Tốt"; if (n >= 72) return "Khá"; return "Vui"; }
function playBeep(type = "win") { try { const AudioCtx = window.AudioContext || window.webkitAudioContext; if (!AudioCtx) return; const ctx = new AudioCtx(); const now = ctx.currentTime; const tones = type === "win" ? [392, 523.25, 659.25] : [220, 277.18]; tones.forEach((freq, idx) => { const osc = ctx.createOscillator(); const gain = ctx.createGain(); osc.type = "sine"; osc.frequency.value = freq; gain.gain.value = 0.0001; osc.connect(gain); gain.connect(ctx.destination); osc.start(now + idx * 0.08); gain.gain.exponentialRampToValueAtTime(0.2, now + idx * 0.08 + 0.01); gain.gain.exponentialRampToValueAtTime(0.0001, now + idx * 0.08 + 0.22); osc.stop(now + idx * 0.08 + 0.24); }); setTimeout(() => ctx.close().catch(() => {}), 1000); } catch { // ignore audio errors } }
function Card({ title, icon, children, className = "" }) { return ( <div className={rounded-3xl border border-white/10 bg-white/5 backdrop-blur-xl shadow-2xl shadow-black/20 ${className}}> <div className="flex items-center gap-2 border-b border-white/10 px-4 py-3 text-white/90"> <div className="rounded-2xl bg-white/10 p-2">{icon}</div> <h3 className="font-semibold">{title}</h3> </div> <div className="p-4">{children}</div> </div> ); }
function TeamChip({ team, onToggleFavorite, favorite }) { return ( <div className={rounded-2xl border border-white/10 bg-gradient-to-br ${team.colors} p-[1px]}> <div className="rounded-2xl bg-slate-950/90 p-3 text-white"> <div className="flex items-start justify-between gap-3"> <div> <div className="text-2xl">{team.logo}</div> <div className="mt-2 font-semibold leading-tight">{team.name}</div> <div className="mt-1 text-xs text-white/65">{team.type === "club" ? team.league : team.region} · {strengthLabel(team.strength)}</div> </div> <button onClick={() => onToggleFavorite(team.id)} className={rounded-full p-2 transition ${favorite ? "bg-pink-500/20 text-pink-300" : "bg-white/8 text-white/60 hover:bg-white/12"}} aria-label="favorite" > <Heart className={h-4 w-4 ${favorite ? "fill-pink-400" : ""}} /> </button> </div> </div> </div> ); }
export default function PesRandomizerWebsite() { const [mode, setMode] = useState("2p"); const [effect, setEffect] = useState("wheel"); const [soundOn, setSoundOn] = useState(true); const [partyMode, setPartyMode] = useState(true); const [uniqueTeams, setUniqueTeams] = useState(true); const [selectedLeague, setSelectedLeague] = useState("All"); const [selectedRegion, setSelectedRegion] = useState("All"); const [bannedLeague, setBannedLeague] = useState("None"); const [favoriteIds, setFavoriteIds] = useLocalStorage("pes-favorites", ["mci", "rma", "bar", "fra", "arg", "bra"]); const [history, setHistory] = useLocalStorage("pes-history", []); const [result, setResult] = useState(null); const [confetti, setConfetti] = useState([]); const [animating, setAnimating] = useState(false); const [specialCard, setSpecialCard] = useState(null); const [forcedMode, setForcedMode] = useState(null); const [partyMessage, setPartyMessage] = useState("Sẵn sàng random chưa? Nhấn nút lớn bên dưới!"); const resultRef = useRef(null);
const allTeams = useMemo(() => { if (mode === "national") return NATIONALS; if (mode === "favorites") { const fav = [...CLUBS, ...NATIONALS].filter((t) => favoriteIds.includes(t.id)); return fav.length ? fav : [...CLUBS, ...NATIONALS]; } return CLUBS; }, [mode, favoriteIds]);
const filteredTeams = useMemo(() => { let list = [...allTeams]; if (mode === "club" || mode === "2p" || mode === "party") { if (selectedLeague !== "All") list = list.filter((t) => t.type === "club" && t.league === selectedLeague); if (bannedLeague !== "None") list = list.filter((t) => t.league !== bannedLeague); } if (mode === "national") { if (selectedRegion !== "All") list = list.filter((t) => t.region === selectedRegion); } if (forcedMode === "strong") list = [...list].sort((a, b) => b.strength - a.strength); if (forcedMode === "weak") list = [...list].sort((a, b) => a.strength - b.strength); return list; }, [allTeams, mode, selectedLeague, selectedRegion, bannedLeague, forcedMode]);
const favoriteTeams = useMemo(() => [...CLUBS, ...NATIONALS].filter((t) => favoriteIds.includes(t.id)), [favoriteIds]);
const stats = useMemo(() => { const leagues = new Set(filteredTeams.filter((t) => t.type === "club").map((t) => t.league)); const regions = new Set(filteredTeams.filter((t) => t.type === "national").map((t) => t.region)); return { teams: filteredTeams.length, leagues: leagues.size, regions: regions.size }; }, [filteredTeams]);
useEffect(() => { if (resultRef.current && result) { resultRef.current.scrollIntoView({ behavior: "smooth", block: "center" }); } }, [result]);
function saveHistory(entry) { setHistory((prev) => [entry, ...prev].slice(0, 8)); }
function toggleFavorite(id) { setFavoriteIds((prev) => prev.includes(id) ? prev.filter((x) => x !== id) : [id, ...prev].slice(0, 18) ); }
function announce(text) { setPartyMessage(text); }
function chooseWithConstraints(source, { different = true } = {}) { if (!source.length) return null; const pool = shuffle(source); return pool[0] || null; }
function pickTwoTeams(source) { if (!source.length) return null; const pool = [...source]; if (pool.length === 1) { return uniqueTeams ? null : { a: pool[0], b: pool[0] }; }
const a = pickRandom(pool);
let remaining = pool.filter((t) => t.id !== a.id);
if (!uniqueTeams && Math.random() > 0.7) remaining = [...pool];
const b = remaining.length ? pickRandom(remaining) : null;
return b ? { a, b } : null;
}
function runRandom({ fromSpecial = false } = {}) { const source = filteredTeams; if (!source.length) { setResult({ error: "Không có đội nào phù hợp với bộ lọc hiện tại." }); return; }
setAnimating(true);
setResult(null);
if (soundOn) playBeep("spin");
const delay = effect === "wheel" ? 1050 : effect === "gift" ? 900 : effect === "cards" ? 780 : 680;
setTimeout(() => {
let nextResult;
if (mode === "2p" || mode === "party") {
const picked = pickTwoTeams(source);
if (!picked) {
nextResult = { error: uniqueTeams ? "Danh sách hiện tại không đủ đội để chọn 2 đội khác nhau." : "Không thể random." };
} else {
nextResult = { type: "pair", a: picked.a, b: picked.b };
}
} else if (mode === "national") {
nextResult = { type: "single", a: chooseWithConstraints(source) };
} else if (mode === "favorites") {
const picked = pickTwoTeams(source);
nextResult = picked ? { type: "pair", a: picked.a, b: picked.b } : { error: "Danh sách yêu thích quá ít để random." };
} else {
const picked = pickTwoTeams(source);
nextResult = picked ? { type: "pair", a: picked.a, b: picked.b } : { error: "Không đủ dữ liệu." };
}
if (nextResult?.error) {
setResult(nextResult);
announce(nextResult.error);
setAnimating(false);
return;
}
if (partyMode && mode === "party" && !fromSpecial) {
const partyRoll = Math.random();
if (partyRoll < 0.2) {
setSpecialCard({ id: "opponent", label: "Thẻ đặc biệt: Chọn đội cho đối phương" });
announce("Party mode: đối phương bị chọn đội bất ngờ!");
} else if (partyRoll < 0.35) {
setSpecialCard({ id: "strongWeak", label: "Thẻ đặc biệt: Chọn đội mạnh/yếu" });
} else if (partyRoll < 0.48) {
setSpecialCard({ id: "extra", label: "Thẻ đặc biệt: Bốc thêm 1 lượt" });
} else if (partyRoll < 0.58) {
setSpecialCard({ id: "swap", label: "Thẻ đặc biệt: Đổi đội" });
} else {
setSpecialCard(null);
}
}
if (soundOn) playBeep("win");
const entry = { ...nextResult, mode, effect, createdAt: new Date().toISOString() };
setResult(nextResult);
saveHistory(entry);
setConfetti(makeConfetti(effect === "gift" ? 72 : 54));
announce(
nextResult.type === "pair"
? `${nextResult.a.name} vs ${nextResult.b.name}`
: `Bạn nhận được ${nextResult.a.name}`
);
setAnimating(false);
setTimeout(() => setConfetti([]), 2200);
}, delay);
}
function reroll() { runRandom({ fromSpecial: false }); }
function swapTeams() { if (!result || result.type !== "pair") return; setResult({ ...result, a: result.b, b: result.a }); const swapped = { ...result, a: result.b, b: result.a, createdAt: new Date().toISOString(), mode, effect }; saveHistory(swapped); setConfetti(makeConfetti(34)); if (soundOn) playBeep("win"); }
function chooseStrongWeak(kind) { const source = filteredTeams; if (!source.length) return; const ordered = [...source].sort((a, b) => (kind === "strong" ? b.strength - a.strength : a.strength - b.strength)); const top = ordered.slice(0, Math.max(2, Math.ceil(ordered.length * 0.3))); const picked = pickTwoTeams(top); if (!picked) return; setForcedMode(kind); setResult({ type: "pair", a: picked.a, b: picked.b }); saveHistory({ type: "pair", a: picked.a, b: picked.b, mode, effect, createdAt: new Date().toISOString(), special: kind }); setConfetti(makeConfetti(60)); announce(kind === "strong" ? "Đã chọn cặp đội mạnh!" : "Đã chọn cặp đội yếu hơn cho party mode!"); }
function chooseForOpponent() { const source = filteredTeams; if (!source.length) return; const other = pickRandom(source); setResult({ type: "single", a: other, note: "Đội dành cho đối phương" }); saveHistory({ type: "single", a: other, mode, effect, createdAt: new Date().toISOString(), special: "opponent" }); setConfetti(makeConfetti(44)); }
function extraDraw() { runRandom({ fromSpecial: true }); setTimeout(() => runRandom({ fromSpecial: true }), 250); }
function banLeagueRandom() { setBannedLeague(pickRandom(LEAGUES)); setPartyMessage("Một giải đấu đã bị cấm ngẫu nhiên."); }
function shareResult() { if (!result) return; const text = result.type === "pair" ? PES/eFootball Random: ${result.a.name} vs ${result.b.name} : PES/eFootball Random: ${result.a.name}; if (navigator.share) { navigator.share({ title: "PES Random", text }).catch(() => {}); } else if (navigator.clipboard) { navigator.clipboard.writeText(text).catch(() => {}); ann