Skip to content

Commit

Permalink
Merge branch 'development' into improve/action-execute
Browse files Browse the repository at this point in the history
  • Loading branch information
ipdae authored Apr 4, 2024
2 parents 1dcb552 + 8f0ec99 commit f7c4236
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 170 deletions.
154 changes: 59 additions & 95 deletions .Lib9c.Tests/Action/RuneEnhancementTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,34 @@ public RuneEnhancementTest()
}

[Theory]
[InlineData(10000)]
[InlineData(1)]
public void Execute(int seed)
// All success
[InlineData(1, 1, 2, 0, 0, 1, null, 0)]
[InlineData(1, 2, 3, 0, 0, 2, null, 0)]
// Success 1 of 2
[InlineData(202, 2, 203, 0, 1000, 40, null, 2)]
// All fail
[InlineData(202, 2, 202, 0, 1000, 40, null, 0)]
// Reaching max level
[InlineData(299, 1, 300, 0, 500, 20, null, 1)]
// Cannot exceed max level
[InlineData(299, 2, 299, 0, 0, 0, typeof(RuneCostDataNotFoundException), 0)]
[InlineData(300, 1, 300, 0, 0, 0, typeof(RuneCostDataNotFoundException), 0)]
public void Execute(
int startLevel,
int tryCount,
int expectedLevel,
int expectedNcgCost,
int expectedCrystalCost,
int expectedRuneCost,
Type expectedException,
int seed
)
{
const int initialNcg = 10_000;
const int initialCrystal = 1_000_000;
const int initialRune = 1_000;
var s = seed;
// Set states
var agentAddress = new PrivateKey().Address;
var avatarAddress = new PrivateKey().Address;
var sheets = TableSheetsImporter.ImportSheets();
Expand Down Expand Up @@ -66,55 +90,22 @@ public void Execute(int seed)
var runeId = runeListSheet.First().Value.Id;
var runeStateAddress = RuneState.DeriveAddress(avatarState.address, runeId);
var runeState = new RuneState(runeId);
runeState.LevelUp(startLevel);
state = state.SetLegacyState(runeStateAddress, runeState.Serialize());

var costSheet = state.GetSheet<RuneCostSheet>();
if (!costSheet.TryGetValue(runeId, out var costRow))
{
throw new RuneCostNotFoundException($"[{nameof(Execute)}] ");
}

if (!costRow.TryGetCost(runeState.Level + 1, out var cost))
{
throw new RuneCostDataNotFoundException($"[{nameof(Execute)}] ");
}

var runeSheet = state.GetSheet<RuneSheet>();
if (!runeSheet.TryGetValue(runeId, out var runeRow))
{
throw new RuneNotFoundException($"[{nameof(Execute)}] ");
}

// Prepare materials
var ncgCurrency = state.GetGoldCurrency();
var crystalCurrency = CrystalCalculator.CRYSTAL;
var runeCurrency = Currency.Legacy(runeRow.Ticker, 0, minters: null);

var ncgBal = cost.NcgQuantity * ncgCurrency * 10000;
var crystalBal = cost.CrystalQuantity * crystalCurrency * 10000;
var runeBal = cost.RuneStoneQuantity * runeCurrency * 10000;

var rand = new TestRandom(seed);
if (!RuneHelper.TryEnhancement(ncgBal, crystalBal, runeBal, ncgCurrency, crystalCurrency, runeCurrency, cost, rand, 99, out var tryCount))
{
throw new RuneNotFoundException($"[{nameof(Execute)}] ");
}

if (ncgBal.Sign > 0)
{
state = state.MintAsset(context, agentAddress, ncgBal);
}
var runeTicker = tableSheets.RuneSheet.Values.First(r => r.Id == runeId).Ticker;
var runeCurrency = Currency.Legacy(runeTicker, 0, minters: null);
var r = new TestRandom(seed: 1);

if (crystalBal.Sign > 0)
{
state = state.MintAsset(context, agentAddress, crystalBal);
}
state = state.MintAsset(context, agentAddress, ncgCurrency * initialNcg);
state = state.MintAsset(context, agentAddress, crystalCurrency * initialCrystal);
state = state.MintAsset(context, avatarAddress, runeCurrency * initialRune);

if (runeBal.Sign > 0)
{
state = state.MintAsset(context, avatarState.address, runeBal);
}

var action = new RuneEnhancement()
// Action
var action = new RuneEnhancement
{
AvatarAddress = avatarState.address,
RuneId = runeId,
Expand All @@ -124,62 +115,35 @@ public void Execute(int seed)
{
BlockIndex = blockIndex,
PreviousState = state,
RandomSeed = rand.Seed,
RandomSeed = seed,
Signer = agentAddress,
};

var nextState = action.Execute(ctx);
if (!nextState.TryGetLegacyState(runeStateAddress, out List nextRuneRawState))
{
throw new Exception();
}

var nextRunState = new RuneState(nextRuneRawState);
var nextNcgBal = nextState.GetBalance(agentAddress, ncgCurrency);
var nextCrystalBal = nextState.GetBalance(agentAddress, crystalCurrency);
var nextRuneBal = nextState.GetBalance(agentAddress, runeCurrency);

if (cost.NcgQuantity != 0)
{
Assert.NotEqual(ncgBal, nextNcgBal);
}

if (cost.CrystalQuantity != 0)
if (expectedException is not null)
{
Assert.NotEqual(crystalBal, nextCrystalBal);
Assert.Throws(expectedException, () => { action.Execute(ctx); });
}

if (cost.RuneStoneQuantity != 0)
else
{
Assert.NotEqual(runeBal, nextRuneBal);
}

var costNcg = tryCount * cost.NcgQuantity * ncgCurrency;
var costCrystal = tryCount * cost.CrystalQuantity * crystalCurrency;
var costRune = tryCount * cost.RuneStoneQuantity * runeCurrency;

if (costNcg.Sign > 0)
{
nextState = nextState.MintAsset(context, agentAddress, costNcg);
}

if (costCrystal.Sign > 0)
{
nextState = nextState.MintAsset(context, agentAddress, costCrystal);
}

if (costRune.Sign > 0)
{
nextState = nextState.MintAsset(context, avatarState.address, costRune);
var nextState = action.Execute(ctx);
if (!nextState.TryGetLegacyState(runeStateAddress, out List nextRuneRawState))
{
throw new Exception();
}

var nextRuneState = new RuneState(nextRuneRawState);
var nextNcgBal = nextState.GetBalance(agentAddress, ncgCurrency);
var nextCrystalBal = nextState.GetBalance(agentAddress, crystalCurrency);
var nextRuneBal = nextState.GetBalance(avatarAddress, runeCurrency);

Assert.Equal((initialNcg - expectedNcgCost) * ncgCurrency, nextNcgBal);
Assert.Equal(
(initialCrystal - expectedCrystalCost) * crystalCurrency,
nextCrystalBal
);
Assert.Equal((initialRune - expectedRuneCost) * runeCurrency, nextRuneBal);
Assert.Equal(expectedLevel, nextRuneState.Level);
}

var finalNcgBal = nextState.GetBalance(agentAddress, ncgCurrency);
var finalCrystalBal = nextState.GetBalance(agentAddress, crystalCurrency);
var finalRuneBal = nextState.GetBalance(avatarState.address, runeCurrency);
Assert.Equal(ncgBal, finalNcgBal);
Assert.Equal(crystalBal, finalCrystalBal);
Assert.Equal(runeBal, finalRuneBal);
Assert.Equal(runeState.Level + 1, nextRunState.Level);
}

[Fact]
Expand Down
50 changes: 50 additions & 0 deletions Lib9c/Action/CreateAvatar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
using System.Linq;
using System.Text.RegularExpressions;
using Bencodex.Types;
using Lib9c;
using Lib9c.Abstractions;
using Libplanet.Action;
using Libplanet.Action.State;
using Libplanet.Crypto;
using Nekoyume.Extensions;
using Nekoyume.Helper;
using Nekoyume.Model.Item;
using Nekoyume.Model.Stat;
using Nekoyume.Model.State;
Expand Down Expand Up @@ -345,6 +347,53 @@ public static AvatarState CreateAvatarState(string name,
return avatarState;
}

#if LIB9C_DEV_EXTENSIONS || UNITY_EDITOR
private static IWorld AddRunesForTest(
IActionContext context,
Address avatarAddress,
IWorld states,
int count = int.MaxValue)
{
var runeSheet = states.GetSheet<RuneSheet>();
foreach (var row in runeSheet.Values)
{
var rune = RuneHelper.ToFungibleAssetValue(row, count);
states = states.MintAsset(context, avatarAddress, rune);
}
return states;
}

private static IWorld AddSoulStoneForTest(
IActionContext context,
Address avatarAddress,
IWorld states,
int count = int.MaxValue)
{
var petSheet = states.GetSheet<PetSheet>();
foreach (var row in petSheet.Values)
{
var soulStone = Currencies.GetSoulStone(row.SoulStoneTicker) * count;
states = states.MintAsset(context, avatarAddress, soulStone);
}
return states;
}

private static IWorld AddPetsForTest(
Address avatarAddress,
IWorld states)
{
var petSheet = states.GetSheet<PetSheet>();
foreach (var id in petSheet.Keys)
{
var petState = new PetState(id);
petState.LevelUp();
var petStateAddress = PetState.DeriveAddress(avatarAddress, id);
states = states.SetLegacyState(petStateAddress, petState.Serialize());
}

return states;
}

private static void AddItemsForTest(
AvatarState avatarState,
IRandom random,
Expand Down Expand Up @@ -453,5 +502,6 @@ private static HashSet<int> AddOption(

return optionIds;
}
#endif
}
}
Loading

0 comments on commit f7c4236

Please sign in to comment.