Skip to content

Commit

Permalink
Merge pull request #35 from planetarium/handle-500
Browse files Browse the repository at this point in the history
Handle 404
  • Loading branch information
boscohyun authored May 7, 2024
2 parents e942d33 + a5afe5e commit 48e61cb
Show file tree
Hide file tree
Showing 10 changed files with 189 additions and 195 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Created by https://www.toptal.com/developers/gitignore/api/dotnetcore,aspnetcore
# Edit at https://www.toptal.com/developers/gitignore?templates=dotnetcore,aspnetcore

# OS junk files
*.DS_Store

### ASPNETCore ###
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
Expand Down
50 changes: 9 additions & 41 deletions NineChroniclesUtilBackend/Controllers/AgentController.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
using Microsoft.AspNetCore.Mvc;
using NineChroniclesUtilBackend.Models.Agent;
using Bencodex.Types;
using Libplanet.Crypto;
using Microsoft.AspNetCore.Mvc;
using Nekoyume;
using Nekoyume.Action;
using Nekoyume.Model.EnumType;
using Nekoyume.Model.Item;
using Nekoyume.Model.State;
using Nekoyume.TableData;
using NineChroniclesUtilBackend.Models.Arena;
using NineChroniclesUtilBackend.Services;
using NineChroniclesUtilBackend.Arena;

using NineChroniclesUtilBackend.Util;

namespace NineChroniclesUtilBackend.Controllers;

Expand All @@ -22,39 +12,17 @@ public class AccountController : ControllerBase
{
[HttpGet("{agentAddress}/avatars")]
public async Task<AvatarsResponse> GetAvatars(string agentAddress, IStateService stateService)
{
var avatarStates = await GetAvatarStates(new Address(agentAddress), stateService);
return new AvatarsResponse(avatarStates
.Select(a => new Avatar(a.address.ToString(), a.name, a.level))
.ToList());
}

private static async Task<List<AvatarState>> GetAvatarStates(Address agentAddress, IStateService stateService)
{
var rawState = await stateService.GetState(agentAddress, Addresses.Agent) ??
await stateService.GetState(agentAddress);
var agentState = rawState switch
var stateGetter = new StateGetter(stateService);
var avatars = await stateGetter.GetAvatarStatesAsync(new Address(agentAddress));
if (avatars is null)
{
Dictionary agentStateDictionary => new AgentState(agentStateDictionary),
List agentStateList => new AgentState(agentStateList),
_ => throw new ArgumentException(nameof(agentAddress)),
};

var avatars = new List<AvatarState>();
foreach(var avatarAddress in agentState.avatarAddresses.Values)
{
var rawAvatarState =
await stateService.GetState(avatarAddress, Addresses.Avatar) ??
await stateService.GetState(avatarAddress);
var avatarState = rawAvatarState switch
{
Dictionary avatarStateDictionary => new AvatarState(avatarStateDictionary),
List avatarStateList => new AvatarState(avatarStateList),
_ => throw new ArgumentException(nameof(avatarAddress))
};
avatars.Add(avatarState);
Response.StatusCode = StatusCodes.Status404NotFound;
return new AvatarsResponse([]);
}

return avatars;
return new AvatarsResponse(avatars
.Select(e => new Avatar(e.address.ToString(), e.name, e.level))
.ToList());
}
}
54 changes: 30 additions & 24 deletions NineChroniclesUtilBackend/Controllers/ArenaController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,14 @@ public class ArenaController(ArenaRankingRepository arenaRankingRepository) : Co
[HttpGet("ranking/{avatarAddress}/rank")]
public async Task<long> GetRankByAvatarAddress(string avatarAddress)
{
return await arenaRankingRepository.GetRankByAvatarAddress(avatarAddress);
var rank = await arenaRankingRepository.GetRankByAvatarAddress(avatarAddress);
if (rank == 0)
{
Response.StatusCode = StatusCodes.Status404NotFound;
return default;
}

return rank;
}

