tx · 5BeNQiorLDbL2pTybbEdae74L8EtwFmKQ6QpnJMvrM4A 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm: -0.06400000 Waves 2023.06.28 20:30 [2642803] smart account 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm > SELF 0.00000000 Waves
{ "type": 13, "id": "5BeNQiorLDbL2pTybbEdae74L8EtwFmKQ6QpnJMvrM4A", "fee": 6400000, "feeAssetId": null, "timestamp": 1687973409065, "version": 2, "chainId": 84, "sender": "3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm", "senderPublicKey": "EVooykMNV691Venwp1dHUTBd7KWequzUcda57Wd3LQEX", "proofs": [ "4Re3Va2kBPK73dYQDRM3zRx4znwmuSkcpzyqxHuQcFvWenBsE95k7ovtHZY5TJDAigYbGp8j29gxyyYwQvgwN6Vw" ], "script": "base64:BgKYAQgCEgMKAQgSAwoBBBIAEgMKAQgSABIDCgEIEgQKAgEIEgQKAgEIEgQKAgICEgUKAwEBARIAEgQKAggIEgASBAoCAgISAwoBCBIDCgEIEgQKAggIEgMKARgSAwoBGBIECgIICBIECgIICBIDCgEIEgMKAQgSBQoDCAgIEgQKAggIEgMKAQESBQoDAQEIEgMKAQgSAwoBCBIAoAEACkxBTkRQUkVGSVgCBExBTkQACkRVQ0tQUkVGSVgCBERVQ0sACkFSVFBSRVNBTEUCB1BSRVNBTEUABk5VTVJFUwAGAA9EQUlMWVJFU0JZUElFQ0UAgPjSAQAJREFZTUlMTElTAIC4mSkADFdITVVMVElQTElFUgCAyK+gJQAPREVGQVVMVExPQ0FUSU9OAg9BZnJpY2FfRl9BZnJpY2EAEFJFU09VUkNFUFJJQ0VNSU4A1bUCAApFU1NFTExDT0VGAAoABU1BWEhQAGQACXByb2RUeXBlcwkAzAgCAhBGaXJzdCBBaWQgS2l0IEwxCQDMCAICEEZpcnN0IEFpZCBLaXQgTDIJAMwIAgIQRmlyc3QgQWlkIEtpdCBMMwkAzAgCAgtCYWNrcGFjayBMMQkAzAgCAgtCYWNrcGFjayBMMgkAzAgCAgtCYWNrcGFjayBMMwkAzAgCAg5Gb29kIFJhdGlvbiBMMQkAzAgCAg5Gb29kIFJhdGlvbiBMMgkAzAgCAg5Gb29kIFJhdGlvbiBMMwkAzAgCAgtKZXQgUGFjayBMMQkAzAgCAgtKZXQgUGFjayBMMgkAzAgCAgtKZXQgUGFjayBMMwkAzAgCAglTaGllbGQgTDEJAMwIAgIJU2hpZWxkIEwyCQDMCAICCVNoaWVsZCBMMwUDbmlsAApjb250aW5lbnRzCQDMCAICCEFtZXJpY2FzCQDMCAICBkV1cm9wZQkAzAgCAgRBc2lhCQDMCAICBkFmcmljYQkAzAgCAgdPY2VhbmlhBQNuaWwAEHByb2R1Y3Rpb25NYXRyaXgJAMwIAgISMV8xXzFfMl8yXzVfMV8xMF8wCQDMCAICEzJfMl8yXzRfNF8xMF8xXzEwXzAJAMwIAgITM18zXzNfNl82XzE1XzFfMTBfMAkAzAgCAhMyXzVfNV8yXzdfNV8yXzEwMF8xCQDMCAICFzRfMTBfMTBfNF8xNF8xMF8yXzEwMF8xCQDMCAICFzZfMTVfMTVfNl8yMV8xNV8yXzEwMF8xCQDMCAICEjFfMV8xXzFfMV84XzFfMTBfMgkAzAgCAhMyXzJfMl8yXzJfMTZfMV8xMF8yCQDMCAICEzNfM18zXzNfM18yNF8xXzEwXzIJAMwIAgITOV85XzFfNV81XzFfNV8xMDBfMwkAzAgCAhcxOF8xOF8yXzEwXzEwXzJfNV8xMDBfMwkAzAgCAhcyN18yN18zXzE1XzE1XzNfNV8xMDBfMwkAzAgCAhIyXzJfMV8yXzJfMl8xXzEwXzQJAMwIAgISNF80XzJfNF80XzRfMV8xMF80CQDMCAICEjZfNl8zXzZfNl82XzFfMTBfNAUDbmlsABFyZWNpcGVJZHhQYWNrc2l6ZQAHAAt3aElkeExldmVscwAAAAh3aElkeFJlcwABAAh3aElkeE1hdAACAAl3aElkeFByb2QAAwAJd2hJZHhMT0ZUAAQACXZvbExvY2tlZAAAAAt2b2xPY2N1cGllZAABAAd2b2xGcmVlAAIACHZvbFRvdGFsAAMACmJwSWR4TGV2ZWwAAAAIYnBJZHhSZXMAAQAIYnBJZHhNYXQAAgAJYnBJZHhQcm9kAAMBCmdldFBrZ1NpemUBB3Byb2RJZHgJAQ1wYXJzZUludFZhbHVlAQkAkQMCCQC1CQIJAJEDAgUQcHJvZHVjdGlvbk1hdHJpeAUHcHJvZElkeAIBXwURcmVjaXBlSWR4UGFja3NpemUBEWtleUxhc3RUeElkQnlVc2VyAQRhZGRyCQCsAgICD2xhc3RUeElkQnlVc2VyXwUEYWRkcgEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQdhc3NldElkCQCsAgICCW5mdE93bmVyXwUHYXNzZXRJZAEaa2V5TGFuZEFzc2V0SWRUb0N1c3RvbU5hbWUBB2Fzc2V0SWQJAKwCAgIYbGFuZEN1c3RvbU5hbWVCeUFzc2V0SWRfBQdhc3NldElkARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQdhc3NldElkCQCsAgICC3N0YWtlZFRpbWVfBQdhc3NldElkARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQdhc3NldElkCQCsAgICC2luZnJhTGV2ZWxfBQdhc3NldElkASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIEdHlwZQdhc3NldElkCQC5CQIJAMwIAgINbGFuZEFydFN0YXR1cwkAzAgCBQR0eXBlCQDMCAIFB2Fzc2V0SWQFA25pbAIBXwEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMHbmZ0VHlwZQdhc3NldElkCW93bmVyQWRkcgkArAICCQCsAgIJAKwCAgkArAICCQCsAgICIHN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXJfBQduZnRUeXBlAgFfBQdhc3NldElkAgFfBQlvd25lckFkZHIBEmtleVdhcmVob3VzZUJ5TGFuZAELbGFuZEFzc2V0SWQJAKwCAgIKd2FyZUhvdXNlXwULbGFuZEFzc2V0SWQBFmtleVN0YWtlZFBpZWNlc0J5T3duZXIBCW93bmVyQWRkcgkArAICAhRzdGFrZWRQaWVjZXNCeU93bmVyXwUJb3duZXJBZGRyARprZXlEdWNrQXNzZXRJZFRvQ3VzdG9tTmFtZQEHYXNzZXRJZAkArAICAhhkdWNrQ3VzdG9tTmFtZUJ5QXNzZXRJZF8FB2Fzc2V0SWQBFmtleUFkZHJlc3NUb0N1c3RvbU5hbWUBBGFkZHIJAKwCAgIYYWNjb3VudEN1c3RvbU5hbWVCeUFkZHJfBQRhZGRyAQ9rZXlBZGRyZXNzUmVmQnkBBGFkZHIJAKwCAgIJYWNjUmVmQnlfBQRhZGRyARNrZXlBZGRyZXNzUmVmZXJyYWxzAQRhZGRyCQCsAgICDWFjY1JlZmVycmFsc18FBGFkZHIBEGtleUR1Y2tJZFRvT3duZXIBB2Fzc2V0SWQJAKwCAgIKZHVja093bmVyXwUHYXNzZXRJZAEUa2V5U3Rha2VkRHVja0J5T3duZXIBCW93bmVyQWRkcgkArAICAhJzdGFrZWREdWNrQnlPd25lcl8FCW93bmVyQWRkcgERa2V5QmFja3BhY2tCeUR1Y2sBC2R1Y2tBc3NldElkCQCsAgICCWJhY2tQYWNrXwULZHVja0Fzc2V0SWQBD2tleUR1Y2tMb2NhdGlvbgELZHVja0Fzc2V0SWQJAKwCAgINZHVja0xvY2F0aW9uXwULZHVja0Fzc2V0SWQBDWtleUR1Y2tIZWFsdGgBC2R1Y2tBc3NldElkCQCsAgICC2R1Y2tIZWFsdGhfBQtkdWNrQXNzZXRJZAEKa2V5QmxvY2tlZAACEGNvbnRyYWN0c0Jsb2NrZWQBFWtleVVzZXJHd2xSZWxlYXNlVGltZQEIdXNlckFkZHIJAKwCAgIaJXMlc19fdXNlckd3bFJlbGVhc2VUaW1lX18FCHVzZXJBZGRyAQ5rZXlFc1dhcmVob3VzZQACGmVtZXJnZW5jeVdhcmVob3VzZVByb2R1Y3RzAApsb2NJZHhUeXBlAAEACGxvY0lkeElkAAIBEmdldFJlY2lwZU1hdGVyaWFscwEGcmVjaXBlCgEGYWRkTWF0AgJhYwFqCQBkAgUCYWMJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZyZWNpcGUFAWoKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQZhZGRNYXQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABWNoYWluCQDJAQIJAMoBAggFBHRoaXMFYnl0ZXMAAQABAAt1c2R0QXNzZXRJZAQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAEghNp6sggDP07Ru8qO7ouTvMmC3Qtd+geWqNQj+agP/7kDCQAAAgEBVAUHJG1hdGNoMAEgVbHYn3KHgu/l41uNrAWrZd6aQ6EvFrsF8xq3h6XxxRgJAAIBAg1Vbmtub3duIGNoYWluABVkZWZhdWx0UmVzdEFkZHJlc3NTdHIEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDACIzNQUUN1dkZidmg0TGtQVW5yblUxejNqbmJBMXA5bTNXTmh2AwkAAAIBAVQFByRtYXRjaDACIzNNdW1rR0d6dENLQVhwV0RxeGtkZG9mcVhTVWJxUWt2U0p5CQACAQINVW5rbm93biBjaGFpbgARSW5mcmFVcGdyYWRlQ29zdFMEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAAgMivoCUDCQAAAgEBVAUHJG1hdGNoMACAwtcvCQACAQINVW5rbm93biBjaGFpbgADU0VQAgJfXwAFTVVMVDYAwIQ9AAVNVUxUOACAwtcvAAVTU0laRQAZAAVNU0laRQBkAAVMU0laRQDhAQAGWExTSVpFAJADAAdYWExTSVpFAPEEAQ9nZXRTdHJpbmdPckZhaWwCB2FkZHJlc3MDa2V5CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUHYWRkcmVzcwUDa2V5CQC5CQIJAMwIAgIKbWFuZGF0b3J5IAkAzAgCCQClCAEFB2FkZHJlc3MJAMwIAgIBLgkAzAgCBQNrZXkJAMwIAgIPIGlzIG5vdCBkZWZpbmVkBQNuaWwCAAARSWR4Q2ZnU3Rha2luZ0RhcHAAAQARSWR4Q2ZnRWNvbm9teURhcHAAAgAUSWR4Q2ZnR292ZXJuYW5jZURhcHAAAwANSWR4Q2ZnV2xnRGFwcAAEAQprZXlSZXN0Q2ZnAAIOJXNfX3Jlc3RDb25maWcBDmtleVJlc3RBZGRyZXNzAAIMJXNfX3Jlc3RBZGRyARFyZWFkUmVzdENmZ09yRmFpbAEEcmVzdAkAvAkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUEcmVzdAkBCmtleVJlc3RDZmcABQNTRVABGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIHcmVzdENmZwNpZHgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFB3Jlc3RDZmcFA2lkeAkArAICAipSZXN0IGNmZyBkb2Vzbid0IGNvbnRhaW4gYWRkcmVzcyBhdCBpbmRleCAJAKQDAQUDaWR4AAxyZXN0Q29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkBDmtleVJlc3RBZGRyZXNzAAUVZGVmYXVsdFJlc3RBZGRyZXNzU3RyAAdyZXN0Q2ZnCQERcmVhZFJlc3RDZmdPckZhaWwBBQxyZXN0Q29udHJhY3QAD3N0YWtpbmdDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFB3Jlc3RDZmcFEUlkeENmZ1N0YWtpbmdEYXBwAA9lY29ub215Q29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQdyZXN0Q2ZnBRFJZHhDZmdFY29ub215RGFwcAALZ292Q29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQdyZXN0Q2ZnBRRJZHhDZmdHb3Zlcm5hbmNlRGFwcAALd2xnQ29udHJhY3QJARhnZXRDb250cmFjdEFkZHJlc3NPckZhaWwCBQdyZXN0Q2ZnBQ1JZHhDZmdXbGdEYXBwAApyZWNMYW5kTnVtAAAAC3JlY0xhbmRTaXplAAEAC3JlY1RlcnJhaW5zAAIADHJlY0NvbnRpbmVudAADARFrZXlSZXNQcm9wb3J0aW9ucwACE3Jlc1R5cGVzUHJvcG9ydGlvbnMBFWtleVN0YWtlZExhbmRzQnlPd25lcgEJb3duZXJBZGRyCQCsAgICE3N0YWtlZExhbmRzQnlPd25lcl8FCW93bmVyQWRkcgEIYXNTdHJpbmcBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwBQFzCQACAQIYZmFpbCB0byBjYXN0IGludG8gU3RyaW5nAQVhc0ludAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgNJbnQEAW4FByRtYXRjaDAFAW4JAAIBAhVmYWlsIHRvIGNhc3QgaW50byBJbnQBD251bVBpZWNlc0J5U2l6ZQEIbGFuZFNpemUEByRtYXRjaDAFCGxhbmRTaXplAwkAAAICAVMFByRtYXRjaDAFBVNTSVpFAwkAAAICAU0FByRtYXRjaDAFBU1TSVpFAwkAAAICAUwFByRtYXRjaDAFBUxTSVpFAwkAAAICAlhMBQckbWF0Y2gwBQZYTFNJWkUDCQAAAgIDWFhMBQckbWF0Y2gwBQdYWExTSVpFCQACAQIRVW5rbm93biBsYW5kIHNpemUADWluY3ViYXRvckFkZHIEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQRWt0VnV4MlJoY2hTTjYzRHNEbzRiNG16NFFxektTZUR2AwkAAAIBAVQFByRtYXRjaDAFBHRoaXMJAAIBAg1Vbmtub3duIGNoYWluAAticmVlZGVyQWRkcgQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1BEVnVVNDVIN0VoNWRtdE5iblJOUlN0R3dVTEE3Tlk2SGIDCQAAAgEBVAUHJG1hdGNoMAUEdGhpcwkAAgECDVVua25vd24gY2hhaW4AA3B1YgEgT1PiGj9UqNadUk4THUYnVb2zU/Mse8lUVLD/Q8G0FCgACG1lZEtpdEhwCQDMCAIAHgkAzAgCADwJAMwIAgB4BQNuaWwAEUZJVkVNSU5VVEVTTUlMTElTAOCnEgAMUkVOQU1JTkdDT1NUAMCWsQIACk1BWE5BTUVMRU4AMgAVSW5mcmFVcGdyYWRlQ29zdFNVc2R0AICt4gQADEVYUE1BVEVSSUFMUwQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMACm3YLtqwcDCQAAAgEBVAUHJG1hdGNoMACqp4GzCQkAAgECDVVua25vd24gY2hhaW4AB0VYUFVTRFQEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAAgOWadwMJAAACAQFUBQckbWF0Y2gwAIDlmncJAAIBAg1Vbmtub3duIGNoYWluAAVGSVZFWAkAtgIBAAUAB1RXRU5UWVgJALYCAQAUAAhUV0VOVFkyWAkAtgIBCQBoAgAUABQACFRXRU5UWTNYCQC2AgEJAGgCCQBoAgAUABQAFAAIVFdFTlRZNFgJALYCAQkAaAIJAGgCCQBoAgAUABQAFAAUAAhUV0VOVFk1WAkAtgIBCQBoAgkAaAIJAGgCCQBoAgAUABQAFAAUABQAD1BSRVNBTEVOVU1MQU5EUwD0AwESa2V5TmV4dEZyZWVMYW5kTnVtAAILbmV4dExhbmROdW0BEGtleUxhbmRUb0Fzc2V0SWQBB2xhbmROdW0JAKwCAgIMbGFuZFRvQXNzZXRfBQdsYW5kTnVtARprZXlMYW5kQ3VzdG9tTmFtZVRvQXNzZXRJZAEEbmFtZQkArAICAhFsYW5kQnlDdXN0b21OYW1lXwUEbmFtZQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgdhc3NldElkCW93bmVyQWRkcgkArAICCQCsAgIJAKwCAgIcaW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyXwUHYXNzZXRJZAIBXwUJb3duZXJBZGRyASVrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQXNzZXRJZEFuZE93bmVyAwR0eXBlB2Fzc2V0SWQJb3duZXJBZGRyCQC5CQIJAMwIAgIibGFuZEFydFN0YXR1c0J5VHlwZUFzc2V0SWRBbmRPd25lcgkAzAgCBQR0eXBlCQDMCAIFB2Fzc2V0SWQJAMwIAgUJb3duZXJBZGRyBQNuaWwCAV8BEWtleUxhbmROdW1Ub093bmVyAQdsYW5kTnVtCQCsAgICCmxhbmRPd25lcl8FB2xhbmROdW0BGmtleUR1Y2tDdXN0b21OYW1lVG9Bc3NldElkAQRuYW1lCQCsAgICEWR1Y2tCeUN1c3RvbU5hbWVfBQRuYW1lARZrZXlDdXN0b21OYW1lVG9BZGRyZXNzAQRuYW1lCQCsAgICFGFjY291bnRCeUN1c3RvbU5hbWVfBQRuYW1lAQlrZXlPbGRpZXMAAgpvbGRpZXNMaXN0AAtjbGFpbU1vZGVXaAAAAA1jbGFpbU1vZGVEdWNrAAEAE2NsYWltTW9kZVdoVGhlbkR1Y2sAAgAIZmxIZWFsdGgAAAALZmxUaW1lc3RhbXAABQAHZmxCb251cwAGAAtmbFByb2RzVXNlZAAHAQduZnROYW1lAgdsYW5kTnVtCGxhbmRTaXplCQCsAgIJAKwCAgUKTEFORFBSRUZJWAUHbGFuZE51bQUIbGFuZFNpemUBE2Rpc3RyaWJ1dGVCeVdlaWdodHMCBXRvdGFsB3dlaWdodHMEA3N1bQkAZAIJAGQCCQBkAgkAZAIJAGQCCQCRAwIFB3dlaWdodHMAAAkAkQMCBQd3ZWlnaHRzAAEJAJEDAgUHd2VpZ2h0cwACCQCRAwIFB3dlaWdodHMAAwkAkQMCBQd3ZWlnaHRzAAQJAJEDAgUHd2VpZ2h0cwAFAwkAZwIAAAUDc3VtCQACAQIQWmVybyB3ZWlnaHRzIHN1bQQFbm9ybTYJAGsDBQV0b3RhbAUFTVVMVDYFA3N1bQoBCm5vcm1hbGl6ZXICA2FjYwRlbGVtCQDNCAIFA2FjYwkAawMFBGVsZW0FBW5vcm02BQVNVUxUNgoAAiRsBQd3ZWlnaHRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpub3JtYWxpemVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGARJnZXROZWVkZWRNYXRlcmlhbHMBBXRvdGFsBAVwcm9wcwkAtQkCCQEFdmFsdWUBCQCiCAEJARFrZXlSZXNQcm9wb3J0aW9ucwACAV8DCQECIT0CCQCQAwEFBXByb3BzBQZOVU1SRVMJAAIBAhZXcm9uZyBwcm9wb3J0aW9ucyBkYXRhBAFyCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAACQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwABCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwACCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwADCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAECQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAFBQNuaWwJARNkaXN0cmlidXRlQnlXZWlnaHRzAgUFdG90YWwFAXIBEXN1YnRyYWN0TWF0ZXJpYWxzAwxzaG91bGRVc2VNYXQDaGFzCXRvdGFsTmVlZAQEbmVlZAkBEmdldE5lZWRlZE1hdGVyaWFscwEFCXRvdGFsTmVlZAoBCnN1YnRyYWN0b3ICA2FjYwNpZHgEBnJlc3VsdAkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNoYXMFA2lkeAkAkQMCBQRuZWVkBQNpZHgDCQBmAgAABQZyZXN1bHQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIYTm90IGVub3VnaCBtYXRlcmlhbCBpZHg9CQCkAwEFA2lkeAILLCB5b3UgaGF2ZSAJAJEDAgUDaGFzBQNpZHgCCywgYnV0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AJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGCQC5CQIFAXICAV8BEXVwZGF0ZVByb3BvcnRpb25zAw10ZXJyYWluQ291bnRzDWxhbmRTaXplSW5kZXgEc2lnbgQIcHJvcExpc3QJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBCQERa2V5UmVzUHJvcG9ydGlvbnMAAgswXzBfMF8wXzBfMAIBXwkBGXVwZGF0ZVByb3BvcnRpb25zSW50ZXJuYWwEBQhwcm9wTGlzdAUNdGVycmFpbkNvdW50cwUNbGFuZFNpemVJbmRleAUEc2lnbgENY291bnRUZXJyYWlucwEIdGVycmFpbnMJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBQQABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUIAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFDAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBRAABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUUAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFGAAEFA25pbAEGYWRkUmVzBQpjdXJyZW50UmVzDXRlcnJhaW5Db3VudHMJZGVsdGFUaW1lDWxhbmRTaXplSW5kZXgXZGFpbHlCeVBpZWNlV2l0aEJvbnVzZXMKAQVhZGRlcgIDYWNjAWkECXJlc09mVHlwZQkAaAIJAGgCCQBrAwUJZGVsdGFUaW1lBRdkYWlseUJ5UGllY2VXaXRoQm9udXNlcwUJREFZTUlMTElTCQCRAwIFDXRlcnJhaW5Db3VudHMFAWkFDWxhbmRTaXplSW5kZXgJAM0IAgUDYWNjCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKY3VycmVudFJlcwUBaQUJcmVzT2ZUeXBlBAFyCgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEFYWRkZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYJALkJAgUBcgIBXwEJdmlydENsYWltBA10ZXJyYWluQ291bnRzCWRlbHRhVGltZQ1sYW5kU2l6ZUluZGV4F2RhaWx5QnlQaWVjZVdpdGhCb251c2VzCgEFYWRkZXICA2FjYwFpBAlyZXNPZlR5cGUJAGgCCQBoAgkAawMFCWRlbHRhVGltZQUXZGFpbHlCeVBpZWNlV2l0aEJvbnVzZXMFCURBWU1JTExJUwkAkQMCBQ10ZXJyYWluQ291bnRzBQFpBQ1sYW5kU2l6ZUluZGV4CQCUCgIJAM0IAggFA2FjYwJfMQUJcmVzT2ZUeXBlCQBkAggFA2FjYwJfMgUJcmVzT2ZUeXBlCgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgUDbmlsAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBBWFkZGVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAQ1kaXN0cmlidXRlUmVzBAxjdXJyZW50V2hSZXMOY3VycmVudFBhY2tSZXMKcmVzVG9DbGFpbQt3aFNwYWNlTGVmdAQOcmVzTGlzdFRvQ2xhaW0IBQpyZXNUb0NsYWltAl8xBAxyZXNBbVRvQ2xhaW0IBQpyZXNUb0NsYWltAl8yAwkAAAIFDHJlc0FtVG9DbGFpbQAACQCUCgIJALkJAgUMY3VycmVudFdoUmVzAgFfCQC5CQIFDmN1cnJlbnRQYWNrUmVzAgFfAwkAZwIFC3doU3BhY2VMZWZ0BQxyZXNBbVRvQ2xhaW0KAQhhZGRMaXN0cwIDYWNjAWkJAM0IAgUDYWNjCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUMY3VycmVudFdoUmVzBQFpCQCRAwIFDnJlc0xpc3RUb0NsYWltBQFpBAFyCgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEIYWRkTGlzdHMCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYJAJQKAgkAuQkCBQFyAgFfCQC5CQIFDmN1cnJlbnRQYWNrUmVzAgFfCgEMYWRkUGFydExpc3RzAgNhY2MBaQQGd2hQYXJ0CQBrAwkAkQMCBQ5yZXNMaXN0VG9DbGFpbQUBaQULd2hTcGFjZUxlZnQFDHJlc0FtVG9DbGFpbQkAlAoCCQDNCAIIBQNhY2MCXzEJAKQDAQkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQxjdXJyZW50V2hSZXMFAWkFBndoUGFydAkAzQgCCAUDYWNjAl8yCQCkAwEJAGUCCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmN1cnJlbnRQYWNrUmVzBQFpCQCRAwIFDnJlc0xpc3RUb0NsYWltBQFpBQZ3aFBhcnQEAXIKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQNu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ZVRvdGFsVm9sdW1lAQUJdm9sUHJlZml4BAV3aFN0cgkBC3ZhbHVlT3JFbHNlAgkAoggBBQV3aEtleQkArAICBQl2b2xQcmVmaXgCGzowXzBfMF8wXzBfMDowXzBfMF8wXzBfMDo6MAQCd2gJALwJAgUFd2hTdHICAToECndoT2NjdXBpZWQJARdnZXRXYXJlaG91c2VPY2N1cGllZFZvbAEFAndoBAZ3aExvZnQDCQBmAgAFCQCQAwEFAndoCQC5CQIJAMwIAgIBMAkAzAgCCQCkAwEFCndoT2NjdXBpZWQJAMwIAgkApAMBCQBlAgUHd2hUb3RhbAUKd2hPY2N1cGllZAkAzAgCCQCkAwEFB3doVG90YWwFA25pbAIBXwQEbG9mdAkAtQkCCQCRAwIFAndoBQl3aElkeExPRlQCAV8ECHdoTG9ja2VkCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAUJdm9sTG9ja2VkBANvY2MDCQBmAgkAkAMBBQRsb2Z0AAEJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAUKd2hPY2N1cGllZAkAuQkCCQDMCAIJAKQDAQUId2hMb2NrZWQJAMwIAgkApAMBBQNvY2MJAMwIAgkApAMBCQBlAgkAZQIFB3doVG90YWwFCHdoTG9ja2VkBQNvY2MJAMwIAgkApAMBBQd3aFRvdGFsBQNuaWwCAV8JAMwIAgkAkQMCBQJ3aAULd2hJZHhMZXZlbHMJAMwIAgMJAAACCQCQAwEJALUJAgkAkQMCBQJ3aAUId2hJZHhSZXMCAV8FBk5VTVJFUwkAkQMCBQJ3aAUId2hJZHhSZXMCCzBfMF8wXzBfMF8wCQDMCAIDCQAAAgkAkAMBCQC1CQIJAJEDAgUCd2gFCHdoSWR4TWF0AgFfBQZOVU1SRVMJAJEDAgUCd2gFCHdoSWR4TWF0AgswXzBfMF8wXzBfMAkAzAgCCQCRAwIFAndoBQl3aElkeFByb2QJAMwIAgUGd2hMb2Z0BQNuaWwBFWdldFdhcmVob3VzZVNwYWNlTGVmdAEJY3VycmVudFdoBAtvY2N1cGllZFZvbAkBF2dldFdhcmVob3VzZU9jY3VwaWVkVm9sAQUJY3VycmVudFdoBA9jdXJyV2hMb2NrZWRWb2wJAQ1wYXJzZUludFZhbHVlAQkAkQMCCQC1CQIJAJEDAgUJY3VycmVudFdoBQl3aElkeExPRlQCAV8FCXZvbExvY2tlZAkAZQIJAGUCCQEXZ2V0V2FyZWhvdXNlVG90YWxWb2x1bWUBCQCRAwIFCWN1cnJlbnRXaAULd2hJZHhMZXZlbHMFC29jY3VwaWVkVm9sBQ9jdXJyV2hMb2NrZWRWb2wBCHRvVm9sdW1lAgZhbW91bnQHcGtnU2l6ZQQEcGtncwMJAGcCBQZhbW91bnQAAAkAaQIJAGUCCQBkAgUGYW1vdW50BQdwa2dTaXplAAEFB3BrZ1NpemUJAQEtAQkAaQIJAGUCCQBkAgkBAS0BBQZhbW91bnQFB3BrZ1NpemUAAQUHcGtnU2l6ZQkAaAIFBHBrZ3MFBU1VTFQ4AQltb3ZlU3R1ZmYDCmNhcmdvUGFydHMJY3VycmVudFdoC2N1cnJlbnRQYWNrAwkBAiE9AgkAkAMBBQpjYXJnb1BhcnRzAAMJAAIBAjRjYXJnb0xpc3RTdHIgc2hvdWxkIGNvbnRhaW4gZXhhY3RseSAyICc6JyBzZXBhcmF0b3JzBAhyZXNQYXJ0cwkAtQkCCQCRAwIFCmNhcmdvUGFydHMAAAIBXwQIbWF0UGFydHMJALUJAgkAkQMCBQpjYXJnb1BhcnRzAAECAV8ECXByb2RQYXJ0cwMJAAACCQCRAwIFCmNhcmdvUGFydHMAAgIABQNuaWwJALUJAgkAkQMCBQpjYXJnb1BhcnRzAAICAV8DCQECIT0CCQCQAwEFCHJlc1BhcnRzBQZOVU1SRVMJAAIBAiBBbGwgNiByZXNvdXJjZXMgc2hvdWxkIGJlIHBhc3NlZAMJAQIhPQIJAJADAQUIbWF0UGFydHMFBk5VTVJFUwkAAgECIEFsbCA2IG1hdGVyaWFscyBzaG91bGQgYmUgcGFzc2VkBAt3aFNwYWNlTGVmdAkBFWdldFdhcmVob3VzZVNwYWNlTGVmdAEFCWN1cnJlbnRXaAQJY3VycldoUmVzCQC1CQIJAJEDAgUJY3VycmVudFdoBQh3aElkeFJlcwIBXwQJY3VycldoTWF0CQC1CQIJAJEDAgUJY3VycmVudFdoBQh3aElkeE1hdAIBXwQKY3VycldoUHJvZAMJAAACCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kAgAFA25pbAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kAgFfBA5jdXJyZW50UGFja1JlcwkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwIBXwQOY3VycmVudFBhY2tNYXQJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8ED2N1cnJlbnRQYWNrUHJvZAMJAAACCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QCAAUDbmlsCQC1CQIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAIBXwoBA212UgIDYWNjBGl0ZW0EAWkIBQNhY2MCXzEEAmFtCQENcGFyc2VJbnRWYWx1ZQEFBGl0ZW0EA3docgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWN1cnJXaFJlcwUBaQQDYnByCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOY3VycmVudFBhY2tSZXMFAWkDCQAAAgUCYW0AAAkAlgoECQBkAgUBaQABCQDNCAIIBQNhY2MCXzIJAJEDAgUJY3VycldoUmVzBQFpCQDNCAIIBQNhY2MCXzMJAJEDAgUOY3VycmVudFBhY2tSZXMFAWkIBQNhY2MCXzQDCQBmAgUCYW0AAAMJAGYCBQJhbQUDYnByCQACAQkArAICCQCsAgIJAKwCAgkArAICAhBBdHRlbXB0IHRvIHRha2UgBQRpdGVtAhkgZnJvbSBiYWNrcGFjaywgYnV0IG9ubHkgCQCkAwEFA2JwcgIKIGF2YWlsYWJsZQkAlgoECQBkAgUBaQABCQDNCAIIBQNhY2MCXzIJAKQDAQkAZAIFA3docgUCYW0JAM0IAggFA2FjYwJfMwkApAMBCQBlAgUDYnByBQJhbQkAZAIIBQNhY2MCXzQFAmFtAwkAZgIJAQEtAQUCYW0FA3docgkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgIQQXR0ZW1wdCB0byB0YWtlIAkApAMBCQEBLQEFAmFtAhogZnJvbSB3YXJlaG91c2UsIGJ1dCBvbmx5IAkApAMBBQN3aHICCiBhdmFpbGFibGUJAJYKBAkAZAIFAWkAAQkAzQgCCAUDYWNjAl8yCQCkAwEJAGQCBQN3aHIFAmFtCQDNCAIIBQNhY2MCXzMJAKQDAQkAZQIFA2JwcgUCYW0JAGQCCAUDYWNjAl80BQJhbQQBcgoAAiRsBQhyZXNQYXJ0cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJYKBAAABQNuaWwFA25pbAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQNtdlICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYKAQNtdk0CA2FjYwRpdGVtBAFpCAUDYWNjAl8xBAJhbQkBDXBhcnNlSW50VmFsdWUBBQRpdGVtBAN3aG0JAQ1wYXJzZUludFZhbHVlAQkAkQMCBQljdXJyV2hNYXQFAWkEA2JwbQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDmN1cnJlbnRQYWNrTWF0BQFpAwkAAAIFAmFtAAAJAJYKBAkAZAIFAWkAAQkAzQgCCAUDYWNjAl8yCQCRAwIFCWN1cnJXaE1hdAUBaQkAzQgCCAUDYWNjAl8zCQCRAwIFDmN1cnJlbnRQYWNrTWF0BQFpCAUDYWNjAl80AwkAZgIFAmFtAAADCQBmAgUCYW0FA2JwbQkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgIQQXR0ZW1wdCB0byB0YWtlIAUEaXRlbQIZIGZyb20gYmFja3BhY2ssIGJ1dCBvbmx5IAkApAMBBQNicG0CCiBhdmFpbGFibGUJAJYKBAkAZAIFAWkAAQkAzQgCCAUDYWNjAl8yCQCkAwEJAGQCBQN3aG0FAmFtCQDNCAIIBQNhY2MCXzMJAKQDAQkAZQIFA2JwbQUCYW0JAGQCCAUDYWNjAl80BQJhbQMJAGYCCQEBLQEFAmFtBQN3aG0JAAIBCQCsAgIJAKwCAgkArAICCQCsAgICEEF0dGVtcHQgdG8gdGFrZSAJAKQDAQkBAS0BBQJhbQIaIGZyb20gd2FyZWhvdXNlLCBidXQgb25seSAJAKQDAQUDd2htAgogYXZhaWxhYmxlCQCWCgQJAGQCBQFpAAEJAM0IAggFA2FjYwJfMgkApAMBCQBkAgUDd2htBQJhbQkAzQgCCAUDYWNjAl8zCQCkAwEJAGUCBQNicG0FAmFtCQBkAggFA2FjYwJfNAUCYW0EAW0KAAIkbAUIbWF0UGFydHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCWCgQAAAUDbmlsBQNuaWwIBQFyAl80CgEFJGYxXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQNtdk0CBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjFfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjFfMgIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIJAQUkZjFfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYKAQNtdlACA2FjYwRpdGVtBAFpCAUDYWNjAl8xBAdwa2dTaXplCQEKZ2V0UGtnU2l6ZQEFAWkEAmFtCQENcGFyc2VJbnRWYWx1ZQEFBGl0ZW0EA3docAMJAGYCCQCQAwEFCmN1cnJXaFByb2QFAWkJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpjdXJyV2hQcm9kBQFpAAAEA2JwcAMJAGYCCQCQAwEFD2N1cnJlbnRQYWNrUHJvZAUBaQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFD2N1cnJlbnRQYWNrUHJvZAUBaQAAAwkAAAIFAmFtAAAJAJYKBAkAZAIFAWkAAQkAzQgCCAUDYWNjAl8yCQCkAwEFA3docAkAzQgCCAUDYWNjAl8zCQCkAwEFA2JwcAgFA2FjYwJfNAMJAGYCBQJhbQAAAwkAZgIFAmFtBQNicHAJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICEEF0dGVtcHQgdG8gdGFrZSAFBGl0ZW0CGSBmcm9tIGJhY2twYWNrLCBidXQgb25seSAJAKQDAQUDYnBwAgogYXZhaWxhYmxlBAhkZWx0YVZvbAkAZQIJAQh0b1ZvbHVtZQIJAGQCBQN3aHAFAmFtBQdwa2dTaXplCQEIdG9Wb2x1bWUCBQN3aHAFB3BrZ1NpemUJAJYKBAkAZAIFAWkAAQkAzQgCCAUDYWNjAl8yCQCkAwEJAGQCBQN3aHAFAmFtCQDNCAIIBQNhY2MCXzMJAKQDAQkAZQIF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bnMJAMwIAgUJY29udGluZW50BQNuaWwCAV8AAQAABwQHYXNzZXRJZAkAuAgBBQVpc3N1ZQQCaWQJANgEAQUHYXNzZXRJZAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQESa2V5TmV4dEZyZWVMYW5kTnVtAAkAZAIFB2ZyZWVOdW0AAQkAzAgCBQVpc3N1ZQkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5TGFuZFRvQXNzZXRJZAEFB2xhbmROdW0FAmlkCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQJpZAUIdXNlckFkZHIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleUxhbmROdW1Ub093bmVyAQUHbGFuZE51bQUIdXNlckFkZHIJAMwIAgkBDEludGVnZXJFbnRyeQIJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQUCaWQAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIFAmlkBQh1c2VyQWRkcgAACQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMFBmNhbGxlcgABBQdhc3NldElkBQNuaWwJAJQKAgUCaWQFCWNvbnRpbmVudAEMZmxpZ2h0Q29tbW9uAwh1c2VyQWRkcgdtZXNzYWdlA3NpZwMJAQEhAQkAxBMDBQdtZXNzYWdlBQNzaWcFA3B1YgkAAgECGHNpZ25hdHVyZSBkb2VzIG5vdCBtYXRjaAQFcGFydHMJALUJAgkAsAkBBQdtZXNzYWdlAgE7BAlmbGlnaHRMb2cJALUJAgkAkQMCBQVwYXJ0cwAAAgF8BAJocAkAtQkCCQCRAwIFCWZsaWdodExvZwUIZmxIZWFsdGgCAV8EBWN1ckhQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaHAAAAQFbmV3SFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAABBAtuZXdMb2NUeFZlcgkAtQkCCQCRAwIFBXBhcnRzAAECAToEC25ld0xvY2F0aW9uCQCRAwIFC25ld0xvY1R4VmVyAAAEBHRpbWUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQlmbGlnaHRMb2cFC2ZsVGltZXN0YW1wAwMJAGYCBQR0aW1lCQBkAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFEUZJVkVNSU5VVEVTTUlMTElTBgkAZgIJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMFBHRpbWUJAAIBCQCsAgIJAKwCAgkArAICAhxzaWduYXR1cmUgb3V0ZGF0ZWQ6IGxvZ1RpbWU9CQCkAwEFBHRpbWUCCSwgYmNUaW1lPQkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQJdHhGcm9tTXNnCQCRAwIFC25ld0xvY1R4VmVyAAEEBmxhc3RUeAkBC3ZhbHVlT3JFbHNlAgkAoggBCQERa2V5TGFzdFR4SWRCeVVzZXIBBQh1c2VyQWRkcgIAAwkBAiE9AgUGbGFzdFR4BQl0eEZyb21Nc2cJAAIBCQCsAgIJAKwCAgkArAICAh5UeCBpZHMgZG9uJ3QgbWF0Y2ghIEluIHN0YXRlOiAFBmxhc3RUeAIKLCBpbiBtc2c6IAUJdHhGcm9tTXNnBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFCHVzZXJBZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQEDG9sZEZyb21TdGF0ZQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAMJAQIhPQIFDG9sZEZyb21TdGF0ZQUFY3VySFAJAAIBCQCsAgIJAKwCAgkArAICAgpvbGRIZWFsdGg9CQCkAwEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoAGQCLyBmcm9tIHN0YXRlIGRvZXMgbm90IG1hdGNoIG9uZSBmcm9tIGZsaWdodCBsb2c9CQCkAwEFBWN1ckhQAwkAZwIAAAUFY3VySFAJAAIBAh5Zb3UgY2FuJ3QgZmx5IHdpdGggemVybyBoZWFsdGgEBWJvbnVzAwkAZgIJAJADAQUJZmxpZ2h0TG9nBQdmbEJvbnVzCQCRAwIFCWZsaWdodExvZwUHZmxCb251cwIABAhwcm9kVXNlZAMJAGYCCQCQAwEFCWZsaWdodExvZwULZmxQcm9kc1VzZWQJAJEDAgUJZmxpZ2h0TG9nBQtmbFByb2RzVXNlZAIABApzZW50QW1vdW50AwMJAGYCBQVuZXdIUAAACQAAAgUFYm9udXMCASQHCQEFYXNJbnQBCQD8BwQFDHJlc3RDb250cmFjdAINc2VuZFVzZHRQcml6ZQkAzAgCBQh1c2VyQWRkcgUDbmlsBQNuaWwAAAkAlwoFBQVuZXdIUAULZHVja0Fzc2V0SWQFCnNlbnRBbW91bnQFC25ld0xvY2F0aW9uBQhwcm9kVXNlZAEQZXhwZWRpdGlvbkNvbW1vbgQGY2FsbGVyBHR4SWQHbWVzc2FnZQNzaWcECHVzZXJBZGRyCQClCAEFBmNhbGxlcgQBZgkBDGZsaWdodENvbW1vbgMFCHVzZXJBZGRyBQdtZXNzYWdlBQNzaWcECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBCAUBZgJfMgQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEIBQFmAl8yBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW1MaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBAZuZXdNYXQJALkJAgkBEXN1YnRyYWN0TWF0ZXJpYWxzAwYFBW1MaXN0BQxFWFBNQVRFUklBTFMCAV8EB25ld1Byb2QJARBzdWJ0cmFjdFByb2R1Y3RzAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kCAUBZgJfNQMJAGcCAAAIBQFmAl8xCQCVCgMJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtleUhlYWx0aAAACQDMCAIJAQtTdHJpbmdFbnRyeQIFBWJwS2V5CQC5CQIJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAkAzAgCBQduZXdQcm9kBQNuaWwCAToFA25pbAIAAAAEAWUJARJleHBlZGl0aW9uSW50ZXJuYWwCBQZjYWxsZXIFBHR4SWQEAmlkCAgFAWUCXzICXzEJAJUKAwkAzQgCCQDNCAIJAM0IAggFAWUCXzEJAQtTdHJpbmdFbnRyeQIJAQ9rZXlEdWNrTG9jYXRpb24BCAUBZgJfMgkAuQkCCQDMCAIICAUBZQJfMgJfMgkAzAgCAgFMCQDMCAIFAmlkBQNuaWwCAV8JAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgIBQFmAl8xCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgUGbmV3TWF0CQDMCAIFB25ld1Byb2QFA25pbAIBOgUCaWQIBQFmAl8zAQxhcHBseUJvbnVzZXMCC2xhbmRBc3NldElkBnBpZWNlcwQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAECWFydFBpZWNlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAAABARhZGQ2CQBpAgUKaW5mcmFMZXZlbAAGBARhZGQ3CQBpAgUKaW5mcmFMZXZlbAAHCQBkAgkAZAIFD0RBSUxZUkVTQllQSUVDRQkAawMFD0RBSUxZUkVTQllQSUVDRQkAZAIJAGQCBQppbmZyYUxldmVsBQRhZGQ2CQBoAgACBQRhZGQ3AAUJAGsDBQ9EQUlMWVJFU0JZUElFQ0UFCWFydFBpZWNlcwkAaAIFBnBpZWNlcwAFARRjaGVja0NsYWltQ29uZGl0aW9ucwMEYWRkcgljbGFpbU1vZGUNbGFuZEFzc2V0SWRJbgQNJHQwMjQ0NDYyNDk4NQMJAAACBQljbGFpbU1vZGUFC2NsYWltTW9kZVdoCQCUCgIFDWxhbmRBc3NldElkSW4JAQt2YWx1ZU9yRWxzZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIABAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OBANsb2MJALUJAgkBBXZhbHVlAQULY3VyTG9jYXRpb24CAV8DCQECIT0CCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIBTAkAAgEJAKwCAgkArAICAhZEdWNrIGxvY2F0aW9uIHR5cGUgaXMgCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIRLCBidXQgc2hvdWxkIGJlIEwJAJQKAgkAkQMCBQNsb2MFCGxvY0lkeElkBQtkdWNrQXNzZXRJZAQLbGFuZEFzc2V0SWQIBQ0kdDAyNDQ0NjI0OTg1Al8xBAZkdWNrSWQIBQ0kdDAyNDQ0NjI0OTg1Al8yBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBAlzYXZlZFRpbWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBQd0aW1lS2V5CQCsAgIJAKwCAgIFTGFuZCAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfCQCWCgQFBmR1Y2tJZAULbGFuZEFzc2V0SWQFAWQFCXNhdmVkVGltZQEQY2xhaW1SZXNJbnRlcm5hbAQEYWRkcgZhbW91bnQJY2xhaW1Nb2RlDWxhbmRBc3NldElkSW4DCQBmAgAABQZhbW91bnQJAAIBAg9OZWdhdGl2ZSBhbW91bnQEAWMJARRjaGVja0NsYWltQ29uZGl0aW9ucwMFBGFkZHIFCWNsYWltTW9kZQUNbGFuZEFzc2V0SWRJbgQIbGFuZFNpemUJAJEDAggFAWMCXzMFC3JlY0xhbmRTaXplBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAggFAWMCXzMFC3JlY1RlcnJhaW5zBAlkZWx0YVRpbWUJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAgFAWMCXzQDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBCAUBYwJfNAIMLCBjdXJyZW50ID0gCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBBQhsYW5kU2l6ZQQWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkBDGFwcGx5Qm9udXNlcwIIBQFjAl8yBQZwaWVjZXMECGF2YWlsUmVzCQBrAwUJZGVsdGFUaW1lCQBoAgUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQUGcGllY2VzBQlEQVlNSUxMSVMDCQBmAgUGYW1vdW50BQhhdmFpbFJlcwkAAgEJAKwCAgkArAICCQCsAgICIk5vdCBlbm91Z2ggcmVzb3VyY2VzLCBhdmFpbGFibGUgPSAJAKQDAQUIYXZhaWxSZXMCDiwgcmVxdWVzdGVkID0gCQCkAwEFBmFtb3VudAQMbmV3RGVsdGFUaW1lCQBrAwkAZQIFCGF2YWlsUmVzBQZhbW91bnQFCURBWU1JTExJUwkAaAIFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UFBnBpZWNlcwQMbmV3VGltZXN0YW1wCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFDG5ld0RlbHRhVGltZQQJbGFuZEluZGV4CQBpAgUGcGllY2VzBQVTU0laRQQKcmVzVG9DbGFpbQkBCXZpcnRDbGFpbQQFDXRlcnJhaW5Db3VudHMJAGUCBQlkZWx0YVRpbWUFDG5ld0RlbHRhVGltZQUJbGFuZEluZGV4BRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBAV3aEtleQkBEmtleVdhcmVob3VzZUJ5TGFuZAEIBQFjAl8yBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQgFAWMCXzIAAAQJY3VycmVudFdoCQEMZ2V0V2FyZWhvdXNlAwUFd2hLZXkFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAQEbG9mdAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhMT0ZUAgFfBAt3aFNwYWNlTGVmdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUDAwkAAAIFCWNsYWltTW9kZQULY2xhaW1Nb2RlV2gJAGYCBQZhbW91bnQFC3doU3BhY2VMZWZ0BwkAAgEJAKwCAgkArAICAgVPbmx5IAkApAMBBQt3aFNwYWNlTGVmdAIYIHNwYWNlIGxlZnQgaW4gd2FyZWhvdXNlBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQgFAWMCXzEEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQOY3VycmVudFBhY2tSZXMJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMCAV8EDGN1cnJlbnRXaFJlcwkAtQkCCQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMCAV8EDSR0MDI3MzU5MjgyMzADCQAAAgUJY2xhaW1Nb2RlBQtjbGFpbU1vZGVXaAkAlgoECQEGYWRkUmVzBQUMY3VycmVudFdoUmVzBQ10ZXJyYWluQ291bnRzCQBlAgUJZGVsdGFUaW1lBQxuZXdEZWx0YVRpbWUFCWxhbmRJbmRleAUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAULdm9sT2NjdXBpZWQIBQpyZXNUb0NsYWltAl8yCQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUIBQpyZXNUb0NsYWltAl8yAwkAAAIFCWNsYWltTW9kZQUNY2xhaW1Nb2RlRHVjawkAlgoECQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMJAQZhZGRSZXMFBQ5jdXJyZW50UGFja1JlcwUNdGVycmFpbkNvdW50cwkAZQIFCWRlbHRhVGltZQUMbmV3RGVsdGFUaW1lBQlsYW5kSW5kZXgFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUEBWRpc3RyCQENZGlzdHJpYnV0ZVJlcwQFDGN1cnJlbnRXaFJlcwUOY3VycmVudFBhY2tSZXMFCnJlc1RvQ2xhaW0FC3doU3BhY2VMZWZ0BAR3aEFtCQCXAwEJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUJAMwIAggFCnJlc1RvQ2xhaW0CXzIFA25pbAkAlgoECAUFZGlzdHICXzEIBQVkaXN0cgJfMgkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAUEd2hBbQkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQd2b2xGcmVlBQR3aEFtBAV3aFJlcwgFDSR0MDI3MzU5MjgyMzACXzEEBWJwUmVzCAUNJHQwMjczNTkyODIzMAJfMgQFbG9mdE8IBQ0kdDAyNzM1OTI4MjMwAl8zBAVsb2Z0RggFDSR0MDI3MzU5MjgyMzACXzQJAJcKBQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBCAUBYwJfMgUMbmV3VGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgIBQFjAl8yBQRhZGRyBQxuZXdUaW1lc3RhbXAFA25pbAUFYnBLZXkJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCBQVicFJlcwkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAUFd2hLZXkJAMwIAgkAkQMCBQljdXJyZW50V2gFC3doSWR4TGV2ZWxzCQDMCAIFBXdoUmVzCQDMCAIJAJEDAgUJY3VycmVudFdoBQh3aElkeE1hdAkAzAgCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kCQDMCAIJALkJAgkAzAgCCQCRAwIFBGxvZnQFCXZvbExvY2tlZAkAzAgCCQCkAwEFBWxvZnRPCQDMCAIJAKQDAQUFbG9mdEYJAMwIAgkAkQMCBQRsb2Z0BQh2b2xUb3RhbAUDbmlsAgFfBQNuaWwBCGNsYWltQWxsBARhZGRyC2xhbmRBc3NldElkBnBpZWNlcwljbGFpbU1vZGUEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBBXZhbHVlAQkAnwgBBQd0aW1lS2V5BAhhdmFpbFJlcwkAaAIJAGsDCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFCXNhdmVkVGltZQkBDGFwcGx5Qm9udXNlcwIFC2xhbmRBc3NldElkBQZwaWVjZXMFCURBWU1JTExJUwUGcGllY2VzCQEQY2xhaW1SZXNJbnRlcm5hbAQFBGFkZHIFCGF2YWlsUmVzBQljbGFpbU1vZGUFC2xhbmRBc3NldElkAQ11cEluZnJhQ29tbW9uBAxzaG91bGRVc2VNYXQGY2FsbGVyDXBheW1lbnRBbW91bnQLbGFuZEFzc2V0SWQEBGFkZHIJAKUIAQUGY2FsbGVyBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMDBQRhZGRyBRNjbGFpbU1vZGVXaFRoZW5EdWNrBQtsYW5kQXNzZXRJZAQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUECGluZnJhS2V5CQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEIBQFjAl8yBAhjdXJMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQhpbmZyYUtleQAAAwkAZwIFCGN1ckxldmVsAAMJAAIBAiZDdXJyZW50bHkgbWF4IGluZnJhc3RydWN0dXJlIGxldmVsID0gMwQIbmV3TGV2ZWwJAGQCBQhjdXJMZXZlbAABBARjb3N0CQBrAwUVSW5mcmFVcGdyYWRlQ29zdFNVc2R0CQBoAgUGcGllY2VzBQhuZXdMZXZlbAUFU1NJWkUDAwkBASEBBQxzaG91bGRVc2VNYXQJAQIhPQIFDXBheW1lbnRBbW91bnQFBGNvc3QHCQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUEY29zdAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEIBQFjAl8xBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW1MaXN0CQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBAZuZXdNYXQJALkJAgkBEXN1YnRyYWN0TWF0ZXJpYWxzAwUMc2hvdWxkVXNlTWF0BQVtTGlzdAkAawMFEUluZnJhVXBncmFkZUNvc3RTCQBoAgUGcGllY2VzBQhuZXdMZXZlbAUFU1NJWkUCAV8EC2NsYWltUmVzdWx0CQEIY2xhaW1BbGwEBQRhZGRyCAUBYwJfMgUGcGllY2VzBRNjbGFpbU1vZGVXaFRoZW5EdWNrBAZ3aERhdGEIBQtjbGFpbVJlc3VsdAJfNQQGb2xkVm9sCQEXZ2V0V2FyZWhvdXNlVG90YWxWb2x1bWUBCQCRAwIFBndoRGF0YQULd2hJZHhMZXZlbHMECm5ld1ZvbERhdGEJALkJAgkAzAgCCQCRAwIJALUJAgkAkQMCBQZ3aERhdGEFC3doSWR4TGV2ZWxzAgFfAAAJAMwIAgkApAMBBQhuZXdMZXZlbAUDbmlsAgFfBAZuZXdWb2wJARdnZXRXYXJlaG91c2VUb3RhbFZvbHVtZQEFCm5ld1ZvbERhdGEEBGxvZnQJALUJAgkAkQMCBQZ3aERhdGEFCXdoSWR4TE9GVAIBXwQKbmV3TG9mdFN0cgkAuQkCCQDMCAIJAJEDAgUEbG9mdAUJdm9sTG9ja2VkCQDMCAIJAJEDAgUEbG9mdAULdm9sT2NjdXBpZWQJAMwIAgkApAMBCQBlAgkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQd2b2xGcmVlBQZuZXdWb2wFBm9sZFZvbAkAzAgCCQCkAwEFBm5ld1ZvbAUDbmlsAgFfCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUIaW5mcmFLZXkFCG5ld0xldmVsCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAggFAWMCXzIFBGFkZHIFCG5ld0xldmVsCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWJwS2V5CQC5CQIJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCCQCRAwIIBQtjbGFpbVJlc3VsdAJfMwUIYnBJZHhSZXMJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6CQDMCAIJAQtTdHJpbmdFbnRyeQIIBQtjbGFpbVJlc3VsdAJfNAkAuQkCCQDMCAIFCm5ld1ZvbERhdGEJAMwIAgkAkQMCBQZ3aERhdGEFCHdoSWR4UmVzCQDMCAIJAJEDAgUGd2hEYXRhBQh3aElkeE1hdAkAzAgCCQCRAwIFBndoRGF0YQUJd2hJZHhQcm9kCQDMCAIFCm5ld0xvZnRTdHIFA25pbAIBOgUDbmlsCAULY2xhaW1SZXN1bHQCXzEFCG5ld0xldmVsARJhY3RpdmF0ZVByZXNhbGVBcnQCBGFkZHINbGFuZEFzc2V0SWRJbgQBYwkBFGNoZWNrQ2xhaW1Db25kaXRpb25zAwUEYWRkcgUTY2xhaW1Nb2RlV2hUaGVuRHVjawUNbGFuZEFzc2V0SWRJbgQLbGFuZEFzc2V0SWQIBQFjAl8yBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIIBQFjAl8zBQtyZWNMYW5kU2l6ZQQNYWN0aXZhdGlvbktleQkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQULbGFuZEFzc2V0SWQDCQBmAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQ1hY3RpdmF0aW9uS2V5AAAAAAkAAgECJVByZXNhbGUgYXJ0aWZhY3QgaXMgYWxyZWFkeSBhY3RpdmF0ZWQDCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIIBQFjAl8zBQpyZWNMYW5kTnVtBQ9QUkVTQUxFTlVNTEFORFMJAAIBCQCsAgIJAKwCAgkArAICBQpMQU5EUFJFRklYAgEgBQtsYW5kQXNzZXRJZAIlIGlzIG5vdCBlbGlnaWJsZSBmb3IgcHJlc2FsZSBhcnRpZmFjdAQLY2xhaW1SZXN1bHQJAQhjbGFpbUFsbAQFBGFkZHIFC2xhbmRBc3NldElkBQZwaWVjZXMFE2NsYWltTW9kZVdoVGhlbkR1Y2sJAM0IAgkAzQgCCQDNCAIJAM0IAggFC2NsYWltUmVzdWx0Al8xCQEMSW50ZWdlckVudHJ5AgUNYWN0aXZhdGlvbktleQUGcGllY2VzCQEMSW50ZWdlckVudHJ5AgkBJWtleUxhbmRBcnRTdGF0dXNCeVR5cGVBc3NldElkQW5kT3duZXIDBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAUEYWRkcgUGcGllY2VzCQELU3RyaW5nRW50cnkCCAULY2xhaW1SZXN1bHQCXzIJALkJAggFC2NsYWltUmVzdWx0Al8zAgE6CQELU3RyaW5nRW50cnkCCAULY2xhaW1SZXN1bHQCXzQJALkJAggFC2NsYWltUmVzdWx0Al81AgE6AQ1tZXJnZUludGVybmFsBwtuZXdMYW5kU2l6ZQhuZXdMZXZlbAdmb3JtdWxhBGFkZHIMbGFuZEFzc2V0SWRzBHR4SWQHbmVlZE1hdAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkCgEKY2hlY2tNZXJnZQIDYWNjC2xhbmRBc3NldElkBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkBAlzYXZlZFRpbWUJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBQd0aW1lS2V5CQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUEYWRkcgkAAgEJAKwCAgUKTEFORFBSRUZJWAINIGlzIG5vdCB5b3VycwQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8ECWNvbnRpbmVudAkAkQMCBQFkBQxyZWNDb250aW5lbnQDAwkBAiE9AggFA2FjYwJfMwIACQECIT0CCAUDYWNjAl8zBQljb250aW5lbnQHCQACAQIuTGFuZHMgc2hvdWxkIGJlIG9uIHRoZSBzYW1lIGNvbnRpbmVudCB0byBtZXJnZQQIbGFuZFNpemUJAJEDAgUBZAULcmVjTGFuZFNpemUEB3NpemVzSW4IBQNhY2MCXzEEAWkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAswkCBQdzaXplc0luBQhsYW5kU2l6ZQInWW91IGhhdmVuJ3QgcGFzc2VkIGFsbCB0aGUgbGFuZHMgbmVlZGVkBAhzaXplc091dAkArAICCQCvAgIFB3NpemVzSW4FAWkJALACAgUHc2l6ZXNJbgkAZAIFAWkAAQQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQUIbGFuZFNpemUEBGFydHMJAGQCCAUDYWNjAl8yCQELdmFsdWVPckVsc2UCCQCfCAEJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkAAAECmluZnJhTGV2ZWwJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAAABAhyZXFMZXZlbAQHJG1hdGNoMAUIbGFuZFNpemUDCQAAAgIBUwUHJG1hdGNoMAADAwkAAAICAU0FByRtYXRjaDAABAMJAAACAgFMBQckbWF0Y2gwAAUDCQAAAgICWEwFByRtYXRjaDAABgkAAgECGk9ubHkgUywgTSwgTCwgWEwgY2FuIG1lcmdlAwkBAiE9AgUKaW5mcmFMZXZlbAUIcmVxTGV2ZWwJAAIBAiJBbGwgbGFuZHMgc2hvdWxkIGJlIG1heGVkIHRvIG1lcmdlBAdsYW5kTnVtCQCRAwIFAWQFCnJlY0xhbmROdW0EDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCBQFkBQtyZWNUZXJyYWlucwQJZGVsdGFUaW1lCQBlAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFCXNhdmVkVGltZQMJAGYCAAAFCWRlbHRhVGltZQkAAgEJAKwCAgkArAICCQCsAgICJlNhdmVkIHRpbWVzdGFtcCBpcyBpbiBmdXR1cmUsIHNhdmVkID0gCQCkAwEFCXNhdmVkVGltZQIMLCBjdXJyZW50ID0gCQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wBBZkYWlseVByb2R1Y3Rpb25CeVBpZWNlCQEMYXBwbHlCb251c2VzAgULbGFuZEFzc2V0SWQFBnBpZWNlcwQJbGFuZEluZGV4CQBpAgUGcGllY2VzBQVTU0laRQQFYnBSZXMJAQZhZGRSZXMFCQC1CQIIBQNhY2MCXzQCAV8FDXRlcnJhaW5Db3VudHMFCWRlbHRhVGltZQUJbGFuZEluZGV4BRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBAVwcm9wcwkBGXVwZGF0ZVByb3BvcnRpb25zSW50ZXJuYWwECQC1CQIIBQNhY2MCXzYCAV8FDXRlcnJhaW5Db3VudHMFCWxhbmRJbmRleAD///////////8BBAVsYW5kcwgFA2FjYwJfNwQDaWR4CQDPCAIFBWxhbmRzBQtsYW5kQXNzZXRJZAMJAQEhAQkBCWlzRGVmaW5lZAEFA2lkeAkAAgEJAKwCAgIgWW91ciBzdGFrZWQgbGFuZHMgZG9uJ3QgY29udGFpbiAFC2xhbmRBc3NldElkBAljdXN0b21LZXkJARprZXlMYW5kQXNzZXRJZFRvQ3VzdG9tTmFtZQEFC2xhbmRBc3NldElkBApjdXN0b21OYW1lCQELdmFsdWVPckVsc2UCCQCiCAEFCWN1c3RvbUtleQIACQCaCggFCHNpemVzT3V0BQRhcnRzBQljb250aW5lbnQFBWJwUmVzCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIIBQNhY2MCXzUJAQtEZWxldGVFbnRyeQEJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQJAQtEZWxldGVFbnRyeQEJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKTEFORFBSRUZJWAULbGFuZEFzc2V0SWQFBGFkZHIJAQtEZWxldGVFbnRyeQEJARBrZXlMYW5kVG9Bc3NldElkAQUHbGFuZE51bQkBC0RlbGV0ZUVudHJ5AQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkCQELRGVsZXRlRW50cnkBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkCQELRGVsZXRlRW50cnkBCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgULbGFuZEFzc2V0SWQFBGFkZHIJAQtEZWxldGVFbnRyeQEJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkCQELRGVsZXRlRW50cnkBCQEla2V5TGFuZEFydFN0YXR1c0J5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkBQRhZGRyCQELRGVsZXRlRW50cnkBCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtCQELRGVsZXRlRW50cnkBCQESa2V5V2FyZWhvdXNlQnlMYW5kAQULbGFuZEFzc2V0SWQJAQtEZWxldGVFbnRyeQEFCWN1c3RvbUtleQkBC0RlbGV0ZUVudHJ5AQkBGmtleUxhbmRDdXN0b21OYW1lVG9Bc3NldElkAQUKY3VzdG9tTmFtZQkBBEJ1cm4CCQDZBAEFC2xhbmRBc3NldElkAAEFBXByb3BzCQDRCAIFBWxhbmRzCQEFdmFsdWUBBQNpZHgJAGQCCAUDYWNjAl84BQZwaWVjZXMEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEFBWJwS2V5BAdwcm9wU3RyCQELdmFsdWVPckVsc2UCCQCiCAEJARFrZXlSZXNQcm9wb3J0aW9ucwACCzBfMF8wXzBfMF8wBAhsYW5kc0tleQkBFWtleVN0YWtlZExhbmRzQnlPd25lcgEFBGFkZHIECGxhbmRzU3RyCQCiCAEFCGxhbmRzS2V5BAdsYW5kc0luAwkBCWlzRGVmaW5lZAEFCGxhbmRzU3RyCQC9CQIJAQV2YWx1ZQEFCGxhbmRzU3RyAgFfBQNuaWwEAXIKAAIkbAUMbGFuZEFzc2V0SWRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAmgoIBQdmb3JtdWxhAAACAAkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMFA25pbAUHcHJvcFN0cgUHbGFuZHNJbgAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpjaGVja01lcmdlAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQQJY29udGluZW50CAUBcgJfMwQMY29udGluZW50SWR4CQETdmFsdWVPckVycm9yTWVzc2FnZQIJAM8IAgUKY29udGluZW50cwUJY29udGluZW50CQCsAgICE1Vua25vd24gY29udGluZW50OiAFCWNvbnRpbmVudAQIdGVycmFpbnMJAQtnZW5UZXJyYWlucwIJAQNhYnMBCQCeAwEFBHR4SWQFDGNvbnRpbmVudElkeAQHZnJlZU51bQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQESa2V5TmV4dEZyZWVMYW5kTnVtAAkAZAIFD1BSRVNBTEVOVU1MQU5EUwABBApuZXdMYW5kTnVtCQCkAwEFB2ZyZWVOdW0EBWlzc3VlCQDCCAUJAQduZnROYW1lAgUKbmV3TGFuZE51bQULbmV3TGFuZFNpemUJALkJAgkAzAgCBQpuZXdMYW5kTnVtCQDMCAIFC25ld0xhbmRTaXplCQDMCAIFCHRlcnJhaW5zCQDMCAIFCWNvbnRpbmVudAUDbmlsAgFfAAEAAAcEB2Fzc2V0SWQJALgIAQUFaXNzdWUEDm5ld0xhbmRBc3NldElkCQDYBAEFB2Fzc2V0SWQEBm5ld01hdAkAuQkCCQERc3VidHJhY3RNYXRlcmlhbHMDCQBmAgUHbmVlZE1hdAAACQC1CQIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0AgFfBQduZWVkTWF0AgFfBAlwaWVjZXNLZXkJARZrZXlTdGFrZWRQaWVjZXNCeU93bmVyAQUEYWRkcgQMc3Rha2VkUGllY2VzCQELdmFsdWVPckVsc2UCCQCfCAEFCXBpZWNlc0tleQAACQCUCgIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIIBQFyAl81AwkAZgIJAJADAQgFAXICXzcAAAkBC1N0cmluZ0VudHJ5AgUIbGFuZHNLZXkJALsJAggFAXICXzcCAV8JAQtEZWxldGVFbnRyeQEFCGxhbmRzS2V5CQEMSW50ZWdlckVudHJ5AgUJcGllY2VzS2V5AwkAZgIIBQFyAl84BQxzdGFrZWRQaWVjZXMAAAkAZQIFDHN0YWtlZFBpZWNlcwgFAXICXzgJAQxJbnRlZ2VyRW50cnkCCQESa2V5TmV4dEZyZWVMYW5kTnVtAAkAZAIFB2ZyZWVOdW0AAQUFaXNzdWUJAQtTdHJpbmdFbnRyeQIJARBrZXlMYW5kVG9Bc3NldElkAQUKbmV3TGFuZE51bQUObmV3TGFuZEFzc2V0SWQJAQtTdHJpbmdFbnRyeQIJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQ5uZXdMYW5kQXNzZXRJZAUEYWRkcgkBC1N0cmluZ0VudHJ5AgkBEWtleUxhbmROdW1Ub093bmVyAQUKbmV3TGFuZE51bQUEYWRkcgkBDEludGVnZXJFbnRyeQIJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFDm5ld0xhbmRBc3NldElkCAUBcgJfMgkBDEludGVnZXJFbnRyeQIJASVrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKQVJUUFJFU0FMRQUObmV3TGFuZEFzc2V0SWQFBGFkZHIIBQFyAl8yCQEMSW50ZWdlckVudHJ5AgkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQ5uZXdMYW5kQXNzZXRJZAUIbmV3TGV2ZWwJAQxJbnRlZ2VyRW50cnkCCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgUObmV3TGFuZEFzc2V0SWQFBGFkZHIFCG5ld0xldmVsCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAggFAXICXzQJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6CQELU3RyaW5nRW50cnkCCQERa2V5UmVzUHJvcG9ydGlvbnMACAUBcgJfNgkBC1N0cmluZ0VudHJ5AgkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkCQC5CQIJAMwIAgUJY29udGluZW50CQDMCAICAUwJAMwIAgUObmV3TGFuZEFzc2V0SWQFA25pbAIBXwkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUEYWRkcgABBQdhc3NldElkBQ5uZXdMYW5kQXNzZXRJZAEDczJtAwRhZGRyDGxhbmRBc3NldElkcwR0eElkCQENbWVyZ2VJbnRlcm5hbAcCAU0AAwIEU1NTUwUEYWRkcgUMbGFuZEFzc2V0SWRzBQR0eElkAAABA20ybAUEYWRkcgxsYW5kQXNzZXRJZHMEdHhJZAxzaG91bGRVc2VNYXQNcGF5bWVudEFtb3VudAQEY29zdAkAaAIFFUluZnJhVXBncmFkZUNvc3RTVXNkdAAEAwMJAQEhAQUMc2hvdWxkVXNlTWF0CQECIT0CBQ1wYXltZW50QW1vdW50BQRjb3N0BwkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFBGNvc3QJAQ1tZXJnZUludGVybmFsBwIBTAAEAgNTTU0FBGFkZHIFDGxhbmRBc3NldElkcwUEdHhJZAkAaAIFEUluZnJhVXBncmFkZUNvc3RTAAQBBGwyeGwFBGFkZHIMbGFuZEFzc2V0SWRzBHR4SWQMc2hvdWxkVXNlTWF0DXBheW1lbnRBbW91bnQEBGNvc3QJAGgCBRVJbmZyYVVwZ3JhZGVDb3N0U1VzZHQALwMDCQEBIQEFDHNob3VsZFVzZU1hdAkBAiE9AgUNcGF5bWVudEFtb3VudAUEY29zdAcJAAIBCQCsAgICG1BheW1lbnQgYXR0YWNoZWQgc2hvdWxkIGJlIAkApAMBBQRjb3N0CQENbWVyZ2VJbnRlcm5hbAcCAlhMAAUCBVNTU01MBQRhZGRyBQxsYW5kQXNzZXRJZHMFBHR4SWQJAGgCBRFJbmZyYVVwZ3JhZGVDb3N0UwAvAQZ4bDJ4eGwFBGFkZHIMbGFuZEFzc2V0SWRzBHR4SWQMc2hvdWxkVXNlTWF0DXBheW1lbnRBbW91bnQEBGNvc3QJAGgCBRVJbmZyYVVwZ3JhZGVDb3N0U1VzZHQANgMDCQEBIQEFDHNob3VsZFVzZU1hdAkBAiE9AgUNcGF5bWVudEFtb3VudAUEY29zdAcJAAIBCQCsAgICG1BheW1lbnQgYXR0YWNoZWQgc2hvdWxkIGJlIAkApAMBBQRjb3N0CQENbWVyZ2VJbnRlcm5hbAcCA1hYTAAGAgNMWEwFBGFkZHIFDGxhbmRBc3NldElkcwUEdHhJZAkAaAIFEUluZnJhVXBncmFkZUNvc3RTADYBC21lcmdlQ29tbW9uBQxzaG91bGRVc2VNYXQEYWRkcg1wYXltZW50QW1vdW50DGxhbmRBc3NldElkcwR0eElkBAttZXJnZVJlc3VsdAQHJG1hdGNoMAkAkAMBBQxsYW5kQXNzZXRJZHMDCQAAAgAEBQckbWF0Y2gwCQEDczJtAwUEYWRkcgUMbGFuZEFzc2V0SWRzBQR0eElkAwkAAAIAAwUHJG1hdGNoMAkBA20ybAUFBGFkZHIFDGxhbmRBc3NldElkcwUEdHhJZAUMc2hvdWxkVXNlTWF0BQ1wYXltZW50QW1vdW50AwkAAAIABQUHJG1hdGNoMAkBBGwyeGwFBQRhZGRyBQxsYW5kQXNzZXRJZHMFBHR4SWQFDHNob3VsZFVzZU1hdAUNcGF5bWVudEFtb3VudAMJAAACAAIFByRtYXRjaDAJAQZ4bDJ4eGwFBQRhZGRyBQxsYW5kQXNzZXRJZHMFBHR4SWQFDHNob3VsZFVzZU1hdAUNcGF5bWVudEFtb3VudAkAAgECDVVua25vd24gbWVyZ2UFC21lcmdlUmVzdWx0AQZwcm9sb2cBAWkDAwkBAiE9AggFAWkMb3JpZ2luQ2FsbGVyBQxyZXN0Q29udHJhY3QJAQt2YWx1ZU9yRWxzZQIJAKAIAQkBCmtleUJsb2NrZWQABwcJAAIBAh9Db250cmFjdHMgYXJlIHVuZGVyIG1haW50ZW5hbmNlCQELU3RyaW5nRW50cnkCCQERa2V5TGFzdFR4SWRCeVVzZXIBCQClCAEIBQFpDG9yaWdpbkNhbGxlcgkA2AQBCAUBaQ10cmFuc2FjdGlvbklkHgFpAQ1jb25zdHJ1Y3RvclYxAQhyZXN0QWRkcgMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEVBlcm1pc3Npb24gZGVuaWVkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ5rZXlSZXN0QWRkcmVzcwAFCHJlc3RBZGRyBQNuaWwBaQEKc2V0QmxvY2tlZAEJaXNCbG9ja2VkAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQprZXlCbG9ja2VkAAUJaXNCbG9ja2VkBQNuaWwBaQEJc3Rha2VMYW5kAAQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAdhc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyAwkBAiE9AggFA3BtdAZhbW91bnQAAQkAAgEJAKwCAgkArAICAgRORlQgBQpMQU5EUFJFRklYAiQgdG9rZW4gc2hvdWxkIGJlIGF0dGFjaGVkIGFzIHBheW1lbnQEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQDCQECIT0CCAUFYXNzZXQGaXNzdWVyBQR0aGlzCQACAQIXVW5rbm93biBpc3N1ZXIgb2YgdG9rZW4DCQEBIQEJAQhjb250YWlucwIIBQVhc3NldARuYW1lBQpMQU5EUFJFRklYCQACAQkArAICCQCsAgICCU9ubHkgTkZUIAUKTEFORFBSRUZJWAIUIHRva2VucyBhcmUgYWNjZXB0ZWQEC2xhbmROdW1TaXplCQCwAgIIBQVhc3NldARuYW1lAAQEB2xhbmROdW0DCQEIY29udGFpbnMCBQtsYW5kTnVtU2l6ZQIDWFhMCQCzAgIFC2xhbmROdW1TaXplAAMDCQEIY29udGFpbnMCBQtsYW5kTnVtU2l6ZQICWEwJALMCAgULbGFuZE51bVNpemUAAgkAswICBQtsYW5kTnVtU2l6ZQABAwkBASEBCQEJaXNEZWZpbmVkAQkAtgkBBQdsYW5kTnVtCQACAQkArAICAh5DYW5ub3QgcGFyc2UgbGFuZCBudW1iZXIgZnJvbSAIBQVhc3NldARuYW1lBAtsYW5kQXNzZXRJZAkA2AQBBQdhc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAwkBCWlzRGVmaW5lZAEJAJ8IAQUHdGltZUtleQkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQISIGlzIGFscmVhZHkgc3Rha2VkBAFkCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIFAWQFC3JlY1RlcnJhaW5zBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIFAWQFC3JlY0xhbmRTaXplBAVwcm9wcwkBEXVwZGF0ZVByb3BvcnRpb25zAwUNdGVycmFpbkNvdW50cwkAaQIFBnBpZWNlcwUFU1NJWkUAAQQJYXJ0UGllY2VzCQELdmFsdWVPckVsc2UCCQCfCAEJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkAAAECGxhbmRzS2V5CQEVa2V5U3Rha2VkTGFuZHNCeU93bmVyAQUHYWRkcmVzcwQIbGFuZHNTdHIJAKIIAQUIbGFuZHNLZXkEBWxhbmRzAwkBCWlzRGVmaW5lZAEFCGxhbmRzU3RyCQC9CQIJAQV2YWx1ZQEFCGxhbmRzU3RyAgFfBQNuaWwDCQEPY29udGFpbnNFbGVtZW50AgUFbGFuZHMFC2xhbmRBc3NldElkCQACAQkArAICAiJZb3VyIHN0YWtlZCBsYW5kcyBhbHJlYWR5IGNvbnRhaW4gBQtsYW5kQXNzZXRJZAQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAECXBpZWNlc0tleQkBFmtleVN0YWtlZFBpZWNlc0J5T3duZXIBBQdhZGRyZXNzBAlvbGRQaWVjZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJcGllY2VzS2V5AAAECXdsZ1Jlc3VsdAMJAAACBQlvbGRQaWVjZXMAAAkBBWFzSW50AQkA/AcEBQt3bGdDb250cmFjdAILb25TdGFrZUxhbmQJAMwIAgUHYWRkcmVzcwUDbmlsBQNuaWwA////////////AQkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQd0aW1lS2V5CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBC1N0cmluZ0VudHJ5AgUIbGFuZHNLZXkJALsJAgkAzQgCBQVsYW5kcwULbGFuZEFzc2V0SWQCAV8JAMwIAgkBDEludGVnZXJFbnRyeQIFCXBpZWNlc0tleQkAZAIFCW9sZFBpZWNlcwUGcGllY2VzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtBQdhZGRyZXNzCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEla2V5TGFuZEFydFN0YXR1c0J5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkBQdhZGRyZXNzBQlhcnRQaWVjZXMJAMwIAgkBDEludGVnZXJFbnRyeQIJAR5rZXlJbmZyYUxldmVsQnlBc3NldElkQW5kT3duZXICBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwUKaW5mcmFMZXZlbAkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5UmVzUHJvcG9ydGlvbnMABQVwcm9wcwkAzAgCBQxwcm9sb2dBY3Rpb24FA25pbAUJd2xnUmVzdWx0AWkBC3Vuc3Rha2VMYW5kAQ1sYW5kQXNzZXRJZEluBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMDBQRhZGRyBQ1jbGFpbU1vZGVEdWNrBQ1sYW5kQXNzZXRJZEluBAtsYW5kQXNzZXRJZAgFAWMCXzIECGxhbmRzS2V5CQEVa2V5U3Rha2VkTGFuZHNCeU93bmVyAQUEYWRkcgQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIIBQFjAl8zBQtyZWNUZXJyYWlucwQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUEBXByb3BzCQERdXBkYXRlUHJvcG9ydGlvbnMDBQ10ZXJyYWluQ291bnRzCQBpAgUGcGllY2VzBQVTU0laRQD///////////8BBAtjbGFpbVJlc3VsdAkBCGNsYWltQWxsBAUEYWRkcgULbGFuZEFzc2V0SWQFBnBpZWNlcwUNY2xhaW1Nb2RlRHVjawQFbGFuZHMJAL0JAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQhsYW5kc0tleQIAAgFfBANpZHgJAM8IAgUFbGFuZHMFC2xhbmRBc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQUDaWR4CQACAQkArAICAiBZb3VyIHN0YWtlZCBsYW5kcyBkb24ndCBjb250YWluIAULbGFuZEFzc2V0SWQEAXQICQEFdmFsdWUBCQDtBwEFBmhlaWdodAl0aW1lc3RhbXAEC3JlbGVhc2VUaW1lCQELdmFsdWVPckVsc2UCCQCaCAIFC2dvdkNvbnRyYWN0CQEVa2V5VXNlckd3bFJlbGVhc2VUaW1lAQUEYWRkcgAAAwkAZwIFC3JlbGVhc2VUaW1lBQF0CQACAQkArAICAjlZb3VyIGdXTCBhcmUgdGFraW5nIHBhcnQgaW4gdm90aW5nLCBjYW5ub3QgdW5zdGFrZSB1bnRpbCAJAKQDAQULcmVsZWFzZVRpbWUECXBpZWNlc0tleQkBFmtleVN0YWtlZFBpZWNlc0J5T3duZXIBBQRhZGRyBAxzdGFrZWRQaWVjZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJcGllY2VzS2V5AAAECW5ld1BpZWNlcwMJAGYCBQZwaWVjZXMFDHN0YWtlZFBpZWNlcwAACQBlAgUMc3Rha2VkUGllY2VzBQZwaWVjZXMECXdsZ1Jlc3VsdAMJAAACBQluZXdQaWVjZXMAAAkBBWFzSW50AQkA/AcEBQt3bGdDb250cmFjdAINb25VbnN0YWtlTGFuZAkAzAgCBQRhZGRyBQNuaWwFA25pbAD///////////8BCQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyAAEJANkEAQULbGFuZEFzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgFC2xhbmRBc3NldElkBQRhZGRyCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlSZXNQcm9wb3J0aW9ucwAFBXByb3BzCQDMCAIJAQtTdHJpbmdFbnRyeQIIBQtjbGFpbVJlc3VsdAJfMgkAuQkCCAULY2xhaW1SZXN1bHQCXzMCAToJAMwIAgMJAGYCCQCQAwEFBWxhbmRzAAEJAQtTdHJpbmdFbnRyeQIFCGxhbmRzS2V5CQC7CQIJANEIAgUFbGFuZHMJAQV2YWx1ZQEFA2lkeAIBXwkBC0RlbGV0ZUVudHJ5AQUIbGFuZHNLZXkJAMwIAgkBDEludGVnZXJFbnRyeQIFCXBpZWNlc0tleQUJbmV3UGllY2VzCQDMCAIFDHByb2xvZ0FjdGlvbgUDbmlsBQl3bGdSZXN1bHQBaQEJc3Rha2VEdWNrAAQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAdhc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyAwkBAiE9AggFA3BtdAZhbW91bnQAAQkAAgEJAKwCAgkArAICAgRORlQgBQpEVUNLUFJFRklYAiQgdG9rZW4gc2hvdWxkIGJlIGF0dGFjaGVkIGFzIHBheW1lbnQEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQDAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUNaW5jdWJhdG9yQWRkcgkBAiE9AggFBWFzc2V0Bmlzc3VlcgULYnJlZWRlckFkZHIHCQACAQkArAICCQCsAgICElVua25vd24gaXNzdWVyIG9mIAUKRFVDS1BSRUZJWAIGIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKRFVDS1BSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkRVQ0tQUkVGSVgCFCB0b2tlbnMgYXJlIGFjY2VwdGVkBAphc3NldElkU3RyCQDYBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUKYXNzZXRJZFN0cgMJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCEiBpcyBhbHJlYWR5IHN0YWtlZAMJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgICHVlvdSBhbHJlYWR5IHN0YWtlZCBvbmUgZHVjazogCAUFYXNzZXQEbmFtZQQGbG9jS2V5CQEPa2V5RHVja0xvY2F0aW9uAQUKYXNzZXRJZFN0cgQIbG9jYXRpb24JAKIIAQUGbG9jS2V5BAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQUKYXNzZXRJZFN0cgQIYmFja3BhY2sJAKIIAQUFYnBLZXkJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUHdGltZUtleQgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKRFVDS1BSRUZJWAkA2AQBBQdhc3NldElkBQdhZGRyZXNzCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5RHVja0lkVG9Pd25lcgEFCmFzc2V0SWRTdHIFB2FkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwUKYXNzZXRJZFN0cgUDbmlsAwkBCWlzRGVmaW5lZAEFCGxvY2F0aW9uBQNuaWwJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQZsb2NLZXkFD0RFRkFVTFRMT0NBVElPTgUDbmlsAwkBCWlzRGVmaW5lZAEFCGJhY2twYWNrBQNuaWwJAM0IAgkAzQgCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWJwS2V5AhowOjBfMF8wXzBfMF8wOjBfMF8wXzBfMF8wOgUDbmlsCQEMSW50ZWdlckVudHJ5AgkBDWtleUR1Y2tIZWFsdGgBBQphc3NldElkU3RyAGQFDHByb2xvZ0FjdGlvbgFpAQt1bnN0YWtlRHVjawEKYXNzZXRJZFN0cgQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBAdhc3NldElkCQDZBAEFCmFzc2V0SWRTdHIEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEJANgEAQUHYXNzZXRJZAMJAQEhAQkBCWlzRGVmaW5lZAEJAJ8IAQUHdGltZUtleQkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQDCQEBIQEJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgIJAKwCAgIJVGhlIGR1Y2sgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBEGtleUR1Y2tJZFRvT3duZXIBCQDYBAEFB2Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFB2FkZHJlc3MJAAIBAhdTdGFrZWQgTkZUIGlzIG5vdCB5b3VycwQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFCmFzc2V0SWRTdHIEBmhlYWx0aAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAMJAGYCAGQFBmhlYWx0aAkAAgECJlBsZWFzZSBoZWFsIHlvdXIgZHVjayBiZWZvcmUgdW5zdGFraW5nCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABBQdhc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEFB3RpbWVLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQUJa2V5SGVhbHRoCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ9rZXlEdWNrTG9jYXRpb24BBQphc3NldElkU3RyCQDMCAIJAQtEZWxldGVFbnRyeQEJARBrZXlEdWNrSWRUb093bmVyAQUKYXNzZXRJZFN0cgkAzAgCCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkRVQ0tQUkVGSVgFCmFzc2V0SWRTdHIFB2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwkAzAgCBQxwcm9sb2dBY3Rpb24FA25pbAFpAQhjbGFpbVJlcwIGYW1vdW50DmxhbmRBc3NldElkU3RyBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBAZyZXN1bHQJARBjbGFpbVJlc0ludGVybmFsBAUEYWRkcgUGYW1vdW50BQ1jbGFpbU1vZGVEdWNrBQ5sYW5kQXNzZXRJZFN0cgkAlAoCCQDNCAIJAM0IAgkAzQgCCAUGcmVzdWx0Al8xCQELU3RyaW5nRW50cnkCCAUGcmVzdWx0Al8yCQC5CQIIBQZyZXN1bHQCXzMCAToJAQtTdHJpbmdFbnRyeQIIBQZyZXN1bHQCXzQJALkJAggFBnJlc3VsdAJfNQIBOgUMcHJvbG9nQWN0aW9uCQCRAwIIBQZyZXN1bHQCXzMFCGJwSWR4UmVzAWkBDGNsYWltUmVzVG9XSAIGYW1vdW50DmxhbmRBc3NldElkU3RyBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBAZyZXN1bHQJARBjbGFpbVJlc0ludGVybmFsBAUEYWRkcgUGYW1vdW50BQtjbGFpbU1vZGVXaAUObGFuZEFzc2V0SWRTdHIJAJQKAgkAzQgCCQDNCAIJAM0IAggFBnJlc3VsdAJfMQkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfMgkAuQkCCAUGcmVzdWx0Al8zAgE6CQELU3RyaW5nRW50cnkCCAUGcmVzdWx0Al80CQC5CQIIBQZyZXN1bHQCXzUCAToFDHByb2xvZ0FjdGlvbgkAkQMCCAUGcmVzdWx0Al81BQh3aElkeFJlcwFpAQZmbGlnaHQCB21lc3NhZ2UDc2lnBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQECHVzZXJBZGRyCQClCAEIBQFpBmNhbGxlcgQBZgkBDGZsaWdodENvbW1vbgMFCHVzZXJBZGRyBQdtZXNzYWdlBQNzaWcEBmxvY0tleQkBD2tleUR1Y2tMb2NhdGlvbgEIBQFmAl8yBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAoggBBQZsb2NLZXkFD0RFRkFVTFRMT0NBVElPTgMJAAACCAUBZgJfNAULY3VyTG9jYXRpb24JAAIBAiJZb3UgY2FuJ3QgZmx5IHRvIHRoZSBzYW1lIGxvY2F0aW9uBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQgFAWYCXzIEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQHbmV3UHJvZAkBEHN1YnRyYWN0UHJvZHVjdHMCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QIBQFmAl81CQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgUGbG9jS2V5AwkAZgIIBQFmAl8xAAAIBQFmAl80BQtjdXJMb2NhdGlvbgkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQJAMwIAgUHbmV3UHJvZAUDbmlsAgE6CQDMCAIJAQxJbnRlZ2VyRW50cnkCCQENa2V5RHVja0hlYWx0aAEIBQFmAl8yCAUBZgJfMQkAzAgCBQxwcm9sb2dBY3Rpb24FA25pbAgFAWYCXzMBaQEEaGVhbAMKcXVhbnRpdHlMMQpxdWFudGl0eUwyCnF1YW50aXR5TDMEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDAwMJAGYCAAAFCnF1YW50aXR5TDEGCQBmAgAABQpxdWFudGl0eUwyBgkAZgIAAAUKcXVhbnRpdHlMMwkAAgECG1F1YW50aXR5IGNhbm5vdCBiZSBuZWdhdGl2ZQQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQDcXRzCQDMCAIFCnF1YW50aXR5TDEJAMwIAgUKcXVhbnRpdHlMMgkAzAgCBQpxdWFudGl0eUwzBQNuaWwECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQJb2xkSGVhbHRoCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAwkAZwIFCW9sZEhlYWx0aAUFTUFYSFAJAAIBCQCsAgIJAKwCAgIPSFAgc2hvdWxkIGJlIDwgCQCkAwEFBU1BWEhQAgggdG8gaGVhbAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkECHByb2RM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CWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQJb2xkSGVhbHRoCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAwkAZgIFCW9sZEhlYWx0aAAACQACAQIoSFAgc2hvdWxkIGJlIDAgdG8gY2FsbCBFbWVyZ2VuY3kgU2VydmljZQQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkECHByb2RMaXN0AwkAAAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAIABQNuaWwJALUJAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kAgFfBA1tZWRLaXRBbW91bnQxAwkAZgIJAJADAQUIcHJvZExpc3QAAAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHByb2RMaXN0AAAAAAQNbWVkS2l0QW1vdW50MgMJAGYCCQCQAwEFCHByb2RMaXN0AAEJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhwcm9kTGlzdAABAAAEDW1lZEtpdEFtb3VudDMDCQBmAgkAkAMBBQhwcm9kTGlzdAACCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIcHJvZExpc3QAAgAAAwMDCQBmAgUNbWVkS2l0QW1vdW50MQAABgkAZgIFDW1lZEtpdEFtb3VudDIAAAYJAGYCBQ1tZWRLaXRBbW91bnQzAAAJAAIBAh9Zb3UgaGF2ZSB0byB1c2Ugb3duIE1lZGljYWwgS2l0BAhleGlzdFN0cgkAnQgCBQ9lY29ub215Q29udHJhY3QJAQ5rZXlFc1dhcmVob3VzZQAEDGV4aXN0QW1vdW50cwMJAQlpc0RlZmluZWQBBQhleGlzdFN0cgkAtQkCCQEFdmFsdWUBBQhleGlzdFN0cgIBXwUDbmlsBAtleGlzdEFtb3VudAMJAGYCCQCQAwEFDGV4aXN0QW1vdW50cwAACQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUMZXhpc3RBbW91bnRzAAAAAAMJAGcCAAAFC2V4aXN0QW1vdW50CQACAQI5VGhlcmUgYXJlIG5vIE1lZGljYWwgS2l0cyBMMSBhdCBFbWVyZ2VuY3kgU2VydmljZSBzdG9yYWdlBAluZXdIZWFsdGgJAGQCBQlvbGRIZWFsdGgJAJEDAgUIbWVkS2l0SHAAAAQFbmV3RVMJALkJAgkAzAgCCQCkAwEJAGUCBQtleGlzdEFtb3VudAABCQDRCAIFDGV4aXN0QW1vdW50cwAAAgFfBAZyZWNpcGUJALUJAgkAkQMCBRBwcm9kdWN0aW9uTWF0cml4AAACAV8ECHRvdGFsTWF0CQESZ2V0UmVjaXBlTWF0ZXJpYWxzAQUGcmVjaXBlBAhwYWNrU2l6ZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBnJlY2lwZQURcmVjaXBlSWR4UGFja3NpemUECXNlbGxQcmljZQkAawMJAGgCBQh0b3RhbE1hdAUKRVNTRUxMQ09FRgUQUkVTT1VSQ0VQUklDRU1JTgkAaAIACgUIcGFja1NpemUDCQECIT0CCAUDcG10BmFtb3VudAUJc2VsbFByaWNlCQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUJc2VsbFByaWNlBAZyZXN1bHQJAQhhc1N0cmluZwEJAPwHBAUPZWNvbm9teUNvbnRyYWN0Ag91cGRhdGVFc1N0b3JhZ2UJAMwIAgUFbmV3RVMFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgULdXNkdEFzc2V0SWQFCXNlbGxQcmljZQUDbmlsCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtleUhlYWx0aAUJbmV3SGVhbHRoCQDMCAIFDHByb2xvZ0FjdGlvbgUDbmlsBQZyZXN1bHQBaQEOdXBkYXRlQmFja3BhY2sCC2R1Y2tBc3NldElkB25ld1BhY2sEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDCQECIT0CCAUBaQZjYWxsZXIFD2Vjb25vbXlDb250cmFjdAkAAgECEXBlcm1pc3Npb24gZGVuaWVkCQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQFB25ld1BhY2sJAMwIAgUMcHJvbG9nQWN0aW9uBQNuaWwFB25ld1BhY2sBaQEIYnV5U0xhbmQABAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZHRBc3NldElkCQACAQIaQWxsb3dlZCBVU0RUIHBheW1lbnQgb25seSEDCQECIT0CCAUDcG10BmFtb3VudAUHRVhQVVNEVAkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFB0VYUFVTRFQEBnJlc3VsdAkBEmV4cGVkaXRpb25JbnRlcm5hbAIIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAkAlAoCCQDNCAIJAM0IAggFBnJlc3VsdAJfMQkBDlNjcmlwdFRyYW5zZmVyAwUPZWNvbm9teUNvbnRyYWN0CAUDcG10BmFtb3VudAULdXNkdEFzc2V0SWQFDHByb2xvZ0FjdGlvbggIBQZyZXN1bHQCXzICXzEBaQEKZXhwZWRpdGlvbgIHbWVzc2FnZQNzaWcEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQGcmVzdWx0CQEQZXhwZWRpdGlvbkNvbW1vbgQIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAUHbWVzc2FnZQUDc2lnCQCUCgIJAM0IAggFBnJlc3VsdAJfMQUMcHJvbG9nQWN0aW9uCQCUCgIIBQZyZXN1bHQCXzIIBQZyZXN1bHQCXzMBaQEMdXBncmFkZUluZnJhAQtsYW5kQXNzZXRJZAQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBAZyZXN1bHQJAQ11cEluZnJhQ29tbW9uBAYIBQFpBmNhbGxlcgAABQtsYW5kQXNzZXRJZAkAlAoCCQDNCAIIBQZyZXN1bHQCXzEFDHByb2xvZ0FjdGlvbggFBnJlc3VsdAJfMgFpARB1cGdyYWRlSW5mcmFVc2R0AQtsYW5kQXNzZXRJZAMJAQIhPQIIBQFpBmNhbGxlcgUEdGhpcwkAAgECEVBlcm1pc3Npb24gZGVuaWVkBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZHRBc3NldElkCQACAQIaQWxsb3dlZCBVU0RUIHBheW1lbnQgb25seSEEBnJlc3VsdAkBDXVwSW5mcmFDb21tb24EBwgFAWkGY2FsbGVyCAUDcG10BmFtb3VudAULbGFuZEFzc2V0SWQJAJQKAgkAzQgCCQDNCAIIBQZyZXN1bHQCXzEJAQ5TY3JpcHRUcmFuc2ZlcgMFD2Vjb25vbXlDb250cmFjdAgFA3BtdAZhbW91bnQFC3VzZHRBc3NldElkBQxwcm9sb2dBY3Rpb24IBQZyZXN1bHQCXzIBaQEQYWN0aXZhdGVBcnRpZmFjdAIHYXJ0TmFtZQtsYW5kQXNzZXRJZAQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBAZyZXN1bHQEByRtYXRjaDAFB2FydE5hbWUDCQAAAgIHUFJFU0FMRQUHJG1hdGNoMAkBEmFjdGl2YXRlUHJlc2FsZUFydAIJAKUIAQgFAWkGY2FsbGVyBQtsYW5kQXNzZXRJZAkAAgECEFVua25vd24gYXJ0aWZhY3QJAM0IAgUGcmVzdWx0BQxwcm9sb2dBY3Rpb24BaQEKbWVyZ2VMYW5kcwEMbGFuZEFzc2V0SWRzBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBnJlc3VsdAkBC21lcmdlQ29tbW9uBQYJAKUIAQgFAWkGY2FsbGVyAAAFDGxhbmRBc3NldElkcwgFAWkNdHJhbnNhY3Rpb25JZAkAlAoCCQDNCAIIBQZyZXN1bHQCXzEFDHByb2xvZ0FjdGlvbggFBnJlc3VsdAJfMgFpAQ5tZXJnZUxhbmRzVXNkdAEMbGFuZEFzc2V0SWRzBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZHRBc3NldElkCQACAQIaQWxsb3dlZCBVU0RUIHBheW1lbnQgb25seSEEBnJlc3VsdAkBC21lcmdlQ29tbW9uBQcJAKUIAQgFAWkGY2FsbGVyCAUDcG10BmFtb3VudAUMbGFuZEFzc2V0SWRzCAUBaQ10cmFuc2FjdGlvbklkCQCUCgIJAM0IAgkAzQgCCAUGcmVzdWx0Al8xCQEOU2NyaXB0VHJhbnNmZXIDBQ9lY29ub215Q29udHJhY3QIBQNwbXQGYW1vdW50BQt1c2R0QXNzZXRJZAUMcHJvbG9nQWN0aW9uCAUGcmVzdWx0Al8yAWkBDWNhcmdvRXhjaGFuZ2UCDGNhcmdvTGlzdFN0cgtsYW5kQXNzZXRJZAQMcHJvbG9nQWN0aW9uCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBApjYXJnb1BhcnRzCQC8CQIFDGNhcmdvTGlzdFN0cgIBOgQEYWRkcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQULbGFuZEFzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMECWxhbmRJbmRleAkAaQIJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBQtyZWNMYW5kU2l6ZQUFU1NJWkUECmluZnJhTGV2ZWwJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAAABAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OBANsb2MJALUJAgkBBXZhbHVlAQULY3VyTG9jYXRpb24CAV8DCQECIT0CCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIBTAkAAgEJAKwCAgkArAICAhZEdWNrIGxvY2F0aW9uIHR5cGUgaXMgCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIRLCBidXQgc2hvdWxkIGJlIEwDCQECIT0CCQCRAwIFA2xvYwUIbG9jSWR4SWQFC2xhbmRBc3NldElkCQACAQkArAICAhtEdWNrIHNob3VsZCBiZSBvbiB0aGUgbGFuZCAFC2xhbmRBc3NldElkBAV3aEtleQkBEmtleVdhcmVob3VzZUJ5TGFuZAEFC2xhbmRBc3NldElkBAljdXJyZW50V2gJAQxnZXRXYXJlaG91c2UDBQV3aEtleQUJbGFuZEluZGV4BQppbmZyYUxldmVsBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQGcmVzdWx0CQEJbW92ZVN0dWZmAwUKY2FyZ29QYXJ0cwUJY3VycmVudFdoBQtjdXJyZW50UGFjawQEbG9mdAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhMT0ZUAgFfBAVsb2Z0TwkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAgFBnJlc3VsdAJfNwQFbG9mdEYJAGUCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAUHdm9sRnJlZQgFBnJlc3VsdAJfNwkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAugkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAggFBnJlc3VsdAJfNAkAzAgCCAUGcmVzdWx0Al81CQDMCAIIBQZyZXN1bHQCXzYFA25pbAIBOgkAzAgCCQELU3RyaW5nRW50cnkCBQV3aEtleQkAugkCCQDMCAIJAJEDAgUJY3VycmVudFdoBQt3aElkeExldmVscwkAzAgCCAUGcmVzdWx0Al8xCQDMCAIIBQZyZXN1bHQCXzIJAMwIAggFBnJlc3VsdAJfMwkAzAgCCQC5CQIJAMwIAgkAkQMCBQRsb2Z0BQl2b2xMb2NrZWQJAMwIAgkApAMBBQVsb2Z0TwkAzAgCCQCkAwEFBWxvZnRGCQDMCAIJAJEDAgUEbG9mdAUIdm9sVG90YWwFA25pbAIBXwUDbmlsAgE6CQDMCAIFDHByb2xvZ0FjdGlvbgUDbmlsAWkBDXNhdmVXYXJlaG91c2UCBXdoU3RyC2xhbmRBc3NldElkBAxwcm9sb2dBY3Rpb24JAQZwcm9sb2cBBQFpAwkBAiE9AggFAWkGY2FsbGVyBQ9lY29ub215Q29udHJhY3QJAAIBAg1BY2Nlc3MgZGVuaWVkBAV3aEtleQkBEmtleVdhcmVob3VzZUJ5TGFuZAEFC2xhbmRBc3NldElkBAJ3aAkAvAkCBQV3aFN0cgIBOgMJAQIhPQIJAJADAQUCd2gABQkAAgECMHdhcmVob3VzZSBzdHJpbmcgc2hvdWxkIGNvbnRhaW4gNCAnOicgc2VwYXJhdG9ycwQFbG9mdEwJAJEDAgkAtQkCCQCRAwIFAndoBQl3aElkeExPRlQCAV8FCXZvbExvY2tlZAQFbG9mdE8JARdnZXRXYXJlaG91c2VPY2N1cGllZFZvbAEFAndoBAVsb2Z0VAkBF2dldFdhcmVob3VzZVRvdGFsVm9sdW1lAQkAkQMCBQJ3aAULd2hJZHhMZXZlbHMEBWxvZnRGCQBlAgkAZQIFBWxvZnRUCQENcGFyc2VJbnRWYWx1ZQEFBWxvZnRMBQVsb2Z0TwQIbmV3V2hTdHIJALoJAgkAzAgCCQCRAwIFAndoBQt3aElkeExldmVscwkAzAgCCQCRAwIFAndoBQh3aElkeFJlcwkAzAgCCQCRAwIFAndoBQh3aElkeE1hdAkAzAgCCQCRAwIFAndoBQl3aElkeFByb2QJAMwIAgkAuQkCCQDMCAIFBWxvZnRMCQDMCAIJAKQDAQUFbG9mdE8JAMwIAgkApAMBBQVsb2Z0RgkAzAgCCQCkAwEFBWxvZnRUBQNuaWwCAV8FA25pbAIBOgkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBXdoS2V5BQhuZXdXaFN0cgkAzAgCBQxwcm9sb2dBY3Rpb24FA25pbAUIbmV3V2hTdHIBaQESZml4V2FyZWhvdXNlRm9ybWF0AQtsYW5kQXNzZXRJZAMJAQIhPQIIBQFpBmNhbGxlcgUMcmVzdENvbnRyYWN0CQACAQINQWNjZXNzIGRlbmllZAQFd2hLZXkJARJrZXlXYXJlaG91c2VCeUxhbmQBBQtsYW5kQXNzZXRJZAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQJbGFuZEluZGV4CQBpAgkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAgkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8FC3JlY0xhbmRTaXplBQVTU0laRQQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAEAndoCQEMZ2V0V2FyZWhvdXNlAwUFd2hLZXkFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAQFbG9mdEwJAQVhc0ludAEJAPwHBAUPZWNvbm9teUNvbnRyYWN0AhpyZWNhbGNMb2NrZWRWb2x1bWVSRUFET05MWQkAzAgCBQtsYW5kQXNzZXRJZAkAzAgCBQJ3aAUDbmlsBQNuaWwEBWxvZnRPCQEXZ2V0V2FyZWhvdXNlT2NjdXBpZWRWb2wBBQJ3aAQFbG9mdFQJARdnZXRXYXJlaG91c2VUb3RhbFZvbHVtZQEJAJEDAgUCd2gFC3doSWR4TGV2ZWxzBAVsb2Z0RgkAZQIJAGUCBQVsb2Z0VAUFbG9mdEwFBWxvZnRPBAhuZXdXaFN0cgkAugkCCQDMCAIJAJEDAgUCd2gFC3doSWR4TGV2ZWxzCQDMCAIJAJEDAgUCd2gFCHdoSWR4UmVzCQDMCAIJAJEDAgUCd2gFCHdoSWR4TWF0CQDMCAIJAJEDAgUCd2gFCXdoSWR4UHJvZAkAzAgCCQC5CQIJAMwIAgkApAMBBQVsb2Z0TAkAzAgCCQCkAwEFBWxvZnRPCQDMCAIJAKQDAQUFbG9mdEYJAMwIAgkApAMBBQVsb2Z0VAUDbmlsAgFfBQNuaWwCAToJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQV3aEtleQUIbmV3V2hTdHIFA25pbAUIbmV3V2hTdHIBaQEPZml4U3Rha2VkUGllY2VzAQdhZGRyZXNzAwkBAiE9AggFAWkGY2FsbGVyBQxyZXN0Q29udHJhY3QJAAIBAg1BY2Nlc3MgZGVuaWVkBAxzdGFrZWRQaWVjZXMDCQAAAgUHYWRkcmVzcwIAAAAECGxhbmRzU3RyCQCdCAIFD3N0YWtpbmdDb250cmFjdAkBFWtleVN0YWtlZExhbmRzQnlPd25lcgEFB2FkZHJlc3MEBWxhbmRzAwkBCWlzRGVmaW5lZAEFCGxhbmRzU3RyCQC9CQIJAQV2YWx1ZQEFCGxhbmRzU3RyAgFfBQNuaWwKAQdvbmVMYW5kAgNhY2MLbGFuZEFzc2V0SWQEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQULbGFuZEFzc2V0SWQECGxhbmRTaXplCQCRAwIJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBQtyZWNMYW5kU2l6ZQkAZAIFA2FjYwkBD251bVBpZWNlc0J5U2l6ZQEFCGxhbmRTaXplCgACJGwFBWxhbmRzCgACJHMJAJADAQUCJGwKAAUkYWNjMAAACgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdvbmVMYW5kAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhVMaXN0IHNpemUgZXhjZWVkcyAxMDAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyADMANAA1ADYANwA4ADkAOgA7ADwAPQA+AD8AQABBAEIAQwBEAEUARgBHAEgASQBKAEsATABNAE4ATwBQAFEAUgBTAFQAVQBWAFcAWABZAFoAWwBcAF0AXgBfAGAAYQBiAGMAZAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5U3Rha2VkUGllY2VzQnlPd25lcgEFB2FkZHJlc3MFDHN0YWtlZFBpZWNlcwUDbmlsBQxzdGFrZWRQaWVjZXMBaQENc2V0Q3VzdG9tTmFtZQMHYXNzZXRJZApjdXN0b21OYW1lBHR5cGUEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIIBQNwbXQHYXNzZXRJZAULdXNkdEFzc2V0SWQJAAIBAhpBbGxvd2VkIFVTRFQgcGF5bWVudCBvbmx5IQMJAQIhPQIIBQNwbXQGYW1vdW50BQxSRU5BTUlOR0NPU1QJAAIBCQCsAgICElBheW1lbnQgc2hvdWxkIGJlIAkApAMBBQxSRU5BTUlOR0NPU1QDCQEIY29udGFpbnMCBQpjdXN0b21OYW1lAgJfXwkAAgEJAKwCAgIeTmFtZSBzaG91bGQgbm90IGNvbnRhaW4gJ19fJzogBQpjdXN0b21OYW1lAwkAZgIJALECAQUKY3VzdG9tTmFtZQUKTUFYTkFNRUxFTgkAAgEJAKwCAgIZTmFtZSB0b28gbG9uZywgbWF4TGVuZ3RoPQkApAMBBQpNQVhOQU1FTEVOBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQHYWN0aW9ucwQHJG1hdGNoMAUEdHlwZQMJAAACAgdBQ0NPVU5UBQckbWF0Y2gwBApyZXZlcnNlS2V5CQEWa2V5Q3VzdG9tTmFtZVRvQWRkcmVzcwEFCmN1c3RvbU5hbWUECW5hbWVPd25lcgkAoggBBQpyZXZlcnNlS2V5AwkBCWlzRGVmaW5lZAEFCW5hbWVPd25lcgkAAgEJAKwCAgIZTmFtZSBhbHJlYWR5IHJlZ2lzdGVyZWQ6IAUKY3VzdG9tTmFtZQQNYWRkclRvTmFtZUtleQkBFmtleUFkZHJlc3NUb0N1c3RvbU5hbWUBBQRhZGRyBAdvbGROYW1lCQCiCAEFDWFkZHJUb05hbWVLZXkEB2ZyZWVPbGQDCQEJaXNEZWZpbmVkAQUHb2xkTmFtZQkAzAgCCQELRGVsZXRlRW50cnkBCQEWa2V5Q3VzdG9tTmFtZVRvQWRkcmVzcwEJAQV2YWx1ZQEFB29sZE5hbWUFA25pbAUDbmlsCQDNCAIJAM0IAgUHZnJlZU9sZAkBC1N0cmluZ0VudHJ5AgUNYWRkclRvTmFtZUtleQUKY3VzdG9tTmFtZQkBC1N0cmluZ0VudHJ5AgUKcmV2ZXJzZUtleQUEYWRkcgMJAAACAgRMQU5EBQckbWF0Y2gwBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUHYXNzZXRJZAMJAQEhAQkBCWlzRGVmaW5lZAEJAJ8IAQUHdGltZUtleQkAAgEJAKwCAggFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQdhc3NldElkCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMJAQIhPQIFBW93bmVyBQRhZGRyCQACAQkArAICBQpMQU5EUFJFRklYAg0gaXMgbm90IHlvdXJzBApyZXZlcnNlS2V5CQEaa2V5TGFuZEN1c3RvbU5hbWVUb0Fzc2V0SWQBBQpjdXN0b21OYW1lBAluYW1lT3duZXIJAKIIAQUKcmV2ZXJzZUtleQMJAQlpc0RlZmluZWQBBQluYW1lT3duZXIJAAIBCQCsAgICGU5hbWUgYWxyZWFkeSByZWdpc3RlcmVkOiAFCmN1c3RvbU5hbWUEDmFzc2V0VG9OYW1lS2V5CQEaa2V5TGFuZEFzc2V0SWRUb0N1c3RvbU5hbWUBBQdhc3NldElkBAdvbGROYW1lCQCiCAEFDmFzc2V0VG9OYW1lS2V5BAdmcmVlT2xkAwkBCWlzRGVmaW5lZAEFB29sZE5hbWUJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBGmtleUxhbmRDdXN0b21OYW1lVG9Bc3NldElkAQkBBXZhbHVlAQUHb2xkTmFtZQUDbmlsBQNuaWwJAM0IAgkAzQgCBQdmcmVlT2xkCQELU3RyaW5nRW50cnkCBQ5hc3NldFRvTmFtZUtleQUKY3VzdG9tTmFtZQkBC1N0cmluZ0VudHJ5AgUKcmV2ZXJzZUtleQUHYXNzZXRJZAMJAAACAgREVUNLBQckbWF0Y2gwBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUHYXNzZXRJZAMDCQEBIQEJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkGCQEBIQEJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHIJAAIBCQCsAgIIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEQa2V5RHVja0lkVG9Pd25lcgEFB2Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkRVQ0tQUkVGSVgCDSBpcyBub3QgeW91cnMECnJldmVyc2VLZXkJARprZXlEdWNrQ3VzdG9tTmFtZVRvQXNzZXRJZAEFCmN1c3RvbU5hbWUECW5hbWVPd25lcgkAoggBBQpyZXZlcnNlS2V5AwkBCWlzRGVmaW5lZAEFCW5hbWVPd25lcgkAAgEJAKwCAgIZTmFtZSBhbHJlYWR5IHJlZ2lzdGVyZWQ6IAUKY3VzdG9tTmFtZQQOYXNzZXRUb05hbWVLZXkJARprZXlEdWNrQXNzZXRJZFRvQ3VzdG9tTmFtZQEFB2Fzc2V0SWQEB29sZE5hbWUJAKIIAQUOYXNzZXRUb05hbWVLZXkEB2ZyZWVPbGQDCQEJaXNEZWZpbmVkAQUHb2xkTmFtZQkAzAgCCQELRGVsZXRlRW50cnkBCQEaa2V5RHVja0N1c3RvbU5hbWVUb0Fzc2V0SWQBCQEFdmFsdWUBBQdvbGROYW1lBQNuaWwFA25pbAkAzQgCCQDNCAIFB2ZyZWVPbGQJAQtTdHJpbmdFbnRyeQIFDmFzc2V0VG9OYW1lS2V5BQpjdXN0b21OYW1lCQELU3RyaW5nRW50cnkCBQpyZXZlcnNlS2V5BQdhc3NldElkCQACAQITVW5rbm93biBlbnRpdHkgdHlwZQkAlAoCCQDNCAIJAM0IAgUHYWN0aW9ucwkBDlNjcmlwdFRyYW5zZmVyAwUPZWNvbm9teUNvbnRyYWN0CAUDcG10BmFtb3VudAULdXNkdEFzc2V0SWQFDHByb2xvZ0FjdGlvbgAAAWkBDHNldFJlZmVycmFscwIJb2xkUGxheWVyCW5ld1BsYXllcgMJAQIhPQIIBQFpD2NhbGxlclB1YmxpY0tleQUDcHViCQACAQIRUGVybWlzc2lvbiBkZW5pZWQEDHByb2xvZ0FjdGlvbgkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAMJAQEhAQkBCWlzRGVmaW5lZAEJAKYIAQUJb2xkUGxheWVyCQACAQkArAICAhFJbnZhbGlkIGFkZHJlc3M6IAUJb2xkUGxheWVyAwkBASEBCQEJaXNEZWZpbmVkAQkApggBBQluZXdQbGF5ZXIJAAIBCQCsAgICEUludmFsaWQgYWRkcmVzczogBQluZXdQbGF5ZXIEB29sZHNLZXkJAQlrZXlPbGRpZXMABARvbGRzCQCiCAEFB29sZHNLZXkEBm9sZGllcwMJAQlpc0RlZmluZWQBBQRvbGRzCQC8CQIJAQV2YWx1ZQEFBG9sZHMCAV8FA25pbAMJAQ9jb250YWluc0VsZW1lbnQCBQZvbGRpZXMFCW5ld1BsYXllcgkAAgEJAKwCAgUJbmV3UGxheWVyAiYgaXMgbm90IG5ld2JpZSAoYWxyZWFkeSBoYXMgcmVmZXJyYWxzKQQIcmVmQnlLZXkJAQ9rZXlBZGRyZXNzUmVmQnkBBQluZXdQbGF5ZXIEBXJlZkJ5CQCiCAEFCHJlZkJ5S2V5AwMJAQlpc0RlZmluZWQBBQVyZWZCeQkBCWlzRGVmaW5lZAEJAKYIAQkBBXZhbHVlAQUFcmVmQnkHCQACAQkArAICCQCsAgIFCW5ld1BsYXllcgIUIGFscmVhZHkgaGFzIHJlZkJ5OiAJAQV2YWx1ZQEFBXJlZkJ5BAdyZWZzS2V5CQETa2V5QWRkcmVzc1JlZmVycmFscwEFCW9sZFBsYXllcgQEcmVmcwkAoggBBQdyZWZzS2V5BAlyZWZzQXJyYXkDCQEJaXNEZWZpbmVkAQUEcmVmcwkAvAkCCQEFdmFsdWUBBQRyZWZzAgFfBQNuaWwDCQEPY29udGFpbnNFbGVtZW50AgUJcmVmc0FycmF5BQluZXdQbGF5ZXIJAAIBCQCsAgIJAKwCAgkArAICBQlvbGRQbGF5ZXICEiBhbHJlYWR5IGNvbnRhaW5zIAUJbmV3UGxheWVyAhEgd2l0aGluIHJlZmVycmFscwQHbmV3UmVmcwkAugkCCQDNCAIFCXJlZnNBcnJheQUJbmV3UGxheWVyAgFfBAduZXdPbGRzAwkBD2NvbnRhaW5zRWxlbWVudAIFBm9sZGllcwUJb2xkUGxheWVyCQEFdmFsdWUBBQRvbGRzCQC6CQIJAM0IAgUGb2xkaWVzBQlvbGRQbGF5ZXICAV8JAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQhyZWZCeUtleQUJb2xkUGxheWVyCQDMCAIJAQtTdHJpbmdFbnRyeQIFB3JlZnNLZXkFB25ld1JlZnMJAMwIAgkBC1N0cmluZ0VudHJ5AgUHb2xkc0tleQUHbmV3T2xkcwkAzAgCBQxwcm9sb2dBY3Rpb24FA25pbAAAAWkBHHNwbGl0QnlHbG9iYWxXZWlnaHRzUkVBRE9OTFkBBmFtb3VudAkAlAoCBQNuaWwJARJnZXROZWVkZWRNYXRlcmlhbHMBBQZhbW91bnQBaQEkc3BsaXRCeUdsb2JhbEFuZExvY2FsV2VpZ2h0c1JFQURPTkxZAwltYXRBbW91bnQJcmVzQW1vdW50CHRlcnJhaW5zBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEFCHRlcnJhaW5zCQCUCgIFA25pbAkAlAoCCQESZ2V0TmVlZGVkTWF0ZXJpYWxzAQUJbWF0QW1vdW50CQETZGlzdHJpYnV0ZUJ5V2VpZ2h0cwIFCXJlc0Ftb3VudAUNdGVycmFpbkNvdW50cwFpARNnZXRCYWNrcGFja1JFQURPTkxZAQtkdWNrQXNzZXRJZAkAlAoCBQNuaWwJALkJAgkBC2dldEJhY2twYWNrAQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQCAToBaQEUZ2V0V2FyZWhvdXNlUkVBRE9OTFkBC2xhbmRBc3NldElkBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAlsYW5kSW5kZXgJAGkCCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwULcmVjTGFuZFNpemUFBVNTSVpFBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAkAlAoCBQNuaWwJALoJAgkBDGdldFdhcmVob3VzZQMJARJrZXlXYXJlaG91c2VCeUxhbmQBBQtsYW5kQXNzZXRJZAUJbGFuZEluZGV4BQppbmZyYUxldmVsAgE6AWkBCnNhdmVMYXN0VHgAAwkBAiE9AggFAWkGY2FsbGVyBQt3bGdDb250cmFjdAkAAgECDUFjY2VzcyBkZW5pZWQJAJQKAgkAzAgCCQEGcHJvbG9nAQUBaQUDbmlsACoAkdkPSQ==", "height": 2642803, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: D29kBp3N4g14JqRFvanaL1j4Q5p1Dcy3VdjVk1cMkr6W Next: EwejSD1u6h8vHdktNygmbmoJ2n7qHUvVbnVSCjhapQ4F Diff:
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | + | let LANDPREFIX = "LAND" | |
5 | + | ||
6 | + | let DUCKPREFIX = "DUCK" | |
7 | + | ||
8 | + | let ARTPRESALE = "PRESALE" | |
9 | + | ||
10 | + | let NUMRES = 6 | |
11 | + | ||
12 | + | let DAILYRESBYPIECE = 3456000 | |
13 | + | ||
14 | + | let DAYMILLIS = 86400000 | |
15 | + | ||
16 | + | let WHMULTIPLIER = 10000000000 | |
17 | + | ||
18 | + | let DEFAULTLOCATION = "Africa_F_Africa" | |
19 | + | ||
20 | + | let RESOURCEPRICEMIN = 39637 | |
21 | + | ||
22 | + | let ESSELLCOEF = 10 | |
23 | + | ||
24 | + | let MAXHP = 100 | |
25 | + | ||
26 | + | 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"] | |
27 | + | ||
28 | + | let continents = ["Americas", "Europe", "Asia", "Africa", "Oceania"] | |
29 | + | ||
30 | + | let productionMatrix = ["1_1_1_2_2_5_1_10_0", "2_2_2_4_4_10_1_10_0", "3_3_3_6_6_15_1_10_0", "2_5_5_2_7_5_2_100_1", "4_10_10_4_14_10_2_100_1", "6_15_15_6_21_15_2_100_1", "1_1_1_1_1_8_1_10_2", "2_2_2_2_2_16_1_10_2", "3_3_3_3_3_24_1_10_2", "9_9_1_5_5_1_5_100_3", "18_18_2_10_10_2_5_100_3", "27_27_3_15_15_3_5_100_3", "2_2_1_2_2_2_1_10_4", "4_4_2_4_4_4_1_10_4", "6_6_3_6_6_6_1_10_4"] | |
31 | + | ||
32 | + | let recipeIdxPacksize = 7 | |
33 | + | ||
34 | + | let whIdxLevels = 0 | |
35 | + | ||
36 | + | let whIdxRes = 1 | |
37 | + | ||
38 | + | let whIdxMat = 2 | |
39 | + | ||
40 | + | let whIdxProd = 3 | |
41 | + | ||
42 | + | let whIdxLOFT = 4 | |
43 | + | ||
44 | + | let volLocked = 0 | |
45 | + | ||
46 | + | let volOccupied = 1 | |
47 | + | ||
48 | + | let volFree = 2 | |
49 | + | ||
50 | + | let volTotal = 3 | |
51 | + | ||
52 | + | let bpIdxLevel = 0 | |
53 | + | ||
54 | + | let bpIdxRes = 1 | |
55 | + | ||
56 | + | let bpIdxMat = 2 | |
57 | + | ||
58 | + | let bpIdxProd = 3 | |
59 | + | ||
60 | + | func getPkgSize (prodIdx) = parseIntValue(split(productionMatrix[prodIdx], "_")[recipeIdxPacksize]) | |
61 | + | ||
62 | + | ||
63 | + | func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr) | |
64 | + | ||
65 | + | ||
66 | + | func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId) | |
67 | + | ||
68 | + | ||
69 | + | func keyLandAssetIdToCustomName (assetId) = ("landCustomNameByAssetId_" + assetId) | |
70 | + | ||
71 | + | ||
72 | + | func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId) | |
73 | + | ||
74 | + | ||
75 | + | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
76 | + | ||
77 | + | ||
78 | + | func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["landArtStatus", type, assetId], "_") | |
79 | + | ||
80 | + | ||
81 | + | func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr) | |
82 | + | ||
83 | + | ||
84 | + | func keyWarehouseByLand (landAssetId) = ("wareHouse_" + landAssetId) | |
85 | + | ||
86 | + | ||
87 | + | func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr) | |
88 | + | ||
89 | + | ||
90 | + | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
91 | + | ||
92 | + | ||
93 | + | func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr) | |
94 | + | ||
95 | + | ||
96 | + | func keyAddressRefBy (addr) = ("accRefBy_" + addr) | |
97 | + | ||
98 | + | ||
99 | + | func keyAddressReferrals (addr) = ("accReferrals_" + addr) | |
100 | + | ||
101 | + | ||
102 | + | func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId) | |
103 | + | ||
104 | + | ||
105 | + | func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr) | |
106 | + | ||
107 | + | ||
108 | + | func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId) | |
109 | + | ||
110 | + | ||
111 | + | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
112 | + | ||
113 | + | ||
114 | + | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
115 | + | ||
116 | + | ||
117 | + | func keyBlocked () = "contractsBlocked" | |
118 | + | ||
119 | + | ||
120 | + | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
121 | + | ||
122 | + | ||
123 | + | func keyEsWarehouse () = "emergencyWarehouseProducts" | |
124 | + | ||
125 | + | ||
126 | + | let locIdxType = 1 | |
127 | + | ||
128 | + | let locIdxId = 2 | |
129 | + | ||
130 | + | func getRecipeMaterials (recipe) = { | |
131 | + | func addMat (ac,j) = (ac + parseIntValue(recipe[j])) | |
132 | + | ||
133 | + | let $l = [0, 1, 2, 3, 4, 5] | |
134 | + | let $s = size($l) | |
135 | + | let $acc0 = 0 | |
136 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
137 | + | then $a | |
138 | + | else addMat($a, $l[$i]) | |
139 | + | ||
140 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
141 | + | then $a | |
142 | + | else throw("List size exceeds 6") | |
143 | + | ||
144 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
145 | + | } | |
146 | + | ||
147 | + | ||
4 | 148 | let chain = take(drop(this.bytes, 1), 1) | |
5 | 149 | ||
6 | 150 | let usdtAssetId = match chain { | |
34 | 178 | ||
35 | 179 | let MULT6 = 1000000 | |
36 | 180 | ||
37 | - | let MULT7 = 10000000 | |
38 | - | ||
39 | 181 | let MULT8 = 100000000 | |
40 | 182 | ||
41 | - | let MULT10 = 10000000000 | |
42 | - | ||
43 | - | let LANDPREFIX = "LAND" | |
44 | - | ||
45 | - | let DUCKPREFIX = "DUCK" | |
46 | - | ||
47 | - | let ARTPRESALE = "PRESALE" | |
48 | - | ||
49 | - | let NUMRES = 6 | |
50 | - | ||
51 | 183 | let SSIZE = 25 | |
52 | 184 | ||
53 | 185 | let MSIZE = 100 | |
58 | 190 | ||
59 | 191 | let XXLSIZE = 625 | |
60 | 192 | ||
61 | - | let DAILYRESBYPIECE = 3456000 | |
62 | - | ||
63 | - | let DAYMILLIS = 86400000 | |
64 | - | ||
65 | - | let WHMULTIPLIER = 10000000000 | |
66 | - | ||
67 | - | let DEFAULTLOCATION = "Africa_F_Africa" | |
68 | - | ||
69 | - | let RESOURCEPRICEMIN = 39637 | |
70 | - | ||
71 | - | let ESMAXPACKAGES = 3 | |
72 | - | ||
73 | - | let ESBUYCOEF = 4 | |
74 | - | ||
75 | - | let ESSELLCOEF = 10 | |
76 | - | ||
77 | - | let MAXHP = 100 | |
78 | - | ||
79 | - | let resTypes = ["Oil", "Ore", "Wood", "Sand", "Clay", "Organic"] | |
80 | - | ||
81 | - | let matTypes = ["Fuel", "Metal", "Plank", "Glass", "Plastic", "Protein"] | |
82 | - | ||
83 | - | 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"] | |
84 | - | ||
85 | - | let continents = ["Americas", "Europe", "Asia", "Africa", "Oceania"] | |
86 | - | ||
87 | - | let productionMatrix = ["1_1_1_2_2_5_1_10_0", "2_2_2_4_4_10_1_10_0", "3_3_3_6_6_15_1_10_0", "2_5_5_2_7_5_2_100_1", "4_10_10_4_14_10_2_100_1", "6_15_15_6_21_15_2_100_1", "1_1_1_1_1_8_1_10_2", "2_2_2_2_2_16_1_10_2", "3_3_3_3_3_24_1_10_2", "9_9_1_5_5_1_5_100_3", "18_18_2_10_10_2_5_100_3", "27_27_3_15_15_3_5_100_3", "2_2_1_2_2_2_1_10_4", "4_4_2_4_4_4_1_10_4", "6_6_3_6_6_6_1_10_4"] | |
88 | - | ||
89 | - | let contIdxAmericas = 0 | |
90 | - | ||
91 | - | let contIdxEurope = 1 | |
92 | - | ||
93 | - | let contIdxAsia = 2 | |
94 | - | ||
95 | - | let contIdxAfrica = 3 | |
96 | - | ||
97 | - | let contIdxOceania = 4 | |
98 | - | ||
99 | - | let recipeIdxFuel = 0 | |
100 | - | ||
101 | - | let recipeIdxMetal = 1 | |
102 | - | ||
103 | - | let recipeIdxPlank = 2 | |
104 | - | ||
105 | - | let recipeIdxGlass = 3 | |
106 | - | ||
107 | - | let recipeIdxPlastic = 4 | |
108 | - | ||
109 | - | let recipeIdxProtein = 5 | |
110 | - | ||
111 | - | let recipeIdxWeight = 6 | |
112 | - | ||
113 | - | let recipeIdxPacksize = 7 | |
114 | - | ||
115 | - | let recipeIdxContinent = 8 | |
193 | + | func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")) | |
194 | + | ||
195 | + | ||
196 | + | let IdxCfgStakingDapp = 1 | |
197 | + | ||
198 | + | let IdxCfgEconomyDapp = 2 | |
199 | + | ||
200 | + | let IdxCfgGovernanceDapp = 3 | |
201 | + | ||
202 | + | let IdxCfgWlgDapp = 4 | |
203 | + | ||
204 | + | func keyRestCfg () = "%s__restConfig" | |
205 | + | ||
206 | + | ||
207 | + | func keyRestAddress () = "%s__restAddr" | |
208 | + | ||
209 | + | ||
210 | + | func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP) | |
211 | + | ||
212 | + | ||
213 | + | func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx))) | |
214 | + | ||
215 | + | ||
216 | + | let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr)) | |
217 | + | ||
218 | + | let restCfg = readRestCfgOrFail(restContract) | |
219 | + | ||
220 | + | let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp) | |
221 | + | ||
222 | + | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
223 | + | ||
224 | + | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
225 | + | ||
226 | + | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
116 | 227 | ||
117 | 228 | let recLandNum = 0 | |
118 | 229 | ||
122 | 233 | ||
123 | 234 | let recContinent = 3 | |
124 | 235 | ||
125 | - | let whIdxLevels = 0 | |
126 | - | ||
127 | - | let whIdxRes = 1 | |
128 | - | ||
129 | - | let whIdxMat = 2 | |
130 | - | ||
131 | - | let whIdxProd = 3 | |
132 | - | ||
133 | - | let whIdxLOFT = 4 | |
134 | - | ||
135 | - | let volLocked = 0 | |
136 | - | ||
137 | - | let volOccupied = 1 | |
138 | - | ||
139 | - | let volFree = 2 | |
140 | - | ||
141 | - | let volTotal = 3 | |
142 | - | ||
143 | - | let bpIdxLevel = 0 | |
144 | - | ||
145 | - | let bpIdxRes = 1 | |
146 | - | ||
147 | - | let bpIdxMat = 2 | |
148 | - | ||
149 | - | let bpIdxProd = 3 | |
150 | - | ||
151 | - | func getPkgSize (prodIdx) = parseIntValue(split(productionMatrix[prodIdx], "_")[recipeIdxPacksize]) | |
152 | - | ||
153 | - | ||
154 | - | func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")) | |
155 | - | ||
156 | - | ||
157 | - | func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal) | |
158 | - | ||
159 | - | ||
160 | - | let IdxCfgStakingDapp = 1 | |
161 | - | ||
162 | - | let IdxCfgEconomyDapp = 2 | |
163 | - | ||
164 | - | let IdxCfgGovernanceDapp = 3 | |
165 | - | ||
166 | - | let IdxCfgWlgDapp = 4 | |
167 | - | ||
168 | - | func keyRestCfg () = "%s__restConfig" | |
169 | - | ||
170 | - | ||
171 | - | func keyRestAddress () = "%s__restAddr" | |
172 | - | ||
173 | - | ||
174 | - | func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP) | |
175 | - | ||
176 | - | ||
177 | - | func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx))) | |
178 | - | ||
179 | - | ||
180 | - | let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr)) | |
181 | - | ||
182 | - | let restCfg = readRestCfgOrFail(restContract) | |
183 | - | ||
184 | - | let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp) | |
185 | - | ||
186 | - | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
187 | - | ||
188 | - | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
189 | - | ||
190 | - | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
191 | - | ||
192 | - | func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr) | |
193 | - | ||
194 | - | ||
195 | - | func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId) | |
196 | - | ||
197 | - | ||
198 | - | func keyLandAssetIdToCustomName (assetId) = ("landCustomNameByAssetId_" + assetId) | |
199 | - | ||
200 | - | ||
201 | - | func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId) | |
202 | - | ||
203 | - | ||
204 | - | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
205 | - | ||
206 | - | ||
207 | - | func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["landArtStatus", type, assetId], "_") | |
208 | - | ||
209 | - | ||
210 | - | func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr) | |
211 | - | ||
212 | - | ||
213 | - | func keyWarehouseByLand (landAssetId) = ("wareHouse_" + landAssetId) | |
236 | + | func keyResProportions () = "resTypesProportions" | |
214 | 237 | ||
215 | 238 | ||
216 | 239 | func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr) | |
217 | 240 | ||
218 | - | ||
219 | - | func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr) | |
220 | - | ||
221 | - | ||
222 | - | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
223 | - | ||
224 | - | ||
225 | - | func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr) | |
226 | - | ||
227 | - | ||
228 | - | func keyAddressRefBy (addr) = ("accRefBy_" + addr) | |
229 | - | ||
230 | - | ||
231 | - | func keyAddressReferrals (addr) = ("accReferrals_" + addr) | |
232 | - | ||
233 | - | ||
234 | - | func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId) | |
235 | - | ||
236 | - | ||
237 | - | func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr) | |
238 | - | ||
239 | - | ||
240 | - | func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId) | |
241 | - | ||
242 | - | ||
243 | - | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
244 | - | ||
245 | - | ||
246 | - | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
247 | - | ||
248 | - | ||
249 | - | func keyResProportions () = "resTypesProportions" | |
250 | - | ||
251 | - | ||
252 | - | func keyBlocked () = "contractsBlocked" | |
253 | - | ||
254 | - | ||
255 | - | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
256 | - | ||
257 | - | ||
258 | - | func keyOrderByLand (landAssetId) = ("landOrder_" + landAssetId) | |
259 | - | ||
260 | - | ||
261 | - | func keyEsWarehouse () = "emergencyWarehouseProducts" | |
262 | - | ||
263 | - | ||
264 | - | let locIdxContinent = 0 | |
265 | - | ||
266 | - | let locIdxType = 1 | |
267 | - | ||
268 | - | let locIdxId = 2 | |
269 | 241 | ||
270 | 242 | func asString (v) = match v { | |
271 | 243 | case s: String => | |
280 | 252 | n | |
281 | 253 | case _ => | |
282 | 254 | throw("fail to cast into Int") | |
283 | - | } | |
284 | - | ||
285 | - | ||
286 | - | func asAnyList (v) = match v { | |
287 | - | case l: List[Any] => | |
288 | - | l | |
289 | - | case _ => | |
290 | - | throw("fail to cast into List[Any]") | |
291 | - | } | |
292 | - | ||
293 | - | ||
294 | - | func asBoolean (v) = match v { | |
295 | - | case s: Boolean => | |
296 | - | s | |
297 | - | case _ => | |
298 | - | throw("fail to cast into Boolean") | |
299 | 255 | } | |
300 | 256 | ||
301 | 257 | ||
315 | 271 | } | |
316 | 272 | ||
317 | 273 | ||
318 | - | let IdxEffTotal = 0 | |
319 | - | ||
320 | - | let IdxEffUser = 1 | |
321 | - | ||
322 | - | func getVotingPower (userAddrStrOrEmpty) = { | |
323 | - | let props = split(valueOrElse(getString(stakingContract, keyResProportions()), "0_0_0_0_0_0"), "_") | |
324 | - | func adder (acc,item) = (acc + parseIntValue(item)) | |
325 | - | ||
326 | - | let totalPower = { | |
327 | - | let $l = props | |
328 | - | let $s = size($l) | |
329 | - | let $acc0 = 0 | |
330 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
331 | - | then $a | |
332 | - | else adder($a, $l[$i]) | |
333 | - | ||
334 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
335 | - | then $a | |
336 | - | else throw("List size exceeds 6") | |
337 | - | ||
338 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
339 | - | } | |
340 | - | let usersPower = if ((userAddrStrOrEmpty == "")) | |
341 | - | then 0 | |
342 | - | else { | |
343 | - | let landsStr = getString(stakingContract, keyStakedLandsByOwner(userAddrStrOrEmpty)) | |
344 | - | let lands = if (isDefined(landsStr)) | |
345 | - | then split_51C(value(landsStr), "_") | |
346 | - | else nil | |
347 | - | func oneLand (acc,landAssetId) = { | |
348 | - | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
349 | - | let landSize = split(asset.description, "_")[recLandSize] | |
350 | - | (acc + numPiecesBySize(landSize)) | |
351 | - | } | |
352 | - | ||
353 | - | let $l = lands | |
354 | - | let $s = size($l) | |
355 | - | let $acc0 = 0 | |
356 | - | func $f1_1 ($a,$i) = if (($i >= $s)) | |
357 | - | then $a | |
358 | - | else oneLand($a, $l[$i]) | |
359 | - | ||
360 | - | func $f1_2 ($a,$i) = if (($i >= $s)) | |
361 | - | then $a | |
362 | - | else throw("List size exceeds 100") | |
363 | - | ||
364 | - | $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($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($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($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), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
365 | - | } | |
366 | - | [totalPower, usersPower] | |
367 | - | } | |
368 | - | ||
369 | - | ||
370 | - | func getRecipeMaterials (recipe) = { | |
371 | - | func addMat (ac,j) = (ac + parseIntValue(recipe[j])) | |
372 | - | ||
373 | - | let $l = [0, 1, 2, 3, 4, 5] | |
374 | - | let $s = size($l) | |
375 | - | let $acc0 = 0 | |
376 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
377 | - | then $a | |
378 | - | else addMat($a, $l[$i]) | |
379 | - | ||
380 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
381 | - | then $a | |
382 | - | else throw("List size exceeds 6") | |
383 | - | ||
384 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
385 | - | } | |
386 | - | ||
387 | - | ||
388 | 274 | let incubatorAddr = match chain { | |
389 | 275 | case _ => | |
390 | 276 | if ((base58'2W' == $match0)) | |
481 | 367 | let claimModeWhThenDuck = 2 | |
482 | 368 | ||
483 | 369 | let flHealth = 0 | |
484 | - | ||
485 | - | let flMission = 1 | |
486 | - | ||
487 | - | let flObstacles = 2 | |
488 | - | ||
489 | - | let flWinds = 3 | |
490 | - | ||
491 | - | let flPath = 4 | |
492 | 370 | ||
493 | 371 | let flTimestamp = 5 | |
494 | 372 | ||
1148 | 1026 | ||
1149 | 1027 | ||
1150 | 1028 | func checkClaimConditions (addr,claimMode,landAssetIdIn) = { | |
1151 | - | let $ | |
1029 | + | let $t02444624985 = if ((claimMode == claimModeWh)) | |
1152 | 1030 | then $Tuple2(landAssetIdIn, valueOrElse(getString(keyStakedDuckByOwner(addr)), "")) | |
1153 | 1031 | else { | |
1154 | 1032 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1158 | 1036 | then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L")) | |
1159 | 1037 | else $Tuple2(loc[locIdxId], duckAssetId) | |
1160 | 1038 | } | |
1161 | - | let landAssetId = $ | |
1162 | - | let duckId = $ | |
1039 | + | let landAssetId = $t02444624985._1 | |
1040 | + | let duckId = $t02444624985._2 | |
1163 | 1041 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
1164 | 1042 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1165 | 1043 | let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Land " + asset.name) + " is not staked")) | |
1207 | 1085 | let currentPack = getBackpack(bpKey) | |
1208 | 1086 | let currentPackRes = split(currentPack[bpIdxRes], "_") | |
1209 | 1087 | let currentWhRes = split(currentWh[whIdxRes], "_") | |
1210 | - | let $ | |
1088 | + | let $t02735928230 = if ((claimMode == claimModeWh)) | |
1211 | 1089 | then $Tuple4(addRes(currentWhRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), currentPack[bpIdxRes], (parseIntValue(loft[volOccupied]) + resToClaim._2), (parseIntValue(loft[volFree]) - resToClaim._2)) | |
1212 | 1090 | else if ((claimMode == claimModeDuck)) | |
1213 | 1091 | then $Tuple4(currentWh[whIdxRes], addRes(currentPackRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), parseIntValue(loft[volOccupied]), parseIntValue(loft[volFree])) | |
1216 | 1094 | let whAm = min([parseIntValue(loft[volFree]), resToClaim._2]) | |
1217 | 1095 | $Tuple4(distr._1, distr._2, (parseIntValue(loft[volOccupied]) + whAm), (parseIntValue(loft[volFree]) - whAm)) | |
1218 | 1096 | } | |
1219 | - | let whRes = $ | |
1220 | - | let bpRes = $ | |
1221 | - | let loftO = $ | |
1222 | - | let loftF = $ | |
1097 | + | let whRes = $t02735928230._1 | |
1098 | + | let bpRes = $t02735928230._2 | |
1099 | + | let loftO = $t02735928230._3 | |
1100 | + | let loftF = $t02735928230._4 | |
1223 | 1101 | $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]], "_")]) | |
1224 | 1102 | } | |
1225 | 1103 | } | |
1266 | 1144 | } | |
1267 | 1145 | } | |
1268 | 1146 | } | |
1269 | - | ||
1270 | - | ||
1271 | - | func activateOnboardArt (addr) = 0 | |
1272 | 1147 | ||
1273 | 1148 | ||
1274 | 1149 | func activatePresaleArt (addr,landAssetIdIn) = { |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | + | let LANDPREFIX = "LAND" | |
5 | + | ||
6 | + | let DUCKPREFIX = "DUCK" | |
7 | + | ||
8 | + | let ARTPRESALE = "PRESALE" | |
9 | + | ||
10 | + | let NUMRES = 6 | |
11 | + | ||
12 | + | let DAILYRESBYPIECE = 3456000 | |
13 | + | ||
14 | + | let DAYMILLIS = 86400000 | |
15 | + | ||
16 | + | let WHMULTIPLIER = 10000000000 | |
17 | + | ||
18 | + | let DEFAULTLOCATION = "Africa_F_Africa" | |
19 | + | ||
20 | + | let RESOURCEPRICEMIN = 39637 | |
21 | + | ||
22 | + | let ESSELLCOEF = 10 | |
23 | + | ||
24 | + | let MAXHP = 100 | |
25 | + | ||
26 | + | 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"] | |
27 | + | ||
28 | + | let continents = ["Americas", "Europe", "Asia", "Africa", "Oceania"] | |
29 | + | ||
30 | + | let productionMatrix = ["1_1_1_2_2_5_1_10_0", "2_2_2_4_4_10_1_10_0", "3_3_3_6_6_15_1_10_0", "2_5_5_2_7_5_2_100_1", "4_10_10_4_14_10_2_100_1", "6_15_15_6_21_15_2_100_1", "1_1_1_1_1_8_1_10_2", "2_2_2_2_2_16_1_10_2", "3_3_3_3_3_24_1_10_2", "9_9_1_5_5_1_5_100_3", "18_18_2_10_10_2_5_100_3", "27_27_3_15_15_3_5_100_3", "2_2_1_2_2_2_1_10_4", "4_4_2_4_4_4_1_10_4", "6_6_3_6_6_6_1_10_4"] | |
31 | + | ||
32 | + | let recipeIdxPacksize = 7 | |
33 | + | ||
34 | + | let whIdxLevels = 0 | |
35 | + | ||
36 | + | let whIdxRes = 1 | |
37 | + | ||
38 | + | let whIdxMat = 2 | |
39 | + | ||
40 | + | let whIdxProd = 3 | |
41 | + | ||
42 | + | let whIdxLOFT = 4 | |
43 | + | ||
44 | + | let volLocked = 0 | |
45 | + | ||
46 | + | let volOccupied = 1 | |
47 | + | ||
48 | + | let volFree = 2 | |
49 | + | ||
50 | + | let volTotal = 3 | |
51 | + | ||
52 | + | let bpIdxLevel = 0 | |
53 | + | ||
54 | + | let bpIdxRes = 1 | |
55 | + | ||
56 | + | let bpIdxMat = 2 | |
57 | + | ||
58 | + | let bpIdxProd = 3 | |
59 | + | ||
60 | + | func getPkgSize (prodIdx) = parseIntValue(split(productionMatrix[prodIdx], "_")[recipeIdxPacksize]) | |
61 | + | ||
62 | + | ||
63 | + | func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr) | |
64 | + | ||
65 | + | ||
66 | + | func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId) | |
67 | + | ||
68 | + | ||
69 | + | func keyLandAssetIdToCustomName (assetId) = ("landCustomNameByAssetId_" + assetId) | |
70 | + | ||
71 | + | ||
72 | + | func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId) | |
73 | + | ||
74 | + | ||
75 | + | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
76 | + | ||
77 | + | ||
78 | + | func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["landArtStatus", type, assetId], "_") | |
79 | + | ||
80 | + | ||
81 | + | func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr) | |
82 | + | ||
83 | + | ||
84 | + | func keyWarehouseByLand (landAssetId) = ("wareHouse_" + landAssetId) | |
85 | + | ||
86 | + | ||
87 | + | func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr) | |
88 | + | ||
89 | + | ||
90 | + | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
91 | + | ||
92 | + | ||
93 | + | func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr) | |
94 | + | ||
95 | + | ||
96 | + | func keyAddressRefBy (addr) = ("accRefBy_" + addr) | |
97 | + | ||
98 | + | ||
99 | + | func keyAddressReferrals (addr) = ("accReferrals_" + addr) | |
100 | + | ||
101 | + | ||
102 | + | func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId) | |
103 | + | ||
104 | + | ||
105 | + | func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr) | |
106 | + | ||
107 | + | ||
108 | + | func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId) | |
109 | + | ||
110 | + | ||
111 | + | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
112 | + | ||
113 | + | ||
114 | + | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
115 | + | ||
116 | + | ||
117 | + | func keyBlocked () = "contractsBlocked" | |
118 | + | ||
119 | + | ||
120 | + | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
121 | + | ||
122 | + | ||
123 | + | func keyEsWarehouse () = "emergencyWarehouseProducts" | |
124 | + | ||
125 | + | ||
126 | + | let locIdxType = 1 | |
127 | + | ||
128 | + | let locIdxId = 2 | |
129 | + | ||
130 | + | func getRecipeMaterials (recipe) = { | |
131 | + | func addMat (ac,j) = (ac + parseIntValue(recipe[j])) | |
132 | + | ||
133 | + | let $l = [0, 1, 2, 3, 4, 5] | |
134 | + | let $s = size($l) | |
135 | + | let $acc0 = 0 | |
136 | + | func $f0_1 ($a,$i) = if (($i >= $s)) | |
137 | + | then $a | |
138 | + | else addMat($a, $l[$i]) | |
139 | + | ||
140 | + | func $f0_2 ($a,$i) = if (($i >= $s)) | |
141 | + | then $a | |
142 | + | else throw("List size exceeds 6") | |
143 | + | ||
144 | + | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
145 | + | } | |
146 | + | ||
147 | + | ||
4 | 148 | let chain = take(drop(this.bytes, 1), 1) | |
5 | 149 | ||
6 | 150 | let usdtAssetId = match chain { | |
7 | 151 | case _ => | |
8 | 152 | if ((base58'2W' == $match0)) | |
9 | 153 | then base58'9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi' | |
10 | 154 | else if ((base58'2T' == $match0)) | |
11 | 155 | then base58'6mWwf9mZBjVgkC54idpyaZLQfAosD914wT8fGf2iiY63' | |
12 | 156 | else throw("Unknown chain") | |
13 | 157 | } | |
14 | 158 | ||
15 | 159 | let defaultRestAddressStr = match chain { | |
16 | 160 | case _ => | |
17 | 161 | if ((base58'2W' == $match0)) | |
18 | 162 | then "3PQCuvFbvh4LkPUnrnU1z3jnbA1p9m3WNhv" | |
19 | 163 | else if ((base58'2T' == $match0)) | |
20 | 164 | then "3MumkGGztCKAXpWDqxkddofqXSUbqQkvSJy" | |
21 | 165 | else throw("Unknown chain") | |
22 | 166 | } | |
23 | 167 | ||
24 | 168 | let InfraUpgradeCostS = match chain { | |
25 | 169 | case _ => | |
26 | 170 | if ((base58'2W' == $match0)) | |
27 | 171 | then 10000000000 | |
28 | 172 | else if ((base58'2T' == $match0)) | |
29 | 173 | then 100000000 | |
30 | 174 | else throw("Unknown chain") | |
31 | 175 | } | |
32 | 176 | ||
33 | 177 | let SEP = "__" | |
34 | 178 | ||
35 | 179 | let MULT6 = 1000000 | |
36 | 180 | ||
37 | - | let MULT7 = 10000000 | |
38 | - | ||
39 | 181 | let MULT8 = 100000000 | |
40 | 182 | ||
41 | - | let MULT10 = 10000000000 | |
42 | - | ||
43 | - | let LANDPREFIX = "LAND" | |
44 | - | ||
45 | - | let DUCKPREFIX = "DUCK" | |
46 | - | ||
47 | - | let ARTPRESALE = "PRESALE" | |
48 | - | ||
49 | - | let NUMRES = 6 | |
50 | - | ||
51 | 183 | let SSIZE = 25 | |
52 | 184 | ||
53 | 185 | let MSIZE = 100 | |
54 | 186 | ||
55 | 187 | let LSIZE = 225 | |
56 | 188 | ||
57 | 189 | let XLSIZE = 400 | |
58 | 190 | ||
59 | 191 | let XXLSIZE = 625 | |
60 | 192 | ||
61 | - | let DAILYRESBYPIECE = 3456000 | |
62 | - | ||
63 | - | let DAYMILLIS = 86400000 | |
64 | - | ||
65 | - | let WHMULTIPLIER = 10000000000 | |
66 | - | ||
67 | - | let DEFAULTLOCATION = "Africa_F_Africa" | |
68 | - | ||
69 | - | let RESOURCEPRICEMIN = 39637 | |
70 | - | ||
71 | - | let ESMAXPACKAGES = 3 | |
72 | - | ||
73 | - | let ESBUYCOEF = 4 | |
74 | - | ||
75 | - | let ESSELLCOEF = 10 | |
76 | - | ||
77 | - | let MAXHP = 100 | |
78 | - | ||
79 | - | let resTypes = ["Oil", "Ore", "Wood", "Sand", "Clay", "Organic"] | |
80 | - | ||
81 | - | let matTypes = ["Fuel", "Metal", "Plank", "Glass", "Plastic", "Protein"] | |
82 | - | ||
83 | - | 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"] | |
84 | - | ||
85 | - | let continents = ["Americas", "Europe", "Asia", "Africa", "Oceania"] | |
86 | - | ||
87 | - | let productionMatrix = ["1_1_1_2_2_5_1_10_0", "2_2_2_4_4_10_1_10_0", "3_3_3_6_6_15_1_10_0", "2_5_5_2_7_5_2_100_1", "4_10_10_4_14_10_2_100_1", "6_15_15_6_21_15_2_100_1", "1_1_1_1_1_8_1_10_2", "2_2_2_2_2_16_1_10_2", "3_3_3_3_3_24_1_10_2", "9_9_1_5_5_1_5_100_3", "18_18_2_10_10_2_5_100_3", "27_27_3_15_15_3_5_100_3", "2_2_1_2_2_2_1_10_4", "4_4_2_4_4_4_1_10_4", "6_6_3_6_6_6_1_10_4"] | |
88 | - | ||
89 | - | let contIdxAmericas = 0 | |
90 | - | ||
91 | - | let contIdxEurope = 1 | |
92 | - | ||
93 | - | let contIdxAsia = 2 | |
94 | - | ||
95 | - | let contIdxAfrica = 3 | |
96 | - | ||
97 | - | let contIdxOceania = 4 | |
98 | - | ||
99 | - | let recipeIdxFuel = 0 | |
100 | - | ||
101 | - | let recipeIdxMetal = 1 | |
102 | - | ||
103 | - | let recipeIdxPlank = 2 | |
104 | - | ||
105 | - | let recipeIdxGlass = 3 | |
106 | - | ||
107 | - | let recipeIdxPlastic = 4 | |
108 | - | ||
109 | - | let recipeIdxProtein = 5 | |
110 | - | ||
111 | - | let recipeIdxWeight = 6 | |
112 | - | ||
113 | - | let recipeIdxPacksize = 7 | |
114 | - | ||
115 | - | let recipeIdxContinent = 8 | |
193 | + | func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")) | |
194 | + | ||
195 | + | ||
196 | + | let IdxCfgStakingDapp = 1 | |
197 | + | ||
198 | + | let IdxCfgEconomyDapp = 2 | |
199 | + | ||
200 | + | let IdxCfgGovernanceDapp = 3 | |
201 | + | ||
202 | + | let IdxCfgWlgDapp = 4 | |
203 | + | ||
204 | + | func keyRestCfg () = "%s__restConfig" | |
205 | + | ||
206 | + | ||
207 | + | func keyRestAddress () = "%s__restAddr" | |
208 | + | ||
209 | + | ||
210 | + | func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP) | |
211 | + | ||
212 | + | ||
213 | + | func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx))) | |
214 | + | ||
215 | + | ||
216 | + | let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr)) | |
217 | + | ||
218 | + | let restCfg = readRestCfgOrFail(restContract) | |
219 | + | ||
220 | + | let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp) | |
221 | + | ||
222 | + | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
223 | + | ||
224 | + | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
225 | + | ||
226 | + | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
116 | 227 | ||
117 | 228 | let recLandNum = 0 | |
118 | 229 | ||
119 | 230 | let recLandSize = 1 | |
120 | 231 | ||
121 | 232 | let recTerrains = 2 | |
122 | 233 | ||
123 | 234 | let recContinent = 3 | |
124 | 235 | ||
125 | - | let whIdxLevels = 0 | |
126 | - | ||
127 | - | let whIdxRes = 1 | |
128 | - | ||
129 | - | let whIdxMat = 2 | |
130 | - | ||
131 | - | let whIdxProd = 3 | |
132 | - | ||
133 | - | let whIdxLOFT = 4 | |
134 | - | ||
135 | - | let volLocked = 0 | |
136 | - | ||
137 | - | let volOccupied = 1 | |
138 | - | ||
139 | - | let volFree = 2 | |
140 | - | ||
141 | - | let volTotal = 3 | |
142 | - | ||
143 | - | let bpIdxLevel = 0 | |
144 | - | ||
145 | - | let bpIdxRes = 1 | |
146 | - | ||
147 | - | let bpIdxMat = 2 | |
148 | - | ||
149 | - | let bpIdxProd = 3 | |
150 | - | ||
151 | - | func getPkgSize (prodIdx) = parseIntValue(split(productionMatrix[prodIdx], "_")[recipeIdxPacksize]) | |
152 | - | ||
153 | - | ||
154 | - | func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")) | |
155 | - | ||
156 | - | ||
157 | - | func getIntOrElse (key,defaultVal) = valueOrElse(getInteger(this, key), defaultVal) | |
158 | - | ||
159 | - | ||
160 | - | let IdxCfgStakingDapp = 1 | |
161 | - | ||
162 | - | let IdxCfgEconomyDapp = 2 | |
163 | - | ||
164 | - | let IdxCfgGovernanceDapp = 3 | |
165 | - | ||
166 | - | let IdxCfgWlgDapp = 4 | |
167 | - | ||
168 | - | func keyRestCfg () = "%s__restConfig" | |
169 | - | ||
170 | - | ||
171 | - | func keyRestAddress () = "%s__restAddr" | |
172 | - | ||
173 | - | ||
174 | - | func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP) | |
175 | - | ||
176 | - | ||
177 | - | func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx))) | |
178 | - | ||
179 | - | ||
180 | - | let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr)) | |
181 | - | ||
182 | - | let restCfg = readRestCfgOrFail(restContract) | |
183 | - | ||
184 | - | let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp) | |
185 | - | ||
186 | - | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
187 | - | ||
188 | - | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
189 | - | ||
190 | - | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
191 | - | ||
192 | - | func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr) | |
193 | - | ||
194 | - | ||
195 | - | func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId) | |
196 | - | ||
197 | - | ||
198 | - | func keyLandAssetIdToCustomName (assetId) = ("landCustomNameByAssetId_" + assetId) | |
199 | - | ||
200 | - | ||
201 | - | func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId) | |
202 | - | ||
203 | - | ||
204 | - | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
205 | - | ||
206 | - | ||
207 | - | func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["landArtStatus", type, assetId], "_") | |
208 | - | ||
209 | - | ||
210 | - | func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr) | |
211 | - | ||
212 | - | ||
213 | - | func keyWarehouseByLand (landAssetId) = ("wareHouse_" + landAssetId) | |
236 | + | func keyResProportions () = "resTypesProportions" | |
214 | 237 | ||
215 | 238 | ||
216 | 239 | func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr) | |
217 | 240 | ||
218 | - | ||
219 | - | func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr) | |
220 | - | ||
221 | - | ||
222 | - | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
223 | - | ||
224 | - | ||
225 | - | func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr) | |
226 | - | ||
227 | - | ||
228 | - | func keyAddressRefBy (addr) = ("accRefBy_" + addr) | |
229 | - | ||
230 | - | ||
231 | - | func keyAddressReferrals (addr) = ("accReferrals_" + addr) | |
232 | - | ||
233 | - | ||
234 | - | func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId) | |
235 | - | ||
236 | - | ||
237 | - | func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr) | |
238 | - | ||
239 | - | ||
240 | - | func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId) | |
241 | - | ||
242 | - | ||
243 | - | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
244 | - | ||
245 | - | ||
246 | - | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
247 | - | ||
248 | - | ||
249 | - | func keyResProportions () = "resTypesProportions" | |
250 | - | ||
251 | - | ||
252 | - | func keyBlocked () = "contractsBlocked" | |
253 | - | ||
254 | - | ||
255 | - | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
256 | - | ||
257 | - | ||
258 | - | func keyOrderByLand (landAssetId) = ("landOrder_" + landAssetId) | |
259 | - | ||
260 | - | ||
261 | - | func keyEsWarehouse () = "emergencyWarehouseProducts" | |
262 | - | ||
263 | - | ||
264 | - | let locIdxContinent = 0 | |
265 | - | ||
266 | - | let locIdxType = 1 | |
267 | - | ||
268 | - | let locIdxId = 2 | |
269 | 241 | ||
270 | 242 | func asString (v) = match v { | |
271 | 243 | case s: String => | |
272 | 244 | s | |
273 | 245 | case _ => | |
274 | 246 | throw("fail to cast into String") | |
275 | 247 | } | |
276 | 248 | ||
277 | 249 | ||
278 | 250 | func asInt (v) = match v { | |
279 | 251 | case n: Int => | |
280 | 252 | n | |
281 | 253 | case _ => | |
282 | 254 | throw("fail to cast into Int") | |
283 | - | } | |
284 | - | ||
285 | - | ||
286 | - | func asAnyList (v) = match v { | |
287 | - | case l: List[Any] => | |
288 | - | l | |
289 | - | case _ => | |
290 | - | throw("fail to cast into List[Any]") | |
291 | - | } | |
292 | - | ||
293 | - | ||
294 | - | func asBoolean (v) = match v { | |
295 | - | case s: Boolean => | |
296 | - | s | |
297 | - | case _ => | |
298 | - | throw("fail to cast into Boolean") | |
299 | 255 | } | |
300 | 256 | ||
301 | 257 | ||
302 | 258 | func numPiecesBySize (landSize) = match landSize { | |
303 | 259 | case _ => | |
304 | 260 | if (("S" == $match0)) | |
305 | 261 | then SSIZE | |
306 | 262 | else if (("M" == $match0)) | |
307 | 263 | then MSIZE | |
308 | 264 | else if (("L" == $match0)) | |
309 | 265 | then LSIZE | |
310 | 266 | else if (("XL" == $match0)) | |
311 | 267 | then XLSIZE | |
312 | 268 | else if (("XXL" == $match0)) | |
313 | 269 | then XXLSIZE | |
314 | 270 | else throw("Unknown land size") | |
315 | 271 | } | |
316 | 272 | ||
317 | 273 | ||
318 | - | let IdxEffTotal = 0 | |
319 | - | ||
320 | - | let IdxEffUser = 1 | |
321 | - | ||
322 | - | func getVotingPower (userAddrStrOrEmpty) = { | |
323 | - | let props = split(valueOrElse(getString(stakingContract, keyResProportions()), "0_0_0_0_0_0"), "_") | |
324 | - | func adder (acc,item) = (acc + parseIntValue(item)) | |
325 | - | ||
326 | - | let totalPower = { | |
327 | - | let $l = props | |
328 | - | let $s = size($l) | |
329 | - | let $acc0 = 0 | |
330 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
331 | - | then $a | |
332 | - | else adder($a, $l[$i]) | |
333 | - | ||
334 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
335 | - | then $a | |
336 | - | else throw("List size exceeds 6") | |
337 | - | ||
338 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
339 | - | } | |
340 | - | let usersPower = if ((userAddrStrOrEmpty == "")) | |
341 | - | then 0 | |
342 | - | else { | |
343 | - | let landsStr = getString(stakingContract, keyStakedLandsByOwner(userAddrStrOrEmpty)) | |
344 | - | let lands = if (isDefined(landsStr)) | |
345 | - | then split_51C(value(landsStr), "_") | |
346 | - | else nil | |
347 | - | func oneLand (acc,landAssetId) = { | |
348 | - | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
349 | - | let landSize = split(asset.description, "_")[recLandSize] | |
350 | - | (acc + numPiecesBySize(landSize)) | |
351 | - | } | |
352 | - | ||
353 | - | let $l = lands | |
354 | - | let $s = size($l) | |
355 | - | let $acc0 = 0 | |
356 | - | func $f1_1 ($a,$i) = if (($i >= $s)) | |
357 | - | then $a | |
358 | - | else oneLand($a, $l[$i]) | |
359 | - | ||
360 | - | func $f1_2 ($a,$i) = if (($i >= $s)) | |
361 | - | then $a | |
362 | - | else throw("List size exceeds 100") | |
363 | - | ||
364 | - | $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($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($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($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), 26), 27), 28), 29), 30), 31), 32), 33), 34), 35), 36), 37), 38), 39), 40), 41), 42), 43), 44), 45), 46), 47), 48), 49), 50), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
365 | - | } | |
366 | - | [totalPower, usersPower] | |
367 | - | } | |
368 | - | ||
369 | - | ||
370 | - | func getRecipeMaterials (recipe) = { | |
371 | - | func addMat (ac,j) = (ac + parseIntValue(recipe[j])) | |
372 | - | ||
373 | - | let $l = [0, 1, 2, 3, 4, 5] | |
374 | - | let $s = size($l) | |
375 | - | let $acc0 = 0 | |
376 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
377 | - | then $a | |
378 | - | else addMat($a, $l[$i]) | |
379 | - | ||
380 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
381 | - | then $a | |
382 | - | else throw("List size exceeds 6") | |
383 | - | ||
384 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
385 | - | } | |
386 | - | ||
387 | - | ||
388 | 274 | let incubatorAddr = match chain { | |
389 | 275 | case _ => | |
390 | 276 | if ((base58'2W' == $match0)) | |
391 | 277 | then addressFromStringValue("3PEktVux2RhchSN63DsDo4b4mz4QqzKSeDv") | |
392 | 278 | else if ((base58'2T' == $match0)) | |
393 | 279 | then this | |
394 | 280 | else throw("Unknown chain") | |
395 | 281 | } | |
396 | 282 | ||
397 | 283 | let breederAddr = match chain { | |
398 | 284 | case _ => | |
399 | 285 | if ((base58'2W' == $match0)) | |
400 | 286 | then addressFromStringValue("3PDVuU45H7Eh5dmtNbnRNRStGwULA7NY6Hb") | |
401 | 287 | else if ((base58'2T' == $match0)) | |
402 | 288 | then this | |
403 | 289 | else throw("Unknown chain") | |
404 | 290 | } | |
405 | 291 | ||
406 | 292 | let pub = base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD' | |
407 | 293 | ||
408 | 294 | let medKitHp = [30, 60, 120] | |
409 | 295 | ||
410 | 296 | let FIVEMINUTESMILLIS = 300000 | |
411 | 297 | ||
412 | 298 | let RENAMINGCOST = 5000000 | |
413 | 299 | ||
414 | 300 | let MAXNAMELEN = 50 | |
415 | 301 | ||
416 | 302 | let InfraUpgradeCostSUsdt = 10000000 | |
417 | 303 | ||
418 | 304 | let EXPMATERIALS = match chain { | |
419 | 305 | case _ => | |
420 | 306 | if ((base58'2W' == $match0)) | |
421 | 307 | then 252289527462 | |
422 | 308 | else if ((base58'2T' == $match0)) | |
423 | 309 | then 2522895274 | |
424 | 310 | else throw("Unknown chain") | |
425 | 311 | } | |
426 | 312 | ||
427 | 313 | let EXPUSDT = match chain { | |
428 | 314 | case _ => | |
429 | 315 | if ((base58'2W' == $match0)) | |
430 | 316 | then 250000000 | |
431 | 317 | else if ((base58'2T' == $match0)) | |
432 | 318 | then 250000000 | |
433 | 319 | else throw("Unknown chain") | |
434 | 320 | } | |
435 | 321 | ||
436 | 322 | let FIVEX = toBigInt(5) | |
437 | 323 | ||
438 | 324 | let TWENTYX = toBigInt(20) | |
439 | 325 | ||
440 | 326 | let TWENTY2X = toBigInt((20 * 20)) | |
441 | 327 | ||
442 | 328 | let TWENTY3X = toBigInt(((20 * 20) * 20)) | |
443 | 329 | ||
444 | 330 | let TWENTY4X = toBigInt((((20 * 20) * 20) * 20)) | |
445 | 331 | ||
446 | 332 | let TWENTY5X = toBigInt(((((20 * 20) * 20) * 20) * 20)) | |
447 | 333 | ||
448 | 334 | let PRESALENUMLANDS = 500 | |
449 | 335 | ||
450 | 336 | func keyNextFreeLandNum () = "nextLandNum" | |
451 | 337 | ||
452 | 338 | ||
453 | 339 | func keyLandToAssetId (landNum) = ("landToAsset_" + landNum) | |
454 | 340 | ||
455 | 341 | ||
456 | 342 | func keyLandCustomNameToAssetId (name) = ("landByCustomName_" + name) | |
457 | 343 | ||
458 | 344 | ||
459 | 345 | func keyInfraLevelByAssetIdAndOwner (assetId,ownerAddr) = ((("infraLevelByAssetIdAndOwner_" + assetId) + "_") + ownerAddr) | |
460 | 346 | ||
461 | 347 | ||
462 | 348 | func keyLandArtStatusByTypeAssetIdAndOwner (type,assetId,ownerAddr) = makeString(["landArtStatusByTypeAssetIdAndOwner", type, assetId, ownerAddr], "_") | |
463 | 349 | ||
464 | 350 | ||
465 | 351 | func keyLandNumToOwner (landNum) = ("landOwner_" + landNum) | |
466 | 352 | ||
467 | 353 | ||
468 | 354 | func keyDuckCustomNameToAssetId (name) = ("duckByCustomName_" + name) | |
469 | 355 | ||
470 | 356 | ||
471 | 357 | func keyCustomNameToAddress (name) = ("accountByCustomName_" + name) | |
472 | 358 | ||
473 | 359 | ||
474 | 360 | func keyOldies () = "oldiesList" | |
475 | 361 | ||
476 | 362 | ||
477 | 363 | let claimModeWh = 0 | |
478 | 364 | ||
479 | 365 | let claimModeDuck = 1 | |
480 | 366 | ||
481 | 367 | let claimModeWhThenDuck = 2 | |
482 | 368 | ||
483 | 369 | let flHealth = 0 | |
484 | - | ||
485 | - | let flMission = 1 | |
486 | - | ||
487 | - | let flObstacles = 2 | |
488 | - | ||
489 | - | let flWinds = 3 | |
490 | - | ||
491 | - | let flPath = 4 | |
492 | 370 | ||
493 | 371 | let flTimestamp = 5 | |
494 | 372 | ||
495 | 373 | let flBonus = 6 | |
496 | 374 | ||
497 | 375 | let flProdsUsed = 7 | |
498 | 376 | ||
499 | 377 | func nftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize) | |
500 | 378 | ||
501 | 379 | ||
502 | 380 | func distributeByWeights (total,weights) = { | |
503 | 381 | let sum = (((((weights[0] + weights[1]) + weights[2]) + weights[3]) + weights[4]) + weights[5]) | |
504 | 382 | if ((0 >= sum)) | |
505 | 383 | then throw("Zero weights sum") | |
506 | 384 | else { | |
507 | 385 | let norm6 = fraction(total, MULT6, sum) | |
508 | 386 | func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6)) | |
509 | 387 | ||
510 | 388 | let $l = weights | |
511 | 389 | let $s = size($l) | |
512 | 390 | let $acc0 = nil | |
513 | 391 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
514 | 392 | then $a | |
515 | 393 | else normalizer($a, $l[$i]) | |
516 | 394 | ||
517 | 395 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
518 | 396 | then $a | |
519 | 397 | else throw("List size exceeds 6") | |
520 | 398 | ||
521 | 399 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
522 | 400 | } | |
523 | 401 | } | |
524 | 402 | ||
525 | 403 | ||
526 | 404 | func getNeededMaterials (total) = { | |
527 | 405 | let props = split(value(getString(keyResProportions())), "_") | |
528 | 406 | if ((size(props) != NUMRES)) | |
529 | 407 | then throw("Wrong proportions data") | |
530 | 408 | else { | |
531 | 409 | let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])] | |
532 | 410 | distributeByWeights(total, r) | |
533 | 411 | } | |
534 | 412 | } | |
535 | 413 | ||
536 | 414 | ||
537 | 415 | func subtractMaterials (shouldUseMat,has,totalNeed) = { | |
538 | 416 | let need = getNeededMaterials(totalNeed) | |
539 | 417 | func subtractor (acc,idx) = { | |
540 | 418 | let result = (parseIntValue(has[idx]) - need[idx]) | |
541 | 419 | if ((0 > result)) | |
542 | 420 | then throw(((((("Not enough material idx=" + toString(idx)) + ", you have ") + has[idx]) + ", but need ") + toString(need[idx]))) | |
543 | 421 | else (acc :+ toString(result)) | |
544 | 422 | } | |
545 | 423 | ||
546 | 424 | if (shouldUseMat) | |
547 | 425 | then { | |
548 | 426 | let $l = [0, 1, 2, 3, 4, 5] | |
549 | 427 | let $s = size($l) | |
550 | 428 | let $acc0 = nil | |
551 | 429 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
552 | 430 | then $a | |
553 | 431 | else subtractor($a, $l[$i]) | |
554 | 432 | ||
555 | 433 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
556 | 434 | then $a | |
557 | 435 | else throw("List size exceeds 6") | |
558 | 436 | ||
559 | 437 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
560 | 438 | } | |
561 | 439 | else has | |
562 | 440 | } | |
563 | 441 | ||
564 | 442 | ||
565 | 443 | func subtractProducts (pHas,pUsed) = if ((pUsed == "")) | |
566 | 444 | then pHas | |
567 | 445 | else { | |
568 | 446 | let pList = if ((pHas == "")) | |
569 | 447 | then nil | |
570 | 448 | else split(pHas, "_") | |
571 | 449 | func subP (acc,item) = { | |
572 | 450 | let j = acc._1 | |
573 | 451 | func checkUsed (ac,idxAmt) = { | |
574 | 452 | let parts = split(idxAmt, ",") | |
575 | 453 | if ((size(parts) != 2)) | |
576 | 454 | then throw("Incorrect format, should be index,amount") | |
577 | 455 | else { | |
578 | 456 | let idx = parseIntValue(parts[0]) | |
579 | 457 | if (if ((0 > idx)) | |
580 | 458 | then true | |
581 | 459 | else (idx >= size(productionMatrix))) | |
582 | 460 | then throw("Unknown product idx") | |
583 | 461 | else if ((idx != j)) | |
584 | 462 | then ac | |
585 | 463 | else { | |
586 | 464 | let amt = parseIntValue(parts[1]) | |
587 | 465 | if ((0 >= amt)) | |
588 | 466 | then throw("Pass only positive amounts") | |
589 | 467 | else (ac + amt) | |
590 | 468 | } | |
591 | 469 | } | |
592 | 470 | } | |
593 | 471 | ||
594 | 472 | let a = { | |
595 | 473 | let $l = split(pUsed, "_") | |
596 | 474 | let $s = size($l) | |
597 | 475 | let $acc0 = 0 | |
598 | 476 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
599 | 477 | then $a | |
600 | 478 | else checkUsed($a, $l[$i]) | |
601 | 479 | ||
602 | 480 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
603 | 481 | then $a | |
604 | 482 | else throw("List size exceeds 10") | |
605 | 483 | ||
606 | 484 | $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) | |
607 | 485 | } | |
608 | 486 | let curr = if ((size(pList) > j)) | |
609 | 487 | then parseIntValue(pList[j]) | |
610 | 488 | else 0 | |
611 | 489 | let newAmt = if ((a > curr)) | |
612 | 490 | then throw(((((("You have " + toString(curr)) + " of ") + prodTypes[j]) + ", but tried to use ") + toString(a))) | |
613 | 491 | else (curr - a) | |
614 | 492 | $Tuple2((j + 1), (acc._2 :+ toString(newAmt))) | |
615 | 493 | } | |
616 | 494 | ||
617 | 495 | let newProd = { | |
618 | 496 | let $l = productionMatrix | |
619 | 497 | let $s = size($l) | |
620 | 498 | let $acc0 = $Tuple2(0, nil) | |
621 | 499 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
622 | 500 | then $a | |
623 | 501 | else subP($a, $l[$i]) | |
624 | 502 | ||
625 | 503 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
626 | 504 | then $a | |
627 | 505 | else throw("List size exceeds 50") | |
628 | 506 | ||
629 | 507 | $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) | |
630 | 508 | } | |
631 | 509 | makeString(newProd._2, "_") | |
632 | 510 | } | |
633 | 511 | ||
634 | 512 | ||
635 | 513 | func updateProportionsInternal (propList,terrainCounts,landSizeIndex,sign) = if ((size(propList) != NUMRES)) | |
636 | 514 | then throw("Wrong proportions data") | |
637 | 515 | else { | |
638 | 516 | func updater (acc,i) = { | |
639 | 517 | let result = (parseIntValue(propList[i]) + ((sign * terrainCounts[i]) * landSizeIndex)) | |
640 | 518 | if ((0 > result)) | |
641 | 519 | then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex))) | |
642 | 520 | else (acc :+ toString(result)) | |
643 | 521 | } | |
644 | 522 | ||
645 | 523 | let r = { | |
646 | 524 | let $l = [0, 1, 2, 3, 4, 5] | |
647 | 525 | let $s = size($l) | |
648 | 526 | let $acc0 = nil | |
649 | 527 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
650 | 528 | then $a | |
651 | 529 | else updater($a, $l[$i]) | |
652 | 530 | ||
653 | 531 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
654 | 532 | then $a | |
655 | 533 | else throw("List size exceeds 6") | |
656 | 534 | ||
657 | 535 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
658 | 536 | } | |
659 | 537 | makeString(r, "_") | |
660 | 538 | } | |
661 | 539 | ||
662 | 540 | ||
663 | 541 | func updateProportions (terrainCounts,landSizeIndex,sign) = { | |
664 | 542 | let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_") | |
665 | 543 | updateProportionsInternal(propList, terrainCounts, landSizeIndex, sign) | |
666 | 544 | } | |
667 | 545 | ||
668 | 546 | ||
669 | 547 | 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)] | |
670 | 548 | ||
671 | 549 | ||
672 | 550 | func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = { | |
673 | 551 | func adder (acc,i) = { | |
674 | 552 | let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex) | |
675 | 553 | (acc :+ toString((parseIntValue(currentRes[i]) + resOfType))) | |
676 | 554 | } | |
677 | 555 | ||
678 | 556 | let r = { | |
679 | 557 | let $l = [0, 1, 2, 3, 4, 5] | |
680 | 558 | let $s = size($l) | |
681 | 559 | let $acc0 = nil | |
682 | 560 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
683 | 561 | then $a | |
684 | 562 | else adder($a, $l[$i]) | |
685 | 563 | ||
686 | 564 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
687 | 565 | then $a | |
688 | 566 | else throw("List size exceeds 6") | |
689 | 567 | ||
690 | 568 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
691 | 569 | } | |
692 | 570 | makeString(r, "_") | |
693 | 571 | } | |
694 | 572 | ||
695 | 573 | ||
696 | 574 | func virtClaim (terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = { | |
697 | 575 | func adder (acc,i) = { | |
698 | 576 | let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex) | |
699 | 577 | $Tuple2((acc._1 :+ resOfType), (acc._2 + resOfType)) | |
700 | 578 | } | |
701 | 579 | ||
702 | 580 | let $l = [0, 1, 2, 3, 4, 5] | |
703 | 581 | let $s = size($l) | |
704 | 582 | let $acc0 = $Tuple2(nil, 0) | |
705 | 583 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
706 | 584 | then $a | |
707 | 585 | else adder($a, $l[$i]) | |
708 | 586 | ||
709 | 587 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
710 | 588 | then $a | |
711 | 589 | else throw("List size exceeds 6") | |
712 | 590 | ||
713 | 591 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
714 | 592 | } | |
715 | 593 | ||
716 | 594 | ||
717 | 595 | func distributeRes (currentWhRes,currentPackRes,resToClaim,whSpaceLeft) = { | |
718 | 596 | let resListToClaim = resToClaim._1 | |
719 | 597 | let resAmToClaim = resToClaim._2 | |
720 | 598 | if ((resAmToClaim == 0)) | |
721 | 599 | then $Tuple2(makeString(currentWhRes, "_"), makeString(currentPackRes, "_")) | |
722 | 600 | else if ((whSpaceLeft >= resAmToClaim)) | |
723 | 601 | then { | |
724 | 602 | func addLists (acc,i) = (acc :+ toString((parseIntValue(currentWhRes[i]) + resListToClaim[i]))) | |
725 | 603 | ||
726 | 604 | let r = { | |
727 | 605 | let $l = [0, 1, 2, 3, 4, 5] | |
728 | 606 | let $s = size($l) | |
729 | 607 | let $acc0 = nil | |
730 | 608 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
731 | 609 | then $a | |
732 | 610 | else addLists($a, $l[$i]) | |
733 | 611 | ||
734 | 612 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
735 | 613 | then $a | |
736 | 614 | else throw("List size exceeds 6") | |
737 | 615 | ||
738 | 616 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
739 | 617 | } | |
740 | 618 | $Tuple2(makeString(r, "_"), makeString(currentPackRes, "_")) | |
741 | 619 | } | |
742 | 620 | else { | |
743 | 621 | func addPartLists (acc,i) = { | |
744 | 622 | let whPart = fraction(resListToClaim[i], whSpaceLeft, resAmToClaim) | |
745 | 623 | $Tuple2((acc._1 :+ toString((parseIntValue(currentWhRes[i]) + whPart))), (acc._2 :+ toString(((parseIntValue(currentPackRes[i]) + resListToClaim[i]) - whPart)))) | |
746 | 624 | } | |
747 | 625 | ||
748 | 626 | let r = { | |
749 | 627 | let $l = [0, 1, 2, 3, 4, 5] | |
750 | 628 | let $s = size($l) | |
751 | 629 | let $acc0 = $Tuple2(nil, nil) | |
752 | 630 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
753 | 631 | then $a | |
754 | 632 | else addPartLists($a, $l[$i]) | |
755 | 633 | ||
756 | 634 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
757 | 635 | then $a | |
758 | 636 | else throw("List size exceeds 6") | |
759 | 637 | ||
760 | 638 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
761 | 639 | } | |
762 | 640 | $Tuple2(makeString(r._1, "_"), makeString(r._2, "_")) | |
763 | 641 | } | |
764 | 642 | } | |
765 | 643 | ||
766 | 644 | ||
767 | 645 | func abs (x) = if ((x >= toBigInt(0))) | |
768 | 646 | then x | |
769 | 647 | else -(x) | |
770 | 648 | ||
771 | 649 | ||
772 | 650 | 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]] | |
773 | 651 | ||
774 | 652 | func genChar (n,freqs) = { | |
775 | 653 | let rem = toInt((n % TWENTYX)) | |
776 | 654 | let letter = if ((freqs[0] > rem)) | |
777 | 655 | then "A" | |
778 | 656 | else if ((freqs[1] > rem)) | |
779 | 657 | then "B" | |
780 | 658 | else if ((freqs[2] > rem)) | |
781 | 659 | then "C" | |
782 | 660 | else if ((freqs[3] > rem)) | |
783 | 661 | then "D" | |
784 | 662 | else if ((freqs[4] > rem)) | |
785 | 663 | then "E" | |
786 | 664 | else "F" | |
787 | 665 | letter | |
788 | 666 | } | |
789 | 667 | ||
790 | 668 | ||
791 | 669 | func genTerrains (seed,continentIdx) = { | |
792 | 670 | let f = freq[continentIdx] | |
793 | 671 | 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)) | |
794 | 672 | ||
795 | 673 | let t = { | |
796 | 674 | let $l = [1, 2, 3, 4, 5] | |
797 | 675 | let $s = size($l) | |
798 | 676 | let $acc0 = $Tuple2("", (seed / FIVEX)) | |
799 | 677 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
800 | 678 | then $a | |
801 | 679 | else terrainGenerator($a, $l[$i]) | |
802 | 680 | ||
803 | 681 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
804 | 682 | then $a | |
805 | 683 | else throw("List size exceeds 5") | |
806 | 684 | ||
807 | 685 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
808 | 686 | } | |
809 | 687 | t._1 | |
810 | 688 | } | |
811 | 689 | ||
812 | 690 | ||
813 | 691 | func getBackpack (bpKey) = { | |
814 | 692 | let p = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":") | |
815 | 693 | [toString(valueOrElse(parseInt(p[bpIdxLevel]), 0)), if ((size(split(p[bpIdxRes], "_")) == NUMRES)) | |
816 | 694 | then p[bpIdxRes] | |
817 | 695 | else "0_0_0_0_0_0", if ((size(split(p[bpIdxMat], "_")) == NUMRES)) | |
818 | 696 | then p[bpIdxMat] | |
819 | 697 | else "0_0_0_0_0_0", p[bpIdxProd]] | |
820 | 698 | } | |
821 | 699 | ||
822 | 700 | ||
823 | 701 | func getWarehouseTotalVolume (volPrefix) = { | |
824 | 702 | let parts = split(volPrefix, "_") | |
825 | 703 | ((WHMULTIPLIER * (parseIntValue(parts[1]) + 1)) * parseIntValue(parts[0])) | |
826 | 704 | } | |
827 | 705 | ||
828 | 706 | ||
829 | 707 | func getWarehouseOccupiedVol (currentWh) = { | |
830 | 708 | let goods = currentWh[whIdxProd] | |
831 | 709 | func sumResMat (acc,item) = (acc + parseIntValue(item)) | |
832 | 710 | ||
833 | 711 | func sumProd (acc,item) = { | |
834 | 712 | let idx = acc._1 | |
835 | 713 | let pkgSize = getPkgSize(idx) | |
836 | 714 | let pkgs = (((parseIntValue(item) + pkgSize) - 1) / pkgSize) | |
837 | 715 | $Tuple2((idx + 1), (acc._2 + (pkgs * MULT8))) | |
838 | 716 | } | |
839 | 717 | ||
840 | 718 | let whResVol = { | |
841 | 719 | let $l = split(currentWh[whIdxRes], "_") | |
842 | 720 | let $s = size($l) | |
843 | 721 | let $acc0 = 0 | |
844 | 722 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
845 | 723 | then $a | |
846 | 724 | else sumResMat($a, $l[$i]) | |
847 | 725 | ||
848 | 726 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
849 | 727 | then $a | |
850 | 728 | else throw("List size exceeds 6") | |
851 | 729 | ||
852 | 730 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
853 | 731 | } | |
854 | 732 | let whMatVol = { | |
855 | 733 | let $l = split(currentWh[whIdxMat], "_") | |
856 | 734 | let $s = size($l) | |
857 | 735 | let $acc0 = 0 | |
858 | 736 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
859 | 737 | then $a | |
860 | 738 | else sumResMat($a, $l[$i]) | |
861 | 739 | ||
862 | 740 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
863 | 741 | then $a | |
864 | 742 | else throw("List size exceeds 6") | |
865 | 743 | ||
866 | 744 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
867 | 745 | } | |
868 | 746 | let whGoodsVol = if ((goods == "")) | |
869 | 747 | then 0 | |
870 | 748 | else ( let $l = split_4C(goods, "_") | |
871 | 749 | let $s = size($l) | |
872 | 750 | let $acc0 = $Tuple2(0, 0) | |
873 | 751 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
874 | 752 | then $a | |
875 | 753 | else sumProd($a, $l[$i]) | |
876 | 754 | ||
877 | 755 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
878 | 756 | then $a | |
879 | 757 | else throw("List size exceeds 50") | |
880 | 758 | ||
881 | 759 | $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 | |
882 | 760 | ((whResVol + whMatVol) + whGoodsVol) | |
883 | 761 | } | |
884 | 762 | ||
885 | 763 | ||
886 | 764 | func getWarehouse (whKey,landIndex,infraLevel) = { | |
887 | 765 | let volPrefix = ((toString(landIndex) + "_") + toString(infraLevel)) | |
888 | 766 | let whTotal = getWarehouseTotalVolume(volPrefix) | |
889 | 767 | let whStr = valueOrElse(getString(whKey), (volPrefix + ":0_0_0_0_0_0:0_0_0_0_0_0::0")) | |
890 | 768 | let wh = split_4C(whStr, ":") | |
891 | 769 | let whOccupied = getWarehouseOccupiedVol(wh) | |
892 | 770 | let whLoft = if ((5 > size(wh))) | |
893 | 771 | then makeString(["0", toString(whOccupied), toString((whTotal - whOccupied)), toString(whTotal)], "_") | |
894 | 772 | else { | |
895 | 773 | let loft = split(wh[whIdxLOFT], "_") | |
896 | 774 | let whLocked = parseIntValue(loft[volLocked]) | |
897 | 775 | let occ = if ((size(loft) > 1)) | |
898 | 776 | then parseIntValue(loft[volOccupied]) | |
899 | 777 | else whOccupied | |
900 | 778 | makeString([toString(whLocked), toString(occ), toString(((whTotal - whLocked) - occ)), toString(whTotal)], "_") | |
901 | 779 | } | |
902 | 780 | [wh[whIdxLevels], if ((size(split(wh[whIdxRes], "_")) == NUMRES)) | |
903 | 781 | then wh[whIdxRes] | |
904 | 782 | else "0_0_0_0_0_0", if ((size(split(wh[whIdxMat], "_")) == NUMRES)) | |
905 | 783 | then wh[whIdxMat] | |
906 | 784 | else "0_0_0_0_0_0", wh[whIdxProd], whLoft] | |
907 | 785 | } | |
908 | 786 | ||
909 | 787 | ||
910 | 788 | func getWarehouseSpaceLeft (currentWh) = { | |
911 | 789 | let occupiedVol = getWarehouseOccupiedVol(currentWh) | |
912 | 790 | let currWhLockedVol = parseIntValue(split(currentWh[whIdxLOFT], "_")[volLocked]) | |
913 | 791 | ((getWarehouseTotalVolume(currentWh[whIdxLevels]) - occupiedVol) - currWhLockedVol) | |
914 | 792 | } | |
915 | 793 | ||
916 | 794 | ||
917 | 795 | func toVolume (amount,pkgSize) = { | |
918 | 796 | let pkgs = if ((amount >= 0)) | |
919 | 797 | then (((amount + pkgSize) - 1) / pkgSize) | |
920 | 798 | else -((((-(amount) + pkgSize) - 1) / pkgSize)) | |
921 | 799 | (pkgs * MULT8) | |
922 | 800 | } | |
923 | 801 | ||
924 | 802 | ||
925 | 803 | func moveStuff (cargoParts,currentWh,currentPack) = if ((size(cargoParts) != 3)) | |
926 | 804 | then throw("cargoListStr should contain exactly 2 ':' separators") | |
927 | 805 | else { | |
928 | 806 | let resParts = split(cargoParts[0], "_") | |
929 | 807 | let matParts = split(cargoParts[1], "_") | |
930 | 808 | let prodParts = if ((cargoParts[2] == "")) | |
931 | 809 | then nil | |
932 | 810 | else split(cargoParts[2], "_") | |
933 | 811 | if ((size(resParts) != NUMRES)) | |
934 | 812 | then throw("All 6 resources should be passed") | |
935 | 813 | else if ((size(matParts) != NUMRES)) | |
936 | 814 | then throw("All 6 materials should be passed") | |
937 | 815 | else { | |
938 | 816 | let whSpaceLeft = getWarehouseSpaceLeft(currentWh) | |
939 | 817 | let currWhRes = split(currentWh[whIdxRes], "_") | |
940 | 818 | let currWhMat = split(currentWh[whIdxMat], "_") | |
941 | 819 | let currWhProd = if ((currentWh[whIdxProd] == "")) | |
942 | 820 | then nil | |
943 | 821 | else split(currentWh[whIdxProd], "_") | |
944 | 822 | let currentPackRes = split(currentPack[bpIdxRes], "_") | |
945 | 823 | let currentPackMat = split(currentPack[bpIdxMat], "_") | |
946 | 824 | let currentPackProd = if ((currentPack[bpIdxProd] == "")) | |
947 | 825 | then nil | |
948 | 826 | else split(currentPack[bpIdxProd], "_") | |
949 | 827 | func mvR (acc,item) = { | |
950 | 828 | let i = acc._1 | |
951 | 829 | let am = parseIntValue(item) | |
952 | 830 | let whr = parseIntValue(currWhRes[i]) | |
953 | 831 | let bpr = parseIntValue(currentPackRes[i]) | |
954 | 832 | if ((am == 0)) | |
955 | 833 | then $Tuple4((i + 1), (acc._2 :+ currWhRes[i]), (acc._3 :+ currentPackRes[i]), acc._4) | |
956 | 834 | else if ((am > 0)) | |
957 | 835 | then if ((am > bpr)) | |
958 | 836 | then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpr)) + " available")) | |
959 | 837 | else $Tuple4((i + 1), (acc._2 :+ toString((whr + am))), (acc._3 :+ toString((bpr - am))), (acc._4 + am)) | |
960 | 838 | else if ((-(am) > whr)) | |
961 | 839 | then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whr)) + " available")) | |
962 | 840 | else $Tuple4((i + 1), (acc._2 :+ toString((whr + am))), (acc._3 :+ toString((bpr - am))), (acc._4 + am)) | |
963 | 841 | } | |
964 | 842 | ||
965 | 843 | let r = { | |
966 | 844 | let $l = resParts | |
967 | 845 | let $s = size($l) | |
968 | 846 | let $acc0 = $Tuple4(0, nil, nil, 0) | |
969 | 847 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
970 | 848 | then $a | |
971 | 849 | else mvR($a, $l[$i]) | |
972 | 850 | ||
973 | 851 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
974 | 852 | then $a | |
975 | 853 | else throw("List size exceeds 6") | |
976 | 854 | ||
977 | 855 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
978 | 856 | } | |
979 | 857 | func mvM (acc,item) = { | |
980 | 858 | let i = acc._1 | |
981 | 859 | let am = parseIntValue(item) | |
982 | 860 | let whm = parseIntValue(currWhMat[i]) | |
983 | 861 | let bpm = parseIntValue(currentPackMat[i]) | |
984 | 862 | if ((am == 0)) | |
985 | 863 | then $Tuple4((i + 1), (acc._2 :+ currWhMat[i]), (acc._3 :+ currentPackMat[i]), acc._4) | |
986 | 864 | else if ((am > 0)) | |
987 | 865 | then if ((am > bpm)) | |
988 | 866 | then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpm)) + " available")) | |
989 | 867 | else $Tuple4((i + 1), (acc._2 :+ toString((whm + am))), (acc._3 :+ toString((bpm - am))), (acc._4 + am)) | |
990 | 868 | else if ((-(am) > whm)) | |
991 | 869 | then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whm)) + " available")) | |
992 | 870 | else $Tuple4((i + 1), (acc._2 :+ toString((whm + am))), (acc._3 :+ toString((bpm - am))), (acc._4 + am)) | |
993 | 871 | } | |
994 | 872 | ||
995 | 873 | let m = { | |
996 | 874 | let $l = matParts | |
997 | 875 | let $s = size($l) | |
998 | 876 | let $acc0 = $Tuple4(0, nil, nil, r._4) | |
999 | 877 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
1000 | 878 | then $a | |
1001 | 879 | else mvM($a, $l[$i]) | |
1002 | 880 | ||
1003 | 881 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
1004 | 882 | then $a | |
1005 | 883 | else throw("List size exceeds 6") | |
1006 | 884 | ||
1007 | 885 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1008 | 886 | } | |
1009 | 887 | func mvP (acc,item) = { | |
1010 | 888 | let i = acc._1 | |
1011 | 889 | let pkgSize = getPkgSize(i) | |
1012 | 890 | let am = parseIntValue(item) | |
1013 | 891 | let whp = if ((size(currWhProd) > i)) | |
1014 | 892 | then parseIntValue(currWhProd[i]) | |
1015 | 893 | else 0 | |
1016 | 894 | let bpp = if ((size(currentPackProd) > i)) | |
1017 | 895 | then parseIntValue(currentPackProd[i]) | |
1018 | 896 | else 0 | |
1019 | 897 | if ((am == 0)) | |
1020 | 898 | then $Tuple4((i + 1), (acc._2 :+ toString(whp)), (acc._3 :+ toString(bpp)), acc._4) | |
1021 | 899 | else if ((am > 0)) | |
1022 | 900 | then if ((am > bpp)) | |
1023 | 901 | then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpp)) + " available")) | |
1024 | 902 | else { | |
1025 | 903 | let deltaVol = (toVolume((whp + am), pkgSize) - toVolume(whp, pkgSize)) | |
1026 | 904 | $Tuple4((i + 1), (acc._2 :+ toString((whp + am))), (acc._3 :+ toString((bpp - am))), (acc._4 + deltaVol)) | |
1027 | 905 | } | |
1028 | 906 | else if ((-(am) > whp)) | |
1029 | 907 | then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whp)) + " available")) | |
1030 | 908 | else { | |
1031 | 909 | let deltaVol = (toVolume((whp + am), pkgSize) - toVolume(whp, pkgSize)) | |
1032 | 910 | $Tuple4((i + 1), (acc._2 :+ toString((whp + am))), (acc._3 :+ toString((bpp - am))), (acc._4 + deltaVol)) | |
1033 | 911 | } | |
1034 | 912 | } | |
1035 | 913 | ||
1036 | 914 | let p = if ((size(prodParts) != 0)) | |
1037 | 915 | then { | |
1038 | 916 | let $l = prodParts | |
1039 | 917 | let $s = size($l) | |
1040 | 918 | let $acc0 = $Tuple4(0, nil, nil, m._4) | |
1041 | 919 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
1042 | 920 | then $a | |
1043 | 921 | else mvP($a, $l[$i]) | |
1044 | 922 | ||
1045 | 923 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
1046 | 924 | then $a | |
1047 | 925 | else throw("List size exceeds 50") | |
1048 | 926 | ||
1049 | 927 | $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) | |
1050 | 928 | } | |
1051 | 929 | else $Tuple4(0, currWhProd, currentPackProd, m._4) | |
1052 | 930 | let volSaldo = p._4 | |
1053 | 931 | if ((volSaldo > whSpaceLeft)) | |
1054 | 932 | then throw((((("Attempt to put total " + toString(volSaldo)) + " stuff, but only ") + toString(whSpaceLeft)) + " warehouse space left")) | |
1055 | 933 | else $Tuple7(makeString(r._2, "_"), makeString(m._2, "_"), makeString(p._2, "_"), makeString(r._3, "_"), makeString(m._3, "_"), makeString(p._3, "_"), volSaldo) | |
1056 | 934 | } | |
1057 | 935 | } | |
1058 | 936 | ||
1059 | 937 | ||
1060 | 938 | func expeditionInternal (caller,txId) = { | |
1061 | 939 | let userAddr = toString(caller) | |
1062 | 940 | let bigNum = abs(toBigInt(txId)) | |
1063 | 941 | let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1)) | |
1064 | 942 | let landNum = toString(freeNum) | |
1065 | 943 | let continentIdx = toInt((bigNum % FIVEX)) | |
1066 | 944 | let terrains = genTerrains(bigNum, continentIdx) | |
1067 | 945 | let continent = continents[continentIdx] | |
1068 | 946 | let issue = Issue(nftName(landNum, "S"), makeString([landNum, "S", terrains, continent], "_"), 1, 0, false) | |
1069 | 947 | let assetId = calculateAssetId(issue) | |
1070 | 948 | let id = toBase58String(assetId) | |
1071 | 949 | $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)) | |
1072 | 950 | } | |
1073 | 951 | ||
1074 | 952 | ||
1075 | 953 | func flightCommon (userAddr,message,sig) = if (!(sigVerify_8Kb(message, sig, pub))) | |
1076 | 954 | then throw("signature does not match") | |
1077 | 955 | else { | |
1078 | 956 | let parts = split(toUtf8String(message), ";") | |
1079 | 957 | let flightLog = split(parts[0], "|") | |
1080 | 958 | let hp = split(flightLog[flHealth], "_") | |
1081 | 959 | let curHP = parseIntValue(hp[0]) | |
1082 | 960 | let newHP = parseIntValue(hp[1]) | |
1083 | 961 | let newLocTxVer = split(parts[1], ":") | |
1084 | 962 | let newLocation = newLocTxVer[0] | |
1085 | 963 | let time = parseIntValue(flightLog[flTimestamp]) | |
1086 | 964 | if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS))) | |
1087 | 965 | then true | |
1088 | 966 | else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time)) | |
1089 | 967 | then throw(((("signature outdated: logTime=" + toString(time)) + ", bcTime=") + toString(lastBlock.timestamp))) | |
1090 | 968 | else { | |
1091 | 969 | let txFromMsg = newLocTxVer[1] | |
1092 | 970 | let lastTx = valueOrElse(getString(keyLastTxIdByUser(userAddr)), "") | |
1093 | 971 | if ((lastTx != txFromMsg)) | |
1094 | 972 | then throw(((("Tx ids don't match! In state: " + lastTx) + ", in msg: ") + txFromMsg)) | |
1095 | 973 | else { | |
1096 | 974 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked") | |
1097 | 975 | let keyHealth = keyDuckHealth(duckAssetId) | |
1098 | 976 | let oldFromState = valueOrElse(getInteger(keyHealth), 100) | |
1099 | 977 | if ((oldFromState != curHP)) | |
1100 | 978 | then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP))) | |
1101 | 979 | else if ((0 >= curHP)) | |
1102 | 980 | then throw("You can't fly with zero health") | |
1103 | 981 | else { | |
1104 | 982 | let bonus = if ((size(flightLog) > flBonus)) | |
1105 | 983 | then flightLog[flBonus] | |
1106 | 984 | else "" | |
1107 | 985 | let prodUsed = if ((size(flightLog) > flProdsUsed)) | |
1108 | 986 | then flightLog[flProdsUsed] | |
1109 | 987 | else "" | |
1110 | 988 | let sentAmount = if (if ((newHP > 0)) | |
1111 | 989 | then (bonus == "$") | |
1112 | 990 | else false) | |
1113 | 991 | then asInt(invoke(restContract, "sendUsdtPrize", [userAddr], nil)) | |
1114 | 992 | else 0 | |
1115 | 993 | $Tuple5(newHP, duckAssetId, sentAmount, newLocation, prodUsed) | |
1116 | 994 | } | |
1117 | 995 | } | |
1118 | 996 | } | |
1119 | 997 | } | |
1120 | 998 | ||
1121 | 999 | ||
1122 | 1000 | func expeditionCommon (caller,txId,message,sig) = { | |
1123 | 1001 | let userAddr = toString(caller) | |
1124 | 1002 | let f = flightCommon(userAddr, message, sig) | |
1125 | 1003 | let keyHealth = keyDuckHealth(f._2) | |
1126 | 1004 | let bpKey = keyBackpackByDuck(f._2) | |
1127 | 1005 | let currentPack = getBackpack(bpKey) | |
1128 | 1006 | let mList = split(currentPack[bpIdxMat], "_") | |
1129 | 1007 | let newMat = makeString(subtractMaterials(true, mList, EXPMATERIALS), "_") | |
1130 | 1008 | let newProd = subtractProducts(currentPack[bpIdxProd], f._5) | |
1131 | 1009 | if ((0 >= f._1)) | |
1132 | 1010 | then $Tuple3([IntegerEntry(keyHealth, 0), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], newProd], ":"))], "", 0) | |
1133 | 1011 | else { | |
1134 | 1012 | let e = expeditionInternal(caller, txId) | |
1135 | 1013 | let id = e._2._1 | |
1136 | 1014 | $Tuple3((((e._1 :+ StringEntry(keyDuckLocation(f._2), makeString([e._2._2, "L", id], "_"))) :+ IntegerEntry(keyHealth, f._1)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, newProd], ":"))), id, f._3) | |
1137 | 1015 | } | |
1138 | 1016 | } | |
1139 | 1017 | ||
1140 | 1018 | ||
1141 | 1019 | func applyBonuses (landAssetId,pieces) = { | |
1142 | 1020 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1143 | 1021 | let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0) | |
1144 | 1022 | let add6 = (infraLevel / 6) | |
1145 | 1023 | let add7 = (infraLevel / 7) | |
1146 | 1024 | ((DAILYRESBYPIECE + fraction(DAILYRESBYPIECE, ((infraLevel + add6) + (2 * add7)), 5)) + fraction(DAILYRESBYPIECE, artPieces, (pieces * 5))) | |
1147 | 1025 | } | |
1148 | 1026 | ||
1149 | 1027 | ||
1150 | 1028 | func checkClaimConditions (addr,claimMode,landAssetIdIn) = { | |
1151 | - | let $ | |
1029 | + | let $t02444624985 = if ((claimMode == claimModeWh)) | |
1152 | 1030 | then $Tuple2(landAssetIdIn, valueOrElse(getString(keyStakedDuckByOwner(addr)), "")) | |
1153 | 1031 | else { | |
1154 | 1032 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1155 | 1033 | let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION) | |
1156 | 1034 | let loc = split(value(curLocation), "_") | |
1157 | 1035 | if ((loc[locIdxType] != "L")) | |
1158 | 1036 | then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L")) | |
1159 | 1037 | else $Tuple2(loc[locIdxId], duckAssetId) | |
1160 | 1038 | } | |
1161 | - | let landAssetId = $ | |
1162 | - | let duckId = $ | |
1039 | + | let landAssetId = $t02444624985._1 | |
1040 | + | let duckId = $t02444624985._2 | |
1163 | 1041 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
1164 | 1042 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1165 | 1043 | let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Land " + asset.name) + " is not staked")) | |
1166 | 1044 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
1167 | 1045 | if ((owner != addr)) | |
1168 | 1046 | then throw((LANDPREFIX + " is not yours")) | |
1169 | 1047 | else { | |
1170 | 1048 | let d = split(asset.description, "_") | |
1171 | 1049 | $Tuple4(duckId, landAssetId, d, savedTime) | |
1172 | 1050 | } | |
1173 | 1051 | } | |
1174 | 1052 | ||
1175 | 1053 | ||
1176 | 1054 | func claimResInternal (addr,amount,claimMode,landAssetIdIn) = if ((0 > amount)) | |
1177 | 1055 | then throw("Negative amount") | |
1178 | 1056 | else { | |
1179 | 1057 | let c = checkClaimConditions(addr, claimMode, landAssetIdIn) | |
1180 | 1058 | let landSize = c._3[recLandSize] | |
1181 | 1059 | let terrainCounts = countTerrains(c._3[recTerrains]) | |
1182 | 1060 | let deltaTime = (lastBlock.timestamp - c._4) | |
1183 | 1061 | if ((0 > deltaTime)) | |
1184 | 1062 | then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", current = ") + toString(lastBlock.timestamp))) | |
1185 | 1063 | else { | |
1186 | 1064 | let pieces = numPiecesBySize(landSize) | |
1187 | 1065 | let dailyProductionByPiece = applyBonuses(c._2, pieces) | |
1188 | 1066 | let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS) | |
1189 | 1067 | if ((amount > availRes)) | |
1190 | 1068 | then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount))) | |
1191 | 1069 | else { | |
1192 | 1070 | let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces)) | |
1193 | 1071 | let newTimestamp = (lastBlock.timestamp - newDeltaTime) | |
1194 | 1072 | let landIndex = (pieces / SSIZE) | |
1195 | 1073 | let resToClaim = virtClaim(terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece) | |
1196 | 1074 | let whKey = keyWarehouseByLand(c._2) | |
1197 | 1075 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(c._2)), 0) | |
1198 | 1076 | let currentWh = getWarehouse(whKey, landIndex, infraLevel) | |
1199 | 1077 | let loft = split(currentWh[whIdxLOFT], "_") | |
1200 | 1078 | let whSpaceLeft = parseIntValue(loft[volFree]) | |
1201 | 1079 | if (if ((claimMode == claimModeWh)) | |
1202 | 1080 | then (amount > whSpaceLeft) | |
1203 | 1081 | else false) | |
1204 | 1082 | then throw((("Only " + toString(whSpaceLeft)) + " space left in warehouse")) | |
1205 | 1083 | else { | |
1206 | 1084 | let bpKey = keyBackpackByDuck(c._1) | |
1207 | 1085 | let currentPack = getBackpack(bpKey) | |
1208 | 1086 | let currentPackRes = split(currentPack[bpIdxRes], "_") | |
1209 | 1087 | let currentWhRes = split(currentWh[whIdxRes], "_") | |
1210 | - | let $ | |
1088 | + | let $t02735928230 = if ((claimMode == claimModeWh)) | |
1211 | 1089 | then $Tuple4(addRes(currentWhRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), currentPack[bpIdxRes], (parseIntValue(loft[volOccupied]) + resToClaim._2), (parseIntValue(loft[volFree]) - resToClaim._2)) | |
1212 | 1090 | else if ((claimMode == claimModeDuck)) | |
1213 | 1091 | then $Tuple4(currentWh[whIdxRes], addRes(currentPackRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), parseIntValue(loft[volOccupied]), parseIntValue(loft[volFree])) | |
1214 | 1092 | else { | |
1215 | 1093 | let distr = distributeRes(currentWhRes, currentPackRes, resToClaim, whSpaceLeft) | |
1216 | 1094 | let whAm = min([parseIntValue(loft[volFree]), resToClaim._2]) | |
1217 | 1095 | $Tuple4(distr._1, distr._2, (parseIntValue(loft[volOccupied]) + whAm), (parseIntValue(loft[volFree]) - whAm)) | |
1218 | 1096 | } | |
1219 | - | let whRes = $ | |
1220 | - | let bpRes = $ | |
1221 | - | let loftO = $ | |
1222 | - | let loftF = $ | |
1097 | + | let whRes = $t02735928230._1 | |
1098 | + | let bpRes = $t02735928230._2 | |
1099 | + | let loftO = $t02735928230._3 | |
1100 | + | let loftF = $t02735928230._4 | |
1223 | 1101 | $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]], "_")]) | |
1224 | 1102 | } | |
1225 | 1103 | } | |
1226 | 1104 | } | |
1227 | 1105 | } | |
1228 | 1106 | ||
1229 | 1107 | ||
1230 | 1108 | func claimAll (addr,landAssetId,pieces,claimMode) = { | |
1231 | 1109 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1232 | 1110 | let savedTime = value(getInteger(timeKey)) | |
1233 | 1111 | let availRes = (fraction((lastBlock.timestamp - savedTime), applyBonuses(landAssetId, pieces), DAYMILLIS) * pieces) | |
1234 | 1112 | claimResInternal(addr, availRes, claimMode, landAssetId) | |
1235 | 1113 | } | |
1236 | 1114 | ||
1237 | 1115 | ||
1238 | 1116 | func upInfraCommon (shouldUseMat,caller,paymentAmount,landAssetId) = { | |
1239 | 1117 | let addr = toString(caller) | |
1240 | 1118 | let c = checkClaimConditions(addr, claimModeWhThenDuck, landAssetId) | |
1241 | 1119 | let pieces = numPiecesBySize(c._3[recLandSize]) | |
1242 | 1120 | let infraKey = keyInfraLevelByAssetId(c._2) | |
1243 | 1121 | let curLevel = valueOrElse(getInteger(infraKey), 0) | |
1244 | 1122 | if ((curLevel >= 3)) | |
1245 | 1123 | then throw("Currently max infrastructure level = 3") | |
1246 | 1124 | else { | |
1247 | 1125 | let newLevel = (curLevel + 1) | |
1248 | 1126 | let cost = fraction(InfraUpgradeCostSUsdt, (pieces * newLevel), SSIZE) | |
1249 | 1127 | if (if (!(shouldUseMat)) | |
1250 | 1128 | then (paymentAmount != cost) | |
1251 | 1129 | else false) | |
1252 | 1130 | then throw(("Payment attached should be " + toString(cost))) | |
1253 | 1131 | else { | |
1254 | 1132 | let bpKey = keyBackpackByDuck(c._1) | |
1255 | 1133 | let currentPack = getBackpack(bpKey) | |
1256 | 1134 | let mList = split(currentPack[bpIdxMat], "_") | |
1257 | 1135 | let newMat = makeString(subtractMaterials(shouldUseMat, mList, fraction(InfraUpgradeCostS, (pieces * newLevel), SSIZE)), "_") | |
1258 | 1136 | let claimResult = claimAll(addr, c._2, pieces, claimModeWhThenDuck) | |
1259 | 1137 | let whData = claimResult._5 | |
1260 | 1138 | let oldVol = getWarehouseTotalVolume(whData[whIdxLevels]) | |
1261 | 1139 | let newVolData = makeString([split(whData[whIdxLevels], "_")[0], toString(newLevel)], "_") | |
1262 | 1140 | let newVol = getWarehouseTotalVolume(newVolData) | |
1263 | 1141 | let loft = split(whData[whIdxLOFT], "_") | |
1264 | 1142 | let newLoftStr = makeString([loft[volLocked], loft[volOccupied], toString(((parseIntValue(loft[volFree]) + newVol) - oldVol)), toString(newVol)], "_") | |
1265 | 1143 | $Tuple2(([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) | |
1266 | 1144 | } | |
1267 | 1145 | } | |
1268 | 1146 | } | |
1269 | - | ||
1270 | - | ||
1271 | - | func activateOnboardArt (addr) = 0 | |
1272 | 1147 | ||
1273 | 1148 | ||
1274 | 1149 | func activatePresaleArt (addr,landAssetIdIn) = { | |
1275 | 1150 | let c = checkClaimConditions(addr, claimModeWhThenDuck, landAssetIdIn) | |
1276 | 1151 | let landAssetId = c._2 | |
1277 | 1152 | let pieces = numPiecesBySize(c._3[recLandSize]) | |
1278 | 1153 | let activationKey = keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId) | |
1279 | 1154 | if ((valueOrElse(getInteger(activationKey), 0) > 0)) | |
1280 | 1155 | then throw("Presale artifact is already activated") | |
1281 | 1156 | else if ((parseIntValue(c._3[recLandNum]) > PRESALENUMLANDS)) | |
1282 | 1157 | then throw((((LANDPREFIX + " ") + landAssetId) + " is not eligible for presale artifact")) | |
1283 | 1158 | else { | |
1284 | 1159 | let claimResult = claimAll(addr, landAssetId, pieces, claimModeWhThenDuck) | |
1285 | 1160 | ((((claimResult._1 :+ IntegerEntry(activationKey, pieces)) :+ IntegerEntry(keyLandArtStatusByTypeAssetIdAndOwner(ARTPRESALE, landAssetId, addr), pieces)) :+ StringEntry(claimResult._2, makeString(claimResult._3, ":"))) :+ StringEntry(claimResult._4, makeString(claimResult._5, ":"))) | |
1286 | 1161 | } | |
1287 | 1162 | } | |
1288 | 1163 | ||
1289 | 1164 | ||
1290 | 1165 | func mergeInternal (newLandSize,newLevel,formula,addr,landAssetIds,txId,needMat) = { | |
1291 | 1166 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1292 | 1167 | func checkMerge (acc,landAssetId) = { | |
1293 | 1168 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
1294 | 1169 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1295 | 1170 | let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked")) | |
1296 | 1171 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
1297 | 1172 | if ((owner != addr)) | |
1298 | 1173 | then throw((LANDPREFIX + " is not yours")) | |
1299 | 1174 | else { | |
1300 | 1175 | let d = split(asset.description, "_") | |
1301 | 1176 | let continent = d[recContinent] | |
1302 | 1177 | if (if ((acc._3 != "")) | |
1303 | 1178 | then (acc._3 != continent) | |
1304 | 1179 | else false) | |
1305 | 1180 | then throw("Lands should be on the same continent to merge") | |
1306 | 1181 | else { | |
1307 | 1182 | let landSize = d[recLandSize] | |
1308 | 1183 | let sizesIn = acc._1 | |
1309 | 1184 | let i = valueOrErrorMessage(indexOf(sizesIn, landSize), "You haven't passed all the lands needed") | |
1310 | 1185 | let sizesOut = (take(sizesIn, i) + drop(sizesIn, (i + 1))) | |
1311 | 1186 | let pieces = numPiecesBySize(landSize) | |
1312 | 1187 | let arts = (acc._2 + valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0)) | |
1313 | 1188 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1314 | 1189 | let reqLevel = match landSize { | |
1315 | 1190 | case _ => | |
1316 | 1191 | if (("S" == $match0)) | |
1317 | 1192 | then 3 | |
1318 | 1193 | else if (("M" == $match0)) | |
1319 | 1194 | then 4 | |
1320 | 1195 | else if (("L" == $match0)) | |
1321 | 1196 | then 5 | |
1322 | 1197 | else if (("XL" == $match0)) | |
1323 | 1198 | then 6 | |
1324 | 1199 | else throw("Only S, M, L, XL can merge") | |
1325 | 1200 | } | |
1326 | 1201 | if ((infraLevel != reqLevel)) | |
1327 | 1202 | then throw("All lands should be maxed to merge") | |
1328 | 1203 | else { | |
1329 | 1204 | let landNum = d[recLandNum] | |
1330 | 1205 | let terrainCounts = countTerrains(d[recTerrains]) | |
1331 | 1206 | let deltaTime = (lastBlock.timestamp - savedTime) | |
1332 | 1207 | if ((0 > deltaTime)) | |
1333 | 1208 | then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp))) | |
1334 | 1209 | else { | |
1335 | 1210 | let dailyProductionByPiece = applyBonuses(landAssetId, pieces) | |
1336 | 1211 | let landIndex = (pieces / SSIZE) | |
1337 | 1212 | let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, landIndex, dailyProductionByPiece) | |
1338 | 1213 | let props = updateProportionsInternal(split(acc._6, "_"), terrainCounts, landIndex, -1) | |
1339 | 1214 | let lands = acc._7 | |
1340 | 1215 | let idx = indexOf(lands, landAssetId) | |
1341 | 1216 | if (!(isDefined(idx))) | |
1342 | 1217 | then throw(("Your staked lands don't contain " + landAssetId)) | |
1343 | 1218 | else { | |
1344 | 1219 | let customKey = keyLandAssetIdToCustomName(landAssetId) | |
1345 | 1220 | let customName = valueOrElse(getString(customKey), "") | |
1346 | 1221 | $Tuple8(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(keyLandArtStatusByTypeAssetIdAndOwner(ARTPRESALE, landAssetId, addr))) :+ DeleteEntry(keyLandNumToOwner(landNum))) :+ DeleteEntry(keyWarehouseByLand(landAssetId))) :+ DeleteEntry(customKey)) :+ DeleteEntry(keyLandCustomNameToAssetId(customName))) :+ Burn(fromBase58String(landAssetId), 1)), props, removeByIndex(lands, value(idx)), (acc._8 + pieces)) | |
1347 | 1222 | } | |
1348 | 1223 | } | |
1349 | 1224 | } | |
1350 | 1225 | } | |
1351 | 1226 | } | |
1352 | 1227 | } | |
1353 | 1228 | ||
1354 | 1229 | let bpKey = keyBackpackByDuck(duckAssetId) | |
1355 | 1230 | let currentPack = getBackpack(bpKey) | |
1356 | 1231 | let propStr = valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0") | |
1357 | 1232 | let landsKey = keyStakedLandsByOwner(addr) | |
1358 | 1233 | let landsStr = getString(landsKey) | |
1359 | 1234 | let landsIn = if (isDefined(landsStr)) | |
1360 | 1235 | then split_51C(value(landsStr), "_") | |
1361 | 1236 | else nil | |
1362 | 1237 | let r = { | |
1363 | 1238 | let $l = landAssetIds | |
1364 | 1239 | let $s = size($l) | |
1365 | 1240 | let $acc0 = $Tuple8(formula, 0, "", currentPack[bpIdxRes], nil, propStr, landsIn, 0) | |
1366 | 1241 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1367 | 1242 | then $a | |
1368 | 1243 | else checkMerge($a, $l[$i]) | |
1369 | 1244 | ||
1370 | 1245 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1371 | 1246 | then $a | |
1372 | 1247 | else throw("List size exceeds 5") | |
1373 | 1248 | ||
1374 | 1249 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5) | |
1375 | 1250 | } | |
1376 | 1251 | let continent = r._3 | |
1377 | 1252 | let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent)) | |
1378 | 1253 | let terrains = genTerrains(abs(toBigInt(txId)), continentIdx) | |
1379 | 1254 | let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1)) | |
1380 | 1255 | let newLandNum = toString(freeNum) | |
1381 | 1256 | let issue = Issue(nftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false) | |
1382 | 1257 | let assetId = calculateAssetId(issue) | |
1383 | 1258 | let newLandAssetId = toBase58String(assetId) | |
1384 | 1259 | let newMat = makeString(subtractMaterials((needMat > 0), split(currentPack[bpIdxMat], "_"), needMat), "_") | |
1385 | 1260 | let piecesKey = keyStakedPiecesByOwner(addr) | |
1386 | 1261 | let stakedPieces = valueOrElse(getInteger(piecesKey), 0) | |
1387 | 1262 | $Tuple2((((((((((((((((r._5 :+ (if ((size(r._7) > 0)) | |
1388 | 1263 | then StringEntry(landsKey, makeString_11C(r._7, "_")) | |
1389 | 1264 | else DeleteEntry(landsKey))) :+ IntegerEntry(piecesKey, if ((r._8 > stakedPieces)) | |
1390 | 1265 | then 0 | |
1391 | 1266 | 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(keyLandArtStatusByTypeAssetIdAndOwner(ARTPRESALE, newLandAssetId, addr), r._2)) :+ IntegerEntry(keyInfraLevelByAssetId(newLandAssetId), newLevel)) :+ IntegerEntry(keyInfraLevelByAssetIdAndOwner(newLandAssetId, addr), newLevel)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], r._4, newMat, currentPack[bpIdxProd]], ":"))) :+ StringEntry(keyResProportions(), r._6)) :+ StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", newLandAssetId], "_"))) :+ ScriptTransfer(addressFromStringValue(addr), 1, assetId)), newLandAssetId) | |
1392 | 1267 | } | |
1393 | 1268 | ||
1394 | 1269 | ||
1395 | 1270 | func s2m (addr,landAssetIds,txId) = mergeInternal("M", 3, "SSSS", addr, landAssetIds, txId, 0) | |
1396 | 1271 | ||
1397 | 1272 | ||
1398 | 1273 | func m2l (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = { | |
1399 | 1274 | let cost = (InfraUpgradeCostSUsdt * 4) | |
1400 | 1275 | if (if (!(shouldUseMat)) | |
1401 | 1276 | then (paymentAmount != cost) | |
1402 | 1277 | else false) | |
1403 | 1278 | then throw(("Payment attached should be " + toString(cost))) | |
1404 | 1279 | else mergeInternal("L", 4, "SMM", addr, landAssetIds, txId, (InfraUpgradeCostS * 4)) | |
1405 | 1280 | } | |
1406 | 1281 | ||
1407 | 1282 | ||
1408 | 1283 | func l2xl (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = { | |
1409 | 1284 | let cost = (InfraUpgradeCostSUsdt * 47) | |
1410 | 1285 | if (if (!(shouldUseMat)) | |
1411 | 1286 | then (paymentAmount != cost) | |
1412 | 1287 | else false) | |
1413 | 1288 | then throw(("Payment attached should be " + toString(cost))) | |
1414 | 1289 | else mergeInternal("XL", 5, "SSSML", addr, landAssetIds, txId, (InfraUpgradeCostS * 47)) | |
1415 | 1290 | } | |
1416 | 1291 | ||
1417 | 1292 | ||
1418 | 1293 | func xl2xxl (addr,landAssetIds,txId,shouldUseMat,paymentAmount) = { | |
1419 | 1294 | let cost = (InfraUpgradeCostSUsdt * 54) | |
1420 | 1295 | if (if (!(shouldUseMat)) | |
1421 | 1296 | then (paymentAmount != cost) | |
1422 | 1297 | else false) | |
1423 | 1298 | then throw(("Payment attached should be " + toString(cost))) | |
1424 | 1299 | else mergeInternal("XXL", 6, "LXL", addr, landAssetIds, txId, (InfraUpgradeCostS * 54)) | |
1425 | 1300 | } | |
1426 | 1301 | ||
1427 | 1302 | ||
1428 | 1303 | func mergeCommon (shouldUseMat,addr,paymentAmount,landAssetIds,txId) = { | |
1429 | 1304 | let mergeResult = match size(landAssetIds) { | |
1430 | 1305 | case _ => | |
1431 | 1306 | if ((4 == $match0)) | |
1432 | 1307 | then s2m(addr, landAssetIds, txId) | |
1433 | 1308 | else if ((3 == $match0)) | |
1434 | 1309 | then m2l(addr, landAssetIds, txId, shouldUseMat, paymentAmount) | |
1435 | 1310 | else if ((5 == $match0)) | |
1436 | 1311 | then l2xl(addr, landAssetIds, txId, shouldUseMat, paymentAmount) | |
1437 | 1312 | else if ((2 == $match0)) | |
1438 | 1313 | then xl2xxl(addr, landAssetIds, txId, shouldUseMat, paymentAmount) | |
1439 | 1314 | else throw("Unknown merge") | |
1440 | 1315 | } | |
1441 | 1316 | mergeResult | |
1442 | 1317 | } | |
1443 | 1318 | ||
1444 | 1319 | ||
1445 | 1320 | func prolog (i) = if (if ((i.originCaller != restContract)) | |
1446 | 1321 | then valueOrElse(getBoolean(keyBlocked()), false) | |
1447 | 1322 | else false) | |
1448 | 1323 | then throw("Contracts are under maintenance") | |
1449 | 1324 | else StringEntry(keyLastTxIdByUser(toString(i.originCaller)), toBase58String(i.transactionId)) | |
1450 | 1325 | ||
1451 | 1326 | ||
1452 | 1327 | @Callable(i) | |
1453 | 1328 | func constructorV1 (restAddr) = if ((i.caller != this)) | |
1454 | 1329 | then throw("Permission denied") | |
1455 | 1330 | else [StringEntry(keyRestAddress(), restAddr)] | |
1456 | 1331 | ||
1457 | 1332 | ||
1458 | 1333 | ||
1459 | 1334 | @Callable(i) | |
1460 | 1335 | func setBlocked (isBlocked) = if ((i.caller != this)) | |
1461 | 1336 | then throw("permission denied") | |
1462 | 1337 | else [BooleanEntry(keyBlocked(), isBlocked)] | |
1463 | 1338 | ||
1464 | 1339 | ||
1465 | 1340 | ||
1466 | 1341 | @Callable(i) | |
1467 | 1342 | func stakeLand () = { | |
1468 | 1343 | let prologAction = prolog(i) | |
1469 | 1344 | if ((size(i.payments) != 1)) | |
1470 | 1345 | then throw("Exactly one payment required") | |
1471 | 1346 | else { | |
1472 | 1347 | let pmt = value(i.payments[0]) | |
1473 | 1348 | let assetId = value(pmt.assetId) | |
1474 | 1349 | let address = toString(i.caller) | |
1475 | 1350 | if ((pmt.amount != 1)) | |
1476 | 1351 | then throw((("NFT " + LANDPREFIX) + " token should be attached as payment")) | |
1477 | 1352 | else { | |
1478 | 1353 | let asset = value(assetInfo(assetId)) | |
1479 | 1354 | if ((asset.issuer != this)) | |
1480 | 1355 | then throw("Unknown issuer of token") | |
1481 | 1356 | else if (!(contains(asset.name, LANDPREFIX))) | |
1482 | 1357 | then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted")) | |
1483 | 1358 | else { | |
1484 | 1359 | let landNumSize = drop(asset.name, 4) | |
1485 | 1360 | let landNum = if (contains(landNumSize, "XXL")) | |
1486 | 1361 | then dropRight(landNumSize, 3) | |
1487 | 1362 | else if (contains(landNumSize, "XL")) | |
1488 | 1363 | then dropRight(landNumSize, 2) | |
1489 | 1364 | else dropRight(landNumSize, 1) | |
1490 | 1365 | if (!(isDefined(parseInt(landNum)))) | |
1491 | 1366 | then throw(("Cannot parse land number from " + asset.name)) | |
1492 | 1367 | else { | |
1493 | 1368 | let landAssetId = toBase58String(assetId) | |
1494 | 1369 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1495 | 1370 | if (isDefined(getInteger(timeKey))) | |
1496 | 1371 | then throw((("NFT " + asset.name) + " is already staked")) | |
1497 | 1372 | else { | |
1498 | 1373 | let d = split(asset.description, "_") | |
1499 | 1374 | let terrainCounts = countTerrains(d[recTerrains]) | |
1500 | 1375 | let pieces = numPiecesBySize(d[recLandSize]) | |
1501 | 1376 | let props = updateProportions(terrainCounts, (pieces / SSIZE), 1) | |
1502 | 1377 | let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0) | |
1503 | 1378 | let landsKey = keyStakedLandsByOwner(address) | |
1504 | 1379 | let landsStr = getString(landsKey) | |
1505 | 1380 | let lands = if (isDefined(landsStr)) | |
1506 | 1381 | then split_51C(value(landsStr), "_") | |
1507 | 1382 | else nil | |
1508 | 1383 | if (containsElement(lands, landAssetId)) | |
1509 | 1384 | then throw(("Your staked lands already contain " + landAssetId)) | |
1510 | 1385 | else { | |
1511 | 1386 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1512 | 1387 | let piecesKey = keyStakedPiecesByOwner(address) | |
1513 | 1388 | let oldPieces = valueOrElse(getInteger(piecesKey), 0) | |
1514 | 1389 | let wlgResult = if ((oldPieces == 0)) | |
1515 | 1390 | then asInt(invoke(wlgContract, "onStakeLand", [address], nil)) | |
1516 | 1391 | else -1 | |
1517 | 1392 | $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(keyLandArtStatusByTypeAssetIdAndOwner(ARTPRESALE, landAssetId, address), artPieces), IntegerEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, address), infraLevel), StringEntry(keyResProportions(), props), prologAction], wlgResult) | |
1518 | 1393 | } | |
1519 | 1394 | } | |
1520 | 1395 | } | |
1521 | 1396 | } | |
1522 | 1397 | } | |
1523 | 1398 | } | |
1524 | 1399 | } | |
1525 | 1400 | ||
1526 | 1401 | ||
1527 | 1402 | ||
1528 | 1403 | @Callable(i) | |
1529 | 1404 | func unstakeLand (landAssetIdIn) = { | |
1530 | 1405 | let prologAction = prolog(i) | |
1531 | 1406 | if ((size(i.payments) != 0)) | |
1532 | 1407 | then throw("No payments required") | |
1533 | 1408 | else { | |
1534 | 1409 | let addr = toString(i.caller) | |
1535 | 1410 | let c = checkClaimConditions(addr, claimModeDuck, landAssetIdIn) | |
1536 | 1411 | let landAssetId = c._2 | |
1537 | 1412 | let landsKey = keyStakedLandsByOwner(addr) | |
1538 | 1413 | let terrainCounts = countTerrains(c._3[recTerrains]) | |
1539 | 1414 | let pieces = numPiecesBySize(c._3[recLandSize]) | |
1540 | 1415 | let props = updateProportions(terrainCounts, (pieces / SSIZE), -1) | |
1541 | 1416 | let claimResult = claimAll(addr, landAssetId, pieces, claimModeDuck) | |
1542 | 1417 | let lands = split_51C(valueOrElse(getString(landsKey), ""), "_") | |
1543 | 1418 | let idx = indexOf(lands, landAssetId) | |
1544 | 1419 | if (!(isDefined(idx))) | |
1545 | 1420 | then throw(("Your staked lands don't contain " + landAssetId)) | |
1546 | 1421 | else { | |
1547 | 1422 | let t = value(blockInfoByHeight(height)).timestamp | |
1548 | 1423 | let releaseTime = valueOrElse(getInteger(govContract, keyUserGwlReleaseTime(addr)), 0) | |
1549 | 1424 | if ((releaseTime >= t)) | |
1550 | 1425 | then throw(("Your gWL are taking part in voting, cannot unstake until " + toString(releaseTime))) | |
1551 | 1426 | else { | |
1552 | 1427 | let piecesKey = keyStakedPiecesByOwner(addr) | |
1553 | 1428 | let stakedPieces = valueOrElse(getInteger(piecesKey), 0) | |
1554 | 1429 | let newPieces = if ((pieces > stakedPieces)) | |
1555 | 1430 | then 0 | |
1556 | 1431 | else (stakedPieces - pieces) | |
1557 | 1432 | let wlgResult = if ((newPieces == 0)) | |
1558 | 1433 | then asInt(invoke(wlgContract, "onUnstakeLand", [addr], nil)) | |
1559 | 1434 | else -1 | |
1560 | 1435 | $Tuple2([ScriptTransfer(i.caller, 1, fromBase58String(landAssetId)), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr)), StringEntry(keyResProportions(), props), StringEntry(claimResult._2, makeString(claimResult._3, ":")), if ((size(lands) > 1)) | |
1561 | 1436 | then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_")) | |
1562 | 1437 | else DeleteEntry(landsKey), IntegerEntry(piecesKey, newPieces), prologAction], wlgResult) | |
1563 | 1438 | } | |
1564 | 1439 | } | |
1565 | 1440 | } | |
1566 | 1441 | } | |
1567 | 1442 | ||
1568 | 1443 | ||
1569 | 1444 | ||
1570 | 1445 | @Callable(i) | |
1571 | 1446 | func stakeDuck () = { | |
1572 | 1447 | let prologAction = prolog(i) | |
1573 | 1448 | if ((size(i.payments) != 1)) | |
1574 | 1449 | then throw("Exactly one payment required") | |
1575 | 1450 | else { | |
1576 | 1451 | let pmt = value(i.payments[0]) | |
1577 | 1452 | let assetId = value(pmt.assetId) | |
1578 | 1453 | let address = toString(i.caller) | |
1579 | 1454 | if ((pmt.amount != 1)) | |
1580 | 1455 | then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment")) | |
1581 | 1456 | else { | |
1582 | 1457 | let asset = value(assetInfo(assetId)) | |
1583 | 1458 | if (if ((asset.issuer != incubatorAddr)) | |
1584 | 1459 | then (asset.issuer != breederAddr) | |
1585 | 1460 | else false) | |
1586 | 1461 | then throw((("Unknown issuer of " + DUCKPREFIX) + " token")) | |
1587 | 1462 | else if (!(contains(asset.name, DUCKPREFIX))) | |
1588 | 1463 | then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted")) | |
1589 | 1464 | else { | |
1590 | 1465 | let assetIdStr = toBase58String(assetId) | |
1591 | 1466 | let timeKey = keyStakedTimeByAssetId(assetIdStr) | |
1592 | 1467 | if (isDefined(getInteger(timeKey))) | |
1593 | 1468 | then throw((("NFT " + asset.name) + " is already staked")) | |
1594 | 1469 | else if (isDefined(getString(keyStakedDuckByOwner(address)))) | |
1595 | 1470 | then throw(("You already staked one duck: " + asset.name)) | |
1596 | 1471 | else { | |
1597 | 1472 | let locKey = keyDuckLocation(assetIdStr) | |
1598 | 1473 | let location = getString(locKey) | |
1599 | 1474 | let bpKey = keyBackpackByDuck(assetIdStr) | |
1600 | 1475 | let backpack = getString(bpKey) | |
1601 | 1476 | ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location)) | |
1602 | 1477 | then nil | |
1603 | 1478 | else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack)) | |
1604 | 1479 | then nil | |
1605 | 1480 | else (([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyDuckHealth(assetIdStr), 100)) :+ prologAction))))) | |
1606 | 1481 | } | |
1607 | 1482 | } | |
1608 | 1483 | } | |
1609 | 1484 | } | |
1610 | 1485 | } | |
1611 | 1486 | ||
1612 | 1487 | ||
1613 | 1488 | ||
1614 | 1489 | @Callable(i) | |
1615 | 1490 | func unstakeDuck (assetIdStr) = { | |
1616 | 1491 | let prologAction = prolog(i) | |
1617 | 1492 | if ((size(i.payments) != 0)) | |
1618 | 1493 | then throw("No payments required") | |
1619 | 1494 | else { | |
1620 | 1495 | let assetId = fromBase58String(assetIdStr) | |
1621 | 1496 | let address = toString(i.caller) | |
1622 | 1497 | let asset = value(assetInfo(assetId)) | |
1623 | 1498 | let timeKey = keyStakedTimeByAssetId(toBase58String(assetId)) | |
1624 | 1499 | if (!(isDefined(getInteger(timeKey)))) | |
1625 | 1500 | then throw((("NFT " + asset.name) + " is not staked")) | |
1626 | 1501 | else if (!(isDefined(getString(keyStakedDuckByOwner(address))))) | |
1627 | 1502 | then throw((("The duck " + asset.name) + " is not staked")) | |
1628 | 1503 | else { | |
1629 | 1504 | let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned")) | |
1630 | 1505 | if ((owner != address)) | |
1631 | 1506 | then throw("Staked NFT is not yours") | |
1632 | 1507 | else { | |
1633 | 1508 | let keyHealth = keyDuckHealth(assetIdStr) | |
1634 | 1509 | let health = valueOrElse(getInteger(keyHealth), 100) | |
1635 | 1510 | if ((100 > health)) | |
1636 | 1511 | then throw("Please heal your duck before unstaking") | |
1637 | 1512 | else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address)), prologAction] | |
1638 | 1513 | } | |
1639 | 1514 | } | |
1640 | 1515 | } | |
1641 | 1516 | } | |
1642 | 1517 | ||
1643 | 1518 | ||
1644 | 1519 | ||
1645 | 1520 | @Callable(i) | |
1646 | 1521 | func claimRes (amount,landAssetIdStr) = { | |
1647 | 1522 | let prologAction = prolog(i) | |
1648 | 1523 | if ((size(i.payments) != 0)) | |
1649 | 1524 | then throw("No payments required") | |
1650 | 1525 | else { | |
1651 | 1526 | let addr = toString(i.originCaller) | |
1652 | 1527 | let result = claimResInternal(addr, amount, claimModeDuck, landAssetIdStr) | |
1653 | 1528 | $Tuple2((((result._1 :+ StringEntry(result._2, makeString(result._3, ":"))) :+ StringEntry(result._4, makeString(result._5, ":"))) :+ prologAction), result._3[bpIdxRes]) | |
1654 | 1529 | } | |
1655 | 1530 | } | |
1656 | 1531 | ||
1657 | 1532 | ||
1658 | 1533 | ||
1659 | 1534 | @Callable(i) | |
1660 | 1535 | func claimResToWH (amount,landAssetIdStr) = { | |
1661 | 1536 | let prologAction = prolog(i) | |
1662 | 1537 | if ((size(i.payments) != 0)) | |
1663 | 1538 | then throw("No payments required") | |
1664 | 1539 | else { | |
1665 | 1540 | let addr = toString(i.originCaller) | |
1666 | 1541 | let result = claimResInternal(addr, amount, claimModeWh, landAssetIdStr) | |
1667 | 1542 | $Tuple2((((result._1 :+ StringEntry(result._2, makeString(result._3, ":"))) :+ StringEntry(result._4, makeString(result._5, ":"))) :+ prologAction), result._5[whIdxRes]) | |
1668 | 1543 | } | |
1669 | 1544 | } | |
1670 | 1545 | ||
1671 | 1546 | ||
1672 | 1547 | ||
1673 | 1548 | @Callable(i) | |
1674 | 1549 | func flight (message,sig) = { | |
1675 | 1550 | let prologAction = prolog(i) | |
1676 | 1551 | if ((size(i.payments) != 0)) | |
1677 | 1552 | then throw("No payments required") | |
1678 | 1553 | else { | |
1679 | 1554 | let userAddr = toString(i.caller) | |
1680 | 1555 | let f = flightCommon(userAddr, message, sig) | |
1681 | 1556 | let locKey = keyDuckLocation(f._2) | |
1682 | 1557 | let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION) | |
1683 | 1558 | if ((f._4 == curLocation)) | |
1684 | 1559 | then throw("You can't fly to the same location") | |
1685 | 1560 | else { | |
1686 | 1561 | let bpKey = keyBackpackByDuck(f._2) | |
1687 | 1562 | let currentPack = getBackpack(bpKey) | |
1688 | 1563 | let newProd = subtractProducts(currentPack[bpIdxProd], f._5) | |
1689 | 1564 | $Tuple2([StringEntry(locKey, if ((f._1 > 0)) | |
1690 | 1565 | then f._4 | |
1691 | 1566 | else curLocation), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], newProd], ":")), IntegerEntry(keyDuckHealth(f._2), f._1), prologAction], f._3) | |
1692 | 1567 | } | |
1693 | 1568 | } | |
1694 | 1569 | } | |
1695 | 1570 | ||
1696 | 1571 | ||
1697 | 1572 | ||
1698 | 1573 | @Callable(i) | |
1699 | 1574 | func heal (quantityL1,quantityL2,quantityL3) = { | |
1700 | 1575 | let prologAction = prolog(i) | |
1701 | 1576 | if (if (if ((0 > quantityL1)) | |
1702 | 1577 | then true | |
1703 | 1578 | else (0 > quantityL2)) | |
1704 | 1579 | then true | |
1705 | 1580 | else (0 > quantityL3)) | |
1706 | 1581 | then throw("Quantity cannot be negative") | |
1707 | 1582 | else { | |
1708 | 1583 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
1709 | 1584 | let qts = [quantityL1, quantityL2, quantityL3] | |
1710 | 1585 | let keyHealth = keyDuckHealth(duckAssetId) | |
1711 | 1586 | let oldHealth = valueOrElse(getInteger(keyHealth), 100) | |
1712 | 1587 | if ((oldHealth >= MAXHP)) | |
1713 | 1588 | then throw((("HP should be < " + toString(MAXHP)) + " to heal")) | |
1714 | 1589 | else { | |
1715 | 1590 | let bpKey = keyBackpackByDuck(duckAssetId) | |
1716 | 1591 | let currentPack = getBackpack(bpKey) | |
1717 | 1592 | let prodList = if ((currentPack[bpIdxProd] == "")) | |
1718 | 1593 | then nil | |
1719 | 1594 | else split(currentPack[bpIdxProd], "_") | |
1720 | 1595 | func iterateProd (acc,ignoredItem) = { | |
1721 | 1596 | let n = acc._2 | |
1722 | 1597 | let x = if ((size(prodList) > n)) | |
1723 | 1598 | then parseIntValue(prodList[n]) | |
1724 | 1599 | else 0 | |
1725 | 1600 | if ((3 > n)) | |
1726 | 1601 | then { | |
1727 | 1602 | let q = qts[n] | |
1728 | 1603 | if ((q > x)) | |
1729 | 1604 | then throw(((("You have only " + toString(x)) + " of ") + prodTypes[n])) | |
1730 | 1605 | else $Tuple3((acc._1 :+ toString((x - q))), (n + 1), (acc._3 + (medKitHp[n] * q))) | |
1731 | 1606 | } | |
1732 | 1607 | else $Tuple3((acc._1 :+ toString(x)), (n + 1), acc._3) | |
1733 | 1608 | } | |
1734 | 1609 | ||
1735 | 1610 | let result = { | |
1736 | 1611 | let $l = productionMatrix | |
1737 | 1612 | let $s = size($l) | |
1738 | 1613 | let $acc0 = $Tuple3(nil, 0, 0) | |
1739 | 1614 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1740 | 1615 | then $a | |
1741 | 1616 | else iterateProd($a, $l[$i]) | |
1742 | 1617 | ||
1743 | 1618 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1744 | 1619 | then $a | |
1745 | 1620 | else throw("List size exceeds 50") | |
1746 | 1621 | ||
1747 | 1622 | $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) | |
1748 | 1623 | } | |
1749 | 1624 | let newHealth = min([MAXHP, (oldHealth + result._3)]) | |
1750 | 1625 | $Tuple2([IntegerEntry(keyHealth, newHealth), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], makeString(result._1, "_")], ":")), prologAction], newHealth) | |
1751 | 1626 | } | |
1752 | 1627 | } | |
1753 | 1628 | } | |
1754 | 1629 | ||
1755 | 1630 | ||
1756 | 1631 | ||
1757 | 1632 | @Callable(i) | |
1758 | 1633 | func healES () = { | |
1759 | 1634 | let prologAction = prolog(i) | |
1760 | 1635 | if ((size(i.payments) != 1)) | |
1761 | 1636 | then throw("Exactly one payment required") | |
1762 | 1637 | else { | |
1763 | 1638 | let pmt = value(i.payments[0]) | |
1764 | 1639 | if ((pmt.assetId != usdtAssetId)) | |
1765 | 1640 | then throw("Allowed USDT payment only!") | |
1766 | 1641 | else { | |
1767 | 1642 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
1768 | 1643 | let keyHealth = keyDuckHealth(duckAssetId) | |
1769 | 1644 | let oldHealth = valueOrElse(getInteger(keyHealth), 100) | |
1770 | 1645 | if ((oldHealth > 0)) | |
1771 | 1646 | then throw("HP should be 0 to call Emergency Service") | |
1772 | 1647 | else { | |
1773 | 1648 | let bpKey = keyBackpackByDuck(duckAssetId) | |
1774 | 1649 | let currentPack = getBackpack(bpKey) | |
1775 | 1650 | let prodList = if ((currentPack[bpIdxProd] == "")) | |
1776 | 1651 | then nil | |
1777 | 1652 | else split(currentPack[bpIdxProd], "_") | |
1778 | 1653 | let medKitAmount1 = if ((size(prodList) > 0)) | |
1779 | 1654 | then parseIntValue(prodList[0]) | |
1780 | 1655 | else 0 | |
1781 | 1656 | let medKitAmount2 = if ((size(prodList) > 1)) | |
1782 | 1657 | then parseIntValue(prodList[1]) | |
1783 | 1658 | else 0 | |
1784 | 1659 | let medKitAmount3 = if ((size(prodList) > 2)) | |
1785 | 1660 | then parseIntValue(prodList[2]) | |
1786 | 1661 | else 0 | |
1787 | 1662 | if (if (if ((medKitAmount1 > 0)) | |
1788 | 1663 | then true | |
1789 | 1664 | else (medKitAmount2 > 0)) | |
1790 | 1665 | then true | |
1791 | 1666 | else (medKitAmount3 > 0)) | |
1792 | 1667 | then throw("You have to use own Medical Kit") | |
1793 | 1668 | else { | |
1794 | 1669 | let existStr = getString(economyContract, keyEsWarehouse()) | |
1795 | 1670 | let existAmounts = if (isDefined(existStr)) | |
1796 | 1671 | then split(value(existStr), "_") | |
1797 | 1672 | else nil | |
1798 | 1673 | let existAmount = if ((size(existAmounts) > 0)) | |
1799 | 1674 | then parseIntValue(existAmounts[0]) | |
1800 | 1675 | else 0 | |
1801 | 1676 | if ((0 >= existAmount)) | |
1802 | 1677 | then throw("There are no Medical Kits L1 at Emergency Service storage") | |
1803 | 1678 | else { | |
1804 | 1679 | let newHealth = (oldHealth + medKitHp[0]) | |
1805 | 1680 | let newES = makeString([toString((existAmount - 1)), removeByIndex(existAmounts, 0)], "_") | |
1806 | 1681 | let recipe = split(productionMatrix[0], "_") | |
1807 | 1682 | let totalMat = getRecipeMaterials(recipe) | |
1808 | 1683 | let packSize = parseIntValue(recipe[recipeIdxPacksize]) | |
1809 | 1684 | let sellPrice = fraction((totalMat * ESSELLCOEF), RESOURCEPRICEMIN, (10 * packSize)) | |
1810 | 1685 | if ((pmt.amount != sellPrice)) | |
1811 | 1686 | then throw(("Payment attached should be " + toString(sellPrice))) | |
1812 | 1687 | else { | |
1813 | 1688 | let result = asString(invoke(economyContract, "updateEsStorage", [newES], [AttachedPayment(usdtAssetId, sellPrice)])) | |
1814 | 1689 | $Tuple2([IntegerEntry(keyHealth, newHealth), prologAction], result) | |
1815 | 1690 | } | |
1816 | 1691 | } | |
1817 | 1692 | } | |
1818 | 1693 | } | |
1819 | 1694 | } | |
1820 | 1695 | } | |
1821 | 1696 | } | |
1822 | 1697 | ||
1823 | 1698 | ||
1824 | 1699 | ||
1825 | 1700 | @Callable(i) | |
1826 | 1701 | func updateBackpack (duckAssetId,newPack) = { | |
1827 | 1702 | let prologAction = prolog(i) | |
1828 | 1703 | if ((i.caller != economyContract)) | |
1829 | 1704 | then throw("permission denied") | |
1830 | 1705 | else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack), prologAction], newPack) | |
1831 | 1706 | } | |
1832 | 1707 | ||
1833 | 1708 | ||
1834 | 1709 | ||
1835 | 1710 | @Callable(i) | |
1836 | 1711 | func buySLand () = { | |
1837 | 1712 | let prologAction = prolog(i) | |
1838 | 1713 | if ((size(i.payments) != 1)) | |
1839 | 1714 | then throw("Exactly one payment required") | |
1840 | 1715 | else { | |
1841 | 1716 | let pmt = value(i.payments[0]) | |
1842 | 1717 | if ((pmt.assetId != usdtAssetId)) | |
1843 | 1718 | then throw("Allowed USDT payment only!") | |
1844 | 1719 | else if ((pmt.amount != EXPUSDT)) | |
1845 | 1720 | then throw(("Payment attached should be " + toString(EXPUSDT))) | |
1846 | 1721 | else { | |
1847 | 1722 | let result = expeditionInternal(i.caller, i.transactionId) | |
1848 | 1723 | $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) :+ prologAction), result._2._1) | |
1849 | 1724 | } | |
1850 | 1725 | } | |
1851 | 1726 | } | |
1852 | 1727 | ||
1853 | 1728 | ||
1854 | 1729 | ||
1855 | 1730 | @Callable(i) | |
1856 | 1731 | func expedition (message,sig) = { | |
1857 | 1732 | let prologAction = prolog(i) | |
1858 | 1733 | if ((size(i.payments) != 0)) | |
1859 | 1734 | then throw("No payments required") | |
1860 | 1735 | else { | |
1861 | 1736 | let result = expeditionCommon(i.caller, i.transactionId, message, sig) | |
1862 | 1737 | $Tuple2((result._1 :+ prologAction), $Tuple2(result._2, result._3)) | |
1863 | 1738 | } | |
1864 | 1739 | } | |
1865 | 1740 | ||
1866 | 1741 | ||
1867 | 1742 | ||
1868 | 1743 | @Callable(i) | |
1869 | 1744 | func upgradeInfra (landAssetId) = { | |
1870 | 1745 | let prologAction = prolog(i) | |
1871 | 1746 | if ((size(i.payments) != 0)) | |
1872 | 1747 | then throw("No payments required") | |
1873 | 1748 | else { | |
1874 | 1749 | let result = upInfraCommon(true, i.caller, 0, landAssetId) | |
1875 | 1750 | $Tuple2((result._1 :+ prologAction), result._2) | |
1876 | 1751 | } | |
1877 | 1752 | } | |
1878 | 1753 | ||
1879 | 1754 | ||
1880 | 1755 | ||
1881 | 1756 | @Callable(i) | |
1882 | 1757 | func upgradeInfraUsdt (landAssetId) = if ((i.caller != this)) | |
1883 | 1758 | then throw("Permission denied") | |
1884 | 1759 | else { | |
1885 | 1760 | let prologAction = prolog(i) | |
1886 | 1761 | if ((size(i.payments) != 1)) | |
1887 | 1762 | then throw("Exactly one payment required") | |
1888 | 1763 | else { | |
1889 | 1764 | let pmt = value(i.payments[0]) | |
1890 | 1765 | if ((pmt.assetId != usdtAssetId)) | |
1891 | 1766 | then throw("Allowed USDT payment only!") | |
1892 | 1767 | else { | |
1893 | 1768 | let result = upInfraCommon(false, i.caller, pmt.amount, landAssetId) | |
1894 | 1769 | $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) :+ prologAction), result._2) | |
1895 | 1770 | } | |
1896 | 1771 | } | |
1897 | 1772 | } | |
1898 | 1773 | ||
1899 | 1774 | ||
1900 | 1775 | ||
1901 | 1776 | @Callable(i) | |
1902 | 1777 | func activateArtifact (artName,landAssetId) = { | |
1903 | 1778 | let prologAction = prolog(i) | |
1904 | 1779 | if ((size(i.payments) != 0)) | |
1905 | 1780 | then throw("No payments required") | |
1906 | 1781 | else { | |
1907 | 1782 | let result = match artName { | |
1908 | 1783 | case _ => | |
1909 | 1784 | if (("PRESALE" == $match0)) | |
1910 | 1785 | then activatePresaleArt(toString(i.caller), landAssetId) | |
1911 | 1786 | else throw("Unknown artifact") | |
1912 | 1787 | } | |
1913 | 1788 | (result :+ prologAction) | |
1914 | 1789 | } | |
1915 | 1790 | } | |
1916 | 1791 | ||
1917 | 1792 | ||
1918 | 1793 | ||
1919 | 1794 | @Callable(i) | |
1920 | 1795 | func mergeLands (landAssetIds) = { | |
1921 | 1796 | let prologAction = prolog(i) | |
1922 | 1797 | if ((size(i.payments) != 0)) | |
1923 | 1798 | then throw("No payments required") | |
1924 | 1799 | else { | |
1925 | 1800 | let result = mergeCommon(true, toString(i.caller), 0, landAssetIds, i.transactionId) | |
1926 | 1801 | $Tuple2((result._1 :+ prologAction), result._2) | |
1927 | 1802 | } | |
1928 | 1803 | } | |
1929 | 1804 | ||
1930 | 1805 | ||
1931 | 1806 | ||
1932 | 1807 | @Callable(i) | |
1933 | 1808 | func mergeLandsUsdt (landAssetIds) = { | |
1934 | 1809 | let prologAction = prolog(i) | |
1935 | 1810 | if ((size(i.payments) != 1)) | |
1936 | 1811 | then throw("Exactly one payment required") | |
1937 | 1812 | else { | |
1938 | 1813 | let pmt = value(i.payments[0]) | |
1939 | 1814 | if ((pmt.assetId != usdtAssetId)) | |
1940 | 1815 | then throw("Allowed USDT payment only!") | |
1941 | 1816 | else { | |
1942 | 1817 | let result = mergeCommon(false, toString(i.caller), pmt.amount, landAssetIds, i.transactionId) | |
1943 | 1818 | $Tuple2(((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) :+ prologAction), result._2) | |
1944 | 1819 | } | |
1945 | 1820 | } | |
1946 | 1821 | } | |
1947 | 1822 | ||
1948 | 1823 | ||
1949 | 1824 | ||
1950 | 1825 | @Callable(i) | |
1951 | 1826 | func cargoExchange (cargoListStr,landAssetId) = { | |
1952 | 1827 | let prologAction = prolog(i) | |
1953 | 1828 | if ((size(i.payments) != 0)) | |
1954 | 1829 | then throw("No payments required") | |
1955 | 1830 | else { | |
1956 | 1831 | let cargoParts = split_4C(cargoListStr, ":") | |
1957 | 1832 | let addr = toString(i.originCaller) | |
1958 | 1833 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
1959 | 1834 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1960 | 1835 | if (!(isDefined(getInteger(timeKey)))) | |
1961 | 1836 | then throw((asset.name + " is not staked")) | |
1962 | 1837 | else { | |
1963 | 1838 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
1964 | 1839 | if ((owner != addr)) | |
1965 | 1840 | then throw((LANDPREFIX + " is not yours")) | |
1966 | 1841 | else { | |
1967 | 1842 | let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE) | |
1968 | 1843 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1969 | 1844 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1970 | 1845 | let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION) | |
1971 | 1846 | let loc = split(value(curLocation), "_") | |
1972 | 1847 | if ((loc[locIdxType] != "L")) | |
1973 | 1848 | then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L")) | |
1974 | 1849 | else if ((loc[locIdxId] != landAssetId)) | |
1975 | 1850 | then throw(("Duck should be on the land " + landAssetId)) | |
1976 | 1851 | else { | |
1977 | 1852 | let whKey = keyWarehouseByLand(landAssetId) | |
1978 | 1853 | let currentWh = getWarehouse(whKey, landIndex, infraLevel) | |
1979 | 1854 | let bpKey = keyBackpackByDuck(duckAssetId) | |
1980 | 1855 | let currentPack = getBackpack(bpKey) | |
1981 | 1856 | let result = moveStuff(cargoParts, currentWh, currentPack) | |
1982 | 1857 | let loft = split(currentWh[whIdxLOFT], "_") | |
1983 | 1858 | let loftO = (parseIntValue(loft[volOccupied]) + result._7) | |
1984 | 1859 | let loftF = (parseIntValue(loft[volFree]) - result._7) | |
1985 | 1860 | [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]], "_")], ":")), prologAction] | |
1986 | 1861 | } | |
1987 | 1862 | } | |
1988 | 1863 | } | |
1989 | 1864 | } | |
1990 | 1865 | } | |
1991 | 1866 | ||
1992 | 1867 | ||
1993 | 1868 | ||
1994 | 1869 | @Callable(i) | |
1995 | 1870 | func saveWarehouse (whStr,landAssetId) = { | |
1996 | 1871 | let prologAction = prolog(i) | |
1997 | 1872 | if ((i.caller != economyContract)) | |
1998 | 1873 | then throw("Access denied") | |
1999 | 1874 | else { | |
2000 | 1875 | let whKey = keyWarehouseByLand(landAssetId) | |
2001 | 1876 | let wh = split_4C(whStr, ":") | |
2002 | 1877 | if ((size(wh) != 5)) | |
2003 | 1878 | then throw("warehouse string should contain 4 ':' separators") | |
2004 | 1879 | else { | |
2005 | 1880 | let loftL = split(wh[whIdxLOFT], "_")[volLocked] | |
2006 | 1881 | let loftO = getWarehouseOccupiedVol(wh) | |
2007 | 1882 | let loftT = getWarehouseTotalVolume(wh[whIdxLevels]) | |
2008 | 1883 | let loftF = ((loftT - parseIntValue(loftL)) - loftO) | |
2009 | 1884 | let newWhStr = makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], wh[whIdxProd], makeString([loftL, toString(loftO), toString(loftF), toString(loftT)], "_")], ":") | |
2010 | 1885 | $Tuple2([StringEntry(whKey, newWhStr), prologAction], newWhStr) | |
2011 | 1886 | } | |
2012 | 1887 | } | |
2013 | 1888 | } | |
2014 | 1889 | ||
2015 | 1890 | ||
2016 | 1891 | ||
2017 | 1892 | @Callable(i) | |
2018 | 1893 | func fixWarehouseFormat (landAssetId) = if ((i.caller != restContract)) | |
2019 | 1894 | then throw("Access denied") | |
2020 | 1895 | else { | |
2021 | 1896 | let whKey = keyWarehouseByLand(landAssetId) | |
2022 | 1897 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
2023 | 1898 | let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE) | |
2024 | 1899 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
2025 | 1900 | let wh = getWarehouse(whKey, landIndex, infraLevel) | |
2026 | 1901 | let loftL = asInt(invoke(economyContract, "recalcLockedVolumeREADONLY", [landAssetId, wh], nil)) | |
2027 | 1902 | let loftO = getWarehouseOccupiedVol(wh) | |
2028 | 1903 | let loftT = getWarehouseTotalVolume(wh[whIdxLevels]) | |
2029 | 1904 | let loftF = ((loftT - loftL) - loftO) | |
2030 | 1905 | let newWhStr = makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], wh[whIdxProd], makeString([toString(loftL), toString(loftO), toString(loftF), toString(loftT)], "_")], ":") | |
2031 | 1906 | $Tuple2([StringEntry(whKey, newWhStr)], newWhStr) | |
2032 | 1907 | } | |
2033 | 1908 | ||
2034 | 1909 | ||
2035 | 1910 | ||
2036 | 1911 | @Callable(i) | |
2037 | 1912 | func fixStakedPieces (address) = if ((i.caller != restContract)) | |
2038 | 1913 | then throw("Access denied") | |
2039 | 1914 | else { | |
2040 | 1915 | let stakedPieces = if ((address == "")) | |
2041 | 1916 | then 0 | |
2042 | 1917 | else { | |
2043 | 1918 | let landsStr = getString(stakingContract, keyStakedLandsByOwner(address)) | |
2044 | 1919 | let lands = if (isDefined(landsStr)) | |
2045 | 1920 | then split_51C(value(landsStr), "_") | |
2046 | 1921 | else nil | |
2047 | 1922 | func oneLand (acc,landAssetId) = { | |
2048 | 1923 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
2049 | 1924 | let landSize = split(asset.description, "_")[recLandSize] | |
2050 | 1925 | (acc + numPiecesBySize(landSize)) | |
2051 | 1926 | } | |
2052 | 1927 | ||
2053 | 1928 | let $l = lands | |
2054 | 1929 | let $s = size($l) | |
2055 | 1930 | let $acc0 = 0 | |
2056 | 1931 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
2057 | 1932 | then $a | |
2058 | 1933 | else oneLand($a, $l[$i]) | |
2059 | 1934 | ||
2060 | 1935 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
2061 | 1936 | then $a | |
2062 | 1937 | else throw("List size exceeds 100") | |
2063 | 1938 | ||
2064 | 1939 | $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($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), 51), 52), 53), 54), 55), 56), 57), 58), 59), 60), 61), 62), 63), 64), 65), 66), 67), 68), 69), 70), 71), 72), 73), 74), 75), 76), 77), 78), 79), 80), 81), 82), 83), 84), 85), 86), 87), 88), 89), 90), 91), 92), 93), 94), 95), 96), 97), 98), 99), 100) | |
2065 | 1940 | } | |
2066 | 1941 | $Tuple2([IntegerEntry(keyStakedPiecesByOwner(address), stakedPieces)], stakedPieces) | |
2067 | 1942 | } | |
2068 | 1943 | ||
2069 | 1944 | ||
2070 | 1945 | ||
2071 | 1946 | @Callable(i) | |
2072 | 1947 | func setCustomName (assetId,customName,type) = { | |
2073 | 1948 | let prologAction = prolog(i) | |
2074 | 1949 | if ((size(i.payments) != 1)) | |
2075 | 1950 | then throw("Exactly one payment required") | |
2076 | 1951 | else { | |
2077 | 1952 | let pmt = value(i.payments[0]) | |
2078 | 1953 | if ((pmt.assetId != usdtAssetId)) | |
2079 | 1954 | then throw("Allowed USDT payment only!") | |
2080 | 1955 | else if ((pmt.amount != RENAMINGCOST)) | |
2081 | 1956 | then throw(("Payment should be " + toString(RENAMINGCOST))) | |
2082 | 1957 | else if (contains(customName, "__")) | |
2083 | 1958 | then throw(("Name should not contain '__': " + customName)) | |
2084 | 1959 | else if ((size(customName) > MAXNAMELEN)) | |
2085 | 1960 | then throw(("Name too long, maxLength=" + toString(MAXNAMELEN))) | |
2086 | 1961 | else { | |
2087 | 1962 | let addr = toString(i.originCaller) | |
2088 | 1963 | let actions = match type { | |
2089 | 1964 | case _ => | |
2090 | 1965 | if (("ACCOUNT" == $match0)) | |
2091 | 1966 | then { | |
2092 | 1967 | let reverseKey = keyCustomNameToAddress(customName) | |
2093 | 1968 | let nameOwner = getString(reverseKey) | |
2094 | 1969 | if (isDefined(nameOwner)) | |
2095 | 1970 | then throw(("Name already registered: " + customName)) | |
2096 | 1971 | else { | |
2097 | 1972 | let addrToNameKey = keyAddressToCustomName(addr) | |
2098 | 1973 | let oldName = getString(addrToNameKey) | |
2099 | 1974 | let freeOld = if (isDefined(oldName)) | |
2100 | 1975 | then [DeleteEntry(keyCustomNameToAddress(value(oldName)))] | |
2101 | 1976 | else nil | |
2102 | 1977 | ((freeOld :+ StringEntry(addrToNameKey, customName)) :+ StringEntry(reverseKey, addr)) | |
2103 | 1978 | } | |
2104 | 1979 | } | |
2105 | 1980 | else if (("LAND" == $match0)) | |
2106 | 1981 | then { | |
2107 | 1982 | let asset = value(assetInfo(fromBase58String(assetId))) | |
2108 | 1983 | let timeKey = keyStakedTimeByAssetId(assetId) | |
2109 | 1984 | if (!(isDefined(getInteger(timeKey)))) | |
2110 | 1985 | then throw((asset.name + " is not staked")) | |
2111 | 1986 | else { | |
2112 | 1987 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(assetId)), (("NFT " + asset.name) + " is orphaned")) | |
2113 | 1988 | if ((owner != addr)) | |
2114 | 1989 | then throw((LANDPREFIX + " is not yours")) | |
2115 | 1990 | else { | |
2116 | 1991 | let reverseKey = keyLandCustomNameToAssetId(customName) | |
2117 | 1992 | let nameOwner = getString(reverseKey) | |
2118 | 1993 | if (isDefined(nameOwner)) | |
2119 | 1994 | then throw(("Name already registered: " + customName)) | |
2120 | 1995 | else { | |
2121 | 1996 | let assetToNameKey = keyLandAssetIdToCustomName(assetId) | |
2122 | 1997 | let oldName = getString(assetToNameKey) | |
2123 | 1998 | let freeOld = if (isDefined(oldName)) | |
2124 | 1999 | then [DeleteEntry(keyLandCustomNameToAssetId(value(oldName)))] | |
2125 | 2000 | else nil | |
2126 | 2001 | ((freeOld :+ StringEntry(assetToNameKey, customName)) :+ StringEntry(reverseKey, assetId)) | |
2127 | 2002 | } | |
2128 | 2003 | } | |
2129 | 2004 | } | |
2130 | 2005 | } | |
2131 | 2006 | else if (("DUCK" == $match0)) | |
2132 | 2007 | then { | |
2133 | 2008 | let asset = value(assetInfo(fromBase58String(assetId))) | |
2134 | 2009 | let timeKey = keyStakedTimeByAssetId(assetId) | |
2135 | 2010 | if (if (!(isDefined(getInteger(timeKey)))) | |
2136 | 2011 | then true | |
2137 | 2012 | else !(isDefined(getString(keyStakedDuckByOwner(addr))))) | |
2138 | 2013 | then throw((asset.name + " is not staked")) | |
2139 | 2014 | else { | |
2140 | 2015 | let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(assetId)), (("NFT " + asset.name) + " is orphaned")) | |
2141 | 2016 | if ((owner != addr)) | |
2142 | 2017 | then throw((DUCKPREFIX + " is not yours")) | |
2143 | 2018 | else { | |
2144 | 2019 | let reverseKey = keyDuckCustomNameToAssetId(customName) | |
2145 | 2020 | let nameOwner = getString(reverseKey) | |
2146 | 2021 | if (isDefined(nameOwner)) | |
2147 | 2022 | then throw(("Name already registered: " + customName)) | |
2148 | 2023 | else { | |
2149 | 2024 | let assetToNameKey = keyDuckAssetIdToCustomName(assetId) | |
2150 | 2025 | let oldName = getString(assetToNameKey) | |
2151 | 2026 | let freeOld = if (isDefined(oldName)) | |
2152 | 2027 | then [DeleteEntry(keyDuckCustomNameToAssetId(value(oldName)))] | |
2153 | 2028 | else nil | |
2154 | 2029 | ((freeOld :+ StringEntry(assetToNameKey, customName)) :+ StringEntry(reverseKey, assetId)) | |
2155 | 2030 | } | |
2156 | 2031 | } | |
2157 | 2032 | } | |
2158 | 2033 | } | |
2159 | 2034 | else throw("Unknown entity type") | |
2160 | 2035 | } | |
2161 | 2036 | $Tuple2(((actions :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) :+ prologAction), 0) | |
2162 | 2037 | } | |
2163 | 2038 | } | |
2164 | 2039 | } | |
2165 | 2040 | ||
2166 | 2041 | ||
2167 | 2042 | ||
2168 | 2043 | @Callable(i) | |
2169 | 2044 | func setReferrals (oldPlayer,newPlayer) = if ((i.callerPublicKey != pub)) | |
2170 | 2045 | then throw("Permission denied") | |
2171 | 2046 | else { | |
2172 | 2047 | let prologAction = prolog(i) | |
2173 | 2048 | if ((size(i.payments) != 0)) | |
2174 | 2049 | then throw("No payments required") | |
2175 | 2050 | else if (!(isDefined(addressFromString(oldPlayer)))) | |
2176 | 2051 | then throw(("Invalid address: " + oldPlayer)) | |
2177 | 2052 | else if (!(isDefined(addressFromString(newPlayer)))) | |
2178 | 2053 | then throw(("Invalid address: " + newPlayer)) | |
2179 | 2054 | else { | |
2180 | 2055 | let oldsKey = keyOldies() | |
2181 | 2056 | let olds = getString(oldsKey) | |
2182 | 2057 | let oldies = if (isDefined(olds)) | |
2183 | 2058 | then split_4C(value(olds), "_") | |
2184 | 2059 | else nil | |
2185 | 2060 | if (containsElement(oldies, newPlayer)) | |
2186 | 2061 | then throw((newPlayer + " is not newbie (already has referrals)")) | |
2187 | 2062 | else { | |
2188 | 2063 | let refByKey = keyAddressRefBy(newPlayer) | |
2189 | 2064 | let refBy = getString(refByKey) | |
2190 | 2065 | if (if (isDefined(refBy)) | |
2191 | 2066 | then isDefined(addressFromString(value(refBy))) | |
2192 | 2067 | else false) | |
2193 | 2068 | then throw(((newPlayer + " already has refBy: ") + value(refBy))) | |
2194 | 2069 | else { | |
2195 | 2070 | let refsKey = keyAddressReferrals(oldPlayer) | |
2196 | 2071 | let refs = getString(refsKey) | |
2197 | 2072 | let refsArray = if (isDefined(refs)) | |
2198 | 2073 | then split_4C(value(refs), "_") | |
2199 | 2074 | else nil | |
2200 | 2075 | if (containsElement(refsArray, newPlayer)) | |
2201 | 2076 | then throw((((oldPlayer + " already contains ") + newPlayer) + " within referrals")) | |
2202 | 2077 | else { | |
2203 | 2078 | let newRefs = makeString_2C((refsArray :+ newPlayer), "_") | |
2204 | 2079 | let newOlds = if (containsElement(oldies, oldPlayer)) | |
2205 | 2080 | then value(olds) | |
2206 | 2081 | else makeString_2C((oldies :+ oldPlayer), "_") | |
2207 | 2082 | $Tuple2([StringEntry(refByKey, oldPlayer), StringEntry(refsKey, newRefs), StringEntry(oldsKey, newOlds), prologAction], 0) | |
2208 | 2083 | } | |
2209 | 2084 | } | |
2210 | 2085 | } | |
2211 | 2086 | } | |
2212 | 2087 | } | |
2213 | 2088 | ||
2214 | 2089 | ||
2215 | 2090 | ||
2216 | 2091 | @Callable(i) | |
2217 | 2092 | func splitByGlobalWeightsREADONLY (amount) = $Tuple2(nil, getNeededMaterials(amount)) | |
2218 | 2093 | ||
2219 | 2094 | ||
2220 | 2095 | ||
2221 | 2096 | @Callable(i) | |
2222 | 2097 | func splitByGlobalAndLocalWeightsREADONLY (matAmount,resAmount,terrains) = { | |
2223 | 2098 | let terrainCounts = countTerrains(terrains) | |
2224 | 2099 | $Tuple2(nil, $Tuple2(getNeededMaterials(matAmount), distributeByWeights(resAmount, terrainCounts))) | |
2225 | 2100 | } | |
2226 | 2101 | ||
2227 | 2102 | ||
2228 | 2103 | ||
2229 | 2104 | @Callable(i) | |
2230 | 2105 | func getBackpackREADONLY (duckAssetId) = $Tuple2(nil, makeString(getBackpack(keyBackpackByDuck(duckAssetId)), ":")) | |
2231 | 2106 | ||
2232 | 2107 | ||
2233 | 2108 | ||
2234 | 2109 | @Callable(i) | |
2235 | 2110 | func getWarehouseREADONLY (landAssetId) = { | |
2236 | 2111 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
2237 | 2112 | let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE) | |
2238 | 2113 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
2239 | 2114 | $Tuple2(nil, makeString_2C(getWarehouse(keyWarehouseByLand(landAssetId), landIndex, infraLevel), ":")) | |
2240 | 2115 | } | |
2241 | 2116 | ||
2242 | 2117 | ||
2243 | 2118 | ||
2244 | 2119 | @Callable(i) | |
2245 | 2120 | func saveLastTx () = if ((i.caller != wlgContract)) | |
2246 | 2121 | then throw("Access denied") | |
2247 | 2122 | else $Tuple2([prolog(i)], 42) | |
2248 | 2123 | ||
2249 | 2124 |
github/deemru/w8io/169f3d6 203.35 ms ◑