Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: handle ArenaParticipant account state with diff poller #481

Merged
merged 24 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions Lib9c.Models.Tests/Arena/ArenaParticipantTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using Bencodex.Types;
using Lib9c.Models.Arena;
using Lib9c.Models.Tests.Fixtures.States;

namespace Lib9c.Models.Tests.States;

public class ArenaParticipantTest
{
[Fact]
public void Test()
{
// Prepare target state
var value = StateReader.ReadState("ArenaParticipant");
var target = new Nekoyume.Model.Arena.ArenaParticipant((List)value);

// serialize target state and deserialize as paired state
var targetBencoded = target.Bencoded;
var paired = new ArenaParticipant(targetBencoded);
Assert.Equal(target.AvatarAddr, paired.AvatarAddr);
Assert.Equal(target.Name, paired.Name);
Assert.Equal(target.PortraitId, paired.PortraitId);
Assert.Equal(target.Level, paired.Level);
Assert.Equal(target.Cp, paired.Cp);
Assert.Equal(target.Score, paired.Score);
Assert.Equal(target.Ticket, paired.Ticket);
Assert.Equal(target.TicketResetCount, paired.TicketResetCount);
Assert.Equal(target.PurchasedTicketCount, paired.PurchasedTicketCount);
Assert.Equal(target.Win, paired.Win);
Assert.Equal(target.Lose, paired.Lose);
Assert.Equal(target.LastBattleBlockIndex, paired.LastBattleBlockIndex);

// serialize paired state and verify
var pairedBencoded = paired.Bencoded;
Assert.Equal(targetBencoded, pairedBencoded);

// deserialize bencoded state as target2 and verify
var target2 = new Nekoyume.Model.Arena.ArenaParticipant((List)pairedBencoded);
var target2Bencoded = target2.Bencoded;
Assert.Equal(targetBencoded, target2Bencoded);
}
}
1 change: 1 addition & 0 deletions Lib9c.Models.Tests/Fixtures/States/ArenaParticipant
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6c69316532303adc61990d14ed397de08901004d5fc11f8336627575343a6e6963656931303235343030316569333438656936323331363865693232353365693665693965693065693734656930656931323431323439306565
9 changes: 2 additions & 7 deletions Lib9c.Models.Tests/Fixtures/States/StateReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,9 @@ public static class StateReader
private static readonly Codec Codec = new();

public static IValue ReadState(string fileName)
{
var file = GetFile(fileName);
return Codec.Decode(ByteUtil.ParseHex(file));
}

private static string GetFile(string fileName)
{
var path = Path.Combine(StatesFullPath, fileName);
return File.ReadAllText(path).Trim();
var text = File.ReadAllText(path).Trim();
return Codec.Decode(ByteUtil.ParseHex(text));
}
}
94 changes: 94 additions & 0 deletions Lib9c.Models/Arena/ArenaParticipant.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using System.Text.Json.Serialization;
using Bencodex;
using Bencodex.Types;
using Lib9c.Models.Exceptions;
using Libplanet.Crypto;
using MongoDB.Bson.Serialization.Attributes;
using Nekoyume.Model.State;
using ValueKind = Bencodex.Types.ValueKind;

namespace Lib9c.Models.Arena;

[BsonIgnoreExtraElements]
public record ArenaParticipant : IBencodable
{
public const int StateVersion = 1;

public Address AvatarAddr { get; init; }

/// <summary>The name of avatar</summary>
/// <remarks>
/// If you need to know <see cref="Nekoyume.Model.State.AvatarState.NameWithHash"/>, check
/// <see cref="Nekoyume.Model.State.AvatarState.PostConstructor"/> method of the
/// <see cref="Nekoyume.Model.State.AvatarState"/> class and you can find the relevant information there. It
/// provides a formatted string that includes the avatar's <see cref="Nekoyume.Model.State.AvatarState.name"/>
/// and a shortened version of their address.
/// </remarks>
/// <example>
/// <code>
/// $"{name} &lt;size=80%&gt;&lt;color=#A68F7E&gt;#{address.ToHex().Substring(0, 4)}&lt;/color&gt;&lt;/size&gt;";
/// </code>
/// </example>
public string Name { get; init; }

public int PortraitId { get; init; }
public int Level { get; init; }
public int Cp { get; init; }

public int Score { get; init; }

public int Ticket { get; init; }
public int TicketResetCount { get; init; }
public int PurchasedTicketCount { get; init; }

public int Win { get; init; }
public int Lose { get; init; }

public long LastBattleBlockIndex { get; init; }

[BsonIgnore, GraphQLIgnore, JsonIgnore]
public IValue Bencoded => List.Empty
.Add(StateVersion)
.Add(AvatarAddr.Serialize())
.Add(Name)
.Add(PortraitId)
.Add(Level)
.Add(Cp)
.Add(Score)
.Add(Ticket)
.Add(TicketResetCount)
.Add(PurchasedTicketCount)
.Add(Win)
.Add(Lose)
.Add(LastBattleBlockIndex);

public ArenaParticipant(IValue bencoded)
{
if (bencoded is not List l)
{
throw new UnsupportedArgumentTypeException<ValueKind>(
nameof(bencoded),
new[] { ValueKind.List },
bencoded.Kind);
}

var stateVersion = (Integer)l[0];
if (stateVersion != StateVersion)
{
throw new UnsupportedModelVersionException(StateVersion, stateVersion);
}

AvatarAddr = l[1].ToAddress();
Name = (Text)l[2];
PortraitId = (Integer)l[3];
Level = (Integer)l[4];
Cp = (Integer)l[5];
Score = (Integer)l[6];
Ticket = (Integer)l[7];
TicketResetCount = (Integer)l[8];
PurchasedTicketCount = (Integer)l[9];
Win = (Integer)l[10];
Lose = (Integer)l[11];
LastBattleBlockIndex = (Integer)l[12];
}
}
14 changes: 14 additions & 0 deletions Lib9c.Models/Exceptions/UnsupportedModelVersionException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Lib9c.Models.Exceptions;

