tx · 7jFHSfB9KugXPtzH4vmeT5bVSqDzf3RvDaQxRft5JtXD

3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm:  -0.02000000 Waves

2022.12.24 04:21 [2373700] smart account 3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm > SELF 0.00000000 Waves

{ "type": 13, "id": "7jFHSfB9KugXPtzH4vmeT5bVSqDzf3RvDaQxRft5JtXD", "fee": 2000000, "feeAssetId": null, "timestamp": 1671844873210, "version": 2, "chainId": 84, "sender": "3NDCyBG5q85JuaRiigUeEtainyjCQT3XpZm", "senderPublicKey": "EVooykMNV691Venwp1dHUTBd7KWequzUcda57Wd3LQEX", "proofs": [ "2sm6MFVpNNf2dMvGpLJwxtoV4AdzTAzftLBQPBGzRYqJDidGFNJ8mxiEoRqa8cy8ykU68XfcVrex6dkLqAHgmNaJ" ], "script": "base64:BgI0CAISABIDCgEIEgASAwoBCBIECgIBCBIECgICAhIECgIBCBIECgIBARIECgIICBIECgICAjwABWNoYWluCQCwCQEJAMkBAgkAygECCAUEdGhpcwVieXRlcwABAAEAC3VzZG5Bc3NldElkBAckbWF0Y2gwBQVjaGFpbgMJAAACAgFXBQckbWF0Y2gwASC2JinDBPXOU5GkDkt1JC9kjFGx+t+vVCm9SNIdKrKq0QMJAAACAgFUBQckbWF0Y2gwASD3dur394PKZdtuE+4CO89YKZWpwdGN8kvabNgdYoDI3gkAAgECDVVua25vd24gY2hhaW4ADWluY3ViYXRvckFkZHIEByRtYXRjaDAFBWNoYWluAwkAAAICAVcFByRtYXRjaDAJARFAZXh0ck5hdGl2ZSgxMDYyKQECIzNQRWt0VnV4MlJoY2hTTjYzRHNEbzRiNG16NFFxektTZUR2AwkAAAICAVQFByRtYXRjaDAFBHRoaXMJAAIBAg1Vbmtub3duIGNoYWluAAticmVlZGVyQWRkcgQHJG1hdGNoMAUFY2hhaW4DCQAAAgIBVwUHJG1hdGNoMAkBEUBleHRyTmF0aXZlKDEwNjIpAQIjM1BEVnVVNDVIN0VoNWRtdE5iblJOUlN0R3dVTEE3Tlk2SGIDCQAAAgIBVAUHJG1hdGNoMAUEdGhpcwkAAgECDVVua25vd24gY2hhaW4AC2Vjb25vbXlBZGRyBAckbWF0Y2gwBQVjaGFpbgMJAAACAgFXBQckbWF0Y2gwCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzUDJzazFLbmNTeFJhWnM4YjRDV0dQdzJqa3Z2YXY3NHU0RAMJAAACAgFUBQckbWF0Y2gwCQERQGV4dHJOYXRpdmUoMTA2MikBAiMzTjh5NHd4WDNKQzRUZHJDSkJYWDE2U2pXZjZYMjU2aHJlcAkAAgECDVVua25vd24gY2hhaW4AA3B1YgEgT1PiGj9UqNadUk4THUYnVb2zU/Mse8lUVLD/Q8G0FCgACEhFQUxDT1NUAJBOAApMQU5EUFJFRklYAgRMQU5EAApEVUNLUFJFRklYAgREVUNLAA9ERUZBVUxUTE9DQVRJT04CD0FmcmljYV9GX0FmcmljYQAGTlVNUkVTAAYAD0RBSUxZUkVTQllQSUVDRQCA+NIBAAlEQVlNSUxMSVMAgLiZKQARRklWRU1JTlVURVNNSUxMSVMA4KcSABBSRVNPVVJDRVBSSUNFTUlOANXWCQAMRVhQTUFURVJJQUxTAMuA1bPLBAAFTVVMVDYAwIQ9AAVGSVZFWAkAtgIBAAUAB1RXRU5UWVgJALYCAQAUAAhUV0VOVFkyWAkAtgIBCQBoAgAUABQACFRXRU5UWTNYCQC2AgEJAGgCCQBoAgAUABQAFAAIVFdFTlRZNFgJALYCAQkAaAIJAGgCCQBoAgAUABQAFAAUAAhUV0VOVFk1WAkAtgIBCQBoAgkAaAIJAGgCCQBoAgAUABQAFAAUABQACG1hdFR5cGVzCQDMCAICBEZ1ZWwJAMwIAgIFTWV0YWwJAMwIAgIFUGxhbmsJAMwIAgIFR2xhc3MJAMwIAgIHUGxhc3RpYwkAzAgCAgdQcm90ZWluBQNuaWwACmNvbnRpbmVudHMJAMwIAgIEQXNpYQkAzAgCAgZFdXJvcGUJAMwIAgIIQW1lcmljYXMJAMwIAgIHT2NlYW5pYQkAzAgCAgZBZnJpY2EFA25pbAESa2V5TmV4dEZyZWVMYW5kTnVtAAILbmV4dExhbmROdW0BEmtleUZyZWVMYW5kTnVtc01hcAACD2ZyZWVMYW5kTnVtc01hcAEQa2V5TGFuZFRvQXNzZXRJZAEHbGFuZE51bQkArAICAgxsYW5kVG9Bc3NldF8FB2xhbmROdW0BCmtleU5mdE5hbWUCB2xhbmROdW0IbGFuZFNpemUJAKwCAgkArAICBQpMQU5EUFJFRklYBQdsYW5kTnVtBQhsYW5kU2l6ZQEVa2V5TGFuZEFzc2V0SWRUb093bmVyAQdhc3NldElkCQCsAgICCW5mdE93bmVyXwUHYXNzZXRJZAEQa2V5RHVja0lkVG9Pd25lcgEHYXNzZXRJZAkArAICAgpkdWNrT3duZXJfBQdhc3NldElkARZrZXlTdGFrZWRUaW1lQnlBc3NldElkAQdhc3NldElkCQCsAgICC3N0YWtlZFRpbWVfBQdhc3NldElkARRrZXlTdGFrZWREdWNrQnlPd25lcgEJb3duZXJBZGRyCQCsAgICEnN0YWtlZER1Y2tCeU93bmVyXwUJb3duZXJBZGRyASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwduZnRUeXBlB2Fzc2V0SWQJb3duZXJBZGRyCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgIgc3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcl8FB25mdFR5cGUCAV8FB2Fzc2V0SWQCAV8FCW93bmVyQWRkcgERa2V5TGFuZE51bVRvT3duZXIBB2xhbmROdW0JAKwCAgIKbGFuZE93bmVyXwUHbGFuZE51bQERa2V5QmFja3BhY2tCeUR1Y2sBC2R1Y2tBc3NldElkCQCsAgICCWJhY2tQYWNrXwULZHVja0Fzc2V0SWQBD2tleUR1Y2tMb2NhdGlvbgELZHVja0Fzc2V0SWQJAKwCAgINZHVja0xvY2F0aW9uXwULZHVja0Fzc2V0SWQBDWtleUR1Y2tIZWFsdGgBC2R1Y2tBc3NldElkCQCsAgICC2R1Y2tIZWFsdGhfBQtkdWNrQXNzZXRJZAERa2V5UmVzUHJvcG9ydGlvbnMAAhNyZXNUeXBlc1Byb3BvcnRpb25zAApyZWNMYW5kTnVtAAAAC3JlY0xhbmRTaXplAAEAC3JlY1RlcnJhaW5zAAIADHJlY0NvbnRpbmVudAADAA9sb2NJZHhDb250aW5lbnQAAAAKbG9jSWR4VHlwZQABAAhsb2NJZHhJZAACAApicElkeExldmVsAAAACGJwSWR4UmVzAAEACGJwSWR4TWF0AAIACWJwSWR4UHJvZAADARJnZXROZWVkZWRNYXRlcmlhbHMABAVwcm9wcwkAtQkCCQEFdmFsdWUBCQCiCAEJARFrZXlSZXNQcm9wb3J0aW9ucwACAV8DCQECIT0CCQCQAwEFBXByb3BzBQZOVU1SRVMJAAIBAhZXcm9uZyBwcm9wb3J0aW9ucyBkYXRhBAFyCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAACQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwABCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwACCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwADCQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAECQDMCAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVwcm9wcwAFBQNuaWwEA3N1bQkAZAIJAGQCCQBkAgkAZAIJAGQCCQCRAwIFAXIAAAkAkQMCBQFyAAEJAJEDAgUBcgACCQCRAwIFAXIAAwkAkQMCBQFyAAQJAJEDAgUBcgAFAwkAZwIAAAUDc3VtCQACAQIPTm8gbGFuZHMgc3Rha2VkBAVub3JtNgkAawMFDEVYUE1BVEVSSUFMUwUFTVVMVDYFA3N1bQoBCm5vcm1hbGl6ZXICA2FjYwRlbGVtCQDNCAIFA2FjYwkAawMFBGVsZW0FBW5vcm02BQVNVUxUNgoAAiRsBQFyCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQpub3JtYWxpemVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGARFzdWJ0cmFjdE1hdGVyaWFscwIDaGFzBG5lZWQKAQpzdWJ0cmFjdG9yAgNhY2MDaWR4BAZyZXN1bHQJAGUCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUDaGFzBQNpZHgJAJEDAgUEbmVlZAUDaWR4AwkAZgIAAAUGcmVzdWx0CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICGE5vdCBlbm91Z2ggbWF0ZXJpYWwgaWR4PQkApAMBBQNpZHgCCywgeW91IGhhdmUgCQCRAwIFA2hhcwUDaWR4AgssIGJ1dCBuZWVkIAkApAMBCQCRAwIFBG5lZWQFA2lkeAkAzQgCBQNhY2MJAKQDAQUGcmVzdWx0CgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEKc3VidHJhY3RvcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgERdXBkYXRlUHJvcG9ydGlvbnMDDXRlcnJhaW5Db3VudHMNbGFuZFNpemVJbmRleARzaWduBAVwcm9wcwkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEJARFrZXlSZXNQcm9wb3J0aW9ucwACCzBfMF8wXzBfMF8wAgFfAwkBAiE9AgkAkAMBBQVwcm9wcwUGTlVNUkVTCQACAQIWV3JvbmcgcHJvcG9ydGlvbnMgZGF0YQoBB3VwZGF0ZXICA2FjYwFpBAZyZXN1bHQJAGQCCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFcHJvcHMFAWkJAGgCCQBoAgUEc2lnbgkAkQMCBQ10ZXJyYWluQ291bnRzBQFpBQ1sYW5kU2l6ZUluZGV4AwkAZgIAAAUGcmVzdWx0CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICAhZQYW5pYyEgUGllY2VzIG9mIHR5cGU9CQCkAwEFAWkCBywgc2lnbj0JAKQDAQUEc2lnbgIULCAgdGVycmFpbkNvdW50c1tpXT0JAKQDAQkAkQMCBQ10ZXJyYWluQ291bnRzBQFpAhAsIGxhbmRTaXplSW5kZXg9CQCkAwEFDWxhbmRTaXplSW5kZXgJAM0IAgUDYWNjCQCkAwEFBnJlc3VsdAQBcgoAAiRsCQDMCAIAAAkAzAgCAAEJAMwIAgACCQDMCAIAAwkAzAgCAAQJAMwIAgAFBQNuaWwKAAIkcwkAkAMBBQIkbAoABSRhY2MwBQNuaWwKAQUkZjBfMQICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkBB3VwZGF0ZXICBQIkYQkAkQMCBQIkbAUCJGkKAQUkZjBfMgICJGECJGkDCQBnAgUCJGkFAiRzBQIkYQkAAgECE0xpc3Qgc2l6ZSBleGNlZWRzIDYJAQUkZjBfMgIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIJAQUkZjBfMQIFBSRhY2MwAAAAAQACAAMABAAFAAYJALkJAgUBcgIBXwENY291bnRUZXJyYWlucwEIdGVycmFpbnMJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBQQABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUIAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFDAAEJAMwIAgkAZQIJAJADAQkAtQkCBQh0ZXJyYWlucwIBRAABCQDMCAIJAGUCCQCQAwEJALUJAgUIdGVycmFpbnMCAUUAAQkAzAgCCQBlAgkAkAMBCQC1CQIFCHRlcnJhaW5zAgFGAAEFA25pbAEPbnVtUGllY2VzQnlTaXplAQhsYW5kU2l6ZQQHJG1hdGNoMAUIbGFuZFNpemUDCQAAAgIBUwUHJG1hdGNoMAAZAwkAAAICAU0FByRtYXRjaDAAZAMJAAACAgFMBQckbWF0Y2gwAOEBAwkAAAICAlhMBQckbWF0Y2gwAJADAwkAAAICA1hYTAUHJG1hdGNoMADxBAkAAgECEVVua25vd24gbGFuZCBzaXplAQxzdWJPbmVJbkxpc3QDBWFMaXN0A2lkeAZhbW91bnQKAQZzdWJiZXICA2FjYwFpCQDNCAIFA2FjYwMJAAACBQFpBQNpZHgJAKQDAQkAZQIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQVhTGlzdAUBaQUGYW1vdW50CQCRAwIFBWFMaXN0BQFpBAFyCgACJGwJAMwIAgAACQDMCAIAAQkAzAgCAAIJAMwIAgADCQDMCAIABAkAzAgCAAUFA25pbAoAAiRzCQCQAwEFAiRsCgAFJGFjYzAFA25pbAoBBSRmMF8xAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQEGc3ViYmVyAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA2CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQAGCQC5CQIFAXICAV8BBmFkZFJlcwQKY3VycmVudFJlcw10ZXJyYWluQ291bnRzCWRlbHRhVGltZQ1sYW5kU2l6ZUluZGV4CgEFYWRkZXICA2FjYwFpBAlyZXNPZlR5cGUJAGgCCQBoAgkAawMFCWRlbHRhVGltZQUPREFJTFlSRVNCWVBJRUNFBQlEQVlNSUxMSVMJAJEDAgUNdGVycmFpbkNvdW50cwUBaQUNbGFuZFNpemVJbmRleAkAzQgCBQNhY2MJAKQDAQkAZAIJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpjdXJyZW50UmVzBQFpBQlyZXNPZlR5cGUEAXIKAAIkbAkAzAgCAAAJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAUDbmlsCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAQVhZGRlcgIFAiRhCQCRAwIFAiRsBQIkaQoBBSRmMF8yAgIkYQIkaQMJAGcCBQIkaQUCJHMFAiRhCQACAQITTGlzdCBzaXplIGV4Y2VlZHMgNgkBBSRmMF8yAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgkBBSRmMF8xAgUFJGFjYzAAAAABAAIAAwAEAAUABgkAuQkCBQFyAgFfAQNhYnMBAXgDCQDAAgIFAXgJALYCAQAABQF4CQC+AgEFAXgABGZyZXEJAMwIAgkAzAgCAAEJAMwIAgAECQDMCAIACQkAzAgCAAoJAMwIAgAPBQNuaWwJAMwIAgkAzAgCAAUJAMwIAgAICQDMCAIADQkAzAgCAA4JAMwIAgAPBQNuaWwJAMwIAgkAzAgCAAYJAMwIAgAJCQDMCAIADgkAzAgCAA8JAMwIAgAQBQNuaWwJAMwIAgkAzAgCAAQJAMwIAgAHCQDMCAIACAkAzAgCAA0JAMwIAgASBQNuaWwJAMwIAgkAzAgCAAEJAMwIAgAGCQDMCAIABwkAzAgCAA8JAMwIAgATBQNuaWwFA25pbAEHZ2VuQ2hhcgIBbgVmcmVxcwQDcmVtCQCgAwEJALsCAgUBbgUHVFdFTlRZWAQGbGV0dGVyAwkAZgIJAJEDAgUFZnJlcXMAAAUDcmVtAgFBAwkAZgIJAJEDAgUFZnJlcXMAAQUDcmVtAgFCAwkAZgIJAJEDAgUFZnJlcXMAAgUDcmVtAgFDAwkAZgIJAJEDAgUFZnJlcXMAAwUDcmVtAgFEAwkAZgIJAJEDAgUFZnJlcXMABAUDcmVtAgFFAgFGBQZsZXR0ZXIKAWkBCXN0YWtlTGFuZAAEA3BtdAkBBXZhbHVlAQkAkQMCCAUBaQhwYXltZW50cwAABAdhc3NldElkCQEFdmFsdWUBCAUDcG10B2Fzc2V0SWQEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyAwkBAiE9AggFA3BtdAZhbW91bnQAAQkAAgEJAKwCAgkArAICAgRORlQgBQpMQU5EUFJFRklYAiQgdG9rZW4gc2hvdWxkIGJlIGF0dGFjaGVkIGFzIHBheW1lbnQEBWFzc2V0CQEFdmFsdWUBCQDsBwEFB2Fzc2V0SWQDCQECIT0CCAUFYXNzZXQGaXNzdWVyBQR0aGlzCQACAQIXVW5rbm93biBpc3N1ZXIgb2YgdG9rZW4DCQEBIQEJAQhjb250YWlucwIIBQVhc3NldARuYW1lBQpMQU5EUFJFRklYCQACAQkArAICCQCsAgICCU9ubHkgTkZUIAUKTEFORFBSRUZJWAIUIHRva2VucyBhcmUgYWNjZXB0ZWQEC2xhbmROdW1TaXplCQCwAgIIBQVhc3NldARuYW1lAAQEB2xhbmROdW0DCQEIY29udGFpbnMCBQtsYW5kTnVtU2l6ZQIDWFhMCQCzAgIFC2xhbmROdW1TaXplAAMDCQEIY29udGFpbnMCBQtsYW5kTnVtU2l6ZQICWEwJALMCAgULbGFuZE51bVNpemUAAgkAswICBQtsYW5kTnVtU2l6ZQABAwkBASEBCQEJaXNEZWZpbmVkAQkAtgkBBQdsYW5kTnVtCQACAQkArAICAh5DYW5ub3QgcGFyc2UgbGFuZCBudW1iZXIgZnJvbSAIBQVhc3NldARuYW1lBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEJANgEAQUHYXNzZXRJZAMJAQlpc0RlZmluZWQBCQCfCAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCEiBpcyBhbHJlYWR5IHN0YWtlZAQBZAkAtQkCCAUFYXNzZXQLZGVzY3JpcHRpb24CAV8EDXRlcnJhaW5Db3VudHMJAQ1jb3VudFRlcnJhaW5zAQkAkQMCBQFkBQtyZWNUZXJyYWlucwQFcHJvcHMJARF1cGRhdGVQcm9wb3J0aW9ucwMFDXRlcnJhaW5Db3VudHMJAGkCCQEPbnVtUGllY2VzQnlTaXplAQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQAZAAEJAMwIAgkBDEludGVnZXJFbnRyeQIFB3RpbWVLZXkIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQxJbnRlZ2VyRW50cnkCCQEia2V5U3Rha2VkVGltZUJ5VHlwZUFzc2V0SWRBbmRPd25lcgMFCkxBTkRQUkVGSVgJANgEAQUHYXNzZXRJZAUHYWRkcmVzcwgFCWxhc3RCbG9jawl0aW1lc3RhbXAJAMwIAgkBC1N0cmluZ0VudHJ5AgkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEJANgEAQUHYXNzZXRJZAUHYWRkcmVzcwkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5TGFuZE51bVRvT3duZXIBBQdsYW5kTnVtBQdhZGRyZXNzCQDMCAIJAQtTdHJpbmdFbnRyeQIJARFrZXlSZXNQcm9wb3J0aW9ucwAFBXByb3BzBQNuaWwBaQELdW5zdGFrZUxhbmQBC2xhbmRBc3NldElkAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIkdW5zdGFrZSBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAdhc3NldElkCQDZBAEFC2xhbmRBc3NldElkBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgQFYXNzZXQJAQV2YWx1ZQEJAOwHAQUHYXNzZXRJZAMJAQIhPQIIBQVhc3NldAZpc3N1ZXIFBHRoaXMJAAIBAhdVbmtub3duIGlzc3VlciBvZiB0b2tlbgMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkxBTkRQUkVGSVgJAAIBCQCsAgIJAKwCAgIJT25seSBORlQgBQpMQU5EUFJFRklYAhcgdG9rZW5zIGNhbiBiZSB1bnN0YWtlZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAMJAQEhAQkBCWlzRGVmaW5lZAEFB3RpbWVLZXkJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQtsYW5kQXNzZXRJZAkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAgwgaXMgb3JwaGFuZWQDCQECIT0CBQVvd25lcgUHYWRkcmVzcwkAAgECF1N0YWtlZCBORlQgaXMgbm90IHlvdXJzBAFkCQC1CQIIBQVhc3NldAtkZXNjcmlwdGlvbgIBXwQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIFAWQFC3JlY1RlcnJhaW5zBAVwcm9wcwkBEXVwZGF0ZVByb3BvcnRpb25zAwUNdGVycmFpbkNvdW50cwkAaQIJAQ9udW1QaWVjZXNCeVNpemUBCQCRAwIFAWQFC3JlY0xhbmRTaXplABkA////////////AQkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIAAQUHYXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBBQd0aW1lS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKTEFORFBSRUZJWAULbGFuZEFzc2V0SWQFB2FkZHJlc3MJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleVJlc1Byb3BvcnRpb25zAAUFcHJvcHMFA25pbAFpAQlzdGFrZUR1Y2sABANwbXQJAQV2YWx1ZQEJAJEDAggFAWkIcGF5bWVudHMAAAQHYXNzZXRJZAkBBXZhbHVlAQgFA3BtdAdhc3NldElkBAdhZGRyZXNzCQClCAEIBQFpBmNhbGxlcgMJAQIhPQIIBQNwbXQGYW1vdW50AAEJAAIBCQCsAgIJAKwCAgIETkZUIAUKRFVDS1BSRUZJWAIkIHRva2VuIHNob3VsZCBiZSBhdHRhY2hlZCBhcyBwYXltZW50BAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkAwMJAQIhPQIIBQVhc3NldAZpc3N1ZXIFDWluY3ViYXRvckFkZHIJAQIhPQIIBQVhc3NldAZpc3N1ZXIFC2JyZWVkZXJBZGRyBwkAAgEJAKwCAgkArAICAhJVbmtub3duIGlzc3VlciBvZiAFCkRVQ0tQUkVGSVgCBiB0b2tlbgMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkRVQ0tQUkVGSVgJAAIBCQCsAgIJAKwCAgIJT25seSBORlQgBQpEVUNLUFJFRklYAhQgdG9rZW5zIGFyZSBhY2NlcHRlZAQKYXNzZXRJZFN0cgkA2AQBBQdhc3NldElkBAd0aW1lS2V5CQEWa2V5U3Rha2VkVGltZUJ5QXNzZXRJZAEFCmFzc2V0SWRTdHIDCQEJaXNEZWZpbmVkAQkAnwgBBQd0aW1lS2V5CQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAhIgaXMgYWxyZWFkeSBzdGFrZWQDCQEJaXNEZWZpbmVkAQkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzCQACAQkArAICAh1Zb3UgYWxyZWFkeSBzdGFrZWQgb25lIGR1Y2s6IAgFBWFzc2V0BG5hbWUEBmxvY0tleQkBD2tleUR1Y2tMb2NhdGlvbgEFCmFzc2V0SWRTdHIECGxvY2F0aW9uCQCiCAEFBmxvY0tleQQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFCmFzc2V0SWRTdHIEBmhlYWx0aAkAnwgBBQlrZXlIZWFsdGgEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQphc3NldElkU3RyBAhiYWNrcGFjawkAoggBBQVicEtleQkAzggCCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQd0aW1lS2V5CAUJbGFzdEJsb2NrCXRpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpEVUNLUFJFRklYCQDYBAEFB2Fzc2V0SWQFB2FkZHJlc3MIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQDMCAIJAQtTdHJpbmdFbnRyeQIJARBrZXlEdWNrSWRUb093bmVyAQUKYXNzZXRJZFN0cgUHYWRkcmVzcwkAzAgCCQELU3RyaW5nRW50cnkCCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzBQphc3NldElkU3RyBQNuaWwDCQEJaXNEZWZpbmVkAQUIbG9jYXRpb24FA25pbAkAzggCCQDMCAIJAQtTdHJpbmdFbnRyeQIFBmxvY0tleQUPREVGQVVMVExPQ0FUSU9OBQNuaWwDCQEJaXNEZWZpbmVkAQUGaGVhbHRoBQNuaWwJAM4IAgkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoAGQFA25pbAMJAQlpc0RlZmluZWQBBQhiYWNrcGFjawUDbmlsCQDMCAIJAQtTdHJpbmdFbnRyeQIFBWJwS2V5AhowOjBfMF8wXzBfMF8wOjBfMF8wXzBfMF8wOgUDbmlsAWkBC3Vuc3Rha2VEdWNrAQphc3NldElkU3RyAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQIkdW5zdGFrZSBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAdhc3NldElkCQDZBAEFCmFzc2V0SWRTdHIEB2FkZHJlc3MJAKUIAQgFAWkGY2FsbGVyBAVhc3NldAkBBXZhbHVlAQkA7AcBBQdhc3NldElkAwMJAQIhPQIIBQVhc3NldAZpc3N1ZXIFDWluY3ViYXRvckFkZHIJAQIhPQIIBQVhc3NldAZpc3N1ZXIFC2JyZWVkZXJBZGRyBwkAAgEJAKwCAgkArAICAhJVbmtub3duIGlzc3VlciBvZiAFCkRVQ0tQUkVGSVgCBiB0b2tlbgMJAQEhAQkBCGNvbnRhaW5zAggFBWFzc2V0BG5hbWUFCkRVQ0tQUkVGSVgJAAIBCQCsAgIJAKwCAgIJT25seSBORlQgBQpEVUNLUFJFRklYAhcgdG9rZW5zIGNhbiBiZSB1bnN0YWtlZAQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBCQDYBAEFB2Fzc2V0SWQDCQEBIQEJAQlpc0RlZmluZWQBBQd0aW1lS2V5CQACAQkArAICCQCsAgICBE5GVCAIBQVhc3NldARuYW1lAg4gaXMgbm90IHN0YWtlZAMJAQEhAQkBCWlzRGVmaW5lZAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFB2FkZHJlc3MJAAIBCQCsAgIJAKwCAgIJVGhlIGR1Y2sgCAUFYXNzZXQEbmFtZQIOIGlzIG5vdCBzdGFrZWQEBW93bmVyCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBEGtleUR1Y2tJZFRvT3duZXIBCQDYBAEFB2Fzc2V0SWQJAKwCAgkArAICAgRORlQgCAUFYXNzZXQEbmFtZQIMIGlzIG9ycGhhbmVkAwkBAiE9AgUFb3duZXIFB2FkZHJlc3MJAAIBAhdTdGFrZWQgTkZUIGlzIG5vdCB5b3VycwkAzAgCCQEOU2NyaXB0VHJhbnNmZXIDCAUBaQZjYWxsZXIAAQUHYXNzZXRJZAkAzAgCCQELRGVsZXRlRW50cnkBBQd0aW1lS2V5CQDMCAIJAQtEZWxldGVFbnRyeQEJAQ9rZXlEdWNrTG9jYXRpb24BBQphc3NldElkU3RyCQDMCAIJAQtEZWxldGVFbnRyeQEJASJrZXlTdGFrZWRUaW1lQnlUeXBlQXNzZXRJZEFuZE93bmVyAwUKRFVDS1BSRUZJWAUKYXNzZXRJZFN0cgUHYWRkcmVzcwkAzAgCCQELRGVsZXRlRW50cnkBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBBQdhZGRyZXNzBQNuaWwBaQEIY2xhaW1SZXMCBmFtb3VudAtsYW5kQXNzZXRJZAMJAQIhPQIJAJADAQgFAWkIcGF5bWVudHMAAAkAAgECJWNsYWltUmVzIGRvZXNuJ3QgcmVxdWlyZSBhbnkgcGF5bWVudHMEBGFkZHIJAKUIAQgFAWkGY2FsbGVyBAVhc3NldAkBBXZhbHVlAQkA7AcBCQDZBAEFC2xhbmRBc3NldElkAwkBASEBCQEIY29udGFpbnMCCAUFYXNzZXQEbmFtZQUKTEFORFBSRUZJWAkAAgEJAKwCAgkArAICAgRORlQgBQpMQU5EUFJFRklYAiAgdG9rZW4gc2hvdWxkIGJlIHBhc3NlZCBhcyBwYXJhbQQHdGltZUtleQkBFmtleVN0YWtlZFRpbWVCeUFzc2V0SWQBBQtsYW5kQXNzZXRJZAQJc2F2ZWRUaW1lCQCfCAEFB3RpbWVLZXkDCQEBIQEJAQlpc0RlZmluZWQBBQlzYXZlZFRpbWUJAAIBCQCsAgIJAKwCAgIETkZUIAgFBWFzc2V0BG5hbWUCDiBpcyBub3Qgc3Rha2VkBAVvd25lcgkBEUBleHRyTmF0aXZlKDEwNTgpAQkBFWtleUxhbmRBc3NldElkVG9Pd25lcgEFC2xhbmRBc3NldElkAwkBAiE9AgUFb3duZXIFBGFkZHIJAAIBCQCsAgIFCkxBTkRQUkVGSVgCDSBpcyBub3QgeW91cnMEAWQJALUJAggFBWFzc2V0C2Rlc2NyaXB0aW9uAgFfBAhsYW5kU2l6ZQkAkQMCBQFkBQtyZWNMYW5kU2l6ZQQNdGVycmFpbkNvdW50cwkBDWNvdW50VGVycmFpbnMBCQCRAwIFAWQFC3JlY1RlcnJhaW5zBARkdWNrCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFBGFkZHIDCQEBIQEJAQlpc0RlZmluZWQBBQRkdWNrCQACAQIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQOZHVja0Fzc2V0SWRTdHIJAQV2YWx1ZQEFBGR1Y2sEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEJAQ9rZXlEdWNrTG9jYXRpb24BBQ5kdWNrQXNzZXRJZFN0cgUPREVGQVVMVExPQ0FUSU9OBANsb2MJALUJAgkBBXZhbHVlAQULY3VyTG9jYXRpb24CAV8DCQECIT0CCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIBTAkAAgEJAKwCAgkArAICAhZEdWNrIGxvY2F0aW9uIHR5cGUgaXMgCQCRAwIFA2xvYwUKbG9jSWR4VHlwZQIRLCBidXQgc2hvdWxkIGJlIEwDCQECIT0CCQCRAwIFA2xvYwUIbG9jSWR4SWQFC2xhbmRBc3NldElkCQACAQkArAICCQCsAgIJAKwCAgIURHVjayBsb2NhdGlvbiBpZCBpcyAJAJEDAgUDbG9jBQhsb2NJZHhJZAIQLCBidXQgc2hvdWxkIGJlIAULbGFuZEFzc2V0SWQECWRlbHRhVGltZQkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wCQEFdmFsdWUBBQlzYXZlZFRpbWUDCQBmAgAABQlkZWx0YVRpbWUJAAIBCQCsAgIJAKwCAgkArAICAiZTYXZlZCB0aW1lc3RhbXAgaXMgaW4gZnV0dXJlLCBzYXZlZCA9IAkApAMBCQEFdmFsdWUBBQlzYXZlZFRpbWUCDCwgY3VycmVudCA9IAkApAMBCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAQGcGllY2VzCQEPbnVtUGllY2VzQnlTaXplAQUIbGFuZFNpemUECGF2YWlsUmVzCQBoAgkAawMFCWRlbHRhVGltZQUPREFJTFlSRVNCWVBJRUNFBQlEQVlNSUxMSVMFBnBpZWNlcwMJAGYCBQZhbW91bnQFCGF2YWlsUmVzCQACAQkArAICCQCsAgIJAKwCAgIiTm90IGVub3VnaCByZXNvdXJjZXMsIGF2YWlsYWJsZSA9IAkApAMBBQhhdmFpbFJlcwIOLCByZXF1ZXN0ZWQgPSAJAKQDAQUGYW1vdW50BAxuZXdEZWx0YVRpbWUJAGsDCQBlAgUIYXZhaWxSZXMFBmFtb3VudAUJREFZTUlMTElTCQBoAgUGcGllY2VzBQ9EQUlMWVJFU0JZUElFQ0UEDG5ld1RpbWVzdGFtcAkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBQxuZXdEZWx0YVRpbWUEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQ5kdWNrQXNzZXRJZFN0cgQLY3VycmVudFBhY2sJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQVicEtleQIaMDowXzBfMF8wXzBfMDowXzBfMF8wXzBfMDoCAToECmN1cnJlbnRSZXMJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMCAV8EBWJwUmVzCQEGYWRkUmVzBAUKY3VycmVudFJlcwUNdGVycmFpbkNvdW50cwkAZQIFCWRlbHRhVGltZQUMbmV3RGVsdGFUaW1lCQBpAgUGcGllY2VzABkEB25ld1BhY2sJALkJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIFBWJwUmVzCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6CQCUCgIJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkFB25ld1BhY2sJAMwIAgkBDEludGVnZXJFbnRyeQIFB3RpbWVLZXkFDG5ld1RpbWVzdGFtcAkAzAgCCQEMSW50ZWdlckVudHJ5AgkBImtleVN0YWtlZFRpbWVCeVR5cGVBc3NldElkQW5kT3duZXIDBQpMQU5EUFJFRklYBQtsYW5kQXNzZXRJZAUFb3duZXIFDG5ld1RpbWVzdGFtcAUDbmlsBQR1bml0AWkBBmZsaWdodAIHbWVzc2FnZQNzaWcDCQEBIQEJAMQTAwUHbWVzc2FnZQUDc2lnBQNwdWIJAAIBAhhzaWduYXR1cmUgZG9lcyBub3QgbWF0Y2gDCQECIT0CCQCQAwEIBQFpCHBheW1lbnRzAAAJAAIBAiNmbGlnaHQgZG9lc24ndCByZXF1aXJlIGFueSBwYXltZW50cwQFcGFydHMJALUJAgkAsAkBBQdtZXNzYWdlAgE7BAJocAkAtQkCCQCRAwIJALUJAgkAkQMCBQVwYXJ0cwAAAgF8AAACAV8EBWN1ckhQCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUCaHAAAAQFbmV3SFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAABBA1uZXdMb2NBbmRUaW1lCQC1CQIJAJEDAgUFcGFydHMAAQIBOgQLbmV3TG9jYXRpb24JAJEDAgUNbmV3TG9jQW5kVGltZQAABAR0aW1lCQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUNbmV3TG9jQW5kVGltZQABAwMJAGYCBQR0aW1lCQBkAggFCWxhc3RCbG9jawl0aW1lc3RhbXAFEUZJVkVNSU5VVEVTTUlMTElTBgkAZgIJAGUCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMFBHRpbWUJAAIBAhJzaWduYXR1cmUgb3V0ZGF0ZWQEC2R1Y2tBc3NldElkCQETdmFsdWVPckVycm9yTWVzc2FnZQIJAKIIAQkBFGtleVN0YWtlZER1Y2tCeU93bmVyAQkApQgBCAUBaQZjYWxsZXICHFlvdSBkb24ndCBoYXZlIGEgZHVjayBzdGFrZWQECWtleUhlYWx0aAkBDWtleUR1Y2tIZWFsdGgBBQtkdWNrQXNzZXRJZAQMb2xkRnJvbVN0YXRlCQELdmFsdWVPckVsc2UCCQCfCAEFCWtleUhlYWx0aABkAwkBAiE9AgUMb2xkRnJvbVN0YXRlBQVjdXJIUAkAAgEJAKwCAgkArAICCQCsAgICCm9sZEhlYWx0aD0JAKQDAQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAIvIGZyb20gc3RhdGUgZG9lcyBub3QgbWF0Y2ggb25lIGZyb20gZmxpZ2h0IGxvZz0JAKQDAQUFY3VySFADCQBnAgAABQVjdXJIUAkAAgECHllvdSBjYW4ndCBmbHkgd2l0aCB6ZXJvIGhlYWx0aAQGbG9jS2V5CQEPa2V5RHVja0xvY2F0aW9uAQULZHVja0Fzc2V0SWQEC2N1ckxvY2F0aW9uCQELdmFsdWVPckVsc2UCCQCiCAEFBmxvY0tleQUPREVGQVVMVExPQ0FUSU9OAwkAAAIFC25ld0xvY2F0aW9uBQtjdXJMb2NhdGlvbgkAAgECIllvdSBjYW4ndCBmbHkgdG8gdGhlIHNhbWUgbG9jYXRpb24JAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCBQZsb2NLZXkDCQBmAgUFbmV3SFAAAAULbmV3TG9jYXRpb24FC2N1ckxvY2F0aW9uCQDMCAIJAQxJbnRlZ2VyRW50cnkCBQlrZXlIZWFsdGgFBW5ld0hQBQNuaWwFBHVuaXQBaQEJc2V0SGVhbHRoAgZoZWFsdGgLZHVja0Fzc2V0SWQDAwkAZgIAAAUGaGVhbHRoBgkAZgIFBmhlYWx0aABkCQACAQIaSFAgc2hvdWxkIGJlIHdpdGhpbiAwLi4xMDAJAMwIAgkBDEludGVnZXJFbnRyeQIJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQFBmhlYWx0aAUDbmlsAWkBBGhlYWwCB21hdFR5cGUGYW1vdW50AwMJAGYCAAAFB21hdFR5cGUGCQBnAgUHbWF0VHlwZQUGTlVNUkVTCQACAQkArAICAhJVbmtub3duIG1hdGVyaWFsOiAJAKQDAQUHbWF0VHlwZQMJAGcCAAAFBmFtb3VudAkAAgEJAKwCAgIbQW1vdW50IHNob3VsZCBiZSBwb3NpdGl2ZSEgCQCkAwEFBmFtb3VudAQLZHVja0Fzc2V0SWQJARN2YWx1ZU9yRXJyb3JNZXNzYWdlAgkAoggBCQEUa2V5U3Rha2VkRHVja0J5T3duZXIBCQClCAEIBQFpBmNhbGxlcgIcWW91IGRvbid0IGhhdmUgYSBkdWNrIHN0YWtlZAQJa2V5SGVhbHRoCQENa2V5RHVja0hlYWx0aAEFC2R1Y2tBc3NldElkBAlvbGRIZWFsdGgJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoAGQDCQBnAgUJb2xkSGVhbHRoAGQJAAIBAhpIUCBzaG91bGQgYmUgPCAxMDAgdG8gaGVhbAQFYnBLZXkJARFrZXlCYWNrcGFja0J5RHVjawEFC2R1Y2tBc3NldElkBAtjdXJyZW50UGFjawkAtQkCCQELdmFsdWVPckVsc2UCCQCiCAEFBWJwS2V5AhowOjBfMF8wXzBfMF8wOjBfMF8wXzBfMF8wOgIBOgQHbWF0TGlzdAkAtQkCCQCRAwIFC2N1cnJlbnRQYWNrBQhicElkeE1hdAIBXwQFbUxpc3QDCQECIT0CCQCQAwEFB21hdExpc3QFBk5VTVJFUwkAzAgCAgEwCQDMCAICATAJAMwIAgIBMAkAzAgCAgEwCQDMCAICATAJAMwIAgIBMAUDbmlsBQdtYXRMaXN0BA1jdXJyZW50QW1vdW50CQENcGFyc2VJbnRWYWx1ZQEJAJEDAgUFbUxpc3QFB21hdFR5cGUEC2RlbHRhSGVhbHRoCQCXAwEJAMwIAgkAaQIFBmFtb3VudAUISEVBTENPU1QJAMwIAgkAZQIAZAUJb2xkSGVhbHRoBQNuaWwEC3NwZW5kQW1vdW50CQBoAgULZGVsdGFIZWFsdGgFCEhFQUxDT1NUAwkAZgIFC3NwZW5kQW1vdW50BQ1jdXJyZW50QW1vdW50CQACAQkArAICCQCsAgIJAKwCAgkArAICCQCsAgICCVlvdSBuZWVkIAkApAMBBQtzcGVuZEFtb3VudAIEIG9mIAkAkQMCBQhtYXRUeXBlcwUHbWF0VHlwZQIkIHRvIGhlYWwsIGJ1dCB5b3UgYmFja3BhY2sgY29udGFpbnMgCQCkAwEFDWN1cnJlbnRBbW91bnQEBm5ld01hdAkBDHN1Yk9uZUluTGlzdAMFBW1MaXN0BQdtYXRUeXBlBQtzcGVuZEFtb3VudAkAzAgCCQEMSW50ZWdlckVudHJ5AgUJa2V5SGVhbHRoCQBkAgUJb2xkSGVhbHRoBQtkZWx0YUhlYWx0aAkAzAgCCQELU3RyaW5nRW50cnkCBQVicEtleQkAuQkCCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCmJwSWR4TGV2ZWwJAMwIAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhSZXMJAMwIAgUGbmV3TWF0CQDMCAIJAJEDAgULY3VycmVudFBhY2sFCWJwSWR4UHJvZAUDbmlsAgE6BQNuaWwBaQEOdXBkYXRlQmFja3BhY2sCC2R1Y2tBc3NldElkB25ld1BhY2sDCQECIT0CCAUBaQZjYWxsZXIFC2Vjb25vbXlBZGRyCQACAQIRcGVybWlzc2lvbiBkZW5pZWQJAJQKAgkAzAgCCQELU3RyaW5nRW50cnkCCQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAUHbmV3UGFjawUDbmlsBQduZXdQYWNrAWkBCmV4cGVkaXRpb24CB21lc3NhZ2UDc2lnAwkBASEBCQDEEwMFB21lc3NhZ2UFA3NpZwUDcHViCQACAQIYc2lnbmF0dXJlIGRvZXMgbm90IG1hdGNoAwkBAiE9AgkAkAMBCAUBaQhwYXltZW50cwAACQACAQInZXhwZWRpdGlvbiBkb2Vzbid0IHJlcXVpcmUgYW55IHBheW1lbnRzBAVwYXJ0cwkAtQkCCQCwCQEFB21lc3NhZ2UCATsEAmhwCQC1CQIJAJEDAgkAtQkCCQCRAwIFBXBhcnRzAAACAXwAAAIBXwQFY3VySFAJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQJocAAABAVuZXdIUAkBDXBhcnNlSW50VmFsdWUBCQCRAwIFAmhwAAEECmxvY0FuZFRpbWUJALUJAgkAkQMCBQVwYXJ0cwABAgE6BA50YXJnZXRMb2NhdGlvbgkAtQkCCQCRAwIFCmxvY0FuZFRpbWUAAAIBXwMJAQIhPQIJAJEDAgUOdGFyZ2V0TG9jYXRpb24AAQIBRQkAAgECK2V4cGVkaXRpb24gdGFyZ2V0IGxvY2F0aW9uIHR5cGUgc2hvdWxkIGJlIEUEBHRpbWUJAQ1wYXJzZUludFZhbHVlAQkAkQMCBQpsb2NBbmRUaW1lAAEDAwkAZgIFBHRpbWUJAGQCCAUJbGFzdEJsb2NrCXRpbWVzdGFtcAURRklWRU1JTlVURVNNSUxMSVMGCQBmAgkAZQIIBQlsYXN0QmxvY2sJdGltZXN0YW1wBRFGSVZFTUlOVVRFU01JTExJUwUEdGltZQkAAgECEnNpZ25hdHVyZSBvdXRkYXRlZAQIdXNlckFkZHIJAKUIAQgFAWkGY2FsbGVyBAtkdWNrQXNzZXRJZAkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARRrZXlTdGFrZWREdWNrQnlPd25lcgEFCHVzZXJBZGRyAhxZb3UgZG9uJ3QgaGF2ZSBhIGR1Y2sgc3Rha2VkBAlrZXlIZWFsdGgJAQ1rZXlEdWNrSGVhbHRoAQULZHVja0Fzc2V0SWQEDG9sZEZyb21TdGF0ZQkBC3ZhbHVlT3JFbHNlAgkAnwgBBQlrZXlIZWFsdGgAZAMJAQIhPQIFDG9sZEZyb21TdGF0ZQUFY3VySFAJAAIBCQCsAgIJAKwCAgkArAICAgpvbGRIZWFsdGg9CQCkAwEJAQt2YWx1ZU9yRWxzZQIJAJ8IAQUJa2V5SGVhbHRoAGQCLyBmcm9tIHN0YXRlIGRvZXMgbm90IG1hdGNoIG9uZSBmcm9tIGZsaWdodCBsb2c9CQCkAwEFBWN1ckhQAwkAZwIAAAUFY3VySFAJAAIBAh5Zb3UgY2FuJ3QgZmx5IHdpdGggemVybyBoZWFsdGgDCQBnAgAABQVuZXdIUAkAAgECK1lvdXIgZHVjayBoZWFsdGggaXMgemVybywgZXhwZWRpdGlvbiBmYWlsZWQEBWJwS2V5CQERa2V5QmFja3BhY2tCeUR1Y2sBBQtkdWNrQXNzZXRJZAQLY3VycmVudFBhY2sJALUJAgkBC3ZhbHVlT3JFbHNlAgkAoggBBQVicEtleQIaMDowXzBfMF8wXzBfMDowXzBfMF8wXzBfMDoCAToEB21hdExpc3QJALUJAgkAkQMCBQtjdXJyZW50UGFjawUIYnBJZHhNYXQCAV8EBW1MaXN0AwkBAiE9AgkAkAMBBQdtYXRMaXN0BQZOVU1SRVMJAMwIAgIBMAkAzAgCAgEwCQDMCAICATAJAMwIAgIBMAkAzAgCAgEwCQDMCAICATAFA25pbAUHbWF0TGlzdAQFbU5lZWQJARJnZXROZWVkZWRNYXRlcmlhbHMABAZuZXdNYXQJALkJAgUFbUxpc3QCAV8EBG51bXMJAL0JAgkBE3ZhbHVlT3JFcnJvck1lc3NhZ2UCCQCiCAEJARJrZXlGcmVlTGFuZE51bXNNYXAACQCsAgIJARJrZXlGcmVlTGFuZE51bXNNYXAAAhMgaXMgbm90IGluaXRpYWxpemVkAgFfBANsZW4JAJADAQUEbnVtcwQGYmlnTnVtCQEDYWJzAQkAngMBCAUBaQ10cmFuc2FjdGlvbklkBBBudW1BY3Rpb25BbmRTZWVkAwkAAAIFA2xlbgAABAdmcmVlTnVtCQELdmFsdWVPckVsc2UCCQCfCAEJARJrZXlOZXh0RnJlZUxhbmROdW0AAPUDCQCVCgMJAKQDAQUHZnJlZU51bQkBDEludGVnZXJFbnRyeQIJARJrZXlOZXh0RnJlZUxhbmROdW0ACQBkAgUHZnJlZU51bQABBQZiaWdOdW0EAXEJALYCAQUDbGVuBAZtYXBJZHgJAKADAQkAuwICBQZiaWdOdW0FAXEJAJUKAwkAkQMCBQRudW1zBQZtYXBJZHgJAQtTdHJpbmdFbnRyeQIJARJrZXlGcmVlTGFuZE51bXNNYXAACQC7CQIJANEIAgUEbnVtcwUGbWFwSWR4AgFfCQC6AgIFBmJpZ051bQUBcQQMY29udGluZW50SWR4CQCgAwEJALsCAggFEG51bUFjdGlvbkFuZFNlZWQCXzMFBUZJVkVYBAFmCQCRAwIFBGZyZXEFDGNvbnRpbmVudElkeAoBEHRlcnJhaW5HZW5lcmF0b3ICA2FjYwRlbGVtCQCUCgIJAKwCAgkArAICCQCsAgIJAKwCAgkArAICCAUDYWNjAl8xCQEHZ2VuQ2hhcgIIBQNhY2MCXzIFAWYJAQdnZW5DaGFyAgkAugICCAUDYWNjAl8yBQdUV0VOVFlYBQFmCQEHZ2VuQ2hhcgIJALoCAggFA2FjYwJfMgUIVFdFTlRZMlgFAWYJAQdnZW5DaGFyAgkAugICCAUDYWNjAl8yBQhUV0VOVFkzWAUBZgkBB2dlbkNoYXICCQC6AgIIBQNhY2MCXzIFCFRXRU5UWTRYBQFmCQC6AgIIBQNhY2MCXzIFCFRXRU5UWTVYBAF0CgACJGwJAMwIAgABCQDMCAIAAgkAzAgCAAMJAMwIAgAECQDMCAIABQUDbmlsCgACJHMJAJADAQUCJGwKAAUkYWNjMAkAlAoCAgAJALoCAggFEG51bUFjdGlvbkFuZFNlZWQCXzMFBUZJVkVYCgEFJGYwXzECAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJARB0ZXJyYWluR2VuZXJhdG9yAgUCJGEJAJEDAgUCJGwFAiRpCgEFJGYwXzICAiRhAiRpAwkAZwIFAiRpBQIkcwUCJGEJAAIBAhNMaXN0IHNpemUgZXhjZWVkcyA1CQEFJGYwXzICCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECCQEFJGYwXzECBQUkYWNjMAAAAAEAAgADAAQABQQJY29udGluZW50CQCRAwIFCmNvbnRpbmVudHMFDGNvbnRpbmVudElkeAQFaXNzdWUJAMIIBQkBCmtleU5mdE5hbWUCCAUQbnVtQWN0aW9uQW5kU2VlZAJfMQIBUwkAuQkCCQDMCAIIBRBudW1BY3Rpb25BbmRTZWVkAl8xCQDMCAICAVMJAMwIAggFAXQCXzEJAMwIAgUJY29udGluZW50BQNuaWwCAV8AAQAABwQHYXNzZXRJZAkAuAgBBQVpc3N1ZQQCaWQJANgEAQUHYXNzZXRJZAkAlAoCCQDMCAIIBRBudW1BY3Rpb25BbmRTZWVkAl8yCQDMCAIFBWlzc3VlCQDMCAIJAQtTdHJpbmdFbnRyeQIJARBrZXlMYW5kVG9Bc3NldElkAQgFEG51bUFjdGlvbkFuZFNlZWQCXzEFAmlkCQDMCAIJAQtTdHJpbmdFbnRyeQIJARVrZXlMYW5kQXNzZXRJZFRvT3duZXIBBQJpZAUIdXNlckFkZHIJAMwIAgkBC1N0cmluZ0VudHJ5AgkBEWtleUxhbmROdW1Ub093bmVyAQgFEG51bUFjdGlvbkFuZFNlZWQCXzEFCHVzZXJBZGRyCQDMCAIJAQ5TY3JpcHRUcmFuc2ZlcgMIBQFpBmNhbGxlcgABBQdhc3NldElkCQDMCAIJAQtTdHJpbmdFbnRyeQIJAQ9rZXlEdWNrTG9jYXRpb24BBQtkdWNrQXNzZXRJZAkAuQkCCQDMCAIFCWNvbnRpbmVudAkAzAgCAgFMCQDMCAIFAmlkBQNuaWwCAV8JAMwIAgkBDEludGVnZXJFbnRyeQIFCWtleUhlYWx0aAUFbmV3SFAJAMwIAgkBC1N0cmluZ0VudHJ5AgUFYnBLZXkJALkJAgkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQpicElkeExldmVsCQDMCAIJAJEDAgULY3VycmVudFBhY2sFCGJwSWR4UmVzCQDMCAIFBm5ld01hdAkAzAgCCQCRAwIFC2N1cnJlbnRQYWNrBQlicElkeFByb2QFA25pbAIBOgUDbmlsBQR1bml0ADhELMw=", "height": 2373700, "applicationStatus": "succeeded", "spentComplexity": 0 } View: original | compacted Prev: 7g5t5rQfrJkYyopZd59UAi4e3tT4Y31EVUV5khJuyWC7 Next: 8XNJmpGm51w3yzhwpht7AkgrZjNust3eFvtWHPaHMzJo Diff:
OldNewDifferences
6161
6262 let EXPMATERIALS = 157679960139
6363
64+let MULT6 = 1000000
65+
6466 let FIVEX = toBigInt(5)
6567
6668 let TWENTYX = toBigInt(20)
116118 func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId)
117119
118120
121+func keyResProportions () = "resTypesProportions"
122+
123+
119124 let recLandNum = 0
120125
121126 let recLandSize = 1
137142 let bpIdxMat = 2
138143
139144 let bpIdxProd = 3
145+
146+func getNeededMaterials () = {
147+ let props = split(value(getString(keyResProportions())), "_")
148+ if ((size(props) != NUMRES))
149+ then throw("Wrong proportions data")
150+ else {
151+ let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])]
152+ let sum = (((((r[0] + r[1]) + r[2]) + r[3]) + r[4]) + r[5])
153+ if ((0 >= sum))
154+ then throw("No lands staked")
155+ else {
156+ let norm6 = fraction(EXPMATERIALS, MULT6, sum)
157+ func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6))
158+
159+ let $l = r
160+ let $s = size($l)
161+ let $acc0 = nil
162+ func $f0_1 ($a,$i) = if (($i >= $s))
163+ then $a
164+ else normalizer($a, $l[$i])
165+
166+ func $f0_2 ($a,$i) = if (($i >= $s))
167+ then $a
168+ else throw("List size exceeds 6")
169+
170+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
171+ }
172+ }
173+ }
174+
175+
176+func subtractMaterials (has,need) = {
177+ func subtractor (acc,idx) = {
178+ let result = (parseIntValue(has[idx]) - need[idx])
179+ if ((0 > result))
180+ then throw(((((("Not enough material idx=" + toString(idx)) + ", you have ") + has[idx]) + ", but need ") + toString(need[idx])))
181+ else (acc :+ toString(result))
182+ }
183+
184+ let $l = [0, 1, 2, 3, 4, 5]
185+ let $s = size($l)
186+ let $acc0 = nil
187+ func $f0_1 ($a,$i) = if (($i >= $s))
188+ then $a
189+ else subtractor($a, $l[$i])
190+
191+ func $f0_2 ($a,$i) = if (($i >= $s))
192+ then $a
193+ else throw("List size exceeds 6")
194+
195+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
196+ }
197+
198+
199+func updateProportions (terrainCounts,landSizeIndex,sign) = {
200+ let props = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
201+ if ((size(props) != NUMRES))
202+ then throw("Wrong proportions data")
203+ else {
204+ func updater (acc,i) = {
205+ let result = (parseIntValue(props[i]) + ((sign * terrainCounts[i]) * landSizeIndex))
206+ if ((0 > result))
207+ then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex)))
208+ else (acc :+ toString(result))
209+ }
210+
211+ let r = {
212+ let $l = [0, 1, 2, 3, 4, 5]
213+ let $s = size($l)
214+ let $acc0 = nil
215+ func $f0_1 ($a,$i) = if (($i >= $s))
216+ then $a
217+ else updater($a, $l[$i])
218+
219+ func $f0_2 ($a,$i) = if (($i >= $s))
220+ then $a
221+ else throw("List size exceeds 6")
222+
223+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
224+ }
225+ makeString(r, "_")
226+ }
227+ }
228+
140229
141230 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)]
142231
254343 let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
255344 if (isDefined(getInteger(timeKey)))
256345 then throw((("NFT " + asset.name) + " is already staked"))
257- else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(toBase58String(assetId)), address), StringEntry(keyLandNumToOwner(landNum), address)]
346+ else {
347+ let d = split(asset.description, "_")
348+ let terrainCounts = countTerrains(d[recTerrains])
349+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), 1)
350+[IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(toBase58String(assetId)), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
351+ }
258352 }
259353 }
260354 }
281375 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
282376 if ((owner != address))
283377 then throw("Staked NFT is not yours")
284- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address))]
378+ else {
379+ let d = split(asset.description, "_")
380+ let terrainCounts = countTerrains(d[recTerrains])
381+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), -1)
382+[ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address)), StringEntry(keyResProportions(), props)]
383+ }
285384 }
286385 }
287386 }
543642 else if ((0 >= newHP))
544643 then throw("Your duck health is zero, expedition failed")
545644 else {
546- let currentPack = split(valueOrElse(getString(keyBackpackByDuck(duckAssetId)), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
645+ let bpKey = keyBackpackByDuck(duckAssetId)
646+ let currentPack = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
647+ let matList = split(currentPack[bpIdxMat], "_")
648+ let mList = if ((size(matList) != NUMRES))
649+ then ["0", "0", "0", "0", "0", "0"]
650+ else matList
651+ let mNeed = getNeededMaterials()
652+ let newMat = makeString(mList, "_")
547653 let nums = split_51C(valueOrErrorMessage(getString(keyFreeLandNumsMap()), (keyFreeLandNumsMap() + " is not initialized")), "_")
548654 let len = size(nums)
549655 let bigNum = abs(toBigInt(i.transactionId))
579685 let issue = Issue(keyNftName(numActionAndSeed._1, "S"), makeString([numActionAndSeed._1, "S", t._1, continent], "_"), 1, 0, false)
580686 let assetId = calculateAssetId(issue)
581687 let id = toBase58String(assetId)
582- $Tuple2([numActionAndSeed._2, issue, StringEntry(keyLandToAssetId(numActionAndSeed._1), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(numActionAndSeed._1), userAddr), ScriptTransfer(i.caller, 1, assetId), StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", id], "_")), IntegerEntry(keyHealth, newHP)], unit)
688+ $Tuple2([numActionAndSeed._2, issue, StringEntry(keyLandToAssetId(numActionAndSeed._1), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(numActionAndSeed._1), userAddr), ScriptTransfer(i.caller, 1, assetId), StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", id], "_")), IntegerEntry(keyHealth, newHP), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))], unit)
583689 }
584690 }
585691 }
Full:
OldNewDifferences
11 {-# STDLIB_VERSION 6 #-}
22 {-# SCRIPT_TYPE ACCOUNT #-}
33 {-# CONTENT_TYPE DAPP #-}
44 let chain = toUtf8String(take(drop(this.bytes, 1), 1))
55
66 let usdnAssetId = match chain {
77 case _ =>
88 if (("W" == $match0))
99 then base58'DG2xFkPdDwKUoBkzGAhQtLpSGzfXLiCYPEzeKH2Ad24p'
1010 else if (("T" == $match0))
1111 then base58'HezsdQuRDtzksAYUy97gfhKy7Z1NW2uXYSHA3bgqenNZ'
1212 else throw("Unknown chain")
1313 }
1414
1515 let incubatorAddr = match chain {
1616 case _ =>
1717 if (("W" == $match0))
1818 then addressFromStringValue("3PEktVux2RhchSN63DsDo4b4mz4QqzKSeDv")
1919 else if (("T" == $match0))
2020 then this
2121 else throw("Unknown chain")
2222 }
2323
2424 let breederAddr = match chain {
2525 case _ =>
2626 if (("W" == $match0))
2727 then addressFromStringValue("3PDVuU45H7Eh5dmtNbnRNRStGwULA7NY6Hb")
2828 else if (("T" == $match0))
2929 then this
3030 else throw("Unknown chain")
3131 }
3232
3333 let economyAddr = match chain {
3434 case _ =>
3535 if (("W" == $match0))
3636 then addressFromStringValue("3P2sk1KncSxRaZs8b4CWGPw2jkvvav74u4D")
3737 else if (("T" == $match0))
3838 then addressFromStringValue("3N8y4wxX3JC4TdrCJBXX16SjWf6X256hrep")
3939 else throw("Unknown chain")
4040 }
4141
4242 let pub = base58'6LfPuKJjLgekmncBhMg2LZyMTNVzZBccXR28ySXm9uXD'
4343
4444 let HEALCOST = 10000
4545
4646 let LANDPREFIX = "LAND"
4747
4848 let DUCKPREFIX = "DUCK"
4949
5050 let DEFAULTLOCATION = "Africa_F_Africa"
5151
5252 let NUMRES = 6
5353
5454 let DAILYRESBYPIECE = 3456000
5555
5656 let DAYMILLIS = 86400000
5757
5858 let FIVEMINUTESMILLIS = 300000
5959
6060 let RESOURCEPRICEMIN = 158549
6161
6262 let EXPMATERIALS = 157679960139
6363
64+let MULT6 = 1000000
65+
6466 let FIVEX = toBigInt(5)
6567
6668 let TWENTYX = toBigInt(20)
6769
6870 let TWENTY2X = toBigInt((20 * 20))
6971
7072 let TWENTY3X = toBigInt(((20 * 20) * 20))
7173
7274 let TWENTY4X = toBigInt((((20 * 20) * 20) * 20))
7375
7476 let TWENTY5X = toBigInt(((((20 * 20) * 20) * 20) * 20))
7577
7678 let matTypes = ["Fuel", "Metal", "Plank", "Glass", "Plastic", "Protein"]
7779
7880 let continents = ["Asia", "Europe", "Americas", "Oceania", "Africa"]
7981
8082 func keyNextFreeLandNum () = "nextLandNum"
8183
8284
8385 func keyFreeLandNumsMap () = "freeLandNumsMap"
8486
8587
8688 func keyLandToAssetId (landNum) = ("landToAsset_" + landNum)
8789
8890
8991 func keyNftName (landNum,landSize) = ((LANDPREFIX + landNum) + landSize)
9092
9193
9294 func keyLandAssetIdToOwner (assetId) = ("nftOwner_" + assetId)
9395
9496
9597 func keyDuckIdToOwner (assetId) = ("duckOwner_" + assetId)
9698
9799
98100 func keyStakedTimeByAssetId (assetId) = ("stakedTime_" + assetId)
99101
100102
101103 func keyStakedDuckByOwner (ownerAddr) = ("stakedDuckByOwner_" + ownerAddr)
102104
103105
104106 func keyStakedTimeByTypeAssetIdAndOwner (nftType,assetId,ownerAddr) = ((((("stakedTimeByTypeAssetIdAndOwner_" + nftType) + "_") + assetId) + "_") + ownerAddr)
105107
106108
107109 func keyLandNumToOwner (landNum) = ("landOwner_" + landNum)
108110
109111
110112 func keyBackpackByDuck (duckAssetId) = ("backPack_" + duckAssetId)
111113
112114
113115 func keyDuckLocation (duckAssetId) = ("duckLocation_" + duckAssetId)
114116
115117
116118 func keyDuckHealth (duckAssetId) = ("duckHealth_" + duckAssetId)
117119
118120
121+func keyResProportions () = "resTypesProportions"
122+
123+
119124 let recLandNum = 0
120125
121126 let recLandSize = 1
122127
123128 let recTerrains = 2
124129
125130 let recContinent = 3
126131
127132 let locIdxContinent = 0
128133
129134 let locIdxType = 1
130135
131136 let locIdxId = 2
132137
133138 let bpIdxLevel = 0
134139
135140 let bpIdxRes = 1
136141
137142 let bpIdxMat = 2
138143
139144 let bpIdxProd = 3
145+
146+func getNeededMaterials () = {
147+ let props = split(value(getString(keyResProportions())), "_")
148+ if ((size(props) != NUMRES))
149+ then throw("Wrong proportions data")
150+ else {
151+ let r = [parseIntValue(props[0]), parseIntValue(props[1]), parseIntValue(props[2]), parseIntValue(props[3]), parseIntValue(props[4]), parseIntValue(props[5])]
152+ let sum = (((((r[0] + r[1]) + r[2]) + r[3]) + r[4]) + r[5])
153+ if ((0 >= sum))
154+ then throw("No lands staked")
155+ else {
156+ let norm6 = fraction(EXPMATERIALS, MULT6, sum)
157+ func normalizer (acc,elem) = (acc :+ fraction(elem, norm6, MULT6))
158+
159+ let $l = r
160+ let $s = size($l)
161+ let $acc0 = nil
162+ func $f0_1 ($a,$i) = if (($i >= $s))
163+ then $a
164+ else normalizer($a, $l[$i])
165+
166+ func $f0_2 ($a,$i) = if (($i >= $s))
167+ then $a
168+ else throw("List size exceeds 6")
169+
170+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
171+ }
172+ }
173+ }
174+
175+
176+func subtractMaterials (has,need) = {
177+ func subtractor (acc,idx) = {
178+ let result = (parseIntValue(has[idx]) - need[idx])
179+ if ((0 > result))
180+ then throw(((((("Not enough material idx=" + toString(idx)) + ", you have ") + has[idx]) + ", but need ") + toString(need[idx])))
181+ else (acc :+ toString(result))
182+ }
183+
184+ let $l = [0, 1, 2, 3, 4, 5]
185+ let $s = size($l)
186+ let $acc0 = nil
187+ func $f0_1 ($a,$i) = if (($i >= $s))
188+ then $a
189+ else subtractor($a, $l[$i])
190+
191+ func $f0_2 ($a,$i) = if (($i >= $s))
192+ then $a
193+ else throw("List size exceeds 6")
194+
195+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
196+ }
197+
198+
199+func updateProportions (terrainCounts,landSizeIndex,sign) = {
200+ let props = split(valueOrElse(getString(keyResProportions()), "0_0_0_0_0_0"), "_")
201+ if ((size(props) != NUMRES))
202+ then throw("Wrong proportions data")
203+ else {
204+ func updater (acc,i) = {
205+ let result = (parseIntValue(props[i]) + ((sign * terrainCounts[i]) * landSizeIndex))
206+ if ((0 > result))
207+ then throw(((((((("Panic! Pieces of type=" + toString(i)) + ", sign=") + toString(sign)) + ", terrainCounts[i]=") + toString(terrainCounts[i])) + ", landSizeIndex=") + toString(landSizeIndex)))
208+ else (acc :+ toString(result))
209+ }
210+
211+ let r = {
212+ let $l = [0, 1, 2, 3, 4, 5]
213+ let $s = size($l)
214+ let $acc0 = nil
215+ func $f0_1 ($a,$i) = if (($i >= $s))
216+ then $a
217+ else updater($a, $l[$i])
218+
219+ func $f0_2 ($a,$i) = if (($i >= $s))
220+ then $a
221+ else throw("List size exceeds 6")
222+
223+ $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
224+ }
225+ makeString(r, "_")
226+ }
227+ }
228+
140229
141230 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)]
142231
143232
144233 func numPiecesBySize (landSize) = match landSize {
145234 case _ =>
146235 if (("S" == $match0))
147236 then 25
148237 else if (("M" == $match0))
149238 then 100
150239 else if (("L" == $match0))
151240 then 225
152241 else if (("XL" == $match0))
153242 then 400
154243 else if (("XXL" == $match0))
155244 then 625
156245 else throw("Unknown land size")
157246 }
158247
159248
160249 func subOneInList (aList,idx,amount) = {
161250 func subber (acc,i) = (acc :+ (if ((i == idx))
162251 then toString((parseIntValue(aList[i]) - amount))
163252 else aList[i]))
164253
165254 let r = {
166255 let $l = [0, 1, 2, 3, 4, 5]
167256 let $s = size($l)
168257 let $acc0 = nil
169258 func $f0_1 ($a,$i) = if (($i >= $s))
170259 then $a
171260 else subber($a, $l[$i])
172261
173262 func $f0_2 ($a,$i) = if (($i >= $s))
174263 then $a
175264 else throw("List size exceeds 6")
176265
177266 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
178267 }
179268 makeString(r, "_")
180269 }
181270
182271
183272 func addRes (currentRes,terrainCounts,deltaTime,landSizeIndex) = {
184273 func adder (acc,i) = {
185274 let resOfType = ((fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * terrainCounts[i]) * landSizeIndex)
186275 (acc :+ toString((parseIntValue(currentRes[i]) + resOfType)))
187276 }
188277
189278 let r = {
190279 let $l = [0, 1, 2, 3, 4, 5]
191280 let $s = size($l)
192281 let $acc0 = nil
193282 func $f0_1 ($a,$i) = if (($i >= $s))
194283 then $a
195284 else adder($a, $l[$i])
196285
197286 func $f0_2 ($a,$i) = if (($i >= $s))
198287 then $a
199288 else throw("List size exceeds 6")
200289
201290 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5), 6)
202291 }
203292 makeString(r, "_")
204293 }
205294
206295
207296 func abs (x) = if ((x >= toBigInt(0)))
208297 then x
209298 else -(x)
210299
211300
212301 let freq = [[1, 4, 9, 10, 15], [5, 8, 13, 14, 15], [6, 9, 14, 15, 16], [4, 7, 8, 13, 18], [1, 6, 7, 15, 19]]
213302
214303 func genChar (n,freqs) = {
215304 let rem = toInt((n % TWENTYX))
216305 let letter = if ((freqs[0] > rem))
217306 then "A"
218307 else if ((freqs[1] > rem))
219308 then "B"
220309 else if ((freqs[2] > rem))
221310 then "C"
222311 else if ((freqs[3] > rem))
223312 then "D"
224313 else if ((freqs[4] > rem))
225314 then "E"
226315 else "F"
227316 letter
228317 }
229318
230319
231320 @Callable(i)
232321 func stakeLand () = {
233322 let pmt = value(i.payments[0])
234323 let assetId = value(pmt.assetId)
235324 let address = toString(i.caller)
236325 if ((pmt.amount != 1))
237326 then throw((("NFT " + LANDPREFIX) + " token should be attached as payment"))
238327 else {
239328 let asset = value(assetInfo(assetId))
240329 if ((asset.issuer != this))
241330 then throw("Unknown issuer of token")
242331 else if (!(contains(asset.name, LANDPREFIX)))
243332 then throw((("Only NFT " + LANDPREFIX) + " tokens are accepted"))
244333 else {
245334 let landNumSize = drop(asset.name, 4)
246335 let landNum = if (contains(landNumSize, "XXL"))
247336 then dropRight(landNumSize, 3)
248337 else if (contains(landNumSize, "XL"))
249338 then dropRight(landNumSize, 2)
250339 else dropRight(landNumSize, 1)
251340 if (!(isDefined(parseInt(landNum))))
252341 then throw(("Cannot parse land number from " + asset.name))
253342 else {
254343 let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
255344 if (isDefined(getInteger(timeKey)))
256345 then throw((("NFT " + asset.name) + " is already staked"))
257- else [IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(toBase58String(assetId)), address), StringEntry(keyLandNumToOwner(landNum), address)]
346+ else {
347+ let d = split(asset.description, "_")
348+ let terrainCounts = countTerrains(d[recTerrains])
349+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), 1)
350+[IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyLandAssetIdToOwner(toBase58String(assetId)), address), StringEntry(keyLandNumToOwner(landNum), address), StringEntry(keyResProportions(), props)]
351+ }
258352 }
259353 }
260354 }
261355 }
262356
263357
264358
265359 @Callable(i)
266360 func unstakeLand (landAssetId) = if ((size(i.payments) != 0))
267361 then throw("unstake doesn't require any payments")
268362 else {
269363 let assetId = fromBase58String(landAssetId)
270364 let address = toString(i.caller)
271365 let asset = value(assetInfo(assetId))
272366 if ((asset.issuer != this))
273367 then throw("Unknown issuer of token")
274368 else if (!(contains(asset.name, LANDPREFIX)))
275369 then throw((("Only NFT " + LANDPREFIX) + " tokens can be unstaked"))
276370 else {
277371 let timeKey = keyStakedTimeByAssetId(landAssetId)
278372 if (!(isDefined(timeKey)))
279373 then throw((("NFT " + asset.name) + " is not staked"))
280374 else {
281375 let owner = valueOrErrorMessage(getString(keyLandAssetIdToOwner(landAssetId)), (("NFT " + asset.name) + " is orphaned"))
282376 if ((owner != address))
283377 then throw("Staked NFT is not yours")
284- else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address))]
378+ else {
379+ let d = split(asset.description, "_")
380+ let terrainCounts = countTerrains(d[recTerrains])
381+ let props = updateProportions(terrainCounts, (numPiecesBySize(d[recLandSize]) / 25), -1)
382+[ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, address)), StringEntry(keyResProportions(), props)]
383+ }
285384 }
286385 }
287386 }
288387
289388
290389
291390 @Callable(i)
292391 func stakeDuck () = {
293392 let pmt = value(i.payments[0])
294393 let assetId = value(pmt.assetId)
295394 let address = toString(i.caller)
296395 if ((pmt.amount != 1))
297396 then throw((("NFT " + DUCKPREFIX) + " token should be attached as payment"))
298397 else {
299398 let asset = value(assetInfo(assetId))
300399 if (if ((asset.issuer != incubatorAddr))
301400 then (asset.issuer != breederAddr)
302401 else false)
303402 then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
304403 else if (!(contains(asset.name, DUCKPREFIX)))
305404 then throw((("Only NFT " + DUCKPREFIX) + " tokens are accepted"))
306405 else {
307406 let assetIdStr = toBase58String(assetId)
308407 let timeKey = keyStakedTimeByAssetId(assetIdStr)
309408 if (isDefined(getInteger(timeKey)))
310409 then throw((("NFT " + asset.name) + " is already staked"))
311410 else if (isDefined(getString(keyStakedDuckByOwner(address))))
312411 then throw(("You already staked one duck: " + asset.name))
313412 else {
314413 let locKey = keyDuckLocation(assetIdStr)
315414 let location = getString(locKey)
316415 let keyHealth = keyDuckHealth(assetIdStr)
317416 let health = getInteger(keyHealth)
318417 let bpKey = keyBackpackByDuck(assetIdStr)
319418 let backpack = getString(bpKey)
320419 ([IntegerEntry(timeKey, lastBlock.timestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, toBase58String(assetId), address), lastBlock.timestamp), StringEntry(keyDuckIdToOwner(assetIdStr), address), StringEntry(keyStakedDuckByOwner(address), assetIdStr)] ++ (if (isDefined(location))
321420 then nil
322421 else ([StringEntry(locKey, DEFAULTLOCATION)] ++ (if (isDefined(health))
323422 then nil
324423 else ([IntegerEntry(keyHealth, 100)] ++ (if (isDefined(backpack))
325424 then nil
326425 else [StringEntry(bpKey, "0:0_0_0_0_0_0:0_0_0_0_0_0:")]))))))
327426 }
328427 }
329428 }
330429 }
331430
332431
333432
334433 @Callable(i)
335434 func unstakeDuck (assetIdStr) = if ((size(i.payments) != 0))
336435 then throw("unstake doesn't require any payments")
337436 else {
338437 let assetId = fromBase58String(assetIdStr)
339438 let address = toString(i.caller)
340439 let asset = value(assetInfo(assetId))
341440 if (if ((asset.issuer != incubatorAddr))
342441 then (asset.issuer != breederAddr)
343442 else false)
344443 then throw((("Unknown issuer of " + DUCKPREFIX) + " token"))
345444 else if (!(contains(asset.name, DUCKPREFIX)))
346445 then throw((("Only NFT " + DUCKPREFIX) + " tokens can be unstaked"))
347446 else {
348447 let timeKey = keyStakedTimeByAssetId(toBase58String(assetId))
349448 if (!(isDefined(timeKey)))
350449 then throw((("NFT " + asset.name) + " is not staked"))
351450 else if (!(isDefined(keyStakedDuckByOwner(address))))
352451 then throw((("The duck " + asset.name) + " is not staked"))
353452 else {
354453 let owner = valueOrErrorMessage(getString(keyDuckIdToOwner(toBase58String(assetId))), (("NFT " + asset.name) + " is orphaned"))
355454 if ((owner != address))
356455 then throw("Staked NFT is not yours")
357456 else [ScriptTransfer(i.caller, 1, assetId), DeleteEntry(timeKey), DeleteEntry(keyDuckLocation(assetIdStr)), DeleteEntry(keyStakedTimeByTypeAssetIdAndOwner(DUCKPREFIX, assetIdStr, address)), DeleteEntry(keyStakedDuckByOwner(address))]
358457 }
359458 }
360459 }
361460
362461
363462
364463 @Callable(i)
365464 func claimRes (amount,landAssetId) = if ((size(i.payments) != 0))
366465 then throw("claimRes doesn't require any payments")
367466 else {
368467 let addr = toString(i.caller)
369468 let asset = value(assetInfo(fromBase58String(landAssetId)))
370469 if (!(contains(asset.name, LANDPREFIX)))
371470 then throw((("NFT " + LANDPREFIX) + " token should be passed as param"))
372471 else {
373472 let timeKey = keyStakedTimeByAssetId(landAssetId)
374473 let savedTime = getInteger(timeKey)
375474 if (!(isDefined(savedTime)))
376475 then throw((("NFT " + asset.name) + " is not staked"))
377476 else {
378477 let owner = getStringValue(keyLandAssetIdToOwner(landAssetId))
379478 if ((owner != addr))
380479 then throw((LANDPREFIX + " is not yours"))
381480 else {
382481 let d = split(asset.description, "_")
383482 let landSize = d[recLandSize]
384483 let terrainCounts = countTerrains(d[recTerrains])
385484 let duck = getString(keyStakedDuckByOwner(addr))
386485 if (!(isDefined(duck)))
387486 then throw("You don't have a duck staked")
388487 else {
389488 let duckAssetIdStr = value(duck)
390489 let curLocation = valueOrElse(getString(keyDuckLocation(duckAssetIdStr)), DEFAULTLOCATION)
391490 let loc = split(value(curLocation), "_")
392491 if ((loc[locIdxType] != "L"))
393492 then throw((("Duck location type is " + loc[locIdxType]) + ", but should be L"))
394493 else if ((loc[locIdxId] != landAssetId))
395494 then throw(((("Duck location id is " + loc[locIdxId]) + ", but should be ") + landAssetId))
396495 else {
397496 let deltaTime = (lastBlock.timestamp - value(savedTime))
398497 if ((0 > deltaTime))
399498 then throw(((("Saved timestamp is in future, saved = " + toString(value(savedTime))) + ", current = ") + toString(lastBlock.timestamp)))
400499 else {
401500 let pieces = numPiecesBySize(landSize)
402501 let availRes = (fraction(deltaTime, DAILYRESBYPIECE, DAYMILLIS) * pieces)
403502 if ((amount > availRes))
404503 then throw(((("Not enough resources, available = " + toString(availRes)) + ", requested = ") + toString(amount)))
405504 else {
406505 let newDeltaTime = fraction((availRes - amount), DAYMILLIS, (pieces * DAILYRESBYPIECE))
407506 let newTimestamp = (lastBlock.timestamp - newDeltaTime)
408507 let bpKey = keyBackpackByDuck(duckAssetIdStr)
409508 let currentPack = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
410509 let currentRes = split(currentPack[bpIdxRes], "_")
411510 let bpRes = addRes(currentRes, terrainCounts, (deltaTime - newDeltaTime), (pieces / 25))
412511 let newPack = makeString([currentPack[bpIdxLevel], bpRes, currentPack[bpIdxMat], currentPack[bpIdxProd]], ":")
413512 $Tuple2([StringEntry(bpKey, newPack), IntegerEntry(timeKey, newTimestamp), IntegerEntry(keyStakedTimeByTypeAssetIdAndOwner(LANDPREFIX, landAssetId, owner), newTimestamp)], unit)
414513 }
415514 }
416515 }
417516 }
418517 }
419518 }
420519 }
421520 }
422521
423522
424523
425524 @Callable(i)
426525 func flight (message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
427526 then throw("signature does not match")
428527 else if ((size(i.payments) != 0))
429528 then throw("flight doesn't require any payments")
430529 else {
431530 let parts = split(toUtf8String(message), ";")
432531 let hp = split(split(parts[0], "|")[0], "_")
433532 let curHP = parseIntValue(hp[0])
434533 let newHP = parseIntValue(hp[1])
435534 let newLocAndTime = split(parts[1], ":")
436535 let newLocation = newLocAndTime[0]
437536 let time = parseIntValue(newLocAndTime[1])
438537 if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
439538 then true
440539 else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
441540 then throw("signature outdated")
442541 else {
443542 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
444543 let keyHealth = keyDuckHealth(duckAssetId)
445544 let oldFromState = valueOrElse(getInteger(keyHealth), 100)
446545 if ((oldFromState != curHP))
447546 then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
448547 else if ((0 >= curHP))
449548 then throw("You can't fly with zero health")
450549 else {
451550 let locKey = keyDuckLocation(duckAssetId)
452551 let curLocation = valueOrElse(getString(locKey), DEFAULTLOCATION)
453552 if ((newLocation == curLocation))
454553 then throw("You can't fly to the same location")
455554 else $Tuple2([StringEntry(locKey, if ((newHP > 0))
456555 then newLocation
457556 else curLocation), IntegerEntry(keyHealth, newHP)], unit)
458557 }
459558 }
460559 }
461560
462561
463562
464563 @Callable(i)
465564 func setHealth (health,duckAssetId) = if (if ((0 > health))
466565 then true
467566 else (health > 100))
468567 then throw("HP should be within 0..100")
469568 else [IntegerEntry(keyDuckHealth(duckAssetId), health)]
470569
471570
472571
473572 @Callable(i)
474573 func heal (matType,amount) = if (if ((0 > matType))
475574 then true
476575 else (matType >= NUMRES))
477576 then throw(("Unknown material: " + toString(matType)))
478577 else if ((0 >= amount))
479578 then throw(("Amount should be positive! " + toString(amount)))
480579 else {
481580 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(toString(i.caller))), "You don't have a duck staked")
482581 let keyHealth = keyDuckHealth(duckAssetId)
483582 let oldHealth = valueOrElse(getInteger(keyHealth), 100)
484583 if ((oldHealth >= 100))
485584 then throw("HP should be < 100 to heal")
486585 else {
487586 let bpKey = keyBackpackByDuck(duckAssetId)
488587 let currentPack = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
489588 let matList = split(currentPack[bpIdxMat], "_")
490589 let mList = if ((size(matList) != NUMRES))
491590 then ["0", "0", "0", "0", "0", "0"]
492591 else matList
493592 let currentAmount = parseIntValue(mList[matType])
494593 let deltaHealth = min([(amount / HEALCOST), (100 - oldHealth)])
495594 let spendAmount = (deltaHealth * HEALCOST)
496595 if ((spendAmount > currentAmount))
497596 then throw(((((("You need " + toString(spendAmount)) + " of ") + matTypes[matType]) + " to heal, but you backpack contains ") + toString(currentAmount)))
498597 else {
499598 let newMat = subOneInList(mList, matType, spendAmount)
500599 [IntegerEntry(keyHealth, (oldHealth + deltaHealth)), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))]
501600 }
502601 }
503602 }
504603
505604
506605
507606 @Callable(i)
508607 func updateBackpack (duckAssetId,newPack) = if ((i.caller != economyAddr))
509608 then throw("permission denied")
510609 else $Tuple2([StringEntry(keyBackpackByDuck(duckAssetId), newPack)], newPack)
511610
512611
513612
514613 @Callable(i)
515614 func expedition (message,sig) = if (!(sigVerify_8Kb(message, sig, pub)))
516615 then throw("signature does not match")
517616 else if ((size(i.payments) != 0))
518617 then throw("expedition doesn't require any payments")
519618 else {
520619 let parts = split(toUtf8String(message), ";")
521620 let hp = split(split(parts[0], "|")[0], "_")
522621 let curHP = parseIntValue(hp[0])
523622 let newHP = parseIntValue(hp[1])
524623 let locAndTime = split(parts[1], ":")
525624 let targetLocation = split(locAndTime[0], "_")
526625 if ((targetLocation[1] != "E"))
527626 then throw("expedition target location type should be E")
528627 else {
529628 let time = parseIntValue(locAndTime[1])
530629 if (if ((time > (lastBlock.timestamp + FIVEMINUTESMILLIS)))
531630 then true
532631 else ((lastBlock.timestamp - FIVEMINUTESMILLIS) > time))
533632 then throw("signature outdated")
534633 else {
535634 let userAddr = toString(i.caller)
536635 let duckAssetId = valueOrErrorMessage(getString(keyStakedDuckByOwner(userAddr)), "You don't have a duck staked")
537636 let keyHealth = keyDuckHealth(duckAssetId)
538637 let oldFromState = valueOrElse(getInteger(keyHealth), 100)
539638 if ((oldFromState != curHP))
540639 then throw(((("oldHealth=" + toString(valueOrElse(getInteger(keyHealth), 100))) + " from state does not match one from flight log=") + toString(curHP)))
541640 else if ((0 >= curHP))
542641 then throw("You can't fly with zero health")
543642 else if ((0 >= newHP))
544643 then throw("Your duck health is zero, expedition failed")
545644 else {
546- let currentPack = split(valueOrElse(getString(keyBackpackByDuck(duckAssetId)), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
645+ let bpKey = keyBackpackByDuck(duckAssetId)
646+ let currentPack = split(valueOrElse(getString(bpKey), "0:0_0_0_0_0_0:0_0_0_0_0_0:"), ":")
647+ let matList = split(currentPack[bpIdxMat], "_")
648+ let mList = if ((size(matList) != NUMRES))
649+ then ["0", "0", "0", "0", "0", "0"]
650+ else matList
651+ let mNeed = getNeededMaterials()
652+ let newMat = makeString(mList, "_")
547653 let nums = split_51C(valueOrErrorMessage(getString(keyFreeLandNumsMap()), (keyFreeLandNumsMap() + " is not initialized")), "_")
548654 let len = size(nums)
549655 let bigNum = abs(toBigInt(i.transactionId))
550656 let numActionAndSeed = if ((len == 0))
551657 then {
552658 let freeNum = valueOrElse(getInteger(keyNextFreeLandNum()), 501)
553659 $Tuple3(toString(freeNum), IntegerEntry(keyNextFreeLandNum(), (freeNum + 1)), bigNum)
554660 }
555661 else {
556662 let q = toBigInt(len)
557663 let mapIdx = toInt((bigNum % q))
558664 $Tuple3(nums[mapIdx], StringEntry(keyFreeLandNumsMap(), makeString_11C(removeByIndex(nums, mapIdx), "_")), (bigNum / q))
559665 }
560666 let continentIdx = toInt((numActionAndSeed._3 % FIVEX))
561667 let f = freq[continentIdx]
562668 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))
563669
564670 let t = {
565671 let $l = [1, 2, 3, 4, 5]
566672 let $s = size($l)
567673 let $acc0 = $Tuple2("", (numActionAndSeed._3 / FIVEX))
568674 func $f0_1 ($a,$i) = if (($i >= $s))
569675 then $a
570676 else terrainGenerator($a, $l[$i])
571677
572678 func $f0_2 ($a,$i) = if (($i >= $s))
573679 then $a
574680 else throw("List size exceeds 5")
575681
576682 $f0_2($f0_1($f0_1($f0_1($f0_1($f0_1($acc0, 0), 1), 2), 3), 4), 5)
577683 }
578684 let continent = continents[continentIdx]
579685 let issue = Issue(keyNftName(numActionAndSeed._1, "S"), makeString([numActionAndSeed._1, "S", t._1, continent], "_"), 1, 0, false)
580686 let assetId = calculateAssetId(issue)
581687 let id = toBase58String(assetId)
582- $Tuple2([numActionAndSeed._2, issue, StringEntry(keyLandToAssetId(numActionAndSeed._1), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(numActionAndSeed._1), userAddr), ScriptTransfer(i.caller, 1, assetId), StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", id], "_")), IntegerEntry(keyHealth, newHP)], unit)
688+ $Tuple2([numActionAndSeed._2, issue, StringEntry(keyLandToAssetId(numActionAndSeed._1), id), StringEntry(keyLandAssetIdToOwner(id), userAddr), StringEntry(keyLandNumToOwner(numActionAndSeed._1), userAddr), ScriptTransfer(i.caller, 1, assetId), StringEntry(keyDuckLocation(duckAssetId), makeString([continent, "L", id], "_")), IntegerEntry(keyHealth, newHP), StringEntry(bpKey, makeString([currentPack[bpIdxLevel], currentPack[bpIdxRes], newMat, currentPack[bpIdxProd]], ":"))], unit)
583689 }
584690 }
585691 }
586692 }
587693
588694

github/deemru/w8io/026f985 
81.94 ms