Esempio n. 1
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IAccountStateDelta states            = context.PreviousStates;
            Address            collectionAddress = MonsterCollectionState0.DeriveAddress(context.Signer, collectRound);

            if (context.Rehearsal)
            {
                return(states
                       .SetState(collectionAddress, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, collectionAddress, context.Signer));
            }

            CheckObsolete(BlockChain.Policy.BlockPolicySource.V100080ObsoleteIndex, context);

            AgentState agentState = states.GetAgentState(context.Signer);

            if (agentState is null)
            {
                throw new FailedLoadStateException("Aborted as the agent state failed to load.");
            }

            if (!states.TryGetState(collectionAddress, out Dictionary stateDict))
            {
                throw new FailedLoadStateException($"Aborted as the monster collection state failed to load.");
            }

            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(stateDict);
            Currency               currency = states.GetGoldCurrency();
            FungibleAssetValue     balance  = 0 * currency;
            MonsterCollectionSheet monsterCollectionSheet = states.GetSheet <MonsterCollectionSheet>();
            int currentLevel = monsterCollectionState.Level;

            if (currentLevel <= level || level <= 0)
            {
                throw new InvalidLevelException($"The level must be greater than 0 and less than {currentLevel}.");
            }

            if (monsterCollectionState.End)
            {
                throw new MonsterCollectionExpiredException($"{collectionAddress} has already expired on {monsterCollectionState.ExpiredBlockIndex}");
            }

            long rewardLevel = monsterCollectionState.GetRewardLevel(context.BlockIndex);
            MonsterCollectionRewardSheet monsterCollectionRewardSheet = states.GetSheet <MonsterCollectionRewardSheet>();

            monsterCollectionState.Update(level, rewardLevel, monsterCollectionRewardSheet);
            for (int i = currentLevel; i > level; i--)
            {
                balance += monsterCollectionSheet[i].RequiredGold * currency;
            }

            return(states
                   .SetState(collectionAddress, monsterCollectionState.Serialize())
                   .TransferAsset(collectionAddress, context.Signer, balance));
        }
        public void Update(long rewardLevel)
        {
            MonsterCollectionState0 monsterCollectionState = new MonsterCollectionState0(_address, 1, 10000, _tableSheets.MonsterCollectionRewardSheet);

            Assert.Equal(1, monsterCollectionState.Level);
            Assert.Equal(10000, monsterCollectionState.StartedBlockIndex);
            Assert.Equal(MonsterCollectionState0.RewardInterval * 4 + 10000, monsterCollectionState.ExpiredBlockIndex);

            monsterCollectionState.Update(2, rewardLevel, _tableSheets.MonsterCollectionRewardSheet);
            Assert.Equal(2, monsterCollectionState.Level);
            List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[2].Rewards;

            for (long i = rewardLevel; i < 4; i++)
            {
                Assert.Equal(rewards, monsterCollectionState.RewardLevelMap[i + 1]);
            }
        }
        public void Execute(int rewardLevel, int prevRewardLevel, int collectionLevel)
        {
            Address collectionAddress = MonsterCollectionState0.DeriveAddress(_signer, 0);
            List <MonsterCollectionRewardSheet.RewardInfo> rewards = _tableSheets.MonsterCollectionRewardSheet[1].Rewards;
            MonsterCollectionState0 monsterCollectionState         = new MonsterCollectionState0(collectionAddress, 1, 0, _tableSheets.MonsterCollectionRewardSheet);

            for (int i = 0; i < prevRewardLevel; i++)
            {
                int level = i + 1;
                MonsterCollectionResult result = new MonsterCollectionResult(Guid.NewGuid(), _avatarAddress, rewards);
                monsterCollectionState.UpdateRewardMap(level, result, i * MonsterCollectionState0.RewardInterval);
            }

            List <MonsterCollectionRewardSheet.RewardInfo> collectionRewards = _tableSheets.MonsterCollectionRewardSheet[collectionLevel].Rewards;

            monsterCollectionState.Update(collectionLevel, rewardLevel, _tableSheets.MonsterCollectionRewardSheet);
            for (long i = rewardLevel; i < 4; i++)
            {
                Assert.Equal(collectionRewards, monsterCollectionState.RewardLevelMap[i + 1]);
            }

            Dictionary <int, int> rewardExpectedMap = new Dictionary <int, int>();

            foreach (var(key, value) in monsterCollectionState.RewardLevelMap)
            {
                if (monsterCollectionState.RewardMap.ContainsKey(key) || key > rewardLevel)
                {
                    continue;
                }

                foreach (var info in value)
                {
                    if (rewardExpectedMap.ContainsKey(info.ItemId))
                    {
                        rewardExpectedMap[info.ItemId] += info.Quantity;
                    }
                    else
                    {
                        rewardExpectedMap[info.ItemId] = info.Quantity;
                    }
                }
            }

            AvatarState prevAvatarState = _state.GetAvatarState(_avatarAddress);

            Assert.Empty(prevAvatarState.mailBox);

            Currency currency        = _state.GetGoldCurrency();
            int      collectionRound = _state.GetAgentState(_signer).MonsterCollectionRound;

            _state = _state
                     .SetState(collectionAddress, monsterCollectionState.Serialize());

            FungibleAssetValue balance = 0 * currency;

            if (rewardLevel == 4)
            {
                foreach (var row in _tableSheets.MonsterCollectionSheet)
                {
                    if (row.Level <= collectionLevel)
                    {
                        balance += row.RequiredGold * currency;
                    }
                }

                collectionRound += 1;
                _state           = _state
                                   .MintAsset(collectionAddress, balance);
            }

            Assert.Equal(prevRewardLevel, monsterCollectionState.RewardLevel);
            Assert.Equal(0, _state.GetAgentState(_signer).MonsterCollectionRound);

            ClaimMonsterCollectionReward0 action = new ClaimMonsterCollectionReward0
            {
                avatarAddress   = _avatarAddress,
                collectionRound = 0,
            };

            IAccountStateDelta nextState = action.Execute(new ActionContext
            {
                PreviousStates = _state,
                Signer         = _signer,
                BlockIndex     = rewardLevel * MonsterCollectionState0.RewardInterval,
                Random         = new TestRandom(),
            });

            MonsterCollectionState0 nextMonsterCollectionState = new MonsterCollectionState0((Dictionary)nextState.GetState(collectionAddress));

            Assert.Equal(rewardLevel, nextMonsterCollectionState.RewardLevel);

            AvatarState nextAvatarState = nextState.GetAvatarState(_avatarAddress);

            foreach (var(itemId, qty) in rewardExpectedMap)
            {
                Assert.True(nextAvatarState.inventory.HasItem(itemId, qty));
            }

            Assert.Equal(rewardLevel - prevRewardLevel, nextAvatarState.mailBox.Count);
            Assert.All(nextAvatarState.mailBox, mail =>
            {
                Assert.IsType <MonsterCollectionMail>(mail);
                MonsterCollectionMail monsterCollectionMail = (MonsterCollectionMail)mail;
                Assert.IsType <MonsterCollectionResult>(monsterCollectionMail.attachment);
                MonsterCollectionResult result = (MonsterCollectionResult)monsterCollectionMail.attachment;
                Assert.Equal(result.id, mail.id);
            });

            for (int i = 0; i < nextMonsterCollectionState.RewardLevel; i++)
            {
                int level = i + 1;
                List <MonsterCollectionRewardSheet.RewardInfo> rewardInfos = _tableSheets.MonsterCollectionRewardSheet[collectionLevel].Rewards;
                Assert.Contains(level, nextMonsterCollectionState.RewardMap.Keys);
                Assert.Equal(_avatarAddress, nextMonsterCollectionState.RewardMap[level].avatarAddress);
            }

            Assert.Equal(0 * currency, nextState.GetBalance(collectionAddress, currency));
            Assert.Equal(balance, nextState.GetBalance(_signer, currency));
            Assert.Equal(collectionRound, nextState.GetAgentState(_signer).MonsterCollectionRound);
            Assert.Equal(nextMonsterCollectionState.End, rewardLevel == 4);
        }