public class UnsupportedModelVersionException : Exception
{
public UnsupportedModelVersionException(
int expected,
int actual,
Exception? innerException = null)
: base(
$"Expected model version: {expected}. Actual: {actual}.",
innerException)
{
}
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"Object":{"AvatarAddr":"Dc61990d14ed397dE08901004d5FC11f83366275","Name":"nice","PortraitId":10254001,"Level":348,"Cp":623168,"Score":2253,"Ticket":6,"TicketResetCount":9,"PurchasedTicketCount":0,"Win":74,"Lose":0,"LastBattleBlockIndex":12412490},"ChampionshipId":0,"Round":0,"SimpleAvatar":{"Version":2,"Name":"Jonik","CharacterId":100010,"Level":302,"Exp":51238,"UpdatedAt":11975018,"AgentAddress":"2cBDdFAf873cAdF19eb78c2036150EBD5Ebc5F18","BlockIndex":11754099,"Hair":6,"Lens":2,"Ear":6,"Tail":6,"CombinationSlotAddresses":["304576414515a020AC24A6a217414353e99Ec31b","6B8Ec4fA8784500dd227F801Fc3720CA2Cd28aE9","8858f547F4BA3DAb7907bEC1fd610e358cE61150","9D318C2C81A8a142528B4b0B985BF54a376C7634"],"RankingMapAddress":"d36Ee641d5FD8F247289EFB4D0aB8266F66A5DEa","Address":"400004d1b249070CA61Dd4349dcb0dF1613d78ab"},"Metadata":{"SchemaVersion":1,"StoredBlockIndex":0}}
23 changes: 23 additions & 0 deletions Mimir.MongoDB.Tests/Bson/ArenaParticipantDocumentTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Lib9c.Models.Arena;
using Lib9c.Models.States;
using Mimir.MongoDB.Bson;
using Mimir.MongoDB.Tests.TestDatas;

namespace Mimir.MongoDB.Tests.Bson;

public class ArenaParticipantDocumentTest
{
[Fact]
public Task JsonSnapshot()
{
var docs = new ArenaParticipantDocument(
default,
default,
new ArenaParticipant(TestDataHelpers.LoadState("ArenaParticipant.bin")),
default,
default,
SimplifiedAvatarState.FromAvatarState(
new AvatarState(TestDataHelpers.LoadState("Avatar.bin"))));
return Verify(docs.ToJson());
}
}
Binary file not shown.
2 changes: 1 addition & 1 deletion Mimir.MongoDB/Bson/ArenaDocument.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
using System.Text.Json.Serialization;
using Lib9c.Models.Arena;
using Lib9c.Models.States;
using Libplanet.Crypto;
using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;
using Newtonsoft.Json;

namespace Mimir.MongoDB.Bson;

Expand Down
18 changes: 18 additions & 0 deletions Mimir.MongoDB/Bson/ArenaParticipantDocument.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Lib9c.Models.Arena;
using Lib9c.Models.States;
using Libplanet.Crypto;
using MongoDB.Bson.Serialization.Attributes;
using Newtonsoft.Json;

namespace Mimir.MongoDB.Bson;

/// <param name="Address">Avatar address</param>
[BsonIgnoreExtraElements]
public record ArenaParticipantDocument(
[property: BsonIgnore, JsonIgnore] long StoredBlockIndex,
[property: BsonIgnore, JsonIgnore] Address Address,
ArenaParticipant Object,
int ChampionshipId,
int Round,
SimplifiedAvatarState SimpleAvatar
) : MimirBsonDocument(Address, new DocumentMetadata(ArenaParticipant.StateVersion, StoredBlockIndex));
11 changes: 10 additions & 1 deletion Mimir.MongoDB/Bson/Simplified/SimplifiedAvatarState.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
using System.Text.Json.Serialization;
using Bencodex.Types;
using HotChocolate;
using Lib9c.Models.Exceptions;
using Lib9c.Models.Extensions;
using Lib9c.Models.Mails;
using Libplanet.Crypto;
using Mimir.MongoDB.Bson;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Attributes;
using Nekoyume.Model;
using Newtonsoft.Json;
using ValueKind = Bencodex.Types.ValueKind;

