tx · AvcsySzhYmHuF2C9zKs3pA79hSTp6TY4GpQPiGXMvuSb

3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm:  -0.09900000 Waves

2023.11.23 20:24 [2856325] smart account 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm > SELF 0.00000000 Waves

{ "type": 13, "id": "AvcsySzhYmHuF2C9zKs3pA79hSTp6TY4GpQPiGXMvuSb", "fee": 9900000, "feeAssetId": null, "timestamp": 1700760270849, "version": 2, "chainId": 84, "sender": "3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm", "senderPublicKey": "EVooykMNV691Venwp1dHUTBd7KWequzUcda57Wd3LQEX", "proofs": [ "ovHsXcVkdnqXYud999X2vtXkZvrmKcg3UP6jSeZckPPmh8Z1UaamnTzqi6v3NVHqk5o4D7iURWb8AdpSCudr1iJ" ], "script": "base64:BgLUAQgCEgMKAQgSBAoCCAESAwoBBBIAEgMKAQgSABIDCgEIEgQKAgEIEgQKAgEIEgQKAgICEgUKAwEBARIAEgQKAggIEgASAwoBARIAEgQKAgICEgASAwoBCBIECgIICBIDCgEYEgQKAggIEgQKAggIEgUKAwgICBIECgIICBIHCgUBAQEBARIDCgEBEgUKAwEBCBIDCgEIEgMKAQgSABIECgIIARIECgIIARIDCgEIEgQKAggIEgMKAQgSABIAEgMKAQgSAwoBCBIECgICAhIECgICAhIAnAIACURBWU1JTExJUwCAuJkpARRrZXlMYXN0QXJiVGltZUJ5VXNlcgEEYWRkcgkArAICAhBsYXN0QXJiVGltZVVzZXJfBQRhZGRyARprZXlBY3Jlc1N0YWtlZEFtb3VudEJ5VXNlcgEEYWRkcgkArAICAhhhY3Jlc1N0YWtlZEFtb3VudEJ5VXNlcl8FBGFkZHIABlNDQUxFOACAwtcvAAx4cExldmVsU2NhbGUAgBkAD3hwTGV2ZWxSZWNpcFBvdwCgHwASbnVtUG9pbnRzT25MZXZlbFVwAAMADnJvYmJlcnlDb3N0TWluAIDC1y8AFHJvYmJlcnlDb29sZG93bkNvZWZmAJADAAxyZXF1aXJlbWVudHMJAMwIAgIIU3RyZW5ndGgJAMwIAgIIQWNjdXJhY3kJAMwIAgIJSW50ZWxsZWN0CQDMCAICCUVuZHVyYW5jZQkAzAgCAglEZXh0ZXJpdHkJAMwIAgIFTGV2ZWwJAMwIAgIGSGVhbHRoBQNuaWwADGNoYXJTdHJlbmd0aAAAAAxjaGFyQWNjdXJhY3kAAQANY2hhckludGVsbGVjdAACAA1jaGFyRW5kdXJhbmNlAAMADWNoYXJEZXh0ZXJpdHkABAALc2VnQmFja3BhY2sAAAALTlVNU0VHTUVOVFMABgAKTlVNTUFJTkFVWAACAAhNQVhTTE9UUwACAA1NQVhQUk9ESU5TTE9UAB4AEGxhbmRSb2JDb29sZG93bnMJAMwIAgAACQDMCAIAwM8kCQDMCAIAoPc2CQDMCAIAgNzMFAkAzAgCAICupgoFA25pbAAOTUlOX1JFU19UT19ST0IAgNrECQAMcm9iSWR4TG9ja2VkAAEAC2R1Y2tJZHhGcmVlAAAAEGR1Y2tJZHhQcmVwYXJpbmcAAQENa2V5RHVja0hlYWx0aAELZHVja0Fzc2V0SWQJAKwCAgILZHVja0hlYWx0aF8FC2R1Y2tBc3NldElkAQxrZXlEdWNrQ2hhcnMBC2R1Y2tBc3NldElkCQCsAgICCmR1Y2tDaGFyc18FC2R1Y2tBc3NldElkAQlrZXlEdWNrWFABC2R1Y2tBc3NldElkCQCsAgICB2R1Y2tYUF8FC2R1Y2tBc3NldElkAQxrZXlEdWNrTGV2ZWwBC2R1Y2tBc3NldElkCQCsAgICCmR1Y2tMZXZlbF8FC2R1Y2tBc3NldElkARFrZXlEdWNrRnJlZVBvaW50cwELZHVja0Fzc2V0SWQJAKwCAgIPZHVja0ZyZWVQb2ludHNfBQtkdWNrQXNzZXRJZAEQa2V5RHVja0VxdWlwbWVudAELZHVja0Fzc2V0SWQJAKwCAgIOZHVja0VxdWlwbWVudF8FC2R1Y2tBc3NldElkAQlrZXlVc2VyWFABBGFkZHIJAKwCAgIHdXNlclhQXwUEYWRkcgEMa2V5VXNlckxldmVsAQRhZGRyCQCsAgICCnVzZXJMZXZlbF8FBGFkZHIBEWtleVVzZXJGcmVlUG9pbnRzAQRhZGRyCQCsAgICD3VzZXJGcmVlUG9pbnRzXwUEYWRkcgEOa2V5U2F2ZWRIZWFsdGgBC2R1Y2tBc3NldElkCQCsAgICDHNhdmVkSGVhbHRoXwULZHVja0Fzc2V0SWQBEGtleVNhdmVkTG9jYXRpb24BC2R1Y2tBc3NldElkCQCsAgICDnNhdmVkTG9jYXRpb25fBQtkdWNrQXNzZXRJZAEMa2V5RHVja0J1ZmZzAQtkdWNrQXNzZXRJZAkArAICAgpkdWNrQnVmZnNfBQtkdWNrQXNzZXRJZAEYa2V5TGFzdFJvYmJlcnlUaW1lQnlEdWNrAQtkdWNrQXNzZXRJZAkArAICAhBsYXN0Um9iYmVyeVRpbWVfBQtkdWNrQXNzZXRJZAEYa2V5TGFzdFJvYmJlcnlDb3N0QnlEdWNrAQtkdWNrQXNzZXRJZAkArAICAhBsYXN0Um9iYmVyeUNvc3RfBQtkdWNrQXNzZXRJZAETa2V5TGFuZFJvYmJlcnlTdGF0ZQELbGFuZEFzc2V0SWQJAKwCAgIRbGFuZFJvYmJlcnlTdGF0ZV8FC2xhbmRBc3NldElkARJrZXlMYW5kQ29vbGRvd25FVEEBC2xhbmRBc3NldElkCQCsAgICEGxhbmRDb29sZG93bkVUQV8FC2xhbmRBc3NldElkARNrZXlEdWNrUm9iYmVyeVN0YXRlAQtkdWNrQXNzZXRJZAkArAICAhFkdWNrUm9iYmVyeVN0YXRlXwULZHVja0Fzc2V0SWQBE2tleUxvY2tlZExhbmRCeUR1Y2sBC2R1Y2tBc3NldElkCQCsAgICEWxvY2tlZExhbmRCeUR1Y2tfBQtkdWNrQXNzZXRJZAEUa2V5VXNlckRlbGl2ZXJ5Q291bnQBBGFkZHIJAKwCAgISdXNlckRlbGl2ZXJ5Q291bnRfBQRhZGRyARZrZXlVc2VyTGFzdERlbGl2ZXJ5RGF5AQRhZGRyCQCsAgICFHVzZXJMYXN0RGVsaXZlcnlEYXlfBQRhZGRyAAd4cENsYWltAJBOAA94cFN1Y2Nlc3NGbGlnaHQAkE4ADHhwRmFpbEZsaWdodADQDwAIeHBDYWxsRVMAoI0GAAx4cEN1c3RvbU5hbWUAwIQ9AAp4cE5ld1NMYW5kAMCWsQIADnhwVXBncmFkZUluZnJhAJBOAAd4cE1lcmdlAMCEPQAJeHBPbmJvYXJkAMCEPQAGeHBIZWFsAJBOAQlsZXZlbEJ5WFABAnhwCQBrAwUMeHBMZXZlbFNjYWxlCQBsBgUCeHAABAUPeHBMZXZlbFJlY2lwUG93AAQABAUERE9XTgUGU0NBTEU4AQltYXhIZWFsdGgBBWxldmVsCQBkAgBkBQVsZXZlbAEHbGV2ZWxVcAIJY3VyckxldmVsBW5ld1hQBAhuZXdMZXZlbAkBCWxldmVsQnlYUAEFBW5ld1hQCQDMCAIFCG5ld0xldmVsCQDMCAIJAGgCBRJudW1Qb2ludHNPbkxldmVsVXAJAGUCBQhuZXdMZXZlbAUJY3VyckxldmVsBQNuaWwBDGdldER1Y2tTdGF0cwQPc3Rha2luZ0NvbnRyYWN0C2R1Y2tBc3NldElkCmJ1ZmZFZmZlY3QKZm9yY2VCdWZmcwQFY2hhcnMJALUJAgkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJAQxrZXlEdWNrQ2hhcnMBBQtkdWNrQXNzZXRJZAIJMF8wXzBfMF8wAgFfBANsdmwJAQt2YWx1ZU9yRWxzZQIJAJoIAgUPc3Rha2luZ0NvbnRyYWN0CQEMa2V5RHVja0xldmVsAQULZHVja0Fzc2V0SWQAAAQGaGVhbHRoCQELdmFsdWVPckVsc2UCCQCaCAIFD3N0YWtpbmdDb250cmFjdAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAkBCW1heEhlYWx0aAEFA2x2bAQKc3RhdGVCdWZmcwkAtQkCCQELdmFsdWVPckVsc2UCCQCdCAIFD3N0YWtpbmdDb250cmFjdAkBDGtleUR1Y2tCdWZmcwEFC2R1Y2tBc3NldElkAgkwXzBfMF8wXzACAV8JAM4IAgkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDGNoYXJTdHJlbmd0aAkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDGNoYXJBY2N1cmFjeQkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJJbnRlbGxlY3QJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWNoYXJzBQ1jaGFyRW5kdXJhbmNlCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVjaGFycwUNY2hhckRleHRlcml0eQkAzAgCBQNsdmwJAMwIAgUGaGVhbHRoBQNuaWwDBQpmb3JjZUJ1ZmZzCQDMCAIFCmJ1ZmZFZmZlY3QJAMwIAgUKYnVmZkVmZmVjdAkAzAgCBQpidWZmRWZmZWN0CQDMCAIFCmJ1ZmZFZmZlY3QJAMwIAgUKYnVmZkVmZmVjdAUDbmlsCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpzdGF0ZUJ1ZmZzBQxjaGFyU3RyZW5ndGgJAMwIAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCnN0YXRlQnVmZnMFDGNoYXJBY2N1cmFjeQkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKc3RhdGVCdWZmcwUNY2hhckludGVsbGVjdAkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKc3RhdGVCdWZmcwUNY2hhckVuZHVyYW5jZQkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUKc3RhdGVCdWZmcwUNY2hhckRleHRlcml0eQUDbmlsAQ5nZXRSb2JiZXJ5RGF0YQIPc3Rha2luZ0NvbnRyYWN0C2R1Y2tBc3NldElkBAtsYXN0Um9iQ29zdAkBC3ZhbHVlT3JFbHNlAgkAmggCBQ9zdGFraW5nQ29udHJhY3QJARhrZXlMYXN0Um9iYmVyeUNvc3RCeUR1Y2sBBQtkdWNrQXNzZXRJZAAABAtsYXN0Um9iVGltZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQ9zdGFraW5nQ29udHJhY3QJARhrZXlMYXN0Um9iYmVyeVRpbWVCeUR1Y2sBBQtkdWNrQXNzZXRJZAAABANub3cIBQlsYXN0QmxvY2sJdGltZXN0YW1wBAdyb2JDb3N0CQCWAwEJAMwIAgUOcm9iYmVyeUNvc3RNaW4JAMwIAgkAZQIFC2xhc3RSb2JDb3N0CQBoAgUUcm9iYmVyeUNvb2xkb3duQ29lZmYJAGUCBQNub3cFC2xhc3RSb2JUaW1lBQNuaWwECWR1Y2tTdGF0ZQkBC3ZhbHVlT3JFbHNlAgkAmggCBQ9zdGFraW5nQ29udHJhY3QJARNrZXlEdWNrUm9iYmVyeVN0YXRlAQULZHVja0Fzc2V0SWQAAAQKbG9ja2VkTGFuZAkBC3ZhbHVlT3JFbHNlAgkAnQgCBQ9zdGFraW5nQ29udHJhY3QJARNrZXlMb2NrZWRMYW5kQnlEdWNrAQULZHVja0Fzc2V0SWQCAAQHbGFuZEVUQQkBC3ZhbHVlT3JFbHNlAgkAmggCBQ9zdGFraW5nQ29udHJhY3QJARJrZXlMYW5kQ29vbGRvd25FVEEBBQpsb2NrZWRMYW5kAAAJAJcKBQUHcm9iQ29zdAULbGFzdFJvYlRpbWUFCWR1Y2tTdGF0ZQUKbG9ja2VkTGFuZAUHbGFuZEVUQQAKTEFORFBSRUZJWAIETEFORAAKRFVDS1BSRUZJWAIERFVDSwALUk9CT19QUkVGSVgCBFJPQk8ACkFSVFBSRVNBTEUCB1BSRVNBTEUABk5VTVJFUwAGABhNQVhfTEFORFNfU1RBS0VEX0JZX1VTRVIAGQAPREFJTFlSRVNCWVBJRUNFAID40gEADFdITVVMVElQTElFUgCAyK+gJQAPREVGQVVMVExPQ0FUSU9OAg9BZnJpY2FfRl9BZnJpY2EAEFJFU09VUkNFUFJJQ0VNSU4A1bUCAApFU1NFTExDT0VGAAoAFU1JTl9VU0RUX0ZFRV9ERUxJVkVSWQDQhgMAF0FMTE9XRURfRlJFRV9ERUxJVkVSSUVTAAEAGkFDUkVTX0ZPUl9ERUxJVkVSWV9BVFRFTVBUAIDh6xcACXByb2RUeXBlcwkAzAgCAhBGaXJzdCBBaWQgS2l0IEwxCQDMCAICEEZpcnN0IEFpZCBLaXQgTDIJAMwIAgIQRmlyc3QgQWlkIEtpdCBMMwkAzAgCAgtCYWNrcGFjayBMMQkAzAgCAgtCYWNrcGFjayBMMgkAzAgCAgtCYWNrcGFjayBMMwkAzAgCAg5Gb29kIFJhdGlvbiBMMQkAzAgCAg5Gb29kIFJhdGlvbiBMMgkAzAgCAg5Gb29kIFJhdGlvbiBMMwkAzAgCAgtKZXQgUGFjayBMMQkAzAgCAgtKZXQgUGFjayBMMgkAzAgCAgtKZXQgUGFjayBMMwkAzAgCAglTaGllbGQgTDEJAMwIAgIJU2hpZWxkIEwyCQDMCAICCVNoaWVsZCBMMwkAzAgCAgdNaW5lIEwxCQDMCAICB01pbmUgTDIJAMwIAgIHTWluZSBMMwkAzAgCAgdUcmFwIEwxCQDMCAICB1RyYXAgTDIJAMwIAgIHVHJhcCBMMwkAzAgCAgtCb29tLURvZyBMMQkAzAgCAgtCb29tLURvZyBMMgkAzAgCAgtCb29tLURvZyBMMwUDbmlsAApjb250aW5lbnRzCQDMCAICCEFtZXJpY2FzCQDMCAICBkV1cm9wZQkAzAgCAgRBc2lhCQDMCAICBkFmcmljYQkAzAgCAgdPY2VhbmlhBQNuaWwACUNPRUZGMk1BVACAreIEABBmb3J0QWxsb3dlZFByb2RzCQDMCAIADwkAzAgCABAJAMwIAgARCQDMCAIAEgkAzAgCABMJAMwIAgAUCQDMCAIAFQkAzAgCABYJAMwIAgAXBQNuaWwAEHByb2R1Y3Rpb25NYXRyaXgJAMwIAgIlOF84XzhfMTdfMTdfNDJfMTJfMF8zMF8wLDAsMCwwLDAsMCwwXwkAzAgCAiU4XzhfOF8xN18xN180Ml8yNF8wXzYwXzAsMCw1LDIsMCwwLDBfCQDMCAICJzhfOF84XzE3XzE3XzQyXzM2XzBfMTIwXzAsMCwxMCw0LDAsMCwwXwkAzAgCAik4XzE5XzE5XzhfMjdfMTlfMjZfMV8yMF8wLDAsMCwwLDAsMCwwXzAwMQkAzAgCAik4XzE5XzE5XzhfMjdfMTlfNTJfMV80MF8wLDAsMCwwLDAsMCwwXzAwMQkAzAgCAik4XzE5XzE5XzhfMjdfMTlfNzhfMV84MF8wLDAsMCwwLDAsMCwwXzAwMQkAzAgCAiU4XzhfOF84XzhfNjBfMTNfMl8yXzAsMCwwLDAsMCwwLDBfMDExCQDMCAICJThfOF84XzhfOF82MF8yNl8yXzRfMCwwLDAsMCwwLDAsMF8wMTEJAMwIAgIlOF84XzhfOF84XzYwXzM5XzJfOF8wLDAsMCwwLDAsMCwwXzAxMQkAzAgCAikzMF8zMF8zXzE3XzE3XzNfMzBfM18zMF8wLDAsMCwwLDAsMCwwXzExMQkAzAgCAikzMF8zMF8zXzE3XzE3XzNfNjBfM181MF8wLDAsMCwwLDAsMCwwXzExMQkAzAgCAikzMF8zMF8zXzE3XzE3XzNfOTBfM183MF8wLDAsMCwwLDAsMCwwXzExMQkAzAgCAisxOF8xOF8xMF8xOF8xOF8xOF8xMV80XzEwXzAsMCwwLDAsMCwwLDBfMjAxCQDMCAICKzE4XzE4XzEwXzE4XzE4XzE4XzIyXzRfMjBfMCwwLDAsMCwwLDAsMF8yMDEJAMwIAgIrMThfMThfMTBfMThfMThfMThfMzNfNF8zMF8wLDAsMCwwLDAsMCwwXzIwMQkAzAgCAio0XzEzXzIyXzRfMzVfMjJfMjNfMF81MCwxLDBfMCwwLDAsMCwwLDAsMF8JAMwIAgIqNF8xM18yMl80XzM1XzIyXzQ2XzBfNTAsMSwxXzAsMiw1LDAsMCwwLDBfCQDMCAICKzRfMTNfMjJfNF8zNV8yMl82OV8wXzUwLDIsMV8wLDUsMTAsMCwwLDAsMF8JAMwIAgIqNV8yNV80MF81XzEwXzE1XzIwXzFfMzAsMSwxXzAsMCwwLDAsMCwwLDBfCQDMCAICKjVfMjVfNDBfNV8xMF8xNV80MF8xXzMwLDEsMl8yLDEsMywwLDAsMCwwXwkAzAgCAio1XzI1XzQwXzVfMTBfMTVfNjBfMV8zMCwxLDNfNSwyLDgsMCwwLDAsMF8JAMwIAgInMjNfMjNfNV8yMF8yM182XzM1XzJfMTAwXzAsMCwwLDAsMCwwLDBfCQDMCAICJzIzXzIzXzVfMjBfMjNfNl83MF8yXzE1MF8wLDAsMCwwLDAsMCwwXwkAzAgCAigyM18yM181XzIwXzIzXzZfMTA1XzJfMjAwXzAsMCwwLDAsMCwwLDBfBQNuaWwACXJJZHhDb2VmZgAGAApySWR4RWZmZWN0AAgAEHJJZHhSZXF1aXJlbWVudHMACQAJcklkeFNsb3RzAAoADlBST0RVQ1RQS0dTSVpFAAoAC3doSWR4TGV2ZWxzAAAACHdoSWR4UmVzAAEACHdoSWR4TWF0AAIACXdoSWR4UHJvZAADAAl3aElkeExPRlQABAAJdm9sTG9ja2VkAAAAC3ZvbE9jY3VwaWVkAAEAB3ZvbEZyZWUAAgAIdm9sVG90YWwAAwAKYnBJZHhMZXZlbAAAAAhicElkeFJlcwABAAhicElkeE1hdAACAAlicElkeFByb2QAAwAPbG9jSWR4Q29udGluZW50AAAACmxvY0lkeFR5cGUAAQAIbG9jSWR4SWQAAgEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQdhc3NldElkCQCsAgICA25vXwUHYXNzZXRJZAEaa2V5TGFuZEFzc2V0SWRUb0N1c3RvbU5hbWUBB2Fzc2V0SWQJAKwCAgIFbGNuYV8FB2Fzc2V0SWQBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBB2Fzc2V0SWQJAKwCAgIDc3RfBQdhc3NldElkASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIEdHlwZQdhc3NldElkCQC5CQIJAMwIAgIDbGFzCQDMCAIFBHR5cGUJAMwIAgUHYXNzZXRJZAUDbmlsAgFfASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwduZnRUeXBlB2Fzc2V0SWQJb3duZXJBZGRyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIGc3R0YW9fBQduZnRUeXBlAgFfBQdhc3NldElkAgFfBQlvd25lckFkZHIBEmtleVdhcmVob3VzZUJ5TGFuZAELbGFuZEFzc2V0SWQJAKwCAgIDd2hfBQtsYW5kQXNzZXRJZAEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEHYXNzZXRJZAkArAICAgtpbmZyYUxldmVsXwUHYXNzZXRJZAEXa2V5Rm9ydGlmaWNhdGlvbnNCeUxhbmQBC2xhbmRBc3NldElkCQCsAgICD2ZvcnRpZmljYXRpb25zXwULbGFuZEFzc2V0SWQBGmtleUR1Y2tBc3NldElkVG9DdXN0b21OYW1lAQdhc3NldElkCQCsAgICGGR1Y2tDdXN0b21OYW1lQnlBc3NldElkXwUHYXNzZXRJZAEWa2V5QWRkcmVzc1RvQ3VzdG9tTmFtZQEEYWRkcgkArAICAhhhY2NvdW50Q3VzdG9tTmFtZUJ5QWRkcl8FBGFkZHIBD2tleUFkZHJlc3NSZWZCeQEEYWRkcgkArAICAglhY2NSZWZCeV8FBGFkZHIBHGtleU9uYm9hcmRBcnRBY3RpdmF0ZWRPbkR1Y2sBC2R1Y2tBc3NldElkCQCsAgICGm9uYm9hcmRBcnRBY3RpdmF0ZWRPbkR1Y2tfBQtkdWNrQXNzZXRJZAEca2V5T25ib2FyZEFydER1Y2tBY3RpdmF0ZWRCeQEEYWRkcgkArAICAhpvbmJvYXJkQXJ0QWN0aXZhdGVkRHVja0J5XwUEYWRkcgETa2V5QWRkcmVzc1JlZmVycmFscwEEYWRkcgkArAICAg1hY2NSZWZlcnJhbHNfBQRhZGRyARBrZXlEdWNrSWRUb093bmVyAQdhc3NldElkCQCsAgICCmR1Y2tPd25lcl8FB2Fzc2V0SWQBFGtleVN0YWtlZER1Y2tCeU93bmVyAQlvd25lckFkZHIJAKwCAgISc3Rha2VkRHVja0J5T3duZXJfBQlvd25lckFkZHIBEWtleUJhY2twYWNrQnlEdWNrAQtkdWNrQXNzZXRJZAkArAICAgliYWNrUGFja18FC2R1Y2tBc3NldElkAQ9rZXlEdWNrTG9jYXRpb24BC2R1Y2tBc3NldElkCQCsAgICDWR1Y2tMb2NhdGlvbl8FC2R1Y2tBc3NldElkARVrZXlVc2VyR3dsUmVsZWFzZVRpbWUBCHVzZXJBZGRyCQCsAgICGiVzJXNfX3VzZXJHd2xSZWxlYXNlVGltZV9fBQh1c2VyQWRkcgEOa2V5RXNXYXJlaG91c2UAAhplbWVyZ2VuY3lXYXJlaG91c2VQcm9kdWN0cwAPZGVsaXZlcnlGdW5kS2V5AgxkZWxpdmVyeUZ1bmQADWxhc3RUb3VySWRLZXkCDiVzX19sYXN0VG91cklkARVrZXlUb3VyU3RhdGljRGF0YUJ5SWQBA3RJZAkArAICAhYlcyVkX190b3VyU3RhdGljRGF0YV9fCQCkAwEFA3RJZAEWa2V5VG91ckR5bmFtaWNEYXRhQnlJZAEDdElkCQCsAgICFyVzJWRfX3RvdXJEeW5hbWljRGF0YV9fCQCkAwEFA3RJZAEaa2V5QmVzdFJlc3VsdEJ5VG91ckFuZER1Y2sCA3RJZAtkdWNrQXNzZXRJZAkAuQkCCQDMCAICHyVzJWQlc19fYmVzdFJlc3VsdEJ5VG91ckFuZER1Y2sJAMwIAgkApAMBBQN0SWQJAMwIAgULZHVja0Fzc2V0SWQFA25pbAICX18ACWlkeFN0YXRpYwAAAAppZHhEeW5hbWljAAEACnRTdGF0aWNFbmQABgAOdER5bmFtaWNTdGF0dXMAAQELZ2V0VG91ckRhdGECDHRvdXJDb250cmFjdAN0SWQEBnN0YXRpYwkAtQkCCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUMdG91ckNvbnRyYWN0CQEVa2V5VG91clN0YXRpY0RhdGFCeUlkAQUDdElkCQCsAgIJAKwCAgIZRXJyb3IgcmVhZGluZyB0b3VybmFtZW50IAkApAMBBQN0SWQCBSBkYXRhAgJfXwQHZHluYW1pYwkAvAkCCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ0IAgUMdG91ckNvbnRyYWN0CQEWa2V5VG91ckR5bmFtaWNEYXRhQnlJZAEFA3RJZAkArAICCQCsAgICGUVycm9yIHJlYWRpbmcgdG91cm5hbWVudCAJAKQDAQUDdElkAgUgZGF0YQICX18JAMwIAgUGc3RhdGljCQDMCAIFB2R5bmFtaWMFA25pbAEOaXNJblRvdXJuYW1lbnQCDHRvdXJDb250cmFjdAhsb2NhdGlvbgQGbGFzdElkCQELdmFsdWVPckVsc2UCCQCaCAIFDHRvdXJDb250cmFjdAUNbGFzdFRvdXJJZEtleQAABANsb2MJALUJAgUIbG9jYXRpb24CAV8EA25vdwgFCWxhc3RCbG9jawl0aW1lc3RhbXAEBXREYXRhCQELZ2V0VG91ckRhdGECBQx0b3VyQ29udHJhY3QFBmxhc3RJZAQGc3RhdGljCQCRAwIFBXREYXRhBQlpZHhTdGF0aWMEB2R5bmFtaWMJAJEDAgUFdERhdGEFCmlkeER5bmFtaWMDAwMJAAACCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIBVAkAAAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQNsb2MFD2xvY0lkeENvbnRpbmVudAUGbGFzdElkBwkAAAIJAJEDAgUHZHluYW1pYwUOdER5bmFtaWNTdGF0dXMCCklOUFJPR1JFU1MHCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBnN0YXRpYwUKdFN0YXRpY0VuZAUDbm93BwEJb25NaXNzaW9uAgx0b3VyQ29udHJhY3QIbG9jYXRpb24EBmxhc3RJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBQx0b3VyQ29udHJhY3QFDWxhc3RUb3VySWRLZXkAAAQDbG9jCQC1CQIFCGxvY2F0aW9uAgFfBANub3cIBQlsYXN0QmxvY2sJdGltZXN0YW1wBAV0RGF0YQkBC2dldFRvdXJEYXRhAgUMdG91ckNvbnRyYWN0BQZsYXN0SWQEBnN0YXRpYwkAkQMCBQV0RGF0YQUJaWR4U3RhdGljBAdkeW5hbWljCQCRAwIFBXREYXRhBQppZHhEeW5hbWljBAdsb2NUeXBlCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQMDAwkAAAIJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAgFUCQAAAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFA2xvYwUPbG9jSWR4Q29udGluZW50BQZsYXN0SWQHCQAAAgkAkQMCBQdkeW5hbWljBQ50RHluYW1pY1N0YXR1cwIKSU5QUk9HUkVTUwcJAGYCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGc3RhdGljBQp0U3RhdGljRW5kBQNub3cHARJnZXRSZWNpcGVNYXRlcmlhbHMBBnJlY2lwZQkAaAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZyZWNpcGUFCXJJZHhDb2VmZgUJQ09FRkYyTUFUAQxjaGVhdEF0dGVtcHQDBm9sZExvYwZuZXdMb2MJY2hlYXRDYXNlCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICFkNoZWF0IGF0dGVtcHQ6IG9sZExvYz0FBm9sZExvYwIJLCBuZXdMb2M9BQZuZXdMb2MCBywgY2FzZT0JAKQDAQUJY2hlYXRDYXNlABZLU19TRVBBUkFURV9QVUJMSUNfS0VZBwAYS1NfQUxMT1dfQklHX0lORlJBX01FUkdFBwATS1NfQUxMT1dfUk9CT19EVUNLUwcACkRBWV9NSUxMSVMAgLiZKQAFY2hhaW4JAMkBAgkAygECCAUEdGhpcwVieXRlcwABAAEAA3B1YgQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAMFFktTX1NFUEFSQVRFX1BVQkxJQ19LRVkBIKsXV48VZ+NZVEGw1nLrZpvEo9NmXtWZhlDfmDcfsgkIASBPU+IaP1So1p1SThMdRidVvbNT8yx7yVRUsP9DwbQUKAMJAAACAQFUBQckbWF0Y2gwASBPU+IaP1So1p1SThMdRidVvbNT8yx7yVRUsP9DwbQUKAkAAgECDVVua25vd24gY2hhaW4AC3VzZHRBc3NldElkBAckbWF0Y2gwBQVjaGFpbgMJAAACAQFXBQckbWF0Y2gwASCE2nqyCAM/TtG7yo7ui5O8yYLdC136B5ao1CP5qA//uQMJAAACAQFUBQckbWF0Y2gwASBVsdifcoeC7+XjW42sBatl3ppDoS8WuwXzGreHpfHFGAkAAgECDVVua25vd24gY2hhaW4AFWRlZmF1bHRSZXN0QWRkcmVzc1N0cgQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAIjM1BRQ3V2RmJ2aDRMa1BVbnJuVTF6M2puYkExcDltM1dOaHYDCQAAAgEBVAUHJG1hdGNoMAIjM011bWtHR3p0Q0tBWHBXRHF4a2Rkb2ZxWFNVYnFRa3ZTSnkJAAIBAg1Vbmtub3duIGNoYWluABFJbmZyYVVwZ3JhZGVDb3N0UwQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMACAyK+gJQMJAAACAQFUBQckbWF0Y2gwAIDC1y8JAAIBAg1Vbmtub3duIGNoYWluAA5hcmJpdHJhZ2VEZWxheQQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAUKREFZX01JTExJUwMJAAACAQFUBQckbWF0Y2gwAODUAwkAAgECDVVua25vd24gY2hhaW4AA1NFUAICX18ABU1VTFQ2AMCEPQAFTVVMVDgAgMLXLwAFU1NJWkUAGQAFTVNJWkUAZAAFTFNJWkUA4QEABlhMU0laRQCQAwAHWFhMU0laRQDxBAAFSVRFUjYJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUFA25pbAEPZ2V0U3RyaW5nT3JGYWlsAgdhZGRyZXNzA2tleQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCdCAIFB2FkZHJlc3MFA2tleQkAuQkCCQDMCAICCm1hbmRhdG9yeSAJAMwIAgkApQgBBQdhZGRyZXNzCQDMCAICAS4JAMwIAgUDa2V5CQDMCAICDyBpcyBub3QgZGVmaW5lZAUDbmlsAgAAEUlkeENmZ1N0YWtpbmdEYXBwAAEAEUlkeENmZ0Vjb25vbXlEYXBwAAIAFElkeENmZ0dvdmVybmFuY2VEYXBwAAMADUlkeENmZ1dsZ0RhcHAABAAUSWR4Q2ZnVG91cm5hbWVudERhcHAABwAPSWR4Q2ZnQWNyZXNEYXBwAAgBCmtleVJlc3RDZmcAAg4lc19fcmVzdENvbmZpZwEOa2V5UmVzdEFkZHJlc3MAAgwlc19fcmVzdEFkZHIBEXJlYWRSZXN0Q2ZnT3JGYWlsAQRyZXN0CQC8CQIJAQ9nZXRTdHJpbmdPckZhaWwCBQRyZXN0CQEKa2V5UmVzdENmZwAFA1NFUAEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgdyZXN0Q2ZnA2lkeAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCmCAEJAJEDAgUHcmVzdENmZwUDaWR4CQCsAgICKlJlc3QgY2ZnIGRvZXNuJ3QgY29udGFpbiBhZGRyZXNzIGF0IGluZGV4IAkApAMBBQNpZHgADHJlc3RDb250cmFjdAkBEUBleHRyTmF0aXZlKDEwNjIpAQkBC3ZhbHVlT3JFbHNlAgkAnQgCBQR0aGlzCQEOa2V5UmVzdEFkZHJlc3MABRVkZWZhdWx0UmVzdEFkZHJlc3NTdHIAB3Jlc3RDZmcJARFyZWFkUmVzdENmZ09yRmFpbAEFDHJlc3RDb250cmFjdAAPc3Rha2luZ0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwURSWR4Q2ZnU3Rha2luZ0RhcHAAD2Vjb25vbXlDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFB3Jlc3RDZmcFEUlkeENmZ0Vjb25vbXlEYXBwAAtnb3ZDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFB3Jlc3RDZmcFFElkeENmZ0dvdmVybmFuY2VEYXBwAAt3bGdDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFB3Jlc3RDZmcFDUlkeENmZ1dsZ0RhcHAAEnRvdXJuYW1lbnRDb250cmFjdAkBGGdldENvbnRyYWN0QWRkcmVzc09yRmFpbAIFB3Jlc3RDZmcFFElkeENmZ1RvdXJuYW1lbnREYXBwAA1hY3Jlc0NvbnRyYWN0CQEYZ2V0Q29udHJhY3RBZGRyZXNzT3JGYWlsAgUHcmVzdENmZwUPSWR4Q2ZnQWNyZXNEYXBwAApyZWNMYW5kTnVtAAAAC3JlY0xhbmRTaXplAAEAC3JlY1RlcnJhaW5zAAIADHJlY0NvbnRpbmVudAADAA13bGdBc3NldElkS2V5Agt3bGdfYXNzZXRJZAAKd2xnQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCcCAIFC3dsZ0NvbnRyYWN0BQ13bGdBc3NldElkS2V5AhhXTEdPTEQgaXMgbm90IGlzc3VlZCB5ZXQAD2FjcmVzQXNzZXRJZEtleQIMYWNyZXNBc3NldElkAAxhY3Jlc0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnAgCBQ1hY3Jlc0NvbnRyYWN0BQ9hY3Jlc0Fzc2V0SWRLZXkCF0FDUkVTIGlzIG5vdCBpc3N1ZWQgeWV0AAtyYW5kb21EZWxheQACAQlrZXlDb21taXQBB2FkZHJlc3MJAKwCAgITZmluaXNoQmxvY2tGb3JBZGRyXwUHYWRkcmVzcwERa2V5UmVzUHJvcG9ydGlvbnMAAhNyZXNUeXBlc1Byb3BvcnRpb25zARZrZXlSZXNUeXBlc0J5Q29udGluZW50AQljb250aW5lbnQJAKwCAgIUcmVzVHlwZXNCeUNvbnRpbmVudF8FCWNvbnRpbmVudAEVa2V5U3Rha2VkTGFuZHNCeU93bmVyAQlvd25lckFkZHIJAKwCAgITc3Rha2VkTGFuZHNCeU93bmVyXwUJb3duZXJBZGRyARZrZXlTdGFrZWRQaWVjZXNCeU93bmVyAQlvd25lckFkZHIJAKwCAgIUc3Rha2VkUGllY2VzQnlPd25lcl8FCW93bmVyQWRkcgEIYXNTdHJpbmcBAXYEByRtYXRjaDAFAXYDCQABAgUHJG1hdGNoMAIGU3RyaW5nBAFzBQckbWF0Y2gwBQFzCQACAQIYZmFpbCB0byBjYXN0IGludG8gU3RyaW5nAQVhc0ludAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgNJbnQEAW4FByRtYXRjaDAFAW4JAAIBAhVmYWlsIHRvIGNhc3QgaW50byBJbnQBCWFzQW55TGlzdAEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAglMaXN0W0FueV0EAWwFByRtYXRjaDAFAWwJAAIBAhtmYWlsIHRvIGNhc3QgaW50byBMaXN0W0FueV0BCWFzQm9vbGVhbgEBdgQHJG1hdGNoMAUBdgMJAAECBQckbWF0Y2gwAgdCb29sZWFuBAFzBQckbWF0Y2gwBQFzCQACAQIZZmFpbCB0byBjYXN0IGludG8gQm9vbGVhbgEPbnVtUGllY2VzQnlTaXplAQhsYW5kU2l6ZQQHJG1hdGNoMAUIbGFuZFNpemUDCQAAAgIBUwUHJG1hdGNoMAUFU1NJWkUDCQAAAgIBTQUHJG1hdGNoMAUFTVNJWkUDCQAAAgIBTAUHJG1hdGNoMAUFTFNJWkUDCQAAAgICWEwFByRtYXRjaDAFBlhMU0laRQMJAAACAgNYWEwFByRtYXRjaDAFB1hYTFNJWkUJAAIBAhFVbmtub3duIGxhbmQgc2l6ZQEHaXNEaWdpdAEBcwkBCWlzRGVmaW5lZAEJALYJAQUBcwEKa2V5QmxvY2tlZAACEGNvbnRyYWN0c0Jsb2NrZWQBEWtleUxhc3RUeElkQnlVc2VyAQRhZGRyCQCsAgICD2xhc3RUeElkQnlVc2VyXwUEYWRkcgEKZml4ZWRQb2ludAIDdmFsCGRlY2ltYWxzBAZ0ZW5Qb3cJAGwGAAoAAAUIZGVjaW1hbHMAAAAABQRET1dOBAdsb3dQYXJ0CQCkAwEJAGoCBQN2YWwFBnRlblBvdwQGemVyb2VzCQCwAgIJAKQDAQUGdGVuUG93CQBkAgABCQCxAgEFB2xvd1BhcnQJAKwCAgkArAICCQCsAgIJAKQDAQkAaQIFA3ZhbAUGdGVuUG93AgEuBQZ6ZXJvZXMFB2xvd1BhcnQBD2dldFJhbmRvbU51bWJlcgMIbWF4VmFsdWUEc2FsdAdlbnRyb3B5AwkAZwIAAAUIbWF4VmFsdWUJAAIBAhZtYXhWYWx1ZSBzaG91bGQgYmUgPiAwBApyYW5kb21IYXNoCQD3AwEJAMsBAgUEc2FsdAUHZW50cm9weQkAagIJALEJAQUKcmFuZG9tSGFzaAUIbWF4VmFsdWUADWluY3ViYXRvckFkZHIEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQRWt0VnV4MlJoY2hTTjYzRHNEbzRiNG16NFFxektTZUR2AwkAAAIBAVQFByRtYXRjaDAFBHRoaXMJAAIBAg1Vbmtub3duIGNoYWluAAticmVlZGVyQWRkcgQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1BEVnVVNDVIN0VoNWRtdE5iblJOUlN0R3dVTEE3Tlk2SGIDCQAAAgEBVAUHJG1hdGNoMAUEdGhpcwkAAgECDVVua25vd24gY2hhaW4ADEVNUFRZX1BST0Q1MAGQAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEUZJVkVNSU5VVEVTTUlMTElTAOCnEgAMUkVOQU1JTkdDT1NUAMCWsQIACk1BWE5BTUVMRU4AMgAVSW5mcmFVcGdyYWRlQ29zdFNVc2R0AICt4gQADEVYUE1BVEVSSUFMUwQHJG1hdGNoMAUFY2hhaW4DCQAAAgEBVwUHJG1hdGNoMACm3YLtqwcDCQAAAgEBVAUHJG1hdGNoMACqp4GzCQkAAgECDVVua25vd24gY2hhaW4AB0VYUFVTRFQEByRtYXRjaDAFBWNoYWluAwkAAAIBAVcFByRtYXRjaDAAgOWadwMJAAACAQFUBQckbWF0Y2gwAIDlmncJAAIBAg1Vbmtub3duIGNoYWluAA5ST0JPX0RVQ0tfVVNEVACgjQYADFNfQ09TVF9BQ1JFUwCA8ouoCQAFRklWRVgJALYCAQAFAAdUV0VOVFlYCQC2AgEAFAAIVFdFTlRZMlgJALYCAQkAaAIAFAAUAAhUV0VOVFkzWAkAtgIBCQBoAgkAaAIAFAAUABQACFRXRU5UWTRYCQC2AgEJAGgCCQBoAgkAaAIAFAAUABQAFAAIVFdFTlRZNVgJALYCAQkAaAIJAGgCCQBoAgkAaAIAFAAUABQAFAAUAA9QUkVTQUxFTlVNTEFORFMA9AMBEmtleU5leHRGcmVlTGFuZE51bQACC25leHRMYW5kTnVtARprZXlMYW5kQ3VzdG9tTmFtZVRvQXNzZXRJZAEEbmFtZQkArAICAgRsY25fBQRuYW1lARBrZXlMYW5kVG9Bc3NldElkAQdsYW5kTnVtCQCsAgICA2xhXwUHbGFuZE51bQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgdhc3NldElkCW93bmVyQWRkcgkArAICCQCsAgIJAKwCAgIFaWxhb18FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgERa2V5TGFuZE51bVRvT3duZXIBB2xhbmROdW0JAKwCAgIDbG9fBQdsYW5kTnVtARprZXlEdWNrQ3VzdG9tTmFtZVRvQXNzZXRJZAEEbmFtZQkArAICAhFkdWNrQnlDdXN0b21OYW1lXwUEbmFtZQEWa2V5Q3VzdG9tTmFtZVRvQWRkcmVzcwEEbmFtZQkArAICAhRhY2NvdW50QnlDdXN0b21OYW1lXwUEbmFtZQEJa2V5T2xkaWVzAAIKb2xkaWVzTGlzdAEPa2V5TmV4dFJvYm9EdWNrAAIMbmV4dFJvYm9EdWNrAAtjbGFpbU1vZGVXaAAAAA1jbGFpbU1vZGVEdWNrAAEAE2NsYWltTW9kZVdoVGhlbkR1Y2sAAgAIZmxIZWFsdGgAAAALZmxUaW1lc3RhbXAABQAHZmxCb251cwAGAAtmbFByb2RzVXNlZAAHAQduZnROYW1lAgdsYW5kTnVtCGxhbmRTaXplCQCsAgIJAKwCAgUKTEFORFBSRUZJWAUHbGFuZE51bQUIbGFuZFNpemUBCHRvVm9sdW1lAgZhbW91bnQHcGtnU2l6ZQQEcGtncwMJAGcCBQZhbW91bnQAAAkAaQIJAGUCCQBkAgUGYW1vdW50BQdwa2dTaXplAAEFB3BrZ1NpemUJAQEtAQkAaQIJAGUCCQBkAgkBAS0BBQZhbW91bnQFB3BrZ1NpemUAAQUHcGtnU2l6ZQkAaAIFBHBrZ3MFBU1VTFQ4ARNkaXN0cmlidXRlQnlXZWlnaHRzAgV0b3RhbAd3ZWlnaHRzBANzdW0JAGQCCQBkAgkAZAIJAGQCCQBkAgkAkQMCBQd3ZWlnaHRzAAAJAJEDAgUHd2VpZ2h0cwABCQCRAwIFB3dlaWdodHMAAgkAkQMCBQd3ZWlnaHRzAAMJAJEDAgUHd2VpZ2h0cwAECQCRAwIFB3dlaWdodHMABQMJAGcCAAAFA3N1bQkAAgECEFplcm8gd2VpZ2h0cyBzdW0EBW5vcm02CQBrAwUFdG90YWwFBU1VTFQ2BQNzdW0KAQpub3JtYWxpemVyAgNhY2MEZWxlbQkAzQgCBQNhY2MJAGsDBQRlbGVtBQVub3JtNgUFTVVMVDYKAAIkbAUHd2VpZ2h0cwoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEKbm9ybWFsaXplcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgESZ2V0TmVlZGVkTWF0ZXJpYWxzAQV0b3RhbAQFcHJvcHMJALUJAgkBBXZhbHVlAQkAoggBCQERa2V5UmVzUHJvcG9ydGlvbnMAAgFfAwkBAiE9AgkAkAMBBQVwcm9wcwUGTlVNUkVTCQACAQIWV3JvbmcgcHJvcG9ydGlvbnMgZGF0YQQBcgkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcHJvcHMAAAkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcHJvcHMAAQkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcHJvcHMAAgkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcHJvcHMAAwkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcHJvcHMABAkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcHJvcHMABQUDbmlsCQETZGlzdHJpYnV0ZUJ5V2VpZ2h0cwIFBXRvdGFsBQFyARFzdWJ0cmFjdE1hdGVyaWFscwMMc2hvdWxkVXNlTWF0A2hhcwl0b3RhbE5lZWQEBG5lZWQJARJnZXROZWVkZWRNYXRlcmlhbHMBBQl0b3RhbE5lZWQKAQpzdWJ0cmFjdG9yAgNhY2MDaWR4BAZyZXN1bHQJAGUCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUDaGFzBQNpZHgJAJEDAgUEbmVlZAUDaWR4AwkAZgIAAAUGcmVzdWx0CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICGE5vdCBlbm91Z2ggbWF0ZXJpYWwgaWR4PQkApAMBBQNpZHgCCywgeW91IGhhdmUgCQCRAwIFA2hhcwUDaWR4AgssIGJ1dCBuZWVkIAkApAMBCQCRAwIFBG5lZWQFA2lkeAkAzQgCBQNhY2MJAKQDAQUGcmVzdWx0AwUMc2hvdWxkVXNlTWF0CgACJGwFBUlURVI2CgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpzdWJ0cmFjdG9yAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGBQNoYXMBEXN1YnRyYWN0RXF1aXBtZW50AgVvbGRFcQVwVXNlZAMJAAACBQVwVXNlZAIACQCUCgIFBW9sZEVxBwoBB3N1YlVzZWQCA2FjYwZpZHhBbXQEBXBhcnRzCQC1CQIFBmlkeEFtdAIBLAMJAQIhPQIJAJADAQUFcGFydHMAAgkAAgECKEluY29ycmVjdCBmb3JtYXQsIHNob3VsZCBiZSBpbmRleCxhbW91bnQEA2lkeAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAADAwkAZgIAAAUDaWR4BgkAZwIFA2lkeAkAkAMBBRBwcm9kdWN0aW9uTWF0cml4CQACAQITVW5rbm93biBwcm9kdWN0IGlkeAQDYW10CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAQQHZXFQYXJ0cwkAtQkCCAUDYWNjAl8xCQCsAgIJAJEDAgUFcGFydHMAAAIBOgMJAQIhPQIJAJADAQUHZXFQYXJ0cwACCQACAQkArAICCQCsAgICD1lvdSBkb24ndCBoYXZlIAkAkQMCBQlwcm9kVHlwZXMFA2lkeAIJIGVxdWlwcGVkBAN0bXAJAJEDAgUHZXFQYXJ0cwABBAZudW1MZW4DCQEHaXNEaWdpdAEJAK8CAgkAsAICBQN0bXAAAQABAAIAAQQEY3VycgkBDXBhcnNlSW50VmFsdWUBCQCvAgIFA3RtcAUGbnVtTGVuBAR0YWlsCQCwAgIFA3RtcAUGbnVtTGVuBAZuZXdBbXQDCQBnAgUEY3VycgUDYW10CQBlAgUEY3VycgUDYW10CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICDVlvdSBlcXVpcHBlZCAJAKQDAQUEY3VycgIEIG9mIAkAkQMCBQlwcm9kVHlwZXMFA2lkeAITLCBidXQgdHJpZWQgdG8gdXNlIAkApAMBBQNhbXQJAJQKAgkArAICCQCsAgIJAKwCAgkArAICCQCRAwIFB2VxUGFydHMAAAkAkQMCBQVwYXJ0cwAAAgE6CQCkAwEFBm5ld0FtdAUEdGFpbAMIBQNhY2MCXzIGAwMJAGcCBQNpZHgABgkAZwIACAUDaWR4BwkAAAIFBm5ld0FtdAAABwoAAiRsCQC1CQIFBXBVc2VkAgFfCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCBQVvbGRFcQcKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3N1YlVzZWQCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDEwCQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoBDnByb2RTdHJUb0J5dGVzAQdwcm9kU3RyBAVwTGlzdAMJAAACBQdwcm9kU3RyAgAFA25pbAkAvAkCBQdwcm9kU3RyAgFfCgEEdG9CVgIDYWNjBnJlY2lwZQQBagkAaQIJAMgBAQUDYWNjAAgEBGN1cnIDCQBmAgkAkAMBBQVwTGlzdAUBagkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBMaXN0BQFqAAAJAMsBAgUDYWNjCQCaAwEFBGN1cnIKAAIkbAUQcHJvZHVjdGlvbk1hdHJpeAoAAiRzCQCQAwEFAiRsCgAFJGFjYzABAAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEEdG9CVgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQIUTGlzdCBzaXplIGV4Y2VlZHMgNTAJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYABwAIAAkACgALAAwADQAOAA8AEAARABIAEwAUABUAFgAXABgAGQAaABsAHAAdAB4AHwAgACEAIgAjACQAJQAmACcAKAApACoAKwAsAC0ALgAvADAAMQAyAQ5ieXRlc1RvUHJvZFN0cgECYnYKAQZmcm9tQlYCA2FjYwZyZWNpcGUEAWoJAJADAQUDYWNjBAFiCQDJAQIJAMoBAgUCYnYJAGgCAAgFAWoACAkAzQgCBQNhY2MJAKQDAQkAsQkBBQFiCQC6CQIKAAIkbAUQcHJvZHVjdGlvbk1hdHJpeAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGZnJvbUJWAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyA1MAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADICAV8BFWNoZWNrU3RhdFJlcXVpcmVtZW50cwIJZHVja1N0YXRzBHJlcXMKAQVjaGVjawIDYWNjAWoEBGJ1ZmYDCQBmAgkAkAMBBQlkdWNrU3RhdHMJAGQCAAcFAWoJAJEDAgUJZHVja1N0YXRzCQBkAgAHBQFqAAADCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBHJlcXMFAWoJAGQCCQCRAwIFCWR1Y2tTdGF0cwUBagUEYnVmZgkAAgEJAKwCAgIbUmVxdWlyZW1lbnQgbm90IHNhdGlzZmllZDogCQCRAwIFDHJlcXVpcmVtZW50cwUBagYKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQkAzAgCAAYFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAHCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQVjaGVjawIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNwkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAQpwbGFjZVByb2RCBgZpZHhDbnQFcExpc3QKaXNQb3NpdGl2ZQlkdWNrU3RhdHMIb2NjdXBpZWQEZnJlZQQFcGFydHMJALUJAgUGaWR4Q250AgE6AwkBAiE9AgkAkAMBBQVwYXJ0cwACCQACAQIoSW5jb3JyZWN0IGZvcm1hdCwgc2hvdWxkIGJlIGluZGV4OmFtb3VudAMDCQEBIQEFCmlzUG9zaXRpdmUJAQIhPQIJALECAQkAkQMCBQVwYXJ0cwAAAAIHCQACAQIrUHJvZHVjdCBpZHggc2hvdWxkIGJlIDIgZGlnaXRzLCB6ZXJvIHBhZGRlZAQKcHJvZHVjdElkeAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAAEBWNvdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAQMJAQEhAQkBD2NvbnRhaW5zRWxlbWVudAIFEGZvcnRBbGxvd2VkUHJvZHMFCnByb2R1Y3RJZHgJAAIBCQCsAgIJAKwCAgIJUHJvZHVjdCAnCQCRAwIFCXByb2RUeXBlcwUKcHJvZHVjdElkeAIhJyBjYW5ub3QgYmUgdXNlZCBmb3IgbGFuZCBkZWZlbnNlAwkAZgIAAAUFY291bnQJAAIBAhdDb3VudCBjYW4ndCBiZSBuZWdhdGl2ZQMJAGYCBQVjb3VudAUNTUFYUFJPRElOU0xPVAkAAgEJAKwCAgkArAICCQCsAgICFENhbid0IHB1dCBtb3JlIHRoYW4gCQCkAwEFDU1BWFBST0RJTlNMT1QCBCBvZiAJAJEDAgUJcHJvZFR5cGVzBQpwcm9kdWN0SWR4AwkAAAIFBWNvdW50AAAJAJUKAwUFcExpc3QFCG9jY3VwaWVkBQRmcmVlBARoZWFkCQDJAQIFBXBMaXN0CQBoAgAIBQpwcm9kdWN0SWR4BARjdXJyCQCxCQEJAMkBAgkAygECBQVwTGlzdAkAaAIACAUKcHJvZHVjdElkeAAIBAR0YWlsCQDKAQIFBXBMaXN0CQBoAgAICQBkAgUKcHJvZHVjdElkeAABBAZyZWNpcGUJALUJAgkAkQMCBRBwcm9kdWN0aW9uTWF0cml4BQpwcm9kdWN0SWR4AgFfAwMJAQEhAQUKaXNQb3NpdGl2ZQkAZgIFBWNvdW50BQRjdXJyBwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAglZb3UgaGF2ZSAJAKQDAQUEY3VycgIEIG9mIAkAkQMCBQlwcm9kVHlwZXMFCnByb2R1Y3RJZHgCEywgYnV0IHRyaWVkIHRvIHVzZSAJAKQDAQUFY291bnQEBm5ld0FtdAMDCQEBIQEFCmlzUG9zaXRpdmUJARVjaGVja1N0YXRSZXF1aXJlbWVudHMCBQlkdWNrU3RhdHMJALUJAgkAkQMCBQZyZWNpcGUFEHJJZHhSZXF1aXJlbWVudHMCASwHCQBlAgUEY3VycgUFY291bnQJAGQCBQRjdXJyBQVjb3VudAQIZGVsdGFWb2wJAGUCCQEIdG9Wb2x1bWUCBQZuZXdBbXQFDlBST0RVQ1RQS0dTSVpFCQEIdG9Wb2x1bWUCBQRjdXJyBQ5QUk9EVUNUUEtHU0laRQkAlQoDCQDLAQIJAMsBAgUEaGVhZAkAmgMBBQZuZXdBbXQFBHRhaWwJAGQCBQhvY2N1cGllZAUIZGVsdGFWb2wJAGUCBQRmcmVlBQhkZWx0YVZvbAEIYWRkUHJvZEIHBmlkeENudAVwTGlzdAppc1Bvc2l0aXZlB3NlZ21lbnQHbWFpbkF1eARzbG90CWR1Y2tTdGF0cwQFcGFydHMJALUJAgUGaWR4Q250AgE6AwkBAiE9AgkAkAMBBQVwYXJ0cwACCQACAQIoSW5jb3JyZWN0IGZvcm1hdCwgc2hvdWxkIGJlIGluZGV4OmFtb3VudAMDCQEBIQEFCmlzUG9zaXRpdmUJAQIhPQIJALECAQkAkQMCBQVwYXJ0cwAAAAIHCQACAQIrUHJvZHVjdCBpZHggc2hvdWxkIGJlIDIgZGlnaXRzLCB6ZXJvIHBhZGRlZAQKcHJvZHVjdElkeAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBXBhcnRzAAAEBWNvdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcGFydHMAAQMDCQBmAgAABQpwcm9kdWN0SWR4BgkAZwIFCnByb2R1Y3RJZHgJAJADAQUQcHJvZHVjdGlvbk1hdHJpeAkAAgECE1Vua25vd24gcHJvZHVjdCBpZHgDCQBmAgAABQVjb3VudAkAAgECF0NvdW50IGNhbid0IGJlIG5lZ2F0aXZlAwkAZgIFBWNvdW50BQ1NQVhQUk9ESU5TTE9UCQACAQkArAICCQCsAgIJAKwCAgIUQ2FuJ3QgcHV0IG1vcmUgdGhhbiAJAKQDAQUNTUFYUFJPRElOU0xPVAIEIG9mIAkAkQMCBQlwcm9kVHlwZXMFCnByb2R1Y3RJZHgDCQAAAgUFY291bnQAAAkAlAoCBQVwTGlzdAcEBGhlYWQJAMkBAgUFcExpc3QJAGgCAAgFCnByb2R1Y3RJZHgEBGN1cnIJALEJAQkAyQECCQDKAQIFBXBMaXN0CQBoAgAIBQpwcm9kdWN0SWR4AAgEBHRhaWwJAMoBAgUFcExpc3QJAGgCAAgJAGQCBQpwcm9kdWN0SWR4AAEEBnJlY2lwZQkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgFCnByb2R1Y3RJZHgCAV8DAwkBASEBBQppc1Bvc2l0aXZlCQBmAgUFY291bnQFBGN1cnIHCQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCVlvdSBoYXZlIAkApAMBBQRjdXJyAgQgb2YgCQCRAwIFCXByb2RUeXBlcwUKcHJvZHVjdElkeAITLCBidXQgdHJpZWQgdG8gdXNlIAkApAMBBQVjb3VudAQJaXNCaWdJdGVtAwMJAQEhAQUKaXNQb3NpdGl2ZQkBFWNoZWNrU3RhdFJlcXVpcmVtZW50cwIFCWR1Y2tTdGF0cwkAtQkCCQCRAwIFBnJlY2lwZQUQcklkeFJlcXVpcmVtZW50cwIBLAcEBmNvbXBhdAkAkQMCBQZyZWNpcGUFCXJJZHhTbG90cwMJAAACBQZjb21wYXQCAAkAAgECF0l0ZW0gY2Fubm90IGJlIGVxdWlwcGVkBAFjCQENcGFyc2VJbnRWYWx1ZQEFBmNvbXBhdAQEY1NlZwkAaQIFAWMAZAMJAQIhPQIFB3NlZ21lbnQFBGNTZWcJAAIBAhRTZWdtZW50IGluY29tcGF0aWJsZQQIY01haW5BdXgJAGkCCQBqAgUBYwBkAAoDCQECIT0CBQdtYWluQXV4BQhjTWFpbkF1eAkAAgECEVNsb3QgaW5jb21wYXRpYmxlBAljTnVtU2xvdHMJAGoCBQFjAAoDAwkBAiE9AgUEc2xvdAAACQBmAgUJY051bVNsb3RzAAEHCQACAQIeQmlnIGl0ZW1zIHNob3VsZCBvY2N1cHkgc2xvdCAwCQBmAgUJY051bVNsb3RzAAEHCQCUCgIJAMsBAgkAywECBQRoZWFkCQCaAwEJAGQCBQRjdXJyAwUKaXNQb3NpdGl2ZQUFY291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c3NldElkBAVlcUtleQkBEGtleUR1Y2tFcXVpcG1lbnQBBQtkdWNrQXNzZXRJZAQGY3VyckVxCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUFZXFLZXkCFyw7LF8sOyxfLDssXyw7LF8sOyxfLDssAgFfBAl0ZW1wUHJvZEIJAQZkcmVzc0IEBQZjdXJyRXEFDEVNUFRZX1BST0Q1MAYFA25pbAQIc2VnQnBBdXgJAJEDAgkAtQkCCQCRAwIFBmN1cnJFcQULc2VnQmFja3BhY2sCATsAAQQKYnVmZkVmZmVjdAMJAAACBQhzZWdCcEF1eAIAAAAEBGF1eDAJAJEDAgkAtQkCBQhzZWdCcEF1eAIBLAAAAwkAAAIFBGF1eDACAAAABAZpZHhDbnQJALUJAgUEYXV4MAIBOgQDaWR4CQCRAwIFBmlkeENudAAABANjbnQJAJEDAgUGaWR4Q250AAEDAwMDAwkAAAIFA2lkeAICMDYGCQAAAgUDaWR4AgIwNwYJAAACBQNpZHgCAjA4CQECIT0CBQNjbnQCAAcJAGYCCQENcGFyc2VJbnRWYWx1ZQEFA2NudAAABwkBDXBhcnNlSW50VmFsdWUBCQCRAwIJALUJAgkAkQMCBRBwcm9kdWN0aW9uTWF0cml4CQENcGFyc2VJbnRWYWx1ZQEFA2lkeAIBXwUKcklkeEVmZmVjdAAABAVzdGF0cwkBDGdldER1Y2tTdGF0cwQFBHRoaXMFC2R1Y2tBc3NldElkBQpidWZmRWZmZWN0BgQIbmV3UHJvZEIJAQZkcmVzc0IEBQZjdXJyRXEFCXRlbXBQcm9kQgcFBXN0YXRzCQAAAgUIbmV3UHJvZEIFCG5ld1Byb2RCARl1cGRhdGVQcm9wb3J0aW9uc0ludGVybmFsBAhwcm9wTGlzdA10ZXJyYWluQ291bnRzDWxhbmRTaXplSW5kZXgEc2lnbgMJAQIhPQIJAJADAQUIcHJvcExpc3QFBk5VTVJFUwkAAgECFldyb25nIHByb3BvcnRpb25zIGRhdGEKAQd1cGRhdGVyAgNhY2MBaQQGcmVzdWx0CQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHByb3BMaXN0BQFpCQBoAgkAaAIFBHNpZ24JAJEDAgUNdGVycmFpbkNvdW50cwUBaQUNbGFuZFNpemVJbmRl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T0ZUAgFfBAh3aExvY2tlZAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFCXZvbExvY2tlZAQDb2NjAwkAZgIJAJADAQUEbG9mdAABCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAULdm9sT2NjdXBpZWQFCndoT2NjdXBpZWQJALkJAgkAzAgCCQCkAwEFCHdoTG9ja2VkCQDMCAIJAKQDAQUDb2NjCQDMCAIJAKQDAQkAZQIJAGUCBQd3aFRvdGFsBQh3aExvY2tlZAUDb2NjCQDMCAIJAKQDAQUHd2hUb3RhbAUDbmlsAgFfCQDMCAIJAJEDAgUCd2gFC3doSWR4TGV2ZWxzCQDMCAIDCQAAAgkAkAMBCQC1CQIJAJEDAgUCd2gFCHdoSWR4UmVzAgFfBQZOVU1SRVMJAJEDAgUCd2gFCHdoSWR4UmVzAgswXzBfMF8wXzBfMAkAzAgCAwkAAAIJAJADAQkAtQkCCQCRAwIFAndoBQh3aElkeE1hdAIBXwUGTlVNUkVTCQCRAwIFAndoBQh3aElkeE1hdAILMF8wXzBfMF8wXzAJAMwIAgkAkQMCBQJ3aAUJd2hJZHhQcm9kCQDMCAIFBndoTG9mdAUDbmlsARVnZXRXYXJlaG91c2VTcGFjZUxlZnQBCWN1cnJlbnRXaAQLb2NjdXBpZWRWb2wJARdnZXRXYXJlaG91c2VPY2N1cGllZFZvbAEFCWN1cnJlbnRXaAQPY3VycldoTG9ja2VkVm9sCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkAtQkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhMT0ZUAgFfBQl2b2xMb2NrZWQJAGUCCQBlAgkBF2dldFdhcmVob3VzZVRvdGFsVm9sdW1lAQkAkQMCBQljdXJyZW50V2gFC3doSWR4TGV2ZWxzBQtvY2N1cGllZFZvbAUPY3VycldoTG9ja2VkVm9sAQltb3ZlU3R1ZmYDCmNhcmdvUGFydHMJY3VycmVudFdoC2N1cnJlbnRQYWNrAwkBAiE9AgkAkAMBBQpjYXJnb1BhcnRzAAMJAAIBAjRjYXJnb0xpc3RTdHIgc2hvdWxkIGNvbnRhaW4gZXhhY3RseSAyICc6JyBzZXBhcmF0b3JzBAhyZXNQYXJ0cwkAtQkCCQCRAwIFCmNhcmdvUGFydHMAAAIBXwQIbWF0UGFydHMJALUJAgkAkQMCBQpjYXJnb1BhcnRzAAECAV8ECXByb2RQYXJ0cwMJAAACCQCRAwIFCmNhcmdvUGFydHMAAgIABQNuaWwJALwJAgkAkQMCBQpjYXJnb1BhcnRzAAICAV8DCQECIT0CCQCQAwEFCHJlc1BhcnRzBQZOVU1SRVMJAAIBAiBBbGwgNiByZXNvdXJjZXMgc2hvdWxkIGJlIHBhc3NlZAMJAQIhPQIJAJADAQUIbWF0UGFydHMFBk5VTVJFUwkAAgECIEFsbCA2IG1hdGVyaWFscyBzaG91bGQgYmUgcGFzc2VkBAt3aFNwYWNlTGVmdAkBFWdldFdhcmVob3VzZVNwYWNlTGVmdAEFCWN1cnJlbnRXaAQJY3VycldoUmVzCQC1CQIJAJEDAgUJY3VycmVudFdoBQh3aElkeFJlcwIBXwQJY3VycldoTWF0CQC1CQIJAJEDAgUJY3VycmVudFdoBQh3aElkeE1hdAIBXwQKY3VycldoUHJvZAMJAAACCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kAgAFA25pbAkAvAkCCQCRAwIFCWN1cnJlbnRXaAUJd2hJZHhQcm9kAgFfBA5jdXJyZW50UGFja1JlcwkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwIBXwQOY3VycmVudFBhY2tNYXQJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8ED2N1cnJlbnRQYWNrUHJvZAMJAAACCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QCAAUDbmlsCQC8CQIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAIBXwoBA212UgIDYWNjBGl0ZW0EAWkIBQNhY2MCXzEEAmFtCQENcGFyc2VJbnRWYWx1ZQEFBGl0ZW0EA3docgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWN1cnJXaFJlcwUBaQQDYnByCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUOY3VycmVudFBhY2tSZXMFAWkDCQAAAgUCYW0AAAkAlgoECQBkAgUBaQABCQDNCAIIBQNhY2MCXzIJAJEDAgUJY3VycldoUmVzBQFpCQDNCAIIBQNhY2MCXzMJAJEDAgUOY3VycmVudFBh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ZW50UGFja1Byb2QFAWkJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQ9jdXJyZW50UGFja1Byb2QFAWkAAAMJAAACBQJhbQAACQCWCgQJAGQCBQFpAAEJAM0IAggFA2FjYwJfMgkApAMBBQN3aHAJAM0IAggFA2FjYwJfMwkApAMBBQNicHAIBQNhY2MCXzQDCQBmAgUCYW0AAAMJAGYCBQJhbQUDYnBwCQACAQkArAICCQCsAgIJAKwCAgkArAICAhBBdHRlbXB0IHRvIHRha2UgBQRpdGVtAhkgZnJvbSBiYWNrcGFjaywgYnV0IG9ubHkgCQCkAwEFA2JwcAIKIGF2YWlsYWJsZQQIZGVsdGFWb2wJAGUCCQEIdG9Wb2x1bWUCCQBkAgUDd2hwBQJhbQUOUFJPRFVDVFBLR1NJWkUJAQh0b1ZvbHVtZQIFA3docAUOUFJPRFVDVFBLR1NJWkUJAJYKBAkAZAIFAWkAAQkAzQgCCAUDYWNjAl8yCQCkAwEJAGQCBQN3aHAFAmFtCQDNCAIIBQNhY2MCXzMJAKQDAQkAZQIFA2JwcAUCYW0JAGQCCAUDYWNjAl80BQhkZWx0YVZvbAMJAGYCCQEBLQEFAmFtBQN3aHAJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICEEF0dGVtcHQgdG8gdGFrZSAJAKQDAQkBAS0BBQJhbQIaIGZyb20gd2FyZWhvdXNlLCBidXQgb25seSAJAKQDAQUDd2hwAgogYXZhaWxhYmxlBAhkZWx0YVZvbAkAZQIJAQh0b1ZvbHVtZQIJAGQCBQN3aHAFAmFtBQ5QUk9EVUNUUEtHU0laRQkBCHRvVm9sdW1lAgUDd2hwBQ5QUk9EVUNUUEtHU0laRQkAlgoECQBkAgUBaQABCQDNCAIIBQNhY2MCXzIJAKQDAQkAZAIFA3docAUCYW0JAM0IAggFA2FjYwJfMwkApAMBCQBlAgUDYnBwBQJhbQkAZAIIBQNhY2MCXzQFCGRlbHRhVm9sBAFwAwkBAiE9AgkAkAMBBQlwcm9kUGFydHMAAAoAAiRsBQlwcm9kUGFydHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCWCgQAAAUDbmlsBQNuaWwIBQFtAl80CgEFJGYyXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQNtdlACBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjJfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECFExpc3Qgc2l6ZSBleGNlZWRzIDUwCQEFJGYyXzICCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECCQEFJGYyXzECBQUkYWNjMAAAAAEAAgADAAQABQAGAAcACAAJAAoACwAMAA0ADgAPABAAEQASABMAFAAVABYAFwAYABkAGgAbABwAHQAeAB8AIAAhACIAIwAkACUAJgAnACgAKQAqACsALAAtAC4ALwAwADEAMgkAlgoEAAAFCmN1cnJXaFByb2QFD2N1cnJlbnRQYWNrUHJvZAgFAW0CXzQECHZvbFNhbGRvCAUBcAJfNAMJAGYCBQh2b2xTYWxkbwULd2hTcGFjZUxlZnQJAAIBCQCsAgIJAKwCAgkArAICCQCsAgICFUF0dGVtcHQgdG8gcHV0IHRvdGFsIAkApAMBBQh2b2xTYWxkbwIRIHN0dWZmLCBidXQgb25seSAJAKQDAQULd2hTcGFjZUxlZnQCFSB3YXJlaG91c2Ugc3BhY2UgbGVmdAkAmQoHCQC5CQIIBQFyAl8yAgFfCQC5CQIIBQFtAl8yAgFfCQC6CQIIBQFwAl8yAgFfCQC5CQIIBQFyAl8zAgFfCQC5CQIIBQFtAl8zAgFfCQC6CQIIBQFwAl8zAgFfBQh2b2xTYWxkbwESZXhwZWRpdGlvbkludGVybmFsAgZjYWxsZXIEdHhJZAQIdXNlckFkZHIJAKUIAQUGY2FsbGVyBAZiaWdOdW0JAQNhYnMBCQCeAwEFBHR4SWQEB2ZyZWVOdW0JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleU5leHRGcmVlTGFuZE51bQAJAGQCBQ9QUkVTQUxFTlVNTEFORFMAAQQHbGFuZE51bQkApAMBBQdmcmVlTnVtBAxjb250aW5lbnRJZHgJAKADAQkAuwICBQZiaWdOdW0FBUZJVkVYBAh0ZXJyYWlucwkBC2dlblRlcnJhaW5zAgUGYmlnTnVtBQxjb250aW5lbnRJZHgECWNvbnRpbmVudAkAkQMCBQpjb250aW5lbnRzBQxjb250aW5lbnRJZHgEBWlzc3VlCQDCCAUJAQduZnROYW1lAgUHbGFuZE51bQIBUwkAuQkCCQDMCAIFB2xhbmROdW0JAMwIAgIBUwkAzAgCBQh0ZXJyYWlucwkAzAgCBQljb250aW5lbnQFA25pbAIBXwABAAAHBAdhc3NldElkCQC4CAEFBWlzc3VlBAJpZAkA2AQBBQdhc3NldElkCQCUCgIJAMwIAgkBDEludGVnZXJFbnRyeQIJARJrZXlOZXh0RnJlZUxhbmROdW0ACQBkAgUHZnJlZU51bQABCQDMCAIFBWlzc3VlCQDMCAIJAQtTdHJpbmdFbnRyeQIJARBrZXlMYW5kVG9Bc3NldElkAQUHbGFuZE51bQUCaWQJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFAmlkBQh1c2VyQWRkcgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtBQh1c2VyQWRkcgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQJpZAAACQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgUCaWQFCHVzZXJBZGRyAAAJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwUGY2FsbGVyAAEFB2Fzc2V0SWQFA25pbAkAlAoCBQJpZAUJY29udGluZW50AQxmbGlnaHRDb21tb24DCHVzZXJBZGRyB21lc3NhZ2UDc2lnAwkBASEBCQDEEwMFB21lc3NhZ2UFA3NpZwUDcHViCQACAQIYc2lnbmF0dXJlIGRvZXMgbm90IG1hdGNoBAVwYXJ0cwkAvAkCCQCwCQEFB21lc3NhZ2UCATsECWZsaWdodExvZwkAvAkCCQCRAwIFBXBhcnRzAAACAXwEAmhwCQC1CQIJAJEDAgUJZmxpZ2h0TG9nBQhmbEhlYWx0aAIBXwQFY3VySFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAAABAVuZXdIUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmhwAAEEC25ld0xvY1R4VmVyCQC1CQIJAJEDAgUFcGFydHMAAQIBOgQLbmV3TG9jYXRpb24JAJEDAgULbmV3TG9jVHhWZXIAAAQEdGltZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCWZsaWdodExvZwULZmxUaW1lc3RhbXADAwkAZgIFBHRpbWUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMGCQBmAgkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBRFGSVZFTUlOVVRFU01JTExJUwUEdGltZQkAAgEJAKwCAgkArAICCQCsAgICHHNpZ25hdHVyZSBvdXRkYXRlZDogbG9nVGltZT0JAKQDAQUEdGltZQIJLCBiY1RpbWU9CQCkAwEIBQlsYXN0QmxvY2sJdGltZXN0YW1wBAl0eEZyb21Nc2cJAJEDAgULbmV3TG9jVHhWZXIAAQQGbGFzdFR4CQELdmFsdWVPckVsc2UCCQCiCAEJARFrZXlMYXN0VHhJZEJ5VXNlcgEFCHVzZXJBZGRyAgADCQECIT0CBQZsYXN0VHgFCXR4RnJvbU1zZwkAAgEJAKwCAgkArAICCQCsAgICHlR4IGlkcyBkb24ndCBtYXRjaCEgSW4gc3RhdGU6IAUGbGFzdFR4AgosIGluIG1zZzogBQl0eEZyb21Nc2cEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUIdXNlckFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQFbWF4SFAJAQltYXhIZWFsdGgBCQELdmFsdWVPckVsc2UCCQCfCAEJAQxrZXlEdWNrTGV2ZWwBBQtkdWNrQXNzZXRJZAAABAxvbGRGcm9tU3RhdGUJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoBQVtYXhIUAMJAQIhPQIFDG9sZEZyb21TdGF0ZQUFY3VySFAJAAIBCQCsAgIJAKwCAgkArAICAgpvbGRIZWFsdGg9CQCkAwEFDG9sZEZyb21TdGF0ZQIvIGZyb20gc3RhdGUgZG9lcyBub3QgbWF0Y2ggb25lIGZyb20gZmxpZ2h0IGxvZz0JAKQDAQUFY3VySFADCQBnAgAABQVjdXJIUAkAAgECHllvdSBjYW4ndCBmbHkgd2l0aCB6ZXJvIGhlYWx0aAMJAQEhAQkBF2NhbldlYXJDdXJyZW50RXF1aXBtZW50AQULZHVja0Fzc2V0SWQJAAIBAhZFcXVpcG1lbnQgaW5jb21wYXRpYmxlBAVib251cwMJAGYCCQCQAwEFCWZsaWdodExvZwUHZmxCb251cwkAkQMCBQlmbGlnaHRMb2cFB2ZsQm9udXMCAAQIcHJvZFVzZWQDCQBmAgkAkAMBBQlmbGlnaHRMb2cFC2ZsUHJvZHNVc2VkCQCRAwIFCWZsaWdodExvZwULZmxQcm9kc1VzZWQCAAQKc2VudEFtb3VudAMDCQBmAgUFbmV3SFAAAAkAAAIFBWJvbnVzAgEkBwkBBWFzSW50AQkA/AcEBQxyZXN0Q29udHJhY3QCDXNlbmRVc2R0UHJpemUJAMwIAgUIdXNlckFkZHIFA25pbAUDbmlsAAAJAJcKBQUFbmV3SFAFC2R1Y2tBc3NldElkBQpzZW50QW1vdW50BQtuZXdMb2NhdGlvbgUIcHJvZFVzZWQBDGFwcGx5Qm9udXNlcwILbGFuZEFzc2V0SWQGcGllY2VzBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQJYXJ0UGllY2VzCQELdmFsdWVPckVsc2UCCQCfCAEJASBrZXlMYW5kQXJ0U3RhdHVzQnlUeXBlQW5kQXNzZXRJZAIFCkFSVFBSRVNBTEUFC2xhbmRBc3NldElkAAAEBGFkZDYJAGkCBQppbmZyYUxldmVsAAYEBGFkZDcJAGkCBQppbmZyYUxldmVsAAcJAGQCCQBkAgUPREFJTFlSRVNCWVBJRUNFCQBrAwUPREFJTFlSRVNCWVBJRUNFCQBkAgkAZAIFCmluZnJhTGV2ZWwFBGFkZDYJAGgCAAIFBGFkZDcABQkAawMFD0RBSUxZUkVTQllQSUVDRQUJYXJ0UGllY2VzCQBoAgUGcGllY2VzAAUBFGNoZWNrQ2xhaW1Db25kaXRpb25zAwRhZGRyCWNsYWltTW9kZQ1sYW5kQXNzZXRJZEluBA0kdDAzMzM0MzMzODgyAwkAAAIFCWNsYWltTW9kZQULY2xhaW1Nb2RlV2gJAJQKAgUNbGFuZEFzc2V0SWRJbgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAgAEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQLY3VyTG9jYXRpb24JAQt2YWx1ZU9yRWxzZQIJAKIIAQkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkBQ9ERUZBVUxUTE9DQVRJT04EA2xvYwkAtQkCCQEFdmFsdWUBBQtjdXJMb2NhdGlvbgIBXwMJAQIhPQIJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAgFMCQACAQkArAICCQCsAgICFkR1Y2sgbG9jYXRpb24gdHlwZSBpcyAJAJEDAgUDbG9jBQpsb2NJZHhUeXBlAhEsIGJ1dCBzaG91bGQgYmUgTAkAlAoCCQCRAwIFA2xvYwUIbG9jSWR4SWQFC2R1Y2tBc3NldElkBAtsYW5kQXNzZXRJZAgFDSR0MDMzMzQzMzM4ODICXzEEBmR1Y2tJZAgFDSR0MDMzMzQzMzM4ODICXzIEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQULbGFuZEFzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQULbGFuZEFzc2V0SWQECXNhdmVkVGltZQkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCfCAEFB3RpbWVLZXkJAKwCAgkArAICAgVMYW5kIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUEYWRkcgkAAgEJAKwCAgUKTEFORFBSRUZJWAINIGlzIG5vdCB5b3VycwQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8JAJYKBAUGZHVja0lkBQtsYW5kQXNzZXRJZAUBZAUJc2F2ZWRUaW1lARBjbGFpbVJlc0ludGVybmFsBARhZGRyBmFtb3VudAljbGFpbU1vZGUNbGFuZEFzc2V0SWRJbgMJAGYCAAAFBmFtb3VudAkAAgECD05lZ2F0aXZlIGFtb3VudAQBYwkBFGNoZWNrQ2xhaW1Db25kaXRpb25zAwUEYWRkcgUJY2xhaW1Nb2RlBQ1sYW5kQXNzZXRJZEluBAhsYW5kU2l6ZQkAkQMCCAUBYwJfMwULcmVjTGFuZFNpemUEDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCCAUBYwJfMwULcmVjVGVycmFpbnMECWRlbHRhVGltZQkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wCAUBYwJfNAMJAGYCAAAFCWRlbHRhVGltZQkAAgEJAKwCAgkArAICCQCsAgICJlNhdmVkIHRpbWVzdGFtcCBpcyBpbiBmdXR1cmUsIHNhdmVkID0gCQCkAwEIBQFjAl80AgwsIGN1cnJlbnQgPSAJAKQDAQgFCWxhc3RCbG9jawl0aW1lc3RhbXAEBnBpZWNlcwkBD251bVBpZWNlc0J5U2l6ZQEFCGxhbmRTaXplBBZkYWlseVByb2R1Y3Rpb25CeVBpZWNlCQEMYXBwbHlCb251c2VzAggFAWMCXzIFBnBpZWNlcwQIYXZhaWxSZXMJAGsDBQlkZWx0YVRpbWUJAGgCBRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlBQZwaWVjZXMFCURBWU1JTExJUwMJAGYCBQZhbW91bnQFCGF2YWlsUmVzCQACAQkArAICCQCsAgIJAKwCAgIiTm90IGVub3VnaCByZXNvdXJjZXMsIGF2YWlsYWJsZSA9IAkApAMBBQhhdmFpbFJlcwIOLCByZXF1ZXN0ZWQgPSAJAKQDAQUGYW1vdW50BAxuZXdEZWx0YVRpbWUJAGsDCQBlAgUIYXZhaWxSZXMFBmFtb3VudAUJREFZTUlMTElTCQBoAgUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQUGcGllY2VzBAxuZXdUaW1lc3RhbXAJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUMbmV3RGVsdGFUaW1lBAlsYW5kSW5kZXgJAGkCBQZwaWVjZXMFBVNTSVpFBApyZXNUb0NsYWltCQEJdmlydENsYWltBAUNdGVycmFpbkNvdW50cwkAZQIFCWRlbHRhVGltZQUMbmV3RGVsdGFUaW1lBQlsYW5kSW5kZXgFFmRhaWx5UHJvZHVjdGlvbkJ5UGllY2UEBXdoS2V5CQESa2V5V2FyZWhvdXNlQnlMYW5kAQgFAWMCXzIECmluZnJhTGV2ZWwJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBCAUBYwJfMgAABAljdXJyZW50V2gJAQxnZXRXYXJlaG91c2UDBQV3aEtleQUJbGFuZEluZGV4BQppbmZyYUxldmVsBARsb2Z0CQC1CQIJAJEDAgUJY3VycmVudFdoBQl3aElkeExPRlQCAV8EC3doU3BhY2VMZWZ0CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAUHdm9sRnJlZQMDCQAAAgUJY2xhaW1Nb2RlBQtjbGFpbU1vZGVXaAkAZgIFBmFtb3VudAULd2hTcGFjZUxlZnQHCQACAQkArAICCQCsAgICBU9ubHkgCQCkAwEFC3doU3BhY2VMZWZ0Ahggc3BhY2UgbGVmdCBpbiB3YXJlaG91c2UEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBCAUBYwJfMQQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEFBWJwS2V5BA5jdXJyZW50UGFja1JlcwkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwIBXwQMY3VycmVudFdoUmVzCQC1CQIJAJEDAgUJY3VycmVudFdoBQh3aElkeFJlcwIBXwQNJHQwMzYyNTYzNzEyNwMJAAACBQljbGFpbU1vZGUFC2NsYWltTW9kZVdoCQCWCgQJAQZhZGRSZXMFBQxjdXJyZW50V2hSZXMFDXRlcnJhaW5Db3VudHMJAGUCBQlkZWx0YVRpbWUFDG5ld0RlbHRhVGltZQUJbGFuZEluZGV4BRZkYWlseVByb2R1Y3Rpb25CeVBpZWNlCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQRsb2Z0BQt2b2xPY2N1cGllZAgFCnJlc1RvQ2xhaW0CXzIJAGUCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAUHdm9sRnJlZQgFCnJlc1RvQ2xhaW0CXzIDCQAAAgUJY2xhaW1Nb2RlBQ1jbGFpbU1vZGVEdWNrCQCWCgQJAJEDAgUJY3VycmVudFdoBQh3aElkeFJlcwkBBmFkZFJlcwUFDmN1cnJlbnRQYWNrUmVzBQ10ZXJyYWluQ291bnRzCQBlAgUJZGVsdGFUaW1lBQxuZXdEZWx0YVRpbWUFCWxhbmRJbmRleAUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFC3ZvbE9jY3VwaWVkCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAUHdm9sRnJlZQQFZGlzdHIJAQ1kaXN0cmlidXRlUmVzBAUMY3VycmVudFdoUmVzBQ5jdXJyZW50UGFja1JlcwUKcmVzVG9DbGFpbQULd2hTcGFjZUxlZnQEBHdoQW0JAJcDAQkAzAgCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAUHdm9sRnJlZQkAzAgCCAUKcmVzVG9DbGFpbQJfMgUDbmlsCQCWCgQIBQVkaXN0cgJfMQgFBWRpc3RyAl8yCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFC3ZvbE9jY3VwaWVkBQR3aEFtCQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUFBHdoQW0EBXdoUmVzCAUNJHQwMzYyNTYzNzEyNwJfMQQFYnBSZXMIBQ0kdDAzNjI1NjM3MTI3Al8yBAVsb2Z0TwgFDSR0MDM2MjU2MzcxMjcCXzMEBWxvZnRGCAUNJHQwMzYyNTYzNzEyNwJfNAkAlwoFCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEIBQFjAl8yBQxuZXdUaW1lc3RhbXAJAMwIAgkBDEludGVnZXJFbnRyeQIJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKTEFORFBSRUZJWAgFAWMCXzIFBGFkZHIFDG5ld1RpbWVzdGFtcAUDbmlsBQVicEtleQkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIFBWJwUmVzCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsBQV3aEtleQkAzAgCCQCRAwIFCWN1cnJlbnRXaAULd2hJZHhMZXZlbHMJAMwIAgUFd2hSZXMJAMwIAgkAkQMCBQljdXJyZW50V2gFCHdoSWR4TWF0CQDMCAIJAJEDAgUJY3VycmVudFdoBQl3aElkeFByb2QJAMwIAgkAuQkCCQDMCAIJAJEDAgUEbG9mdAUJdm9sTG9ja2VkCQDMCAIJAKQDAQUFbG9mdE8JAMwIAgkApAMBBQVsb2Z0RgkAzAgCCQCRAwIFBGxvZnQFCHZvbFRvdGFsBQNuaWwCAV8FA25pbAEIY2xhaW1BbGwEBGFkZHILbGFuZEFzc2V0SWQGcGllY2VzCWNsYWltTW9kZQQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAQJc2F2ZWRUaW1lCQEFdmFsdWUBCQCfCAEFB3RpbWVLZXkECGF2YWlsUmVzCQBoAgkAawMJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAUJc2F2ZWRUaW1lCQEMYXBwbHlCb251c2VzAgULbGFuZEFzc2V0SWQFBnBpZWNlcwUJREFZTUlMTElTBQZwaWVjZXMJARBjbGFpbVJlc0ludGVybmFsBAUEYWRkcgUIYXZhaWxSZXMFCWNsYWltTW9kZQULbGFuZEFzc2V0SWQBDXVwSW5mcmFDb21tb24EDHNob3VsZFVzZU1hdAZjYWxsZXINcGF5bWVudEFtb3VudAtsYW5kQXNzZXRJZAQEYWRkcgkApQgBBQZjYWxsZXIEAWMJARRjaGVja0NsYWltQ29uZGl0aW9ucwMFBGFkZHIFE2NsYWltTW9kZVdoVGhlbkR1Y2sFC2xhbmRBc3NldElkBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIIBQFjAl8zBQtyZWNMYW5kU2l6ZQQIaW5mcmFLZXkJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQgFAWMCXzIECGN1ckxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEFCGluZnJhS2V5AAADAwkBASEBBRhLU19BTExPV19CSUdfSU5GUkFfTUVSR0UJAGcCBQhjdXJMZXZlbAADBwkAAgECJkN1cnJlbnRseSBtYXggaW5mcmFzdHJ1Y3R1cmUgbGV2ZWwgPSAzBAhtYXhJbmZyYQkAZAIJAGkCCQEEc3FydAQFBnBpZWNlcwAAAAAFBERPV04ABQACBAhuZXdMZXZlbAkAZAIFCGN1ckxldmVsAAEDAwUYS1NfQUxMT1dfQklHX0lORlJBX01FUkdFCQBmAgUIbmV3TGV2ZWwFCG1heEluZnJhBwkAAgEJAKwCAgIlQ3VycmVudGx5IG1heCBpbmZyYXN0cnVjdHVyZSBsZXZlbCA9IAkApAMBBQhtYXhJbmZyYQQEY29zdAkAawMFFUluZnJhVXBncmFkZUNvc3RTVXNkdAkAaAIFBnBpZWNlcwUIbmV3TGV2ZWwFBVNTSVpFAwMJAQEhAQUMc2hvdWxkVXNlTWF0CQECIT0CBQ1wYXltZW50QW1vdW50BQRjb3N0BwkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFBGNvc3QEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBCAUBYwJfMQQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEFBWJwS2V5BAVtTGlzdAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAIBXwQHbWF0VXNlZAkAawMFEUluZnJhVXBncmFkZUNvc3RTCQBoAgUGcGllY2VzBQhuZXdMZXZlbAUFU1NJWkUEBm5ld01hdAkAuQkCCQERc3VidHJhY3RNYXRlcmlhbHMDBQxzaG91bGRVc2VNYXQFBW1MaXN0BQdtYXRVc2VkAgFfBAtjbGFpbVJlc3VsdAkBCGNsYWltQWxsBAUEYWRkcggFAWMCXzIFBnBpZWNlcwUTY2xhaW1Nb2RlV2hUaGVuRHVjawQGd2hEYXRhCAULY2xhaW1SZXN1bHQCXzUEBm9sZFZvbAkBF2dldFdhcmVob3VzZVRvdGFsVm9sdW1lAQkAkQMCBQZ3aERhdGEFC3doSWR4TGV2ZWxzBApuZXdWb2xEYXRhCQC5CQIJAMwIAgkAkQMCCQC1CQIJAJEDAgUGd2hEYXRhBQt3aElkeExldmVscwIBXwAACQDMCAIJAKQDAQUIbmV3TGV2ZWwFA25pbAIBXwQGbmV3Vm9sCQEXZ2V0V2FyZWhvdXNlVG90YWxWb2x1bWUBBQpuZXdWb2xEYXRhBARsb2Z0CQC1CQIJAJEDAgUGd2hEYXRhBQl3aElkeExPRlQCAV8ECm5ld0xvZnRTdHIJALkJAgkAzAgCCQCRAwIFBGxvZnQFCXZvbExvY2tlZAkAzAgCCQCRAwIFBGxvZnQFC3ZvbE9jY3VwaWVkCQDMCAIJAKQDAQkAZQIJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAUHdm9sRnJlZQUGbmV3Vm9sBQZvbGRWb2wJAMwIAgkApAMBBQZuZXdWb2wFA25pbAIBXwkAlQoDCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFCGluZnJhS2V5BQhuZXdMZXZlbAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIIBQFjAl8yBQRhZGRyBQhuZXdMZXZlbAkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCCAULY2xhaW1SZXN1bHQCXzMFCGJwSWR4UmVzCQDMCAIFBm5ld01hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAIBOgkAzAgCCQELU3RyaW5nRW50cnkCCAULY2xhaW1SZXN1bHQCXzQJALkJAgkAzAgCBQpuZXdWb2xEYXRhCQDMCAIJAJEDAgUGd2hEYXRhBQh3aElkeFJlcwkAzAgCCQCRAwIFBndoRGF0YQUId2hJZHhNYXQJAMwIAgkAkQMCBQZ3aERhdGEFCXdoSWR4UHJvZAkAzAgCBQpuZXdMb2Z0U3RyBQNuaWwCAToFA25pbAgFC2NsYWltUmVzdWx0Al8xBQhuZXdMZXZlbAUHbWF0VXNlZAETdXBkYXRlU3RhdHNJbnRlcm5hbAQGbHZsS2V5BXhwS2V5CXBvaW50c0tleQdkZWx0YVhQBAJ4cAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQV4cEtleQAABAVuZXdYUAkAZAIFAnhwBQdkZWx0YVhQBAlsdmxQb2ludHMJAQdsZXZlbFVwAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQZsdmxLZXkAAAUFbmV3WFAJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUGbHZsS2V5CQCRAwIFCWx2bFBvaW50cwAACQDMCAIJAQxJbnRlZ2VyRW50cnkCBQV4cEtleQUFbmV3WFAJAMwIAgkBDEludGVnZXJFbnRyeQIFCXBvaW50c0tleQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJcG9pbnRzS2V5AAAJAJEDAgUJbHZsUG9pbnRzAAEFA25pbAUFbmV3WFABF3VwZGF0ZUR1Y2tTdGF0c0ludGVybmFsAgtkdWNrQXNzZXRJZAdkZWx0YVhQBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2R1Y2tBc3NldElkBARhZGRyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBEGtleUR1Y2tJZFRvT3duZXIBBQtkdWNrQXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDAwMFE0tTX0FMTE9XX1JPQk9fRFVDS1MJAAACCAUFYXNzZXQGaXNzdWVyBQR0aGlzBwkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFC1JPQk9fUFJFRklYBwkBE3VwZGF0ZVN0YXRzSW50ZXJuYWwECQEMa2V5VXNlckxldmVsAQUEYWRkcgkBCWtleVVzZXJYUAEFBGFkZHIJARFrZXlVc2VyRnJlZVBvaW50cwEFBGFkZHIFB2RlbHRhWFAJARN1cGRhdGVTdGF0c0ludGVybmFsBAkBDGtleUR1Y2tMZXZlbAEFC2R1Y2tBc3NldElkCQEJa2V5RHVja1hQAQULZHVja0Fzc2V0SWQJARFrZXlEdWNrRnJlZVBvaW50cwEFC2R1Y2tBc3NldElkBQdkZWx0YVhQARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgRhZGRyB2RlbHRhWFAJARN1cGRhdGVTdGF0c0ludGVybmFsBAkBDGtleVVzZXJMZXZlbAEFBGFkZHIJAQlrZXlVc2VyWFABBQRhZGRyCQERa2V5VXNlckZyZWVQb2ludHMBBQRhZGRyBQdkZWx0YVhQARJhY3RpdmF0ZU9uYm9hcmRBcnQBBGFkZHIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQIcmVmQnlLZXkJAQ9rZXlBZGRyZXNzUmVmQnkBBQRhZGRyBAVyZWZCeQkAoggBBQhyZWZCeUtleQMJAQEhAQkBCWlzRGVmaW5lZAEFBXJlZkJ5CQACAQIpWW91IGFyZSBub3QgZWxpZ2libGUgZm9yIE9OQk9BUkQgYXJ0aWZhY3QEBmFydEtleQkBHGtleU9uYm9hcmRBcnREdWNrQWN0aXZhdGVkQnkBBQRhZGRyBAdhcnREdWNrCQCiCAEFBmFydEtleQMJAQlpc0RlZmluZWQBBQdhcnREdWNrCQACAQkArAICAi9Zb3UgYWxyZWFkeSB1c2VkIHlvdXIgT05CT0FSRCBhcnRpZmFjdCBvbiBkdWNrIAkBBXZhbHVlAQUHYXJ0RHVjawQQZHVja0FjdGl2YXRvcktleQkBHGtleU9uYm9hcmRBcnRBY3RpdmF0ZWRPbkR1Y2sBBQtkdWNrQXNzZXRJZAQNZHVja0FjdGl2YXRvcgkAoggBBRBkdWNrQWN0aXZhdG9yS2V5AwkBCWlzRGVmaW5lZAEFDWR1Y2tBY3RpdmF0b3IJAAIBCQCsAgIJAKwCAgkArAICAglUaGUgZHVjayAFC2R1Y2tBc3NldElkAjQgYWxyZWFkeSBnb3QgcG9pbnRzIGZyb20gT05CT0FSRCBhcnRpZmFjdCBmcm9tIHVzZXIgCQEFdmFsdWUBBQ1kdWNrQWN0aXZhdG9yCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUGYXJ0S2V5BQtkdWNrQXNzZXRJZAkAzAgCCQELU3RyaW5nRW50cnkCBRBkdWNrQWN0aXZhdG9yS2V5BQRhZGRyBQNuaWwICQEXdXBkYXRlRHVja1N0YXRzSW50ZXJuYWwCBQtkdWNrQXNzZXRJZAUJeHBPbmJvYXJkAl8xARJhY3RpdmF0ZVByZXNhbGVBcnQCBGFkZHINbGFuZEFzc2V0SWRJbgQBYwkBFGNoZWNrQ2xhaW1Db25kaXRpb25zAwUEYWRkcgUTY2xhaW1Nb2RlV2hUaGVuRHVjawUNbGFuZEFzc2V0SWRJbgQLbGFuZEFzc2V0SWQIBQFjAl8yBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIIBQFjAl8zBQtyZWNMYW5kU2l6ZQQNYWN0aXZhdGlvbktleQkBIGtleUxhbmRBcnRTdGF0dXNCeVR5cGVBbmRBc3NldElkAgUKQVJUUFJFU0FMRQULbGFuZEFzc2V0SWQDCQBmAgkBC3ZhbHVlT3JFbHNlAgkAnwgBBQ1hY3RpdmF0aW9uS2V5AAAAAAkAAgECJVByZXNhbGUgYXJ0aWZhY3QgaXMgYWxyZWFkeSBhY3RpdmF0ZWQDCQBmAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIIBQFjAl8zBQpyZWNMYW5kTnVtBQ9QUkVTQUxFTlVNTEFORFMJAAIBCQCsAgIJAKwCAgkArAICBQpMQU5EUFJFRklYAgEgBQtsYW5kQXNzZXRJZAIlIGlzIG5vdCBlbGlnaWJsZSBmb3IgcHJlc2FsZSBhcnRpZmFjdAQLY2xhaW1SZXN1bHQJAQhjbGFpbUFsbAQFBGFkZHIFC2xhbmRBc3NldElkBQZwaWVjZXMFE2NsYWltTW9kZVdoVGhlbkR1Y2sJAM0IAgkAzQgCCQDNCAIIBQtjbGFpbVJlc3VsdAJfMQkBDEludGVnZXJFbnRyeQIFDWFjdGl2YXRpb25LZXkFBnBpZWNlcwkBC1N0cmluZ0VudHJ5AggFC2NsYWltUmVzdWx0Al8yCQC5CQIIBQtjbGFpbVJlc3VsdAJfMwIBOgkBC1N0cmluZ0VudHJ5AggFC2NsYWltUmVzdWx0Al80CQC5CQIIBQtjbGFpbVJlc3VsdAJfNQIBOgEPY2hlY2tUb3VybmFtZW50AQtkdWNrQXNzZXRJZAQGbGFzdElkCQELdmFsdWVPckVsc2UCCQCaCAIFEnRvdXJuYW1lbnRDb250cmFjdAUNbGFzdFRvdXJJZEtleQAABAtjdXJMb2NhdGlvbgkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAUPREVGQVVMVExPQ0FUSU9OAgFfBANub3cIBQlsYXN0QmxvY2sJdGltZXN0YW1wBAV0RGF0YQkBC2dldFRvdXJEYXRhAgUSdG91cm5hbWVudENvbnRyYWN0BQZsYXN0SWQEBnN0YXRpYwkAkQMCBQV0RGF0YQUJaWR4U3RhdGljBAdkeW5hbWljCQCRAwIFBXREYXRhBQppZHhEeW5hbWljAwkBAiE9AgkAkQMCBQtjdXJMb2NhdGlvbgUKbG9jSWR4VHlwZQIBVAcDAwMJAAACCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgULY3VyTG9jYXRpb24FD2xvY0lkeENvbnRpbmVudAUGbGFzdElkCQAAAgkAkQMCBQdkeW5hbWljBQ50RHluYW1pY1N0YXR1cwIKSU5QUk9HUkVTUwcJAGYCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUGc3RhdGljBQp0U3RhdGljRW5kBQNub3cHCQACAQIqWW91ciBkdWNrIGlzIHRha2luZyBwYXJ0IGluIHRoZSB0b3VybmFtZW50CQEJYXNCb29sZWFuAQkA/AcEBQR0aGlzAhZleGl0VG91cm5hbWVudEludGVybmFsCQDMCAIFC2R1Y2tBc3NldElkBQNuaWwFA25pbAENbWVyZ2VJbnRlcm5hbAYLbmV3TGFuZFNpemUIbmV3TGV2ZWwHZm9ybXVsYQRhZGRyDGxhbmRBc3NldElkcwduZWVkTWF0BAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQDCQEPY2hlY2tUb3VybmFtZW50AQULZHVja0Fzc2V0SWQJAAIBAh1tZXJnZUludGVybmFsX2NoZWNrVG91cm5hbWVudAoBCmNoZWNrTWVyZ2UCA2FjYwtsYW5kQXNzZXRJZAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAQJc2F2ZWRUaW1lCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAJ8IAQUHdGltZUtleQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQULbGFuZEFzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBAljb250aW5lbnQJAJEDAgUBZAUMcmVjQ29udGluZW50AwMJAQIhPQIIBQNhY2MCXzMCAAkBAiE9AggFA2FjYwJfMwUJY29udGluZW50BwkAAgECLkxhbmRzIHNob3VsZCBiZSBvbiB0aGUgc2FtZSBjb250aW5lbnQgdG8gbWVyZ2UECGxhbmRTaXplCQCRAwIFAWQFC3JlY0xhbmRTaXplBAdzaXplc0luCAUDYWNjAl8xBAFpCQETdmFsdWVPckVycm9yTWVzc2FnZQIJALMJAgUHc2l6ZXNJbgUIbGFuZFNpemUCJ1lvdSBoYXZlbid0IHBhc3NlZCBhbGwgdGhlIGxhbmRzIG5lZWRlZAQIc2l6ZXNPdXQJAKwCAgkArwICBQdzaXplc0luBQFpCQCwAgIFB3NpemVzSW4JAGQCBQFpAAEEBnBpZWNlcwkBD251bVBpZWNlc0J5U2l6ZQEFCGxhbmRTaXplBARhcnRzCQBkAggFA2FjYwJfMgkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAAABAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQIcmVxTGV2ZWwEByRtYXRjaDAFCGxhbmRTaXplAwkAAAICAVMFByRtYXRjaDAAAwMJAAACAgFNBQckbWF0Y2gwAAQDCQAAAgIBTAUHJG1hdGNoMAAFAwkAAAICAlhMBQckbWF0Y2gwAAYJAAIBAhpPbmx5IFMsIE0sIEwsIFhMIGNhbiBtZXJnZQMJAQIhPQIFCmluZnJhTGV2ZWwFCHJlcUxldmVsCQACAQIiQWxsIGxhbmRzIHNob3VsZCBiZSBtYXhlZCB0byBtZXJnZQQHbGFuZE51bQkAkQMCBQFkBQpyZWNMYW5kTnVtBA10ZXJyYWluQ291bnRzCQENY291bnRUZXJyYWlucwEJAJEDAgUBZAULcmVjVGVycmFpbnMECWRlbHRhVGltZQkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQlzYXZlZFRpbWUDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBBQlzYXZlZFRpbWUCDCwgY3VycmVudCA9IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQkBDGFwcGx5Qm9udXNlcwIFC2xhbmRBc3NldElkBQZwaWVjZXMECWxhbmRJbmRleAkAaQIFBnBpZWNlcwUFU1NJWkUEBWJwUmVzCQEGYWRkUmVzBQkAtQkCCAUDYWNjAl80AgFfBQ10ZXJyYWluQ291bnRzBQlkZWx0YVRpbWUFCWxhbmRJbmRleAUWZGFpbHlQcm9kdWN0aW9uQnlQaWVjZQQFcHJvcHMJARl1cGRhdGVQcm9wb3J0aW9uc0ludGVybmFsBAgFA2FjYwJfNgUNdGVycmFpbkNvdW50cwUJbGFuZEluZGV4AP///////////wEEBmNQcm9wcwkBGXVwZGF0ZVByb3BvcnRpb25zSW50ZXJuYWwECAUDYWNjA18xMAUNdGVycmFpbkNvdW50cwUJbGFuZEluZGV4AP///////////wEEC3N1bVRlcnJhaW5zCQEZdXBkYXRlUHJvcG9ydGlvbnNJbnRlcm5hbAQIBQNhY2MCXzkFDXRlcnJhaW5Db3VudHMFCWxhbmRJbmRleAABBAVsYW5kcwgFA2FjYwJfNwQDaWR4CQDPCAIFBWxhbmRzBQtsYW5kQXNzZXRJZAMJAQEhAQkBCWlzRGVmaW5lZAEFA2lkeAkAAgEJAKwCAgIgWW91ciBzdGFrZWQgbGFuZHMgZG9uJ3QgY29udGFpbiAFC2xhbmRBc3NldElkBAljdXN0b21LZXkJARprZXlMYW5kQXNzZXRJZFRvQ3VzdG9tTmFtZQEFC2xhbmRBc3NldElkBApjdXN0b21OYW1lCQELdmFsdWVPckVsc2UCCQCiCAEFCWN1c3RvbUtleQIACQCcCgoFCHNpemVzT3V0BQRhcnRzBQljb250aW5lbnQFBWJwUmVzCQDOCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCAUDYWNjAl81CQELRGVsZXRlRW50cnkBCQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgFC2xhbmRBc3NldElkBQRhZGRyCQELRGVsZXRlRW50cnkBCQEQa2V5TGFuZFRvQXNzZXRJZAEFB2xhbmROdW0JAQtEZWxldGVFbnRyeQEJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBFmtleUluZnJhTGV2ZWxCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBHmtleUluZnJhTGV2ZWxCeUFzc2V0SWRBbmRPd25lcgIFC2xhbmRBc3NldElkBQRhZGRyCQELRGVsZXRlRW50cnkBCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQtsYW5kQXNzZXRJZAkBC0RlbGV0ZUVudHJ5AQkBEWtleUxhbmROdW1Ub093bmVyAQUHbGFuZE51bQkBC0RlbGV0ZUVudHJ5AQkBEmtleVdhcmVob3VzZUJ5TGFuZAEFC2xhbmRBc3NldElkCQELRGVsZXRlRW50cnkBBQljdXN0b21LZXkJAQRCdXJuAgkA2QQBBQtsYW5kQXNzZXRJZAABAwkBAiE9AgUKY3VzdG9tTmFtZQIACQDMCAIJAQtEZWxldGVFbnRyeQEJARprZXlMYW5kQ3VzdG9tTmFtZVRvQXNzZXRJZAEFCmN1c3RvbU5hbWUFA25pbAUDbmlsBQVwcm9wcwkA0QgCBQVsYW5kcwkBBXZhbHVlAQUDaWR4CQBkAggFA2FjYwJfOAUGcGllY2VzBQtzdW1UZXJyYWlucwUGY1Byb3BzBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQIcHJvcExpc3QJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBCQERa2V5UmVzUHJvcG9ydGlvbnMAAgswXzBfMF8wXzBfMAIBXwQIbGFuZHNLZXkJARVrZXlTdGFrZWRMYW5kc0J5T3duZXIBBQRhZGRyBAhsYW5kc1N0cgkAoggBBQhsYW5kc0tleQQHbGFuZHNJbgMJAQlpc0RlZmluZWQBBQhsYW5kc1N0cgkAvQkCCQEFdmFsdWUBBQhsYW5kc1N0cgIBXwUDbmlsBAVjb250MAkAkQMCCQC1CQIICQEFdmFsdWUBCQDsBwEJANkEAQkAkQMCBQxsYW5kQXNzZXRJZHMAAAtkZXNjcmlwdGlvbgIBXwUMcmVjQ29udGluZW50BAljb250UHJvcHMJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEWa2V5UmVzVHlwZXNCeUNvbnRpbmVudAEFBWNvbnQwAgswXzBfMF8wXzBfMAIBXwQBcgoAAiRsBQxsYW5kQXNzZXRJZHMKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCcCgoFB2Zvcm11bGEAAAIACQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwUDbmlsBQhwcm9wTGlzdAUHbGFuZHNJbgAACQC1CQICCzBfMF8wXzBfMF8wAgFfBQljb250UHJvcHMKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBCmNoZWNrTWVyZ2UCBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDUJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFBAljb250aW5lbnQIBQFyAl8zBAxjb250aW5lbnRJZHgJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAzwgCBQpjb250aW5lbnRzBQljb250aW5lbnQJAKwCAgITVW5rbm93biBjb250aW5lbnQ6IAUJY29udGluZW50BAh0ZXJyYWlucwkBE2dlblRlcnJhaW5zRm9yTWVyZ2UCCAUBcgJfOQkAaQIJAQ9udW1QaWVjZXNCeVNpemUBBQtuZXdMYW5kU2l6ZQUFU1NJWkUEB2ZyZWVOdW0JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleU5leHRGcmVlTGFuZE51bQAJAGQCBQ9QUkVTQUxFTlVNTEFORFMAAQQKbmV3TGFuZE51bQkApAMBBQdmcmVlTnVtBAVpc3N1ZQkAwggFCQEHbmZ0TmFtZQIFCm5ld0xhbmROdW0FC25ld0xhbmRTaXplCQC5CQIJAMwIAgUKbmV3TGFuZE51bQkAzAgCBQtuZXdMYW5kU2l6ZQkAzAgCBQh0ZXJyYWlucwkAzAgCBQljb250aW5lbnQFA25pbAIBXwABAAAHBAdhc3NldElkCQC4CAEFBWlzc3VlBA5uZXdMYW5kQXNzZXRJZAkA2AQBBQdhc3NldElkBAZuZXdNYXQJALkJAgkBEXN1YnRyYWN0TWF0ZXJpYWxzAwkAZgIFB25lZWRNYXQAAAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAIBXwUHbmVlZE1hdAIBXwQJcGllY2VzS2V5CQEWa2V5U3Rha2VkUGllY2VzQnlPd25lcgEFBGFkZHIEDHN0YWtlZFBpZWNlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlwaWVjZXNLZXkAAAkAlAoCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCQDNCAIJAM0IAgkAzQgCCAUBcgJfNQMJAGYCCQCQAwEIBQFyAl83AAAJAQtTdHJpbmdFbnRyeQIFCGxhbmRzS2V5CQC7CQIIBQFyAl83AgFfCQELRGVsZXRlRW50cnkBBQhsYW5kc0tleQkBDEludGVnZXJFbnRyeQIFCXBpZWNlc0tleQMJAGYCCAUBcgJfOAUMc3Rha2VkUGllY2VzAAAJAGUCBQxzdGFrZWRQaWVjZXMIBQFyAl84CQEMSW50ZWdlckVudHJ5AgkBEmtleU5leHRGcmVlTGFuZE51bQAJAGQCBQdmcmVlTnVtAAEFBWlzc3VlCQELU3RyaW5nRW50cnkCCQEQa2V5TGFuZFRvQXNzZXRJZAEFCm5ld0xhbmROdW0FDm5ld0xhbmRBc3NldElkCQELU3RyaW5nRW50cnkCCQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQUObmV3TGFuZEFzc2V0SWQFBGFkZHIJAQtTdHJpbmdFbnRyeQIJARFrZXlMYW5kTnVtVG9Pd25lcgEFCm5ld0xhbmROdW0FBGFkZHIJAQxJbnRlZ2VyRW50cnkCCQEga2V5TGFuZEFydFN0YXR1c0J5VHlwZUFuZEFzc2V0SWQCBQpBUlRQUkVTQUxFBQ5uZXdMYW5kQXNzZXRJZAgFAXICXzIJAQxJbnRlZ2VyRW50cnkCCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFDm5ld0xhbmRBc3NldElkBQhuZXdMZXZlbAkBDEludGVnZXJFbnRyeQIJAR5rZXlJbmZyYUxldmVsQnlBc3NldElkQW5kT3duZXICBQ5uZXdMYW5kQXNzZXRJZAUEYWRkcgUIbmV3TGV2ZWwJAQtTdHJpbmdFbnRyeQIFBWJwS2V5CQC5CQIJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCCAUBcgJfNAkAzAgCBQZuZXdNYXQJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kBQNuaWwCAToJAQtTdHJpbmdFbnRyeQIJARFrZXlSZXNQcm9wb3J0aW9ucwAJALkJAggFAXICXzYCAV8JAQtTdHJpbmdFbnRyeQIJARZrZXlSZXNUeXBlc0J5Q29udGluZW50AQUJY29udGluZW50CQC5CQIIBQFyA18xMAIBXwkBC1N0cmluZ0VudHJ5AgkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkCQC5CQIJAMwIAgUJY29udGluZW50CQDMCAICAUwJAMwIAgUObmV3TGFuZEFzc2V0SWQFA25pbAIBXwkBDlNjcmlwdFRyYW5zZmVyAwkBEUBleHRyTmF0aXZlKDEwNjIpAQUEYWRkcgABBQdhc3NldElkBQ5uZXdMYW5kQXNzZXRJZAEDczJtAgRhZGRyDGxhbmRBc3NldElkcwkBDW1lcmdlSW50ZXJuYWwGAgFNAAMCBFNTU1MFBGFkZHIFDGxhbmRBc3NldElkcwAAAQNtMmwCBGFkZHIMbGFuZEFzc2V0SWRzCQENbWVyZ2VJbnRlcm5hbAYCAUwABAIDU01NBQRhZGRyBQxsYW5kQXNzZXRJZHMJAGgCBRFJbmZyYVVwZ3JhZGVDb3N0UwAEAQRsMnhsAgRhZGRyDGxhbmRBc3NldElkcwkBDW1lcmdlSW50ZXJuYWwGAgJYTAAFAgVTU1NNTAUEYWRkcgUMbGFuZEFzc2V0SWRzCQBoAgURSW5mcmFVcGdyYWRlQ29zdFMALwEGeGwyeHhsAgRhZGRyDGxhbmRBc3NldElkcwkBDW1lcmdlSW50ZXJuYWwGAgNYWEwABgIDTFhMBQRhZGRyBQxsYW5kQXNzZXRJZHMJAGgCBRFJbmZyYVVwZ3JhZGVDb3N0UwA2AQttZXJnZUNvbW1vbgIEYWRkcgxsYW5kQXNzZXRJZHMEByRtYXRjaDAJAJADAQUMbGFuZEFzc2V0SWRzAwkAAAIABAUHJG1hdGNoMAkBA3MybQIFBGFkZHIFDGxhbmRBc3NldElkcwMJAAACAAMFByRtYXRjaDAJAQNtMmwCBQRhZGRyBQxsYW5kQXNzZXRJZHMDCQAAAgAFBQckbWF0Y2gwCQEEbDJ4bAIFBGFkZHIFDGxhbmRBc3NldElkcwMJAAACAAIFByRtYXRjaDAJAQZ4bDJ4eGwCBQRhZGRyBQxsYW5kQXNzZXRJZHMJAAIBAg1Vbmtub3duIG1lcmdlAQZwcm9sb2cBAWkDAwkBAiE9AggFAWkMb3JpZ2luQ2FsbGVyBQxyZXN0Q29udHJhY3QJAQt2YWx1ZU9yRWxzZQIJAKAIAQkBCmtleUJsb2NrZWQABwcJAAIBAh9Db250cmFjdHMgYXJlIHVuZGVyIG1haW50ZW5hbmNlCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlMYXN0VHhJZEJ5VXNlcgEJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyCQDYBAEIBQFpDXRyYW5zYWN0aW9uSWQFA25pbCsBaQENY29uc3RydWN0b3JWMQEIcmVzdEFkZHIDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAhFQZXJtaXNzaW9uIGRlbmllZAkAzAgCCQELU3RyaW5nRW50cnkCCQEOa2V5UmVzdEFkZHJlc3MABQhyZXN0QWRkcgUDbmlsAWkBC3NhdmVJbnRlZ2VyAgNrZXkGYW1vdW50AwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIgc2F2ZUludGVnZXIgaXMgbm90IHB1YmxpYyBtZXRob2QJAMwIAgkBDEludGVnZXJFbnRyeQIFA2tleQUGYW1vdW50BQNuaWwBaQEKc2V0QmxvY2tlZAEJaXNCbG9ja2VkAwkBAiE9AggFAWkGY2FsbGVyBQR0aGlzCQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAMwIAgkBDEJvb2xlYW5FbnRyeQIJAQprZXlCbG9ja2VkAAUJaXNCbG9ja2VkBQNuaWwBaQEJc3Rha2VMYW5kAAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQHYXNzZXRJZAkBBXZhbHVlAQgFA3BtdAdhc3NldElkBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgMJAQIhPQIIBQNwbXQGYW1vdW50AAEJAAIBCQCsAgIJAKwCAgIETkZUIAUKTEFORFBSRUZJWAIkIHRva2VuIHNob3VsZCBiZSBhdHRhY2hlZCBhcyBwYXltZW50BAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkAwkBAiE9AggFBWFzc2V0Bmlzc3VlcgUEdGhpcwkAAgECF1Vua25vd24gaXNzdWVyIG9mIHRva2VuAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKTEFORFBSRUZJWAkAAgEJAKwCAgkArAICAglPbmx5IE5GVCAFCkxBTkRQUkVGSVgCFCB0b2tlbnMgYXJlIGFjY2VwdGVkBAtsYW5kTnVtU2l6ZQkAsAICCAUFYXNzZXQEbmFtZQAEBAdsYW5kTnVtAwkBCGNvbnRhaW5zAgULbGFuZE51bVNpemUCA1hYTAkAswICBQtsYW5kTnVtU2l6ZQADAwkBCGNvbnRhaW5zAgULbGFuZE51bVNpemUCAlhMCQCzAgIFC2xhbmROdW1TaXplAAIJALMCAgULbGFuZE51bVNpemUAAQMJAQEhAQkBCWlzRGVmaW5lZAEJALYJAQUHbGFuZE51bQkAAgEJAKwCAgIeQ2Fubm90IHBhcnNlIGxhbmQgbnVtYmVyIGZyb20gCAUFYXNzZXQEbmFtZQQLbGFuZEFzc2V0SWQJANgEAQUHYXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAMJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCEiBpcyBhbHJlYWR5IHN0YWtlZAQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8EDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCBQFkBQtyZWNUZXJyYWlucwQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQQJbGFuZEluZGV4CQBpAgUGcGllY2VzBQVTU0laRQQFcHJvcHMJARF1cGRhdGVQcm9wb3J0aW9ucwMFDXRlcnJhaW5Db3VudHMFCWxhbmRJbmRleAABBAxyZXNCeUNvbnRLZXkJARZrZXlSZXNUeXBlc0J5Q29udGluZW50AQkAkQMCBQFkBQxyZWNDb250aW5lbnQECWNvbnRQcm9wcwkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFDHJlc0J5Q29udEtleQILMF8wXzBfMF8wXzACAV8EEHVwZGF0ZWRDb250UHJvcHMJALkJAgkBGXVwZGF0ZVByb3BvcnRpb25zSW50ZXJuYWwEBQljb250UHJvcHMFDXRlcnJhaW5Db3VudHMFCWxhbmRJbmRleAABAgFfBAhsYW5kc0tleQkBFWtleVN0YWtlZExhbmRzQnlPd25lcgEFB2FkZHJlc3MECGxhbmRzU3RyCQCiCAEFCGxhbmRzS2V5BAVsYW5kcwMJAQlpc0RlZmluZWQBBQhsYW5kc1N0cgkAvQkCCQEFdmFsdWUBBQhsYW5kc1N0cgIBXwUDbmlsAwkBD2NvbnRhaW5zRWxlbWVudAIFBWxhbmRzBQtsYW5kQXNzZXRJZAkAAgEJAKwCAgIiWW91ciBzdGFrZWQgbGFuZHMgYWxyZWFkeSBjb250YWluIAULbGFuZEFzc2V0SWQDCQBnAgkAkAMBBQVsYW5kcwUYTUFYX0xBTkRTX1NUQUtFRF9CWV9VU0VSCQACAQkArAICCQCsAgICGVlvdXIgYWxyZWFkeSBzdGFrZWQgbWF4ICgJAKQDAQUYTUFYX0xBTkRTX1NUQUtFRF9CWV9VU0VSAgcpIGxhbmRzBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQJcGllY2VzS2V5CQEWa2V5U3Rha2VkUGllY2VzQnlPd25lcgEFB2FkZHJlc3MECW9sZFBpZWNlcwkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlwaWVjZXNLZXkAAAQJd2xnUmVzdWx0CQD8BwQFC3dsZ0NvbnRyYWN0AhJvblN0YWtlVW5zdGFrZUxhbmQJAMwIAgUHYWRkcmVzcwUDbmlsBQNuaWwJAJQKAgkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQd0aW1lS2V5CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBC1N0cmluZ0VudHJ5AgUIbGFuZHNLZXkJALsJAgkAzQgCBQVsYW5kcwULbGFuZEFzc2V0SWQCAV8JAMwIAgkBDEludGVnZXJFbnRyeQIFCXBpZWNlc0tleQkAZAIFCW9sZFBpZWNlcwUGcGllY2VzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAUHYWRkcmVzcwkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtBQdhZGRyZXNzCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEea2V5SW5mcmFMZXZlbEJ5QXNzZXRJZEFuZE93bmVyAgULbGFuZEFzc2V0SWQFB2FkZHJlc3MFCmluZnJhTGV2ZWwJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleVJlc1Byb3BvcnRpb25zAAUFcHJvcHMJAMwIAgkBC1N0cmluZ0VudHJ5AgUMcmVzQnlDb250S2V5BRB1cGRhdGVkQ29udFByb3BzBQNuaWwFDXByb2xvZ0FjdGlvbnMFCXdsZ1Jlc3VsdAFpAQt1bnN0YWtlTGFuZAENbGFuZEFzc2V0SWRJbgQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQEYWRkcgkApQgBCAUBaQZjYWxsZXIEAWMJARRjaGVja0NsYWltQ29uZGl0aW9ucwMFBGFkZHIFDWNsYWltTW9kZUR1Y2sFDWxhbmRBc3NldElkSW4EC2xhbmRBc3NldElkCAUBYwJfMgQBZAgFAWMCXzMECGxhbmRzS2V5CQEVa2V5U3Rha2VkTGFuZHNCeU93bmVyAQUEYWRkcgQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIFAWQFC3JlY1RlcnJhaW5zBAZwaWVjZXMJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIFAWQFC3JlY0xhbmRTaXplBAlsYW5kSW5kZXgJAGkCBQZwaWVjZXMFBVNTSVpFBAVwcm9wcwkBEXVwZGF0ZVByb3BvcnRpb25zAwUNdGVycmFpbkNvdW50cwUJbGFuZEluZGV4AP///////////wEEDHJlc0J5Q29udEtleQkBFmtleVJlc1R5cGVzQnlDb250aW5lbnQBCQCRAwIFAWQFDHJlY0NvbnRpbmVudAQJY29udFByb3BzCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUMcmVzQnlDb250S2V5AgswXzBfMF8wXzBfMAIBXwQQdXBkYXRlZENvbnRQcm9wcwkAuQkCCQEZdXBkYXRlUHJvcG9ydGlvbnNJbnRlcm5hbAQFCWNvbnRQcm9wcwUNdGVycmFpbkNvdW50cwUJbGFuZEluZGV4AP///////////wECAV8EC2NsYWltUmVzdWx0CQEIY2xhaW1BbGwEBQRhZGRyBQtsYW5kQXNzZXRJZAUGcGllY2VzBQ1jbGFpbU1vZGVEdWNrBAVsYW5kcwkAvQkCCQELdmFsdWVPckVsc2UCCQCiCAEFCGxhbmRzS2V5AgACAV8EA2lkeAkAzwgCBQVsYW5kcwULbGFuZEFzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBBQNpZHgJAAIBCQCsAgICIFlvdXIgc3Rha2VkIGxhbmRzIGRvbid0IGNvbnRhaW4gBQtsYW5kQXNzZXRJZAQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQOZ292UmVsZWFzZVRpbWUJAQt2YWx1ZU9yRWxzZQIJAJoIAgULZ292Q29udHJhY3QJARVrZXlVc2VyR3dsUmVsZWFzZVRpbWUBBQRhZGRyAAADCQBnAgUOZ292UmVsZWFzZVRpbWUFA25vdwkAAgEJAKwCAgI5WW91ciBnV0wgYXJlIHRha2luZyBwYXJ0IGluIHZvdGluZywgY2Fubm90IHVuc3Rha2UgdW50aWwgCQCkAwEFDmdvdlJlbGVhc2VUaW1lBA5hcmJSZWxlYXNlVGltZQkAZAIJAQt2YWx1ZU9yRWxzZQIJAJoIAgULd2xnQ29udHJhY3QJARRrZXlMYXN0QXJiVGltZUJ5VXNlcgEFBGFkZHIAAAUOYXJiaXRyYWdlRGVsYXkDCQBmAgUOYXJiUmVsZWFzZVRpbWUFA25vdwkAAgEJAKwCAgI/WW91ciBzdGFrZWQgbGFuZHMgdG9vayBwYXJ0IGluIGFyYml0cmFnZSwgY2Fubm90IHVuc3Rha2UgdW50aWwgCQCkAwEFDmFyYlJlbGVhc2VUaW1lBAlwaWVjZXNLZXkJARZrZXlTdGFrZWRQaWVjZXNCeU93bmVyAQUEYWRkcgQMc3Rha2VkUGllY2VzCQELdmFsdWVPckVsc2UCCQCfCAEFCXBpZWNlc0tleQAABAluZXdQaWVjZXMDCQBmAgUGcGllY2VzBQxzdGFrZWRQaWVjZXMAAAkAZQIFDHN0YWtlZFBpZWNlcwUGcGllY2VzBAl3bGdSZXN1bHQJAPwHBAULd2xnQ29udHJhY3QCEm9uU3Rha2VVbnN0YWtlTGFuZAkAzAgCBQRhZGRyBQNuaWwFA25pbAkAlAoCCQDOCAIJAMwIAgkBDlNjcmlwdFRyYW5zZmVyAwgFAWkGY2FsbGVyAAEJANkEAQULbGFuZEFzc2V0SWQJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgFC2xhbmRBc3NldElkBQRhZGRyCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlSZXNQcm9wb3J0aW9ucwAFBXByb3BzCQDMCAIJAQtTdHJpbmdFbnRyeQIFDHJlc0J5Q29udEtleQUQdXBkYXRlZENvbnRQcm9wcwkAzAgCCQELU3RyaW5nRW50cnkCCAULY2xhaW1SZXN1bHQCXzIJALkJAggFC2NsYWltUmVzdWx0Al8zAgE6CQDMCAIDCQBmAgkAkAMBBQVsYW5kcwABCQELU3RyaW5nRW50cnkCBQhsYW5kc0tleQkAuwkCCQDRCAIFBWxhbmRzCQEFdmFsdWUBBQNpZHgCAV8JAQtEZWxldGVFbnRyeQEFCGxhbmRzS2V5CQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlwaWVjZXNLZXkFCW5ld1BpZWNlcwUDbmlsBQ1wcm9sb2dBY3Rpb25zBQl3bGdSZXN1bHQBaQEJc3Rha2VEdWNrAAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQHYXNzZXRJZAkBBXZhbHVlAQgFA3BtdAdhc3NldElkBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgMJAQIhPQIIBQNwbXQGYW1vdW50AAEJAAIBCQCsAgIJAKwCAgIETkZUIAUKRFVDS1BSRUZJWAIkIHRva2VuIHNob3VsZCBiZSBhdHRhY2hlZCBhcyBwYXltZW50BAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkBAZpc1JvYm8DAwUTS1NfQUxMT1dfUk9CT19EVUNLUwkAAAIIBQVhc3NldAZpc3N1ZXIFBHRoaXMHCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQULUk9CT19QUkVGSVgHAwMDCQECIT0CCAUFYXNzZXQGaXNzdWVyBQ1pbmN1YmF0b3JBZGRyCQECIT0CCAUFYXNzZXQGaXNzdWVyBQticmVlZGVyQWRkcgcJAQEhAQUGaXNSb2JvBwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgISVW5rbm93biBpc3N1ZXIgb2YgBQpEVUNLUFJFRklYAgQgb3IgBQtST0JPX1BSRUZJWAIGIHRva2VuAwMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkRVQ0tQUkVGSVgJAQEhAQUGaXNSb2JvBwkAAgEJAKwCAgkArAICCQCsAgIJAKwCAgIJT25seSBORlQgBQpEVUNLUFJFRklYAgQgb3IgBQtST0JPX1BSRUZJWAIUIHRva2VucyBhcmUgYWNjZXB0ZWQECmFzc2V0SWRTdHIJANgEAQUHYXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQphc3NldElkU3RyAwkBCWlzRGVmaW5lZAEJAJ8IAQUHdGltZUtleQkAAgEJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQISIGlzIGFscmVhZHkgc3Rha2VkAwkBCWlzRGVmaW5lZAEJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwkAAgEJAKwCAgIdWW91IGFscmVhZHkgc3Rha2VkIG9uZSBkdWNrOiAIBQVhc3NldARuYW1lBAZsb2NLZXkJAQ9rZXlEdWNrTG9jYXRpb24BBQphc3NldElkU3RyBAhsb2NhdGlvbgkAoggBBQZsb2NLZXkEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQphc3NldElkU3RyBAhiYWNrcGFjawkAoggBBQVicEtleQQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFCmFzc2V0SWRTdHIEBW1heEhQCQEJbWF4SGVhbHRoAQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEMa2V5RHVja0xldmVsAQUKYXNzZXRJZFN0cgAABAljdXJIZWFsdGgJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoBQVtYXhIUAkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQd0aW1lS2V5CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpEVUNLUFJFRklYCQDYBAEFB2Fzc2V0SWQFB2FkZHJlc3MIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQtTdHJpbmdFbnRyeQIJARBrZXlEdWNrSWRUb093bmVyAQUKYXNzZXRJZFN0cgUHYWRkcmVzcwkAzAgCCQELU3RyaW5nRW50cnkCCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzBQphc3NldElkU3RyBQNuaWwDCQEJaXNEZWZpbmVkAQUIbG9jYXRpb24FA25pbAkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBmxvY0tleQUPREVGQVVMVExPQ0FUSU9OBQNuaWwDCQEJaXNEZWZpbmVkAQUIYmFja3BhY2sFA25pbAkAzggCCQDNCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkCGjA6MF8wXzBfMF8wXzA6MF8wXzBfMF8wXzA6BQNuaWwJAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgFCWN1ckhlYWx0aAUNcHJvbG9nQWN0aW9ucwFpAQt1bnN0YWtlRHVjawEKYXNzZXRJZFN0cgQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQHYXNzZXRJZAkA2QQBBQphc3NldElkU3RyBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQphc3NldElkU3RyAwkBASEBCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAMJAQEhAQkBCWlzRGVmaW5lZAEJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwkAAgEJAKwCAgkArAICAglUaGUgZHVjayAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEQa2V5RHVja0lkVG9Pd25lcgEFCmFzc2V0SWRTdHIJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFB2FkZHJlc3MJAAIBAhdTdGFrZWQgTkZUIGlzIG5vdCB5b3VycwMJAQ9jaGVja1RvdXJuYW1lbnQBBQphc3NldElkU3RyCQACAQIbdW5zdGFrZUR1Y2tfY2hlY2tUb3VybmFtZW50BAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQUKYXNzZXRJZFN0cgQFbWF4SFAJAQltYXhIZWFsdGgBCQELdmFsdWVPckVsc2UCCQCfCAEJAQxrZXlEdWNrTGV2ZWwBBQphc3NldElkU3RyAAAEBmhlYWx0aAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgFBW1heEhQAwkAZgIFBW1heEhQBQZoZWFsdGgJAAIBCQCsAgIJAKwCAgIZUGxlYXNlIGhlYWwgeW91ciBkdWNrIHRvIAkApAMBBQVtYXhIUAITaHAgYmVmb3JlIHVuc3Rha2luZwkAzggCCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABBQdhc3NldElkCQDMCAIJAQtEZWxldGVFbnRyeQEFB3RpbWVLZXkJAMwIAgkBC0RlbGV0ZUVudHJ5AQUJa2V5SGVhbHRoCQDMCAIJAQtEZWxldGVFbnRyeQEJAQ9rZXlEdWNrTG9jYXRpb24BBQphc3NldElkU3RyCQDMCAIJAQtEZWxldGVFbnRyeQEJARBrZXlEdWNrSWRUb093bmVyAQUKYXNzZXRJZFN0cgkAzAgCCQELRGVsZXRlRW50cnkBCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkRVQ0tQUkVGSVgFCmFzc2V0SWRTdHIFB2FkZHJlc3MJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUHYWRkcmVzcwUDbmlsBQ1wcm9sb2dBY3Rpb25zAWkBCGNsYWltUmVzAgZhbW91bnQObGFuZEFzc2V0SWRTdHIEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBAZyZXN1bHQJARBjbGFpbVJlc0ludGVybmFsBAUEYWRkcgUGYW1vdW50BQ1jbGFpbU1vZGVEdWNrBQ5sYW5kQXNzZXRJZFN0cgQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkCQCUCgIJAM4IAgkAzQgCCQDNCAIJAM4IAggFBnJlc3VsdAJfMQgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkCQBrAwUHeHBDbGFpbQUGYW1vdW50BQVNVUxUOAJfMQkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfMgkAuQkCCAUGcmVzdWx0Al8zAgE6CQELU3RyaW5nRW50cnkCCAUGcmVzdWx0Al80CQC5CQIIBQZyZXN1bHQCXzUCAToFDXByb2xvZ0FjdGlvbnMJAJEDAggFBnJlc3VsdAJfMwUIYnBJZHhSZXMBaQEMY2xhaW1SZXNUb1dIAgZhbW91bnQObGFuZEFzc2V0SWRTdHIEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBAZyZXN1bHQJARBjbGFpbVJlc0ludGVybmFsBAUEYWRkcgUGYW1vdW50BQtjbGFpbU1vZGVXaAUObGFuZEFzc2V0SWRTdHIJAJQKAgkAzggCCQDNCAIJAM0IAgkAzggCCAUGcmVzdWx0Al8xCAkBFnVwZGF0ZUFjY1N0YXRzSW50ZXJuYWwCBQRhZGRyCQBrAwUHeHBDbGFpbQUGYW1vdW50BQVNVUxUOAJfMQkBC1N0cmluZ0VudHJ5AggFBnJlc3VsdAJfMgkAuQkCCAUGcmVzdWx0Al8zAgE6CQELU3RyaW5nRW50cnkCCAUGcmVzdWx0Al80CQC5CQIIBQZyZXN1bHQCXzUCAToFDXByb2xvZ0FjdGlvbnMJAJEDAggFBnJlc3VsdAJfNQUId2hJZHhSZXMBaQEGZmxpZ2h0AgdtZXNzYWdlA3NpZwQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQIdXNlckFkZHIJAKUIAQgFAWkGY2FsbGVyBAFmCQEMZmxpZ2h0Q29tbW9uAwUIdXNlckFkZHIFB21lc3NhZ2UFA3NpZwQFbmV3SFAIBQFmAl8xBAtkdWNrQXNzZXRJZAgFAWYCXzIEBmxvY0tleQkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAoggBBQZsb2NLZXkFD0RFRkFVTFRMT0NBVElPTgQLbmV3TG9jYXRpb24IBQFmAl80AwkAAAIFC25ld0xvY2F0aW9uBQtjdXJMb2NhdGlvbgkAAgECIllvdSBjYW4ndCBmbHkgdG8gdGhlIHNhbWUgbG9jYXRpb24EBm5ld0xvYwkAtQkCBQtuZXdMb2NhdGlvbgIBXwQGaXNUb3VyCQAAAgkAkQMCBQZuZXdMb2MFCmxvY0lkeFR5cGUCAVQEB2lzRGVsaXYJAAACCQCRAwIFBm5ld0xvYwUKbG9jSWR4VHlwZQIBRAQFZXFLZXkJARBrZXlEdWNrRXF1aXBtZW50AQULZHVja0Fzc2V0SWQECWN1cnJlbnRFcQkBC3ZhbHVlT3JFbHNlAgkAoggBBQVlcUtleQIXLDssXyw7LF8sOyxfLDssXyw7LF8sOywEDSR0MDY2MDM1NjYxMzIJARFzdWJ0cmFjdEVxdWlwbWVudAIFCWN1cnJlbnRFcQgFAWYCXzUEBW5ld0VxCAUNJHQwNjYwMzU2NjEzMgJfMQQPc2hvdWxkWmVyb0J1ZmZzCAUNJHQwNjYwMzU2NjEzMgJfMgQNJHQwNjYxMzU2Nzk2NwMJAQEhAQkBCW9uTWlzc2lvbgIFEnRvdXJuYW1lbnRDb250cmFjdAULY3VyTG9jYXRpb24DBQZpc1RvdXIJAQxjaGVhdEF0dGVtcHQDBQtjdXJMb2NhdGlvbgULbmV3TG9jYXRpb24ABQMJAQEhAQUHaXNEZWxpdgMJAGYCBQVuZXdIUAAACQCUCgIFC25ld0xvY2F0aW9uBQVuZXdIUAkAlAoCBQtjdXJMb2NhdGlvbgAAAwkAZgIFBW5ld0hQAAAEAXMJAPwHBAUEdGhpcwIPcHJvY2Vzc0RlbGl2ZXJ5CQDMCAIFC2R1Y2tBc3NldElkBQNuaWwFA25pbAMJAAACBQFzBQFzCQCUCgIFC2N1ckxvY2F0aW9uBQVuZXdIUAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgkAlAoCBQtjdXJMb2NhdGlvbgAAAwkBDmlzSW5Ub3VybmFtZW50AgUSdG91cm5hbWVudENvbnRyYWN0BQtjdXJMb2NhdGlvbgMJAQEhAQkBDmlzSW5Ub3VybmFtZW50AgUSdG91cm5hbWVudENvbnRyYWN0BQtuZXdMb2NhdGlvbgkAAgECKllvdXIgZHVjayBpcyB0YWtpbmcgcGFydCBpbiB0aGUgdG91cm5hbWVudAQFc2NvcmUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQZuZXdMb2MFCGxvY0lkeElkBAZjdXJMb2MJALUJAgULY3VyTG9jYXRpb24CAV8EBmxhc3RJZAkBC3ZhbHVlT3JFbHNlAgkAmggCBRJ0b3VybmFtZW50Q29udHJhY3QFDWxhc3RUb3VySWRLZXkAAAMJAQIhPQIFBXNjb3JlCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBmN1ckxvYwUIbG9jSWR4SWQAAQkBDGNoZWF0QXR0ZW1wdAMFC2N1ckxvY2F0aW9uBQtuZXdMb2NhdGlvbgAHAwkAZgIFBW5ld0hQAAAECWxvY2FsQmVzdAkBC3ZhbHVlT3JFbHNlAgkAmggCBRJ0b3VybmFtZW50Q29udHJhY3QJARprZXlCZXN0UmVzdWx0QnlUb3VyQW5kRHVjawIFBmxhc3RJZAULZHVja0Fzc2V0SWQAAAQIdXBkTG9jYWwDCQBmAgUFc2NvcmUFCWxvY2FsQmVzdAkA/AcEBRJ0b3VybmFtZW50Q29udHJhY3QCDnNhdmVEdWNrUmVzdWx0CQDMCAIFC2R1Y2tBc3NldElkCQDMCAIFBXNjb3JlBQNuaWwFA25pbAUEdW5pdAMJAAACBQh1cGRMb2NhbAUIdXBkTG9jYWwJAJQKAgULbmV3TG9jYXRpb24FBW5ld0hQCQACAQIkU3RyaWN0IHZhbHVlIGlzIG5vdCBlcXVhbCB0byBpdHNlbGYuCQCUCgIFC2N1ckxvY2F0aW9uAAAJAAIBCQCsAgICFFVua25vd24gY3VyTG9jYXRpb246BQtjdXJMb2NhdGlvbgQJbG9jVG9TYXZlCAUNJHQwNjYxMzU2Nzk2NwJfMQQIaHBUb1NhdmUIBQ0kdDA2NjEzNTY3OTY3Al8yCQCUCgIJAM4IAgkAzggCCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUGbG9jS2V5BQlsb2NUb1NhdmUJAMwIAgkBC1N0cmluZ0VudHJ5AgUFZXFLZXkFBW5ld0VxCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBQhocFRvU2F2ZQUDbmlsBQ1wcm9sb2dBY3Rpb25zAwUPc2hvdWxkWmVyb0J1ZmZzCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQxrZXlEdWNrQnVmZnMBBQtkdWNrQXNzZXRJZAIJMF8wXzBfMF8wBQNuaWwFA25pbAgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkAwkAZgIFBW5ld0hQAAAFD3hwU3VjY2Vzc0ZsaWdodAUMeHBGYWlsRmxpZ2h0Al8xCAUBZgJfMwFpAQRoZWFsAwpxdWFudGl0eUwxCnF1YW50aXR5TDIKcXVhbnRpdHlMMwQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDAwMJAGYCAAAFCnF1YW50aXR5TDEGCQBmAgAABQpxdWFudGl0eUwyBgkAZgIAAAUKcXVhbnRpdHlMMwkAAgECG1F1YW50aXR5IGNhbm5vdCBiZSBuZWdhdGl2ZQQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAMJAQ9jaGVja1RvdXJuYW1lbnQBBQtkdWNrQXNzZXRJZAkAAgECFGhlYWxfY2hlY2tUb3VybmFtZW50BANxdHMJAMwIAgUKcXVhbnRpdHlMMQkAzAgCBQpxdWFudGl0eUwyCQDMCAIFCnF1YW50aXR5TDMFA25pbAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAVtYXhIUAkBCW1heEhlYWx0aAEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBDGtleUR1Y2tMZXZlbAEFC2R1Y2tBc3NldElkAAAECW9sZEhlYWx0aAkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgFBW1heEhQAwkAZwIFCW9sZEhlYWx0aAUFbWF4SFAJAAIBCQCsAgIJAKwCAgIPSFAgc2hvdWxkIGJlIDwgCQCkAwEFBW1heEhQAgggdG8gaGVhbAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkECHByb2RMaXN0AwkAAAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAIABQNuaWwJALwJAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kAgFfCgELaXRlcmF0ZVByb2QCA2FjYwZyZWNpcGUEAW4IBQNhY2MCXzIEAXgDCQBmAgkAkAMBBQhwcm9kTGlzdAUBbgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHByb2RMaXN0BQFuAAADCQBmAgADBQFuBAFxCQCRAwIFA3F0cwUBbgMJAGYCBQFxBQF4CQACAQkArAICCQCsAgIJAKwCAgIOWW91IGhhdmUgb25seSAJAKQDAQUBeAIEIG9mIAkAkQMCBQlwcm9kVHlwZXMFAW4JAJUKAwkAzQgCCAUDYWNjAl8xCQCkAwEJAGUCBQF4BQFxCQBkAgUBbgABCQBkAggFA2FjYwJfMwkAaAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCCQC1CQIFBnJlY2lwZQIBXwUKcklkeEVmZmVjdAUBcQkAlQoDCQDNCAIIBQNhY2MCXzEJAKQDAQUBeAkAZAIFAW4AAQgFA2FjYwJfMwQGcmVzdWx0CgACJGwFEHByb2R1Y3Rpb25NYXRyaXgKAAIkcwkAkAMBBQIkbAoABSRhY2MwCQCVCgMFA25pbAAAAAAKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBC2l0ZXJhdGVQcm9kAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyA1MAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAAsADAANAA4ADwAQABEAEgATABQAFQAWABcAGAAZABoAGwAcAB0AHgAfACAAIQAiACMAJAAlACYAJwAoACkAKgArACwALQAuAC8AMAAxADIECW5ld0hlYWx0aAkAlwMBCQDMCAIFBW1heEhQCQDMCAIJAGQCBQlvbGRIZWFsdGgIBQZyZXN1bHQCXzMFA25pbAkAlAoCCQDOCAIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoBQluZXdIZWFsdGgJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALoJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0CQDMCAIJALkJAggFBnJlc3VsdAJfMQIBXwUDbmlsAgE6BQNuaWwFDXByb2xvZ0FjdGlvbnMICQEXdXBkYXRlRHVja1N0YXRzSW50ZXJuYWwCBQtkdWNrQXNzZXRJZAkAaAIFBnhwSGVhbAkAZAIJAGQCBQpxdWFudGl0eUwxBQpxdWFudGl0eUwyBQpxdWFudGl0eUwzAl8xBQluZXdIZWFsdGgBaQEGaGVhbEVTAAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIIBQNwbXQHYXNzZXRJZAULdXNkdEFzc2V0SWQJAAIBAhpBbGxvd2VkIFVTRFQgcGF5bWVudCBvbmx5IQQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAMJAQ9jaGVja1RvdXJuYW1lbnQBBQtkdWNrQXNzZXRJZAkAAgECFmhlYWxFU19jaGVja1RvdXJuYW1lbnQECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQFbWF4SFAJAQltYXhIZWFsdGgBCQELdmFsdWVPckVsc2UCCQCfCAEJAQxrZXlEdWNrTGV2ZWwBBQtkdWNrQXNzZXRJZAAABAlvbGRIZWFsdGgJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoBQVtYXhIUAMJAGYCBQlvbGRIZWFsdGgAAAkAAgECKEhQIHNob3VsZCBiZSAwIHRvIGNhbGwgRW1lcmdlbmN5IFNlcnZpY2UEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAQLY3VycmVudFBhY2sJAQtnZXRCYWNrcGFjawEFBWJwS2V5BAhwcm9kTGlzdAMJAAACCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QCAAUDbmlsCQC8CQIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAIBXwQNbWVkS2l0QW1vdW50MQMJAGYCCQCQAwEFCHByb2RMaXN0AAAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQhwcm9kTGlzdAAAAAAEDW1lZEtpdEFtb3VudDIDCQBmAgkAkAMBBQhwcm9kTGlzdAABCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUIcHJvZExpc3QAAQAABA1tZWRLaXRBbW91bnQzAwkAZgIJAJADAQUIcHJvZExpc3QAAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFCHByb2RMaXN0AAIAAAMDAwkAZgIFDW1lZEtpdEFtb3VudDEAAAYJAGYCBQ1tZWRLaXRBbW91bnQyAAAGCQBmAgUNbWVkS2l0QW1vdW50MwAACQACAQIfWW91IGhhdmUgdG8gdXNlIG93biBNZWRpY2FsIEtpdAQIZXhpc3RTdHIJAJ0IAgUPZWNvbm9teUNvbnRyYWN0CQEOa2V5RXNXYXJlaG91c2UABAxleGlzdEFtb3VudHMDCQEJaXNEZWZpbmVkAQUIZXhpc3RTdHIJALwJAgkBBXZhbHVlAQUIZXhpc3RTdHICAV8FA25pbAQLZXhpc3RBbW91bnQDCQBmAgkAkAMBBQxleGlzdEFtb3VudHMAAAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFDGV4aXN0QW1vdW50cwAAAAADCQBnAgAABQtleGlzdEFtb3VudAkAAgECOVRoZXJlIGFyZSBubyBNZWRpY2FsIEtpdHMgTDEgYXQgRW1lcmdlbmN5IFNlcnZpY2Ugc3RvcmFnZQQJbmV3SGVhbHRoCQBkAgUJb2xkSGVhbHRoCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgAAAIBXwUKcklkeEVmZmVjdAQFbmV3RVMJALkJAgkAzAgCCQCkAwEJAGUCBQtleGlzdEFtb3VudAABCQDRCAIFDGV4aXN0QW1vdW50cwAAAgFfBAZyZWNpcGUJALUJAgkAkQMCBRBwcm9kdWN0aW9uTWF0cml4AAACAV8ECHRvdGFsTWF0CQESZ2V0UmVjaXBlTWF0ZXJpYWxzAQUGcmVjaXBlBAlzZWxsUHJpY2UJAGsDCQBoAgUIdG90YWxNYXQFCkVTU0VMTENPRUYFEFJFU09VUkNFUFJJQ0VNSU4JAGgCBQVNVUxUOAUOUFJPRFVDVFBLR1NJWkUDCQECIT0CCAUDcG10BmFtb3VudAUJc2VsbFByaWNlCQACAQkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAKQDAQUJc2VsbFByaWNlBAZyZXN1bHQJAQhhc1N0cmluZwEJAPwHBAUPZWNvbm9teUNvbnRyYWN0Ag91cGRhdGVFc1N0b3JhZ2UJAMwIAgUFbmV3RVMFA25pbAkAzAgCCQEPQXR0YWNoZWRQYXltZW50AgULdXNkdEFzc2V0SWQFCXNlbGxQcmljZQUDbmlsCQCUCgIJAM4IAgkAzQgCBQ1wcm9sb2dBY3Rpb25zCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoBQluZXdIZWFsdGgICQEXdXBkYXRlRHVja1N0YXRzSW50ZXJuYWwCBQtkdWNrQXNzZXRJZAUIeHBDYWxsRVMCXzEFBnJlc3VsdAFpAQ51cGRhdGVCYWNrcGFjawILZHVja0Fzc2V0SWQHbmV3UGFjawMJAQIhPQIIBQFpBmNhbGxlcgUPZWNvbm9teUNvbnRyYWN0CQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAUHbmV3UGFjawUDbmlsBQduZXdQYWNrAWkBD2NvbW1pdEZvclJhbmRvbQAEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpBAtmaW5pc2hCbG9jawkAZAIFBmhlaWdodAULcmFuZG9tRGVsYXkEBGFkZHIJAKUIAQgFAWkGY2FsbGVyCQCUCgIJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBCWtleUNvbW1pdAEFBGFkZHIFC2ZpbmlzaEJsb2NrBQNuaWwFDXByb2xvZ0FjdGlvbnMFC2ZpbmlzaEJsb2NrAWkBDHJldmVhbFJhbmRvbQEIbWF4VmFsdWUEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpBARhZGRyCQClCAEIBQFpBmNhbGxlcgQJZmluaXNoS2V5CQEJa2V5Q29tbWl0AQUEYWRkcgQLZmluaXNoQmxvY2sJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAnwgBBQlmaW5pc2hLZXkCJFlvdSBoYXZlIHRvIGNvbW1pdEZvclJhbmRvbSgpIGZpcnN0IQMJAGYCBQtmaW5pc2hCbG9jawUGaGVpZ2h0CQACAQkArAICAjRSYW5kb20gbnVtYmVyIGlzIG5vdCByZWFkeSB5ZXQsIHdhaXQgdW50aWwgaGVpZ2h0ID0gCQCkAwEFC2ZpbmlzaEJsb2NrBAdlbnRyb3B5CQEFdmFsdWUBCAkBBXZhbHVlAQkA7QcBBQtmaW5pc2hCbG9jawN2cmYEBHNhbHQJAJsDAQkBC3ZhbHVlT3JFbHNlAgkAoggBCQERa2V5TGFzdFR4SWRCeVVzZXIBBQRhZGRyAgAEBHJhbmQJAQ9nZXRSYW5kb21OdW1iZXIDBQhtYXhWYWx1ZQUEc2FsdAUHZW50cm9weQkAlAoCCQDOCAIJAMwIAgkBC0RlbGV0ZUVudHJ5AQUJZmluaXNoS2V5BQNuaWwFDXByb2xvZ0FjdGlvbnMFBHJhbmQBaQEIYnV5U0xhbmQABA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECHEV4YWN0bHkgb25lIHBheW1lbnQgcmVxdWlyZWQEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAAAwkBAiE9AggFA3BtdAdhc3NldElkBQt1c2R0QXNzZXRJZAkAAgECGkFsbG93ZWQgVVNEVCBwYXltZW50IG9ubHkhAwkBAiE9AggFA3BtdAZhbW91bnQFB0VYUFVTRFQJAAIBCQCsAgICG1BheW1lbnQgYXR0YWNoZWQgc2hvdWxkIGJlIAkApAMBBQdFWFBVU0RUBAZyZXN1bHQJARJleHBlZGl0aW9uSW50ZXJuYWwCCAUBaQZjYWxsZXIIBQFpDXRyYW5zYWN0aW9uSWQEC2FjcmVzUmVzdWx0CQEFYXNJbnQBCQD8BwQFDWFjcmVzQ29udHJhY3QCCWJ1cm5BY3JlcwkAzAgCBQxTX0NPU1RfQUNSRVMFA25pbAUDbmlsCQCUCgIJAM4IAgkAzggCCQDNCAIIBQZyZXN1bHQCXzEJAQ5TY3JpcHRUcmFuc2ZlcgMFD2Vjb25vbXlDb250cmFjdAgFA3BtdAZhbW91bnQFC3VzZHRBc3NldElkCAkBFnVwZGF0ZUFjY1N0YXRzSW50ZXJuYWwCCQClCAEIBQFpBmNhbGxlcgUKeHBOZXdTTGFuZAJfMQUNcHJvbG9nQWN0aW9ucwkAlAoCCAgFBnJlc3VsdAJfMgJfMQULYWNyZXNSZXN1bHQBaQEKZXhwZWRpdGlvbgIHbWVzc2FnZQNzaWcEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQECHVzZXJBZGRyCQClCAEIBQFpBmNhbGxlcgQBZgkBDGZsaWdodENvbW1vbgMFCHVzZXJBZGRyBQdtZXNzYWdlBQNzaWcEC2R1Y2tBc3NldElkCAUBZgJfMgQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAVicEtleQkBEWtleUJhY2twYWNrQnlEdWNrAQULZHVja0Fzc2V0SWQEC2N1cnJlbnRQYWNrCQELZ2V0QmFja3BhY2sBBQVicEtleQQFbUxpc3QJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8EBm5ld01hdAkAuQkCCQERc3VidHJhY3RNYXRlcmlhbHMDBgUFbUxpc3QFDEVYUE1BVEVSSUFMUwIBXwQFZXFLZXkJARBrZXlEdWNrRXF1aXBtZW50AQULZHVja0Fzc2V0SWQECWN1cnJlbnRFcQkBC3ZhbHVlT3JFbHNlAgkAoggBBQVlcUtleQIXLDssXyw7LF8sOyxfLDssXyw7LF8sOywEDSR0MDc1ODg3NzU5ODQJARFzdWJ0cmFjdEVxdWlwbWVudAIFCWN1cnJlbnRFcQgFAWYCXzUEBW5ld0VxCAUNJHQwNzU4ODc3NTk4NAJfMQQPc2hvdWxkWmVyb0J1ZmZzCAUNJHQwNzU4ODc3NTk4NAJfMgQBZQkBEmV4cGVkaXRpb25JbnRlcm5hbAIIBQFpBmNhbGxlcggFAWkNdHJhbnNhY3Rpb25JZAQCaWQICAUBZQJfMgJfMQQGcmVzdWx0AwkAZwIAAAgFAWYCXzEJAJUKAwkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoAAAJAMwIAgkBC1N0cmluZ0VudHJ5AgUFZXFLZXkFBW5ld0VxBQNuaWwCAAAACQCVCgMJAM4IAggFAWUCXzEDBQ9zaG91bGRaZXJvQnVmZnMJAMwIAgkBC1N0cmluZ0VudHJ5AgkBDGtleUR1Y2tCdWZmcwEFC2R1Y2tBc3NldElkAgkwXzBfMF8wXzAFA25pbAkAzQgCCQDNCAIJAM0IAgkAzQgCBQNuaWwJAQtTdHJpbmdFbnRyeQIJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAkAuQkCCQDMCAIICAUBZQJfMgJfMgkAzAgCAgFMCQDMCAIFAmlkBQNuaWwCAV8JAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgIBQFmAl8xCQELU3RyaW5nRW50cnkCBQVlcUtleQUFbmV3RXEJAQtTdHJpbmdFbnRyeQIFBWJwS2V5CQC5CQIJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUKYnBJZHhMZXZlbAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeFJlcwkAzAgCBQZuZXdNYXQJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUJYnBJZHhQcm9kBQNuaWwCAToFAmlkCAUBZgJfMwMJAQ9jaGVja1RvdXJuYW1lbnQBBQtkdWNrQXNzZXRJZAkAAgECGmV4cGVkaXRpb25fY2hlY2tUb3VybmFtZW50BAthY3Jlc1Jlc3VsdAkBBWFzSW50AQkA/AcEBQ1hY3Jlc0NvbnRyYWN0AglidXJuQWNyZXMJAMwIAgUMU19DT1NUX0FDUkVTBQNuaWwFA25pbAkAlAoCCQDOCAIJAM4IAggFBnJlc3VsdAJfMQgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkBQp4cE5ld1NMYW5kAl8xBQ1wcm9sb2dBY3Rpb25zCQCVCgMIBQZyZXN1bHQCXzIIBQZyZXN1bHQCXzMFC2FjcmVzUmVzdWx0AWkBEGJ1eVNMYW5kRm9yQWNyZXMABA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAQkAAgECImV4YWN0bHkgMSBwYXltZW50IG11c3QgYmUgYXR0YWNoZWQEA3BtdAkAkQMCCAUBaQhwYXltZW50cwAABANhbXQIBQNwbXQGYW1vdW50AwMJAQEhAQkBCWlzRGVmaW5lZAEIBQNwbXQHYXNzZXRJZAYJAQIhPQIJAQV2YWx1ZQEIBQNwbXQHYXNzZXRJZAUMYWNyZXNBc3NldElkCQACAQIUQUNSRVMgcGF5bWVudHMgb25seSEDCQECIT0CBQNhbXQFDFNfQ09TVF9BQ1JFUwkAAgEJAKwCAgIbUGF5bWVudCBhdHRhY2hlZCBzaG91bGQgYmUgCQCkAwEFDFNfQ09TVF9BQ1JFUwQGcmVzdWx0CQESZXhwZWRpdGlvbkludGVybmFsAggFAWkGY2FsbGVyCAUBaQ10cmFuc2FjdGlvbklkBAthY3Jlc1Jlc3VsdAkBBWFzSW50AQkA/AcEBQ1hY3Jlc0NvbnRyYWN0AglidXJuQWNyZXMJAMwIAgUMU19DT1NUX0FDUkVTBQNuaWwJAMwIAgkBD0F0dGFjaGVkUGF5bWVudAIFDGFjcmVzQXNzZXRJZAUDYW10BQNuaWwJAJQKAgkAzggCCQDOCAIIBQZyZXN1bHQCXzEICQEWdXBkYXRlQWNjU3RhdHNJbnRlcm5hbAIJAKUIAQgFAWkGY2FsbGVyBQp4cE5ld1NMYW5kAl8xBQ1wcm9sb2dBY3Rpb25zCQCUCgIICAUGcmVzdWx0Al8yAl8xBQthY3Jlc1Jlc3VsdAFpAQx1cGdyYWRlSW5mcmEBC2xhbmRBc3NldElkBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBAZyZXN1bHQJAQ11cEluZnJhQ29tbW9uBAYIBQFpBmNhbGxlcgAABQtsYW5kQXNzZXRJZAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAkAlAoCCQDOCAIJAM4IAggFBnJlc3VsdAJfMQUNcHJvbG9nQWN0aW9ucwgJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkCQBrAwUOeHBVcGdyYWRlSW5mcmEIBQZyZXN1bHQCXzMFBU1VTFQ4Al8xCAUGcmVzdWx0Al8yAWkBEGFjdGl2YXRlQXJ0aWZhY3QCB2FydE5hbWUObGFuZEFzc2V0SWRPcHQEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAZyZXN1bHQEByRtYXRjaDAFB2FydE5hbWUDCQAAAgIHUFJFU0FMRQUHJG1hdGNoMAkBEmFjdGl2YXRlUHJlc2FsZUFydAIFBGFkZHIFDmxhbmRBc3NldElkT3B0AwkAAAICB09OQk9BUkQFByRtYXRjaDAJARJhY3RpdmF0ZU9uYm9hcmRBcnQBBQRhZGRyCQACAQIQVW5rbm93biBhcnRpZmFjdAkAzggCBQZyZXN1bHQFDXByb2xvZ0FjdGlvbnMBaQEKbWVyZ2VMYW5kcwEMbGFuZEFzc2V0SWRzBA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBAZyZXN1bHQJAQttZXJnZUNvbW1vbgIJAKUIAQgFAWkGY2FsbGVyBQxsYW5kQXNzZXRJZHMJAJQKAgkAzggCCQDOCAIIBQZyZXN1bHQCXzEFDXByb2xvZ0FjdGlvbnMICQEWdXBkYXRlQWNjU3RhdHNJbnRlcm5hbAIJAKUIAQgFAWkGY2FsbGVyBQd4cE1lcmdlAl8xCAUGcmVzdWx0Al8yAWkBDWNhcmdvRXhjaGFuZ2UCDGNhcmdvTGlzdFN0cgtsYW5kQXNzZXRJZAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQKY2FyZ29QYXJ0cwkAvAkCBQxjYXJnb0xpc3RTdHICAToEBGFkZHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDCBpcyBvcnBoYW5lZAMJAQIhPQIFBW93bmVyBQRhZGRyCQACAQkArAICBQpMQU5EUFJFRklYAg0gaXMgbm90IHlvdXJzBAlsYW5kSW5kZXgJAGkCCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwULcmVjTGFuZFNpemUFBVNTSVpFBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAoggBCQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQFD0RFRkFVTFRMT0NBVElPTgQDbG9jCQC1CQIJAQV2YWx1ZQEFC2N1ckxvY2F0aW9uAgFfAwkBAiE9AgkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCAUwJAAIBCQCsAgIJAKwCAgIWRHVjayBsb2NhdGlvbiB0eXBlIGlzIAkAkQMCBQNsb2MFCmxvY0lkeFR5cGUCESwgYnV0IHNob3VsZCBiZSBMAwkBAiE9AgkAkQMCBQNsb2MFCGxvY0lkeElkBQtsYW5kQXNzZXRJZAkAAgEJAKwCAgIbRHVjayBzaG91bGQgYmUgb24gdGhlIGxhbmQgBQtsYW5kQXNzZXRJZAQFd2hLZXkJARJrZXlXYXJlaG91c2VCeUxhbmQBBQtsYW5kQXNzZXRJZAQJY3VycmVudFdoCQEMZ2V0V2FyZWhvdXNlAwUFd2hLZXkFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBnJlc3VsdAkBCW1vdmVTdHVmZgMFCmNhcmdvUGFydHMFCWN1cnJlbnRXaAULY3VycmVudFBhY2sEBGxvZnQJALUJAgkAkQMCBQljdXJyZW50V2gFCXdoSWR4TE9GVAIBXwQFbG9mdE8JAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUEbG9mdAULdm9sT2NjdXBpZWQIBQZyZXN1bHQCXzcEBWxvZnRGCQBlAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBGxvZnQFB3ZvbEZyZWUIBQZyZXN1bHQCXzcJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAugkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAggFBnJlc3VsdAJfNAkAzAgCCAUGcmVzdWx0Al81CQDMCAIIBQZyZXN1bHQCXzYFA25pbAIBOgkAzAgCCQELU3RyaW5nRW50cnkCBQV3aEtleQkAugkCCQDMCAIJAJEDAgUJY3VycmVudFdoBQt3aElkeExldmVscwkAzAgCCAUGcmVzdWx0Al8xCQDMCAIIBQZyZXN1bHQCXzIJAMwIAggFBnJlc3VsdAJfMwkAzAgCCQC5CQIJAMwIAgkAkQMCBQRsb2Z0BQl2b2xMb2NrZWQJAMwIAgkApAMBBQVsb2Z0TwkAzAgCCQCkAwEFBWxvZnRGCQDMCAIJAJEDAgUEbG9mdAUIdm9sVG90YWwFA25pbAIBXwUDbmlsAgE6BQNuaWwFDXByb2xvZ0FjdGlvbnMBaQENc2F2ZVdhcmVob3VzZQIFd2hTdHILbGFuZEFzc2V0SWQDCQECIT0CCAUBaQZjYWxsZXIFD2Vjb25vbXlDb250cmFjdAkAAgECDUFjY2VzcyBkZW5pZWQEBXdoS2V5CQESa2V5V2FyZWhvdXNlQnlMYW5kAQULbGFuZEFzc2V0SWQEAndoCQC8CQIFBXdoU3RyAgE6AwkBAiE9AgkAkAMBBQJ3aAAFCQACAQIwd2FyZWhvdXNlIHN0cmluZyBzaG91bGQgY29udGFpbiA0ICc6JyBzZXBhcmF0b3JzBAVsb2Z0TAkAkQMCCQC1CQIJAJEDAgUCd2gFCXdoSWR4TE9GVAIBXwUJdm9sTG9ja2VkBAVsb2Z0TwkBF2dldFdhcmVob3VzZU9jY3VwaWVkVm9sAQUCd2gEBWxvZnRUCQEXZ2V0V2FyZWhvdXNlVG90YWxWb2x1bWUBCQCRAwIFAndoBQt3aElkeExldmVscwQFbG9mdEYJAGUCCQBlAgUFbG9mdFQJAQ1wYXJzZUludFZhbHVlAQUFbG9mdEwFBWxvZnRPAwkAZgIAAAUFbG9mdEYJAAIBAjBPcGVyYXRpb24gbGVhZHMgdG8gbmVnYXRpdmUgZnJlZSB3YXJlaG91c2Ugc3BhY2UECG5ld1doU3RyCQC6CQIJAMwIAgkAkQMCBQJ3aAULd2hJZHhMZXZlbHMJAMwIAgkAkQMCBQJ3aAUId2hJZHhSZXMJAMwIAgkAkQMCBQJ3aAUId2hJZHhNYXQJAMwIAgkAkQMCBQJ3aAUJd2hJZHhQcm9kCQDMCAIJALkJAgkAzAgCBQVsb2Z0TAkAzAgCCQCkAwEFBWxvZnRPCQDMCAIJAKQDAQUFbG9mdEYJAMwIAgkApAMBBQVsb2Z0VAUDbmlsAgFfBQNuaWwCAToJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQV3aEtleQUIbmV3V2hTdHIFA25pbAUIbmV3V2hTdHIBaQENc2V0Q3VzdG9tTmFtZQMHYXNzZXRJZApjdXN0b21OYW1lBHR5cGUEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwABCQACAQIcRXhhY3RseSBvbmUgcGF5bWVudCByZXF1aXJlZAQDcG10CQEFdmFsdWUBCQCRAwIIBQFpCHBheW1lbnRzAAADCQECIT0CCAUDcG10B2Fzc2V0SWQFC3VzZHRBc3NldElkCQACAQIaQWxsb3dlZCBVU0RUIHBheW1lbnQgb25seSEDCQECIT0CCAUDcG10BmFtb3VudAUMUkVOQU1JTkdDT1NUCQACAQkArAICAhJQYXltZW50IHNob3VsZCBiZSAJAKQDAQUMUkVOQU1JTkdDT1NUAwkBCGNvbnRhaW5zAgUKY3VzdG9tTmFtZQICX18JAAIBCQCsAgICHk5hbWUgc2hvdWxkIG5vdCBjb250YWluICdfXyc6IAUKY3VzdG9tTmFtZQMJAGYCCQCxAgEFCmN1c3RvbU5hbWUFCk1BWE5BTUVMRU4JAAIBCQCsAgICGU5hbWUgdG9vIGxvbmcsIG1heExlbmd0aD0JAKQDAQUKTUFYTkFNRUxFTgQEYWRkcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEB2FjdGlvbnMEByRtYXRjaDAFBHR5cGUDCQAAAgIHQUNDT1VOVAUHJG1hdGNoMAQKcmV2ZXJzZUtleQkBFmtleUN1c3RvbU5hbWVUb0FkZHJlc3MBBQpjdXN0b21OYW1lBAluYW1lT3duZXIJAKIIAQUKcmV2ZXJzZUtleQMJAQlpc0RlZmluZWQBBQluYW1lT3duZXIJAAIBCQCsAgICGU5hbWUgYWxyZWFkeSByZWdpc3RlcmVkOiAFCmN1c3RvbU5hbWUEDWFkZHJUb05hbWVLZXkJARZrZXlBZGRyZXNzVG9DdXN0b21OYW1lAQUEYWRkcgQHb2xkTmFtZQkAoggBBQ1hZGRyVG9OYW1lS2V5BAdmcmVlT2xkAwkBCWlzRGVmaW5lZAEFB29sZE5hbWUJAMwIAgkBC0RlbGV0ZUVudHJ5AQkBFmtleUN1c3RvbU5hbWVUb0FkZHJlc3MBCQEFdmFsdWUBBQdvbGROYW1lBQNuaWwFA25pbAkAzggCCQDNCAIJAM0IAgUHZnJlZU9sZAkBC1N0cmluZ0VudHJ5AgUNYWRkclRvTmFtZUtleQUKY3VzdG9tTmFtZQkBC1N0cmluZ0VudHJ5AgUKcmV2ZXJzZUtleQUEYWRkcggJARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgUEYWRkcgUMeHBDdXN0b21OYW1lAl8xAwkAAAICBExBTkQFByRtYXRjaDAEBWFzc2V0CQEFdmFsdWUBCQDsBwEJANkEAQUHYXNzZXRJZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQdhc3NldElkAwkBASEBCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFB2Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMECnJldmVyc2VLZXkJARprZXlMYW5kQ3VzdG9tTmFtZVRvQXNzZXRJZAEFCmN1c3RvbU5hbWUECW5hbWVPd25lcgkAoggBBQpyZXZlcnNlS2V5AwkBCWlzRGVmaW5lZAEFCW5hbWVPd25lcgkAAgEJAKwCAgIZTmFtZSBhbHJlYWR5IHJlZ2lzdGVyZWQ6IAUKY3VzdG9tTmFtZQQOYXNzZXRUb05hbWVLZXkJARprZXlMYW5kQXNzZXRJZFRvQ3VzdG9tTmFtZQEFB2Fzc2V0SWQEB29sZE5hbWUJAKIIAQUOYXNzZXRUb05hbWVLZXkEB2ZyZWVPbGQDCQEJaXNEZWZpbmVkAQUHb2xkTmFtZQkAzAgCCQELRGVsZXRlRW50cnkBCQEaa2V5TGFuZEN1c3RvbU5hbWVUb0Fzc2V0SWQBCQEFdmFsdWUBBQdvbGROYW1lBQNuaWwFA25pbAkAzggCCQDNCAIJAM0IAgUHZnJlZU9sZAkBC1N0cmluZ0VudHJ5AgUOYXNzZXRUb05hbWVLZXkFCmN1c3RvbU5hbWUJAQtTdHJpbmdFbnRyeQIFCnJldmVyc2VLZXkFB2Fzc2V0SWQICQEWdXBkYXRlQWNjU3RhdHNJbnRlcm5hbAIFBGFkZHIFDHhwQ3VzdG9tTmFtZQJfMQMJAAACAgREVUNLBQckbWF0Y2gwBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFB2Fzc2V0SWQEB3RpbWVLZXkJARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQUHYXNzZXRJZAMDCQEBIQEJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkGCQEBIQEJAQlpc0RlZmluZWQBCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHIJAAIBCQCsAgIIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAQFb3duZXIJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEQa2V5RHVja0lkVG9Pd25lcgEFB2Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkRVQ0tQUkVGSVgCDSBpcyBub3QgeW91cnMECnJldmVyc2VLZXkJARprZXlEdWNrQ3VzdG9tTmFtZVRvQXNzZXRJZAEFCmN1c3RvbU5hbWUECW5hbWVPd25lcgkAoggBBQpyZXZlcnNlS2V5AwkBCWlzRGVmaW5lZAEFCW5hbWVPd25lcgkAAgEJAKwCAgIZTmFtZSBhbHJlYWR5IHJlZ2lzdGVyZWQ6IAUKY3VzdG9tTmFtZQQOYXNzZXRUb05hbWVLZXkJARprZXlEdWNrQXNzZXRJZFRvQ3VzdG9tTmFtZQEFB2Fzc2V0SWQEB29sZE5hbWUJAKIIAQUOYXNzZXRUb05hbWVLZXkEB2ZyZWVPbGQDCQEJaXNEZWZpbmVkAQUHb2xkTmFtZQkAzAgCCQELRGVsZXRlRW50cnkBCQEaa2V5RHVja0N1c3RvbU5hbWVUb0Fzc2V0SWQBCQEFdmFsdWUBBQdvbGROYW1lBQNuaWwFA25pbAkAzggCCQDNCAIJAM0IAgUHZnJlZU9sZAkBC1N0cmluZ0VudHJ5AgUOYXNzZXRUb05hbWVLZXkFCmN1c3RvbU5hbWUJAQtTdHJpbmdFbnRyeQIFCnJldmVyc2VLZXkFB2Fzc2V0SWQICQEXdXBkYXRlRHVja1N0YXRzSW50ZXJuYWwCBQdhc3NldElkBQx4cEN1c3RvbU5hbWUCXzEJAAIBAhNVbmtub3duIGVudGl0eSB0eXBlCQCUCgIJAM4IAgkAzQgCBQdhY3Rpb25zCQEOU2NyaXB0VHJhbnNmZXIDBQ9lY29ub215Q29udHJhY3QIBQNwbXQGYW1vdW50BQt1c2R0QXNzZXRJZAUNcHJvbG9nQWN0aW9ucwAAAWkBDHNldFJlZmVycmFscwIJb2xkUGxheWVyCW5ld1BsYXllcgMJAQIhPQIIBQFpD2NhbGxlclB1YmxpY0tleQUDcHViCQACAQIRUGVybWlzc2lvbiBkZW5pZWQEDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQDCQEBIQEJAQlpc0RlZmluZWQBCQCmCAEFCW9sZFBsYXllcgkAAgEJAKwCAgIRSW52YWxpZCBhZGRyZXNzOiAFCW9sZFBsYXllcgQKbmV3YmllQWRkcgkApggBBQluZXdQbGF5ZXIDCQEBIQEJAQlpc0RlZmluZWQBBQpuZXdiaWVBZGRyCQACAQkArAICAhFJbnZhbGlkIGFkZHJlc3M6IAUJbmV3UGxheWVyBAlvbGRMYXN0VHgJAKIIAQkBEWtleUxhc3RUeElkQnlVc2VyAQUJb2xkUGxheWVyAwkBASEBCQEJaXNEZWZpbmVkAQUJb2xkTGFzdFR4CQACAQIib2xkUGxheWVyIGRpZG4ndCBkbyBhbnkgdHggaW4gZ2FtZQMJAGcCAAAICQDvBwEJAQV2YWx1ZQEFCm5ld2JpZUFkZHIJYXZhaWxhYmxlCQACAQIWbmV3UGxheWVyIGhhcyBubyBXQVZFUwQHb2xkc0tleQkBCWtleU9sZGllcwAEBG9sZHMJAKIIAQUHb2xkc0tleQQGb2xkaWVzAwkBCWlzRGVmaW5lZAEFBG9sZHMJALwJAgkBBXZhbHVlAQUEb2xkcwIBXwUDbmlsAwkBD2NvbnRhaW5zRWxlbWVudAIFBm9sZGllcwUJbmV3UGxheWVyCQACAQkArAICBQluZXdQbGF5ZXICJiBpcyBub3QgbmV3YmllIChhbHJlYWR5IGhhcyByZWZlcnJhbHMpBAhyZWZCeUtleQkBD2tleUFkZHJlc3NSZWZCeQEFCW5ld1BsYXllcgQFcmVmQnkJAKIIAQUIcmVmQnlLZXkDAwkBCWlzRGVmaW5lZAEFBXJlZkJ5CQEJaXNEZWZpbmVkAQkApggBCQEFdmFsdWUBBQVyZWZCeQcJAAIBCQCsAgIJAKwCAgUJbmV3UGxheWVyAhQgYWxyZWFkeSBoYXMgcmVmQnk6IAkBBXZhbHVlAQUFcmVmQnkEB3JlZnNLZXkJARNrZXlBZGRyZXNzUmVmZXJyYWxzAQUJb2xkUGxheWVyBARyZWZzCQCiCAEFB3JlZnNLZXkECXJlZnNBcnJheQMJAQlpc0RlZmluZWQBBQRyZWZzCQC8CQIJAQV2YWx1ZQEFBHJlZnMCAV8FA25pbAMJAQ9jb250YWluc0VsZW1lbnQCBQlyZWZzQXJyYXkFCW5ld1BsYXllcgkAAgEJAKwCAgkArAICCQCsAgIFCW9sZFBsYXllcgISIGFscmVhZHkgY29udGFpbnMgBQluZXdQbGF5ZXICESB3aXRoaW4gcmVmZXJyYWxzBAduZXdSZWZzCQC6CQIJAM0IAgUJcmVmc0FycmF5BQluZXdQbGF5ZXICAV8EB25ld09sZHMDCQEPY29udGFpbnNFbGVtZW50AgUGb2xkaWVzBQlvbGRQbGF5ZXIJAQV2YWx1ZQEFBG9sZHMJALoJAgkAzQgCBQZvbGRpZXMFCW9sZFBsYXllcgIBXwkAlAoCCQDOCAIJAMwIAgkBC1N0cmluZ0VudHJ5AgUIcmVmQnlLZXkFCW9sZFBsYXllcgkAzAgCCQELU3RyaW5nRW50cnkCBQdyZWZzS2V5BQduZXdSZWZzCQDMCAIJAQtTdHJpbmdFbnRyeQIFB29sZHNLZXkFB25ld09sZHMFA25pbAUNcHJvbG9nQWN0aW9ucwAAAWkBEGRpc3RyaWJ1dGVQb2ludHMFCHN0cmVuZ3RoCGFjY3VyYWN5CWludGVsbGVjdAllbmR1cmFuY2UJZGV4dGVyaXR5BA1wcm9sb2dBY3Rpb25zCQEGcHJvbG9nAQUBaQMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECFE5vIHBheW1lbnRzIHJlcXVpcmVkBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQLdmlydFdsZ0RhdGEJAQlhc0FueUxpc3QBCQD8BwQFC3dsZ0NvbnRyYWN0AhJjaGVja1dsZ1hwUkVBRE9OTFkJAMwIAgUEYWRkcgUDbmlsBQNuaWwEDXZpcnRXbGdQb2ludHMJAQVhc0ludAEJAJEDAgULdmlydFdsZ0RhdGEAAQQNJHQwOTE3OTY5MjE4NgMJAGcCAAAFDXZpcnRXbGdQb2ludHMJAJQKAgAABQNuaWwEB2RlbHRhWFAJAQVhc0ludAEJAPwHBAULd2xnQ29udHJhY3QCCXRha2VXbGdYcAkAzAgCBQRhZGRyBQNuaWwFA25pbAMJAAACBQdkZWx0YVhQBQdkZWx0YVhQCQCUCgIFDXZpcnRXbGdQb2ludHMJAMwIAgkBDEludGVnZXJFbnRyeQIJAQxrZXlVc2VyTGV2ZWwBBQRhZGRyCQEFYXNJbnQBCQCRAwIFC3ZpcnRXbGdEYXRhAAAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQlrZXlVc2VyWFABBQRhZGRyCQEFYXNJbnQBCQCRAwIFC3ZpcnRXbGdEYXRhAAIFA25pbAkAAgECJFN0cmljdCB2YWx1ZSBpcyBub3QgZXF1YWwgdG8gaXRzZWxmLgQJd2xnUG9pbnRzCAUNJHQwOTE3OTY5MjE4NgJfMQQKd2xnQWN0aW9ucwgFDSR0MDkxNzk2OTIxODYCXzIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQKZnJlZUtleUFjYwkBEWtleVVzZXJGcmVlUG9pbnRzAQUEYWRkcgQNZnJlZVBvaW50c0FjYwkAZAIJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUKZnJlZUtleUFjYwAABQl3bGdQb2ludHMEC2ZyZWVLZXlEdWNrCQERa2V5RHVja0ZyZWVQb2ludHMBBQtkdWNrQXNzZXRJZAQOZnJlZVBvaW50c0R1Y2sJAQt2YWx1ZU9yRWxzZQIJAJ8IAQULZnJlZUtleUR1Y2sAAAQHc3VtRnJlZQkAZAIFDWZyZWVQb2ludHNBY2MFDmZyZWVQb2ludHNEdWNrBA9zdW1Ub0Rpc3RyaWJ1dGUJAGQCCQBkAgkAZAIJAGQCBQhzdHJlbmd0aAUIYWNjdXJhY3kFCWludGVsbGVjdAUJZW5kdXJhbmNlBQlkZXh0ZXJpdHkDCQBmAgUPc3VtVG9EaXN0cmlidXRlBQdzdW1GcmVlCQACAQkArAICCQCsAgICD1RoZXJlIGFyZSBvbmx5IAkApAMBBQdzdW1GcmVlAhogZnJlZSBwb2ludHMgdG8gZGlzdHJpYnV0ZQQIY2hhcnNLZXkJAQxrZXlEdWNrQ2hhcnMBBQtkdWNrQXNzZXRJZAQFY2hhcnMJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQhjaGFyc0tleQIJMF8wXzBfMF8wAgFfBAZuZXdBY2MJAGUCBQ1mcmVlUG9pbnRzQWNjBQ9zdW1Ub0Rpc3RyaWJ1dGUJAJQKAgkAzggCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIFCmZyZWVLZXlBY2MDCQBmAgAABQZuZXdBY2MAAAUGbmV3QWNjCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQtmcmVlS2V5RHVjawMJAGYCAAAFBm5ld0FjYwkAZAIFDmZyZWVQb2ludHNEdWNrBQZuZXdBY2MFDmZyZWVQb2ludHNEdWNrCQDMCAIJAQtTdHJpbmdFbnRyeQIFCGNoYXJzS2V5CQC5CQIJAMwIAgkApAMBCQBkAgkBDXBhcnNlSW50VmFsdWUBCQCRAwIFBWNoYXJzBQxjaGFyU3RyZW5ndGgFCHN0cmVuZ3RoCQDMCAIJAKQDAQkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVjaGFycwUMY2hhckFjY3VyYWN5BQhhY2N1cmFjeQkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJJbnRlbGxlY3QFCWludGVsbGVjdAkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJFbmR1cmFuY2UFCWVuZHVyYW5jZQkAzAgCCQCkAwEJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFY2hhcnMFDWNoYXJEZXh0ZXJpdHkFCWRleHRlcml0eQUDbmlsAgFfBQNuaWwFDXByb2xvZ0FjdGlvbnMFCndsZ0FjdGlvbnMAAAFpARxzcGxpdEJ5R2xvYmFsV2VpZ2h0c1JFQURPTkxZAQZhbW91bnQJAJQKAgUDbmlsCQESZ2V0TmVlZGVkTWF0ZXJpYWxzAQUGYW1vdW50AWkBJHNwbGl0QnlHbG9iYWxBbmRMb2NhbFdlaWdodHNSRUFET05MWQMJbWF0QW1vdW50CXJlc0Ftb3VudAh0ZXJyYWlucwQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBBQh0ZXJyYWlucwkAlAoCBQNuaWwJAJQKAgkBEmdldE5lZWRlZE1hdGVyaWFscwEFCW1hdEFtb3VudAkBE2Rpc3RyaWJ1dGVCeVdlaWdodHMCBQlyZXNBbW91bnQFDXRlcnJhaW5Db3VudHMBaQETZ2V0QmFja3BhY2tSRUFET05MWQELZHVja0Fzc2V0SWQJAJQKAgUDbmlsCQC5CQIJAQtnZXRCYWNrcGFjawEJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkAgE6AWkBFGdldFdhcmVob3VzZVJFQURPTkxZAQtsYW5kQXNzZXRJZAQFYXNzZXQJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQJbGFuZEluZGV4CQBpAgkBD251bVBpZWNlc0J5U2l6ZQEJAJEDAgkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8FC3JlY0xhbmRTaXplBQVTU0laRQQKaW5mcmFMZXZlbAkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5SW5mcmFMZXZlbEJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAAJAJQKAgUDbmlsCQC6CQIJAQxnZXRXYXJlaG91c2UDCQESa2V5V2FyZWhvdXNlQnlMYW5kAQULbGFuZEFzc2V0SWQFCWxhbmRJbmRleAUKaW5mcmFMZXZlbAIBOgFpAQpzYXZlTGFzdFR4AAMJAQEhAQkBD2NvbnRhaW5zRWxlbWVudAIJAMwIAgULd2xnQ29udHJhY3QJAMwIAgUPZWNvbm9teUNvbnRyYWN0CQDMCAIFEnRvdXJuYW1lbnRDb250cmFjdAkAzAgCBQ1hY3Jlc0NvbnRyYWN0BQNuaWwIBQFpBmNhbGxlcgkAAgECDUFjY2VzcyBkZW5pZWQJAJQKAgkBBnByb2xvZwEFAWkAKgFpAQ91cGRhdGVEdWNrU3RhdHMCC2R1Y2tBc3NldElkB2RlbHRhWFADCQECIT0CCAUBaQZjYWxsZXIFD2Vjb25vbXlDb250cmFjdAkAAgECDUFjY2VzcyBkZW5pZWQJARd1cGRhdGVEdWNrU3RhdHNJbnRlcm5hbAIFC2R1Y2tBc3NldElkBQdkZWx0YVhQAWkBDnVwZGF0ZUFjY1N0YXRzAgRhZGRyB2RlbHRhWFADCQEBIQEJAQ9jb250YWluc0VsZW1lbnQCCQDMCAIFC3dsZ0NvbnRyYWN0CQDMCAIFD2Vjb25vbXlDb250cmFjdAkAzAgCBQ1hY3Jlc0NvbnRyYWN0BQNuaWwIBQFpBmNhbGxlcgkAAgECDUFjY2VzcyBkZW5pZWQJARZ1cGRhdGVBY2NTdGF0c0ludGVybmFsAgUEYWRkcgUHZGVsdGFYUAFpAQllcXVpcER1Y2sBCWVxdWlwbWVudAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAhRObyBwYXltZW50cyByZXF1aXJlZAQEYWRkcgkApQgBCAUBaQxvcmlnaW5DYWxsZXIEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQUEYWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAMJAQ9jaGVja1RvdXJuYW1lbnQBBQtkdWNrQXNzZXRJZAkAAgECGWVxdWlwRHVja19jaGVja1RvdXJuYW1lbnQEBWVxS2V5CQEQa2V5RHVja0VxdWlwbWVudAEFC2R1Y2tBc3NldElkBAtjdXJyZW50U2VncwkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFBWVxS2V5AhcsOyxfLDssXyw7LF8sOyxfLDssXyw7LAIBXwQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkBC2dldEJhY2twYWNrAQUFYnBLZXkEBW5ld0VxCQC1CQIFCWVxdWlwbWVudAIBXwMJAQIhPQIJAJADAQUFbmV3RXEFC05VTVNFR01FTlRTCQACAQIWV3JvbmcgZXF1aXBtZW50IHN0cmluZwQJdGVtcFByb2RCCQEGZHJlc3NCBAULY3VycmVudFNlZ3MJAQ5wcm9kU3RyVG9CeXRlcwEJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAYFA25pbAQIc2VnQnBBdXgJAJEDAgkAtQkCCQCRAwIFBW5ld0VxBQtzZWdCYWNrcGFjawIBOwABBApidWZmRWZmZWN0AwkAAAIFCHNlZ0JwQXV4AgAAAAQEYXV4MAkAkQMCCQC1CQIFCHNlZ0JwQXV4AgEsAAADCQAAAgUEYXV4MAIAAAAEBmlkeENudAkAtQkCBQRhdXgwAgE6BANpZHgJAJEDAgUGaWR4Q250AAAEA2NudAkAkQMCBQZpZHhDbnQAAQMDAwMDCQAAAgUDaWR4AgIwNgYJAAACBQNpZHgCAjA3BgkAAAIFA2lkeAICMDgJAQIhPQIFA2NudAIABwkAZgIJAQ1wYXJzZUludFZhbHVlAQUDY250AAAHCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgkAtQkCCQCRAwIFEHByb2R1Y3Rpb25NYXRyaXgJAQ1wYXJzZUludFZhbHVlAQUDaWR4AgFfBQpySWR4RWZmZWN0AAAEBXN0YXRzCQEMZ2V0RHVja1N0YXRzBAUEdGhpcwULZHVja0Fzc2V0SWQFCmJ1ZmZFZmZlY3QGBAhuZXdQcm9kQgkBBmRyZXNzQgQFBW5ld0VxBQl0ZW1wUHJvZEIHBQVzdGF0cwQKbmV3UHJvZFN0cgkBDmJ5dGVzVG9Qcm9kU3RyAQUIbmV3UHJvZEIJAJQKAgkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWVxS2V5BQllcXVpcG1lbnQJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALoJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0CQDMCAIFCm5ld1Byb2RTdHIFA25pbAIBOgkAzAgCCQELU3RyaW5nRW50cnkCCQEMa2V5RHVja0J1ZmZzAQULZHVja0Fzc2V0SWQJALkJAgkAzAgCCQCkAwEJAJEDAgUFc3RhdHMABwkAzAgCCQCkAwEJAJEDAgUFc3RhdHMACAkAzAgCCQCkAwEJAJEDAgUFc3RhdHMACQkAzAgCCQCkAwEJAJEDAgUFc3RhdHMACgkAzAgCCQCkAwEJAJEDAgUFc3RhdHMACwUDbmlsAgFfBQNuaWwFDXByb2xvZ0FjdGlvbnMAAAFpAQ9mb3J0aWZpY2F0ZUxhbmQCC2xhbmRBc3NldElkBHBsYW4EDXByb2xvZ0FjdGlvbnMJAQZwcm9sb2cBBQFpAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIUTm8gcGF5bWVudHMgcmVxdWlyZWQEBGFkZHIJAKUIAQgFAWkMb3JpZ2luQ2FsbGVyBAtkdWNrQXNzZXRJZAkBC3ZhbHVlT3JFbHNlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQRhZGRyAgAECWR1Y2tTdGF0cwkBDGdldER1Y2tTdGF0cwQFBHRoaXMFC2R1Y2tBc3NldElkAAAHBAdmb3J0S2V5CQEXa2V5Rm9ydGlmaWNhdGlvbnNCeUxhbmQBBQtsYW5kQXNzZXRJZAQMY3VycmVudEZvcnRzCQC1CQIJAQt2YWx1ZU9yRWxzZQIJAKIIAQUHZm9ydEtleQIMOjBfMTU6MF8xODowAgFfBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkBAlsYW5kSW5kZXgJAGkCCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwULcmVjTGFuZFNpemUFBVNTSVpFBAppbmZyYUxldmVsCQELdmFsdWVPckVsc2UCCQCfCAEJARZrZXlJbmZyYUxldmVsQnlBc3NldElkAQULbGFuZEFzc2V0SWQAAAQFd2hLZXkJARJrZXlXYXJlaG91c2VCeUxhbmQBBQtsYW5kQXNzZXRJZAQCd2gJAQxnZXRXYXJlaG91c2UDBQV3aEtleQUJbGFuZEluZGV4BQppbmZyYUxldmVsBAdjdXJMb2Z0CQC1CQIJAJEDAgUCd2gFCXdoSWR4TE9GVAIBXwQEY3VyTwkBDXBhcnNlSW50VmFsdWUBCQCRAwIFB2N1ckxvZnQFC3ZvbE9jY3VwaWVkBARjdXJGCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUHY3VyTG9mdAUHdm9sRnJlZQQIbmV3Rm9ydHMJALUJAgUEcGxhbgIBXwQNJHQwOTg5NDc5OTA2MgkBBWZvcnRCBgUMY3VycmVudEZvcnRzCQEOcHJvZFN0clRvQnl0ZXMBCQCRAwIFAndoBQl3aElkeFByb2QFBGN1ck8FBGN1ckYGBQNuaWwECXRlbXBQcm9kQggFDSR0MDk4OTQ3OTkwNjICXzEEBXRlbXBPCAUNJHQwOTg5NDc5OTA2MgJfMgQFdGVtcEYIBQ0kdDA5ODk0Nzk5MDYyAl8zBA0kdDA5OTA2NTk5MTYxCQEFZm9ydEIGBQhuZXdGb3J0cwUJdGVtcFByb2RCBQV0ZW1wTwUFdGVtcEYHBQlkdWNrU3RhdHMECG5ld1Byb2RCCAUNJHQwOTkwNjU5OTE2MQJfMQQEbmV3TwgFDSR0MDk5MDY1OTkxNjECXzIEBG5ld0YIBQ0kdDA5OTA2NTk5MTYxAl8zBApuZXdQcm9kU3RyCQEOYnl0ZXNUb1Byb2RTdHIBBQhuZXdQcm9kQgQKbmV3TG9mdFN0cgkAuQkCCQDMCAIJAJEDAgUHY3VyTG9mdAUJdm9sTG9ja2VkCQDMCAIJAKQDAQUEbmV3TwkAzAgCCQCkAwEFBG5ld0YJAMwIAgkAkQMCBQdjdXJMb2Z0BQh2b2xUb3RhbAUDbmlsAgFfCQCUCgIJAM4IAgkAzAgCCQELU3RyaW5nRW50cnkCBQdmb3J0S2V5BQRwbGFuCQDMCAIJAQtTdHJpbmdFbnRyeQIFBXdoS2V5CQC6CQIJAMwIAgkAkQMCBQJ3aAULd2hJZHhMZXZlbHMJAMwIAgkAkQMCBQJ3aAUId2hJZHhSZXMJAMwIAgkAkQMCBQJ3aAUId2hJZHhNYXQJAMwIAgUKbmV3UHJvZFN0cgkAzAgCBQpuZXdMb2Z0U3RyBQNuaWwCAToFA25pbAUNcHJvbG9nQWN0aW9ucwAAAWkBE2luaXREdWNrVG91ckF0dGVtcHQBC2R1Y2tBc3NldElkAwkBAiE9AggFAWkGY2FsbGVyBRJ0b3VybmFtZW50Q29udHJhY3QJAAIBAg1BY2Nlc3MgZGVuaWVkBAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQEBW1heEhQCQEJbWF4SGVhbHRoAQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEMa2V5RHVja0xldmVsAQULZHVja0Fzc2V0SWQAAAQJY3VySGVhbHRoCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aAUFbWF4SFAECWN1ckxvY0tleQkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAoggBBQljdXJMb2NLZXkFD0RFRkFVTFRMT0NBVElPTgQGbGFzdElkCQELdmFsdWVPckVsc2UCCQCaCAIFEnRvdXJuYW1lbnRDb250cmFjdAUNbGFzdFRvdXJJZEtleQAABAx0b3VyTG9jYXRpb24JAKwCAgkApAMBBQZsYXN0SWQCBF9UXzAJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDmtleVNhdmVkSGVhbHRoAQULZHVja0Fzc2V0SWQFCWN1ckhlYWx0aAkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoBQVtYXhIUAkAzAgCCQELU3RyaW5nRW50cnkCCQEQa2V5U2F2ZWRMb2NhdGlvbgEFC2R1Y2tBc3NldElkBQtjdXJMb2NhdGlvbgkAzAgCCQELU3RyaW5nRW50cnkCBQljdXJMb2NLZXkFDHRvdXJMb2NhdGlvbgUDbmlsBQx0b3VyTG9jYXRpb24BaQEMYnJlYWtBdHRlbXB0AAQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQZjYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECWN1ckxvY0tleQkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkBAtjdXJMb2NhdGlvbgkBC3ZhbHVlT3JFbHNlAgkAoggBBQljdXJMb2NLZXkFD0RFRkFVTFRMT0NBVElPTgMJAQIhPQIJAJEDAgkAtQkCBQtjdXJMb2NhdGlvbgIBXwUKbG9jSWR4VHlwZQIBVAkAAgECIllvdXIgZHVjayBpcyBub3QgaW4gdGhlIHRvdXJuYW1lbnQEC3NhdmVkSGVhbHRoCQERQGV4dHJOYXRpdmUoMTA1NSkBCQEOa2V5U2F2ZWRIZWFsdGgBBQtkdWNrQXNzZXRJZAQNc2F2ZWRMb2NhdGlvbgkBEUBleHRyTmF0aXZlKDEwNTgpAQkBEGtleVNhdmVkTG9jYXRpb24BBQtkdWNrQXNzZXRJZAkAlAoCCQDNCAIJAM0IAgUNcHJvbG9nQWN0aW9ucwkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQFC3NhdmVkSGVhbHRoCQELU3RyaW5nRW50cnkCBQljdXJMb2NLZXkFDXNhdmVkTG9jYXRpb24FC2N1ckxvY2F0aW9uAWkBFGJyZWFrQXR0ZW1wdENhbGxiYWNrAAMJAQIhPQIIBQFpBmNhbGxlcgUSdG91cm5hbWVudENvbnRyYWN0CQACAQINQWNjZXNzIGRlbmllZAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpDG9yaWdpbkNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkCQERQGV4dHJOYXRpdmUoMTA1NSkBCQEOa2V5U2F2ZWRIZWFsdGgBBQtkdWNrQXNzZXRJZAkAzAgCCQELU3RyaW5nRW50cnkCCQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQJARFAZXh0ck5hdGl2ZSgxMDU4KQEJARBrZXlTYXZlZExvY2F0aW9uAQULZHVja0Fzc2V0SWQFA25pbAIUYnJlYWtBdHRlbXB0Q2FsbGJhY2sBaQEWZXhpdFRvdXJuYW1lbnRJbnRlcm5hbAELZHVja0Fzc2V0SWQDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAg1BY2Nlc3MgZGVuaWVkBAtzYXZlZEhlYWx0aAkBEUBleHRyTmF0aXZlKDEwNTUpAQkBDmtleVNhdmVkSGVhbHRoAQULZHVja0Fzc2V0SWQEDXNhdmVkTG9jYXRpb24JARFAZXh0ck5hdGl2ZSgxMDU4KQEJARBrZXlTYXZlZExvY2F0aW9uAQULZHVja0Fzc2V0SWQJAJQKAgkAzAgCCQEMSW50ZWdlckVudHJ5AgkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAULc2F2ZWRIZWFsdGgJAMwIAgkBC1N0cmluZ0VudHJ5AgkBD2tleUR1Y2tMb2NhdGlvbgEFC2R1Y2tBc3NldElkBQ1zYXZlZExvY2F0aW9uBQNuaWwHAWkBD3Byb2Nlc3NEZWxpdmVyeQELZHVja0Fzc2V0SWQDCQECIT0CCAUBaQZjYWxsZXIFBHRoaXMJAAIBAg1BY2Nlc3MgZGVuaWVkBARhZGRyCQClCAEIBQFpDG9yaWdpbkNhbGxlcgQJZnVuZFRvdGFsCQELdmFsdWVPckVsc2UCCQCaCAIFD2Vjb25vbXlDb250cmFjdAUPZGVsaXZlcnlGdW5kS2V5AAADCQBmAgUVTUlOX1VTRFRfRkVFX0RFTElWRVJZBQlmdW5kVG90YWwJAAIBCQCsAgICIERlbGl2ZXJ5IGlzIG5vdCBhdmFpbGFibGUsIGZ1bmQ9CQEKZml4ZWRQb2ludAIFCWZ1bmRUb3RhbAAGBANub3cIBQlsYXN0QmxvY2sJdGltZXN0YW1wBAhjb3VudEtleQkBFGtleVVzZXJEZWxpdmVyeUNvdW50AQUEYWRkcgQFY291bnQJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUIY291bnRLZXkAAAQHbGFzdERheQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5VXNlckxhc3REZWxpdmVyeURheQEFBGFkZHIAAAQFdG9kYXkJAGkCBQNub3cFCURBWU1JTExJUwQFYWNyZXMJAQt2YWx1ZU9yRWxzZQIJAJoIAgUNYWNyZXNDb250cmFjdAkBGmtleUFjcmVzU3Rha2VkQW1vdW50QnlVc2VyAQUEYWRkcgAABBFhbGxvd2VkRGVsaXZlcmllcwkAZAIFF0FMTE9XRURfRlJFRV9ERUxJVkVSSUVTCQBpAgUFYWNyZXMFGkFDUkVTX0ZPUl9ERUxJVkVSWV9BVFRFTVBUAwMJAGcCBQVjb3VudAURYWxsb3dlZERlbGl2ZXJpZXMJAAACBQdsYXN0RGF5BQV0b2RheQcJAAIBCQCsAgIJAKwCAgIRWW91IGFscmVhZHkgdXNlZCAJAKQDAQURYWxsb3dlZERlbGl2ZXJpZXMCHCBkZWxpdmVyeSBhdHRlbXB0cyBmb3IgdG9kYXkEBnJld2FyZAkA/AcEBQ9lY29ub215Q29udHJhY3QCEnNlbmREZWxpdmVyeVJld2FyZAkAzAgCBQRhZGRyBQNuaWwFA25pbAkAlAoCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQhjb3VudEtleQkAZAIFBWNvdW50AAEJAMwIAgkBDEludGVnZXJFbnRyeQIJARZrZXlVc2VyTGFzdERlbGl2ZXJ5RGF5AQUEYWRkcgUFdG9kYXkFA25pbAUGcmV3YXJkAWkBDnByZXBhcmVSb2JiZXJ5AgdtZXNzYWdlA3NpZwQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQEBIQEJAMQTAwUHbWVzc2FnZQUDc2lnBQNwdWIJAAIBAhhzaWduYXR1cmUgZG9lcyBub3QgbWF0Y2gDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAiJleGFjdGx5IDEgcGF5bWVudCBtdXN0IGJlIGF0dGFjaGVkBANwbXQJAJEDAggFAWkIcGF5bWVudHMAAAQGd2xnQW10CAUDcG10BmFtb3VudAMDCQEBIQEJAQlpc0RlZmluZWQBCAUDcG10B2Fzc2V0SWQGCQECIT0CCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQFCndsZ0Fzc2V0SWQJAAIBAhVXTEdPTEQgcGF5bWVudHMgb25seSEEBXBhcnRzCQC1CQIJALAJAQUHbWVzc2FnZQIBfAMJAGYCAAIJAJADAQUFcGFydHMJAAIBAhRXcm9uZyBtZXNzYWdlIGZvcm1hdAQJdHhGcm9tTXNnAwkAZwIJAJADAQUFcGFydHMAAgkAkQMCBQVwYXJ0cwACAgAECHVzZXJBZGRyCQClCAEIBQFpBmNhbGxlcgQGbGFzdFR4CQELdmFsdWVPckVsc2UCCQCiCAEJARFrZXlMYXN0VHhJZEJ5VXNlcgEFCHVzZXJBZGRyAgADCQECIT0CBQZsYXN0VHgFCXR4RnJvbU1zZwkAAgEJAKwCAgkArAICCQCsAgICHlR4IGlkcyBkb24ndCBtYXRjaCEgSW4gc3RhdGU6IAUGbGFzdFR4AgosIGluIG1zZzogBQl0eEZyb21Nc2cEC2R1Y2tBc3NldElkCQCRAwIFBXBhcnRzAAADCQEPY2hlY2tUb3VybmFtZW50AQULZHVja0Fzc2V0SWQJAAIBAh5wcmVwYXJlUm9iYmVyeV9jaGVja1RvdXJuYW1lbnQEB3JvYkNvc3QICQEOZ2V0Um9iYmVyeURhdGECBQR0aGlzBQtkdWNrQXNzZXRJZAJfMQMJAGYCBQdyb2JDb3N0BQZ3bGdBbXQJAAIBCQCsAgIJAKwCAgkArAICAghQYXltZW50IAkApAMBBQZ3bGdBbXQCDCA8IHJlcXVpcmVkIAkApAMBBQdyb2JDb3N0BApjYW5kaWRhdGVzCQC1CQIJAJEDAgUFcGFydHMAAQIBXwQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQJZHVja1N0YXRlCQELdmFsdWVPckVsc2UCCQCfCAEJARNrZXlEdWNrUm9iYmVyeVN0YXRlAQULZHVja0Fzc2V0SWQAAAQKbG9ja2VkTGFuZAkBC3ZhbHVlT3JFbHNlAgkAoggBCQETa2V5TG9ja2VkTGFuZEJ5RHVjawEFC2R1Y2tBc3NldElkAgAEB2xhbmRFVEEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleUxhbmRDb29sZG93bkVUQQEFCmxvY2tlZExhbmQAAAMDCQECIT0CBQlkdWNrU3RhdGUFC2R1Y2tJZHhGcmVlCQBmAgUHbGFuZEVUQQUDbm93BwkAAgEJAKwCAgInWW91IGFscmVhZHkgc3RhcnRlZCByb2JiaW5nLCB3YWl0IHRpbGwgCQCkAwEFB2xhbmRFVEEKAQdjaGVja2VyAgNhY2MLbGFuZEFzc2V0SWQEBXN0YXRlCQELdmFsdWVPckVsc2UCCQCfCAEJARNrZXlMYW5kUm9iYmVyeVN0YXRlAQULbGFuZEFzc2V0SWQAAAQLY29vbGRvd25FVEEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBEmtleUxhbmRDb29sZG93bkVUQQEFC2xhbmRBc3NldElkAAADCQBmAgUFc3RhdGUJAJADAQUQbGFuZFJvYkNvb2xkb3ducwkAAgECDUludmFsaWQgc3RhdGUDCQBmAgUDbm93BQtjb29sZG93bkVUQQQKc3Rha2VkVGltZQkBC3ZhbHVlT3JFbHNlAgkAnwgBCQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFC2xhbmRBc3NldElkAAADCQBnAgAABQpzdGFrZWRUaW1lBQNhY2MEAWEJAQV2YWx1ZQEJAOwHAQkA2QQBBQtsYW5kQXNzZXRJZAQBZAkAtQkCCAUBYQtkZXNjcmlwdGlvbgIBXwQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQQMcHJvZHVjdGl2aXR5CQEMYXBwbHlCb251c2VzAgULbGFuZEFzc2V0SWQFBnBpZWNlcwQJZGVsdGFUaW1lCQBlAgUDbm93BQpzdGFrZWRUaW1lBAhhdmFpbFJlcwkAawMFCWRlbHRhVGltZQkAaAIFDHByb2R1Y3Rpdml0eQUGcGllY2VzBQlEQVlNSUxMSVMDCQBmAgUOTUlOX1JFU19UT19ST0IFCGF2YWlsUmVzBQNhY2MJAM0IAgUDYWNjBQtsYW5kQXNzZXRJZAUDYWNjBAhmaWx0ZXJlZAoAAiRsBQpjYW5kaWRhdGVzCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQdjaGVja2VyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhRMaXN0IHNpemUgZXhjZWVkcyAxMAkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgAHAAgACQAKAwkAAAIJAJADAQUIZmlsdGVyZWQAAAkAAgECGU5vIGNhbmRpZGF0ZXMgZm9yIHJvYmJlcnkEBnJuZElkeAkBD2dldFJhbmRvbU51bWJlcgMJAJADAQUIZmlsdGVyZWQFB21lc3NhZ2UFA3NpZwQLbGFuZEFzc2V0SWQJAJEDAgUIZmlsdGVyZWQFBnJuZElkeAkAlAoCCQDOCAIJAMwIAgkBDEludGVnZXJFbnRyeQIJARNrZXlMYW5kUm9iYmVyeVN0YXRlAQULbGFuZEFzc2V0SWQFDHJvYklkeExvY2tlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBEmtleUxhbmRDb29sZG93bkVUQQEFC2xhbmRBc3NldElkCQBkAgUDbm93CQCRAwIFEGxhbmRSb2JDb29sZG93bnMFDHJvYklkeExvY2tlZAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBE2tleUR1Y2tSb2JiZXJ5U3RhdGUBBQtkdWNrQXNzZXRJZAUQZHVja0lkeFByZXBhcmluZwkAzAgCCQELU3RyaW5nRW50cnkCCQETa2V5TG9ja2VkTGFuZEJ5RHVjawEFC2R1Y2tBc3NldElkBQtsYW5kQXNzZXRJZAUDbmlsBQ1wcm9sb2dBY3Rpb25zBQtsYW5kQXNzZXRJZAFpAQdyb2JMYW5kAgdtZXNzYWdlA3NpZwQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQEBIQEJAMQTAwUHbWVzc2FnZQUDc2lnBQNwdWIJAAIBAhhzaWduYXR1cmUgZG9lcyBub3QgbWF0Y2gECHVzZXJBZGRyCQClCAEIBQFpBmNhbGxlcgQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQh1c2VyQWRkcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQDbm93CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAlAoCCQDNCAIFDXByb2xvZ0FjdGlvbnMJAQxJbnRlZ2VyRW50cnkCCQEYa2V5TGFzdFJvYmJlcnlUaW1lQnlEdWNrAQULZHVja0Fzc2V0SWQFA25vdwAAAWkBC2J1eVJvYm9EdWNrAAMJAQEhAQUTS1NfQUxMT1dfUk9CT19EVUNLUwkAAgECFUZlYXR1cmUgaXMgdHVybmVkIG9mZgQNcHJvbG9nQWN0aW9ucwkBBnByb2xvZwEFAWkDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAEJAAIBAhxFeGFjdGx5IG9uZSBwYXltZW50IHJlcXVpcmVkBANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAMJAQIhPQIIBQNwbXQHYXNzZXRJZAULdXNkdEFzc2V0SWQJAAIBAhpBbGxvd2VkIFVTRFQgcGF5bWVudCBvbmx5IQMJAQIhPQIIBQNwbXQGYW1vdW50BQ5ST0JPX0RVQ0tfVVNEVAkAAgEJAKwCAgkArAICAhtQYXltZW50IGF0dGFjaGVkIHNob3VsZCBiZSAJAQpmaXhlZFBvaW50AgUOUk9CT19EVUNLX1VTRFQABgIFIFVTRFQEB25leHROdW0JAQt2YWx1ZU9yRWxzZQIJAJ8IAQkBD2tleU5leHRSb2JvRHVjawAAAAQFYnl0ZXoJAJoDAQUHbmV4dE51bQQEbmFtZQkArAICCQCsAgIFC1JPQk9fUFJFRklYAgEtCQCyAgIJANwEAQUFYnl0ZXoACAQFY29sb3IJALICAgkA3AQBCQDUFgEFBWJ5dGV6AAYEBWlzc3VlCQDCCAUFBG5hbWUJAKwCAgI3Um9ibyBEdWNrIE5GVCBmb3IgV2F2ZXNMYW5kcyBnYW1lLCBiYWNrZ3JvdW5kIGNvbG9yID0gIwUFY29sb3IAAQAABwQHYXNzZXRJZAkAuAgBBQVpc3N1ZQkAlAoCCQDNCAIJAM0IAgkAzQgCCQDNCAIFDXByb2xvZ0FjdGlvbnMJAQxJbnRlZ2VyRW50cnkCCQEPa2V5TmV4dFJvYm9EdWNrAAkAZAIFB25leHROdW0AAQUFaXNzdWUJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpDG9yaWdpbkNhbGxlcgABBQdhc3NldElkCQEOU2NyaXB0VHJhbnNmZXIDBQ9lY29ub215Q29udHJhY3QIBQNwbXQGYW1vdW50BQt1c2R0QXNzZXRJZAkAlAoCCQDYBAEFB2Fzc2V0SWQFBWNvbG9yAIPaCeo=", "height": 2856325, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 6tWZBaKfp3Tk73vDQbYUBTXFsSwmGArxTrLke1uqc7xf Next: 824xxgQAk3VUU8QcSWzZ1DQ9s1cDp4QyFrhxF2HaGxpr Diff:
OldNewDifferences
105105
106106
107107 func keyLockedLandByDuck (duckAssetId) = ("lockedLandByDuck_" + duckAssetId)
108-
109-
110-func keyDeliveryDelayByDuck (duckAssetId) = ("deliveryDelayByDuck_" + duckAssetId)
111108
112109
113110 func keyUserDeliveryCount (addr) = ("userDeliveryCount_" + addr)
195192
196193 let MIN_USDT_FEE_DELIVERY = 50000
197194
198-let TEN_MINUTES_MILLIS = 600000
199-
200195 let ALLOWED_FREE_DELIVERIES = 1
201196
202197 let ACRES_FOR_DELIVERY_ATTEMPT = 50000000
314309
315310
316311 let deliveryFundKey = "deliveryFund"
317-
318-let deliveryLockedKey = "deliveryLocked"
319312
320313 let lastTourIdKey = "%s__lastTourId"
321314
360353 }
361354
362355
363-func isInDelivery (location) = {
364- let loc = split(location, "_")
365- let now = lastBlock.timestamp
366- let startTime = parseIntValue(loc[locIdxContinent])
367- let distance = parseIntValue(loc[locIdxId])
368- if (if ((loc[locIdxType] == "D"))
369- then ((startTime + TEN_MINUTES_MILLIS) > now)
370- else false)
371- then (3 >= distance)
372- else false
373- }
374-
375-
376-func isUsualLocation (location) = {
377- let locType = split(location, "_")[locIdxType]
378- if ((locType != "T"))
379- then (locType != "D")
380- else false
381- }
382-
383-
384356 func onMission (tourContract,location) = {
385357 let lastId = valueOrElse(getInteger(tourContract, lastTourIdKey), 0)
386358 let loc = split(location, "_")
389361 let static = tData[idxStatic]
390362 let dynamic = tData[idxDynamic]
391363 let locType = loc[locIdxType]
392- if ((locType == "D"))
393- then true
394- else if (if (if ((loc[locIdxType] == "T"))
395- then (parseIntValue(loc[locIdxContinent]) == lastId)
396- else false)
397- then (dynamic[tDynamicStatus] == "INPROGRESS")
398- else false)
399- then (parseIntValue(static[tStaticEnd]) > now)
400- else false
364+ if (if (if ((loc[locIdxType] == "T"))
365+ then (parseIntValue(loc[locIdxContinent]) == lastId)
366+ else false)
367+ then (dynamic[tDynamicStatus] == "INPROGRESS")
368+ else false)
369+ then (parseIntValue(static[tStaticEnd]) > now)
370+ else false
401371 }
402372
403373
461431 then DAY_MILLIS
462432 else if ((base58'2T' == $match0))
463433 then 60000
464- else throw("Unknown chain")
465-}
466-
467-let DELIVERY_PUNISHMENT = match chain {
468- case _ =>
469- if ((base58'2W' == $match0))
470- then 10800000
471- else if ((base58'2T' == $match0))
472- then 900000
473434 else throw("Unknown chain")
474435 }
475436
632593 }
633594
634595
635-func getRandomNumber (maxValue,salt,entropy) = {
636- let randomHash = sha256((salt + entropy))
637- (toInt(randomHash) % maxValue)
638- }
596+func getRandomNumber (maxValue,salt,entropy) = if ((0 >= maxValue))
597+ then throw("maxValue should be > 0")
598+ else {
599+ let randomHash = sha256((salt + entropy))
600+ (toInt(randomHash) % maxValue)
601+ }
639602
640603
641604 let incubatorAddr = match chain {
19781941 }
19791942
19801943
1981-func checkDelivery (duckAssetId) = {
1982- let curLocation = split(valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_")
1983- let now = lastBlock.timestamp
1984- if ((curLocation[locIdxType] != "D"))
1985- then false
1986- else {
1987- let startTime = parseIntValue(curLocation[locIdxContinent])
1988- let distance = parseIntValue(curLocation[locIdxId])
1989- if (if (((startTime + TEN_MINUTES_MILLIS) > now))
1990- then (1 > distance)
1991- else false)
1992- then throw("Your duck is on delivery mission")
1993- else asBoolean(invoke(this, "exitDeliveryInternal", [duckAssetId], nil))
1994- }
1995- }
1996-
1997-
1998-func exitDeliveryCommon (duckAssetId,check,newHP,score) = {
1999- let curLocation = split(valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_")
2000- let now = lastBlock.timestamp
2001- let startTime = parseIntValue(curLocation[locIdxContinent])
2002- let distance = parseIntValue(curLocation[locIdxId])
2003- let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(duckAssetId)), "NFT duck is orphaned")
2004- let healthKey = keyDuckHealth(duckAssetId)
2005- let curHealth = getIntegerValue(healthKey)
2006- let outcomeActions = if (if ((distance > 0))
2007- then true
2008- else if (if (check)
2009- then (score > 0)
2010- else false)
2011- then (newHP > 0)
2012- else false)
2013- then {
2014- let reward = invoke(economyContract, "sendDeliveryReward", [owner], nil)
2015- if ((reward == reward))
2016- then {
2017- let countKey = keyUserDeliveryCount(owner)
2018-[IntegerEntry(countKey, (valueOrElse(getInteger(countKey), 0) + 1)), IntegerEntry(keyUserLastDeliveryDay(owner), (startTime / DAYMILLIS))]
2019- }
2020- else throw("Strict value is not equal to itself.")
2021- }
2022- else if (if (if (check)
2023- then (newHP > 0)
2024- else false)
2025- then ((startTime + TEN_MINUTES_MILLIS) > now)
2026- else false)
2027- then throw("Your duck is still on delivery mission")
2028- else {
2029- let lockedTotal = valueOrElse(getInteger(economyContract, deliveryLockedKey), 0)
2030- let unlock = invoke(economyContract, "updateDeliveryLocked", [(lockedTotal - MIN_USDT_FEE_DELIVERY)], nil)
2031- if ((unlock == unlock))
2032- then if (if (if (check)
2033- then (0 >= newHP)
2034- else false)
2035- then true
2036- else (0 >= curHealth))
2037- then nil
2038- else [IntegerEntry(keyDeliveryDelayByDuck(duckAssetId), (startTime + DELIVERY_PUNISHMENT))]
2039- else throw("Strict value is not equal to itself.")
2040- }
2041- let savedLocation = getStringValue(keySavedLocation(duckAssetId))
2042- $Tuple3(outcomeActions, [StringEntry(keyDuckLocation(duckAssetId), savedLocation)], savedLocation)
2043- }
2044-
2045-
20461944 func mergeInternal (newLandSize,newLevel,formula,addr,landAssetIds,needMat) = {
20471945 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
20481946 if (checkTournament(duckAssetId))
20491947 then throw("mergeInternal_checkTournament")
2050- else if (checkDelivery(duckAssetId))
2051- then throw("mergeInternal_checkDelivery")
2052- else {
2053- func checkMerge (acc,landAssetId) = {
2054- let asset = value(assetInfo(fromBase58String(landAssetId)))
2055- let timeKey = keyStakedTimeByAssetId(landAssetId)
2056- let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
2057- let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
2058- if ((owner != addr))
2059- then throw((LANDPREFIX + " is not yours"))
2060- else {
2061- let d = split(asset.description, "_")
2062- let continent = d[recContinent]
2063- if (if ((acc._3 != ""))
2064- then (acc._3 != continent)
2065- else false)
2066- then throw("Lands should be on the same continent to merge")
2067- else {
2068- let landSize = d[recLandSize]
2069- let sizesIn = acc._1
2070- let i = valueOrErrorMessage(indexOf(sizesIn, landSize), "You haven't passed all the lands needed")
2071- let sizesOut = (take(sizesIn, i) + drop(sizesIn, (i + 1)))
2072- let pieces = numPiecesBySize(landSize)
2073- let arts = (acc._2 + valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0))
2074- let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
2075- let reqLevel = match landSize {
2076- case _ =>
2077- if (("S" == $match0))
2078- then 3
2079- else if (("M" == $match0))
2080- then 4
2081- else if (("L" == $match0))
2082- then 5
2083- else if (("XL" == $match0))
2084- then 6
2085- else throw("Only S, M, L, XL can merge")
2086- }
2087- if ((infraLevel != reqLevel))
2088- then throw("All lands should be maxed to merge")
2089- else {
2090- let landNum = d[recLandNum]
2091- let terrainCounts = countTerrains(d[recTerrains])
2092- let deltaTime = (lastBlock.timestamp - savedTime)
2093- if ((0 > deltaTime))
2094- then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
2095- else {
2096- let dailyProductionByPiece = applyBonuses(landAssetId, pieces)
2097- let landIndex = (pieces / SSIZE)
2098- let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, landIndex, dailyProductionByPiece)
2099- let props = updateProportionsInternal(acc._6, terrainCounts, landIndex, -1)
2100- let cProps = updateProportionsInternal(acc._10, terrainCounts, landIndex, -1)
2101- let sumTerrains = updateProportionsInternal(acc._9, terrainCounts, landIndex, 1)
2102- let lands = acc._7
2103- let idx = indexOf(lands, landAssetId)
2104- if (!(isDefined(idx)))
2105- then throw(("Your staked lands don't contain " + landAssetId))
2106- else {
2107- let customKey = keyLandAssetIdToCustomName(landAssetId)
2108- let customName = valueOrElse(getString(customKey), "")
2109- $Tuple10(sizesOut, arts, continent, bpRes, ((((((((((((acc._5 :+ DeleteEntry(keyStakedTimeByAssetId(landAssetId))) :+ DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr))) :+ DeleteEntry(keyLandToAssetId(landNum))) :+ DeleteEntry(keyLandAssetIdToOwner(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetId(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, addr))) :+ DeleteEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId))) :+ DeleteEntry(keyLandNumToOwner(landNum))) :+ DeleteEntry(keyWarehouseByLand(landAssetId))) :+ DeleteEntry(customKey)) :+ Burn(fromBase58String(landAssetId), 1)) ++ (if ((customName != ""))
2110- then [DeleteEntry(keyLandCustomNameToAssetId(customName))]
2111- else nil)), props, removeByIndex(lands, value(idx)), (acc._8 + pieces), sumTerrains, cProps)
2112- }
2113- }
2114- }
2115- }
2116- }
2117- }
2118-
2119- let bpKey = keyBackpackByDuck(duckAssetId)
2120- let currentPack = getBackpack(bpKey)
2121- let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
2122- let landsKey = keyStakedLandsByOwner(addr)
2123- let landsStr = getString(landsKey)
2124- let landsIn = if (isDefined(landsStr))
2125- then split_51C(value(landsStr), "_")
2126- else nil
2127- let cont0 = split(value(assetInfo(fromBase58String(landAssetIds[0]))).description, "_")[recContinent]
2128- let contProps = split(valueOrElse(getString(keyResTypesByContinent(cont0)), "0_0_0_0_0_0"), "_")
2129- let r = {
2130- let $l = landAssetIds
2131- let $s = size($l)
2132- let $acc0 = $Tuple10(formula, 0, "", currentPack[bpIdxRes], nil, propList, landsIn, 0, split("0_0_0_0_0_0", "_"), contProps)
2133- func $f0_1 ($a,$i) = if (($i >= $s))
2134- then $a
2135- else checkMerge($a, $l[$i])
2136-
2137- func $f0_2 ($a,$i) = if (($i >= $s))
2138- then $a
2139- else throw("List size exceeds 5")
2140-
2141- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
2142- }
2143- let continent = r._3
2144- let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent))
2145- let terrains = genTerrainsForMerge(r._9, (numPiecesBySize(newLandSize) / SSIZE))
2146- let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
2147- let newLandNum = toString(freeNum)
2148- let issue = Issue(nftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false)
2149- let assetId = calculateAssetId(issue)
2150- let newLandAssetId = toBase58String(assetId)
2151- let newMat = makeString(subtractMaterials((needMat > 0), split(currentPack[bpIdxMat], "_"), needMat), "_")
2152- let piecesKey = keyStakedPiecesByOwner(addr)
2153- let stakedPieces = valueOrElse(getInteger(piecesKey), 0)
2154- $Tuple2((((((((((((((((r._5 :+ (if ((size(r._7) > 0))
2155- then StringEntry(landsKey, makeString_11C(r._7, "_"))
2156- else DeleteEntry(landsKey))) :+ IntegerEntry(piecesKey, if ((r._8 > stakedPieces))
2157- then 0
2158- else (stakedPieces - r._8))) :+ IntegerEntry(keyNextFreeLandNum(), (freeNum + 1))) :+ issue) :+ StringEntry(keyLandToAssetId(newLandNum), newLandAssetId)) :+ StringEntry(keyLandAssetIdToOwner(newLandAssetId), addr)) :+ StringEntry(keyLandNumToOwner(newLandNum), addr)) :+ IntegerEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, newLandAssetId), r._2)) :+ IntegerEntry(keyInfraLevelByAssetId(newLandAssetId), newLevel)) :+ IntegerEntry(keyInfraLevelByAssetIdAndOwner(newLandAssetId, addr), newLevel)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], r._4, newMat, currentPack[bpIdxProd]], ":"))) :+ StringEntry(keyResProportions(), makeString(r._6, "_"))) :+ StringEntry(keyResTypesByContinent(continent), makeString(r._10, "_"))) :+ StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", newLandAssetId], "_"))) :+ ScriptTransfer(addressFromStringValue(addr), 1, assetId)), newLandAssetId)
1948+ else {
1949+ func checkMerge (acc,landAssetId) = {
1950+ let asset = value(assetInfo(fromBase58String(landAssetId)))
1951+ let timeKey = keyStakedTimeByAssetId(landAssetId)
1952+ let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
1953+ let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
1954+ if ((owner != addr))
1955+ then throw((LANDPREFIX + " is not yours"))
1956+ else {
1957+ let d = split(asset.description, "_")
1958+ let continent = d[recContinent]
1959+ if (if ((acc._3 != ""))
1960+ then (acc._3 != continent)
1961+ else false)
1962+ then throw("Lands should be on the same continent to merge")
1963+ else {
1964+ let landSize = d[recLandSize]
1965+ let sizesIn = acc._1
1966+ let i = valueOrErrorMessage(indexOf(sizesIn, landSize), "You haven't passed all the lands needed")
1967+ let sizesOut = (take(sizesIn, i) + drop(sizesIn, (i + 1)))
1968+ let pieces = numPiecesBySize(landSize)
1969+ let arts = (acc._2 + valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0))
1970+ let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
1971+ let reqLevel = match landSize {
1972+ case _ =>
1973+ if (("S" == $match0))
1974+ then 3
1975+ else if (("M" == $match0))
1976+ then 4
1977+ else if (("L" == $match0))
1978+ then 5
1979+ else if (("XL" == $match0))
1980+ then 6
1981+ else throw("Only S, M, L, XL can merge")
1982+ }
1983+ if ((infraLevel != reqLevel))
1984+ then throw("All lands should be maxed to merge")
1985+ else {
1986+ let landNum = d[recLandNum]
1987+ let terrainCounts = countTerrains(d[recTerrains])
1988+ let deltaTime = (lastBlock.timestamp - savedTime)
1989+ if ((0 > deltaTime))
1990+ then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
1991+ else {
1992+ let dailyProductionByPiece = applyBonuses(landAssetId, pieces)
1993+ let landIndex = (pieces / SSIZE)
1994+ let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, landIndex, dailyProductionByPiece)
1995+ let props = updateProportionsInternal(acc._6, terrainCounts, landIndex, -1)
1996+ let cProps = updateProportionsInternal(acc._10, terrainCounts, landIndex, -1)
1997+ let sumTerrains = updateProportionsInternal(acc._9, terrainCounts, landIndex, 1)
1998+ let lands = acc._7
1999+ let idx = indexOf(lands, landAssetId)
2000+ if (!(isDefined(idx)))
2001+ then throw(("Your staked lands don't contain " + landAssetId))
2002+ else {
2003+ let customKey = keyLandAssetIdToCustomName(landAssetId)
2004+ let customName = valueOrElse(getString(customKey), "")
2005+ $Tuple10(sizesOut, arts, continent, bpRes, ((((((((((((acc._5 :+ DeleteEntry(keyStakedTimeByAssetId(landAssetId))) :+ DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr))) :+ DeleteEntry(keyLandToAssetId(landNum))) :+ DeleteEntry(keyLandAssetIdToOwner(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetId(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, addr))) :+ DeleteEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId))) :+ DeleteEntry(keyLandNumToOwner(landNum))) :+ DeleteEntry(keyWarehouseByLand(landAssetId))) :+ DeleteEntry(customKey)) :+ Burn(fromBase58String(landAssetId), 1)) ++ (if ((customName != ""))
2006+ then [DeleteEntry(keyLandCustomNameToAssetId(customName))]
2007+ else nil)), props, removeByIndex(lands, value(idx)), (acc._8 + pieces), sumTerrains, cProps)
2008+ }
2009+ }
2010+ }
2011+ }
2012+ }
21592013 }
2014+
2015+ let bpKey = keyBackpackByDuck(duckAssetId)
2016+ let currentPack = getBackpack(bpKey)
2017+ let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
2018+ let landsKey = keyStakedLandsByOwner(addr)
2019+ let landsStr = getString(landsKey)
2020+ let landsIn = if (isDefined(landsStr))
2021+ then split_51C(value(landsStr), "_")
2022+ else nil
2023+ let cont0 = split(value(assetInfo(fromBase58String(landAssetIds[0]))).description, "_")[recContinent]
2024+ let contProps = split(valueOrElse(getString(keyResTypesByContinent(cont0)), "0_0_0_0_0_0"), "_")
2025+ let r = {
2026+ let $l = landAssetIds
2027+ let $s = size($l)
2028+ let $acc0 = $Tuple10(formula, 0, "", currentPack[bpIdxRes], nil, propList, landsIn, 0, split("0_0_0_0_0_0", "_"), contProps)
2029+ func $f0_1 ($a,$i) = if (($i >= $s))
2030+ then $a
2031+ else checkMerge($a, $l[$i])
2032+
2033+ func $f0_2 ($a,$i) = if (($i >= $s))
2034+ then $a
2035+ else throw("List size exceeds 5")
2036+
2037+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
2038+ }
2039+ let continent = r._3
2040+ let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent))
2041+ let terrains = genTerrainsForMerge(r._9, (numPiecesBySize(newLandSize) / SSIZE))
2042+ let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
2043+ let newLandNum = toString(freeNum)
2044+ let issue = Issue(nftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false)
2045+ let assetId = calculateAssetId(issue)
2046+ let newLandAssetId = toBase58String(assetId)
2047+ let newMat = makeString(subtractMaterials((needMat > 0), split(currentPack[bpIdxMat], "_"), needMat), "_")
2048+ let piecesKey = keyStakedPiecesByOwner(addr)
2049+ let stakedPieces = valueOrElse(getInteger(piecesKey), 0)
2050+ $Tuple2((((((((((((((((r._5 :+ (if ((size(r._7) > 0))
2051+ then StringEntry(landsKey, makeString_11C(r._7, "_"))
2052+ else DeleteEntry(landsKey))) :+ IntegerEntry(piecesKey, if ((r._8 > stakedPieces))
2053+ then 0
2054+ else (stakedPieces - r._8))) :+ IntegerEntry(keyNextFreeLandNum(), (freeNum + 1))) :+ issue) :+ StringEntry(keyLandToAssetId(newLandNum), newLandAssetId)) :+ StringEntry(keyLandAssetIdToOwner(newLandAssetId), addr)) :+ StringEntry(keyLandNumToOwner(newLandNum), addr)) :+ IntegerEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, newLandAssetId), r._2)) :+ IntegerEntry(keyInfraLevelByAssetId(newLandAssetId), newLevel)) :+ IntegerEntry(keyInfraLevelByAssetIdAndOwner(newLandAssetId, addr), newLevel)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], r._4, newMat, currentPack[bpIdxProd]], ":"))) :+ StringEntry(keyResProportions(), makeString(r._6, "_"))) :+ StringEntry(keyResTypesByContinent(continent), makeString(r._10, "_"))) :+ StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", newLandAssetId], "_"))) :+ ScriptTransfer(addressFromStringValue(addr), 1, assetId)), newLandAssetId)
2055+ }
21602056 }
21612057
21622058
21862082 }
21872083
21882084
2189-func checkOutdatedDelivery (userAddr) = {
2190- let duck = getString(keyStakedDuckByOwner(userAddr))
2191- if (isDefined(duck))
2192- then {
2193- let duckAssetId = value(duck)
2194- let locKey = keyDuckLocation(duckAssetId)
2195- let loc = split(valueOrElse(getString(locKey), DEFAULTLOCATION), "_")
2196- let startTime = parseIntValue(loc[locIdxContinent])
2197- if (if ((loc[locIdxType] != "D"))
2198- then true
2199- else ((startTime + TEN_MINUTES_MILLIS) > lastBlock.timestamp))
2200- then nil
2201- else {
2202- let healthKey = keyDuckHealth(duckAssetId)
2203- if ((parseIntValue(loc[locIdxId]) > 0))
2204- then {
2205- let reward = invoke(economyContract, "sendDeliveryReward", [userAddr], nil)
2206- if ((reward == reward))
2207- then nil
2208- else throw("Strict value is not equal to itself.")
2209- }
2210- else ({
2211- let lockedTotal = valueOrElse(getInteger(economyContract, deliveryLockedKey), 0)
2212- let unlock = invoke(economyContract, "updateDeliveryLocked", [(lockedTotal - MIN_USDT_FEE_DELIVERY)], nil)
2213- if ((unlock == unlock))
2214- then if ((0 >= getIntegerValue(healthKey)))
2215- then nil
2216- else {
2217- let punishment = invoke(this, "saveInteger", [keyDeliveryDelayByDuck(duckAssetId), (startTime + DELIVERY_PUNISHMENT)], nil)
2218- if ((punishment == punishment))
2219- then nil
2220- else throw("Strict value is not equal to itself.")
2221- }
2222- else throw("Strict value is not equal to itself.")
2223- } :+ StringEntry(locKey, getStringValue(keySavedLocation(duckAssetId))))
2224- }
2225- }
2226- else nil
2227- }
2228-
2229-
22302085 func prolog (i) = if (if ((i.originCaller != restContract))
2231- then valueOrElse(getBoolean(keyBlocked()), false)
2232- else false)
2233- then throw("Contracts are under maintenance")
2234- else {
2235- let userAddr = toString(i.originCaller)
2236- (checkOutdatedDelivery(userAddr) :+ StringEntry(keyLastTxIdByUser(userAddr), toBase58String(i.transactionId)))
2237- }
2238-
2239-
2240-func prologFlight (i) = if (if ((i.originCaller != restContract))
22412086 then valueOrElse(getBoolean(keyBlocked()), false)
22422087 else false)
22432088 then throw("Contracts are under maintenance")
24562301 then throw("Staked NFT is not yours")
24572302 else if (checkTournament(assetIdStr))
24582303 then throw("unstakeDuck_checkTournament")
2459- else if (checkDelivery(assetIdStr))
2460- then throw("unstakeDuck_checkDelivery")
2461- else {
2462- let keyHealth = keyDuckHealth(assetIdStr)
2463- let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(assetIdStr)), 0))
2464- let health = valueOrElse(getInteger(keyHealth), maxHP)
2465- if ((maxHP > health))
2466- then throw((("Please heal your duck to " + toString(maxHP)) + "hp before unstaking"))
2467- else ([ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))] ++ prologActions)
2468- }
2304+ else {
2305+ let keyHealth = keyDuckHealth(assetIdStr)
2306+ let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(assetIdStr)), 0))
2307+ let health = valueOrElse(getInteger(keyHealth), maxHP)
2308+ if ((maxHP > health))
2309+ then throw((("Please heal your duck to " + toString(maxHP)) + "hp before unstaking"))
2310+ else ([ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))] ++ prologActions)
2311+ }
24692312 }
24702313 }
24712314 }
25032346
25042347 @Callable(i)
25052348 func flight (message,sig) = {
2506- let prologActions = prologFlight(i)
2349+ let prologActions = prolog(i)
25072350 if ((size(i.payments) != 0))
25082351 then throw("No payments required")
25092352 else {
25222365 let isDeliv = (newLoc[locIdxType] == "D")
25232366 let eqKey = keyDuckEquipment(duckAssetId)
25242367 let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,")
2525- let $t07023070327 = subtractEquipment(currentEq, f._5)
2526- let newEq = $t07023070327._1
2527- let shouldZeroBuffs = $t07023070327._2
2528- let $t07033073442 = if (!(onMission(tournamentContract, curLocation)))
2529- then if (!(isUsualLocation(newLocation)))
2368+ let $t06603566132 = subtractEquipment(currentEq, f._5)
2369+ let newEq = $t06603566132._1
2370+ let shouldZeroBuffs = $t06603566132._2
2371+ let $t06613567967 = if (!(onMission(tournamentContract, curLocation)))
2372+ then if (isTour)
25302373 then cheatAttempt(curLocation, newLocation, 5)
2531- else if ((newHP > 0))
2532- then $Tuple2(newLocation, newHP)
2533- else $Tuple2(curLocation, 0)
2374+ else if (!(isDeliv))
2375+ then if ((newHP > 0))
2376+ then $Tuple2(newLocation, newHP)
2377+ else $Tuple2(curLocation, 0)
2378+ else if ((newHP > 0))
2379+ then {
2380+ let s = invoke(this, "processDelivery", [duckAssetId], nil)
2381+ if ((s == s))
2382+ then $Tuple2(curLocation, newHP)
2383+ else throw("Strict value is not equal to itself.")
2384+ }
2385+ else $Tuple2(curLocation, 0)
25342386 else if (isInTournament(tournamentContract, curLocation))
25352387 then if (!(isInTournament(tournamentContract, newLocation)))
25362388 then throw("Your duck is taking part in the tournament")
25522404 }
25532405 else $Tuple2(curLocation, 0)
25542406 }
2555- else if (!(isInDelivery(curLocation)))
2556- then {
2557- let savedLoc = asString(invoke(this, "autoExitDelivery", [duckAssetId, newHP, if (isDeliv)
2558- then "10"
2559- else "11", 0], nil))
2560- if ((savedLoc == savedLoc))
2561- then if (isDeliv)
2562- then $Tuple2(savedLoc, newHP)
2563- else if ((newHP > 0))
2564- then $Tuple2(newLocation, newHP)
2565- else $Tuple2(savedLoc, 0)
2566- else throw("Strict value is not equal to itself.")
2567- }
2568- else if (!(isDeliv))
2569- then throw("Your duck is taking part in delivery")
2570- else if (!(isInDelivery(newLocation)))
2571- then cheatAttempt(curLocation, newLocation, 13)
2572- else {
2573- let score = parseIntValue(newLoc[locIdxId])
2574- let curLoc = split(curLocation, "_")
2575- if ((score != (parseIntValue(curLoc[locIdxId]) + 1)))
2576- then cheatAttempt(curLocation, newLocation, 14)
2577- else if (if ((newHP > 0))
2578- then (1 > score)
2579- else false)
2580- then $Tuple2(newLocation, newHP)
2581- else {
2582- let savedLoc = asString(invoke(this, "autoExitDelivery", [duckAssetId, newHP, "15-17", score], nil))
2583- if ((savedLoc == savedLoc))
2584- then $Tuple2(savedLoc, newHP)
2585- else throw("Strict value is not equal to itself.")
2586- }
2587- }
2588- let locToSave = $t07033073442._1
2589- let hpToSave = $t07033073442._2
2407+ else throw(("Unknown curLocation:" + curLocation))
2408+ let locToSave = $t06613567967._1
2409+ let hpToSave = $t06613567967._2
25902410 $Tuple2(((([StringEntry(locKey, locToSave), StringEntry(eqKey, newEq), IntegerEntry(keyDuckHealth(duckAssetId), hpToSave)] ++ prologActions) ++ (if (shouldZeroBuffs)
25912411 then [StringEntry(keyDuckBuffs(duckAssetId), "0_0_0_0_0")]
25922412 else nil)) ++ updateDuckStatsInternal(duckAssetId, if ((newHP > 0))
26112431 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
26122432 if (checkTournament(duckAssetId))
26132433 then throw("heal_checkTournament")
2614- else if (checkDelivery(duckAssetId))
2615- then throw("heal_checkDelivery")
2616- else {
2617- let qts = [quantityL1, quantityL2, quantityL3]
2618- let keyHealth = keyDuckHealth(duckAssetId)
2619- let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
2620- let oldHealth = valueOrElse(getInteger(keyHealth), maxHP)
2621- if ((oldHealth >= maxHP))
2622- then throw((("HP should be < " + toString(maxHP)) + " to heal"))
2623- else {
2624- let bpKey = keyBackpackByDuck(duckAssetId)
2625- let currentPack = getBackpack(bpKey)
2626- let prodList = if ((currentPack[bpIdxProd] == ""))
2627- then nil
2628- else split_4C(currentPack[bpIdxProd], "_")
2629- func iterateProd (acc,recipe) = {
2630- let n = acc._2
2631- let x = if ((size(prodList) > n))
2632- then parseIntValue(prodList[n])
2633- else 0
2634- if ((3 > n))
2635- then {
2636- let q = qts[n]
2637- if ((q > x))
2638- then throw(((("You have only " + toString(x)) + " of ") + prodTypes[n]))
2639- else $Tuple3((acc._1 :+ toString((x - q))), (n + 1), (acc._3 + (parseIntValue(split(recipe, "_")[rIdxEffect]) * q)))
2640- }
2641- else $Tuple3((acc._1 :+ toString(x)), (n + 1), acc._3)
2642- }
2643-
2644- let result = {
2645- let $l = productionMatrix
2646- let $s = size($l)
2647- let $acc0 = $Tuple3(nil, 0, 0)
2648- func $f0_1 ($a,$i) = if (($i >= $s))
2649- then $a
2650- else iterateProd($a, $l[$i])
2651-
2652- func $f0_2 ($a,$i) = if (($i >= $s))
2653- then $a
2654- else throw("List size exceeds 50")
2655-
2656- $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)
2657- }
2658- let newHealth = min([maxHP, (oldHealth + result._3)])
2659- $Tuple2((([IntegerEntry(keyHealth, newHealth), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], makeString(result._1, "_")], ":"))] ++ prologActions) ++ updateDuckStatsInternal(duckAssetId, (xpHeal * ((quantityL1 + quantityL2) + quantityL3)))._1), newHealth)
2434+ else {
2435+ let qts = [quantityL1, quantityL2, quantityL3]
2436+ let keyHealth = keyDuckHealth(duckAssetId)
2437+ let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
2438+ let oldHealth = valueOrElse(getInteger(keyHealth), maxHP)
2439+ if ((oldHealth >= maxHP))
2440+ then throw((("HP should be < " + toString(maxHP)) + " to heal"))
2441+ else {
2442+ let bpKey = keyBackpackByDuck(duckAssetId)
2443+ let currentPack = getBackpack(bpKey)
2444+ let prodList = if ((currentPack[bpIdxProd] == ""))
2445+ then nil
2446+ else split_4C(currentPack[bpIdxProd], "_")
2447+ func iterateProd (acc,recipe) = {
2448+ let n = acc._2
2449+ let x = if ((size(prodList) > n))
2450+ then parseIntValue(prodList[n])
2451+ else 0
2452+ if ((3 > n))
2453+ then {
2454+ let q = qts[n]
2455+ if ((q > x))
2456+ then throw(((("You have only " + toString(x)) + " of ") + prodTypes[n]))
2457+ else $Tuple3((acc._1 :+ toString((x - q))), (n + 1), (acc._3 + (parseIntValue(split(recipe, "_")[rIdxEffect]) * q)))
2458+ }
2459+ else $Tuple3((acc._1 :+ toString(x)), (n + 1), acc._3)
26602460 }
2661- }
2461+
2462+ let result = {
2463+ let $l = productionMatrix
2464+ let $s = size($l)
2465+ let $acc0 = $Tuple3(nil, 0, 0)
2466+ func $f0_1 ($a,$i) = if (($i >= $s))
2467+ then $a
2468+ else iterateProd($a, $l[$i])
2469+
2470+ func $f0_2 ($a,$i) = if (($i >= $s))
2471+ then $a
2472+ else throw("List size exceeds 50")
2473+
2474+ $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)
2475+ }
2476+ let newHealth = min([maxHP, (oldHealth + result._3)])
2477+ $Tuple2((([IntegerEntry(keyHealth, newHealth), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], makeString(result._1, "_")], ":"))] ++ prologActions) ++ updateDuckStatsInternal(duckAssetId, (xpHeal * ((quantityL1 + quantityL2) + quantityL3)))._1), newHealth)
2478+ }
2479+ }
26622480 }
26632481 }
26642482
26772495 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
26782496 if (checkTournament(duckAssetId))
26792497 then throw("healES_checkTournament")
2680- else if (checkDelivery(duckAssetId))
2681- then throw("healES_checkDelivery")
2682- else {
2683- let keyHealth = keyDuckHealth(duckAssetId)
2684- let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
2685- let oldHealth = valueOrElse(getInteger(keyHealth), maxHP)
2686- if ((oldHealth > 0))
2687- then throw("HP should be 0 to call Emergency Service")
2688- else {
2689- let bpKey = keyBackpackByDuck(duckAssetId)
2690- let currentPack = getBackpack(bpKey)
2691- let prodList = if ((currentPack[bpIdxProd] == ""))
2692- then nil
2693- else split_4C(currentPack[bpIdxProd], "_")
2694- let medKitAmount1 = if ((size(prodList) > 0))
2695- then parseIntValue(prodList[0])
2696- else 0
2697- let medKitAmount2 = if ((size(prodList) > 1))
2698- then parseIntValue(prodList[1])
2699- else 0
2700- let medKitAmount3 = if ((size(prodList) > 2))
2701- then parseIntValue(prodList[2])
2702- else 0
2703- if (if (if ((medKitAmount1 > 0))
2704- then true
2705- else (medKitAmount2 > 0))
2706- then true
2707- else (medKitAmount3 > 0))
2708- then throw("You have to use own Medical Kit")
2709- else {
2710- let existStr = getString(economyContract, keyEsWarehouse())
2711- let existAmounts = if (isDefined(existStr))
2712- then split_4C(value(existStr), "_")
2713- else nil
2714- let existAmount = if ((size(existAmounts) > 0))
2715- then parseIntValue(existAmounts[0])
2716- else 0
2717- if ((0 >= existAmount))
2718- then throw("There are no Medical Kits L1 at Emergency Service storage")
2719- else {
2720- let newHealth = (oldHealth + parseIntValue(split(productionMatrix[0], "_")[rIdxEffect]))
2721- let newES = makeString([toString((existAmount - 1)), removeByIndex(existAmounts, 0)], "_")
2722- let recipe = split(productionMatrix[0], "_")
2723- let totalMat = getRecipeMaterials(recipe)
2724- let sellPrice = fraction((totalMat * ESSELLCOEF), RESOURCEPRICEMIN, (MULT8 * PRODUCTPKGSIZE))
2725- if ((pmt.amount != sellPrice))
2726- then throw(("Payment attached should be " + toString(sellPrice)))
2727- else {
2728- let result = asString(invoke(economyContract, "updateEsStorage", [newES], [AttachedPayment(usdtAssetId, sellPrice)]))
2729- $Tuple2(((prologActions :+ IntegerEntry(keyHealth, newHealth)) ++ updateDuckStatsInternal(duckAssetId, xpCallES)._1), result)
2730- }
2731- }
2732- }
2733- }
2734- }
2498+ else {
2499+ let keyHealth = keyDuckHealth(duckAssetId)
2500+ let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
2501+ let oldHealth = valueOrElse(getInteger(keyHealth), maxHP)
2502+ if ((oldHealth > 0))
2503+ then throw("HP should be 0 to call Emergency Service")
2504+ else {
2505+ let bpKey = keyBackpackByDuck(duckAssetId)
2506+ let currentPack = getBackpack(bpKey)
2507+ let prodList = if ((currentPack[bpIdxProd] == ""))
2508+ then nil
2509+ else split_4C(currentPack[bpIdxProd], "_")
2510+ let medKitAmount1 = if ((size(prodList) > 0))
2511+ then parseIntValue(prodList[0])
2512+ else 0
2513+ let medKitAmount2 = if ((size(prodList) > 1))
2514+ then parseIntValue(prodList[1])
2515+ else 0
2516+ let medKitAmount3 = if ((size(prodList) > 2))
2517+ then parseIntValue(prodList[2])
2518+ else 0
2519+ if (if (if ((medKitAmount1 > 0))
2520+ then true
2521+ else (medKitAmount2 > 0))
2522+ then true
2523+ else (medKitAmount3 > 0))
2524+ then throw("You have to use own Medical Kit")
2525+ else {
2526+ let existStr = getString(economyContract, keyEsWarehouse())
2527+ let existAmounts = if (isDefined(existStr))
2528+ then split_4C(value(existStr), "_")
2529+ else nil
2530+ let existAmount = if ((size(existAmounts) > 0))
2531+ then parseIntValue(existAmounts[0])
2532+ else 0
2533+ if ((0 >= existAmount))
2534+ then throw("There are no Medical Kits L1 at Emergency Service storage")
2535+ else {
2536+ let newHealth = (oldHealth + parseIntValue(split(productionMatrix[0], "_")[rIdxEffect]))
2537+ let newES = makeString([toString((existAmount - 1)), removeByIndex(existAmounts, 0)], "_")
2538+ let recipe = split(productionMatrix[0], "_")
2539+ let totalMat = getRecipeMaterials(recipe)
2540+ let sellPrice = fraction((totalMat * ESSELLCOEF), RESOURCEPRICEMIN, (MULT8 * PRODUCTPKGSIZE))
2541+ if ((pmt.amount != sellPrice))
2542+ then throw(("Payment attached should be " + toString(sellPrice)))
2543+ else {
2544+ let result = asString(invoke(economyContract, "updateEsStorage", [newES], [AttachedPayment(usdtAssetId, sellPrice)]))
2545+ $Tuple2(((prologActions :+ IntegerEntry(keyHealth, newHealth)) ++ updateDuckStatsInternal(duckAssetId, xpCallES)._1), result)
2546+ }
2547+ }
2548+ }
2549+ }
2550+ }
27352551 }
27362552 }
27372553 }
27512567 let finishBlock = (height + randomDelay)
27522568 let addr = toString(i.caller)
27532569 $Tuple2(([IntegerEntry(keyCommit(addr), finishBlock)] ++ prologActions), finishBlock)
2570+ }
2571+
2572+
2573+
2574+@Callable(i)
2575+func revealRandom (maxValue) = {
2576+ let prologActions = prolog(i)
2577+ let addr = toString(i.caller)
2578+ let finishKey = keyCommit(addr)
2579+ let finishBlock = valueOrErrorMessage(getInteger(finishKey), "You have to commitForRandom() first!")
2580+ if ((finishBlock > height))
2581+ then throw(("Random number is not ready yet, wait until height = " + toString(finishBlock)))
2582+ else {
2583+ let entropy = value(value(blockInfoByHeight(finishBlock)).vrf)
2584+ let salt = toBytes(valueOrElse(getString(keyLastTxIdByUser(addr)), ""))
2585+ let rand = getRandomNumber(maxValue, salt, entropy)
2586+ $Tuple2(([DeleteEntry(finishKey)] ++ prologActions), rand)
2587+ }
27542588 }
27552589
27562590
27922626 let newMat = makeString(subtractMaterials(true, mList, EXPMATERIALS), "_")
27932627 let eqKey = keyDuckEquipment(duckAssetId)
27942628 let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,")
2795- let $t08088280979 = subtractEquipment(currentEq, f._5)
2796- let newEq = $t08088280979._1
2797- let shouldZeroBuffs = $t08088280979._2
2629+ let $t07588775984 = subtractEquipment(currentEq, f._5)
2630+ let newEq = $t07588775984._1
2631+ let shouldZeroBuffs = $t07588775984._2
27982632 let e = expeditionInternal(i.caller, i.transactionId)
27992633 let id = e._2._1
28002634 let result = if ((0 >= f._1))
28042638 else ((((nil :+ StringEntry(keyDuckLocation(duckAssetId), makeString([e._2._2, "L", id], "_"))) :+ IntegerEntry(keyHealth, f._1)) :+ StringEntry(eqKey, newEq)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))))), id, f._3)
28052639 if (checkTournament(duckAssetId))
28062640 then throw("expedition_checkTournament")
2807- else if (checkDelivery(duckAssetId))
2808- then throw("expedition_checkDelivery")
2809- else {
2810- let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], nil))
2811- $Tuple2(((result._1 ++ updateDuckStatsInternal(duckAssetId, xpNewSLand)._1) ++ prologActions), $Tuple3(result._2, result._3, acresResult))
2812- }
2641+ else {
2642+ let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], nil))
2643+ $Tuple2(((result._1 ++ updateDuckStatsInternal(duckAssetId, xpNewSLand)._1) ++ prologActions), $Tuple3(result._2, result._3, acresResult))
2644+ }
28132645 }
28142646 }
28152647
31192951 let addr = toString(i.originCaller)
31202952 let virtWlgData = asAnyList(invoke(wlgContract, "checkWlgXpREADONLY", [addr], nil))
31212953 let virtWlgPoints = asInt(virtWlgData[1])
3122- let $t09686997259 = if ((0 >= virtWlgPoints))
2954+ let $t09179692186 = if ((0 >= virtWlgPoints))
31232955 then $Tuple2(0, nil)
31242956 else {
31252957 let deltaXP = asInt(invoke(wlgContract, "takeWlgXp", [addr], nil))
31272959 then $Tuple2(virtWlgPoints, [IntegerEntry(keyUserLevel(addr), asInt(virtWlgData[0])), IntegerEntry(keyUserXP(addr), asInt(virtWlgData[2]))])
31282960 else throw("Strict value is not equal to itself.")
31292961 }
3130- let wlgPoints = $t09686997259._1
3131- let wlgActions = $t09686997259._2
2962+ let wlgPoints = $t09179692186._1
2963+ let wlgActions = $t09179692186._2
31322964 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
31332965 let freeKeyAcc = keyUserFreePoints(addr)
31342966 let freePointsAcc = (valueOrElse(getInteger(freeKeyAcc), 0) + wlgPoints)
32123044 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
32133045 if (checkTournament(duckAssetId))
32143046 then throw("equipDuck_checkTournament")
3215- else if (checkDelivery(duckAssetId))
3216- then throw("equipDuck_checkDelivery")
3217- else {
3218- let eqKey = keyDuckEquipment(duckAssetId)
3219- let currentSegs = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_")
3220- let bpKey = keyBackpackByDuck(duckAssetId)
3221- let currentPack = getBackpack(bpKey)
3222- let newEq = split(equipment, "_")
3223- if ((size(newEq) != NUMSEGMENTS))
3224- then throw("Wrong equipment string")
3225- else {
3226- let tempProdB = dressB(currentSegs, prodStrToBytes(currentPack[bpIdxProd]), true, nil)
3227- let segBpAux = split(newEq[segBackpack], ";")[1]
3228- let buffEffect = if ((segBpAux == ""))
3229- then 0
3230- else {
3231- let aux0 = split(segBpAux, ",")[0]
3232- if ((aux0 == ""))
3233- then 0
3234- else {
3235- let idxCnt = split(aux0, ":")
3236- let idx = idxCnt[0]
3237- let cnt = idxCnt[1]
3238- if (if (if (if (if ((idx == "06"))
3239- then true
3240- else (idx == "07"))
3241- then true
3242- else (idx == "08"))
3243- then (cnt != "")
3244- else false)
3245- then (parseIntValue(cnt) > 0)
3246- else false)
3247- then parseIntValue(split(productionMatrix[parseIntValue(idx)], "_")[rIdxEffect])
3248- else 0
3249- }
3250- }
3251- let stats = getDuckStats(this, duckAssetId, buffEffect, true)
3252- let newProdB = dressB(newEq, tempProdB, false, stats)
3253- let newProdStr = bytesToProdStr(newProdB)
3254- $Tuple2(([StringEntry(eqKey, equipment), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], newProdStr], ":")), StringEntry(keyDuckBuffs(duckAssetId), makeString([toString(stats[7]), toString(stats[8]), toString(stats[9]), toString(stats[10]), toString(stats[11])], "_"))] ++ prologActions), 0)
3255- }
3256- }
3047+ else {
3048+ let eqKey = keyDuckEquipment(duckAssetId)
3049+ let currentSegs = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_")
3050+ let bpKey = keyBackpackByDuck(duckAssetId)
3051+ let currentPack = getBackpack(bpKey)
3052+ let newEq = split(equipment, "_")
3053+ if ((size(newEq) != NUMSEGMENTS))
3054+ then throw("Wrong equipment string")
3055+ else {
3056+ let tempProdB = dressB(currentSegs, prodStrToBytes(currentPack[bpIdxProd]), true, nil)
3057+ let segBpAux = split(newEq[segBackpack], ";")[1]
3058+ let buffEffect = if ((segBpAux == ""))
3059+ then 0
3060+ else {
3061+ let aux0 = split(segBpAux, ",")[0]
3062+ if ((aux0 == ""))
3063+ then 0
3064+ else {
3065+ let idxCnt = split(aux0, ":")
3066+ let idx = idxCnt[0]
3067+ let cnt = idxCnt[1]
3068+ if (if (if (if (if ((idx == "06"))
3069+ then true
3070+ else (idx == "07"))
3071+ then true
3072+ else (idx == "08"))
3073+ then (cnt != "")
3074+ else false)
3075+ then (parseIntValue(cnt) > 0)
3076+ else false)
3077+ then parseIntValue(split(productionMatrix[parseIntValue(idx)], "_")[rIdxEffect])
3078+ else 0
3079+ }
3080+ }
3081+ let stats = getDuckStats(this, duckAssetId, buffEffect, true)
3082+ let newProdB = dressB(newEq, tempProdB, false, stats)
3083+ let newProdStr = bytesToProdStr(newProdB)
3084+ $Tuple2(([StringEntry(eqKey, equipment), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], newProdStr], ":")), StringEntry(keyDuckBuffs(duckAssetId), makeString([toString(stats[7]), toString(stats[8]), toString(stats[9]), toString(stats[10]), toString(stats[11])], "_"))] ++ prologActions), 0)
3085+ }
3086+ }
32573087 }
32583088 }
32593089
32793109 let curO = parseIntValue(curLoft[volOccupied])
32803110 let curF = parseIntValue(curLoft[volFree])
32813111 let newForts = split(plan, "_")
3282- let $t0104097104212 = fortB(currentForts, prodStrToBytes(wh[whIdxProd]), curO, curF, true, nil)
3283- let tempProdB = $t0104097104212._1
3284- let tempO = $t0104097104212._2
3285- let tempF = $t0104097104212._3
3286- let $t0104215104311 = fortB(newForts, tempProdB, tempO, tempF, false, duckStats)
3287- let newProdB = $t0104215104311._1
3288- let newO = $t0104215104311._2
3289- let newF = $t0104215104311._3
3112+ let $t09894799062 = fortB(currentForts, prodStrToBytes(wh[whIdxProd]), curO, curF, true, nil)
3113+ let tempProdB = $t09894799062._1
3114+ let tempO = $t09894799062._2
3115+ let tempF = $t09894799062._3
3116+ let $t09906599161 = fortB(newForts, tempProdB, tempO, tempF, false, duckStats)
3117+ let newProdB = $t09906599161._1
3118+ let newO = $t09906599161._2
3119+ let newF = $t09906599161._3
32903120 let newProdStr = bytesToProdStr(newProdB)
32913121 let newLoftStr = makeString([curLoft[volLocked], toString(newO), toString(newF), curLoft[volTotal]], "_")
32923122 $Tuple2(([StringEntry(fortKey, plan), StringEntry(whKey, makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], newProdStr, newLoftStr], ":"))] ++ prologActions), 0)
33503180
33513181
33523182 @Callable(i)
3353-func exitDeliveryInternal (duckAssetId) = if ((i.caller != this))
3183+func processDelivery (duckAssetId) = if ((i.caller != this))
33543184 then throw("Access denied")
33553185 else {
3356- let e = exitDeliveryCommon(duckAssetId, false, 0, 0)
3357- $Tuple2((e._1 ++ e._2), false)
3186+ let addr = toString(i.originCaller)
3187+ let fundTotal = valueOrElse(getInteger(economyContract, deliveryFundKey), 0)
3188+ if ((MIN_USDT_FEE_DELIVERY > fundTotal))
3189+ then throw(("Delivery is not available, fund=" + fixedPoint(fundTotal, 6)))
3190+ else {
3191+ let now = lastBlock.timestamp
3192+ let countKey = keyUserDeliveryCount(addr)
3193+ let count = valueOrElse(getInteger(countKey), 0)
3194+ let lastDay = valueOrElse(getInteger(keyUserLastDeliveryDay(addr)), 0)
3195+ let today = (now / DAYMILLIS)
3196+ let acres = valueOrElse(getInteger(acresContract, keyAcresStakedAmountByUser(addr)), 0)
3197+ let allowedDeliveries = (ALLOWED_FREE_DELIVERIES + (acres / ACRES_FOR_DELIVERY_ATTEMPT))
3198+ if (if ((count >= allowedDeliveries))
3199+ then (lastDay == today)
3200+ else false)
3201+ then throw((("You already used " + toString(allowedDeliveries)) + " delivery attempts for today"))
3202+ else {
3203+ let reward = invoke(economyContract, "sendDeliveryReward", [addr], nil)
3204+ $Tuple2([IntegerEntry(countKey, (count + 1)), IntegerEntry(keyUserLastDeliveryDay(addr), today)], reward)
3205+ }
3206+ }
33583207 }
3359-
3360-
3361-
3362-@Callable(i)
3363-func autoExitDelivery (duckAssetId,newHP,reason,score) = if ((i.caller != this))
3364- then throw("Access denied")
3365- else {
3366- let e = exitDeliveryCommon(duckAssetId, true, newHP, score)
3367- $Tuple2(e._1, e._3)
3368- }
3369-
3370-
3371-
3372-@Callable(i)
3373-func breakDelivery () = $Tuple2(prolog(i), "breakDelivery")
33743208
33753209
33763210
34043238 let duckAssetId = parts[0]
34053239 if (checkTournament(duckAssetId))
34063240 then throw("prepareRobbery_checkTournament")
3407- else if (checkDelivery(duckAssetId))
3408- then throw("prepareRobbery_checkDelivery")
3409- else {
3410- let robCost = getRobberyData(this, duckAssetId)._1
3411- if ((robCost > wlgAmt))
3412- then throw(((("Payment " + toString(wlgAmt)) + " < required ") + toString(robCost)))
3413- else {
3414- let candidates = split(parts[1], "_")
3415- let now = lastBlock.timestamp
3416- let duckState = valueOrElse(getInteger(keyDuckRobberyState(duckAssetId)), 0)
3417- let lockedLand = valueOrElse(getString(keyLockedLandByDuck(duckAssetId)), "")
3418- let landETA = valueOrElse(getInteger(keyLandCooldownETA(lockedLand)), 0)
3419- if (if ((duckState != duckIdxFree))
3420- then (landETA > now)
3421- else false)
3422- then throw(("You already started robbing, wait till " + toString(landETA)))
3423- else {
3424- func checker (acc,landAssetId) = {
3425- let state = valueOrElse(getInteger(keyLandRobberyState(landAssetId)), 0)
3426- let cooldownETA = valueOrElse(getInteger(keyLandCooldownETA(landAssetId)), 0)
3427- if ((state > size(landRobCooldowns)))
3428- then throw("Invalid state")
3429- else if ((now > cooldownETA))
3430- then {
3431- let stakedTime = valueOrElse(getInteger(keyStakedTimeByAssetId(landAssetId)), 0)
3432- if ((0 >= stakedTime))
3433- then acc
3434- else {
3435- let a = value(assetInfo(fromBase58String(landAssetId)))
3436- let d = split(a.description, "_")
3437- let pieces = numPiecesBySize(d[recLandSize])
3438- let productivity = applyBonuses(landAssetId, pieces)
3439- let deltaTime = (now - stakedTime)
3440- let availRes = fraction(deltaTime, (productivity * pieces), DAYMILLIS)
3441- if ((MIN_RES_TO_ROB > availRes))
3442- then acc
3443- else (acc :+ landAssetId)
3444- }
3445- }
3446- else acc
3241+ else {
3242+ let robCost = getRobberyData(this, duckAssetId)._1
3243+ if ((robCost > wlgAmt))
3244+ then throw(((("Payment " + toString(wlgAmt)) + " < required ") + toString(robCost)))
3245+ else {
3246+ let candidates = split(parts[1], "_")
3247+ let now = lastBlock.timestamp
3248+ let duckState = valueOrElse(getInteger(keyDuckRobberyState(duckAssetId)), 0)
3249+ let lockedLand = valueOrElse(getString(keyLockedLandByDuck(duckAssetId)), "")
3250+ let landETA = valueOrElse(getInteger(keyLandCooldownETA(lockedLand)), 0)
3251+ if (if ((duckState != duckIdxFree))
3252+ then (landETA > now)
3253+ else false)
3254+ then throw(("You already started robbing, wait till " + toString(landETA)))
3255+ else {
3256+ func checker (acc,landAssetId) = {
3257+ let state = valueOrElse(getInteger(keyLandRobberyState(landAssetId)), 0)
3258+ let cooldownETA = valueOrElse(getInteger(keyLandCooldownETA(landAssetId)), 0)
3259+ if ((state > size(landRobCooldowns)))
3260+ then throw("Invalid state")
3261+ else if ((now > cooldownETA))
3262+ then {
3263+ let stakedTime = valueOrElse(getInteger(keyStakedTimeByAssetId(landAssetId)), 0)
3264+ if ((0 >= stakedTime))
3265+ then acc
3266+ else {
3267+ let a = value(assetInfo(fromBase58String(landAssetId)))
3268+ let d = split(a.description, "_")
3269+ let pieces = numPiecesBySize(d[recLandSize])
3270+ let productivity = applyBonuses(landAssetId, pieces)
3271+ let deltaTime = (now - stakedTime)
3272+ let availRes = fraction(deltaTime, (productivity * pieces), DAYMILLIS)
3273+ if ((MIN_RES_TO_ROB > availRes))
3274+ then acc
3275+ else (acc :+ landAssetId)
3276+ }
3277+ }
3278+ else acc
3279+ }
3280+
3281+ let filtered = {
3282+ let $l = candidates
3283+ let $s = size($l)
3284+ let $acc0 = nil
3285+ func $f0_1 ($a,$i) = if (($i >= $s))
3286+ then $a
3287+ else checker($a, $l[$i])
3288+
3289+ func $f0_2 ($a,$i) = if (($i >= $s))
3290+ then $a
3291+ else throw("List size exceeds 10")
3292+
3293+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
3294+ }
3295+ if ((size(filtered) == 0))
3296+ then throw("No candidates for robbery")
3297+ else {
3298+ let rndIdx = getRandomNumber(size(filtered), message, sig)
3299+ let landAssetId = filtered[rndIdx]
3300+ $Tuple2(([IntegerEntry(keyLandRobberyState(landAssetId), robIdxLocked), IntegerEntry(keyLandCooldownETA(landAssetId), (now + landRobCooldowns[robIdxLocked])), IntegerEntry(keyDuckRobberyState(duckAssetId), duckIdxPreparing), StringEntry(keyLockedLandByDuck(duckAssetId), landAssetId)] ++ prologActions), landAssetId)
34473301 }
3448-
3449- let filtered = {
3450- let $l = candidates
3451- let $s = size($l)
3452- let $acc0 = nil
3453- func $f0_1 ($a,$i) = if (($i >= $s))
3454- then $a
3455- else checker($a, $l[$i])
3456-
3457- func $f0_2 ($a,$i) = if (($i >= $s))
3458- then $a
3459- else throw("List size exceeds 10")
3460-
3461- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
3462- }
3463- if ((size(filtered) == 0))
3464- then throw("No candidates for robbery")
3465- else {
3466- let rndIdx = getRandomNumber(size(filtered), message, sig)
3467- let landAssetId = filtered[rndIdx]
3468- $Tuple2(([IntegerEntry(keyLandRobberyState(landAssetId), robIdxLocked), IntegerEntry(keyLandCooldownETA(landAssetId), (now + landRobCooldowns[robIdxLocked])), IntegerEntry(keyDuckRobberyState(duckAssetId), duckIdxPreparing), StringEntry(keyLockedLandByDuck(duckAssetId), landAssetId)] ++ prologActions), landAssetId)
3469- }
3470- }
3471- }
3472- }
3302+ }
3303+ }
3304+ }
34733305 }
34743306 }
34753307 }
34903322 $Tuple2((prologActions :+ IntegerEntry(keyLastRobberyTimeByDuck(duckAssetId), now)), 0)
34913323 }
34923324 }
3493-
3494-
3495-
3496-@Callable(i)
3497-func acceptDelivery () = {
3498- let prologActions = prolog(i)
3499- let userAddr = toString(i.caller)
3500- let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked")
3501- let fundTotal = valueOrElse(getInteger(economyContract, deliveryFundKey), 0)
3502- let lockedTotal = valueOrElse(getInteger(economyContract, deliveryLockedKey), 0)
3503- if ((MIN_USDT_FEE_DELIVERY > (fundTotal - lockedTotal)))
3504- then throw(((("Delivery is not available, fund=" + fixedPoint(fundTotal, 6)) + ", locked=") + fixedPoint(lockedTotal, 6)))
3505- else {
3506- let now = lastBlock.timestamp
3507- let delayETA = valueOrElse(getInteger(keyDeliveryDelayByDuck(duckAssetId)), 0)
3508- if ((delayETA > now))
3509- then throw(("Delivery is forbidden for your duck until " + toString(delayETA)))
3510- else {
3511- let health = getIntegerValue(keyDuckHealth(duckAssetId))
3512- if ((0 >= health))
3513- then throw("You cannot accept delivery with zero health")
3514- else {
3515- let countKey = keyUserDeliveryCount(userAddr)
3516- let count = valueOrElse(getInteger(countKey), 0)
3517- let lastDay = valueOrElse(getInteger(keyUserLastDeliveryDay(userAddr)), 0)
3518- let today = (now / DAYMILLIS)
3519- let acres = valueOrElse(getInteger(acresContract, keyAcresStakedAmountByUser(userAddr)), 0)
3520- let allowedDeliveries = (ALLOWED_FREE_DELIVERIES + (acres / ACRES_FOR_DELIVERY_ATTEMPT))
3521- if (if ((count >= allowedDeliveries))
3522- then (lastDay == today)
3523- else false)
3524- then throw((("You already used " + toString(allowedDeliveries)) + " delivery attempts for today"))
3525- else if (checkTournament(duckAssetId))
3526- then throw("acceptDelivery_checkTournament")
3527- else if (checkDelivery(duckAssetId))
3528- then throw("acceptDelivery_checkDelivery")
3529- else {
3530- let newLockedTotal = asInt(invoke(economyContract, "updateDeliveryLocked", [(lockedTotal + MIN_USDT_FEE_DELIVERY)], nil))
3531- let curLocKey = keyDuckLocation(duckAssetId)
3532- let curLocation = valueOrElse(getString(curLocKey), DEFAULTLOCATION)
3533- let deliveryLocation = (toString(now) + "_D_0")
3534- $Tuple2(([StringEntry(keySavedLocation(duckAssetId), curLocation), StringEntry(curLocKey, deliveryLocation), IntegerEntry(countKey, if ((lastDay != today))
3535- then 0
3536- else count)] ++ prologActions), $Tuple2(deliveryLocation, newLockedTotal))
3537- }
3538- }
3539- }
3540- }
3541- }
3542-
3543-
3544-
3545-@Callable(i)
3546-func checkDeliveryCallback (duckAssetId) = if ((i.caller != tournamentContract))
3547- then throw("Access denied")
3548- else $Tuple2(nil, checkDelivery(duckAssetId))
35493325
35503326
35513327
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let DAYMILLIS = 86400000
55
66 func keyLastArbTimeByUser (addr) = ("lastArbTimeUser_" + addr)
77
88
99 func keyAcresStakedAmountByUser (addr) = ("acresStakedAmountByUser_" + addr)
1010
1111
1212 let SCALE8 = 100000000
1313
1414 let xpLevelScale = 3200
1515
1616 let xpLevelRecipPow = 4000
1717
1818 let numPointsOnLevelUp = 3
1919
2020 let robberyCostMin = 100000000
2121
2222 let robberyCooldownCoeff = 400
2323
2424 let requirements = ["Strength", "Accuracy", "Intellect", "Endurance", "Dexterity", "Level", "Health"]
2525
2626 let charStrength = 0
2727
2828 let charAccuracy = 1
2929
3030 let charIntellect = 2
3131
3232 let charEndurance = 3
3333
3434 let charDexterity = 4
3535
3636 let segBackpack = 0
3737
3838 let NUMSEGMENTS = 6
3939
4040 let NUMMAINAUX = 2
4141
4242 let MAXSLOTS = 2
4343
4444 let MAXPRODINSLOT = 30
4545
4646 let landRobCooldowns = [0, 600000, 900000, 43200000, 21600000]
4747
4848 let MIN_RES_TO_ROB = 20000000
4949
5050 let robIdxLocked = 1
5151
5252 let duckIdxFree = 0
5353
5454 let duckIdxPreparing = 1
5555
5656 func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId)
5757
5858
5959 func keyDuckChars (duckAssetId) = ("duckChars_" + duckAssetId)
6060
6161
6262 func keyDuckXP (duckAssetId) = ("duckXP_" + duckAssetId)
6363
6464
6565 func keyDuckLevel (duckAssetId) = ("duckLevel_" + duckAssetId)
6666
6767
6868 func keyDuckFreePoints (duckAssetId) = ("duckFreePoints_" + duckAssetId)
6969
7070
7171 func keyDuckEquipment (duckAssetId) = ("duckEquipment_" + duckAssetId)
7272
7373
7474 func keyUserXP (addr) = ("userXP_" + addr)
7575
7676
7777 func keyUserLevel (addr) = ("userLevel_" + addr)
7878
7979
8080 func keyUserFreePoints (addr) = ("userFreePoints_" + addr)
8181
8282
8383 func keySavedHealth (duckAssetId) = ("savedHealth_" + duckAssetId)
8484
8585
8686 func keySavedLocation (duckAssetId) = ("savedLocation_" + duckAssetId)
8787
8888
8989 func keyDuckBuffs (duckAssetId) = ("duckBuffs_" + duckAssetId)
9090
9191
9292 func keyLastRobberyTimeByDuck (duckAssetId) = ("lastRobberyTime_" + duckAssetId)
9393
9494
9595 func keyLastRobberyCostByDuck (duckAssetId) = ("lastRobberyCost_" + duckAssetId)
9696
9797
9898 func keyLandRobberyState (landAssetId) = ("landRobberyState_" + landAssetId)
9999
100100
101101 func keyLandCooldownETA (landAssetId) = ("landCooldownETA_" + landAssetId)
102102
103103
104104 func keyDuckRobberyState (duckAssetId) = ("duckRobberyState_" + duckAssetId)
105105
106106
107107 func keyLockedLandByDuck (duckAssetId) = ("lockedLandByDuck_" + duckAssetId)
108-
109-
110-func keyDeliveryDelayByDuck (duckAssetId) = ("deliveryDelayByDuck_" + duckAssetId)
111108
112109
113110 func keyUserDeliveryCount (addr) = ("userDeliveryCount_" + addr)
114111
115112
116113 func keyUserLastDeliveryDay (addr) = ("userLastDeliveryDay_" + addr)
117114
118115
119116 let xpClaim = 10000
120117
121118 let xpSuccessFlight = 10000
122119
123120 let xpFailFlight = 2000
124121
125122 let xpCallES = 100000
126123
127124 let xpCustomName = 1000000
128125
129126 let xpNewSLand = 5000000
130127
131128 let xpUpgradeInfra = 10000
132129
133130 let xpMerge = 1000000
134131
135132 let xpOnboard = 1000000
136133
137134 let xpHeal = 10000
138135
139136 func levelByXP (xp) = fraction(xpLevelScale, pow(xp, 4, xpLevelRecipPow, 4, 4, DOWN), SCALE8)
140137
141138
142139 func maxHealth (level) = (100 + level)
143140
144141
145142 func levelUp (currLevel,newXP) = {
146143 let newLevel = levelByXP(newXP)
147144 [newLevel, (numPointsOnLevelUp * (newLevel - currLevel))]
148145 }
149146
150147
151148 func getDuckStats (stakingContract,duckAssetId,buffEffect,forceBuffs) = {
152149 let chars = split(valueOrElse(getString(stakingContract, keyDuckChars(duckAssetId)), "0_0_0_0_0"), "_")
153150 let lvl = valueOrElse(getInteger(stakingContract, keyDuckLevel(duckAssetId)), 0)
154151 let health = valueOrElse(getInteger(stakingContract, keyDuckHealth(duckAssetId)), maxHealth(lvl))
155152 let stateBuffs = split(valueOrElse(getString(stakingContract, keyDuckBuffs(duckAssetId)), "0_0_0_0_0"), "_")
156153 ([parseIntValue(chars[charStrength]), parseIntValue(chars[charAccuracy]), parseIntValue(chars[charIntellect]), parseIntValue(chars[charEndurance]), parseIntValue(chars[charDexterity]), lvl, health] ++ (if (forceBuffs)
157154 then [buffEffect, buffEffect, buffEffect, buffEffect, buffEffect]
158155 else [parseIntValue(stateBuffs[charStrength]), parseIntValue(stateBuffs[charAccuracy]), parseIntValue(stateBuffs[charIntellect]), parseIntValue(stateBuffs[charEndurance]), parseIntValue(stateBuffs[charDexterity])]))
159156 }
160157
161158
162159 func getRobberyData (stakingContract,duckAssetId) = {
163160 let lastRobCost = valueOrElse(getInteger(stakingContract, keyLastRobberyCostByDuck(duckAssetId)), 0)
164161 let lastRobTime = valueOrElse(getInteger(stakingContract, keyLastRobberyTimeByDuck(duckAssetId)), 0)
165162 let now = lastBlock.timestamp
166163 let robCost = max([robberyCostMin, (lastRobCost - (robberyCooldownCoeff * (now - lastRobTime)))])
167164 let duckState = valueOrElse(getInteger(stakingContract, keyDuckRobberyState(duckAssetId)), 0)
168165 let lockedLand = valueOrElse(getString(stakingContract, keyLockedLandByDuck(duckAssetId)), "")
169166 let landETA = valueOrElse(getInteger(stakingContract, keyLandCooldownETA(lockedLand)), 0)
170167 $Tuple5(robCost, lastRobTime, duckState, lockedLand, landETA)
171168 }
172169
173170
174171 let LANDPREFIX = "LAND"
175172
176173 let DUCKPREFIX = "DUCK"
177174
178175 let ROBO_PREFIX = "ROBO"
179176
180177 let ARTPRESALE = "PRESALE"
181178
182179 let NUMRES = 6
183180
184181 let MAX_LANDS_STAKED_BY_USER = 25
185182
186183 let DAILYRESBYPIECE = 3456000
187184
188185 let WHMULTIPLIER = 10000000000
189186
190187 let DEFAULTLOCATION = "Africa_F_Africa"
191188
192189 let RESOURCEPRICEMIN = 39637
193190
194191 let ESSELLCOEF = 10
195192
196193 let MIN_USDT_FEE_DELIVERY = 50000
197194
198-let TEN_MINUTES_MILLIS = 600000
199-
200195 let ALLOWED_FREE_DELIVERIES = 1
201196
202197 let ACRES_FOR_DELIVERY_ATTEMPT = 50000000
203198
204199 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"]
205200
206201 let continents = ["Americas", "Europe", "Asia", "Africa", "Oceania"]
207202
208203 let COEFF2MAT = 10000000
209204
210205 let fortAllowedProds = [15, 16, 17, 18, 19, 20, 21, 22, 23]
211206
212207 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_"]
213208
214209 let rIdxCoeff = 6
215210
216211 let rIdxEffect = 8
217212
218213 let rIdxRequirements = 9
219214
220215 let rIdxSlots = 10
221216
222217 let PRODUCTPKGSIZE = 10
223218
224219 let whIdxLevels = 0
225220
226221 let whIdxRes = 1
227222
228223 let whIdxMat = 2
229224
230225 let whIdxProd = 3
231226
232227 let whIdxLOFT = 4
233228
234229 let volLocked = 0
235230
236231 let volOccupied = 1
237232
238233 let volFree = 2
239234
240235 let volTotal = 3
241236
242237 let bpIdxLevel = 0
243238
244239 let bpIdxRes = 1
245240
246241 let bpIdxMat = 2
247242
248243 let bpIdxProd = 3
249244
250245 let locIdxContinent = 0
251246
252247 let locIdxType = 1
253248
254249 let locIdxId = 2
255250
256251 func keyLandAssetIdToOwner (assetId) = ("no_" + assetId)
257252
258253
259254 func keyLandAssetIdToCustomName (assetId) = ("lcna_" + assetId)
260255
261256
262257 func keyStakedTimeByAssetId (assetId) = ("st_" + assetId)
263258
264259
265260 func keyLandArtStatusByTypeAndAssetId (type,assetId) = makeString(["las", type, assetId], "_")
266261
267262
268263 func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("sttao_" + nftType) + "_") + assetId) + "_") + ownerAddr)
269264
270265
271266 func keyWarehouseByLand (landAssetId) = ("wh_" + landAssetId)
272267
273268
274269 func keyInfraLevelByAssetId (assetId) = ("infraLevel_" + assetId)
275270
276271
277272 func keyFortificationsByLand (landAssetId) = ("fortifications_" + landAssetId)
278273
279274
280275 func keyDuckAssetIdToCustomName (assetId) = ("duckCustomNameByAssetId_" + assetId)
281276
282277
283278 func keyAddressToCustomName (addr) = ("accountCustomNameByAddr_" + addr)
284279
285280
286281 func keyAddressRefBy (addr) = ("accRefBy_" + addr)
287282
288283
289284 func keyOnboardArtActivatedOnDuck (duckAssetId) = ("onboardArtActivatedOnDuck_" + duckAssetId)
290285
291286
292287 func keyOnboardArtDuckActivatedBy (addr) = ("onboardArtActivatedDuckBy_" + addr)
293288
294289
295290 func keyAddressReferrals (addr) = ("accReferrals_" + addr)
296291
297292
298293 func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId)
299294
300295
301296 func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
302297
303298
304299 func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId)
305300
306301
307302 func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
308303
309304
310305 func keyUserGwlReleaseTime (userAddr) = ("%s%s__userGwlReleaseTime__" + userAddr)
311306
312307
313308 func keyEsWarehouse () = "emergencyWarehouseProducts"
314309
315310
316311 let deliveryFundKey = "deliveryFund"
317-
318-let deliveryLockedKey = "deliveryLocked"
319312
320313 let lastTourIdKey = "%s__lastTourId"
321314
322315 func keyTourStaticDataById (tId) = ("%s%d__tourStaticData__" + toString(tId))
323316
324317
325318 func keyTourDynamicDataById (tId) = ("%s%d__tourDynamicData__" + toString(tId))
326319
327320
328321 func keyBestResultByTourAndDuck (tId,duckAssetId) = makeString(["%s%d%s__bestResultByTourAndDuck", toString(tId), duckAssetId], "__")
329322
330323
331324 let idxStatic = 0
332325
333326 let idxDynamic = 1
334327
335328 let tStaticEnd = 6
336329
337330 let tDynamicStatus = 1
338331
339332 func getTourData (tourContract,tId) = {
340333 let static = split(valueOrErrorMessage(getString(tourContract, keyTourStaticDataById(tId)), (("Error reading tournament " + toString(tId)) + " data")), "__")
341334 let dynamic = split_4C(valueOrErrorMessage(getString(tourContract, keyTourDynamicDataById(tId)), (("Error reading tournament " + toString(tId)) + " data")), "__")
342335 [static, dynamic]
343336 }
344337
345338
346339 func isInTournament (tourContract,location) = {
347340 let lastId = valueOrElse(getInteger(tourContract, lastTourIdKey), 0)
348341 let loc = split(location, "_")
349342 let now = lastBlock.timestamp
350343 let tData = getTourData(tourContract, lastId)
351344 let static = tData[idxStatic]
352345 let dynamic = tData[idxDynamic]
353346 if (if (if ((loc[locIdxType] == "T"))
354347 then (parseIntValue(loc[locIdxContinent]) == lastId)
355348 else false)
356349 then (dynamic[tDynamicStatus] == "INPROGRESS")
357350 else false)
358351 then (parseIntValue(static[tStaticEnd]) > now)
359352 else false
360353 }
361354
362355
363-func isInDelivery (location) = {
364- let loc = split(location, "_")
365- let now = lastBlock.timestamp
366- let startTime = parseIntValue(loc[locIdxContinent])
367- let distance = parseIntValue(loc[locIdxId])
368- if (if ((loc[locIdxType] == "D"))
369- then ((startTime + TEN_MINUTES_MILLIS) > now)
370- else false)
371- then (3 >= distance)
372- else false
373- }
374-
375-
376-func isUsualLocation (location) = {
377- let locType = split(location, "_")[locIdxType]
378- if ((locType != "T"))
379- then (locType != "D")
380- else false
381- }
382-
383-
384356 func onMission (tourContract,location) = {
385357 let lastId = valueOrElse(getInteger(tourContract, lastTourIdKey), 0)
386358 let loc = split(location, "_")
387359 let now = lastBlock.timestamp
388360 let tData = getTourData(tourContract, lastId)
389361 let static = tData[idxStatic]
390362 let dynamic = tData[idxDynamic]
391363 let locType = loc[locIdxType]
392- if ((locType == "D"))
393- then true
394- else if (if (if ((loc[locIdxType] == "T"))
395- then (parseIntValue(loc[locIdxContinent]) == lastId)
396- else false)
397- then (dynamic[tDynamicStatus] == "INPROGRESS")
398- else false)
399- then (parseIntValue(static[tStaticEnd]) > now)
400- else false
364+ if (if (if ((loc[locIdxType] == "T"))
365+ then (parseIntValue(loc[locIdxContinent]) == lastId)
366+ else false)
367+ then (dynamic[tDynamicStatus] == "INPROGRESS")
368+ else false)
369+ then (parseIntValue(static[tStaticEnd]) > now)
370+ else false
401371 }
402372
403373
404374 func getRecipeMaterials (recipe) = (parseIntValue(recipe[rIdxCoeff]) * COEFF2MAT)
405375
406376
407377 func cheatAttempt (oldLoc,newLoc,cheatCase) = throw(((((("Cheat attempt: oldLoc=" + oldLoc) + ", newLoc=") + newLoc) + ", case=") + toString(cheatCase)))
408378
409379
410380 let KS_SEPARATE_PUBLIC_KEY = false
411381
412382 let KS_ALLOW_BIG_INFRA_MERGE = false
413383
414384 let KS_ALLOW_ROBO_DUCKS = false
415385
416386 let DAY_MILLIS = 86400000
417387
418388 let chain = take(drop(this.bytes, 1), 1)
419389
420390 let pub = match chain {
421391 case _ =>
422392 if ((base58'2W' == $match0))
423393 then if (KS_SEPARATE_PUBLIC_KEY)
424394 then base58'CWsMtTZC5BjjoL4Q1ayW4Wwb1ehGACQB6DrKyPgotKfm'
425395 else base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD'
426396 else if ((base58'2T' == $match0))
427397 then base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD'
428398 else throw("Unknown chain")
429399 }
430400
431401 let usdtAssetId = match chain {
432402 case _ =>
433403 if ((base58'2W' == $match0))
434404 then base58'9wc3LXNA4TEBsXyKtoLE9mrbDD7WMHXvXrCjZvabLAsi'
435405 else if ((base58'2T' == $match0))
436406 then base58'6mWwf9mZBjVgkC54idpyaZLQfAosD914wT8fGf2iiY63'
437407 else throw("Unknown chain")
438408 }
439409
440410 let defaultRestAddressStr = match chain {
441411 case _ =>
442412 if ((base58'2W' == $match0))
443413 then "3PQCuvFbvh4LkPUnrnU1z3jnbA1p9m3WNhv"
444414 else if ((base58'2T' == $match0))
445415 then "3MumkGGztCKAXpWDqxkddofqXSUbqQkvSJy"
446416 else throw("Unknown chain")
447417 }
448418
449419 let InfraUpgradeCostS = match chain {
450420 case _ =>
451421 if ((base58'2W' == $match0))
452422 then 10000000000
453423 else if ((base58'2T' == $match0))
454424 then 100000000
455425 else throw("Unknown chain")
456426 }
457427
458428 let arbitrageDelay = match chain {
459429 case _ =>
460430 if ((base58'2W' == $match0))
461431 then DAY_MILLIS
462432 else if ((base58'2T' == $match0))
463433 then 60000
464- else throw("Unknown chain")
465-}
466-
467-let DELIVERY_PUNISHMENT = match chain {
468- case _ =>
469- if ((base58'2W' == $match0))
470- then 10800000
471- else if ((base58'2T' == $match0))
472- then 900000
473434 else throw("Unknown chain")
474435 }
475436
476437 let SEP = "__"
477438
478439 let MULT6 = 1000000
479440
480441 let MULT8 = 100000000
481442
482443 let SSIZE = 25
483444
484445 let MSIZE = 100
485446
486447 let LSIZE = 225
487448
488449 let XLSIZE = 400
489450
490451 let XXLSIZE = 625
491452
492453 let ITER6 = [0, 1, 2, 3, 4, 5]
493454
494455 func getStringOrFail (address,key) = valueOrErrorMessage(getString(address, key), makeString(["mandatory ", toString(address), ".", key, " is not defined"], ""))
495456
496457
497458 let IdxCfgStakingDapp = 1
498459
499460 let IdxCfgEconomyDapp = 2
500461
501462 let IdxCfgGovernanceDapp = 3
502463
503464 let IdxCfgWlgDapp = 4
504465
505466 let IdxCfgTournamentDapp = 7
506467
507468 let IdxCfgAcresDapp = 8
508469
509470 func keyRestCfg () = "%s__restConfig"
510471
511472
512473 func keyRestAddress () = "%s__restAddr"
513474
514475
515476 func readRestCfgOrFail (rest) = split_4C(getStringOrFail(rest, keyRestCfg()), SEP)
516477
517478
518479 func getContractAddressOrFail (restCfg,idx) = valueOrErrorMessage(addressFromString(restCfg[idx]), ("Rest cfg doesn't contain address at index " + toString(idx)))
519480
520481
521482 let restContract = addressFromStringValue(valueOrElse(getString(this, keyRestAddress()), defaultRestAddressStr))
522483
523484 let restCfg = readRestCfgOrFail(restContract)
524485
525486 let stakingContract = getContractAddressOrFail(restCfg, IdxCfgStakingDapp)
526487
527488 let economyContract = getContractAddressOrFail(restCfg, IdxCfgEconomyDapp)
528489
529490 let govContract = getContractAddressOrFail(restCfg, IdxCfgGovernanceDapp)
530491
531492 let wlgContract = getContractAddressOrFail(restCfg, IdxCfgWlgDapp)
532493
533494 let tournamentContract = getContractAddressOrFail(restCfg, IdxCfgTournamentDapp)
534495
535496 let acresContract = getContractAddressOrFail(restCfg, IdxCfgAcresDapp)
536497
537498 let recLandNum = 0
538499
539500 let recLandSize = 1
540501
541502 let recTerrains = 2
542503
543504 let recContinent = 3
544505
545506 let wlgAssetIdKey = "wlg_assetId"
546507
547508 let wlgAssetId = valueOrErrorMessage(getBinary(wlgContract, wlgAssetIdKey), "WLGOLD is not issued yet")
548509
549510 let acresAssetIdKey = "acresAssetId"
550511
551512 let acresAssetId = valueOrErrorMessage(getBinary(acresContract, acresAssetIdKey), "ACRES is not issued yet")
552513
553514 let randomDelay = 2
554515
555516 func keyCommit (address) = ("finishBlockForAddr_" + address)
556517
557518
558519 func keyResProportions () = "resTypesProportions"
559520
560521
561522 func keyResTypesByContinent (continent) = ("resTypesByContinent_" + continent)
562523
563524
564525 func keyStakedLandsByOwner (ownerAddr) = ("stakedLandsByOwner_" + ownerAddr)
565526
566527
567528 func keyStakedPiecesByOwner (ownerAddr) = ("stakedPiecesByOwner_" + ownerAddr)
568529
569530
570531 func asString (v) = match v {
571532 case s: String =>
572533 s
573534 case _ =>
574535 throw("fail to cast into String")
575536 }
576537
577538
578539 func asInt (v) = match v {
579540 case n: Int =>
580541 n
581542 case _ =>
582543 throw("fail to cast into Int")
583544 }
584545
585546
586547 func asAnyList (v) = match v {
587548 case l: List[Any] =>
588549 l
589550 case _ =>
590551 throw("fail to cast into List[Any]")
591552 }
592553
593554
594555 func asBoolean (v) = match v {
595556 case s: Boolean =>
596557 s
597558 case _ =>
598559 throw("fail to cast into Boolean")
599560 }
600561
601562
602563 func numPiecesBySize (landSize) = match landSize {
603564 case _ =>
604565 if (("S" == $match0))
605566 then SSIZE
606567 else if (("M" == $match0))
607568 then MSIZE
608569 else if (("L" == $match0))
609570 then LSIZE
610571 else if (("XL" == $match0))
611572 then XLSIZE
612573 else if (("XXL" == $match0))
613574 then XXLSIZE
614575 else throw("Unknown land size")
615576 }
616577
617578
618579 func isDigit (s) = isDefined(parseInt(s))
619580
620581
621582 func keyBlocked () = "contractsBlocked"
622583
623584
624585 func keyLastTxIdByUser (addr) = ("lastTxIdByUser_" + addr)
625586
626587
627588 func fixedPoint (val,decimals) = {
628589 let tenPow = pow(10, 0, decimals, 0, 0, DOWN)
629590 let lowPart = toString((val % tenPow))
630591 let zeroes = drop(toString(tenPow), (1 + size(lowPart)))
631592 (((toString((val / tenPow)) + ".") + zeroes) + lowPart)
632593 }
633594
634595
635-func getRandomNumber (maxValue,salt,entropy) = {
636- let randomHash = sha256((salt + entropy))
637- (toInt(randomHash) % maxValue)
638- }
596+func getRandomNumber (maxValue,salt,entropy) = if ((0 >= maxValue))
597+ then throw("maxValue should be > 0")
598+ else {
599+ let randomHash = sha256((salt + entropy))
600+ (toInt(randomHash) % maxValue)
601+ }
639602
640603
641604 let incubatorAddr = match chain {
642605 case _ =>
643606 if ((base58'2W' == $match0))
644607 then addressFromStringValue("3PEktVux2RhchSN63DsDo4b4mz4QqzKSeDv")
645608 else if ((base58'2T' == $match0))
646609 then this
647610 else throw("Unknown chain")
648611 }
649612
650613 let breederAddr = match chain {
651614 case _ =>
652615 if ((base58'2W' == $match0))
653616 then addressFromStringValue("3PDVuU45H7Eh5dmtNbnRNRStGwULA7NY6Hb")
654617 else if ((base58'2T' == $match0))
655618 then this
656619 else throw("Unknown chain")
657620 }
658621
659622 let EMPTY_PROD50 = base64'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=='
660623
661624 let FIVEMINUTESMILLIS = 300000
662625
663626 let RENAMINGCOST = 5000000
664627
665628 let MAXNAMELEN = 50
666629
667630 let InfraUpgradeCostSUsdt = 10000000
668631
669632 let EXPMATERIALS = match chain {
670633 case _ =>
671634 if ((base58'2W' == $match0))
672635 then 252289527462
673636 else if ((base58'2T' == $match0))
674637 then 2522895274
675638 else throw("Unknown chain")
676639 }
677640
678641 let EXPUSDT = match chain {
679642 case _ =>
680643 if ((base58'2W' == $match0))
681644 then 250000000
682645 else if ((base58'2T' == $match0))
683646 then 250000000
684647 else throw("Unknown chain")
685648 }
686649
687650 let ROBO_DUCK_USDT = 100000
688651
689652 let S_COST_ACRES = 2500000000
690653
691654 let FIVEX = toBigInt(5)
692655
693656 let TWENTYX = toBigInt(20)
694657
695658 let TWENTY2X = toBigInt((20 * 20))
696659
697660 let TWENTY3X = toBigInt(((20 * 20) * 20))
698661
699662 let TWENTY4X = toBigInt((((20 * 20) * 20) * 20))
700663
701664 let TWENTY5X = toBigInt(((((20 * 20) * 20) * 20) * 20))
702665
703666 let PRESALENUMLANDS = 500
704667
705668 func keyNextFreeLandNum () = "nextLandNum"
706669
707670
708671 func keyLandCustomNameToAssetId (name) = ("lcn_" + name)
709672
710673
711674 func keyLandToAssetId (landNum) = ("la_" + landNum)
712675
713676
714677 func keyInfraLevelByAssetIdAndOwner (assetId,ownerAddr) = ((("ilao_" + assetId) + "_") + ownerAddr)
715678
716679
717680 func keyLandNumToOwner (landNum) = ("lo_" + landNum)
718681
719682
720683 func keyDuckCustomNameToAssetId (name) = ("duckByCustomName_" + name)
721684
722685
723686 func keyCustomNameToAddress (name) = ("accountByCustomName_" + name)
724687
725688
726689 func keyOldies () = "oldiesList"
727690
728691
729692 func keyNextRoboDuck () = "nextRoboDuck"
730693
731694
732695 let claimModeWh = 0
733696
734697 let claimModeDuck = 1
735698
736699 let claimModeWhThenDuck = 2
737700
738701 let flHealth = 0
739702
740703 let flTimestamp = 5
741704
742705 let flBonus = 6
743706
744707 let flProdsUsed = 7
745708
746709 func nftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize)
747710
748711
749712 func toVolume (amount,pkgSize) = {
750713 let pkgs = if ((amount >= 0))
751714 then (((amount + pkgSize) - 1) / pkgSize)
752715 else -((((-(amount) + pkgSize) - 1) / pkgSize))
753716 (pkgs * MULT8)
754717 }
755718
756719
757720 func distributeByWeights (total,weights) = {
758721 let sum = (((((weights[0] + weights[1]) + weights[2]) + weights[3]) + weights[4]) + weights[5])
759722 if ((0 >= sum))
760723 then throw("Zero weights sum")
761724 else {
762725 let norm6 = fraction(total, MULT6, sum)
763726 func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6))
764727
765728 let $l = weights
766729 let $s = size($l)
767730 let $acc0 = nil
768731 func $f0_1 ($a,$i) = if (($i >= $s))
769732 then $a
770733 else normalizer($a, $l[$i])
771734
772735 func $f0_2 ($a,$i) = if (($i >= $s))
773736 then $a
774737 else throw("List size exceeds 6")
775738
776739 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
777740 }
778741 }
779742
780743
781744 func getNeededMaterials (total) = {
782745 let props = split(value(getString(keyResProportions())), "_")
783746 if ((size(props) != NUMRES))
784747 then throw("Wrong proportions data")
785748 else {
786749 let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])]
787750 distributeByWeights(total, r)
788751 }
789752 }
790753
791754
792755 func subtractMaterials (shouldUseMat,has,totalNeed) = {
793756 let need = getNeededMaterials(totalNeed)
794757 func subtractor (acc,idx) = {
795758 let result = (parseIntValue(has[idx]) - need[idx])
796759 if ((0 > result))
797760 then throw(((((("Not enough material idx=" + toString(idx)) + ", you have ") + has[idx]) + ", but need ") + toString(need[idx])))
798761 else (acc :+ toString(result))
799762 }
800763
801764 if (shouldUseMat)
802765 then {
803766 let $l = ITER6
804767 let $s = size($l)
805768 let $acc0 = nil
806769 func $f0_1 ($a,$i) = if (($i >= $s))
807770 then $a
808771 else subtractor($a, $l[$i])
809772
810773 func $f0_2 ($a,$i) = if (($i >= $s))
811774 then $a
812775 else throw("List size exceeds 6")
813776
814777 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
815778 }
816779 else has
817780 }
818781
819782
820783 func subtractEquipment (oldEq,pUsed) = if ((pUsed == ""))
821784 then $Tuple2(oldEq, false)
822785 else {
823786 func subUsed (acc,idxAmt) = {
824787 let parts = split(idxAmt, ",")
825788 if ((size(parts) != 2))
826789 then throw("Incorrect format, should be index,amount")
827790 else {
828791 let idx = parseIntValue(parts[0])
829792 if (if ((0 > idx))
830793 then true
831794 else (idx >= size(productionMatrix)))
832795 then throw("Unknown product idx")
833796 else {
834797 let amt = parseIntValue(parts[1])
835798 let eqParts = split(acc._1, (parts[0] + ":"))
836799 if ((size(eqParts) != 2))
837800 then throw((("You don't have " + prodTypes[idx]) + " equipped"))
838801 else {
839802 let tmp = eqParts[1]
840803 let numLen = if (isDigit(take(drop(tmp, 1), 1)))
841804 then 2
842805 else 1
843806 let curr = parseIntValue(take(tmp, numLen))
844807 let tail = drop(tmp, numLen)
845808 let newAmt = if ((curr >= amt))
846809 then (curr - amt)
847810 else throw(((((("You equipped " + toString(curr)) + " of ") + prodTypes[idx]) + ", but tried to use ") + toString(amt)))
848811 $Tuple2(((((eqParts[0] + parts[0]) + ":") + toString(newAmt)) + tail), if (acc._2)
849812 then true
850813 else if (if ((idx >= 6))
851814 then (8 >= idx)
852815 else false)
853816 then (newAmt == 0)
854817 else false)
855818 }
856819 }
857820 }
858821 }
859822
860823 let $l = split(pUsed, "_")
861824 let $s = size($l)
862825 let $acc0 = $Tuple2(oldEq, false)
863826 func $f0_1 ($a,$i) = if (($i >= $s))
864827 then $a
865828 else subUsed($a, $l[$i])
866829
867830 func $f0_2 ($a,$i) = if (($i >= $s))
868831 then $a
869832 else throw("List size exceeds 10")
870833
871834 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
872835 }
873836
874837
875838 func prodStrToBytes (prodStr) = {
876839 let pList = if ((prodStr == ""))
877840 then nil
878841 else split_4C(prodStr, "_")
879842 func toBV (acc,recipe) = {
880843 let j = (size(acc) / 8)
881844 let curr = if ((size(pList) > j))
882845 then parseIntValue(pList[j])
883846 else 0
884847 (acc + toBytes(curr))
885848 }
886849
887850 let $l = productionMatrix
888851 let $s = size($l)
889852 let $acc0 = base58''
890853 func $f0_1 ($a,$i) = if (($i >= $s))
891854 then $a
892855 else toBV($a, $l[$i])
893856
894857 func $f0_2 ($a,$i) = if (($i >= $s))
895858 then $a
896859 else throw("List size exceeds 50")
897860
898861 $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)
899862 }
900863
901864
902865 func bytesToProdStr (bv) = {
903866 func fromBV (acc,recipe) = {
904867 let j = size(acc)
905868 let b = take(drop(bv, (8 * j)), 8)
906869 (acc :+ toString(toInt(b)))
907870 }
908871
909872 makeString_2C({
910873 let $l = productionMatrix
911874 let $s = size($l)
912875 let $acc0 = nil
913876 func $f0_1 ($a,$i) = if (($i >= $s))
914877 then $a
915878 else fromBV($a, $l[$i])
916879
917880 func $f0_2 ($a,$i) = if (($i >= $s))
918881 then $a
919882 else throw("List size exceeds 50")
920883
921884 $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)
922885 }, "_")
923886 }
924887
925888
926889 func checkStatRequirements (duckStats,reqs) = {
927890 func check (acc,j) = {
928891 let buff = if ((size(duckStats) > (7 + j)))
929892 then duckStats[(7 + j)]
930893 else 0
931894 if ((parseIntValue(reqs[j]) > (duckStats[j] + buff)))
932895 then throw(("Requirement not satisfied: " + requirements[j]))
933896 else true
934897 }
935898
936899 let $l = [0, 1, 2, 3, 4, 5, 6]
937900 let $s = size($l)
938901 let $acc0 = false
939902 func $f0_1 ($a,$i) = if (($i >= $s))
940903 then $a
941904 else check($a, $l[$i])
942905
943906 func $f0_2 ($a,$i) = if (($i >= $s))
944907 then $a
945908 else throw("List size exceeds 7")
946909
947910 $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)
948911 }
949912
950913
951914 func placeProdB (idxCnt,pList,isPositive,duckStats,occupied,free) = {
952915 let parts = split(idxCnt, ":")
953916 if ((size(parts) != 2))
954917 then throw("Incorrect format, should be index:amount")
955918 else if (if (!(isPositive))
956919 then (size(parts[0]) != 2)
957920 else false)
958921 then throw("Product idx should be 2 digits, zero padded")
959922 else {
960923 let productIdx = parseIntValue(parts[0])
961924 let count = parseIntValue(parts[1])
962925 if (!(containsElement(fortAllowedProds, productIdx)))
963926 then throw((("Product '" + prodTypes[productIdx]) + "' cannot be used for land defense"))
964927 else if ((0 > count))
965928 then throw("Count can't be negative")
966929 else if ((count > MAXPRODINSLOT))
967930 then throw(((("Can't put more than " + toString(MAXPRODINSLOT)) + " of ") + prodTypes[productIdx]))
968931 else if ((count == 0))
969932 then $Tuple3(pList, occupied, free)
970933 else {
971934 let head = take(pList, (8 * productIdx))
972935 let curr = toInt(take(drop(pList, (8 * productIdx)), 8))
973936 let tail = drop(pList, (8 * (productIdx + 1)))
974937 let recipe = split(productionMatrix[productIdx], "_")
975938 if (if (!(isPositive))
976939 then (count > curr)
977940 else false)
978941 then throw(((((("You have " + toString(curr)) + " of ") + prodTypes[productIdx]) + ", but tried to use ") + toString(count)))
979942 else {
980943 let newAmt = if (if (!(isPositive))
981944 then checkStatRequirements(duckStats, split(recipe[rIdxRequirements], ","))
982945 else false)
983946 then (curr - count)
984947 else (curr + count)
985948 let deltaVol = (toVolume(newAmt, PRODUCTPKGSIZE) - toVolume(curr, PRODUCTPKGSIZE))
986949 $Tuple3(((head + toBytes(newAmt)) + tail), (occupied + deltaVol), (free - deltaVol))
987950 }
988951 }
989952 }
990953 }
991954
992955
993956 func addProdB (idxCnt,pList,isPositive,segment,mainAux,slot,duckStats) = {
994957 let parts = split(idxCnt, ":")
995958 if ((size(parts) != 2))
996959 then throw("Incorrect format, should be index:amount")
997960 else if (if (!(isPositive))
998961 then (size(parts[0]) != 2)
999962 else false)
1000963 then throw("Product idx should be 2 digits, zero padded")
1001964 else {
1002965 let productIdx = parseIntValue(parts[0])
1003966 let count = parseIntValue(parts[1])
1004967 if (if ((0 > productIdx))
1005968 then true
1006969 else (productIdx >= size(productionMatrix)))
1007970 then throw("Unknown product idx")
1008971 else if ((0 > count))
1009972 then throw("Count can't be negative")
1010973 else if ((count > MAXPRODINSLOT))
1011974 then throw(((("Can't put more than " + toString(MAXPRODINSLOT)) + " of ") + prodTypes[productIdx]))
1012975 else if ((count == 0))
1013976 then $Tuple2(pList, false)
1014977 else {
1015978 let head = take(pList, (8 * productIdx))
1016979 let curr = toInt(take(drop(pList, (8 * productIdx)), 8))
1017980 let tail = drop(pList, (8 * (productIdx + 1)))
1018981 let recipe = split(productionMatrix[productIdx], "_")
1019982 if (if (!(isPositive))
1020983 then (count > curr)
1021984 else false)
1022985 then throw(((((("You have " + toString(curr)) + " of ") + prodTypes[productIdx]) + ", but tried to use ") + toString(count)))
1023986 else {
1024987 let isBigItem = if (if (!(isPositive))
1025988 then checkStatRequirements(duckStats, split(recipe[rIdxRequirements], ","))
1026989 else false)
1027990 then {
1028991 let compat = recipe[rIdxSlots]
1029992 if ((compat == ""))
1030993 then throw("Item cannot be equipped")
1031994 else {
1032995 let c = parseIntValue(compat)
1033996 let cSeg = (c / 100)
1034997 if ((segment != cSeg))
1035998 then throw("Segment incompatible")
1036999 else {
10371000 let cMainAux = ((c % 100) / 10)
10381001 if ((mainAux != cMainAux))
10391002 then throw("Slot incompatible")
10401003 else {
10411004 let cNumSlots = (c % 10)
10421005 if (if ((slot != 0))
10431006 then (cNumSlots > 1)
10441007 else false)
10451008 then throw("Big items should occupy slot 0")
10461009 else (cNumSlots > 1)
10471010 }
10481011 }
10491012 }
10501013 }
10511014 else false
10521015 $Tuple2(((head + toBytes((curr + (if (isPositive)
10531016 then count
10541017 else -(count))))) + tail), isBigItem)
10551018 }
10561019 }
10571020 }
10581021 }
10591022
10601023
10611024 func slotsGroupB (g,bpIn,isPositive,segment,mainAux,stats) = if ((g != ""))
10621025 then {
10631026 let slots = split(g, ",")
10641027 if ((size(slots) > MAXSLOTS))
10651028 then throw("Wrong slots format")
10661029 else {
10671030 let s0 = slots[0]
10681031 let s1 = if ((size(slots) > 1))
10691032 then slots[1]
10701033 else ""
10711034 if (if ((s0 == ""))
10721035 then (s1 == "")
10731036 else false)
10741037 then bpIn
10751038 else {
10761039 let tmpS0 = if ((s0 != ""))
10771040 then addProdB(s0, bpIn, isPositive, segment, mainAux, 0, stats)
10781041 else $Tuple2(bpIn, false)
10791042 if ((s1 != ""))
10801043 then if (tmpS0._2)
10811044 then throw("Big item already occupies slot")
10821045 else addProdB(s1, tmpS0._1, isPositive, segment, mainAux, 1, stats)._1
10831046 else tmpS0._1
10841047 }
10851048 }
10861049 }
10871050 else bpIn
10881051
10891052
10901053 func dressB (segList,pBytes,isPositive,stats) = {
10911054 func segment (acc,seg) = {
10921055 let j = acc._1
10931056 let mainAux = split(seg, ";")
10941057 if ((size(mainAux) != NUMMAINAUX))
10951058 then throw("Wrong segment format")
10961059 else {
10971060 let m = mainAux[0]
10981061 let a = mainAux[1]
10991062 if (if ((m == ""))
11001063 then (a == "")
11011064 else false)
11021065 then $Tuple2((j + 1), acc._2)
11031066 else {
11041067 let tmpM = slotsGroupB(m, acc._2, isPositive, j, 0, stats)
11051068 $Tuple2((j + 1), slotsGroupB(a, tmpM, isPositive, j, 1, stats))
11061069 }
11071070 }
11081071 }
11091072
11101073 ( let $l = segList
11111074 let $s = size($l)
11121075 let $acc0 = $Tuple2(0, pBytes)
11131076 func $f0_1 ($a,$i) = if (($i >= $s))
11141077 then $a
11151078 else segment($a, $l[$i])
11161079
11171080 func $f0_2 ($a,$i) = if (($i >= $s))
11181081 then $a
11191082 else throw("List size exceeds 6")
11201083
11211084 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6))._2
11221085 }
11231086
11241087
11251088 func fortB (segList,pBytes,occupied,free,isPositive,duckStats) = if ((3 > size(segList)))
11261089 then throw("At least duck, mines and traps parts are required")
11271090 else {
11281091 func segment (acc,seg) = {
11291092 let j = acc._1
11301093 if ((j == 0))
11311094 then $Tuple4((j + 1), acc._2, acc._3, acc._4)
11321095 else {
11331096 let p = placeProdB(seg, acc._2, isPositive, duckStats, acc._3, acc._4)
11341097 $Tuple4((j + 1), p._1, p._2, p._3)
11351098 }
11361099 }
11371100
11381101 let t = {
11391102 let $l = segList
11401103 let $s = size($l)
11411104 let $acc0 = $Tuple4(0, pBytes, occupied, free)
11421105 func $f0_1 ($a,$i) = if (($i >= $s))
11431106 then $a
11441107 else segment($a, $l[$i])
11451108
11461109 func $f0_2 ($a,$i) = if (($i >= $s))
11471110 then $a
11481111 else throw("List size exceeds 10")
11491112
11501113 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
11511114 }
11521115 $Tuple3(t._2, t._3, t._4)
11531116 }
11541117
11551118
11561119 func canWearCurrentEquipment (duckAssetId) = {
11571120 let eqKey = keyDuckEquipment(duckAssetId)
11581121 let currEq = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_")
11591122 let tempProdB = dressB(currEq, EMPTY_PROD50, true, nil)
11601123 let segBpAux = split(currEq[segBackpack], ";")[1]
11611124 let buffEffect = if ((segBpAux == ""))
11621125 then 0
11631126 else {
11641127 let aux0 = split(segBpAux, ",")[0]
11651128 if ((aux0 == ""))
11661129 then 0
11671130 else {
11681131 let idxCnt = split(aux0, ":")
11691132 let idx = idxCnt[0]
11701133 let cnt = idxCnt[1]
11711134 if (if (if (if (if ((idx == "06"))
11721135 then true
11731136 else (idx == "07"))
11741137 then true
11751138 else (idx == "08"))
11761139 then (cnt != "")
11771140 else false)
11781141 then (parseIntValue(cnt) > 0)
11791142 else false)
11801143 then parseIntValue(split(productionMatrix[parseIntValue(idx)], "_")[rIdxEffect])
11811144 else 0
11821145 }
11831146 }
11841147 let stats = getDuckStats(this, duckAssetId, buffEffect, true)
11851148 let newProdB = dressB(currEq, tempProdB, false, stats)
11861149 (newProdB == newProdB)
11871150 }
11881151
11891152
11901153 func updateProportionsInternal (propList,terrainCounts,landSizeIndex,sign) = if ((size(propList) != NUMRES))
11911154 then throw("Wrong proportions data")
11921155 else {
11931156 func updater (acc,i) = {
11941157 let result = (parseIntValue(propList[i]) + ((sign * terrainCounts[i]) * landSizeIndex))
11951158 if ((0 > result))
11961159 then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex)))
11971160 else (acc :+ toString(result))
11981161 }
11991162
12001163 let $l = ITER6
12011164 let $s = size($l)
12021165 let $acc0 = nil
12031166 func $f0_1 ($a,$i) = if (($i >= $s))
12041167 then $a
12051168 else updater($a, $l[$i])
12061169
12071170 func $f0_2 ($a,$i) = if (($i >= $s))
12081171 then $a
12091172 else throw("List size exceeds 6")
12101173
12111174 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
12121175 }
12131176
12141177
12151178 func updateProportions (terrainCounts,landSizeIndex,sign) = {
12161179 let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
12171180 makeString(updateProportionsInternal(propList, terrainCounts, landSizeIndex, sign), "_")
12181181 }
12191182
12201183
12211184 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)]
12221185
12231186
12241187 func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = {
12251188 func adder (acc,i) = {
12261189 let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
12271190 (acc :+ toString((parseIntValue(currentRes[i]) + resOfType)))
12281191 }
12291192
12301193 let r = {
12311194 let $l = ITER6
12321195 let $s = size($l)
12331196 let $acc0 = nil
12341197 func $f0_1 ($a,$i) = if (($i >= $s))
12351198 then $a
12361199 else adder($a, $l[$i])
12371200
12381201 func $f0_2 ($a,$i) = if (($i >= $s))
12391202 then $a
12401203 else throw("List size exceeds 6")
12411204
12421205 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
12431206 }
12441207 makeString(r, "_")
12451208 }
12461209
12471210
12481211 func virtClaim (terrainCounts,deltaTime,landSizeIndex,dailyByPieceWithBonuses) = {
12491212 func adder (acc,i) = {
12501213 let resOfType = ((fraction(deltaTime, dailyByPieceWithBonuses, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
12511214 $Tuple2((acc._1 :+ resOfType), (acc._2 + resOfType))
12521215 }
12531216
12541217 let $l = ITER6
12551218 let $s = size($l)
12561219 let $acc0 = $Tuple2(nil, 0)
12571220 func $f0_1 ($a,$i) = if (($i >= $s))
12581221 then $a
12591222 else adder($a, $l[$i])
12601223
12611224 func $f0_2 ($a,$i) = if (($i >= $s))
12621225 then $a
12631226 else throw("List size exceeds 6")
12641227
12651228 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
12661229 }
12671230
12681231
12691232 func distributeRes (currentWhRes,currentPackRes,resToClaim,whSpaceLeft) = {
12701233 let resListToClaim = resToClaim._1
12711234 let resAmToClaim = resToClaim._2
12721235 if ((resAmToClaim == 0))
12731236 then $Tuple2(makeString(currentWhRes, "_"), makeString(currentPackRes, "_"))
12741237 else if ((whSpaceLeft >= resAmToClaim))
12751238 then {
12761239 func addLists (acc,i) = (acc :+ toString((parseIntValue(currentWhRes[i]) + resListToClaim[i])))
12771240
12781241 let r = {
12791242 let $l = ITER6
12801243 let $s = size($l)
12811244 let $acc0 = nil
12821245 func $f0_1 ($a,$i) = if (($i >= $s))
12831246 then $a
12841247 else addLists($a, $l[$i])
12851248
12861249 func $f0_2 ($a,$i) = if (($i >= $s))
12871250 then $a
12881251 else throw("List size exceeds 6")
12891252
12901253 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
12911254 }
12921255 $Tuple2(makeString(r, "_"), makeString(currentPackRes, "_"))
12931256 }
12941257 else {
12951258 func addPartLists (acc,i) = {
12961259 let whPart = fraction(resListToClaim[i], whSpaceLeft, resAmToClaim)
12971260 $Tuple2((acc._1 :+ toString((parseIntValue(currentWhRes[i]) + whPart))), (acc._2 :+ toString(((parseIntValue(currentPackRes[i]) + resListToClaim[i]) - whPart))))
12981261 }
12991262
13001263 let r = {
13011264 let $l = ITER6
13021265 let $s = size($l)
13031266 let $acc0 = $Tuple2(nil, nil)
13041267 func $f0_1 ($a,$i) = if (($i >= $s))
13051268 then $a
13061269 else addPartLists($a, $l[$i])
13071270
13081271 func $f0_2 ($a,$i) = if (($i >= $s))
13091272 then $a
13101273 else throw("List size exceeds 6")
13111274
13121275 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
13131276 }
13141277 $Tuple2(makeString(r._1, "_"), makeString(r._2, "_"))
13151278 }
13161279 }
13171280
13181281
13191282 func abs (x) = if ((x >= toBigInt(0)))
13201283 then x
13211284 else -(x)
13221285
13231286
13241287 let freq = [[6, 9, 14, 15, 16], [5, 8, 13, 14, 15], [1, 4, 9, 10, 15], [1, 6, 7, 15, 19], [4, 7, 8, 13, 18]]
13251288
13261289 func genChar (n,freqs) = {
13271290 let rem = toInt((n % TWENTYX))
13281291 let letter = if ((freqs[0] > rem))
13291292 then "A"
13301293 else if ((freqs[1] > rem))
13311294 then "B"
13321295 else if ((freqs[2] > rem))
13331296 then "C"
13341297 else if ((freqs[3] > rem))
13351298 then "D"
13361299 else if ((freqs[4] > rem))
13371300 then "E"
13381301 else "F"
13391302 letter
13401303 }
13411304
13421305
13431306 func genTerrains (seed,continentIdx) = {
13441307 let f = freq[continentIdx]
13451308 func terrainGenerator (acc,elem) = $Tuple2((((((acc._1 + genChar(acc._2, f)) + genChar((acc._2 / TWENTYX), f)) + genChar((acc._2 / TWENTY2X), f)) + genChar((acc._2 / TWENTY3X), f)) + genChar((acc._2 / TWENTY4X), f)), (acc._2 / TWENTY5X))
13461309
13471310 let t = {
13481311 let $l = [1, 2, 3, 4, 5]
13491312 let $s = size($l)
13501313 let $acc0 = $Tuple2("", (seed / FIVEX))
13511314 func $f0_1 ($a,$i) = if (($i >= $s))
13521315 then $a
13531316 else terrainGenerator($a, $l[$i])
13541317
13551318 func $f0_2 ($a,$i) = if (($i >= $s))
13561319 then $a
13571320 else throw("List size exceeds 5")
13581321
13591322 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
13601323 }
13611324 t._1
13621325 }
13631326
13641327
13651328 let PERM25 = [7, 2, 15, 19, 8, 24, 1, 21, 16, 5, 0, 22, 20, 23, 11, 4, 18, 12, 6, 10, 3, 17, 13, 9, 14]
13661329
13671330 let TCHARS = ["A", "B", "C", "D", "E", "F"]
13681331
13691332 func genTerrainsForMerge (sumTerrains,landSizeIndex) = {
13701333 func step1 (acc,s) = {
13711334 let j = acc._2
13721335 let el = parseIntValue(s)
13731336 let x = if ((el == 0))
13741337 then 0
13751338 else if ((el >= (4 * landSizeIndex)))
13761339 then (el / landSizeIndex)
13771340 else if ((el > (3 * landSizeIndex)))
13781341 then 3
13791342 else (((el - 1) / landSizeIndex) + 1)
13801343 $Tuple3((acc._1 :+ x), (acc._2 + 1), (acc._3 + x))
13811344 }
13821345
13831346 let t = {
13841347 let $l = sumTerrains
13851348 let $s = size($l)
13861349 let $acc0 = $Tuple3(nil, 0, 0)
13871350 func $f0_1 ($a,$i) = if (($i >= $s))
13881351 then $a
13891352 else step1($a, $l[$i])
13901353
13911354 func $f0_2 ($a,$i) = if (($i >= $s))
13921355 then $a
13931356 else throw("List size exceeds 6")
13941357
13951358 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
13961359 }
13971360 let arr = t._1
13981361 let maxIdx = value(indexOf(arr, max(arr)))
13991362 let delta = (t._3 - 25)
14001363 func subber (acc,idx) = {
14011364 let val = if ((idx == maxIdx))
14021365 then (arr[idx] - delta)
14031366 else arr[idx]
14041367 let zeroes = if ((val == 0))
14051368 then nil
14061369 else split(drop(toString(pow(10, 0, val, 0, 0, DOWN)), 1), "")
14071370 let c = TCHARS[idx]
14081371 func listGen (ac,ignored) = (ac :+ c)
14091372
14101373 let z = {
14111374 let $l = zeroes
14121375 let $s = size($l)
14131376 let $acc0 = nil
14141377 func $f1_1 ($a,$i) = if (($i >= $s))
14151378 then $a
14161379 else listGen($a, $l[$i])
14171380
14181381 func $f1_2 ($a,$i) = if (($i >= $s))
14191382 then $a
14201383 else throw("List size exceeds 25")
14211384
14221385 $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25)
14231386 }
14241387 (acc ++ z)
14251388 }
14261389
14271390 let r = {
14281391 let $l = ITER6
14291392 let $s = size($l)
14301393 let $acc0 = nil
14311394 func $f1_1 ($a,$i) = if (($i >= $s))
14321395 then $a
14331396 else subber($a, $l[$i])
14341397
14351398 func $f1_2 ($a,$i) = if (($i >= $s))
14361399 then $a
14371400 else throw("List size exceeds 6")
14381401
14391402 $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6)
14401403 }
14411404 func permut (acc,j) = (acc + r[j])
14421405
14431406 let $l = PERM25
14441407 let $s = size($l)
14451408 let $acc0 = ""
14461409 func $f2_1 ($a,$i) = if (($i >= $s))
14471410 then $a
14481411 else permut($a, $l[$i])
14491412
14501413 func $f2_2 ($a,$i) = if (($i >= $s))
14511414 then $a
14521415 else throw("List size exceeds 25")
14531416
14541417 $f2_2($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($f2_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10), 11), 12), 13), 14), 15), 16), 17), 18), 19), 20), 21), 22), 23), 24), 25)
14551418 }
14561419
14571420
14581421 func getBackpack (bpKey) = {
14591422 let p = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
14601423 [toString(valueOrElse(parseInt(p[bpIdxLevel]), 0)), if ((size(split(p[bpIdxRes], "_")) == NUMRES))
14611424 then p[bpIdxRes]
14621425 else "0_0_0_0_0_0", if ((size(split(p[bpIdxMat], "_")) == NUMRES))
14631426 then p[bpIdxMat]
14641427 else "0_0_0_0_0_0", p[bpIdxProd]]
14651428 }
14661429
14671430
14681431 func getWarehouseTotalVolume (volPrefix) = {
14691432 let parts = split(volPrefix, "_")
14701433 ((WHMULTIPLIER * (parseIntValue(parts[1]) + 1)) * parseIntValue(parts[0]))
14711434 }
14721435
14731436
14741437 func getWarehouseOccupiedVol (currentWh) = {
14751438 let goods = currentWh[whIdxProd]
14761439 func sumResMat (acc,item) = (acc + parseIntValue(item))
14771440
14781441 func sumProd (acc,item) = {
14791442 let idx = acc._1
14801443 let pkgs = (((parseIntValue(item) + PRODUCTPKGSIZE) - 1) / PRODUCTPKGSIZE)
14811444 $Tuple2((idx + 1), (acc._2 + (pkgs * MULT8)))
14821445 }
14831446
14841447 let whResVol = {
14851448 let $l = split(currentWh[whIdxRes], "_")
14861449 let $s = size($l)
14871450 let $acc0 = 0
14881451 func $f0_1 ($a,$i) = if (($i >= $s))
14891452 then $a
14901453 else sumResMat($a, $l[$i])
14911454
14921455 func $f0_2 ($a,$i) = if (($i >= $s))
14931456 then $a
14941457 else throw("List size exceeds 6")
14951458
14961459 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
14971460 }
14981461 let whMatVol = {
14991462 let $l = split(currentWh[whIdxMat], "_")
15001463 let $s = size($l)
15011464 let $acc0 = 0
15021465 func $f1_1 ($a,$i) = if (($i >= $s))
15031466 then $a
15041467 else sumResMat($a, $l[$i])
15051468
15061469 func $f1_2 ($a,$i) = if (($i >= $s))
15071470 then $a
15081471 else throw("List size exceeds 6")
15091472
15101473 $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6)
15111474 }
15121475 let whGoodsVol = if ((goods == ""))
15131476 then 0
15141477 else ( let $l = split_4C(goods, "_")
15151478 let $s = size($l)
15161479 let $acc0 = $Tuple2(0, 0)
15171480 func $f2_1 ($a,$i) = if (($i >= $s))
15181481 then $a
15191482 else sumProd($a, $l[$i])
15201483
15211484 func $f2_2 ($a,$i) = if (($i >= $s))
15221485 then $a
15231486 else throw("List size exceeds 50")
15241487
15251488 $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
15261489 ((whResVol + whMatVol) + whGoodsVol)
15271490 }
15281491
15291492
15301493 func getWarehouse (whKey,landIndex,infraLevel) = {
15311494 let volPrefix = ((toString(landIndex) + "_") + toString(infraLevel))
15321495 let whTotal = getWarehouseTotalVolume(volPrefix)
15331496 let whStr = valueOrElse(getString(whKey), (volPrefix + ":0_0_0_0_0_0:0_0_0_0_0_0::0"))
15341497 let wh = split_4C(whStr, ":")
15351498 let whOccupied = getWarehouseOccupiedVol(wh)
15361499 let whLoft = if ((5 > size(wh)))
15371500 then makeString(["0", toString(whOccupied), toString((whTotal - whOccupied)), toString(whTotal)], "_")
15381501 else {
15391502 let loft = split(wh[whIdxLOFT], "_")
15401503 let whLocked = parseIntValue(loft[volLocked])
15411504 let occ = if ((size(loft) > 1))
15421505 then parseIntValue(loft[volOccupied])
15431506 else whOccupied
15441507 makeString([toString(whLocked), toString(occ), toString(((whTotal - whLocked) - occ)), toString(whTotal)], "_")
15451508 }
15461509 [wh[whIdxLevels], if ((size(split(wh[whIdxRes], "_")) == NUMRES))
15471510 then wh[whIdxRes]
15481511 else "0_0_0_0_0_0", if ((size(split(wh[whIdxMat], "_")) == NUMRES))
15491512 then wh[whIdxMat]
15501513 else "0_0_0_0_0_0", wh[whIdxProd], whLoft]
15511514 }
15521515
15531516
15541517 func getWarehouseSpaceLeft (currentWh) = {
15551518 let occupiedVol = getWarehouseOccupiedVol(currentWh)
15561519 let currWhLockedVol = parseIntValue(split(currentWh[whIdxLOFT], "_")[volLocked])
15571520 ((getWarehouseTotalVolume(currentWh[whIdxLevels]) - occupiedVol) - currWhLockedVol)
15581521 }
15591522
15601523
15611524 func moveStuff (cargoParts,currentWh,currentPack) = if ((size(cargoParts) != 3))
15621525 then throw("cargoListStr should contain exactly 2 ':' separators")
15631526 else {
15641527 let resParts = split(cargoParts[0], "_")
15651528 let matParts = split(cargoParts[1], "_")
15661529 let prodParts = if ((cargoParts[2] == ""))
15671530 then nil
15681531 else split_4C(cargoParts[2], "_")
15691532 if ((size(resParts) != NUMRES))
15701533 then throw("All 6 resources should be passed")
15711534 else if ((size(matParts) != NUMRES))
15721535 then throw("All 6 materials should be passed")
15731536 else {
15741537 let whSpaceLeft = getWarehouseSpaceLeft(currentWh)
15751538 let currWhRes = split(currentWh[whIdxRes], "_")
15761539 let currWhMat = split(currentWh[whIdxMat], "_")
15771540 let currWhProd = if ((currentWh[whIdxProd] == ""))
15781541 then nil
15791542 else split_4C(currentWh[whIdxProd], "_")
15801543 let currentPackRes = split(currentPack[bpIdxRes], "_")
15811544 let currentPackMat = split(currentPack[bpIdxMat], "_")
15821545 let currentPackProd = if ((currentPack[bpIdxProd] == ""))
15831546 then nil
15841547 else split_4C(currentPack[bpIdxProd], "_")
15851548 func mvR (acc,item) = {
15861549 let i = acc._1
15871550 let am = parseIntValue(item)
15881551 let whr = parseIntValue(currWhRes[i])
15891552 let bpr = parseIntValue(currentPackRes[i])
15901553 if ((am == 0))
15911554 then $Tuple4((i + 1), (acc._2 :+ currWhRes[i]), (acc._3 :+ currentPackRes[i]), acc._4)
15921555 else if ((am > 0))
15931556 then if ((am > bpr))
15941557 then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpr)) + " available"))
15951558 else $Tuple4((i + 1), (acc._2 :+ toString((whr + am))), (acc._3 :+ toString((bpr - am))), (acc._4 + am))
15961559 else if ((-(am) > whr))
15971560 then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whr)) + " available"))
15981561 else $Tuple4((i + 1), (acc._2 :+ toString((whr + am))), (acc._3 :+ toString((bpr - am))), (acc._4 + am))
15991562 }
16001563
16011564 let r = {
16021565 let $l = resParts
16031566 let $s = size($l)
16041567 let $acc0 = $Tuple4(0, nil, nil, 0)
16051568 func $f0_1 ($a,$i) = if (($i >= $s))
16061569 then $a
16071570 else mvR($a, $l[$i])
16081571
16091572 func $f0_2 ($a,$i) = if (($i >= $s))
16101573 then $a
16111574 else throw("List size exceeds 6")
16121575
16131576 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
16141577 }
16151578 func mvM (acc,item) = {
16161579 let i = acc._1
16171580 let am = parseIntValue(item)
16181581 let whm = parseIntValue(currWhMat[i])
16191582 let bpm = parseIntValue(currentPackMat[i])
16201583 if ((am == 0))
16211584 then $Tuple4((i + 1), (acc._2 :+ currWhMat[i]), (acc._3 :+ currentPackMat[i]), acc._4)
16221585 else if ((am > 0))
16231586 then if ((am > bpm))
16241587 then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpm)) + " available"))
16251588 else $Tuple4((i + 1), (acc._2 :+ toString((whm + am))), (acc._3 :+ toString((bpm - am))), (acc._4 + am))
16261589 else if ((-(am) > whm))
16271590 then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whm)) + " available"))
16281591 else $Tuple4((i + 1), (acc._2 :+ toString((whm + am))), (acc._3 :+ toString((bpm - am))), (acc._4 + am))
16291592 }
16301593
16311594 let m = {
16321595 let $l = matParts
16331596 let $s = size($l)
16341597 let $acc0 = $Tuple4(0, nil, nil, r._4)
16351598 func $f1_1 ($a,$i) = if (($i >= $s))
16361599 then $a
16371600 else mvM($a, $l[$i])
16381601
16391602 func $f1_2 ($a,$i) = if (($i >= $s))
16401603 then $a
16411604 else throw("List size exceeds 6")
16421605
16431606 $f1_2($f1_1($f1_1($f1_1($f1_1($f1_1($f1_1($acc0, 0), 1), 2), 3), 4), 5), 6)
16441607 }
16451608 func mvP (acc,item) = {
16461609 let i = acc._1
16471610 let am = parseIntValue(item)
16481611 let whp = if ((size(currWhProd) > i))
16491612 then parseIntValue(currWhProd[i])
16501613 else 0
16511614 let bpp = if ((size(currentPackProd) > i))
16521615 then parseIntValue(currentPackProd[i])
16531616 else 0
16541617 if ((am == 0))
16551618 then $Tuple4((i + 1), (acc._2 :+ toString(whp)), (acc._3 :+ toString(bpp)), acc._4)
16561619 else if ((am > 0))
16571620 then if ((am > bpp))
16581621 then throw((((("Attempt to take " + item) + " from backpack, but only ") + toString(bpp)) + " available"))
16591622 else {
16601623 let deltaVol = (toVolume((whp + am), PRODUCTPKGSIZE) - toVolume(whp, PRODUCTPKGSIZE))
16611624 $Tuple4((i + 1), (acc._2 :+ toString((whp + am))), (acc._3 :+ toString((bpp - am))), (acc._4 + deltaVol))
16621625 }
16631626 else if ((-(am) > whp))
16641627 then throw((((("Attempt to take " + toString(-(am))) + " from warehouse, but only ") + toString(whp)) + " available"))
16651628 else {
16661629 let deltaVol = (toVolume((whp + am), PRODUCTPKGSIZE) - toVolume(whp, PRODUCTPKGSIZE))
16671630 $Tuple4((i + 1), (acc._2 :+ toString((whp + am))), (acc._3 :+ toString((bpp - am))), (acc._4 + deltaVol))
16681631 }
16691632 }
16701633
16711634 let p = if ((size(prodParts) != 0))
16721635 then {
16731636 let $l = prodParts
16741637 let $s = size($l)
16751638 let $acc0 = $Tuple4(0, nil, nil, m._4)
16761639 func $f2_1 ($a,$i) = if (($i >= $s))
16771640 then $a
16781641 else mvP($a, $l[$i])
16791642
16801643 func $f2_2 ($a,$i) = if (($i >= $s))
16811644 then $a
16821645 else throw("List size exceeds 50")
16831646
16841647 $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)
16851648 }
16861649 else $Tuple4(0, currWhProd, currentPackProd, m._4)
16871650 let volSaldo = p._4
16881651 if ((volSaldo > whSpaceLeft))
16891652 then throw((((("Attempt to put total " + toString(volSaldo)) + " stuff, but only ") + toString(whSpaceLeft)) + " warehouse space left"))
16901653 else $Tuple7(makeString(r._2, "_"), makeString(m._2, "_"), makeString_2C(p._2, "_"), makeString(r._3, "_"), makeString(m._3, "_"), makeString_2C(p._3, "_"), volSaldo)
16911654 }
16921655 }
16931656
16941657
16951658 func expeditionInternal (caller,txId) = {
16961659 let userAddr = toString(caller)
16971660 let bigNum = abs(toBigInt(txId))
16981661 let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
16991662 let landNum = toString(freeNum)
17001663 let continentIdx = toInt((bigNum % FIVEX))
17011664 let terrains = genTerrains(bigNum, continentIdx)
17021665 let continent = continents[continentIdx]
17031666 let issue = Issue(nftName(landNum, "S"), makeString([landNum, "S", terrains, continent], "_"), 1, 0, false)
17041667 let assetId = calculateAssetId(issue)
17051668 let id = toBase58String(assetId)
17061669 $Tuple2([IntegerEntry(keyNextFreeLandNum(), (freeNum + 1)), issue, StringEntry(keyLandToAssetId(landNum), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(landNum), userAddr), IntegerEntry(keyInfraLevelByAssetId(id), 0), IntegerEntry(keyInfraLevelByAssetIdAndOwner(id, userAddr), 0), ScriptTransfer(caller, 1, assetId)], $Tuple2(id, continent))
17071670 }
17081671
17091672
17101673 func flightCommon (userAddr,message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
17111674 then throw("signature does not match")
17121675 else {
17131676 let parts = split_4C(toUtf8String(message), ";")
17141677 let flightLog = split_4C(parts[0], "|")
17151678 let hp = split(flightLog[flHealth], "_")
17161679 let curHP = parseIntValue(hp[0])
17171680 let newHP = parseIntValue(hp[1])
17181681 let newLocTxVer = split(parts[1], ":")
17191682 let newLocation = newLocTxVer[0]
17201683 let time = parseIntValue(flightLog[flTimestamp])
17211684 if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
17221685 then true
17231686 else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
17241687 then throw(((("signature outdated: logTime=" + toString(time)) + ", bcTime=") + toString(lastBlock.timestamp)))
17251688 else {
17261689 let txFromMsg = newLocTxVer[1]
17271690 let lastTx = valueOrElse(getString(keyLastTxIdByUser(userAddr)), "")
17281691 if ((lastTx != txFromMsg))
17291692 then throw(((("Tx ids don't match! In state: " + lastTx) + ", in msg: ") + txFromMsg))
17301693 else {
17311694 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked")
17321695 let keyHealth = keyDuckHealth(duckAssetId)
17331696 let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
17341697 let oldFromState = valueOrElse(getInteger(keyHealth), maxHP)
17351698 if ((oldFromState != curHP))
17361699 then throw(((("oldHealth=" + toString(oldFromState)) + " from state does not match one from flight log=") + toString(curHP)))
17371700 else if ((0 >= curHP))
17381701 then throw("You can't fly with zero health")
17391702 else if (!(canWearCurrentEquipment(duckAssetId)))
17401703 then throw("Equipment incompatible")
17411704 else {
17421705 let bonus = if ((size(flightLog) > flBonus))
17431706 then flightLog[flBonus]
17441707 else ""
17451708 let prodUsed = if ((size(flightLog) > flProdsUsed))
17461709 then flightLog[flProdsUsed]
17471710 else ""
17481711 let sentAmount = if (if ((newHP > 0))
17491712 then (bonus == "$")
17501713 else false)
17511714 then asInt(invoke(restContract, "sendUsdtPrize", [userAddr], nil))
17521715 else 0
17531716 $Tuple5(newHP, duckAssetId, sentAmount, newLocation, prodUsed)
17541717 }
17551718 }
17561719 }
17571720 }
17581721
17591722
17601723 func applyBonuses (landAssetId,pieces) = {
17611724 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
17621725 let artPieces = valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0)
17631726 let add6 = (infraLevel / 6)
17641727 let add7 = (infraLevel / 7)
17651728 ((DAILYRESBYPIECE + fraction(DAILYRESBYPIECE, ((infraLevel + add6) + (2 * add7)), 5)) + fraction(DAILYRESBYPIECE, artPieces, (pieces * 5)))
17661729 }
17671730
17681731
17691732 func checkClaimConditions (addr,claimMode,landAssetIdIn) = {
17701733 let $t03334333882 = if ((claimMode == claimModeWh))
17711734 then $Tuple2(landAssetIdIn, valueOrElse(getString(keyStakedDuckByOwner(addr)), ""))
17721735 else {
17731736 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
17741737 let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION)
17751738 let loc = split(value(curLocation), "_")
17761739 if ((loc[locIdxType] != "L"))
17771740 then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
17781741 else $Tuple2(loc[locIdxId], duckAssetId)
17791742 }
17801743 let landAssetId = $t03334333882._1
17811744 let duckId = $t03334333882._2
17821745 let asset = value(assetInfo(fromBase58String(landAssetId)))
17831746 let timeKey = keyStakedTimeByAssetId(landAssetId)
17841747 let savedTime = valueOrErrorMessage(getInteger(timeKey), (("Land " + asset.name) + " is not staked"))
17851748 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
17861749 if ((owner != addr))
17871750 then throw((LANDPREFIX + " is not yours"))
17881751 else {
17891752 let d = split(asset.description, "_")
17901753 $Tuple4(duckId, landAssetId, d, savedTime)
17911754 }
17921755 }
17931756
17941757
17951758 func claimResInternal (addr,amount,claimMode,landAssetIdIn) = if ((0 > amount))
17961759 then throw("Negative amount")
17971760 else {
17981761 let c = checkClaimConditions(addr, claimMode, landAssetIdIn)
17991762 let landSize = c._3[recLandSize]
18001763 let terrainCounts = countTerrains(c._3[recTerrains])
18011764 let deltaTime = (lastBlock.timestamp - c._4)
18021765 if ((0 > deltaTime))
18031766 then throw(((("Saved timestamp is in future, saved = " + toString(c._4)) + ", current = ") + toString(lastBlock.timestamp)))
18041767 else {
18051768 let pieces = numPiecesBySize(landSize)
18061769 let dailyProductionByPiece = applyBonuses(c._2, pieces)
18071770 let availRes = fraction(deltaTime, (dailyProductionByPiece * pieces), DAYMILLIS)
18081771 if ((amount > availRes))
18091772 then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
18101773 else {
18111774 let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (dailyProductionByPiece * pieces))
18121775 let newTimestamp = (lastBlock.timestamp - newDeltaTime)
18131776 let landIndex = (pieces / SSIZE)
18141777 let resToClaim = virtClaim(terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece)
18151778 let whKey = keyWarehouseByLand(c._2)
18161779 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(c._2)), 0)
18171780 let currentWh = getWarehouse(whKey, landIndex, infraLevel)
18181781 let loft = split(currentWh[whIdxLOFT], "_")
18191782 let whSpaceLeft = parseIntValue(loft[volFree])
18201783 if (if ((claimMode == claimModeWh))
18211784 then (amount > whSpaceLeft)
18221785 else false)
18231786 then throw((("Only " + toString(whSpaceLeft)) + " space left in warehouse"))
18241787 else {
18251788 let bpKey = keyBackpackByDuck(c._1)
18261789 let currentPack = getBackpack(bpKey)
18271790 let currentPackRes = split(currentPack[bpIdxRes], "_")
18281791 let currentWhRes = split(currentWh[whIdxRes], "_")
18291792 let $t03625637127 = if ((claimMode == claimModeWh))
18301793 then $Tuple4(addRes(currentWhRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), currentPack[bpIdxRes], (parseIntValue(loft[volOccupied]) + resToClaim._2), (parseIntValue(loft[volFree]) - resToClaim._2))
18311794 else if ((claimMode == claimModeDuck))
18321795 then $Tuple4(currentWh[whIdxRes], addRes(currentPackRes, terrainCounts, (deltaTime - newDeltaTime), landIndex, dailyProductionByPiece), parseIntValue(loft[volOccupied]), parseIntValue(loft[volFree]))
18331796 else {
18341797 let distr = distributeRes(currentWhRes, currentPackRes, resToClaim, whSpaceLeft)
18351798 let whAm = min([parseIntValue(loft[volFree]), resToClaim._2])
18361799 $Tuple4(distr._1, distr._2, (parseIntValue(loft[volOccupied]) + whAm), (parseIntValue(loft[volFree]) - whAm))
18371800 }
18381801 let whRes = $t03625637127._1
18391802 let bpRes = $t03625637127._2
18401803 let loftO = $t03625637127._3
18411804 let loftF = $t03625637127._4
18421805 $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]], "_")])
18431806 }
18441807 }
18451808 }
18461809 }
18471810
18481811
18491812 func claimAll (addr,landAssetId,pieces,claimMode) = {
18501813 let timeKey = keyStakedTimeByAssetId(landAssetId)
18511814 let savedTime = value(getInteger(timeKey))
18521815 let availRes = (fraction((lastBlock.timestamp - savedTime), applyBonuses(landAssetId, pieces), DAYMILLIS) * pieces)
18531816 claimResInternal(addr, availRes, claimMode, landAssetId)
18541817 }
18551818
18561819
18571820 func upInfraCommon (shouldUseMat,caller,paymentAmount,landAssetId) = {
18581821 let addr = toString(caller)
18591822 let c = checkClaimConditions(addr, claimModeWhThenDuck, landAssetId)
18601823 let pieces = numPiecesBySize(c._3[recLandSize])
18611824 let infraKey = keyInfraLevelByAssetId(c._2)
18621825 let curLevel = valueOrElse(getInteger(infraKey), 0)
18631826 if (if (!(KS_ALLOW_BIG_INFRA_MERGE))
18641827 then (curLevel >= 3)
18651828 else false)
18661829 then throw("Currently max infrastructure level = 3")
18671830 else {
18681831 let maxInfra = ((sqrt(pieces, 0, 0, DOWN) / 5) + 2)
18691832 let newLevel = (curLevel + 1)
18701833 if (if (KS_ALLOW_BIG_INFRA_MERGE)
18711834 then (newLevel > maxInfra)
18721835 else false)
18731836 then throw(("Currently max infrastructure level = " + toString(maxInfra)))
18741837 else {
18751838 let cost = fraction(InfraUpgradeCostSUsdt, (pieces * newLevel), SSIZE)
18761839 if (if (!(shouldUseMat))
18771840 then (paymentAmount != cost)
18781841 else false)
18791842 then throw(("Payment attached should be " + toString(cost)))
18801843 else {
18811844 let bpKey = keyBackpackByDuck(c._1)
18821845 let currentPack = getBackpack(bpKey)
18831846 let mList = split(currentPack[bpIdxMat], "_")
18841847 let matUsed = fraction(InfraUpgradeCostS, (pieces * newLevel), SSIZE)
18851848 let newMat = makeString(subtractMaterials(shouldUseMat, mList, matUsed), "_")
18861849 let claimResult = claimAll(addr, c._2, pieces, claimModeWhThenDuck)
18871850 let whData = claimResult._5
18881851 let oldVol = getWarehouseTotalVolume(whData[whIdxLevels])
18891852 let newVolData = makeString([split(whData[whIdxLevels], "_")[0], toString(newLevel)], "_")
18901853 let newVol = getWarehouseTotalVolume(newVolData)
18911854 let loft = split(whData[whIdxLOFT], "_")
18921855 let newLoftStr = makeString([loft[volLocked], loft[volOccupied], toString(((parseIntValue(loft[volFree]) + newVol) - oldVol)), toString(newVol)], "_")
18931856 $Tuple3(([IntegerEntry(infraKey, newLevel), IntegerEntry(keyInfraLevelByAssetIdAndOwner(c._2, addr), newLevel), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], claimResult._3[bpIdxRes], newMat, currentPack[bpIdxProd]], ":")), StringEntry(claimResult._4, makeString([newVolData, whData[whIdxRes], whData[whIdxMat], whData[whIdxProd], newLoftStr], ":"))] ++ claimResult._1), newLevel, matUsed)
18941857 }
18951858 }
18961859 }
18971860 }
18981861
18991862
19001863 func updateStatsInternal (lvlKey,xpKey,pointsKey,deltaXP) = {
19011864 let xp = valueOrElse(getInteger(xpKey), 0)
19021865 let newXP = (xp + deltaXP)
19031866 let lvlPoints = levelUp(valueOrElse(getInteger(lvlKey), 0), newXP)
19041867 $Tuple2([IntegerEntry(lvlKey, lvlPoints[0]), IntegerEntry(xpKey, newXP), IntegerEntry(pointsKey, (valueOrElse(getInteger(pointsKey), 0) + lvlPoints[1]))], newXP)
19051868 }
19061869
19071870
19081871 func updateDuckStatsInternal (duckAssetId,deltaXP) = {
19091872 let asset = value(assetInfo(fromBase58String(duckAssetId)))
19101873 let addr = valueOrErrorMessage(getString(keyDuckIdToOwner(duckAssetId)), (("NFT " + asset.name) + " is orphaned"))
19111874 if (if (if (KS_ALLOW_ROBO_DUCKS)
19121875 then (asset.issuer == this)
19131876 else false)
19141877 then contains(asset.name, ROBO_PREFIX)
19151878 else false)
19161879 then updateStatsInternal(keyUserLevel(addr), keyUserXP(addr), keyUserFreePoints(addr), deltaXP)
19171880 else updateStatsInternal(keyDuckLevel(duckAssetId), keyDuckXP(duckAssetId), keyDuckFreePoints(duckAssetId), deltaXP)
19181881 }
19191882
19201883
19211884 func updateAccStatsInternal (addr,deltaXP) = updateStatsInternal(keyUserLevel(addr), keyUserXP(addr), keyUserFreePoints(addr), deltaXP)
19221885
19231886
19241887 func activateOnboardArt (addr) = {
19251888 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
19261889 let refByKey = keyAddressRefBy(addr)
19271890 let refBy = getString(refByKey)
19281891 if (!(isDefined(refBy)))
19291892 then throw("You are not eligible for ONBOARD artifact")
19301893 else {
19311894 let artKey = keyOnboardArtDuckActivatedBy(addr)
19321895 let artDuck = getString(artKey)
19331896 if (isDefined(artDuck))
19341897 then throw(("You already used your ONBOARD artifact on duck " + value(artDuck)))
19351898 else {
19361899 let duckActivatorKey = keyOnboardArtActivatedOnDuck(duckAssetId)
19371900 let duckActivator = getString(duckActivatorKey)
19381901 if (isDefined(duckActivator))
19391902 then throw(((("The duck " + duckAssetId) + " already got points from ONBOARD artifact from user ") + value(duckActivator)))
19401903 else ([StringEntry(artKey, duckAssetId), StringEntry(duckActivatorKey, addr)] ++ updateDuckStatsInternal(duckAssetId, xpOnboard)._1)
19411904 }
19421905 }
19431906 }
19441907
19451908
19461909 func activatePresaleArt (addr,landAssetIdIn) = {
19471910 let c = checkClaimConditions(addr, claimModeWhThenDuck, landAssetIdIn)
19481911 let landAssetId = c._2
19491912 let pieces = numPiecesBySize(c._3[recLandSize])
19501913 let activationKey = keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)
19511914 if ((valueOrElse(getInteger(activationKey), 0) > 0))
19521915 then throw("Presale artifact is already activated")
19531916 else if ((parseIntValue(c._3[recLandNum]) > PRESALENUMLANDS))
19541917 then throw((((LANDPREFIX + " ") + landAssetId) + " is not eligible for presale artifact"))
19551918 else {
19561919 let claimResult = claimAll(addr, landAssetId, pieces, claimModeWhThenDuck)
19571920 (((claimResult._1 :+ IntegerEntry(activationKey, pieces)) :+ StringEntry(claimResult._2, makeString(claimResult._3, ":"))) :+ StringEntry(claimResult._4, makeString(claimResult._5, ":")))
19581921 }
19591922 }
19601923
19611924
19621925 func checkTournament (duckAssetId) = {
19631926 let lastId = valueOrElse(getInteger(tournamentContract, lastTourIdKey), 0)
19641927 let curLocation = split(valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_")
19651928 let now = lastBlock.timestamp
19661929 let tData = getTourData(tournamentContract, lastId)
19671930 let static = tData[idxStatic]
19681931 let dynamic = tData[idxDynamic]
19691932 if ((curLocation[locIdxType] != "T"))
19701933 then false
19711934 else if (if (if ((parseIntValue(curLocation[locIdxContinent]) == lastId))
19721935 then (dynamic[tDynamicStatus] == "INPROGRESS")
19731936 else false)
19741937 then (parseIntValue(static[tStaticEnd]) > now)
19751938 else false)
19761939 then throw("Your duck is taking part in the tournament")
19771940 else asBoolean(invoke(this, "exitTournamentInternal", [duckAssetId], nil))
19781941 }
19791942
19801943
1981-func checkDelivery (duckAssetId) = {
1982- let curLocation = split(valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_")
1983- let now = lastBlock.timestamp
1984- if ((curLocation[locIdxType] != "D"))
1985- then false
1986- else {
1987- let startTime = parseIntValue(curLocation[locIdxContinent])
1988- let distance = parseIntValue(curLocation[locIdxId])
1989- if (if (((startTime + TEN_MINUTES_MILLIS) > now))
1990- then (1 > distance)
1991- else false)
1992- then throw("Your duck is on delivery mission")
1993- else asBoolean(invoke(this, "exitDeliveryInternal", [duckAssetId], nil))
1994- }
1995- }
1996-
1997-
1998-func exitDeliveryCommon (duckAssetId,check,newHP,score) = {
1999- let curLocation = split(valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION), "_")
2000- let now = lastBlock.timestamp
2001- let startTime = parseIntValue(curLocation[locIdxContinent])
2002- let distance = parseIntValue(curLocation[locIdxId])
2003- let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(duckAssetId)), "NFT duck is orphaned")
2004- let healthKey = keyDuckHealth(duckAssetId)
2005- let curHealth = getIntegerValue(healthKey)
2006- let outcomeActions = if (if ((distance > 0))
2007- then true
2008- else if (if (check)
2009- then (score > 0)
2010- else false)
2011- then (newHP > 0)
2012- else false)
2013- then {
2014- let reward = invoke(economyContract, "sendDeliveryReward", [owner], nil)
2015- if ((reward == reward))
2016- then {
2017- let countKey = keyUserDeliveryCount(owner)
2018-[IntegerEntry(countKey, (valueOrElse(getInteger(countKey), 0) + 1)), IntegerEntry(keyUserLastDeliveryDay(owner), (startTime / DAYMILLIS))]
2019- }
2020- else throw("Strict value is not equal to itself.")
2021- }
2022- else if (if (if (check)
2023- then (newHP > 0)
2024- else false)
2025- then ((startTime + TEN_MINUTES_MILLIS) > now)
2026- else false)
2027- then throw("Your duck is still on delivery mission")
2028- else {
2029- let lockedTotal = valueOrElse(getInteger(economyContract, deliveryLockedKey), 0)
2030- let unlock = invoke(economyContract, "updateDeliveryLocked", [(lockedTotal - MIN_USDT_FEE_DELIVERY)], nil)
2031- if ((unlock == unlock))
2032- then if (if (if (check)
2033- then (0 >= newHP)
2034- else false)
2035- then true
2036- else (0 >= curHealth))
2037- then nil
2038- else [IntegerEntry(keyDeliveryDelayByDuck(duckAssetId), (startTime + DELIVERY_PUNISHMENT))]
2039- else throw("Strict value is not equal to itself.")
2040- }
2041- let savedLocation = getStringValue(keySavedLocation(duckAssetId))
2042- $Tuple3(outcomeActions, [StringEntry(keyDuckLocation(duckAssetId), savedLocation)], savedLocation)
2043- }
2044-
2045-
20461944 func mergeInternal (newLandSize,newLevel,formula,addr,landAssetIds,needMat) = {
20471945 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
20481946 if (checkTournament(duckAssetId))
20491947 then throw("mergeInternal_checkTournament")
2050- else if (checkDelivery(duckAssetId))
2051- then throw("mergeInternal_checkDelivery")
2052- else {
2053- func checkMerge (acc,landAssetId) = {
2054- let asset = value(assetInfo(fromBase58String(landAssetId)))
2055- let timeKey = keyStakedTimeByAssetId(landAssetId)
2056- let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
2057- let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
2058- if ((owner != addr))
2059- then throw((LANDPREFIX + " is not yours"))
2060- else {
2061- let d = split(asset.description, "_")
2062- let continent = d[recContinent]
2063- if (if ((acc._3 != ""))
2064- then (acc._3 != continent)
2065- else false)
2066- then throw("Lands should be on the same continent to merge")
2067- else {
2068- let landSize = d[recLandSize]
2069- let sizesIn = acc._1
2070- let i = valueOrErrorMessage(indexOf(sizesIn, landSize), "You haven't passed all the lands needed")
2071- let sizesOut = (take(sizesIn, i) + drop(sizesIn, (i + 1)))
2072- let pieces = numPiecesBySize(landSize)
2073- let arts = (acc._2 + valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0))
2074- let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
2075- let reqLevel = match landSize {
2076- case _ =>
2077- if (("S" == $match0))
2078- then 3
2079- else if (("M" == $match0))
2080- then 4
2081- else if (("L" == $match0))
2082- then 5
2083- else if (("XL" == $match0))
2084- then 6
2085- else throw("Only S, M, L, XL can merge")
2086- }
2087- if ((infraLevel != reqLevel))
2088- then throw("All lands should be maxed to merge")
2089- else {
2090- let landNum = d[recLandNum]
2091- let terrainCounts = countTerrains(d[recTerrains])
2092- let deltaTime = (lastBlock.timestamp - savedTime)
2093- if ((0 > deltaTime))
2094- then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
2095- else {
2096- let dailyProductionByPiece = applyBonuses(landAssetId, pieces)
2097- let landIndex = (pieces / SSIZE)
2098- let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, landIndex, dailyProductionByPiece)
2099- let props = updateProportionsInternal(acc._6, terrainCounts, landIndex, -1)
2100- let cProps = updateProportionsInternal(acc._10, terrainCounts, landIndex, -1)
2101- let sumTerrains = updateProportionsInternal(acc._9, terrainCounts, landIndex, 1)
2102- let lands = acc._7
2103- let idx = indexOf(lands, landAssetId)
2104- if (!(isDefined(idx)))
2105- then throw(("Your staked lands don't contain " + landAssetId))
2106- else {
2107- let customKey = keyLandAssetIdToCustomName(landAssetId)
2108- let customName = valueOrElse(getString(customKey), "")
2109- $Tuple10(sizesOut, arts, continent, bpRes, ((((((((((((acc._5 :+ DeleteEntry(keyStakedTimeByAssetId(landAssetId))) :+ DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr))) :+ DeleteEntry(keyLandToAssetId(landNum))) :+ DeleteEntry(keyLandAssetIdToOwner(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetId(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, addr))) :+ DeleteEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId))) :+ DeleteEntry(keyLandNumToOwner(landNum))) :+ DeleteEntry(keyWarehouseByLand(landAssetId))) :+ DeleteEntry(customKey)) :+ Burn(fromBase58String(landAssetId), 1)) ++ (if ((customName != ""))
2110- then [DeleteEntry(keyLandCustomNameToAssetId(customName))]
2111- else nil)), props, removeByIndex(lands, value(idx)), (acc._8 + pieces), sumTerrains, cProps)
2112- }
2113- }
2114- }
2115- }
2116- }
2117- }
2118-
2119- let bpKey = keyBackpackByDuck(duckAssetId)
2120- let currentPack = getBackpack(bpKey)
2121- let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
2122- let landsKey = keyStakedLandsByOwner(addr)
2123- let landsStr = getString(landsKey)
2124- let landsIn = if (isDefined(landsStr))
2125- then split_51C(value(landsStr), "_")
2126- else nil
2127- let cont0 = split(value(assetInfo(fromBase58String(landAssetIds[0]))).description, "_")[recContinent]
2128- let contProps = split(valueOrElse(getString(keyResTypesByContinent(cont0)), "0_0_0_0_0_0"), "_")
2129- let r = {
2130- let $l = landAssetIds
2131- let $s = size($l)
2132- let $acc0 = $Tuple10(formula, 0, "", currentPack[bpIdxRes], nil, propList, landsIn, 0, split("0_0_0_0_0_0", "_"), contProps)
2133- func $f0_1 ($a,$i) = if (($i >= $s))
2134- then $a
2135- else checkMerge($a, $l[$i])
2136-
2137- func $f0_2 ($a,$i) = if (($i >= $s))
2138- then $a
2139- else throw("List size exceeds 5")
2140-
2141- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
2142- }
2143- let continent = r._3
2144- let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent))
2145- let terrains = genTerrainsForMerge(r._9, (numPiecesBySize(newLandSize) / SSIZE))
2146- let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
2147- let newLandNum = toString(freeNum)
2148- let issue = Issue(nftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false)
2149- let assetId = calculateAssetId(issue)
2150- let newLandAssetId = toBase58String(assetId)
2151- let newMat = makeString(subtractMaterials((needMat > 0), split(currentPack[bpIdxMat], "_"), needMat), "_")
2152- let piecesKey = keyStakedPiecesByOwner(addr)
2153- let stakedPieces = valueOrElse(getInteger(piecesKey), 0)
2154- $Tuple2((((((((((((((((r._5 :+ (if ((size(r._7) > 0))
2155- then StringEntry(landsKey, makeString_11C(r._7, "_"))
2156- else DeleteEntry(landsKey))) :+ IntegerEntry(piecesKey, if ((r._8 > stakedPieces))
2157- then 0
2158- else (stakedPieces - r._8))) :+ IntegerEntry(keyNextFreeLandNum(), (freeNum + 1))) :+ issue) :+ StringEntry(keyLandToAssetId(newLandNum), newLandAssetId)) :+ StringEntry(keyLandAssetIdToOwner(newLandAssetId), addr)) :+ StringEntry(keyLandNumToOwner(newLandNum), addr)) :+ IntegerEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, newLandAssetId), r._2)) :+ IntegerEntry(keyInfraLevelByAssetId(newLandAssetId), newLevel)) :+ IntegerEntry(keyInfraLevelByAssetIdAndOwner(newLandAssetId, addr), newLevel)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], r._4, newMat, currentPack[bpIdxProd]], ":"))) :+ StringEntry(keyResProportions(), makeString(r._6, "_"))) :+ StringEntry(keyResTypesByContinent(continent), makeString(r._10, "_"))) :+ StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", newLandAssetId], "_"))) :+ ScriptTransfer(addressFromStringValue(addr), 1, assetId)), newLandAssetId)
1948+ else {
1949+ func checkMerge (acc,landAssetId) = {
1950+ let asset = value(assetInfo(fromBase58String(landAssetId)))
1951+ let timeKey = keyStakedTimeByAssetId(landAssetId)
1952+ let savedTime = valueOrErrorMessage(getInteger(timeKey), (("NFT " + asset.name) + " is not staked"))
1953+ let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
1954+ if ((owner != addr))
1955+ then throw((LANDPREFIX + " is not yours"))
1956+ else {
1957+ let d = split(asset.description, "_")
1958+ let continent = d[recContinent]
1959+ if (if ((acc._3 != ""))
1960+ then (acc._3 != continent)
1961+ else false)
1962+ then throw("Lands should be on the same continent to merge")
1963+ else {
1964+ let landSize = d[recLandSize]
1965+ let sizesIn = acc._1
1966+ let i = valueOrErrorMessage(indexOf(sizesIn, landSize), "You haven't passed all the lands needed")
1967+ let sizesOut = (take(sizesIn, i) + drop(sizesIn, (i + 1)))
1968+ let pieces = numPiecesBySize(landSize)
1969+ let arts = (acc._2 + valueOrElse(getInteger(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId)), 0))
1970+ let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
1971+ let reqLevel = match landSize {
1972+ case _ =>
1973+ if (("S" == $match0))
1974+ then 3
1975+ else if (("M" == $match0))
1976+ then 4
1977+ else if (("L" == $match0))
1978+ then 5
1979+ else if (("XL" == $match0))
1980+ then 6
1981+ else throw("Only S, M, L, XL can merge")
1982+ }
1983+ if ((infraLevel != reqLevel))
1984+ then throw("All lands should be maxed to merge")
1985+ else {
1986+ let landNum = d[recLandNum]
1987+ let terrainCounts = countTerrains(d[recTerrains])
1988+ let deltaTime = (lastBlock.timestamp - savedTime)
1989+ if ((0 > deltaTime))
1990+ then throw(((("Saved timestamp is in future, saved = " + toString(savedTime)) + ", current = ") + toString(lastBlock.timestamp)))
1991+ else {
1992+ let dailyProductionByPiece = applyBonuses(landAssetId, pieces)
1993+ let landIndex = (pieces / SSIZE)
1994+ let bpRes = addRes(split(acc._4, "_"), terrainCounts, deltaTime, landIndex, dailyProductionByPiece)
1995+ let props = updateProportionsInternal(acc._6, terrainCounts, landIndex, -1)
1996+ let cProps = updateProportionsInternal(acc._10, terrainCounts, landIndex, -1)
1997+ let sumTerrains = updateProportionsInternal(acc._9, terrainCounts, landIndex, 1)
1998+ let lands = acc._7
1999+ let idx = indexOf(lands, landAssetId)
2000+ if (!(isDefined(idx)))
2001+ then throw(("Your staked lands don't contain " + landAssetId))
2002+ else {
2003+ let customKey = keyLandAssetIdToCustomName(landAssetId)
2004+ let customName = valueOrElse(getString(customKey), "")
2005+ $Tuple10(sizesOut, arts, continent, bpRes, ((((((((((((acc._5 :+ DeleteEntry(keyStakedTimeByAssetId(landAssetId))) :+ DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, addr))) :+ DeleteEntry(keyLandToAssetId(landNum))) :+ DeleteEntry(keyLandAssetIdToOwner(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetId(landAssetId))) :+ DeleteEntry(keyInfraLevelByAssetIdAndOwner(landAssetId, addr))) :+ DeleteEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, landAssetId))) :+ DeleteEntry(keyLandNumToOwner(landNum))) :+ DeleteEntry(keyWarehouseByLand(landAssetId))) :+ DeleteEntry(customKey)) :+ Burn(fromBase58String(landAssetId), 1)) ++ (if ((customName != ""))
2006+ then [DeleteEntry(keyLandCustomNameToAssetId(customName))]
2007+ else nil)), props, removeByIndex(lands, value(idx)), (acc._8 + pieces), sumTerrains, cProps)
2008+ }
2009+ }
2010+ }
2011+ }
2012+ }
21592013 }
2014+
2015+ let bpKey = keyBackpackByDuck(duckAssetId)
2016+ let currentPack = getBackpack(bpKey)
2017+ let propList = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
2018+ let landsKey = keyStakedLandsByOwner(addr)
2019+ let landsStr = getString(landsKey)
2020+ let landsIn = if (isDefined(landsStr))
2021+ then split_51C(value(landsStr), "_")
2022+ else nil
2023+ let cont0 = split(value(assetInfo(fromBase58String(landAssetIds[0]))).description, "_")[recContinent]
2024+ let contProps = split(valueOrElse(getString(keyResTypesByContinent(cont0)), "0_0_0_0_0_0"), "_")
2025+ let r = {
2026+ let $l = landAssetIds
2027+ let $s = size($l)
2028+ let $acc0 = $Tuple10(formula, 0, "", currentPack[bpIdxRes], nil, propList, landsIn, 0, split("0_0_0_0_0_0", "_"), contProps)
2029+ func $f0_1 ($a,$i) = if (($i >= $s))
2030+ then $a
2031+ else checkMerge($a, $l[$i])
2032+
2033+ func $f0_2 ($a,$i) = if (($i >= $s))
2034+ then $a
2035+ else throw("List size exceeds 5")
2036+
2037+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
2038+ }
2039+ let continent = r._3
2040+ let continentIdx = valueOrErrorMessage(indexOf(continents, continent), ("Unknown continent: " + continent))
2041+ let terrains = genTerrainsForMerge(r._9, (numPiecesBySize(newLandSize) / SSIZE))
2042+ let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), (PRESALENUMLANDS + 1))
2043+ let newLandNum = toString(freeNum)
2044+ let issue = Issue(nftName(newLandNum, newLandSize), makeString([newLandNum, newLandSize, terrains, continent], "_"), 1, 0, false)
2045+ let assetId = calculateAssetId(issue)
2046+ let newLandAssetId = toBase58String(assetId)
2047+ let newMat = makeString(subtractMaterials((needMat > 0), split(currentPack[bpIdxMat], "_"), needMat), "_")
2048+ let piecesKey = keyStakedPiecesByOwner(addr)
2049+ let stakedPieces = valueOrElse(getInteger(piecesKey), 0)
2050+ $Tuple2((((((((((((((((r._5 :+ (if ((size(r._7) > 0))
2051+ then StringEntry(landsKey, makeString_11C(r._7, "_"))
2052+ else DeleteEntry(landsKey))) :+ IntegerEntry(piecesKey, if ((r._8 > stakedPieces))
2053+ then 0
2054+ else (stakedPieces - r._8))) :+ IntegerEntry(keyNextFreeLandNum(), (freeNum + 1))) :+ issue) :+ StringEntry(keyLandToAssetId(newLandNum), newLandAssetId)) :+ StringEntry(keyLandAssetIdToOwner(newLandAssetId), addr)) :+ StringEntry(keyLandNumToOwner(newLandNum), addr)) :+ IntegerEntry(keyLandArtStatusByTypeAndAssetId(ARTPRESALE, newLandAssetId), r._2)) :+ IntegerEntry(keyInfraLevelByAssetId(newLandAssetId), newLevel)) :+ IntegerEntry(keyInfraLevelByAssetIdAndOwner(newLandAssetId, addr), newLevel)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], r._4, newMat, currentPack[bpIdxProd]], ":"))) :+ StringEntry(keyResProportions(), makeString(r._6, "_"))) :+ StringEntry(keyResTypesByContinent(continent), makeString(r._10, "_"))) :+ StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", newLandAssetId], "_"))) :+ ScriptTransfer(addressFromStringValue(addr), 1, assetId)), newLandAssetId)
2055+ }
21602056 }
21612057
21622058
21632059 func s2m (addr,landAssetIds) = mergeInternal("M", 3, "SSSS", addr, landAssetIds, 0)
21642060
21652061
21662062 func m2l (addr,landAssetIds) = mergeInternal("L", 4, "SMM", addr, landAssetIds, (InfraUpgradeCostS * 4))
21672063
21682064
21692065 func l2xl (addr,landAssetIds) = mergeInternal("XL", 5, "SSSML", addr, landAssetIds, (InfraUpgradeCostS * 47))
21702066
21712067
21722068 func xl2xxl (addr,landAssetIds) = mergeInternal("XXL", 6, "LXL", addr, landAssetIds, (InfraUpgradeCostS * 54))
21732069
21742070
21752071 func mergeCommon (addr,landAssetIds) = match size(landAssetIds) {
21762072 case _ =>
21772073 if ((4 == $match0))
21782074 then s2m(addr, landAssetIds)
21792075 else if ((3 == $match0))
21802076 then m2l(addr, landAssetIds)
21812077 else if ((5 == $match0))
21822078 then l2xl(addr, landAssetIds)
21832079 else if ((2 == $match0))
21842080 then xl2xxl(addr, landAssetIds)
21852081 else throw("Unknown merge")
21862082 }
21872083
21882084
2189-func checkOutdatedDelivery (userAddr) = {
2190- let duck = getString(keyStakedDuckByOwner(userAddr))
2191- if (isDefined(duck))
2192- then {
2193- let duckAssetId = value(duck)
2194- let locKey = keyDuckLocation(duckAssetId)
2195- let loc = split(valueOrElse(getString(locKey), DEFAULTLOCATION), "_")
2196- let startTime = parseIntValue(loc[locIdxContinent])
2197- if (if ((loc[locIdxType] != "D"))
2198- then true
2199- else ((startTime + TEN_MINUTES_MILLIS) > lastBlock.timestamp))
2200- then nil
2201- else {
2202- let healthKey = keyDuckHealth(duckAssetId)
2203- if ((parseIntValue(loc[locIdxId]) > 0))
2204- then {
2205- let reward = invoke(economyContract, "sendDeliveryReward", [userAddr], nil)
2206- if ((reward == reward))
2207- then nil
2208- else throw("Strict value is not equal to itself.")
2209- }
2210- else ({
2211- let lockedTotal = valueOrElse(getInteger(economyContract, deliveryLockedKey), 0)
2212- let unlock = invoke(economyContract, "updateDeliveryLocked", [(lockedTotal - MIN_USDT_FEE_DELIVERY)], nil)
2213- if ((unlock == unlock))
2214- then if ((0 >= getIntegerValue(healthKey)))
2215- then nil
2216- else {
2217- let punishment = invoke(this, "saveInteger", [keyDeliveryDelayByDuck(duckAssetId), (startTime + DELIVERY_PUNISHMENT)], nil)
2218- if ((punishment == punishment))
2219- then nil
2220- else throw("Strict value is not equal to itself.")
2221- }
2222- else throw("Strict value is not equal to itself.")
2223- } :+ StringEntry(locKey, getStringValue(keySavedLocation(duckAssetId))))
2224- }
2225- }
2226- else nil
2227- }
2228-
2229-
22302085 func prolog (i) = if (if ((i.originCaller != restContract))
2231- then valueOrElse(getBoolean(keyBlocked()), false)
2232- else false)
2233- then throw("Contracts are under maintenance")
2234- else {
2235- let userAddr = toString(i.originCaller)
2236- (checkOutdatedDelivery(userAddr) :+ StringEntry(keyLastTxIdByUser(userAddr), toBase58String(i.transactionId)))
2237- }
2238-
2239-
2240-func prologFlight (i) = if (if ((i.originCaller != restContract))
22412086 then valueOrElse(getBoolean(keyBlocked()), false)
22422087 else false)
22432088 then throw("Contracts are under maintenance")
22442089 else [StringEntry(keyLastTxIdByUser(toString(i.originCaller)), toBase58String(i.transactionId))]
22452090
22462091
22472092 @Callable(i)
22482093 func constructorV1 (restAddr) = if ((i.caller != this))
22492094 then throw("Permission denied")
22502095 else [StringEntry(keyRestAddress(), restAddr)]
22512096
22522097
22532098
22542099 @Callable(i)
22552100 func saveInteger (key,amount) = if ((i.caller != this))
22562101 then throw("saveInteger is not public method")
22572102 else [IntegerEntry(key, amount)]
22582103
22592104
22602105
22612106 @Callable(i)
22622107 func setBlocked (isBlocked) = if ((i.caller != this))
22632108 then throw("permission denied")
22642109 else [BooleanEntry(keyBlocked(), isBlocked)]
22652110
22662111
22672112
22682113 @Callable(i)
22692114 func stakeLand () = {
22702115 let prologActions = prolog(i)
22712116 if ((size(i.payments) != 1))
22722117 then throw("Exactly one payment required")
22732118 else {
22742119 let pmt = value(i.payments[0])
22752120 let assetId = value(pmt.assetId)
22762121 let address = toString(i.caller)
22772122 if ((pmt.amount != 1))
22782123 then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
22792124 else {
22802125 let asset = value(assetInfo(assetId))
22812126 if ((asset.issuer != this))
22822127 then throw("Unknown issuer of token")
22832128 else if (!(contains(asset.name, LANDPREFIX)))
22842129 then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
22852130 else {
22862131 let landNumSize = drop(asset.name, 4)
22872132 let landNum = if (contains(landNumSize, "XXL"))
22882133 then dropRight(landNumSize, 3)
22892134 else if (contains(landNumSize, "XL"))
22902135 then dropRight(landNumSize, 2)
22912136 else dropRight(landNumSize, 1)
22922137 if (!(isDefined(parseInt(landNum))))
22932138 then throw(("Cannot parse land number from " + asset.name))
22942139 else {
22952140 let landAssetId = toBase58String(assetId)
22962141 let timeKey = keyStakedTimeByAssetId(landAssetId)
22972142 if (isDefined(getInteger(timeKey)))
22982143 then throw((("NFT " + asset.name) + " is already staked"))
22992144 else {
23002145 let d = split(asset.description, "_")
23012146 let terrainCounts = countTerrains(d[recTerrains])
23022147 let pieces = numPiecesBySize(d[recLandSize])
23032148 let landIndex = (pieces / SSIZE)
23042149 let props = updateProportions(terrainCounts, landIndex, 1)
23052150 let resByContKey = keyResTypesByContinent(d[recContinent])
23062151 let contProps = split(valueOrElse(getString(resByContKey), "0_0_0_0_0_0"), "_")
23072152 let updatedContProps = makeString(updateProportionsInternal(contProps, terrainCounts, landIndex, 1), "_")
23082153 let landsKey = keyStakedLandsByOwner(address)
23092154 let landsStr = getString(landsKey)
23102155 let lands = if (isDefined(landsStr))
23112156 then split_51C(value(landsStr), "_")
23122157 else nil
23132158 if (containsElement(lands, landAssetId))
23142159 then throw(("Your staked lands already contain " + landAssetId))
23152160 else if ((size(lands) >= MAX_LANDS_STAKED_BY_USER))
23162161 then throw((("Your already staked max (" + toString(MAX_LANDS_STAKED_BY_USER)) + ") lands"))
23172162 else {
23182163 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
23192164 let piecesKey = keyStakedPiecesByOwner(address)
23202165 let oldPieces = valueOrElse(getInteger(piecesKey), 0)
23212166 let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [address], nil)
23222167 $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)
23232168 }
23242169 }
23252170 }
23262171 }
23272172 }
23282173 }
23292174 }
23302175
23312176
23322177
23332178 @Callable(i)
23342179 func unstakeLand (landAssetIdIn) = {
23352180 let prologActions = prolog(i)
23362181 if ((size(i.payments) != 0))
23372182 then throw("No payments required")
23382183 else {
23392184 let addr = toString(i.caller)
23402185 let c = checkClaimConditions(addr, claimModeDuck, landAssetIdIn)
23412186 let landAssetId = c._2
23422187 let d = c._3
23432188 let landsKey = keyStakedLandsByOwner(addr)
23442189 let terrainCounts = countTerrains(d[recTerrains])
23452190 let pieces = numPiecesBySize(d[recLandSize])
23462191 let landIndex = (pieces / SSIZE)
23472192 let props = updateProportions(terrainCounts, landIndex, -1)
23482193 let resByContKey = keyResTypesByContinent(d[recContinent])
23492194 let contProps = split(valueOrElse(getString(resByContKey), "0_0_0_0_0_0"), "_")
23502195 let updatedContProps = makeString(updateProportionsInternal(contProps, terrainCounts, landIndex, -1), "_")
23512196 let claimResult = claimAll(addr, landAssetId, pieces, claimModeDuck)
23522197 let lands = split_51C(valueOrElse(getString(landsKey), ""), "_")
23532198 let idx = indexOf(lands, landAssetId)
23542199 if (!(isDefined(idx)))
23552200 then throw(("Your staked lands don't contain " + landAssetId))
23562201 else {
23572202 let now = lastBlock.timestamp
23582203 let govReleaseTime = valueOrElse(getInteger(govContract, keyUserGwlReleaseTime(addr)), 0)
23592204 if ((govReleaseTime >= now))
23602205 then throw(("Your gWL are taking part in voting, cannot unstake until " + toString(govReleaseTime)))
23612206 else {
23622207 let arbReleaseTime = (valueOrElse(getInteger(wlgContract, keyLastArbTimeByUser(addr)), 0) + arbitrageDelay)
23632208 if ((arbReleaseTime > now))
23642209 then throw(("Your staked lands took part in arbitrage, cannot unstake until " + toString(arbReleaseTime)))
23652210 else {
23662211 let piecesKey = keyStakedPiecesByOwner(addr)
23672212 let stakedPieces = valueOrElse(getInteger(piecesKey), 0)
23682213 let newPieces = if ((pieces > stakedPieces))
23692214 then 0
23702215 else (stakedPieces - pieces)
23712216 let wlgResult = invoke(wlgContract, "onStakeUnstakeLand", [addr], nil)
23722217 $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))
23732218 then StringEntry(landsKey, makeString_11C(removeByIndex(lands, value(idx)), "_"))
23742219 else DeleteEntry(landsKey), IntegerEntry(piecesKey, newPieces)] ++ prologActions), wlgResult)
23752220 }
23762221 }
23772222 }
23782223 }
23792224 }
23802225
23812226
23822227
23832228 @Callable(i)
23842229 func stakeDuck () = {
23852230 let prologActions = prolog(i)
23862231 if ((size(i.payments) != 1))
23872232 then throw("Exactly one payment required")
23882233 else {
23892234 let pmt = value(i.payments[0])
23902235 let assetId = value(pmt.assetId)
23912236 let address = toString(i.caller)
23922237 if ((pmt.amount != 1))
23932238 then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
23942239 else {
23952240 let asset = value(assetInfo(assetId))
23962241 let isRobo = if (if (KS_ALLOW_ROBO_DUCKS)
23972242 then (asset.issuer == this)
23982243 else false)
23992244 then contains(asset.name, ROBO_PREFIX)
24002245 else false
24012246 if (if (if ((asset.issuer != incubatorAddr))
24022247 then (asset.issuer != breederAddr)
24032248 else false)
24042249 then !(isRobo)
24052250 else false)
24062251 then throw((((("Unknown issuer of " + DUCKPREFIX) + " or ") + ROBO_PREFIX) + " token"))
24072252 else if (if (!(contains(asset.name, DUCKPREFIX)))
24082253 then !(isRobo)
24092254 else false)
24102255 then throw((((("Only NFT " + DUCKPREFIX) + " or ") + ROBO_PREFIX) + " tokens are accepted"))
24112256 else {
24122257 let assetIdStr = toBase58String(assetId)
24132258 let timeKey = keyStakedTimeByAssetId(assetIdStr)
24142259 if (isDefined(getInteger(timeKey)))
24152260 then throw((("NFT " + asset.name) + " is already staked"))
24162261 else if (isDefined(getString(keyStakedDuckByOwner(address))))
24172262 then throw(("You already staked one duck: " + asset.name))
24182263 else {
24192264 let locKey = keyDuckLocation(assetIdStr)
24202265 let location = getString(locKey)
24212266 let bpKey = keyBackpackByDuck(assetIdStr)
24222267 let backpack = getString(bpKey)
24232268 let keyHealth = keyDuckHealth(assetIdStr)
24242269 let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(assetIdStr)), 0))
24252270 let curHealth = valueOrElse(getInteger(keyHealth), maxHP)
24262271 ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
24272272 then nil
24282273 else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(backpack))
24292274 then nil
24302275 else (([StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")] :+ IntegerEntry(keyHealth, curHealth)) ++ prologActions)))))
24312276 }
24322277 }
24332278 }
24342279 }
24352280 }
24362281
24372282
24382283
24392284 @Callable(i)
24402285 func unstakeDuck (assetIdStr) = {
24412286 let prologActions = prolog(i)
24422287 if ((size(i.payments) != 0))
24432288 then throw("No payments required")
24442289 else {
24452290 let assetId = fromBase58String(assetIdStr)
24462291 let address = toString(i.caller)
24472292 let asset = value(assetInfo(assetId))
24482293 let timeKey = keyStakedTimeByAssetId(assetIdStr)
24492294 if (!(isDefined(getInteger(timeKey))))
24502295 then throw((("NFT " + asset.name) + " is not staked"))
24512296 else if (!(isDefined(getString(keyStakedDuckByOwner(address)))))
24522297 then throw((("The duck " + asset.name) + " is not staked"))
24532298 else {
24542299 let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(assetIdStr)), (("NFT " + asset.name) + " is orphaned"))
24552300 if ((owner != address))
24562301 then throw("Staked NFT is not yours")
24572302 else if (checkTournament(assetIdStr))
24582303 then throw("unstakeDuck_checkTournament")
2459- else if (checkDelivery(assetIdStr))
2460- then throw("unstakeDuck_checkDelivery")
2461- else {
2462- let keyHealth = keyDuckHealth(assetIdStr)
2463- let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(assetIdStr)), 0))
2464- let health = valueOrElse(getInteger(keyHealth), maxHP)
2465- if ((maxHP > health))
2466- then throw((("Please heal your duck to " + toString(maxHP)) + "hp before unstaking"))
2467- else ([ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))] ++ prologActions)
2468- }
2304+ else {
2305+ let keyHealth = keyDuckHealth(assetIdStr)
2306+ let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(assetIdStr)), 0))
2307+ let health = valueOrElse(getInteger(keyHealth), maxHP)
2308+ if ((maxHP > health))
2309+ then throw((("Please heal your duck to " + toString(maxHP)) + "hp before unstaking"))
2310+ else ([ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyHealth), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyDuckIdToOwner(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))] ++ prologActions)
2311+ }
24692312 }
24702313 }
24712314 }
24722315
24732316
24742317
24752318 @Callable(i)
24762319 func claimRes (amount,landAssetIdStr) = {
24772320 let prologActions = prolog(i)
24782321 if ((size(i.payments) != 0))
24792322 then throw("No payments required")
24802323 else {
24812324 let addr = toString(i.originCaller)
24822325 let result = claimResInternal(addr, amount, claimModeDuck, landAssetIdStr)
24832326 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
24842327 $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])
24852328 }
24862329 }
24872330
24882331
24892332
24902333 @Callable(i)
24912334 func claimResToWH (amount,landAssetIdStr) = {
24922335 let prologActions = prolog(i)
24932336 if ((size(i.payments) != 0))
24942337 then throw("No payments required")
24952338 else {
24962339 let addr = toString(i.originCaller)
24972340 let result = claimResInternal(addr, amount, claimModeWh, landAssetIdStr)
24982341 $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])
24992342 }
25002343 }
25012344
25022345
25032346
25042347 @Callable(i)
25052348 func flight (message,sig) = {
2506- let prologActions = prologFlight(i)
2349+ let prologActions = prolog(i)
25072350 if ((size(i.payments) != 0))
25082351 then throw("No payments required")
25092352 else {
25102353 let userAddr = toString(i.caller)
25112354 let f = flightCommon(userAddr, message, sig)
25122355 let newHP = f._1
25132356 let duckAssetId = f._2
25142357 let locKey = keyDuckLocation(duckAssetId)
25152358 let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
25162359 let newLocation = f._4
25172360 if ((newLocation == curLocation))
25182361 then throw("You can't fly to the same location")
25192362 else {
25202363 let newLoc = split(newLocation, "_")
25212364 let isTour = (newLoc[locIdxType] == "T")
25222365 let isDeliv = (newLoc[locIdxType] == "D")
25232366 let eqKey = keyDuckEquipment(duckAssetId)
25242367 let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,")
2525- let $t07023070327 = subtractEquipment(currentEq, f._5)
2526- let newEq = $t07023070327._1
2527- let shouldZeroBuffs = $t07023070327._2
2528- let $t07033073442 = if (!(onMission(tournamentContract, curLocation)))
2529- then if (!(isUsualLocation(newLocation)))
2368+ let $t06603566132 = subtractEquipment(currentEq, f._5)
2369+ let newEq = $t06603566132._1
2370+ let shouldZeroBuffs = $t06603566132._2
2371+ let $t06613567967 = if (!(onMission(tournamentContract, curLocation)))
2372+ then if (isTour)
25302373 then cheatAttempt(curLocation, newLocation, 5)
2531- else if ((newHP > 0))
2532- then $Tuple2(newLocation, newHP)
2533- else $Tuple2(curLocation, 0)
2374+ else if (!(isDeliv))
2375+ then if ((newHP > 0))
2376+ then $Tuple2(newLocation, newHP)
2377+ else $Tuple2(curLocation, 0)
2378+ else if ((newHP > 0))
2379+ then {
2380+ let s = invoke(this, "processDelivery", [duckAssetId], nil)
2381+ if ((s == s))
2382+ then $Tuple2(curLocation, newHP)
2383+ else throw("Strict value is not equal to itself.")
2384+ }
2385+ else $Tuple2(curLocation, 0)
25342386 else if (isInTournament(tournamentContract, curLocation))
25352387 then if (!(isInTournament(tournamentContract, newLocation)))
25362388 then throw("Your duck is taking part in the tournament")
25372389 else {
25382390 let score = parseIntValue(newLoc[locIdxId])
25392391 let curLoc = split(curLocation, "_")
25402392 let lastId = valueOrElse(getInteger(tournamentContract, lastTourIdKey), 0)
25412393 if ((score != (parseIntValue(curLoc[locIdxId]) + 1)))
25422394 then cheatAttempt(curLocation, newLocation, 7)
25432395 else if ((newHP > 0))
25442396 then {
25452397 let localBest = valueOrElse(getInteger(tournamentContract, keyBestResultByTourAndDuck(lastId, duckAssetId)), 0)
25462398 let updLocal = if ((score > localBest))
25472399 then invoke(tournamentContract, "saveDuckResult", [duckAssetId, score], nil)
25482400 else unit
25492401 if ((updLocal == updLocal))
25502402 then $Tuple2(newLocation, newHP)
25512403 else throw("Strict value is not equal to itself.")
25522404 }
25532405 else $Tuple2(curLocation, 0)
25542406 }
2555- else if (!(isInDelivery(curLocation)))
2556- then {
2557- let savedLoc = asString(invoke(this, "autoExitDelivery", [duckAssetId, newHP, if (isDeliv)
2558- then "10"
2559- else "11", 0], nil))
2560- if ((savedLoc == savedLoc))
2561- then if (isDeliv)
2562- then $Tuple2(savedLoc, newHP)
2563- else if ((newHP > 0))
2564- then $Tuple2(newLocation, newHP)
2565- else $Tuple2(savedLoc, 0)
2566- else throw("Strict value is not equal to itself.")
2567- }
2568- else if (!(isDeliv))
2569- then throw("Your duck is taking part in delivery")
2570- else if (!(isInDelivery(newLocation)))
2571- then cheatAttempt(curLocation, newLocation, 13)
2572- else {
2573- let score = parseIntValue(newLoc[locIdxId])
2574- let curLoc = split(curLocation, "_")
2575- if ((score != (parseIntValue(curLoc[locIdxId]) + 1)))
2576- then cheatAttempt(curLocation, newLocation, 14)
2577- else if (if ((newHP > 0))
2578- then (1 > score)
2579- else false)
2580- then $Tuple2(newLocation, newHP)
2581- else {
2582- let savedLoc = asString(invoke(this, "autoExitDelivery", [duckAssetId, newHP, "15-17", score], nil))
2583- if ((savedLoc == savedLoc))
2584- then $Tuple2(savedLoc, newHP)
2585- else throw("Strict value is not equal to itself.")
2586- }
2587- }
2588- let locToSave = $t07033073442._1
2589- let hpToSave = $t07033073442._2
2407+ else throw(("Unknown curLocation:" + curLocation))
2408+ let locToSave = $t06613567967._1
2409+ let hpToSave = $t06613567967._2
25902410 $Tuple2(((([StringEntry(locKey, locToSave), StringEntry(eqKey, newEq), IntegerEntry(keyDuckHealth(duckAssetId), hpToSave)] ++ prologActions) ++ (if (shouldZeroBuffs)
25912411 then [StringEntry(keyDuckBuffs(duckAssetId), "0_0_0_0_0")]
25922412 else nil)) ++ updateDuckStatsInternal(duckAssetId, if ((newHP > 0))
25932413 then xpSuccessFlight
25942414 else xpFailFlight)._1), f._3)
25952415 }
25962416 }
25972417 }
25982418
25992419
26002420
26012421 @Callable(i)
26022422 func heal (quantityL1,quantityL2,quantityL3) = {
26032423 let prologActions = prolog(i)
26042424 if (if (if ((0 > quantityL1))
26052425 then true
26062426 else (0 > quantityL2))
26072427 then true
26082428 else (0 > quantityL3))
26092429 then throw("Quantity cannot be negative")
26102430 else {
26112431 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
26122432 if (checkTournament(duckAssetId))
26132433 then throw("heal_checkTournament")
2614- else if (checkDelivery(duckAssetId))
2615- then throw("heal_checkDelivery")
2616- else {
2617- let qts = [quantityL1, quantityL2, quantityL3]
2618- let keyHealth = keyDuckHealth(duckAssetId)
2619- let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
2620- let oldHealth = valueOrElse(getInteger(keyHealth), maxHP)
2621- if ((oldHealth >= maxHP))
2622- then throw((("HP should be < " + toString(maxHP)) + " to heal"))
2623- else {
2624- let bpKey = keyBackpackByDuck(duckAssetId)
2625- let currentPack = getBackpack(bpKey)
2626- let prodList = if ((currentPack[bpIdxProd] == ""))
2627- then nil
2628- else split_4C(currentPack[bpIdxProd], "_")
2629- func iterateProd (acc,recipe) = {
2630- let n = acc._2
2631- let x = if ((size(prodList) > n))
2632- then parseIntValue(prodList[n])
2633- else 0
2634- if ((3 > n))
2635- then {
2636- let q = qts[n]
2637- if ((q > x))
2638- then throw(((("You have only " + toString(x)) + " of ") + prodTypes[n]))
2639- else $Tuple3((acc._1 :+ toString((x - q))), (n + 1), (acc._3 + (parseIntValue(split(recipe, "_")[rIdxEffect]) * q)))
2640- }
2641- else $Tuple3((acc._1 :+ toString(x)), (n + 1), acc._3)
2642- }
2643-
2644- let result = {
2645- let $l = productionMatrix
2646- let $s = size($l)
2647- let $acc0 = $Tuple3(nil, 0, 0)
2648- func $f0_1 ($a,$i) = if (($i >= $s))
2649- then $a
2650- else iterateProd($a, $l[$i])
2651-
2652- func $f0_2 ($a,$i) = if (($i >= $s))
2653- then $a
2654- else throw("List size exceeds 50")
2655-
2656- $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)
2657- }
2658- let newHealth = min([maxHP, (oldHealth + result._3)])
2659- $Tuple2((([IntegerEntry(keyHealth, newHealth), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], makeString(result._1, "_")], ":"))] ++ prologActions) ++ updateDuckStatsInternal(duckAssetId, (xpHeal * ((quantityL1 + quantityL2) + quantityL3)))._1), newHealth)
2434+ else {
2435+ let qts = [quantityL1, quantityL2, quantityL3]
2436+ let keyHealth = keyDuckHealth(duckAssetId)
2437+ let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
2438+ let oldHealth = valueOrElse(getInteger(keyHealth), maxHP)
2439+ if ((oldHealth >= maxHP))
2440+ then throw((("HP should be < " + toString(maxHP)) + " to heal"))
2441+ else {
2442+ let bpKey = keyBackpackByDuck(duckAssetId)
2443+ let currentPack = getBackpack(bpKey)
2444+ let prodList = if ((currentPack[bpIdxProd] == ""))
2445+ then nil
2446+ else split_4C(currentPack[bpIdxProd], "_")
2447+ func iterateProd (acc,recipe) = {
2448+ let n = acc._2
2449+ let x = if ((size(prodList) > n))
2450+ then parseIntValue(prodList[n])
2451+ else 0
2452+ if ((3 > n))
2453+ then {
2454+ let q = qts[n]
2455+ if ((q > x))
2456+ then throw(((("You have only " + toString(x)) + " of ") + prodTypes[n]))
2457+ else $Tuple3((acc._1 :+ toString((x - q))), (n + 1), (acc._3 + (parseIntValue(split(recipe, "_")[rIdxEffect]) * q)))
2458+ }
2459+ else $Tuple3((acc._1 :+ toString(x)), (n + 1), acc._3)
26602460 }
2661- }
2461+
2462+ let result = {
2463+ let $l = productionMatrix
2464+ let $s = size($l)
2465+ let $acc0 = $Tuple3(nil, 0, 0)
2466+ func $f0_1 ($a,$i) = if (($i >= $s))
2467+ then $a
2468+ else iterateProd($a, $l[$i])
2469+
2470+ func $f0_2 ($a,$i) = if (($i >= $s))
2471+ then $a
2472+ else throw("List size exceeds 50")
2473+
2474+ $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)
2475+ }
2476+ let newHealth = min([maxHP, (oldHealth + result._3)])
2477+ $Tuple2((([IntegerEntry(keyHealth, newHealth), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], makeString(result._1, "_")], ":"))] ++ prologActions) ++ updateDuckStatsInternal(duckAssetId, (xpHeal * ((quantityL1 + quantityL2) + quantityL3)))._1), newHealth)
2478+ }
2479+ }
26622480 }
26632481 }
26642482
26652483
26662484
26672485 @Callable(i)
26682486 func healES () = {
26692487 let prologActions = prolog(i)
26702488 if ((size(i.payments) != 1))
26712489 then throw("Exactly one payment required")
26722490 else {
26732491 let pmt = value(i.payments[0])
26742492 if ((pmt.assetId != usdtAssetId))
26752493 then throw("Allowed USDT payment only!")
26762494 else {
26772495 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
26782496 if (checkTournament(duckAssetId))
26792497 then throw("healES_checkTournament")
2680- else if (checkDelivery(duckAssetId))
2681- then throw("healES_checkDelivery")
2682- else {
2683- let keyHealth = keyDuckHealth(duckAssetId)
2684- let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
2685- let oldHealth = valueOrElse(getInteger(keyHealth), maxHP)
2686- if ((oldHealth > 0))
2687- then throw("HP should be 0 to call Emergency Service")
2688- else {
2689- let bpKey = keyBackpackByDuck(duckAssetId)
2690- let currentPack = getBackpack(bpKey)
2691- let prodList = if ((currentPack[bpIdxProd] == ""))
2692- then nil
2693- else split_4C(currentPack[bpIdxProd], "_")
2694- let medKitAmount1 = if ((size(prodList) > 0))
2695- then parseIntValue(prodList[0])
2696- else 0
2697- let medKitAmount2 = if ((size(prodList) > 1))
2698- then parseIntValue(prodList[1])
2699- else 0
2700- let medKitAmount3 = if ((size(prodList) > 2))
2701- then parseIntValue(prodList[2])
2702- else 0
2703- if (if (if ((medKitAmount1 > 0))
2704- then true
2705- else (medKitAmount2 > 0))
2706- then true
2707- else (medKitAmount3 > 0))
2708- then throw("You have to use own Medical Kit")
2709- else {
2710- let existStr = getString(economyContract, keyEsWarehouse())
2711- let existAmounts = if (isDefined(existStr))
2712- then split_4C(value(existStr), "_")
2713- else nil
2714- let existAmount = if ((size(existAmounts) > 0))
2715- then parseIntValue(existAmounts[0])
2716- else 0
2717- if ((0 >= existAmount))
2718- then throw("There are no Medical Kits L1 at Emergency Service storage")
2719- else {
2720- let newHealth = (oldHealth + parseIntValue(split(productionMatrix[0], "_")[rIdxEffect]))
2721- let newES = makeString([toString((existAmount - 1)), removeByIndex(existAmounts, 0)], "_")
2722- let recipe = split(productionMatrix[0], "_")
2723- let totalMat = getRecipeMaterials(recipe)
2724- let sellPrice = fraction((totalMat * ESSELLCOEF), RESOURCEPRICEMIN, (MULT8 * PRODUCTPKGSIZE))
2725- if ((pmt.amount != sellPrice))
2726- then throw(("Payment attached should be " + toString(sellPrice)))
2727- else {
2728- let result = asString(invoke(economyContract, "updateEsStorage", [newES], [AttachedPayment(usdtAssetId, sellPrice)]))
2729- $Tuple2(((prologActions :+ IntegerEntry(keyHealth, newHealth)) ++ updateDuckStatsInternal(duckAssetId, xpCallES)._1), result)
2730- }
2731- }
2732- }
2733- }
2734- }
2498+ else {
2499+ let keyHealth = keyDuckHealth(duckAssetId)
2500+ let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
2501+ let oldHealth = valueOrElse(getInteger(keyHealth), maxHP)
2502+ if ((oldHealth > 0))
2503+ then throw("HP should be 0 to call Emergency Service")
2504+ else {
2505+ let bpKey = keyBackpackByDuck(duckAssetId)
2506+ let currentPack = getBackpack(bpKey)
2507+ let prodList = if ((currentPack[bpIdxProd] == ""))
2508+ then nil
2509+ else split_4C(currentPack[bpIdxProd], "_")
2510+ let medKitAmount1 = if ((size(prodList) > 0))
2511+ then parseIntValue(prodList[0])
2512+ else 0
2513+ let medKitAmount2 = if ((size(prodList) > 1))
2514+ then parseIntValue(prodList[1])
2515+ else 0
2516+ let medKitAmount3 = if ((size(prodList) > 2))
2517+ then parseIntValue(prodList[2])
2518+ else 0
2519+ if (if (if ((medKitAmount1 > 0))
2520+ then true
2521+ else (medKitAmount2 > 0))
2522+ then true
2523+ else (medKitAmount3 > 0))
2524+ then throw("You have to use own Medical Kit")
2525+ else {
2526+ let existStr = getString(economyContract, keyEsWarehouse())
2527+ let existAmounts = if (isDefined(existStr))
2528+ then split_4C(value(existStr), "_")
2529+ else nil
2530+ let existAmount = if ((size(existAmounts) > 0))
2531+ then parseIntValue(existAmounts[0])
2532+ else 0
2533+ if ((0 >= existAmount))
2534+ then throw("There are no Medical Kits L1 at Emergency Service storage")
2535+ else {
2536+ let newHealth = (oldHealth + parseIntValue(split(productionMatrix[0], "_")[rIdxEffect]))
2537+ let newES = makeString([toString((existAmount - 1)), removeByIndex(existAmounts, 0)], "_")
2538+ let recipe = split(productionMatrix[0], "_")
2539+ let totalMat = getRecipeMaterials(recipe)
2540+ let sellPrice = fraction((totalMat * ESSELLCOEF), RESOURCEPRICEMIN, (MULT8 * PRODUCTPKGSIZE))
2541+ if ((pmt.amount != sellPrice))
2542+ then throw(("Payment attached should be " + toString(sellPrice)))
2543+ else {
2544+ let result = asString(invoke(economyContract, "updateEsStorage", [newES], [AttachedPayment(usdtAssetId, sellPrice)]))
2545+ $Tuple2(((prologActions :+ IntegerEntry(keyHealth, newHealth)) ++ updateDuckStatsInternal(duckAssetId, xpCallES)._1), result)
2546+ }
2547+ }
2548+ }
2549+ }
2550+ }
27352551 }
27362552 }
27372553 }
27382554
27392555
27402556
27412557 @Callable(i)
27422558 func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyContract))
27432559 then throw("permission denied")
27442560 else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack)
27452561
27462562
27472563
27482564 @Callable(i)
27492565 func commitForRandom () = {
27502566 let prologActions = prolog(i)
27512567 let finishBlock = (height + randomDelay)
27522568 let addr = toString(i.caller)
27532569 $Tuple2(([IntegerEntry(keyCommit(addr), finishBlock)] ++ prologActions), finishBlock)
2570+ }
2571+
2572+
2573+
2574+@Callable(i)
2575+func revealRandom (maxValue) = {
2576+ let prologActions = prolog(i)
2577+ let addr = toString(i.caller)
2578+ let finishKey = keyCommit(addr)
2579+ let finishBlock = valueOrErrorMessage(getInteger(finishKey), "You have to commitForRandom() first!")
2580+ if ((finishBlock > height))
2581+ then throw(("Random number is not ready yet, wait until height = " + toString(finishBlock)))
2582+ else {
2583+ let entropy = value(value(blockInfoByHeight(finishBlock)).vrf)
2584+ let salt = toBytes(valueOrElse(getString(keyLastTxIdByUser(addr)), ""))
2585+ let rand = getRandomNumber(maxValue, salt, entropy)
2586+ $Tuple2(([DeleteEntry(finishKey)] ++ prologActions), rand)
2587+ }
27542588 }
27552589
27562590
27572591
27582592 @Callable(i)
27592593 func buySLand () = {
27602594 let prologActions = prolog(i)
27612595 if ((size(i.payments) != 1))
27622596 then throw("Exactly one payment required")
27632597 else {
27642598 let pmt = value(i.payments[0])
27652599 if ((pmt.assetId != usdtAssetId))
27662600 then throw("Allowed USDT payment only!")
27672601 else if ((pmt.amount != EXPUSDT))
27682602 then throw(("Payment attached should be " + toString(EXPUSDT)))
27692603 else {
27702604 let result = expeditionInternal(i.caller, i.transactionId)
27712605 let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], nil))
27722606 $Tuple2((((result._1 :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) ++ updateAccStatsInternal(toString(i.caller), xpNewSLand)._1) ++ prologActions), $Tuple2(result._2._1, acresResult))
27732607 }
27742608 }
27752609 }
27762610
27772611
27782612
27792613 @Callable(i)
27802614 func expedition (message,sig) = {
27812615 let prologActions = prolog(i)
27822616 if ((size(i.payments) != 0))
27832617 then throw("No payments required")
27842618 else {
27852619 let userAddr = toString(i.caller)
27862620 let f = flightCommon(userAddr, message, sig)
27872621 let duckAssetId = f._2
27882622 let keyHealth = keyDuckHealth(duckAssetId)
27892623 let bpKey = keyBackpackByDuck(duckAssetId)
27902624 let currentPack = getBackpack(bpKey)
27912625 let mList = split(currentPack[bpIdxMat], "_")
27922626 let newMat = makeString(subtractMaterials(true, mList, EXPMATERIALS), "_")
27932627 let eqKey = keyDuckEquipment(duckAssetId)
27942628 let currentEq = valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,")
2795- let $t08088280979 = subtractEquipment(currentEq, f._5)
2796- let newEq = $t08088280979._1
2797- let shouldZeroBuffs = $t08088280979._2
2629+ let $t07588775984 = subtractEquipment(currentEq, f._5)
2630+ let newEq = $t07588775984._1
2631+ let shouldZeroBuffs = $t07588775984._2
27982632 let e = expeditionInternal(i.caller, i.transactionId)
27992633 let id = e._2._1
28002634 let result = if ((0 >= f._1))
28012635 then $Tuple3([IntegerEntry(keyHealth, 0), StringEntry(eqKey, newEq)], "", 0)
28022636 else $Tuple3((e._1 ++ (if (shouldZeroBuffs)
28032637 then [StringEntry(keyDuckBuffs(duckAssetId), "0_0_0_0_0")]
28042638 else ((((nil :+ StringEntry(keyDuckLocation(duckAssetId), makeString([e._2._2, "L", id], "_"))) :+ IntegerEntry(keyHealth, f._1)) :+ StringEntry(eqKey, newEq)) :+ StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))))), id, f._3)
28052639 if (checkTournament(duckAssetId))
28062640 then throw("expedition_checkTournament")
2807- else if (checkDelivery(duckAssetId))
2808- then throw("expedition_checkDelivery")
2809- else {
2810- let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], nil))
2811- $Tuple2(((result._1 ++ updateDuckStatsInternal(duckAssetId, xpNewSLand)._1) ++ prologActions), $Tuple3(result._2, result._3, acresResult))
2812- }
2641+ else {
2642+ let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], nil))
2643+ $Tuple2(((result._1 ++ updateDuckStatsInternal(duckAssetId, xpNewSLand)._1) ++ prologActions), $Tuple3(result._2, result._3, acresResult))
2644+ }
28132645 }
28142646 }
28152647
28162648
28172649
28182650 @Callable(i)
28192651 func buySLandForAcres () = {
28202652 let prologActions = prolog(i)
28212653 if ((size(i.payments) != 1))
28222654 then throw("exactly 1 payment must be attached")
28232655 else {
28242656 let pmt = i.payments[0]
28252657 let amt = pmt.amount
28262658 if (if (!(isDefined(pmt.assetId)))
28272659 then true
28282660 else (value(pmt.assetId) != acresAssetId))
28292661 then throw("ACRES payments only!")
28302662 else if ((amt != S_COST_ACRES))
28312663 then throw(("Payment attached should be " + toString(S_COST_ACRES)))
28322664 else {
28332665 let result = expeditionInternal(i.caller, i.transactionId)
28342666 let acresResult = asInt(invoke(acresContract, "burnAcres", [S_COST_ACRES], [AttachedPayment(acresAssetId, amt)]))
28352667 $Tuple2(((result._1 ++ updateAccStatsInternal(toString(i.caller), xpNewSLand)._1) ++ prologActions), $Tuple2(result._2._1, acresResult))
28362668 }
28372669 }
28382670 }
28392671
28402672
28412673
28422674 @Callable(i)
28432675 func upgradeInfra (landAssetId) = {
28442676 let prologActions = prolog(i)
28452677 if ((size(i.payments) != 0))
28462678 then throw("No payments required")
28472679 else {
28482680 let result = upInfraCommon(true, i.caller, 0, landAssetId)
28492681 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
28502682 $Tuple2(((result._1 ++ prologActions) ++ updateDuckStatsInternal(duckAssetId, fraction(xpUpgradeInfra, result._3, MULT8))._1), result._2)
28512683 }
28522684 }
28532685
28542686
28552687
28562688 @Callable(i)
28572689 func activateArtifact (artName,landAssetIdOpt) = {
28582690 let prologActions = prolog(i)
28592691 if ((size(i.payments) != 0))
28602692 then throw("No payments required")
28612693 else {
28622694 let addr = toString(i.caller)
28632695 let result = match artName {
28642696 case _ =>
28652697 if (("PRESALE" == $match0))
28662698 then activatePresaleArt(addr, landAssetIdOpt)
28672699 else if (("ONBOARD" == $match0))
28682700 then activateOnboardArt(addr)
28692701 else throw("Unknown artifact")
28702702 }
28712703 (result ++ prologActions)
28722704 }
28732705 }
28742706
28752707
28762708
28772709 @Callable(i)
28782710 func mergeLands (landAssetIds) = {
28792711 let prologActions = prolog(i)
28802712 if ((size(i.payments) != 0))
28812713 then throw("No payments required")
28822714 else {
28832715 let result = mergeCommon(toString(i.caller), landAssetIds)
28842716 $Tuple2(((result._1 ++ prologActions) ++ updateAccStatsInternal(toString(i.caller), xpMerge)._1), result._2)
28852717 }
28862718 }
28872719
28882720
28892721
28902722 @Callable(i)
28912723 func cargoExchange (cargoListStr,landAssetId) = {
28922724 let prologActions = prolog(i)
28932725 if ((size(i.payments) != 0))
28942726 then throw("No payments required")
28952727 else {
28962728 let cargoParts = split_4C(cargoListStr, ":")
28972729 let addr = toString(i.originCaller)
28982730 let asset = value(assetInfo(fromBase58String(landAssetId)))
28992731 let timeKey = keyStakedTimeByAssetId(landAssetId)
29002732 if (!(isDefined(getInteger(timeKey))))
29012733 then throw((asset.name + " is not staked"))
29022734 else {
29032735 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
29042736 if ((owner != addr))
29052737 then throw((LANDPREFIX + " is not yours"))
29062738 else {
29072739 let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE)
29082740 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
29092741 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
29102742 let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetId)), DEFAULTLOCATION)
29112743 let loc = split(value(curLocation), "_")
29122744 if ((loc[locIdxType] != "L"))
29132745 then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
29142746 else if ((loc[locIdxId] != landAssetId))
29152747 then throw(("Duck should be on the land " + landAssetId))
29162748 else {
29172749 let whKey = keyWarehouseByLand(landAssetId)
29182750 let currentWh = getWarehouse(whKey, landIndex, infraLevel)
29192751 let bpKey = keyBackpackByDuck(duckAssetId)
29202752 let currentPack = getBackpack(bpKey)
29212753 let result = moveStuff(cargoParts, currentWh, currentPack)
29222754 let loft = split(currentWh[whIdxLOFT], "_")
29232755 let loftO = (parseIntValue(loft[volOccupied]) + result._7)
29242756 let loftF = (parseIntValue(loft[volFree]) - result._7)
29252757 ([StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], result._4, result._5, result._6], ":")), StringEntry(whKey, makeString_2C([currentWh[whIdxLevels], result._1, result._2, result._3, makeString([loft[volLocked], toString(loftO), toString(loftF), loft[volTotal]], "_")], ":"))] ++ prologActions)
29262758 }
29272759 }
29282760 }
29292761 }
29302762 }
29312763
29322764
29332765
29342766 @Callable(i)
29352767 func saveWarehouse (whStr,landAssetId) = if ((i.caller != economyContract))
29362768 then throw("Access denied")
29372769 else {
29382770 let whKey = keyWarehouseByLand(landAssetId)
29392771 let wh = split_4C(whStr, ":")
29402772 if ((size(wh) != 5))
29412773 then throw("warehouse string should contain 4 ':' separators")
29422774 else {
29432775 let loftL = split(wh[whIdxLOFT], "_")[volLocked]
29442776 let loftO = getWarehouseOccupiedVol(wh)
29452777 let loftT = getWarehouseTotalVolume(wh[whIdxLevels])
29462778 let loftF = ((loftT - parseIntValue(loftL)) - loftO)
29472779 if ((0 > loftF))
29482780 then throw("Operation leads to negative free warehouse space")
29492781 else {
29502782 let newWhStr = makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], wh[whIdxProd], makeString([loftL, toString(loftO), toString(loftF), toString(loftT)], "_")], ":")
29512783 $Tuple2([StringEntry(whKey, newWhStr)], newWhStr)
29522784 }
29532785 }
29542786 }
29552787
29562788
29572789
29582790 @Callable(i)
29592791 func setCustomName (assetId,customName,type) = {
29602792 let prologActions = prolog(i)
29612793 if ((size(i.payments) != 1))
29622794 then throw("Exactly one payment required")
29632795 else {
29642796 let pmt = value(i.payments[0])
29652797 if ((pmt.assetId != usdtAssetId))
29662798 then throw("Allowed USDT payment only!")
29672799 else if ((pmt.amount != RENAMINGCOST))
29682800 then throw(("Payment should be " + toString(RENAMINGCOST)))
29692801 else if (contains(customName, "__"))
29702802 then throw(("Name should not contain '__': " + customName))
29712803 else if ((size(customName) > MAXNAMELEN))
29722804 then throw(("Name too long, maxLength=" + toString(MAXNAMELEN)))
29732805 else {
29742806 let addr = toString(i.originCaller)
29752807 let actions = match type {
29762808 case _ =>
29772809 if (("ACCOUNT" == $match0))
29782810 then {
29792811 let reverseKey = keyCustomNameToAddress(customName)
29802812 let nameOwner = getString(reverseKey)
29812813 if (isDefined(nameOwner))
29822814 then throw(("Name already registered: " + customName))
29832815 else {
29842816 let addrToNameKey = keyAddressToCustomName(addr)
29852817 let oldName = getString(addrToNameKey)
29862818 let freeOld = if (isDefined(oldName))
29872819 then [DeleteEntry(keyCustomNameToAddress(value(oldName)))]
29882820 else nil
29892821 (((freeOld :+ StringEntry(addrToNameKey, customName)) :+ StringEntry(reverseKey, addr)) ++ updateAccStatsInternal(addr, xpCustomName)._1)
29902822 }
29912823 }
29922824 else if (("LAND" == $match0))
29932825 then {
29942826 let asset = value(assetInfo(fromBase58String(assetId)))
29952827 let timeKey = keyStakedTimeByAssetId(assetId)
29962828 if (!(isDefined(getInteger(timeKey))))
29972829 then throw((asset.name + " is not staked"))
29982830 else {
29992831 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(assetId)), (("NFT " + asset.name) + " is orphaned"))
30002832 if ((owner != addr))
30012833 then throw((LANDPREFIX + " is not yours"))
30022834 else {
30032835 let reverseKey = keyLandCustomNameToAssetId(customName)
30042836 let nameOwner = getString(reverseKey)
30052837 if (isDefined(nameOwner))
30062838 then throw(("Name already registered: " + customName))
30072839 else {
30082840 let assetToNameKey = keyLandAssetIdToCustomName(assetId)
30092841 let oldName = getString(assetToNameKey)
30102842 let freeOld = if (isDefined(oldName))
30112843 then [DeleteEntry(keyLandCustomNameToAssetId(value(oldName)))]
30122844 else nil
30132845 (((freeOld :+ StringEntry(assetToNameKey, customName)) :+ StringEntry(reverseKey, assetId)) ++ updateAccStatsInternal(addr, xpCustomName)._1)
30142846 }
30152847 }
30162848 }
30172849 }
30182850 else if (("DUCK" == $match0))
30192851 then {
30202852 let asset = value(assetInfo(fromBase58String(assetId)))
30212853 let timeKey = keyStakedTimeByAssetId(assetId)
30222854 if (if (!(isDefined(getInteger(timeKey))))
30232855 then true
30242856 else !(isDefined(getString(keyStakedDuckByOwner(addr)))))
30252857 then throw((asset.name + " is not staked"))
30262858 else {
30272859 let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(assetId)), (("NFT " + asset.name) + " is orphaned"))
30282860 if ((owner != addr))
30292861 then throw((DUCKPREFIX + " is not yours"))
30302862 else {
30312863 let reverseKey = keyDuckCustomNameToAssetId(customName)
30322864 let nameOwner = getString(reverseKey)
30332865 if (isDefined(nameOwner))
30342866 then throw(("Name already registered: " + customName))
30352867 else {
30362868 let assetToNameKey = keyDuckAssetIdToCustomName(assetId)
30372869 let oldName = getString(assetToNameKey)
30382870 let freeOld = if (isDefined(oldName))
30392871 then [DeleteEntry(keyDuckCustomNameToAssetId(value(oldName)))]
30402872 else nil
30412873 (((freeOld :+ StringEntry(assetToNameKey, customName)) :+ StringEntry(reverseKey, assetId)) ++ updateDuckStatsInternal(assetId, xpCustomName)._1)
30422874 }
30432875 }
30442876 }
30452877 }
30462878 else throw("Unknown entity type")
30472879 }
30482880 $Tuple2(((actions :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)) ++ prologActions), 0)
30492881 }
30502882 }
30512883 }
30522884
30532885
30542886
30552887 @Callable(i)
30562888 func setReferrals (oldPlayer,newPlayer) = if ((i.callerPublicKey != pub))
30572889 then throw("Permission denied")
30582890 else {
30592891 let prologActions = prolog(i)
30602892 if ((size(i.payments) != 0))
30612893 then throw("No payments required")
30622894 else if (!(isDefined(addressFromString(oldPlayer))))
30632895 then throw(("Invalid address: " + oldPlayer))
30642896 else {
30652897 let newbieAddr = addressFromString(newPlayer)
30662898 if (!(isDefined(newbieAddr)))
30672899 then throw(("Invalid address: " + newPlayer))
30682900 else {
30692901 let oldLastTx = getString(keyLastTxIdByUser(oldPlayer))
30702902 if (!(isDefined(oldLastTx)))
30712903 then throw("oldPlayer didn't do any tx in game")
30722904 else if ((0 >= wavesBalance(value(newbieAddr)).available))
30732905 then throw("newPlayer has no WAVES")
30742906 else {
30752907 let oldsKey = keyOldies()
30762908 let olds = getString(oldsKey)
30772909 let oldies = if (isDefined(olds))
30782910 then split_4C(value(olds), "_")
30792911 else nil
30802912 if (containsElement(oldies, newPlayer))
30812913 then throw((newPlayer + " is not newbie (already has referrals)"))
30822914 else {
30832915 let refByKey = keyAddressRefBy(newPlayer)
30842916 let refBy = getString(refByKey)
30852917 if (if (isDefined(refBy))
30862918 then isDefined(addressFromString(value(refBy)))
30872919 else false)
30882920 then throw(((newPlayer + " already has refBy: ") + value(refBy)))
30892921 else {
30902922 let refsKey = keyAddressReferrals(oldPlayer)
30912923 let refs = getString(refsKey)
30922924 let refsArray = if (isDefined(refs))
30932925 then split_4C(value(refs), "_")
30942926 else nil
30952927 if (containsElement(refsArray, newPlayer))
30962928 then throw((((oldPlayer + " already contains ") + newPlayer) + " within referrals"))
30972929 else {
30982930 let newRefs = makeString_2C((refsArray :+ newPlayer), "_")
30992931 let newOlds = if (containsElement(oldies, oldPlayer))
31002932 then value(olds)
31012933 else makeString_2C((oldies :+ oldPlayer), "_")
31022934 $Tuple2(([StringEntry(refByKey, oldPlayer), StringEntry(refsKey, newRefs), StringEntry(oldsKey, newOlds)] ++ prologActions), 0)
31032935 }
31042936 }
31052937 }
31062938 }
31072939 }
31082940 }
31092941 }
31102942
31112943
31122944
31132945 @Callable(i)
31142946 func distributePoints (strength,accuracy,intellect,endurance,dexterity) = {
31152947 let prologActions = prolog(i)
31162948 if ((size(i.payments) != 0))
31172949 then throw("No payments required")
31182950 else {
31192951 let addr = toString(i.originCaller)
31202952 let virtWlgData = asAnyList(invoke(wlgContract, "checkWlgXpREADONLY", [addr], nil))
31212953 let virtWlgPoints = asInt(virtWlgData[1])
3122- let $t09686997259 = if ((0 >= virtWlgPoints))
2954+ let $t09179692186 = if ((0 >= virtWlgPoints))
31232955 then $Tuple2(0, nil)
31242956 else {
31252957 let deltaXP = asInt(invoke(wlgContract, "takeWlgXp", [addr], nil))
31262958 if ((deltaXP == deltaXP))
31272959 then $Tuple2(virtWlgPoints, [IntegerEntry(keyUserLevel(addr), asInt(virtWlgData[0])), IntegerEntry(keyUserXP(addr), asInt(virtWlgData[2]))])
31282960 else throw("Strict value is not equal to itself.")
31292961 }
3130- let wlgPoints = $t09686997259._1
3131- let wlgActions = $t09686997259._2
2962+ let wlgPoints = $t09179692186._1
2963+ let wlgActions = $t09179692186._2
31322964 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
31332965 let freeKeyAcc = keyUserFreePoints(addr)
31342966 let freePointsAcc = (valueOrElse(getInteger(freeKeyAcc), 0) + wlgPoints)
31352967 let freeKeyDuck = keyDuckFreePoints(duckAssetId)
31362968 let freePointsDuck = valueOrElse(getInteger(freeKeyDuck), 0)
31372969 let sumFree = (freePointsAcc + freePointsDuck)
31382970 let sumToDistribute = ((((strength + accuracy) + intellect) + endurance) + dexterity)
31392971 if ((sumToDistribute > sumFree))
31402972 then throw((("There are only " + toString(sumFree)) + " free points to distribute"))
31412973 else {
31422974 let charsKey = keyDuckChars(duckAssetId)
31432975 let chars = split(valueOrElse(getString(charsKey), "0_0_0_0_0"), "_")
31442976 let newAcc = (freePointsAcc - sumToDistribute)
31452977 $Tuple2((([IntegerEntry(freeKeyAcc, if ((0 > newAcc))
31462978 then 0
31472979 else newAcc), IntegerEntry(freeKeyDuck, if ((0 > newAcc))
31482980 then (freePointsDuck + newAcc)
31492981 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)
31502982 }
31512983 }
31522984 }
31532985
31542986
31552987
31562988 @Callable(i)
31572989 func splitByGlobalWeightsREADONLY (amount) = $Tuple2(nil, getNeededMaterials(amount))
31582990
31592991
31602992
31612993 @Callable(i)
31622994 func splitByGlobalAndLocalWeightsREADONLY (matAmount,resAmount,terrains) = {
31632995 let terrainCounts = countTerrains(terrains)
31642996 $Tuple2(nil, $Tuple2(getNeededMaterials(matAmount), distributeByWeights(resAmount, terrainCounts)))
31652997 }
31662998
31672999
31683000
31693001 @Callable(i)
31703002 func getBackpackREADONLY (duckAssetId) = $Tuple2(nil, makeString(getBackpack(keyBackpackByDuck(duckAssetId)), ":"))
31713003
31723004
31733005
31743006 @Callable(i)
31753007 func getWarehouseREADONLY (landAssetId) = {
31763008 let asset = value(assetInfo(fromBase58String(landAssetId)))
31773009 let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE)
31783010 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
31793011 $Tuple2(nil, makeString_2C(getWarehouse(keyWarehouseByLand(landAssetId), landIndex, infraLevel), ":"))
31803012 }
31813013
31823014
31833015
31843016 @Callable(i)
31853017 func saveLastTx () = if (!(containsElement([wlgContract, economyContract, tournamentContract, acresContract], i.caller)))
31863018 then throw("Access denied")
31873019 else $Tuple2(prolog(i), 42)
31883020
31893021
31903022
31913023 @Callable(i)
31923024 func updateDuckStats (duckAssetId,deltaXP) = if ((i.caller != economyContract))
31933025 then throw("Access denied")
31943026 else updateDuckStatsInternal(duckAssetId, deltaXP)
31953027
31963028
31973029
31983030 @Callable(i)
31993031 func updateAccStats (addr,deltaXP) = if (!(containsElement([wlgContract, economyContract, acresContract], i.caller)))
32003032 then throw("Access denied")
32013033 else updateAccStatsInternal(addr, deltaXP)
32023034
32033035
32043036
32053037 @Callable(i)
32063038 func equipDuck (equipment) = {
32073039 let prologActions = prolog(i)
32083040 if ((size(i.payments) != 0))
32093041 then throw("No payments required")
32103042 else {
32113043 let addr = toString(i.originCaller)
32123044 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(addr)), "You don't have a duck staked")
32133045 if (checkTournament(duckAssetId))
32143046 then throw("equipDuck_checkTournament")
3215- else if (checkDelivery(duckAssetId))
3216- then throw("equipDuck_checkDelivery")
3217- else {
3218- let eqKey = keyDuckEquipment(duckAssetId)
3219- let currentSegs = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_")
3220- let bpKey = keyBackpackByDuck(duckAssetId)
3221- let currentPack = getBackpack(bpKey)
3222- let newEq = split(equipment, "_")
3223- if ((size(newEq) != NUMSEGMENTS))
3224- then throw("Wrong equipment string")
3225- else {
3226- let tempProdB = dressB(currentSegs, prodStrToBytes(currentPack[bpIdxProd]), true, nil)
3227- let segBpAux = split(newEq[segBackpack], ";")[1]
3228- let buffEffect = if ((segBpAux == ""))
3229- then 0
3230- else {
3231- let aux0 = split(segBpAux, ",")[0]
3232- if ((aux0 == ""))
3233- then 0
3234- else {
3235- let idxCnt = split(aux0, ":")
3236- let idx = idxCnt[0]
3237- let cnt = idxCnt[1]
3238- if (if (if (if (if ((idx == "06"))
3239- then true
3240- else (idx == "07"))
3241- then true
3242- else (idx == "08"))
3243- then (cnt != "")
3244- else false)
3245- then (parseIntValue(cnt) > 0)
3246- else false)
3247- then parseIntValue(split(productionMatrix[parseIntValue(idx)], "_")[rIdxEffect])
3248- else 0
3249- }
3250- }
3251- let stats = getDuckStats(this, duckAssetId, buffEffect, true)
3252- let newProdB = dressB(newEq, tempProdB, false, stats)
3253- let newProdStr = bytesToProdStr(newProdB)
3254- $Tuple2(([StringEntry(eqKey, equipment), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], newProdStr], ":")), StringEntry(keyDuckBuffs(duckAssetId), makeString([toString(stats[7]), toString(stats[8]), toString(stats[9]), toString(stats[10]), toString(stats[11])], "_"))] ++ prologActions), 0)
3255- }
3256- }
3047+ else {
3048+ let eqKey = keyDuckEquipment(duckAssetId)
3049+ let currentSegs = split(valueOrElse(getString(eqKey), ",;,_,;,_,;,_,;,_,;,_,;,"), "_")
3050+ let bpKey = keyBackpackByDuck(duckAssetId)
3051+ let currentPack = getBackpack(bpKey)
3052+ let newEq = split(equipment, "_")
3053+ if ((size(newEq) != NUMSEGMENTS))
3054+ then throw("Wrong equipment string")
3055+ else {
3056+ let tempProdB = dressB(currentSegs, prodStrToBytes(currentPack[bpIdxProd]), true, nil)
3057+ let segBpAux = split(newEq[segBackpack], ";")[1]
3058+ let buffEffect = if ((segBpAux == ""))
3059+ then 0
3060+ else {
3061+ let aux0 = split(segBpAux, ",")[0]
3062+ if ((aux0 == ""))
3063+ then 0
3064+ else {
3065+ let idxCnt = split(aux0, ":")
3066+ let idx = idxCnt[0]
3067+ let cnt = idxCnt[1]
3068+ if (if (if (if (if ((idx == "06"))
3069+ then true
3070+ else (idx == "07"))
3071+ then true
3072+ else (idx == "08"))
3073+ then (cnt != "")
3074+ else false)
3075+ then (parseIntValue(cnt) > 0)
3076+ else false)
3077+ then parseIntValue(split(productionMatrix[parseIntValue(idx)], "_")[rIdxEffect])
3078+ else 0
3079+ }
3080+ }
3081+ let stats = getDuckStats(this, duckAssetId, buffEffect, true)
3082+ let newProdB = dressB(newEq, tempProdB, false, stats)
3083+ let newProdStr = bytesToProdStr(newProdB)
3084+ $Tuple2(([StringEntry(eqKey, equipment), StringEntry(bpKey, makeString_2C([currentPack[bpIdxLevel], currentPack[bpIdxRes], currentPack[bpIdxMat], newProdStr], ":")), StringEntry(keyDuckBuffs(duckAssetId), makeString([toString(stats[7]), toString(stats[8]), toString(stats[9]), toString(stats[10]), toString(stats[11])], "_"))] ++ prologActions), 0)
3085+ }
3086+ }
32573087 }
32583088 }
32593089
32603090
32613091
32623092 @Callable(i)
32633093 func fortificateLand (landAssetId,plan) = {
32643094 let prologActions = prolog(i)
32653095 if ((size(i.payments) != 0))
32663096 then throw("No payments required")
32673097 else {
32683098 let addr = toString(i.originCaller)
32693099 let duckAssetId = valueOrElse(getString(keyStakedDuckByOwner(addr)), "")
32703100 let duckStats = getDuckStats(this, duckAssetId, 0, false)
32713101 let fortKey = keyFortificationsByLand(landAssetId)
32723102 let currentForts = split(valueOrElse(getString(fortKey), ":0_15:0_18:0"), "_")
32733103 let asset = value(assetInfo(fromBase58String(landAssetId)))
32743104 let landIndex = (numPiecesBySize(split(asset.description, "_")[recLandSize]) / SSIZE)
32753105 let infraLevel = valueOrElse(getInteger(keyInfraLevelByAssetId(landAssetId)), 0)
32763106 let whKey = keyWarehouseByLand(landAssetId)
32773107 let wh = getWarehouse(whKey, landIndex, infraLevel)
32783108 let curLoft = split(wh[whIdxLOFT], "_")
32793109 let curO = parseIntValue(curLoft[volOccupied])
32803110 let curF = parseIntValue(curLoft[volFree])
32813111 let newForts = split(plan, "_")
3282- let $t0104097104212 = fortB(currentForts, prodStrToBytes(wh[whIdxProd]), curO, curF, true, nil)
3283- let tempProdB = $t0104097104212._1
3284- let tempO = $t0104097104212._2
3285- let tempF = $t0104097104212._3
3286- let $t0104215104311 = fortB(newForts, tempProdB, tempO, tempF, false, duckStats)
3287- let newProdB = $t0104215104311._1
3288- let newO = $t0104215104311._2
3289- let newF = $t0104215104311._3
3112+ let $t09894799062 = fortB(currentForts, prodStrToBytes(wh[whIdxProd]), curO, curF, true, nil)
3113+ let tempProdB = $t09894799062._1
3114+ let tempO = $t09894799062._2
3115+ let tempF = $t09894799062._3
3116+ let $t09906599161 = fortB(newForts, tempProdB, tempO, tempF, false, duckStats)
3117+ let newProdB = $t09906599161._1
3118+ let newO = $t09906599161._2
3119+ let newF = $t09906599161._3
32903120 let newProdStr = bytesToProdStr(newProdB)
32913121 let newLoftStr = makeString([curLoft[volLocked], toString(newO), toString(newF), curLoft[volTotal]], "_")
32923122 $Tuple2(([StringEntry(fortKey, plan), StringEntry(whKey, makeString_2C([wh[whIdxLevels], wh[whIdxRes], wh[whIdxMat], newProdStr, newLoftStr], ":"))] ++ prologActions), 0)
32933123 }
32943124 }
32953125
32963126
32973127
32983128 @Callable(i)
32993129 func initDuckTourAttempt (duckAssetId) = if ((i.caller != tournamentContract))
33003130 then throw("Access denied")
33013131 else {
33023132 let keyHealth = keyDuckHealth(duckAssetId)
33033133 let maxHP = maxHealth(valueOrElse(getInteger(keyDuckLevel(duckAssetId)), 0))
33043134 let curHealth = valueOrElse(getInteger(keyHealth), maxHP)
33053135 let curLocKey = keyDuckLocation(duckAssetId)
33063136 let curLocation = valueOrElse(getString(curLocKey), DEFAULTLOCATION)
33073137 let lastId = valueOrElse(getInteger(tournamentContract, lastTourIdKey), 0)
33083138 let tourLocation = (toString(lastId) + "_T_0")
33093139 $Tuple2([IntegerEntry(keySavedHealth(duckAssetId), curHealth), IntegerEntry(keyHealth, maxHP), StringEntry(keySavedLocation(duckAssetId), curLocation), StringEntry(curLocKey, tourLocation)], tourLocation)
33103140 }
33113141
33123142
33133143
33143144 @Callable(i)
33153145 func breakAttempt () = {
33163146 let prologActions = prolog(i)
33173147 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
33183148 let curLocKey = keyDuckLocation(duckAssetId)
33193149 let curLocation = valueOrElse(getString(curLocKey), DEFAULTLOCATION)
33203150 if ((split(curLocation, "_")[locIdxType] != "T"))
33213151 then throw("Your duck is not in the tournament")
33223152 else {
33233153 let savedHealth = getIntegerValue(keySavedHealth(duckAssetId))
33243154 let savedLocation = getStringValue(keySavedLocation(duckAssetId))
33253155 $Tuple2(((prologActions :+ IntegerEntry(keyDuckHealth(duckAssetId), savedHealth)) :+ StringEntry(curLocKey, savedLocation)), curLocation)
33263156 }
33273157 }
33283158
33293159
33303160
33313161 @Callable(i)
33323162 func breakAttemptCallback () = if ((i.caller != tournamentContract))
33333163 then throw("Access denied")
33343164 else {
33353165 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.originCaller))), "You don't have a duck staked")
33363166 $Tuple2([IntegerEntry(keyDuckHealth(duckAssetId), getIntegerValue(keySavedHealth(duckAssetId))), StringEntry(keyDuckLocation(duckAssetId), getStringValue(keySavedLocation(duckAssetId)))], "breakAttemptCallback")
33373167 }
33383168
33393169
33403170
33413171 @Callable(i)
33423172 func exitTournamentInternal (duckAssetId) = if ((i.caller != this))
33433173 then throw("Access denied")
33443174 else {
33453175 let savedHealth = getIntegerValue(keySavedHealth(duckAssetId))
33463176 let savedLocation = getStringValue(keySavedLocation(duckAssetId))
33473177 $Tuple2([IntegerEntry(keyDuckHealth(duckAssetId), savedHealth), StringEntry(keyDuckLocation(duckAssetId), savedLocation)], false)
33483178 }
33493179
33503180
33513181
33523182 @Callable(i)
3353-func exitDeliveryInternal (duckAssetId) = if ((i.caller != this))
3183+func processDelivery (duckAssetId) = if ((i.caller != this))
33543184 then throw("Access denied")
33553185 else {
3356- let e = exitDeliveryCommon(duckAssetId, false, 0, 0)
3357- $Tuple2((e._1 ++ e._2), false)
3186+ let addr = toString(i.originCaller)
3187+ let fundTotal = valueOrElse(getInteger(economyContract, deliveryFundKey), 0)
3188+ if ((MIN_USDT_FEE_DELIVERY > fundTotal))
3189+ then throw(("Delivery is not available, fund=" + fixedPoint(fundTotal, 6)))
3190+ else {
3191+ let now = lastBlock.timestamp
3192+ let countKey = keyUserDeliveryCount(addr)
3193+ let count = valueOrElse(getInteger(countKey), 0)
3194+ let lastDay = valueOrElse(getInteger(keyUserLastDeliveryDay(addr)), 0)
3195+ let today = (now / DAYMILLIS)
3196+ let acres = valueOrElse(getInteger(acresContract, keyAcresStakedAmountByUser(addr)), 0)
3197+ let allowedDeliveries = (ALLOWED_FREE_DELIVERIES + (acres / ACRES_FOR_DELIVERY_ATTEMPT))
3198+ if (if ((count >= allowedDeliveries))
3199+ then (lastDay == today)
3200+ else false)
3201+ then throw((("You already used " + toString(allowedDeliveries)) + " delivery attempts for today"))
3202+ else {
3203+ let reward = invoke(economyContract, "sendDeliveryReward", [addr], nil)
3204+ $Tuple2([IntegerEntry(countKey, (count + 1)), IntegerEntry(keyUserLastDeliveryDay(addr), today)], reward)
3205+ }
3206+ }
33583207 }
3359-
3360-
3361-
3362-@Callable(i)
3363-func autoExitDelivery (duckAssetId,newHP,reason,score) = if ((i.caller != this))
3364- then throw("Access denied")
3365- else {
3366- let e = exitDeliveryCommon(duckAssetId, true, newHP, score)
3367- $Tuple2(e._1, e._3)
3368- }
3369-
3370-
3371-
3372-@Callable(i)
3373-func breakDelivery () = $Tuple2(prolog(i), "breakDelivery")
33743208
33753209
33763210
33773211 @Callable(i)
33783212 func prepareRobbery (message,sig) = {
33793213 let prologActions = prolog(i)
33803214 if (!(sigVerify_8Kb(message, sig, pub)))
33813215 then throw("signature does not match")
33823216 else if ((size(i.payments) != 1))
33833217 then throw("exactly 1 payment must be attached")
33843218 else {
33853219 let pmt = i.payments[0]
33863220 let wlgAmt = pmt.amount
33873221 if (if (!(isDefined(pmt.assetId)))
33883222 then true
33893223 else (value(pmt.assetId) != wlgAssetId))
33903224 then throw("WLGOLD payments only!")
33913225 else {
33923226 let parts = split(toUtf8String(message), "|")
33933227 if ((2 > size(parts)))
33943228 then throw("Wrong message format")
33953229 else {
33963230 let txFromMsg = if ((size(parts) >= 2))
33973231 then parts[2]
33983232 else ""
33993233 let userAddr = toString(i.caller)
34003234 let lastTx = valueOrElse(getString(keyLastTxIdByUser(userAddr)), "")
34013235 if ((lastTx != txFromMsg))
34023236 then throw(((("Tx ids don't match! In state: " + lastTx) + ", in msg: ") + txFromMsg))
34033237 else {
34043238 let duckAssetId = parts[0]
34053239 if (checkTournament(duckAssetId))
34063240 then throw("prepareRobbery_checkTournament")
3407- else if (checkDelivery(duckAssetId))
3408- then throw("prepareRobbery_checkDelivery")
3409- else {
3410- let robCost = getRobberyData(this, duckAssetId)._1
3411- if ((robCost > wlgAmt))
3412- then throw(((("Payment " + toString(wlgAmt)) + " < required ") + toString(robCost)))
3413- else {
3414- let candidates = split(parts[1], "_")
3415- let now = lastBlock.timestamp
3416- let duckState = valueOrElse(getInteger(keyDuckRobberyState(duckAssetId)), 0)
3417- let lockedLand = valueOrElse(getString(keyLockedLandByDuck(duckAssetId)), "")
3418- let landETA = valueOrElse(getInteger(keyLandCooldownETA(lockedLand)), 0)
3419- if (if ((duckState != duckIdxFree))
3420- then (landETA > now)
3421- else false)
3422- then throw(("You already started robbing, wait till " + toString(landETA)))
3423- else {
3424- func checker (acc,landAssetId) = {
3425- let state = valueOrElse(getInteger(keyLandRobberyState(landAssetId)), 0)
3426- let cooldownETA = valueOrElse(getInteger(keyLandCooldownETA(landAssetId)), 0)
3427- if ((state > size(landRobCooldowns)))
3428- then throw("Invalid state")
3429- else if ((now > cooldownETA))
3430- then {
3431- let stakedTime = valueOrElse(getInteger(keyStakedTimeByAssetId(landAssetId)), 0)
3432- if ((0 >= stakedTime))
3433- then acc
3434- else {
3435- let a = value(assetInfo(fromBase58String(landAssetId)))
3436- let d = split(a.description, "_")
3437- let pieces = numPiecesBySize(d[recLandSize])
3438- let productivity = applyBonuses(landAssetId, pieces)
3439- let deltaTime = (now - stakedTime)
3440- let availRes = fraction(deltaTime, (productivity * pieces), DAYMILLIS)
3441- if ((MIN_RES_TO_ROB > availRes))
3442- then acc
3443- else (acc :+ landAssetId)
3444- }
3445- }
3446- else acc
3241+ else {
3242+ let robCost = getRobberyData(this, duckAssetId)._1
3243+ if ((robCost > wlgAmt))
3244+ then throw(((("Payment " + toString(wlgAmt)) + " < required ") + toString(robCost)))
3245+ else {
3246+ let candidates = split(parts[1], "_")
3247+ let now = lastBlock.timestamp
3248+ let duckState = valueOrElse(getInteger(keyDuckRobberyState(duckAssetId)), 0)
3249+ let lockedLand = valueOrElse(getString(keyLockedLandByDuck(duckAssetId)), "")
3250+ let landETA = valueOrElse(getInteger(keyLandCooldownETA(lockedLand)), 0)
3251+ if (if ((duckState != duckIdxFree))
3252+ then (landETA > now)
3253+ else false)
3254+ then throw(("You already started robbing, wait till " + toString(landETA)))
3255+ else {
3256+ func checker (acc,landAssetId) = {
3257+ let state = valueOrElse(getInteger(keyLandRobberyState(landAssetId)), 0)
3258+ let cooldownETA = valueOrElse(getInteger(keyLandCooldownETA(landAssetId)), 0)
3259+ if ((state > size(landRobCooldowns)))
3260+ then throw("Invalid state")
3261+ else if ((now > cooldownETA))
3262+ then {
3263+ let stakedTime = valueOrElse(getInteger(keyStakedTimeByAssetId(landAssetId)), 0)
3264+ if ((0 >= stakedTime))
3265+ then acc
3266+ else {
3267+ let a = value(assetInfo(fromBase58String(landAssetId)))
3268+ let d = split(a.description, "_")
3269+ let pieces = numPiecesBySize(d[recLandSize])
3270+ let productivity = applyBonuses(landAssetId, pieces)
3271+ let deltaTime = (now - stakedTime)
3272+ let availRes = fraction(deltaTime, (productivity * pieces), DAYMILLIS)
3273+ if ((MIN_RES_TO_ROB > availRes))
3274+ then acc
3275+ else (acc :+ landAssetId)
3276+ }
3277+ }
3278+ else acc
3279+ }
3280+
3281+ let filtered = {
3282+ let $l = candidates
3283+ let $s = size($l)
3284+ let $acc0 = nil
3285+ func $f0_1 ($a,$i) = if (($i >= $s))
3286+ then $a
3287+ else checker($a, $l[$i])
3288+
3289+ func $f0_2 ($a,$i) = if (($i >= $s))
3290+ then $a
3291+ else throw("List size exceeds 10")
3292+
3293+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
3294+ }
3295+ if ((size(filtered) == 0))
3296+ then throw("No candidates for robbery")
3297+ else {
3298+ let rndIdx = getRandomNumber(size(filtered), message, sig)
3299+ let landAssetId = filtered[rndIdx]
3300+ $Tuple2(([IntegerEntry(keyLandRobberyState(landAssetId), robIdxLocked), IntegerEntry(keyLandCooldownETA(landAssetId), (now + landRobCooldowns[robIdxLocked])), IntegerEntry(keyDuckRobberyState(duckAssetId), duckIdxPreparing), StringEntry(keyLockedLandByDuck(duckAssetId), landAssetId)] ++ prologActions), landAssetId)
34473301 }
3448-
3449- let filtered = {
3450- let $l = candidates
3451- let $s = size($l)
3452- let $acc0 = nil
3453- func $f0_1 ($a,$i) = if (($i >= $s))
3454- then $a
3455- else checker($a, $l[$i])
3456-
3457- func $f0_2 ($a,$i) = if (($i >= $s))
3458- then $a
3459- else throw("List size exceeds 10")
3460-
3461- $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6), 7), 8), 9), 10)
3462- }
3463- if ((size(filtered) == 0))
3464- then throw("No candidates for robbery")
3465- else {
3466- let rndIdx = getRandomNumber(size(filtered), message, sig)
3467- let landAssetId = filtered[rndIdx]
3468- $Tuple2(([IntegerEntry(keyLandRobberyState(landAssetId), robIdxLocked), IntegerEntry(keyLandCooldownETA(landAssetId), (now + landRobCooldowns[robIdxLocked])), IntegerEntry(keyDuckRobberyState(duckAssetId), duckIdxPreparing), StringEntry(keyLockedLandByDuck(duckAssetId), landAssetId)] ++ prologActions), landAssetId)
3469- }
3470- }
3471- }
3472- }
3302+ }
3303+ }
3304+ }
34733305 }
34743306 }
34753307 }
34763308 }
34773309 }
34783310
34793311
34803312
34813313 @Callable(i)
34823314 func robLand (message,sig) = {
34833315 let prologActions = prolog(i)
34843316 if (!(sigVerify_8Kb(message, sig, pub)))
34853317 then throw("signature does not match")
34863318 else {
34873319 let userAddr = toString(i.caller)
34883320 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked")
34893321 let now = lastBlock.timestamp
34903322 $Tuple2((prologActions :+ IntegerEntry(keyLastRobberyTimeByDuck(duckAssetId), now)), 0)
34913323 }
34923324 }
3493-
3494-
3495-
3496-@Callable(i)
3497-func acceptDelivery () = {
3498- let prologActions = prolog(i)
3499- let userAddr = toString(i.caller)
3500- let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked")
3501- let fundTotal = valueOrElse(getInteger(economyContract, deliveryFundKey), 0)
3502- let lockedTotal = valueOrElse(getInteger(economyContract, deliveryLockedKey), 0)
3503- if ((MIN_USDT_FEE_DELIVERY > (fundTotal - lockedTotal)))
3504- then throw(((("Delivery is not available, fund=" + fixedPoint(fundTotal, 6)) + ", locked=") + fixedPoint(lockedTotal, 6)))
3505- else {
3506- let now = lastBlock.timestamp
3507- let delayETA = valueOrElse(getInteger(keyDeliveryDelayByDuck(duckAssetId)), 0)
3508- if ((delayETA > now))
3509- then throw(("Delivery is forbidden for your duck until " + toString(delayETA)))
3510- else {
3511- let health = getIntegerValue(keyDuckHealth(duckAssetId))
3512- if ((0 >= health))
3513- then throw("You cannot accept delivery with zero health")
3514- else {
3515- let countKey = keyUserDeliveryCount(userAddr)
3516- let count = valueOrElse(getInteger(countKey), 0)
3517- let lastDay = valueOrElse(getInteger(keyUserLastDeliveryDay(userAddr)), 0)
3518- let today = (now / DAYMILLIS)
3519- let acres = valueOrElse(getInteger(acresContract, keyAcresStakedAmountByUser(userAddr)), 0)
3520- let allowedDeliveries = (ALLOWED_FREE_DELIVERIES + (acres / ACRES_FOR_DELIVERY_ATTEMPT))
3521- if (if ((count >= allowedDeliveries))
3522- then (lastDay == today)
3523- else false)
3524- then throw((("You already used " + toString(allowedDeliveries)) + " delivery attempts for today"))
3525- else if (checkTournament(duckAssetId))
3526- then throw("acceptDelivery_checkTournament")
3527- else if (checkDelivery(duckAssetId))
3528- then throw("acceptDelivery_checkDelivery")
3529- else {
3530- let newLockedTotal = asInt(invoke(economyContract, "updateDeliveryLocked", [(lockedTotal + MIN_USDT_FEE_DELIVERY)], nil))
3531- let curLocKey = keyDuckLocation(duckAssetId)
3532- let curLocation = valueOrElse(getString(curLocKey), DEFAULTLOCATION)
3533- let deliveryLocation = (toString(now) + "_D_0")
3534- $Tuple2(([StringEntry(keySavedLocation(duckAssetId), curLocation), StringEntry(curLocKey, deliveryLocation), IntegerEntry(countKey, if ((lastDay != today))
3535- then 0
3536- else count)] ++ prologActions), $Tuple2(deliveryLocation, newLockedTotal))
3537- }
3538- }
3539- }
3540- }
3541- }
3542-
3543-
3544-
3545-@Callable(i)
3546-func checkDeliveryCallback (duckAssetId) = if ((i.caller != tournamentContract))
3547- then throw("Access denied")
3548- else $Tuple2(nil, checkDelivery(duckAssetId))
35493325
35503326
35513327
35523328 @Callable(i)
35533329 func buyRoboDuck () = if (!(KS_ALLOW_ROBO_DUCKS))
35543330 then throw("Feature is turned off")
35553331 else {
35563332 let prologActions = prolog(i)
35573333 if ((size(i.payments) != 1))
35583334 then throw("Exactly one payment required")
35593335 else {
35603336 let pmt = value(i.payments[0])
35613337 if ((pmt.assetId != usdtAssetId))
35623338 then throw("Allowed USDT payment only!")
35633339 else if ((pmt.amount != ROBO_DUCK_USDT))
35643340 then throw((("Payment attached should be " + fixedPoint(ROBO_DUCK_USDT, 6)) + " USDT"))
35653341 else {
35663342 let nextNum = valueOrElse(getInteger(keyNextRoboDuck()), 0)
35673343 let bytez = toBytes(nextNum)
35683344 let name = ((ROBO_PREFIX + "-") + takeRight(toBase16String(bytez), 8))
35693345 let color = takeRight(toBase16String(sha256_16Kb(bytez)), 6)
35703346 let issue = Issue(name, ("Robo Duck NFT for WavesLands game, background color = #" + color), 1, 0, false)
35713347 let assetId = calculateAssetId(issue)
35723348 $Tuple2(((((prologActions :+ IntegerEntry(keyNextRoboDuck(), (nextNum + 1))) :+ issue) :+ ScriptTransfer(i.originCaller, 1, assetId)) :+ ScriptTransfer(economyContract, pmt.amount, usdtAssetId)), $Tuple2(toBase58String(assetId), color))
35733349 }
35743350 }
35753351 }
35763352
35773353

github/deemru/w8io/03bedc9 
291.51 ms