Esempio n. 4
0
        public override IAccountStateDelta Execute(IActionContext context)
        {
            IAccountStateDelta states = context.PreviousStates;
            Address            monsterCollectionAddress = MonsterCollectionState0.DeriveAddress(context.Signer, collectionRound);

            if (context.Rehearsal)
            {
                return(states
                       .SetState(monsterCollectionAddress, MarkChanged)
                       .SetState(context.Signer, MarkChanged)
                       .MarkBalanceChanged(GoldCurrencyMock, context.Signer, monsterCollectionAddress));
            }

            CheckObsolete(BlockChain.Policy.BlockPolicySource.V100080ObsoleteIndex, context);

            MonsterCollectionSheet monsterCollectionSheet = states.GetSheet <MonsterCollectionSheet>();

            AgentState agentState = states.GetAgentState(context.Signer);

            if (agentState is null)
            {
                throw new FailedLoadStateException("Aborted as the agent state failed to load.");
            }

            if (agentState.MonsterCollectionRound != collectionRound)
            {
                throw new InvalidMonsterCollectionRoundException(
                          $"Expected collection round is {agentState.MonsterCollectionRound}, but actual collection round is {collectionRound}.");
            }

            if (!monsterCollectionSheet.TryGetValue(level, out MonsterCollectionSheet.Row _))
            {
                throw new SheetRowNotFoundException(nameof(MonsterCollectionSheet), level);
            }

            Currency currency = states.GetGoldCurrency();
            // Set default gold value.
            FungibleAssetValue requiredGold = currency * 0;
            FungibleAssetValue balance      = states.GetBalance(context.Signer, states.GetGoldCurrency());

            MonsterCollectionState0 monsterCollectionState;
            int currentLevel = 1;
            MonsterCollectionRewardSheet monsterCollectionRewardSheet = states.GetSheet <MonsterCollectionRewardSheet>();

            if (states.TryGetState(monsterCollectionAddress, out Dictionary stateDict))
            {
                monsterCollectionState = new MonsterCollectionState0(stateDict);

                if (monsterCollectionState.ExpiredBlockIndex < context.BlockIndex)
                {
                    throw new MonsterCollectionExpiredException(
                              $"{monsterCollectionAddress} has already expired on {monsterCollectionState.ExpiredBlockIndex}");
                }

                if (monsterCollectionState.Level >= level)
                {
                    throw new InvalidLevelException($"The level must be greater than {monsterCollectionState.Level}.");
                }

                currentLevel = monsterCollectionState.Level + 1;
                long rewardLevel = monsterCollectionState.GetRewardLevel(context.BlockIndex);
                monsterCollectionState.Update(level, rewardLevel, monsterCollectionRewardSheet);
            }
            else
            {
                monsterCollectionState = new MonsterCollectionState0(monsterCollectionAddress, level, context.BlockIndex, monsterCollectionRewardSheet);
            }

            for (int i = currentLevel; i < level + 1; i++)
            {
                requiredGold += currency * monsterCollectionSheet[i].RequiredGold;
            }

            if (balance < requiredGold)
            {
                throw new InsufficientBalanceException(context.Signer, requiredGold,
                                                       $"There is no sufficient balance for {context.Signer}: {balance} < {requiredGold}");
            }
            states = states.TransferAsset(context.Signer, monsterCollectionAddress, requiredGold);
            states = states.SetState(monsterCollectionAddress, monsterCollectionState.Serialize());
            return(states);
        }