namespace Lib9c.Models.States;
Expand Down Expand Up @@ -192,4 +195,10 @@ public static SimplifiedAvatarState FromAvatarState(AvatarState avatarState)
avatarState.RankingMapAddress
);
}

public static SimplifiedAvatarState FromAvatarDocument(BsonValue bsonValue)
{
var avatarDoc = BsonSerializer.Deserialize<AvatarDocument>(bsonValue.AsBsonDocument);
return FromAvatarState(avatarDoc.Object);
}
}
1 change: 1 addition & 0 deletions Mimir.MongoDB/CollectionNames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ private static void RegisterCollectionAndStateMappings()
CollectionAndStateTypeMappings.Add(typeof(AllRuneDocument), "all_rune");
CollectionAndStateTypeMappings.Add(typeof(AvatarDocument), "avatar");
CollectionAndStateTypeMappings.Add(typeof(ArenaDocument), "arena");
CollectionAndStateTypeMappings.Add(typeof(ArenaParticipantDocument), "arena_participant");
CollectionAndStateTypeMappings.Add(typeof(CollectionDocument), "collection");
CollectionAndStateTypeMappings.Add(typeof(DailyRewardDocument), "daily_reward");
CollectionAndStateTypeMappings.Add(typeof(ItemSlotDocument), "item_slot");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
using Bencodex.Types;
using Libplanet.Common;

namespace Lib9c.Models.Tests.Fixtures.States;
namespace Mimir.Worker.Tests.Fixtures.States;

public static class StateWriter
public static class StateReader
{
private static readonly string StatesFullPath = Path.GetFullPath(
Path.Combine(
Expand All @@ -15,15 +15,10 @@ public static class StateWriter

private static readonly Codec Codec = new();

public static void WriteState(string fileName, IValue bencoded)
{
var hex = ByteUtil.Hex(Codec.Encode(bencoded));
WriteFile(fileName, hex);
}

private static void WriteFile(string fileName, string hex)
public static IValue ReadState(string fileName)
{
var path = Path.Combine(StatesFullPath, fileName);
File.WriteAllText(path, hex);
var text = File.ReadAllText(path).Trim();
return Codec.Decode(ByteUtil.ParseHex(text));
}
}
1 change: 1 addition & 0 deletions Mimir.Worker.Tests/Fixtures/States/arenaParticipant
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
6c69316532303adc61990d14ed397de08901004d5fc11f8336627575343a6e6963656931303235343030316569333438656936323331363865693232353365693665693965693065693734656930656931323431323439306565
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using Libplanet.Crypto;
using Mimir.MongoDB.Bson;
using Mimir.Worker.StateDocumentConverter;

namespace Mimir.Worker.Tests.StateDocumentConverter;

public class ArenaParticipantDocumentConverterTests
{
[Fact]
public void ConvertToStateData()
{
var address = new PrivateKey().Address;
var state = new Nekoyume.Model.Arena.ArenaParticipant(address)
{
Name = "Test Participant",
};
var bencoded = state.Bencoded;
var context = new AddressStatePair
{
Address = address,
RawState = bencoded,
};
var doc = ArenaParticipantDocumentConverter.ConvertToDocument(
context,
1,
1,
null);
Assert.IsType<ArenaParticipantDocument>(doc);
var arenaParticipantDoc = (ArenaParticipantDocument)doc;
Assert.Equal(address, arenaParticipantDoc.Address);
Assert.Equal(bencoded, arenaParticipantDoc.Object.Bencoded);
Assert.Equal(1, arenaParticipantDoc.ChampionshipId);
Assert.Equal(1, arenaParticipantDoc.Round);
Assert.Null(arenaParticipantDoc.SimpleAvatar);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using Libplanet.Crypto;
using Mimir.MongoDB.Bson;
using Mimir.Worker.StateDocumentConverter;
using Mimir.Worker.Tests.Fixtures.States;

namespace Mimir.Worker.Tests.StateDocumentConverter;

Expand All @@ -14,11 +15,11 @@ public class AvatarStateDocumentConverterTests
public void ConvertToStateData()
{
var address = new Address("4b4eccd6c6b17fe8d4312a0d2fadb0c93ad5a7ba");
var rawState = TestHelpers.ReadTestData("avatarState.txt");
var rawState = StateReader.ReadState("avatarState");
var context = new AddressStatePair()
{
Address = address,
RawState = Codec.Decode(Convert.FromHexString(rawState)),
RawState = rawState,
};
var state = _converter.ConvertToDocument(context);

Expand Down
13 changes: 0 additions & 13 deletions Mimir.Worker.Tests/TestHelpers.cs

This file was deleted.

Loading
Loading