[HttpGet("ranking")]
Expand All @@ -28,19 +35,18 @@ public async Task<List<ArenaRanking>> GetRanking(int limit, int offset)
[HttpPost("simulate")]
public async Task<ArenaSimulateResponse> Simulate(
[FromBody] ArenaSimulateRequest arenaSimulateRequest,
IStateService stateService
)
IStateService stateService)
{
var stateGetter = new StateGetter(stateService);

var myAvatarAddress = new Address(arenaSimulateRequest.MyAvatarAddress);
var enemyAvatarAddress = new Address(arenaSimulateRequest.EnemyAvatarAddress);
var myAvatarState = await stateGetter.GetAvatarState(myAvatarAddress);
var myAvatarItemSlotState = await stateGetter.GetItemSlotState(myAvatarAddress);
var myAvatarRuneStates = await stateGetter.GetRuneStates(myAvatarAddress);
var enemyAvatarState = await stateGetter.GetAvatarState(enemyAvatarAddress);
var enemyAvatarItemSlotState = await stateGetter.GetItemSlotState(enemyAvatarAddress);
var enemyAvatarRuneStates = await stateGetter.GetRuneStates(enemyAvatarAddress);
var myAvatarState = await stateGetter.GetAvatarStateAsync(myAvatarAddress);
var myAvatarItemSlotState = await stateGetter.GetItemSlotStateAsync(myAvatarAddress);
var myAvatarRuneStates = await stateGetter.GetRuneStatesAsync(myAvatarAddress);
var enemyAvatarState = await stateGetter.GetAvatarStateAsync(enemyAvatarAddress);
var enemyAvatarItemSlotState = await stateGetter.GetItemSlotStateAsync(enemyAvatarAddress);
var enemyAvatarRuneStates = await stateGetter.GetRuneStatesAsync(enemyAvatarAddress);

var bulkSimulator = new ArenaBulkSimulator();
var result = await bulkSimulator.BulkSimulate(
Expand All @@ -51,22 +57,22 @@ IStateService stateService
enemyAvatarRuneStates
),
new ArenaSimulatorSheets(
await stateGetter.GetSheet<MaterialItemSheet>(),
await stateGetter.GetSheet<SkillSheet>(),
await stateGetter.GetSheet<SkillBuffSheet>(),
await stateGetter.GetSheet<StatBuffSheet>(),
await stateGetter.GetSheet<SkillActionBuffSheet>(),
await stateGetter.GetSheet<ActionBuffSheet>(),
await stateGetter.GetSheet<CharacterSheet>(),
await stateGetter.GetSheet<CharacterLevelSheet>(),
await stateGetter.GetSheet<EquipmentItemSetEffectSheet>(),
await stateGetter.GetSheet<CostumeStatSheet>(),
await stateGetter.GetSheet<WeeklyArenaRewardSheet>(),
await stateGetter.GetSheet<RuneOptionSheet>()
await stateGetter.GetSheetAsync<MaterialItemSheet>(),
await stateGetter.GetSheetAsync<SkillSheet>(),
await stateGetter.GetSheetAsync<SkillBuffSheet>(),
await stateGetter.GetSheetAsync<StatBuffSheet>(),
await stateGetter.GetSheetAsync<SkillActionBuffSheet>(),
await stateGetter.GetSheetAsync<ActionBuffSheet>(),
await stateGetter.GetSheetAsync<CharacterSheet>(),
await stateGetter.GetSheetAsync<CharacterLevelSheet>(),
await stateGetter.GetSheetAsync<EquipmentItemSetEffectSheet>(),
await stateGetter.GetSheetAsync<CostumeStatSheet>(),
await stateGetter.GetSheetAsync<WeeklyArenaRewardSheet>(),
await stateGetter.GetSheetAsync<RuneOptionSheet>()
),
await stateGetter.GetCollectionStates([myAvatarAddress, enemyAvatarAddress]),
await stateGetter.GetSheet<CollectionSheet>(),
await stateGetter.GetSheet<DeBuffLimitSheet>()
await stateGetter.GetCollectionStatesAsync([myAvatarAddress, enemyAvatarAddress]),
await stateGetter.GetSheetAsync<CollectionSheet>(),
await stateGetter.GetSheetAsync<DeBuffLimitSheet>()
);

return new ArenaSimulateResponse(result);
Expand Down
13 changes: 11 additions & 2 deletions NineChroniclesUtilBackend/Controllers/AvatarController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ namespace NineChroniclesUtilBackend.Controllers;
public class AvatarController(AvatarRepository avatarRepository) : ControllerBase
{
[HttpGet("{avatarAddress}/inventory")]
public Inventory GetInventory(string avatarAddress) =>
avatarRepository.GetInventory(avatarAddress);
public Inventory? GetInventory(string avatarAddress)
{
var inventory = avatarRepository.GetInventory(avatarAddress);
if (inventory is null)
{
Response.StatusCode = StatusCodes.Status404NotFound;
return null;
}

return inventory;
}
}
2 changes: 0 additions & 2 deletions NineChroniclesUtilBackend/Models/Agent/Avatar.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using MongoDB.Bson;

