From 91d76bfeb52dd6ab91604f778440bbe55fb0e729 Mon Sep 17 00:00:00 2001 From: asesidaa <1061472754@qq.com> Date: Fri, 9 Sep 2022 20:31:45 +0800 Subject: [PATCH] Add play result sample page and update related parts --- .../Models/Requests/SetFavoriteRequest.cs | 8 ++ SharedProject/SharedProject.csproj | 4 - TaikoLocalServer.sln.DotSettings | 2 + .../Api/FavoriteSongsController.cs | 9 +- .../Controllers/Game/MyDonEntryController.cs | 2 +- TaikoLocalServer/Services/UserDatumService.cs | 9 +- TaikoWebUI/.gitignore | 2 + TaikoWebUI/Pages/Card.razor | 4 +- TaikoWebUI/Pages/PlayResults.razor | 82 +++++++++++++++++++ TaikoWebUI/Program.cs | 11 ++- TaikoWebUI/Services/GameDataService.cs | 52 ++++++++++++ TaikoWebUI/Services/IGameDataService.cs | 10 +++ TaikoWebUI/Shared/Models/MusicInfo.cs | 9 ++ TaikoWebUI/Shared/Models/MusicInfoEntry.cs | 15 ++++ TaikoWebUI/Shared/Models/WordList.cs | 9 ++ TaikoWebUI/Shared/Models/WordListEntry.cs | 21 +++++ TaikoWebUI/TaikoWebUI.csproj | 9 ++ TaikoWebUI/wwwroot/appsettings.json | 3 +- 18 files changed, 245 insertions(+), 16 deletions(-) create mode 100644 SharedProject/Models/Requests/SetFavoriteRequest.cs create mode 100644 TaikoLocalServer.sln.DotSettings create mode 100644 TaikoWebUI/.gitignore create mode 100644 TaikoWebUI/Pages/PlayResults.razor create mode 100644 TaikoWebUI/Services/GameDataService.cs create mode 100644 TaikoWebUI/Services/IGameDataService.cs create mode 100644 TaikoWebUI/Shared/Models/MusicInfo.cs create mode 100644 TaikoWebUI/Shared/Models/MusicInfoEntry.cs create mode 100644 TaikoWebUI/Shared/Models/WordList.cs create mode 100644 TaikoWebUI/Shared/Models/WordListEntry.cs diff --git a/SharedProject/Models/Requests/SetFavoriteRequest.cs b/SharedProject/Models/Requests/SetFavoriteRequest.cs new file mode 100644 index 0000000..a9d6441 --- /dev/null +++ b/SharedProject/Models/Requests/SetFavoriteRequest.cs @@ -0,0 +1,8 @@ +namespace SharedProject.Models.Requests; + +public class SetFavoriteRequest +{ + public uint Baid { get; set; } + public uint SongId { get; set; } + public bool IsFavorite { get; set; } +} \ No newline at end of file diff --git a/SharedProject/SharedProject.csproj b/SharedProject/SharedProject.csproj index e3c7c83..f6af8be 100644 --- a/SharedProject/SharedProject.csproj +++ b/SharedProject/SharedProject.csproj @@ -6,10 +6,6 @@ enable - - - - diff --git a/TaikoLocalServer.sln.DotSettings b/TaikoLocalServer.sln.DotSettings new file mode 100644 index 0000000..4153d9b --- /dev/null +++ b/TaikoLocalServer.sln.DotSettings @@ -0,0 +1,2 @@ + + True \ No newline at end of file diff --git a/TaikoLocalServer/Controllers/Api/FavoriteSongsController.cs b/TaikoLocalServer/Controllers/Api/FavoriteSongsController.cs index 7dbda2c..5ecded6 100644 --- a/TaikoLocalServer/Controllers/Api/FavoriteSongsController.cs +++ b/TaikoLocalServer/Controllers/Api/FavoriteSongsController.cs @@ -1,4 +1,5 @@ -using TaikoLocalServer.Services.Interfaces; +using SharedProject.Models.Requests; +using TaikoLocalServer.Services.Interfaces; namespace TaikoLocalServer.Controllers.Api; @@ -14,16 +15,16 @@ public class FavoriteSongsController : BaseController } [HttpPost] - public async Task UpdateFavoriteSong(uint baid, uint songId, bool isFavorite) + public async Task UpdateFavoriteSong(SetFavoriteRequest request) { - var user = await userDatumService.GetFirstUserDatumOrNull(baid); + var user = await userDatumService.GetFirstUserDatumOrNull(request.Baid); if (user is null) { return NotFound(); } - await userDatumService.UpdateFavoriteSong(baid, songId, isFavorite); + await userDatumService.UpdateFavoriteSong(request.Baid, request.SongId, request.IsFavorite); return NoContent(); } } \ No newline at end of file diff --git a/TaikoLocalServer/Controllers/Game/MyDonEntryController.cs b/TaikoLocalServer/Controllers/Game/MyDonEntryController.cs index b11f3a7..e4ac874 100644 --- a/TaikoLocalServer/Controllers/Game/MyDonEntryController.cs +++ b/TaikoLocalServer/Controllers/Game/MyDonEntryController.cs @@ -40,7 +40,7 @@ public class MyDonEntryController : BaseController ColorFace = 0, ColorBody = 1, ColorLimb = 3, - FavoriteSongsArray = "{}" + FavoriteSongsArray = "[]" }; await userDatumService.InsertUserDatum(newUser); diff --git a/TaikoLocalServer/Services/UserDatumService.cs b/TaikoLocalServer/Services/UserDatumService.cs index 39225ed..8b3d5ca 100644 --- a/TaikoLocalServer/Services/UserDatumService.cs +++ b/TaikoLocalServer/Services/UserDatumService.cs @@ -102,9 +102,14 @@ public class UserDatumService : IUserDatumService { favoriteSet.Remove(songId); } - - await JsonSerializer.SerializeAsync(stringStream, favoriteSet); + using var newFavoriteSongStream = new MemoryStream(); + await JsonSerializer.SerializeAsync(newFavoriteSongStream, favoriteSet); + newFavoriteSongStream.Position = 0; + using var reader = new StreamReader(newFavoriteSongStream); + + userDatum.FavoriteSongsArray = await reader.ReadToEndAsync(); + logger.LogInformation("Favorite songs are: {Favorite}", userDatum.FavoriteSongsArray); context.Update(userDatum); await context.SaveChangesAsync(); } diff --git a/TaikoWebUI/.gitignore b/TaikoWebUI/.gitignore new file mode 100644 index 0000000..5a7f5b5 --- /dev/null +++ b/TaikoWebUI/.gitignore @@ -0,0 +1,2 @@ +wwwroot/data/musicinfo +wwwroot/data/wordlist \ No newline at end of file diff --git a/TaikoWebUI/Pages/Card.razor b/TaikoWebUI/Pages/Card.razor index 09d1755..e04e583 100644 --- a/TaikoWebUI/Pages/Card.razor +++ b/TaikoWebUI/Pages/Card.razor @@ -1,4 +1,4 @@ -@page "/Card/{baid}" +@page "/Card/{baid:int}" @using SharedProject.Enums @using SharedProject.Models @inject HttpClient Client @@ -121,7 +121,7 @@ @code { [Parameter] - public string? Baid { get; set; } + public int Baid { get; set; } private UserSetting? response; diff --git a/TaikoWebUI/Pages/PlayResults.razor b/TaikoWebUI/Pages/PlayResults.razor new file mode 100644 index 0000000..8a76e13 --- /dev/null +++ b/TaikoWebUI/Pages/PlayResults.razor @@ -0,0 +1,82 @@ +@using TaikoWebUI.Services +@using SharedProject.Models.Responses +@using SharedProject.Models +@using SharedProject.Models.Requests +@inject IGameDataService GameDataService +@inject HttpClient Client + +@page "/PlayResults/{baid:int}" +

PlayResults for baid : @Baid

+ +@if (response is null) +{ + No data +} +else +{ + + + @* Notice here we have to use cell template for custom conversion *@ + @* Field is retrieved using reflection, so it is a string with name equals field name*@ + + + @GameDataService.GetMusicNameBySongId(context.Item.SongId) + + + + + @GameDataService.GetMusicArtistBySongId(context.Item.SongId) + + + + + + + + + + + + + + + + + +} + + +@code { + + [Parameter] + public int Baid { get; set; } + + private SongBestResponse? response; + + protected override async Task OnInitializedAsync() + { + await base.OnInitializedAsync(); + response = await Client.GetFromJsonAsync($"api/PlayData/{Baid}"); + } + + private async Task OnFavoriteToggled(SongBestData data) + { + var request = new SetFavoriteRequest + { + Baid = (uint)Baid, + IsFavorite = !data.IsFavorite, + SongId = data.SongId + }; + var result = await Client.PostAsJsonAsync("api/FavoriteSongs", request); + if (result.IsSuccessStatusCode) + { + data.IsFavorite = !data.IsFavorite; + } + } + +} \ No newline at end of file diff --git a/TaikoWebUI/Program.cs b/TaikoWebUI/Program.cs index 8e3eca2..bdb486b 100644 --- a/TaikoWebUI/Program.cs +++ b/TaikoWebUI/Program.cs @@ -2,15 +2,22 @@ using Microsoft.AspNetCore.Components.Web; using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using TaikoWebUI; using MudBlazor.Services; +using TaikoWebUI.Services; var builder = WebAssemblyHostBuilder.CreateDefault(args); builder.RootComponents.Add("#app"); builder.RootComponents.Add("head::after"); -builder.Services.AddScoped(sp => new HttpClient +builder.Services.AddSingleton(sp => new HttpClient { BaseAddress = new Uri(builder.Configuration.GetValue("BaseUrl")) }); builder.Services.AddMudServices(); +builder.Services.AddSingleton(); -await builder.Build().RunAsync(); \ No newline at end of file +var host = builder.Build(); + +var gameDataService = host.Services.GetRequiredService(); +await gameDataService.InitializeAsync(builder.Configuration.GetValue("DataBaseUrl")); + +await host.RunAsync(); \ No newline at end of file diff --git a/TaikoWebUI/Services/GameDataService.cs b/TaikoWebUI/Services/GameDataService.cs new file mode 100644 index 0000000..73cc79c --- /dev/null +++ b/TaikoWebUI/Services/GameDataService.cs @@ -0,0 +1,52 @@ +using System.Collections.Immutable; +using System.Net.Http.Json; +using TaikoWebUI.Shared.Models; +using Throw; + +namespace TaikoWebUI.Services; + +public class GameDataService : IGameDataService +{ + private readonly HttpClient client; + + private readonly Dictionary musicNameMap = new(); + + private readonly Dictionary musicArtistMap = new(); + + public GameDataService(HttpClient client) + { + this.client = client; + } + + public async Task InitializeAsync(string dataBaseUrl) + { + var musicInfo = await client.GetFromJsonAsync($"{dataBaseUrl}/data/musicinfo"); + var wordList = await client.GetFromJsonAsync($"{dataBaseUrl}/data/wordlist"); + + musicInfo.ThrowIfNull(); + wordList.ThrowIfNull(); + + var dict = wordList.WordListEntries.ToImmutableDictionary(entry => entry.Key); + foreach (var music in musicInfo.Items) + { + var songNameKey = $"song_{music.Id}"; + var songArtistKey = $"song_sub_{music.Id}"; + + var musicName = dict.GetValueOrDefault(songNameKey, new WordListEntry()); + var musicArtist = dict.GetValueOrDefault(songArtistKey, new WordListEntry()); + + musicNameMap.TryAdd(music.SongId, musicName.JapaneseText); + musicArtistMap.TryAdd(music.SongId, musicArtist.JapaneseText); + } + } + + public string GetMusicNameBySongId(uint songId) + { + return musicNameMap.GetValueOrDefault(songId, string.Empty); + } + + public string GetMusicArtistBySongId(uint songId) + { + return musicArtistMap.GetValueOrDefault(songId, string.Empty); + } +} \ No newline at end of file diff --git a/TaikoWebUI/Services/IGameDataService.cs b/TaikoWebUI/Services/IGameDataService.cs new file mode 100644 index 0000000..d5a1410 --- /dev/null +++ b/TaikoWebUI/Services/IGameDataService.cs @@ -0,0 +1,10 @@ +namespace TaikoWebUI.Services; + +public interface IGameDataService +{ + public Task InitializeAsync(string dataBaseUrl); + + public string GetMusicNameBySongId(uint songId); + + public string GetMusicArtistBySongId(uint songId); +} \ No newline at end of file diff --git a/TaikoWebUI/Shared/Models/MusicInfo.cs b/TaikoWebUI/Shared/Models/MusicInfo.cs new file mode 100644 index 0000000..3cedc11 --- /dev/null +++ b/TaikoWebUI/Shared/Models/MusicInfo.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace TaikoWebUI.Shared.Models; + +public class MusicInfo +{ + [JsonPropertyName("items")] + public List Items { get; set; } = new(); +} \ No newline at end of file diff --git a/TaikoWebUI/Shared/Models/MusicInfoEntry.cs b/TaikoWebUI/Shared/Models/MusicInfoEntry.cs new file mode 100644 index 0000000..0eda2de --- /dev/null +++ b/TaikoWebUI/Shared/Models/MusicInfoEntry.cs @@ -0,0 +1,15 @@ +using System.Text.Json.Serialization; + +namespace TaikoWebUI.Shared.Models; + +public class MusicInfoEntry +{ + [JsonPropertyName("id")] + public string Id { get; set; } = string.Empty; + + [JsonPropertyName("uniqueId")] + public uint SongId { get; set; } + + [JsonPropertyName("genreNo")] + public uint Genre { get; set; } +} \ No newline at end of file diff --git a/TaikoWebUI/Shared/Models/WordList.cs b/TaikoWebUI/Shared/Models/WordList.cs new file mode 100644 index 0000000..ce837a9 --- /dev/null +++ b/TaikoWebUI/Shared/Models/WordList.cs @@ -0,0 +1,9 @@ +using System.Text.Json.Serialization; + +namespace TaikoWebUI.Shared.Models; + +public class WordList +{ + [JsonPropertyName("items")] + public List WordListEntries { get; set; } = new(); +} \ No newline at end of file diff --git a/TaikoWebUI/Shared/Models/WordListEntry.cs b/TaikoWebUI/Shared/Models/WordListEntry.cs new file mode 100644 index 0000000..3fe7324 --- /dev/null +++ b/TaikoWebUI/Shared/Models/WordListEntry.cs @@ -0,0 +1,21 @@ +using System.Text.Json.Serialization; + +namespace TaikoWebUI.Shared.Models; + +public class WordListEntry +{ + [JsonPropertyName("key")] + public string Key { get; set; } = string.Empty; + + [JsonPropertyName("japaneseText")] + public string JapaneseText { get; set; } = string.Empty; + + [JsonPropertyName("englishUsText")] + public string EnglishUsText { get; set; } = string.Empty; + + [JsonPropertyName("chineseTText")] + public string ChineseTText { get; set; } = string.Empty; + + [JsonPropertyName("koreanText")] + public string KoreanText { get; set; } = string.Empty; +} \ No newline at end of file diff --git a/TaikoWebUI/TaikoWebUI.csproj b/TaikoWebUI/TaikoWebUI.csproj index 68108c1..408f607 100644 --- a/TaikoWebUI/TaikoWebUI.csproj +++ b/TaikoWebUI/TaikoWebUI.csproj @@ -16,5 +16,14 @@ + + + PreserveNewest + + + PreserveNewest + + + \ No newline at end of file diff --git a/TaikoWebUI/wwwroot/appsettings.json b/TaikoWebUI/wwwroot/appsettings.json index e575e49..44139dc 100644 --- a/TaikoWebUI/wwwroot/appsettings.json +++ b/TaikoWebUI/wwwroot/appsettings.json @@ -1,3 +1,4 @@ { - "BaseUrl": "http://localhost:5000" + "BaseUrl": "http://localhost:5000", + "DataBaseUrl": "https://localhost:44398" } \ No newline at end of file