tx · 6Ecs2wULeZs81TzNNQfr3ZVrbyYB4eziHytn8vib6ss2 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm: -0.09500000 Waves 2023.12.29 23:12 [2908526] smart account 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm > SELF 0.00000000 Waves
{ "type": 13, "id": "6Ecs2wULeZs81TzNNQfr3ZVrbyYB4eziHytn8vib6ss2", "fee": 9500000, "feeAssetId": null, "timestamp": 1703880790712, "version": 2, "chainId": 84, "sender": "3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm", "senderPublicKey": "EVooykMNV691Venwp1dHUTBd7KWequzUcda57Wd3LQEX", "proofs": [ "4f7DKz1rkqKXEwTaprpeewMxbRZNdNaBjyxEVn9FPapXXTSepnJ1sZkUPSVTTZLin9uc8YLgSZh6m9R392vEjrBg" ], "script": "base64:BgLIAQgCEgMKAQgSBAoCCAESAwoBBBIAEgMKAQgSABIDCgEIEgQKAgEIEgQKAgEIEgQKAgICEgUKAwEBARIAEgQKAggIEgASAwoBARIAEgQKAgICEgASAwoBCBIECgIICBIDCgEYEgQKAggIEgQKAggIEgUKAwgICBIECgIICBIHCgUBAQEBARIDCgEBEgUKAwEBCBIDCgEIEgMKAQgSABIECgIIARIECgIIARIDCgEIEgMKAQgSABIAEgMKAQgSAwoBCBIECgICAhIAmAIACURBWU1JTExJUwCAuJkpARRrZXlMYXN0QXJiVGltZUJ5VXNlcgEEYWRkcgkArAICAhBsYXN0QXJiVGltZVVzZXJfBQRhZGRyARprZXlBY3Jlc1N0YWtlZEFtb3VudEJ5VXNlcgEEYWRkcgkArAICAhhhY3Jlc1N0YWtlZEFtb3VudEJ5VXNlcl8FBGFkZHIABlNDQUxFOACAwtcvAAx4cExldmVsU2NhbGUAgBkAD3hwTGV2ZWxSZWNpcFBvdwCgHwASbnVtUG9pbnRzT25MZXZlbFVwAAMADHJlcXVpcmVtZW50cwkAzAgCAghTdHJlbmd0aAkAzAgCAghBY2N1cmFjeQkAzAgCAglJbnRlbGxlY3QJAMwIAgIJRW5kdXJhbmNlCQDMCAICCURleHRlcml0eQkAzAgCAgVMZXZlbAkAzAgCAgZIZWFsdGgFA25pbAAMY2hhclN0cmVuZ3RoAAAADGNoYXJBY2N1cmFjeQABAA1jaGFySW50ZWxsZWN0AAIADWNoYXJFbmR1cmFuY2UAAwANY2hhckRleHRlcml0eQAEAAtzZWdCYWNrcGFjawAAAAtOVU1TRUdNRU5UUwAGAApOVU1NQUlOQVVYAAIACE1BWFNMT1RTAAIADU1BWFBST0RJTlNMT1QAHgENa2V5RHVja0hlYWx0aAELZHVja0Fzc2V0SWQJAKwCAgILZHVja0hlYWx0aF8FC2R1Y2tBc3NldElkAQxrZXlEdWNrQ2hhcnMBC2R1Y2tBc3NldElkCQCsAgICCmR1Y2tDaGFyc18FC2R1Y2tBc3NldElkAQlrZXlEdWNrWFABC2R1Y2tBc3NldElkCQCsAgICB2R1Y2tYUF8FC2R1Y2tBc3NldElkAQxrZXlEdWNrTGV2ZWwBC2R1Y2tBc3NldElkCQCsAgICCmR1Y2tMZXZlbF8FC2R1Y2tBc3NldElkARFrZXlEdWNrRnJlZVBvaW50cwELZHVja0Fzc2V0SWQJAKwCAgIPZHVja0ZyZWVQb2ludHNfBQtkdWNrQXNzZXRJZAEQa2V5RHVja0VxdWlwbWVudAELZHVja0Fzc2V0SWQJAKwCAgIOZHVja0VxdWlwbWVudF8FC2R1Y2tBc3NldElkAQlrZXlVc2VyWFABBGFkZHIJAKwCAgIHdXNlclhQXwUEYWRkcgEMa2V5VXNlckxldmVsAQRhZGRyCQCsAgICCnVzZXJMZXZlbF8FBGFkZHIBEWtleVVzZXJGcmVlUG9pbnRzAQRhZGRyCQCsAgICD3VzZXJGcmVlUG9pbnRzXwUEYWRkcgEOa2V5U2F2ZWRIZWFsdGgBC2R1Y2tBc3NldElkCQCsAgICDHNhdmVkSGVhbHRoXwULZHVja0Fzc2V0SWQBEGtleVNhdmVkTG9jYXRpb24BC2R1Y2tBc3NldElkCQCsAgICDnNhdmVkTG9jYXRpb25fBQtkdWNrQXNzZXRJZAEMa2V5RHVja0J1ZmZzAQtkdWNrQXNzZXRJZAkArAICAgpkdWNrQnVmZnNfBQtkdWNrQXNzZXRJZAEYa2V5TGFzdFJvYmJlcnlUaW1lQnlEdWNrAQtkdWNrQXNzZXRJZAkArAICAhBsYXN0Um9iYmVyeVRpbWVfBQtkdWNrQXNzZXRJZAETa2V5RHVja1JvYmJlcnlDb3VudAELZHVja0Fzc2V0SWQJAKwCAgIYdG90YWxSb2JiZXJ5Q291bnRCeUR1Y2tfBQtkdWNrQXNzZXRJZAETa2V5VXNlclJvYmJlcnlDb3VudAEEYWRkcgkArAICAhF1c2VyUm9iYmVyeUNvdW50XwUEYWRkcgEVa2V5VXNlckxhc3RSb2JiZXJ5RGF5AQRhZGRyCQCsAgICE3VzZXJMYXN0Um9iYmVyeURheV8FBGFkZHIBFGtleUR1Y2tEZWxpdmVyeUNvdW50AQtkdWNrQXNzZXRJZAkArAICAhl0b3RhbERlbGl2ZXJ5Q291bnRCeUR1Y2tfBQtkdWNrQXNzZXRJZAEUa2V5VXNlckRlbGl2ZXJ5Q291bnQBBGFkZHIJAKwCAgISdXNlckRlbGl2ZXJ5Q291bnRfBQRhZGRyARZrZXlVc2VyTGFzdERlbGl2ZXJ5RGF5AQRhZGRyCQCsAgICFHVzZXJMYXN0RGVsaXZlcnlEYXlfBQRhZGRyAAd4cENsYWltAJBOAA94cFN1Y2Nlc3NGbGlnaHQAkE4ADHhwRmFpbEZsaWdodADQDwAMeHBTdWNjZXNzUm9iAJBOAAl4cEZhaWxSb2IA0A8ACHhwQ2FsbEVTAKCNBgAMeHBDdXN0b21OYW1lAMCEPQAKeHBOZXdTTGFuZADAlrECAA54cFVwZ3JhZGVJbmZyYQCQTgAHeHBNZXJnZQDAhD0ACXhwT25ib2FyZADAhD0ABnhwSGVhbACQTgEJbGV2ZWxCeVhQAQJ4cAkAawMFDHhwTGV2ZWxTY2FsZQkAbAYFAnhwAAQFD3hwTGV2ZWxSZWNpcFBvdwAEAAQFBERPV04FBlNDQUxFOAEJbWF4SGVhbHRoAQVsZXZlbAkAZAIAZAUFbGV2ZWwBB2xldmVsVXACCWN1cnJMZXZlbAVuZXdYUAQIbmV3TGV2ZWwJAQlsZXZlbEJ5WFABBQVuZXdYUAkAzAgCBQhuZXdMZXZlbAkAzAgCCQBoAgUSbnVtUG9pbnRzT25MZXZlbFVwCQBlAgUIbmV3TGV2ZWwFCWN1cnJMZXZlbAUDbmlsAQxnZXREdWNrU3RhdHMED3N0YWtpbmdDb250cmFjdAtkdWNrQXNzZXRJZApidWZmRWZmZWN0CmZvcmNlQnVmZnMEBWNoYXJzCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUPc3Rha2luZ0NvbnRyYWN0CQEMa2V5RHVja0NoYXJzAQULZHVja0Fzc2V0SWQCCTBfMF8wXzBfMAIBXwQDbHZsCQELdmFsdWVPckVsc2UCCQCaCAIFD3N0YWtpbmdDb250cmFjdAkBDGtleUR1Y2tMZXZlbAEFC2R1Y2tBc3NldElkAAAEBmhlYWx0aAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ9zdGFraW5nQ29udHJhY3QJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQJAQltYXhIZWFsdGgBBQNsdmwECnN0YXRlQnVmZnMJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJAQxrZXlEdWNrQnVmZnMBBQtkdWNrQXNzZXRJZAIJMF8wXzBfMF8wAgFfCQDOCAIJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWNoYXJzBQxjaGFyU3RyZW5ndGgJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWNoYXJzBQxjaGFyQWNjdXJhY3kJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWNoYXJzBQ1jaGFySW50ZWxsZWN0CQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVjaGFycwUNY2hhckVuZHVyYW5jZQkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJEZXh0ZXJpdHkJAMwIAgUDbHZsCQDMCAIFBmhlYWx0aAUDbmlsAwUKZm9yY2VCdWZmcwkAzAgCBQpidWZmRWZmZWN0CQDMCAIFCmJ1ZmZFZmZlY3QJAMwIAgUKYnVmZkVmZmVjdAkAzAgCBQpidWZmRWZmZWN0CQDMCAIFCmJ1ZmZFZmZlY3QFA25pbAkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKc3RhdGVCdWZmcwUMY2hhclN0cmVuZ3RoCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpzdGF0ZUJ1ZmZzBQxjaGFyQWNjdXJhY3kJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCnN0YXRlQnVmZnMFDWNoYXJJbnRlbGxlY3QJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCnN0YXRlQnVmZnMFDWNoYXJFbmR1cmFuY2UJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCnN0YXRlQnVmZnMFDWNoYXJEZXh0ZXJpdHkFA25pbAAKTEFORFBSRUZJWAIETEFORAAKRFVDS1BSRUZJWAIERFVDSwALUk9CT19QUkVGSVgCBFJPQk8ACkFSVFBSRVNBTEUCB1BSRVNBTEUABk5VTVJFUwAGABhNQVhfTEFORFNfU1RBS0VEX0JZX1VTRVIAGQAPREFJTFlSRVNCWVBJRUNFAID40gEADFdITVVMVElQTElFUgCAyK+gJQAPREVGQVVMVExPQ0FUSU9OAg9BZnJpY2FfRl9BZnJpY2EAEFJFU09VUkNFUFJJQ0VNSU4A1bUCAApFU1NFTExDT0VGAAoAFU1JTl9VU0RUX0ZFRV9ERUxJVkVSWQDQhgMAEk1JTl9XTEdPTERfUk9CQkVSWQCAwtcvABZBTExPV0VEX0ZSRUVfUk9CQkVSSUVTAAAAGUFDUkVTX0ZPUl9ST0JCRVJZX0FUVEVNUFQAgISvXwAXQUxMT1dFRF9GUkVFX0RFTElWRVJJRVMAAAAaQUNSRVNfRk9SX0RFTElWRVJZX0FUVEVNUFQAgISvXwAJcHJvZFR5cGVzCQDMCAICEEZpcnN0IEFpZCBLaXQgTDEJAMwIAgIQRmlyc3QgQWlkIEtpdCBMMgkAzAgCAhBGaXJzdCBBaWQgS2l0IEwzCQDMCAICC0JhY2twYWNrIEwxCQDMCAICC0JhY2twYWNrIEwyCQDMCAICC0JhY2twYWNrIEwzCQDMCAICDkZvb2QgUmF0aW9uIEwxCQDMCAICDkZvb2QgUmF0aW9uIEwyCQDMCAICDkZvb2QgUmF0aW9uIEwzCQDMCAICC0pldCBQYWNrIEwxCQDMCAICC0pldCBQYWNrIEwyCQDMCAICC0pldCBQYWNrIEwzCQDMCAICCVNoaWVsZCBMMQkAzAgCAglTaGllbGQgTDIJAMwIAgIJU2hpZWxkIEwzCQDMCAICB01pbmUgTDEJAMwIAgIHTWluZSBMMgkAzAgCAgdNaW5lIEwzCQDMCAICB1RyYXAgTDEJAMwIAgIHVHJhcCBMMgkAzAgCAgdUcmFwIEwzCQDMCAICC0Jvb20tRG9nIEwxCQDMCAICC0Jvb20tRG9nIEwyCQDMCAICC0Jvb20tRG9nIEwzBQNuaWwACmNvbnRpbmVudHMJAMwIAgIIQW1lcmljYXMJAMwIAgIGRXVyb3BlCQDMCAICBEFzaWEJAMwIAgIGQWZyaWNhCQDMCAICB09jZWFuaWEFA25pbAAJQ09FRkYyTUFUAICt4gQAEHByb2R1Y3Rpb25NYXRyaXgJAMwIAgIlOF84XzhfMTdfMTdfNDJfMTJfMF8zMF8wLDAsMCwwLDAsMCwwXwkAzAgCAiU4XzhfOF8xN18xN180Ml8yNF8wXzYwXzAsMCw1LDIsMCwwLDBfCQDMCAICJzhfOF84XzE3XzE3XzQyXzM2XzBfMTIwXzAsMCwxMCw0LDAsMCwwXwkAzAgCAik4XzE5XzE5XzhfMjdfMTlfMjZfMV8yMF8wLDAsMCwwLDAsMCwwXzAwMQkAzAgCAik4XzE5XzE5XzhfMjdfMTlfNTJfMV80MF8wLDAsMCwwLDAsMCwwXzAwMQkAzAgCAik4XzE5XzE5XzhfMjdfMTlfNzhfMV84MF8wLDAsMCwwLDAsMCwwXzAwMQkAzAgCAiU4XzhfOF84XzhfNjBfMTNfMl8yXzAsMCwwLDAsMCwwLDBfMDExCQDMCAICJThfOF84XzhfOF82MF8yNl8yXzRfMCwwLDAsMCwwLDAsMF8wMTEJAMwIAgIlOF84XzhfOF84XzYwXzM5XzJfOF8wLDAsMCwwLDAsMCwwXzAxMQkAzAgCAikzMF8zMF8zXzE3XzE3XzNfMzBfM18zMF8wLDAsMCwwLDAsMCwwXzExMQkAzAgCAikzMF8zMF8zXzE3XzE3XzNfNjBfM181MF8wLDAsMCwwLDAsMCwwXzExMQkAzAgCAikzMF8zMF8zXzE3XzE3XzNfOTBfM183MF8wLDAsMCwwLDAsMCwwXzExMQkAzAgCAisxOF8xOF8xMF8xOF8xOF8xOF8xMV80XzEwXzAsMCwwLDAsMCwwLDBfMjAxCQDMCAICKzE4XzE4XzEwXzE4XzE4XzE4XzIyXzRfMjBfMCwwLDAsMCwwLDAsMF8yMDEJAMwIAgIrMThfMThfMTBfMThfMThfMThfMzNfNF8zMF8wLDAsMCwwLDAsMCwwXzIwMQkAzAgCAio0XzEzXzIyXzRfMzVfMjJfMjNfMF81MCwxLDBfMCwwLDAsMCwwLDAsMF8JAMwIAgIqNF8xM18yMl80XzM1XzIyXzQ2XzBfNTAsMSwxXzAsMiw1LDAsMCwwLDBfCQDMCAICKzRfMTNfMjJfNF8zNV8yMl82OV8wXzUwLDIsMV8wLDUsMTAsMCwwLDAsMF8JAMwIAgIqNV8yNV80MF81XzEwXzE1XzIwXzFfMzAsMSwxXzAsMCwwLDAsMCwwLDBfCQDMCAICKjVfMjVfNDBfNV8xMF8xNV80MF8xXzMwLDEsMl8yLDEsMywwLDAsMCwwXwkAzAgCAio1XzI1XzQwXzVfMTBfMTVfNjBfMV8zMCwxLDNfNSwyLDgsMCwwLDAsMF8JAMwIAgInMjNfMjNfNV8yMF8yM182XzM1XzJfMTAwXzAsMCwwLDAsMCwwLDBfCQDMCAICJzIzXzIzXzVfMjBfMjNfNl83MF8yXzE1MF8wLDAsMCwwLDAsMCwwXwkAzAgCAigyM18yM181XzIwXzIzXzZfMTA1XzJfMjAwXzAsMCwwLDAsMCwwLDBfBQNuaWwACXJJZHhDb2VmZgAGAApySWR4RWZmZWN0AAgAEHJJZHhSZXF1aXJlbWVudHMACQAJcklkeFNsb3RzAAoADlBST0RVQ1RQS0dTSVpFAAoAC3doSWR4TGV2ZWxzAAAACHdoSWR4UmVzAAEACHdoSWR4TWF0AAIACXdoSWR4UHJvZAADAAl3aElkeExPRlQABAAJdm9sTG9ja2VkAAAAC3ZvbE9jY3VwaWVkAAEAB3ZvbEZyZWUAAgAIdm9sVG90YWwAAwAKYnBJZHhMZXZlbAAAAAhicElkeFJlcwABAAhicElkeE1hdAACAAlicElkeFByb2QAAwAPbG9jSWR4Q29udGluZW50AAAACmxvY0lkeFR5cGUAAQAIbG9jSWR4SWQAAgEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQdhc3NldElkCQCsAgICA25vXwUHYXNzZXRJZAEaa2V5TGFuZEFzc2V0SWRUb0N1c3RvbU5hbWUBB2Fzc2V0SWQJAKwCAgIFbGNuYV8FB2Fzc2V0SWQBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgIDc3RfBQdhc3NldElkASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIEdHlwZQdhc3NldElkCQC5CQIJAMwIAgIDbGFzCQDMCAIFBHR5cGUJAMwIAgUHYXNzZXRJZAUDbmlsAgFfASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwduZnRUeXBlB2Fzc2V0SWQJb3duZXJBZGRyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIGc3R0YW9fBQduZnRUeXBlAgFfBQdhc3NldElkAgFfBQlvd25lckFkZHIBEmtleVdhcmVob3VzZUJ5TGFuZAELbGFuZEFzc2V0SWQJAKwCAgIDd2hfBQtsYW5kQXNzZXRJZAEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEHYXNzZXRJZAkArAICAgtpbmZyYUxldmVsXwUHYXNzZXRJZAEaa2V5RHVja0Fzc2V0SWRUb0N1c3RvbU5hbWUBB2Fzc2V0SWQJAKwCAgIYZHVja0N1c3RvbU5hbWVCeUFzc2V0SWRfBQdhc3NldElkARZrZXlBZGRyZXNzVG9DdXN0b21OYW1lAQRhZGRyCQCsAgICGGFjY291bnRDdXN0b21OYW1lQnlBZGRyXwUEYWRkcgEPa2V5QWRkcmVzc1JlZkJ5AQRhZGRyCQCsAgICCWFjY1JlZkJ5XwUEYWRkcgEca2V5T25ib2FyZEFydEFjdGl2YXRlZE9uRHVjawELZHVja0Fzc2V0SWQJAKwCAgIab25ib2FyZEFydEFjdGl2YXRlZE9uRHVja18FC2R1Y2tBc3NldElkARxrZXlPbmJvYXJkQXJ0RHVja0FjdGl2YXRlZEJ5AQRhZGRyCQCsAgICGm9uYm9hcmRBcnRBY3RpdmF0ZWREdWNrQnlfBQRhZGRyARNrZXlBZGRyZXNzUmVmZXJyYWxzAQRhZGRyCQCsAgICDWFjY1JlZmVycmFsc18FBGFkZHIBEGtleUR1Y2tJZFRvT3duZXIBB2Fzc2V0SWQJAKwCAgIKZHVja093bmVyXwUHYXNzZXRJZAEUa2V5U3Rha2VkRHVja0J5T3duZXIBCW93bmVyQWRkcgkArAICAhJzdGFrZWREdWNrQnlPd25lcl8FCW93bmVyQWRkcgERa2V5QmFja3BhY2tCeUR1Y2sBC2R1Y2tBc3NldElkCQCsAgICCWJhY2tQYWNrXwULZHVja0Fzc2V0SWQBD2tleUR1Y2tMb2NhdGlvbgELZHVja0Fzc2V0SWQJAKwCAgINZHVja0xvY2F0aW9uXwULZHVja0Fzc2V0SWQBFWtleVVzZXJHd2xSZWxlYXNlVGltZQEIdXNlckFkZHIJAKwCAgIaJXMlc19fdXNlckd3bFJlbGVhc2VUaW1lX18FCHVzZXJBZGRyAQ5rZXlFc1dhcmVob3VzZQACGmVtZXJnZW5jeVdhcmVob3VzZVByb2R1Y3RzAA9kZWxpdmVyeUZ1bmRLZXkCDGRlbGl2ZXJ5RnVuZAANbGFzdFRvdXJJZEtleQIOJXNfX2xhc3RUb3VySWQBFWtleVRvdXJTdGF0aWNEYXRhQnlJZAEDdElkCQCsAgICFiVzJWRfX3RvdXJTdGF0aWNEYXRhX18JAKQDAQUDdElkARZrZXlUb3VyRHluYW1pY0RhdGFCeUlkAQN0SWQJAKwCAgIXJXMlZF9fdG91ckR5bmFtaWNEYXRhX18JAKQDAQUDdElkARprZXlCZXN0UmVzdWx0QnlUb3VyQW5kRHVjawIDdElkC2R1Y2tBc3NldElkCQC5CQIJAMwIAgIfJXMlZCVzX19iZXN0UmVzdWx0QnlUb3VyQW5kRHVjawkAzAgCCQCkAwEFA3RJZAkAzAgCBQtkdWNrQXNzZXRJZAUDbmlsAgJfXwAJaWR4U3RhdGljAAAACmlkeER5bmFtaWMAAQAKdFN0YXRpY0VuZAAGAA50RHluYW1pY1N0YXR1cwABAQtnZXRUb3VyRGF0YQIMdG91ckNvbnRyYWN0A3RJZAQGc3RhdGljCQC1CQIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQx0b3VyQ29udHJhY3QJARVrZXlUb3VyU3RhdGljRGF0YUJ5SWQBBQN0SWQJAKwCAgkArAICAhlFcnJvciByZWFkaW5nIHRvdXJuYW1lbnQgCQCkAwEFA3RJZAIFIGRhdGECAl9fBAdkeW5hbWljCQC8CQIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQx0b3VyQ29udHJhY3QJARZrZXlUb3VyRHluYW1pY0RhdGFCeUlkAQUDdElkCQCsAgIJAKwCAgIZRXJyb3IgcmVhZGluZyB0b3VybmFtZW50IAkApAMBBQN0SWQCBSBkYXRhAgJfXwkAzAgCBQZzdGF0aWMJAMwIAgUHZHluYW1pYwUDbmlsAQ5pc0luVG91cm5hbWVudAIMdG91ckNvbnRyYWN0CGxvY2F0aW9uBAZsYXN0SWQJAQt2YWx1ZU9yRWxzZQIJAJoIAgUMdG91ckNvbnRyYWN0BQ1sYXN0VG91cklkS2V5AAAEA2xvYwkAtQkCBQhsb2NhdGlvbgIBXwQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQFdERhdGEJAQtnZXRUb3VyRGF0YQIFDHRvdXJDb250cmFjdAUGbGFzdElkBAZzdGF0aWMJAJEDAgUFdERhdGEFCWlkeFN0YXRpYwQHZHluYW1pYwkAkQMCBQV0RGF0YQUKaWR4RHluYW1pYwMDAwkAAAIJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAgFUCQAAAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFA2xvYwUPbG9jSWR4Q29udGluZW50BQZsYXN0SWQHCQAAAgkAkQMCBQdkeW5hbWljBQ50RHluYW1pY1N0YXR1cwIKSU5QUk9HUkVTUwcJAGYCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGc3RhdGljBQp0U3RhdGljRW5kBQNub3cHAQlvbk1pc3Npb24CDHRvdXJDb250cmFjdAhsb2NhdGlvbgQGbGFzdElkCQELdmFsdWVPckVsc2UCCQCaCAIFDHRvdXJDb250cmFjdAUNbGFzdFRvdXJJZEtleQAABANsb2MJALUJAgUIbG9jYXRpb24CAV8EA25vdwgFCWxhc3RCbG9jawl0aW1lc3RhbXAEBXREYXRhCQELZ2V0VG91ckRhdGECBQx0b3VyQ29udHJhY3QFBmxhc3RJZAQGc3RhdGljCQCRAwIFBXREYXRhBQlpZHhTdGF0aWMEB2R5bmFtaWMJAJEDAgUFdERhdGEFCmlkeER5bmFtaWMEB2xvY1R5cGUJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAwMDCQAAAgkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCAVQJAAACCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUDbG9jBQ9sb2NJZHhDb250aW5lbnQFBmxhc3RJZAcJAAACCQCRAwIFB2R5bmFtaWMFDnREeW5hbWljU3RhdHVzAgpJTlBST0dSRVNTBwkAZgIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZzdGF0aWMFCnRTdGF0aWNFbmQFA25vdwcBEmdldFJlY2lwZU1hdGVyaWFscwEGcmVjaXBlCQBoAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBnJlY2lwZQUJcklkeENvZWZmBQlDT0VGRjJNQVQBDGNoZWF0QXR0ZW1wdAMGb2xkTG9jBm5ld0xvYwljaGVhdENhc2UJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIWQ2hlYXQgYXR0ZW1wdDogb2xkTG9jPQUGb2xkTG9jAgksIG5ld0xvYz0FBm5ld0xvYwIHLCBjYXNlPQkApAMBBQljaGVhdENhc2UAFktTX1NFUEFSQVRFX1BVQkxJQ19LRVkHABhLU19BTExPV19CSUdfSU5GUkFfTUVSR0UHABNLU19BTExPV19ST0JPX0RVQ0tTBwAKREFZX01JTExJUwCAuJkpAAVjaGFpbgkAyQECCQDKAQIIBQR0aGlzBWJ5dGVzAAEAAQADcHViBAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwAwUWS1NfU0VQQVJBVEVfUFVCTElDX0tFWQEgqxdXjxVn41lUQbDWcutmm8Sj02Ze1ZmGUN+YNx+yCQgBIE9T4ho/VKjWnVJOEx1GJ1W9s1PzLHvJVFSw/0PBtBQoAwkAAAIBAVQFByRtYXRjaDABIE9T4ho/VKjWnVJOEx1GJ1W9s1PzLHvJVFSw/0PBtBQoCQACAQINVW5rbm93biBjaGFpbgALdXNkdEFzc2V0SWQEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDABIITaerIIAz9O0bvKju6Lk7zJgt0LXfoHlqjUI/moD/+5AwkAAAIBAVQFByRtYXRjaDABIFWx2J9yh4Lv5eNbjawFq2XemkOhLxa7BfMat4el8cUYCQACAQINVW5rbm93biBjaGFpbgAVZGVmYXVsdFJlc3RBZGRyZXNzU3RyBAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwAiMzUFFDdXZGYnZoNExrUFVucm5VMXozam5iQTFwOW0zV05odgMJAAACAQFUBQckbWF0Y2gwAiMzTXVta0dHenRDS0FYcFdEcXhrZGRvZnFYU1VicVFrdlNKeQkAAgECDVVua25vd24gY2hhaW4AEUluZnJhVXBncmFkZUNvc3RTBAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwAIDIr6AlAwkAAAIBAVQFByRtYXRjaDAAgMLXLwkAAgECDVVua25vd24gY2hhaW4ADmFyYml0cmFnZURlbGF5BAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwBQpEQVlfTUlMTElTAwkAAAIBAVQFByRtYXRjaDAA4NQDCQACAQINVW5rbm93biBjaGFpbgADU0VQAgJfXwAFTVVMVDYAwIQ9AAVNVUxUOACAwtcvAAVTU0laRQAZAAVNU0laRQBkAAVMU0laRQDhAQAGWExTSVpFAJADAAdYWExTSVpFAPEEAAVJVEVSNgkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsAQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFB2FkZHJlc3MJAMwIAgIBLgkAzAgCBQNrZXkJAMwIAgIPIGlzIG5vdCBkZWZpbmVkBQNuaWwCAAARSWR4Q2ZnU3Rha2luZ0RhcHAAAQARSWR4Q2ZnRWNvbm9teURhcHAAAgAUSWR4Q2ZnR292ZXJuYW5jZURhcHAAAwANSWR4Q2ZnV2xnRGFwcAAEABRJZHhDZmdUb3VybmFtZW50RGFwcAAHAA9JZHhDZmdBY3Jlc0RhcHAACAEKa2V5UmVzdENmZwACDiVzX19yZXN0Q29uZmlnAQ5rZXlSZXN0QWRkcmVzcwACDCVzX19yZXN0QWRkcgERcmVhZFJlc3RDZmdPckZhaWwBBHJlc3QJALwJAgkBD2dldFN0cmluZ09yRmFpbAIFBHJlc3QJAQprZXlSZXN0Q2ZnAAUDU0VQARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCB3Jlc3RDZmcDaWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKYIAQkAkQMCBQdyZXN0Q2ZnBQNpZHgJAKwCAgIqUmVzdCBjZmcgZG9lc24ndCBjb250YWluIGFkZHJlc3MgYXQgaW5kZXggCQCkAwEFA2lkeAAMcmVzdENvbnRyYWN0CQERQGV4dHJOYXRpdmUoMTA2MikBCQELdmFsdWVPckVsc2UCCQCdCAIFBHRoaXMJAQ5rZXlSZXN0QWRkcmVzcwAFFWRlZmF1bHRSZXN0QWRkcmVzc1N0cgAHcmVzdENmZwkBEXJlYWRSZXN0Q2ZnT3JGYWlsAQUMcmVzdENvbnRyYWN0AA9zdGFraW5nQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQdyZXN0Q2ZnBRFJZHhDZmdTdGFraW5nRGFwcAAPZWNvbm9teUNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwURSWR4Q2ZnRWNvbm9teURhcHAAC2dvdkNvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwUUSWR4Q2ZnR292ZXJuYW5jZURhcHAAC3dsZ0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwUNSWR4Q2ZnV2xnRGFwcAASdG91cm5hbWVudENvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwUUSWR4Q2ZnVG91cm5hbWVudERhcHAADWFjcmVzQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQdyZXN0Q2ZnBQ9JZHhDZmdBY3Jlc0RhcHAACnJlY0xhbmROdW0AAAALcmVjTGFuZFNpemUAAQALcmVjVGVycmFpbnMAAgAMcmVjQ29udGluZW50AAMADXdsZ0Fzc2V0SWRLZXkCC3dsZ19hc3NldElkAAp3bGdBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJwIAgULd2xnQ29udHJhY3QFDXdsZ0Fzc2V0SWRLZXkCGFdMR09MRCBpcyBub3QgaXNzdWVkIHlldAAPYWNyZXNBc3NldElkS2V5AgxhY3Jlc0Fzc2V0SWQADGFjcmVzQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCcCAIFDWFjcmVzQ29udHJhY3QFD2FjcmVzQXNzZXRJZEtleQIXQUNSRVMgaXMgbm90IGlzc3VlZCB5ZXQAC3JhbmRvbURlbGF5AAIBCWtleUNvbW1pdAEHYWRkcmVzcwkArAICAg9maW5pc2hCbG9ja0Zvcl8FB2FkZHJlc3MBEWtleVJlc1Byb3BvcnRpb25zAAITcmVzVHlwZXNQcm9wb3J0aW9ucwEWa2V5UmVzVHlwZXNCeUNvbnRpbmVudAEJY29udGluZW50CQCsAgICFHJlc1R5cGVzQnlDb250aW5lbnRfBQljb250aW5lbnQBFWtleVN0YWtlZExhbmRzQnlPd25lcgEJb3duZXJBZGRyCQCsAgICE3N0YWtlZExhbmRzQnlPd25lcl8FCW93bmVyQWRkcgEWa2V5U3Rha2VkUGllY2VzQnlPd25lcgEJb3duZXJBZGRyCQCsAgICFHN0YWtlZFBpZWNlc0J5T3duZXJfBQlvd25lckFkZHIBCGFzU3RyaW5nAQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACBlN0cmluZwQBcwUHJG1hdGNoMAUBcwkAAgECGGZhaWwgdG8gY2FzdCBpbnRvIFN0cmluZwEFYXNJbnQBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIDSW50BAFuBQckbWF0Y2gwBQFuCQACAQIVZmFpbCB0byBjYXN0IGludG8gSW50AQlhc0FueUxpc3QBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIJTGlzdFtBbnldBAFsBQckbWF0Y2gwBQFsCQACAQIbZmFpbCB0byBjYXN0IGludG8gTGlzdFtBbnldAQlhc0Jvb2xlYW4BAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIHQm9vbGVhbgQBcwUHJG1hdGNoMAUBcwkAAgECGWZhaWwgdG8gY2FzdCBpbnRvIEJvb2xlYW4BD251bVBpZWNlc0J5U2l6ZQEIbGFuZFNpemUEByRtYXRjaDAFCGxhbmRTaXplAwkAAAICAVMFByRtYXRjaDAFBVNTSVpFAwkAAAICAU0FByRtYXRjaDAFBU1TSVpFAwkAAAICAUwFByRtYXRjaDAFBUxTSVpFAwkAAAICAlhMBQckbWF0Y2gwBQZYTFNJWkUDCQAAAgIDWFhMBQckbWF0Y2gwBQdYWExTSVpFCQACAQIRVW5rbm93biBsYW5kIHNpemUBB2lzRGlnaXQBAXMJAQlpc0RlZmluZWQBCQC2CQEFAXMBCmtleUJsb2NrZWQAAhBjb250cmFjdHNCbG9ja2VkARFrZXlMYXN0VHhJZEJ5VXNlcgEEYWRkcgkArAICAg9sYXN0VHhJZEJ5VXNlcl8FBGFkZHIBCmZpeGVkUG9pbnQCA3ZhbAhkZWNpbWFscwQGdGVuUG93CQBsBgAKAAAFCGRlY2ltYWxzAAAAAAUERE9XTgQHbG93UGFydAkApAMBCQBqAgUDdmFsBQZ0ZW5Qb3cEBnplcm9lcwkAsAICCQCkAwEFBnRlblBvdwkAZAIAAQkAsQIBBQdsb3dQYXJ0CQCsAgIJAKwCAgkArAICCQCkAwEJAGkCBQN2YWwFBnRlblBvdwIBLgUGemVyb2VzBQdsb3dQYXJ0AQ9nZXRSYW5kb21OdW1iZXIDCG1heFZhbHVlBHNhbHQHZW50cm9weQMJAGcCAAAFCG1heFZhbHVlCQACAQIWbWF4VmFsdWUgc2hvdWxkIGJlID4gMAQKcmFuZG9tSGFzaAkA9wMBCQDLAQIFBHNhbHQFB2VudHJvcHkJAGoCCQCxCQEFCnJhbmRvbUhhc2gFCG1heFZhbHVlAA1pbmN1YmF0b3JBZGRyBAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzUEVrdFZ1eDJSaGNoU042M0RzRG80YjRtejRRcXpLU2VEdgMJAAACAQFUBQckbWF0Y2gwBQR0aGlzCQACAQINVW5rbm93biBjaGFpbgALYnJlZWRlckFkZHIEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQRFZ1VTQ1SDdFaDVkbXROYm5STlJTdEd3VUxBN05ZNkhiAwkAAAIBAVQFByRtYXRjaDAFBHRoaXMJAAIBAg1Vbmtub3duIGNoYWluABFGSVZFTUlOVVRFU01JTExJUwDgpxIADFJFTkFNSU5HQ09TVADAlrECAApNQVhOQU1FTEVOADIAFUluZnJhVXBncmFkZUNvc3RTVXNkdACAreIEAAxFWFBNQVRFUklBTFMEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAApt2C7asHAwkAAAIBAVQFByRtYXRjaDAAqqeBswkJAAIBAg1Vbmtub3duIGNoYWluAAdFWFBVU0RUBAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwAIDlmncDCQAAAgEBVAUHJG1hdGNoMACA5Zp3CQACAQINVW5rbm93biBjaGFpbgAOUk9CT19EVUNLX1VTRFQAoI0GAAxTX0NPU1RfQUNSRVMAgPKLqAkABUZJVkVYCQC2AgEABQAHVFdFTlRZWAkAtgIBABQACFRXRU5UWTJYCQC2AgEJAGgCABQAFAAIVFdFTlRZM1gJALYCAQkAaAIJAGgCABQAFAAUAAhUV0VOVFk0WAkAtgIBCQBoAgkAaAIJAGgCABQAFAAUABQACFRXRU5UWTVYCQC2AgEJAGgCCQBoAgkAaAIJAGgCABQAFAAUABQAFAAPUFJFU0FMRU5VTUxBTkRTAPQDARJrZXlOZXh0RnJlZUxhbmROdW0AAgtuZXh0TGFuZE51bQEaa2V5TGFuZEN1c3RvbU5hbWVUb0Fzc2V0SWQBBG5hbWUJAKwCAgIEbGNuXwUEbmFtZQEQa2V5TGFuZFRvQXNzZXRJZAEHbGFuZE51bQkArAICAgNsYV8FB2xhbmROdW0BHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIHYXNzZXRJZAlvd25lckFkZHIJAKwCAgkArAICCQCsAgICBWlsYW9fBQdhc3NldElkAgFfBQlvd25lckFkZHIBEWtleUxhbmROdW1Ub093bmVyAQdsYW5kTnVtCQCsAgICA2xvXwUHbGFuZE51bQEaa2V5RHVja0N1c3RvbU5hbWVUb0Fzc2V0SWQBBG5hbWUJAKwCAgIRZHVja0J5Q3VzdG9tTmFtZV8FBG5hbWUBFmtleUN1c3RvbU5hbWVUb0FkZHJlc3MBBG5hbWUJAKwCAgIUYWNjb3VudEJ5Q3VzdG9tTmFtZV8FBG5hbWUBCWtleU9sZGllcwACCm9sZGllc0xpc3QBD2tleU5leHRSb2JvRHVjawACDG5leHRSb2JvRHVjawALY2xhaW1Nb2RlV2gAAAANY2xhaW1Nb2RlRHVjawABABNjbGFpbU1vZGVXaFRoZW5EdWNrAAIACGZsSGVhbHRoAAAAC2ZsVGltZXN0YW1wAAUAB2ZsQm9udXMABgALZmxQcm9kc1VzZWQABwAIcmxIZWFsdGgAAAALcmxQcm9kc1VzZWQAAQAGcmxUeXBlAAAACHJsTGFzdFR4AAIAC3JsVGltZXN0YW1wAAMBB25mdE5hbWUCB2xhbmROdW0IbGFuZFNpemUJAKwCAgkArAICBQpMQU5EUFJFRklYBQdsYW5kTnVtBQhsYW5kU2l6ZQEIdG9Wb2x1bWUCBmFtb3VudAdwa2dTaXplBARwa2dzAwkAZwIFBmFtb3VudAAACQBpAgkAZQIJAGQCBQZhbW91bnQFB3BrZ1NpemUAAQUHcGtnU2l6ZQkBAS0BCQBpAgkAZQIJAGQCCQEBLQEFBmFtb3VudAUHcGtnU2l6ZQABBQdwa2dTaXplCQBoAgUEcGtncwUFTVVMVDgBE2Rpc3RyaWJ1dGVCeVdlaWdodHMCBXRvdGFsB3dlaWdodHMEA3N1bQkAZAIJAGQCCQBkAgkAZAIJAGQCCQCRAwIFB3dlaWdodHMAAAkAkQMCBQd3ZWlnaHRzAAEJAJEDAgUHd2VpZ2h0cwACCQCRAwIFB3dlaWdodHMAAwkAkQMCBQd3ZWlnaHRzAAQJAJEDAgUHd2VpZ2h0cwAFAwkAZwIAAAUDc3VtCQACAQIQWmVybyB3ZWlnaHRzIHN1bQQFbm9ybTYJAGsDBQV0b3RhbAUFTVVMVDYFA3N1bQoBCm5vcm1hbGl6ZXICA2FjYwRlbGVtCQDNCAIFA2FjYwkAawMFBGVsZW0FBW5vcm02BQVNVUxUNgoAAiRsBQd3ZWlnaHRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpub3JtYWxpemVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGARJnZXROZWVkZWRNYXRlcmlhbHMBBXRvdGFsBAVwcm9wcwkAtQkCCQEFdmFsdWUBCQCiCAEJARFrZXlSZXNQcm9wb3J0aW9ucwACAV8DCQECIT0CCQCQAwEFBXByb3BzBQZOVU1SRVMJAAIBAhZXcm9uZyBwcm9wb3J0aW9ucyBkYXRhBAFyCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAACQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwABCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwACCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwADCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAECQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAFBQNuaWwJARNkaXN0cmlidXRlQnlXZWlnaHRzAgUFdG90YWwFAXIBEXN1YnRyYWN0TWF0ZXJpYWxzAwxzaG91bGRVc2VNYXQDaGFzCXRvdGFsTmVlZAQEbmVlZAkBEmdldE5lZWRlZE1hdGVyaWFscwEFCXRvdGFs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Uk9ESU5TTE9UCQACAQkArAICCQCsAgIJAKwCAgIUQ2FuJ3QgcHV0IG1vcmUgdGhhbiAJAKQDAQUNTUFYUFJPRElOU0xPVAIEIG9mIAkAkQMCBQlwcm9kVHlwZXMFCnByb2R1Y3RJZHgDCQAAAgUFY291bnQAAAkAlAoCBQVwTGlzdAcEBGhlYWQJAMkBAgUFcExpc3QJAGgCAAgFCnByb2R1Y3RJZHgEBGN1cnIJALEJAQkAyQECCQDKAQIFBXBMaXN0CQBoAgAIBQpwcm9kdWN0SWR4AAgEBHRhaWwJAMoBAgUFcExpc3QJAGgCAAgJAGQCBQpwcm9kdWN0SWR4AAEEBnJlY2lwZQkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgFCnByb2R1Y3RJZHgCAV8DAwkBASEBBQppc1Bvc2l0aXZlCQBmAgUFY291bnQFBGN1cnIHCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCVlvdSBoYXZlIAkApAMBBQRjdXJyAgQgb2YgCQCRAwIFCXByb2RUeXBlcwUKcHJvZHVjdElkeAITLCBidXQgdHJpZWQgdG8gdXNlIAkApAMBBQVjb3VudAQJaXNCaWdJdGVtAwMJAQEhAQUKaXNQb3NpdGl2ZQkBFWNoZWNrU3RhdFJlcXVpcmVtZW50cwIFCWR1Y2tTdGF0cwkAtQkCCQCRAwIFBnJlY2lwZQUQcklkeFJlcXVpcmVtZW50cwIBLAcEBmNvbXBhdAkAkQMCBQZyZWNpcGUFCXJJZHhTbG90cwMJAAACBQZjb21wYXQCAAkAAgECF0l0ZW0gY2Fubm90IGJlIGVxdWlwcGVkBAFjCQENcGFyc2VJbnRWYWx1ZQEFBmNvbXBhdAQEY1NlZwkAaQIFAWMAZAMJAQIhPQIFB3NlZ21lbnQFBGNTZWcJAAIBAhRTZWdtZW50IGluY29tcGF0aWJsZQQIY01haW5BdXgJAGkCCQBqAgUBYwBkAAoDCQECIT0CBQdtYWluQXV4BQhjTWFpbkF1eAkAAgECEVNsb3QgaW5jb21wYXRpYmxlBAljTnVtU2xvdHMJAGoCBQFjAAoDAwkBAiE9AgUEc2xvdAAACQBmAgUJY051bVNsb3RzAAEHCQACAQIeQmlnIGl0ZW1zIHNob3VsZCBvY2N1cHkgc2xvdCAwCQBmAgUJY051bVNsb3RzAAEHCQCUCgIJAMsBAgkAywECBQRoZWFkCQCaAwEJAGQCBQRjdXJyAwUKaXNQb3NpdGl2ZQUFY291bnQJAQEtAQUFY291bnQFBHRhaWwFCWlzQmlnSXRlbQELc2xvdHNHcm91cEIGAWcEYnBJbgppc1Bvc2l0aXZlB3NlZ21lbnQHbWFpbkF1eAVzdGF0cwMJAQIhPQIFAWcCAAQFc2xvdHMJALUJAgUBZwIBLAMJAGYCCQCQAwEFBXNsb3RzBQhNQVhTTE9UUwkAAgECEldyb25nIHNsb3RzIGZvcm1hdAQCczAJAJEDAgUFc2xvdHMAAAQCczEDCQBmAgkAkAMBBQVzbG90cwABCQCRAwIFBXNsb3RzAAECAAMDCQAAAgUCczACAAkAAAIFAnMxAgAHBQRicEluBAV0bXBTMAMJAQIhPQIFAnMwAgAJAQhhZGRQcm9kQgcFAnMwBQRicEluBQppc1Bvc2l0aXZlBQdzZWdtZW50BQdtYWluQXV4AAAFBXN0YXRzCQCUCgIFBGJwSW4HAwkBAiE9AgUCczECAAMIBQV0bXBTMAJfMgkAAgECHkJpZyBpdGVtIGFscmVhZHkgb2NjdXBpZXMgc2xvdAgJAQhhZGRQcm9kQgcFAnMxCAUFdG1wUzACXzEFCmlzUG9zaXRpdmUFB3NlZ21lbnQFB21haW5BdXgAAQUFc3RhdHMCXzEIBQV0bXBTMAJfMQUEYnBJbgEGZHJlc3NCBAdzZWdMaXN0BnBCeXRlcwppc1Bvc2l0aXZlBXN0YXRzCgEHc2VnbWVudAIDYWNjA3NlZwQBaggFA2FjYwJfMQQHbWFpbkF1eAkAtQkCBQNzZWcCATsDCQECIT0CCQCQAwEFB21haW5BdXgFCk5VTU1BSU5BVVgJAAIBAhRXcm9uZyBzZWdtZW50IGZvcm1hdAQBbQkAkQMCBQdtYWluQXV4AAAEAWEJAJEDAgUHbWFpbkF1eAABAwMJAAACBQFtAgAJAAACBQFhAgAHCQCUCgIJAGQCBQFqAAEIBQNhY2MCXzIEBHRtcE0JAQtzbG90c0dyb3VwQgYFAW0IBQNhY2MCXzIFCmlzUG9zaXRpdmUFAWoAAAUFc3RhdHMJAJQKAgkAZAIFAWoAAQkBC3Nsb3RzR3JvdXBCBgUBYQUEdG1wTQUKaXNQb3NpdGl2ZQUBagABBQVzdGF0cwgKAAIkbAUHc2VnTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgAABQZwQnl0ZXMKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3NlZ21lbnQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYCXzIBF2NhbldlYXJDdXJyZW50RXF1aXBtZW50AQtkdWNrQXNzZXRJZAQFZXFLZXkJARBrZXlEdWNrRXF1aXBtZW50AQULZHVja0Fzc2V0SWQEBmN1cnJFcQkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFBWVxS2V5AhcsOyxfLDssXyw7LF8sOyxfLDssXyw7LAIBXwQMRU1QVFlfUFJPRDUwAZADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQJdGVtcFByb2RCCQEGZHJlc3NCBAUGY3VyckVxBQxFTVBUWV9QUk9ENTAGBQNuaWwECHNlZ0JwQXV4CQCRAwIJALUJAgkAkQMCBQZjdXJyRXEFC3NlZ0JhY2twYWNrAgE7AAEECmJ1ZmZFZmZlY3QDCQAAAgUIc2VnQnBBdXgCAAAABARhdXgwCQCRAwIJALUJAgUIc2VnQnBBdXgCASwAAAMJAAACBQRhdXgwAgAAAAQGaWR4Q250CQC1CQIFBGF1eDACAToEA2lkeAkAkQMCBQZpZHhDbnQAAAQDY250CQCRAwIFBmlkeENudAABAwMDAwMJAAACBQNpZHgCAjA2BgkAAAIFA2lkeAICMDcGCQAAAgUDaWR4AgIwOAkBAiE9AgUDY250AgAHCQBmAgkBDXBhcnNlSW50VmFsdWUBBQNjbnQAAAcJAQ1wYXJzZUludFZhbHVlAQkAkQMCCQC1CQIJAJEDAgUQcHJvZHVjdGlvbk1hdHJpeAkBDXBhcnNlSW50VmFsdWUBBQNpZHgCAV8FCnJJZHhFZmZlY3QAAAQFc3RhdHMJAQxnZXREdWNrU3RhdHMEBQR0aGlzBQtkdWNrQXNzZXRJZAUKYnVmZkVmZmVjdAYECG5ld1Byb2RCCQEGZHJlc3NCBAUGY3VyckVxBQl0ZW1wUHJvZEIHBQVzdGF0cwkAAAIFCG5ld1Byb2RCBQhuZXdQcm9kQgEZdXBkYXRlUHJvcG9ydGlvbnNJbnRlcm5hbAQIcHJvcExpc3QNdGVycmFpbkNvdW50cw1sYW5kU2l6ZUluZGV4BHNpZ24DCQECIT0CCQCQAwEFCHByb3BMaXN0BQZOVU1SRVMJAAIBAhZXcm9uZyBwcm9wb3J0aW9ucyBkYXRhCgEHdXBkYXRlcgIDYWNjAWkEBnJlc3VsdAkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhwcm9wTGlzdAUBaQkAaAIJAGgCBQRzaWduCQCRAwIFDXRlcnJhaW5Db3VudHMFAWkFDWxhbmRTaXplSW5kZXgDCQBmAgAABQZyZXN1bHQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICFlBhbmljISBQaWVjZXMgb2YgdHlwZT0JAKQDAQUBaQIHLCBzaWduPQkApAMBBQRzaWduAhMsIHRlcnJhaW5Db3VudHNbaV09CQCkAwEJAJEDAgUNdGVycmFpbkNvdW50cwUBaQIQLCBsYW5kU2l6ZUluZGV4PQkApAMBBQ1sYW5kU2l6ZUluZGV4CQDNCAIFA2FjYwkApAMBBQZyZXN1bHQKAAIkbAUFSVRFUjYKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3VwZGF0ZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYBEXVwZGF0ZVByb3BvcnRpb25zAw10ZXJyYWluQ291bnRzDWxhbmRTaXplSW5kZXgEc2lnbgQIcHJvcExpc3QJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBCQERa2V5UmVzUHJvcG9ydGlvbnMAAgswXzBfMF8wXzBfMAIBXwkAuQkCCQEZdXBkYXRlUHJvcG9ydGlvbnNJbnRlcm5hbAQFCHByb3BMaXN0BQ10ZXJyYWluQ291bnRzBQ1sYW5kU2l6ZUluZGV4BQRzaWduAgFfAQ1jb3VudFRlcnJhaW5zAQh0ZXJyYWlucwkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFBAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBQgABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUMAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFEAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBRQABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUYAAQUDbmlsAQZhZGRSZXMFCmN1cnJlbnRSZXMNdGVycmFpbkNvdW50cwlkZWx0YVRpbWUNbGFuZFNpemVJbmRleBdkYWlseUJ5UGllY2VXaXRoQm9udXNlcwoBBWFkZGVyAgNhY2MBaQQJcmVzT2ZUeXBlCQBoAgkAaAIJAGsDBQlkZWx0YVRpbWUFF2RhaWx5QnlQaWVjZVdpdGhCb251c2VzBQlEQVlNSUxMSVMJAJEDAgUNdGVycmFpbkNvdW50cwUBaQUNbGFuZFNpemVJbmRleAkAzQgCBQNhY2MJAKQDAQkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpjdXJyZW50UmVzBQFpBQlyZXNPZlR5cGUEAXIKAAIkbAUFSVRFUjYKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBWFkZGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGCQC5CQIFAXICAV8BCXZpcnRDbGFpbQQNdGVycmFpbkNvdW50cwlkZWx0YVRpbWUNbGFuZFNpemVJbmRleBdkYWlseUJ5UGllY2VXaXRoQm9udXNlcwoBBWFkZGVyAgNhY2MBaQQJcmVzT2ZUeXBlCQBoAgkAaAIJAGsDBQlkZWx0YVRpbWUFF2RhaWx5QnlQaWVjZVdpdGhCb251c2VzBQlEQVlNSUxMSVMJAJEDAgUNdGVycmFpbkNvdW50cwUBaQUNbGFuZFNpemVJbmRleAkAlAoCCQDNCAIIBQNhY2MCXzEFCXJlc09mVHlwZQkAZAIIBQNhY2MCXzIFCXJlc09mVHlwZQoAAiRsBQVJVEVSNgoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBWFkZGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAQ1kaXN0cmlidXRlUmVzBAxjdXJyZW50V2hSZXMOY3VycmVudFBhY2tSZXMKcmVzVG9DbGFpbQt3aFNwYWNlTGVmdAQOcmVzTGlzdFRvQ2xhaW0IBQpyZXNUb0NsYWltAl8xBAxyZXNBbVRvQ2xhaW0IBQpyZXNUb0NsYWltAl8yAwkAAAIFDHJlc0FtVG9DbGFpbQAACQCUCgIJALkJAgUMY3VycmVudFdoUmVzAgFfCQC5CQIFDmN1cnJlbnRQYWNrUmVzAgFfAwkAZwIFC3doU3BhY2VMZWZ0BQxyZXNBbVRvQ2xhaW0KAQhhZGRMaXN0cwIDYWNjAWkJAM0IAgUDYWNjCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUMY3VycmVudFdoUmVzBQFpCQCRAwIFDnJlc0xpc3RUb0NsYWltBQFpBAFyCgACJGwFBUlURVI2CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQhhZGRMaXN0cwIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgkAlAoCCQC5CQIFAXICAV8JALkJAgUOY3VycmVudFBhY2tSZXMCAV8KAQxhZGRQYXJ0TGlzdHMCA2FjYwFpBAZ3aFBhcnQJAGsDCQCRAwIFDnJlc0xpc3RUb0NsYWltBQFpBQt3aFNwYWNlTGVmdAUMcmVzQW1Ub0NsYWltCQCUCgIJAM0IAggFA2FjYwJfMQkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDGN1cnJlbnRXaFJlcwUBaQUGd2hQYXJ0CQDNCAIIBQNhY2MCXzIJAKQDAQkAZQIJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOY3VycmVudFBhY2tSZXMFAWkJAJEDAgUOcmVzTGlzdFRvQ2xhaW0FAWkFBndoUGFydAQBcgoAAiRsBQVJVEVSNgoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRz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dmFsdWVPckVsc2UCCQCiCAEFBWJwS2V5AhowOjBfMF8wXzBfMF8wOjBfMF8wXzBfMF8wOgIBOgkAzAgCCQCkAwEJAQt2YWx1ZU9yRWxzZQIJALYJAQkAkQMCBQFwBQpicElkeExldmVsAAAJAMwIAgMJAAACCQCQAwEJALUJAgkAkQMCBQFwBQhicElkeFJlcwIBXwUGTlVNUkVTCQCRAwIFAXAFCGJwSWR4UmVzAgswXzBfMF8wXzBfMAkAzAgCAwkAAAIJAJADAQkAtQkCCQCRAwIFAXAFCGJwSWR4TWF0AgFfBQZOVU1SRVMJAJEDAgUBcAUIYnBJZHhNYXQCCzBfMF8wXzBfMF8wCQDMCAIJAJEDAgUBcAUJYnBJZHhQcm9kBQNuaWwBF2dldFdhcmVob3VzZVRvdGFsVm9sdW1lAQl2b2xQcmVmaXgEBXBhcnRzCQC1CQIFCXZvbFByZWZpeAIBXwkAaAIJAGgCBQxXSE1VTFRJUExJRVIJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAQABCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAAEXZ2V0V2FyZWhvdXNlT2NjdXBpZWRWb2wBCWN1cnJlbnRXaAQFZ29vZHMJAJEDAgUJY3VycmVudFdoBQl3aElkeFByb2QKAQlzdW1SZXNNYXQCA2FjYwRpdGVtCQBkAgUDYWNjCQENcGFyc2VJbnRWYWx1ZQEFBGl0ZW0KAQdzdW1Qcm9kAgNhY2MEaXRlbQQDaWR4CAUDYWNjAl8xBARwa2dzCQBpAgkAZQIJAGQCCQENcGFyc2VJbnRWYWx1ZQEFBGl0ZW0FDlBST0RVQ1RQS0dTSVpFAAEFDlBST0RVQ1RQS0dTSVpFCQCUCgIJAGQCBQNpZHgAAQkAZAIIBQNhY2MCXzIJAGgCBQRwa2dzBQVNVUxUOAQId2hSZXNWb2wKAAIkbAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMCAV8KAAIkcwkAkAMBBQIkbAoABSRhY2MwAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCXN1bVJlc01hdAIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIT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CQCkAwEJAGUCCQBlAgUHd2hUb3RhbAUId2hMb2NrZWQFA29jYwkAzAgCCQCkAwEFB3doVG90YWwFA25pbAIBXwkAzAgCCQCRAwIFAndoBQt3aElkeExldmVscwkAzAgCAwkAAAIJAJADAQkAtQkCCQCRAwIFAndoBQh3aElkeFJlcwIBXwUGTlVNUkVTCQCRAwIFAndoBQh3aElkeFJlcwILMF8wXzBfMF8wXzAJAMwIAgMJAAACCQCQAwEJALUJAgkAkQMCBQJ3aAUId2hJZHhNYXQCAV8FBk5VTVJFUwkAkQMCBQJ3aAUId2hJZHhNYXQCCzBfMF8wXzBfMF8wCQDMCAIJAJEDAgUCd2gFCXdoSWR4UHJvZAkAzAgCBQZ3aExvZnQFA25pbAEVZ2V0V2FyZWhvdXNlU3BhY2VMZWZ0AQljdXJyZW50V2gEC29jY3VwaWVkVm9sCQEXZ2V0V2FyZWhvdXNlT2NjdXBpZWRWb2wBBQljdXJyZW50V2gED2N1cnJXaExvY2tlZFZvbAkBDXBhcnNlSW50VmFsdWUBCQCRAwIJALUJAgkAkQMCBQljdXJyZW50V2gFCXdoSWR4TE9GVAIBXwUJdm9sTG9ja2VkCQBlAgkAZQIJARdnZXRXYXJlaG91c2VUb3RhbFZvbHVtZQEJAJEDAgUJY3VycmVudFdoBQt3aElkeExldmVscwULb2NjdXBpZWRWb2wFD2N1cnJXaExvY2tlZFZvbAEJbW92ZVN0dWZmAwpjYXJnb1BhcnRzCWN1cnJlbnRXaAtjdXJyZW50UGFjawMJAQIhPQIJAJADAQUKY2FyZ29QYXJ0cwADCQACAQI0Y2FyZ29MaXN0U3RyIHNob3VsZCBjb250YWluIGV4YWN0bHkgMiAnOicgc2VwYXJhdG9ycwQIcmVzUGFydHMJALUJAgkAkQMCBQpjYXJnb1BhcnRzAAACAV8ECG1hdFBhcnRzCQC1CQIJAJEDAgUKY2FyZ29QYXJ0cwABAgFfBAlwcm9kUGFydHMDCQAAAgkAkQMCBQpjYXJnb1BhcnRzAAICAAUDbmlsCQC8CQIJAJEDAgUKY2FyZ29QYXJ0cwACAgFfAwkBAiE9AgkAkAMBBQhyZXNQYXJ0cwUGTlVNUkVTCQACAQIgQWxsIDYgcmVzb3VyY2VzIHNob3VsZCBiZSBwYXNzZWQDCQECIT0CCQCQAwEFCG1hdFBhcnRzBQZOVU1SRVMJAAIBAiBBbGwgNiBtYXRlcmlhbHMgc2hvdWxkIGJlIHBhc3NlZAQLd2hTcGFjZUxlZnQJARVnZXRXYXJlaG91c2VTcGFjZUxlZnQBBQljdXJyZW50V2gECWN1cnJXaFJlcwkAtQkCCQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMCAV8ECWN1cnJXaE1hdAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUId2hJZHhNYXQCAV8ECmN1cnJXaFByb2QDCQAAAgkAkQMCBQljdXJyZW50V2gFCXdoSWR4UHJvZAIABQNuaWwJALwJAgkAkQMCBQljdXJyZW50V2gFCXdoSWR4UHJvZAIBXwQOY3VycmVudFBhY2tSZXMJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMCAV8EDmN1cnJlbnRQYWNrTWF0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBA9jdXJyZW50UGFja1Byb2QDCQAAAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kAgAFA25pbAkAvAkCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QCAV8KAQNtdlICA2FjYwRpdGVtBAFpCAUDYWNjAl8xBAJhbQkBDXBhcnNlSW50VmFsdWUBBQRpdGVtBAN3aHIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQljdXJyV2hSZXMFAWkEA2JwcgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmN1cnJlbnRQYWNrUmVzBQFpAwkAAAIFAmFtAAAJAJYKBAkAZAIFAWkAAQkAzQgCCAUDYWNjAl8yCQCRAwIFCWN1cnJXaFJlcwUBaQkAzQgCCAUDYWNjAl8zCQCRAwIFDmN1cnJlbnRQYWNrUmVzBQFpCAUDYWNjAl80AwkAZgIFAmFtAAADCQBmAgUCYW0FA2JwcgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgIQQXR0ZW1wdCB0byB0YWtlIAUEaXRlbQIZIGZyb20gYmFja3BhY2ssIGJ1dCBvbmx5IAkApAMBBQNicHICCiBhdmFpbGFibGUJAJYKBAkAZAIFAWkAAQkAzQgCCAUDYWNjAl8yCQCkAwEJAGQC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ZUxhbmROdW0ACQBkAgUPUFJFU0FMRU5VTUxBTkRTAAEEB2xhbmROdW0JAKQDAQUHZnJlZU51bQQMY29udGluZW50SWR4CQCgAwEJALsCAgUGYmlnTnVtBQVGSVZFWAQIdGVycmFpbnMJAQtnZW5UZXJyYWlucwIFBmJpZ051bQUMY29udGluZW50SWR4BAljb250aW5lbnQJAJEDAgUKY29udGluZW50cwUMY29udGluZW50SWR4BAVpc3N1ZQkAwggFCQEHbmZ0TmFtZQIFB2xhbmROdW0CAVMJALkJAgkAzAgCBQdsYW5kTnVtCQDMCAICAVMJAMwIAgUIdGVycmFpbnMJAMwIAgUJY29udGluZW50BQNuaWwCAV8AAQAABwQHYXNzZXRJZAkAuAgBBQVpc3N1ZQQCaWQJANgEAQUHYXNzZXRJZAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESa2V5TmV4dEZyZWVMYW5kTnVtAAkAZAIFB2ZyZWVOdW0AAQkAzAgCBQVpc3N1ZQkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5TGFuZFRvQXNzZXRJZAEFB2xhbmROdW0FAmlkCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQJpZAUIdXNlckFkZHIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleUxhbmROdW1Ub093bmVyAQUHbGFuZE51bQUIdXNlckFkZHIJAMwIAgkBDEludGVnZXJFbnRyeQIJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQUCaWQAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIFAmlkBQh1c2VyQWRkcgAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFBmNhbGxlcgABBQdhc3NldElkBQNuaWwJAJQKAgUCaWQFCWNvbnRpbmVudAEMZmxpZ2h0Q29tbW9uAwh1c2VyQWRkcgdtZXNzYWdlA3NpZwMJAQEhAQkAxBMDBQdtZXNzYWdlBQNzaWcFA3B1YgkAAgECGHNpZ25hdHVyZSBkb2VzIG5vdCBtYXRjaAQFcGFydHMJALwJAgkAsAkBBQdtZXNzYWdlAgE7BAlmbGlnaHRMb2cJALwJAgkAkQMCBQVwYXJ0cwAAAgF8BAJocAkAtQkCCQCRAwIFCWZsaWdodExvZwUIZmxIZWFsdGgCAV8EBWN1ckhQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaHAAAAQFbmV3SFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAABBAtuZXdMb2NUeFZlcgkAtQkCCQCRAwIFBXBhcnRzAAECAToEC25ld0xvY2F0aW9uCQCRAwIFC25ld0xvY1R4VmVyAAAEBHRpbWUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlmbGlnaHRMb2cFC2ZsVGltZXN0YW1wAwMJAGYCBQR0aW1lCQBkAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFEUZJVkVNSU5VVEVTTUlMTElTBgkAZgIJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMFBHRpbWUJAAIBCQCsAgIJAKwCAgkArAICAhxzaWduYXR1cmUgb3V0ZGF0ZWQ6IGxvZ1RpbWU9CQCkAwEFBHRpbWUCCSwgYmNUaW1lPQkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQJdHhGcm9tTXNnCQCRAwIFC25ld0xvY1R4VmVyAAEEBmxhc3RUeAkBC3ZhbHVlT3JFbHNlAgkAoggBCQERa2V5TGFzdFR4SWRCeVVzZXIBBQh1c2VyQWRkcgIAAwkBAiE9AgUGbGFzdFR4BQl0eEZyb21Nc2cJAAIBCQCsAgIJAKwCAgkArAICAh5UeCBpZHMgZG9uJ3QgbWF0Y2ghIEluIHN0YXRlOiAFBmxhc3RUeAIKLCBpbiBtc2c6IAUJdHhGcm9tTXNnBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFCHVzZXJBZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQEBW1heEhQCQEJbWF4SGVhbHRoAQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEMa2V5RHVja0xldmVsAQULZHVja0Fzc2V0SWQAAAQMb2xkRnJvbVN0YXRlCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aAUFbWF4SFADCQECIT0CBQxvbGRGcm9tU3RhdGUFBWN1ckhQCQACAQkArAICCQCsAgIJAKwCAgIKb2xkSGVhbHRoPQkApAMBBQxvbGRGcm9tU3RhdGUCLyBmcm9tIHN0YXRlIGRvZXMgbm90IG1hdGNoIG9uZSBmcm9tIGZsaWdodCBsb2c9CQCkAwEFBWN1ckhQAwkAZwIAAAUFY3VySFAJAAIBAh5Zb3UgY2FuJ3QgZmx5IHdpdGggemVybyBoZWFsdGgDCQEBIQEJARdjYW5XZWFyQ3VycmVudEVxdWlwbWVudAEFC2R1Y2tBc3NldElkCQACAQIWRXF1aXBtZW50IGluY29tcGF0aWJsZQQFYm9udXMDCQBmAgkAkAMBBQlmbGlnaHRMb2cFB2ZsQm9udXMJAJEDAgUJZmxpZ2h0TG9nBQdmbEJvbnVzAgAECHByb2RVc2VkAwkAZgIJAJADAQUJZmxpZ2h0TG9nBQtmbFByb2RzVXNlZAkAkQMCBQlmbGlnaHRMb2cFC2ZsUHJvZHNVc2VkAgAECnNlbnRBbW91bnQDAwkAZgIFBW5ld0hQAAAJAAACBQVib251cwIBJAcJAQVhc0ludAEJAPwHBAUMcmVzdENvbnRyYWN0Ag1zZW5kVXNkdFByaXplCQDMCAIFCHVzZXJBZGRyBQNuaWwFA25pbAAACQCXCgUFBW5ld0hQBQtkdWNrQXNzZXRJZAUKc2VudEFtb3VudAULbmV3TG9jYXRpb24FCHByb2RVc2VkAQxhcHBseUJvbnVzZXMCC2xhbmRBc3NldElkBnBpZWNlcwQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAECWFydFBpZWNlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAAABARhZGQ2CQBpAgUKaW5mcmFMZXZlbAAGBARhZGQ3CQBpAgUKaW5mcmFMZXZlbAAHCQBkAgkAZAIFD0RBSUxZUkVTQllQSUVDRQkAawMFD0RBSUxZUkVTQllQSUVDRQkAZAIJAGQCBQppbmZyYUxldmVsBQRhZGQ2CQBoAgACBQRhZGQ3AAUJAGsDBQ9EQUlMWVJFU0JZUElFQ0UFCWFydFBpZWNlcwkAaAIFBnBpZWNlcwAFARRjaGVja0NsYWltQ29uZGl0aW9ucwMEYWRkcgljbGFpbU1vZGUNbGFuZEFzc2V0SWRJbgQNJHQwMzM2NzgzNDIxNwMJAAACBQljbGFpbU1vZGUFC2NsYWltTW9kZVdoCQCUCgIFDWxhbmRBc3NldElkSW4JAQt2YWx1ZU9yRWxzZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIABAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OBANsb2MJALUJAgkBBXZhbHVlAQULY3VyTG9jYXRpb24CAV8DCQECIT0CCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIBTAkAAgEJAKwCAgkArAICAhZEdWNrIGxvY2F0aW9uIHR5cGUgaXMgCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIRLCBidXQgc2hvdWxkIGJlIEwJAJQKAgkAkQMCBQNsb2MFCGxvY0lkeElkBQtkdWNrQXNzZXRJZAQLbGFuZEFzc2V0SWQIBQ0kdDAzMzY3ODM0MjE3Al8xBAZkdWNrSWQIBQ0kdDAzMzY3ODM0MjE3Al8yBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBAlzYXZlZFRpbWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBQd0aW1lS2V5CQCsAgIJAKwCAgIFTGFuZCAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfCQCWCgQFBmR1Y2tJZAULbGFuZEFzc2V0SWQFAWQFCXNhdmVkVGltZQEQY2xhaW1SZXNJbnRlcm5hbAQEYWRkcgZhbW91bnQJY2xhaW1Nb2RlDWxhbmRBc3NldElkSW4DCQBmAgAABQZhbW91bnQJAAIBAg9OZWdhdGl2ZSBhbW91bnQEAWMJARRjaGVja0NsYWltQ29uZGl0aW9ucwMFBGFkZHIFCWNsYWltTW9kZQUNbGFuZEFzc2V0SWRJbgQIbGFuZFNpemUJAJEDAggFAWMCXzMFC3JlY0xhbmRTaXplBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAggFAWMCXzMFC3JlY1RlcnJhaW5zBAlkZWx0YVRpbWUJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAgFAWMCXzQDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBCAUBYwJfNAIMLCBjdXJyZW50ID0gCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBBQhsYW5kU2l6ZQQWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkBDGFwcGx5Qm9udXNlcwIIBQFjAl8yBQZwaWVjZXMECGF2YWlsUmVzCQBrAwUJZGVsdGFUaW1lCQBoAgUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQUGcGllY2VzBQlEQVlNSUxMSVMDCQBmAgUGYW1vdW50BQhhdmFpbFJlcwkAAgEJAKwCAgkArAICCQCsAgICIk5vdCBlbm91Z2ggcmVzb3VyY2VzLCBhdmFpbGFibGUgPSAJAKQDAQUIYXZhaWxSZXMCDiwgcmVxdWVzdGVkID0gCQCkAwEFBmFtb3VudAQMbmV3RGVsdGFUaW1lCQBrAwkAZQIFCGF2YWlsUmVzBQZhbW91bnQFCURBWU1JTExJUwkAaAIFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UFBnBpZWNlcwQMbmV3VGltZXN0YW1wCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFDG5ld0RlbHRhVGltZQQJbGFuZEluZGV4CQBpAgUGcGllY2VzBQVTU0laRQQKcmVzVG9DbGFpbQkBCXZpcnRDbGFpbQQFDXRlcnJhaW5Db3VudHMJAGUCBQlkZWx0YVRpbWUFDG5ld0RlbHRhVGltZQUJbGFuZEluZGV4BRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBAV3aEtleQkBEmtleVdhcmVob3VzZUJ5TGFuZAEIBQFjAl8yBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQgFAWMCXzIAAAQJY3VycmVudFdoCQEMZ2V0V2FyZWhvdXNlAwUFd2hLZXkFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAQEbG9mdAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhMT0ZUAgFfBAt3aFNwYWNlTGVmdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUDAwkAAAIFCWNsYWltTW9kZQULY2xhaW1Nb2RlV2gJAGYCBQZhbW91bnQFC3doU3BhY2VMZWZ0BwkAAgEJAKwCAgkArAICAgVPbmx5IAkApAMBBQt3aFNwYWNlTGVmdAIYIHNwYWNlIGxlZnQgaW4gd2FyZWhvdXNlBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQgFAWMCXzEEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQOY3VycmVudFBhY2tSZXMJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMCAV8EDGN1cnJlbnRXaFJlcwkAtQkCCQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMCAV8EDSR0MDM2NTkxMzc0NjIDCQAAAgUJY2xhaW1Nb2RlBQtjbGFpbU1vZGVXaAkAlgoECQEGYWRkUmVzBQUMY3VycmVudFdoUmVzBQ10ZXJyYWluQ291bnRzCQBlAgUJZGVsdGFUaW1lBQxuZXdEZWx0YVRpbWUFCWxhbmRJbmRleAUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAULdm9sT2NjdXBpZWQIBQpyZXNUb0NsYWltAl8yCQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUIBQpyZXNUb0NsYWltAl8yAwkAAAIFCWNsYWltTW9kZQUNY2xhaW1Nb2RlRHVjawkAlgoECQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMJAQZhZGRSZXMFBQ5jdXJyZW50UGFja1JlcwUNdGVycmFpbkNvdW50cwkAZQIFCWRlbHRhVGltZQUMbmV3RGVsdGFUaW1lBQlsYW5kSW5kZXgFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUEBWRpc3RyCQENZGlzdHJpYnV0ZVJlcwQFDGN1cnJlbnRXaFJlcwUOY3VycmVudFBhY2tSZXMFCnJlc1RvQ2xhaW0FC3doU3BhY2VMZWZ0BAR3aEFtCQCXAwEJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUJAMwIAggFCnJlc1RvQ2xhaW0CXzIFA25pbAkAlgoECAUFZGlzdHICXzEIBQVkaXN0cgJfMgkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAUEd2hBbQkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQd2b2xGcmVlBQR3aEFtBAV3aFJlcwgFDSR0MDM2NTkxMzc0NjICXzEEBWJwUmVzCAUNJHQwMzY1OTEzNzQ2MgJfMgQFbG9mdE8IBQ0kdDAzNjU5MTM3NDYyAl8zBAVsb2Z0RggFDSR0MDM2NTkxMzc0NjICXzQJAJcKBQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBCAUBYwJfMgUMbmV3VGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgIBQFjAl8yBQRhZGRyBQxuZXdUaW1lc3RhbXAFA25pbAUFYnBLZXkJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCBQVicFJlcwkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAUFd2hLZXkJAMwIAgkAkQMCBQljdXJyZW50V2gFC3doSWR4TGV2ZWxzCQDMCAIFBXdoUmVzCQDMCAIJAJEDAgUJY3VycmVudFdoBQh3aElkeE1hdAkAzAgCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kCQDMCAIJALkJAgkAzAgCCQCRAwIFBGxvZnQFCXZvbExvY2tlZAkAzAgCCQCkAwEFBWxvZnRPCQDMCAIJAKQDAQUFbG9mdEYJAMwIAgkAkQMCBQRsb2Z0BQh2b2xUb3RhbAUDbmlsAgFfBQNuaWwBCGNsYWltQWxsBARhZGRyC2xhbmRBc3NldElkBnBpZWNlcwljbGFpbU1vZGUEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBBXZhbHVlAQkAnwgBBQd0aW1lS2V5BAhhdmFpbFJlcwkAaAIJAGsDCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFCXNhdmVkVGltZQkBDGFwcGx5Qm9udXNlcwIFC2xhbmRBc3NldElkBQZwaWVjZXMFCURBWU1JTExJUwUGcGllY2VzCQEQY2xhaW1SZXNJbnRlcm5hbAQFBGFkZHIFCGF2YWlsUmVzBQljbGFpbU1vZGUFC2xhbmRBc3NldElkAQ11cEluZnJhQ29tbW9uBAxzaG91bGRVc2VNYXQGY2FsbGVyDXBheW1lbnRBbW91bnQLbGFuZEFzc2V0SWQEBGFkZHIJAKUIAQUGY2FsbGVyBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMDBQRhZGRyBRNjbGFpbU1vZGVXaFRoZW5EdWNrBQtsYW5kQXNzZXRJZAQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUECGluZnJhS2V5CQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEIBQFjAl8yBAhjdXJMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQhpbmZyYUtleQAAAwMJAQEhAQUYS1NfQUxMT1dfQklHX0lORlJBX01FUkdFCQBnAgUIY3VyTGV2ZWwAAwcJAAIBAiZDdXJyZW50bHkgbWF4IGluZnJhc3RydWN0dXJlIGxldmVsID0gMwQIbWF4SW5mcmEJAGQCCQBpAgkBBHNxcnQEBQZwaWVjZXMAAAAABQRET1dOAAUAAgQIbmV3TGV2ZWwJAGQCBQhjdXJMZXZlbAABAwMFGEtTX0FMTE9XX0JJR19JTkZSQV9NRVJHRQkAZgIFCG5ld0xldmVsBQhtYXhJbmZyYQcJAAIBCQCsAgICJUN1cnJlbnRseSBtYXggaW5mcmFzdHJ1Y3R1cmUgbGV2ZWwgPSAJAKQDAQUIbWF4SW5mcmEEBGNvc3QJAGsDBRVJbmZyYVVwZ3JhZGVDb3N0U1VzZHQJAGgCBQZwaWVjZXMFCG5ld0xldmVsBQVTU0laRQMDCQEBIQEFDHNob3VsZFVzZU1hdAkBAiE9AgUNcGF5bWVudEFtb3VudAUEY29zdAcJAAIBCQCsAgICG1BheW1lbnQgYXR0YWNoZWQgc2hvdWxkIGJlIAkApAMBBQRjb3N0BAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQgFAWMCXzEEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQFbUxpc3QJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8EB21hdFVzZWQJAGsDBRFJbmZyYVVwZ3JhZGVDb3N0UwkAaAIFBnBpZWNlcwUIbmV3TGV2ZWwFBVNTSVpFBAZuZXdNYXQJALkJAgkBEXN1YnRyYWN0TWF0ZXJpYWxzAwUMc2hvdWxkVXNlTWF0BQVtTGlzdAUHbWF0VXNlZAIBXwQLY2xhaW1SZXN1bHQJAQhjbGFpbUFsbAQFBGFkZHIIBQFjAl8yBQZwaWVjZXMFE2NsYWltTW9kZVdoVGhlbkR1Y2sEBndoRGF0YQgFC2NsYWltUmVzdWx0Al81BAZvbGRWb2wJARdnZXRXYXJlaG91c2VUb3RhbFZvbHVtZQEJAJEDAgUGd2hEYXRhBQt3aElkeExldmVscwQKbmV3Vm9sRGF0YQkAuQkCCQDMCAIJAJEDAgkAtQkCCQCRAwIFBndoRGF0YQULd2hJZHhMZXZlbHMCAV8AAAkAzAgCCQCkAwEFCG5ld0xldmVsBQNuaWwCAV8EBm5ld1ZvbAkBF2dldFdhcmVob3VzZVRvdGFsVm9sdW1lAQUKbmV3Vm9sRGF0YQQEbG9mdAkAtQkCCQCRAwIFBndoRGF0YQUJd2hJZHhMT0ZUAgFfBApuZXdMb2Z0U3RyCQC5CQIJAMwIAgkAkQMCBQRsb2Z0BQl2b2xMb2NrZWQJAMwIAgkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAkAzAgCCQCkAwEJAGUCCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUFBm5ld1ZvbAUGb2xkVm9sCQDMCAIJAKQDAQUGbmV3Vm9sBQNuaWwCAV8JAJUKAwkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQhpbmZyYUtleQUIbmV3TGV2ZWwJAMwIAgkBDEludGVnZXJFbnRyeQIJAR5rZXlJbmZyYUxldmVsQnlBc3NldElkQW5kT3duZXICCAUBYwJfMgUEYWRkcgUIbmV3TGV2ZWwJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALkJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJAJEDAggFC2NsYWltUmVzdWx0Al8zBQhicElkeFJlcwkAzAgCBQZuZXdNYXQJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kBQNuaWwCAToJAMwIAgkBC1N0cmluZ0VudHJ5AggFC2NsYWltUmVzdWx0Al80CQC5CQIJAMwIAgUKbmV3Vm9sRGF0YQkAzAgCCQCRAwIFBndoRGF0YQUId2hJZHhSZXMJAMwIAgkAkQMCBQZ3aERhdGEFCHdoSWR4TWF0CQDMCAIJAJEDAgUGd2hEYXRhBQl3aElkeFByb2QJAMwIAgUKbmV3TG9mdFN0cgUDbmlsAgE6BQNuaWwIBQtjbGFpbVJlc3VsdAJfMQUIbmV3TGV2ZWwFB21hdFVzZWQBE3VwZGF0ZVN0YXRzSW50ZXJuYWwEBmx2bEtleQV4cEtleQlwb2ludHNLZXkHZGVsdGFYUAQCeHAJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUFeHBLZXkAAAQFbmV3WFAJAGQCBQJ4cAUHZGVsdGFYUAQJbHZsUG9pbnRzCQEHbGV2ZWxVcAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUGbHZsS2V5AAAFBW5ld1hQCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFBmx2bEtleQkAkQMCBQlsdmxQb2ludHMAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgUFeHBLZXkFBW5ld1hQCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlwb2ludHNLZXkJAGQCCQELdmFsdWVPckVsc2UCCQCfCAEFCXBvaW50c0tleQAACQCRAwIFCWx2bFBvaW50cwABBQNuaWwFBW5ld1hQARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAILZHVja0Fzc2V0SWQHZGVsdGFYUAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtkdWNrQXNzZXRJZAQEYWRkcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARBrZXlEdWNrSWRUb093bmVyAQULZHVja0Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwMDBRNLU19BTExPV19ST0JPX0RVQ0tTCQAAAggFBWFzc2V0Bmlzc3VlcgUEdGhpcwcJAQhjb250YWlucwIIBQVhc3NldARuYW1lBQtST0JPX1BSRUZJWAcJARN1cGRhdGVTdGF0c0ludGVybmFsBAkBDGtleVVzZXJMZXZlbAEFBGFkZHIJAQlrZXlVc2VyWFABBQRhZGRyCQERa2V5VXNlckZyZWVQb2ludHMBBQRhZGRyBQdkZWx0YVhQCQETdXBkYXRlU3RhdHNJbnRlcm5hbAQJAQxrZXlEdWNrTGV2ZWwBBQtkdWNrQXNzZXRJZAkBCWtleUR1Y2tYUAEFC2R1Y2tBc3NldElkCQERa2V5RHVja0ZyZWVQb2ludHMBBQtkdWNrQXNzZXRJZAUHZGVsdGFYUAEWdXBkYXRlQWNjU3RhdHNJbnRlcm5hbAIEYWRkcgdkZWx0YVhQCQETdXBkYXRlU3RhdHNJbnRlcm5hbAQJAQxrZXlVc2VyTGV2ZWwBBQRhZGRyCQEJa2V5VXNlclhQAQUEYWRkcgkBEWtleVVzZXJGcmVlUG9pbnRzAQUEYWRkcgUHZGVsdGFYUAESYWN0aXZhdGVPbmJvYXJkQXJ0AQRhZGRyBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECHJlZkJ5S2V5CQEPa2V5QWRkcmVzc1JlZkJ5AQUEYWRkcgQFcmVmQnkJAKIIAQUIcmVmQnlLZXkDCQEBIQEJAQlpc0RlZmluZWQBBQVyZWZCeQkAAgECKVlvdSBhcmUgbm90IGVsaWdpYmxlIGZvciBPTkJPQVJEIGFydGlmYWN0BAZhcnRLZXkJARxrZXlPbmJvYXJkQXJ0RHVja0FjdGl2YXRlZEJ5AQUEYWRkcgQHYXJ0RHVjawkAoggBBQZhcnRLZXkDCQEJaXNEZWZpbmVkAQUHYXJ0RHVjawkAAgEJAKwCAgIvWW91IGFscmVhZHkgdXNlZCB5b3VyIE9OQk9BUkQgYXJ0aWZhY3Qgb24gZHVjayAJAQV2YWx1ZQEFB2FydER1Y2sEEGR1Y2tBY3RpdmF0b3JLZXkJARxrZXlPbmJvYXJkQXJ0QWN0aXZhdGVkT25EdWNrAQULZHVja0Fzc2V0SWQEDWR1Y2tBY3RpdmF0b3IJAKIIAQUQZHVja0FjdGl2YXRvcktleQMJAQlpc0RlZmluZWQBBQ1kdWNrQWN0aXZhdG9yCQACAQkArAICCQCsAgIJAKwCAgIJVGhlIGR1Y2sgBQtkdWNrQXNzZXRJZAI0IGFscmVhZHkgZ290IHBvaW50cyBmcm9tIE9OQk9BUkQgYXJ0aWZhY3QgZnJvbSB1c2VyIAkBBXZhbHVlAQUNZHVja0FjdGl2YXRvcgkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBmFydEtleQULZHVja0Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgUQZHVja0FjdGl2YXRvcktleQUEYWRkcgUDbmlsCAkBF3VwZGF0ZUR1Y2tTdGF0c0ludGVybmFsAgULZHVja0Fzc2V0SWQFCXhwT25ib2FyZAJfMQESYWN0aXZhdGVQcmVzYWxlQXJ0AgRhZGRyDWxhbmRBc3NldElkSW4EAWMJARRjaGVja0NsYWltQ29uZGl0aW9ucwMFBGFkZHIFE2NsYWltTW9kZVdoVGhlbkR1Y2sFDWxhbmRBc3NldElkSW4EC2xhbmRBc3NldElkCAUBYwJfMgQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUEDWFjdGl2YXRpb25LZXkJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkAwkAZgIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUNYWN0aXZhdGlvbktleQAAAAAJAAIBAiVQcmVzYWxlIGFydGlmYWN0IGlzIGFscmVhZHkgYWN0aXZhdGVkAwkAZgIJAQ1wYXJzZUludFZhbHVlAQkAkQMCCAUBYwJfMwUKcmVjTGFuZE51bQUPUFJFU0FMRU5VTUxBTkRTCQACAQkArAICCQCsAgIJAKwCAgUKTEFORFBSRUZJWAIBIAULbGFuZEFzc2V0SWQCJSBpcyBub3QgZWxpZ2libGUgZm9yIHByZXNhbGUgYXJ0aWZhY3QEC2NsYWltUmVzdWx0CQEIY2xhaW1BbGwEBQRhZGRyBQtsYW5kQXNzZXRJZAUGcGllY2VzBRNjbGFpbU1vZGVXaFRoZW5EdWNrCQDNCAIJAM0IAgkAzQgCCAULY2xhaW1SZXN1bHQCXzEJAQxJbnRlZ2VyRW50cnkCBQ1hY3RpdmF0aW9uS2V5BQZwaWVjZXMJAQtTdHJpbmdFbnRyeQIIBQtjbGFpbVJlc3VsdAJfMgkAuQkCCAULY2xhaW1SZXN1bHQCXzMCAToJAQtTdHJpbmdFbnRyeQIIBQtjbGFpbVJlc3VsdAJfNAkAuQkCCAULY2xhaW1SZXN1bHQCXzUCAToBD2NoZWNrVG91cm5hbWVudAELZHVja0Fzc2V0SWQEBmxhc3RJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBRJ0b3VybmFtZW50Q29udHJhY3QFDWxhc3RUb3VySWRLZXkAAAQLY3VyTG9jYXRpb24JALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQFD0RFRkFVTFRMT0NBVElPTgIBXwQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQFdERhdGEJAQtnZXRUb3VyRGF0YQIFEnRvdXJuYW1lbnRDb250cmFjdAUGbGFzdElkBAZzdGF0aWMJAJEDAgUFdERhdGEFCWlkeFN0YXRpYwQHZHluYW1pYwkAkQMCBQV0RGF0YQUKaWR4RHluYW1pYwMJAQIhPQIJAJEDAgULY3VyTG9jYXRpb24FCmxvY0lkeFR5cGUCAVQHAwMDCQAAAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFC2N1ckxvY2F0aW9uBQ9sb2NJZHhDb250aW5lbnQFBmxhc3RJZAkAAAIJAJEDAgUHZHluYW1pYwUOdER5bmFtaWNTdGF0dXMCCklOUFJPR1JFU1MHCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBnN0YXRpYwUKdFN0YXRpY0VuZAUDbm93BwkAAgECKllvdXIgZHVjayBpcyB0YWtpbmcgcGFydCBpbiB0aGUgdG91cm5hbWVudAkBCWFzQm9vbGVhbgEJAPwHBAUEdGhpcwIWZXhpdFRvdXJuYW1lbnRJbnRlcm5hbAkAzAgCBQtkdWNrQXNzZXRJZAUDbmlsBQNuaWwBDW1lcmdlSW50ZXJuYWwGC25ld0xhbmRTaXplCG5ld0xldmVsB2Zvcm11bGEEYWRkcgxsYW5kQXNzZXRJZHMHbmVlZE1hdAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkAwkBD2NoZWNrVG91cm5hbWVudAEFC2R1Y2tBc3NldElkCQACAQIdbWVyZ2VJbnRlcm5hbF9jaGVja1RvdXJuYW1lbnQKAQpjaGVja01lcmdlAgNhY2MLbGFuZEFzc2V0SWQEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQULbGFuZEFzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFB3RpbWVLZXkJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMJAQIhPQIFBW93bmVyBQRhZGRyCQACAQkArAICBQpMQU5EUFJFRklYAg0gaXMgbm90IHlvdXJzBAFkCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwQJY29udGluZW50CQCRAwIFAWQFDHJlY0NvbnRpbmVudAMDCQECIT0CCAUDYWNjAl8zAgAJAQIhPQIIBQNhY2MCXzMFCWNvbnRpbmVudAcJAAIBAi5MYW5kcyBzaG91bGQgYmUgb24gdGhlIHNhbWUgY29udGluZW50IHRvIG1lcmdlBAhsYW5kU2l6ZQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQQHc2l6ZXNJbggFA2FjYwJfMQQBaQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCzCQIFB3NpemVzSW4FCGxhbmRTaXplAidZb3UgaGF2ZW4ndCBwYXNzZWQgYWxsIHRoZSBsYW5kcyBuZWVkZWQECHNpemVzT3V0CQCsAgIJAK8CAgUHc2l6ZXNJbgUBaQkAsAICBQdzaXplc0luCQBkAgUBaQABBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBBQhsYW5kU2l6ZQQEYXJ0cwkAZAIIBQNhY2MCXzIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQULbGFuZEFzc2V0SWQAAAQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAECHJlcUxldmVsBAckbWF0Y2gwBQhsYW5kU2l6ZQMJAAACAgFTBQckbWF0Y2gwAAMDCQAAAgIBTQUHJG1hdGNoMAAEAwkAAAICAUwFByRtYXRjaDAABQMJAAACAgJYTAUHJG1hdGNoMAAGCQACAQIaT25seSBTLCBNLCBMLCBYTCBjYW4gbWVyZ2UDCQECIT0CBQppbmZyYUxldmVsBQhyZXFMZXZlbAkAAgECIkFsbCBsYW5kcyBzaG91bGQgYmUgbWF4ZWQgdG8gbWVyZ2UEB2xhbmROdW0JAJEDAgUBZAUKcmVjTGFuZE51bQQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIFAWQFC3JlY1RlcnJhaW5zBAlkZWx0YVRpbWUJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUJc2F2ZWRUaW1lAwkAZgIAAAUJZGVsdGFUaW1lCQACAQkArAICCQCsAgIJAKwCAgImU2F2ZWQgdGltZXN0YW1wIGlzIGluIGZ1dHVyZSwgc2F2ZWQgPSAJAKQDAQUJc2F2ZWRUaW1lAgwsIGN1cnJlbnQgPSAJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAEFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UJAQxhcHBseUJvbnVzZXMCBQtsYW5kQXNzZXRJZAUGcGllY2VzBAlsYW5kSW5kZXgJAGkCBQZwaWVjZXMFBVNTSVpFBAVicFJlcwkBBmFkZFJlcwUJALUJAggFA2FjYwJfNAIBXwUNdGVycmFpbkNvdW50cwUJZGVsdGFUaW1lBQlsYW5kSW5kZXgFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UEBXByb3BzCQEZdXBkYXRlUHJvcG9ydGlvbnNJbnRlcm5hbAQIBQNhY2MCXzYFDXRlcnJhaW5Db3VudHMFCWxhbmRJbmRleAD///////////8BBAZjUHJvcHMJARl1cGRhdGVQcm9wb3J0aW9uc0ludGVybmFsBAgFA2FjYwNfMTAFDXRlcnJhaW5Db3VudHMFCWxhbmRJbmRleAD///////////8BBAtzdW1UZXJyYWlucwkBGXVwZGF0ZVByb3BvcnRpb25zSW50ZXJuYWwECAUDYWNjAl85BQ10ZXJyYWluQ291bnRzBQlsYW5kSW5kZXgAAQQFbGFuZHMIBQNhY2MCXzcEA2lkeAkAzwgCBQVsYW5kcwULbGFuZEFzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBBQNpZHgJAAIBCQCsAgICIFlvdXIgc3Rha2VkIGxhbmRzIGRvbid0IGNvbnRhaW4gBQtsYW5kQXNzZXRJZAQJY3VzdG9tS2V5CQEaa2V5TGFuZEFzc2V0SWRUb0N1c3RvbU5hbWUBBQtsYW5kQXNzZXRJZAQKY3VzdG9tTmFtZQkBC3ZhbHVlT3JFbHNlAgkAoggBBQljdXN0b21LZXkCAAkAnAoKBQhzaXplc091dAUEYXJ0cwUJY29udGluZW50BQVicFJlcwkAzggCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAggFA2FjYwJfNQkBC0RlbGV0ZUVudHJ5AQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUEYWRkcgkBC0RlbGV0ZUVudHJ5AQkBEGtleUxhbmRUb0Fzc2V0SWQBBQdsYW5kTnVtCQELRGVsZXRlRW50cnkBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAQtEZWxldGVFbnRyeQEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQJAQtEZWxldGVFbnRyeQEJAR5rZXlJbmZyYUxldmVsQnlBc3NldElkQW5kT3duZXICBQtsYW5kQXNzZXRJZAUEYWRkcgkBC0RlbGV0ZUVudHJ5AQkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQULbGFuZEFzc2V0SWQJAQtEZWxldGVFbnRyeQEJARFrZXlMYW5kTnVtVG9Pd25lcgEFB2xhbmROdW0JAQtEZWxldGVFbnRyeQEJARJrZXlXYXJlaG91c2VCeUxhbmQBBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQUJY3VzdG9tS2V5CQEEQnVybgIJANkEAQULbGFuZEFzc2V0SWQAAQMJAQIhPQIFCmN1c3RvbU5hbWUCAAkAzAgCCQELRGVsZXRlRW50cnkBCQEaa2V5TGFuZEN1c3RvbU5hbWVUb0Fzc2V0SWQBBQpjdXN0b21OYW1lBQNuaWwFA25pbAUFcHJvcHMJANEIAgUFbGFuZHMJAQV2YWx1ZQEFA2lkeAkAZAIIBQNhY2MCXzgFBnBpZWNlcwULc3VtVGVycmFpbnMFBmNQcm9wcwQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkECHByb3BMaXN0CQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQkBEWtleVJlc1Byb3BvcnRpb25zAAILMF8wXzBfMF8wXzACAV8ECGxhbmRzS2V5CQEVa2V5U3Rha2VkTGFuZHNCeU93bmVyAQUEYWRkcgQIbGFuZHNTdHIJAKIIAQUIbGFuZHNLZXkEB2xhbmRzSW4DCQEJaXNEZWZpbmVkAQUIbGFuZHNTdHIJAL0JAgkBBXZhbHVlAQUIbGFuZHNTdHICAV8FA25pbAQFY29udDAJAJEDAgkAtQkCCAkBBXZhbHVlAQkA7AcBCQDZBAEJAJEDAgUMbGFuZEFzc2V0SWRzAAALZGVzY3JpcHRpb24CAV8FDHJlY0NvbnRpbmVudAQJY29udFByb3BzCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQkBFmtleVJlc1R5cGVzQnlDb250aW5lbnQBBQVjb250MAILMF8wXzBfMF8wXzACAV8EAXIKAAIkbAUMbGFuZEFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAnAoKBQdmb3JtdWxhAAACAAkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMFA25pbAUIcHJvcExpc3QFB2xhbmRzSW4AAAkAtQkCAgswXzBfMF8wXzBfMAIBXwUJY29udFByb3BzCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpjaGVja01lcmdlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQQJY29udGluZW50CAUBcgJfMwQMY29udGluZW50SWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAM8IAgUKY29udGluZW50cwUJY29udGluZW50CQCsAgICE1Vua25vd24gY29udGluZW50OiAFCWNvbnRpbmVudAQIdGVycmFpbnMJARNnZW5UZXJyYWluc0Zvck1lcmdlAggFAXICXzkJAGkCCQEPbnVtUGllY2VzQnlTaXplAQULbmV3TGFuZFNpemUFBVNTSVpFBAdmcmVlTnVtCQELdmFsdWVPckVsc2UCCQCfCAEJARJrZXlOZXh0RnJlZUxhbmROdW0ACQBkAgUPUFJFU0FMRU5VTUxBTkRTAAEECm5ld0xhbmROdW0JAKQDAQUHZnJlZU51bQQFaXNzdWUJAMIIBQkBB25mdE5hbWUCBQpuZXdMYW5kTnVtBQtuZXdMYW5kU2l6ZQkAuQkCCQDMCAIFCm5ld0xhbmROdW0JAMwIAgULbmV3TGFuZFNpemUJAMwIAgUIdGVycmFpbnMJAMwIAgUJY29udGluZW50BQNuaWwCAV8AAQAABwQHYXNzZXRJZAkAuAgBBQVpc3N1ZQQObmV3TGFuZEFzc2V0SWQJANgEAQUHYXNzZXRJZAQGbmV3TWF0CQC5CQIJARFzdWJ0cmFjdE1hdGVyaWFscwMJAGYCBQduZWVkTWF0AAAJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8FB25lZWRNYXQCAV8ECXBpZWNlc0tleQkBFmtleVN0YWtlZFBpZWNlc0J5T3duZXIBBQRhZGRyBAxzdGFrZWRQaWVjZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJcGllY2VzS2V5AAAJAJQKAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAggFAXICXzUDCQBmAgkAkAMBCAUBcgJfNwAACQELU3RyaW5nRW50cnkCBQhsYW5kc0tleQkAuwkCCAUBcgJfNwIBXwkBC0RlbGV0ZUVudHJ5AQUIbGFuZHNLZXkJAQxJbnRlZ2VyRW50cnkCBQlwaWVjZXNLZXkDCQBmAggFAXICXzgFDHN0YWtlZFBpZWNlcwAACQBlAgUMc3Rha2VkUGllY2VzCAUBcgJfOAkBDEludGVnZXJFbnRyeQIJARJrZXlOZXh0RnJlZUxhbmROdW0ACQBkAgUHZnJlZU51bQABBQVpc3N1ZQkBC1N0cmluZ0VudHJ5AgkBEGtleUxhbmRUb0Fzc2V0SWQBBQpuZXdMYW5kTnVtBQ5uZXdMYW5kQXNzZXRJZAkBC1N0cmluZ0VudHJ5AgkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFDm5ld0xhbmRBc3NldElkBQRhZGRyCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQpuZXdMYW5kTnVtBQRhZGRyCQEMSW50ZWdlckVudHJ5AgkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQUObmV3TGFuZEFzc2V0SWQIBQFyAl8yCQEMSW50ZWdlckVudHJ5AgkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQ5uZXdMYW5kQXNzZXRJZAUIbmV3TGV2ZWwJAQxJbnRlZ2VyRW50cnkCCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgUObmV3TGFuZEFzc2V0SWQFBGFkZHIFCG5ld0xldmVsCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAggFAXICXzQJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6CQELU3RyaW5nRW50cnkCCQERa2V5UmVzUHJvcG9ydGlvbnMACQC5CQIIBQFyAl82AgFfCQELU3RyaW5nRW50cnkCCQEWa2V5UmVzVHlwZXNCeUNvbnRpbmVudAEFCWNvbnRpbmVudAkAuQkCCAUBcgNfMTACAV8JAQtTdHJpbmdFbnRyeQIJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAkAuQkCCQDMCAIFCWNvbnRpbmVudAkAzAgCAgFMCQDMCAIFDm5ld0xhbmRBc3NldElkBQNuaWwCAV8JAQ5TY3JpcHRUcmFuc2ZlcgMJARFAZXh0ck5hdGl2ZSgxMDYyKQEFBGFkZHIAAQUHYXNzZXRJZAUObmV3TGFuZEFzc2V0SWQBA3MybQIEYWRkcgxsYW5kQXNzZXRJZHMJAQ1tZXJnZUludGVybmFsBgIBTQADAgRTU1NTBQRhZGRyBQxsYW5kQXNzZXRJZHMAAAEDbTJsAgRhZGRyDGxhbmRBc3NldElkcwkBDW1lcmdlSW50ZXJuYWwGAgFMAAQCA1NNTQUEYWRkcgUMbGFuZEFzc2V0SWRzCQBoAgURSW5mcmFVcGdyYWRlQ29zdFMABAEEbDJ4bAIEYWRkcgxsYW5kQXNzZXRJZHMJAQ1tZXJnZUludGVybmFsBgICWEwABQIFU1NTTUwFBGFkZHIFDGxhbmRBc3NldElkcwkAaAIFEUluZnJhVXBncmFkZUNvc3RTAC8BBnhsMnh4bAIEYWRkcgxsYW5kQXNzZXRJZHMJAQ1tZXJnZUludGVybmFsBgIDWFhMAAYCA0xYTAUEYWRkcgUMbGFuZEFzc2V0SWRzCQBoAgURSW5mcmFVcGdyYWRlQ29zdFMANgELbWVyZ2VDb21tb24CBGFkZHIMbGFuZEFzc2V0SWRzBAckbWF0Y2gwCQCQAwEFDGxhbmRBc3NldElkcwMJAAACAAQFByRtYXRjaDAJAQNzMm0CBQRhZGRyBQxsYW5kQXNzZXRJZHMDCQAAAgADBQckbWF0Y2gwCQEDbTJsAgUEYWRkcgUMbGFuZEFzc2V0SWRzAwkAAAIABQUHJG1hdGNoMAkBBGwyeGwCBQRhZGRyBQxsYW5kQXNzZXRJZHMDCQAAAgACBQckbWF0Y2gwCQEGeGwyeHhsAgUEYWRkcgUMbGFuZEFzc2V0SWRzCQACAQINVW5rbm93biBtZXJnZQEGcHJvbG9nAQFpAwMJAQIhPQIIBQFpDG9yaWdpbkNhbGxlcgUMcmVzdENvbnRyYWN0CQELdmFsdWVPckVsc2UCCQCgCAEJAQprZXlCbG9ja2VkAAcHCQACAQIfQ29udHJhY3RzIGFyZSB1bmRlciBtYWludGVuYW5jZQkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5TGFzdFR4SWRCeVVzZXIBCQClCAEIBQFpDG9yaWdpbkNhbGxlcgkA2AQBCAUBaQ10cmFuc2FjdGlvbklkBQNuaWwpAWkBDWNvbnN0cnVjdG9yVjEBCHJlc3RBZGRyAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIRUGVybWlzc2lvbiBkZW5pZWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDmtleVJlc3RBZGRyZXNzAAUIcmVzdEFkZHIFA25pbAFpAQtzYXZlSW50ZWdlcgIDa2V5BmFtb3VudAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECIHNhdmVJbnRlZ2VyIGlzIG5vdCBwdWJsaWMgbWV0aG9kCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQNrZXkFBmFtb3VudAUDbmlsAWkBCnNldEJsb2NrZWQBCWlzQmxvY2tlZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEXBlcm1pc3Npb24gZGVuaWVkCQDMCAIJAQxCb29sZWFuRW50cnkCCQEKa2V5QmxvY2tlZAAFCWlzQmxvY2tlZAUDbmlsAWkBCXN0YWtlTGFuZAAEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAEB2Fzc2V0SWQJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAQHYWRkcmVzcwkApQgBCAUBaQZjYWxsZXIDCQECIT0CCAUDcG10BmFtb3VudAABCQACAQkArAICCQCsAgICBE5GVCAFCkxBTkRQUkVGSVgCJCB0b2tlbiBzaG91bGQgYmUgYXR0YWNoZWQgYXMgcGF5bWVudAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAMJAQIhPQIIBQVhc3NldAZpc3N1ZXIFBHRoaXMJAAIBAhdVbmtub3duIGlzc3VlciBvZiB0b2tlbgMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkxBTkRQUkVGSVgJAAIBCQCsAgIJAKwCAgIJT25seSBORlQgBQpMQU5EUFJFRklYAhQgdG9rZW5zIGFyZSBhY2NlcHRlZAQLbGFuZE51bVNpemUJALACAggFBWFzc2V0BG5hbWUABAQHbGFuZE51bQMJAQhjb250YWlucwIFC2xhbmROdW1TaXplAgNYWEwJALMCAgULbGFuZE51bVNpemUAAwMJAQhjb250YWlucwIFC2xhbmROdW1TaXplAgJYTAkAswICBQtsYW5kTnVtU2l6ZQACCQCzAgIFC2xhbmROdW1TaXplAAEDCQEBIQEJAQlpc0RlZmluZWQBCQC2CQEFB2xhbmROdW0JAAIBCQCsAgICHkNhbm5vdCBwYXJzZSBsYW5kIG51bWJlciBmcm9tIAgFBWFzc2V0BG5hbWUEC2xhbmRBc3NldElkCQDYBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQDCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAhIgaXMgYWxyZWFkeSBzdGFrZWQEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAgUBZAULcmVjVGVycmFpbnMEBnBpZWNlcwkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAgUBZAULcmVjTGFuZFNpemUECWxhbmRJbmRleAkAaQIFBnBpZWNlcwUFU1NJWkUEBXByb3BzCQERdXBkYXRlUHJvcG9ydGlvbnMDBQ10ZXJyYWluQ291bnRzBQlsYW5kSW5kZXgAAQQMcmVzQnlDb250S2V5CQEWa2V5UmVzVHlwZXNCeUNvbnRpbmVudAEJAJEDAgUBZAUMcmVjQ29udGluZW50BAljb250UHJvcHMJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQxyZXNCeUNvbnRLZXkCCzBfMF8wXzBfMF8wAgFfBBB1cGRhdGVkQ29udFByb3BzCQC5CQIJARl1cGRhdGVQcm9wb3J0aW9uc0ludGVybmFsBAUJY29udFByb3BzBQ10ZXJyYWluQ291bnRzBQlsYW5kSW5kZXgAAQIBXwQIbGFuZHNLZXkJARVrZXlTdGFrZWRMYW5kc0J5T3duZXIBBQdhZGRyZXNzBAhsYW5kc1N0cgkAoggBBQhsYW5kc0tleQQFbGFuZHMDCQEJaXNEZWZpbmVkAQUIbGFuZHNTdHIJAL0JAgkBBXZhbHVlAQUIbGFuZHNTdHICAV8FA25pbAMJAQ9jb250YWluc0VsZW1lbnQCBQVsYW5kcwULbGFuZEFzc2V0SWQJAAIBCQCsAgICIllvdXIgc3Rha2VkIGxhbmRzIGFscmVhZHkgY29udGFpbiAFC2xhbmRBc3NldElkAwkAZwIJAJADAQUFbGFuZHMFGE1BWF9MQU5EU19TVEFLRURfQllfVVNFUgkAAgEJAKwCAgkArAICAhlZb3VyIGFscmVhZHkgc3Rha2VkIG1heCAoCQCkAwEFGE1BWF9MQU5EU19TVEFLRURfQllfVVNFUgIHKSBsYW5kcwQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAECXBpZWNlc0tleQkBFmtleVN0YWtlZFBpZWNlc0J5T3duZXIBBQdhZGRyZXNzBAlvbGRQaWVjZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJcGllY2VzS2V5AAAECXdsZ1Jlc3VsdAkA/AcEBQt3bGdDb250cmFjdAISb25TdGFrZVVuc3Rha2VMYW5kCQDMCAIFB2FkZHJlc3MFA25pbAUDbmlsCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdGltZUtleQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKTEFORFBSRUZJWAULbGFuZEFzc2V0SWQFB2FkZHJlc3MIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQtTdHJpbmdFbnRyeQIFCGxhbmRzS2V5CQC7CQIJAM0IAgUFbGFuZHMFC2xhbmRBc3NldElkAgFfCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlwaWVjZXNLZXkJAGQCBQlvbGRQaWVjZXMFBnBpZWNlcwkAzAgCCQELU3RyaW5nRW50cnkCCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQFB2FkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleUxhbmROdW1Ub093bmVyAQUHbGFuZE51bQUHYWRkcmVzcwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIFC2xhbmRBc3NldElkBQdhZGRyZXNzBQppbmZyYUxldmVsCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlSZXNQcm9wb3J0aW9ucwAFBXByb3BzCQDMCAIJAQtTdHJpbmdFbnRyeQIFDHJlc0J5Q29udEtleQUQdXBkYXRlZENvbnRQcm9wcwUDbmlsBQ1wcm9sb2dBY3Rpb25zBQl3bGdSZXN1bHQBaQELdW5zdGFrZUxhbmQBDWxhbmRBc3NldElkSW4EDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMDBQRhZGRyBQ1jbGFpbU1vZGVEdWNrBQ1sYW5kQXNzZXRJZEluBAtsYW5kQXNzZXRJZAgFAWMCXzIEAWQIBQFjAl8zBAhsYW5kc0tleQkBFWtleVN0YWtlZExhbmRzQnlPd25lcgEFBGFkZHIEDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCBQFkBQtyZWNUZXJyYWlucwQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQQJbGFuZEluZGV4CQBpAgUGcGllY2VzBQVTU0laRQQFcHJvcHMJARF1cGRhdGVQcm9wb3J0aW9ucwMFDXRlcnJhaW5Db3VudHMFCWxhbmRJbmRleAD///////////8BBAxyZXNCeUNvbnRLZXkJARZrZXlSZXNUeXBlc0J5Q29udGluZW50AQkAkQMCBQFkBQxyZWNDb250aW5lbnQECWNvbnRQcm9wcwkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFDHJlc0J5Q29udEtleQILMF8wXzBfMF8wXzACAV8EEHVwZGF0ZWRDb250UHJvcHMJALkJAgkBGXVwZGF0ZVByb3BvcnRpb25zSW50ZXJuYWwEBQljb250UHJvcHMFDXRlcnJhaW5Db3VudHMFCWxhbmRJbmRleAD///////////8BAgFfBAtjbGFpbVJlc3VsdAkBCGNsYWltQWxsBAUEYWRkcgULbGFuZEFzc2V0SWQFBnBpZWNlcwUNY2xhaW1Nb2RlRHVjawQFbGFuZHMJAL0JAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQhsYW5kc0tleQIAAgFfBANpZHgJAM8IAgUFbGFuZHMFC2xhbmRBc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQUDaWR4CQACAQkArAICAiBZb3VyIHN0YWtlZCBsYW5kcyBkb24ndCBjb250YWluIAULbGFuZEFzc2V0SWQEA25vdwgFCWxhc3RCbG9jawl0aW1lc3RhbXAEDmdvdlJlbGVhc2VUaW1lCQELdmFsdWVPckVsc2UCCQCaCAIFC2dvdkNvbnRyYWN0CQEVa2V5VXNlckd3bFJlbGVhc2VUaW1lAQUEYWRkcgAAAwkAZwIFDmdvdlJlbGVhc2VUaW1lBQNub3cJAAIBCQCsAgICOVlvdXIgZ1dMIGFyZSB0YWtpbmcgcGFydCBpbiB2b3RpbmcsIGNhbm5vdCB1bnN0YWtlIHVudGlsIAkApAMBBQ5nb3ZSZWxlYXNlVGltZQQOYXJiUmVsZWFzZVRpbWUJAGQCCQELdmFsdWVPckVsc2UCCQCaCAIFC3dsZ0NvbnRyYWN0CQEUa2V5TGFzdEFyYlRpbWVCeVVzZXIBBQRhZGRyAAAFDmFyYml0cmFnZURlbGF5AwkAZgIFDmFyYlJlbGVhc2VUaW1lBQNub3cJAAIBCQCsAgICP1lvdXIgc3Rha2VkIGxhbmRzIHRvb2sgcGFydCBpbiBhcmJpdHJhZ2UsIGNhbm5vdCB1bnN0YWtlIHVudGlsIAkApAMBBQ5hcmJSZWxlYXNlVGltZQQJcGllY2VzS2V5CQEWa2V5U3Rha2VkUGllY2VzQnlPd25lcgEFBGFkZHIEDHN0YWtlZFBpZWNlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlwaWVjZXNLZXkAAAQJbmV3UGllY2VzAwkAZgIFBnBpZWNlcwUMc3Rha2VkUGllY2VzAAAJAGUCBQxzdGFrZWRQaWVjZXMFBnBpZWNlcwQJd2xnUmVzdWx0CQD8BwQFC3dsZ0NvbnRyYWN0AhJvblN0YWtlVW5zdGFrZUxhbmQJAMwIAgUEYWRkcgUDbmlsBQNuaWwJAJQKAgkAzggCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABCQDZBAEFC2xhbmRBc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUEYWRkcgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5UmVzUHJvcG9ydGlvbnMABQVwcm9wcwkAzAgCCQELU3RyaW5nRW50cnkCBQxyZXNCeUNvbnRLZXkFEHVwZGF0ZWRDb250UHJvcHMJAMwIAgkBC1N0cmluZ0VudHJ5AggFC2NsYWltUmVzdWx0Al8yCQC5CQIIBQtjbGFpbVJlc3VsdAJfMwIBOgkAzAgCAwkAZgIJAJADAQUFbGFuZHMAAQkBC1N0cmluZ0VudHJ5AgUIbGFuZHNLZXkJALsJAgkA0QgCBQVsYW5kcwkBBXZhbHVlAQUDaWR4AgFfCQELRGVsZXRlRW50cnkBBQhsYW5kc0tleQkAzAgCCQEMSW50ZWdlckVudHJ5AgUJcGllY2VzS2V5BQluZXdQaWVjZXMFA25pbAUNcHJvbG9nQWN0aW9ucwUJd2xnUmVzdWx0AWkBCXN0YWtlRHVjawAEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAEB2Fzc2V0SWQJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAQHYWRkcmVzcwkApQgBCAUBaQZjYWxsZXIDCQECIT0CCAUDcG10BmFtb3VudAABCQACAQkArAICCQCsAgICBE5GVCAFCkRVQ0tQUkVGSVgCJCB0b2tlbiBzaG91bGQgYmUgYXR0YWNoZWQgYXMgcGF5bWVudAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAQGaXNSb2JvAwMFE0tTX0FMTE9XX1JPQk9fRFVDS1MJAAACCAUFYXNzZXQGaXNzdWVyBQR0aGlzBwkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFC1JPQk9fUFJFRklYBwMDAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUNaW5jdWJhdG9yQWRkcgkBAiE9AggFBWFzc2V0Bmlzc3VlcgULYnJlZWRlckFkZHIHCQEBIQEFBmlzUm9ibwcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICElVua25vd24gaXNzdWVyIG9mIAUKRFVDS1BSRUZJWAIEIG9yIAULUk9CT19QUkVGSVgCBiB0b2tlbgMDCQEBIQEJAQhjb250YWlucwIIBQVhc3NldARuYW1lBQpEVUNLUFJFRklYCQEBIQEFBmlzUm9ibwcJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICCU9ubHkgTkZUIAUKRFVDS1BSRUZJWAIEIG9yIAULUk9CT19QUkVGSVgCFCB0b2tlbnMgYXJlIGFjY2VwdGVkBAphc3NldElkU3RyCQDYBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUKYXNzZXRJZFN0cgMJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCEiBpcyBhbHJlYWR5IHN0YWtlZAMJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgICHVlvdSBhbHJlYWR5IHN0YWtlZCBvbmUgZHVjazogCAUFYXNzZXQEbmFtZQQGbG9jS2V5CQEPa2V5RHVja0xvY2F0aW9uAQUKYXNzZXRJZFN0cgQIbG9jYXRpb24JAKIIAQUGbG9jS2V5BAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQUKYXNzZXRJZFN0cgQIYmFja3BhY2sJAKIIAQUFYnBLZXkECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQphc3NldElkU3RyBAVtYXhIUAkBCW1heEhlYWx0aAEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBDGtleUR1Y2tMZXZlbAEFCmFzc2V0SWRTdHIAAAQJY3VySGVhbHRoCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aAUFbWF4SFAJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdGltZUtleQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKRFVDS1BSRUZJWAkA2AQBBQdhc3NldElkBQdhZGRyZXNzCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5RHVja0lkVG9Pd25lcgEFCmFzc2V0SWRTdHIFB2FkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwUKYXNzZXRJZFN0cgUDbmlsAwkBCWlzRGVmaW5lZAEFCGxvY2F0aW9uBQNuaWwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQZsb2NLZXkFD0RFRkFVTFRMT0NBVElPTgUDbmlsAwkBCWlzRGVmaW5lZAEFCGJhY2twYWNrBQNuaWwJAM4IAgkAzQgCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWJwS2V5AhowOjBfMF8wXzBfMF8wOjBfMF8wXzBfMF8wOgUDbmlsCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoBQljdXJIZWFsdGgFDXByb2xvZ0FjdGlvbnMBaQELdW5zdGFrZUR1Y2sBCmFzc2V0SWRTdHIEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEB2Fzc2V0SWQJANkEAQUKYXNzZXRJZFN0cgQHYWRkcmVzcwkApQgBCAUBaQZjYWxsZXIEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUKYXNzZXRJZFN0cgMJAQEhAQkBCWlzRGVmaW5lZAEJAJ8IAQUHdGltZUtleQkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQDCQEBIQEJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgIJAKwCAgIJVGhlIGR1Y2sgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBEGtleUR1Y2tJZFRvT3duZXIBBQphc3NldElkU3RyCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMJAQIhPQIFBW93bmVyBQdhZGRyZXNzCQACAQIXU3Rha2VkIE5GVCBpcyBub3QgeW91cnMDCQEPY2hlY2tUb3VybmFtZW50AQUKYXNzZXRJZFN0cgkAAgECG3Vuc3Rha2VEdWNrX2NoZWNrVG91cm5hbWVudAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFCmFzc2V0SWRTdHIEBW1heEhQCQEJbWF4SGVhbHRoAQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEMa2V5RHVja0xldmVsAQUKYXNzZXRJZFN0cgAABAZoZWFsdGgJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoBQVtYXhIUAMJAGYCBQVtYXhIUAUGaGVhbHRoCQACAQkArAICCQCsAgICGVBsZWFzZSBoZWFsIHlvdXIgZHVjayB0byAJAKQDAQUFbWF4SFACE2hwIGJlZm9yZSB1bnN0YWtpbmcJAM4IAgkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIAAQUHYXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBBQd0aW1lS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEFCWtleUhlYWx0aAkAzAgCCQELRGVsZXRlRW50cnkBCQEPa2V5RHVja0xvY2F0aW9uAQUKYXNzZXRJZFN0cgkAzAgCCQELRGVsZXRlRW50cnkBCQEQa2V5RHVja0lkVG9Pd25lcgEFCmFzc2V0SWRTdHIJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpEVUNLUFJFRklYBQphc3NldElkU3RyBQdhZGRyZXNzCQDMCAIJAQtEZWxldGVFbnRyeQEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MFA25pbAUNcHJvbG9nQWN0aW9ucwFpAQhjbGFpbVJlcwIGYW1vdW50DmxhbmRBc3NldElkU3RyBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQGcmVzdWx0CQEQY2xhaW1SZXNJbnRlcm5hbAQFBGFkZHIFBmFtb3VudAUNY2xhaW1Nb2RlRHVjawUObGFuZEFzc2V0SWRTdHIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAkAlAoCCQDOCAIJAM0IAgkAzQgCCQDOCAIIBQZyZXN1bHQCXzEICQEXdXBkYXRlRHVja1N0YXRzSW50ZXJuYWwCBQtkdWNrQXNzZXRJZAkAawMFB3hwQ2xhaW0FBmFtb3VudAUFTVVMVDgCXzEJAQtTdHJpbmdFbnRyeQIIBQZyZXN1bHQCXzIJALkJAggFBnJlc3VsdAJfMwIBOgkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfNAkAuQkCCAUGcmVzdWx0Al81AgE6BQ1wcm9sb2dBY3Rpb25zCQCRAwIIBQZyZXN1bHQCXzMFCGJwSWR4UmVzAWkBDGNsYWltUmVzVG9XSAIGYW1vdW50DmxhbmRBc3NldElkU3RyBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQGcmVzdWx0CQEQY2xhaW1SZXNJbnRlcm5hbAQFBGFkZHIFBmFtb3VudAULY2xhaW1Nb2RlV2gFDmxhbmRBc3NldElkU3RyCQCUCgIJAM4IAgkAzQgCCQDNCAIJAM4IAggFBnJlc3VsdAJfMQgJARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgUEYWRkcgkAawMFB3hwQ2xhaW0FBmFtb3VudAUFTVVMVDgCXzEJAQtTdHJpbmdFbnRyeQIIBQZyZXN1bHQCXzIJALkJAggFBnJlc3VsdAJfMwIBOgkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfNAkAuQkCCAUGcmVzdWx0Al81AgE6BQ1wcm9sb2dBY3Rpb25zCQCRAwIIBQZyZXN1bHQCXzUFCHdoSWR4UmVzAWkBBmZsaWdodAIHbWVzc2FnZQNzaWcEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQECHVzZXJBZGRyCQClCAEIBQFpBmNhbGxlcgQBZgkBDGZsaWdodENvbW1vbgMFCHVzZXJBZGRyBQdtZXNzYWdlBQNzaWcEBW5ld0hQCAUBZgJfMQQLZHVja0Fzc2V0SWQIBQFmAl8yBAZsb2NLZXkJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQUGbG9jS2V5BQ9ERUZBVUxUTE9DQVRJT04EC25ld0xvY2F0aW9uCAUBZgJfNAMJAAACBQtuZXdMb2NhdGlvbgULY3VyTG9jYXRpb24JAAIBAiJZb3UgY2FuJ3QgZmx5IHRvIHRoZSBzYW1lIGxvY2F0aW9uBAZuZXdMb2MJALUJAgULbmV3TG9jYXRpb24CAV8EBmlzVG91cgkAAAIJAJEDAgUGbmV3TG9jBQpsb2NJZHhUeXBlAgFUBAdpc0RlbGl2CQAAAgkAkQMCBQZuZXdMb2MFCmxvY0lkeFR5cGUCAUQEBWVxS2V5CQEQa2V5RHVja0VxdWlwbWVudAEFC2R1Y2tBc3NldElkBAljdXJyZW50RXEJAQt2YWx1ZU9yRWxzZQIJAKIIAQUFZXFLZXkCFyw7LF8sOyxfLDssXyw7LF8sOyxfLDssBA0kdDA2NjM3MDY2NDc2CQERc3VidHJhY3RFcXVpcG1lbnQCBQljdXJyZW50RXEIBQFmAl81BAVuZXdFcQgFDSR0MDY2MzcwNjY0NzYCXzEED3Nob3VsZFplcm9CdWZmcwgFDSR0MDY2MzcwNjY0NzYCXzIEB2lnbm9yZWQIBQ0kdDA2NjM3MDY2NDc2Al8zBA0kdDA2NjQ3OTY4MzExAwkBASEBCQEJb25NaXNzaW9uAgUSdG91cm5hbWVudENvbnRyYWN0BQtjdXJMb2NhdGlvbgMFBmlzVG91cgkBDGNoZWF0QXR0ZW1wdAMFC2N1ckxvY2F0aW9uBQtuZXdMb2NhdGlvbgAFAwkBASEBBQdpc0RlbGl2AwkAZgIFBW5ld0hQAAAJAJQKAgULbmV3TG9jYXRpb24FBW5ld0hQCQCUCgIFC2N1ckxvY2F0aW9uAAADCQBmAgUFbmV3SFAAAAQBcwkA/AcEBQR0aGlzAg9wcm9jZXNzRGVsaXZlcnkJAMwIAgULZHVja0Fzc2V0SWQFA25pbAUDbmlsAwkAAAIFAXMFAXMJAJQKAgULY3VyTG9jYXRpb24FBW5ld0hQCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQCUCgIFC2N1ckxvY2F0aW9uAAADCQEOaXNJblRvdXJuYW1lbnQCBRJ0b3VybmFtZW50Q29udHJhY3QFC2N1ckxvY2F0aW9uAwkBASEBCQEOaXNJblRvdXJuYW1lbnQCBRJ0b3VybmFtZW50Q29udHJhY3QFC25ld0xvY2F0aW9uCQACAQIqWW91ciBkdWNrIGlzIHRha2luZyBwYXJ0IGluIHRoZSB0b3VybmFtZW50BAVzY29yZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBm5ld0xvYwUIbG9jSWR4SWQEBmN1ckxvYwkAtQkCBQtjdXJMb2NhdGlvbgIBXwQGbGFzdElkCQELdmFsdWVPckVsc2UCCQCaCAIFEnRvdXJuYW1lbnRDb250cmFjdAUNbGFzdFRvdXJJZEtleQAAAwkBAiE9AgUFc2NvcmUJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGY3VyTG9jBQhsb2NJZHhJZAABCQEMY2hlYXRBdHRlbXB0AwULY3VyTG9jYXRpb24FC25ld0xvY2F0aW9uAAcDCQBmAgUFbmV3SFAAAAQJbG9jYWxCZXN0CQELdmFsdWVPckVsc2UCCQCaCAIFEnRvdXJuYW1lbnRDb250cmFjdAkBGmtleUJlc3RSZXN1bHRCeVRvdXJBbmREdWNrAgUGbGFzdElkBQtkdWNrQXNzZXRJZAAABAh1cGRMb2NhbAMJAGYCBQVzY29yZQUJbG9jYWxCZXN0CQD8BwQFEnRvdXJuYW1lbnRDb250cmFjdAIOc2F2ZUR1Y2tSZXN1bHQJAMwIAgULZHVja0Fzc2V0SWQJAMwIAgUFc2NvcmUFA25pbAUDbmlsBQR1bml0AwkAAAIFCHVwZExvY2FsBQh1cGRMb2NhbAkAlAoCBQtuZXdMb2NhdGlvbgUFbmV3SFAJAAIBAiRTdHJpY3QgdmFsdWUgaXMgbm90IGVxdWFsIHRvIGl0c2VsZi4JAJQKAgULY3VyTG9jYXRpb24AAAkAAgEJAKwCAgIUVW5rbm93biBjdXJMb2NhdGlvbjoFC2N1ckxvY2F0aW9uBAlsb2NUb1NhdmUIBQ0kdDA2NjQ3OTY4MzExAl8xBAhocFRvU2F2ZQgFDSR0MDY2NDc5NjgzMTECXzIJAJQKAgkAzggCCQDOCAIJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQZsb2NLZXkFCWxvY1RvU2F2ZQkAzAgCCQELU3RyaW5nRW50cnkCBQVlcUtleQUFbmV3RXEJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQFCGhwVG9TYXZlBQNuaWwFDXByb2xvZ0FjdGlvbnMDBQ9zaG91bGRaZXJvQnVmZnMJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGtleUR1Y2tCdWZmcwEFC2R1Y2tBc3NldElkAgkwXzBfMF8wXzAFA25pbAUDbmlsCAkBF3VwZGF0ZUR1Y2tTdGF0c0ludGVybmFsAgULZHVja0Fzc2V0SWQDCQBmAgUFbmV3SFAAAAUPeHBTdWNjZXNzRmxpZ2h0BQx4cEZhaWxGbGlnaHQCXzEIBQFmAl8zAWkBBGhlYWwDCnF1YW50aXR5TDEKcXVhbnRpdHlMMgpxdWFudGl0eUwzBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMDAwkAZgIAAAUKcXVhbnRpdHlMMQYJAGYCAAAFCnF1YW50aXR5TDIGCQBmAgAABQpxdWFudGl0eUwzCQACAQIbUXVhbnRpdHkgY2Fubm90IGJlIG5lZ2F0aXZlBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEJAKUIAQgFAWkGY2FsbGVyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkAwkBD2NoZWNrVG91cm5hbWVudAEFC2R1Y2tBc3NldElkCQACAQIUaGVhbF9jaGVja1RvdXJuYW1lbnQEA3F0cwkAzAgCBQpxdWFudGl0eUwxCQDMCAIFCnF1YW50aXR5TDIJAMwIAgUKcXVhbnRpdHlMMwUDbmlsBAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQEBW1heEhQCQEJbWF4SGVhbHRoAQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEMa2V5RHVja0xldmVsAQULZHVja0Fzc2V0SWQAAAQJb2xkSGVhbHRoCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aAUFbWF4SFADCQBnAgUJb2xkSGVhbHRoBQVtYXhIUAkAAgEJAKwCAgkArAICAg9IUCBzaG91bGQgYmUgPCAJAKQDAQUFbWF4SFACCCB0byBoZWFsBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQIcHJvZExpc3QDCQAAAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kAgAFA25pbAkAvAkCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QCAV8KAQtpdGVyYXRlUHJvZAIDYWNjBnJlY2lwZQQBbggFA2FjYwJfMgQBeAMJAGYCCQCQAwEFCHByb2RMaXN0BQFuCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIcHJvZExpc3QFAW4AAAMJAGYCAAMFAW4EAXEJAJEDAgUDcXRzBQFuAwkAZgIFAXEFAXgJAAIBCQCsAgIJAKwCAgkArAICAg5Zb3UgaGF2ZSBvbmx5IAkApAMBBQF4AgQgb2YgCQCRAwIFCXByb2RUeXBlcwUBbgkAlQoDCQDNCAIIBQNhY2MCXzEJAKQDAQkAZQIFAXgFAXEJAGQCBQFuAAEJAGQCCAUDYWNjAl8zCQBoAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIJALUJAgUGcmVjaXBlAgFfBQpySWR4RWZmZWN0BQFxCQCVCgMJAM0IAggFA2FjYwJfMQkApAMBBQF4CQBkAgUBbgABCAUDYWNjAl8zBAZyZXN1bHQKAAIkbAUQcHJvZHVjdGlvbk1hdHJpeAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJUKAwUDbmlsAAAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQELaXRlcmF0ZVByb2QCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDUwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgQJbmV3SGVhbHRoCQCXAwEJAMwIAgUFbWF4SFAJAMwIAgkAZAIFCW9sZEhlYWx0aAgFBnJlc3VsdAJfMwUDbmlsCQCUCgIJAM4IAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgFCW5ld0hlYWx0aAkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAugkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQJAMwIAgkAuQkCCAUGcmVzdWx0Al8xAgFfBQNuaWwCAToFA25pbAUNcHJvbG9nQWN0aW9ucwgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkCQBoAgUGeHBIZWFsCQBkAgkAZAIFCnF1YW50aXR5TDEFCnF1YW50aXR5TDIFCnF1YW50aXR5TDMCXzEFCW5ld0hlYWx0aAFpAQZoZWFsRVMABA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQt1c2R0QXNzZXRJZAkAAgECGkFsbG93ZWQgVVNEVCBwYXltZW50IG9ubHkhBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEJAKUIAQgFAWkGY2FsbGVyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkAwkBD2NoZWNrVG91cm5hbWVudAEFC2R1Y2tBc3NldElkCQACAQIWaGVhbEVTX2NoZWNrVG91cm5hbWVudAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAVtYXhIUAkBCW1heEhlYWx0aAEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBDGtleUR1Y2tMZXZlbAEFC2R1Y2tBc3NldElkAAAECW9sZEhlYWx0aAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgFBW1heEhQAwkAZgIFCW9sZEhlYWx0aAAACQACAQIoSFAgc2hvdWxkIGJlIDAgdG8gY2FsbCBFbWVyZ2VuY3kgU2VydmljZQQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkECHByb2RMaXN0AwkAAAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAIABQNuaWwJALwJAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kAgFfBA1tZWRLaXRBbW91bnQxAwkAZgIJAJADAQUIcHJvZExpc3QAAAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHByb2RMaXN0AAAAAAQNbWVkS2l0QW1vdW50MgMJAGYCCQCQAwEFCHByb2RMaXN0AAEJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhwcm9kTGlzdAABAAAEDW1lZEtpdEFtb3VudDMDCQBmAgkAkAMBBQhwcm9kTGlzdAACCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIcHJvZExpc3QAAgAAAwMDCQBmAgUNbWVkS2l0QW1vdW50MQAABgkAZgIFDW1lZEtpdEFtb3VudDIAAAYJAGYCBQ1tZWRLaXRBbW91bnQzAAAJAAIBAh9Zb3UgaGF2ZSB0byB1c2Ugb3duIE1lZGljYWwgS2l0BAhleGlzdFN0cgkAnQgCBQ9lY29ub215Q29udHJhY3QJAQ5rZXlFc1dhcmVob3VzZQAEDGV4aXN0QW1vdW50cwMJAQlpc0RlZmluZWQBBQhleGlzdFN0cgkAvAkCCQEFdmFsdWUBBQhleGlzdFN0cgIBXwUDbmlsBAtleGlzdEFtb3VudAMJAGYCCQCQAwEFDGV4aXN0QW1vdW50cwAACQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUMZXhpc3RBbW91bnRzAAAAAAMJAGcCAAAFC2V4aXN0QW1vdW50CQACAQI5VGhlcmUgYXJlIG5vIE1lZGljYWwgS2l0cyBMMSBhdCBFbWVyZ2VuY3kgU2VydmljZSBzdG9yYWdlBAluZXdIZWFsdGgJAGQCBQlvbGRIZWFsdGgJAQ1wYXJzZUludFZhbHVlAQkAkQMCCQC1CQIJAJEDAgUQcHJvZHVjdGlvbk1hdHJpeAAAAgFfBQpySWR4RWZmZWN0BAVuZXdFUwkAuQkCCQDMCAIJAKQDAQkAZQIFC2V4aXN0QW1vdW50AAEJANEIAgUMZXhpc3RBbW91bnRzAAACAV8EBnJlY2lwZQkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgAAAIBXwQIdG90YWxNYXQJARJnZXRSZWNpcGVNYXRlcmlhbHMBBQZyZWNpcGUECXNlbGxQcmljZQkAawMJAGgCBQh0b3RhbE1hdAUKRVNTRUxMQ09FRgUQUkVTT1VSQ0VQUklDRU1JTgkAaAIFBU1VTFQ4BQ5QUk9EVUNUUEtHU0laRQMJAQIhPQIIBQNwbXQGYW1vdW50BQlzZWxsUHJpY2UJAAIBCQCsAgICG1BheW1lbnQgYXR0YWNoZWQgc2hvdWxkIGJlIAkApAMBBQlzZWxsUHJpY2UEBnJlc3VsdAkBCGFzU3RyaW5nAQkA/AcEBQ9lY29ub215Q29udHJhY3QCD3VwZGF0ZUVzU3RvcmFnZQkAzAgCBQVuZXdFUwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQt1c2R0QXNzZXRJZAUJc2VsbFByaWNlBQNuaWwJAJQKAgkAzggCCQDNCAIFDXByb2xvZ0FjdGlvbnMJAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgFCW5ld0hlYWx0aAgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkBQh4cENhbGxFUwJfMQUGcmVzdWx0AWkBDnVwZGF0ZUJhY2twYWNrAgtkdWNrQXNzZXRJZAduZXdQYWNrAwkBAiE9AggFAWkGY2FsbGVyBQ9lY29ub215Q29udHJhY3QJAAIBAhFwZXJtaXNzaW9uIGRlbmllZAkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBQduZXdQYWNrBQNuaWwFB25ld1BhY2sBaQEPY29tbWl0Rm9yUmFuZG9tAAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkEC2ZpbmlzaEJsb2NrCQBkAgUGaGVpZ2h0BQtyYW5kb21EZWxheQQEYWRkcgkApQgBCAUBaQZjYWxsZXIJAJQKAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEJa2V5Q29tbWl0AQUEYWRkcgULZmluaXNoQmxvY2sFA25pbAUNcHJvbG9nQWN0aW9ucwULZmluaXNoQmxvY2sBaQEMcmV2ZWFsUmFuZG9tAQhtYXhWYWx1ZQQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAlmaW5pc2hLZXkJAQlrZXlDb21taXQBBQRhZGRyBAtmaW5pc2hCbG9jawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFCWZpbmlzaEtleQIkWW91IGhhdmUgdG8gY29tbWl0Rm9yUmFuZG9tKCkgZmlyc3QhAwkAZgIFC2ZpbmlzaEJsb2NrBQZoZWlnaHQJAAIBCQCsAgICNFJhbmRvbSBudW1iZXIgaXMgbm90IHJlYWR5IHlldCwgd2FpdCB1bnRpbCBoZWlnaHQgPSAJAKQDAQULZmluaXNoQmxvY2sEB2VudHJvcHkJAQV2YWx1ZQEICQEFdmFsdWUBCQDtBwEFC2ZpbmlzaEJsb2NrA3ZyZgQEc2FsdAkAmwMBCQELdmFsdWVPckVsc2UCCQCiCAEJARFrZXlMYXN0VHhJZEJ5VXNlcgEFBGFkZHICAAQEcmFuZAkBD2dldFJhbmRvbU51bWJlcgMFCG1heFZhbHVlBQRzYWx0BQdlbnRyb3B5CQCUCgIJAM4IAgkAzAgCCQELRGVsZXRlRW50cnkBBQlmaW5pc2hLZXkFA25pbAUNcHJvbG9nQWN0aW9ucwUEcmFuZAFpAQhidXlTTGFuZAAEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZHRBc3NldElkCQACAQIaQWxsb3dlZCBVU0RUIHBheW1lbnQgb25seSEDCQECIT0CCAUDcG10BmFtb3VudAUHRVhQVVNEVAkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFB0VYUFVTRFQEBnJlc3VsdAkBEmV4cGVkaXRpb25JbnRlcm5hbAIIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAQLYWNyZXNSZXN1bHQJAQVhc0ludAEJAPwHBAUNYWNyZXNDb250cmFjdAIJYnVybkFjcmVzCQDMCAIFDFNfQ09TVF9BQ1JFUwUDbmlsBQNuaWwJAJQKAgkAzggCCQDOCAIJAM0IAggFBnJlc3VsdAJfMQkBDlNjcmlwdFRyYW5zZmVyAwUPZWNvbm9teUNvbnRyYWN0CAUDcG10BmFtb3VudAULdXNkdEFzc2V0SWQICQEWdXBkYXRlQWNjU3RhdHNJbnRlcm5hbAIJAKUIAQgFAWkGY2FsbGVyBQp4cE5ld1NMYW5kAl8xBQ1wcm9sb2dBY3Rpb25zCQCUCgIICAUGcmVzdWx0Al8yAl8xBQthY3Jlc1Jlc3VsdAFpAQpleHBlZGl0aW9uAgdtZXNzYWdlA3NpZwQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQIdXNlckFkZHIJAKUIAQgFAWkGY2FsbGVyBAFmCQEMZmxpZ2h0Q29tbW9uAwUIdXNlckFkZHIFB21lc3NhZ2UFA3NpZwQLZHVja0Fzc2V0SWQIBQFmAl8yBAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEFBWJwS2V5BAVtTGlzdAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAIBXwQGbmV3TWF0CQC5CQIJARFzdWJ0cmFjdE1hdGVyaWFscwMGBQVtTGlzdAUMRVhQTUFURVJJQUxTAgFfBAVlcUtleQkBEGtleUR1Y2tFcXVpcG1lbnQBBQtkdWNrQXNzZXRJZAQJY3VycmVudEVxCQELdmFsdWVPckVsc2UCCQCiCAEFBWVxS2V5AhcsOyxfLDssXyw7LF8sOyxfLDssXyw7LAQNJHQwNzYyMzE3NjMzNwkBEXN1YnRyYWN0RXF1aXBtZW50AgUJY3VycmVudEVxCAUBZgJfNQQFbmV3RXEIBQ0kdDA3NjIzMTc2MzM3Al8xBA9zaG91bGRaZXJvQnVmZnMIBQ0kdDA3NjIzMTc2MzM3Al8yBAdpZ25vcmVkCAUNJHQwNzYyMzE3NjMzNwJfMwQBZQkBEmV4cGVkaXRpb25JbnRlcm5hbAIIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAQCaWQICAUBZQJfMgJfMQQGcmVzdWx0AwkAZwIAAAgFAWYCXzEJAJUKAwkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoAAAJAMwIAgkBC1N0cmluZ0VudHJ5AgUFZXFLZXkFBW5ld0VxBQNuaWwCAAAACQCVCgMJAM4IAggFAWUCXzEDBQ9zaG91bGRaZXJvQnVmZnMJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGtleUR1Y2tCdWZmcwEFC2R1Y2tBc3NldElkAgkwXzBfMF8wXzAFA25pbAkAzQgCCQDNCAIJAM0IAgkAzQgCBQNuaWwJAQtTdHJpbmdFbnRyeQIJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAkAuQkCCQDMCAIICAUBZQJfMgJfMgkAzAgCAgFMCQDMCAIFAmlkBQNuaWwCAV8JAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgIBQFmAl8xCQELU3RyaW5nRW50cnkCBQVlcUtleQUFbmV3RXEJAQtTdHJpbmdFbnRyeQIFBWJwS2V5CQC5CQIJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwkAzAgCBQZuZXdNYXQJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kBQNuaWwCAToFAmlkCAUBZgJfMwMJAQ9jaGVja1RvdXJuYW1lbnQBBQtkdWNrQXNzZXRJZAkAAgECGmV4cGVkaXRpb25fY2hlY2tUb3VybmFtZW50BAthY3Jlc1Jlc3VsdAkBBWFzSW50AQkA/AcEBQ1hY3Jlc0NvbnRyYWN0AglidXJuQWNyZXMJAMwIAgUMU19DT1NUX0FDUkVTBQNuaWwFA25pbAkAlAoCCQDOCAIJAM4IAggFBnJlc3VsdAJfMQgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkBQp4cE5ld1NMYW5kAl8xBQ1wcm9sb2dBY3Rpb25zCQCVCgMIBQZyZXN1bHQCXzIIBQZyZXN1bHQCXzMFC2FjcmVzUmVzdWx0AWkBEGJ1eVNMYW5kRm9yQWNyZXMABA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECImV4YWN0bHkgMSBwYXltZW50IG11c3QgYmUgYXR0YWNoZWQEA3BtdAkAkQMCCAUBaQhwYXltZW50cwAABANhbXQIBQNwbXQGYW1vdW50AwMJAQEhAQkBCWlzRGVmaW5lZAEIBQNwbXQHYXNzZXRJZAYJAQIhPQIJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAUMYWNyZXNBc3NldElkCQACAQIUQUNSRVMgcGF5bWVudHMgb25seSEDCQECIT0CBQNhbXQFDFNfQ09TVF9BQ1JFUwkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFDFNfQ09TVF9BQ1JFUwQGcmVzdWx0CQESZXhwZWRpdGlvbkludGVybmFsAggFAWkGY2FsbGVyCAUBaQ10cmFuc2FjdGlvbklkBAthY3Jlc1Jlc3VsdAkBBWFzSW50AQkA/AcEBQ1hY3Jlc0NvbnRyYWN0AglidXJuQWNyZXMJAMwIAgUMU19DT1NUX0FDUkVTBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFDGFjcmVzQXNzZXRJZAUDYW10BQNuaWwJAJQKAgkAzggCCQDOCAIIBQZyZXN1bHQCXzEICQEWdXBkYXRlQWNjU3RhdHNJbnRlcm5hbAIJAKUIAQgFAWkGY2FsbGVyBQp4cE5ld1NMYW5kAl8xBQ1wcm9sb2dBY3Rpb25zCQCUCgIICAUGcmVzdWx0Al8yAl8xBQthY3Jlc1Jlc3VsdAFpAQx1cGdyYWRlSW5mcmEBC2xhbmRBc3NldElkBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBAZyZXN1bHQJAQ11cEluZnJhQ29tbW9uBAYIBQFpBmNhbGxlcgAABQtsYW5kQXNzZXRJZAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAkAlAoCCQDOCAIJAM4IAggFBnJlc3VsdAJfMQUNcHJvbG9nQWN0aW9ucwgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkCQBrAwUOeHBVcGdyYWRlSW5mcmEIBQZyZXN1bHQCXzMFBU1VTFQ4Al8xCAUGcmVzdWx0Al8yAWkBEGFjdGl2YXRlQXJ0aWZhY3QCB2FydE5hbWUObGFuZEFzc2V0SWRPcHQEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAZyZXN1bHQEByRtYXRjaDAFB2FydE5hbWUDCQAAAgIHUFJFU0FMRQUHJG1hdGNoMAkBEmFjdGl2YXRlUHJlc2FsZUFydAIFBGFkZHIFDmxhbmRBc3NldElkT3B0AwkAAAICB09OQk9BUkQFByRtYXRjaDAJARJhY3RpdmF0ZU9uYm9hcmRBcnQBBQRhZGRyCQACAQIQVW5rbm93biBhcnRpZmFjdAkAzggCBQZyZXN1bHQFDXByb2xvZ0FjdGlvbnMBaQEKbWVyZ2VMYW5kcwEMbGFuZEFzc2V0SWRzBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBAZyZXN1bHQJAQttZXJnZUNvbW1vbgIJAKUIAQgFAWkGY2FsbGVyBQxsYW5kQXNzZXRJZHMJAJQKAgkAzggCCQDOCAIIBQZyZXN1bHQCXzEFDXByb2xvZ0FjdGlvbnMICQEWdXBkYXRlQWNjU3RhdHNJbnRlcm5hbAIJAKUIAQgFAWkGY2FsbGVyBQd4cE1lcmdlAl8xCAUGcmVzdWx0Al8yAWkBDWNhcmdvRXhjaGFuZ2UCDGNhcmdvTGlzdFN0cgtsYW5kQXNzZXRJZAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQKY2FyZ29QYXJ0cwkAvAkCBQxjYXJnb0xpc3RTdHICAToEBGFkZHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMJAQIhPQIFBW93bmVyBQRhZGRyCQACAQkArAICBQpMQU5EUFJFRklYAg0gaXMgbm90IHlvdXJzBAlsYW5kSW5kZXgJAGkCCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwULcmVjTGFuZFNpemUFBVNTSVpFBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQFD0RFRkFVTFRMT0NBVElPTgQDbG9jCQC1CQIJAQV2YWx1ZQEFC2N1ckxvY2F0aW9uAgFfAwkBAiE9AgkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCAUwJAAIBCQCsAgIJAKwCAgIWRHVjayBsb2NhdGlvbiB0eXBlIGlzIAkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCESwgYnV0IHNob3VsZCBiZSBMAwkBAiE9AgkAkQMCBQNsb2MFCGxvY0lkeElkBQtsYW5kQXNzZXRJZAkAAgEJAKwCAgIbRHVjayBzaG91bGQgYmUgb24gdGhlIGxhbmQgBQtsYW5kQXNzZXRJZAQFd2hLZXkJARJrZXlXYXJlaG91c2VCeUxhbmQBBQtsYW5kQXNzZXRJZAQJY3VycmVudFdoCQEMZ2V0V2FyZWhvdXNlAwUFd2hLZXkFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBnJlc3VsdAkBCW1vdmVTdHVmZgMFCmNhcmdvUGFydHMFCWN1cnJlbnRXaAULY3VycmVudFBhY2sEBGxvZnQJALUJAgkAkQMCBQljdXJyZW50V2gFCXdoSWR4TE9GVAIBXwQFbG9mdE8JAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAULdm9sT2NjdXBpZWQIBQZyZXN1bHQCXzcEBWxvZnRGCQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUIBQZyZXN1bHQCXzcJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAugkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAggFBnJlc3VsdAJfNAkAzAgCCAUGcmVzdWx0Al81CQDMCAIIBQZyZXN1bHQCXzYFA25pbAIBOgkAzAgCCQELU3RyaW5nRW50cnkCBQV3aEtleQkAugkCCQDMCAIJAJEDAgUJY3VycmVudFdoBQt3aElkeExldmVscwkAzAgCCAUGcmVzdWx0Al8xCQDMCAIIBQZyZXN1bHQCXzIJAMwIAggFBnJlc3VsdAJfMwkAzAgCCQC5CQIJAMwIAgkAkQMCBQRsb2Z0BQl2b2xMb2NrZWQJAMwIAgkApAMBBQVsb2Z0TwkAzAgCCQCkAwEFBWxvZnRGCQDMCAIJAJEDAgUEbG9mdAUIdm9sVG90YWwFA25pbAIBXwUDbmlsAgE6BQNuaWwFDXByb2xvZ0FjdGlvbnMBaQENc2F2ZVdhcmVob3VzZQIFd2hTdHILbGFuZEFzc2V0SWQDCQECIT0CCAUBaQZjYWxsZXIFD2Vjb25vbXlDb250cmFjdAkAAgECDUFjY2VzcyBkZW5pZWQEBXdoS2V5CQESa2V5V2FyZWhvdXNlQnlMYW5kAQULbGFuZEFzc2V0SWQEAndoCQC8CQIFBXdoU3RyAgE6AwkBAiE9AgkAkAMBBQJ3aAAFCQACAQIwd2FyZWhvdXNlIHN0cmluZyBzaG91bGQgY29udGFpbiA0ICc6JyBzZXBhcmF0b3JzBAVsb2Z0TAkAkQMCCQC1CQIJAJEDAgUCd2gFCXdoSWR4TE9GVAIBXwUJdm9sTG9ja2VkBAVsb2Z0TwkBF2dldFdhcmVob3VzZU9jY3VwaWVkVm9sAQUCd2gEBWxvZnRUCQEXZ2V0V2FyZWhvdXNlVG90YWxWb2x1bWUBCQCRAwIFAndoBQt3aElkeExldmVscwQFbG9mdEYJAGUCCQBlAgUFbG9mdFQJAQ1wYXJzZUludFZhbHVlAQUFbG9mdEwFBWxvZnRPAwkAZgIAAAUFbG9mdEYJAAIBAjBPcGVyYXRpb24gbGVhZHMgdG8gbmVnYXRpdmUgZnJlZSB3YXJlaG91c2Ugc3BhY2UECG5ld1doU3RyCQC6CQIJAMwIAgkAkQMCBQJ3aAULd2hJZHhMZXZlbHMJAMwIAgkAkQMCBQJ3aAUId2hJZHhSZXMJAMwIAgkAkQMCBQJ3aAUId2hJZHhNYXQJAMwIAgkAkQMCBQJ3aAUJd2hJZHhQcm9kCQDMCAIJALkJAgkAzAgCBQVsb2Z0TAkAzAgCCQCkAwEFBWxvZnRPCQDMCAIJAKQDAQUFbG9mdEYJAMwIAgkApAMBBQVsb2Z0VAUDbmlsAgFfBQNuaWwCAToJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQV3aEtleQUIbmV3V2hTdHIFA25pbAUIbmV3V2hTdHIBaQENc2V0Q3VzdG9tTmFtZQMHYXNzZXRJZApjdXN0b21OYW1lBHR5cGUEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZHRBc3NldElkCQACAQIaQWxsb3dlZCBVU0RUIHBheW1lbnQgb25seSEDCQECIT0CCAUDcG10BmFtb3VudAUMUkVOQU1JTkdDT1NUCQACAQkArAICAhJQYXltZW50IHNob3VsZCBiZSAJAKQDAQUMUkVOQU1JTkdDT1NUAwkBCGNvbnRhaW5zAgUKY3VzdG9tTmFtZQICX18JAAIBCQCsAgICHk5hbWUgc2hvdWxkIG5vdCBjb250YWluICdfXyc6IAUKY3VzdG9tTmFtZQMJAGYCCQCxAgEFCmN1c3RvbU5hbWUFCk1BWE5BTUVMRU4JAAIBCQCsAgICGU5hbWUgdG9vIGxvbmcsIG1heExlbmd0aD0JAKQDAQUKTUFYTkFNRUxFTgQEYWRkcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEB2FjdGlvbnMEByRtYXRjaDAFBHR5cGUDCQAAAgIHQUNDT1VOVAUHJG1hdGNoMAQKcmV2ZXJzZUtleQkBFmtleUN1c3RvbU5hbWVUb0FkZHJlc3MBBQpjdXN0b21OYW1lBAluYW1lT3duZXIJAKIIAQUKcmV2ZXJzZUtleQMJAQlpc0RlZmluZWQBBQluYW1lT3duZXIJAAIBCQCsAgICGU5hbWUgYWxyZWFkeSByZWdpc3RlcmVkOiAFCmN1c3RvbU5hbWUEDWFkZHJUb05hbWVLZXkJARZrZXlBZGRyZXNzVG9DdXN0b21OYW1lAQUEYWRkcgQHb2xkTmFtZQkAoggBBQ1hZGRyVG9OYW1lS2V5BAdmcmVlT2xkAwkBCWlzRGVmaW5lZAEFB29sZE5hbWUJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFmtleUN1c3RvbU5hbWVUb0FkZHJlc3MBCQEFdmFsdWUBBQdvbGROYW1lBQNuaWwFA25pbAkAzggCCQDNCAIJAM0IAgUHZnJlZU9sZAkBC1N0cmluZ0VudHJ5AgUNYWRkclRvTmFtZUtleQUKY3VzdG9tTmFtZQkBC1N0cmluZ0VudHJ5AgUKcmV2ZXJzZUtleQUEYWRkcggJARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgUEYWRkcgUMeHBDdXN0b21OYW1lAl8xAwkAAAICBExBTkQFByRtYXRjaDAEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQUHYXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQdhc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFB2Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMECnJldmVyc2VLZXkJARprZXlMYW5kQ3VzdG9tTmFtZVRvQXNzZXRJZAEFCmN1c3RvbU5hbWUECW5hbWVPd25lcgkAoggBBQpyZXZlcnNlS2V5AwkBCWlzRGVmaW5lZAEFCW5hbWVPd25lcgkAAgEJAKwCAgIZTmFtZSBhbHJlYWR5IHJlZ2lzdGVyZWQ6IAUKY3VzdG9tTmFtZQQOYXNzZXRUb05hbWVLZXkJARprZXlMYW5kQXNzZXRJZFRvQ3VzdG9tTmFtZQEFB2Fzc2V0SWQEB29sZE5hbWUJAKIIAQUOYXNzZXRUb05hbWVLZXkEB2ZyZWVPbGQDCQEJaXNEZWZpbmVkAQUHb2xkTmFtZQkAzAgCCQELRGVsZXRlRW50cnkBCQEaa2V5TGFuZEN1c3RvbU5hbWVUb0Fzc2V0SWQBCQEFdmFsdWUBBQdvbGROYW1lBQNuaWwFA25pbAkAzggCCQDNCAIJAM0IAgUHZnJlZU9sZAkBC1N0cmluZ0VudHJ5AgUOYXNzZXRUb05hbWVLZXkFCmN1c3RvbU5hbWUJAQtTdHJpbmdFbnRyeQIFCnJldmVyc2VLZXkFB2Fzc2V0SWQICQEWdXBkYXRlQWNjU3RhdHNJbnRlcm5hbAIFBGFkZHIFDHhwQ3VzdG9tTmFtZQJfMQMJAAACAgREVUNLBQckbWF0Y2gwBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUHYXNzZXRJZAMDCQEBIQEJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkGCQEBIQEJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHIJAAIBCQCsAgIIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEQa2V5RHVja0lkVG9Pd25lcgEFB2Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkRVQ0tQUkVGSVgCDSBpcyBub3QgeW91cnMECnJldmVyc2VLZXkJARprZXlEdWNrQ3VzdG9tTmFtZVRvQXNzZXRJZAEFCmN1c3RvbU5hbWUECW5hbWVPd25lcgkAoggBBQpyZXZlcnNlS2V5AwkBCWlzRGVmaW5lZAEFCW5hbWVPd25lcgkAAgEJAKwCAgIZTmFtZSBhbHJlYWR5IHJlZ2lzdGVyZWQ6IAUKY3VzdG9tTmFtZQQOYXNzZXRUb05hbWVLZXkJARprZXlEdWNrQXNzZXRJZFRvQ3VzdG9tTmFtZQEFB2Fzc2V0SWQEB29sZE5hbWUJAKIIAQUOYXNzZXRUb05hbWVLZXkEB2ZyZWVPbGQDCQEJaXNEZWZpbmVkAQUHb2xkTmFtZQkAzAgCCQELRGVsZXRlRW50cnkBCQEaa2V5RHVja0N1c3RvbU5hbWVUb0Fzc2V0SWQBCQEFdmFsdWUBBQdvbGROYW1lBQNuaWwFA25pbAkAzggCCQDNCAIJAM0IAgUHZnJlZU9sZAkBC1N0cmluZ0VudHJ5AgUOYXNzZXRUb05hbWVLZXkFCmN1c3RvbU5hbWUJAQtTdHJpbmdFbnRyeQIFCnJldmVyc2VLZXkFB2Fzc2V0SWQICQEXdXBkYXRlRHVja1N0YXRzSW50ZXJuYWwCBQdhc3NldElkBQx4cEN1c3RvbU5hbWUCXzEJAAIBAhNVbmtub3duIGVudGl0eSB0eXBlCQCUCgIJAM4IAgkAzQgCBQdhY3Rpb25zCQEOU2NyaXB0VHJhbnNmZXIDBQ9lY29ub215Q29udHJhY3QIBQNwbXQGYW1vdW50BQt1c2R0QXNzZXRJZAUNcHJvbG9nQWN0aW9ucwAAAWkBDHNldFJlZmVycmFscwIJb2xkUGxheWVyCW5ld1BsYXllcgMJAQIhPQIIBQFpD2NhbGxlclB1YmxpY0tleQUDcHViCQACAQIRUGVybWlzc2lvbiBkZW5pZWQEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQDCQEBIQEJAQlpc0RlZmluZWQBCQCmCAEFCW9sZFBsYXllcgkAAgEJAKwCAgIRSW52YWxpZCBhZGRyZXNzOiAFCW9sZFBsYXllcgQKbmV3YmllQWRkcgkApggBBQluZXdQbGF5ZXIDCQEBIQEJAQlpc0RlZmluZWQBBQpuZXdiaWVBZGRyCQACAQkArAICAhFJbnZhbGlkIGFkZHJlc3M6IAUJbmV3UGxheWVyBAlvbGRMYXN0VHgJAKIIAQkBEWtleUxhc3RUeElkQnlVc2VyAQUJb2xkUGxheWVyAwkBASEBCQEJaXNEZWZpbmVkAQUJb2xkTGFzdFR4CQACAQIib2xkUGxheWVyIGRpZG4ndCBkbyBhbnkgdHggaW4gZ2FtZQMJAGcCAAAICQDvBwEJAQV2YWx1ZQEFCm5ld2JpZUFkZHIJYXZhaWxhYmxlCQACAQIWbmV3UGxheWVyIGhhcyBubyBXQVZFUwQHb2xkc0tleQkBCWtleU9sZGllcwAEBG9sZHMJAKIIAQUHb2xkc0tleQQGb2xkaWVzAwkBCWlzRGVmaW5lZAEFBG9sZHMJALwJAgkBBXZhbHVlAQUEb2xkcwIBXwUDbmlsAwkBD2NvbnRhaW5zRWxlbWVudAIFBm9sZGllcwUJbmV3UGxheWVyCQACAQkArAICBQluZXdQbGF5ZXICJiBpcyBub3QgbmV3YmllIChhbHJlYWR5IGhhcyByZWZlcnJhbHMpBAhyZWZCeUtleQkBD2tleUFkZHJlc3NSZWZCeQEFCW5ld1BsYXllcgQFcmVmQnkJAKIIAQUIcmVmQnlLZXkDAwkBCWlzRGVmaW5lZAEFBXJlZkJ5CQEJaXNEZWZpbmVkAQkApggBCQEFdmFsdWUBBQVyZWZCeQcJAAIBCQCsAgIJAKwCAgUJbmV3UGxheWVyAhQgYWxyZWFkeSBoYXMgcmVmQnk6IAkBBXZhbHVlAQUFcmVmQnkEB3JlZnNLZXkJARNrZXlBZGRyZXNzUmVmZXJyYWxzAQUJb2xkUGxheWVyBARyZWZzCQCiCAEFB3JlZnNLZXkECXJlZnNBcnJheQMJAQlpc0RlZmluZWQBBQRyZWZzCQC8CQIJAQV2YWx1ZQEFBHJlZnMCAV8FA25pbAMJAQ9jb250YWluc0VsZW1lbnQCBQlyZWZzQXJyYXkFCW5ld1BsYXllcgkAAgEJAKwCAgkArAICCQCsAgIFCW9sZFBsYXllcgISIGFscmVhZHkgY29udGFpbnMgBQluZXdQbGF5ZXICESB3aXRoaW4gcmVmZXJyYWxzBAduZXdSZWZzCQC6CQIJAM0IAgUJcmVmc0FycmF5BQluZXdQbGF5ZXICAV8EB25ld09sZHMDCQEPY29udGFpbnNFbGVtZW50AgUGb2xkaWVzBQlvbGRQbGF5ZXIJAQV2YWx1ZQEFBG9sZHMJALoJAgkAzQgCBQZvbGRpZXMFCW9sZFBsYXllcgIBXwkAlAoCCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUIcmVmQnlLZXkFCW9sZFBsYXllcgkAzAgCCQELU3RyaW5nRW50cnkCBQdyZWZzS2V5BQduZXdSZWZzCQDMCAIJAQtTdHJpbmdFbnRyeQIFB29sZHNLZXkFB25ld09sZHMFA25pbAUNcHJvbG9nQWN0aW9ucwAAAWkBEGRpc3RyaWJ1dGVQb2ludHMFCHN0cmVuZ3RoCGFjY3VyYWN5CWludGVsbGVjdAllbmR1cmFuY2UJZGV4dGVyaXR5BA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQLdmlydFdsZ0RhdGEJAQlhc0FueUxpc3QBCQD8BwQFC3dsZ0NvbnRyYWN0AhJjaGVja1dsZ1hwUkVBRE9OTFkJAMwIAgUEYWRkcgUDbmlsBQNuaWwEDXZpcnRXbGdQb2ludHMJAQVhc0ludAEJAJEDAgULdmlydFdsZ0RhdGEAAQQNJHQwOTIxNDk5MjUzOQMJAGcCAAAFDXZpcnRXbGdQb2ludHMJAJQKAgAABQNuaWwEB2RlbHRhWFAJAQVhc0ludAEJAPwHBAULd2xnQ29udHJhY3QCCXRha2VXbGdYcAkAzAgCBQRhZGRyBQNuaWwFA25pbAMJAAACBQdkZWx0YVhQBQdkZWx0YVhQCQCUCgIFDXZpcnRXbGdQb2ludHMJAMwIAgkBDEludGVnZXJFbnRyeQIJAQxrZXlVc2VyTGV2ZWwBBQRhZGRyCQEFYXNJbnQBCQCRAwIFC3ZpcnRXbGdEYXRhAAAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQlrZXlVc2VyWFABBQRhZGRyCQEFYXNJbnQBCQCRAwIFC3ZpcnRXbGdEYXRhAAIFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQJd2xnUG9pbnRzCAUNJHQwOTIxNDk5MjUzOQJfMQQKd2xnQWN0aW9ucwgFDSR0MDkyMTQ5OTI1MzkCXzIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQKZnJlZUtleUFjYwkBEWtleVVzZXJGcmVlUG9pbnRzAQUEYWRkcgQNZnJlZVBvaW50c0FjYwkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUKZnJlZUtleUFjYwAABQl3bGdQb2ludHMEC2ZyZWVLZXlEdWNrCQERa2V5RHVja0ZyZWVQb2ludHMBBQtkdWNrQXNzZXRJZAQOZnJlZVBvaW50c0R1Y2sJAQt2YWx1ZU9yRWxzZQIJAJ8IAQULZnJlZUtleUR1Y2sAAAQHc3VtRnJlZQkAZAIFDWZyZWVQb2ludHNBY2MFDmZyZWVQb2ludHNEdWNrBA9zdW1Ub0Rpc3RyaWJ1dGUJAGQCCQBkAgkAZAIJAGQCBQhzdHJlbmd0aAUIYWNjdXJhY3kFCWludGVsbGVjdAUJZW5kdXJhbmNlBQlkZXh0ZXJpdHkDCQBmAgUPc3VtVG9EaXN0cmlidXRlBQdzdW1GcmVlCQACAQkArAICCQCsAgICD1RoZXJlIGFyZSBvbmx5IAkApAMBBQdzdW1GcmVlAhogZnJlZSBwb2ludHMgdG8gZGlzdHJpYnV0ZQQIY2hhcnNLZXkJAQxrZXlEdWNrQ2hhcnMBBQtkdWNrQXNzZXRJZAQFY2hhcnMJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQhjaGFyc0tleQIJMF8wXzBfMF8wAgFfBAZuZXdBY2MJAGUCBQ1mcmVlUG9pbnRzQWNjBQ9zdW1Ub0Rpc3RyaWJ1dGUJAJQKAgkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFCmZyZWVLZXlBY2MDCQBmAgAABQZuZXdBY2MAAAUGbmV3QWNjCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQtmcmVlS2V5RHVjawMJAGYCAAAFBm5ld0FjYwkAZAIFDmZyZWVQb2ludHNEdWNrBQZuZXdBY2MFDmZyZWVQb2ludHNEdWNrCQDMCAIJAQtTdHJpbmdFbnRyeQIFCGNoYXJzS2V5CQC5CQIJAMwIAgkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWNoYXJzBQxjaGFyU3RyZW5ndGgFCHN0cmVuZ3RoCQDMCAIJAKQDAQkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVjaGFycwUMY2hhckFjY3VyYWN5BQhhY2N1cmFjeQkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJJbnRlbGxlY3QFCWludGVsbGVjdAkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJFbmR1cmFuY2UFCWVuZHVyYW5jZQkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJEZXh0ZXJpdHkFCWRleHRlcml0eQUDbmlsAgFfBQNuaWwFDXByb2xvZ0FjdGlvbnMFCndsZ0FjdGlvbnMAAAFpARxzcGxpdEJ5R2xvYmFsV2VpZ2h0c1JFQURPTkxZAQZhbW91bnQJAJQKAgUDbmlsCQESZ2V0TmVlZGVkTWF0ZXJpYWxzAQUGYW1vdW50AWkBJHNwbGl0QnlHbG9iYWxBbmRMb2NhbFdlaWdodHNSRUFET05MWQMJbWF0QW1vdW50CXJlc0Ftb3VudAh0ZXJyYWlucwQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBBQh0ZXJyYWlucwkAlAoCBQNuaWwJAJQKAgkBEmdldE5lZWRlZE1hdGVyaWFscwEFCW1hdEFtb3VudAkBE2Rpc3RyaWJ1dGVCeVdlaWdodHMCBQlyZXNBbW91bnQFDXRlcnJhaW5Db3VudHMBaQETZ2V0QmFja3BhY2tSRUFET05MWQELZHVja0Fzc2V0SWQJAJQKAgUDbmlsCQC5CQIJAQtnZXRCYWNrcGFjawEJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkAgE6AWkBFGdldFdhcmVob3VzZVJFQURPTkxZAQtsYW5kQXNzZXRJZAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQJbGFuZEluZGV4CQBpAgkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAgkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8FC3JlY0xhbmRTaXplBQVTU0laRQQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAJAJQKAgUDbmlsCQC6CQIJAQxnZXRXYXJlaG91c2UDCQESa2V5V2FyZWhvdXNlQnlMYW5kAQULbGFuZEFzc2V0SWQFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAIBOgFpAQpzYXZlTGFzdFR4AAMJAQEhAQkBD2NvbnRhaW5zRWxlbWVudAIJAMwIAgULd2xnQ29udHJhY3QJAMwIAgUPZWNvbm9teUNvbnRyYWN0CQDMCAIFEnRvdXJuYW1lbnRDb250cmFjdAkAzAgCBQ1hY3Jlc0NvbnRyYWN0BQNuaWwIBQFpBmNhbGxlcgkAAgECDUFjY2VzcyBkZW5pZWQJAJQKAgkBBnByb2xvZwEFAWkAKgFpAQ91cGRhdGVEdWNrU3RhdHMCC2R1Y2tBc3NldElkB2RlbHRhWFADCQECIT0CCAUBaQZjYWxsZXIFD2Vjb25vbXlDb250cmFjdAkAAgECDUFjY2VzcyBkZW5pZWQJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkBQdkZWx0YVhQAWkBDnVwZGF0ZUFjY1N0YXRzAgRhZGRyB2RlbHRhWFADCQEBIQEJAQ9jb250YWluc0VsZW1lbnQCCQDMCAIFC3dsZ0NvbnRyYWN0CQDMCAIFD2Vjb25vbXlDb250cmFjdAkAzAgCBQ1hY3Jlc0NvbnRyYWN0BQNuaWwIBQFpBmNhbGxlcgkAAgECDUFjY2VzcyBkZW5pZWQJARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgUEYWRkcgUHZGVsdGFYUAFpAQllcXVpcER1Y2sBCWVxdWlwbWVudAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQEYWRkcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAMJAQ9jaGVja1RvdXJuYW1lbnQBBQtkdWNrQXNzZXRJZAkAAgECGWVxdWlwRHVja19jaGVja1RvdXJuYW1lbnQEBWVxS2V5CQEQa2V5RHVja0VxdWlwbWVudAEFC2R1Y2tBc3NldElkBAtjdXJyZW50U2VncwkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFBWVxS2V5AhcsOyxfLDssXyw7LF8sOyxfLDssXyw7LAIBXwQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW5ld0VxCQC1CQIFCWVxdWlwbWVudAIBXwMJAQIhPQIJAJADAQUFbmV3RXEFC05VTVNFR01FTlRTCQACAQIWV3JvbmcgZXF1aXBtZW50IHN0cmluZwQJdGVtcFByb2RCCQEGZHJlc3NCBAULY3VycmVudFNlZ3MJAQ5wcm9kU3RyVG9CeXRlcwEJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAYFA25pbAQIc2VnQnBBdXgJAJEDAgkAtQkCCQCRAwIFBW5ld0VxBQtzZWdCYWNrcGFjawIBOwABBApidWZmRWZmZWN0AwkAAAIFCHNlZ0JwQXV4AgAAAAQEYXV4MAkAkQMCCQC1CQIFCHNlZ0JwQXV4AgEsAAADCQAAAgUEYXV4MAIAAAAEBmlkeENudAkAtQkCBQRhdXgwAgE6BANpZHgJAJEDAgUGaWR4Q250AAAEA2NudAkAkQMCBQZpZHhDbnQAAQMDAwMDCQAAAgUDaWR4AgIwNgYJAAACBQNpZHgCAjA3BgkAAAIFA2lkeAICMDgJAQIhPQIFA2NudAIABwkAZgIJAQ1wYXJzZUludFZhbHVlAQUDY250AAAHCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgJAQ1wYXJzZUludFZhbHVlAQUDaWR4AgFfBQpySWR4RWZmZWN0AAAEBXN0YXRzCQEMZ2V0RHVja1N0YXRzBAUEdGhpcwULZHVja0Fzc2V0SWQFCmJ1ZmZFZmZlY3QGBAhuZXdQcm9kQgkBBmRyZXNzQgQFBW5ld0VxBQl0ZW1wUHJvZEIHBQVzdGF0cwQKbmV3UHJvZFN0cgkBDmJ5dGVzVG9Qcm9kU3RyAQUIbmV3UHJvZEIJAJQKAgkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWVxS2V5BQllcXVpcG1lbnQJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALoJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0CQDMCAIFCm5ld1Byb2RTdHIFA25pbAIBOgkAzAgCCQELU3RyaW5nRW50cnkCCQEMa2V5RHVja0J1ZmZzAQULZHVja0Fzc2V0SWQJALkJAgkAzAgCCQCkAwEJAJEDAgUFc3RhdHMABwkAzAgCCQCkAwEJAJEDAgUFc3RhdHMACAkAzAgCCQCkAwEJAJEDAgUFc3RhdHMACQkAzAgCCQCkAwEJAJEDAgUFc3RhdHMACgkAzAgCCQCkAwEJAJEDAgUFc3RhdHMACwUDbmlsAgFfBQNuaWwFDXByb2xvZ0FjdGlvbnMAAAFpARNpbml0RHVja1RvdXJBdHRlbXB0AQtkdWNrQXNzZXRJZAMJAQIhPQIIBQFpBmNhbGxlcgUSdG91cm5hbWVudENvbnRyYWN0CQACAQINQWNjZXNzIGRlbmllZAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAVtYXhIUAkBCW1heEhlYWx0aAEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBDGtleUR1Y2tMZXZlbAEFC2R1Y2tBc3NldElkAAAECWN1ckhlYWx0aAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgFBW1heEhQBAljdXJMb2NLZXkJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQUJY3VyTG9jS2V5BQ9ERUZBVUxUTE9DQVRJT04EBmxhc3RJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBRJ0b3VybmFtZW50Q29udHJhY3QFDWxhc3RUb3VySWRLZXkAAAQMdG91ckxvY2F0aW9uCQCsAgIJAKQDAQUGbGFzdElkAgRfVF8wCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ5rZXlTYXZlZEhlYWx0aAEFC2R1Y2tBc3NldElkBQljdXJIZWFsdGgJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtleUhlYWx0aAUFbWF4SFAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEGtleVNhdmVkTG9jYXRpb24BBQtkdWNrQXNzZXRJZAULY3VyTG9jYXRpb24JAMwIAgkBC1N0cmluZ0VudHJ5AgUJY3VyTG9jS2V5BQx0b3VyTG9jYXRpb24FA25pbAUMdG91ckxvY2F0aW9uAWkBDGJyZWFrQXR0ZW1wdAAEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEJAKUIAQgFAWkGY2FsbGVyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAljdXJMb2NLZXkJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQUJY3VyTG9jS2V5BQ9ERUZBVUxUTE9DQVRJT04DCQECIT0CCQCRAwIJALUJAgULY3VyTG9jYXRpb24CAV8FCmxvY0lkeFR5cGUCAVQJAAIBAiJZb3VyIGR1Y2sgaXMgbm90IGluIHRoZSB0b3VybmFtZW50BAtzYXZlZEhlYWx0aAkBEUBleHRyTmF0aXZlKDEwNTUpAQkBDmtleVNhdmVkSGVhbHRoAQULZHVja0Fzc2V0SWQEDXNhdmVkTG9jYXRpb24JARFAZXh0ck5hdGl2ZSgxMDU4KQEJARBrZXlTYXZlZExvY2F0aW9uAQULZHVja0Fzc2V0SWQJAJQKAgkAzQgCCQDNCAIFDXByb2xvZ0FjdGlvbnMJAQxJbnRlZ2VyRW50cnkCCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBQtzYXZlZEhlYWx0aAkBC1N0cmluZ0VudHJ5AgUJY3VyTG9jS2V5BQ1zYXZlZExvY2F0aW9uBQtjdXJMb2NhdGlvbgFpARRicmVha0F0dGVtcHRDYWxsYmFjawADCQECIT0CCAUBaQZjYWxsZXIFEnRvdXJuYW1lbnRDb250cmFjdAkAAgECDUFjY2VzcyBkZW5pZWQEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQxvcmlnaW5DYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAkBEUBleHRyTmF0aXZlKDEwNTUpAQkBDmtleVNhdmVkSGVhbHRoAQULZHVja0Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEQa2V5U2F2ZWRMb2NhdGlvbgEFC2R1Y2tBc3NldElkBQNuaWwCFGJyZWFrQXR0ZW1wdENhbGxiYWNrAWkBFmV4aXRUb3VybmFtZW50SW50ZXJuYWwBC2R1Y2tBc3NldElkAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQINQWNjZXNzIGRlbmllZAQLc2F2ZWRIZWFsdGgJARFAZXh0ck5hdGl2ZSgxMDU1KQEJAQ5rZXlTYXZlZEhlYWx0aAEFC2R1Y2tBc3NldElkBA1zYXZlZExvY2F0aW9uCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEQa2V5U2F2ZWRMb2NhdGlvbgEFC2R1Y2tBc3NldElkCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQFC3NhdmVkSGVhbHRoCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUNc2F2ZWRMb2NhdGlvbgUDbmlsBwFpAQ9wcm9jZXNzRGVsaXZlcnkBC2R1Y2tBc3NldElkAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQINQWNjZXNzIGRlbmllZAQEYWRkcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIECWZ1bmRUb3RhbAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ9lY29ub215Q29udHJhY3QFD2RlbGl2ZXJ5RnVuZEtleQAAAwkAZgIFFU1JTl9VU0RUX0ZFRV9ERUxJVkVSWQUJZnVuZFRvdGFsCQACAQkArAICAiBEZWxpdmVyeSBpcyBub3QgYXZhaWxhYmxlLCBmdW5kPQkBCmZpeGVkUG9pbnQCBQlmdW5kVG90YWwABgQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQIY291bnRLZXkJARRrZXlVc2VyRGVsaXZlcnlDb3VudAEFBGFkZHIEB2xhc3REYXkJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBFmtleVVzZXJMYXN0RGVsaXZlcnlEYXkBBQRhZGRyAAAEBXRvZGF5CQBpAgUDbm93BQlEQVlNSUxMSVMEBWNvdW50AwkAAAIFB2xhc3REYXkFBXRvZGF5CQELdmFsdWVPckVsc2UCCQCfCAEFCGNvdW50S2V5AAAAAAQFYWNyZXMJAQt2YWx1ZU9yRWxzZQIJAJoIAgUNYWNyZXNDb250cmFjdAkBGmtleUFjcmVzU3Rha2VkQW1vdW50QnlVc2VyAQUEYWRkcgAABBFhbGxvd2VkRGVsaXZlcmllcwkAZAIFF0FMTE9XRURfRlJFRV9ERUxJVkVSSUVTCQBpAgUFYWNyZXMFGkFDUkVTX0ZPUl9ERUxJVkVSWV9BVFRFTVBUAwkAZwIFBWNvdW50BRFhbGxvd2VkRGVsaXZlcmllcwkAAgEJAKwCAgkArAICAhFZb3UgYWxyZWFkeSB1c2VkIAkApAMBBRFhbGxvd2VkRGVsaXZlcmllcwIcIGRlbGl2ZXJ5IGF0dGVtcHRzIGZvciB0b2RheQQOZ2xvYmFsQ291bnRLZXkJARRrZXlEdWNrRGVsaXZlcnlDb3VudAEFC2R1Y2tBc3NldElkBAZyZXdhcmQJAPwHBAUPZWNvbm9teUNvbnRyYWN0AhJzZW5kRGVsaXZlcnlSZXdhcmQJAMwIAgUEYWRkcgUDbmlsBQNuaWwJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUIY291bnRLZXkJAGQCBQVjb3VudAABCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5VXNlckxhc3REZWxpdmVyeURheQEFBGFkZHIFBXRvZGF5CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5nbG9iYWxDb3VudEtleQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUOZ2xvYmFsQ291bnRLZXkAAAABBQNuaWwFBnJld2FyZAFpAQdyb2JMYW5kAgdtZXNzYWdlA3NpZwQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAiJleGFjdGx5IDEgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAQGd2xnQW10CAUDcG10BmFtb3VudAMDCQEBIQEJAQlpc0RlZmluZWQBCAUDcG10B2Fzc2V0SWQGCQECIT0CCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQFCndsZ0Fzc2V0SWQJAAIBAhVXTEdPTEQgcGF5bWVudHMgb25seSEDCQECIT0CBQZ3bGdBbXQFEk1JTl9XTEdPTERfUk9CQkVSWQkAAgEJAKwCAgkArAICAhJQYXltZW50IHNob3VsZCBiZSAJAQpmaXhlZFBvaW50AgUSTUlOX1dMR09MRF9ST0JCRVJZAAgCByBXTEdPTEQEBGFkZHIJAKUIAQgFAWkGY2FsbGVyAwkBASEBCQDEEwMFB21lc3NhZ2UFA3NpZwUDcHViCQACAQIYc2lnbmF0dXJlIGRvZXMgbm90IG1hdGNoBAVwYXJ0cwkAvAkCCQCwCQEFB21lc3NhZ2UCATsEBnJvYkxvZwkAvAkCCQCRAwIFBXBhcnRzAAACAXwEAmhwCQC1CQIJAJEDAgUGcm9iTG9nBQhybEhlYWx0aAIBXwQFY3VySFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAAABAVuZXdIUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmhwAAEECHByb2RVc2VkCQCRAwIFBnJvYkxvZwULcmxQcm9kc1VzZWQECGxhc3RQYXJ0CQC1CQIJAJEDAgUFcGFydHMAAQIBfAQHcm9iVHlwZQkAkQMCBQhsYXN0UGFydAUGcmxUeXBlAwkBAiE9AgUHcm9iVHlwZQIBQgkAAgECHk9ubHkgYmFuayByb2JiZXJ5IGlzIHN1cHBvcnRlZAQEdGltZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCGxhc3RQYXJ0BQtybFRpbWVzdGFtcAMDCQBmAgUEdGltZQkAZAIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBRFGSVZFTUlOVVRFU01JTExJUwYJAGYCCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFEUZJVkVNSU5VVEVTTUlMTElTBQR0aW1lCQACAQkArAICCQCsAgIJAKwCAgIcc2lnbmF0dXJlIG91dGRhdGVkOiBsb2dUaW1lPQkApAMBBQR0aW1lAgksIGJjVGltZT0JAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAECXR4RnJvbU1zZwkAkQMCBQhsYXN0UGFydAUIcmxMYXN0VHgEBmxhc3RUeAkBC3ZhbHVlT3JFbHNlAgkAoggBCQERa2V5TGFzdFR4SWRCeVVzZXIBBQRhZGRyAgADCQECIT0CBQZsYXN0VHgFCXR4RnJvbU1zZwkAAgEJAKwCAgkArAICCQCsAgICHlR4IGlkcyBkb24ndCBtYXRjaCEgSW4gc3RhdGU6IAUGbGFzdFR4AgosIGluIG1zZzogBQl0eEZyb21Nc2cEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQFZXFLZXkJARBrZXlEdWNrRXF1aXBtZW50AQULZHVja0Fzc2V0SWQECWN1cnJlbnRFcQkBC3ZhbHVlT3JFbHNlAgkAoggBBQVlcUtleQIXLDssXyw7LF8sOyxfLDssXyw7LF8sOywEDyR0MDEwOTcxNzEwOTgyOAkBEXN1YnRyYWN0RXF1aXBtZW50AgUJY3VycmVudEVxBQhwcm9kVXNlZAQFbmV3RXEIBQ8kdDAxMDk3MTcxMDk4MjgCXzEED3Nob3VsZFplcm9CdWZmcwgFDyR0MDEwOTcxNzEwOTgyOAJfMgQIaXNCcFVzZWQIBQ8kdDAxMDk3MTcxMDk4MjgCXzMEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OAwkBDmlzSW5Ub3VybmFtZW50AgUSdG91cm5hbWVudENvbnRyYWN0BQtjdXJMb2NhdGlvbgkAAgECKllvdXIgZHVjayBpcyB0YWtpbmcgcGFydCBpbiB0aGUgdG91cm5hbWVudAQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQIY291bnRLZXkJARNrZXlVc2VyUm9iYmVyeUNvdW50AQUEYWRkcgQHbGFzdERheQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEVa2V5VXNlckxhc3RSb2JiZXJ5RGF5AQUEYWRkcgAABAV0b2RheQkAaQIFA25vdwUJREFZTUlMTElTBAVjb3VudAMJAAACBQdsYXN0RGF5BQV0b2RheQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQhjb3VudEtleQAAAAAEBWFjcmVzCQELdmFsdWVPckVsc2UCCQCaCAIFDWFjcmVzQ29udHJhY3QJARprZXlBY3Jlc1N0YWtlZEFtb3VudEJ5VXNlcgEFBGFkZHIAAAQQYWxsb3dlZFJvYmJlcmllcwkAZAIFFkFMTE9XRURfRlJFRV9ST0JCRVJJRVMJAGkCBQVhY3JlcwUZQUNSRVNfRk9SX1JPQkJFUllfQVRURU1QVAMJAGcCBQVjb3VudAUQYWxsb3dlZFJvYmJlcmllcwkAAgEJAKwCAgkArAICAhFZb3UgYWxyZWFkeSB1c2VkIAkApAMBBRBhbGxvd2VkUm9iYmVyaWVzAhsgcm9iYmVyeSBhdHRlbXB0cyBmb3IgdG9kYXkEDmdsb2JhbENvdW50S2V5CQETa2V5RHVja1JvYmJlcnlDb3VudAEFC2R1Y2tBc3NldElkBARsb290AwkAZgIFBW5ld0hQAAAECWZ1bmRUb3RhbAkA8AcCBQR0aGlzBQp3bGdBc3NldElkBAVwcml6ZQMFCGlzQnBVc2VkCQBoAgACBRJNSU5fV0xHT0xEX1JPQkJFUlkJAGgCAAUFEk1JTl9XTEdPTERfUk9CQkVSWQMJAGYCBQVwcml6ZQUJZnVuZFRvdGFsCQACAQkArAICCQCsAgIJAKwCAgIiUm9iYmVyeSBpcyBub3QgYXZhaWxhYmxlLCBmdW5kcyA9IAkBCmZpeGVkUG9pbnQCBQlmdW5kVG90YWwACAIUIFdMR09MRCwgcmVxdWlyZWQgPSAJAQpmaXhlZFBvaW50AgUFcHJpemUACAkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIFBXByaXplBQp3bGdBc3NldElkBQNuaWwFA25pbAkAlAoCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDOCAIJAM4IAgkAzggCBQ1wcm9sb2dBY3Rpb25zBQRsb290AwUPc2hvdWxkWmVyb0J1ZmZzCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxrZXlEdWNrQnVmZnMBBQtkdWNrQXNzZXRJZAIJMF8wXzBfMF8wBQNuaWwFA25pbAgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkAwkAZgIFBW5ld0hQAAAFDHhwU3VjY2Vzc1JvYgUJeHBGYWlsUm9iAl8xCQEMSW50ZWdlckVudHJ5AgkBGGtleUxhc3RSb2JiZXJ5VGltZUJ5RHVjawEFC2R1Y2tBc3NldElkBQNub3cJAQxJbnRlZ2VyRW50cnkCBQhjb3VudEtleQkAZAIFBWNvdW50AAEJAQxJbnRlZ2VyRW50cnkCCQEVa2V5VXNlckxhc3RSb2JiZXJ5RGF5AQUEYWRkcgUFdG9kYXkJAQxJbnRlZ2VyRW50cnkCBQ5nbG9iYWxDb3VudEtleQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUOZ2xvYmFsQ291bnRLZXkAAAABCQELU3RyaW5nRW50cnkCBQVlcUtleQUFbmV3RXEJAQxJbnRlZ2VyRW50cnkCCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkCQCWAwEJAMwIAgUFbmV3SFAJAMwIAgAABQNuaWwAAAFpAQtidXlSb2JvRHVjawADCQEBIQEFE0tTX0FMTE9XX1JPQk9fRFVDS1MJAAIBAhVGZWF0dXJlIGlzIHR1cm5lZCBvZmYEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZHRBc3NldElkCQACAQIaQWxsb3dlZCBVU0RUIHBheW1lbnQgb25seSEDCQECIT0CCAUDcG10BmFtb3VudAUOUk9CT19EVUNLX1VTRFQJAAIBCQCsAgIJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQEKZml4ZWRQb2ludAIFDlJPQk9fRFVDS19VU0RUAAYCBSBVU0RUBAduZXh0TnVtCQELdmFsdWVPckVsc2UCCQCfCAEJAQ9rZXlOZXh0Um9ib0R1Y2sAAAAEBWJ5dGV6CQCaAwEFB25leHROdW0EBG5hbWUJAKwCAgkArAICBQtST0JPX1BSRUZJWAIBLQkAsgICCQDcBAEFBWJ5dGV6AAgEBWNvbG9yCQCyAgIJANwEAQkA1BYBBQVieXRlegAGBAVpc3N1ZQkAwggFBQRuYW1lCQCsAgICN1JvYm8gRHVjayBORlQgZm9yIFdhdmVzTGFuZHMgZ2FtZSwgYmFja2dyb3VuZCBjb2xvciA9ICMFBWNvbG9yAAEAAAcEB2Fzc2V0SWQJALgIAQUFaXNzdWUJAJQKAgkAzQgCCQDNCAIJAM0IAgkAzQgCBQ1wcm9sb2dBY3Rpb25zCQEMSW50ZWdlckVudHJ5AgkBD2tleU5leHRSb2JvRHVjawAJAGQCBQduZXh0TnVtAAEFBWlzc3VlCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQxvcmlnaW5DYWxsZXIAAQUHYXNzZXRJZAkBDlNjcmlwdFRyYW5zZmVyAwUPZWNvbm9teUNvbnRyYWN0CAUDcG10BmFtb3VudAULdXNkdEFzc2V0SWQJAJQKAgkA2AQBBQdhc3NldElkBQVjb2xvcgBQdjGR", "height": 2908526, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 3SQXtVVxLUUN5jytAaq6AuXuiUGHmAhFhVTyCv3v6nCW Next: 7YtfLVRpbiGN3Dc1uuTqV9RS47mUbvj6fWrGgoCDQrSV Diff:
Old | New | Differences | |
---|---|---|---|
17 | 17 | ||
18 | 18 | let numPointsOnLevelUp = 3 | |
19 | 19 | ||
20 | - | let robberyCostMin = 100000000 | |
21 | - | ||
22 | - | let robberyCooldownCoeff = 400 | |
23 | - | ||
24 | 20 | let requirements = ["Strength", "Accuracy", "Intellect", "Endurance", "Dexterity", "Level", "Health"] | |
25 | 21 | ||
26 | 22 | let charStrength = 0 | |
43 | 39 | ||
44 | 40 | let MAXPRODINSLOT = 30 | |
45 | 41 | ||
46 | - | let landRobCooldowns = [0, 600000, 900000, 43200000, 21600000] | |
47 | - | ||
48 | - | let MIN_RES_TO_ROB = 20000000 | |
49 | - | ||
50 | - | let robIdxLocked = 1 | |
51 | - | ||
52 | - | let duckIdxFree = 0 | |
53 | - | ||
54 | - | let duckIdxPreparing = 1 | |
55 | - | ||
56 | 42 | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
57 | 43 | ||
58 | 44 | ||
92 | 78 | func keyLastRobberyTimeByDuck (duckAssetId) = ("lastRobberyTime_" + duckAssetId) | |
93 | 79 | ||
94 | 80 | ||
95 | - | func keyLastRobberyCostByDuck (duckAssetId) = ("lastRobberyCost_" + duckAssetId) | |
96 | - | ||
97 | - | ||
98 | - | func keyLandRobberyState (landAssetId) = ("landRobberyState_" + landAssetId) | |
99 | - | ||
100 | - | ||
101 | - | func keyLandCooldownETA (landAssetId) = ("landCooldownETA_" + landAssetId) | |
102 | - | ||
103 | - | ||
104 | - | func keyDuckRobberyState (duckAssetId) = ("duckRobberyState_" + duckAssetId) | |
105 | - | ||
106 | - | ||
107 | - | func keyLockedLandByDuck (duckAssetId) = ("lockedLandByDuck_" + duckAssetId) | |
81 | + | func keyDuckRobberyCount (duckAssetId) = ("totalRobberyCountByDuck_" + duckAssetId) | |
82 | + | ||
83 | + | ||
84 | + | func keyUserRobberyCount (addr) = ("userRobberyCount_" + addr) | |
85 | + | ||
86 | + | ||
87 | + | func keyUserLastRobberyDay (addr) = ("userLastRobberyDay_" + addr) | |
108 | 88 | ||
109 | 89 | ||
110 | 90 | func keyDuckDeliveryCount (duckAssetId) = ("totalDeliveryCountByDuck_" + duckAssetId) | |
121 | 101 | let xpSuccessFlight = 10000 | |
122 | 102 | ||
123 | 103 | let xpFailFlight = 2000 | |
104 | + | ||
105 | + | let xpSuccessRob = 10000 | |
106 | + | ||
107 | + | let xpFailRob = 2000 | |
124 | 108 | ||
125 | 109 | let xpCallES = 100000 | |
126 | 110 | ||
159 | 143 | } | |
160 | 144 | ||
161 | 145 | ||
162 | - | func getRobberyData (stakingContract,duckAssetId) = { | |
163 | - | let lastRobCost = valueOrElse(getInteger(stakingContract, keyLastRobberyCostByDuck(duckAssetId)), 0) | |
164 | - | let lastRobTime = valueOrElse(getInteger(stakingContract, keyLastRobberyTimeByDuck(duckAssetId)), 0) | |
165 | - | let now = lastBlock.timestamp | |
166 | - | let robCost = max([robberyCostMin, (lastRobCost - (robberyCooldownCoeff * (now - lastRobTime)))]) | |
167 | - | let duckState = valueOrElse(getInteger(stakingContract, keyDuckRobberyState(duckAssetId)), 0) | |
168 | - | let lockedLand = valueOrElse(getString(stakingContract, keyLockedLandByDuck(duckAssetId)), "") | |
169 | - | let landETA = valueOrElse(getInteger(stakingContract, keyLandCooldownETA(lockedLand)), 0) | |
170 | - | $Tuple5(robCost, lastRobTime, duckState, lockedLand, landETA) | |
171 | - | } | |
172 | - | ||
173 | - | ||
174 | 146 | let LANDPREFIX = "LAND" | |
175 | 147 | ||
176 | 148 | let DUCKPREFIX = "DUCK" | |
195 | 167 | ||
196 | 168 | let MIN_USDT_FEE_DELIVERY = 50000 | |
197 | 169 | ||
170 | + | let MIN_WLGOLD_ROBBERY = 100000000 | |
171 | + | ||
172 | + | let ALLOWED_FREE_ROBBERIES = 0 | |
173 | + | ||
174 | + | let ACRES_FOR_ROBBERY_ATTEMPT = 200000000 | |
175 | + | ||
198 | 176 | let ALLOWED_FREE_DELIVERIES = 0 | |
199 | 177 | ||
200 | 178 | let ACRES_FOR_DELIVERY_ATTEMPT = 200000000 | |
205 | 183 | ||
206 | 184 | let COEFF2MAT = 10000000 | |
207 | 185 | ||
208 | - | let fortAllowedProds = [15, 16, 17, 18, 19, 20, 21, 22, 23] | |
209 | - | ||
210 | 186 | let productionMatrix = ["8_8_8_17_17_42_12_0_30_0,0,0,0,0,0,0_", "8_8_8_17_17_42_24_0_60_0,0,5,2,0,0,0_", "8_8_8_17_17_42_36_0_120_0,0,10,4,0,0,0_", "8_19_19_8_27_19_26_1_20_0,0,0,0,0,0,0_001", "8_19_19_8_27_19_52_1_40_0,0,0,0,0,0,0_001", "8_19_19_8_27_19_78_1_80_0,0,0,0,0,0,0_001", "8_8_8_8_8_60_13_2_2_0,0,0,0,0,0,0_011", "8_8_8_8_8_60_26_2_4_0,0,0,0,0,0,0_011", "8_8_8_8_8_60_39_2_8_0,0,0,0,0,0,0_011", "30_30_3_17_17_3_30_3_30_0,0,0,0,0,0,0_111", "30_30_3_17_17_3_60_3_50_0,0,0,0,0,0,0_111", "30_30_3_17_17_3_90_3_70_0,0,0,0,0,0,0_111", "18_18_10_18_18_18_11_4_10_0,0,0,0,0,0,0_201", "18_18_10_18_18_18_22_4_20_0,0,0,0,0,0,0_201", "18_18_10_18_18_18_33_4_30_0,0,0,0,0,0,0_201", "4_13_22_4_35_22_23_0_50,1,0_0,0,0,0,0,0,0_", "4_13_22_4_35_22_46_0_50,1,1_0,2,5,0,0,0,0_", "4_13_22_4_35_22_69_0_50,2,1_0,5,10,0,0,0,0_", "5_25_40_5_10_15_20_1_30,1,1_0,0,0,0,0,0,0_", "5_25_40_5_10_15_40_1_30,1,2_2,1,3,0,0,0,0_", "5_25_40_5_10_15_60_1_30,1,3_5,2,8,0,0,0,0_", "23_23_5_20_23_6_35_2_100_0,0,0,0,0,0,0_", "23_23_5_20_23_6_70_2_150_0,0,0,0,0,0,0_", "23_23_5_20_23_6_105_2_200_0,0,0,0,0,0,0_"] | |
211 | 187 | ||
212 | 188 | let rIdxCoeff = 6 | |
270 | 246 | ||
271 | 247 | ||
272 | 248 | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
273 | - | ||
274 | - | ||
275 | - | func keyFortificationsByLand (landAssetId) = ("fortifications_" + landAssetId) | |
276 | 249 | ||
277 | 250 | ||
278 | 251 | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
622 | 595 | else throw("Unknown chain") | |
623 | 596 | } | |
624 | 597 | ||
625 | - | let EMPTY_PROD50 = base64'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' | |
626 | - | ||
627 | 598 | let FIVEMINUTESMILLIS = 300000 | |
628 | 599 | ||
629 | 600 | let RENAMINGCOST = 5000000 | |
709 | 680 | ||
710 | 681 | let flProdsUsed = 7 | |
711 | 682 | ||
683 | + | let rlHealth = 0 | |
684 | + | ||
685 | + | let rlProdsUsed = 1 | |
686 | + | ||
687 | + | let rlType = 0 | |
688 | + | ||
689 | + | let rlLastTx = 2 | |
690 | + | ||
691 | + | let rlTimestamp = 3 | |
692 | + | ||
712 | 693 | func nftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize) | |
713 | 694 | ||
714 | 695 | ||
784 | 765 | ||
785 | 766 | ||
786 | 767 | func subtractEquipment (oldEq,pUsed) = if ((pUsed == "")) | |
787 | - | then $ | |
768 | + | then $Tuple3(oldEq, false, false) | |
788 | 769 | else { | |
789 | 770 | func subUsed (acc,idxAmt) = { | |
790 | 771 | let parts = split(idxAmt, ",") | |
811 | 792 | let newAmt = if ((curr >= amt)) | |
812 | 793 | then (curr - amt) | |
813 | 794 | else throw(((((("You equipped " + toString(curr)) + " of ") + prodTypes[idx]) + ", but tried to use ") + toString(amt))) | |
814 | - | $ | |
795 | + | $Tuple3(((((eqParts[0] + parts[0]) + ":") + toString(newAmt)) + tail), if (acc._2) | |
815 | 796 | then true | |
816 | 797 | else if (if ((idx >= 6)) | |
817 | 798 | then (8 >= idx) | |
818 | 799 | else false) | |
819 | 800 | then (newAmt == 0) | |
801 | + | else false, if (acc._3) | |
802 | + | then true | |
803 | + | else if (if ((idx >= 3)) | |
804 | + | then (5 >= idx) | |
805 | + | else false) | |
806 | + | then (amt > 0) | |
820 | 807 | else false) | |
821 | 808 | } | |
822 | 809 | } | |
825 | 812 | ||
826 | 813 | let $l = split(pUsed, "_") | |
827 | 814 | let $s = size($l) | |
828 | - | let $acc0 = $ | |
815 | + | let $acc0 = $Tuple3(oldEq, false, false) | |
829 | 816 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
830 | 817 | then $a | |
831 | 818 | else subUsed($a, $l[$i]) | |
911 | 898 | else throw("List size exceeds 7") | |
912 | 899 | ||
913 | 900 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7) | |
914 | - | } | |
915 | - | ||
916 | - | ||
917 | - | func placeProdB (idxCnt,pList,isPositive,duckStats,occupied,free) = { | |
918 | - | let parts = split(idxCnt, ":") | |
919 | - | if ((size(parts) != 2)) | |
920 | - | then throw("Incorrect format, should be index:amount") | |
921 | - | else if (if (!(isPositive)) | |
922 | - | then (size(parts[0]) != 2) | |
923 | - | else false) | |
924 | - | then throw("Product idx should be 2 digits, zero padded") | |
925 | - | else { | |
926 | - | let productIdx = parseIntValue(parts[0]) | |
927 | - | let count = parseIntValue(parts[1]) | |
928 | - | if (!(containsElement(fortAllowedProds, productIdx))) | |
929 | - | then throw((("Product '" + prodTypes[productIdx]) + "' cannot be used for land defense")) | |
930 | - | else if ((0 > count)) | |
931 | - | then throw("Count can't be negative") | |
932 | - | else if ((count > MAXPRODINSLOT)) | |
933 | - | then throw(((("Can't put more than " + toString(MAXPRODINSLOT)) + " of ") + prodTypes[productIdx])) | |
934 | - | else if ((count == 0)) | |
935 | - | then $Tuple3(pList, occupied, free) | |
936 | - | else { | |
937 | - | let head = take(pList, (8 * productIdx)) | |
938 | - | let curr = toInt(take(drop(pList, (8 * productIdx)), 8)) | |
939 | - | let tail = drop(pList, (8 * (productIdx + 1))) | |
940 | - | let recipe = split(productionMatrix[productIdx], "_") | |
941 | - | if (if (!(isPositive)) | |
942 | - | then (count > curr) | |
943 | - | else false) | |
944 | - | then throw(((((("You have " + toString(curr)) + " of ") + prodTypes[productIdx]) + ", but tried to use ") + toString(count))) | |
945 | - | else { | |
946 | - | let newAmt = if (if (!(isPositive)) | |
947 | - | then checkStatRequirements(duckStats, split(recipe[rIdxRequirements], ",")) | |
948 | - | else false) | |
949 | - | then (curr - count) | |
950 | - | else (curr + count) | |
951 | - | let deltaVol = (toVolume(newAmt, PRODUCTPKGSIZE) - toVolume(curr, PRODUCTPKGSIZE)) | |
952 | - | $Tuple3(((head + toBytes(newAmt)) + tail), (occupied + deltaVol), (free - deltaVol)) | |
953 | - | } | |
954 | - | } | |
955 | - | } | |
956 | 901 | } | |
957 | 902 | ||
958 | 903 | ||
1088 | 1033 | } | |
1089 | 1034 | ||
1090 | 1035 | ||
1091 | - | func fortB (segList,pBytes,occupied,free,isPositive,duckStats) = if ((3 > size(segList))) | |
1092 | - | then throw("At least duck, mines and traps parts are required") | |
1093 | - | else { | |
1094 | - | func segment (acc,seg) = { | |
1095 | - | let j = acc._1 | |
1096 | - | if ((j == 0)) | |
1097 | - | then $Tuple4((j + 1), acc._2, acc._3, acc._4) | |
1098 | - | else { | |
1099 | - | let p = placeProdB(seg, acc._2, isPositive, duckStats, acc._3, acc._4) | |
1100 | - | $Tuple4((j + 1), p._1, p._2, p._3) | |
1101 | - | } | |
1102 | - | } | |
1103 | - | ||
1104 | - | let t = { | |
1105 | - | let $l = segList | |
1106 | - | let $s = size($l) | |
1107 | - | let $acc0 = $Tuple4(0, pBytes, occupied, free) | |
1108 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1109 | - | then $a | |
1110 | - | else segment($a, $l[$i]) | |
1111 | - | ||
1112 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1113 | - | then $a | |
1114 | - | else throw("List size exceeds 10") | |
1115 | - | ||
1116 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
1117 | - | } | |
1118 | - | $Tuple3(t._2, t._3, t._4) | |
1119 | - | } | |
1120 | - | ||
1121 | - | ||
1122 | 1036 | func canWearCurrentEquipment (duckAssetId) = { | |
1123 | 1037 | let eqKey = keyDuckEquipment(duckAssetId) | |
1124 | 1038 | let currEq = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_") | |
1039 | + | let EMPTY_PROD50 = base64'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' | |
1125 | 1040 | let tempProdB = dressB(currEq, EMPTY_PROD50, true, nil) | |
1126 | 1041 | let segBpAux = split(currEq[segBackpack], ";")[1] | |
1127 | 1042 | let buffEffect = if ((segBpAux == "")) | |
1733 | 1648 | ||
1734 | 1649 | ||
1735 | 1650 | func checkClaimConditions (addr,claimMode,landAssetIdIn) = { | |
1736 | - | let $ | |
1651 | + | let $t03367834217 = if ((claimMode == claimModeWh)) | |
1737 | 1652 | then $Tuple2(landAssetIdIn, valueOrElse(getString(keyStakedDuckByOwner(addr)), "")) | |
1738 | 1653 | else { | |
1739 | 1654 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1743 | 1658 | then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L")) | |
1744 | 1659 | else $Tuple2(loc[locIdxId], duckAssetId) | |
1745 | 1660 | } | |
1746 | - | let landAssetId = $ | |
1747 | - | let duckId = $ | |
1661 | + | let landAssetId = $t03367834217._1 | |
1662 | + | let duckId = $t03367834217._2 | |
1748 | 1663 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
1749 | 1664 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1750 | 1665 | let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Land " + asset.name) + " is not staked")) | |
1792 | 1707 | let currentPack = getBackpack(bpKey) | |
1793 | 1708 | let currentPackRes = split(currentPack[bpIdxRes], "_") | |
1794 | 1709 | let currentWhRes = split(currentWh[whIdxRes], "_") | |
1795 | - | let $ | |
1710 | + | let $t03659137462 = if ((claimMode == claimModeWh)) | |
1796 | 1711 | then $Tuple4(addRes(currentWhRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), currentPack[bpIdxRes], (parseIntValue(loft[volOccupied]) + resToClaim._2), (parseIntValue(loft[volFree]) - resToClaim._2)) | |
1797 | 1712 | else if ((claimMode == claimModeDuck)) | |
1798 | 1713 | then $Tuple4(currentWh[whIdxRes], addRes(currentPackRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), parseIntValue(loft[volOccupied]), parseIntValue(loft[volFree])) | |
1801 | 1716 | let whAm = min([parseIntValue(loft[volFree]), resToClaim._2]) | |
1802 | 1717 | $Tuple4(distr._1, distr._2, (parseIntValue(loft[volOccupied]) + whAm), (parseIntValue(loft[volFree]) - whAm)) | |
1803 | 1718 | } | |
1804 | - | let whRes = $ | |
1805 | - | let bpRes = $ | |
1806 | - | let loftO = $ | |
1807 | - | let loftF = $ | |
1719 | + | let whRes = $t03659137462._1 | |
1720 | + | let bpRes = $t03659137462._2 | |
1721 | + | let loftO = $t03659137462._3 | |
1722 | + | let loftF = $t03659137462._4 | |
1808 | 1723 | $Tuple5([IntegerEntry(keyStakedTimeByAssetId(c._2), newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr), newTimestamp)], bpKey, [currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]], whKey, [currentWh[whIdxLevels], whRes, currentWh[whIdxMat], currentWh[whIdxProd], makeString([loft[volLocked], toString(loftO), toString(loftF), loft[volTotal]], "_")]) | |
1809 | 1724 | } | |
1810 | 1725 | } | |
2368 | 2283 | let isDeliv = (newLoc[locIdxType] == "D") | |
2369 | 2284 | let eqKey = keyDuckEquipment(duckAssetId) | |
2370 | 2285 | let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,") | |
2371 | - | let $t06603566132 = subtractEquipment(currentEq, f._5) | |
2372 | - | let newEq = $t06603566132._1 | |
2373 | - | let shouldZeroBuffs = $t06603566132._2 | |
2374 | - | let $t06613567967 = if (!(onMission(tournamentContract, curLocation))) | |
2286 | + | let $t06637066476 = subtractEquipment(currentEq, f._5) | |
2287 | + | let newEq = $t06637066476._1 | |
2288 | + | let shouldZeroBuffs = $t06637066476._2 | |
2289 | + | let ignored = $t06637066476._3 | |
2290 | + | let $t06647968311 = if (!(onMission(tournamentContract, curLocation))) | |
2375 | 2291 | then if (isTour) | |
2376 | 2292 | then cheatAttempt(curLocation, newLocation, 5) | |
2377 | 2293 | else if (!(isDeliv)) | |
2408 | 2324 | else $Tuple2(curLocation, 0) | |
2409 | 2325 | } | |
2410 | 2326 | else throw(("Unknown curLocation:" + curLocation)) | |
2411 | - | let locToSave = $ | |
2412 | - | let hpToSave = $ | |
2327 | + | let locToSave = $t06647968311._1 | |
2328 | + | let hpToSave = $t06647968311._2 | |
2413 | 2329 | $Tuple2(((([StringEntry(locKey, locToSave), StringEntry(eqKey, newEq), IntegerEntry(keyDuckHealth(duckAssetId), hpToSave)] ++ prologActions) ++ (if (shouldZeroBuffs) | |
2414 | 2330 | then [StringEntry(keyDuckBuffs(duckAssetId), "0_0_0_0_0")] | |
2415 | 2331 | else nil)) ++ updateDuckStatsInternal(duckAssetId, if ((newHP > 0)) | |
2629 | 2545 | let newMat = makeString(subtractMaterials(true, mList, EXPMATERIALS), "_") | |
2630 | 2546 | let eqKey = keyDuckEquipment(duckAssetId) | |
2631 | 2547 | let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,") | |
2632 | - | let $t07588775984 = subtractEquipment(currentEq, f._5) | |
2633 | - | let newEq = $t07588775984._1 | |
2634 | - | let shouldZeroBuffs = $t07588775984._2 | |
2548 | + | let $t07623176337 = subtractEquipment(currentEq, f._5) | |
2549 | + | let newEq = $t07623176337._1 | |
2550 | + | let shouldZeroBuffs = $t07623176337._2 | |
2551 | + | let ignored = $t07623176337._3 | |
2635 | 2552 | let e = expeditionInternal(i.caller, i.transactionId) | |
2636 | 2553 | let id = e._2._1 | |
2637 | 2554 | let result = if ((0 >= f._1)) | |
2954 | 2871 | let addr = toString(i.originCaller) | |
2955 | 2872 | let virtWlgData = asAnyList(invoke(wlgContract, "checkWlgXpREADONLY", [addr], nil)) | |
2956 | 2873 | let virtWlgPoints = asInt(virtWlgData[1]) | |
2957 | - | let $ | |
2874 | + | let $t09214992539 = if ((0 >= virtWlgPoints)) | |
2958 | 2875 | then $Tuple2(0, nil) | |
2959 | 2876 | else { | |
2960 | 2877 | let deltaXP = asInt(invoke(wlgContract, "takeWlgXp", [addr], nil)) | |
2962 | 2879 | then $Tuple2(virtWlgPoints, [IntegerEntry(keyUserLevel(addr), asInt(virtWlgData[0])), IntegerEntry(keyUserXP(addr), asInt(virtWlgData[2]))]) | |
2963 | 2880 | else throw("Strict value is not equal to itself.") | |
2964 | 2881 | } | |
2965 | - | let wlgPoints = $ | |
2966 | - | let wlgActions = $ | |
2882 | + | let wlgPoints = $t09214992539._1 | |
2883 | + | let wlgActions = $t09214992539._2 | |
2967 | 2884 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
2968 | 2885 | let freeKeyAcc = keyUserFreePoints(addr) | |
2969 | 2886 | let freePointsAcc = (valueOrElse(getInteger(freeKeyAcc), 0) + wlgPoints) | |
3093 | 3010 | ||
3094 | 3011 | ||
3095 | 3012 | @Callable(i) | |
3096 | - | func fortificateLand (landAssetId,plan) = { | |
3097 | - | let prologActions = prolog(i) | |
3098 | - | if ((size(i.payments) != 0)) | |
3099 | - | then throw("No payments required") | |
3100 | - | else { | |
3101 | - | let addr = toString(i.originCaller) | |
3102 | - | let duckAssetId = valueOrElse(getString(keyStakedDuckByOwner(addr)), "") | |
3103 | - | let duckStats = getDuckStats(this, duckAssetId, 0, false) | |
3104 | - | let fortKey = keyFortificationsByLand(landAssetId) | |
3105 | - | let currentForts = split(valueOrElse(getString(fortKey), ":0_15:0_18:0"), "_") | |
3106 | - | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
3107 | - | let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE) | |
3108 | - | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
3109 | - | let whKey = keyWarehouseByLand(landAssetId) | |
3110 | - | let wh = getWarehouse(whKey, landIndex, infraLevel) | |
3111 | - | let curLoft = split(wh[whIdxLOFT], "_") | |
3112 | - | let curO = parseIntValue(curLoft[volOccupied]) | |
3113 | - | let curF = parseIntValue(curLoft[volFree]) | |
3114 | - | let newForts = split(plan, "_") | |
3115 | - | let $t09894799062 = fortB(currentForts, prodStrToBytes(wh[whIdxProd]), curO, curF, true, nil) | |
3116 | - | let tempProdB = $t09894799062._1 | |
3117 | - | let tempO = $t09894799062._2 | |
3118 | - | let tempF = $t09894799062._3 | |
3119 | - | let $t09906599161 = fortB(newForts, tempProdB, tempO, tempF, false, duckStats) | |
3120 | - | let newProdB = $t09906599161._1 | |
3121 | - | let newO = $t09906599161._2 | |
3122 | - | let newF = $t09906599161._3 | |
3123 | - | let newProdStr = bytesToProdStr(newProdB) | |
3124 | - | let newLoftStr = makeString([curLoft[volLocked], toString(newO), toString(newF), curLoft[volTotal]], "_") | |
3125 | - | $Tuple2(([StringEntry(fortKey, plan), StringEntry(whKey, makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], newProdStr, newLoftStr], ":"))] ++ prologActions), 0) | |
3126 | - | } | |
3127 | - | } | |
3128 | - | ||
3129 | - | ||
3130 | - | ||
3131 | - | @Callable(i) | |
3132 | 3013 | func initDuckTourAttempt (duckAssetId) = if ((i.caller != tournamentContract)) | |
3133 | 3014 | then throw("Access denied") | |
3134 | 3015 | else { | |
3213 | 3094 | ||
3214 | 3095 | ||
3215 | 3096 | @Callable(i) | |
3216 | - | func | |
3097 | + | func robLand (message,sig) = { | |
3217 | 3098 | let prologActions = prolog(i) | |
3218 | - | if (! | |
3219 | - | then throw(" | |
3220 | - | else | |
3221 | - | | |
3222 | - | | |
3223 | - | | |
3224 | - | | |
3225 | - | | |
3226 | - | ||
3227 | - | ||
3228 | - | then throw("WLGOLD | |
3099 | + | if ((size(i.payments) != 1)) | |
3100 | + | then throw("exactly 1 payment must be attached") | |
3101 | + | else { | |
3102 | + | let pmt = i.payments[0] | |
3103 | + | let wlgAmt = pmt.amount | |
3104 | + | if (if (!(isDefined(pmt.assetId))) | |
3105 | + | then true | |
3106 | + | else (value(pmt.assetId) != wlgAssetId)) | |
3107 | + | then throw("WLGOLD payments only!") | |
3108 | + | else if ((wlgAmt != MIN_WLGOLD_ROBBERY)) | |
3109 | + | then throw((("Payment should be " + fixedPoint(MIN_WLGOLD_ROBBERY, 8)) + " WLGOLD")) | |
3229 | 3110 | else { | |
3230 | - | let | |
3231 | - | if (( | |
3232 | - | then throw(" | |
3111 | + | let addr = toString(i.caller) | |
3112 | + | if (!(sigVerify_8Kb(message, sig, pub))) | |
3113 | + | then throw("signature does not match") | |
3233 | 3114 | else { | |
3234 | - | let txFromMsg = if ((size(parts) >= 2)) | |
3235 | - | then parts[2] | |
3236 | - | else "" | |
3237 | - | let userAddr = toString(i.caller) | |
3238 | - | let lastTx = valueOrElse(getString(keyLastTxIdByUser(userAddr)), "") | |
3239 | - | if ((lastTx != txFromMsg)) | |
3240 | - | then throw(((("Tx ids don't match! In state: " + lastTx) + ", in msg: ") + txFromMsg)) | |
3115 | + | let parts = split_4C(toUtf8String(message), ";") | |
3116 | + | let robLog = split_4C(parts[0], "|") | |
3117 | + | let hp = split(robLog[rlHealth], "_") | |
3118 | + | let curHP = parseIntValue(hp[0]) | |
3119 | + | let newHP = parseIntValue(hp[1]) | |
3120 | + | let prodUsed = robLog[rlProdsUsed] | |
3121 | + | let lastPart = split(parts[1], "|") | |
3122 | + | let robType = lastPart[rlType] | |
3123 | + | if ((robType != "B")) | |
3124 | + | then throw("Only bank robbery is supported") | |
3241 | 3125 | else { | |
3242 | - | let duckAssetId = parts[0] | |
3243 | - | if (checkTournament(duckAssetId)) | |
3244 | - | then throw("prepareRobbery_checkTournament") | |
3126 | + | let time = parseIntValue(lastPart[rlTimestamp]) | |
3127 | + | if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS))) | |
3128 | + | then true | |
3129 | + | else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time)) | |
3130 | + | then throw(((("signature outdated: logTime=" + toString(time)) + ", bcTime=") + toString(lastBlock.timestamp))) | |
3245 | 3131 | else { | |
3246 | - | let robCost = getRobberyData(this, duckAssetId)._1 | |
3247 | - | if ((robCost > wlgAmt)) | |
3248 | - | then throw(((("Payment " + toString(wlgAmt)) + " < required ") + toString(robCost))) | |
3132 | + | let txFromMsg = lastPart[rlLastTx] | |
3133 | + | let lastTx = valueOrElse(getString(keyLastTxIdByUser(addr)), "") | |
3134 | + | if ((lastTx != txFromMsg)) | |
3135 | + | then throw(((("Tx ids don't match! In state: " + lastTx) + ", in msg: ") + txFromMsg)) | |
3249 | 3136 | else { | |
3250 | - | let candidates = split(parts[1], "_") | |
3251 | - | let now = lastBlock.timestamp | |
3252 | - | let duckState = valueOrElse(getInteger(keyDuckRobberyState(duckAssetId)), 0) | |
3253 | - | let lockedLand = valueOrElse(getString(keyLockedLandByDuck(duckAssetId)), "") | |
3254 | - | let landETA = valueOrElse(getInteger(keyLandCooldownETA(lockedLand)), 0) | |
3255 | - | if (if ((duckState != duckIdxFree)) | |
3256 | - | then (landETA > now) | |
3257 | - | else false) | |
3258 | - | then throw(("You already started robbing, wait till " + toString(landETA))) | |
3137 | + | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
3138 | + | let eqKey = keyDuckEquipment(duckAssetId) | |
3139 | + | let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,") | |
3140 | + | let $t0109717109828 = subtractEquipment(currentEq, prodUsed) | |
3141 | + | let newEq = $t0109717109828._1 | |
3142 | + | let shouldZeroBuffs = $t0109717109828._2 | |
3143 | + | let isBpUsed = $t0109717109828._3 | |
3144 | + | let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION) | |
3145 | + | if (isInTournament(tournamentContract, curLocation)) | |
3146 | + | then throw("Your duck is taking part in the tournament") | |
3259 | 3147 | else { | |
3260 | - | func checker (acc,landAssetId) = { | |
3261 | - | let state = valueOrElse(getInteger(keyLandRobberyState(landAssetId)), 0) | |
3262 | - | let cooldownETA = valueOrElse(getInteger(keyLandCooldownETA(landAssetId)), 0) | |
3263 | - | if ((state > size(landRobCooldowns))) | |
3264 | - | then throw("Invalid state") | |
3265 | - | else if ((now > cooldownETA)) | |
3148 | + | let now = lastBlock.timestamp | |
3149 | + | let countKey = keyUserRobberyCount(addr) | |
3150 | + | let lastDay = valueOrElse(getInteger(keyUserLastRobberyDay(addr)), 0) | |
3151 | + | let today = (now / DAYMILLIS) | |
3152 | + | let count = if ((lastDay == today)) | |
3153 | + | then valueOrElse(getInteger(countKey), 0) | |
3154 | + | else 0 | |
3155 | + | let acres = valueOrElse(getInteger(acresContract, keyAcresStakedAmountByUser(addr)), 0) | |
3156 | + | let allowedRobberies = (ALLOWED_FREE_ROBBERIES + (acres / ACRES_FOR_ROBBERY_ATTEMPT)) | |
3157 | + | if ((count >= allowedRobberies)) | |
3158 | + | then throw((("You already used " + toString(allowedRobberies)) + " robbery attempts for today")) | |
3159 | + | else { | |
3160 | + | let globalCountKey = keyDuckRobberyCount(duckAssetId) | |
3161 | + | let loot = if ((newHP > 0)) | |
3266 | 3162 | then { | |
3267 | - | let stakedTime = valueOrElse(getInteger(keyStakedTimeByAssetId(landAssetId)), 0) | |
3268 | - | if ((0 >= stakedTime)) | |
3269 | - | then acc | |
3270 | - | else { | |
3271 | - | let a = value(assetInfo(fromBase58String(landAssetId))) | |
3272 | - | let d = split(a.description, "_") | |
3273 | - | let pieces = numPiecesBySize(d[recLandSize]) | |
3274 | - | let productivity = applyBonuses(landAssetId, pieces) | |
3275 | - | let deltaTime = (now - stakedTime) | |
3276 | - | let availRes = fraction(deltaTime, (productivity * pieces), DAYMILLIS) | |
3277 | - | if ((MIN_RES_TO_ROB > availRes)) | |
3278 | - | then acc | |
3279 | - | else (acc :+ landAssetId) | |
3280 | - | } | |
3163 | + | let fundTotal = assetBalance(this, wlgAssetId) | |
3164 | + | let prize = if (isBpUsed) | |
3165 | + | then (2 * MIN_WLGOLD_ROBBERY) | |
3166 | + | else (5 * MIN_WLGOLD_ROBBERY) | |
3167 | + | if ((prize > fundTotal)) | |
3168 | + | then throw(((("Robbery is not available, funds = " + fixedPoint(fundTotal, 8)) + " WLGOLD, required = ") + fixedPoint(prize, 8))) | |
3169 | + | else [ScriptTransfer(i.caller, prize, wlgAssetId)] | |
3281 | 3170 | } | |
3282 | - | else acc | |
3283 | - | } | |
3284 | - | ||
3285 | - | let filtered = { | |
3286 | - | let $l = candidates | |
3287 | - | let $s = size($l) | |
3288 | - | let $acc0 = nil | |
3289 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
3290 | - | then $a | |
3291 | - | else checker($a, $l[$i]) | |
3292 | - | ||
3293 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
3294 | - | then $a | |
3295 | - | else throw("List size exceeds 10") | |
3296 | - | ||
3297 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
3298 | - | } | |
3299 | - | if ((size(filtered) == 0)) | |
3300 | - | then throw("No candidates for robbery") | |
3301 | - | else { | |
3302 | - | let rndIdx = getRandomNumber(size(filtered), message, sig) | |
3303 | - | let landAssetId = filtered[rndIdx] | |
3304 | - | $Tuple2(([IntegerEntry(keyLandRobberyState(landAssetId), robIdxLocked), IntegerEntry(keyLandCooldownETA(landAssetId), (now + landRobCooldowns[robIdxLocked])), IntegerEntry(keyDuckRobberyState(duckAssetId), duckIdxPreparing), StringEntry(keyLockedLandByDuck(duckAssetId), landAssetId)] ++ prologActions), landAssetId) | |
3171 | + | else nil | |
3172 | + | $Tuple2((((((((((prologActions ++ loot) ++ (if (shouldZeroBuffs) | |
3173 | + | then [StringEntry(keyDuckBuffs(duckAssetId), "0_0_0_0_0")] | |
3174 | + | else nil)) ++ updateDuckStatsInternal(duckAssetId, if ((newHP > 0)) | |
3175 | + | then xpSuccessRob | |
3176 | + | else xpFailRob)._1) :+ IntegerEntry(keyLastRobberyTimeByDuck(duckAssetId), now)) :+ IntegerEntry(countKey, (count + 1))) :+ IntegerEntry(keyUserLastRobberyDay(addr), today)) :+ IntegerEntry(globalCountKey, (valueOrElse(getInteger(globalCountKey), 0) + 1))) :+ StringEntry(eqKey, newEq)) :+ IntegerEntry(keyDuckHealth(duckAssetId), max([newHP, 0]))), 0) | |
3305 | 3177 | } | |
3306 | 3178 | } | |
3307 | 3179 | } | |
3309 | 3181 | } | |
3310 | 3182 | } | |
3311 | 3183 | } | |
3312 | - | } | |
3313 | - | } | |
3314 | - | ||
3315 | - | ||
3316 | - | ||
3317 | - | @Callable(i) | |
3318 | - | func robLand (message,sig) = { | |
3319 | - | let prologActions = prolog(i) | |
3320 | - | if (!(sigVerify_8Kb(message, sig, pub))) | |
3321 | - | then throw("signature does not match") | |
3322 | - | else { | |
3323 | - | let userAddr = toString(i.caller) | |
3324 | - | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked") | |
3325 | - | let now = lastBlock.timestamp | |
3326 | - | $Tuple2((prologActions :+ IntegerEntry(keyLastRobberyTimeByDuck(duckAssetId), now)), 0) | |
3327 | 3184 | } | |
3328 | 3185 | } | |
3329 | 3186 |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let DAYMILLIS = 86400000 | |
5 | 5 | ||
6 | 6 | func keyLastArbTimeByUser (addr) = ("lastArbTimeUser_" + addr) | |
7 | 7 | ||
8 | 8 | ||
9 | 9 | func keyAcresStakedAmountByUser (addr) = ("acresStakedAmountByUser_" + addr) | |
10 | 10 | ||
11 | 11 | ||
12 | 12 | let SCALE8 = 100000000 | |
13 | 13 | ||
14 | 14 | let xpLevelScale = 3200 | |
15 | 15 | ||
16 | 16 | let xpLevelRecipPow = 4000 | |
17 | 17 | ||
18 | 18 | let numPointsOnLevelUp = 3 | |
19 | 19 | ||
20 | - | let robberyCostMin = 100000000 | |
21 | - | ||
22 | - | let robberyCooldownCoeff = 400 | |
23 | - | ||
24 | 20 | let requirements = ["Strength", "Accuracy", "Intellect", "Endurance", "Dexterity", "Level", "Health"] | |
25 | 21 | ||
26 | 22 | let charStrength = 0 | |
27 | 23 | ||
28 | 24 | let charAccuracy = 1 | |
29 | 25 | ||
30 | 26 | let charIntellect = 2 | |
31 | 27 | ||
32 | 28 | let charEndurance = 3 | |
33 | 29 | ||
34 | 30 | let charDexterity = 4 | |
35 | 31 | ||
36 | 32 | let segBackpack = 0 | |
37 | 33 | ||
38 | 34 | let NUMSEGMENTS = 6 | |
39 | 35 | ||
40 | 36 | let NUMMAINAUX = 2 | |
41 | 37 | ||
42 | 38 | let MAXSLOTS = 2 | |
43 | 39 | ||
44 | 40 | let MAXPRODINSLOT = 30 | |
45 | 41 | ||
46 | - | let landRobCooldowns = [0, 600000, 900000, 43200000, 21600000] | |
47 | - | ||
48 | - | let MIN_RES_TO_ROB = 20000000 | |
49 | - | ||
50 | - | let robIdxLocked = 1 | |
51 | - | ||
52 | - | let duckIdxFree = 0 | |
53 | - | ||
54 | - | let duckIdxPreparing = 1 | |
55 | - | ||
56 | 42 | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
57 | 43 | ||
58 | 44 | ||
59 | 45 | func keyDuckChars (duckAssetId) = ("duckChars_" + duckAssetId) | |
60 | 46 | ||
61 | 47 | ||
62 | 48 | func keyDuckXP (duckAssetId) = ("duckXP_" + duckAssetId) | |
63 | 49 | ||
64 | 50 | ||
65 | 51 | func keyDuckLevel (duckAssetId) = ("duckLevel_" + duckAssetId) | |
66 | 52 | ||
67 | 53 | ||
68 | 54 | func keyDuckFreePoints (duckAssetId) = ("duckFreePoints_" + duckAssetId) | |
69 | 55 | ||
70 | 56 | ||
71 | 57 | func keyDuckEquipment (duckAssetId) = ("duckEquipment_" + duckAssetId) | |
72 | 58 | ||
73 | 59 | ||
74 | 60 | func keyUserXP (addr) = ("userXP_" + addr) | |
75 | 61 | ||
76 | 62 | ||
77 | 63 | func keyUserLevel (addr) = ("userLevel_" + addr) | |
78 | 64 | ||
79 | 65 | ||
80 | 66 | func keyUserFreePoints (addr) = ("userFreePoints_" + addr) | |
81 | 67 | ||
82 | 68 | ||
83 | 69 | func keySavedHealth (duckAssetId) = ("savedHealth_" + duckAssetId) | |
84 | 70 | ||
85 | 71 | ||
86 | 72 | func keySavedLocation (duckAssetId) = ("savedLocation_" + duckAssetId) | |
87 | 73 | ||
88 | 74 | ||
89 | 75 | func keyDuckBuffs (duckAssetId) = ("duckBuffs_" + duckAssetId) | |
90 | 76 | ||
91 | 77 | ||
92 | 78 | func keyLastRobberyTimeByDuck (duckAssetId) = ("lastRobberyTime_" + duckAssetId) | |
93 | 79 | ||
94 | 80 | ||
95 | - | func keyLastRobberyCostByDuck (duckAssetId) = ("lastRobberyCost_" + duckAssetId) | |
96 | - | ||
97 | - | ||
98 | - | func keyLandRobberyState (landAssetId) = ("landRobberyState_" + landAssetId) | |
99 | - | ||
100 | - | ||
101 | - | func keyLandCooldownETA (landAssetId) = ("landCooldownETA_" + landAssetId) | |
102 | - | ||
103 | - | ||
104 | - | func keyDuckRobberyState (duckAssetId) = ("duckRobberyState_" + duckAssetId) | |
105 | - | ||
106 | - | ||
107 | - | func keyLockedLandByDuck (duckAssetId) = ("lockedLandByDuck_" + duckAssetId) | |
81 | + | func keyDuckRobberyCount (duckAssetId) = ("totalRobberyCountByDuck_" + duckAssetId) | |
82 | + | ||
83 | + | ||
84 | + | func keyUserRobberyCount (addr) = ("userRobberyCount_" + addr) | |
85 | + | ||
86 | + | ||
87 | + | func keyUserLastRobberyDay (addr) = ("userLastRobberyDay_" + addr) | |
108 | 88 | ||
109 | 89 | ||
110 | 90 | func keyDuckDeliveryCount (duckAssetId) = ("totalDeliveryCountByDuck_" + duckAssetId) | |
111 | 91 | ||
112 | 92 | ||
113 | 93 | func keyUserDeliveryCount (addr) = ("userDeliveryCount_" + addr) | |
114 | 94 | ||
115 | 95 | ||
116 | 96 | func keyUserLastDeliveryDay (addr) = ("userLastDeliveryDay_" + addr) | |
117 | 97 | ||
118 | 98 | ||
119 | 99 | let xpClaim = 10000 | |
120 | 100 | ||
121 | 101 | let xpSuccessFlight = 10000 | |
122 | 102 | ||
123 | 103 | let xpFailFlight = 2000 | |
104 | + | ||
105 | + | let xpSuccessRob = 10000 | |
106 | + | ||
107 | + | let xpFailRob = 2000 | |
124 | 108 | ||
125 | 109 | let xpCallES = 100000 | |
126 | 110 | ||
127 | 111 | let xpCustomName = 1000000 | |
128 | 112 | ||
129 | 113 | let xpNewSLand = 5000000 | |
130 | 114 | ||
131 | 115 | let xpUpgradeInfra = 10000 | |
132 | 116 | ||
133 | 117 | let xpMerge = 1000000 | |
134 | 118 | ||
135 | 119 | let xpOnboard = 1000000 | |
136 | 120 | ||
137 | 121 | let xpHeal = 10000 | |
138 | 122 | ||
139 | 123 | func levelByXP (xp) = fraction(xpLevelScale, pow(xp, 4, xpLevelRecipPow, 4, 4, DOWN), SCALE8) | |
140 | 124 | ||
141 | 125 | ||
142 | 126 | func maxHealth (level) = (100 + level) | |
143 | 127 | ||
144 | 128 | ||
145 | 129 | func levelUp (currLevel,newXP) = { | |
146 | 130 | let newLevel = levelByXP(newXP) | |
147 | 131 | [newLevel, (numPointsOnLevelUp * (newLevel - currLevel))] | |
148 | 132 | } | |
149 | 133 | ||
150 | 134 | ||
151 | 135 | func getDuckStats (stakingContract,duckAssetId,buffEffect,forceBuffs) = { | |
152 | 136 | let chars = split(valueOrElse(getString(stakingContract, keyDuckChars(duckAssetId)), "0_0_0_0_0"), "_") | |
153 | 137 | let lvl = valueOrElse(getInteger(stakingContract, keyDuckLevel(duckAssetId)), 0) | |
154 | 138 | let health = valueOrElse(getInteger(stakingContract, keyDuckHealth(duckAssetId)), maxHealth(lvl)) | |
155 | 139 | let stateBuffs = split(valueOrElse(getString(stakingContract, keyDuckBuffs(duckAssetId)), "0_0_0_0_0"), "_") | |
156 | 140 | ([parseIntValue(chars[charStrength]), parseIntValue(chars[charAccuracy]), parseIntValue(chars[charIntellect]), parseIntValue(chars[charEndurance]), parseIntValue(chars[charDexterity]), lvl, health] ++ (if (forceBuffs) | |
157 | 141 | then [buffEffect, buffEffect, buffEffect, buffEffect, buffEffect] | |
158 | 142 | else [parseIntValue(stateBuffs[charStrength]), parseIntValue(stateBuffs[charAccuracy]), parseIntValue(stateBuffs[charIntellect]), parseIntValue(stateBuffs[charEndurance]), parseIntValue(stateBuffs[charDexterity])])) | |
159 | 143 | } | |
160 | 144 | ||
161 | 145 | ||
162 | - | func getRobberyData (stakingContract,duckAssetId) = { | |
163 | - | let lastRobCost = valueOrElse(getInteger(stakingContract, keyLastRobberyCostByDuck(duckAssetId)), 0) | |
164 | - | let lastRobTime = valueOrElse(getInteger(stakingContract, keyLastRobberyTimeByDuck(duckAssetId)), 0) | |
165 | - | let now = lastBlock.timestamp | |
166 | - | let robCost = max([robberyCostMin, (lastRobCost - (robberyCooldownCoeff * (now - lastRobTime)))]) | |
167 | - | let duckState = valueOrElse(getInteger(stakingContract, keyDuckRobberyState(duckAssetId)), 0) | |
168 | - | let lockedLand = valueOrElse(getString(stakingContract, keyLockedLandByDuck(duckAssetId)), "") | |
169 | - | let landETA = valueOrElse(getInteger(stakingContract, keyLandCooldownETA(lockedLand)), 0) | |
170 | - | $Tuple5(robCost, lastRobTime, duckState, lockedLand, landETA) | |
171 | - | } | |
172 | - | ||
173 | - | ||
174 | 146 | let LANDPREFIX = "LAND" | |
175 | 147 | ||
176 | 148 | let DUCKPREFIX = "DUCK" | |
177 | 149 | ||
178 | 150 | let ROBO_PREFIX = "ROBO" | |
179 | 151 | ||
180 | 152 | let ARTPRESALE = "PRESALE" | |
181 | 153 | ||
182 | 154 | let NUMRES = 6 | |
183 | 155 | ||
184 | 156 | let MAX_LANDS_STAKED_BY_USER = 25 | |
185 | 157 | ||
186 | 158 | let DAILYRESBYPIECE = 3456000 | |
187 | 159 | ||
188 | 160 | let WHMULTIPLIER = 10000000000 | |
189 | 161 | ||
190 | 162 | let DEFAULTLOCATION = "Africa_F_Africa" | |
191 | 163 | ||
192 | 164 | let RESOURCEPRICEMIN = 39637 | |
193 | 165 | ||
194 | 166 | let ESSELLCOEF = 10 | |
195 | 167 | ||
196 | 168 | let MIN_USDT_FEE_DELIVERY = 50000 | |
197 | 169 | ||
170 | + | let MIN_WLGOLD_ROBBERY = 100000000 | |
171 | + | ||
172 | + | let ALLOWED_FREE_ROBBERIES = 0 | |
173 | + | ||
174 | + | let ACRES_FOR_ROBBERY_ATTEMPT = 200000000 | |
175 | + | ||
198 | 176 | let ALLOWED_FREE_DELIVERIES = 0 | |
199 | 177 | ||
200 | 178 | let ACRES_FOR_DELIVERY_ATTEMPT = 200000000 | |
201 | 179 | ||
202 | 180 | let prodTypes = ["First Aid Kit L1", "First Aid Kit L2", "First Aid Kit L3", "Backpack L1", "Backpack L2", "Backpack L3", "Food Ration L1", "Food Ration L2", "Food Ration L3", "Jet Pack L1", "Jet Pack L2", "Jet Pack L3", "Shield L1", "Shield L2", "Shield L3", "Mine L1", "Mine L2", "Mine L3", "Trap L1", "Trap L2", "Trap L3", "Boom-Dog L1", "Boom-Dog L2", "Boom-Dog L3"] | |
203 | 181 | ||
204 | 182 | let continents = ["Americas", "Europe", "Asia", "Africa", "Oceania"] | |
205 | 183 | ||
206 | 184 | let COEFF2MAT = 10000000 | |
207 | 185 | ||
208 | - | let fortAllowedProds = [15, 16, 17, 18, 19, 20, 21, 22, 23] | |
209 | - | ||
210 | 186 | let productionMatrix = ["8_8_8_17_17_42_12_0_30_0,0,0,0,0,0,0_", "8_8_8_17_17_42_24_0_60_0,0,5,2,0,0,0_", "8_8_8_17_17_42_36_0_120_0,0,10,4,0,0,0_", "8_19_19_8_27_19_26_1_20_0,0,0,0,0,0,0_001", "8_19_19_8_27_19_52_1_40_0,0,0,0,0,0,0_001", "8_19_19_8_27_19_78_1_80_0,0,0,0,0,0,0_001", "8_8_8_8_8_60_13_2_2_0,0,0,0,0,0,0_011", "8_8_8_8_8_60_26_2_4_0,0,0,0,0,0,0_011", "8_8_8_8_8_60_39_2_8_0,0,0,0,0,0,0_011", "30_30_3_17_17_3_30_3_30_0,0,0,0,0,0,0_111", "30_30_3_17_17_3_60_3_50_0,0,0,0,0,0,0_111", "30_30_3_17_17_3_90_3_70_0,0,0,0,0,0,0_111", "18_18_10_18_18_18_11_4_10_0,0,0,0,0,0,0_201", "18_18_10_18_18_18_22_4_20_0,0,0,0,0,0,0_201", "18_18_10_18_18_18_33_4_30_0,0,0,0,0,0,0_201", "4_13_22_4_35_22_23_0_50,1,0_0,0,0,0,0,0,0_", "4_13_22_4_35_22_46_0_50,1,1_0,2,5,0,0,0,0_", "4_13_22_4_35_22_69_0_50,2,1_0,5,10,0,0,0,0_", "5_25_40_5_10_15_20_1_30,1,1_0,0,0,0,0,0,0_", "5_25_40_5_10_15_40_1_30,1,2_2,1,3,0,0,0,0_", "5_25_40_5_10_15_60_1_30,1,3_5,2,8,0,0,0,0_", "23_23_5_20_23_6_35_2_100_0,0,0,0,0,0,0_", "23_23_5_20_23_6_70_2_150_0,0,0,0,0,0,0_", "23_23_5_20_23_6_105_2_200_0,0,0,0,0,0,0_"] | |
211 | 187 | ||
212 | 188 | let rIdxCoeff = 6 | |
213 | 189 | ||
214 | 190 | let rIdxEffect = 8 | |
215 | 191 | ||
216 | 192 | let rIdxRequirements = 9 | |
217 | 193 | ||
218 | 194 | let rIdxSlots = 10 | |
219 | 195 | ||
220 | 196 | let PRODUCTPKGSIZE = 10 | |
221 | 197 | ||
222 | 198 | let whIdxLevels = 0 | |
223 | 199 | ||
224 | 200 | let whIdxRes = 1 | |
225 | 201 | ||
226 | 202 | let whIdxMat = 2 | |
227 | 203 | ||
228 | 204 | let whIdxProd = 3 | |
229 | 205 | ||
230 | 206 | let whIdxLOFT = 4 | |
231 | 207 | ||
232 | 208 | let volLocked = 0 | |
233 | 209 | ||
234 | 210 | let volOccupied = 1 | |
235 | 211 | ||
236 | 212 | let volFree = 2 | |
237 | 213 | ||
238 | 214 | let volTotal = 3 | |
239 | 215 | ||
240 | 216 | let bpIdxLevel = 0 | |
241 | 217 | ||
242 | 218 | let bpIdxRes = 1 | |
243 | 219 | ||
244 | 220 | let bpIdxMat = 2 | |
245 | 221 | ||
246 | 222 | let bpIdxProd = 3 | |
247 | 223 | ||
248 | 224 | let locIdxContinent = 0 | |
249 | 225 | ||
250 | 226 | let locIdxType = 1 | |
251 | 227 | ||
252 | 228 | let locIdxId = 2 | |
253 | 229 | ||
254 | 230 | func keyLandAssetIdToOwner (assetId) = ("no_" + assetId) | |
255 | 231 | ||
256 | 232 | ||
257 | 233 | func keyLandAssetIdToCustomName (assetId) = ("lcna_" + assetId) | |
258 | 234 | ||
259 | 235 | ||
260 | 236 | func keyStakedTimeByAssetId (assetId) = ("st_" + assetId) | |
261 | 237 | ||
262 | 238 | ||
263 | 239 | func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["las", type, assetId], "_") | |
264 | 240 | ||
265 | 241 | ||
266 | 242 | func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("sttao_" + nftType) + "_") + assetId) + "_") + ownerAddr) | |
267 | 243 | ||
268 | 244 | ||
269 | 245 | func keyWarehouseByLand (landAssetId) = ("wh_" + landAssetId) | |
270 | 246 | ||
271 | 247 | ||
272 | 248 | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
273 | - | ||
274 | - | ||
275 | - | func keyFortificationsByLand (landAssetId) = ("fortifications_" + landAssetId) | |
276 | 249 | ||
277 | 250 | ||
278 | 251 | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
279 | 252 | ||
280 | 253 | ||
281 | 254 | func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr) | |
282 | 255 | ||
283 | 256 | ||
284 | 257 | func keyAddressRefBy (addr) = ("accRefBy_" + addr) | |
285 | 258 | ||
286 | 259 | ||
287 | 260 | func keyOnboardArtActivatedOnDuck (duckAssetId) = ("onboardArtActivatedOnDuck_" + duckAssetId) | |
288 | 261 | ||
289 | 262 | ||
290 | 263 | func keyOnboardArtDuckActivatedBy (addr) = ("onboardArtActivatedDuckBy_" + addr) | |
291 | 264 | ||
292 | 265 | ||
293 | 266 | func keyAddressReferrals (addr) = ("accReferrals_" + addr) | |
294 | 267 | ||
295 | 268 | ||
296 | 269 | func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId) | |
297 | 270 | ||
298 | 271 | ||
299 | 272 | func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr) | |
300 | 273 | ||
301 | 274 | ||
302 | 275 | func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId) | |
303 | 276 | ||
304 | 277 | ||
305 | 278 | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
306 | 279 | ||
307 | 280 | ||
308 | 281 | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
309 | 282 | ||
310 | 283 | ||
311 | 284 | func keyEsWarehouse () = "emergencyWarehouseProducts" | |
312 | 285 | ||
313 | 286 | ||
314 | 287 | let deliveryFundKey = "deliveryFund" | |
315 | 288 | ||
316 | 289 | let lastTourIdKey = "%s__lastTourId" | |
317 | 290 | ||
318 | 291 | func keyTourStaticDataById (tId) = ("%s%d__tourStaticData__" + toString(tId)) | |
319 | 292 | ||
320 | 293 | ||
321 | 294 | func keyTourDynamicDataById (tId) = ("%s%d__tourDynamicData__" + toString(tId)) | |
322 | 295 | ||
323 | 296 | ||
324 | 297 | func keyBestResultByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__bestResultByTourAndDuck", toString(tId), duckAssetId], "__") | |
325 | 298 | ||
326 | 299 | ||
327 | 300 | let idxStatic = 0 | |
328 | 301 | ||
329 | 302 | let idxDynamic = 1 | |
330 | 303 | ||
331 | 304 | let tStaticEnd = 6 | |
332 | 305 | ||
333 | 306 | let tDynamicStatus = 1 | |
334 | 307 | ||
335 | 308 | func getTourData (tourContract,tId) = { | |
336 | 309 | let static = split(valueOrErrorMessage(getString(tourContract, keyTourStaticDataById(tId)), (("Error reading tournament " + toString(tId)) + " data")), "__") | |
337 | 310 | let dynamic = split_4C(valueOrErrorMessage(getString(tourContract, keyTourDynamicDataById(tId)), (("Error reading tournament " + toString(tId)) + " data")), "__") | |
338 | 311 | [static, dynamic] | |
339 | 312 | } | |
340 | 313 | ||
341 | 314 | ||
342 | 315 | func isInTournament (tourContract,location) = { | |
343 | 316 | let lastId = valueOrElse(getInteger(tourContract, lastTourIdKey), 0) | |
344 | 317 | let loc = split(location, "_") | |
345 | 318 | let now = lastBlock.timestamp | |
346 | 319 | let tData = getTourData(tourContract, lastId) | |
347 | 320 | let static = tData[idxStatic] | |
348 | 321 | let dynamic = tData[idxDynamic] | |
349 | 322 | if (if (if ((loc[locIdxType] == "T")) | |
350 | 323 | then (parseIntValue(loc[locIdxContinent]) == lastId) | |
351 | 324 | else false) | |
352 | 325 | then (dynamic[tDynamicStatus] == "INPROGRESS") | |
353 | 326 | else false) | |
354 | 327 | then (parseIntValue(static[tStaticEnd]) > now) | |
355 | 328 | else false | |
356 | 329 | } | |
357 | 330 | ||
358 | 331 | ||
359 | 332 | func onMission (tourContract,location) = { | |
360 | 333 | let lastId = valueOrElse(getInteger(tourContract, lastTourIdKey), 0) | |
361 | 334 | let loc = split(location, "_") | |
362 | 335 | let now = lastBlock.timestamp | |
363 | 336 | let tData = getTourData(tourContract, lastId) | |
364 | 337 | let static = tData[idxStatic] | |
365 | 338 | let dynamic = tData[idxDynamic] | |
366 | 339 | let locType = loc[locIdxType] | |
367 | 340 | if (if (if ((loc[locIdxType] == "T")) | |
368 | 341 | then (parseIntValue(loc[locIdxContinent]) == lastId) | |
369 | 342 | else false) | |
370 | 343 | then (dynamic[tDynamicStatus] == "INPROGRESS") | |
371 | 344 | else false) | |
372 | 345 | then (parseIntValue(static[tStaticEnd]) > now) | |
373 | 346 | else false | |
374 | 347 | } | |
375 | 348 | ||
376 | 349 | ||
377 | 350 | func getRecipeMaterials (recipe) = (parseIntValue(recipe[rIdxCoeff]) * COEFF2MAT) | |
378 | 351 | ||
379 | 352 | ||
380 | 353 | func cheatAttempt (oldLoc,newLoc,cheatCase) = throw(((((("Cheat attempt: oldLoc=" + oldLoc) + ", newLoc=") + newLoc) + ", case=") + toString(cheatCase))) | |
381 | 354 | ||
382 | 355 | ||
383 | 356 | let KS_SEPARATE_PUBLIC_KEY = false | |
384 | 357 | ||
385 | 358 | let KS_ALLOW_BIG_INFRA_MERGE = false | |
386 | 359 | ||
387 | 360 | let KS_ALLOW_ROBO_DUCKS = false | |
388 | 361 | ||
389 | 362 | let DAY_MILLIS = 86400000 | |
390 | 363 | ||
391 | 364 | let chain = take(drop(this.bytes, 1), 1) | |
392 | 365 | ||
393 | 366 | let pub = match chain { | |
394 | 367 | case _ => | |
395 | 368 | if ((base58'2W' == $match0)) | |
396 | 369 | then if (KS_SEPARATE_PUBLIC_KEY) | |
397 | 370 | then base58'CWsMtTZC5BjjoL4Q1ayW4Wwb1ehGACQB6DrKyPgotKfm' | |
398 | 371 | else base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD' | |
399 | 372 | else if ((base58'2T' == $match0)) | |
400 | 373 | then base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD' | |
401 | 374 | else throw("Unknown chain") | |
402 | 375 | } | |
403 | 376 | ||
404 | 377 | let usdtAssetId = match chain { | |
405 | 378 | case _ => | |
406 | 379 | if ((base58'2W' == $match0)) | |
407 | 380 | then base58'9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi' | |
408 | 381 | else if ((base58'2T' == $match0)) | |
409 | 382 | then base58'6mWwf9mZBjVgkC54idpyaZLQfAosD914wT8fGf2iiY63' | |
410 | 383 | else throw("Unknown chain") | |
411 | 384 | } | |
412 | 385 | ||
413 | 386 | let defaultRestAddressStr = match chain { | |
414 | 387 | case _ => | |
415 | 388 | if ((base58'2W' == $match0)) | |
416 | 389 | then "3PQCuvFbvh4LkPUnrnU1z3jnbA1p9m3WNhv" | |
417 | 390 | else if ((base58'2T' == $match0)) | |
418 | 391 | then "3MumkGGztCKAXpWDqxkddofqXSUbqQkvSJy" | |
419 | 392 | else throw("Unknown chain") | |
420 | 393 | } | |
421 | 394 | ||
422 | 395 | let InfraUpgradeCostS = match chain { | |
423 | 396 | case _ => | |
424 | 397 | if ((base58'2W' == $match0)) | |
425 | 398 | then 10000000000 | |
426 | 399 | else if ((base58'2T' == $match0)) | |
427 | 400 | then 100000000 | |
428 | 401 | else throw("Unknown chain") | |
429 | 402 | } | |
430 | 403 | ||
431 | 404 | let arbitrageDelay = match chain { | |
432 | 405 | case _ => | |
433 | 406 | if ((base58'2W' == $match0)) | |
434 | 407 | then DAY_MILLIS | |
435 | 408 | else if ((base58'2T' == $match0)) | |
436 | 409 | then 60000 | |
437 | 410 | else throw("Unknown chain") | |
438 | 411 | } | |
439 | 412 | ||
440 | 413 | let SEP = "__" | |
441 | 414 | ||
442 | 415 | let MULT6 = 1000000 | |
443 | 416 | ||
444 | 417 | let MULT8 = 100000000 | |
445 | 418 | ||
446 | 419 | let SSIZE = 25 | |
447 | 420 | ||
448 | 421 | let MSIZE = 100 | |
449 | 422 | ||
450 | 423 | let LSIZE = 225 | |
451 | 424 | ||
452 | 425 | let XLSIZE = 400 | |
453 | 426 | ||
454 | 427 | let XXLSIZE = 625 | |
455 | 428 | ||
456 | 429 | let ITER6 = [0, 1, 2, 3, 4, 5] | |
457 | 430 | ||
458 | 431 | func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")) | |
459 | 432 | ||
460 | 433 | ||
461 | 434 | let IdxCfgStakingDapp = 1 | |
462 | 435 | ||
463 | 436 | let IdxCfgEconomyDapp = 2 | |
464 | 437 | ||
465 | 438 | let IdxCfgGovernanceDapp = 3 | |
466 | 439 | ||
467 | 440 | let IdxCfgWlgDapp = 4 | |
468 | 441 | ||
469 | 442 | let IdxCfgTournamentDapp = 7 | |
470 | 443 | ||
471 | 444 | let IdxCfgAcresDapp = 8 | |
472 | 445 | ||
473 | 446 | func keyRestCfg () = "%s__restConfig" | |
474 | 447 | ||
475 | 448 | ||
476 | 449 | func keyRestAddress () = "%s__restAddr" | |
477 | 450 | ||
478 | 451 | ||
479 | 452 | func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP) | |
480 | 453 | ||
481 | 454 | ||
482 | 455 | func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx))) | |
483 | 456 | ||
484 | 457 | ||
485 | 458 | let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr)) | |
486 | 459 | ||
487 | 460 | let restCfg = readRestCfgOrFail(restContract) | |
488 | 461 | ||
489 | 462 | let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp) | |
490 | 463 | ||
491 | 464 | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
492 | 465 | ||
493 | 466 | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
494 | 467 | ||
495 | 468 | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
496 | 469 | ||
497 | 470 | let tournamentContract = getContractAddressOrFail(restCfg, IdxCfgTournamentDapp) | |
498 | 471 | ||
499 | 472 | let acresContract = getContractAddressOrFail(restCfg, IdxCfgAcresDapp) | |
500 | 473 | ||
501 | 474 | let recLandNum = 0 | |
502 | 475 | ||
503 | 476 | let recLandSize = 1 | |
504 | 477 | ||
505 | 478 | let recTerrains = 2 | |
506 | 479 | ||
507 | 480 | let recContinent = 3 | |
508 | 481 | ||
509 | 482 | let wlgAssetIdKey = "wlg_assetId" | |
510 | 483 | ||
511 | 484 | let wlgAssetId = valueOrErrorMessage(getBinary(wlgContract, wlgAssetIdKey), "WLGOLD is not issued yet") | |
512 | 485 | ||
513 | 486 | let acresAssetIdKey = "acresAssetId" | |
514 | 487 | ||
515 | 488 | let acresAssetId = valueOrErrorMessage(getBinary(acresContract, acresAssetIdKey), "ACRES is not issued yet") | |
516 | 489 | ||
517 | 490 | let randomDelay = 2 | |
518 | 491 | ||
519 | 492 | func keyCommit (address) = ("finishBlockFor_" + address) | |
520 | 493 | ||
521 | 494 | ||
522 | 495 | func keyResProportions () = "resTypesProportions" | |
523 | 496 | ||
524 | 497 | ||
525 | 498 | func keyResTypesByContinent (continent) = ("resTypesByContinent_" + continent) | |
526 | 499 | ||
527 | 500 | ||
528 | 501 | func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr) | |
529 | 502 | ||
530 | 503 | ||
531 | 504 | func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr) | |
532 | 505 | ||
533 | 506 | ||
534 | 507 | func asString (v) = match v { | |
535 | 508 | case s: String => | |
536 | 509 | s | |
537 | 510 | case _ => | |
538 | 511 | throw("fail to cast into String") | |
539 | 512 | } | |
540 | 513 | ||
541 | 514 | ||
542 | 515 | func asInt (v) = match v { | |
543 | 516 | case n: Int => | |
544 | 517 | n | |
545 | 518 | case _ => | |
546 | 519 | throw("fail to cast into Int") | |
547 | 520 | } | |
548 | 521 | ||
549 | 522 | ||
550 | 523 | func asAnyList (v) = match v { | |
551 | 524 | case l: List[Any] => | |
552 | 525 | l | |
553 | 526 | case _ => | |
554 | 527 | throw("fail to cast into List[Any]") | |
555 | 528 | } | |
556 | 529 | ||
557 | 530 | ||
558 | 531 | func asBoolean (v) = match v { | |
559 | 532 | case s: Boolean => | |
560 | 533 | s | |
561 | 534 | case _ => | |
562 | 535 | throw("fail to cast into Boolean") | |
563 | 536 | } | |
564 | 537 | ||
565 | 538 | ||
566 | 539 | func numPiecesBySize (landSize) = match landSize { | |
567 | 540 | case _ => | |
568 | 541 | if (("S" == $match0)) | |
569 | 542 | then SSIZE | |
570 | 543 | else if (("M" == $match0)) | |
571 | 544 | then MSIZE | |
572 | 545 | else if (("L" == $match0)) | |
573 | 546 | then LSIZE | |
574 | 547 | else if (("XL" == $match0)) | |
575 | 548 | then XLSIZE | |
576 | 549 | else if (("XXL" == $match0)) | |
577 | 550 | then XXLSIZE | |
578 | 551 | else throw("Unknown land size") | |
579 | 552 | } | |
580 | 553 | ||
581 | 554 | ||
582 | 555 | func isDigit (s) = isDefined(parseInt(s)) | |
583 | 556 | ||
584 | 557 | ||
585 | 558 | func keyBlocked () = "contractsBlocked" | |
586 | 559 | ||
587 | 560 | ||
588 | 561 | func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr) | |
589 | 562 | ||
590 | 563 | ||
591 | 564 | func fixedPoint (val,decimals) = { | |
592 | 565 | let tenPow = pow(10, 0, decimals, 0, 0, DOWN) | |
593 | 566 | let lowPart = toString((val % tenPow)) | |
594 | 567 | let zeroes = drop(toString(tenPow), (1 + size(lowPart))) | |
595 | 568 | (((toString((val / tenPow)) + ".") + zeroes) + lowPart) | |
596 | 569 | } | |
597 | 570 | ||
598 | 571 | ||
599 | 572 | func getRandomNumber (maxValue,salt,entropy) = if ((0 >= maxValue)) | |
600 | 573 | then throw("maxValue should be > 0") | |
601 | 574 | else { | |
602 | 575 | let randomHash = sha256((salt + entropy)) | |
603 | 576 | (toInt(randomHash) % maxValue) | |
604 | 577 | } | |
605 | 578 | ||
606 | 579 | ||
607 | 580 | let incubatorAddr = match chain { | |
608 | 581 | case _ => | |
609 | 582 | if ((base58'2W' == $match0)) | |
610 | 583 | then addressFromStringValue("3PEktVux2RhchSN63DsDo4b4mz4QqzKSeDv") | |
611 | 584 | else if ((base58'2T' == $match0)) | |
612 | 585 | then this | |
613 | 586 | else throw("Unknown chain") | |
614 | 587 | } | |
615 | 588 | ||
616 | 589 | let breederAddr = match chain { | |
617 | 590 | case _ => | |
618 | 591 | if ((base58'2W' == $match0)) | |
619 | 592 | then addressFromStringValue("3PDVuU45H7Eh5dmtNbnRNRStGwULA7NY6Hb") | |
620 | 593 | else if ((base58'2T' == $match0)) | |
621 | 594 | then this | |
622 | 595 | else throw("Unknown chain") | |
623 | 596 | } | |
624 | 597 | ||
625 | - | let EMPTY_PROD50 = base64'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' | |
626 | - | ||
627 | 598 | let FIVEMINUTESMILLIS = 300000 | |
628 | 599 | ||
629 | 600 | let RENAMINGCOST = 5000000 | |
630 | 601 | ||
631 | 602 | let MAXNAMELEN = 50 | |
632 | 603 | ||
633 | 604 | let InfraUpgradeCostSUsdt = 10000000 | |
634 | 605 | ||
635 | 606 | let EXPMATERIALS = match chain { | |
636 | 607 | case _ => | |
637 | 608 | if ((base58'2W' == $match0)) | |
638 | 609 | then 252289527462 | |
639 | 610 | else if ((base58'2T' == $match0)) | |
640 | 611 | then 2522895274 | |
641 | 612 | else throw("Unknown chain") | |
642 | 613 | } | |
643 | 614 | ||
644 | 615 | let EXPUSDT = match chain { | |
645 | 616 | case _ => | |
646 | 617 | if ((base58'2W' == $match0)) | |
647 | 618 | then 250000000 | |
648 | 619 | else if ((base58'2T' == $match0)) | |
649 | 620 | then 250000000 | |
650 | 621 | else throw("Unknown chain") | |
651 | 622 | } | |
652 | 623 | ||
653 | 624 | let ROBO_DUCK_USDT = 100000 | |
654 | 625 | ||
655 | 626 | let S_COST_ACRES = 2500000000 | |
656 | 627 | ||
657 | 628 | let FIVEX = toBigInt(5) | |
658 | 629 | ||
659 | 630 | let TWENTYX = toBigInt(20) | |
660 | 631 | ||
661 | 632 | let TWENTY2X = toBigInt((20 * 20)) | |
662 | 633 | ||
663 | 634 | let TWENTY3X = toBigInt(((20 * 20) * 20)) | |
664 | 635 | ||
665 | 636 | let TWENTY4X = toBigInt((((20 * 20) * 20) * 20)) | |
666 | 637 | ||
667 | 638 | let TWENTY5X = toBigInt(((((20 * 20) * 20) * 20) * 20)) | |
668 | 639 | ||
669 | 640 | let PRESALENUMLANDS = 500 | |
670 | 641 | ||
671 | 642 | func keyNextFreeLandNum () = "nextLandNum" | |
672 | 643 | ||
673 | 644 | ||
674 | 645 | func keyLandCustomNameToAssetId (name) = ("lcn_" + name) | |
675 | 646 | ||
676 | 647 | ||
677 | 648 | func keyLandToAssetId (landNum) = ("la_" + landNum) | |
678 | 649 | ||
679 | 650 | ||
680 | 651 | func keyInfraLevelByAssetIdAndOwner (assetId,ownerAddr) = ((("ilao_" + assetId) + "_") + ownerAddr) | |
681 | 652 | ||
682 | 653 | ||
683 | 654 | func keyLandNumToOwner (landNum) = ("lo_" + landNum) | |
684 | 655 | ||
685 | 656 | ||
686 | 657 | func keyDuckCustomNameToAssetId (name) = ("duckByCustomName_" + name) | |
687 | 658 | ||
688 | 659 | ||
689 | 660 | func keyCustomNameToAddress (name) = ("accountByCustomName_" + name) | |
690 | 661 | ||
691 | 662 | ||
692 | 663 | func keyOldies () = "oldiesList" | |
693 | 664 | ||
694 | 665 | ||
695 | 666 | func keyNextRoboDuck () = "nextRoboDuck" | |
696 | 667 | ||
697 | 668 | ||
698 | 669 | let claimModeWh = 0 | |
699 | 670 | ||
700 | 671 | let claimModeDuck = 1 | |
701 | 672 | ||
702 | 673 | let claimModeWhThenDuck = 2 | |
703 | 674 | ||
704 | 675 | let flHealth = 0 | |
705 | 676 | ||
706 | 677 | let flTimestamp = 5 | |
707 | 678 | ||
708 | 679 | let flBonus = 6 | |
709 | 680 | ||
710 | 681 | let flProdsUsed = 7 | |
711 | 682 | ||
683 | + | let rlHealth = 0 | |
684 | + | ||
685 | + | let rlProdsUsed = 1 | |
686 | + | ||
687 | + | let rlType = 0 | |
688 | + | ||
689 | + | let rlLastTx = 2 | |
690 | + | ||
691 | + | let rlTimestamp = 3 | |
692 | + | ||
712 | 693 | func nftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize) | |
713 | 694 | ||
714 | 695 | ||
715 | 696 | func toVolume (amount,pkgSize) = { | |
716 | 697 | let pkgs = if ((amount >= 0)) | |
717 | 698 | then (((amount + pkgSize) - 1) / pkgSize) | |
718 | 699 | else -((((-(amount) + pkgSize) - 1) / pkgSize)) | |
719 | 700 | (pkgs * MULT8) | |
720 | 701 | } | |
721 | 702 | ||
722 | 703 | ||
723 | 704 | func distributeByWeights (total,weights) = { | |
724 | 705 | let sum = (((((weights[0] + weights[1]) + weights[2]) + weights[3]) + weights[4]) + weights[5]) | |
725 | 706 | if ((0 >= sum)) | |
726 | 707 | then throw("Zero weights sum") | |
727 | 708 | else { | |
728 | 709 | let norm6 = fraction(total, MULT6, sum) | |
729 | 710 | func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6)) | |
730 | 711 | ||
731 | 712 | let $l = weights | |
732 | 713 | let $s = size($l) | |
733 | 714 | let $acc0 = nil | |
734 | 715 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
735 | 716 | then $a | |
736 | 717 | else normalizer($a, $l[$i]) | |
737 | 718 | ||
738 | 719 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
739 | 720 | then $a | |
740 | 721 | else throw("List size exceeds 6") | |
741 | 722 | ||
742 | 723 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
743 | 724 | } | |
744 | 725 | } | |
745 | 726 | ||
746 | 727 | ||
747 | 728 | func getNeededMaterials (total) = { | |
748 | 729 | let props = split(value(getString(keyResProportions())), "_") | |
749 | 730 | if ((size(props) != NUMRES)) | |
750 | 731 | then throw("Wrong proportions data") | |
751 | 732 | else { | |
752 | 733 | let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])] | |
753 | 734 | distributeByWeights(total, r) | |
754 | 735 | } | |
755 | 736 | } | |
756 | 737 | ||
757 | 738 | ||
758 | 739 | func subtractMaterials (shouldUseMat,has,totalNeed) = { | |
759 | 740 | let need = getNeededMaterials(totalNeed) | |
760 | 741 | func subtractor (acc,idx) = { | |
761 | 742 | let result = (parseIntValue(has[idx]) - need[idx]) | |
762 | 743 | if ((0 > result)) | |
763 | 744 | then throw(((((("Not enough material idx=" + toString(idx)) + ", you have ") + has[idx]) + ", but need ") + toString(need[idx]))) | |
764 | 745 | else (acc :+ toString(result)) | |
765 | 746 | } | |
766 | 747 | ||
767 | 748 | if (shouldUseMat) | |
768 | 749 | then { | |
769 | 750 | let $l = ITER6 | |
770 | 751 | let $s = size($l) | |
771 | 752 | let $acc0 = nil | |
772 | 753 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
773 | 754 | then $a | |
774 | 755 | else subtractor($a, $l[$i]) | |
775 | 756 | ||
776 | 757 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
777 | 758 | then $a | |
778 | 759 | else throw("List size exceeds 6") | |
779 | 760 | ||
780 | 761 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
781 | 762 | } | |
782 | 763 | else has | |
783 | 764 | } | |
784 | 765 | ||
785 | 766 | ||
786 | 767 | func subtractEquipment (oldEq,pUsed) = if ((pUsed == "")) | |
787 | - | then $ | |
768 | + | then $Tuple3(oldEq, false, false) | |
788 | 769 | else { | |
789 | 770 | func subUsed (acc,idxAmt) = { | |
790 | 771 | let parts = split(idxAmt, ",") | |
791 | 772 | if ((size(parts) != 2)) | |
792 | 773 | then throw("Incorrect format, should be index,amount") | |
793 | 774 | else { | |
794 | 775 | let idx = parseIntValue(parts[0]) | |
795 | 776 | if (if ((0 > idx)) | |
796 | 777 | then true | |
797 | 778 | else (idx >= size(productionMatrix))) | |
798 | 779 | then throw("Unknown product idx") | |
799 | 780 | else { | |
800 | 781 | let amt = parseIntValue(parts[1]) | |
801 | 782 | let eqParts = split(acc._1, (parts[0] + ":")) | |
802 | 783 | if ((size(eqParts) != 2)) | |
803 | 784 | then throw((("You don't have " + prodTypes[idx]) + " equipped")) | |
804 | 785 | else { | |
805 | 786 | let tmp = eqParts[1] | |
806 | 787 | let numLen = if (isDigit(take(drop(tmp, 1), 1))) | |
807 | 788 | then 2 | |
808 | 789 | else 1 | |
809 | 790 | let curr = parseIntValue(take(tmp, numLen)) | |
810 | 791 | let tail = drop(tmp, numLen) | |
811 | 792 | let newAmt = if ((curr >= amt)) | |
812 | 793 | then (curr - amt) | |
813 | 794 | else throw(((((("You equipped " + toString(curr)) + " of ") + prodTypes[idx]) + ", but tried to use ") + toString(amt))) | |
814 | - | $ | |
795 | + | $Tuple3(((((eqParts[0] + parts[0]) + ":") + toString(newAmt)) + tail), if (acc._2) | |
815 | 796 | then true | |
816 | 797 | else if (if ((idx >= 6)) | |
817 | 798 | then (8 >= idx) | |
818 | 799 | else false) | |
819 | 800 | then (newAmt == 0) | |
801 | + | else false, if (acc._3) | |
802 | + | then true | |
803 | + | else if (if ((idx >= 3)) | |
804 | + | then (5 >= idx) | |
805 | + | else false) | |
806 | + | then (amt > 0) | |
820 | 807 | else false) | |
821 | 808 | } | |
822 | 809 | } | |
823 | 810 | } | |
824 | 811 | } | |
825 | 812 | ||
826 | 813 | let $l = split(pUsed, "_") | |
827 | 814 | let $s = size($l) | |
828 | - | let $acc0 = $ | |
815 | + | let $acc0 = $Tuple3(oldEq, false, false) | |
829 | 816 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
830 | 817 | then $a | |
831 | 818 | else subUsed($a, $l[$i]) | |
832 | 819 | ||
833 | 820 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
834 | 821 | then $a | |
835 | 822 | else throw("List size exceeds 10") | |
836 | 823 | ||
837 | 824 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
838 | 825 | } | |
839 | 826 | ||
840 | 827 | ||
841 | 828 | func prodStrToBytes (prodStr) = { | |
842 | 829 | let pList = if ((prodStr == "")) | |
843 | 830 | then nil | |
844 | 831 | else split_4C(prodStr, "_") | |
845 | 832 | func toBV (acc,recipe) = { | |
846 | 833 | let j = (size(acc) / 8) | |
847 | 834 | let curr = if ((size(pList) > j)) | |
848 | 835 | then parseIntValue(pList[j]) | |
849 | 836 | else 0 | |
850 | 837 | (acc + toBytes(curr)) | |
851 | 838 | } | |
852 | 839 | ||
853 | 840 | let $l = productionMatrix | |
854 | 841 | let $s = size($l) | |
855 | 842 | let $acc0 = base58'' | |
856 | 843 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
857 | 844 | then $a | |
858 | 845 | else toBV($a, $l[$i]) | |
859 | 846 | ||
860 | 847 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
861 | 848 | then $a | |
862 | 849 | else throw("List size exceeds 50") | |
863 | 850 | ||
864 | 851 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 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) | |
865 | 852 | } | |
866 | 853 | ||
867 | 854 | ||
868 | 855 | func bytesToProdStr (bv) = { | |
869 | 856 | func fromBV (acc,recipe) = { | |
870 | 857 | let j = size(acc) | |
871 | 858 | let b = take(drop(bv, (8 * j)), 8) | |
872 | 859 | (acc :+ toString(toInt(b))) | |
873 | 860 | } | |
874 | 861 | ||
875 | 862 | makeString_2C({ | |
876 | 863 | let $l = productionMatrix | |
877 | 864 | let $s = size($l) | |
878 | 865 | let $acc0 = nil | |
879 | 866 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
880 | 867 | then $a | |
881 | 868 | else fromBV($a, $l[$i]) | |
882 | 869 | ||
883 | 870 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
884 | 871 | then $a | |
885 | 872 | else throw("List size exceeds 50") | |
886 | 873 | ||
887 | 874 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 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) | |
888 | 875 | }, "_") | |
889 | 876 | } | |
890 | 877 | ||
891 | 878 | ||
892 | 879 | func checkStatRequirements (duckStats,reqs) = { | |
893 | 880 | func check (acc,j) = { | |
894 | 881 | let buff = if ((size(duckStats) > (7 + j))) | |
895 | 882 | then duckStats[(7 + j)] | |
896 | 883 | else 0 | |
897 | 884 | if ((parseIntValue(reqs[j]) > (duckStats[j] + buff))) | |
898 | 885 | then throw(("Requirement not satisfied: " + requirements[j])) | |
899 | 886 | else true | |
900 | 887 | } | |
901 | 888 | ||
902 | 889 | let $l = [0, 1, 2, 3, 4, 5, 6] | |
903 | 890 | let $s = size($l) | |
904 | 891 | let $acc0 = false | |
905 | 892 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
906 | 893 | then $a | |
907 | 894 | else check($a, $l[$i]) | |
908 | 895 | ||
909 | 896 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
910 | 897 | then $a | |
911 | 898 | else throw("List size exceeds 7") | |
912 | 899 | ||
913 | 900 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7) | |
914 | - | } | |
915 | - | ||
916 | - | ||
917 | - | func placeProdB (idxCnt,pList,isPositive,duckStats,occupied,free) = { | |
918 | - | let parts = split(idxCnt, ":") | |
919 | - | if ((size(parts) != 2)) | |
920 | - | then throw("Incorrect format, should be index:amount") | |
921 | - | else if (if (!(isPositive)) | |
922 | - | then (size(parts[0]) != 2) | |
923 | - | else false) | |
924 | - | then throw("Product idx should be 2 digits, zero padded") | |
925 | - | else { | |
926 | - | let productIdx = parseIntValue(parts[0]) | |
927 | - | let count = parseIntValue(parts[1]) | |
928 | - | if (!(containsElement(fortAllowedProds, productIdx))) | |
929 | - | then throw((("Product '" + prodTypes[productIdx]) + "' cannot be used for land defense")) | |
930 | - | else if ((0 > count)) | |
931 | - | then throw("Count can't be negative") | |
932 | - | else if ((count > MAXPRODINSLOT)) | |
933 | - | then throw(((("Can't put more than " + toString(MAXPRODINSLOT)) + " of ") + prodTypes[productIdx])) | |
934 | - | else if ((count == 0)) | |
935 | - | then $Tuple3(pList, occupied, free) | |
936 | - | else { | |
937 | - | let head = take(pList, (8 * productIdx)) | |
938 | - | let curr = toInt(take(drop(pList, (8 * productIdx)), 8)) | |
939 | - | let tail = drop(pList, (8 * (productIdx + 1))) | |
940 | - | let recipe = split(productionMatrix[productIdx], "_") | |
941 | - | if (if (!(isPositive)) | |
942 | - | then (count > curr) | |
943 | - | else false) | |
944 | - | then throw(((((("You have " + toString(curr)) + " of ") + prodTypes[productIdx]) + ", but tried to use ") + toString(count))) | |
945 | - | else { | |
946 | - | let newAmt = if (if (!(isPositive)) | |
947 | - | then checkStatRequirements(duckStats, split(recipe[rIdxRequirements], ",")) | |
948 | - | else false) | |
949 | - | then (curr - count) | |
950 | - | else (curr + count) | |
951 | - | let deltaVol = (toVolume(newAmt, PRODUCTPKGSIZE) - toVolume(curr, PRODUCTPKGSIZE)) | |
952 | - | $Tuple3(((head + toBytes(newAmt)) + tail), (occupied + deltaVol), (free - deltaVol)) | |
953 | - | } | |
954 | - | } | |
955 | - | } | |
956 | 901 | } | |
957 | 902 | ||
958 | 903 | ||
959 | 904 | func addProdB (idxCnt,pList,isPositive,segment,mainAux,slot,duckStats) = { | |
960 | 905 | let parts = split(idxCnt, ":") | |
961 | 906 | if ((size(parts) != 2)) | |
962 | 907 | then throw("Incorrect format, should be index:amount") | |
963 | 908 | else if (if (!(isPositive)) | |
964 | 909 | then (size(parts[0]) != 2) | |
965 | 910 | else false) | |
966 | 911 | then throw("Product idx should be 2 digits, zero padded") | |
967 | 912 | else { | |
968 | 913 | let productIdx = parseIntValue(parts[0]) | |
969 | 914 | let count = parseIntValue(parts[1]) | |
970 | 915 | if (if ((0 > productIdx)) | |
971 | 916 | then true | |
972 | 917 | else (productIdx >= size(productionMatrix))) | |
973 | 918 | then throw("Unknown product idx") | |
974 | 919 | else if ((0 > count)) | |
975 | 920 | then throw("Count can't be negative") | |
976 | 921 | else if ((count > MAXPRODINSLOT)) | |
977 | 922 | then throw(((("Can't put more than " + toString(MAXPRODINSLOT)) + " of ") + prodTypes[productIdx])) | |
978 | 923 | else if ((count == 0)) | |
979 | 924 | then $Tuple2(pList, false) | |
980 | 925 | else { | |
981 | 926 | let head = take(pList, (8 * productIdx)) | |
982 | 927 | let curr = toInt(take(drop(pList, (8 * productIdx)), 8)) | |
983 | 928 | let tail = drop(pList, (8 * (productIdx + 1))) | |
984 | 929 | let recipe = split(productionMatrix[productIdx], "_") | |
985 | 930 | if (if (!(isPositive)) | |
986 | 931 | then (count > curr) | |
987 | 932 | else false) | |
988 | 933 | then throw(((((("You have " + toString(curr)) + " of ") + prodTypes[productIdx]) + ", but tried to use ") + toString(count))) | |
989 | 934 | else { | |
990 | 935 | let isBigItem = if (if (!(isPositive)) | |
991 | 936 | then checkStatRequirements(duckStats, split(recipe[rIdxRequirements], ",")) | |
992 | 937 | else false) | |
993 | 938 | then { | |
994 | 939 | let compat = recipe[rIdxSlots] | |
995 | 940 | if ((compat == "")) | |
996 | 941 | then throw("Item cannot be equipped") | |
997 | 942 | else { | |
998 | 943 | let c = parseIntValue(compat) | |
999 | 944 | let cSeg = (c / 100) | |
1000 | 945 | if ((segment != cSeg)) | |
1001 | 946 | then throw("Segment incompatible") | |
1002 | 947 | else { | |
1003 | 948 | let cMainAux = ((c % 100) / 10) | |
1004 | 949 | if ((mainAux != cMainAux)) | |
1005 | 950 | then throw("Slot incompatible") | |
1006 | 951 | else { | |
1007 | 952 | let cNumSlots = (c % 10) | |
1008 | 953 | if (if ((slot != 0)) | |
1009 | 954 | then (cNumSlots > 1) | |
1010 | 955 | else false) | |
1011 | 956 | then throw("Big items should occupy slot 0") | |
1012 | 957 | else (cNumSlots > 1) | |
1013 | 958 | } | |
1014 | 959 | } | |
1015 | 960 | } | |
1016 | 961 | } | |
1017 | 962 | else false | |
1018 | 963 | $Tuple2(((head + toBytes((curr + (if (isPositive) | |
1019 | 964 | then count | |
1020 | 965 | else -(count))))) + tail), isBigItem) | |
1021 | 966 | } | |
1022 | 967 | } | |
1023 | 968 | } | |
1024 | 969 | } | |
1025 | 970 | ||
1026 | 971 | ||
1027 | 972 | func slotsGroupB (g,bpIn,isPositive,segment,mainAux,stats) = if ((g != "")) | |
1028 | 973 | then { | |
1029 | 974 | let slots = split(g, ",") | |
1030 | 975 | if ((size(slots) > MAXSLOTS)) | |
1031 | 976 | then throw("Wrong slots format") | |
1032 | 977 | else { | |
1033 | 978 | let s0 = slots[0] | |
1034 | 979 | let s1 = if ((size(slots) > 1)) | |
1035 | 980 | then slots[1] | |
1036 | 981 | else "" | |
1037 | 982 | if (if ((s0 == "")) | |
1038 | 983 | then (s1 == "") | |
1039 | 984 | else false) | |
1040 | 985 | then bpIn | |
1041 | 986 | else { | |
1042 | 987 | let tmpS0 = if ((s0 != "")) | |
1043 | 988 | then addProdB(s0, bpIn, isPositive, segment, mainAux, 0, stats) | |
1044 | 989 | else $Tuple2(bpIn, false) | |
1045 | 990 | if ((s1 != "")) | |
1046 | 991 | then if (tmpS0._2) | |
1047 | 992 | then throw("Big item already occupies slot") | |
1048 | 993 | else addProdB(s1, tmpS0._1, isPositive, segment, mainAux, 1, stats)._1 | |
1049 | 994 | else tmpS0._1 | |
1050 | 995 | } | |
1051 | 996 | } | |
1052 | 997 | } | |
1053 | 998 | else bpIn | |
1054 | 999 | ||
1055 | 1000 | ||
1056 | 1001 | func dressB (segList,pBytes,isPositive,stats) = { | |
1057 | 1002 | func segment (acc,seg) = { | |
1058 | 1003 | let j = acc._1 | |
1059 | 1004 | let mainAux = split(seg, ";") | |
1060 | 1005 | if ((size(mainAux) != NUMMAINAUX)) | |
1061 | 1006 | then throw("Wrong segment format") | |
1062 | 1007 | else { | |
1063 | 1008 | let m = mainAux[0] | |
1064 | 1009 | let a = mainAux[1] | |
1065 | 1010 | if (if ((m == "")) | |
1066 | 1011 | then (a == "") | |
1067 | 1012 | else false) | |
1068 | 1013 | then $Tuple2((j + 1), acc._2) | |
1069 | 1014 | else { | |
1070 | 1015 | let tmpM = slotsGroupB(m, acc._2, isPositive, j, 0, stats) | |
1071 | 1016 | $Tuple2((j + 1), slotsGroupB(a, tmpM, isPositive, j, 1, stats)) | |
1072 | 1017 | } | |
1073 | 1018 | } | |
1074 | 1019 | } | |
1075 | 1020 | ||
1076 | 1021 | ( let $l = segList | |
1077 | 1022 | let $s = size($l) | |
1078 | 1023 | let $acc0 = $Tuple2(0, pBytes) | |
1079 | 1024 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1080 | 1025 | then $a | |
1081 | 1026 | else segment($a, $l[$i]) | |
1082 | 1027 | ||
1083 | 1028 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1084 | 1029 | then $a | |
1085 | 1030 | else throw("List size exceeds 6") | |
1086 | 1031 | ||
1087 | 1032 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6))._2 | |
1088 | 1033 | } | |
1089 | 1034 | ||
1090 | 1035 | ||
1091 | - | func fortB (segList,pBytes,occupied,free,isPositive,duckStats) = if ((3 > size(segList))) | |
1092 | - | then throw("At least duck, mines and traps parts are required") | |
1093 | - | else { | |
1094 | - | func segment (acc,seg) = { | |
1095 | - | let j = acc._1 | |
1096 | - | if ((j == 0)) | |
1097 | - | then $Tuple4((j + 1), acc._2, acc._3, acc._4) | |
1098 | - | else { | |
1099 | - | let p = placeProdB(seg, acc._2, isPositive, duckStats, acc._3, acc._4) | |
1100 | - | $Tuple4((j + 1), p._1, p._2, p._3) | |
1101 | - | } | |
1102 | - | } | |
1103 | - | ||
1104 | - | let t = { | |
1105 | - | let $l = segList | |
1106 | - | let $s = size($l) | |
1107 | - | let $acc0 = $Tuple4(0, pBytes, occupied, free) | |
1108 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1109 | - | then $a | |
1110 | - | else segment($a, $l[$i]) | |
1111 | - | ||
1112 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1113 | - | then $a | |
1114 | - | else throw("List size exceeds 10") | |
1115 | - | ||
1116 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
1117 | - | } | |
1118 | - | $Tuple3(t._2, t._3, t._4) | |
1119 | - | } | |
1120 | - | ||
1121 | - | ||
1122 | 1036 | func canWearCurrentEquipment (duckAssetId) = { | |
1123 | 1037 | let eqKey = keyDuckEquipment(duckAssetId) | |
1124 | 1038 | let currEq = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_") | |
1039 | + | let EMPTY_PROD50 = base64'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' | |
1125 | 1040 | let tempProdB = dressB(currEq, EMPTY_PROD50, true, nil) | |
1126 | 1041 | let segBpAux = split(currEq[segBackpack], ";")[1] | |
1127 | 1042 | let buffEffect = if ((segBpAux == "")) | |
1128 | 1043 | then 0 | |
1129 | 1044 | else { | |
1130 | 1045 | let aux0 = split(segBpAux, ",")[0] | |
1131 | 1046 | if ((aux0 == "")) | |
1132 | 1047 | then 0 | |
1133 | 1048 | else { | |
1134 | 1049 | let idxCnt = split(aux0, ":") | |
1135 | 1050 | let idx = idxCnt[0] | |
1136 | 1051 | let cnt = idxCnt[1] | |
1137 | 1052 | if (if (if (if (if ((idx == "06")) | |
1138 | 1053 | then true | |
1139 | 1054 | else (idx == "07")) | |
1140 | 1055 | then true | |
1141 | 1056 | else (idx == "08")) | |
1142 | 1057 | then (cnt != "") | |
1143 | 1058 | else false) | |
1144 | 1059 | then (parseIntValue(cnt) > 0) | |
1145 | 1060 | else false) | |
1146 | 1061 | then parseIntValue(split(productionMatrix[parseIntValue(idx)], "_")[rIdxEffect]) | |
1147 | 1062 | else 0 | |
1148 | 1063 | } | |
1149 | 1064 | } | |
1150 | 1065 | let stats = getDuckStats(this, duckAssetId, buffEffect, true) | |
1151 | 1066 | let newProdB = dressB(currEq, tempProdB, false, stats) | |
1152 | 1067 | (newProdB == newProdB) | |
1153 | 1068 | } | |
1154 | 1069 | ||
1155 | 1070 | ||
1156 | 1071 | func updateProportionsInternal (propList,terrainCounts,landSizeIndex,sign) = if ((size(propList) != NUMRES)) | |
1157 | 1072 | then throw("Wrong proportions data") | |
1158 | 1073 | else { | |
1159 | 1074 | func updater (acc,i) = { | |
1160 | 1075 | let result = (parseIntValue(propList[i]) + ((sign * terrainCounts[i]) * landSizeIndex)) | |
1161 | 1076 | if ((0 > result)) | |
1162 | 1077 | then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex))) | |
1163 | 1078 | else (acc :+ toString(result)) | |
1164 | 1079 | } | |
1165 | 1080 | ||
1166 | 1081 | let $l = ITER6 | |
1167 | 1082 | let $s = size($l) | |
1168 | 1083 | let $acc0 = nil | |
1169 | 1084 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1170 | 1085 | then $a | |
1171 | 1086 | else updater($a, $l[$i]) | |
1172 | 1087 | ||
1173 | 1088 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1174 | 1089 | then $a | |
1175 | 1090 | else throw("List size exceeds 6") | |
1176 | 1091 | ||
1177 | 1092 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1178 | 1093 | } | |
1179 | 1094 | ||
1180 | 1095 | ||
1181 | 1096 | func updateProportions (terrainCounts,landSizeIndex,sign) = { | |
1182 | 1097 | let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_") | |
1183 | 1098 | makeString(updateProportionsInternal(propList, terrainCounts, landSizeIndex, sign), "_") | |
1184 | 1099 | } | |
1185 | 1100 | ||
1186 | 1101 | ||
1187 | 1102 | func countTerrains (terrains) = [(size(split(terrains, "A")) - 1), (size(split(terrains, "B")) - 1), (size(split(terrains, "C")) - 1), (size(split(terrains, "D")) - 1), (size(split(terrains, "E")) - 1), (size(split(terrains, "F")) - 1)] | |
1188 | 1103 | ||
1189 | 1104 | ||
1190 | 1105 | func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = { | |
1191 | 1106 | func adder (acc,i) = { | |
1192 | 1107 | let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex) | |
1193 | 1108 | (acc :+ toString((parseIntValue(currentRes[i]) + resOfType))) | |
1194 | 1109 | } | |
1195 | 1110 | ||
1196 | 1111 | let r = { | |
1197 | 1112 | let $l = ITER6 | |
1198 | 1113 | let $s = size($l) | |
1199 | 1114 | let $acc0 = nil | |
1200 | 1115 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1201 | 1116 | then $a | |
1202 | 1117 | else adder($a, $l[$i]) | |
1203 | 1118 | ||
1204 | 1119 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1205 | 1120 | then $a | |
1206 | 1121 | else throw("List size exceeds 6") | |
1207 | 1122 | ||
1208 | 1123 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1209 | 1124 | } | |
1210 | 1125 | makeString(r, "_") | |
1211 | 1126 | } | |
1212 | 1127 | ||
1213 | 1128 | ||
1214 | 1129 | func virtClaim (terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = { | |
1215 | 1130 | func adder (acc,i) = { | |
1216 | 1131 | let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex) | |
1217 | 1132 | $Tuple2((acc._1 :+ resOfType), (acc._2 + resOfType)) | |
1218 | 1133 | } | |
1219 | 1134 | ||
1220 | 1135 | let $l = ITER6 | |
1221 | 1136 | let $s = size($l) | |
1222 | 1137 | let $acc0 = $Tuple2(nil, 0) | |
1223 | 1138 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1224 | 1139 | then $a | |
1225 | 1140 | else adder($a, $l[$i]) | |
1226 | 1141 | ||
1227 | 1142 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1228 | 1143 | then $a | |
1229 | 1144 | else throw("List size exceeds 6") | |
1230 | 1145 | ||
1231 | 1146 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1232 | 1147 | } | |
1233 | 1148 | ||
1234 | 1149 | ||
1235 | 1150 | func distributeRes (currentWhRes,currentPackRes,resToClaim,whSpaceLeft) = { | |
1236 | 1151 | let resListToClaim = resToClaim._1 | |
1237 | 1152 | let resAmToClaim = resToClaim._2 | |
1238 | 1153 | if ((resAmToClaim == 0)) | |
1239 | 1154 | then $Tuple2(makeString(currentWhRes, "_"), makeString(currentPackRes, "_")) | |
1240 | 1155 | else if ((whSpaceLeft >= resAmToClaim)) | |
1241 | 1156 | then { | |
1242 | 1157 | func addLists (acc,i) = (acc :+ toString((parseIntValue(currentWhRes[i]) + resListToClaim[i]))) | |
1243 | 1158 | ||
1244 | 1159 | let r = { | |
1245 | 1160 | let $l = ITER6 | |
1246 | 1161 | let $s = size($l) | |
1247 | 1162 | let $acc0 = nil | |
1248 | 1163 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1249 | 1164 | then $a | |
1250 | 1165 | else addLists($a, $l[$i]) | |
1251 | 1166 | ||
1252 | 1167 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1253 | 1168 | then $a | |
1254 | 1169 | else throw("List size exceeds 6") | |
1255 | 1170 | ||
1256 | 1171 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1257 | 1172 | } | |
1258 | 1173 | $Tuple2(makeString(r, "_"), makeString(currentPackRes, "_")) | |
1259 | 1174 | } | |
1260 | 1175 | else { | |
1261 | 1176 | func addPartLists (acc,i) = { | |
1262 | 1177 | let whPart = fraction(resListToClaim[i], whSpaceLeft, resAmToClaim) | |
1263 | 1178 | $Tuple2((acc._1 :+ toString((parseIntValue(currentWhRes[i]) + whPart))), (acc._2 :+ toString(((parseIntValue(currentPackRes[i]) + resListToClaim[i]) - whPart)))) | |
1264 | 1179 | } | |
1265 | 1180 | ||
1266 | 1181 | let r = { | |
1267 | 1182 | let $l = ITER6 | |
1268 | 1183 | let $s = size($l) | |
1269 | 1184 | let $acc0 = $Tuple2(nil, nil) | |
1270 | 1185 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1271 | 1186 | then $a | |
1272 | 1187 | else addPartLists($a, $l[$i]) | |
1273 | 1188 | ||
1274 | 1189 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1275 | 1190 | then $a | |
1276 | 1191 | else throw("List size exceeds 6") | |
1277 | 1192 | ||
1278 | 1193 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1279 | 1194 | } | |
1280 | 1195 | $Tuple2(makeString(r._1, "_"), makeString(r._2, "_")) | |
1281 | 1196 | } | |
1282 | 1197 | } | |
1283 | 1198 | ||
1284 | 1199 | ||
1285 | 1200 | func abs (x) = if ((x >= toBigInt(0))) | |
1286 | 1201 | then x | |
1287 | 1202 | else -(x) | |
1288 | 1203 | ||
1289 | 1204 | ||
1290 | 1205 | let freq = [[6, 9, 14, 15, 16], [5, 8, 13, 14, 15], [1, 4, 9, 10, 15], [1, 6, 7, 15, 19], [4, 7, 8, 13, 18]] | |
1291 | 1206 | ||
1292 | 1207 | func genChar (n,freqs) = { | |
1293 | 1208 | let rem = toInt((n % TWENTYX)) | |
1294 | 1209 | let letter = if ((freqs[0] > rem)) | |
1295 | 1210 | then "A" | |
1296 | 1211 | else if ((freqs[1] > rem)) | |
1297 | 1212 | then "B" | |
1298 | 1213 | else if ((freqs[2] > rem)) | |
1299 | 1214 | then "C" | |
1300 | 1215 | else if ((freqs[3] > rem)) | |
1301 | 1216 | then "D" | |
1302 | 1217 | else if ((freqs[4] > rem)) | |
1303 | 1218 | then "E" | |
1304 | 1219 | else "F" | |
1305 | 1220 | letter | |
1306 | 1221 | } | |
1307 | 1222 | ||
1308 | 1223 | ||
1309 | 1224 | func genTerrains (seed,continentIdx) = { | |
1310 | 1225 | let f = freq[continentIdx] | |
1311 | 1226 | func terrainGenerator (acc,elem) = $Tuple2((((((acc._1 + genChar(acc._2, f)) + genChar((acc._2 / TWENTYX), f)) + genChar((acc._2 / TWENTY2X), f)) + genChar((acc._2 / TWENTY3X), f)) + genChar((acc._2 / TWENTY4X), f)), (acc._2 / TWENTY5X)) | |
1312 | 1227 | ||
1313 | 1228 | let t = { | |
1314 | 1229 | let $l = [1, 2, 3, 4, 5] | |
1315 | 1230 | let $s = size($l) | |
1316 | 1231 | let $acc0 = $Tuple2("", (seed / FIVEX)) | |
1317 | 1232 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1318 | 1233 | then $a | |
1319 | 1234 | else terrainGenerator($a, $l[$i]) | |
1320 | 1235 | ||
1321 | 1236 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1322 | 1237 | then $a | |
1323 | 1238 | else throw("List size exceeds 5") | |
1324 | 1239 | ||
1325 | 1240 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
1326 | 1241 | } | |
1327 | 1242 | t._1 | |
1328 | 1243 | } | |
1329 | 1244 | ||
1330 | 1245 | ||
1331 | 1246 | let PERM25 = [7, 2, 15, 19, 8, 24, 1, 21, 16, 5, 0, 22, 20, 23, 11, 4, 18, 12, 6, 10, 3, 17, 13, 9, 14] | |
1332 | 1247 | ||
1333 | 1248 | let TCHARS = ["A", "B", "C", "D", "E", "F"] | |
1334 | 1249 | ||
1335 | 1250 | func genTerrainsForMerge (sumTerrains,landSizeIndex) = { | |
1336 | 1251 | func step1 (acc,s) = { | |
1337 | 1252 | let j = acc._2 | |
1338 | 1253 | let el = parseIntValue(s) | |
1339 | 1254 | let x = if ((el == 0)) | |
1340 | 1255 | then 0 | |
1341 | 1256 | else if ((el >= (4 * landSizeIndex))) | |
1342 | 1257 | then (el / landSizeIndex) | |
1343 | 1258 | else if ((el > (3 * landSizeIndex))) | |
1344 | 1259 | then 3 | |
1345 | 1260 | else (((el - 1) / landSizeIndex) + 1) | |
1346 | 1261 | $Tuple3((acc._1 :+ x), (acc._2 + 1), (acc._3 + x)) | |
1347 | 1262 | } | |
1348 | 1263 | ||
1349 | 1264 | let t = { | |
1350 | 1265 | let $l = sumTerrains | |
1351 | 1266 | let $s = size($l) | |
1352 | 1267 | let $acc0 = $Tuple3(nil, 0, 0) | |
1353 | 1268 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1354 | 1269 | then $a | |
1355 | 1270 | else step1($a, $l[$i]) | |
1356 | 1271 | ||
1357 | 1272 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1358 | 1273 | then $a | |
1359 | 1274 | else throw("List size exceeds 6") | |
1360 | 1275 | ||
1361 | 1276 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1362 | 1277 | } | |
1363 | 1278 | let arr = t._1 | |
1364 | 1279 | let maxIdx = value(indexOf(arr, max(arr))) | |
1365 | 1280 | let delta = (t._3 - 25) | |
1366 | 1281 | func subber (acc,idx) = { | |
1367 | 1282 | let val = if ((idx == maxIdx)) | |
1368 | 1283 | then (arr[idx] - delta) | |
1369 | 1284 | else arr[idx] | |
1370 | 1285 | let zeroes = if ((val == 0)) | |
1371 | 1286 | then nil | |
1372 | 1287 | else split(drop(toString(pow(10, 0, val, 0, 0, DOWN)), 1), "") | |
1373 | 1288 | let c = TCHARS[idx] | |
1374 | 1289 | func listGen (ac,ignored) = (ac :+ c) | |
1375 | 1290 | ||
1376 | 1291 | let z = { | |
1377 | 1292 | let $l = zeroes | |
1378 | 1293 | let $s = size($l) | |
1379 | 1294 | let $acc0 = nil | |
1380 | 1295 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
1381 | 1296 | then $a | |
1382 | 1297 | else listGen($a, $l[$i]) | |
1383 | 1298 | ||
1384 | 1299 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
1385 | 1300 | then $a | |
1386 | 1301 | else throw("List size exceeds 25") | |
1387 | 1302 | ||
1388 | 1303 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 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) | |
1389 | 1304 | } | |
1390 | 1305 | (acc ++ z) | |
1391 | 1306 | } | |
1392 | 1307 | ||
1393 | 1308 | let r = { | |
1394 | 1309 | let $l = ITER6 | |
1395 | 1310 | let $s = size($l) | |
1396 | 1311 | let $acc0 = nil | |
1397 | 1312 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
1398 | 1313 | then $a | |
1399 | 1314 | else subber($a, $l[$i]) | |
1400 | 1315 | ||
1401 | 1316 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
1402 | 1317 | then $a | |
1403 | 1318 | else throw("List size exceeds 6") | |
1404 | 1319 | ||
1405 | 1320 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1406 | 1321 | } | |
1407 | 1322 | func permut (acc,j) = (acc + r[j]) | |
1408 | 1323 | ||
1409 | 1324 | let $l = PERM25 | |
1410 | 1325 | let $s = size($l) | |
1411 | 1326 | let $acc0 = "" | |
1412 | 1327 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
1413 | 1328 | then $a | |
1414 | 1329 | else permut($a, $l[$i]) | |
1415 | 1330 | ||
1416 | 1331 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
1417 | 1332 | then $a | |
1418 | 1333 | else throw("List size exceeds 25") | |
1419 | 1334 | ||
1420 | 1335 | $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 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) | |
1421 | 1336 | } | |
1422 | 1337 | ||
1423 | 1338 | ||
1424 | 1339 | func getBackpack (bpKey) = { | |
1425 | 1340 | let p = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":") | |
1426 | 1341 | [toString(valueOrElse(parseInt(p[bpIdxLevel]), 0)), if ((size(split(p[bpIdxRes], "_")) == NUMRES)) | |
1427 | 1342 | then p[bpIdxRes] | |
1428 | 1343 | else "0_0_0_0_0_0", if ((size(split(p[bpIdxMat], "_")) == NUMRES)) | |
1429 | 1344 | then p[bpIdxMat] | |
1430 | 1345 | else "0_0_0_0_0_0", p[bpIdxProd]] | |
1431 | 1346 | } | |
1432 | 1347 | ||
1433 | 1348 | ||
1434 | 1349 | func getWarehouseTotalVolume (volPrefix) = { | |
1435 | 1350 | let parts = split(volPrefix, "_") | |
1436 | 1351 | ((WHMULTIPLIER * (parseIntValue(parts[1]) + 1)) * parseIntValue(parts[0])) | |
1437 | 1352 | } | |
1438 | 1353 | ||
1439 | 1354 | ||
1440 | 1355 | func getWarehouseOccupiedVol (currentWh) = { | |
1441 | 1356 | let goods = currentWh[whIdxProd] | |
1442 | 1357 | func sumResMat (acc,item) = (acc + parseIntValue(item)) | |
1443 | 1358 | ||
1444 | 1359 | func sumProd (acc,item) = { | |
1445 | 1360 | let idx = acc._1 | |
1446 | 1361 | let pkgs = (((parseIntValue(item) + PRODUCTPKGSIZE) - 1) / PRODUCTPKGSIZE) | |
1447 | 1362 | $Tuple2((idx + 1), (acc._2 + (pkgs * MULT8))) | |
1448 | 1363 | } | |
1449 | 1364 | ||
1450 | 1365 | let whResVol = { | |
1451 | 1366 | let $l = split(currentWh[whIdxRes], "_") | |
1452 | 1367 | let $s = size($l) | |
1453 | 1368 | let $acc0 = 0 | |
1454 | 1369 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1455 | 1370 | then $a | |
1456 | 1371 | else sumResMat($a, $l[$i]) | |
1457 | 1372 | ||
1458 | 1373 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1459 | 1374 | then $a | |
1460 | 1375 | else throw("List size exceeds 6") | |
1461 | 1376 | ||
1462 | 1377 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1463 | 1378 | } | |
1464 | 1379 | let whMatVol = { | |
1465 | 1380 | let $l = split(currentWh[whIdxMat], "_") | |
1466 | 1381 | let $s = size($l) | |
1467 | 1382 | let $acc0 = 0 | |
1468 | 1383 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
1469 | 1384 | then $a | |
1470 | 1385 | else sumResMat($a, $l[$i]) | |
1471 | 1386 | ||
1472 | 1387 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
1473 | 1388 | then $a | |
1474 | 1389 | else throw("List size exceeds 6") | |
1475 | 1390 | ||
1476 | 1391 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1477 | 1392 | } | |
1478 | 1393 | let whGoodsVol = if ((goods == "")) | |
1479 | 1394 | then 0 | |
1480 | 1395 | else ( let $l = split_4C(goods, "_") | |
1481 | 1396 | let $s = size($l) | |
1482 | 1397 | let $acc0 = $Tuple2(0, 0) | |
1483 | 1398 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
1484 | 1399 | then $a | |
1485 | 1400 | else sumProd($a, $l[$i]) | |
1486 | 1401 | ||
1487 | 1402 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
1488 | 1403 | then $a | |
1489 | 1404 | else throw("List size exceeds 50") | |
1490 | 1405 | ||
1491 | 1406 | $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 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))._2 | |
1492 | 1407 | ((whResVol + whMatVol) + whGoodsVol) | |
1493 | 1408 | } | |
1494 | 1409 | ||
1495 | 1410 | ||
1496 | 1411 | func getWarehouse (whKey,landIndex,infraLevel) = { | |
1497 | 1412 | let volPrefix = ((toString(landIndex) + "_") + toString(infraLevel)) | |
1498 | 1413 | let whTotal = getWarehouseTotalVolume(volPrefix) | |
1499 | 1414 | let whStr = valueOrElse(getString(whKey), (volPrefix + ":0_0_0_0_0_0:0_0_0_0_0_0::0")) | |
1500 | 1415 | let wh = split_4C(whStr, ":") | |
1501 | 1416 | let whOccupied = getWarehouseOccupiedVol(wh) | |
1502 | 1417 | let whLoft = if ((5 > size(wh))) | |
1503 | 1418 | then makeString(["0", toString(whOccupied), toString((whTotal - whOccupied)), toString(whTotal)], "_") | |
1504 | 1419 | else { | |
1505 | 1420 | let loft = split(wh[whIdxLOFT], "_") | |
1506 | 1421 | let whLocked = parseIntValue(loft[volLocked]) | |
1507 | 1422 | let occ = if ((size(loft) > 1)) | |
1508 | 1423 | then parseIntValue(loft[volOccupied]) | |
1509 | 1424 | else whOccupied | |
1510 | 1425 | makeString([toString(whLocked), toString(occ), toString(((whTotal - whLocked) - occ)), toString(whTotal)], "_") | |
1511 | 1426 | } | |
1512 | 1427 | [wh[whIdxLevels], if ((size(split(wh[whIdxRes], "_")) == NUMRES)) | |
1513 | 1428 | then wh[whIdxRes] | |
1514 | 1429 | else "0_0_0_0_0_0", if ((size(split(wh[whIdxMat], "_")) == NUMRES)) | |
1515 | 1430 | then wh[whIdxMat] | |
1516 | 1431 | else "0_0_0_0_0_0", wh[whIdxProd], whLoft] | |
1517 | 1432 | } | |
1518 | 1433 | ||
1519 | 1434 | ||
1520 | 1435 | func getWarehouseSpaceLeft (currentWh) = { | |
1521 | 1436 | let occupiedVol = getWarehouseOccupiedVol(currentWh) | |
1522 | 1437 | let currWhLockedVol = parseIntValue(split(currentWh[whIdxLOFT], "_")[volLocked]) | |
1523 | 1438 | ((getWarehouseTotalVolume(currentWh[whIdxLevels]) - occupiedVol) - currWhLockedVol) | |
1524 | 1439 | } | |
1525 | 1440 | ||
1526 | 1441 | ||
1527 | 1442 | func moveStuff (cargoParts,currentWh,currentPack) = if ((size(cargoParts) != 3)) | |
1528 | 1443 | then throw("cargoListStr should contain exactly 2 ':' separators") | |
1529 | 1444 | else { | |
1530 | 1445 | let resParts = split(cargoParts[0], "_") | |
1531 | 1446 | let matParts = split(cargoParts[1], "_") | |
1532 | 1447 | let prodParts = if ((cargoParts[2] == "")) | |
1533 | 1448 | then nil | |
1534 | 1449 | else split_4C(cargoParts[2], "_") | |
1535 | 1450 | if ((size(resParts) != NUMRES)) | |
1536 | 1451 | then throw("All 6 resources should be passed") | |
1537 | 1452 | else if ((size(matParts) != NUMRES)) | |
1538 | 1453 | then throw("All 6 materials should be passed") | |
1539 | 1454 | else { | |
1540 | 1455 | let whSpaceLeft = getWarehouseSpaceLeft(currentWh) | |
1541 | 1456 | let currWhRes = split(currentWh[whIdxRes], "_") | |
1542 | 1457 | let currWhMat = split(currentWh[whIdxMat], "_") | |
1543 | 1458 | let currWhProd = if ((currentWh[whIdxProd] == "")) | |
1544 | 1459 | then nil | |
1545 | 1460 | else split_4C(currentWh[whIdxProd], "_") | |
1546 | 1461 | let currentPackRes = split(currentPack[bpIdxRes], "_") | |
1547 | 1462 | let currentPackMat = split(currentPack[bpIdxMat], "_") | |
1548 | 1463 | let currentPackProd = if ((currentPack[bpIdxProd] == "")) | |
1549 | 1464 | then nil | |
1550 | 1465 | else split_4C(currentPack[bpIdxProd], "_") | |
1551 | 1466 | func mvR (acc,item) = { | |
1552 | 1467 | let i = acc._1 | |
1553 | 1468 | let am = parseIntValue(item) | |
1554 | 1469 | let whr = parseIntValue(currWhRes[i]) | |
1555 | 1470 | let bpr = parseIntValue(currentPackRes[i]) | |
1556 | 1471 | if ((am == 0)) | |
1557 | 1472 | then $Tuple4((i + 1), (acc._2 :+ currWhRes[i]), (acc._3 :+ currentPackRes[i]), acc._4) | |
1558 | 1473 | else if ((am > 0)) | |
1559 | 1474 | then if ((am > bpr)) | |
1560 | 1475 | then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpr)) + " available")) | |
1561 | 1476 | else $Tuple4((i + 1), (acc._2 :+ toString((whr + am))), (acc._3 :+ toString((bpr - am))), (acc._4 + am)) | |
1562 | 1477 | else if ((-(am) > whr)) | |
1563 | 1478 | then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whr)) + " available")) | |
1564 | 1479 | else $Tuple4((i + 1), (acc._2 :+ toString((whr + am))), (acc._3 :+ toString((bpr - am))), (acc._4 + am)) | |
1565 | 1480 | } | |
1566 | 1481 | ||
1567 | 1482 | let r = { | |
1568 | 1483 | let $l = resParts | |
1569 | 1484 | let $s = size($l) | |
1570 | 1485 | let $acc0 = $Tuple4(0, nil, nil, 0) | |
1571 | 1486 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1572 | 1487 | then $a | |
1573 | 1488 | else mvR($a, $l[$i]) | |
1574 | 1489 | ||
1575 | 1490 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1576 | 1491 | then $a | |
1577 | 1492 | else throw("List size exceeds 6") | |
1578 | 1493 | ||
1579 | 1494 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1580 | 1495 | } | |
1581 | 1496 | func mvM (acc,item) = { | |
1582 | 1497 | let i = acc._1 | |
1583 | 1498 | let am = parseIntValue(item) | |
1584 | 1499 | let whm = parseIntValue(currWhMat[i]) | |
1585 | 1500 | let bpm = parseIntValue(currentPackMat[i]) | |
1586 | 1501 | if ((am == 0)) | |
1587 | 1502 | then $Tuple4((i + 1), (acc._2 :+ currWhMat[i]), (acc._3 :+ currentPackMat[i]), acc._4) | |
1588 | 1503 | else if ((am > 0)) | |
1589 | 1504 | then if ((am > bpm)) | |
1590 | 1505 | then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpm)) + " available")) | |
1591 | 1506 | else $Tuple4((i + 1), (acc._2 :+ toString((whm + am))), (acc._3 :+ toString((bpm - am))), (acc._4 + am)) | |
1592 | 1507 | else if ((-(am) > whm)) | |
1593 | 1508 | then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whm)) + " available")) | |
1594 | 1509 | else $Tuple4((i + 1), (acc._2 :+ toString((whm + am))), (acc._3 :+ toString((bpm - am))), (acc._4 + am)) | |
1595 | 1510 | } | |
1596 | 1511 | ||
1597 | 1512 | let m = { | |
1598 | 1513 | let $l = matParts | |
1599 | 1514 | let $s = size($l) | |
1600 | 1515 | let $acc0 = $Tuple4(0, nil, nil, r._4) | |
1601 | 1516 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
1602 | 1517 | then $a | |
1603 | 1518 | else mvM($a, $l[$i]) | |
1604 | 1519 | ||
1605 | 1520 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
1606 | 1521 | then $a | |
1607 | 1522 | else throw("List size exceeds 6") | |
1608 | 1523 | ||
1609 | 1524 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1610 | 1525 | } | |
1611 | 1526 | func mvP (acc,item) = { | |
1612 | 1527 | let i = acc._1 | |
1613 | 1528 | let am = parseIntValue(item) | |
1614 | 1529 | let whp = if ((size(currWhProd) > i)) | |
1615 | 1530 | then parseIntValue(currWhProd[i]) | |
1616 | 1531 | else 0 | |
1617 | 1532 | let bpp = if ((size(currentPackProd) > i)) | |
1618 | 1533 | then parseIntValue(currentPackProd[i]) | |
1619 | 1534 | else 0 | |
1620 | 1535 | if ((am == 0)) | |
1621 | 1536 | then $Tuple4((i + 1), (acc._2 :+ toString(whp)), (acc._3 :+ toString(bpp)), acc._4) | |
1622 | 1537 | else if ((am > 0)) | |
1623 | 1538 | then if ((am > bpp)) | |
1624 | 1539 | then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpp)) + " available")) | |
1625 | 1540 | else { | |
1626 | 1541 | let deltaVol = (toVolume((whp + am), PRODUCTPKGSIZE) - toVolume(whp, PRODUCTPKGSIZE)) | |
1627 | 1542 | $Tuple4((i + 1), (acc._2 :+ toString((whp + am))), (acc._3 :+ toString((bpp - am))), (acc._4 + deltaVol)) | |
1628 | 1543 | } | |
1629 | 1544 | else if ((-(am) > whp)) | |
1630 | 1545 | then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whp)) + " available")) | |
1631 | 1546 | else { | |
1632 | 1547 | let deltaVol = (toVolume((whp + am), PRODUCTPKGSIZE) - toVolume(whp, PRODUCTPKGSIZE)) | |
1633 | 1548 | $Tuple4((i + 1), (acc._2 :+ toString((whp + am))), (acc._3 :+ toString((bpp - am))), (acc._4 + deltaVol)) | |
1634 | 1549 | } | |
1635 | 1550 | } | |
1636 | 1551 | ||
1637 | 1552 | let p = if ((size(prodParts) != 0)) | |
1638 | 1553 | then { | |
1639 | 1554 | let $l = prodParts | |
1640 | 1555 | let $s = size($l) | |
1641 | 1556 | let $acc0 = $Tuple4(0, nil, nil, m._4) | |
1642 | 1557 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
1643 | 1558 | then $a | |
1644 | 1559 | else mvP($a, $l[$i]) | |
1645 | 1560 | ||
1646 | 1561 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
1647 | 1562 | then $a | |
1648 | 1563 | else throw("List size exceeds 50") | |
1649 | 1564 | ||
1650 | 1565 | $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 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) | |
1651 | 1566 | } | |
1652 | 1567 | else $Tuple4(0, currWhProd, currentPackProd, m._4) | |
1653 | 1568 | let volSaldo = p._4 | |
1654 | 1569 | if ((volSaldo > whSpaceLeft)) | |
1655 | 1570 | then throw((((("Attempt to put total " + toString(volSaldo)) + " stuff, but only ") + toString(whSpaceLeft)) + " warehouse space left")) | |
1656 | 1571 | else $Tuple7(makeString(r._2, "_"), makeString(m._2, "_"), makeString_2C(p._2, "_"), makeString(r._3, "_"), makeString(m._3, "_"), makeString_2C(p._3, "_"), volSaldo) | |
1657 | 1572 | } | |
1658 | 1573 | } | |
1659 | 1574 | ||
1660 | 1575 | ||
1661 | 1576 | func expeditionInternal (caller,txId) = { | |
1662 | 1577 | let userAddr = toString(caller) | |
1663 | 1578 | let bigNum = abs(toBigInt(txId)) | |
1664 | 1579 | let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1)) | |
1665 | 1580 | let landNum = toString(freeNum) | |
1666 | 1581 | let continentIdx = toInt((bigNum % FIVEX)) | |
1667 | 1582 | let terrains = genTerrains(bigNum, continentIdx) | |
1668 | 1583 | let continent = continents[continentIdx] | |
1669 | 1584 | let issue = Issue(nftName(landNum, "S"), makeString([landNum, "S", terrains, continent], "_"), 1, 0, false) | |
1670 | 1585 | let assetId = calculateAssetId(issue) | |
1671 | 1586 | let id = toBase58String(assetId) | |
1672 | 1587 | $Tuple2([IntegerEntry(keyNextFreeLandNum(), (freeNum + 1)), issue, StringEntry(keyLandToAssetId(landNum), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(landNum), userAddr), IntegerEntry(keyInfraLevelByAssetId(id), 0), IntegerEntry(keyInfraLevelByAssetIdAndOwner(id, userAddr), 0), ScriptTransfer(caller, 1, assetId)], $Tuple2(id, continent)) | |
1673 | 1588 | } | |
1674 | 1589 | ||
1675 | 1590 | ||
1676 | 1591 | func flightCommon (userAddr,message,sig) = if (!(sigVerify_8Kb(message, sig, pub))) | |
1677 | 1592 | then throw("signature does not match") | |
1678 | 1593 | else { | |
1679 | 1594 | let parts = split_4C(toUtf8String(message), ";") | |
1680 | 1595 | let flightLog = split_4C(parts[0], "|") | |
1681 | 1596 | let hp = split(flightLog[flHealth], "_") | |
1682 | 1597 | let curHP = parseIntValue(hp[0]) | |
1683 | 1598 | let newHP = parseIntValue(hp[1]) | |
1684 | 1599 | let newLocTxVer = split(parts[1], ":") | |
1685 | 1600 | let newLocation = newLocTxVer[0] | |
1686 | 1601 | let time = parseIntValue(flightLog[flTimestamp]) | |
1687 | 1602 | if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS))) | |
1688 | 1603 | then true | |
1689 | 1604 | else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time)) | |
1690 | 1605 | then throw(((("signature outdated: logTime=" + toString(time)) + ", bcTime=") + toString(lastBlock.timestamp))) | |
1691 | 1606 | else { | |
1692 | 1607 | let txFromMsg = newLocTxVer[1] | |
1693 | 1608 | let lastTx = valueOrElse(getString(keyLastTxIdByUser(userAddr)), "") | |
1694 | 1609 | if ((lastTx != txFromMsg)) | |
1695 | 1610 | then throw(((("Tx ids don't match! In state: " + lastTx) + ", in msg: ") + txFromMsg)) | |
1696 | 1611 | else { | |
1697 | 1612 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked") | |
1698 | 1613 | let keyHealth = keyDuckHealth(duckAssetId) | |
1699 | 1614 | let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0)) | |
1700 | 1615 | let oldFromState = valueOrElse(getInteger(keyHealth), maxHP) | |
1701 | 1616 | if ((oldFromState != curHP)) | |
1702 | 1617 | then throw(((("oldHealth=" + toString(oldFromState)) + " from state does not match one from flight log=") + toString(curHP))) | |
1703 | 1618 | else if ((0 >= curHP)) | |
1704 | 1619 | then throw("You can't fly with zero health") | |
1705 | 1620 | else if (!(canWearCurrentEquipment(duckAssetId))) | |
1706 | 1621 | then throw("Equipment incompatible") | |
1707 | 1622 | else { | |
1708 | 1623 | let bonus = if ((size(flightLog) > flBonus)) | |
1709 | 1624 | then flightLog[flBonus] | |
1710 | 1625 | else "" | |
1711 | 1626 | let prodUsed = if ((size(flightLog) > flProdsUsed)) | |
1712 | 1627 | then flightLog[flProdsUsed] | |
1713 | 1628 | else "" | |
1714 | 1629 | let sentAmount = if (if ((newHP > 0)) | |
1715 | 1630 | then (bonus == "$") | |
1716 | 1631 | else false) | |
1717 | 1632 | then asInt(invoke(restContract, "sendUsdtPrize", [userAddr], nil)) | |
1718 | 1633 | else 0 | |
1719 | 1634 | $Tuple5(newHP, duckAssetId, sentAmount, newLocation, prodUsed) | |
1720 | 1635 | } | |
1721 | 1636 | } | |
1722 | 1637 | } | |
1723 | 1638 | } | |
1724 | 1639 | ||
1725 | 1640 | ||
1726 | 1641 | func applyBonuses (landAssetId,pieces) = { | |
1727 | 1642 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1728 | 1643 | let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0) | |
1729 | 1644 | let add6 = (infraLevel / 6) | |
1730 | 1645 | let add7 = (infraLevel / 7) | |
1731 | 1646 | ((DAILYRESBYPIECE + fraction(DAILYRESBYPIECE, ((infraLevel + add6) + (2 * add7)), 5)) + fraction(DAILYRESBYPIECE, artPieces, (pieces * 5))) | |
1732 | 1647 | } | |
1733 | 1648 | ||
1734 | 1649 | ||
1735 | 1650 | func checkClaimConditions (addr,claimMode,landAssetIdIn) = { | |
1736 | - | let $ | |
1651 | + | let $t03367834217 = if ((claimMode == claimModeWh)) | |
1737 | 1652 | then $Tuple2(landAssetIdIn, valueOrElse(getString(keyStakedDuckByOwner(addr)), "")) | |
1738 | 1653 | else { | |
1739 | 1654 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1740 | 1655 | let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION) | |
1741 | 1656 | let loc = split(value(curLocation), "_") | |
1742 | 1657 | if ((loc[locIdxType] != "L")) | |
1743 | 1658 | then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L")) | |
1744 | 1659 | else $Tuple2(loc[locIdxId], duckAssetId) | |
1745 | 1660 | } | |
1746 | - | let landAssetId = $ | |
1747 | - | let duckId = $ | |
1661 | + | let landAssetId = $t03367834217._1 | |
1662 | + | let duckId = $t03367834217._2 | |
1748 | 1663 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
1749 | 1664 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1750 | 1665 | let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Land " + asset.name) + " is not staked")) | |
1751 | 1666 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
1752 | 1667 | if ((owner != addr)) | |
1753 | 1668 | then throw((LANDPREFIX + " is not yours")) | |
1754 | 1669 | else { | |
1755 | 1670 | let d = split(asset.description, "_") | |
1756 | 1671 | $Tuple4(duckId, landAssetId, d, savedTime) | |
1757 | 1672 | } | |
1758 | 1673 | } | |
1759 | 1674 | ||
1760 | 1675 | ||
1761 | 1676 | func claimResInternal (addr,amount,claimMode,landAssetIdIn) = if ((0 > amount)) | |
1762 | 1677 | then throw("Negative amount") | |
1763 | 1678 | else { | |
1764 | 1679 | let c = checkClaimConditions(addr, claimMode, landAssetIdIn) | |
1765 | 1680 | let landSize = c._3[recLandSize] | |
1766 | 1681 | let terrainCounts = countTerrains(c._3[recTerrains]) | |
1767 | 1682 | let deltaTime = (lastBlock.timestamp - c._4) | |
1768 | 1683 | if ((0 > deltaTime)) | |
1769 | 1684 | then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", current = ") + toString(lastBlock.timestamp))) | |
1770 | 1685 | else { | |
1771 | 1686 | let pieces = numPiecesBySize(landSize) | |
1772 | 1687 | let dailyProductionByPiece = applyBonuses(c._2, pieces) | |
1773 | 1688 | let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS) | |
1774 | 1689 | if ((amount > availRes)) | |
1775 | 1690 | then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount))) | |
1776 | 1691 | else { | |
1777 | 1692 | let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces)) | |
1778 | 1693 | let newTimestamp = (lastBlock.timestamp - newDeltaTime) | |
1779 | 1694 | let landIndex = (pieces / SSIZE) | |
1780 | 1695 | let resToClaim = virtClaim(terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece) | |
1781 | 1696 | let whKey = keyWarehouseByLand(c._2) | |
1782 | 1697 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(c._2)), 0) | |
1783 | 1698 | let currentWh = getWarehouse(whKey, landIndex, infraLevel) | |
1784 | 1699 | let loft = split(currentWh[whIdxLOFT], "_") | |
1785 | 1700 | let whSpaceLeft = parseIntValue(loft[volFree]) | |
1786 | 1701 | if (if ((claimMode == claimModeWh)) | |
1787 | 1702 | then (amount > whSpaceLeft) | |
1788 | 1703 | else false) | |
1789 | 1704 | then throw((("Only " + toString(whSpaceLeft)) + " space left in warehouse")) | |
1790 | 1705 | else { | |
1791 | 1706 | let bpKey = keyBackpackByDuck(c._1) | |
1792 | 1707 | let currentPack = getBackpack(bpKey) | |
1793 | 1708 | let currentPackRes = split(currentPack[bpIdxRes], "_") | |
1794 | 1709 | let currentWhRes = split(currentWh[whIdxRes], "_") | |
1795 | - | let $ | |
1710 | + | let $t03659137462 = if ((claimMode == claimModeWh)) | |
1796 | 1711 | then $Tuple4(addRes(currentWhRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), currentPack[bpIdxRes], (parseIntValue(loft[volOccupied]) + resToClaim._2), (parseIntValue(loft[volFree]) - resToClaim._2)) | |
1797 | 1712 | else if ((claimMode == claimModeDuck)) | |
1798 | 1713 | then $Tuple4(currentWh[whIdxRes], addRes(currentPackRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), parseIntValue(loft[volOccupied]), parseIntValue(loft[volFree])) | |
1799 | 1714 | else { | |
1800 | 1715 | let distr = distributeRes(currentWhRes, currentPackRes, resToClaim, whSpaceLeft) | |
1801 | 1716 | let whAm = min([parseIntValue(loft[volFree]), resToClaim._2]) | |
1802 | 1717 | $Tuple4(distr._1, distr._2, (parseIntValue(loft[volOccupied]) + whAm), (parseIntValue(loft[volFree]) - whAm)) | |
1803 | 1718 | } | |
1804 | - | let whRes = $ | |
1805 | - | let bpRes = $ | |
1806 | - | let loftO = $ | |
1807 | - | let loftF = $ | |
1719 | + | let whRes = $t03659137462._1 | |
1720 | + | let bpRes = $t03659137462._2 | |
1721 | + | let loftO = $t03659137462._3 | |
1722 | + | let loftF = $t03659137462._4 | |
1808 | 1723 | $Tuple5([IntegerEntry(keyStakedTimeByAssetId(c._2), newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, c._2, addr), newTimestamp)], bpKey, [currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]], whKey, [currentWh[whIdxLevels], whRes, currentWh[whIdxMat], currentWh[whIdxProd], makeString([loft[volLocked], toString(loftO), toString(loftF), loft[volTotal]], "_")]) | |
1809 | 1724 | } | |
1810 | 1725 | } | |
1811 | 1726 | } | |
1812 | 1727 | } | |
1813 | 1728 | ||
1814 | 1729 | ||
1815 | 1730 | func claimAll (addr,landAssetId,pieces,claimMode) = { | |
1816 | 1731 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1817 | 1732 | let savedTime = value(getInteger(timeKey)) | |
1818 | 1733 | let availRes = (fraction((lastBlock.timestamp - savedTime), applyBonuses(landAssetId, pieces), DAYMILLIS) * pieces) | |
1819 | 1734 | claimResInternal(addr, availRes, claimMode, landAssetId) | |
1820 | 1735 | } | |
1821 | 1736 | ||
1822 | 1737 | ||
1823 | 1738 | func upInfraCommon (shouldUseMat,caller,paymentAmount,landAssetId) = { | |
1824 | 1739 | let addr = toString(caller) | |
1825 | 1740 | let c = checkClaimConditions(addr, claimModeWhThenDuck, landAssetId) | |
1826 | 1741 | let pieces = numPiecesBySize(c._3[recLandSize]) | |
1827 | 1742 | let infraKey = keyInfraLevelByAssetId(c._2) | |
1828 | 1743 | let curLevel = valueOrElse(getInteger(infraKey), 0) | |
1829 | 1744 | if (if (!(KS_ALLOW_BIG_INFRA_MERGE)) | |
1830 | 1745 | then (curLevel >= 3) | |
1831 | 1746 | else false) | |
1832 | 1747 | then throw("Currently max infrastructure level = 3") | |
1833 | 1748 | else { | |
1834 | 1749 | let maxInfra = ((sqrt(pieces, 0, 0, DOWN) / 5) + 2) | |
1835 | 1750 | let newLevel = (curLevel + 1) | |
1836 | 1751 | if (if (KS_ALLOW_BIG_INFRA_MERGE) | |
1837 | 1752 | then (newLevel > maxInfra) | |
1838 | 1753 | else false) | |
1839 | 1754 | then throw(("Currently max infrastructure level = " + toString(maxInfra))) | |
1840 | 1755 | else { | |
1841 | 1756 | let cost = fraction(InfraUpgradeCostSUsdt, (pieces * newLevel), SSIZE) | |
1842 | 1757 | if (if (!(shouldUseMat)) | |
1843 | 1758 | then (paymentAmount != cost) | |
1844 | 1759 | else false) | |
1845 | 1760 | then throw(("Payment attached should be " + toString(cost))) | |
1846 | 1761 | else { | |
1847 | 1762 | let bpKey = keyBackpackByDuck(c._1) | |
1848 | 1763 | let currentPack = getBackpack(bpKey) | |
1849 | 1764 | let mList = split(currentPack[bpIdxMat], "_") | |
1850 | 1765 | let matUsed = fraction(InfraUpgradeCostS, (pieces * newLevel), SSIZE) | |
1851 | 1766 | let newMat = makeString(subtractMaterials(shouldUseMat, mList, matUsed), "_") | |
1852 | 1767 | let claimResult = claimAll(addr, c._2, pieces, claimModeWhThenDuck) | |
1853 | 1768 | let whData = claimResult._5 | |
1854 | 1769 | let oldVol = getWarehouseTotalVolume(whData[whIdxLevels]) | |
1855 | 1770 | let newVolData = makeString([split(whData[whIdxLevels], "_")[0], toString(newLevel)], "_") | |
1856 | 1771 | let newVol = getWarehouseTotalVolume(newVolData) | |
1857 | 1772 | let loft = split(whData[whIdxLOFT], "_") | |
1858 | 1773 | let newLoftStr = makeString([loft[volLocked], loft[volOccupied], toString(((parseIntValue(loft[volFree]) + newVol) - oldVol)), toString(newVol)], "_") | |
1859 | 1774 | $Tuple3(([IntegerEntry(infraKey, newLevel), IntegerEntry(keyInfraLevelByAssetIdAndOwner(c._2, addr), newLevel), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], claimResult._3[bpIdxRes], newMat, currentPack[bpIdxProd]], ":")), StringEntry(claimResult._4, makeString([newVolData, whData[whIdxRes], whData[whIdxMat], whData[whIdxProd], newLoftStr], ":"))] ++ claimResult._1), newLevel, matUsed) | |
1860 | 1775 | } | |
1861 | 1776 | } | |
1862 | 1777 | } | |
1863 | 1778 | } | |
1864 | 1779 | ||
1865 | 1780 | ||
1866 | 1781 | func updateStatsInternal (lvlKey,xpKey,pointsKey,deltaXP) = { | |
1867 | 1782 | let xp = valueOrElse(getInteger(xpKey), 0) | |
1868 | 1783 | let newXP = (xp + deltaXP) | |
1869 | 1784 | let lvlPoints = levelUp(valueOrElse(getInteger(lvlKey), 0), newXP) | |
1870 | 1785 | $Tuple2([IntegerEntry(lvlKey, lvlPoints[0]), IntegerEntry(xpKey, newXP), IntegerEntry(pointsKey, (valueOrElse(getInteger(pointsKey), 0) + lvlPoints[1]))], newXP) | |
1871 | 1786 | } | |
1872 | 1787 | ||
1873 | 1788 | ||
1874 | 1789 | func updateDuckStatsInternal (duckAssetId,deltaXP) = { | |
1875 | 1790 | let asset = value(assetInfo(fromBase58String(duckAssetId))) | |
1876 | 1791 | let addr = valueOrErrorMessage(getString(keyDuckIdToOwner(duckAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
1877 | 1792 | if (if (if (KS_ALLOW_ROBO_DUCKS) | |
1878 | 1793 | then (asset.issuer == this) | |
1879 | 1794 | else false) | |
1880 | 1795 | then contains(asset.name, ROBO_PREFIX) | |
1881 | 1796 | else false) | |
1882 | 1797 | then updateStatsInternal(keyUserLevel(addr), keyUserXP(addr), keyUserFreePoints(addr), deltaXP) | |
1883 | 1798 | else updateStatsInternal(keyDuckLevel(duckAssetId), keyDuckXP(duckAssetId), keyDuckFreePoints(duckAssetId), deltaXP) | |
1884 | 1799 | } | |
1885 | 1800 | ||
1886 | 1801 | ||
1887 | 1802 | func updateAccStatsInternal (addr,deltaXP) = updateStatsInternal(keyUserLevel(addr), keyUserXP(addr), keyUserFreePoints(addr), deltaXP) | |
1888 | 1803 | ||
1889 | 1804 | ||
1890 | 1805 | func activateOnboardArt (addr) = { | |
1891 | 1806 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1892 | 1807 | let refByKey = keyAddressRefBy(addr) | |
1893 | 1808 | let refBy = getString(refByKey) | |
1894 | 1809 | if (!(isDefined(refBy))) | |
1895 | 1810 | then throw("You are not eligible for ONBOARD artifact") | |
1896 | 1811 | else { | |
1897 | 1812 | let artKey = keyOnboardArtDuckActivatedBy(addr) | |
1898 | 1813 | let artDuck = getString(artKey) | |
1899 | 1814 | if (isDefined(artDuck)) | |
1900 | 1815 | then throw(("You already used your ONBOARD artifact on duck " + value(artDuck))) | |
1901 | 1816 | else { | |
1902 | 1817 | let duckActivatorKey = keyOnboardArtActivatedOnDuck(duckAssetId) | |
1903 | 1818 | let duckActivator = getString(duckActivatorKey) | |
1904 | 1819 | if (isDefined(duckActivator)) | |
1905 | 1820 | then throw(((("The duck " + duckAssetId) + " already got points from ONBOARD artifact from user ") + value(duckActivator))) | |
1906 | 1821 | else ([StringEntry(artKey, duckAssetId), StringEntry(duckActivatorKey, addr)] ++ updateDuckStatsInternal(duckAssetId, xpOnboard)._1) | |
1907 | 1822 | } | |
1908 | 1823 | } | |
1909 | 1824 | } | |
1910 | 1825 | ||
1911 | 1826 | ||
1912 | 1827 | func activatePresaleArt (addr,landAssetIdIn) = { | |
1913 | 1828 | let c = checkClaimConditions(addr, claimModeWhThenDuck, landAssetIdIn) | |
1914 | 1829 | let landAssetId = c._2 | |
1915 | 1830 | let pieces = numPiecesBySize(c._3[recLandSize]) | |
1916 | 1831 | let activationKey = keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId) | |
1917 | 1832 | if ((valueOrElse(getInteger(activationKey), 0) > 0)) | |
1918 | 1833 | then throw("Presale artifact is already activated") | |
1919 | 1834 | else if ((parseIntValue(c._3[recLandNum]) > PRESALENUMLANDS)) | |
1920 | 1835 | then throw((((LANDPREFIX + " ") + landAssetId) + " is not eligible for presale artifact")) | |
1921 | 1836 | else { | |
1922 | 1837 | let claimResult = claimAll(addr, landAssetId, pieces, claimModeWhThenDuck) | |
1923 | 1838 | (((claimResult._1 :+ IntegerEntry(activationKey, pieces)) :+ StringEntry(claimResult._2, makeString(claimResult._3, ":"))) :+ StringEntry(claimResult._4, makeString(claimResult._5, ":"))) | |
1924 | 1839 | } | |
1925 | 1840 | } | |
1926 | 1841 | ||
1927 | 1842 | ||
1928 | 1843 | func checkTournament (duckAssetId) = { | |
1929 | 1844 | let lastId = valueOrElse(getInteger(tournamentContract, lastTourIdKey), 0) | |
1930 | 1845 | let curLocation = split(valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_") | |
1931 | 1846 | let now = lastBlock.timestamp | |
1932 | 1847 | let tData = getTourData(tournamentContract, lastId) | |
1933 | 1848 | let static = tData[idxStatic] | |
1934 | 1849 | let dynamic = tData[idxDynamic] | |
1935 | 1850 | if ((curLocation[locIdxType] != "T")) | |
1936 | 1851 | then false | |
1937 | 1852 | else if (if (if ((parseIntValue(curLocation[locIdxContinent]) == lastId)) | |
1938 | 1853 | then (dynamic[tDynamicStatus] == "INPROGRESS") | |
1939 | 1854 | else false) | |
1940 | 1855 | then (parseIntValue(static[tStaticEnd]) > now) | |
1941 | 1856 | else false) | |
1942 | 1857 | then throw("Your duck is taking part in the tournament") | |
1943 | 1858 | else asBoolean(invoke(this, "exitTournamentInternal", [duckAssetId], nil)) | |
1944 | 1859 | } | |
1945 | 1860 | ||
1946 | 1861 | ||
1947 | 1862 | func mergeInternal (newLandSize,newLevel,formula,addr,landAssetIds,needMat) = { | |
1948 | 1863 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1949 | 1864 | if (checkTournament(duckAssetId)) | |
1950 | 1865 | then throw("mergeInternal_checkTournament") | |
1951 | 1866 | else { | |
1952 | 1867 | func checkMerge (acc,landAssetId) = { | |
1953 | 1868 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
1954 | 1869 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1955 | 1870 | let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked")) | |
1956 | 1871 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
1957 | 1872 | if ((owner != addr)) | |
1958 | 1873 | then throw((LANDPREFIX + " is not yours")) | |
1959 | 1874 | else { | |
1960 | 1875 | let d = split(asset.description, "_") | |
1961 | 1876 | let continent = d[recContinent] | |
1962 | 1877 | if (if ((acc._3 != "")) | |
1963 | 1878 | then (acc._3 != continent) | |
1964 | 1879 | else false) | |
1965 | 1880 | then throw("Lands should be on the same continent to merge") | |
1966 | 1881 | else { | |
1967 | 1882 | let landSize = d[recLandSize] | |
1968 | 1883 | let sizesIn = acc._1 | |
1969 | 1884 | let i = valueOrErrorMessage(indexOf(sizesIn, landSize), "You haven't passed all the lands needed") | |
1970 | 1885 | let sizesOut = (take(sizesIn, i) + drop(sizesIn, (i + 1))) | |
1971 | 1886 | let pieces = numPiecesBySize(landSize) | |
1972 | 1887 | let arts = (acc._2 + valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0)) | |
1973 | 1888 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1974 | 1889 | let reqLevel = match landSize { | |
1975 | 1890 | case _ => | |
1976 | 1891 | if (("S" == $match0)) | |
1977 | 1892 | then 3 | |
1978 | 1893 | else if (("M" == $match0)) | |
1979 | 1894 | then 4 | |
1980 | 1895 | else if (("L" == $match0)) | |
1981 | 1896 | then 5 | |
1982 | 1897 | else if (("XL" == $match0)) | |
1983 | 1898 | then 6 | |
1984 | 1899 | else throw("Only S, M, L, XL can merge") | |
1985 | 1900 | } | |
1986 | 1901 | if ((infraLevel != reqLevel)) | |
1987 | 1902 | then throw("All lands should be maxed to merge") | |
1988 | 1903 | else { | |
1989 | 1904 | let landNum = d[recLandNum] | |
1990 | 1905 | let terrainCounts = countTerrains(d[recTerrains]) | |
1991 | 1906 | let deltaTime = (lastBlock.timestamp - savedTime) | |
1992 | 1907 | if ((0 > deltaTime)) | |
1993 | 1908 | then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp))) | |
1994 | 1909 | else { | |
1995 | 1910 | let dailyProductionByPiece = applyBonuses(landAssetId, pieces) | |
1996 | 1911 | let landIndex = (pieces / SSIZE) | |
1997 | 1912 | let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, landIndex, dailyProductionByPiece) | |
1998 | 1913 | let props = updateProportionsInternal(acc._6, terrainCounts, landIndex, -1) | |
1999 | 1914 | let cProps = updateProportionsInternal(acc._10, terrainCounts, landIndex, -1) | |
2000 | 1915 | let sumTerrains = updateProportionsInternal(acc._9, terrainCounts, landIndex, 1) | |
2001 | 1916 | let lands = acc._7 | |
2002 | 1917 | let idx = indexOf(lands, landAssetId) | |
2003 | 1918 | if (!(isDefined(idx))) | |
2004 | 1919 | then throw(("Your staked lands don't contain " + landAssetId)) | |
2005 | 1920 | else { | |
2006 | 1921 | let customKey = keyLandAssetIdToCustomName(landAssetId) | |
2007 | 1922 | let customName = valueOrElse(getString(customKey), "") | |
2008 | 1923 | $Tuple10(sizesOut, arts, continent, bpRes, ((((((((((((acc._5 :+ DeleteEntry(keyStakedTimeByAssetId(landAssetId))) :+ DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr))) :+ DeleteEntry(keyLandToAssetId(landNum))) :+ DeleteEntry(keyLandAssetIdToOwner(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetId(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, addr))) :+ DeleteEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId))) :+ DeleteEntry(keyLandNumToOwner(landNum))) :+ DeleteEntry(keyWarehouseByLand(landAssetId))) :+ DeleteEntry(customKey)) :+ Burn(fromBase58String(landAssetId), 1)) ++ (if ((customName != "")) | |
2009 | 1924 | then [DeleteEntry(keyLandCustomNameToAssetId(customName))] | |
2010 | 1925 | else nil)), props, removeByIndex(lands, value(idx)), (acc._8 + pieces), sumTerrains, cProps) | |
2011 | 1926 | } | |
2012 | 1927 | } | |
2013 | 1928 | } | |
2014 | 1929 | } | |
2015 | 1930 | } | |
2016 | 1931 | } | |
2017 | 1932 | ||
2018 | 1933 | let bpKey = keyBackpackByDuck(duckAssetId) | |
2019 | 1934 | let currentPack = getBackpack(bpKey) | |
2020 | 1935 | let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_") | |
2021 | 1936 | let landsKey = keyStakedLandsByOwner(addr) | |
2022 | 1937 | let landsStr = getString(landsKey) | |
2023 | 1938 | let landsIn = if (isDefined(landsStr)) | |
2024 | 1939 | then split_51C(value(landsStr), "_") | |
2025 | 1940 | else nil | |
2026 | 1941 | let cont0 = split(value(assetInfo(fromBase58String(landAssetIds[0]))).description, "_")[recContinent] | |
2027 | 1942 | let contProps = split(valueOrElse(getString(keyResTypesByContinent(cont0)), "0_0_0_0_0_0"), "_") | |
2028 | 1943 | let r = { | |
2029 | 1944 | let $l = landAssetIds | |
2030 | 1945 | let $s = size($l) | |
2031 | 1946 | let $acc0 = $Tuple10(formula, 0, "", currentPack[bpIdxRes], nil, propList, landsIn, 0, split("0_0_0_0_0_0", "_"), contProps) | |
2032 | 1947 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
2033 | 1948 | then $a | |
2034 | 1949 | else checkMerge($a, $l[$i]) | |
2035 | 1950 | ||
2036 | 1951 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
2037 | 1952 | then $a | |
2038 | 1953 | else throw("List size exceeds 5") | |
2039 | 1954 | ||
2040 | 1955 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
2041 | 1956 | } | |
2042 | 1957 | let continent = r._3 | |
2043 | 1958 | let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent)) | |
2044 | 1959 | let terrains = genTerrainsForMerge(r._9, (numPiecesBySize(newLandSize) / SSIZE)) | |
2045 | 1960 | let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1)) | |
2046 | 1961 | let newLandNum = toString(freeNum) | |
2047 | 1962 | let issue = Issue(nftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false) | |
2048 | 1963 | let assetId = calculateAssetId(issue) | |
2049 | 1964 | let newLandAssetId = toBase58String(assetId) | |
2050 | 1965 | let newMat = makeString(subtractMaterials((needMat > 0), split(currentPack[bpIdxMat], "_"), needMat), "_") | |
2051 | 1966 | let piecesKey = keyStakedPiecesByOwner(addr) | |
2052 | 1967 | let stakedPieces = valueOrElse(getInteger(piecesKey), 0) | |
2053 | 1968 | $Tuple2((((((((((((((((r._5 :+ (if ((size(r._7) > 0)) | |
2054 | 1969 | then StringEntry(landsKey, makeString_11C(r._7, "_")) | |
2055 | 1970 | else DeleteEntry(landsKey))) :+ IntegerEntry(piecesKey, if ((r._8 > stakedPieces)) | |
2056 | 1971 | then 0 | |
2057 | 1972 | else (stakedPieces - r._8))) :+ IntegerEntry(keyNextFreeLandNum(), (freeNum + 1))) :+ issue) :+ StringEntry(keyLandToAssetId(newLandNum), newLandAssetId)) :+ StringEntry(keyLandAssetIdToOwner(newLandAssetId), addr)) :+ StringEntry(keyLandNumToOwner(newLandNum), addr)) :+ IntegerEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, newLandAssetId), r._2)) :+ IntegerEntry(keyInfraLevelByAssetId(newLandAssetId), newLevel)) :+ IntegerEntry(keyInfraLevelByAssetIdAndOwner(newLandAssetId, addr), newLevel)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], r._4, newMat, currentPack[bpIdxProd]], ":"))) :+ StringEntry(keyResProportions(), makeString(r._6, "_"))) :+ StringEntry(keyResTypesByContinent(continent), makeString(r._10, "_"))) :+ StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", newLandAssetId], "_"))) :+ ScriptTransfer(addressFromStringValue(addr), 1, assetId)), newLandAssetId) | |
2058 | 1973 | } | |
2059 | 1974 | } | |
2060 | 1975 | ||
2061 | 1976 | ||
2062 | 1977 | func s2m (addr,landAssetIds) = mergeInternal("M", 3, "SSSS", addr, landAssetIds, 0) | |
2063 | 1978 | ||
2064 | 1979 | ||
2065 | 1980 | func m2l (addr,landAssetIds) = mergeInternal("L", 4, "SMM", addr, landAssetIds, (InfraUpgradeCostS * 4)) | |
2066 | 1981 | ||
2067 | 1982 | ||
2068 | 1983 | func l2xl (addr,landAssetIds) = mergeInternal("XL", 5, "SSSML", addr, landAssetIds, (InfraUpgradeCostS * 47)) | |
2069 | 1984 | ||
2070 | 1985 | ||
2071 | 1986 | func xl2xxl (addr,landAssetIds) = mergeInternal("XXL", 6, "LXL", addr, landAssetIds, (InfraUpgradeCostS * 54)) | |
2072 | 1987 | ||
2073 | 1988 | ||
2074 | 1989 | func mergeCommon (addr,landAssetIds) = match size(landAssetIds) { | |
2075 | 1990 | case _ => | |
2076 | 1991 | if ((4 == $match0)) | |
2077 | 1992 | then s2m(addr, landAssetIds) | |
2078 | 1993 | else if ((3 == $match0)) | |
2079 | 1994 | then m2l(addr, landAssetIds) | |
2080 | 1995 | else if ((5 == $match0)) | |
2081 | 1996 | then l2xl(addr, landAssetIds) | |
2082 | 1997 | else if ((2 == $match0)) | |
2083 | 1998 | then xl2xxl(addr, landAssetIds) | |
2084 | 1999 | else throw("Unknown merge") | |
2085 | 2000 | } | |
2086 | 2001 | ||
2087 | 2002 | ||
2088 | 2003 | func prolog (i) = if (if ((i.originCaller != restContract)) | |
2089 | 2004 | then valueOrElse(getBoolean(keyBlocked()), false) | |
2090 | 2005 | else false) | |
2091 | 2006 | then throw("Contracts are under maintenance") | |
2092 | 2007 | else [StringEntry(keyLastTxIdByUser(toString(i.originCaller)), toBase58String(i.transactionId))] | |
2093 | 2008 | ||
2094 | 2009 | ||
2095 | 2010 | @Callable(i) | |
2096 | 2011 | func constructorV1 (restAddr) = if ((i.caller != this)) | |
2097 | 2012 | then throw("Permission denied") | |
2098 | 2013 | else [StringEntry(keyRestAddress(), restAddr)] | |
2099 | 2014 | ||
2100 | 2015 | ||
2101 | 2016 | ||
2102 | 2017 | @Callable(i) | |
2103 | 2018 | func saveInteger (key,amount) = if ((i.caller != this)) | |
2104 | 2019 | then throw("saveInteger is not public method") | |
2105 | 2020 | else [IntegerEntry(key, amount)] | |
2106 | 2021 | ||
2107 | 2022 | ||
2108 | 2023 | ||
2109 | 2024 | @Callable(i) | |
2110 | 2025 | func setBlocked (isBlocked) = if ((i.caller != this)) | |
2111 | 2026 | then throw("permission denied") | |
2112 | 2027 | else [BooleanEntry(keyBlocked(), isBlocked)] | |
2113 | 2028 | ||
2114 | 2029 | ||
2115 | 2030 | ||
2116 | 2031 | @Callable(i) | |
2117 | 2032 | func stakeLand () = { | |
2118 | 2033 | let prologActions = prolog(i) | |
2119 | 2034 | if ((size(i.payments) != 1)) | |
2120 | 2035 | then throw("Exactly one payment required") | |
2121 | 2036 | else { | |
2122 | 2037 | let pmt = value(i.payments[0]) | |
2123 | 2038 | let assetId = value(pmt.assetId) | |
2124 | 2039 | let address = toString(i.caller) | |
2125 | 2040 | if ((pmt.amount != 1)) | |
2126 | 2041 | then throw((("NFT " + LANDPREFIX) + " token should be attached as payment")) | |
2127 | 2042 | else { | |
2128 | 2043 | let asset = value(assetInfo(assetId)) | |
2129 | 2044 | if ((asset.issuer != this)) | |
2130 | 2045 | then throw("Unknown issuer of token") | |
2131 | 2046 | else if (!(contains(asset.name, LANDPREFIX))) | |
2132 | 2047 | then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted")) | |
2133 | 2048 | else { | |
2134 | 2049 | let landNumSize = drop(asset.name, 4) | |
2135 | 2050 | let landNum = if (contains(landNumSize, "XXL")) | |
2136 | 2051 | then dropRight(landNumSize, 3) | |
2137 | 2052 | else if (contains(landNumSize, "XL")) | |
2138 | 2053 | then dropRight(landNumSize, 2) | |
2139 | 2054 | else dropRight(landNumSize, 1) | |
2140 | 2055 | if (!(isDefined(parseInt(landNum)))) | |
2141 | 2056 | then throw(("Cannot parse land number from " + asset.name)) | |
2142 | 2057 | else { | |
2143 | 2058 | let landAssetId = toBase58String(assetId) | |
2144 | 2059 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
2145 | 2060 | if (isDefined(getInteger(timeKey))) | |
2146 | 2061 | then throw((("NFT " + asset.name) + " is already staked")) | |
2147 | 2062 | else { | |
2148 | 2063 | let d = split(asset.description, "_") | |
2149 | 2064 | let terrainCounts = countTerrains(d[recTerrains]) | |
2150 | 2065 | let pieces = numPiecesBySize(d[recLandSize]) | |
2151 | 2066 | let landIndex = (pieces / SSIZE) | |
2152 | 2067 | let props = updateProportions(terrainCounts, landIndex, 1) | |
2153 | 2068 | let resByContKey = keyResTypesByContinent(d[recContinent]) | |
2154 | 2069 | let contProps = split(valueOrElse(getString(resByContKey), "0_0_0_0_0_0"), "_") | |
2155 | 2070 | let updatedContProps = makeString(updateProportionsInternal(contProps, terrainCounts, landIndex, 1), "_") | |
2156 | 2071 | let landsKey = keyStakedLandsByOwner(address) | |
2157 | 2072 | let landsStr = getString(landsKey) | |
2158 | 2073 | let lands = if (isDefined(landsStr)) | |
2159 | 2074 | then split_51C(value(landsStr), "_") | |
2160 | 2075 | else nil | |
2161 | 2076 | if (containsElement(lands, landAssetId)) | |
2162 | 2077 | then throw(("Your staked lands already contain " + landAssetId)) | |
2163 | 2078 | else if ((size(lands) >= MAX_LANDS_STAKED_BY_USER)) | |
2164 | 2079 | then throw((("Your already staked max (" + toString(MAX_LANDS_STAKED_BY_USER)) + ") lands")) | |
2165 | 2080 | else { | |
2166 | 2081 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
2167 | 2082 | let piecesKey = keyStakedPiecesByOwner(address) | |
2168 | 2083 | let oldPieces = valueOrElse(getInteger(piecesKey), 0) | |
2169 | 2084 | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [address], nil) | |
2170 | 2085 | $Tuple2(([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(landsKey, makeString_11C((lands :+ landAssetId), "_")), IntegerEntry(piecesKey, (oldPieces + pieces)), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), IntegerEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, address), infraLevel), StringEntry(keyResProportions(), props), StringEntry(resByContKey, updatedContProps)] ++ prologActions), wlgResult) | |
2171 | 2086 | } | |
2172 | 2087 | } | |
2173 | 2088 | } | |
2174 | 2089 | } | |
2175 | 2090 | } | |
2176 | 2091 | } | |
2177 | 2092 | } | |
2178 | 2093 | ||
2179 | 2094 | ||
2180 | 2095 | ||
2181 | 2096 | @Callable(i) | |
2182 | 2097 | func unstakeLand (landAssetIdIn) = { | |
2183 | 2098 | let prologActions = prolog(i) | |
2184 | 2099 | if ((size(i.payments) != 0)) | |
2185 | 2100 | then throw("No payments required") | |
2186 | 2101 | else { | |
2187 | 2102 | let addr = toString(i.caller) | |
2188 | 2103 | let c = checkClaimConditions(addr, claimModeDuck, landAssetIdIn) | |
2189 | 2104 | let landAssetId = c._2 | |
2190 | 2105 | let d = c._3 | |
2191 | 2106 | let landsKey = keyStakedLandsByOwner(addr) | |
2192 | 2107 | let terrainCounts = countTerrains(d[recTerrains]) | |
2193 | 2108 | let pieces = numPiecesBySize(d[recLandSize]) | |
2194 | 2109 | let landIndex = (pieces / SSIZE) | |
2195 | 2110 | let props = updateProportions(terrainCounts, landIndex, -1) | |
2196 | 2111 | let resByContKey = keyResTypesByContinent(d[recContinent]) | |
2197 | 2112 | let contProps = split(valueOrElse(getString(resByContKey), "0_0_0_0_0_0"), "_") | |
2198 | 2113 | let updatedContProps = makeString(updateProportionsInternal(contProps, terrainCounts, landIndex, -1), "_") | |
2199 | 2114 | let claimResult = claimAll(addr, landAssetId, pieces, claimModeDuck) | |
2200 | 2115 | let lands = split_51C(valueOrElse(getString(landsKey), ""), "_") | |
2201 | 2116 | let idx = indexOf(lands, landAssetId) | |
2202 | 2117 | if (!(isDefined(idx))) | |
2203 | 2118 | then throw(("Your staked lands don't contain " + landAssetId)) | |
2204 | 2119 | else { | |
2205 | 2120 | let now = lastBlock.timestamp | |
2206 | 2121 | let govReleaseTime = valueOrElse(getInteger(govContract, keyUserGwlReleaseTime(addr)), 0) | |
2207 | 2122 | if ((govReleaseTime >= now)) | |
2208 | 2123 | then throw(("Your gWL are taking part in voting, cannot unstake until " + toString(govReleaseTime))) | |
2209 | 2124 | else { | |
2210 | 2125 | let arbReleaseTime = (valueOrElse(getInteger(wlgContract, keyLastArbTimeByUser(addr)), 0) + arbitrageDelay) | |
2211 | 2126 | if ((arbReleaseTime > now)) | |
2212 | 2127 | then throw(("Your staked lands took part in arbitrage, cannot unstake until " + toString(arbReleaseTime))) | |
2213 | 2128 | else { | |
2214 | 2129 | let piecesKey = keyStakedPiecesByOwner(addr) | |
2215 | 2130 | let stakedPieces = valueOrElse(getInteger(piecesKey), 0) | |
2216 | 2131 | let newPieces = if ((pieces > stakedPieces)) | |
2217 | 2132 | then 0 | |
2218 | 2133 | else (stakedPieces - pieces) | |
2219 | 2134 | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [addr], nil) | |
2220 | 2135 | $Tuple2(([ScriptTransfer(i.caller, 1, fromBase58String(landAssetId)), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr)), StringEntry(keyResProportions(), props), StringEntry(resByContKey, updatedContProps), StringEntry(claimResult._2, makeString(claimResult._3, ":")), if ((size(lands) > 1)) | |
2221 | 2136 | then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_")) | |
2222 | 2137 | else DeleteEntry(landsKey), IntegerEntry(piecesKey, newPieces)] ++ prologActions), wlgResult) | |
2223 | 2138 | } | |
2224 | 2139 | } | |
2225 | 2140 | } | |
2226 | 2141 | } | |
2227 | 2142 | } | |
2228 | 2143 | ||
2229 | 2144 | ||
2230 | 2145 | ||
2231 | 2146 | @Callable(i) | |
2232 | 2147 | func stakeDuck () = { | |
2233 | 2148 | let prologActions = prolog(i) | |
2234 | 2149 | if ((size(i.payments) != 1)) | |
2235 | 2150 | then throw("Exactly one payment required") | |
2236 | 2151 | else { | |
2237 | 2152 | let pmt = value(i.payments[0]) | |
2238 | 2153 | let assetId = value(pmt.assetId) | |
2239 | 2154 | let address = toString(i.caller) | |
2240 | 2155 | if ((pmt.amount != 1)) | |
2241 | 2156 | then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment")) | |
2242 | 2157 | else { | |
2243 | 2158 | let asset = value(assetInfo(assetId)) | |
2244 | 2159 | let isRobo = if (if (KS_ALLOW_ROBO_DUCKS) | |
2245 | 2160 | then (asset.issuer == this) | |
2246 | 2161 | else false) | |
2247 | 2162 | then contains(asset.name, ROBO_PREFIX) | |
2248 | 2163 | else false | |
2249 | 2164 | if (if (if ((asset.issuer != incubatorAddr)) | |
2250 | 2165 | then (asset.issuer != breederAddr) | |
2251 | 2166 | else false) | |
2252 | 2167 | then !(isRobo) | |
2253 | 2168 | else false) | |
2254 | 2169 | then throw((((("Unknown issuer of " + DUCKPREFIX) + " or ") + ROBO_PREFIX) + " token")) | |
2255 | 2170 | else if (if (!(contains(asset.name, DUCKPREFIX))) | |
2256 | 2171 | then !(isRobo) | |
2257 | 2172 | else false) | |
2258 | 2173 | then throw((((("Only NFT " + DUCKPREFIX) + " or ") + ROBO_PREFIX) + " tokens are accepted")) | |
2259 | 2174 | else { | |
2260 | 2175 | let assetIdStr = toBase58String(assetId) | |
2261 | 2176 | let timeKey = keyStakedTimeByAssetId(assetIdStr) | |
2262 | 2177 | if (isDefined(getInteger(timeKey))) | |
2263 | 2178 | then throw((("NFT " + asset.name) + " is already staked")) | |
2264 | 2179 | else if (isDefined(getString(keyStakedDuckByOwner(address)))) | |
2265 | 2180 | then throw(("You already staked one duck: " + asset.name)) | |
2266 | 2181 | else { | |
2267 | 2182 | let locKey = keyDuckLocation(assetIdStr) | |
2268 | 2183 | let location = getString(locKey) | |
2269 | 2184 | let bpKey = keyBackpackByDuck(assetIdStr) | |
2270 | 2185 | let backpack = getString(bpKey) | |
2271 | 2186 | let keyHealth = keyDuckHealth(assetIdStr) | |
2272 | 2187 | let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(assetIdStr)), 0)) | |
2273 | 2188 | let curHealth = valueOrElse(getInteger(keyHealth), maxHP) | |
2274 | 2189 | ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location)) | |
2275 | 2190 | then nil | |
2276 | 2191 | else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack)) | |
2277 | 2192 | then nil | |
2278 | 2193 | else (([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyHealth, curHealth)) ++ prologActions))))) | |
2279 | 2194 | } | |
2280 | 2195 | } | |
2281 | 2196 | } | |
2282 | 2197 | } | |
2283 | 2198 | } | |
2284 | 2199 | ||
2285 | 2200 | ||
2286 | 2201 | ||
2287 | 2202 | @Callable(i) | |
2288 | 2203 | func unstakeDuck (assetIdStr) = { | |
2289 | 2204 | let prologActions = prolog(i) | |
2290 | 2205 | if ((size(i.payments) != 0)) | |
2291 | 2206 | then throw("No payments required") | |
2292 | 2207 | else { | |
2293 | 2208 | let assetId = fromBase58String(assetIdStr) | |
2294 | 2209 | let address = toString(i.caller) | |
2295 | 2210 | let asset = value(assetInfo(assetId)) | |
2296 | 2211 | let timeKey = keyStakedTimeByAssetId(assetIdStr) | |
2297 | 2212 | if (!(isDefined(getInteger(timeKey)))) | |
2298 | 2213 | then throw((("NFT " + asset.name) + " is not staked")) | |
2299 | 2214 | else if (!(isDefined(getString(keyStakedDuckByOwner(address))))) | |
2300 | 2215 | then throw((("The duck " + asset.name) + " is not staked")) | |
2301 | 2216 | else { | |
2302 | 2217 | let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(assetIdStr)), (("NFT " + asset.name) + " is orphaned")) | |
2303 | 2218 | if ((owner != address)) | |
2304 | 2219 | then throw("Staked NFT is not yours") | |
2305 | 2220 | else if (checkTournament(assetIdStr)) | |
2306 | 2221 | then throw("unstakeDuck_checkTournament") | |
2307 | 2222 | else { | |
2308 | 2223 | let keyHealth = keyDuckHealth(assetIdStr) | |
2309 | 2224 | let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(assetIdStr)), 0)) | |
2310 | 2225 | let health = valueOrElse(getInteger(keyHealth), maxHP) | |
2311 | 2226 | if ((maxHP > health)) | |
2312 | 2227 | then throw((("Please heal your duck to " + toString(maxHP)) + "hp before unstaking")) | |
2313 | 2228 | else ([ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))] ++ prologActions) | |
2314 | 2229 | } | |
2315 | 2230 | } | |
2316 | 2231 | } | |
2317 | 2232 | } | |
2318 | 2233 | ||
2319 | 2234 | ||
2320 | 2235 | ||
2321 | 2236 | @Callable(i) | |
2322 | 2237 | func claimRes (amount,landAssetIdStr) = { | |
2323 | 2238 | let prologActions = prolog(i) | |
2324 | 2239 | if ((size(i.payments) != 0)) | |
2325 | 2240 | then throw("No payments required") | |
2326 | 2241 | else { | |
2327 | 2242 | let addr = toString(i.originCaller) | |
2328 | 2243 | let result = claimResInternal(addr, amount, claimModeDuck, landAssetIdStr) | |
2329 | 2244 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
2330 | 2245 | $Tuple2(((((result._1 ++ updateDuckStatsInternal(duckAssetId, fraction(xpClaim, amount, MULT8))._1) :+ StringEntry(result._2, makeString(result._3, ":"))) :+ StringEntry(result._4, makeString(result._5, ":"))) ++ prologActions), result._3[bpIdxRes]) | |
2331 | 2246 | } | |
2332 | 2247 | } | |
2333 | 2248 | ||
2334 | 2249 | ||
2335 | 2250 | ||
2336 | 2251 | @Callable(i) | |
2337 | 2252 | func claimResToWH (amount,landAssetIdStr) = { | |
2338 | 2253 | let prologActions = prolog(i) | |
2339 | 2254 | if ((size(i.payments) != 0)) | |
2340 | 2255 | then throw("No payments required") | |
2341 | 2256 | else { | |
2342 | 2257 | let addr = toString(i.originCaller) | |
2343 | 2258 | let result = claimResInternal(addr, amount, claimModeWh, landAssetIdStr) | |
2344 | 2259 | $Tuple2(((((result._1 ++ updateAccStatsInternal(addr, fraction(xpClaim, amount, MULT8))._1) :+ StringEntry(result._2, makeString(result._3, ":"))) :+ StringEntry(result._4, makeString(result._5, ":"))) ++ prologActions), result._5[whIdxRes]) | |
2345 | 2260 | } | |
2346 | 2261 | } | |
2347 | 2262 | ||
2348 | 2263 | ||
2349 | 2264 | ||
2350 | 2265 | @Callable(i) | |
2351 | 2266 | func flight (message,sig) = { | |
2352 | 2267 | let prologActions = prolog(i) | |
2353 | 2268 | if ((size(i.payments) != 0)) | |
2354 | 2269 | then throw("No payments required") | |
2355 | 2270 | else { | |
2356 | 2271 | let userAddr = toString(i.caller) | |
2357 | 2272 | let f = flightCommon(userAddr, message, sig) | |
2358 | 2273 | let newHP = f._1 | |
2359 | 2274 | let duckAssetId = f._2 | |
2360 | 2275 | let locKey = keyDuckLocation(duckAssetId) | |
2361 | 2276 | let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION) | |
2362 | 2277 | let newLocation = f._4 | |
2363 | 2278 | if ((newLocation == curLocation)) | |
2364 | 2279 | then throw("You can't fly to the same location") | |
2365 | 2280 | else { | |
2366 | 2281 | let newLoc = split(newLocation, "_") | |
2367 | 2282 | let isTour = (newLoc[locIdxType] == "T") | |
2368 | 2283 | let isDeliv = (newLoc[locIdxType] == "D") | |
2369 | 2284 | let eqKey = keyDuckEquipment(duckAssetId) | |
2370 | 2285 | let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,") | |
2371 | - | let $t06603566132 = subtractEquipment(currentEq, f._5) | |
2372 | - | let newEq = $t06603566132._1 | |
2373 | - | let shouldZeroBuffs = $t06603566132._2 | |
2374 | - | let $t06613567967 = if (!(onMission(tournamentContract, curLocation))) | |
2286 | + | let $t06637066476 = subtractEquipment(currentEq, f._5) | |
2287 | + | let newEq = $t06637066476._1 | |
2288 | + | let shouldZeroBuffs = $t06637066476._2 | |
2289 | + | let ignored = $t06637066476._3 | |
2290 | + | let $t06647968311 = if (!(onMission(tournamentContract, curLocation))) | |
2375 | 2291 | then if (isTour) | |
2376 | 2292 | then cheatAttempt(curLocation, newLocation, 5) | |
2377 | 2293 | else if (!(isDeliv)) | |
2378 | 2294 | then if ((newHP > 0)) | |
2379 | 2295 | then $Tuple2(newLocation, newHP) | |
2380 | 2296 | else $Tuple2(curLocation, 0) | |
2381 | 2297 | else if ((newHP > 0)) | |
2382 | 2298 | then { | |
2383 | 2299 | let s = invoke(this, "processDelivery", [duckAssetId], nil) | |
2384 | 2300 | if ((s == s)) | |
2385 | 2301 | then $Tuple2(curLocation, newHP) | |
2386 | 2302 | else throw("Strict value is not equal to itself.") | |
2387 | 2303 | } | |
2388 | 2304 | else $Tuple2(curLocation, 0) | |
2389 | 2305 | else if (isInTournament(tournamentContract, curLocation)) | |
2390 | 2306 | then if (!(isInTournament(tournamentContract, newLocation))) | |
2391 | 2307 | then throw("Your duck is taking part in the tournament") | |
2392 | 2308 | else { | |
2393 | 2309 | let score = parseIntValue(newLoc[locIdxId]) | |
2394 | 2310 | let curLoc = split(curLocation, "_") | |
2395 | 2311 | let lastId = valueOrElse(getInteger(tournamentContract, lastTourIdKey), 0) | |
2396 | 2312 | if ((score != (parseIntValue(curLoc[locIdxId]) + 1))) | |
2397 | 2313 | then cheatAttempt(curLocation, newLocation, 7) | |
2398 | 2314 | else if ((newHP > 0)) | |
2399 | 2315 | then { | |
2400 | 2316 | let localBest = valueOrElse(getInteger(tournamentContract, keyBestResultByTourAndDuck(lastId, duckAssetId)), 0) | |
2401 | 2317 | let updLocal = if ((score > localBest)) | |
2402 | 2318 | then invoke(tournamentContract, "saveDuckResult", [duckAssetId, score], nil) | |
2403 | 2319 | else unit | |
2404 | 2320 | if ((updLocal == updLocal)) | |
2405 | 2321 | then $Tuple2(newLocation, newHP) | |
2406 | 2322 | else throw("Strict value is not equal to itself.") | |
2407 | 2323 | } | |
2408 | 2324 | else $Tuple2(curLocation, 0) | |
2409 | 2325 | } | |
2410 | 2326 | else throw(("Unknown curLocation:" + curLocation)) | |
2411 | - | let locToSave = $ | |
2412 | - | let hpToSave = $ | |
2327 | + | let locToSave = $t06647968311._1 | |
2328 | + | let hpToSave = $t06647968311._2 | |
2413 | 2329 | $Tuple2(((([StringEntry(locKey, locToSave), StringEntry(eqKey, newEq), IntegerEntry(keyDuckHealth(duckAssetId), hpToSave)] ++ prologActions) ++ (if (shouldZeroBuffs) | |
2414 | 2330 | then [StringEntry(keyDuckBuffs(duckAssetId), "0_0_0_0_0")] | |
2415 | 2331 | else nil)) ++ updateDuckStatsInternal(duckAssetId, if ((newHP > 0)) | |
2416 | 2332 | then xpSuccessFlight | |
2417 | 2333 | else xpFailFlight)._1), f._3) | |
2418 | 2334 | } | |
2419 | 2335 | } | |
2420 | 2336 | } | |
2421 | 2337 | ||
2422 | 2338 | ||
2423 | 2339 | ||
2424 | 2340 | @Callable(i) | |
2425 | 2341 | func heal (quantityL1,quantityL2,quantityL3) = { | |
2426 | 2342 | let prologActions = prolog(i) | |
2427 | 2343 | if (if (if ((0 > quantityL1)) | |
2428 | 2344 | then true | |
2429 | 2345 | else (0 > quantityL2)) | |
2430 | 2346 | then true | |
2431 | 2347 | else (0 > quantityL3)) | |
2432 | 2348 | then throw("Quantity cannot be negative") | |
2433 | 2349 | else { | |
2434 | 2350 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
2435 | 2351 | if (checkTournament(duckAssetId)) | |
2436 | 2352 | then throw("heal_checkTournament") | |
2437 | 2353 | else { | |
2438 | 2354 | let qts = [quantityL1, quantityL2, quantityL3] | |
2439 | 2355 | let keyHealth = keyDuckHealth(duckAssetId) | |
2440 | 2356 | let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0)) | |
2441 | 2357 | let oldHealth = valueOrElse(getInteger(keyHealth), maxHP) | |
2442 | 2358 | if ((oldHealth >= maxHP)) | |
2443 | 2359 | then throw((("HP should be < " + toString(maxHP)) + " to heal")) | |
2444 | 2360 | else { | |
2445 | 2361 | let bpKey = keyBackpackByDuck(duckAssetId) | |
2446 | 2362 | let currentPack = getBackpack(bpKey) | |
2447 | 2363 | let prodList = if ((currentPack[bpIdxProd] == "")) | |
2448 | 2364 | then nil | |
2449 | 2365 | else split_4C(currentPack[bpIdxProd], "_") | |
2450 | 2366 | func iterateProd (acc,recipe) = { | |
2451 | 2367 | let n = acc._2 | |
2452 | 2368 | let x = if ((size(prodList) > n)) | |
2453 | 2369 | then parseIntValue(prodList[n]) | |
2454 | 2370 | else 0 | |
2455 | 2371 | if ((3 > n)) | |
2456 | 2372 | then { | |
2457 | 2373 | let q = qts[n] | |
2458 | 2374 | if ((q > x)) | |
2459 | 2375 | then throw(((("You have only " + toString(x)) + " of ") + prodTypes[n])) | |
2460 | 2376 | else $Tuple3((acc._1 :+ toString((x - q))), (n + 1), (acc._3 + (parseIntValue(split(recipe, "_")[rIdxEffect]) * q))) | |
2461 | 2377 | } | |
2462 | 2378 | else $Tuple3((acc._1 :+ toString(x)), (n + 1), acc._3) | |
2463 | 2379 | } | |
2464 | 2380 | ||
2465 | 2381 | let result = { | |
2466 | 2382 | let $l = productionMatrix | |
2467 | 2383 | let $s = size($l) | |
2468 | 2384 | let $acc0 = $Tuple3(nil, 0, 0) | |
2469 | 2385 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
2470 | 2386 | then $a | |
2471 | 2387 | else iterateProd($a, $l[$i]) | |
2472 | 2388 | ||
2473 | 2389 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
2474 | 2390 | then $a | |
2475 | 2391 | else throw("List size exceeds 50") | |
2476 | 2392 | ||
2477 | 2393 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 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) | |
2478 | 2394 | } | |
2479 | 2395 | let newHealth = min([maxHP, (oldHealth + result._3)]) | |
2480 | 2396 | $Tuple2((([IntegerEntry(keyHealth, newHealth), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], makeString(result._1, "_")], ":"))] ++ prologActions) ++ updateDuckStatsInternal(duckAssetId, (xpHeal * ((quantityL1 + quantityL2) + quantityL3)))._1), newHealth) | |
2481 | 2397 | } | |
2482 | 2398 | } | |
2483 | 2399 | } | |
2484 | 2400 | } | |
2485 | 2401 | ||
2486 | 2402 | ||
2487 | 2403 | ||
2488 | 2404 | @Callable(i) | |
2489 | 2405 | func healES () = { | |
2490 | 2406 | let prologActions = prolog(i) | |
2491 | 2407 | if ((size(i.payments) != 1)) | |
2492 | 2408 | then throw("Exactly one payment required") | |
2493 | 2409 | else { | |
2494 | 2410 | let pmt = value(i.payments[0]) | |
2495 | 2411 | if ((pmt.assetId != usdtAssetId)) | |
2496 | 2412 | then throw("Allowed USDT payment only!") | |
2497 | 2413 | else { | |
2498 | 2414 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
2499 | 2415 | if (checkTournament(duckAssetId)) | |
2500 | 2416 | then throw("healES_checkTournament") | |
2501 | 2417 | else { | |
2502 | 2418 | let keyHealth = keyDuckHealth(duckAssetId) | |
2503 | 2419 | let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0)) | |
2504 | 2420 | let oldHealth = valueOrElse(getInteger(keyHealth), maxHP) | |
2505 | 2421 | if ((oldHealth > 0)) | |
2506 | 2422 | then throw("HP should be 0 to call Emergency Service") | |
2507 | 2423 | else { | |
2508 | 2424 | let bpKey = keyBackpackByDuck(duckAssetId) | |
2509 | 2425 | let currentPack = getBackpack(bpKey) | |
2510 | 2426 | let prodList = if ((currentPack[bpIdxProd] == "")) | |
2511 | 2427 | then nil | |
2512 | 2428 | else split_4C(currentPack[bpIdxProd], "_") | |
2513 | 2429 | let medKitAmount1 = if ((size(prodList) > 0)) | |
2514 | 2430 | then parseIntValue(prodList[0]) | |
2515 | 2431 | else 0 | |
2516 | 2432 | let medKitAmount2 = if ((size(prodList) > 1)) | |
2517 | 2433 | then parseIntValue(prodList[1]) | |
2518 | 2434 | else 0 | |
2519 | 2435 | let medKitAmount3 = if ((size(prodList) > 2)) | |
2520 | 2436 | then parseIntValue(prodList[2]) | |
2521 | 2437 | else 0 | |
2522 | 2438 | if (if (if ((medKitAmount1 > 0)) | |
2523 | 2439 | then true | |
2524 | 2440 | else (medKitAmount2 > 0)) | |
2525 | 2441 | then true | |
2526 | 2442 | else (medKitAmount3 > 0)) | |
2527 | 2443 | then throw("You have to use own Medical Kit") | |
2528 | 2444 | else { | |
2529 | 2445 | let existStr = getString(economyContract, keyEsWarehouse()) | |
2530 | 2446 | let existAmounts = if (isDefined(existStr)) | |
2531 | 2447 | then split_4C(value(existStr), "_") | |
2532 | 2448 | else nil | |
2533 | 2449 | let existAmount = if ((size(existAmounts) > 0)) | |
2534 | 2450 | then parseIntValue(existAmounts[0]) | |
2535 | 2451 | else 0 | |
2536 | 2452 | if ((0 >= existAmount)) | |
2537 | 2453 | then throw("There are no Medical Kits L1 at Emergency Service storage") | |
2538 | 2454 | else { | |
2539 | 2455 | let newHealth = (oldHealth + parseIntValue(split(productionMatrix[0], "_")[rIdxEffect])) | |
2540 | 2456 | let newES = makeString([toString((existAmount - 1)), removeByIndex(existAmounts, 0)], "_") | |
2541 | 2457 | let recipe = split(productionMatrix[0], "_") | |
2542 | 2458 | let totalMat = getRecipeMaterials(recipe) | |
2543 | 2459 | let sellPrice = fraction((totalMat * ESSELLCOEF), RESOURCEPRICEMIN, (MULT8 * PRODUCTPKGSIZE)) | |
2544 | 2460 | if ((pmt.amount != sellPrice)) | |
2545 | 2461 | then throw(("Payment attached should be " + toString(sellPrice))) | |
2546 | 2462 | else { | |
2547 | 2463 | let result = asString(invoke(economyContract, "updateEsStorage", [newES], [AttachedPayment(usdtAssetId, sellPrice)])) | |
2548 | 2464 | $Tuple2(((prologActions :+ IntegerEntry(keyHealth, newHealth)) ++ updateDuckStatsInternal(duckAssetId, xpCallES)._1), result) | |
2549 | 2465 | } | |
2550 | 2466 | } | |
2551 | 2467 | } | |
2552 | 2468 | } | |
2553 | 2469 | } | |
2554 | 2470 | } | |
2555 | 2471 | } | |
2556 | 2472 | } | |
2557 | 2473 | ||
2558 | 2474 | ||
2559 | 2475 | ||
2560 | 2476 | @Callable(i) | |
2561 | 2477 | func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyContract)) | |
2562 | 2478 | then throw("permission denied") | |
2563 | 2479 | else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack) | |
2564 | 2480 | ||
2565 | 2481 | ||
2566 | 2482 | ||
2567 | 2483 | @Callable(i) | |
2568 | 2484 | func commitForRandom () = { | |
2569 | 2485 | let prologActions = prolog(i) | |
2570 | 2486 | let finishBlock = (height + randomDelay) | |
2571 | 2487 | let addr = toString(i.caller) | |
2572 | 2488 | $Tuple2(([IntegerEntry(keyCommit(addr), finishBlock)] ++ prologActions), finishBlock) | |
2573 | 2489 | } | |
2574 | 2490 | ||
2575 | 2491 | ||
2576 | 2492 | ||
2577 | 2493 | @Callable(i) | |
2578 | 2494 | func revealRandom (maxValue) = { | |
2579 | 2495 | let prologActions = prolog(i) | |
2580 | 2496 | let addr = toString(i.caller) | |
2581 | 2497 | let finishKey = keyCommit(addr) | |
2582 | 2498 | let finishBlock = valueOrErrorMessage(getInteger(finishKey), "You have to commitForRandom() first!") | |
2583 | 2499 | if ((finishBlock > height)) | |
2584 | 2500 | then throw(("Random number is not ready yet, wait until height = " + toString(finishBlock))) | |
2585 | 2501 | else { | |
2586 | 2502 | let entropy = value(value(blockInfoByHeight(finishBlock)).vrf) | |
2587 | 2503 | let salt = toBytes(valueOrElse(getString(keyLastTxIdByUser(addr)), "")) | |
2588 | 2504 | let rand = getRandomNumber(maxValue, salt, entropy) | |
2589 | 2505 | $Tuple2(([DeleteEntry(finishKey)] ++ prologActions), rand) | |
2590 | 2506 | } | |
2591 | 2507 | } | |
2592 | 2508 | ||
2593 | 2509 | ||
2594 | 2510 | ||
2595 | 2511 | @Callable(i) | |
2596 | 2512 | func buySLand () = { | |
2597 | 2513 | let prologActions = prolog(i) | |
2598 | 2514 | if ((size(i.payments) != 1)) | |
2599 | 2515 | then throw("Exactly one payment required") | |
2600 | 2516 | else { | |
2601 | 2517 | let pmt = value(i.payments[0]) | |
2602 | 2518 | if ((pmt.assetId != usdtAssetId)) | |
2603 | 2519 | then throw("Allowed USDT payment only!") | |
2604 | 2520 | else if ((pmt.amount != EXPUSDT)) | |
2605 | 2521 | then throw(("Payment attached should be " + toString(EXPUSDT))) | |
2606 | 2522 | else { | |
2607 | 2523 | let result = expeditionInternal(i.caller, i.transactionId) | |
2608 | 2524 | let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], nil)) | |
2609 | 2525 | $Tuple2((((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) ++ updateAccStatsInternal(toString(i.caller), xpNewSLand)._1) ++ prologActions), $Tuple2(result._2._1, acresResult)) | |
2610 | 2526 | } | |
2611 | 2527 | } | |
2612 | 2528 | } | |
2613 | 2529 | ||
2614 | 2530 | ||
2615 | 2531 | ||
2616 | 2532 | @Callable(i) | |
2617 | 2533 | func expedition (message,sig) = { | |
2618 | 2534 | let prologActions = prolog(i) | |
2619 | 2535 | if ((size(i.payments) != 0)) | |
2620 | 2536 | then throw("No payments required") | |
2621 | 2537 | else { | |
2622 | 2538 | let userAddr = toString(i.caller) | |
2623 | 2539 | let f = flightCommon(userAddr, message, sig) | |
2624 | 2540 | let duckAssetId = f._2 | |
2625 | 2541 | let keyHealth = keyDuckHealth(duckAssetId) | |
2626 | 2542 | let bpKey = keyBackpackByDuck(duckAssetId) | |
2627 | 2543 | let currentPack = getBackpack(bpKey) | |
2628 | 2544 | let mList = split(currentPack[bpIdxMat], "_") | |
2629 | 2545 | let newMat = makeString(subtractMaterials(true, mList, EXPMATERIALS), "_") | |
2630 | 2546 | let eqKey = keyDuckEquipment(duckAssetId) | |
2631 | 2547 | let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,") | |
2632 | - | let $t07588775984 = subtractEquipment(currentEq, f._5) | |
2633 | - | let newEq = $t07588775984._1 | |
2634 | - | let shouldZeroBuffs = $t07588775984._2 | |
2548 | + | let $t07623176337 = subtractEquipment(currentEq, f._5) | |
2549 | + | let newEq = $t07623176337._1 | |
2550 | + | let shouldZeroBuffs = $t07623176337._2 | |
2551 | + | let ignored = $t07623176337._3 | |
2635 | 2552 | let e = expeditionInternal(i.caller, i.transactionId) | |
2636 | 2553 | let id = e._2._1 | |
2637 | 2554 | let result = if ((0 >= f._1)) | |
2638 | 2555 | then $Tuple3([IntegerEntry(keyHealth, 0), StringEntry(eqKey, newEq)], "", 0) | |
2639 | 2556 | else $Tuple3((e._1 ++ (if (shouldZeroBuffs) | |
2640 | 2557 | then [StringEntry(keyDuckBuffs(duckAssetId), "0_0_0_0_0")] | |
2641 | 2558 | else ((((nil :+ StringEntry(keyDuckLocation(duckAssetId), makeString([e._2._2, "L", id], "_"))) :+ IntegerEntry(keyHealth, f._1)) :+ StringEntry(eqKey, newEq)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))))), id, f._3) | |
2642 | 2559 | if (checkTournament(duckAssetId)) | |
2643 | 2560 | then throw("expedition_checkTournament") | |
2644 | 2561 | else { | |
2645 | 2562 | let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], nil)) | |
2646 | 2563 | $Tuple2(((result._1 ++ updateDuckStatsInternal(duckAssetId, xpNewSLand)._1) ++ prologActions), $Tuple3(result._2, result._3, acresResult)) | |
2647 | 2564 | } | |
2648 | 2565 | } | |
2649 | 2566 | } | |
2650 | 2567 | ||
2651 | 2568 | ||
2652 | 2569 | ||
2653 | 2570 | @Callable(i) | |
2654 | 2571 | func buySLandForAcres () = { | |
2655 | 2572 | let prologActions = prolog(i) | |
2656 | 2573 | if ((size(i.payments) != 1)) | |
2657 | 2574 | then throw("exactly 1 payment must be attached") | |
2658 | 2575 | else { | |
2659 | 2576 | let pmt = i.payments[0] | |
2660 | 2577 | let amt = pmt.amount | |
2661 | 2578 | if (if (!(isDefined(pmt.assetId))) | |
2662 | 2579 | then true | |
2663 | 2580 | else (value(pmt.assetId) != acresAssetId)) | |
2664 | 2581 | then throw("ACRES payments only!") | |
2665 | 2582 | else if ((amt != S_COST_ACRES)) | |
2666 | 2583 | then throw(("Payment attached should be " + toString(S_COST_ACRES))) | |
2667 | 2584 | else { | |
2668 | 2585 | let result = expeditionInternal(i.caller, i.transactionId) | |
2669 | 2586 | let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], [AttachedPayment(acresAssetId, amt)])) | |
2670 | 2587 | $Tuple2(((result._1 ++ updateAccStatsInternal(toString(i.caller), xpNewSLand)._1) ++ prologActions), $Tuple2(result._2._1, acresResult)) | |
2671 | 2588 | } | |
2672 | 2589 | } | |
2673 | 2590 | } | |
2674 | 2591 | ||
2675 | 2592 | ||
2676 | 2593 | ||
2677 | 2594 | @Callable(i) | |
2678 | 2595 | func upgradeInfra (landAssetId) = { | |
2679 | 2596 | let prologActions = prolog(i) | |
2680 | 2597 | if ((size(i.payments) != 0)) | |
2681 | 2598 | then throw("No payments required") | |
2682 | 2599 | else { | |
2683 | 2600 | let result = upInfraCommon(true, i.caller, 0, landAssetId) | |
2684 | 2601 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
2685 | 2602 | $Tuple2(((result._1 ++ prologActions) ++ updateDuckStatsInternal(duckAssetId, fraction(xpUpgradeInfra, result._3, MULT8))._1), result._2) | |
2686 | 2603 | } | |
2687 | 2604 | } | |
2688 | 2605 | ||
2689 | 2606 | ||
2690 | 2607 | ||
2691 | 2608 | @Callable(i) | |
2692 | 2609 | func activateArtifact (artName,landAssetIdOpt) = { | |
2693 | 2610 | let prologActions = prolog(i) | |
2694 | 2611 | if ((size(i.payments) != 0)) | |
2695 | 2612 | then throw("No payments required") | |
2696 | 2613 | else { | |
2697 | 2614 | let addr = toString(i.caller) | |
2698 | 2615 | let result = match artName { | |
2699 | 2616 | case _ => | |
2700 | 2617 | if (("PRESALE" == $match0)) | |
2701 | 2618 | then activatePresaleArt(addr, landAssetIdOpt) | |
2702 | 2619 | else if (("ONBOARD" == $match0)) | |
2703 | 2620 | then activateOnboardArt(addr) | |
2704 | 2621 | else throw("Unknown artifact") | |
2705 | 2622 | } | |
2706 | 2623 | (result ++ prologActions) | |
2707 | 2624 | } | |
2708 | 2625 | } | |
2709 | 2626 | ||
2710 | 2627 | ||
2711 | 2628 | ||
2712 | 2629 | @Callable(i) | |
2713 | 2630 | func mergeLands (landAssetIds) = { | |
2714 | 2631 | let prologActions = prolog(i) | |
2715 | 2632 | if ((size(i.payments) != 0)) | |
2716 | 2633 | then throw("No payments required") | |
2717 | 2634 | else { | |
2718 | 2635 | let result = mergeCommon(toString(i.caller), landAssetIds) | |
2719 | 2636 | $Tuple2(((result._1 ++ prologActions) ++ updateAccStatsInternal(toString(i.caller), xpMerge)._1), result._2) | |
2720 | 2637 | } | |
2721 | 2638 | } | |
2722 | 2639 | ||
2723 | 2640 | ||
2724 | 2641 | ||
2725 | 2642 | @Callable(i) | |
2726 | 2643 | func cargoExchange (cargoListStr,landAssetId) = { | |
2727 | 2644 | let prologActions = prolog(i) | |
2728 | 2645 | if ((size(i.payments) != 0)) | |
2729 | 2646 | then throw("No payments required") | |
2730 | 2647 | else { | |
2731 | 2648 | let cargoParts = split_4C(cargoListStr, ":") | |
2732 | 2649 | let addr = toString(i.originCaller) | |
2733 | 2650 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
2734 | 2651 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
2735 | 2652 | if (!(isDefined(getInteger(timeKey)))) | |
2736 | 2653 | then throw((asset.name + " is not staked")) | |
2737 | 2654 | else { | |
2738 | 2655 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
2739 | 2656 | if ((owner != addr)) | |
2740 | 2657 | then throw((LANDPREFIX + " is not yours")) | |
2741 | 2658 | else { | |
2742 | 2659 | let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE) | |
2743 | 2660 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
2744 | 2661 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
2745 | 2662 | let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION) | |
2746 | 2663 | let loc = split(value(curLocation), "_") | |
2747 | 2664 | if ((loc[locIdxType] != "L")) | |
2748 | 2665 | then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L")) | |
2749 | 2666 | else if ((loc[locIdxId] != landAssetId)) | |
2750 | 2667 | then throw(("Duck should be on the land " + landAssetId)) | |
2751 | 2668 | else { | |
2752 | 2669 | let whKey = keyWarehouseByLand(landAssetId) | |
2753 | 2670 | let currentWh = getWarehouse(whKey, landIndex, infraLevel) | |
2754 | 2671 | let bpKey = keyBackpackByDuck(duckAssetId) | |
2755 | 2672 | let currentPack = getBackpack(bpKey) | |
2756 | 2673 | let result = moveStuff(cargoParts, currentWh, currentPack) | |
2757 | 2674 | let loft = split(currentWh[whIdxLOFT], "_") | |
2758 | 2675 | let loftO = (parseIntValue(loft[volOccupied]) + result._7) | |
2759 | 2676 | let loftF = (parseIntValue(loft[volFree]) - result._7) | |
2760 | 2677 | ([StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], result._4, result._5, result._6], ":")), StringEntry(whKey, makeString_2C([currentWh[whIdxLevels], result._1, result._2, result._3, makeString([loft[volLocked], toString(loftO), toString(loftF), loft[volTotal]], "_")], ":"))] ++ prologActions) | |
2761 | 2678 | } | |
2762 | 2679 | } | |
2763 | 2680 | } | |
2764 | 2681 | } | |
2765 | 2682 | } | |
2766 | 2683 | ||
2767 | 2684 | ||
2768 | 2685 | ||
2769 | 2686 | @Callable(i) | |
2770 | 2687 | func saveWarehouse (whStr,landAssetId) = if ((i.caller != economyContract)) | |
2771 | 2688 | then throw("Access denied") | |
2772 | 2689 | else { | |
2773 | 2690 | let whKey = keyWarehouseByLand(landAssetId) | |
2774 | 2691 | let wh = split_4C(whStr, ":") | |
2775 | 2692 | if ((size(wh) != 5)) | |
2776 | 2693 | then throw("warehouse string should contain 4 ':' separators") | |
2777 | 2694 | else { | |
2778 | 2695 | let loftL = split(wh[whIdxLOFT], "_")[volLocked] | |
2779 | 2696 | let loftO = getWarehouseOccupiedVol(wh) | |
2780 | 2697 | let loftT = getWarehouseTotalVolume(wh[whIdxLevels]) | |
2781 | 2698 | let loftF = ((loftT - parseIntValue(loftL)) - loftO) | |
2782 | 2699 | if ((0 > loftF)) | |
2783 | 2700 | then throw("Operation leads to negative free warehouse space") | |
2784 | 2701 | else { | |
2785 | 2702 | let newWhStr = makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], wh[whIdxProd], makeString([loftL, toString(loftO), toString(loftF), toString(loftT)], "_")], ":") | |
2786 | 2703 | $Tuple2([StringEntry(whKey, newWhStr)], newWhStr) | |
2787 | 2704 | } | |
2788 | 2705 | } | |
2789 | 2706 | } | |
2790 | 2707 | ||
2791 | 2708 | ||
2792 | 2709 | ||
2793 | 2710 | @Callable(i) | |
2794 | 2711 | func setCustomName (assetId,customName,type) = { | |
2795 | 2712 | let prologActions = prolog(i) | |
2796 | 2713 | if ((size(i.payments) != 1)) | |
2797 | 2714 | then throw("Exactly one payment required") | |
2798 | 2715 | else { | |
2799 | 2716 | let pmt = value(i.payments[0]) | |
2800 | 2717 | if ((pmt.assetId != usdtAssetId)) | |
2801 | 2718 | then throw("Allowed USDT payment only!") | |
2802 | 2719 | else if ((pmt.amount != RENAMINGCOST)) | |
2803 | 2720 | then throw(("Payment should be " + toString(RENAMINGCOST))) | |
2804 | 2721 | else if (contains(customName, "__")) | |
2805 | 2722 | then throw(("Name should not contain '__': " + customName)) | |
2806 | 2723 | else if ((size(customName) > MAXNAMELEN)) | |
2807 | 2724 | then throw(("Name too long, maxLength=" + toString(MAXNAMELEN))) | |
2808 | 2725 | else { | |
2809 | 2726 | let addr = toString(i.originCaller) | |
2810 | 2727 | let actions = match type { | |
2811 | 2728 | case _ => | |
2812 | 2729 | if (("ACCOUNT" == $match0)) | |
2813 | 2730 | then { | |
2814 | 2731 | let reverseKey = keyCustomNameToAddress(customName) | |
2815 | 2732 | let nameOwner = getString(reverseKey) | |
2816 | 2733 | if (isDefined(nameOwner)) | |
2817 | 2734 | then throw(("Name already registered: " + customName)) | |
2818 | 2735 | else { | |
2819 | 2736 | let addrToNameKey = keyAddressToCustomName(addr) | |
2820 | 2737 | let oldName = getString(addrToNameKey) | |
2821 | 2738 | let freeOld = if (isDefined(oldName)) | |
2822 | 2739 | then [DeleteEntry(keyCustomNameToAddress(value(oldName)))] | |
2823 | 2740 | else nil | |
2824 | 2741 | (((freeOld :+ StringEntry(addrToNameKey, customName)) :+ StringEntry(reverseKey, addr)) ++ updateAccStatsInternal(addr, xpCustomName)._1) | |
2825 | 2742 | } | |
2826 | 2743 | } | |
2827 | 2744 | else if (("LAND" == $match0)) | |
2828 | 2745 | then { | |
2829 | 2746 | let asset = value(assetInfo(fromBase58String(assetId))) | |
2830 | 2747 | let timeKey = keyStakedTimeByAssetId(assetId) | |
2831 | 2748 | if (!(isDefined(getInteger(timeKey)))) | |
2832 | 2749 | then throw((asset.name + " is not staked")) | |
2833 | 2750 | else { | |
2834 | 2751 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(assetId)), (("NFT " + asset.name) + " is orphaned")) | |
2835 | 2752 | if ((owner != addr)) | |
2836 | 2753 | then throw((LANDPREFIX + " is not yours")) | |
2837 | 2754 | else { | |
2838 | 2755 | let reverseKey = keyLandCustomNameToAssetId(customName) | |
2839 | 2756 | let nameOwner = getString(reverseKey) | |
2840 | 2757 | if (isDefined(nameOwner)) | |
2841 | 2758 | then throw(("Name already registered: " + customName)) | |
2842 | 2759 | else { | |
2843 | 2760 | let assetToNameKey = keyLandAssetIdToCustomName(assetId) | |
2844 | 2761 | let oldName = getString(assetToNameKey) | |
2845 | 2762 | let freeOld = if (isDefined(oldName)) | |
2846 | 2763 | then [DeleteEntry(keyLandCustomNameToAssetId(value(oldName)))] | |
2847 | 2764 | else nil | |
2848 | 2765 | (((freeOld :+ StringEntry(assetToNameKey, customName)) :+ StringEntry(reverseKey, assetId)) ++ updateAccStatsInternal(addr, xpCustomName)._1) | |
2849 | 2766 | } | |
2850 | 2767 | } | |
2851 | 2768 | } | |
2852 | 2769 | } | |
2853 | 2770 | else if (("DUCK" == $match0)) | |
2854 | 2771 | then { | |
2855 | 2772 | let asset = value(assetInfo(fromBase58String(assetId))) | |
2856 | 2773 | let timeKey = keyStakedTimeByAssetId(assetId) | |
2857 | 2774 | if (if (!(isDefined(getInteger(timeKey)))) | |
2858 | 2775 | then true | |
2859 | 2776 | else !(isDefined(getString(keyStakedDuckByOwner(addr))))) | |
2860 | 2777 | then throw((asset.name + " is not staked")) | |
2861 | 2778 | else { | |
2862 | 2779 | let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(assetId)), (("NFT " + asset.name) + " is orphaned")) | |
2863 | 2780 | if ((owner != addr)) | |
2864 | 2781 | then throw((DUCKPREFIX + " is not yours")) | |
2865 | 2782 | else { | |
2866 | 2783 | let reverseKey = keyDuckCustomNameToAssetId(customName) | |
2867 | 2784 | let nameOwner = getString(reverseKey) | |
2868 | 2785 | if (isDefined(nameOwner)) | |
2869 | 2786 | then throw(("Name already registered: " + customName)) | |
2870 | 2787 | else { | |
2871 | 2788 | let assetToNameKey = keyDuckAssetIdToCustomName(assetId) | |
2872 | 2789 | let oldName = getString(assetToNameKey) | |
2873 | 2790 | let freeOld = if (isDefined(oldName)) | |
2874 | 2791 | then [DeleteEntry(keyDuckCustomNameToAssetId(value(oldName)))] | |
2875 | 2792 | else nil | |
2876 | 2793 | (((freeOld :+ StringEntry(assetToNameKey, customName)) :+ StringEntry(reverseKey, assetId)) ++ updateDuckStatsInternal(assetId, xpCustomName)._1) | |
2877 | 2794 | } | |
2878 | 2795 | } | |
2879 | 2796 | } | |
2880 | 2797 | } | |
2881 | 2798 | else throw("Unknown entity type") | |
2882 | 2799 | } | |
2883 | 2800 | $Tuple2(((actions :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) ++ prologActions), 0) | |
2884 | 2801 | } | |
2885 | 2802 | } | |
2886 | 2803 | } | |
2887 | 2804 | ||
2888 | 2805 | ||
2889 | 2806 | ||
2890 | 2807 | @Callable(i) | |
2891 | 2808 | func setReferrals (oldPlayer,newPlayer) = if ((i.callerPublicKey != pub)) | |
2892 | 2809 | then throw("Permission denied") | |
2893 | 2810 | else { | |
2894 | 2811 | let prologActions = prolog(i) | |
2895 | 2812 | if ((size(i.payments) != 0)) | |
2896 | 2813 | then throw("No payments required") | |
2897 | 2814 | else if (!(isDefined(addressFromString(oldPlayer)))) | |
2898 | 2815 | then throw(("Invalid address: " + oldPlayer)) | |
2899 | 2816 | else { | |
2900 | 2817 | let newbieAddr = addressFromString(newPlayer) | |
2901 | 2818 | if (!(isDefined(newbieAddr))) | |
2902 | 2819 | then throw(("Invalid address: " + newPlayer)) | |
2903 | 2820 | else { | |
2904 | 2821 | let oldLastTx = getString(keyLastTxIdByUser(oldPlayer)) | |
2905 | 2822 | if (!(isDefined(oldLastTx))) | |
2906 | 2823 | then throw("oldPlayer didn't do any tx in game") | |
2907 | 2824 | else if ((0 >= wavesBalance(value(newbieAddr)).available)) | |
2908 | 2825 | then throw("newPlayer has no WAVES") | |
2909 | 2826 | else { | |
2910 | 2827 | let oldsKey = keyOldies() | |
2911 | 2828 | let olds = getString(oldsKey) | |
2912 | 2829 | let oldies = if (isDefined(olds)) | |
2913 | 2830 | then split_4C(value(olds), "_") | |
2914 | 2831 | else nil | |
2915 | 2832 | if (containsElement(oldies, newPlayer)) | |
2916 | 2833 | then throw((newPlayer + " is not newbie (already has referrals)")) | |
2917 | 2834 | else { | |
2918 | 2835 | let refByKey = keyAddressRefBy(newPlayer) | |
2919 | 2836 | let refBy = getString(refByKey) | |
2920 | 2837 | if (if (isDefined(refBy)) | |
2921 | 2838 | then isDefined(addressFromString(value(refBy))) | |
2922 | 2839 | else false) | |
2923 | 2840 | then throw(((newPlayer + " already has refBy: ") + value(refBy))) | |
2924 | 2841 | else { | |
2925 | 2842 | let refsKey = keyAddressReferrals(oldPlayer) | |
2926 | 2843 | let refs = getString(refsKey) | |
2927 | 2844 | let refsArray = if (isDefined(refs)) | |
2928 | 2845 | then split_4C(value(refs), "_") | |
2929 | 2846 | else nil | |
2930 | 2847 | if (containsElement(refsArray, newPlayer)) | |
2931 | 2848 | then throw((((oldPlayer + " already contains ") + newPlayer) + " within referrals")) | |
2932 | 2849 | else { | |
2933 | 2850 | let newRefs = makeString_2C((refsArray :+ newPlayer), "_") | |
2934 | 2851 | let newOlds = if (containsElement(oldies, oldPlayer)) | |
2935 | 2852 | then value(olds) | |
2936 | 2853 | else makeString_2C((oldies :+ oldPlayer), "_") | |
2937 | 2854 | $Tuple2(([StringEntry(refByKey, oldPlayer), StringEntry(refsKey, newRefs), StringEntry(oldsKey, newOlds)] ++ prologActions), 0) | |
2938 | 2855 | } | |
2939 | 2856 | } | |
2940 | 2857 | } | |
2941 | 2858 | } | |
2942 | 2859 | } | |
2943 | 2860 | } | |
2944 | 2861 | } | |
2945 | 2862 | ||
2946 | 2863 | ||
2947 | 2864 | ||
2948 | 2865 | @Callable(i) | |
2949 | 2866 | func distributePoints (strength,accuracy,intellect,endurance,dexterity) = { | |
2950 | 2867 | let prologActions = prolog(i) | |
2951 | 2868 | if ((size(i.payments) != 0)) | |
2952 | 2869 | then throw("No payments required") | |
2953 | 2870 | else { | |
2954 | 2871 | let addr = toString(i.originCaller) | |
2955 | 2872 | let virtWlgData = asAnyList(invoke(wlgContract, "checkWlgXpREADONLY", [addr], nil)) | |
2956 | 2873 | let virtWlgPoints = asInt(virtWlgData[1]) | |
2957 | - | let $ | |
2874 | + | let $t09214992539 = if ((0 >= virtWlgPoints)) | |
2958 | 2875 | then $Tuple2(0, nil) | |
2959 | 2876 | else { | |
2960 | 2877 | let deltaXP = asInt(invoke(wlgContract, "takeWlgXp", [addr], nil)) | |
2961 | 2878 | if ((deltaXP == deltaXP)) | |
2962 | 2879 | then $Tuple2(virtWlgPoints, [IntegerEntry(keyUserLevel(addr), asInt(virtWlgData[0])), IntegerEntry(keyUserXP(addr), asInt(virtWlgData[2]))]) | |
2963 | 2880 | else throw("Strict value is not equal to itself.") | |
2964 | 2881 | } | |
2965 | - | let wlgPoints = $ | |
2966 | - | let wlgActions = $ | |
2882 | + | let wlgPoints = $t09214992539._1 | |
2883 | + | let wlgActions = $t09214992539._2 | |
2967 | 2884 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
2968 | 2885 | let freeKeyAcc = keyUserFreePoints(addr) | |
2969 | 2886 | let freePointsAcc = (valueOrElse(getInteger(freeKeyAcc), 0) + wlgPoints) | |
2970 | 2887 | let freeKeyDuck = keyDuckFreePoints(duckAssetId) | |
2971 | 2888 | let freePointsDuck = valueOrElse(getInteger(freeKeyDuck), 0) | |
2972 | 2889 | let sumFree = (freePointsAcc + freePointsDuck) | |
2973 | 2890 | let sumToDistribute = ((((strength + accuracy) + intellect) + endurance) + dexterity) | |
2974 | 2891 | if ((sumToDistribute > sumFree)) | |
2975 | 2892 | then throw((("There are only " + toString(sumFree)) + " free points to distribute")) | |
2976 | 2893 | else { | |
2977 | 2894 | let charsKey = keyDuckChars(duckAssetId) | |
2978 | 2895 | let chars = split(valueOrElse(getString(charsKey), "0_0_0_0_0"), "_") | |
2979 | 2896 | let newAcc = (freePointsAcc - sumToDistribute) | |
2980 | 2897 | $Tuple2((([IntegerEntry(freeKeyAcc, if ((0 > newAcc)) | |
2981 | 2898 | then 0 | |
2982 | 2899 | else newAcc), IntegerEntry(freeKeyDuck, if ((0 > newAcc)) | |
2983 | 2900 | then (freePointsDuck + newAcc) | |
2984 | 2901 | else freePointsDuck), StringEntry(charsKey, makeString([toString((parseIntValue(chars[charStrength]) + strength)), toString((parseIntValue(chars[charAccuracy]) + accuracy)), toString((parseIntValue(chars[charIntellect]) + intellect)), toString((parseIntValue(chars[charEndurance]) + endurance)), toString((parseIntValue(chars[charDexterity]) + dexterity))], "_"))] ++ prologActions) ++ wlgActions), 0) | |
2985 | 2902 | } | |
2986 | 2903 | } | |
2987 | 2904 | } | |
2988 | 2905 | ||
2989 | 2906 | ||
2990 | 2907 | ||
2991 | 2908 | @Callable(i) | |
2992 | 2909 | func splitByGlobalWeightsREADONLY (amount) = $Tuple2(nil, getNeededMaterials(amount)) | |
2993 | 2910 | ||
2994 | 2911 | ||
2995 | 2912 | ||
2996 | 2913 | @Callable(i) | |
2997 | 2914 | func splitByGlobalAndLocalWeightsREADONLY (matAmount,resAmount,terrains) = { | |
2998 | 2915 | let terrainCounts = countTerrains(terrains) | |
2999 | 2916 | $Tuple2(nil, $Tuple2(getNeededMaterials(matAmount), distributeByWeights(resAmount, terrainCounts))) | |
3000 | 2917 | } | |
3001 | 2918 | ||
3002 | 2919 | ||
3003 | 2920 | ||
3004 | 2921 | @Callable(i) | |
3005 | 2922 | func getBackpackREADONLY (duckAssetId) = $Tuple2(nil, makeString(getBackpack(keyBackpackByDuck(duckAssetId)), ":")) | |
3006 | 2923 | ||
3007 | 2924 | ||
3008 | 2925 | ||
3009 | 2926 | @Callable(i) | |
3010 | 2927 | func getWarehouseREADONLY (landAssetId) = { | |
3011 | 2928 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
3012 | 2929 | let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE) | |
3013 | 2930 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
3014 | 2931 | $Tuple2(nil, makeString_2C(getWarehouse(keyWarehouseByLand(landAssetId), landIndex, infraLevel), ":")) | |
3015 | 2932 | } | |
3016 | 2933 | ||
3017 | 2934 | ||
3018 | 2935 | ||
3019 | 2936 | @Callable(i) | |
3020 | 2937 | func saveLastTx () = if (!(containsElement([wlgContract, economyContract, tournamentContract, acresContract], i.caller))) | |
3021 | 2938 | then throw("Access denied") | |
3022 | 2939 | else $Tuple2(prolog(i), 42) | |
3023 | 2940 | ||
3024 | 2941 | ||
3025 | 2942 | ||
3026 | 2943 | @Callable(i) | |
3027 | 2944 | func updateDuckStats (duckAssetId,deltaXP) = if ((i.caller != economyContract)) | |
3028 | 2945 | then throw("Access denied") | |
3029 | 2946 | else updateDuckStatsInternal(duckAssetId, deltaXP) | |
3030 | 2947 | ||
3031 | 2948 | ||
3032 | 2949 | ||
3033 | 2950 | @Callable(i) | |
3034 | 2951 | func updateAccStats (addr,deltaXP) = if (!(containsElement([wlgContract, economyContract, acresContract], i.caller))) | |
3035 | 2952 | then throw("Access denied") | |
3036 | 2953 | else updateAccStatsInternal(addr, deltaXP) | |
3037 | 2954 | ||
3038 | 2955 | ||
3039 | 2956 | ||
3040 | 2957 | @Callable(i) | |
3041 | 2958 | func equipDuck (equipment) = { | |
3042 | 2959 | let prologActions = prolog(i) | |
3043 | 2960 | if ((size(i.payments) != 0)) | |
3044 | 2961 | then throw("No payments required") | |
3045 | 2962 | else { | |
3046 | 2963 | let addr = toString(i.originCaller) | |
3047 | 2964 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
3048 | 2965 | if (checkTournament(duckAssetId)) | |
3049 | 2966 | then throw("equipDuck_checkTournament") | |
3050 | 2967 | else { | |
3051 | 2968 | let eqKey = keyDuckEquipment(duckAssetId) | |
3052 | 2969 | let currentSegs = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_") | |
3053 | 2970 | let bpKey = keyBackpackByDuck(duckAssetId) | |
3054 | 2971 | let currentPack = getBackpack(bpKey) | |
3055 | 2972 | let newEq = split(equipment, "_") | |
3056 | 2973 | if ((size(newEq) != NUMSEGMENTS)) | |
3057 | 2974 | then throw("Wrong equipment string") | |
3058 | 2975 | else { | |
3059 | 2976 | let tempProdB = dressB(currentSegs, prodStrToBytes(currentPack[bpIdxProd]), true, nil) | |
3060 | 2977 | let segBpAux = split(newEq[segBackpack], ";")[1] | |
3061 | 2978 | let buffEffect = if ((segBpAux == "")) | |
3062 | 2979 | then 0 | |
3063 | 2980 | else { | |
3064 | 2981 | let aux0 = split(segBpAux, ",")[0] | |
3065 | 2982 | if ((aux0 == "")) | |
3066 | 2983 | then 0 | |
3067 | 2984 | else { | |
3068 | 2985 | let idxCnt = split(aux0, ":") | |
3069 | 2986 | let idx = idxCnt[0] | |
3070 | 2987 | let cnt = idxCnt[1] | |
3071 | 2988 | if (if (if (if (if ((idx == "06")) | |
3072 | 2989 | then true | |
3073 | 2990 | else (idx == "07")) | |
3074 | 2991 | then true | |
3075 | 2992 | else (idx == "08")) | |
3076 | 2993 | then (cnt != "") | |
3077 | 2994 | else false) | |
3078 | 2995 | then (parseIntValue(cnt) > 0) | |
3079 | 2996 | else false) | |
3080 | 2997 | then parseIntValue(split(productionMatrix[parseIntValue(idx)], "_")[rIdxEffect]) | |
3081 | 2998 | else 0 | |
3082 | 2999 | } | |
3083 | 3000 | } | |
3084 | 3001 | let stats = getDuckStats(this, duckAssetId, buffEffect, true) | |
3085 | 3002 | let newProdB = dressB(newEq, tempProdB, false, stats) | |
3086 | 3003 | let newProdStr = bytesToProdStr(newProdB) | |
3087 | 3004 | $Tuple2(([StringEntry(eqKey, equipment), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], newProdStr], ":")), StringEntry(keyDuckBuffs(duckAssetId), makeString([toString(stats[7]), toString(stats[8]), toString(stats[9]), toString(stats[10]), toString(stats[11])], "_"))] ++ prologActions), 0) | |
3088 | 3005 | } | |
3089 | 3006 | } | |
3090 | 3007 | } | |
3091 | 3008 | } | |
3092 | 3009 | ||
3093 | 3010 | ||
3094 | 3011 | ||
3095 | 3012 | @Callable(i) | |
3096 | - | func fortificateLand (landAssetId,plan) = { | |
3097 | - | let prologActions = prolog(i) | |
3098 | - | if ((size(i.payments) != 0)) | |
3099 | - | then throw("No payments required") | |
3100 | - | else { | |
3101 | - | let addr = toString(i.originCaller) | |
3102 | - | let duckAssetId = valueOrElse(getString(keyStakedDuckByOwner(addr)), "") | |
3103 | - | let duckStats = getDuckStats(this, duckAssetId, 0, false) | |
3104 | - | let fortKey = keyFortificationsByLand(landAssetId) | |
3105 | - | let currentForts = split(valueOrElse(getString(fortKey), ":0_15:0_18:0"), "_") | |
3106 | - | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
3107 | - | let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE) | |
3108 | - | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
3109 | - | let whKey = keyWarehouseByLand(landAssetId) | |
3110 | - | let wh = getWarehouse(whKey, landIndex, infraLevel) | |
3111 | - | let curLoft = split(wh[whIdxLOFT], "_") | |
3112 | - | let curO = parseIntValue(curLoft[volOccupied]) | |
3113 | - | let curF = parseIntValue(curLoft[volFree]) | |
3114 | - | let newForts = split(plan, "_") | |
3115 | - | let $t09894799062 = fortB(currentForts, prodStrToBytes(wh[whIdxProd]), curO, curF, true, nil) | |
3116 | - | let tempProdB = $t09894799062._1 | |
3117 | - | let tempO = $t09894799062._2 | |
3118 | - | let tempF = $t09894799062._3 | |
3119 | - | let $t09906599161 = fortB(newForts, tempProdB, tempO, tempF, false, duckStats) | |
3120 | - | let newProdB = $t09906599161._1 | |
3121 | - | let newO = $t09906599161._2 | |
3122 | - | let newF = $t09906599161._3 | |
3123 | - | let newProdStr = bytesToProdStr(newProdB) | |
3124 | - | let newLoftStr = makeString([curLoft[volLocked], toString(newO), toString(newF), curLoft[volTotal]], "_") | |
3125 | - | $Tuple2(([StringEntry(fortKey, plan), StringEntry(whKey, makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], newProdStr, newLoftStr], ":"))] ++ prologActions), 0) | |
3126 | - | } | |
3127 | - | } | |
3128 | - | ||
3129 | - | ||
3130 | - | ||
3131 | - | @Callable(i) | |
3132 | 3013 | func initDuckTourAttempt (duckAssetId) = if ((i.caller != tournamentContract)) | |
3133 | 3014 | then throw("Access denied") | |
3134 | 3015 | else { | |
3135 | 3016 | let keyHealth = keyDuckHealth(duckAssetId) | |
3136 | 3017 | let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0)) | |
3137 | 3018 | let curHealth = valueOrElse(getInteger(keyHealth), maxHP) | |
3138 | 3019 | let curLocKey = keyDuckLocation(duckAssetId) | |
3139 | 3020 | let curLocation = valueOrElse(getString(curLocKey), DEFAULTLOCATION) | |
3140 | 3021 | let lastId = valueOrElse(getInteger(tournamentContract, lastTourIdKey), 0) | |
3141 | 3022 | let tourLocation = (toString(lastId) + "_T_0") | |
3142 | 3023 | $Tuple2([IntegerEntry(keySavedHealth(duckAssetId), curHealth), IntegerEntry(keyHealth, maxHP), StringEntry(keySavedLocation(duckAssetId), curLocation), StringEntry(curLocKey, tourLocation)], tourLocation) | |
3143 | 3024 | } | |
3144 | 3025 | ||
3145 | 3026 | ||
3146 | 3027 | ||
3147 | 3028 | @Callable(i) | |
3148 | 3029 | func breakAttempt () = { | |
3149 | 3030 | let prologActions = prolog(i) | |
3150 | 3031 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
3151 | 3032 | let curLocKey = keyDuckLocation(duckAssetId) | |
3152 | 3033 | let curLocation = valueOrElse(getString(curLocKey), DEFAULTLOCATION) | |
3153 | 3034 | if ((split(curLocation, "_")[locIdxType] != "T")) | |
3154 | 3035 | then throw("Your duck is not in the tournament") | |
3155 | 3036 | else { | |
3156 | 3037 | let savedHealth = getIntegerValue(keySavedHealth(duckAssetId)) | |
3157 | 3038 | let savedLocation = getStringValue(keySavedLocation(duckAssetId)) | |
3158 | 3039 | $Tuple2(((prologActions :+ IntegerEntry(keyDuckHealth(duckAssetId), savedHealth)) :+ StringEntry(curLocKey, savedLocation)), curLocation) | |
3159 | 3040 | } | |
3160 | 3041 | } | |
3161 | 3042 | ||
3162 | 3043 | ||
3163 | 3044 | ||
3164 | 3045 | @Callable(i) | |
3165 | 3046 | func breakAttemptCallback () = if ((i.caller != tournamentContract)) | |
3166 | 3047 | then throw("Access denied") | |
3167 | 3048 | else { | |
3168 | 3049 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.originCaller))), "You don't have a duck staked") | |
3169 | 3050 | $Tuple2([IntegerEntry(keyDuckHealth(duckAssetId), getIntegerValue(keySavedHealth(duckAssetId))), StringEntry(keyDuckLocation(duckAssetId), getStringValue(keySavedLocation(duckAssetId)))], "breakAttemptCallback") | |
3170 | 3051 | } | |
3171 | 3052 | ||
3172 | 3053 | ||
3173 | 3054 | ||
3174 | 3055 | @Callable(i) | |
3175 | 3056 | func exitTournamentInternal (duckAssetId) = if ((i.caller != this)) | |
3176 | 3057 | then throw("Access denied") | |
3177 | 3058 | else { | |
3178 | 3059 | let savedHealth = getIntegerValue(keySavedHealth(duckAssetId)) | |
3179 | 3060 | let savedLocation = getStringValue(keySavedLocation(duckAssetId)) | |
3180 | 3061 | $Tuple2([IntegerEntry(keyDuckHealth(duckAssetId), savedHealth), StringEntry(keyDuckLocation(duckAssetId), savedLocation)], false) | |
3181 | 3062 | } | |
3182 | 3063 | ||
3183 | 3064 | ||
3184 | 3065 | ||
3185 | 3066 | @Callable(i) | |
3186 | 3067 | func processDelivery (duckAssetId) = if ((i.caller != this)) | |
3187 | 3068 | then throw("Access denied") | |
3188 | 3069 | else { | |
3189 | 3070 | let addr = toString(i.originCaller) | |
3190 | 3071 | let fundTotal = valueOrElse(getInteger(economyContract, deliveryFundKey), 0) | |
3191 | 3072 | if ((MIN_USDT_FEE_DELIVERY > fundTotal)) | |
3192 | 3073 | then throw(("Delivery is not available, fund=" + fixedPoint(fundTotal, 6))) | |
3193 | 3074 | else { | |
3194 | 3075 | let now = lastBlock.timestamp | |
3195 | 3076 | let countKey = keyUserDeliveryCount(addr) | |
3196 | 3077 | let lastDay = valueOrElse(getInteger(keyUserLastDeliveryDay(addr)), 0) | |
3197 | 3078 | let today = (now / DAYMILLIS) | |
3198 | 3079 | let count = if ((lastDay == today)) | |
3199 | 3080 | then valueOrElse(getInteger(countKey), 0) | |
3200 | 3081 | else 0 | |
3201 | 3082 | let acres = valueOrElse(getInteger(acresContract, keyAcresStakedAmountByUser(addr)), 0) | |
3202 | 3083 | let allowedDeliveries = (ALLOWED_FREE_DELIVERIES + (acres / ACRES_FOR_DELIVERY_ATTEMPT)) | |
3203 | 3084 | if ((count >= allowedDeliveries)) | |
3204 | 3085 | then throw((("You already used " + toString(allowedDeliveries)) + " delivery attempts for today")) | |
3205 | 3086 | else { | |
3206 | 3087 | let globalCountKey = keyDuckDeliveryCount(duckAssetId) | |
3207 | 3088 | let reward = invoke(economyContract, "sendDeliveryReward", [addr], nil) | |
3208 | 3089 | $Tuple2([IntegerEntry(countKey, (count + 1)), IntegerEntry(keyUserLastDeliveryDay(addr), today), IntegerEntry(globalCountKey, (valueOrElse(getInteger(globalCountKey), 0) + 1))], reward) | |
3209 | 3090 | } | |
3210 | 3091 | } | |
3211 | 3092 | } | |
3212 | 3093 | ||
3213 | 3094 | ||
3214 | 3095 | ||
3215 | 3096 | @Callable(i) | |
3216 | - | func | |
3097 | + | func robLand (message,sig) = { | |
3217 | 3098 | let prologActions = prolog(i) | |
3218 | - | if (! | |
3219 | - | then throw(" | |
3220 | - | else | |
3221 | - | | |
3222 | - | | |
3223 | - | | |
3224 | - | | |
3225 | - | | |
3226 | - | ||
3227 | - | ||
3228 | - | then throw("WLGOLD | |
3099 | + | if ((size(i.payments) != 1)) | |
3100 | + | then throw("exactly 1 payment must be attached") | |
3101 | + | else { | |
3102 | + | let pmt = i.payments[0] | |
3103 | + | let wlgAmt = pmt.amount | |
3104 | + | if (if (!(isDefined(pmt.assetId))) | |
3105 | + | then true | |
3106 | + | else (value(pmt.assetId) != wlgAssetId)) | |
3107 | + | then throw("WLGOLD payments only!") | |
3108 | + | else if ((wlgAmt != MIN_WLGOLD_ROBBERY)) | |
3109 | + | then throw((("Payment should be " + fixedPoint(MIN_WLGOLD_ROBBERY, 8)) + " WLGOLD")) | |
3229 | 3110 | else { | |
3230 | - | let | |
3231 | - | if (( | |
3232 | - | then throw(" | |
3111 | + | let addr = toString(i.caller) | |
3112 | + | if (!(sigVerify_8Kb(message, sig, pub))) | |
3113 | + | then throw("signature does not match") | |
3233 | 3114 | else { | |
3234 | - | let txFromMsg = if ((size(parts) >= 2)) | |
3235 | - | then parts[2] | |
3236 | - | else "" | |
3237 | - | let userAddr = toString(i.caller) | |
3238 | - | let lastTx = valueOrElse(getString(keyLastTxIdByUser(userAddr)), "") | |
3239 | - | if ((lastTx != txFromMsg)) | |
3240 | - | then throw(((("Tx ids don't match! In state: " + lastTx) + ", in msg: ") + txFromMsg)) | |
3115 | + | let parts = split_4C(toUtf8String(message), ";") | |
3116 | + | let robLog = split_4C(parts[0], "|") | |
3117 | + | let hp = split(robLog[rlHealth], "_") | |
3118 | + | let curHP = parseIntValue(hp[0]) | |
3119 | + | let newHP = parseIntValue(hp[1]) | |
3120 | + | let prodUsed = robLog[rlProdsUsed] | |
3121 | + | let lastPart = split(parts[1], "|") | |
3122 | + | let robType = lastPart[rlType] | |
3123 | + | if ((robType != "B")) | |
3124 | + | then throw("Only bank robbery is supported") | |
3241 | 3125 | else { | |
3242 | - | let duckAssetId = parts[0] | |
3243 | - | if (checkTournament(duckAssetId)) | |
3244 | - | then throw("prepareRobbery_checkTournament") | |
3126 | + | let time = parseIntValue(lastPart[rlTimestamp]) | |
3127 | + | if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS))) | |
3128 | + | then true | |
3129 | + | else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time)) | |
3130 | + | then throw(((("signature outdated: logTime=" + toString(time)) + ", bcTime=") + toString(lastBlock.timestamp))) | |
3245 | 3131 | else { | |
3246 | - | let robCost = getRobberyData(this, duckAssetId)._1 | |
3247 | - | if ((robCost > wlgAmt)) | |
3248 | - | then throw(((("Payment " + toString(wlgAmt)) + " < required ") + toString(robCost))) | |
3132 | + | let txFromMsg = lastPart[rlLastTx] | |
3133 | + | let lastTx = valueOrElse(getString(keyLastTxIdByUser(addr)), "") | |
3134 | + | if ((lastTx != txFromMsg)) | |
3135 | + | then throw(((("Tx ids don't match! In state: " + lastTx) + ", in msg: ") + txFromMsg)) | |
3249 | 3136 | else { | |
3250 | - | let candidates = split(parts[1], "_") | |
3251 | - | let now = lastBlock.timestamp | |
3252 | - | let duckState = valueOrElse(getInteger(keyDuckRobberyState(duckAssetId)), 0) | |
3253 | - | let lockedLand = valueOrElse(getString(keyLockedLandByDuck(duckAssetId)), "") | |
3254 | - | let landETA = valueOrElse(getInteger(keyLandCooldownETA(lockedLand)), 0) | |
3255 | - | if (if ((duckState != duckIdxFree)) | |
3256 | - | then (landETA > now) | |
3257 | - | else false) | |
3258 | - | then throw(("You already started robbing, wait till " + toString(landETA))) | |
3137 | + | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
3138 | + | let eqKey = keyDuckEquipment(duckAssetId) | |
3139 | + | let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,") | |
3140 | + | let $t0109717109828 = subtractEquipment(currentEq, prodUsed) | |
3141 | + | let newEq = $t0109717109828._1 | |
3142 | + | let shouldZeroBuffs = $t0109717109828._2 | |
3143 | + | let isBpUsed = $t0109717109828._3 | |
3144 | + | let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION) | |
3145 | + | if (isInTournament(tournamentContract, curLocation)) | |
3146 | + | then throw("Your duck is taking part in the tournament") | |
3259 | 3147 | else { | |
3260 | - | func checker (acc,landAssetId) = { | |
3261 | - | let state = valueOrElse(getInteger(keyLandRobberyState(landAssetId)), 0) | |
3262 | - | let cooldownETA = valueOrElse(getInteger(keyLandCooldownETA(landAssetId)), 0) | |
3263 | - | if ((state > size(landRobCooldowns))) | |
3264 | - | then throw("Invalid state") | |
3265 | - | else if ((now > cooldownETA)) | |
3148 | + | let now = lastBlock.timestamp | |
3149 | + | let countKey = keyUserRobberyCount(addr) | |
3150 | + | let lastDay = valueOrElse(getInteger(keyUserLastRobberyDay(addr)), 0) | |
3151 | + | let today = (now / DAYMILLIS) | |
3152 | + | let count = if ((lastDay == today)) | |
3153 | + | then valueOrElse(getInteger(countKey), 0) | |
3154 | + | else 0 | |
3155 | + | let acres = valueOrElse(getInteger(acresContract, keyAcresStakedAmountByUser(addr)), 0) | |
3156 | + | let allowedRobberies = (ALLOWED_FREE_ROBBERIES + (acres / ACRES_FOR_ROBBERY_ATTEMPT)) | |
3157 | + | if ((count >= allowedRobberies)) | |
3158 | + | then throw((("You already used " + toString(allowedRobberies)) + " robbery attempts for today")) | |
3159 | + | else { | |
3160 | + | let globalCountKey = keyDuckRobberyCount(duckAssetId) | |
3161 | + | let loot = if ((newHP > 0)) | |
3266 | 3162 | then { | |
3267 | - | let stakedTime = valueOrElse(getInteger(keyStakedTimeByAssetId(landAssetId)), 0) | |
3268 | - | if ((0 >= stakedTime)) | |
3269 | - | then acc | |
3270 | - | else { | |
3271 | - | let a = value(assetInfo(fromBase58String(landAssetId))) | |
3272 | - | let d = split(a.description, "_") | |
3273 | - | let pieces = numPiecesBySize(d[recLandSize]) | |
3274 | - | let productivity = applyBonuses(landAssetId, pieces) | |
3275 | - | let deltaTime = (now - stakedTime) | |
3276 | - | let availRes = fraction(deltaTime, (productivity * pieces), DAYMILLIS) | |
3277 | - | if ((MIN_RES_TO_ROB > availRes)) | |
3278 | - | then acc | |
3279 | - | else (acc :+ landAssetId) | |
3280 | - | } | |
3163 | + | let fundTotal = assetBalance(this, wlgAssetId) | |
3164 | + | let prize = if (isBpUsed) | |
3165 | + | then (2 * MIN_WLGOLD_ROBBERY) | |
3166 | + | else (5 * MIN_WLGOLD_ROBBERY) | |
3167 | + | if ((prize > fundTotal)) | |
3168 | + | then throw(((("Robbery is not available, funds = " + fixedPoint(fundTotal, 8)) + " WLGOLD, required = ") + fixedPoint(prize, 8))) | |
3169 | + | else [ScriptTransfer(i.caller, prize, wlgAssetId)] | |
3281 | 3170 | } | |
3282 | - | else acc | |
3283 | - | } | |
3284 | - | ||
3285 | - | let filtered = { | |
3286 | - | let $l = candidates | |
3287 | - | let $s = size($l) | |
3288 | - | let $acc0 = nil | |
3289 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
3290 | - | then $a | |
3291 | - | else checker($a, $l[$i]) | |
3292 | - | ||
3293 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
3294 | - | then $a | |
3295 | - | else throw("List size exceeds 10") | |
3296 | - | ||
3297 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10) | |
3298 | - | } | |
3299 | - | if ((size(filtered) == 0)) | |
3300 | - | then throw("No candidates for robbery") | |
3301 | - | else { | |
3302 | - | let rndIdx = getRandomNumber(size(filtered), message, sig) | |
3303 | - | let landAssetId = filtered[rndIdx] | |
3304 | - | $Tuple2(([IntegerEntry(keyLandRobberyState(landAssetId), robIdxLocked), IntegerEntry(keyLandCooldownETA(landAssetId), (now + landRobCooldowns[robIdxLocked])), IntegerEntry(keyDuckRobberyState(duckAssetId), duckIdxPreparing), StringEntry(keyLockedLandByDuck(duckAssetId), landAssetId)] ++ prologActions), landAssetId) | |
3171 | + | else nil | |
3172 | + | $Tuple2((((((((((prologActions ++ loot) ++ (if (shouldZeroBuffs) | |
3173 | + | then [StringEntry(keyDuckBuffs(duckAssetId), "0_0_0_0_0")] | |
3174 | + | else nil)) ++ updateDuckStatsInternal(duckAssetId, if ((newHP > 0)) | |
3175 | + | then xpSuccessRob | |
3176 | + | else xpFailRob)._1) :+ IntegerEntry(keyLastRobberyTimeByDuck(duckAssetId), now)) :+ IntegerEntry(countKey, (count + 1))) :+ IntegerEntry(keyUserLastRobberyDay(addr), today)) :+ IntegerEntry(globalCountKey, (valueOrElse(getInteger(globalCountKey), 0) + 1))) :+ StringEntry(eqKey, newEq)) :+ IntegerEntry(keyDuckHealth(duckAssetId), max([newHP, 0]))), 0) | |
3305 | 3177 | } | |
3306 | 3178 | } | |
3307 | 3179 | } | |
3308 | 3180 | } | |
3309 | 3181 | } | |
3310 | 3182 | } | |
3311 | 3183 | } | |
3312 | - | } | |
3313 | - | } | |
3314 | - | ||
3315 | - | ||
3316 | - | ||
3317 | - | @Callable(i) | |
3318 | - | func robLand (message,sig) = { | |
3319 | - | let prologActions = prolog(i) | |
3320 | - | if (!(sigVerify_8Kb(message, sig, pub))) | |
3321 | - | then throw("signature does not match") | |
3322 | - | else { | |
3323 | - | let userAddr = toString(i.caller) | |
3324 | - | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked") | |
3325 | - | let now = lastBlock.timestamp | |
3326 | - | $Tuple2((prologActions :+ IntegerEntry(keyLastRobberyTimeByDuck(duckAssetId), now)), 0) | |
3327 | 3184 | } | |
3328 | 3185 | } | |
3329 | 3186 | ||
3330 | 3187 | ||
3331 | 3188 | ||
3332 | 3189 | @Callable(i) | |
3333 | 3190 | func buyRoboDuck () = if (!(KS_ALLOW_ROBO_DUCKS)) | |
3334 | 3191 | then throw("Feature is turned off") | |
3335 | 3192 | else { | |
3336 | 3193 | let prologActions = prolog(i) | |
3337 | 3194 | if ((size(i.payments) != 1)) | |
3338 | 3195 | then throw("Exactly one payment required") | |
3339 | 3196 | else { | |
3340 | 3197 | let pmt = value(i.payments[0]) | |
3341 | 3198 | if ((pmt.assetId != usdtAssetId)) | |
3342 | 3199 | then throw("Allowed USDT payment only!") | |
3343 | 3200 | else if ((pmt.amount != ROBO_DUCK_USDT)) | |
3344 | 3201 | then throw((("Payment attached should be " + fixedPoint(ROBO_DUCK_USDT, 6)) + " USDT")) | |
3345 | 3202 | else { | |
3346 | 3203 | let nextNum = valueOrElse(getInteger(keyNextRoboDuck()), 0) | |
3347 | 3204 | let bytez = toBytes(nextNum) | |
3348 | 3205 | let name = ((ROBO_PREFIX + "-") + takeRight(toBase16String(bytez), 8)) | |
3349 | 3206 | let color = takeRight(toBase16String(sha256_16Kb(bytez)), 6) | |
3350 | 3207 | let issue = Issue(name, ("Robo Duck NFT for WavesLands game, background color = #" + color), 1, 0, false) | |
3351 | 3208 | let assetId = calculateAssetId(issue) | |
3352 | 3209 | $Tuple2(((((prologActions :+ IntegerEntry(keyNextRoboDuck(), (nextNum + 1))) :+ issue) :+ ScriptTransfer(i.originCaller, 1, assetId)) :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)), $Tuple2(toBase58String(assetId), color)) | |
3353 | 3210 | } | |
3354 | 3211 | } | |
3355 | 3212 | } | |
3356 | 3213 | ||
3357 | 3214 |
github/deemru/w8io/169f3d6 272.09 ms ◑