namespace NineChroniclesUtilBackend.Models.Agent;

public class Avatar(string avatarAddress, string avatarName, int level)
Expand Down
36 changes: 18 additions & 18 deletions NineChroniclesUtilBackend/Models/Arena/ArenaRanking.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@
namespace NineChroniclesUtilBackend.Models.Arena;

public class ArenaRanking(
string AvatarAddress,
string ArenaAddress,
int Win,
int Lose,
long Rank,
int Ticket,
int TicketResetCount,
int PurchasedTicketCount,
int Score
string avatarAddress,
string arenaAddress,
int win,
int lose,
long rank,
int ticket,
int ticketResetCount,
int purchasedTicketCount,
int score
)
{
public string AvatarAddress { get; set; } = AvatarAddress;
public string ArenaAddress { get; set; } = ArenaAddress;
public string AvatarAddress { get; set; } = avatarAddress;
public string ArenaAddress { get; set; } = arenaAddress;
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public int? CP { get; set; }
public int Win { get; set; } = Win;
public int Lose { get; set; } = Lose;
public long Rank { get; set; } = Rank;
public int Ticket { get; set; } = Ticket;
public int TicketResetCount { get; set; } = TicketResetCount;
public int PurchasedTicketCount { get; set; } = PurchasedTicketCount;
public int Score { get; set; } = Score;
public int Win { get; set; } = win;
public int Lose { get; set; } = lose;
public long Rank { get; set; } = rank;
public int Ticket { get; set; } = ticket;
public int TicketResetCount { get; set; } = ticketResetCount;
public int PurchasedTicketCount { get; set; } = purchasedTicketCount;
public int Score { get; set; } = score;

[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public Agent.Avatar? Avatar { get; set; }
Expand Down
29 changes: 14 additions & 15 deletions NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using MongoDB.Bson;
using MongoDB.Driver;
using Nekoyume.Model.State;
using NineChroniclesUtilBackend.Models.Agent;
using NineChroniclesUtilBackend.Models.Arena;
using NineChroniclesUtilBackend.Services;
Expand All @@ -9,10 +8,9 @@ namespace NineChroniclesUtilBackend.Repositories;

public class ArenaRankingRepository(MongoDBCollectionService mongoDBCollectionService, IStateService stateService)
{
private CpRepository cpRepository = new CpRepository(stateService);

private readonly IMongoCollection<dynamic> ArenaCollection =
private readonly IMongoCollection<dynamic> _arenaCollection =
mongoDBCollectionService.GetCollection<dynamic>("arena");
private readonly CpRepository _cpRepository = new(stateService);

public async Task<long> GetRankByAvatarAddress(string avatarAddress)
{
Expand All @@ -33,10 +31,10 @@ public async Task<long> GetRankByAvatarAddress(string avatarAddress)
),
new("$match", new BsonDocument("docs.AvatarAddress", avatarAddress)),
};

var aggregation = await ArenaCollection.Aggregate<dynamic>(pipelines).ToListAsync();

return aggregation.First().Rank;
var aggregation = await _arenaCollection.Aggregate<dynamic>(pipelines).ToListAsync();
return aggregation.Count == 0
? 0
: (long)aggregation.First().Rank;
}

public async Task<List<ArenaRanking>> GetRanking(long limit, long offset)
Expand All @@ -50,10 +48,8 @@ public async Task<List<ArenaRanking>> GetRanking(long limit, long offset)
@"{ $unwind: { path: '$Avatar', preserveNullAndEmptyArrays: true } }",
@"{ $unset: ['Avatar.Avatar.inventory', 'Avatar.Avatar.mailBox', 'Avatar.Avatar.stageMap', 'Avatar.Avatar.monsterMap', 'Avatar.Avatar.itemMap', 'Avatar.Avatar.eventMap'] }",
}.Select(BsonDocument.Parse).ToArray();

var aggregation = ArenaCollection.Aggregate<BsonDocument>(pipelines).ToList();
var aggregation = _arenaCollection.Aggregate<BsonDocument>(pipelines).ToList();
var arenaRankings = await Task.WhenAll(aggregation.OfType<BsonDocument>().Select(BuildArenaRankingFromDocument));

return [.. arenaRankings];
}

Expand All @@ -71,7 +67,10 @@ private async Task<ArenaRanking> BuildArenaRankingFromDocument(BsonDocument docu
document["Score"]["Score"].AsInt32
);

if (!document.Contains("Avatar")) return arenaRanking;
if (!document.Contains("Avatar"))
{
return arenaRanking;
}

