From 4a1313b1695d156b3329ef67ba357eec587244a4 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Tue, 7 May 2024 16:30:16 +0900 Subject: [PATCH 1/6] refactor StateGatter --- .../Controllers/AgentController.cs | 50 +---- NineChroniclesUtilBackend/Util/StateGetter.cs | 178 +++++++++--------- 2 files changed, 101 insertions(+), 127 deletions(-) diff --git a/NineChroniclesUtilBackend/Controllers/AgentController.cs b/NineChroniclesUtilBackend/Controllers/AgentController.cs index 6e2a5bb2..bd72ee72 100644 --- a/NineChroniclesUtilBackend/Controllers/AgentController.cs +++ b/NineChroniclesUtilBackend/Controllers/AgentController.cs @@ -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; @@ -22,39 +12,17 @@ public class AccountController : ControllerBase { [HttpGet("{agentAddress}/avatars")] public async Task 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> 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(); - 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()); } } diff --git a/NineChroniclesUtilBackend/Util/StateGetter.cs b/NineChroniclesUtilBackend/Util/StateGetter.cs index a51ebf3b..0fc2bef5 100644 --- a/NineChroniclesUtilBackend/Util/StateGetter.cs +++ b/NineChroniclesUtilBackend/Util/StateGetter.cs @@ -10,21 +10,23 @@ namespace NineChroniclesUtilBackend.Util; -public class StateGetter +public class StateGetter(IStateService stateService) { - private readonly IStateService _stateService; - - public StateGetter(IStateService stateService) - { - _stateService = stateService; - } - - public async Task GetSheet() + public async Task GetStateAsync(Address address, Address accountAddress) => + await stateService.GetState(address, accountAddress) ?? + await stateService.GetState(address); + + public async Task GetStateWithLegacyAccountAsync( + Address address, + Address accountAddress, + Address legacyAddress) => + await stateService.GetState(address, accountAddress) ?? + await stateService.GetState(legacyAddress); + + public async Task GetSheetAsync() where T : ISheet, new() { - var sheetState = await _stateService.GetState( - Addresses.TableSheet.Derive(typeof(T).Name) - ); + var sheetState = await stateService.GetState(Addresses.GetSheetAddress()); if (sheetState is not Text sheetValue) { throw new ArgumentException(nameof(T)); @@ -34,127 +36,131 @@ public async Task GetSheet() sheet.Set(sheetValue.Value); return sheet; } - - public async Task GetAvatarState(Address avatarAddress) + + public async Task?> GetAvatarStatesAsync( + Address agentAddress, + bool withInventory = true) { - var state = await GetStateWithLegacyAccount(avatarAddress, Addresses.Avatar); - var inventory = await GetInventoryState(avatarAddress); - - AvatarState avatarState; - if (state is Dictionary dictionary) + var rawState = await stateService.GetState(agentAddress, Addresses.Agent) ?? + await stateService.GetState(agentAddress); + var agentState = rawState switch { - avatarState = new AvatarState(dictionary) - { - inventory = inventory - }; - } - else if (state is List alist) + List agentStateList => new AgentState(agentStateList), + Dictionary agentStateDictionary => new AgentState(agentStateDictionary), + _ => null, + }; + if (agentState is null) { - avatarState = new AvatarState(alist) - { - inventory = inventory - }; + return null; } - else + + var avatars = new List(); + foreach(var avatarAddress in agentState.avatarAddresses.Values) { - throw new ArgumentException($"Unsupported state type for address: {avatarAddress}"); + var avatarState = await GetAvatarStateAsync(avatarAddress, withInventory); + if (avatarState is null) + { + continue; + } + + avatars.Add(avatarState); } - return avatarState; + return avatars; } - public async Task GetInventoryState(Address avatarAddress) + public async Task GetAvatarStateAsync( + Address avatarAddress, + bool withInventory = true) { + var avatarValue = await GetStateAsync(avatarAddress, Addresses.Avatar); + var avatarState = avatarValue switch + { + List list => new AvatarState(list), + Dictionary dictionary => new AvatarState(dictionary), + _ => null, + }; + if (avatarState is null) + { + return null; + } - var legacyInventoryAddress = avatarAddress.Derive("inventory"); - var rawState = await GetAvatarStateWithLegacyAccount( - avatarAddress, Addresses.Inventory, legacyInventoryAddress); - - if (rawState is not List list) + if (withInventory) { - throw new ArgumentException(nameof(avatarAddress)); + var inventory = await GetInventoryStateAsync(avatarAddress); + if (inventory is not null) + { + avatarState.inventory = inventory; + } } + + return avatarState; + } - return new Inventory(list); + public async Task GetInventoryStateAsync(Address avatarAddress) + { + var rawState = await GetStateWithLegacyAccountAsync( + avatarAddress, + Addresses.Inventory, + avatarAddress.Derive("inventory")); + return rawState is List list + ? new Inventory(list) + : null; } - public async Task GetItemSlotState(Address avatarAddress) + public async Task GetItemSlotStateAsync(Address avatarAddress) { - var state = await _stateService.GetState( + var state = await stateService.GetState( ItemSlotState.DeriveAddress(avatarAddress, BattleType.Arena)); return state switch { List list => new ItemSlotState(list), null => new ItemSlotState(BattleType.Arena), - _ => throw new ArgumentException(nameof(avatarAddress)) + _ => null, }; } - public async Task> GetRuneStates(Address avatarAddress) + public async Task> GetRuneStatesAsync(Address avatarAddress) { - var state = await _stateService.GetState( + var state = await stateService.GetState( RuneSlotState.DeriveAddress(avatarAddress, BattleType.Arena)); var runeSlotState = state switch { List list => new RuneSlotState(list), null => new RuneSlotState(BattleType.Arena), - _ => throw new ArgumentException(nameof(avatarAddress)) + _ => null, }; - - var runes = new List(); - foreach (var runeStateAddress in runeSlotState.GetEquippedRuneSlotInfos().Select(info => RuneState.DeriveAddress(avatarAddress, info.RuneId))) + if (runeSlotState is null) { - if (await _stateService.GetState(runeStateAddress) is List list) - { - runes.Add(new RuneState(list)); - } + return []; } - return runes; + var runeAddresses = runeSlotState.GetEquippedRuneSlotInfos() + .Select(info => RuneState.DeriveAddress(avatarAddress, info.RuneId)) + .ToArray(); + var runeValues = await stateService.GetStates(runeAddresses); + return runeValues.OfType() + .Select(e => new RuneState(e)) + .ToList(); } - public async Task> GetCollectionStates(List
addresses) + public async Task> GetCollectionStatesAsync(List
addresses) { var result = new Dictionary(); - - var values = await _stateService.GetStates( + var values = await stateService.GetStates( addresses.ToArray(), Addresses.Collection ); - - for (int i = 0; i < addresses.Count; i++) + for (var i = 0; i < addresses.Count; i++) { - var serialized = values[i]; var address = addresses[i]; - - if (serialized is List bencoded) + var serialized = values[i]; + if (serialized is List list) { - result.TryAdd(address, new CollectionState(bencoded)); + result.TryAdd(address, new CollectionState(list)); } } - - return result; - } - - public async Task GetStateWithLegacyAccount(Address address, Address accountAddress) - { - var state = await _stateService.GetState(address, accountAddress); - - if (state == null) - { - state = await _stateService.GetState(address); - } - return state; - } - public async Task GetAvatarStateWithLegacyAccount(Address avatarAddress, Address accountAddress, Address legacyAddress) - { - var state = await _stateService.GetState(avatarAddress, accountAddress); - - if (state == null) - { - state = await _stateService.GetState(legacyAddress); - } - return state; + return result; } } From f1f85747d71d49b6dfa2f3a69eb2bacafde9d93f Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Tue, 7 May 2024 16:31:22 +0900 Subject: [PATCH 2/6] rename minor --- .../Controllers/ArenaController.cs | 45 +++++++++---------- .../Models/Arena/ArenaRanking.cs | 36 +++++++-------- .../Repositories/ArenaRankingRespository.cs | 21 +++++---- .../Repositories/CpRepository.cs | 12 ++--- 4 files changed, 56 insertions(+), 58 deletions(-) diff --git a/NineChroniclesUtilBackend/Controllers/ArenaController.cs b/NineChroniclesUtilBackend/Controllers/ArenaController.cs index 3edcc184..7b015003 100644 --- a/NineChroniclesUtilBackend/Controllers/ArenaController.cs +++ b/NineChroniclesUtilBackend/Controllers/ArenaController.cs @@ -28,19 +28,18 @@ public async Task> GetRanking(int limit, int offset) [HttpPost("simulate")] public async Task 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( @@ -51,22 +50,22 @@ IStateService stateService enemyAvatarRuneStates ), new ArenaSimulatorSheets( - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet(), - await stateGetter.GetSheet() + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync() ), - await stateGetter.GetCollectionStates([myAvatarAddress, enemyAvatarAddress]), - await stateGetter.GetSheet(), - await stateGetter.GetSheet() + await stateGetter.GetCollectionStatesAsync([myAvatarAddress, enemyAvatarAddress]), + await stateGetter.GetSheetAsync(), + await stateGetter.GetSheetAsync() ); return new ArenaSimulateResponse(result); diff --git a/NineChroniclesUtilBackend/Models/Arena/ArenaRanking.cs b/NineChroniclesUtilBackend/Models/Arena/ArenaRanking.cs index 915d130b..3dcd74a9 100644 --- a/NineChroniclesUtilBackend/Models/Arena/ArenaRanking.cs +++ b/NineChroniclesUtilBackend/Models/Arena/ArenaRanking.cs @@ -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; } diff --git a/NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs b/NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs index e1bfc95c..41019735 100644 --- a/NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs +++ b/NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs @@ -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; @@ -9,10 +8,9 @@ namespace NineChroniclesUtilBackend.Repositories; public class ArenaRankingRepository(MongoDBCollectionService mongoDBCollectionService, IStateService stateService) { - private CpRepository cpRepository = new CpRepository(stateService); - - private readonly IMongoCollection ArenaCollection = + private readonly IMongoCollection _arenaCollection = mongoDBCollectionService.GetCollection("arena"); + private readonly CpRepository _cpRepository = new(stateService); public async Task GetRankByAvatarAddress(string avatarAddress) { @@ -50,10 +48,8 @@ public async Task> 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(pipelines).ToList(); + var aggregation = _arenaCollection.Aggregate(pipelines).ToList(); var arenaRankings = await Task.WhenAll(aggregation.OfType().Select(BuildArenaRankingFromDocument)); - return [.. arenaRankings]; } @@ -71,7 +67,10 @@ private async Task 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, @@ -81,13 +80,13 @@ private async Task 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}"); diff --git a/NineChroniclesUtilBackend/Repositories/CpRepository.cs b/NineChroniclesUtilBackend/Repositories/CpRepository.cs index 9c21437a..986ad9af 100644 --- a/NineChroniclesUtilBackend/Repositories/CpRepository.cs +++ b/NineChroniclesUtilBackend/Repositories/CpRepository.cs @@ -33,10 +33,10 @@ public CpRepository(IStateService stateService) var avatarAddress = new Address(avatar.AvatarAddress); var characterRow = await GetCharacterRow(characterId); - var costumeStatSheet = await _stateGetter.GetSheet(); - var collectionSheets = await _stateGetter.GetSheet(); + var costumeStatSheet = await _stateGetter.GetSheetAsync(); + var collectionSheets = await _stateGetter.GetSheetAsync(); - var inventoryState = await _stateGetter.GetInventoryState(avatarAddress); + var inventoryState = await _stateGetter.GetInventoryStateAsync(avatarAddress); List equipments = inventoryState .Equipments @@ -45,7 +45,7 @@ public CpRepository(IStateService stateService) .Costumes .Where(x => x.Equipped).ToList(); List 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> { [avatarAddress] = new(), @@ -83,7 +83,7 @@ public CpRepository(IStateService stateService) int level ) { - var sheets = await _stateGetter.GetSheet(); + var sheets = await _stateGetter.GetSheetAsync(); if (!sheets.TryGetValue(id, out var optionRow)) { @@ -100,7 +100,7 @@ int level private async Task GetCharacterRow(int characterId) { - var sheets = await _stateGetter.GetSheet(); + var sheets = await _stateGetter.GetSheetAsync(); if (!sheets.TryGetValue(characterId, out var row)) { From 8ac4a451a91e785310892c9cd707d2c33b949086 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Tue, 7 May 2024 16:32:16 +0900 Subject: [PATCH 3/6] handle 404 of ranking/{avatarAddress}/rank --- NineChroniclesUtilBackend/Controllers/ArenaController.cs | 9 ++++++++- .../Repositories/ArenaRankingRespository.cs | 8 ++++---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/NineChroniclesUtilBackend/Controllers/ArenaController.cs b/NineChroniclesUtilBackend/Controllers/ArenaController.cs index 7b015003..59607aed 100644 --- a/NineChroniclesUtilBackend/Controllers/ArenaController.cs +++ b/NineChroniclesUtilBackend/Controllers/ArenaController.cs @@ -16,7 +16,14 @@ public class ArenaController(ArenaRankingRepository arenaRankingRepository) : Co [HttpGet("ranking/{avatarAddress}/rank")] public async Task 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")] diff --git a/NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs b/NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs index 41019735..e6e64c9c 100644 --- a/NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs +++ b/NineChroniclesUtilBackend/Repositories/ArenaRankingRespository.cs @@ -31,10 +31,10 @@ public async Task GetRankByAvatarAddress(string avatarAddress) ), new("$match", new BsonDocument("docs.AvatarAddress", avatarAddress)), }; - - var aggregation = await ArenaCollection.Aggregate(pipelines).ToListAsync(); - - return aggregation.First().Rank; + var aggregation = await _arenaCollection.Aggregate(pipelines).ToListAsync(); + return aggregation.Count == 0 + ? 0 + : (long)aggregation.First().Rank; } public async Task> GetRanking(long limit, long offset) From 385003a52378c5af099d8664de43df8b1691475f Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Tue, 7 May 2024 16:32:29 +0900 Subject: [PATCH 4/6] delete useless using --- NineChroniclesUtilBackend/Models/Agent/Avatar.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/NineChroniclesUtilBackend/Models/Agent/Avatar.cs b/NineChroniclesUtilBackend/Models/Agent/Avatar.cs index 03ff7e62..fcdf2d18 100644 --- a/NineChroniclesUtilBackend/Models/Agent/Avatar.cs +++ b/NineChroniclesUtilBackend/Models/Agent/Avatar.cs @@ -1,5 +1,3 @@ -using MongoDB.Bson; - namespace NineChroniclesUtilBackend.Models.Agent; public class Avatar(string avatarAddress, string avatarName, int level) From 3db137cfd3bd7f149a7bcdbf67587a4256989871 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Tue, 7 May 2024 16:34:02 +0900 Subject: [PATCH 5/6] ignore .DS_Store --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index e48f02b6..599f728d 100644 --- a/.gitignore +++ b/.gitignore @@ -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. From a5afe5e5fba0326ab015c651c43dfa9084f714a4 Mon Sep 17 00:00:00 2001 From: Hyun Seungmin Date: Tue, 7 May 2024 16:43:53 +0900 Subject: [PATCH 6/6] handle 404 of avatars/{avatarAddress}/inventory --- .../Controllers/AvatarController.cs | 13 +++++++++++-- .../Repositories/AvatarRepository.cs | 7 ++++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/NineChroniclesUtilBackend/Controllers/AvatarController.cs b/NineChroniclesUtilBackend/Controllers/AvatarController.cs index 2c44eabb..de02ea07 100644 --- a/NineChroniclesUtilBackend/Controllers/AvatarController.cs +++ b/NineChroniclesUtilBackend/Controllers/AvatarController.cs @@ -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; + } } diff --git a/NineChroniclesUtilBackend/Repositories/AvatarRepository.cs b/NineChroniclesUtilBackend/Repositories/AvatarRepository.cs index 48224c33..9242e6b3 100644 --- a/NineChroniclesUtilBackend/Repositories/AvatarRepository.cs +++ b/NineChroniclesUtilBackend/Repositories/AvatarRepository.cs @@ -10,11 +10,16 @@ public class AvatarRepository(MongoDBCollectionService mongoDBCollectionService) private readonly IMongoCollection _avatarsCollection = mongoDBCollectionService.GetCollection("avatars"); - public Inventory GetInventory(string avatarAddress) + public Inventory? GetInventory(string avatarAddress) { var filter = Builders.Filter.Eq(f => f["Avatar"]["address"], avatarAddress); var projection = Builders.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"]); } }