tx · 7MuLPdzs3qR1xJWpXbHvd6tvWFoHPm3h37WQytXpUdbU 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm: -0.04900000 Waves 2024.12.03 23:11 [3398924] smart account 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm > SELF 0.00000000 Waves
{ "type": 13, "id": "7MuLPdzs3qR1xJWpXbHvd6tvWFoHPm3h37WQytXpUdbU", "fee": 4900000, "feeAssetId": null, "timestamp": 1733256700696, "version": 2, "chainId": 84, "sender": "3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm", "senderPublicKey": "EVooykMNV691Venwp1dHUTBd7KWequzUcda57Wd3LQEX", "proofs": [ "PPnZcA74rVjyGnMC5kneTyeHXtFbcyF1g7vQENG6DBhnyW3zpaNcBWkWrAmNPuNQBfHbGx4erareVHk7qhLyMKp" ], "script": "base64:BgKjAQgCEgMKAQgSBAoCCAESAwoBBBIECgIICBIECgIICBIDCgEIEgASBAoCCAgSBAoCCAgSBAoCAQgSBAoCAQgSBAoCCAgSABIDCgEBEgQKAggIEgQKAggIEgUKAwgICBIECgIICBIHCgUBAQEBARIDCgEBEgUKAwEBCBIDCgEIEgMKAQgSABIECgIIARIECgIIARIDCgEIEgASABIDCgEIEgMKAQiyAQAWS1NfU0VQQVJBVEVfUFVCTElDX0tFWQcAE0tTX0FMTE9XX1JPQk9fRFVDS1MHABRPTERfU1RBS0lOR19ERUFETElORQCAqrftuDIABWNoYWluCQDJAQIJAMoBAggFBHRoaXMFYnl0ZXMAAQABAANwdWIEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDADBRZLU19TRVBBUkFURV9QVUJMSUNfS0VZASCrF1ePFWfjWVRBsNZy62abxKPTZl7VmYZQ35g3H7IJCAEgT1PiGj9UqNadUk4THUYnVb2zU/Mse8lUVLD/Q8G0FCgDCQAAAgEBVAUHJG1hdGNoMAEgT1PiGj9UqNadUk4THUYnVb2zU/Mse8lUVLD/Q8G0FCgJAAIBAg1Vbmtub3duIGNoYWluAAt1c2R0QXNzZXRJZAQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAEghNp6sggDP07Ru8qO7ouTvMmC3Qtd+geWqNQj+agP/7kDCQAAAgEBVAUHJG1hdGNoMAEgVbHYn3KHgu/l41uNrAWrZd6aQ6EvFrsF8xq3h6XxxRgJAAIBAg1Vbmtub3duIGNoYWluABVkZWZhdWx0UmVzdEFkZHJlc3NTdHIEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDACIzNQUUN1dkZidmg0TGtQVW5yblUxejNqbmJBMXA5bTNXTmh2AwkAAAIBAVQFByRtYXRjaDACIzNNdW1rR0d6dENLQVhwV0RxeGtkZG9mcVhTVWJxUWt2U0p5CQACAQINVW5rbm93biBjaGFpbgAQYWNyZXMyQWRkcmVzc1N0cgQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAIjM1A0VUgzVDluWHBNTnBVbVNtUWpQbUV6M0c4NXQzem42ZUEDCQAAAgEBVAUHJG1hdGNoMAIjM05CUHgxRmNpdTNKUU5FR1oyMWpTblRkdXRMTkdHQlVTWGgJAAIBAg1Vbmtub3duIGNoYWluAANTRVACAl9fAAVNVUxUNgDAhD0ABU1VTFQ4AIDC1y8ABVNTSVpFABkABU1TSVpFAGQABUxTSVpFAOEBAAZYTFNJWkUAkAMAB1hYTFNJWkUA8QQABUlURVI2CQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwBD2dldFN0cmluZ09yRmFpbAIHYWRkcmVzcwNrZXkJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnQgCBQdhZGRyZXNzBQNrZXkJALkJAgkAzAgCAgptYW5kYXRvcnkgCQDMCAIJAKUIAQUHYWRkcmVzcwkAzAgCAgEuCQDMCAIFA2tleQkAzAgCAg8gaXMgbm90IGRlZmluZWQFA25pbAIAABFJZHhDZmdFY29ub215RGFwcAACAA1JZHhDZmdXbGdEYXBwAAQAFElkeENmZ1RvdXJuYW1lbnREYXBwAAcAD0lkeENmZ0FjcmVzRGFwcAAIAQprZXlSZXN0Q2ZnAAIOJXNfX3Jlc3RDb25maWcBDmtleVJlc3RBZGRyZXNzAAIMJXNfX3Jlc3RBZGRyARFyZWFkUmVzdENmZ09yRmFpbAEEcmVzdAkAvAkCCQEPZ2V0U3RyaW5nT3JGYWlsAgUEcmVzdAkBCmtleVJlc3RDZmcABQNTRVABGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIHcmVzdENmZwNpZHgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkApggBCQCRAwIFB3Jlc3RDZmcFA2lkeAkArAICAipSZXN0IGNmZyBkb2Vzbid0IGNvbnRhaW4gYWRkcmVzcyBhdCBpbmRleCAJAKQDAQUDaWR4AAxyZXN0Q29udHJhY3QJARFAZXh0ck5hdGl2ZSgxMDYyKQEJAQt2YWx1ZU9yRWxzZQIJAJ0IAgUEdGhpcwkBDmtleVJlc3RBZGRyZXNzAAUVZGVmYXVsdFJlc3RBZGRyZXNzU3RyAAdyZXN0Q2ZnCQERcmVhZFJlc3RDZmdPckZhaWwBBQxyZXN0Q29udHJhY3QAD2Vjb25vbXlDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFB3Jlc3RDZmcFEUlkeENmZ0Vjb25vbXlEYXBwAAt3bGdDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFB3Jlc3RDZmcFDUlkeENmZ1dsZ0RhcHAAEnRvdXJuYW1lbnRDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFB3Jlc3RDZmcFFElkeENmZ1RvdXJuYW1lbnREYXBwAA1hY3Jlc0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwUPSWR4Q2ZnQWNyZXNEYXBwAApyZWNMYW5kTnVtAAAAC3JlY0xhbmRTaXplAAEAC3JlY1RlcnJhaW5zAAIAD2FjcmVzQXNzZXRJZEtleQIMYWNyZXNBc3NldElkAAxhY3Jlc0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnAgCBQ1hY3Jlc0NvbnRyYWN0BQ9hY3Jlc0Fzc2V0SWRLZXkCF0FDUkVTIGlzIG5vdCBpc3N1ZWQgeWV0AAtyYW5kb21EZWxheQACAQlrZXlDb21taXQBB2FkZHJlc3MJAKwCAgIPZmluaXNoQmxvY2tGb3JfBQdhZGRyZXNzARFrZXlSZXNQcm9wb3J0aW9ucwACE3Jlc1R5cGVzUHJvcG9ydGlvbnMBFWtleVN0YWtlZExhbmRzQnlPd25lcgEJb3duZXJBZGRyCQCsAgICE3N0YWtlZExhbmRzQnlPd25lcl8FCW93bmVyQWRkcgEWa2V5U3Rha2VkUGllY2VzQnlPd25lcgEJb3duZXJBZGRyCQCsAgICFHN0YWtlZFBpZWNlc0J5T3duZXJfBQlvd25lckFkZHIBBWFzSW50AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACA0ludAQBbgUHJG1hdGNoMAUBbgkAAgECFWZhaWwgdG8gY2FzdCBpbnRvIEludAEJYXNBbnlMaXN0AQF2BAckbWF0Y2gwBQF2AwkAAQIFByRtYXRjaDACCUxpc3RbQW55XQQBbAUHJG1hdGNoMAUBbAkAAgECG2ZhaWwgdG8gY2FzdCBpbnRvIExpc3RbQW55XQEPbnVtUGllY2VzQnlTaXplAQhsYW5kU2l6ZQQHJG1hdGNoMAUIbGFuZFNpemUDCQAAAgIBUwUHJG1hdGNoMAUFU1NJWkUDCQAAAgIBTQUHJG1hdGNoMAUFTVNJWkUDCQAAAgIBTAUHJG1hdGNoMAUFTFNJWkUDCQAAAgICWEwFByRtYXRjaDAFBlhMU0laRQMJAAACAgNYWEwFByRtYXRjaDAFB1hYTFNJWkUJAAIBAhFVbmtub3duIGxhbmQgc2l6ZQEKa2V5QmxvY2tlZAACEGNvbnRyYWN0c0Jsb2NrZWQBFWtleUxhc3RXZWVrVHhJZEJ5VXNlcgEEYWRkcgkArAICAhNsYXN0V2Vla1R4SWRCeVVzZXJfBQRhZGRyARRrZXlDdXJXZWVrVHhJZEJ5VXNlcgEEYWRkcgkArAICAhJjdXJXZWVrVHhJZEJ5VXNlcl8FBGFkZHIBCmZpeGVkUG9pbnQCA3ZhbAhkZWNpbWFscwQGdGVuUG93CQBsBgAKAAAFCGRlY2ltYWxzAAAAAAUERE9XTgQHbG93UGFydAkApAMBCQBqAgUDdmFsBQZ0ZW5Qb3cEBnplcm9lcwkAsAICCQCkAwEFBnRlblBvdwkAZAIAAQkAsQIBBQdsb3dQYXJ0CQCsAgIJAKwCAgkArAICCQCkAwEJAGkCBQN2YWwFBnRlblBvdwIBLgUGemVyb2VzBQdsb3dQYXJ0AQ9nZXRSYW5kb21OdW1iZXIDCG1heFZhbHVlBHNhbHQHZW50cm9weQMJAGcCAAAFCG1heFZhbHVlCQACAQIWbWF4VmFsdWUgc2hvdWxkIGJlID4gMAQKcmFuZG9tSGFzaAkA1BYBCQDLAQIFBHNhbHQFB2VudHJvcHkJAGoCCQCxCQEFCnJhbmRvbUhhc2gFCG1heFZhbHVlAQlmaW5hbFRpbWUACQCXAwEJAMwIAggFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgUUT0xEX1NUQUtJTkdfREVBRExJTkUFA25pbAAKTEFORFBSRUZJWAIETEFORAAKRFVDS1BSRUZJWAIERFVDSwALUk9CT19QUkVGSVgCBFJPQk8ACkFSVFBSRVNBTEUCB1BSRVNBTEUABk5VTVJFUwAGAA9EQUlMWVJFU0JZUElFQ0UAgPjSAQAMV0hNVUxUSVBMSUVSAIDIr6AlAA9ERUZBVUxUTE9DQVRJT04CD0FmcmljYV9GX0FmcmljYQAQUkVTT1VSQ0VQUklDRU1JTgDVtQIAFU1JTl9VU0RUX0ZFRV9ERUxJVkVSWQDQhgMAFVVTRFQyQUNSRVNfTVVMVElQTElFUgAKABdBTExPV0VEX0ZSRUVfREVMSVZFUklFUwAAABpBQ1JFU19GT1JfREVMSVZFUllfQVRURU1QVACAhK9fAAlwcm9kVHlwZXMJAMwIAgIQRmlyc3QgQWlkIEtpdCBMMQkAzAgCAhBGaXJzdCBBaWQgS2l0IEwyCQDMCAICEEZpcnN0IEFpZCBLaXQgTDMJAMwIAgILQmFja3BhY2sgTDEJAMwIAgILQmFja3BhY2sgTDIJAMwIAgILQmFja3BhY2sgTDMJAMwIAgIORm9vZCBSYXRpb24gTDEJAMwIAgIORm9vZCBSYXRpb24gTDIJAMwIAgIORm9vZCBSYXRpb24gTDMJAMwIAgILSmV0IFBhY2sgTDEJAMwIAgILSmV0IFBhY2sgTDIJAMwIAgILSmV0IFBhY2sgTDMJAMwIAgIJU2hpZWxkIEwxCQDMCAICCVNoaWVsZCBMMgkAzAgCAglTaGllbGQgTDMJAMwIAgIHTWluZSBMMQkAzAgCAgdNaW5lIEwyCQDMCAICB01pbmUgTDMJAMwIAgIHVHJhcCBMMQkAzAgCAgdUcmFwIEwyCQDMCAICB1RyYXAgTDMJAMwIAgILQm9vbS1Eb2cgTDEJAMwIAgILQm9vbS1Eb2cgTDIJAMwIAgILQm9vbS1Eb2cgTDMFA25pbAAQcHJvZHVjdGlvbk1hdHJpeAkAzAgCAiU4XzhfOF8xN18xN180Ml8xMl8wXzMwXzAsMCwwLDAsMCwwLDBfCQDMCAICJThfOF84XzE3XzE3XzQyXzI0XzBfNjBfMCwwLDUsMiwwLDAsMF8JAMwIAgInOF84XzhfMTdfMTdfNDJfMzZfMF8xMjBfMCwwLDEwLDQsMCwwLDBfCQDMCAICKThfMTlfMTlfOF8yN18xOV8yNl8xXzIwXzAsMCwwLDAsMCwwLDBfMDAxCQDMCAICKThfMTlfMTlfOF8yN18xOV81Ml8xXzQwXzAsMCwwLDAsMCwwLDBfMDAxCQDMCAICKThfMTlfMTlfOF8yN18xOV83OF8xXzgwXzAsMCwwLDAsMCwwLDBfMDAxCQDMCAICJThfOF84XzhfOF82MF8xM18yXzJfMCwwLDAsMCwwLDAsMF8wMTEJAMwIAgIlOF84XzhfOF84XzYwXzI2XzJfNF8wLDAsMCwwLDAsMCwwXzAxMQkAzAgCAiU4XzhfOF84XzhfNjBfMzlfMl84XzAsMCwwLDAsMCwwLDBfMDExCQDMCAICKTMwXzMwXzNfMTdfMTdfM18zMF8zXzMwXzAsMCwwLDAsMCwwLDBfMTExCQDMCAICKTMwXzMwXzNfMTdfMTdfM182MF8zXzUwXzAsMCwwLDAsMCwwLDBfMTExCQDMCAICKTMwXzMwXzNfMTdfMTdfM185MF8zXzcwXzAsMCwwLDAsMCwwLDBfMTExCQDMCAICKzE4XzE4XzEwXzE4XzE4XzE4XzExXzRfMTBfMCwwLDAsMCwwLDAsMF8yMDEJAMwIAgIrMThfMThfMTBfMThfMThfMThfMjJfNF8yMF8wLDAsMCwwLDAsMCwwXzIwMQkAzAgCAisxOF8xOF8xMF8xOF8xOF8xOF8zM180XzMwXzAsMCwwLDAsMCwwLDBfMjAxCQDMCAICKjRfMTNfMjJfNF8zNV8yMl8yM18wXzUwLDEsMF8wLDAsMCwwLDAsMCwwXwkAzAgCAio0XzEzXzIyXzRfMzVfMjJfNDZfMF81MCwxLDFfMCwyLDUsMCwwLDAsMF8JAMwIAgIrNF8xM18yMl80XzM1XzIyXzY5XzBfNTAsMiwxXzAsNSwxMCwwLDAsMCwwXwkAzAgCAio1XzI1XzQwXzVfMTBfMTVfMjBfMV8zMCwxLDFfMCwwLDAsMCwwLDAsMF8JAMwIAgIqNV8yNV80MF81XzEwXzE1XzQwXzFfMzAsMSwyXzIsMSwzLDAsMCwwLDBfCQDMCAICKjVfMjVfNDBfNV8xMF8xNV82MF8xXzMwLDEsM181LDIsOCwwLDAsMCwwXwkAzAgCAicyM18yM181XzIwXzIzXzZfMzVfMl8xMDBfMCwwLDAsMCwwLDAsMF8JAMwIAgInMjNfMjNfNV8yMF8yM182XzcwXzJfMTUwXzAsMCwwLDAsMCwwLDBfCQDMCAICKDIzXzIzXzVfMjBfMjNfNl8xMDVfMl8yMDBfMCwwLDAsMCwwLDAsMF8FA25pbAAJcklkeENvZWZmAAYAEHJJZHhSZXF1aXJlbWVudHMACQAJcklkeFNsb3RzAAoADlBST0RVQ1RQS0dTSVpFAAoAC3doSWR4TGV2ZWxzAAAACHdoSWR4UmVzAAEACHdoSWR4TWF0AAIACXdoSWR4UHJvZAADAAl3aElkeExPRlQABAAJdm9sTG9ja2VkAAAAC3ZvbE9jY3VwaWVkAAEAB3ZvbEZyZWUAAgAIdm9sVG90YWwAAwAKYnBJZHhMZXZlbAAAAAhicElkeFJlcwABAAhicElkeE1hdAACAAlicElkeFByb2QAAwAKbG9jSWR4VHlwZQABAAhsb2NJZHhJZAACARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBB2Fzc2V0SWQJAKwCAgIDbm9fBQdhc3NldElkARprZXlMYW5kQXNzZXRJZFRvQ3VzdG9tTmFtZQEHYXNzZXRJZAkArAICAgVsY25hXwUHYXNzZXRJZAEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEHYXNzZXRJZAkArAICAgNzdF8FB2Fzc2V0SWQBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgR0eXBlB2Fzc2V0SWQJALkJAgkAzAgCAgNsYXMJAMwIAgUEdHlwZQkAzAgCBQdhc3NldElkBQNuaWwCAV8BImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDB25mdFR5cGUHYXNzZXRJZAlvd25lckFkZHIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAgZzdHRhb18FB25mdFR5cGUCAV8FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgESa2V5V2FyZWhvdXNlQnlMYW5kAQtsYW5kQXNzZXRJZAkArAICAgN3aF8FC2xhbmRBc3NldElkARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQdhc3NldElkCQCsAgICC2luZnJhTGV2ZWxfBQdhc3NldElkARprZXlEdWNrQXNzZXRJZFRvQ3VzdG9tTmFtZQEHYXNzZXRJZAkArAICAhhkdWNrQ3VzdG9tTmFtZUJ5QXNzZXRJZF8FB2Fzc2V0SWQBFmtleUFkZHJlc3NUb0N1c3RvbU5hbWUBBGFkZHIJAKwCAgIYYWNjb3VudEN1c3RvbU5hbWVCeUFkZHJfBQRhZGRyAQ9rZXlBZGRyZXNzUmVmQnkBBGFkZHIJAKwCAgIJYWNjUmVmQnlfBQRhZGRyARxrZXlPbmJvYXJkQXJ0QWN0aXZhdGVkT25EdWNrAQtkdWNrQXNzZXRJZAkArAICAhpvbmJvYXJkQXJ0QWN0aXZhdGVkT25EdWNrXwULZHVja0Fzc2V0SWQBHGtleU9uYm9hcmRBcnREdWNrQWN0aXZhdGVkQnkBBGFkZHIJAKwCAgIab25ib2FyZEFydEFjdGl2YXRlZER1Y2tCeV8FBGFkZHIBE2tleUFkZHJlc3NSZWZlcnJhbHMBBGFkZHIJAKwCAgINYWNjUmVmZXJyYWxzXwUEYWRkcgEQa2V5RHVja0lkVG9Pd25lcgEHYXNzZXRJZAkArAICAgpkdWNrT3duZXJfBQdhc3NldElkARRrZXlTdGFrZWREdWNrQnlPd25lcgEJb3duZXJBZGRyCQCsAgICEnN0YWtlZER1Y2tCeU93bmVyXwUJb3duZXJBZGRyARFrZXlCYWNrcGFja0J5RHVjawELZHVja0Fzc2V0SWQJAKwCAgIJYmFja1BhY2tfBQtkdWNrQXNzZXRJZAEPa2V5RHVja0xvY2F0aW9uAQtkdWNrQXNzZXRJZAkArAICAg1kdWNrTG9jYXRpb25fBQtkdWNrQXNzZXRJZAAPZGVsaXZlcnlGdW5kS2V5AgxkZWxpdmVyeUZ1bmQADWxhc3RUb3VySWRLZXkCDiVzX19sYXN0VG91cklkAAZTQ0FMRTgAgMLXLwAMeHBMZXZlbFNjYWxlAIAZAA94cExldmVsUmVjaXBQb3cAoB8AEm51bVBvaW50c09uTGV2ZWxVcAADAAxyZXF1aXJlbWVudHMJAMwIAgIIU3RyZW5ndGgJAMwIAgIIQWNjdXJhY3kJAMwIAgIJSW50ZWxsZWN0CQDMCAICCUVuZHVyYW5jZQkAzAgCAglEZXh0ZXJpdHkJAMwIAgIFTGV2ZWwJAMwIAgIGSGVhbHRoBQNuaWwADGNoYXJTdHJlbmd0aAAAAAxjaGFyQWNjdXJhY3kAAQANY2hhckludGVsbGVjdAACAA1jaGFyRW5kdXJhbmNlAAMADWNoYXJEZXh0ZXJpdHkABAAKTlVNTUFJTkFVWAACAAhNQVhTTE9UUwACAA1NQVhQUk9ESU5TTE9UAB4BDWtleUR1Y2tIZWFsdGgBC2R1Y2tBc3NldElkCQCsAgICC2R1Y2tIZWFsdGhfBQtkdWNrQXNzZXRJZAEMa2V5RHVja0NoYXJzAQtkdWNrQXNzZXRJZAkArAICAgpkdWNrQ2hhcnNfBQtkdWNrQXNzZXRJZAEJa2V5RHVja1hQAQtkdWNrQXNzZXRJZAkArAICAgdkdWNrWFBfBQtkdWNrQXNzZXRJZAEMa2V5RHVja0xldmVsAQtkdWNrQXNzZXRJZAkArAICAgpkdWNrTGV2ZWxfBQtkdWNrQXNzZXRJZAERa2V5RHVja0ZyZWVQb2ludHMBC2R1Y2tBc3NldElkCQCsAgICD2R1Y2tGcmVlUG9pbnRzXwULZHVja0Fzc2V0SWQBEGtleUR1Y2tFcXVpcG1lbnQBC2R1Y2tBc3NldElkCQCsAgICDmR1Y2tFcXVpcG1lbnRfBQtkdWNrQXNzZXRJZAEJa2V5VXNlclhQAQRhZGRyCQCsAgICB3VzZXJYUF8FBGFkZHIBDGtleVVzZXJMZXZlbAEEYWRkcgkArAICAgp1c2VyTGV2ZWxfBQRhZGRyARFrZXlVc2VyRnJlZVBvaW50cwEEYWRkcgkArAICAg91c2VyRnJlZVBvaW50c18FBGFkZHIBDmtleVNhdmVkSGVhbHRoAQtkdWNrQXNzZXRJZAkArAICAgxzYXZlZEhlYWx0aF8FC2R1Y2tBc3NldElkARBrZXlTYXZlZExvY2F0aW9uAQtkdWNrQXNzZXRJZAkArAICAg5zYXZlZExvY2F0aW9uXwULZHVja0Fzc2V0SWQBFGtleUR1Y2tEZWxpdmVyeUNvdW50AQtkdWNrQXNzZXRJZAkArAICAhl0b3RhbERlbGl2ZXJ5Q291bnRCeUR1Y2tfBQtkdWNrQXNzZXRJZAEUa2V5VXNlckRlbGl2ZXJ5Q291bnQBBGFkZHIJAKwCAgISdXNlckRlbGl2ZXJ5Q291bnRfBQRhZGRyARZrZXlVc2VyTGFzdERlbGl2ZXJ5RGF5AQRhZGRyCQCsAgICFHVzZXJMYXN0RGVsaXZlcnlEYXlfBQRhZGRyAAd4cENsYWltAJBOAAx4cEN1c3RvbU5hbWUAwIQ9AAl4cE9uYm9hcmQAwIQ9AQlsZXZlbEJ5WFABAnhwCQBrAwUMeHBMZXZlbFNjYWxlCQBsBgUCeHAABAUPeHBMZXZlbFJlY2lwUG93AAQABAUERE9XTgUGU0NBTEU4AQltYXhIZWFsdGgBBWxldmVsCQBkAgBkBQVsZXZlbAEHbGV2ZWxVcAIJY3VyckxldmVsBW5ld1hQBAhuZXdMZXZlbAkBCWxldmVsQnlYUAEFBW5ld1hQCQDMCAIFCG5ld0xldmVsCQDMCAIJAGgCBRJudW1Qb2ludHNPbkxldmVsVXAJAGUCBQhuZXdMZXZlbAUJY3VyckxldmVsBQNuaWwACURBWU1JTExJUwCAuJkpARprZXlBY3Jlc1N0YWtlZEFtb3VudEJ5VXNlcgEEYWRkcgkArAICAhhhY3Jlc1N0YWtlZEFtb3VudEJ5VXNlcl8FBGFkZHIADFJFTkFNSU5HQ09TVADAlrECAApNQVhOQU1FTEVOADIAD1BSRVNBTEVOVU1MQU5EUwD0AwEaa2V5TGFuZEN1c3RvbU5hbWVUb0Fzc2V0SWQBBG5hbWUJAKwCAgIEbGNuXwUEbmFtZQEaa2V5RHVja0N1c3RvbU5hbWVUb0Fzc2V0SWQBBG5hbWUJAKwCAgIRZHVja0J5Q3VzdG9tTmFtZV8FBG5hbWUBFmtleUN1c3RvbU5hbWVUb0FkZHJlc3MBBG5hbWUJAKwCAgIUYWNjb3VudEJ5Q3VzdG9tTmFtZV8FBG5hbWUBCWtleU9sZGllcwACCm9sZGllc0xpc3QAC2NsYWltTW9kZVdoAAAADWNsYWltTW9kZUR1Y2sAAQATY2xhaW1Nb2RlV2hUaGVuRHVjawACARNkaXN0cmlidXRlQnlXZWlnaHRzAgV0b3RhbAd3ZWlnaHRzBANzdW0JAGQCCQBkAgkAZAIJAGQCCQBkAgkAkQMCBQd3ZWlnaHRzAAAJAJEDAgUHd2VpZ2h0cwABCQCRAwIFB3dlaWdodHMAAgkAkQMCBQd3ZWlnaHRzAAMJAJEDAgUHd2VpZ2h0cwAECQCRAwIFB3dlaWdodHMABQMJAGcCAAAFA3N1bQkAAgECEFplcm8gd2VpZ2h0cyBzdW0EBW5vcm02CQBrAwUFdG90YWwFBU1VTFQ2BQNzdW0KAQpub3JtYWxpemVyAgNhY2MEZWxlbQkAzQgCBQNhY2MJAGsDBQRlbGVtBQVub3JtNgUFTVVMVDYKAAIkbAUHd2VpZ2h0cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEKbm9ybWFsaXplcgIFAiRhCQCRAwIFAiRsBQIkaQoB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JGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDcJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwEIYWRkUHJvZEIHBmlkeENudAVwTGlzdAppc1Bvc2l0aXZlB3NlZ21lbnQHbWFpbkF1eARzbG90CWR1Y2tTdGF0cwQFcGFydHMJALUJAgUGaWR4Q250AgE6AwkBAiE9AgkAkAMBBQVwYXJ0cwACCQACAQIoSW5jb3JyZWN0IGZvcm1hdCwgc2hvdWxkIGJlIGluZGV4OmFtb3VudAMDCQEBIQEFCmlzUG9zaXRpdmUJAQIhPQIJALECAQkAkQMCBQVwYXJ0cwAAAAIHCQACAQIrUHJvZHVjdCBpZHggc2hvdWxkIGJlIDIgZGlnaXRzLCB6ZXJvIHBhZGRlZAQKcHJvZHVjdElkeAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAAEBWNvdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAQMDCQBmAgAABQpwcm9kdWN0SWR4BgkAZwIFCnByb2R1Y3RJZHgJAJADAQUQcHJvZHVjdGlvbk1hdHJpeAkAAgECE1Vua25vd24gcHJvZHVjdCBpZHgDCQBmAgAABQVjb3VudAkAAgECF0NvdW50IGNhbid0IGJlIG5lZ2F0aXZlAwkAZgIFBWNvdW50BQ1NQVhQUk9ESU5TTE9UCQACAQkArAICCQCsAgIJAKwCAgIUQ2FuJ3QgcHV0IG1vcmUgdGhhbiAJAKQDAQUNTUFYUFJPRElOU0xPVAIEIG9mIAkAkQMCBQlwcm9kVHlwZXMFCnByb2R1Y3RJZHgDCQAAAgUFY291bnQAAAkAlAoCBQVwTGlzdAcEBGhlYWQJAMkBAgUFcExpc3QJAGgCAAgFCnByb2R1Y3RJZHgEBGN1cnIJALEJAQkAyQECCQDKAQIFBXBMaXN0CQBoAgAIBQpwcm9kdWN0SWR4AAgEBHRhaWwJAMoBAgUFcExpc3QJAGgCAAgJAGQCBQpwcm9kdWN0SWR4AAEEBnJlY2lwZQkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgFCnByb2R1Y3RJZHgCAV8DAwkBASEBBQppc1Bvc2l0aXZlCQBmAgUFY291bnQFBGN1cnIHCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCVlvdSBoYXZlIAkApAMBBQRjdXJyAgQgb2YgCQCRAwIFCXByb2RUeXBlcwUKcHJvZHVjdElkeAITLCBidXQgdHJpZWQgdG8gdXNlIAkApAMBBQVjb3VudAQJaXNCaWdJdGVtAwMJAQEhAQUKaXNQb3NpdGl2ZQkBFWNoZWNrU3RhdFJlcXVpcmVtZW50cwIFCWR1Y2tTdGF0cwkAtQkCCQCRAwIFBnJlY2lwZQUQcklkeFJlcXVpcmVtZW50cwIBLAcEBmNvbXBhdAkAkQMCBQZyZWNpcGUFCXJJZHhTbG90cwMJAAACBQZjb21wYXQCAAkAAgECF0l0ZW0gY2Fubm90IGJlIGVxdWlwcGVkBAFjCQENcGFyc2VJbnRWYWx1ZQEFBmNvbXBhdAQEY1NlZwkAaQIFAWMAZAMJAQIhPQIFB3NlZ21lbnQFBGNTZWcJAAIBAhRTZWdtZW50IGluY29tcGF0aWJsZQQIY01haW5BdXgJAGkCCQBqAgUBYwBkAAoDCQECIT0CBQdtYWluQXV4BQhjTWFpbkF1eAkAAgECEVNsb3QgaW5jb21wYXRpYmxlBAljTnVtU2xvdHMJAGoCBQFjAAoDAwkBAiE9AgUEc2xvdAAACQBmAgUJY051bVNsb3RzAAEHCQACAQIeQmlnIGl0ZW1zIHNob3VsZCBvY2N1cHkgc2xvdCAwCQBmAgUJY051bVNsb3RzAAEHCQCUCgIJAMsBAgkAywECBQRoZWFkCQCaAwEJAGQCBQRjdXJyAwUKaXNQb3NpdGl2ZQUFY291bnQJAQEtAQUFY291bnQFBHRhaWwFCWlzQmlnSXRlbQELc2xvdHNHcm91cEIGAWcEYnBJbgppc1Bvc2l0aXZlB3NlZ21lbnQHbWFpbkF1eAVzdGF0cwMJAQIhPQIFAWcCAAQFc2xvdHMJALUJAgUBZwIBLAMJAGYCCQCQAwEFBXNsb3RzBQhNQVhTTE9UUwkAAgECEldyb25nIHNsb3RzIGZvcm1hdAQCczAJAJEDAgUFc2xvdHMAAAQCczEDCQBmAgkAkAMBBQVzbG90cwABCQCRAwIFBXNsb3RzAAECAAMDCQAAAgUCczACAAkAAAIFAnMxAgAHBQRicEluBAV0bXBTMAMJAQIhPQIFAnMwAgAJAQhhZGRQcm9kQgcFAnMwBQRicEluBQppc1Bvc2l0aXZlBQdzZWdtZW50BQdtYWluQXV4AAAFBXN0YXRzCQCUCgIFBGJwSW4HAwkBAiE9AgUCczECAAMIBQV0bXBTMAJfMgkAAgECHkJpZyBpdGVtIGFscmVhZHkgb2NjdXBpZXMgc2xvdAgJAQhhZGRQcm9kQgcFAnMxCAUFdG1wUzACXzEFCmlzUG9zaXRpdmUFB3NlZ21lbnQFB21haW5BdXgAAQUFc3RhdHMCXzEIBQV0bXBTMAJfMQUEYnBJbgEGZHJlc3NCBAdzZWdMaXN0BnBCeXRlcwppc1Bvc2l0aXZlBXN0YXRzCgEHc2VnbWVudAIDYWNjA3NlZwQBaggFA2FjYwJfMQQHbWFpbkF1eAkAtQkCBQNzZWcCATsDCQECIT0CCQCQAwEFB21haW5BdXgFCk5VTU1BSU5BVVgJAAIBAhRXcm9uZyBzZWdtZW50IGZvcm1hdAQBbQkAkQMCBQdtYWluQXV4AAAEAWEJAJEDAgUHbWFpbkF1eAABAwMJAAACBQFtAgAJAAACBQFhAgAHCQCUCgIJAGQCBQFqAAEIBQNhY2MCXzIEBHRtcE0JAQtzbG90c0dyb3VwQgYFAW0IBQNhY2MCXzIFCmlzUG9zaXRpdmUFAWoAAAUFc3RhdHMJAJQKAgkAZAIFAWoAAQkBC3Nsb3RzR3JvdXBCBgUBYQUEdG1wTQUKaXNQb3NpdGl2ZQUBagABBQVzdGF0cwgKAAIkbAUHc2VnTGlzdAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAJAJQKAgAABQZwQnl0ZXMKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3NlZ21lbnQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYCXzIBDWNvdW50VGVycmFpbnMBCHRlcnJhaW5zCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUEAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFCAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBQwABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUQAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFFAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBRgABBQNuaWwBBmFkZFJlcwUKY3VycmVudFJlcw10ZXJyYWluQ291bnRzCWRlbHRhVGltZQ1sYW5kU2l6ZUluZGV4F2RhaWx5QnlQaWVjZVdpdGhCb251c2VzCgEFYWRkZXICA2FjYwFpBAlyZXNPZlR5cGUJAGgCCQBoAgkAawMFCWRlbHRhVGltZQUXZGFpbHlCeVBpZWNlV2l0aEJvbnVzZXMFCURBWU1JTExJUwkAkQMCBQ10ZXJyYWluQ291bnRzBQFpBQ1sYW5kU2l6ZUluZGV4CQDNCAIFA2FjYwkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCmN1cnJlbnRSZXMFAWkFCXJlc09mVHlwZQQBcgoAAiRsBQVJVEVSNgoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEFYWRkZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYJALkJAgUBcgIBXwEPdmlydENsYWltQWRkUmVzBQpjdXJyZW50UmVzDXRlcnJhaW5Db3VudHMJZGVsdGFUaW1lDWxhbmRTaXplSW5kZXgXZGFpbHlCeVBpZWNlV2l0aEJvbnVzZXMKAQVhZGRlcgIDYWNjAWkECXJlc09mVHlwZQkAaAIJAGgCCQBrAwUJZGVsdGFUaW1lBRdkYWlseUJ5UGllY2VXaXRo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ZFZvbAEFAndoBAZ3aExvZnQDCQBmAgAFCQCQAwEFAndoCQC5CQIJAMwIAgIBMAkAzAgCCQCkAwEFCndoT2NjdXBpZWQJAMwIAgkApAMBCQBlAgUHd2hUb3RhbAUKd2hPY2N1cGllZAkAzAgCCQCkAwEFB3doVG90YWwFA25pbAIBXwQEbG9mdAkAtQkCCQCRAwIFAndoBQl3aElkeExPRlQCAV8ECHdoTG9ja2VkCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAUJdm9sTG9ja2VkBANvY2MDCQBmAgkAkAMBBQRsb2Z0AAEJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAUKd2hPY2N1cGllZAkAuQkCCQDMCAIJAKQDAQUId2hMb2NrZWQJAMwIAgkApAMBBQNvY2MJAMwIAgkApAMBCQBlAgkAZQIFB3doVG90YWwFCHdoTG9ja2VkBQNvY2MJAMwIAgkApAMBBQd3aFRvdGFsBQNuaWwCAV8JAMwIAgkAkQMCBQJ3aAULd2hJZHhMZXZlbHMJAMwIAgMJAAACCQCQAwEJALUJAgkAkQMCBQJ3aAUId2hJZHhSZXMCAV8FBk5VTVJFUwkAkQMCBQJ3aAUId2hJZHhSZXMCCzBfMF8wXzBfMF8wCQDMCAIDCQAAAgkAkAMBCQC1CQIJAJEDAgUCd2gFCHdoSWR4TWF0AgFfBQZOVU1SRVMJAJEDAgUCd2gFCHdoSWR4TWF0AgswXzBfMF8wXzBfMAkAzAgCCQCRAwIFAndoBQl3aElkeFByb2QJAMwIAgUGd2hMb2Z0BQNuaWwBDGFwcGx5Qm9udXNlcwILbGFuZEFzc2V0SWQGcGllY2VzBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQJYXJ0UGllY2VzCQELdmFsdWVPckVsc2UCCQCfCAEJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkAAAEBGFkZDYJAGkCBQppbmZyYUxldmVsAAYEBGFkZDcJAGkCBQppbmZyYUxldmVsAAcJAGQCCQBkAgUPREFJTFlSRVNCWVBJRUNFCQBrAwUPREFJTFlSRVNCWVBJRUNFCQBkAgkAZAIFCmluZnJhTGV2ZWwFBGFkZDYJAGgCAAIFBGFkZDcABQkAawMFD0RBSUxZUkVTQllQSUVDRQUJYXJ0UGllY2VzCQBoAgUGcGllY2VzAAUBFGNoZWNrQ2xhaW1Db25kaXRpb25zAwRhZGRyCWNsYWltTW9kZQ1sYW5kQXNzZXRJZEluBA0kdDAzNDI0NzM0Nzg2AwkAAAIFCWNsYWltTW9kZQULY2xhaW1Nb2RlV2gJAJQKAgUNbGFuZEFzc2V0SWRJbgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAgAEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkBQ9ERUZBVUxUTE9DQVRJT04EA2xvYwkAtQkCCQEFdmFsdWUBBQtjdXJMb2NhdGlvbgIBXwMJAQIhPQIJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAgFMCQACAQkArAICCQCsAgICFkR1Y2sgbG9jYXRpb24gdHlwZSBpcyAJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAhEsIGJ1dCBzaG91bGQgYmUgTAkAlAoCCQCRAwIFA2xvYwUIbG9jSWR4SWQFC2R1Y2tBc3NldElkBAtsYW5kQXNzZXRJZAgFDSR0MDM0MjQ3MzQ3ODYCXzEEBmR1Y2tJZAgFDSR0MDM0MjQ3MzQ3ODYCXzIEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQULbGFuZEFzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFB3RpbWVLZXkJAKwCAgkArAICAgVMYW5kIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUEYWRkcgkAAgEJAKwCAgUKTEFORFBSRUZJWAINIGlzIG5vdCB5b3VycwQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8JAJYKBAUGZHVja0lkBQtsYW5kQXNzZXRJZAUBZAUJc2F2ZWRUaW1lARBjbGFpbVJlc0ludGVybmFsBARhZGRyBmFtb3VudAljbGFpbU1vZGUNbGFuZEFzc2V0SWRJbgMJAGYCAAAFBmFtb3VudAkAAgECD05lZ2F0aXZlIGFtb3VudAQBYwkBFGNoZWNrQ2xhaW1Db25kaXRpb25zAwUEYWRkcgUJY2xhaW1Nb2RlBQ1sYW5kQXNzZXRJZEluBAhsYW5kU2l6ZQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUEDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCCAUBYwJfMwULcmVjVGVycmFpbnMECWRlbHRhVGltZQkAZQIJAQlmaW5hbFRpbWUACAUBYwJfNAMJAGYCAAAFCWRlbHRhVGltZQkAAgEJAKwCAgkArAICCQCsAgICJlNhdmVkIHRpbWVzdGFtcCBpcyBpbiBmdXR1cmUsIHNhdmVkID0gCQCkAwEIBQFjAl80AgosIGZpbmFsID0gCQCkAwEJAQlmaW5hbFRpbWUABAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBBQhsYW5kU2l6ZQQWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkBDGFwcGx5Qm9udXNlcwIIBQFjAl8yBQZwaWVjZXMECGF2YWlsUmVzCQBrAwUJZGVsdGFUaW1lCQBoAgUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQUGcGllY2VzBQlEQVlNSUxMSVMDCQBmAgUGYW1vdW50BQhhdmFpbFJlcwkAAgEJAKwCAgkArAICCQCsAgICIk5vdCBlbm91Z2ggcmVzb3VyY2VzLCBhdmFpbGFibGUgPSAJAKQDAQUIYXZhaWxSZXMCDiwgcmVxdWVzdGVkID0gCQCkAwEFBmFtb3VudAQMbmV3RGVsdGFUaW1lCQBrAwkAZQIFCGF2YWlsUmVzBQZhbW91bnQFCURBWU1JTExJUwkAaAIFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UFBnBpZWNlcwQMbmV3VGltZXN0YW1wCQBlAgkBCWZpbmFsVGltZQAFDG5ld0RlbHRhVGltZQQJbGFuZEluZGV4CQBpAgUGcGllY2VzBQVTU0laRQQKcmVzVG9DbGFpbQkBCXZpcnRDbGFpbQQFDXRlcnJhaW5Db3VudHMJAGUCBQlkZWx0YVRpbWUFDG5ld0RlbHRhVGltZQUJbGFuZEluZGV4BRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBAV3aEtleQkBEmtleVdhcmVob3VzZUJ5TGFuZAEIBQFjAl8yBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQgFAWMCXzIAAAQJY3VycmVudFdoCQEMZ2V0V2FyZWhvdXNlAwUFd2hLZXkFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAQEbG9mdAkAtQkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhMT0ZUAgFfBAt3aFNwYWNlTGVmdAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUDAwkAAAIFCWNsYWltTW9kZQULY2xhaW1Nb2RlV2gJAGYCBQZhbW91bnQFC3doU3BhY2VMZWZ0BwkAAgEJAKwCAgkArAICAgVPbmx5IAkApAMBBQt3aFNwYWNlTGVmdAIYIHNwYWNlIGxlZnQgaW4gd2FyZWhvdXNlBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQgFAWMCXzEEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQOY3VycmVudFBhY2tSZXMJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMCAV8EDGN1cnJlbnRXaFJlcwkAtQkCCQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMCAV8EDSR0MDM3MTU2MzgwMjcDCQAAAgUJY2xhaW1Nb2RlBQtjbGFpbU1vZGVXaAkAlgoECQEGYWRkUmVzBQUMY3VycmVudFdoUmVzBQ10ZXJyYWluQ291bnRzCQBlAgUJZGVsdGFUaW1lBQxuZXdEZWx0YVRpbWUFCWxhbmRJbmRleAUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAULdm9sT2NjdXBpZWQIBQpyZXNUb0NsYWltAl8yCQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUIBQpyZXNUb0NsYWltAl8yAwkAAAIFCWNsYWltTW9kZQUNY2xhaW1Nb2RlRHVjawkAlgoECQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMJAQZhZGRSZXMFBQ5jdXJyZW50UGFja1JlcwUNdGVycmFpbkNvdW50cwkAZQIFCWRlbHRhVGltZQUMbmV3RGVsdGFUaW1lBQlsYW5kSW5kZXgFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUEBWRpc3RyCQENZGlzdHJpYnV0ZVJlcwQFDGN1cnJlbnRXaFJlcwUOY3VycmVudFBhY2tSZXMFCnJlc1RvQ2xhaW0FC3doU3BhY2VMZWZ0BAR3aEFtCQCXAwEJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUJAMwIAggFCnJlc1RvQ2xhaW0CXzIFA25pbAkAlgoECAUFZGlzdHICXzEIBQVkaXN0cgJfMgkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAUEd2hBbQkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQd2b2xGcmVlBQR3aEFtBAV3aFJlcwgFDSR0MDM3MTU2MzgwMjcCXzEEBWJwUmVzCAUNJHQwMzcxNTYzODAyNwJfMgQFbG9mdE8IBQ0kdDAzNzE1NjM4MDI3Al8zBAVsb2Z0RggFDSR0MDM3MTU2MzgwMjcCXzQJAJcKBQkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBCAUBYwJfMgUMbmV3VGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgIBQFjAl8yBQRhZGRyBQxuZXdUaW1lc3RhbXAFA25pbAUFYnBLZXkJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCBQVicFJlcwkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAUFd2hLZXkJAMwIAgkAkQMCBQljdXJyZW50V2gFC3doSWR4TGV2ZWxzCQDMCAIFBXdoUmVzCQDMCAIJAJEDAgUJY3VycmVudFdoBQh3aElkeE1hdAkAzAgCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kCQDMCAIJALkJAgkAzAgCCQCRAwIFBGxvZnQFCXZvbExvY2tlZAkAzAgCCQCkAwEFBWxvZnRPCQDMCAIJAKQDAQUFbG9mdEYJAMwIAgkAkQMCBQRsb2Z0BQh2b2xUb3RhbAUDbmlsAgFfBQNuaWwBCGNsYWltQWxsBARhZGRyC2xhbmRBc3NldElkBnBpZWNlcwljbGFpbU1vZGUEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBBXZhbHVlAQkAnwgBBQd0aW1lS2V5BAhhdmFpbFJlcwkAaAIJAGsDCQBlAgkBCWZpbmFsVGltZQAFCXNhdmVkVGltZQkBDGFwcGx5Qm9udXNlcwIFC2xhbmRBc3NldElkBQZwaWVjZXMFCURBWU1JTExJUwUGcGllY2VzCQEQY2xhaW1SZXNJbnRlcm5hbAQFBGFkZHIFCGF2YWlsUmVzBQljbGFpbU1vZGUFC2xhbmRBc3NldElkARN1cGRhdGVTdGF0c0ludGVybmFsBAZsdmxLZXkFeHBLZXkJcG9pbnRzS2V5B2RlbHRhWFAEAnhwCQELdmFsdWVPckVsc2UCCQCfCAEFBXhwS2V5AAAEBW5ld1hQCQBkAgUCeHAFB2RlbHRhWFAECWx2bFBvaW50cwkBB2xldmVsVXACCQELdmFsdWVPckVsc2UCCQCfCAEFBmx2bEtleQAABQVuZXdYUAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQZsdmxLZXkJAJEDAgUJbHZsUG9pbnRzAAAJAMwIAgkBDEludGVnZXJFbnRyeQIFBXhwS2V5BQVuZXdYUAkAzAgCCQEMSW50ZWdlckVudHJ5AgUJcG9pbnRzS2V5CQBkAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlwb2ludHNLZXkAAAkAkQMCBQlsdmxQb2ludHMAAQUDbmlsBQVuZXdYUAEXdXBkYXRlRHVja1N0YXRzSW50ZXJuYWwCC2R1Y2tBc3NldElkB2RlbHRhWFAEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQULZHVja0Fzc2V0SWQEBGFkZHIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEQa2V5RHVja0lkVG9Pd25lcgEFC2R1Y2tBc3NldElkCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMDAwUTS1NfQUxMT1dfUk9CT19EVUNLUwkAAAIIBQVhc3NldAZpc3N1ZXIFBHRoaXMHCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQULUk9CT19QUkVGSVgHCQETdXBkYXRlU3RhdHNJbnRlcm5hbAQJAQxrZXlVc2VyTGV2ZWwBBQRhZGRyCQEJa2V5VXNlclhQAQUEYWRkcgkBEWtleVVzZXJGcmVlUG9pbnRzAQUEYWRkcgUHZGVsdGFYUAkBE3VwZGF0ZVN0YXRzSW50ZXJuYWwECQEMa2V5RHVja0xldmVsAQULZHVja0Fzc2V0SWQJAQlrZXlEdWNrWFABBQtkdWNrQXNzZXRJZAkBEWtleUR1Y2tGcmVlUG9pbnRzAQULZHVja0Fzc2V0SWQFB2RlbHRhWFABFnVwZGF0ZUFjY1N0YXRzSW50ZXJuYWwCBGFkZHIHZGVsdGFYUAkBE3VwZGF0ZVN0YXRzSW50ZXJuYWwECQEMa2V5VXNlckxldmVsAQUEYWRkcgkBCWtleVVzZXJYUAEFBGFkZHIJARFrZXlVc2VyRnJlZVBvaW50cwEFBGFkZHIFB2RlbHRhWFABEmFjdGl2YXRlT25ib2FyZEFydAEEYWRkcgQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAhyZWZCeUtleQkBD2tleUFkZHJlc3NSZWZCeQEFBGFkZHIEBXJlZkJ5CQCiCAEFCHJlZkJ5S2V5AwkBASEBCQEJaXNEZWZpbmVkAQUFcmVmQnkJAAIBAilZb3UgYXJlIG5vdCBlbGlnaWJsZSBmb3IgT05CT0FSRCBhcnRpZmFjdAQGYXJ0S2V5CQEca2V5T25ib2FyZEFydER1Y2tBY3RpdmF0ZWRCeQEFBGFkZHIEB2FydER1Y2sJAKIIAQUGYXJ0S2V5AwkBCWlzRGVmaW5lZAEFB2FydER1Y2sJAAIBCQCsAgICL1lvdSBhbHJlYWR5IHVzZWQgeW91ciBPTkJPQVJEIGFydGlmYWN0IG9uIGR1Y2sgCQEFdmFsdWUBBQdhcnREdWNrBBBkdWNrQWN0aXZhdG9yS2V5CQEca2V5T25ib2FyZEFydEFjdGl2YXRlZE9uRHVjawEFC2R1Y2tBc3NldElkBA1kdWNrQWN0aXZhdG9yCQCiCAEFEGR1Y2tBY3RpdmF0b3JLZXkDCQEJaXNEZWZpbmVkAQUNZHVja0FjdGl2YXRvcgkAAgEJAKwCAgkArAICCQCsAgICCVRoZSBkdWNrIAULZHVja0Fzc2V0SWQCNCBhbHJlYWR5IGdvdCBwb2ludHMgZnJvbSBPTkJPQVJEIGFydGlmYWN0IGZyb20gdXNlciAJAQV2YWx1ZQEFDWR1Y2tBY3RpdmF0b3IJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQZhcnRLZXkFC2R1Y2tBc3NldElkCQDMCAIJAQtTdHJpbmdFbnRyeQIFEGR1Y2tBY3RpdmF0b3JLZXkFBGFkZHIFA25pbAgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkBQl4cE9uYm9hcmQCXzEBEmFjdGl2YXRlUHJlc2FsZUFydAIEYWRkcg1sYW5kQXNzZXRJZEluBAFjCQEUY2hlY2tDbGFpbUNvbmRpdGlvbnMDBQRhZGRyBRNjbGFpbU1vZGVXaFRoZW5EdWNrBQ1sYW5kQXNzZXRJZEluBAtsYW5kQXNzZXRJZAgFAWMCXzIEBnBpZWNlcwkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAggFAWMCXzMFC3JlY0xhbmRTaXplBA1hY3RpdmF0aW9uS2V5CQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAMJAGYCCQELdmFsdWVPckVsc2UCCQCfCAEFDWFjdGl2YXRpb25LZXkAAAAACQACAQIlUHJlc2FsZSBhcnRpZmFjdCBpcyBhbHJlYWR5IGFjdGl2YXRlZAMJAGYCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAggFAWMCXzMFCnJlY0xhbmROdW0FD1BSRVNBTEVOVU1MQU5EUwkAAgEJAKwCAgkArAICCQCsAgIFCkxBTkRQUkVGSVgCASAFC2xhbmRBc3NldElkAiUgaXMgbm90IGVsaWdpYmxlIGZvciBwcmVzYWxlIGFydGlmYWN0BAtjbGFpbVJlc3VsdAkBCGNsYWltQWxsBAUEYWRkcgULbGFuZEFzc2V0SWQFBnBpZWNlcwUTY2xhaW1Nb2RlV2hUaGVuRHVjawkAzQgCCQDNCAIJAM0IAggFC2NsYWltUmVzdWx0Al8xCQEMSW50ZWdlckVudHJ5AgUNYWN0aXZhdGlvbktleQUGcGllY2VzCQELU3RyaW5nRW50cnkCCAULY2xhaW1SZXN1bHQCXzIJALkJAggFC2NsYWltUmVzdWx0Al8zAgE6CQELU3RyaW5nRW50cnkCCAULY2xhaW1SZXN1bHQCXzQJALkJAggFC2NsYWltUmVzdWx0Al81AgE6AQZwcm9sb2cBAWkDAwkBAiE9AggFAWkMb3JpZ2luQ2FsbGVyBQxyZXN0Q29udHJhY3QJAQt2YWx1ZU9yRWxzZQIJAKAIAQkBCmtleUJsb2NrZWQABwcJAAIBAh9Db250cmFjdHMgYXJlIHVuZGVyIG1haW50ZW5hbmNlCQDMCAIJAQtTdHJpbmdFbnRyeQIJARRrZXlDdXJXZWVrVHhJZEJ5VXNlcgEJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQFA25pbAETdW5zdGFrZUxhbmRJbnRlcm5hbAIEYWRkcgtsYW5kQXNzZXRJZAQFd2hLZXkJARJrZXlXYXJlaG91c2VCeUxhbmQBBQtsYW5kQXNzZXRJZAQIbGFuZEluZm8JALUJAggJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAtkZXNjcmlwdGlvbgIBXwQIbGFuZFNpemUJAJEDAgUIbGFuZEluZm8FC3JlY0xhbmRTaXplBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBBQhsYW5kU2l6ZQQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAECWxhbmRJbmRleAkAaQIFBnBpZWNlcwUFU1NJWkUEDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCBQhsYW5kSW5mbwULcmVjVGVycmFpbnMECWN1cnJlbnRXaAkBDGdldFdhcmVob3VzZQMFBXdoS2V5BQlsYW5kSW5kZXgFCmluZnJhTGV2ZWwEDGN1cnJlbnRXaFJlcwkAtQkCCQCRAwIFCWN1cnJlbnRXaAUId2hJZHhSZXMCAV8EB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBEUBleHRyTmF0aXZlKDEwNTUpAQUHdGltZUtleQQJZGVsdGFUaW1lCQBlAgkBCWZpbmFsVGltZQAFCXNhdmVkVGltZQMJAGYCAAAFCWRlbHRhVGltZQkAAgEJAKwCAgkArAICCQCsAgICJlNhdmVkIHRpbWVzdGFtcCBpcyBpbiBmdXR1cmUsIHNhdmVkID0gCQCkAwEFCXNhdmVkVGltZQIKLCBmaW5hbCA9IAkApAMBCQEJZmluYWxUaW1lAAQWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkBDGFwcGx5Qm9udXNlcwIFC2xhbmRBc3NldElkBQZwaWVjZXMEDXJlc0FmdGVyQ2xhaW0JAQ92aXJ0Q2xhaW1BZGRSZXMFBQxjdXJyZW50V2hSZXMFDXRlcnJhaW5Db3VudHMFCWRlbHRhVGltZQUJbGFuZEluZGV4BRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBAlhcnRQaWVjZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQULbGFuZEFzc2V0SWQAAAQPYWNyZXNGcm9tUGllY2VzCQBkAgkAaAIFBnBpZWNlcwUFTVVMVDgJAGkCCQBoAgkAZAIJAGgCBQZwaWVjZXMFCmluZnJhTGV2ZWwFCWFydFBpZWNlcwUFTVVMVDgABQQMYWNyZXNGcm9tUmVzCQBoAgkAawMIBQ1yZXNBZnRlckNsYWltAl8yBRBSRVNPVVJDRVBSSUNFTUlOBQVNVUxUOAUVVVNEVDJBQ1JFU19NVUxUSVBMSUVSCgEGc3VtTWF0AgNhY2MEaXRlbQkAZAIFA2FjYwkBDXBhcnNlSW50VmFsdWUBBQRpdGVtBAV3aE1hdAoAAiRsCQC1CQIJAJEDAgUJY3VycmVudFdoBQh3aElkeE1hdAIBXwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAAAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGc3VtTWF0AgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGBAxhY3Jlc0Zyb21NYXQJAGgCCQBrAwUFd2hNYXQJAGgCAAIFEFJFU09VUkNFUFJJQ0VNSU4FBU1VTFQ4BRVVU0RUMkFDUkVTX01VTFRJUExJRVIEBXByb2RzAwkAAAIJAJEDAgUJY3VycmVudFdoBQl3aElkeFByb2QCAAUDbmlsCQC8CQIJAJEDAgUJY3VycmVudFdoBQl3aElkeFByb2QCAV8KAQdzdW1Qcm9kAgNhY2MEaXRlbQQBaggFA2FjYwJfMgQLcmVjaXBlQ29lZmYJAQ1wYXJzZUludFZhbHVlAQkAkQMCCQC1CQIJAJEDAgUQcHJvZHVjdGlvbk1hdHJpeAUBagIBXwUJcklkeENvZWZmCQCUCgIJAGQCCAUDYWNjAl8xCQBoAgkAaAIJAQ1wYXJzZUludFZhbHVlAQUEaXRlbQULcmVjaXBlQ29lZmYFBU1VTFQ2CQBkAgUBagABBAZ3aFByb2QKAAIkbAUFcHJvZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCUCgIAAAAACgEFJGYxXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdzdW1Qcm9kAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYxXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAyNAkBBSRmMV8yAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgkBBSRmMV8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAQNYWNyZXNGcm9tUHJvZAkAaAIJAGsDCAUGd2hQcm9kAl8xCQBoAgACBRBSRVNPVVJDRVBSSUNFTUlOBQVNVUxUOAUVVVNEVDJBQ1JFU19NVUxUSVBMSUVSCQCWCgQFD2FjcmVzRnJvbVBpZWNlcwUMYWNyZXNGcm9tUmVzBQxhY3Jlc0Zyb21NYXQFDWFjcmVzRnJvbVByb2QBE3Vuc3Rha2VEdWNrSW50ZXJuYWwCBGFkZHILZHVja0Fzc2V0SWQEBWVxS2V5CQEQa2V5RHVja0VxdWlwbWVudAEFC2R1Y2tBc3NldElkBAtjdXJyZW50U2VncwkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFBWVxS2V5AhcsOyxfLDssXyw7LF8sOyxfLDssXyw7LAIBXwQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkECXRlbXBQcm9kQgkBBmRyZXNzQgQFC2N1cnJlbnRTZWdzCQEOcHJvZFN0clRv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bmlsAWkBC3NhdmVJbnRlZ2VyAgNrZXkGYW1vdW50AwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIgc2F2ZUludGVnZXIgaXMgbm90IHB1YmxpYyBtZXRob2QJAMwIAgkBDEludGVnZXJFbnRyeQIFA2tleQUGYW1vdW50BQNuaWwBaQEKc2V0QmxvY2tlZAEJaXNCbG9ja2VkAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQprZXlCbG9ja2VkAAUJaXNCbG9ja2VkBQNuaWwBaQETdW5zdGFrZUxhbmRDYWxsYmFjawILbGFuZEFzc2V0SWQEYWRkcgMJAQIhPQIJAKUIAQgFAWkGY2FsbGVyBRBhY3JlczJBZGRyZXNzU3RyCQACAQIRUGVybWlzc2lvbiBkZW5pZWQEDXVuc3Rha2VSZXN1bHQJARN1bnN0YWtlTGFuZEludGVybmFsAgUEYWRkcgULbGFuZEFzc2V0SWQECXdsZ1Jlc3VsdAkA/AcEBQt3bGdDb250cmFjdAISb25TdGFrZVVuc3Rha2VMYW5kCQDMCAIFBGFkZHIJAMwIAgcFA25pbAUDbmlsCQCUCgIJAMwIAgkBBEJ1cm4CCQDZBAEFC2xhbmRBc3NldElkAAEJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgFC2xhbmRBc3NldElkBQRhZGRyBQNuaWwJAJcKBQgFDXVuc3Rha2VSZXN1bHQCXzEIBQ11bnN0YWtlUmVzdWx0Al8yCAUNdW5zdGFrZVJlc3VsdAJfMwgFDXVuc3Rha2VSZXN1bHQCXzQFCXdsZ1Jlc3VsdAFpARN1bnN0YWtlTGFuZFJFQURPTkxZAgtsYW5kQXNzZXRJZARhZGRyBA11bnN0YWtlUmVzdWx0CQETdW5zdGFrZUxhbmRJbnRlcm5hbAIFBGFkZHIFC2xhbmRBc3NldElkCQCUCgIFA25pbAUNdW5zdGFrZVJlc3VsdAFpARx1bnN0YWtlTGFuZHNGaW5hbGl6ZUNhbGxiYWNrAQRhZGRyAwkBAiE9AgkApQgBCAUBaQZjYWxsZXIFEGFjcmVzMkFkZHJlc3NTdHIJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAkAlAoCCQDMCAIJAQtEZWxldGVFbnRyeQEJARVrZXlTdGFrZWRMYW5kc0J5T3duZXIBBQRhZGRyCQDMCAIJAQtEZWxldGVFbnRyeQEJARZrZXlTdGFrZWRQaWVjZXNCeU93bmVyAQUEYWRkcgUDbmlsAAABaQEUY29udmVydFVuc3Rha2VkTGFuZHMAAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAAEB2Fzc2V0SWQJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAQHYWRkcmVzcwkApQgBCAUBaQZjYWxsZXIDCQECIT0CCAUDcG10BmFtb3VudAABCQACAQkArAICCQCsAgICBE5GVCAFCkxBTkRQUkVGSVgCJCB0b2tlbiBzaG91bGQgYmUgYXR0YWNoZWQgYXMgcGF5bWVudAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAMJAQIhPQIIBQVhc3NldAZpc3N1ZXIFBHRoaXMJAAIBAhdVbmtub3duIGlzc3VlciBvZiB0b2tlbgMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkxBTkRQUkVGSVgJAAIBCQCsAgIJAKwCAgIJT25seSBORlQgBQpMQU5EUFJFRklYAhQgdG9rZW5zIGFyZSBhY2NlcHRlZAQLbGFuZEFzc2V0SWQJANgEAQUHYXNzZXRJZAQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8EBnBpZWNlcwkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAgUBZAULcmVjTGFuZFNpemUECmluZnJhTGV2ZWwJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAAABAlhcnRQaWVjZXMJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQULbGFuZEFzc2V0SWQAAAQLYWNyZXNBbW91bnQJAGQCCQBoAgUGcGllY2VzBQVNVUxUOAkAaQIJAGgCCQBkAgkAaAIFBnBpZWNlcwUKaW5mcmFMZXZlbAUJYXJ0UGllY2VzBQVNVUxUOAAFBANyZXEJAPwHBAUNYWNyZXNDb250cmFjdAIUcmVxdWVzdEFjcmVzQ2FsbGJhY2sJAMwIAgULYWNyZXNBbW91bnQFA25pbAUDbmlsAwkAAAIFA3JlcQUDcmVxBAVjYWxsYgkA/AcECQERQGV4dHJOYXRpdmUoMTA2MikBBRBhY3JlczJBZGRyZXNzU3RyAhJzdGFrZUFjcmVzQ2FsbGJhY2sJAMwIAgUHYWRkcmVzcwUDbmlsCQDMCAIJAQ9BdHRhY2hlZFBheW1lbnQCBQxhY3Jlc0Fzc2V0SWQFC2FjcmVzQW1vdW50BQNuaWwDCQAAAgUFY2FsbGIFBWNhbGxiCQCUCgIJAMwIAgkBBEJ1cm4CCQDZBAEFC2xhbmRBc3NldElkAAEFA25pbAAACQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuAWkBE3Vuc3Rha2VEdWNrQ2FsbGJhY2sCC2R1Y2tBc3NldElkBGFkZHIDCQECIT0CCQClCAEIBQFpBmNhbGxlcgUQYWNyZXMyQWRkcmVzc1N0cgkAAgECEVBlcm1pc3Npb24gZGVuaWVkBA11bnN0YWtlUmVzdWx0CQETdW5zdGFrZUR1Y2tJbnRlcm5hbAIFBGFkZHIFC2R1Y2tBc3NldElkCQCUCgIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUEYWRkcgABCQDZBAEFC2R1Y2tBc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULZHVja0Fzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBEGtleUR1Y2tJZFRvT3duZXIBBQtkdWNrQXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkRVQ0tQUkVGSVgFC2R1Y2tBc3NldElkBQRhZGRyCQDMCAIJAQtEZWxldGVFbnRyeQEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHIFA25pbAUNdW5zdGFrZVJlc3VsdAFpARN1bnN0YWtlRHVja1JFQURPTkxZAgtkdWNrQXNzZXRJZARhZGRyBA11bnN0YWtlUmVzdWx0CQETdW5zdGFrZUR1Y2tJbnRlcm5hbAIFBGFkZHIFC2R1Y2tBc3NldElkCQCUCgIFA25pbAUNdW5zdGFrZVJlc3VsdAFpAQhjbGFpbVJlcwIGYW1vdW50DmxhbmRBc3NldElkU3RyBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQGcmVzdWx0CQEQY2xhaW1SZXNJbnRlcm5hbAQFBGFkZHIFBmFtb3VudAUNY2xhaW1Nb2RlRHVjawUObGFuZEFzc2V0SWRTdHIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAkAlAoCCQDOCAIJAM0IAgkAzQgCCQDOCAIIBQZyZXN1bHQCXzEICQEXdXBkYXRlRHVja1N0YXRzSW50ZXJuYWwCBQtkdWNrQXNzZXRJZAkAawMFB3hwQ2xhaW0FBmFtb3VudAUFTVVMVDgCXzEJAQtTdHJpbmdFbnRyeQIIBQZyZXN1bHQCXzIJALkJAggFBnJlc3VsdAJfMwIBOgkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfNAkAuQkCCAUGcmVzdWx0Al81AgE6BQ1wcm9sb2dBY3Rpb25zCQCRAwIIBQZyZXN1bHQCXzMFCGJwSWR4UmVzAWkBDGNsYWltUmVzVG9XSAIGYW1vdW50DmxhbmRBc3NldElkU3RyBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQGcmVzdWx0CQEQY2xhaW1SZXNJbnRlcm5hbAQFBGFkZHIFBmFtb3VudAULY2xhaW1Nb2RlV2gFDmxhbmRBc3NldElkU3RyCQCUCgIJAM4IAgkAzQgCCQDNCAIJAM4IAggFBnJlc3VsdAJfMQgJARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgUEYWRkcgkAawMFB3hwQ2xhaW0FBmFtb3VudAUFTVVMVDgCXzEJAQtTdHJpbmdFbnRyeQIIBQZyZXN1bHQCXzIJALkJAggFBnJlc3VsdAJfMwIBOgkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfNAkAuQkCCAUGcmVzdWx0Al81AgE6BQ1wcm9sb2dBY3Rpb25zCQCRAwIIBQZyZXN1bHQCXzUFCHdoSWR4UmVzAWkBDnVwZGF0ZUJhY2twYWNrAgtkdWNrQXNzZXRJZAduZXdQYWNrAwkBAiE9AggFAWkGY2FsbGVyBQ9lY29ub215Q29udHJhY3QJAAIBAhFwZXJtaXNzaW9uIGRlbmllZAkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBQduZXdQYWNrBQNuaWwFB25ld1BhY2sBaQEPY29tbWl0Rm9yUmFuZG9tAAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkEC2ZpbmlzaEJsb2NrCQBkAgUGaGVpZ2h0BQtyYW5kb21EZWxheQQEYWRkcgkApQgBCAUBaQZjYWxsZXIJAJQKAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEJa2V5Q29tbWl0AQUEYWRkcgULZmluaXNoQmxvY2sFA25pbAUNcHJvbG9nQWN0aW9ucwULZmluaXNoQmxvY2sBaQEMcmV2ZWFsUmFuZG9tAQhtYXhWYWx1ZQQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAlmaW5pc2hLZXkJAQlrZXlDb21taXQBBQRhZGRyBAtmaW5pc2hCbG9jawkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFCWZpbmlzaEtleQIkWW91IGhhdmUgdG8gY29tbWl0Rm9yUmFuZG9tKCkgZmlyc3QhAwkAZgIFC2ZpbmlzaEJsb2NrBQZoZWlnaHQJAAIBCQCsAgICNFJhbmRvbSBudW1iZXIgaXMgbm90IHJlYWR5IHlldCwgd2FpdCB1bnRpbCBoZWlnaHQgPSAJAKQDAQULZmluaXNoQmxvY2sEB2VudHJvcHkJAQV2YWx1ZQEICQEFdmFsdWUBCQDtBwEFC2ZpbmlzaEJsb2NrA3ZyZgQEc2FsdAkAmwMBCQELdmFsdWVPckVsc2UCCQCiCAEJARVrZXlMYXN0V2Vla1R4SWRCeVVzZXIBBQRhZGRyAgAEBHJhbmQJAQ9nZXRSYW5kb21OdW1iZXIDBQhtYXhWYWx1ZQUEc2FsdAUHZW50cm9weQkAlAoCCQDOCAIJAMwIAgkBC0RlbGV0ZUVudHJ5AQUJZmluaXNoS2V5BQNuaWwFDXByb2xvZ0FjdGlvbnMFBHJhbmQBaQEQYWN0aXZhdGVBcnRpZmFjdAIHYXJ0TmFtZQ5sYW5kQXNzZXRJZE9wdAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQEYWRkcgkApQgBCAUBaQZjYWxsZXIEBnJlc3VsdAQHJG1hdGNoMAUHYXJ0TmFtZQMJAAACAgdQUkVTQUxFBQckbWF0Y2gwCQESYWN0aXZhdGVQcmVzYWxlQXJ0AgUEYWRkcgUObGFuZEFzc2V0SWRPcHQDCQAAAgIHT05CT0FSRAUHJG1hdGNoMAkBEmFjdGl2YXRlT25ib2FyZEFydAEFBGFkZHIJAAIBAhBVbmtub3duIGFydGlmYWN0CQDOCAIFBnJlc3VsdAUNcHJvbG9nQWN0aW9ucwFpAQ1zYXZlV2FyZWhvdXNlAgV3aFN0cgtsYW5kQXNzZXRJZAMJAQIhPQIIBQFpBmNhbGxlcgUPZWNvbm9teUNvbnRyYWN0CQACAQINQWNjZXNzIGRlbmllZAQFd2hLZXkJARJrZXlXYXJlaG91c2VCeUxhbmQBBQtsYW5kQXNzZXRJZAQCd2gJALwJAgUFd2hTdHICAToDCQECIT0CCQCQAwEFAndoAAUJAAIBAjB3YXJlaG91c2Ugc3RyaW5nIHNob3VsZCBjb250YWluIDQgJzonIHNlcGFyYXRvcnMEBWxvZnRMCQCRAwIJALUJAgkAkQMCBQJ3aAUJd2hJZHhMT0ZUAgFfBQl2b2xMb2NrZWQEBWxvZnRPCQEXZ2V0V2FyZWhvdXNlT2NjdXBpZWRWb2wBBQJ3aAQFbG9mdFQJARdnZXRXYXJlaG91c2VUb3RhbFZvbHVtZQEJAJEDAgUCd2gFC3doSWR4TGV2ZWxzBAVsb2Z0RgkAZQIJAGUCBQVsb2Z0VAkBDXBhcnNlSW50VmFsdWUBBQVsb2Z0TAUFbG9mdE8DCQBmAgAABQVsb2Z0RgkAAgECME9wZXJhdGlvbiBsZWFkcyB0byBuZWdhdGl2ZSBmcmVlIHdhcmVob3VzZSBzcGFjZQQIbmV3V2hTdHIJALoJAgkAzAgCCQCRAwIFAndoBQt3aElkeExldmVscwkAzAgCCQCRAwIFAndoBQh3aElkeFJlcwkAzAgCCQCRAwIFAndoBQh3aElkeE1hdAkAzAgCCQCRAwIFAndoBQl3aElkeFByb2QJAMwIAgkAuQkCCQDMCAIFBWxvZnRMCQDMCAIJAKQDAQUFbG9mdE8JAMwIAgkApAMBBQVsb2Z0RgkAzAgCCQCkAwEFBWxvZnRUBQNuaWwCAV8FA25pbAIBOgkAlAoCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBXdoS2V5BQhuZXdXaFN0cgUDbmlsBQhuZXdXaFN0cgFpAQ1zZXRDdXN0b21OYW1lAwdhc3NldElkCmN1c3RvbU5hbWUEdHlwZQQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIIBQNwbXQHYXNzZXRJZAULdXNkdEFzc2V0SWQJAAIBAhpBbGxvd2VkIFVTRFQgcGF5bWVudCBvbmx5IQMJAQIhPQIIBQNwbXQGYW1vdW50BQxSRU5BTUlOR0NPU1QJAAIBCQCsAgICElBheW1lbnQgc2hvdWxkIGJlIAkApAMBBQxSRU5BTUlOR0NPU1QDCQEIY29udGFpbnMCBQpjdXN0b21OYW1lAgJfXwkAAgEJAKwCAgIeTmFtZSBzaG91bGQgbm90IGNvbnRhaW4gJ19fJzogBQpjdXN0b21OYW1lAwkAZgIJALECAQUKY3VzdG9tTmFtZQUKTUFYTkFNRUxFTgkAAgEJAKwCAgIZTmFtZSB0b28gbG9uZywgbWF4TGVuZ3RoPQkApAMBBQpNQVhOQU1FTEVOBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQHYWN0aW9ucwQHJG1hdGNoMAUEdHlwZQMJAAACAgdBQ0NPVU5UBQckbWF0Y2gwBApyZXZlcnNlS2V5CQEWa2V5Q3VzdG9tTmFtZVRvQWRkcmVzcwEFCmN1c3RvbU5hbWUECW5hbWVPd25lcgkAoggBBQpyZXZlcnNlS2V5AwkBCWlzRGVmaW5lZAEFCW5hbWVPd25lcgkAAgEJAKwCAgIZTmFtZSBhbHJlYWR5IHJlZ2lzdGVyZWQ6IAUKY3VzdG9tTmFtZQQNYWRkclRvTmFtZUtleQkBFmtleUFkZHJlc3NUb0N1c3RvbU5hbWUBBQRhZGRyBAdvbGROYW1lCQCiCAEFDWFkZHJUb05hbWVLZXkEB2ZyZWVPbGQDCQEJaXNEZWZpbmVkAQUHb2xkTmFtZQkAzAgCCQELRGVsZXRlRW50cnkBCQEWa2V5Q3VzdG9tTmFtZVRvQWRkcmVzcwEJAQV2YWx1ZQEFB29sZE5hbWUFA25pbAUDbmlsCQDOCAIJAM0IAgkAzQgCBQdmcmVlT2xkCQELU3RyaW5nRW50cnkCBQ1hZGRyVG9OYW1lS2V5BQpjdXN0b21OYW1lCQELU3RyaW5nRW50cnkCBQpyZXZlcnNlS2V5BQRhZGRyCAkBFnVwZGF0ZUFjY1N0YXRzSW50ZXJuYWwCBQRhZGRyBQx4cEN1c3RvbU5hbWUCXzEDCQAAAgIETEFORAUHJG1hdGNoMAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQdhc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFB2Fzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQUHYXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUEYWRkcgkAAgEJAKwCAgUKTEFORFBSRUZJWAINIGlzIG5vdCB5b3VycwQKcmV2ZXJzZUtleQkBGmtleUxhbmRDdXN0b21OYW1lVG9Bc3NldElkAQUKY3VzdG9tTmFtZQQJbmFtZU93bmVyCQCiCAEFCnJldmVyc2VLZXkDCQEJaXNEZWZpbmVkAQUJbmFtZU93bmVyCQACAQkArAICAhlOYW1lIGFscmVhZHkgcmVnaXN0ZXJlZDogBQpjdXN0b21OYW1lBA5hc3NldFRvTmFtZUtleQkBGmtleUxhbmRBc3NldElkVG9DdXN0b21OYW1lAQUHYXNzZXRJZAQHb2xkTmFtZQkAoggBBQ5hc3NldFRvTmFtZUtleQQHZnJlZU9sZAMJAQlpc0RlZmluZWQBBQdvbGROYW1lCQDMCAIJAQtEZWxldGVFbnRyeQEJARprZXlMYW5kQ3VzdG9tTmFtZVRvQXNzZXRJZAEJAQV2YWx1ZQEFB29sZE5hbWUFA25pbAUDbmlsCQDOCAIJAM0IAgkAzQgCBQdmcmVlT2xkCQELU3RyaW5nRW50cnkCBQ5hc3NldFRvTmFtZUtleQUKY3VzdG9tTmFtZQkBC1N0cmluZ0VudHJ5AgUKcmV2ZXJzZUtleQUHYXNzZXRJZAgJARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgUEYWRkcgUMeHBDdXN0b21OYW1lAl8xAwkAAAICBERVQ0sFByRtYXRjaDAEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQUHYXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQdhc3NldElkAwMJAQEhAQkBCWlzRGVmaW5lZAEJAJ8IAQUHdGltZUtleQYJAQEhAQkBCWlzRGVmaW5lZAEJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgkAAgEJAKwCAggFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARBrZXlEdWNrSWRUb093bmVyAQUHYXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUEYWRkcgkAAgEJAKwCAgUKRFVDS1BSRUZJWAINIGlzIG5vdCB5b3VycwQKcmV2ZXJzZUtleQkBGmtleUR1Y2tDdXN0b21OYW1lVG9Bc3NldElkAQUKY3VzdG9tTmFtZQQJbmFtZU93bmVyCQCiCAEFCnJldmVyc2VLZXkDCQEJaXNEZWZpbmVkAQUJbmFtZU93bmVyCQACAQkArAICAhlOYW1lIGFscmVhZHkgcmVnaXN0ZXJlZDogBQpjdXN0b21OYW1lBA5hc3NldFRvTmFtZUtleQkBGmtleUR1Y2tBc3NldElkVG9DdXN0b21OYW1lAQUHYXNzZXRJZAQHb2xkTmFtZQkAoggBBQ5hc3NldFRvTmFtZUtleQQHZnJlZU9sZAMJAQlpc0RlZmluZWQBBQdvbGROYW1lCQDMCAIJAQtEZWxldGVFbnRyeQEJARprZXlEdWNrQ3VzdG9tTmFtZVRvQXNzZXRJZAEJAQV2YWx1ZQEFB29sZE5hbWUFA25pbAUDbmlsCQDOCAIJAM0IAgkAzQgCBQdmcmVlT2xkCQELU3RyaW5nRW50cnkCBQ5hc3NldFRvTmFtZUtleQUKY3VzdG9tTmFtZQkBC1N0cmluZ0VudHJ5AgUKcmV2ZXJzZUtleQUHYXNzZXRJZAgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFB2Fzc2V0SWQFDHhwQ3VzdG9tTmFtZQJfMQkAAgECE1Vua25vd24gZW50aXR5IHR5cGUJAJQKAgkAzggCCQDNCAIFB2FjdGlvbnMJAQ5TY3JpcHRUcmFuc2ZlcgMFD2Vjb25vbXlDb250cmFjdAgFA3BtdAZhbW91bnQFC3VzZHRBc3NldElkBQ1wcm9sb2dBY3Rpb25zAAABaQEMc2V0UmVmZXJyYWxzAglvbGRQbGF5ZXIJbmV3UGxheWVyAwkBAiE9AggFAWkPY2FsbGVyUHVibGljS2V5BQNwdWIJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAMJAQEhAQkBCWlzRGVmaW5lZAEJAKYIAQUJb2xkUGxheWVyCQACAQkArAICAhFJbnZhbGlkIGFkZHJlc3M6IAUJb2xkUGxheWVyBApuZXdiaWVBZGRyCQCmCAEFCW5ld1BsYXllcgMJAQEhAQkBCWlzRGVmaW5lZAEFCm5ld2JpZUFkZHIJAAIBCQCsAgICEUludmFsaWQgYWRkcmVzczogBQluZXdQbGF5ZXIECW9sZExhc3RUeAkAoggBCQEVa2V5TGFzdFdlZWtUeElkQnlVc2VyAQUJb2xkUGxheWVyAwkBASEBCQEJaXNEZWZpbmVkAQUJb2xkTGFzdFR4CQACAQIib2xkUGxheWVyIGRpZG4ndCBkbyBhbnkgdHggaW4gZ2FtZQMJAGcCAAAICQDvBwEJAQV2YWx1ZQEFCm5ld2JpZUFkZHIJYXZhaWxhYmxlCQACAQIWbmV3UGxheWVyIGhhcyBubyBXQVZFUwQHb2xkc0tleQkBCWtleU9sZGllcwAEBG9sZHMJAKIIAQUHb2xkc0tleQQGb2xkaWVzAwkBCWlzRGVmaW5lZAEFBG9sZHMJALwJAgkBBXZhbHVlAQUEb2xkcwIBXwUDbmlsAwkBD2NvbnRhaW5zRWxlbWVudAIFBm9sZGllcwUJbmV3UGxheWVyCQACAQkArAICBQluZXdQbGF5ZXICJiBpcyBub3QgbmV3YmllIChhbHJlYWR5IGhhcyByZWZlcnJhbHMpBAhyZWZCeUtleQkBD2tleUFkZHJlc3NSZWZCeQEFCW5ld1BsYXllcgQFcmVmQnkJAKIIAQUIcmVmQnlLZXkDAwkBCWlzRGVmaW5lZAEFBXJlZkJ5CQEJaXNEZWZpbmVkAQkApggBCQEFdmFsdWUBBQVyZWZCeQcJAAIBCQCsAgIJAKwCAgUJbmV3UGxheWVyAhQgYWxyZWFkeSBoYXMgcmVmQnk6IAkBBXZhbHVlAQUFcmVmQnkEB3JlZnNLZXkJARNrZXlBZGRyZXNzUmVmZXJyYWxzAQUJb2xkUGxheWVyBARyZWZzCQCiCAEFB3JlZnNLZXkECXJlZnNBcnJheQMJAQlpc0RlZmluZWQBBQRyZWZzCQC8CQIJAQV2YWx1ZQEFBHJlZnMCAV8FA25pbAMJAQ9jb250YWluc0VsZW1lbnQCBQlyZWZzQXJyYXkFCW5ld1BsYXllcgkAAgEJAKwCAgkArAICCQCsAgIFCW9sZFBsYXllcgISIGFscmVhZHkgY29udGFpbnMgBQluZXdQbGF5ZXICESB3aXRoaW4gcmVmZXJyYWxzBAduZXdSZWZzCQC6CQIJAM0IAgUJcmVmc0FycmF5BQluZXdQbGF5ZXICAV8EB25ld09sZHMDCQEPY29udGFpbnNFbGVtZW50AgUGb2xkaWVzBQlvbGRQbGF5ZXIJAQV2YWx1ZQEFBG9sZHMJALoJAgkAzQgCBQZvbGRpZXMFCW9sZFBsYXllcgIBXwkAlAoCCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUIcmVmQnlLZXkFCW9sZFBsYXllcgkAzAgCCQELU3RyaW5nRW50cnkCBQdyZWZzS2V5BQduZXdSZWZzCQDMCAIJAQtTdHJpbmdFbnRyeQIFB29sZHNLZXkFB25ld09sZHMFA25pbAUNcHJvbG9nQWN0aW9ucwAAAWkBEGRpc3RyaWJ1dGVQb2ludHMFCHN0cmVuZ3RoCGFjY3VyYWN5CWludGVsbGVjdAllbmR1cmFuY2UJZGV4dGVyaXR5BA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQLdmlydFdsZ0RhdGEJAQlhc0FueUxpc3QBCQD8BwQFC3dsZ0NvbnRyYWN0AhJjaGVja1dsZ1hwUkVBRE9OTFkJAMwIAgUEYWRkcgUDbmlsBQNuaWwEDXZpcnRXbGdQb2ludHMJAQVhc0ludAEJAJEDAgULdmlydFdsZ0RhdGEAAQQPJHQwMTAwNDk2MTAwODg2AwkAZwIAAAUNdmlydFdsZ1BvaW50cwkAlAoCAAAFA25pbAQHZGVsdGFYUAkBBWFzSW50AQkA/AcEBQt3bGdDb250cmFjdAIJdGFrZVdsZ1hwCQDMCAIFBGFkZHIFA25pbAUDbmlsAwkAAAIFB2RlbHRhWFAFB2RlbHRhWFAJAJQKAgUNdmlydFdsZ1BvaW50cwkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDGtleVVzZXJMZXZlbAEFBGFkZHIJAQVhc0ludAEJAJEDAgULdmlydFdsZ0RhdGEAAAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBCWtleVVzZXJYUAEFBGFkZHIJAQVhc0ludAEJAJEDAgULdmlydFdsZ0RhdGEAAgUDbmlsCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuBAl3bGdQb2ludHMIBQ8kdDAxMDA0OTYxMDA4ODYCXzEECndsZ0FjdGlvbnMIBQ8kdDAxMDA0OTYxMDA4ODYCXzIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQKZnJlZUtleUFjYwkBEWtleVVzZXJGcmVlUG9pbnRzAQUEYWRkcgQNZnJlZVBvaW50c0FjYwkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUKZnJlZUtleUFjYwAABQl3bGdQb2ludHMEC2ZyZWVLZXlEdWNrCQERa2V5RHVja0ZyZWVQb2ludHMBBQtkdWNrQXNzZXRJZAQOZnJlZVBvaW50c0R1Y2sJAQt2YWx1ZU9yRWxzZQIJAJ8IAQULZnJlZUtleUR1Y2sAAAQHc3VtRnJlZQkAZAIFDWZyZWVQb2ludHNBY2MFDmZyZWVQb2ludHNEdWNrBA9zdW1Ub0Rpc3RyaWJ1dGUJAGQCCQBkAgkAZAIJAGQCBQhzdHJlbmd0aAUIYWNjdXJhY3kFCWludGVsbGVjdAUJZW5kdXJhbmNlBQlkZXh0ZXJpdHkDCQBmAgUPc3VtVG9EaXN0cmlidXRlBQdzdW1GcmVlCQACAQkArAICCQCsAgICD1RoZXJlIGFyZSBvbmx5IAkApAMBBQdzdW1GcmVlAhogZnJlZSBwb2ludHMgdG8gZGlzdHJpYnV0ZQQIY2hhcnNLZXkJAQxrZXlEdWNrQ2hhcnMBBQtkdWNrQXNzZXRJZAQFY2hhcnMJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQhjaGFyc0tleQIJMF8wXzBfMF8wAgFfBAZuZXdBY2MJAGUCBQ1mcmVlUG9pbnRzQWNjBQ9zdW1Ub0Rpc3RyaWJ1dGUJAJQKAgkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFCmZyZWVLZXlBY2MDCQBmAgAABQZuZXdBY2MAAAUGbmV3QWNjCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQtmcmVlS2V5RHVjawMJAGYCAAAFBm5ld0FjYwkAZAIFDmZyZWVQb2ludHNEdWNrBQZuZXdBY2MFDmZyZWVQb2ludHNEdWNrCQDMCAIJAQtTdHJpbmdFbnRyeQIFCGNoYXJzS2V5CQC5CQIJAMwIAgkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWNoYXJzBQxjaGFyU3RyZW5ndGgFCHN0cmVuZ3RoCQDMCAIJAKQDAQkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVjaGFycwUMY2hhckFjY3VyYWN5BQhhY2N1cmFjeQkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJJbnRlbGxlY3QFCWludGVsbGVjdAkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJFbmR1cmFuY2UFCWVuZHVyYW5jZQkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJEZXh0ZXJpdHkFCWRleHRlcml0eQUDbmlsAgFfBQNuaWwFDXByb2xvZ0FjdGlvbnMFCndsZ0FjdGlvbnMAAAFpARxzcGxpdEJ5R2xvYmFsV2VpZ2h0c1JFQURPTkxZAQZhbW91bnQJAJQKAgUDbmlsCQESZ2V0TmVlZGVkTWF0ZXJpYWxzAQUGYW1vdW50AWkBJHNwbGl0QnlHbG9iYWxBbmRMb2NhbFdlaWdodHNSRUFET05MWQMJbWF0QW1vdW50CXJlc0Ftb3VudAh0ZXJyYWlucwQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBBQh0ZXJyYWlucwkAlAoCBQNuaWwJAJQKAgkBEmdldE5lZWRlZE1hdGVyaWFscwEFCW1hdEFtb3VudAkBE2Rpc3RyaWJ1dGVCeVdlaWdodHMCBQlyZXNBbW91bnQFDXRlcnJhaW5Db3VudHMBaQETZ2V0QmFja3BhY2tSRUFET05MWQELZHVja0Fzc2V0SWQJAJQKAgUDbmlsCQC5CQIJAQtnZXRCYWNrcGFjawEJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkAgE6AWkBFGdldFdhcmVob3VzZVJFQURPTkxZAQtsYW5kQXNzZXRJZAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQJbGFuZEluZGV4CQBpAgkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAgkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8FC3JlY0xhbmRTaXplBQVTU0laRQQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAJAJQKAgUDbmlsCQC6CQIJAQxnZXRXYXJlaG91c2UDCQESa2V5V2FyZWhvdXNlQnlMYW5kAQULbGFuZEFzc2V0SWQFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAIBOgFpAQpzYXZlTGFzdFR4AAMJAQEhAQkBD2NvbnRhaW5zRWxlbWVudAIJAMwIAgULd2xnQ29udHJhY3QJAMwIAgUPZWNvbm9teUNvbnRyYWN0CQDMCAIFEnRvdXJuYW1lbnRDb250cmFjdAkAzAgCBQ1hY3Jlc0NvbnRyYWN0BQNuaWwIBQFpBmNhbGxlcgkAAgECDUFjY2VzcyBkZW5pZWQJAJQKAgkBBnByb2xvZwEFAWkAKgFpAQ91cGRhdGVEdWNrU3RhdHMCC2R1Y2tBc3NldElkB2RlbHRhWFADCQECIT0CCAUBaQZjYWxsZXIFD2Vjb25vbXlDb250cmFjdAkAAgECDUFjY2VzcyBkZW5pZWQJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkBQdkZWx0YVhQAWkBDnVwZGF0ZUFjY1N0YXRzAgRhZGRyB2RlbHRhWFADCQEBIQEJAQ9jb250YWluc0VsZW1lbnQCCQDMCAIFC3dsZ0NvbnRyYWN0CQDMCAIFD2Vjb25vbXlDb250cmFjdAkAzAgCBQ1hY3Jlc0NvbnRyYWN0BQNuaWwIBQFpBmNhbGxlcgkAAgECDUFjY2VzcyBkZW5pZWQJARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgUEYWRkcgUHZGVsdGFYUAFpARNpbml0RHVja1RvdXJBdHRlbXB0AQtkdWNrQXNzZXRJZAMJAQIhPQIIBQFpBmNhbGxlcgUSdG91cm5hbWVudENvbnRyYWN0CQACAQINQWNjZXNzIGRlbmllZAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAVtYXhIUAkBCW1heEhlYWx0aAEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBDGtleUR1Y2tMZXZlbAEFC2R1Y2tBc3NldElkAAAECWN1ckhlYWx0aAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgFBW1heEhQBAljdXJMb2NLZXkJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQUJY3VyTG9jS2V5BQ9ERUZBVUxUTE9DQVRJT04EBmxhc3RJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBRJ0b3VybmFtZW50Q29udHJhY3QFDWxhc3RUb3VySWRLZXkAAAQMdG91ckxvY2F0aW9uCQCsAgIJAKQDAQUGbGFzdElkAgRfVF8wCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ5rZXlTYXZlZEhlYWx0aAEFC2R1Y2tBc3NldElkBQljdXJIZWFsdGgJAMwIAgkBDEludGVnZXJFbnRyeQIFCWtleUhlYWx0aAUFbWF4SFAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEGtleVNhdmVkTG9jYXRpb24BBQtkdWNrQXNzZXRJZAULY3VyTG9jYXRpb24JAMwIAgkBC1N0cmluZ0VudHJ5AgUJY3VyTG9jS2V5BQx0b3VyTG9jYXRpb24FA25pbAUMdG91ckxvY2F0aW9uAWkBDGJyZWFrQXR0ZW1wdAAEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEJAKUIAQgFAWkGY2FsbGVyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAljdXJMb2NLZXkJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQUJY3VyTG9jS2V5BQ9ERUZBVUxUTE9DQVRJT04DCQECIT0CCQCRAwIJALUJAgULY3VyTG9jYXRpb24CAV8FCmxvY0lkeFR5cGUCAVQJAAIBAiJZb3VyIGR1Y2sgaXMgbm90IGluIHRoZSB0b3VybmFtZW50BAtzYXZlZEhlYWx0aAkBEUBleHRyTmF0aXZlKDEwNTUpAQkBDmtleVNhdmVkSGVhbHRoAQULZHVja0Fzc2V0SWQEDXNhdmVkTG9jYXRpb24JARFAZXh0ck5hdGl2ZSgxMDU4KQEJARBrZXlTYXZlZExvY2F0aW9uAQULZHVja0Fzc2V0SWQJAJQKAgkAzQgCCQDNCAIFDXByb2xvZ0FjdGlvbnMJAQxJbnRlZ2VyRW50cnkCCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBQtzYXZlZEhlYWx0aAkBC1N0cmluZ0VudHJ5AgUJY3VyTG9jS2V5BQ1zYXZlZExvY2F0aW9uBQtjdXJMb2NhdGlvbgFpARRicmVha0F0dGVtcHRDYWxsYmFjawADCQECIT0CCAUBaQZjYWxsZXIFEnRvdXJuYW1lbnRDb250cmFjdAkAAgECDUFjY2VzcyBkZW5pZWQEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQxvcmlnaW5DYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAkBEUBleHRyTmF0aXZlKDEwNTUpAQkBDmtleVNhdmVkSGVhbHRoAQULZHVja0Fzc2V0SWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEQa2V5U2F2ZWRMb2NhdGlvbgEFC2R1Y2tBc3NldElkBQNuaWwCFGJyZWFrQXR0ZW1wdENhbGxiYWNrAWkBFmV4aXRUb3VybmFtZW50SW50ZXJuYWwBC2R1Y2tBc3NldElkAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQINQWNjZXNzIGRlbmllZAQLc2F2ZWRIZWFsdGgJARFAZXh0ck5hdGl2ZSgxMDU1KQEJAQ5rZXlTYXZlZEhlYWx0aAEFC2R1Y2tBc3NldElkBA1zYXZlZExvY2F0aW9uCQERQGV4dHJOYXRpdmUoMTA1OCkBCQEQa2V5U2F2ZWRMb2NhdGlvbgEFC2R1Y2tBc3NldElkCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQFC3NhdmVkSGVhbHRoCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUNc2F2ZWRMb2NhdGlvbgUDbmlsBwFpAQ9wcm9jZXNzRGVsaXZlcnkBC2R1Y2tBc3NldElkAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQINQWNjZXNzIGRlbmllZAQEYWRkcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIECWZ1bmRUb3RhbAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ9lY29ub215Q29udHJhY3QFD2RlbGl2ZXJ5RnVuZEtleQAAAwkAZgIFFU1JTl9VU0RUX0ZFRV9ERUxJVkVSWQUJZnVuZFRvdGFsCQACAQkArAICAiBEZWxpdmVyeSBpcyBub3QgYXZhaWxhYmxlLCBmdW5kPQkBCmZpeGVkUG9pbnQCBQlmdW5kVG90YWwABgQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQIY291bnRLZXkJARRrZXlVc2VyRGVsaXZlcnlDb3VudAEFBGFkZHIEB2xhc3REYXkJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBFmtleVVzZXJMYXN0RGVsaXZlcnlEYXkBBQRhZGRyAAAEBXRvZGF5CQBpAgUDbm93BQlEQVlNSUxMSVMEBWNvdW50AwkAAAIFB2xhc3REYXkFBXRvZGF5CQELdmFsdWVPckVsc2UCCQCfCAEFCGNvdW50S2V5AAAAAAQFYWNyZXMJAQt2YWx1ZU9yRWxzZQIJAJoIAgUNYWNyZXNDb250cmFjdAkBGmtleUFjcmVzU3Rha2VkQW1vdW50QnlVc2VyAQUEYWRkcgAABBFhbGxvd2VkRGVsaXZlcmllcwkAZAIFF0FMTE9XRURfRlJFRV9ERUxJVkVSSUVTCQBpAgUFYWNyZXMFGkFDUkVTX0ZPUl9ERUxJVkVSWV9BVFRFTVBUAwkAZwIFBWNvdW50BRFhbGxvd2VkRGVsaXZlcmllcwkAAgEJAKwCAgkArAICAhFZb3UgYWxyZWFkeSB1c2VkIAkApAMBBRFhbGxvd2VkRGVsaXZlcmllcwIcIGRlbGl2ZXJ5IGF0dGVtcHRzIGZvciB0b2RheQQOZ2xvYmFsQ291bnRLZXkJARRrZXlEdWNrRGVsaXZlcnlDb3VudAEFC2R1Y2tBc3NldElkBAZyZXdhcmQJAPwHBAUPZWNvbm9teUNvbnRyYWN0AhJzZW5kRGVsaXZlcnlSZXdhcmQJAMwIAgUEYWRkcgUDbmlsBQNuaWwJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUIY291bnRLZXkJAGQCBQVjb3VudAABCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5VXNlckxhc3REZWxpdmVyeURheQEFBGFkZHIFBXRvZGF5CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQ5nbG9iYWxDb3VudEtleQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUOZ2xvYmFsQ291bnRLZXkAAAABBQNuaWwFBnJld2FyZABVFx5g", "height": 3398924, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 45MEatBMriNwvV7iNPWMo7VUycqPKfiHjaKbtTSUcxg6 Next: HfjbSr62YuaABLXhYCboL3J4yoEZPcv71YumgwbGieoT Diff:
Old | New | Differences | |
---|---|---|---|
4 | 4 | let KS_SEPARATE_PUBLIC_KEY = false | |
5 | 5 | ||
6 | 6 | let KS_ALLOW_ROBO_DUCKS = false | |
7 | - | ||
8 | - | let DAY_MILLIS = 86400000 | |
9 | 7 | ||
10 | 8 | let OLD_STAKING_DEADLINE = 1733248800000 | |
11 | 9 | ||
49 | 47 | else throw("Unknown chain") | |
50 | 48 | } | |
51 | 49 | ||
52 | - | let arbitrageDelay = match chain { | |
53 | - | case _ => | |
54 | - | if ((base58'2W' == $match0)) | |
55 | - | then DAY_MILLIS | |
56 | - | else if ((base58'2T' == $match0)) | |
57 | - | then 60000 | |
58 | - | else throw("Unknown chain") | |
59 | - | } | |
60 | - | ||
61 | 50 | let SEP = "__" | |
62 | 51 | ||
63 | 52 | let MULT6 = 1000000 | |
80 | 69 | ||
81 | 70 | ||
82 | 71 | let IdxCfgEconomyDapp = 2 | |
83 | - | ||
84 | - | let IdxCfgGovernanceDapp = 3 | |
85 | 72 | ||
86 | 73 | let IdxCfgWlgDapp = 4 | |
87 | 74 | ||
107 | 94 | ||
108 | 95 | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
109 | 96 | ||
110 | - | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
111 | - | ||
112 | 97 | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
113 | 98 | ||
114 | 99 | let tournamentContract = getContractAddressOrFail(restCfg, IdxCfgTournamentDapp) | |
121 | 106 | ||
122 | 107 | let recTerrains = 2 | |
123 | 108 | ||
124 | - | let recContinent = 3 | |
125 | - | ||
126 | 109 | let acresAssetIdKey = "acresAssetId" | |
127 | 110 | ||
128 | 111 | let acresAssetId = valueOrErrorMessage(getBinary(acresContract, acresAssetIdKey), "ACRES is not issued yet") | |
133 | 116 | ||
134 | 117 | ||
135 | 118 | func keyResProportions () = "resTypesProportions" | |
136 | - | ||
137 | - | ||
138 | - | func keyResTypesByContinent (continent) = ("resTypesByContinent_" + continent) | |
139 | 119 | ||
140 | 120 | ||
141 | 121 | func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr) | |
213 | 193 | let ARTPRESALE = "PRESALE" | |
214 | 194 | ||
215 | 195 | let NUMRES = 6 | |
216 | - | ||
217 | - | let MAX_LANDS_STAKED_BY_USER = 25 | |
218 | 196 | ||
219 | 197 | let DAILYRESBYPIECE = 3456000 | |
220 | 198 | ||
325 | 303 | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
326 | 304 | ||
327 | 305 | ||
328 | - | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
329 | - | ||
330 | - | ||
331 | 306 | let deliveryFundKey = "deliveryFund" | |
332 | 307 | ||
333 | 308 | let lastTourIdKey = "%s__lastTourId" | |
420 | 395 | ||
421 | 396 | let DAYMILLIS = 86400000 | |
422 | 397 | ||
423 | - | func keyLastWlgTradeTimeByUser (addr) = ("lastArbTimeUser_" + addr) | |
424 | - | ||
425 | - | ||
426 | 398 | func keyAcresStakedAmountByUser (addr) = ("acresStakedAmountByUser_" + addr) | |
427 | 399 | ||
428 | 400 | ||
433 | 405 | let PRESALENUMLANDS = 500 | |
434 | 406 | ||
435 | 407 | func keyLandCustomNameToAssetId (name) = ("lcn_" + name) | |
436 | - | ||
437 | - | ||
438 | - | func keyInfraLevelByAssetIdAndOwner (assetId,ownerAddr) = ((("ilao_" + assetId) + "_") + ownerAddr) | |
439 | - | ||
440 | - | ||
441 | - | func keyLandNumToOwner (landNum) = ("lo_" + landNum) | |
442 | 408 | ||
443 | 409 | ||
444 | 410 | func keyDuckCustomNameToAssetId (name) = ("duckByCustomName_" + name) | |
696 | 662 | else throw("List size exceeds 6") | |
697 | 663 | ||
698 | 664 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6))._2 | |
699 | - | } | |
700 | - | ||
701 | - | ||
702 | - | func updateProportionsInternal (propList,terrainCounts,landSizeIndex,sign) = if ((size(propList) != NUMRES)) | |
703 | - | then throw("Wrong proportions data") | |
704 | - | else { | |
705 | - | func updater (acc,i) = { | |
706 | - | let result = (parseIntValue(propList[i]) + ((sign * terrainCounts[i]) * landSizeIndex)) | |
707 | - | if ((0 > result)) | |
708 | - | then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex))) | |
709 | - | else (acc :+ toString(result)) | |
710 | - | } | |
711 | - | ||
712 | - | let $l = ITER6 | |
713 | - | let $s = size($l) | |
714 | - | let $acc0 = nil | |
715 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
716 | - | then $a | |
717 | - | else updater($a, $l[$i]) | |
718 | - | ||
719 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
720 | - | then $a | |
721 | - | else throw("List size exceeds 6") | |
722 | - | ||
723 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
724 | - | } | |
725 | - | ||
726 | - | ||
727 | - | func updateProportions (terrainCounts,landSizeIndex,sign) = { | |
728 | - | let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_") | |
729 | - | makeString(updateProportionsInternal(propList, terrainCounts, landSizeIndex, sign), "_") | |
730 | 665 | } | |
731 | 666 | ||
732 | 667 | ||
1268 | 1203 | ||
1269 | 1204 | ||
1270 | 1205 | @Callable(i) | |
1271 | - | func stakeLand () = { | |
1272 | - | let prologActions = prolog(i) | |
1273 | - | if ((size(i.payments) != 1)) | |
1274 | - | then throw("Exactly one payment required") | |
1275 | - | else { | |
1276 | - | let pmt = value(i.payments[0]) | |
1277 | - | let assetId = value(pmt.assetId) | |
1278 | - | let address = toString(i.caller) | |
1279 | - | if ((pmt.amount != 1)) | |
1280 | - | then throw((("NFT " + LANDPREFIX) + " token should be attached as payment")) | |
1281 | - | else { | |
1282 | - | let asset = value(assetInfo(assetId)) | |
1283 | - | if ((asset.issuer != this)) | |
1284 | - | then throw("Unknown issuer of token") | |
1285 | - | else if (!(contains(asset.name, LANDPREFIX))) | |
1286 | - | then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted")) | |
1287 | - | else { | |
1288 | - | let landNumSize = drop(asset.name, 4) | |
1289 | - | let landNum = if (contains(landNumSize, "XXL")) | |
1290 | - | then dropRight(landNumSize, 3) | |
1291 | - | else if (contains(landNumSize, "XL")) | |
1292 | - | then dropRight(landNumSize, 2) | |
1293 | - | else dropRight(landNumSize, 1) | |
1294 | - | if (!(isDefined(parseInt(landNum)))) | |
1295 | - | then throw(("Cannot parse land number from " + asset.name)) | |
1296 | - | else { | |
1297 | - | let landAssetId = toBase58String(assetId) | |
1298 | - | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1299 | - | if (isDefined(getInteger(timeKey))) | |
1300 | - | then throw((("NFT " + asset.name) + " is already staked")) | |
1301 | - | else { | |
1302 | - | let d = split(asset.description, "_") | |
1303 | - | let terrainCounts = countTerrains(d[recTerrains]) | |
1304 | - | let pieces = numPiecesBySize(d[recLandSize]) | |
1305 | - | let landIndex = (pieces / SSIZE) | |
1306 | - | let props = updateProportions(terrainCounts, landIndex, 1) | |
1307 | - | let resByContKey = keyResTypesByContinent(d[recContinent]) | |
1308 | - | let contProps = split(valueOrElse(getString(resByContKey), "0_0_0_0_0_0"), "_") | |
1309 | - | let updatedContProps = makeString(updateProportionsInternal(contProps, terrainCounts, landIndex, 1), "_") | |
1310 | - | let landsKey = keyStakedLandsByOwner(address) | |
1311 | - | let landsStr = getString(landsKey) | |
1312 | - | let lands = if (isDefined(landsStr)) | |
1313 | - | then split_51C(value(landsStr), "_") | |
1314 | - | else nil | |
1315 | - | if (containsElement(lands, landAssetId)) | |
1316 | - | then throw(("Your staked lands already contain " + landAssetId)) | |
1317 | - | else if ((size(lands) >= MAX_LANDS_STAKED_BY_USER)) | |
1318 | - | then throw((("Your already staked max (" + toString(MAX_LANDS_STAKED_BY_USER)) + ") lands")) | |
1319 | - | else { | |
1320 | - | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1321 | - | let piecesKey = keyStakedPiecesByOwner(address) | |
1322 | - | let oldPieces = valueOrElse(getInteger(piecesKey), 0) | |
1323 | - | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [address], nil) | |
1324 | - | $Tuple2(([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(landsKey, makeString_11C((lands :+ landAssetId), "_")), IntegerEntry(piecesKey, (oldPieces + pieces)), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), IntegerEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, address), infraLevel), StringEntry(keyResProportions(), props), StringEntry(resByContKey, updatedContProps)] ++ prologActions), wlgResult) | |
1325 | - | } | |
1326 | - | } | |
1327 | - | } | |
1328 | - | } | |
1329 | - | } | |
1330 | - | } | |
1331 | - | } | |
1332 | - | ||
1333 | - | ||
1334 | - | ||
1335 | - | @Callable(i) | |
1336 | - | func unstakeLand (landAssetIdIn) = { | |
1337 | - | let prologActions = prolog(i) | |
1338 | - | if ((size(i.payments) != 0)) | |
1339 | - | then throw("No payments required") | |
1340 | - | else { | |
1341 | - | let addr = toString(i.caller) | |
1342 | - | let c = checkClaimConditions(addr, claimModeDuck, landAssetIdIn) | |
1343 | - | let landAssetId = c._2 | |
1344 | - | let d = c._3 | |
1345 | - | let landsKey = keyStakedLandsByOwner(addr) | |
1346 | - | let terrainCounts = countTerrains(d[recTerrains]) | |
1347 | - | let pieces = numPiecesBySize(d[recLandSize]) | |
1348 | - | let landIndex = (pieces / SSIZE) | |
1349 | - | let props = updateProportions(terrainCounts, landIndex, -1) | |
1350 | - | let resByContKey = keyResTypesByContinent(d[recContinent]) | |
1351 | - | let contProps = split(valueOrElse(getString(resByContKey), "0_0_0_0_0_0"), "_") | |
1352 | - | let updatedContProps = makeString(updateProportionsInternal(contProps, terrainCounts, landIndex, -1), "_") | |
1353 | - | let claimResult = claimAll(addr, landAssetId, pieces, claimModeDuck) | |
1354 | - | let lands = split_51C(valueOrElse(getString(landsKey), ""), "_") | |
1355 | - | let idx = indexOf(lands, landAssetId) | |
1356 | - | if (!(isDefined(idx))) | |
1357 | - | then throw(("Your staked lands don't contain " + landAssetId)) | |
1358 | - | else { | |
1359 | - | let now = lastBlock.timestamp | |
1360 | - | let govReleaseTime = valueOrElse(getInteger(govContract, keyUserGwlReleaseTime(addr)), 0) | |
1361 | - | if ((govReleaseTime >= now)) | |
1362 | - | then throw(("Your gWL are taking part in voting, cannot unstake until " + toString(govReleaseTime))) | |
1363 | - | else { | |
1364 | - | let arbReleaseTime = (valueOrElse(getInteger(wlgContract, keyLastWlgTradeTimeByUser(addr)), 0) + arbitrageDelay) | |
1365 | - | if ((arbReleaseTime > now)) | |
1366 | - | then throw(("Your staked lands took part in arbitrage, cannot unstake until " + toString(arbReleaseTime))) | |
1367 | - | else { | |
1368 | - | let piecesKey = keyStakedPiecesByOwner(addr) | |
1369 | - | let stakedPieces = valueOrElse(getInteger(piecesKey), 0) | |
1370 | - | let newPieces = if ((pieces > stakedPieces)) | |
1371 | - | then 0 | |
1372 | - | else (stakedPieces - pieces) | |
1373 | - | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [addr], nil) | |
1374 | - | $Tuple2(([ScriptTransfer(i.caller, 1, fromBase58String(landAssetId)), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr)), StringEntry(keyResProportions(), props), StringEntry(resByContKey, updatedContProps), StringEntry(claimResult._2, makeString(claimResult._3, ":")), if ((size(lands) > 1)) | |
1375 | - | then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_")) | |
1376 | - | else DeleteEntry(landsKey), IntegerEntry(piecesKey, newPieces)] ++ prologActions), wlgResult) | |
1377 | - | } | |
1378 | - | } | |
1379 | - | } | |
1380 | - | } | |
1381 | - | } | |
1382 | - | ||
1383 | - | ||
1384 | - | ||
1385 | - | @Callable(i) | |
1386 | 1206 | func unstakeLandCallback (landAssetId,addr) = if ((toString(i.caller) != acres2AddressStr)) | |
1387 | 1207 | then throw("Permission denied") | |
1388 | 1208 | else { | |
1389 | 1209 | let unstakeResult = unstakeLandInternal(addr, landAssetId) | |
1390 | - | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [addr], nil) | |
1210 | + | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [addr, false], nil) | |
1391 | 1211 | $Tuple2([Burn(fromBase58String(landAssetId), 1), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr))], $Tuple5(unstakeResult._1, unstakeResult._2, unstakeResult._3, unstakeResult._4, wlgResult)) | |
1392 | 1212 | } | |
1393 | 1213 | ||
1736 | 1556 | let addr = toString(i.originCaller) | |
1737 | 1557 | let virtWlgData = asAnyList(invoke(wlgContract, "checkWlgXpREADONLY", [addr], nil)) | |
1738 | 1558 | let virtWlgPoints = asInt(virtWlgData[1]) | |
1739 | - | let $ | |
1559 | + | let $t0100496100886 = if ((0 >= virtWlgPoints)) | |
1740 | 1560 | then $Tuple2(0, nil) | |
1741 | 1561 | else { | |
1742 | 1562 | let deltaXP = asInt(invoke(wlgContract, "takeWlgXp", [addr], nil)) | |
1744 | 1564 | then $Tuple2(virtWlgPoints, [IntegerEntry(keyUserLevel(addr), asInt(virtWlgData[0])), IntegerEntry(keyUserXP(addr), asInt(virtWlgData[2]))]) | |
1745 | 1565 | else throw("Strict value is not equal to itself.") | |
1746 | 1566 | } | |
1747 | - | let wlgPoints = $ | |
1748 | - | let wlgActions = $ | |
1567 | + | let wlgPoints = $t0100496100886._1 | |
1568 | + | let wlgActions = $t0100496100886._2 | |
1749 | 1569 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1750 | 1570 | let freeKeyAcc = keyUserFreePoints(addr) | |
1751 | 1571 | let freePointsAcc = (valueOrElse(getInteger(freeKeyAcc), 0) + wlgPoints) |
Old | New | Differences | |
---|---|---|---|
1 | 1 | {-# STDLIB_VERSION 6 #-} | |
2 | 2 | {-# SCRIPT_TYPE ACCOUNT #-} | |
3 | 3 | {-# CONTENT_TYPE DAPP #-} | |
4 | 4 | let KS_SEPARATE_PUBLIC_KEY = false | |
5 | 5 | ||
6 | 6 | let KS_ALLOW_ROBO_DUCKS = false | |
7 | - | ||
8 | - | let DAY_MILLIS = 86400000 | |
9 | 7 | ||
10 | 8 | let OLD_STAKING_DEADLINE = 1733248800000 | |
11 | 9 | ||
12 | 10 | let chain = take(drop(this.bytes, 1), 1) | |
13 | 11 | ||
14 | 12 | let pub = match chain { | |
15 | 13 | case _ => | |
16 | 14 | if ((base58'2W' == $match0)) | |
17 | 15 | then if (KS_SEPARATE_PUBLIC_KEY) | |
18 | 16 | then base58'CWsMtTZC5BjjoL4Q1ayW4Wwb1ehGACQB6DrKyPgotKfm' | |
19 | 17 | else base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD' | |
20 | 18 | else if ((base58'2T' == $match0)) | |
21 | 19 | then base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD' | |
22 | 20 | else throw("Unknown chain") | |
23 | 21 | } | |
24 | 22 | ||
25 | 23 | let usdtAssetId = match chain { | |
26 | 24 | case _ => | |
27 | 25 | if ((base58'2W' == $match0)) | |
28 | 26 | then base58'9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi' | |
29 | 27 | else if ((base58'2T' == $match0)) | |
30 | 28 | then base58'6mWwf9mZBjVgkC54idpyaZLQfAosD914wT8fGf2iiY63' | |
31 | 29 | else throw("Unknown chain") | |
32 | 30 | } | |
33 | 31 | ||
34 | 32 | let defaultRestAddressStr = match chain { | |
35 | 33 | case _ => | |
36 | 34 | if ((base58'2W' == $match0)) | |
37 | 35 | then "3PQCuvFbvh4LkPUnrnU1z3jnbA1p9m3WNhv" | |
38 | 36 | else if ((base58'2T' == $match0)) | |
39 | 37 | then "3MumkGGztCKAXpWDqxkddofqXSUbqQkvSJy" | |
40 | 38 | else throw("Unknown chain") | |
41 | 39 | } | |
42 | 40 | ||
43 | 41 | let acres2AddressStr = match chain { | |
44 | 42 | case _ => | |
45 | 43 | if ((base58'2W' == $match0)) | |
46 | 44 | then "3P4UH3T9nXpMNpUmSmQjPmEz3G85t3zn6eA" | |
47 | 45 | else if ((base58'2T' == $match0)) | |
48 | 46 | then "3NBPx1Fciu3JQNEGZ21jSnTdutLNGGBUSXh" | |
49 | 47 | else throw("Unknown chain") | |
50 | 48 | } | |
51 | 49 | ||
52 | - | let arbitrageDelay = match chain { | |
53 | - | case _ => | |
54 | - | if ((base58'2W' == $match0)) | |
55 | - | then DAY_MILLIS | |
56 | - | else if ((base58'2T' == $match0)) | |
57 | - | then 60000 | |
58 | - | else throw("Unknown chain") | |
59 | - | } | |
60 | - | ||
61 | 50 | let SEP = "__" | |
62 | 51 | ||
63 | 52 | let MULT6 = 1000000 | |
64 | 53 | ||
65 | 54 | let MULT8 = 100000000 | |
66 | 55 | ||
67 | 56 | let SSIZE = 25 | |
68 | 57 | ||
69 | 58 | let MSIZE = 100 | |
70 | 59 | ||
71 | 60 | let LSIZE = 225 | |
72 | 61 | ||
73 | 62 | let XLSIZE = 400 | |
74 | 63 | ||
75 | 64 | let XXLSIZE = 625 | |
76 | 65 | ||
77 | 66 | let ITER6 = [0, 1, 2, 3, 4, 5] | |
78 | 67 | ||
79 | 68 | func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], "")) | |
80 | 69 | ||
81 | 70 | ||
82 | 71 | let IdxCfgEconomyDapp = 2 | |
83 | - | ||
84 | - | let IdxCfgGovernanceDapp = 3 | |
85 | 72 | ||
86 | 73 | let IdxCfgWlgDapp = 4 | |
87 | 74 | ||
88 | 75 | let IdxCfgTournamentDapp = 7 | |
89 | 76 | ||
90 | 77 | let IdxCfgAcresDapp = 8 | |
91 | 78 | ||
92 | 79 | func keyRestCfg () = "%s__restConfig" | |
93 | 80 | ||
94 | 81 | ||
95 | 82 | func keyRestAddress () = "%s__restAddr" | |
96 | 83 | ||
97 | 84 | ||
98 | 85 | func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP) | |
99 | 86 | ||
100 | 87 | ||
101 | 88 | func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx))) | |
102 | 89 | ||
103 | 90 | ||
104 | 91 | let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr)) | |
105 | 92 | ||
106 | 93 | let restCfg = readRestCfgOrFail(restContract) | |
107 | 94 | ||
108 | 95 | let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp) | |
109 | 96 | ||
110 | - | let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp) | |
111 | - | ||
112 | 97 | let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp) | |
113 | 98 | ||
114 | 99 | let tournamentContract = getContractAddressOrFail(restCfg, IdxCfgTournamentDapp) | |
115 | 100 | ||
116 | 101 | let acresContract = getContractAddressOrFail(restCfg, IdxCfgAcresDapp) | |
117 | 102 | ||
118 | 103 | let recLandNum = 0 | |
119 | 104 | ||
120 | 105 | let recLandSize = 1 | |
121 | 106 | ||
122 | 107 | let recTerrains = 2 | |
123 | 108 | ||
124 | - | let recContinent = 3 | |
125 | - | ||
126 | 109 | let acresAssetIdKey = "acresAssetId" | |
127 | 110 | ||
128 | 111 | let acresAssetId = valueOrErrorMessage(getBinary(acresContract, acresAssetIdKey), "ACRES is not issued yet") | |
129 | 112 | ||
130 | 113 | let randomDelay = 2 | |
131 | 114 | ||
132 | 115 | func keyCommit (address) = ("finishBlockFor_" + address) | |
133 | 116 | ||
134 | 117 | ||
135 | 118 | func keyResProportions () = "resTypesProportions" | |
136 | - | ||
137 | - | ||
138 | - | func keyResTypesByContinent (continent) = ("resTypesByContinent_" + continent) | |
139 | 119 | ||
140 | 120 | ||
141 | 121 | func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr) | |
142 | 122 | ||
143 | 123 | ||
144 | 124 | func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr) | |
145 | 125 | ||
146 | 126 | ||
147 | 127 | func asInt (v) = match v { | |
148 | 128 | case n: Int => | |
149 | 129 | n | |
150 | 130 | case _ => | |
151 | 131 | throw("fail to cast into Int") | |
152 | 132 | } | |
153 | 133 | ||
154 | 134 | ||
155 | 135 | func asAnyList (v) = match v { | |
156 | 136 | case l: List[Any] => | |
157 | 137 | l | |
158 | 138 | case _ => | |
159 | 139 | throw("fail to cast into List[Any]") | |
160 | 140 | } | |
161 | 141 | ||
162 | 142 | ||
163 | 143 | func numPiecesBySize (landSize) = match landSize { | |
164 | 144 | case _ => | |
165 | 145 | if (("S" == $match0)) | |
166 | 146 | then SSIZE | |
167 | 147 | else if (("M" == $match0)) | |
168 | 148 | then MSIZE | |
169 | 149 | else if (("L" == $match0)) | |
170 | 150 | then LSIZE | |
171 | 151 | else if (("XL" == $match0)) | |
172 | 152 | then XLSIZE | |
173 | 153 | else if (("XXL" == $match0)) | |
174 | 154 | then XXLSIZE | |
175 | 155 | else throw("Unknown land size") | |
176 | 156 | } | |
177 | 157 | ||
178 | 158 | ||
179 | 159 | func keyBlocked () = "contractsBlocked" | |
180 | 160 | ||
181 | 161 | ||
182 | 162 | func keyLastWeekTxIdByUser (addr) = ("lastWeekTxIdByUser_" + addr) | |
183 | 163 | ||
184 | 164 | ||
185 | 165 | func keyCurWeekTxIdByUser (addr) = ("curWeekTxIdByUser_" + addr) | |
186 | 166 | ||
187 | 167 | ||
188 | 168 | func fixedPoint (val,decimals) = { | |
189 | 169 | let tenPow = pow(10, 0, decimals, 0, 0, DOWN) | |
190 | 170 | let lowPart = toString((val % tenPow)) | |
191 | 171 | let zeroes = drop(toString(tenPow), (1 + size(lowPart))) | |
192 | 172 | (((toString((val / tenPow)) + ".") + zeroes) + lowPart) | |
193 | 173 | } | |
194 | 174 | ||
195 | 175 | ||
196 | 176 | func getRandomNumber (maxValue,salt,entropy) = if ((0 >= maxValue)) | |
197 | 177 | then throw("maxValue should be > 0") | |
198 | 178 | else { | |
199 | 179 | let randomHash = sha256_16Kb((salt + entropy)) | |
200 | 180 | (toInt(randomHash) % maxValue) | |
201 | 181 | } | |
202 | 182 | ||
203 | 183 | ||
204 | 184 | func finalTime () = min([lastBlock.timestamp, OLD_STAKING_DEADLINE]) | |
205 | 185 | ||
206 | 186 | ||
207 | 187 | let LANDPREFIX = "LAND" | |
208 | 188 | ||
209 | 189 | let DUCKPREFIX = "DUCK" | |
210 | 190 | ||
211 | 191 | let ROBO_PREFIX = "ROBO" | |
212 | 192 | ||
213 | 193 | let ARTPRESALE = "PRESALE" | |
214 | 194 | ||
215 | 195 | let NUMRES = 6 | |
216 | - | ||
217 | - | let MAX_LANDS_STAKED_BY_USER = 25 | |
218 | 196 | ||
219 | 197 | let DAILYRESBYPIECE = 3456000 | |
220 | 198 | ||
221 | 199 | let WHMULTIPLIER = 10000000000 | |
222 | 200 | ||
223 | 201 | let DEFAULTLOCATION = "Africa_F_Africa" | |
224 | 202 | ||
225 | 203 | let RESOURCEPRICEMIN = 39637 | |
226 | 204 | ||
227 | 205 | let MIN_USDT_FEE_DELIVERY = 50000 | |
228 | 206 | ||
229 | 207 | let USDT2ACRES_MULTIPLIER = 10 | |
230 | 208 | ||
231 | 209 | let ALLOWED_FREE_DELIVERIES = 0 | |
232 | 210 | ||
233 | 211 | let ACRES_FOR_DELIVERY_ATTEMPT = 200000000 | |
234 | 212 | ||
235 | 213 | let prodTypes = ["First Aid Kit L1", "First Aid Kit L2", "First Aid Kit L3", "Backpack L1", "Backpack L2", "Backpack L3", "Food Ration L1", "Food Ration L2", "Food Ration L3", "Jet Pack L1", "Jet Pack L2", "Jet Pack L3", "Shield L1", "Shield L2", "Shield L3", "Mine L1", "Mine L2", "Mine L3", "Trap L1", "Trap L2", "Trap L3", "Boom-Dog L1", "Boom-Dog L2", "Boom-Dog L3"] | |
236 | 214 | ||
237 | 215 | let productionMatrix = ["8_8_8_17_17_42_12_0_30_0,0,0,0,0,0,0_", "8_8_8_17_17_42_24_0_60_0,0,5,2,0,0,0_", "8_8_8_17_17_42_36_0_120_0,0,10,4,0,0,0_", "8_19_19_8_27_19_26_1_20_0,0,0,0,0,0,0_001", "8_19_19_8_27_19_52_1_40_0,0,0,0,0,0,0_001", "8_19_19_8_27_19_78_1_80_0,0,0,0,0,0,0_001", "8_8_8_8_8_60_13_2_2_0,0,0,0,0,0,0_011", "8_8_8_8_8_60_26_2_4_0,0,0,0,0,0,0_011", "8_8_8_8_8_60_39_2_8_0,0,0,0,0,0,0_011", "30_30_3_17_17_3_30_3_30_0,0,0,0,0,0,0_111", "30_30_3_17_17_3_60_3_50_0,0,0,0,0,0,0_111", "30_30_3_17_17_3_90_3_70_0,0,0,0,0,0,0_111", "18_18_10_18_18_18_11_4_10_0,0,0,0,0,0,0_201", "18_18_10_18_18_18_22_4_20_0,0,0,0,0,0,0_201", "18_18_10_18_18_18_33_4_30_0,0,0,0,0,0,0_201", "4_13_22_4_35_22_23_0_50,1,0_0,0,0,0,0,0,0_", "4_13_22_4_35_22_46_0_50,1,1_0,2,5,0,0,0,0_", "4_13_22_4_35_22_69_0_50,2,1_0,5,10,0,0,0,0_", "5_25_40_5_10_15_20_1_30,1,1_0,0,0,0,0,0,0_", "5_25_40_5_10_15_40_1_30,1,2_2,1,3,0,0,0,0_", "5_25_40_5_10_15_60_1_30,1,3_5,2,8,0,0,0,0_", "23_23_5_20_23_6_35_2_100_0,0,0,0,0,0,0_", "23_23_5_20_23_6_70_2_150_0,0,0,0,0,0,0_", "23_23_5_20_23_6_105_2_200_0,0,0,0,0,0,0_"] | |
238 | 216 | ||
239 | 217 | let rIdxCoeff = 6 | |
240 | 218 | ||
241 | 219 | let rIdxRequirements = 9 | |
242 | 220 | ||
243 | 221 | let rIdxSlots = 10 | |
244 | 222 | ||
245 | 223 | let PRODUCTPKGSIZE = 10 | |
246 | 224 | ||
247 | 225 | let whIdxLevels = 0 | |
248 | 226 | ||
249 | 227 | let whIdxRes = 1 | |
250 | 228 | ||
251 | 229 | let whIdxMat = 2 | |
252 | 230 | ||
253 | 231 | let whIdxProd = 3 | |
254 | 232 | ||
255 | 233 | let whIdxLOFT = 4 | |
256 | 234 | ||
257 | 235 | let volLocked = 0 | |
258 | 236 | ||
259 | 237 | let volOccupied = 1 | |
260 | 238 | ||
261 | 239 | let volFree = 2 | |
262 | 240 | ||
263 | 241 | let volTotal = 3 | |
264 | 242 | ||
265 | 243 | let bpIdxLevel = 0 | |
266 | 244 | ||
267 | 245 | let bpIdxRes = 1 | |
268 | 246 | ||
269 | 247 | let bpIdxMat = 2 | |
270 | 248 | ||
271 | 249 | let bpIdxProd = 3 | |
272 | 250 | ||
273 | 251 | let locIdxType = 1 | |
274 | 252 | ||
275 | 253 | let locIdxId = 2 | |
276 | 254 | ||
277 | 255 | func keyLandAssetIdToOwner (assetId) = ("no_" + assetId) | |
278 | 256 | ||
279 | 257 | ||
280 | 258 | func keyLandAssetIdToCustomName (assetId) = ("lcna_" + assetId) | |
281 | 259 | ||
282 | 260 | ||
283 | 261 | func keyStakedTimeByAssetId (assetId) = ("st_" + assetId) | |
284 | 262 | ||
285 | 263 | ||
286 | 264 | func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["las", type, assetId], "_") | |
287 | 265 | ||
288 | 266 | ||
289 | 267 | func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("sttao_" + nftType) + "_") + assetId) + "_") + ownerAddr) | |
290 | 268 | ||
291 | 269 | ||
292 | 270 | func keyWarehouseByLand (landAssetId) = ("wh_" + landAssetId) | |
293 | 271 | ||
294 | 272 | ||
295 | 273 | func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId) | |
296 | 274 | ||
297 | 275 | ||
298 | 276 | func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId) | |
299 | 277 | ||
300 | 278 | ||
301 | 279 | func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr) | |
302 | 280 | ||
303 | 281 | ||
304 | 282 | func keyAddressRefBy (addr) = ("accRefBy_" + addr) | |
305 | 283 | ||
306 | 284 | ||
307 | 285 | func keyOnboardArtActivatedOnDuck (duckAssetId) = ("onboardArtActivatedOnDuck_" + duckAssetId) | |
308 | 286 | ||
309 | 287 | ||
310 | 288 | func keyOnboardArtDuckActivatedBy (addr) = ("onboardArtActivatedDuckBy_" + addr) | |
311 | 289 | ||
312 | 290 | ||
313 | 291 | func keyAddressReferrals (addr) = ("accReferrals_" + addr) | |
314 | 292 | ||
315 | 293 | ||
316 | 294 | func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId) | |
317 | 295 | ||
318 | 296 | ||
319 | 297 | func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr) | |
320 | 298 | ||
321 | 299 | ||
322 | 300 | func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId) | |
323 | 301 | ||
324 | 302 | ||
325 | 303 | func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId) | |
326 | 304 | ||
327 | 305 | ||
328 | - | func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr) | |
329 | - | ||
330 | - | ||
331 | 306 | let deliveryFundKey = "deliveryFund" | |
332 | 307 | ||
333 | 308 | let lastTourIdKey = "%s__lastTourId" | |
334 | 309 | ||
335 | 310 | let SCALE8 = 100000000 | |
336 | 311 | ||
337 | 312 | let xpLevelScale = 3200 | |
338 | 313 | ||
339 | 314 | let xpLevelRecipPow = 4000 | |
340 | 315 | ||
341 | 316 | let numPointsOnLevelUp = 3 | |
342 | 317 | ||
343 | 318 | let requirements = ["Strength", "Accuracy", "Intellect", "Endurance", "Dexterity", "Level", "Health"] | |
344 | 319 | ||
345 | 320 | let charStrength = 0 | |
346 | 321 | ||
347 | 322 | let charAccuracy = 1 | |
348 | 323 | ||
349 | 324 | let charIntellect = 2 | |
350 | 325 | ||
351 | 326 | let charEndurance = 3 | |
352 | 327 | ||
353 | 328 | let charDexterity = 4 | |
354 | 329 | ||
355 | 330 | let NUMMAINAUX = 2 | |
356 | 331 | ||
357 | 332 | let MAXSLOTS = 2 | |
358 | 333 | ||
359 | 334 | let MAXPRODINSLOT = 30 | |
360 | 335 | ||
361 | 336 | func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId) | |
362 | 337 | ||
363 | 338 | ||
364 | 339 | func keyDuckChars (duckAssetId) = ("duckChars_" + duckAssetId) | |
365 | 340 | ||
366 | 341 | ||
367 | 342 | func keyDuckXP (duckAssetId) = ("duckXP_" + duckAssetId) | |
368 | 343 | ||
369 | 344 | ||
370 | 345 | func keyDuckLevel (duckAssetId) = ("duckLevel_" + duckAssetId) | |
371 | 346 | ||
372 | 347 | ||
373 | 348 | func keyDuckFreePoints (duckAssetId) = ("duckFreePoints_" + duckAssetId) | |
374 | 349 | ||
375 | 350 | ||
376 | 351 | func keyDuckEquipment (duckAssetId) = ("duckEquipment_" + duckAssetId) | |
377 | 352 | ||
378 | 353 | ||
379 | 354 | func keyUserXP (addr) = ("userXP_" + addr) | |
380 | 355 | ||
381 | 356 | ||
382 | 357 | func keyUserLevel (addr) = ("userLevel_" + addr) | |
383 | 358 | ||
384 | 359 | ||
385 | 360 | func keyUserFreePoints (addr) = ("userFreePoints_" + addr) | |
386 | 361 | ||
387 | 362 | ||
388 | 363 | func keySavedHealth (duckAssetId) = ("savedHealth_" + duckAssetId) | |
389 | 364 | ||
390 | 365 | ||
391 | 366 | func keySavedLocation (duckAssetId) = ("savedLocation_" + duckAssetId) | |
392 | 367 | ||
393 | 368 | ||
394 | 369 | func keyDuckDeliveryCount (duckAssetId) = ("totalDeliveryCountByDuck_" + duckAssetId) | |
395 | 370 | ||
396 | 371 | ||
397 | 372 | func keyUserDeliveryCount (addr) = ("userDeliveryCount_" + addr) | |
398 | 373 | ||
399 | 374 | ||
400 | 375 | func keyUserLastDeliveryDay (addr) = ("userLastDeliveryDay_" + addr) | |
401 | 376 | ||
402 | 377 | ||
403 | 378 | let xpClaim = 10000 | |
404 | 379 | ||
405 | 380 | let xpCustomName = 1000000 | |
406 | 381 | ||
407 | 382 | let xpOnboard = 1000000 | |
408 | 383 | ||
409 | 384 | func levelByXP (xp) = fraction(xpLevelScale, pow(xp, 4, xpLevelRecipPow, 4, 4, DOWN), SCALE8) | |
410 | 385 | ||
411 | 386 | ||
412 | 387 | func maxHealth (level) = (100 + level) | |
413 | 388 | ||
414 | 389 | ||
415 | 390 | func levelUp (currLevel,newXP) = { | |
416 | 391 | let newLevel = levelByXP(newXP) | |
417 | 392 | [newLevel, (numPointsOnLevelUp * (newLevel - currLevel))] | |
418 | 393 | } | |
419 | 394 | ||
420 | 395 | ||
421 | 396 | let DAYMILLIS = 86400000 | |
422 | 397 | ||
423 | - | func keyLastWlgTradeTimeByUser (addr) = ("lastArbTimeUser_" + addr) | |
424 | - | ||
425 | - | ||
426 | 398 | func keyAcresStakedAmountByUser (addr) = ("acresStakedAmountByUser_" + addr) | |
427 | 399 | ||
428 | 400 | ||
429 | 401 | let RENAMINGCOST = 5000000 | |
430 | 402 | ||
431 | 403 | let MAXNAMELEN = 50 | |
432 | 404 | ||
433 | 405 | let PRESALENUMLANDS = 500 | |
434 | 406 | ||
435 | 407 | func keyLandCustomNameToAssetId (name) = ("lcn_" + name) | |
436 | - | ||
437 | - | ||
438 | - | func keyInfraLevelByAssetIdAndOwner (assetId,ownerAddr) = ((("ilao_" + assetId) + "_") + ownerAddr) | |
439 | - | ||
440 | - | ||
441 | - | func keyLandNumToOwner (landNum) = ("lo_" + landNum) | |
442 | 408 | ||
443 | 409 | ||
444 | 410 | func keyDuckCustomNameToAssetId (name) = ("duckByCustomName_" + name) | |
445 | 411 | ||
446 | 412 | ||
447 | 413 | func keyCustomNameToAddress (name) = ("accountByCustomName_" + name) | |
448 | 414 | ||
449 | 415 | ||
450 | 416 | func keyOldies () = "oldiesList" | |
451 | 417 | ||
452 | 418 | ||
453 | 419 | let claimModeWh = 0 | |
454 | 420 | ||
455 | 421 | let claimModeDuck = 1 | |
456 | 422 | ||
457 | 423 | let claimModeWhThenDuck = 2 | |
458 | 424 | ||
459 | 425 | func distributeByWeights (total,weights) = { | |
460 | 426 | let sum = (((((weights[0] + weights[1]) + weights[2]) + weights[3]) + weights[4]) + weights[5]) | |
461 | 427 | if ((0 >= sum)) | |
462 | 428 | then throw("Zero weights sum") | |
463 | 429 | else { | |
464 | 430 | let norm6 = fraction(total, MULT6, sum) | |
465 | 431 | func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6)) | |
466 | 432 | ||
467 | 433 | let $l = weights | |
468 | 434 | let $s = size($l) | |
469 | 435 | let $acc0 = nil | |
470 | 436 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
471 | 437 | then $a | |
472 | 438 | else normalizer($a, $l[$i]) | |
473 | 439 | ||
474 | 440 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
475 | 441 | then $a | |
476 | 442 | else throw("List size exceeds 6") | |
477 | 443 | ||
478 | 444 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
479 | 445 | } | |
480 | 446 | } | |
481 | 447 | ||
482 | 448 | ||
483 | 449 | func getNeededMaterials (total) = { | |
484 | 450 | let props = split(value(getString(keyResProportions())), "_") | |
485 | 451 | if ((size(props) != NUMRES)) | |
486 | 452 | then throw("Wrong proportions data") | |
487 | 453 | else { | |
488 | 454 | let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])] | |
489 | 455 | distributeByWeights(total, r) | |
490 | 456 | } | |
491 | 457 | } | |
492 | 458 | ||
493 | 459 | ||
494 | 460 | func prodStrToBytes (prodStr) = { | |
495 | 461 | let pList = if ((prodStr == "")) | |
496 | 462 | then nil | |
497 | 463 | else split_4C(prodStr, "_") | |
498 | 464 | func toBV (acc,recipe) = { | |
499 | 465 | let j = (size(acc) / 8) | |
500 | 466 | let curr = if ((size(pList) > j)) | |
501 | 467 | then parseIntValue(pList[j]) | |
502 | 468 | else 0 | |
503 | 469 | (acc + toBytes(curr)) | |
504 | 470 | } | |
505 | 471 | ||
506 | 472 | let $l = productionMatrix | |
507 | 473 | let $s = size($l) | |
508 | 474 | let $acc0 = base58'' | |
509 | 475 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
510 | 476 | then $a | |
511 | 477 | else toBV($a, $l[$i]) | |
512 | 478 | ||
513 | 479 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
514 | 480 | then $a | |
515 | 481 | else throw("List size exceeds 50") | |
516 | 482 | ||
517 | 483 | $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) | |
518 | 484 | } | |
519 | 485 | ||
520 | 486 | ||
521 | 487 | func bytesToProdStr (bv) = { | |
522 | 488 | func fromBV (acc,recipe) = { | |
523 | 489 | let j = size(acc) | |
524 | 490 | let b = take(drop(bv, (8 * j)), 8) | |
525 | 491 | (acc :+ toString(toInt(b))) | |
526 | 492 | } | |
527 | 493 | ||
528 | 494 | makeString_2C({ | |
529 | 495 | let $l = productionMatrix | |
530 | 496 | let $s = size($l) | |
531 | 497 | let $acc0 = nil | |
532 | 498 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
533 | 499 | then $a | |
534 | 500 | else fromBV($a, $l[$i]) | |
535 | 501 | ||
536 | 502 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
537 | 503 | then $a | |
538 | 504 | else throw("List size exceeds 50") | |
539 | 505 | ||
540 | 506 | $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) | |
541 | 507 | }, "_") | |
542 | 508 | } | |
543 | 509 | ||
544 | 510 | ||
545 | 511 | func checkStatRequirements (duckStats,reqs) = { | |
546 | 512 | func check (acc,j) = { | |
547 | 513 | let buff = if ((size(duckStats) > (7 + j))) | |
548 | 514 | then duckStats[(7 + j)] | |
549 | 515 | else 0 | |
550 | 516 | if ((parseIntValue(reqs[j]) > (duckStats[j] + buff))) | |
551 | 517 | then throw(("Requirement not satisfied: " + requirements[j])) | |
552 | 518 | else true | |
553 | 519 | } | |
554 | 520 | ||
555 | 521 | let $l = [0, 1, 2, 3, 4, 5, 6] | |
556 | 522 | let $s = size($l) | |
557 | 523 | let $acc0 = false | |
558 | 524 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
559 | 525 | then $a | |
560 | 526 | else check($a, $l[$i]) | |
561 | 527 | ||
562 | 528 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
563 | 529 | then $a | |
564 | 530 | else throw("List size exceeds 7") | |
565 | 531 | ||
566 | 532 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7) | |
567 | 533 | } | |
568 | 534 | ||
569 | 535 | ||
570 | 536 | func addProdB (idxCnt,pList,isPositive,segment,mainAux,slot,duckStats) = { | |
571 | 537 | let parts = split(idxCnt, ":") | |
572 | 538 | if ((size(parts) != 2)) | |
573 | 539 | then throw("Incorrect format, should be index:amount") | |
574 | 540 | else if (if (!(isPositive)) | |
575 | 541 | then (size(parts[0]) != 2) | |
576 | 542 | else false) | |
577 | 543 | then throw("Product idx should be 2 digits, zero padded") | |
578 | 544 | else { | |
579 | 545 | let productIdx = parseIntValue(parts[0]) | |
580 | 546 | let count = parseIntValue(parts[1]) | |
581 | 547 | if (if ((0 > productIdx)) | |
582 | 548 | then true | |
583 | 549 | else (productIdx >= size(productionMatrix))) | |
584 | 550 | then throw("Unknown product idx") | |
585 | 551 | else if ((0 > count)) | |
586 | 552 | then throw("Count can't be negative") | |
587 | 553 | else if ((count > MAXPRODINSLOT)) | |
588 | 554 | then throw(((("Can't put more than " + toString(MAXPRODINSLOT)) + " of ") + prodTypes[productIdx])) | |
589 | 555 | else if ((count == 0)) | |
590 | 556 | then $Tuple2(pList, false) | |
591 | 557 | else { | |
592 | 558 | let head = take(pList, (8 * productIdx)) | |
593 | 559 | let curr = toInt(take(drop(pList, (8 * productIdx)), 8)) | |
594 | 560 | let tail = drop(pList, (8 * (productIdx + 1))) | |
595 | 561 | let recipe = split(productionMatrix[productIdx], "_") | |
596 | 562 | if (if (!(isPositive)) | |
597 | 563 | then (count > curr) | |
598 | 564 | else false) | |
599 | 565 | then throw(((((("You have " + toString(curr)) + " of ") + prodTypes[productIdx]) + ", but tried to use ") + toString(count))) | |
600 | 566 | else { | |
601 | 567 | let isBigItem = if (if (!(isPositive)) | |
602 | 568 | then checkStatRequirements(duckStats, split(recipe[rIdxRequirements], ",")) | |
603 | 569 | else false) | |
604 | 570 | then { | |
605 | 571 | let compat = recipe[rIdxSlots] | |
606 | 572 | if ((compat == "")) | |
607 | 573 | then throw("Item cannot be equipped") | |
608 | 574 | else { | |
609 | 575 | let c = parseIntValue(compat) | |
610 | 576 | let cSeg = (c / 100) | |
611 | 577 | if ((segment != cSeg)) | |
612 | 578 | then throw("Segment incompatible") | |
613 | 579 | else { | |
614 | 580 | let cMainAux = ((c % 100) / 10) | |
615 | 581 | if ((mainAux != cMainAux)) | |
616 | 582 | then throw("Slot incompatible") | |
617 | 583 | else { | |
618 | 584 | let cNumSlots = (c % 10) | |
619 | 585 | if (if ((slot != 0)) | |
620 | 586 | then (cNumSlots > 1) | |
621 | 587 | else false) | |
622 | 588 | then throw("Big items should occupy slot 0") | |
623 | 589 | else (cNumSlots > 1) | |
624 | 590 | } | |
625 | 591 | } | |
626 | 592 | } | |
627 | 593 | } | |
628 | 594 | else false | |
629 | 595 | $Tuple2(((head + toBytes((curr + (if (isPositive) | |
630 | 596 | then count | |
631 | 597 | else -(count))))) + tail), isBigItem) | |
632 | 598 | } | |
633 | 599 | } | |
634 | 600 | } | |
635 | 601 | } | |
636 | 602 | ||
637 | 603 | ||
638 | 604 | func slotsGroupB (g,bpIn,isPositive,segment,mainAux,stats) = if ((g != "")) | |
639 | 605 | then { | |
640 | 606 | let slots = split(g, ",") | |
641 | 607 | if ((size(slots) > MAXSLOTS)) | |
642 | 608 | then throw("Wrong slots format") | |
643 | 609 | else { | |
644 | 610 | let s0 = slots[0] | |
645 | 611 | let s1 = if ((size(slots) > 1)) | |
646 | 612 | then slots[1] | |
647 | 613 | else "" | |
648 | 614 | if (if ((s0 == "")) | |
649 | 615 | then (s1 == "") | |
650 | 616 | else false) | |
651 | 617 | then bpIn | |
652 | 618 | else { | |
653 | 619 | let tmpS0 = if ((s0 != "")) | |
654 | 620 | then addProdB(s0, bpIn, isPositive, segment, mainAux, 0, stats) | |
655 | 621 | else $Tuple2(bpIn, false) | |
656 | 622 | if ((s1 != "")) | |
657 | 623 | then if (tmpS0._2) | |
658 | 624 | then throw("Big item already occupies slot") | |
659 | 625 | else addProdB(s1, tmpS0._1, isPositive, segment, mainAux, 1, stats)._1 | |
660 | 626 | else tmpS0._1 | |
661 | 627 | } | |
662 | 628 | } | |
663 | 629 | } | |
664 | 630 | else bpIn | |
665 | 631 | ||
666 | 632 | ||
667 | 633 | func dressB (segList,pBytes,isPositive,stats) = { | |
668 | 634 | func segment (acc,seg) = { | |
669 | 635 | let j = acc._1 | |
670 | 636 | let mainAux = split(seg, ";") | |
671 | 637 | if ((size(mainAux) != NUMMAINAUX)) | |
672 | 638 | then throw("Wrong segment format") | |
673 | 639 | else { | |
674 | 640 | let m = mainAux[0] | |
675 | 641 | let a = mainAux[1] | |
676 | 642 | if (if ((m == "")) | |
677 | 643 | then (a == "") | |
678 | 644 | else false) | |
679 | 645 | then $Tuple2((j + 1), acc._2) | |
680 | 646 | else { | |
681 | 647 | let tmpM = slotsGroupB(m, acc._2, isPositive, j, 0, stats) | |
682 | 648 | $Tuple2((j + 1), slotsGroupB(a, tmpM, isPositive, j, 1, stats)) | |
683 | 649 | } | |
684 | 650 | } | |
685 | 651 | } | |
686 | 652 | ||
687 | 653 | ( let $l = segList | |
688 | 654 | let $s = size($l) | |
689 | 655 | let $acc0 = $Tuple2(0, pBytes) | |
690 | 656 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
691 | 657 | then $a | |
692 | 658 | else segment($a, $l[$i]) | |
693 | 659 | ||
694 | 660 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
695 | 661 | then $a | |
696 | 662 | else throw("List size exceeds 6") | |
697 | 663 | ||
698 | 664 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6))._2 | |
699 | - | } | |
700 | - | ||
701 | - | ||
702 | - | func updateProportionsInternal (propList,terrainCounts,landSizeIndex,sign) = if ((size(propList) != NUMRES)) | |
703 | - | then throw("Wrong proportions data") | |
704 | - | else { | |
705 | - | func updater (acc,i) = { | |
706 | - | let result = (parseIntValue(propList[i]) + ((sign * terrainCounts[i]) * landSizeIndex)) | |
707 | - | if ((0 > result)) | |
708 | - | then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex))) | |
709 | - | else (acc :+ toString(result)) | |
710 | - | } | |
711 | - | ||
712 | - | let $l = ITER6 | |
713 | - | let $s = size($l) | |
714 | - | let $acc0 = nil | |
715 | - | func $f0_1 ($a,$i) = if (($i >= $s)) | |
716 | - | then $a | |
717 | - | else updater($a, $l[$i]) | |
718 | - | ||
719 | - | func $f0_2 ($a,$i) = if (($i >= $s)) | |
720 | - | then $a | |
721 | - | else throw("List size exceeds 6") | |
722 | - | ||
723 | - | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
724 | - | } | |
725 | - | ||
726 | - | ||
727 | - | func updateProportions (terrainCounts,landSizeIndex,sign) = { | |
728 | - | let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_") | |
729 | - | makeString(updateProportionsInternal(propList, terrainCounts, landSizeIndex, sign), "_") | |
730 | 665 | } | |
731 | 666 | ||
732 | 667 | ||
733 | 668 | 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)] | |
734 | 669 | ||
735 | 670 | ||
736 | 671 | func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = { | |
737 | 672 | func adder (acc,i) = { | |
738 | 673 | let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex) | |
739 | 674 | (acc :+ toString((parseIntValue(currentRes[i]) + resOfType))) | |
740 | 675 | } | |
741 | 676 | ||
742 | 677 | let r = { | |
743 | 678 | let $l = ITER6 | |
744 | 679 | let $s = size($l) | |
745 | 680 | let $acc0 = nil | |
746 | 681 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
747 | 682 | then $a | |
748 | 683 | else adder($a, $l[$i]) | |
749 | 684 | ||
750 | 685 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
751 | 686 | then $a | |
752 | 687 | else throw("List size exceeds 6") | |
753 | 688 | ||
754 | 689 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
755 | 690 | } | |
756 | 691 | makeString(r, "_") | |
757 | 692 | } | |
758 | 693 | ||
759 | 694 | ||
760 | 695 | func virtClaimAddRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = { | |
761 | 696 | func adder (acc,i) = { | |
762 | 697 | let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex) | |
763 | 698 | let totalResType = (parseIntValue(currentRes[i]) + resOfType) | |
764 | 699 | $Tuple2((acc._1 :+ totalResType), (acc._2 + totalResType)) | |
765 | 700 | } | |
766 | 701 | ||
767 | 702 | let $l = ITER6 | |
768 | 703 | let $s = size($l) | |
769 | 704 | let $acc0 = $Tuple2(nil, 0) | |
770 | 705 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
771 | 706 | then $a | |
772 | 707 | else adder($a, $l[$i]) | |
773 | 708 | ||
774 | 709 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
775 | 710 | then $a | |
776 | 711 | else throw("List size exceeds 6") | |
777 | 712 | ||
778 | 713 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
779 | 714 | } | |
780 | 715 | ||
781 | 716 | ||
782 | 717 | func virtClaim (terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = { | |
783 | 718 | func adder (acc,terrainCount) = { | |
784 | 719 | let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCount) * landSizeIndex) | |
785 | 720 | $Tuple2((acc._1 :+ resOfType), (acc._2 + resOfType)) | |
786 | 721 | } | |
787 | 722 | ||
788 | 723 | let $l = terrainCounts | |
789 | 724 | let $s = size($l) | |
790 | 725 | let $acc0 = $Tuple2(nil, 0) | |
791 | 726 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
792 | 727 | then $a | |
793 | 728 | else adder($a, $l[$i]) | |
794 | 729 | ||
795 | 730 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
796 | 731 | then $a | |
797 | 732 | else throw("List size exceeds 6") | |
798 | 733 | ||
799 | 734 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
800 | 735 | } | |
801 | 736 | ||
802 | 737 | ||
803 | 738 | func distributeRes (currentWhRes,currentPackRes,resToClaim,whSpaceLeft) = { | |
804 | 739 | let resListToClaim = resToClaim._1 | |
805 | 740 | let resAmToClaim = resToClaim._2 | |
806 | 741 | if ((resAmToClaim == 0)) | |
807 | 742 | then $Tuple2(makeString(currentWhRes, "_"), makeString(currentPackRes, "_")) | |
808 | 743 | else if ((whSpaceLeft >= resAmToClaim)) | |
809 | 744 | then { | |
810 | 745 | func addLists (acc,i) = (acc :+ toString((parseIntValue(currentWhRes[i]) + resListToClaim[i]))) | |
811 | 746 | ||
812 | 747 | let r = { | |
813 | 748 | let $l = ITER6 | |
814 | 749 | let $s = size($l) | |
815 | 750 | let $acc0 = nil | |
816 | 751 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
817 | 752 | then $a | |
818 | 753 | else addLists($a, $l[$i]) | |
819 | 754 | ||
820 | 755 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
821 | 756 | then $a | |
822 | 757 | else throw("List size exceeds 6") | |
823 | 758 | ||
824 | 759 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
825 | 760 | } | |
826 | 761 | $Tuple2(makeString(r, "_"), makeString(currentPackRes, "_")) | |
827 | 762 | } | |
828 | 763 | else { | |
829 | 764 | func addPartLists (acc,i) = { | |
830 | 765 | let whPart = fraction(resListToClaim[i], whSpaceLeft, resAmToClaim) | |
831 | 766 | $Tuple2((acc._1 :+ toString((parseIntValue(currentWhRes[i]) + whPart))), (acc._2 :+ toString(((parseIntValue(currentPackRes[i]) + resListToClaim[i]) - whPart)))) | |
832 | 767 | } | |
833 | 768 | ||
834 | 769 | let r = { | |
835 | 770 | let $l = ITER6 | |
836 | 771 | let $s = size($l) | |
837 | 772 | let $acc0 = $Tuple2(nil, nil) | |
838 | 773 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
839 | 774 | then $a | |
840 | 775 | else addPartLists($a, $l[$i]) | |
841 | 776 | ||
842 | 777 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
843 | 778 | then $a | |
844 | 779 | else throw("List size exceeds 6") | |
845 | 780 | ||
846 | 781 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
847 | 782 | } | |
848 | 783 | $Tuple2(makeString(r._1, "_"), makeString(r._2, "_")) | |
849 | 784 | } | |
850 | 785 | } | |
851 | 786 | ||
852 | 787 | ||
853 | 788 | func getBackpack (bpKey) = { | |
854 | 789 | let p = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":") | |
855 | 790 | [toString(valueOrElse(parseInt(p[bpIdxLevel]), 0)), if ((size(split(p[bpIdxRes], "_")) == NUMRES)) | |
856 | 791 | then p[bpIdxRes] | |
857 | 792 | else "0_0_0_0_0_0", if ((size(split(p[bpIdxMat], "_")) == NUMRES)) | |
858 | 793 | then p[bpIdxMat] | |
859 | 794 | else "0_0_0_0_0_0", p[bpIdxProd]] | |
860 | 795 | } | |
861 | 796 | ||
862 | 797 | ||
863 | 798 | func getWarehouseTotalVolume (volPrefix) = { | |
864 | 799 | let parts = split(volPrefix, "_") | |
865 | 800 | ((WHMULTIPLIER * (parseIntValue(parts[1]) + 1)) * parseIntValue(parts[0])) | |
866 | 801 | } | |
867 | 802 | ||
868 | 803 | ||
869 | 804 | func getWarehouseOccupiedVol (currentWh) = { | |
870 | 805 | let goods = currentWh[whIdxProd] | |
871 | 806 | func sumResMat (acc,item) = (acc + parseIntValue(item)) | |
872 | 807 | ||
873 | 808 | func sumProd (acc,item) = { | |
874 | 809 | let idx = acc._1 | |
875 | 810 | let pkgs = (((parseIntValue(item) + PRODUCTPKGSIZE) - 1) / PRODUCTPKGSIZE) | |
876 | 811 | $Tuple2((idx + 1), (acc._2 + (pkgs * MULT8))) | |
877 | 812 | } | |
878 | 813 | ||
879 | 814 | let whResVol = { | |
880 | 815 | let $l = split(currentWh[whIdxRes], "_") | |
881 | 816 | let $s = size($l) | |
882 | 817 | let $acc0 = 0 | |
883 | 818 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
884 | 819 | then $a | |
885 | 820 | else sumResMat($a, $l[$i]) | |
886 | 821 | ||
887 | 822 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
888 | 823 | then $a | |
889 | 824 | else throw("List size exceeds 6") | |
890 | 825 | ||
891 | 826 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
892 | 827 | } | |
893 | 828 | let whMatVol = { | |
894 | 829 | let $l = split(currentWh[whIdxMat], "_") | |
895 | 830 | let $s = size($l) | |
896 | 831 | let $acc0 = 0 | |
897 | 832 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
898 | 833 | then $a | |
899 | 834 | else sumResMat($a, $l[$i]) | |
900 | 835 | ||
901 | 836 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
902 | 837 | then $a | |
903 | 838 | else throw("List size exceeds 6") | |
904 | 839 | ||
905 | 840 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
906 | 841 | } | |
907 | 842 | let whGoodsVol = if ((goods == "")) | |
908 | 843 | then 0 | |
909 | 844 | else ( let $l = split_4C(goods, "_") | |
910 | 845 | let $s = size($l) | |
911 | 846 | let $acc0 = $Tuple2(0, 0) | |
912 | 847 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
913 | 848 | then $a | |
914 | 849 | else sumProd($a, $l[$i]) | |
915 | 850 | ||
916 | 851 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
917 | 852 | then $a | |
918 | 853 | else throw("List size exceeds 50") | |
919 | 854 | ||
920 | 855 | $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 | |
921 | 856 | ((whResVol + whMatVol) + whGoodsVol) | |
922 | 857 | } | |
923 | 858 | ||
924 | 859 | ||
925 | 860 | func getWarehouse (whKey,landIndex,infraLevel) = { | |
926 | 861 | let volPrefix = ((toString(landIndex) + "_") + toString(infraLevel)) | |
927 | 862 | let whTotal = getWarehouseTotalVolume(volPrefix) | |
928 | 863 | let whStr = valueOrElse(getString(whKey), (volPrefix + ":0_0_0_0_0_0:0_0_0_0_0_0::0")) | |
929 | 864 | let wh = split_4C(whStr, ":") | |
930 | 865 | let whOccupied = getWarehouseOccupiedVol(wh) | |
931 | 866 | let whLoft = if ((5 > size(wh))) | |
932 | 867 | then makeString(["0", toString(whOccupied), toString((whTotal - whOccupied)), toString(whTotal)], "_") | |
933 | 868 | else { | |
934 | 869 | let loft = split(wh[whIdxLOFT], "_") | |
935 | 870 | let whLocked = parseIntValue(loft[volLocked]) | |
936 | 871 | let occ = if ((size(loft) > 1)) | |
937 | 872 | then parseIntValue(loft[volOccupied]) | |
938 | 873 | else whOccupied | |
939 | 874 | makeString([toString(whLocked), toString(occ), toString(((whTotal - whLocked) - occ)), toString(whTotal)], "_") | |
940 | 875 | } | |
941 | 876 | [wh[whIdxLevels], if ((size(split(wh[whIdxRes], "_")) == NUMRES)) | |
942 | 877 | then wh[whIdxRes] | |
943 | 878 | else "0_0_0_0_0_0", if ((size(split(wh[whIdxMat], "_")) == NUMRES)) | |
944 | 879 | then wh[whIdxMat] | |
945 | 880 | else "0_0_0_0_0_0", wh[whIdxProd], whLoft] | |
946 | 881 | } | |
947 | 882 | ||
948 | 883 | ||
949 | 884 | func applyBonuses (landAssetId,pieces) = { | |
950 | 885 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
951 | 886 | let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0) | |
952 | 887 | let add6 = (infraLevel / 6) | |
953 | 888 | let add7 = (infraLevel / 7) | |
954 | 889 | ((DAILYRESBYPIECE + fraction(DAILYRESBYPIECE, ((infraLevel + add6) + (2 * add7)), 5)) + fraction(DAILYRESBYPIECE, artPieces, (pieces * 5))) | |
955 | 890 | } | |
956 | 891 | ||
957 | 892 | ||
958 | 893 | func checkClaimConditions (addr,claimMode,landAssetIdIn) = { | |
959 | 894 | let $t03424734786 = if ((claimMode == claimModeWh)) | |
960 | 895 | then $Tuple2(landAssetIdIn, valueOrElse(getString(keyStakedDuckByOwner(addr)), "")) | |
961 | 896 | else { | |
962 | 897 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
963 | 898 | let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION) | |
964 | 899 | let loc = split(value(curLocation), "_") | |
965 | 900 | if ((loc[locIdxType] != "L")) | |
966 | 901 | then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L")) | |
967 | 902 | else $Tuple2(loc[locIdxId], duckAssetId) | |
968 | 903 | } | |
969 | 904 | let landAssetId = $t03424734786._1 | |
970 | 905 | let duckId = $t03424734786._2 | |
971 | 906 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
972 | 907 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
973 | 908 | let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Land " + asset.name) + " is not staked")) | |
974 | 909 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
975 | 910 | if ((owner != addr)) | |
976 | 911 | then throw((LANDPREFIX + " is not yours")) | |
977 | 912 | else { | |
978 | 913 | let d = split(asset.description, "_") | |
979 | 914 | $Tuple4(duckId, landAssetId, d, savedTime) | |
980 | 915 | } | |
981 | 916 | } | |
982 | 917 | ||
983 | 918 | ||
984 | 919 | func claimResInternal (addr,amount,claimMode,landAssetIdIn) = if ((0 > amount)) | |
985 | 920 | then throw("Negative amount") | |
986 | 921 | else { | |
987 | 922 | let c = checkClaimConditions(addr, claimMode, landAssetIdIn) | |
988 | 923 | let landSize = c._3[recLandSize] | |
989 | 924 | let terrainCounts = countTerrains(c._3[recTerrains]) | |
990 | 925 | let deltaTime = (finalTime() - c._4) | |
991 | 926 | if ((0 > deltaTime)) | |
992 | 927 | then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", final = ") + toString(finalTime()))) | |
993 | 928 | else { | |
994 | 929 | let pieces = numPiecesBySize(landSize) | |
995 | 930 | let dailyProductionByPiece = applyBonuses(c._2, pieces) | |
996 | 931 | let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS) | |
997 | 932 | if ((amount > availRes)) | |
998 | 933 | then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount))) | |
999 | 934 | else { | |
1000 | 935 | let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces)) | |
1001 | 936 | let newTimestamp = (finalTime() - newDeltaTime) | |
1002 | 937 | let landIndex = (pieces / SSIZE) | |
1003 | 938 | let resToClaim = virtClaim(terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece) | |
1004 | 939 | let whKey = keyWarehouseByLand(c._2) | |
1005 | 940 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(c._2)), 0) | |
1006 | 941 | let currentWh = getWarehouse(whKey, landIndex, infraLevel) | |
1007 | 942 | let loft = split(currentWh[whIdxLOFT], "_") | |
1008 | 943 | let whSpaceLeft = parseIntValue(loft[volFree]) | |
1009 | 944 | if (if ((claimMode == claimModeWh)) | |
1010 | 945 | then (amount > whSpaceLeft) | |
1011 | 946 | else false) | |
1012 | 947 | then throw((("Only " + toString(whSpaceLeft)) + " space left in warehouse")) | |
1013 | 948 | else { | |
1014 | 949 | let bpKey = keyBackpackByDuck(c._1) | |
1015 | 950 | let currentPack = getBackpack(bpKey) | |
1016 | 951 | let currentPackRes = split(currentPack[bpIdxRes], "_") | |
1017 | 952 | let currentWhRes = split(currentWh[whIdxRes], "_") | |
1018 | 953 | let $t03715638027 = if ((claimMode == claimModeWh)) | |
1019 | 954 | then $Tuple4(addRes(currentWhRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), currentPack[bpIdxRes], (parseIntValue(loft[volOccupied]) + resToClaim._2), (parseIntValue(loft[volFree]) - resToClaim._2)) | |
1020 | 955 | else if ((claimMode == claimModeDuck)) | |
1021 | 956 | then $Tuple4(currentWh[whIdxRes], addRes(currentPackRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), parseIntValue(loft[volOccupied]), parseIntValue(loft[volFree])) | |
1022 | 957 | else { | |
1023 | 958 | let distr = distributeRes(currentWhRes, currentPackRes, resToClaim, whSpaceLeft) | |
1024 | 959 | let whAm = min([parseIntValue(loft[volFree]), resToClaim._2]) | |
1025 | 960 | $Tuple4(distr._1, distr._2, (parseIntValue(loft[volOccupied]) + whAm), (parseIntValue(loft[volFree]) - whAm)) | |
1026 | 961 | } | |
1027 | 962 | let whRes = $t03715638027._1 | |
1028 | 963 | let bpRes = $t03715638027._2 | |
1029 | 964 | let loftO = $t03715638027._3 | |
1030 | 965 | let loftF = $t03715638027._4 | |
1031 | 966 | $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]], "_")]) | |
1032 | 967 | } | |
1033 | 968 | } | |
1034 | 969 | } | |
1035 | 970 | } | |
1036 | 971 | ||
1037 | 972 | ||
1038 | 973 | func claimAll (addr,landAssetId,pieces,claimMode) = { | |
1039 | 974 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1040 | 975 | let savedTime = value(getInteger(timeKey)) | |
1041 | 976 | let availRes = (fraction((finalTime() - savedTime), applyBonuses(landAssetId, pieces), DAYMILLIS) * pieces) | |
1042 | 977 | claimResInternal(addr, availRes, claimMode, landAssetId) | |
1043 | 978 | } | |
1044 | 979 | ||
1045 | 980 | ||
1046 | 981 | func updateStatsInternal (lvlKey,xpKey,pointsKey,deltaXP) = { | |
1047 | 982 | let xp = valueOrElse(getInteger(xpKey), 0) | |
1048 | 983 | let newXP = (xp + deltaXP) | |
1049 | 984 | let lvlPoints = levelUp(valueOrElse(getInteger(lvlKey), 0), newXP) | |
1050 | 985 | $Tuple2([IntegerEntry(lvlKey, lvlPoints[0]), IntegerEntry(xpKey, newXP), IntegerEntry(pointsKey, (valueOrElse(getInteger(pointsKey), 0) + lvlPoints[1]))], newXP) | |
1051 | 986 | } | |
1052 | 987 | ||
1053 | 988 | ||
1054 | 989 | func updateDuckStatsInternal (duckAssetId,deltaXP) = { | |
1055 | 990 | let asset = value(assetInfo(fromBase58String(duckAssetId))) | |
1056 | 991 | let addr = valueOrErrorMessage(getString(keyDuckIdToOwner(duckAssetId)), (("NFT " + asset.name) + " is orphaned")) | |
1057 | 992 | if (if (if (KS_ALLOW_ROBO_DUCKS) | |
1058 | 993 | then (asset.issuer == this) | |
1059 | 994 | else false) | |
1060 | 995 | then contains(asset.name, ROBO_PREFIX) | |
1061 | 996 | else false) | |
1062 | 997 | then updateStatsInternal(keyUserLevel(addr), keyUserXP(addr), keyUserFreePoints(addr), deltaXP) | |
1063 | 998 | else updateStatsInternal(keyDuckLevel(duckAssetId), keyDuckXP(duckAssetId), keyDuckFreePoints(duckAssetId), deltaXP) | |
1064 | 999 | } | |
1065 | 1000 | ||
1066 | 1001 | ||
1067 | 1002 | func updateAccStatsInternal (addr,deltaXP) = updateStatsInternal(keyUserLevel(addr), keyUserXP(addr), keyUserFreePoints(addr), deltaXP) | |
1068 | 1003 | ||
1069 | 1004 | ||
1070 | 1005 | func activateOnboardArt (addr) = { | |
1071 | 1006 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1072 | 1007 | let refByKey = keyAddressRefBy(addr) | |
1073 | 1008 | let refBy = getString(refByKey) | |
1074 | 1009 | if (!(isDefined(refBy))) | |
1075 | 1010 | then throw("You are not eligible for ONBOARD artifact") | |
1076 | 1011 | else { | |
1077 | 1012 | let artKey = keyOnboardArtDuckActivatedBy(addr) | |
1078 | 1013 | let artDuck = getString(artKey) | |
1079 | 1014 | if (isDefined(artDuck)) | |
1080 | 1015 | then throw(("You already used your ONBOARD artifact on duck " + value(artDuck))) | |
1081 | 1016 | else { | |
1082 | 1017 | let duckActivatorKey = keyOnboardArtActivatedOnDuck(duckAssetId) | |
1083 | 1018 | let duckActivator = getString(duckActivatorKey) | |
1084 | 1019 | if (isDefined(duckActivator)) | |
1085 | 1020 | then throw(((("The duck " + duckAssetId) + " already got points from ONBOARD artifact from user ") + value(duckActivator))) | |
1086 | 1021 | else ([StringEntry(artKey, duckAssetId), StringEntry(duckActivatorKey, addr)] ++ updateDuckStatsInternal(duckAssetId, xpOnboard)._1) | |
1087 | 1022 | } | |
1088 | 1023 | } | |
1089 | 1024 | } | |
1090 | 1025 | ||
1091 | 1026 | ||
1092 | 1027 | func activatePresaleArt (addr,landAssetIdIn) = { | |
1093 | 1028 | let c = checkClaimConditions(addr, claimModeWhThenDuck, landAssetIdIn) | |
1094 | 1029 | let landAssetId = c._2 | |
1095 | 1030 | let pieces = numPiecesBySize(c._3[recLandSize]) | |
1096 | 1031 | let activationKey = keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId) | |
1097 | 1032 | if ((valueOrElse(getInteger(activationKey), 0) > 0)) | |
1098 | 1033 | then throw("Presale artifact is already activated") | |
1099 | 1034 | else if ((parseIntValue(c._3[recLandNum]) > PRESALENUMLANDS)) | |
1100 | 1035 | then throw((((LANDPREFIX + " ") + landAssetId) + " is not eligible for presale artifact")) | |
1101 | 1036 | else { | |
1102 | 1037 | let claimResult = claimAll(addr, landAssetId, pieces, claimModeWhThenDuck) | |
1103 | 1038 | (((claimResult._1 :+ IntegerEntry(activationKey, pieces)) :+ StringEntry(claimResult._2, makeString(claimResult._3, ":"))) :+ StringEntry(claimResult._4, makeString(claimResult._5, ":"))) | |
1104 | 1039 | } | |
1105 | 1040 | } | |
1106 | 1041 | ||
1107 | 1042 | ||
1108 | 1043 | func prolog (i) = if (if ((i.originCaller != restContract)) | |
1109 | 1044 | then valueOrElse(getBoolean(keyBlocked()), false) | |
1110 | 1045 | else false) | |
1111 | 1046 | then throw("Contracts are under maintenance") | |
1112 | 1047 | else [StringEntry(keyCurWeekTxIdByUser(toString(i.originCaller)), toBase58String(i.transactionId))] | |
1113 | 1048 | ||
1114 | 1049 | ||
1115 | 1050 | func unstakeLandInternal (addr,landAssetId) = { | |
1116 | 1051 | let whKey = keyWarehouseByLand(landAssetId) | |
1117 | 1052 | let landInfo = split(value(assetInfo(fromBase58String(landAssetId))).description, "_") | |
1118 | 1053 | let landSize = landInfo[recLandSize] | |
1119 | 1054 | let pieces = numPiecesBySize(landSize) | |
1120 | 1055 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1121 | 1056 | let landIndex = (pieces / SSIZE) | |
1122 | 1057 | let terrainCounts = countTerrains(landInfo[recTerrains]) | |
1123 | 1058 | let currentWh = getWarehouse(whKey, landIndex, infraLevel) | |
1124 | 1059 | let currentWhRes = split(currentWh[whIdxRes], "_") | |
1125 | 1060 | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1126 | 1061 | let savedTime = getIntegerValue(timeKey) | |
1127 | 1062 | let deltaTime = (finalTime() - savedTime) | |
1128 | 1063 | if ((0 > deltaTime)) | |
1129 | 1064 | then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", final = ") + toString(finalTime()))) | |
1130 | 1065 | else { | |
1131 | 1066 | let dailyProductionByPiece = applyBonuses(landAssetId, pieces) | |
1132 | 1067 | let resAfterClaim = virtClaimAddRes(currentWhRes, terrainCounts, deltaTime, landIndex, dailyProductionByPiece) | |
1133 | 1068 | let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0) | |
1134 | 1069 | let acresFromPieces = ((pieces * MULT8) + ((((pieces * infraLevel) + artPieces) * MULT8) / 5)) | |
1135 | 1070 | let acresFromRes = (fraction(resAfterClaim._2, RESOURCEPRICEMIN, MULT8) * USDT2ACRES_MULTIPLIER) | |
1136 | 1071 | func sumMat (acc,item) = (acc + parseIntValue(item)) | |
1137 | 1072 | ||
1138 | 1073 | let whMat = { | |
1139 | 1074 | let $l = split(currentWh[whIdxMat], "_") | |
1140 | 1075 | let $s = size($l) | |
1141 | 1076 | let $acc0 = 0 | |
1142 | 1077 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1143 | 1078 | then $a | |
1144 | 1079 | else sumMat($a, $l[$i]) | |
1145 | 1080 | ||
1146 | 1081 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1147 | 1082 | then $a | |
1148 | 1083 | else throw("List size exceeds 6") | |
1149 | 1084 | ||
1150 | 1085 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1151 | 1086 | } | |
1152 | 1087 | let acresFromMat = (fraction(whMat, (2 * RESOURCEPRICEMIN), MULT8) * USDT2ACRES_MULTIPLIER) | |
1153 | 1088 | let prods = if ((currentWh[whIdxProd] == "")) | |
1154 | 1089 | then nil | |
1155 | 1090 | else split_4C(currentWh[whIdxProd], "_") | |
1156 | 1091 | func sumProd (acc,item) = { | |
1157 | 1092 | let j = acc._2 | |
1158 | 1093 | let recipeCoeff = parseIntValue(split(productionMatrix[j], "_")[rIdxCoeff]) | |
1159 | 1094 | $Tuple2((acc._1 + ((parseIntValue(item) * recipeCoeff) * MULT6)), (j + 1)) | |
1160 | 1095 | } | |
1161 | 1096 | ||
1162 | 1097 | let whProd = { | |
1163 | 1098 | let $l = prods | |
1164 | 1099 | let $s = size($l) | |
1165 | 1100 | let $acc0 = $Tuple2(0, 0) | |
1166 | 1101 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
1167 | 1102 | then $a | |
1168 | 1103 | else sumProd($a, $l[$i]) | |
1169 | 1104 | ||
1170 | 1105 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
1171 | 1106 | then $a | |
1172 | 1107 | else throw("List size exceeds 24") | |
1173 | 1108 | ||
1174 | 1109 | $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($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) | |
1175 | 1110 | } | |
1176 | 1111 | let acresFromProd = (fraction(whProd._1, (2 * RESOURCEPRICEMIN), MULT8) * USDT2ACRES_MULTIPLIER) | |
1177 | 1112 | $Tuple4(acresFromPieces, acresFromRes, acresFromMat, acresFromProd) | |
1178 | 1113 | } | |
1179 | 1114 | } | |
1180 | 1115 | ||
1181 | 1116 | ||
1182 | 1117 | func unstakeDuckInternal (addr,duckAssetId) = { | |
1183 | 1118 | let eqKey = keyDuckEquipment(duckAssetId) | |
1184 | 1119 | let currentSegs = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_") | |
1185 | 1120 | let bpKey = keyBackpackByDuck(duckAssetId) | |
1186 | 1121 | let currentPack = getBackpack(bpKey) | |
1187 | 1122 | let tempProdB = dressB(currentSegs, prodStrToBytes(currentPack[bpIdxProd]), true, nil) | |
1188 | 1123 | let newProdStr = bytesToProdStr(tempProdB) | |
1189 | 1124 | func sumResMat (acc,item) = (acc + parseIntValue(item)) | |
1190 | 1125 | ||
1191 | 1126 | let bpRes = { | |
1192 | 1127 | let $l = split(currentPack[bpIdxRes], "_") | |
1193 | 1128 | let $s = size($l) | |
1194 | 1129 | let $acc0 = 0 | |
1195 | 1130 | func $f0_1 ($a,$i) = if (($i >= $s)) | |
1196 | 1131 | then $a | |
1197 | 1132 | else sumResMat($a, $l[$i]) | |
1198 | 1133 | ||
1199 | 1134 | func $f0_2 ($a,$i) = if (($i >= $s)) | |
1200 | 1135 | then $a | |
1201 | 1136 | else throw("List size exceeds 6") | |
1202 | 1137 | ||
1203 | 1138 | $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1204 | 1139 | } | |
1205 | 1140 | let acresFromRes = (fraction(bpRes, RESOURCEPRICEMIN, MULT8) * USDT2ACRES_MULTIPLIER) | |
1206 | 1141 | let bpMat = { | |
1207 | 1142 | let $l = split(currentPack[bpIdxMat], "_") | |
1208 | 1143 | let $s = size($l) | |
1209 | 1144 | let $acc0 = 0 | |
1210 | 1145 | func $f1_1 ($a,$i) = if (($i >= $s)) | |
1211 | 1146 | then $a | |
1212 | 1147 | else sumResMat($a, $l[$i]) | |
1213 | 1148 | ||
1214 | 1149 | func $f1_2 ($a,$i) = if (($i >= $s)) | |
1215 | 1150 | then $a | |
1216 | 1151 | else throw("List size exceeds 6") | |
1217 | 1152 | ||
1218 | 1153 | $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6) | |
1219 | 1154 | } | |
1220 | 1155 | let acresFromMat = (fraction(bpMat, (2 * RESOURCEPRICEMIN), MULT8) * USDT2ACRES_MULTIPLIER) | |
1221 | 1156 | let prods = if ((newProdStr == "")) | |
1222 | 1157 | then nil | |
1223 | 1158 | else split_4C(newProdStr, "_") | |
1224 | 1159 | func sumProd (acc,item) = { | |
1225 | 1160 | let j = acc._2 | |
1226 | 1161 | let recipeCoeff = parseIntValue(split(productionMatrix[j], "_")[rIdxCoeff]) | |
1227 | 1162 | $Tuple2((acc._1 + ((parseIntValue(item) * recipeCoeff) * MULT6)), (j + 1)) | |
1228 | 1163 | } | |
1229 | 1164 | ||
1230 | 1165 | let bpProd = { | |
1231 | 1166 | let $l = prods | |
1232 | 1167 | let $s = size($l) | |
1233 | 1168 | let $acc0 = $Tuple2(0, 0) | |
1234 | 1169 | func $f2_1 ($a,$i) = if (($i >= $s)) | |
1235 | 1170 | then $a | |
1236 | 1171 | else sumProd($a, $l[$i]) | |
1237 | 1172 | ||
1238 | 1173 | func $f2_2 ($a,$i) = if (($i >= $s)) | |
1239 | 1174 | then $a | |
1240 | 1175 | else throw("List size exceeds 24") | |
1241 | 1176 | ||
1242 | 1177 | $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($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) | |
1243 | 1178 | } | |
1244 | 1179 | let acresFromProd = (fraction(bpProd._1, (2 * RESOURCEPRICEMIN), MULT8) * USDT2ACRES_MULTIPLIER) | |
1245 | 1180 | $Tuple3(acresFromRes, acresFromMat, acresFromProd) | |
1246 | 1181 | } | |
1247 | 1182 | ||
1248 | 1183 | ||
1249 | 1184 | @Callable(i) | |
1250 | 1185 | func constructorV1 (restAddr) = if ((i.caller != this)) | |
1251 | 1186 | then throw("Permission denied") | |
1252 | 1187 | else [StringEntry(keyRestAddress(), restAddr)] | |
1253 | 1188 | ||
1254 | 1189 | ||
1255 | 1190 | ||
1256 | 1191 | @Callable(i) | |
1257 | 1192 | func saveInteger (key,amount) = if ((i.caller != this)) | |
1258 | 1193 | then throw("saveInteger is not public method") | |
1259 | 1194 | else [IntegerEntry(key, amount)] | |
1260 | 1195 | ||
1261 | 1196 | ||
1262 | 1197 | ||
1263 | 1198 | @Callable(i) | |
1264 | 1199 | func setBlocked (isBlocked) = if ((i.caller != this)) | |
1265 | 1200 | then throw("permission denied") | |
1266 | 1201 | else [BooleanEntry(keyBlocked(), isBlocked)] | |
1267 | 1202 | ||
1268 | 1203 | ||
1269 | 1204 | ||
1270 | 1205 | @Callable(i) | |
1271 | - | func stakeLand () = { | |
1272 | - | let prologActions = prolog(i) | |
1273 | - | if ((size(i.payments) != 1)) | |
1274 | - | then throw("Exactly one payment required") | |
1275 | - | else { | |
1276 | - | let pmt = value(i.payments[0]) | |
1277 | - | let assetId = value(pmt.assetId) | |
1278 | - | let address = toString(i.caller) | |
1279 | - | if ((pmt.amount != 1)) | |
1280 | - | then throw((("NFT " + LANDPREFIX) + " token should be attached as payment")) | |
1281 | - | else { | |
1282 | - | let asset = value(assetInfo(assetId)) | |
1283 | - | if ((asset.issuer != this)) | |
1284 | - | then throw("Unknown issuer of token") | |
1285 | - | else if (!(contains(asset.name, LANDPREFIX))) | |
1286 | - | then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted")) | |
1287 | - | else { | |
1288 | - | let landNumSize = drop(asset.name, 4) | |
1289 | - | let landNum = if (contains(landNumSize, "XXL")) | |
1290 | - | then dropRight(landNumSize, 3) | |
1291 | - | else if (contains(landNumSize, "XL")) | |
1292 | - | then dropRight(landNumSize, 2) | |
1293 | - | else dropRight(landNumSize, 1) | |
1294 | - | if (!(isDefined(parseInt(landNum)))) | |
1295 | - | then throw(("Cannot parse land number from " + asset.name)) | |
1296 | - | else { | |
1297 | - | let landAssetId = toBase58String(assetId) | |
1298 | - | let timeKey = keyStakedTimeByAssetId(landAssetId) | |
1299 | - | if (isDefined(getInteger(timeKey))) | |
1300 | - | then throw((("NFT " + asset.name) + " is already staked")) | |
1301 | - | else { | |
1302 | - | let d = split(asset.description, "_") | |
1303 | - | let terrainCounts = countTerrains(d[recTerrains]) | |
1304 | - | let pieces = numPiecesBySize(d[recLandSize]) | |
1305 | - | let landIndex = (pieces / SSIZE) | |
1306 | - | let props = updateProportions(terrainCounts, landIndex, 1) | |
1307 | - | let resByContKey = keyResTypesByContinent(d[recContinent]) | |
1308 | - | let contProps = split(valueOrElse(getString(resByContKey), "0_0_0_0_0_0"), "_") | |
1309 | - | let updatedContProps = makeString(updateProportionsInternal(contProps, terrainCounts, landIndex, 1), "_") | |
1310 | - | let landsKey = keyStakedLandsByOwner(address) | |
1311 | - | let landsStr = getString(landsKey) | |
1312 | - | let lands = if (isDefined(landsStr)) | |
1313 | - | then split_51C(value(landsStr), "_") | |
1314 | - | else nil | |
1315 | - | if (containsElement(lands, landAssetId)) | |
1316 | - | then throw(("Your staked lands already contain " + landAssetId)) | |
1317 | - | else if ((size(lands) >= MAX_LANDS_STAKED_BY_USER)) | |
1318 | - | then throw((("Your already staked max (" + toString(MAX_LANDS_STAKED_BY_USER)) + ") lands")) | |
1319 | - | else { | |
1320 | - | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1321 | - | let piecesKey = keyStakedPiecesByOwner(address) | |
1322 | - | let oldPieces = valueOrElse(getInteger(piecesKey), 0) | |
1323 | - | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [address], nil) | |
1324 | - | $Tuple2(([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address), lastBlock.timestamp), StringEntry(landsKey, makeString_11C((lands :+ landAssetId), "_")), IntegerEntry(piecesKey, (oldPieces + pieces)), StringEntry(keyLandAssetIdToOwner(landAssetId), address), StringEntry(keyLandNumToOwner(landNum), address), IntegerEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, address), infraLevel), StringEntry(keyResProportions(), props), StringEntry(resByContKey, updatedContProps)] ++ prologActions), wlgResult) | |
1325 | - | } | |
1326 | - | } | |
1327 | - | } | |
1328 | - | } | |
1329 | - | } | |
1330 | - | } | |
1331 | - | } | |
1332 | - | ||
1333 | - | ||
1334 | - | ||
1335 | - | @Callable(i) | |
1336 | - | func unstakeLand (landAssetIdIn) = { | |
1337 | - | let prologActions = prolog(i) | |
1338 | - | if ((size(i.payments) != 0)) | |
1339 | - | then throw("No payments required") | |
1340 | - | else { | |
1341 | - | let addr = toString(i.caller) | |
1342 | - | let c = checkClaimConditions(addr, claimModeDuck, landAssetIdIn) | |
1343 | - | let landAssetId = c._2 | |
1344 | - | let d = c._3 | |
1345 | - | let landsKey = keyStakedLandsByOwner(addr) | |
1346 | - | let terrainCounts = countTerrains(d[recTerrains]) | |
1347 | - | let pieces = numPiecesBySize(d[recLandSize]) | |
1348 | - | let landIndex = (pieces / SSIZE) | |
1349 | - | let props = updateProportions(terrainCounts, landIndex, -1) | |
1350 | - | let resByContKey = keyResTypesByContinent(d[recContinent]) | |
1351 | - | let contProps = split(valueOrElse(getString(resByContKey), "0_0_0_0_0_0"), "_") | |
1352 | - | let updatedContProps = makeString(updateProportionsInternal(contProps, terrainCounts, landIndex, -1), "_") | |
1353 | - | let claimResult = claimAll(addr, landAssetId, pieces, claimModeDuck) | |
1354 | - | let lands = split_51C(valueOrElse(getString(landsKey), ""), "_") | |
1355 | - | let idx = indexOf(lands, landAssetId) | |
1356 | - | if (!(isDefined(idx))) | |
1357 | - | then throw(("Your staked lands don't contain " + landAssetId)) | |
1358 | - | else { | |
1359 | - | let now = lastBlock.timestamp | |
1360 | - | let govReleaseTime = valueOrElse(getInteger(govContract, keyUserGwlReleaseTime(addr)), 0) | |
1361 | - | if ((govReleaseTime >= now)) | |
1362 | - | then throw(("Your gWL are taking part in voting, cannot unstake until " + toString(govReleaseTime))) | |
1363 | - | else { | |
1364 | - | let arbReleaseTime = (valueOrElse(getInteger(wlgContract, keyLastWlgTradeTimeByUser(addr)), 0) + arbitrageDelay) | |
1365 | - | if ((arbReleaseTime > now)) | |
1366 | - | then throw(("Your staked lands took part in arbitrage, cannot unstake until " + toString(arbReleaseTime))) | |
1367 | - | else { | |
1368 | - | let piecesKey = keyStakedPiecesByOwner(addr) | |
1369 | - | let stakedPieces = valueOrElse(getInteger(piecesKey), 0) | |
1370 | - | let newPieces = if ((pieces > stakedPieces)) | |
1371 | - | then 0 | |
1372 | - | else (stakedPieces - pieces) | |
1373 | - | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [addr], nil) | |
1374 | - | $Tuple2(([ScriptTransfer(i.caller, 1, fromBase58String(landAssetId)), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr)), StringEntry(keyResProportions(), props), StringEntry(resByContKey, updatedContProps), StringEntry(claimResult._2, makeString(claimResult._3, ":")), if ((size(lands) > 1)) | |
1375 | - | then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_")) | |
1376 | - | else DeleteEntry(landsKey), IntegerEntry(piecesKey, newPieces)] ++ prologActions), wlgResult) | |
1377 | - | } | |
1378 | - | } | |
1379 | - | } | |
1380 | - | } | |
1381 | - | } | |
1382 | - | ||
1383 | - | ||
1384 | - | ||
1385 | - | @Callable(i) | |
1386 | 1206 | func unstakeLandCallback (landAssetId,addr) = if ((toString(i.caller) != acres2AddressStr)) | |
1387 | 1207 | then throw("Permission denied") | |
1388 | 1208 | else { | |
1389 | 1209 | let unstakeResult = unstakeLandInternal(addr, landAssetId) | |
1390 | - | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [addr], nil) | |
1210 | + | let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [addr, false], nil) | |
1391 | 1211 | $Tuple2([Burn(fromBase58String(landAssetId), 1), DeleteEntry(keyStakedTimeByAssetId(landAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr))], $Tuple5(unstakeResult._1, unstakeResult._2, unstakeResult._3, unstakeResult._4, wlgResult)) | |
1392 | 1212 | } | |
1393 | 1213 | ||
1394 | 1214 | ||
1395 | 1215 | ||
1396 | 1216 | @Callable(i) | |
1397 | 1217 | func unstakeLandREADONLY (landAssetId,addr) = { | |
1398 | 1218 | let unstakeResult = unstakeLandInternal(addr, landAssetId) | |
1399 | 1219 | $Tuple2(nil, unstakeResult) | |
1400 | 1220 | } | |
1401 | 1221 | ||
1402 | 1222 | ||
1403 | 1223 | ||
1404 | 1224 | @Callable(i) | |
1405 | 1225 | func unstakeLandsFinalizeCallback (addr) = if ((toString(i.caller) != acres2AddressStr)) | |
1406 | 1226 | then throw("Permission denied") | |
1407 | 1227 | else $Tuple2([DeleteEntry(keyStakedLandsByOwner(addr)), DeleteEntry(keyStakedPiecesByOwner(addr))], 0) | |
1408 | 1228 | ||
1409 | 1229 | ||
1410 | 1230 | ||
1411 | 1231 | @Callable(i) | |
1412 | 1232 | func convertUnstakedLands () = if ((size(i.payments) != 1)) | |
1413 | 1233 | then throw("Exactly one payment required") | |
1414 | 1234 | else { | |
1415 | 1235 | let pmt = value(i.payments[0]) | |
1416 | 1236 | let assetId = value(pmt.assetId) | |
1417 | 1237 | let address = toString(i.caller) | |
1418 | 1238 | if ((pmt.amount != 1)) | |
1419 | 1239 | then throw((("NFT " + LANDPREFIX) + " token should be attached as payment")) | |
1420 | 1240 | else { | |
1421 | 1241 | let asset = value(assetInfo(assetId)) | |
1422 | 1242 | if ((asset.issuer != this)) | |
1423 | 1243 | then throw("Unknown issuer of token") | |
1424 | 1244 | else if (!(contains(asset.name, LANDPREFIX))) | |
1425 | 1245 | then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted")) | |
1426 | 1246 | else { | |
1427 | 1247 | let landAssetId = toBase58String(assetId) | |
1428 | 1248 | let d = split(asset.description, "_") | |
1429 | 1249 | let pieces = numPiecesBySize(d[recLandSize]) | |
1430 | 1250 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1431 | 1251 | let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0) | |
1432 | 1252 | let acresAmount = ((pieces * MULT8) + ((((pieces * infraLevel) + artPieces) * MULT8) / 5)) | |
1433 | 1253 | let req = invoke(acresContract, "requestAcresCallback", [acresAmount], nil) | |
1434 | 1254 | if ((req == req)) | |
1435 | 1255 | then { | |
1436 | 1256 | let callb = invoke(addressFromStringValue(acres2AddressStr), "stakeAcresCallback", [address], [AttachedPayment(acresAssetId, acresAmount)]) | |
1437 | 1257 | if ((callb == callb)) | |
1438 | 1258 | then $Tuple2([Burn(fromBase58String(landAssetId), 1)], 0) | |
1439 | 1259 | else throw("Strict value is not equal to itself.") | |
1440 | 1260 | } | |
1441 | 1261 | else throw("Strict value is not equal to itself.") | |
1442 | 1262 | } | |
1443 | 1263 | } | |
1444 | 1264 | } | |
1445 | 1265 | ||
1446 | 1266 | ||
1447 | 1267 | ||
1448 | 1268 | @Callable(i) | |
1449 | 1269 | func unstakeDuckCallback (duckAssetId,addr) = if ((toString(i.caller) != acres2AddressStr)) | |
1450 | 1270 | then throw("Permission denied") | |
1451 | 1271 | else { | |
1452 | 1272 | let unstakeResult = unstakeDuckInternal(addr, duckAssetId) | |
1453 | 1273 | $Tuple2([ScriptTransfer(addressFromStringValue(addr), 1, fromBase58String(duckAssetId)), DeleteEntry(keyStakedTimeByAssetId(duckAssetId)), DeleteEntry(keyDuckIdToOwner(duckAssetId)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, duckAssetId, addr)), DeleteEntry(keyStakedDuckByOwner(addr))], unstakeResult) | |
1454 | 1274 | } | |
1455 | 1275 | ||
1456 | 1276 | ||
1457 | 1277 | ||
1458 | 1278 | @Callable(i) | |
1459 | 1279 | func unstakeDuckREADONLY (duckAssetId,addr) = { | |
1460 | 1280 | let unstakeResult = unstakeDuckInternal(addr, duckAssetId) | |
1461 | 1281 | $Tuple2(nil, unstakeResult) | |
1462 | 1282 | } | |
1463 | 1283 | ||
1464 | 1284 | ||
1465 | 1285 | ||
1466 | 1286 | @Callable(i) | |
1467 | 1287 | func claimRes (amount,landAssetIdStr) = { | |
1468 | 1288 | let prologActions = prolog(i) | |
1469 | 1289 | if ((size(i.payments) != 0)) | |
1470 | 1290 | then throw("No payments required") | |
1471 | 1291 | else { | |
1472 | 1292 | let addr = toString(i.originCaller) | |
1473 | 1293 | let result = claimResInternal(addr, amount, claimModeDuck, landAssetIdStr) | |
1474 | 1294 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1475 | 1295 | $Tuple2(((((result._1 ++ updateDuckStatsInternal(duckAssetId, fraction(xpClaim, amount, MULT8))._1) :+ StringEntry(result._2, makeString(result._3, ":"))) :+ StringEntry(result._4, makeString(result._5, ":"))) ++ prologActions), result._3[bpIdxRes]) | |
1476 | 1296 | } | |
1477 | 1297 | } | |
1478 | 1298 | ||
1479 | 1299 | ||
1480 | 1300 | ||
1481 | 1301 | @Callable(i) | |
1482 | 1302 | func claimResToWH (amount,landAssetIdStr) = { | |
1483 | 1303 | let prologActions = prolog(i) | |
1484 | 1304 | if ((size(i.payments) != 0)) | |
1485 | 1305 | then throw("No payments required") | |
1486 | 1306 | else { | |
1487 | 1307 | let addr = toString(i.originCaller) | |
1488 | 1308 | let result = claimResInternal(addr, amount, claimModeWh, landAssetIdStr) | |
1489 | 1309 | $Tuple2(((((result._1 ++ updateAccStatsInternal(addr, fraction(xpClaim, amount, MULT8))._1) :+ StringEntry(result._2, makeString(result._3, ":"))) :+ StringEntry(result._4, makeString(result._5, ":"))) ++ prologActions), result._5[whIdxRes]) | |
1490 | 1310 | } | |
1491 | 1311 | } | |
1492 | 1312 | ||
1493 | 1313 | ||
1494 | 1314 | ||
1495 | 1315 | @Callable(i) | |
1496 | 1316 | func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyContract)) | |
1497 | 1317 | then throw("permission denied") | |
1498 | 1318 | else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack) | |
1499 | 1319 | ||
1500 | 1320 | ||
1501 | 1321 | ||
1502 | 1322 | @Callable(i) | |
1503 | 1323 | func commitForRandom () = { | |
1504 | 1324 | let prologActions = prolog(i) | |
1505 | 1325 | let finishBlock = (height + randomDelay) | |
1506 | 1326 | let addr = toString(i.caller) | |
1507 | 1327 | $Tuple2(([IntegerEntry(keyCommit(addr), finishBlock)] ++ prologActions), finishBlock) | |
1508 | 1328 | } | |
1509 | 1329 | ||
1510 | 1330 | ||
1511 | 1331 | ||
1512 | 1332 | @Callable(i) | |
1513 | 1333 | func revealRandom (maxValue) = { | |
1514 | 1334 | let prologActions = prolog(i) | |
1515 | 1335 | let addr = toString(i.caller) | |
1516 | 1336 | let finishKey = keyCommit(addr) | |
1517 | 1337 | let finishBlock = valueOrErrorMessage(getInteger(finishKey), "You have to commitForRandom() first!") | |
1518 | 1338 | if ((finishBlock > height)) | |
1519 | 1339 | then throw(("Random number is not ready yet, wait until height = " + toString(finishBlock))) | |
1520 | 1340 | else { | |
1521 | 1341 | let entropy = value(value(blockInfoByHeight(finishBlock)).vrf) | |
1522 | 1342 | let salt = toBytes(valueOrElse(getString(keyLastWeekTxIdByUser(addr)), "")) | |
1523 | 1343 | let rand = getRandomNumber(maxValue, salt, entropy) | |
1524 | 1344 | $Tuple2(([DeleteEntry(finishKey)] ++ prologActions), rand) | |
1525 | 1345 | } | |
1526 | 1346 | } | |
1527 | 1347 | ||
1528 | 1348 | ||
1529 | 1349 | ||
1530 | 1350 | @Callable(i) | |
1531 | 1351 | func activateArtifact (artName,landAssetIdOpt) = { | |
1532 | 1352 | let prologActions = prolog(i) | |
1533 | 1353 | if ((size(i.payments) != 0)) | |
1534 | 1354 | then throw("No payments required") | |
1535 | 1355 | else { | |
1536 | 1356 | let addr = toString(i.caller) | |
1537 | 1357 | let result = match artName { | |
1538 | 1358 | case _ => | |
1539 | 1359 | if (("PRESALE" == $match0)) | |
1540 | 1360 | then activatePresaleArt(addr, landAssetIdOpt) | |
1541 | 1361 | else if (("ONBOARD" == $match0)) | |
1542 | 1362 | then activateOnboardArt(addr) | |
1543 | 1363 | else throw("Unknown artifact") | |
1544 | 1364 | } | |
1545 | 1365 | (result ++ prologActions) | |
1546 | 1366 | } | |
1547 | 1367 | } | |
1548 | 1368 | ||
1549 | 1369 | ||
1550 | 1370 | ||
1551 | 1371 | @Callable(i) | |
1552 | 1372 | func saveWarehouse (whStr,landAssetId) = if ((i.caller != economyContract)) | |
1553 | 1373 | then throw("Access denied") | |
1554 | 1374 | else { | |
1555 | 1375 | let whKey = keyWarehouseByLand(landAssetId) | |
1556 | 1376 | let wh = split_4C(whStr, ":") | |
1557 | 1377 | if ((size(wh) != 5)) | |
1558 | 1378 | then throw("warehouse string should contain 4 ':' separators") | |
1559 | 1379 | else { | |
1560 | 1380 | let loftL = split(wh[whIdxLOFT], "_")[volLocked] | |
1561 | 1381 | let loftO = getWarehouseOccupiedVol(wh) | |
1562 | 1382 | let loftT = getWarehouseTotalVolume(wh[whIdxLevels]) | |
1563 | 1383 | let loftF = ((loftT - parseIntValue(loftL)) - loftO) | |
1564 | 1384 | if ((0 > loftF)) | |
1565 | 1385 | then throw("Operation leads to negative free warehouse space") | |
1566 | 1386 | else { | |
1567 | 1387 | let newWhStr = makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], wh[whIdxProd], makeString([loftL, toString(loftO), toString(loftF), toString(loftT)], "_")], ":") | |
1568 | 1388 | $Tuple2([StringEntry(whKey, newWhStr)], newWhStr) | |
1569 | 1389 | } | |
1570 | 1390 | } | |
1571 | 1391 | } | |
1572 | 1392 | ||
1573 | 1393 | ||
1574 | 1394 | ||
1575 | 1395 | @Callable(i) | |
1576 | 1396 | func setCustomName (assetId,customName,type) = { | |
1577 | 1397 | let prologActions = prolog(i) | |
1578 | 1398 | if ((size(i.payments) != 1)) | |
1579 | 1399 | then throw("Exactly one payment required") | |
1580 | 1400 | else { | |
1581 | 1401 | let pmt = value(i.payments[0]) | |
1582 | 1402 | if ((pmt.assetId != usdtAssetId)) | |
1583 | 1403 | then throw("Allowed USDT payment only!") | |
1584 | 1404 | else if ((pmt.amount != RENAMINGCOST)) | |
1585 | 1405 | then throw(("Payment should be " + toString(RENAMINGCOST))) | |
1586 | 1406 | else if (contains(customName, "__")) | |
1587 | 1407 | then throw(("Name should not contain '__': " + customName)) | |
1588 | 1408 | else if ((size(customName) > MAXNAMELEN)) | |
1589 | 1409 | then throw(("Name too long, maxLength=" + toString(MAXNAMELEN))) | |
1590 | 1410 | else { | |
1591 | 1411 | let addr = toString(i.originCaller) | |
1592 | 1412 | let actions = match type { | |
1593 | 1413 | case _ => | |
1594 | 1414 | if (("ACCOUNT" == $match0)) | |
1595 | 1415 | then { | |
1596 | 1416 | let reverseKey = keyCustomNameToAddress(customName) | |
1597 | 1417 | let nameOwner = getString(reverseKey) | |
1598 | 1418 | if (isDefined(nameOwner)) | |
1599 | 1419 | then throw(("Name already registered: " + customName)) | |
1600 | 1420 | else { | |
1601 | 1421 | let addrToNameKey = keyAddressToCustomName(addr) | |
1602 | 1422 | let oldName = getString(addrToNameKey) | |
1603 | 1423 | let freeOld = if (isDefined(oldName)) | |
1604 | 1424 | then [DeleteEntry(keyCustomNameToAddress(value(oldName)))] | |
1605 | 1425 | else nil | |
1606 | 1426 | (((freeOld :+ StringEntry(addrToNameKey, customName)) :+ StringEntry(reverseKey, addr)) ++ updateAccStatsInternal(addr, xpCustomName)._1) | |
1607 | 1427 | } | |
1608 | 1428 | } | |
1609 | 1429 | else if (("LAND" == $match0)) | |
1610 | 1430 | then { | |
1611 | 1431 | let asset = value(assetInfo(fromBase58String(assetId))) | |
1612 | 1432 | let timeKey = keyStakedTimeByAssetId(assetId) | |
1613 | 1433 | if (!(isDefined(getInteger(timeKey)))) | |
1614 | 1434 | then throw((asset.name + " is not staked")) | |
1615 | 1435 | else { | |
1616 | 1436 | let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(assetId)), (("NFT " + asset.name) + " is orphaned")) | |
1617 | 1437 | if ((owner != addr)) | |
1618 | 1438 | then throw((LANDPREFIX + " is not yours")) | |
1619 | 1439 | else { | |
1620 | 1440 | let reverseKey = keyLandCustomNameToAssetId(customName) | |
1621 | 1441 | let nameOwner = getString(reverseKey) | |
1622 | 1442 | if (isDefined(nameOwner)) | |
1623 | 1443 | then throw(("Name already registered: " + customName)) | |
1624 | 1444 | else { | |
1625 | 1445 | let assetToNameKey = keyLandAssetIdToCustomName(assetId) | |
1626 | 1446 | let oldName = getString(assetToNameKey) | |
1627 | 1447 | let freeOld = if (isDefined(oldName)) | |
1628 | 1448 | then [DeleteEntry(keyLandCustomNameToAssetId(value(oldName)))] | |
1629 | 1449 | else nil | |
1630 | 1450 | (((freeOld :+ StringEntry(assetToNameKey, customName)) :+ StringEntry(reverseKey, assetId)) ++ updateAccStatsInternal(addr, xpCustomName)._1) | |
1631 | 1451 | } | |
1632 | 1452 | } | |
1633 | 1453 | } | |
1634 | 1454 | } | |
1635 | 1455 | else if (("DUCK" == $match0)) | |
1636 | 1456 | then { | |
1637 | 1457 | let asset = value(assetInfo(fromBase58String(assetId))) | |
1638 | 1458 | let timeKey = keyStakedTimeByAssetId(assetId) | |
1639 | 1459 | if (if (!(isDefined(getInteger(timeKey)))) | |
1640 | 1460 | then true | |
1641 | 1461 | else !(isDefined(getString(keyStakedDuckByOwner(addr))))) | |
1642 | 1462 | then throw((asset.name + " is not staked")) | |
1643 | 1463 | else { | |
1644 | 1464 | let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(assetId)), (("NFT " + asset.name) + " is orphaned")) | |
1645 | 1465 | if ((owner != addr)) | |
1646 | 1466 | then throw((DUCKPREFIX + " is not yours")) | |
1647 | 1467 | else { | |
1648 | 1468 | let reverseKey = keyDuckCustomNameToAssetId(customName) | |
1649 | 1469 | let nameOwner = getString(reverseKey) | |
1650 | 1470 | if (isDefined(nameOwner)) | |
1651 | 1471 | then throw(("Name already registered: " + customName)) | |
1652 | 1472 | else { | |
1653 | 1473 | let assetToNameKey = keyDuckAssetIdToCustomName(assetId) | |
1654 | 1474 | let oldName = getString(assetToNameKey) | |
1655 | 1475 | let freeOld = if (isDefined(oldName)) | |
1656 | 1476 | then [DeleteEntry(keyDuckCustomNameToAssetId(value(oldName)))] | |
1657 | 1477 | else nil | |
1658 | 1478 | (((freeOld :+ StringEntry(assetToNameKey, customName)) :+ StringEntry(reverseKey, assetId)) ++ updateDuckStatsInternal(assetId, xpCustomName)._1) | |
1659 | 1479 | } | |
1660 | 1480 | } | |
1661 | 1481 | } | |
1662 | 1482 | } | |
1663 | 1483 | else throw("Unknown entity type") | |
1664 | 1484 | } | |
1665 | 1485 | $Tuple2(((actions :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) ++ prologActions), 0) | |
1666 | 1486 | } | |
1667 | 1487 | } | |
1668 | 1488 | } | |
1669 | 1489 | ||
1670 | 1490 | ||
1671 | 1491 | ||
1672 | 1492 | @Callable(i) | |
1673 | 1493 | func setReferrals (oldPlayer,newPlayer) = if ((i.callerPublicKey != pub)) | |
1674 | 1494 | then throw("Permission denied") | |
1675 | 1495 | else { | |
1676 | 1496 | let prologActions = prolog(i) | |
1677 | 1497 | if ((size(i.payments) != 0)) | |
1678 | 1498 | then throw("No payments required") | |
1679 | 1499 | else if (!(isDefined(addressFromString(oldPlayer)))) | |
1680 | 1500 | then throw(("Invalid address: " + oldPlayer)) | |
1681 | 1501 | else { | |
1682 | 1502 | let newbieAddr = addressFromString(newPlayer) | |
1683 | 1503 | if (!(isDefined(newbieAddr))) | |
1684 | 1504 | then throw(("Invalid address: " + newPlayer)) | |
1685 | 1505 | else { | |
1686 | 1506 | let oldLastTx = getString(keyLastWeekTxIdByUser(oldPlayer)) | |
1687 | 1507 | if (!(isDefined(oldLastTx))) | |
1688 | 1508 | then throw("oldPlayer didn't do any tx in game") | |
1689 | 1509 | else if ((0 >= wavesBalance(value(newbieAddr)).available)) | |
1690 | 1510 | then throw("newPlayer has no WAVES") | |
1691 | 1511 | else { | |
1692 | 1512 | let oldsKey = keyOldies() | |
1693 | 1513 | let olds = getString(oldsKey) | |
1694 | 1514 | let oldies = if (isDefined(olds)) | |
1695 | 1515 | then split_4C(value(olds), "_") | |
1696 | 1516 | else nil | |
1697 | 1517 | if (containsElement(oldies, newPlayer)) | |
1698 | 1518 | then throw((newPlayer + " is not newbie (already has referrals)")) | |
1699 | 1519 | else { | |
1700 | 1520 | let refByKey = keyAddressRefBy(newPlayer) | |
1701 | 1521 | let refBy = getString(refByKey) | |
1702 | 1522 | if (if (isDefined(refBy)) | |
1703 | 1523 | then isDefined(addressFromString(value(refBy))) | |
1704 | 1524 | else false) | |
1705 | 1525 | then throw(((newPlayer + " already has refBy: ") + value(refBy))) | |
1706 | 1526 | else { | |
1707 | 1527 | let refsKey = keyAddressReferrals(oldPlayer) | |
1708 | 1528 | let refs = getString(refsKey) | |
1709 | 1529 | let refsArray = if (isDefined(refs)) | |
1710 | 1530 | then split_4C(value(refs), "_") | |
1711 | 1531 | else nil | |
1712 | 1532 | if (containsElement(refsArray, newPlayer)) | |
1713 | 1533 | then throw((((oldPlayer + " already contains ") + newPlayer) + " within referrals")) | |
1714 | 1534 | else { | |
1715 | 1535 | let newRefs = makeString_2C((refsArray :+ newPlayer), "_") | |
1716 | 1536 | let newOlds = if (containsElement(oldies, oldPlayer)) | |
1717 | 1537 | then value(olds) | |
1718 | 1538 | else makeString_2C((oldies :+ oldPlayer), "_") | |
1719 | 1539 | $Tuple2(([StringEntry(refByKey, oldPlayer), StringEntry(refsKey, newRefs), StringEntry(oldsKey, newOlds)] ++ prologActions), 0) | |
1720 | 1540 | } | |
1721 | 1541 | } | |
1722 | 1542 | } | |
1723 | 1543 | } | |
1724 | 1544 | } | |
1725 | 1545 | } | |
1726 | 1546 | } | |
1727 | 1547 | ||
1728 | 1548 | ||
1729 | 1549 | ||
1730 | 1550 | @Callable(i) | |
1731 | 1551 | func distributePoints (strength,accuracy,intellect,endurance,dexterity) = { | |
1732 | 1552 | let prologActions = prolog(i) | |
1733 | 1553 | if ((size(i.payments) != 0)) | |
1734 | 1554 | then throw("No payments required") | |
1735 | 1555 | else { | |
1736 | 1556 | let addr = toString(i.originCaller) | |
1737 | 1557 | let virtWlgData = asAnyList(invoke(wlgContract, "checkWlgXpREADONLY", [addr], nil)) | |
1738 | 1558 | let virtWlgPoints = asInt(virtWlgData[1]) | |
1739 | - | let $ | |
1559 | + | let $t0100496100886 = if ((0 >= virtWlgPoints)) | |
1740 | 1560 | then $Tuple2(0, nil) | |
1741 | 1561 | else { | |
1742 | 1562 | let deltaXP = asInt(invoke(wlgContract, "takeWlgXp", [addr], nil)) | |
1743 | 1563 | if ((deltaXP == deltaXP)) | |
1744 | 1564 | then $Tuple2(virtWlgPoints, [IntegerEntry(keyUserLevel(addr), asInt(virtWlgData[0])), IntegerEntry(keyUserXP(addr), asInt(virtWlgData[2]))]) | |
1745 | 1565 | else throw("Strict value is not equal to itself.") | |
1746 | 1566 | } | |
1747 | - | let wlgPoints = $ | |
1748 | - | let wlgActions = $ | |
1567 | + | let wlgPoints = $t0100496100886._1 | |
1568 | + | let wlgActions = $t0100496100886._2 | |
1749 | 1569 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked") | |
1750 | 1570 | let freeKeyAcc = keyUserFreePoints(addr) | |
1751 | 1571 | let freePointsAcc = (valueOrElse(getInteger(freeKeyAcc), 0) + wlgPoints) | |
1752 | 1572 | let freeKeyDuck = keyDuckFreePoints(duckAssetId) | |
1753 | 1573 | let freePointsDuck = valueOrElse(getInteger(freeKeyDuck), 0) | |
1754 | 1574 | let sumFree = (freePointsAcc + freePointsDuck) | |
1755 | 1575 | let sumToDistribute = ((((strength + accuracy) + intellect) + endurance) + dexterity) | |
1756 | 1576 | if ((sumToDistribute > sumFree)) | |
1757 | 1577 | then throw((("There are only " + toString(sumFree)) + " free points to distribute")) | |
1758 | 1578 | else { | |
1759 | 1579 | let charsKey = keyDuckChars(duckAssetId) | |
1760 | 1580 | let chars = split(valueOrElse(getString(charsKey), "0_0_0_0_0"), "_") | |
1761 | 1581 | let newAcc = (freePointsAcc - sumToDistribute) | |
1762 | 1582 | $Tuple2((([IntegerEntry(freeKeyAcc, if ((0 > newAcc)) | |
1763 | 1583 | then 0 | |
1764 | 1584 | else newAcc), IntegerEntry(freeKeyDuck, if ((0 > newAcc)) | |
1765 | 1585 | then (freePointsDuck + newAcc) | |
1766 | 1586 | else freePointsDuck), StringEntry(charsKey, makeString([toString((parseIntValue(chars[charStrength]) + strength)), toString((parseIntValue(chars[charAccuracy]) + accuracy)), toString((parseIntValue(chars[charIntellect]) + intellect)), toString((parseIntValue(chars[charEndurance]) + endurance)), toString((parseIntValue(chars[charDexterity]) + dexterity))], "_"))] ++ prologActions) ++ wlgActions), 0) | |
1767 | 1587 | } | |
1768 | 1588 | } | |
1769 | 1589 | } | |
1770 | 1590 | ||
1771 | 1591 | ||
1772 | 1592 | ||
1773 | 1593 | @Callable(i) | |
1774 | 1594 | func splitByGlobalWeightsREADONLY (amount) = $Tuple2(nil, getNeededMaterials(amount)) | |
1775 | 1595 | ||
1776 | 1596 | ||
1777 | 1597 | ||
1778 | 1598 | @Callable(i) | |
1779 | 1599 | func splitByGlobalAndLocalWeightsREADONLY (matAmount,resAmount,terrains) = { | |
1780 | 1600 | let terrainCounts = countTerrains(terrains) | |
1781 | 1601 | $Tuple2(nil, $Tuple2(getNeededMaterials(matAmount), distributeByWeights(resAmount, terrainCounts))) | |
1782 | 1602 | } | |
1783 | 1603 | ||
1784 | 1604 | ||
1785 | 1605 | ||
1786 | 1606 | @Callable(i) | |
1787 | 1607 | func getBackpackREADONLY (duckAssetId) = $Tuple2(nil, makeString(getBackpack(keyBackpackByDuck(duckAssetId)), ":")) | |
1788 | 1608 | ||
1789 | 1609 | ||
1790 | 1610 | ||
1791 | 1611 | @Callable(i) | |
1792 | 1612 | func getWarehouseREADONLY (landAssetId) = { | |
1793 | 1613 | let asset = value(assetInfo(fromBase58String(landAssetId))) | |
1794 | 1614 | let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE) | |
1795 | 1615 | let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0) | |
1796 | 1616 | $Tuple2(nil, makeString_2C(getWarehouse(keyWarehouseByLand(landAssetId), landIndex, infraLevel), ":")) | |
1797 | 1617 | } | |
1798 | 1618 | ||
1799 | 1619 | ||
1800 | 1620 | ||
1801 | 1621 | @Callable(i) | |
1802 | 1622 | func saveLastTx () = if (!(containsElement([wlgContract, economyContract, tournamentContract, acresContract], i.caller))) | |
1803 | 1623 | then throw("Access denied") | |
1804 | 1624 | else $Tuple2(prolog(i), 42) | |
1805 | 1625 | ||
1806 | 1626 | ||
1807 | 1627 | ||
1808 | 1628 | @Callable(i) | |
1809 | 1629 | func updateDuckStats (duckAssetId,deltaXP) = if ((i.caller != economyContract)) | |
1810 | 1630 | then throw("Access denied") | |
1811 | 1631 | else updateDuckStatsInternal(duckAssetId, deltaXP) | |
1812 | 1632 | ||
1813 | 1633 | ||
1814 | 1634 | ||
1815 | 1635 | @Callable(i) | |
1816 | 1636 | func updateAccStats (addr,deltaXP) = if (!(containsElement([wlgContract, economyContract, acresContract], i.caller))) | |
1817 | 1637 | then throw("Access denied") | |
1818 | 1638 | else updateAccStatsInternal(addr, deltaXP) | |
1819 | 1639 | ||
1820 | 1640 | ||
1821 | 1641 | ||
1822 | 1642 | @Callable(i) | |
1823 | 1643 | func initDuckTourAttempt (duckAssetId) = if ((i.caller != tournamentContract)) | |
1824 | 1644 | then throw("Access denied") | |
1825 | 1645 | else { | |
1826 | 1646 | let keyHealth = keyDuckHealth(duckAssetId) | |
1827 | 1647 | let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0)) | |
1828 | 1648 | let curHealth = valueOrElse(getInteger(keyHealth), maxHP) | |
1829 | 1649 | let curLocKey = keyDuckLocation(duckAssetId) | |
1830 | 1650 | let curLocation = valueOrElse(getString(curLocKey), DEFAULTLOCATION) | |
1831 | 1651 | let lastId = valueOrElse(getInteger(tournamentContract, lastTourIdKey), 0) | |
1832 | 1652 | let tourLocation = (toString(lastId) + "_T_0") | |
1833 | 1653 | $Tuple2([IntegerEntry(keySavedHealth(duckAssetId), curHealth), IntegerEntry(keyHealth, maxHP), StringEntry(keySavedLocation(duckAssetId), curLocation), StringEntry(curLocKey, tourLocation)], tourLocation) | |
1834 | 1654 | } | |
1835 | 1655 | ||
1836 | 1656 | ||
1837 | 1657 | ||
1838 | 1658 | @Callable(i) | |
1839 | 1659 | func breakAttempt () = { | |
1840 | 1660 | let prologActions = prolog(i) | |
1841 | 1661 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked") | |
1842 | 1662 | let curLocKey = keyDuckLocation(duckAssetId) | |
1843 | 1663 | let curLocation = valueOrElse(getString(curLocKey), DEFAULTLOCATION) | |
1844 | 1664 | if ((split(curLocation, "_")[locIdxType] != "T")) | |
1845 | 1665 | then throw("Your duck is not in the tournament") | |
1846 | 1666 | else { | |
1847 | 1667 | let savedHealth = getIntegerValue(keySavedHealth(duckAssetId)) | |
1848 | 1668 | let savedLocation = getStringValue(keySavedLocation(duckAssetId)) | |
1849 | 1669 | $Tuple2(((prologActions :+ IntegerEntry(keyDuckHealth(duckAssetId), savedHealth)) :+ StringEntry(curLocKey, savedLocation)), curLocation) | |
1850 | 1670 | } | |
1851 | 1671 | } | |
1852 | 1672 | ||
1853 | 1673 | ||
1854 | 1674 | ||
1855 | 1675 | @Callable(i) | |
1856 | 1676 | func breakAttemptCallback () = if ((i.caller != tournamentContract)) | |
1857 | 1677 | then throw("Access denied") | |
1858 | 1678 | else { | |
1859 | 1679 | let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.originCaller))), "You don't have a duck staked") | |
1860 | 1680 | $Tuple2([IntegerEntry(keyDuckHealth(duckAssetId), getIntegerValue(keySavedHealth(duckAssetId))), StringEntry(keyDuckLocation(duckAssetId), getStringValue(keySavedLocation(duckAssetId)))], "breakAttemptCallback") | |
1861 | 1681 | } | |
1862 | 1682 | ||
1863 | 1683 | ||
1864 | 1684 | ||
1865 | 1685 | @Callable(i) | |
1866 | 1686 | func exitTournamentInternal (duckAssetId) = if ((i.caller != this)) | |
1867 | 1687 | then throw("Access denied") | |
1868 | 1688 | else { | |
1869 | 1689 | let savedHealth = getIntegerValue(keySavedHealth(duckAssetId)) | |
1870 | 1690 | let savedLocation = getStringValue(keySavedLocation(duckAssetId)) | |
1871 | 1691 | $Tuple2([IntegerEntry(keyDuckHealth(duckAssetId), savedHealth), StringEntry(keyDuckLocation(duckAssetId), savedLocation)], false) | |
1872 | 1692 | } | |
1873 | 1693 | ||
1874 | 1694 | ||
1875 | 1695 | ||
1876 | 1696 | @Callable(i) | |
1877 | 1697 | func processDelivery (duckAssetId) = if ((i.caller != this)) | |
1878 | 1698 | then throw("Access denied") | |
1879 | 1699 | else { | |
1880 | 1700 | let addr = toString(i.originCaller) | |
1881 | 1701 | let fundTotal = valueOrElse(getInteger(economyContract, deliveryFundKey), 0) | |
1882 | 1702 | if ((MIN_USDT_FEE_DELIVERY > fundTotal)) | |
1883 | 1703 | then throw(("Delivery is not available, fund=" + fixedPoint(fundTotal, 6))) | |
1884 | 1704 | else { | |
1885 | 1705 | let now = lastBlock.timestamp | |
1886 | 1706 | let countKey = keyUserDeliveryCount(addr) | |
1887 | 1707 | let lastDay = valueOrElse(getInteger(keyUserLastDeliveryDay(addr)), 0) | |
1888 | 1708 | let today = (now / DAYMILLIS) | |
1889 | 1709 | let count = if ((lastDay == today)) | |
1890 | 1710 | then valueOrElse(getInteger(countKey), 0) | |
1891 | 1711 | else 0 | |
1892 | 1712 | let acres = valueOrElse(getInteger(acresContract, keyAcresStakedAmountByUser(addr)), 0) | |
1893 | 1713 | let allowedDeliveries = (ALLOWED_FREE_DELIVERIES + (acres / ACRES_FOR_DELIVERY_ATTEMPT)) | |
1894 | 1714 | if ((count >= allowedDeliveries)) | |
1895 | 1715 | then throw((("You already used " + toString(allowedDeliveries)) + " delivery attempts for today")) | |
1896 | 1716 | else { | |
1897 | 1717 | let globalCountKey = keyDuckDeliveryCount(duckAssetId) | |
1898 | 1718 | let reward = invoke(economyContract, "sendDeliveryReward", [addr], nil) | |
1899 | 1719 | $Tuple2([IntegerEntry(countKey, (count + 1)), IntegerEntry(keyUserLastDeliveryDay(addr), today), IntegerEntry(globalCountKey, (valueOrElse(getInteger(globalCountKey), 0) + 1))], reward) | |
1900 | 1720 | } | |
1901 | 1721 | } | |
1902 | 1722 | } | |
1903 | 1723 | ||
1904 | 1724 |
github/deemru/w8io/026f985 191.98 ms ◑