var avatar = new Avatar(
document["Avatar"]["Avatar"]["address"].AsString,
Expand All @@ -81,13 +80,13 @@ private async Task<ArenaRanking> BuildArenaRankingFromDocument(BsonDocument docu
arenaRanking.Avatar = avatar;

var characterId = document["Avatar"]["Avatar"]["characterId"].AsInt32;
var equipmentids = document["Avatar"]["ItemSlot"]["Equipments"].AsBsonArray.Select(x => x.AsString);
var costumeids = document["Avatar"]["ItemSlot"]["Costumes"].AsBsonArray.Select(x => x.AsString);
var equipmentIds = document["Avatar"]["ItemSlot"]["Equipments"].AsBsonArray.Select(x => x.AsString);
var costumeIds = document["Avatar"]["ItemSlot"]["Costumes"].AsBsonArray.Select(x => x.AsString);
var runeSlots = document["Avatar"]["RuneSlot"].AsBsonArray.Select(rune =>
(rune["RuneId"].AsInt32, rune["Level"].AsInt32)
);

var cp = await cpRepository.CalculateCp(avatar, characterId, equipmentids, costumeids, runeSlots);
var cp = await _cpRepository.CalculateCp(avatar, characterId, equipmentIds, costumeIds, runeSlots);
arenaRanking.CP = cp;
Console.WriteLine($"CP Calculate {arenaRanking.ArenaAddress}");

Expand Down
7 changes: 6 additions & 1 deletion NineChroniclesUtilBackend/Repositories/AvatarRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,16 @@ public class AvatarRepository(MongoDBCollectionService mongoDBCollectionService)
private readonly IMongoCollection<BsonDocument> _avatarsCollection =
mongoDBCollectionService.GetCollection<BsonDocument>("avatars");

public Inventory GetInventory(string avatarAddress)
public Inventory? GetInventory(string avatarAddress)
{
var filter = Builders<BsonDocument>.Filter.Eq(f => f["Avatar"]["address"], avatarAddress);
var projection = Builders<BsonDocument>.Projection.Include(f => f["Avatar"]["inventory"]["Equipments"]);
var document = _avatarsCollection.Find(filter).Project(projection).FirstOrDefault();
if (document is null)
{
return null;
}

return new Inventory(document["Avatar"]["inventory"]);
}
}
12 changes: 6 additions & 6 deletions NineChroniclesUtilBackend/Repositories/CpRepository.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ public CpRepository(IStateService stateService)
var avatarAddress = new Address(avatar.AvatarAddress);

var characterRow = await GetCharacterRow(characterId);
var costumeStatSheet = await _stateGetter.GetSheet<CostumeStatSheet>();
var collectionSheets = await _stateGetter.GetSheet<CollectionSheet>();
var costumeStatSheet = await _stateGetter.GetSheetAsync<CostumeStatSheet>();
var collectionSheets = await _stateGetter.GetSheetAsync<CollectionSheet>();

var inventoryState = await _stateGetter.GetInventoryState(avatarAddress);
var inventoryState = await _stateGetter.GetInventoryStateAsync(avatarAddress);

List<Equipment> equipments = inventoryState
.Equipments
Expand All @@ -45,7 +45,7 @@ public CpRepository(IStateService stateService)
.Costumes
.Where(x => x.Equipped).ToList();
List<RuneOptionSheet.Row.RuneOptionInfo> runes = runeOption.Select(x => GetRuneOptionInfo(x.id, x.level).Result).ToList();
var collectionStates = await _stateGetter.GetCollectionStates([avatarAddress]);
var collectionStates = await _stateGetter.GetCollectionStatesAsync([avatarAddress]);
var modifiers = new Dictionary<Address, List<StatModifier>>
{
[avatarAddress] = new(),
Expand Down Expand Up @@ -83,7 +83,7 @@ public CpRepository(IStateService stateService)
int level
)
{
var sheets = await _stateGetter.GetSheet<RuneOptionSheet>();
var sheets = await _stateGetter.GetSheetAsync<RuneOptionSheet>();

if (!sheets.TryGetValue(id, out var optionRow))
{
Expand All @@ -100,7 +100,7 @@ int level

private async Task<CharacterSheet.Row> GetCharacterRow(int characterId)
{
var sheets = await _stateGetter.GetSheet<CharacterSheet>();
var sheets = await _stateGetter.GetSheetAsync<CharacterSheet>();

if (!sheets.TryGetValue(characterId, out var row))
{
Expand Down
Loading

0 comments on commit 48e61cb

Please sign in to comment.