diff --git a/backend/app/Savor22b.Tests/Action/PlantingSeedActionTests.cs b/backend/app/Savor22b.Tests/Action/PlantingSeedActionTests.cs index f20c9e76..06d43c02 100644 --- a/backend/app/Savor22b.Tests/Action/PlantingSeedActionTests.cs +++ b/backend/app/Savor22b.Tests/Action/PlantingSeedActionTests.cs @@ -6,7 +6,6 @@ namespace Savor22b.Tests.Action; using Savor22b.Action; using Savor22b.States; using Savor22b.Action.Exceptions; -using System.Collections.Immutable; public class PlantingSeedActionTests : ActionTests { @@ -18,8 +17,10 @@ public PlantingSeedActionTests() private InventoryState getInventoryState() { InventoryState inventoryState = new InventoryState(); - var newSeed = new SeedState(Guid.NewGuid(), 1); - inventoryState = inventoryState.AddSeed(newSeed); + + var itemState = new ItemState(Guid.NewGuid(), 1); + inventoryState = inventoryState.AddItem(itemState); + return inventoryState; } @@ -58,10 +59,12 @@ public void Execute_ValidAction() SignerAddress(), beforeRootState.Serialize() ); + var beforeSeedGuid = Guid.NewGuid(); PlantingSeedAction plantingSeedAction = new PlantingSeedAction( - beforeRootState.InventoryState.SeedStateList[0].StateID, - 0 + beforeSeedGuid, + 0, + beforeRootState.InventoryState.ItemStateList[0].StateID ); var random = new DummyRandom(1); @@ -80,8 +83,9 @@ public void Execute_ValidAction() ? new RootState(bdict) : throw new Exception(); - Assert.Equal(rootState.VillageState!.HouseFieldStates[0]!.InstalledSeedGuid, beforeRootState.InventoryState.SeedStateList[0].StateID); - Assert.Equal(rootState.InventoryState.SeedStateList.Count, 0); + Assert.Equal(rootState.VillageState!.HouseFieldStates[0]!.InstalledSeedGuid, beforeSeedGuid); + Assert.Equal(rootState.InventoryState.SeedStateList.Count, 1); + Assert.Equal(rootState.InventoryState.ItemStateList.Count, 0); } [Fact] @@ -98,10 +102,12 @@ public void Execute_InvalidVillageState() SignerAddress(), beforeRootState.Serialize() ); + var beforeSeedGuid = Guid.NewGuid(); PlantingSeedAction plantingSeedAction = new PlantingSeedAction( - beforeRootState.InventoryState.SeedStateList[0].StateID, - 1 + beforeSeedGuid, + 1, + beforeRootState.InventoryState.ItemStateList[0].StateID ); var random = new DummyRandom(1); @@ -130,10 +136,12 @@ public void Execute_InvalidFieldIndex() SignerAddress(), beforeRootState.Serialize() ); + var beforeSeedGuid = Guid.NewGuid(); PlantingSeedAction plantingSeedAction = new PlantingSeedAction( - beforeRootState.InventoryState.SeedStateList[0].StateID, - VillageState.HouseFieldCount + 1 + beforeSeedGuid, + VillageState.HouseFieldCount + 1, + beforeRootState.InventoryState.ItemStateList[0].StateID ); var random = new DummyRandom(1); @@ -152,7 +160,7 @@ public void Execute_InvalidFieldIndex() } [Fact] - public void Execute_InvalidSeedStateId() + public void Execute_InvalidItemStateId() { IAccountStateDelta beforeState = new DummyState(); @@ -162,15 +170,17 @@ public void Execute_InvalidSeedStateId() SignerAddress(), beforeRootState.Serialize() ); + var beforeSeedGuid = Guid.NewGuid(); PlantingSeedAction plantingSeedAction = new PlantingSeedAction( - Guid.NewGuid(), - 0 + beforeSeedGuid, + 0, + Guid.NewGuid() ); var random = new DummyRandom(1); - Assert.Throws(() => + Assert.Throws(() => { plantingSeedAction.Execute(new DummyActionContext { @@ -182,5 +192,4 @@ public void Execute_InvalidSeedStateId() }); }); } - } diff --git a/backend/app/Savor22b.Tests/Action/UseRandomSeedItemActionTests.cs b/backend/app/Savor22b.Tests/Action/UseRandomSeedItemActionTests.cs deleted file mode 100644 index 87817c67..00000000 --- a/backend/app/Savor22b.Tests/Action/UseRandomSeedItemActionTests.cs +++ /dev/null @@ -1,115 +0,0 @@ -namespace Savor22b.Tests.Action; - -using System; -using Libplanet.Crypto; -using Libplanet.State; -using Xunit; -using Savor22b.Action; -using Savor22b.States; -using Libplanet; - -public class UseRandomSeedItemActionTests : ActionTests -{ - public UseRandomSeedItemActionTests() { } - - [Fact] - public void UseRandomSeedItemActionExecute_AddsSeedToSeedStateList() - { - var seedStateID = Guid.NewGuid(); - var random = new DummyRandom(1); - var villageId = 1; - - IAccountStateDelta state = new DummyState(); - RootState beforeRootState = new RootState(); - InventoryState beforeInventoryState = new InventoryState(); - - var itemState = new ItemState(Guid.NewGuid(), 1); - beforeInventoryState = beforeInventoryState.AddItem(itemState); - - beforeRootState.SetInventoryState(beforeInventoryState); - beforeRootState.SetVillageState( - new VillageState(new HouseState(villageId, 0, 0, new KitchenState())) - ); - - state = state.SetState(SignerAddress(), beforeRootState.Serialize()); - - var action = new UseRandomSeedItemAction(seedStateID, itemState.StateID); - - state = action.Execute( - new DummyActionContext - { - PreviousStates = state, - Signer = SignerAddress(), - Random = random, - Rehearsal = false, - BlockIndex = 1, - } - ); - - var rootStateEncoded = state.GetState(SignerAddress()); - RootState rootState = rootStateEncoded is Bencodex.Types.Dictionary bdict - ? new RootState(bdict) - : throw new Exception(); - InventoryState inventoryState = rootState.InventoryState; - - Assert.Equal(inventoryState.SeedStateList.Count, 1); - Assert.Equal(inventoryState.ItemStateList.Count, 0); - } - - [Theory] - [InlineData(1)] - [InlineData(5)] - [InlineData(10)] - [InlineData(100)] - [InlineData(1000)] - [InlineData(10000)] - public void UseRandomSeedItemActionExecute_AddsSeedStateToExistsSeedsList( - int existsSeedsListLength - ) - { - int villageId = 1; - - IAccountStateDelta state = new DummyState(); - var itemState = new ItemState(Guid.NewGuid(), 1); - RootState rootState = new RootState(); - InventoryState beforeInventoryState = new InventoryState(); - - for (int i = 0; i < existsSeedsListLength; i++) - { - var newSeed = new SeedState(Guid.NewGuid(), 1); - beforeInventoryState = beforeInventoryState.AddSeed(newSeed); - } - - beforeInventoryState = beforeInventoryState.AddItem(itemState); - rootState.SetInventoryState(beforeInventoryState); - rootState.SetVillageState( - new VillageState(new HouseState(villageId, 0, 0, new KitchenState())) - ); - - state = state.SetState(SignerAddress(), rootState.Serialize()); - - var random = new DummyRandom(1); - - var action = new UseRandomSeedItemAction(Guid.NewGuid(), itemState.StateID); - - state = action.Execute( - new DummyActionContext - { - PreviousStates = state, - Signer = SignerAddress(), - Random = random, - Rehearsal = false, - BlockIndex = 1, - } - ); - - var afterRootStateEncoded = state.GetState(SignerAddress()); - - RootState afterRootState = afterRootStateEncoded is Bencodex.Types.Dictionary bdict - ? new RootState(bdict) - : throw new Exception(); - - Assert.Equal(existsSeedsListLength + 1, afterRootState.InventoryState.SeedStateList.Count); - Assert.Equal(afterRootState.InventoryState.ItemStateList.Count, 0); - } -} diff --git a/backend/app/Savor22b/Action/PlantingSeedAction.cs b/backend/app/Savor22b/Action/PlantingSeedAction.cs index fefa6c90..7448d553 100644 --- a/backend/app/Savor22b/Action/PlantingSeedAction.cs +++ b/backend/app/Savor22b/Action/PlantingSeedAction.cs @@ -16,13 +16,15 @@ public class PlantingSeedAction : SVRAction { public Guid SeedGuid; public int FieldIndex; + public Guid ItemStateIdToUse; public PlantingSeedAction() { } - public PlantingSeedAction(Guid seedGuid, int fieldIndex) + public PlantingSeedAction(Guid seedGuid, int fieldIndex, Guid itemStateIdToUse) { SeedGuid = seedGuid; FieldIndex = fieldIndex; + ItemStateIdToUse = itemStateIdToUse; } protected override IImmutableDictionary PlainValueInternal => @@ -30,12 +32,14 @@ public PlantingSeedAction(Guid seedGuid, int fieldIndex) { [nameof(SeedGuid)] = SeedGuid.Serialize(), [nameof(FieldIndex)] = FieldIndex.Serialize(), + [nameof(ItemStateIdToUse)] = ItemStateIdToUse.Serialize() }.ToImmutableDictionary(); protected override void LoadPlainValueInternal(IImmutableDictionary plainValue) { SeedGuid = plainValue[nameof(SeedGuid)].ToGuid(); FieldIndex = plainValue[nameof(FieldIndex)].ToInteger(); + ItemStateIdToUse = plainValue[nameof(ItemStateIdToUse)].ToGuid(); } public void checkAndRaisePlantingAble(RootState rootState) @@ -54,13 +58,36 @@ public void checkAndRaisePlantingAble(RootState rootState) { throw new FieldAlreadyOccupiedException("Field is already occupied"); } + } + + private Seed generateRandomSeed(IRandom random, int villageId) + { + int randomIndex; + var seeds = CsvDataHelper.GetSeedCSVData(); + var village = CsvDataHelper.GetVillageCharacteristicByVillageId(villageId)!; + + do + { + randomIndex = random.Next(0, seeds.Count); + } while (!village.AvailableSeedIdList.Contains(seeds[randomIndex].Id)); + + var randomSeedCsvData = seeds[randomIndex]; + + return randomSeedCsvData; + } - SeedState? seedState = rootState.InventoryState.GetSeedState(SeedGuid); + private InventoryState FindAndRemoveItem(InventoryState state) + { + var item = state.ItemStateList.Find(state => state.StateID == ItemStateIdToUse); - if (seedState is null) + if (item is null) { - throw new NotFoundDataException("Seed not found"); + throw new NotHaveRequiredException($"You don't have `{ItemStateIdToUse}` item"); } + + state = state.RemoveItem(ItemStateIdToUse); + + return state; } public override IAccountStateDelta Execute(IActionContext ctx) @@ -76,18 +103,22 @@ is Bencodex.Types.Dictionary rootStateEncoded checkAndRaisePlantingAble(rootState); InventoryState inventoryState = rootState.InventoryState; - SeedState seedState = rootState.InventoryState.GetSeedState(SeedGuid)!; + inventoryState = FindAndRemoveItem(inventoryState); - inventoryState = inventoryState.RemoveSeed(SeedGuid); - rootState.SetInventoryState(inventoryState); + Seed seedCsvData = generateRandomSeed( + ctx.Random, + rootState.VillageState!.HouseState.VillageID + ); + var seedState = new SeedState(SeedGuid, seedCsvData.Id); + inventoryState = inventoryState.AddSeed(seedState); - Seed seed = CsvDataHelper.GetSeedById(seedState.SeedID)!; + rootState.SetInventoryState(inventoryState); HouseFieldState houseFieldState = new HouseFieldState( SeedGuid, - seedState.SeedID, + seedCsvData.Id, ctx.BlockIndex, - seed.RequiredBlock + seedCsvData.RequiredBlock ); rootState.VillageState!.UpdateHouseFieldState(FieldIndex, houseFieldState); diff --git a/backend/app/Savor22b/Action/UseRandomSeedItemAction.cs b/backend/app/Savor22b/Action/UseRandomSeedItemAction.cs deleted file mode 100644 index a3116beb..00000000 --- a/backend/app/Savor22b/Action/UseRandomSeedItemAction.cs +++ /dev/null @@ -1,97 +0,0 @@ -namespace Savor22b.Action; - -using System.Collections.Immutable; -using Bencodex.Types; -using Libplanet.Action; -using Libplanet.Headless.Extensions; -using Libplanet.State; -using Savor22b.Action.Exceptions; -using Savor22b.States; -using Savor22b.Action.Util; - -[ActionType(nameof(UseRandomSeedItemAction))] -public class UseRandomSeedItemAction : SVRAction -{ - public Guid SeedStateID; - public Guid ItemStateIdToUse; - - public UseRandomSeedItemAction() { } - - public UseRandomSeedItemAction(Guid seedStateID, Guid itemStateIdToUse) - { - SeedStateID = seedStateID; - ItemStateIdToUse = itemStateIdToUse; - } - - protected override IImmutableDictionary PlainValueInternal => - new Dictionary() - { - [nameof(SeedStateID)] = SeedStateID.Serialize(), - [nameof(ItemStateIdToUse)] = ItemStateIdToUse.Serialize() - }.ToImmutableDictionary(); - - protected override void LoadPlainValueInternal(IImmutableDictionary plainValue) - { - SeedStateID = plainValue[nameof(SeedStateID)].ToGuid(); - ItemStateIdToUse = plainValue[nameof(ItemStateIdToUse)].ToGuid(); - } - - private SeedState generateRandomSeed(IRandom random, int villageId) - { - int randomIndex; - var seeds = CsvDataHelper.GetSeedCSVData(); - var village = CsvDataHelper.GetVillageCharacteristicByVillageId(villageId)!; - - do - { - randomIndex = random.Next(0, seeds.Count); - } while (!village.AvailableSeedIdList.Contains(seeds[randomIndex].Id)); - - var randomSeedData = seeds[randomIndex]; - var randomSeed = new SeedState(SeedStateID, randomSeedData.Id); - - return randomSeed; - } - - private InventoryState FindAndRemoveItem(InventoryState state) - { - var item = state.ItemStateList.Find(state => state.StateID == ItemStateIdToUse); - - if (item is null) - { - throw new NotHaveRequiredException($"You don't have `{ItemStateIdToUse}` item"); - } - - state = state.RemoveItem(ItemStateIdToUse); - - return state; - } - - public override IAccountStateDelta Execute(IActionContext ctx) - { - IAccountStateDelta states = ctx.PreviousStates; - - RootState rootState = states.GetState(ctx.Signer) - is Bencodex.Types.Dictionary rootStateEncoded - ? new RootState(rootStateEncoded) - : new RootState(); - - Validation.EnsureVillageStateExists(rootState); - - InventoryState inventoryState = rootState.InventoryState; - - SeedState seedState = generateRandomSeed( - ctx.Random, - rootState.VillageState!.HouseState.VillageID - ); - inventoryState = FindAndRemoveItem(inventoryState); - inventoryState = inventoryState.AddSeed(seedState); - - rootState.SetInventoryState(inventoryState); - - var encodedValue = rootState.Serialize(); - var statesWithUpdated = states.SetState(ctx.Signer, encodedValue); - - return statesWithUpdated; - } -} diff --git a/backend/app/Savor22b/GraphTypes/Query/Query.cs b/backend/app/Savor22b/GraphTypes/Query/Query.cs index 28631974..442bac85 100644 --- a/backend/app/Savor22b/GraphTypes/Query/Query.cs +++ b/backend/app/Savor22b/GraphTypes/Query/Query.cs @@ -164,41 +164,6 @@ swarm is null } ); - Field>( - "createAction_UseRandomSeedItem", - description: "Use Random Seed Item", - arguments: new QueryArguments( - new QueryArgument> - { - Name = "publicKey", - Description = "The base64-encoded public key for Transaction.", - }, - new QueryArgument> - { - Name = "itemStateID", - Description = "item state id to use", - } - ), - resolve: context => - { - var publicKey = new PublicKey( - ByteUtil.ParseHex(context.GetArgument("publicKey")) - ); - - var action = new UseRandomSeedItemAction( - Guid.NewGuid(), - context.GetArgument("itemStateID") - ); - - return new GetUnsignedTransactionHex( - action, - publicKey, - _blockChain, - _swarm - ).UnsignedTransactionHex; - } - ); - Field>( "createAction_BuyKitchenEquipment", description: "Buy kitchen equipment", @@ -252,6 +217,11 @@ swarm is null { Name = "fieldIndex", Description = "Target field Index", + }, + new QueryArgument> + { + Name = "itemStateIdToUse", + Description = "Item state id to use (Guid)", } ), resolve: context => @@ -262,7 +232,8 @@ swarm is null var action = new PlantingSeedAction( context.GetArgument("seedStateId"), - context.GetArgument("fieldIndex") + context.GetArgument("fieldIndex"), + context.GetArgument("itemStateIdToUse") ); return new GetUnsignedTransactionHex(