public MonsterCollectionState(Address address, int level, long blockIndex, MonsterCollectionRewardSheet monsterCollectionRewardSheet) : base(address) { Level = level; StartedBlockIndex = blockIndex; ExpiredBlockIndex = blockIndex + LockUpInterval; List <MonsterCollectionRewardSheet.RewardInfo> rewardInfos = monsterCollectionRewardSheet[level].Rewards; }
public void Update(int level, long rewardLevel, MonsterCollectionRewardSheet monsterCollectionRewardSheet) { Level = level; List <MonsterCollectionRewardSheet.RewardInfo> rewardInfos = monsterCollectionRewardSheet[level].Rewards; for (long i = rewardLevel; i < RewardLevelMap.Count; i++) { RewardLevelMap[i + 1] = rewardInfos; } }
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 MonsterCollectionState0(Address address, int level, long blockIndex, MonsterCollectionRewardSheet monsterCollectionRewardSheet) : base(address) { Level = level; StartedBlockIndex = blockIndex; ExpiredBlockIndex = blockIndex + ExpirationIndex; RewardMap = new Dictionary <long, MonsterCollectionResult>(); List <MonsterCollectionRewardSheet.RewardInfo> rewardInfos = monsterCollectionRewardSheet[level].Rewards; RewardLevelMap = new Dictionary <long, List <MonsterCollectionRewardSheet.RewardInfo> > { [1] = rewardInfos, [2] = rewardInfos, [3] = rewardInfos, [4] = rewardInfos, }; }
public void SetToSheet() { var sheet = new MonsterCollectionRewardSheet(); sheet.Set("collection_level,item_id,quantity\n1,1,1\n1,2,2"); MonsterCollectionRewardSheet.Row row = sheet[1]; Assert.Equal(1, row.MonsterCollectionLevel); List <MonsterCollectionRewardSheet.RewardInfo> rewards = row.Rewards; for (int i = 0; i < rewards.Count; i++) { MonsterCollectionRewardSheet.RewardInfo reward = rewards[i]; Assert.Equal(i + 1, reward.ItemId); Assert.Equal(i + 1, reward.Quantity); } }
public List <MonsterCollectionRewardSheet.RewardInfo> CalculateRewards( MonsterCollectionRewardSheet sheet, long blockIndex ) { int step = CalculateStep(blockIndex); if (step > 0) { return(sheet[Level].Rewards .GroupBy(ri => ri.ItemId) .Select(g => new MonsterCollectionRewardSheet.RewardInfo( g.Key, g.Sum(ri => ri.Quantity) * step)) .ToList()); } else { return(new List <MonsterCollectionRewardSheet.RewardInfo>()); } }
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); }