using System.Collections.Immutable; namespace TaikoWebUI.Services; public class GameDataService : IGameDataService { private readonly HttpClient client; private ImmutableDictionary danMap = ImmutableDictionary.Empty; private Dictionary? musicDetailDictionary = new(); private List? costumeList; private Dictionary? titleDictionary = new(); private bool musicDetailInitialized; private bool costumesInitialized; private bool titlesInitialized; private Dictionary>? lockedCostumeDataDictionary = new(); private Dictionary>? lockedTitleDataDictionary = new(); public GameDataService(HttpClient client) { this.client = client; } public async Task InitializeAsync(string dataBaseUrl) { dataBaseUrl = dataBaseUrl.TrimEnd('/'); var danData = await client.GetFromJsonAsync>($"{dataBaseUrl}/data/dan_data.json"); danData.ThrowIfNull(); danMap = danData.ToImmutableDictionary(data => data.DanId); } public async Task> GetMusicDetailDictionary() { if (!musicDetailInitialized) { await InitializeMusicDetailAsync(); } return musicDetailDictionary ?? new Dictionary(); } public async Task> GetCostumeList() { if (!costumesInitialized) { await InitializeCostumesAsync(); } return costumeList ?? new List(); } public async Task> GetTitleDictionary() { if (!titlesInitialized) { await InitializeTitlesAsync(); } return titleDictionary ?? new Dictionary(); } public async Task>> GetLockedCostumeDataDictionary() { if (!costumesInitialized) { await InitializeCostumesAsync(); } return lockedCostumeDataDictionary ?? new Dictionary>(); } public async Task>> GetLockedTitleDataDictionary() { if (!titlesInitialized) { await InitializeTitlesAsync(); } return lockedTitleDataDictionary ?? new Dictionary>(); } public string GetMusicNameBySongId(Dictionary musicDetails, uint songId, string? language = "ja") { return musicDetails.TryGetValue(songId, out var musicDetail) ? language switch { "ja" => musicDetail.SongName, "en-US" => musicDetail.SongNameEN, "fr-FR" => musicDetail.SongNameEN, "zh-Hans" => musicDetail.SongNameCN, "zh-Hant" => musicDetail.SongNameCN, "ko" => musicDetail.SongNameKO, _ => musicDetail.SongName } : string.Empty; } public string GetMusicArtistBySongId(Dictionary musicDetails, uint songId, string? language = "ja") { return musicDetails.TryGetValue(songId, out var musicDetail) ? language switch { "jp" => musicDetail.ArtistName, "en-US" => musicDetail.ArtistNameEN, "fr-FR" => musicDetail.ArtistNameEN, "zh-Hans" => musicDetail.ArtistNameCN, "zh-Hant" => musicDetail.ArtistNameCN, "ko" => musicDetail.ArtistNameKO, _ => musicDetail.ArtistName } : string.Empty; } public SongGenre GetMusicGenreBySongId(Dictionary musicDetails, uint songId) { return musicDetails.TryGetValue(songId, out var musicDetail) ? musicDetail.Genre : SongGenre.Variety; } public int GetMusicIndexBySongId(Dictionary musicDetails, uint songId) { return musicDetails.TryGetValue(songId, out var musicDetail) ? musicDetail.Index : int.MaxValue; } public ImmutableDictionary GetDanMap() { return danMap; } public int GetMusicStarLevel(Dictionary musicDetails, uint songId, Difficulty difficulty) { var success = musicDetails.TryGetValue(songId, out var musicDetail); return difficulty switch { Difficulty.None => throw new ArgumentException("Difficulty cannot be none"), Difficulty.Easy => success ? musicDetail!.StarEasy : 0, Difficulty.Normal => success ? musicDetail!.StarNormal : 0, Difficulty.Hard => success ? musicDetail!.StarHard : 0, Difficulty.Oni => success ? musicDetail!.StarOni : 0, Difficulty.UraOni => success ? musicDetail!.StarUra : 0, _ => throw new ArgumentOutOfRangeException(nameof(difficulty), difficulty, null) }; } public string GetHeadTitle(IEnumerable costumes, uint index, string? language = "ja") { return language switch { "jp" => costumes.FirstOrDefault(costume => costume.CostumeType == "head" && costume.CostumeId == index)?.CostumeName ?? string.Empty, "en-US" => costumes.FirstOrDefault(costume => costume.CostumeType == "head" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "fr-FR" => costumes.FirstOrDefault(costume => costume.CostumeType == "head" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "zh-Hans" => costumes.FirstOrDefault(costume => costume.CostumeType == "head" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "zh-Hant" => costumes.FirstOrDefault(costume => costume.CostumeType == "head" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "ko" => costumes.FirstOrDefault(costume => costume.CostumeType == "head" && costume.CostumeId == index)?.CostumeNameKO ?? string.Empty, _ => costumes.FirstOrDefault(costume => costume.CostumeType == "head" && costume.CostumeId == index)?.CostumeName ?? string.Empty }; } public string GetKigurumiTitle(IEnumerable costumes, uint index, string? language = "ja") { return language switch { "jp" => costumes.FirstOrDefault(costume => costume.CostumeType == "kigurumi" && costume.CostumeId == index)?.CostumeName ?? string.Empty, "en-US" => costumes.FirstOrDefault(costume => costume.CostumeType == "kigurumi" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "fr-FR" => costumes.FirstOrDefault(costume => costume.CostumeType == "kigurumi" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "zh-Hans" => costumes.FirstOrDefault(costume => costume.CostumeType == "kigurumi" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "zh-Hant" => costumes.FirstOrDefault(costume => costume.CostumeType == "kigurumi" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "ko" => costumes.FirstOrDefault(costume => costume.CostumeType == "kigurumi" && costume.CostumeId == index)?.CostumeNameKO ?? string.Empty, _ => costumes.FirstOrDefault(costume => costume.CostumeType == "kigurumi" && costume.CostumeId == index)?.CostumeName ?? string.Empty }; } public string GetBodyTitle(IEnumerable costumes, uint index, string? language = "ja") { return language switch { "jp" => costumes.FirstOrDefault(costume => costume.CostumeType == "body" && costume.CostumeId == index)?.CostumeName ?? string.Empty, "en-US" => costumes.FirstOrDefault(costume => costume.CostumeType == "body" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "fr-FR" => costumes.FirstOrDefault(costume => costume.CostumeType == "body" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "zh-Hans" => costumes.FirstOrDefault(costume => costume.CostumeType == "body" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "zh-Hant" => costumes.FirstOrDefault(costume => costume.CostumeType == "body" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "ko" => costumes.FirstOrDefault(costume => costume.CostumeType == "body" && costume.CostumeId == index)?.CostumeNameKO ?? string.Empty, _ => costumes.FirstOrDefault(costume => costume.CostumeType == "body" && costume.CostumeId == index)?.CostumeName ?? string.Empty }; } public string GetFaceTitle(IEnumerable costumes, uint index, string? language = "ja") { return language switch { "jp" => costumes.FirstOrDefault(costume => costume.CostumeType == "face" && costume.CostumeId == index)?.CostumeName ?? string.Empty, "en-US" => costumes.FirstOrDefault(costume => costume.CostumeType == "face" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "fr-FR" => costumes.FirstOrDefault(costume => costume.CostumeType == "face" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "zh-Hans" => costumes.FirstOrDefault(costume => costume.CostumeType == "face" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "zh-Hant" => costumes.FirstOrDefault(costume => costume.CostumeType == "face" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "ko" => costumes.FirstOrDefault(costume => costume.CostumeType == "face" && costume.CostumeId == index)?.CostumeNameKO ?? string.Empty, _ => costumes.FirstOrDefault(costume => costume.CostumeType == "face" && costume.CostumeId == index)?.CostumeName ?? string.Empty }; } public string GetPuchiTitle(IEnumerable costumes, uint index, string? language = "ja") { return language switch { "jp" => costumes.FirstOrDefault(costume => costume.CostumeType == "puchi" && costume.CostumeId == index)?.CostumeName ?? string.Empty, "en-US" => costumes.FirstOrDefault(costume => costume.CostumeType == "puchi" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "fr-FR" => costumes.FirstOrDefault(costume => costume.CostumeType == "puchi" && costume.CostumeId == index)?.CostumeNameEN ?? string.Empty, "zh-Hans" => costumes.FirstOrDefault(costume => costume.CostumeType == "puchi" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "zh-Hant" => costumes.FirstOrDefault(costume => costume.CostumeType == "puchi" && costume.CostumeId == index)?.CostumeNameCN ?? string.Empty, "ko" => costumes.FirstOrDefault(costume => costume.CostumeType == "puchi" && costume.CostumeId == index)?.CostumeNameKO ?? string.Empty, _ => costumes.FirstOrDefault(costume => costume.CostumeType == "puchi" && costume.CostumeId == index)?.CostumeName ?? string.Empty }; } private async Task InitializeMusicDetailAsync() { musicDetailDictionary = await client.GetFromJsonAsync>("api/GameData/MusicDetails"); musicDetailInitialized = true; } private async Task InitializeCostumesAsync() { costumeList = await client.GetFromJsonAsync>("api/GameData/Costumes"); lockedCostumeDataDictionary = await client.GetFromJsonAsync>>("api/GameData/LockedCostumes"); costumesInitialized = true; } private async Task InitializeTitlesAsync() { titleDictionary = await client.GetFromJsonAsync>("api/GameData/Titles"); lockedTitleDataDictionary = await client.GetFromJsonAsync>>("api/GameData/LockedTitles"); titlesInitialized = true; } }