using System.Collections.Immutable; using Microsoft.JSInterop; namespace TaikoWebUI.Pages; public partial class DaniDojo { [Parameter] public int Baid { get; set; } private string? SongNameLanguage { get; set; } private DanBestDataResponse? response; private UserSetting? userSetting; private static Dictionary _bestDataMap = new(); private Dictionary musicDetailDictionary = new(); private ImmutableDictionary danMap = ImmutableDictionary.Empty; protected override async Task OnInitializedAsync() { await base.OnInitializedAsync(); if (AuthService.LoginRequired && !AuthService.IsLoggedIn) { await AuthService.LoginWithAuthToken(); } response = await Client.GetFromJsonAsync($"api/DanBestData/{Baid}"); response.ThrowIfNull(); response.DanBestDataList.ForEach(data => data.DanBestStageDataList .Sort((stageData, otherStageData) => stageData.SongNumber.CompareTo(otherStageData.SongNumber))); _bestDataMap = response.DanBestDataList.ToDictionary(data => data.DanId); danMap = GameDataService.GetDanMap(); SongNameLanguage = await LocalStorage.GetItemAsync("songNameLanguage"); userSetting = await Client.GetFromJsonAsync($"api/UserSettings/{Baid}"); musicDetailDictionary = await GameDataService.GetMusicDetailDictionary(); // Breadcrumbs BreadcrumbsStateContainer.breadcrumbs.Clear(); if (AuthService.IsLoggedIn && !AuthService.IsAdmin) BreadcrumbsStateContainer.breadcrumbs.Add(new BreadcrumbItem(Localizer["Dashboard"], href: "/")); else BreadcrumbsStateContainer.breadcrumbs.Add(new BreadcrumbItem(Localizer["Users"], href: "/Users")); BreadcrumbsStateContainer.breadcrumbs.Add(new BreadcrumbItem($"{userSetting?.MyDonName}", href: null, disabled: true)); BreadcrumbsStateContainer.breadcrumbs.Add(new BreadcrumbItem(Localizer["Dani Dojo"], href: $"/Users/{Baid}/DaniDojo", disabled: false)); BreadcrumbsStateContainer.NotifyStateChanged(); } private string GetDanClearStateString(DanClearState danClearState) { return danClearState switch { DanClearState.NotClear => Localizer["Not Passed"], DanClearState.RedNormalClear => Localizer["Red"], DanClearState.RedFullComboClear => Localizer["Red Full Combo"], DanClearState.RedPerfectClear => Localizer["Red Donderful Combo"], DanClearState.GoldNormalClear => Localizer["Gold"], DanClearState.GoldFullComboClear => Localizer["Gold Full Combo"], DanClearState.GoldPerfectClear => Localizer["Gold Donderful Combo"], _ => "" }; } private string GetDanRequirementString(DanConditionType danConditionType) { return danConditionType switch { DanConditionType.TotalHitCount => Localizer["Total Hits"], DanConditionType.GoodCount => Localizer["Good"], DanConditionType.OkCount => Localizer["OK"], DanConditionType.BadCount => Localizer["Bad"], DanConditionType.SoulGauge => Localizer["Soul Gauge"], DanConditionType.DrumrollCount => Localizer["Drumroll"], DanConditionType.Score => Localizer["Score"], DanConditionType.ComboCount => Localizer["MAX Combo"], _ => "" }; } private string GetDanRequirementTitle(DanData.OdaiBorder data) { var danConditionType = (DanConditionType)data.OdaiType; return GetDanRequirementString(danConditionType); } private static long GetAllBestFromData(DanConditionType type, DanBestData data) { return type switch { DanConditionType.SoulGauge => throw new ArgumentException("Soul gauge should not be here"), DanConditionType.GoodCount => data.DanBestStageDataList.Sum(stageData => stageData.GoodCount), DanConditionType.OkCount => data.DanBestStageDataList.Sum(stageData => stageData.OkCount), DanConditionType.BadCount => data.DanBestStageDataList.Sum(stageData => stageData.BadCount), DanConditionType.ComboCount => data.ComboCountTotal, DanConditionType.DrumrollCount => data.DanBestStageDataList.Sum(stageData => stageData.DrumrollCount), DanConditionType.Score => data.DanBestStageDataList.Sum(stageData => stageData.PlayScore), DanConditionType.TotalHitCount => data.DanBestStageDataList.Sum(stageData => stageData.TotalHitCount), _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) }; } private static uint GetSongBestFromData(DanConditionType type, DanBestData data, int songNumber) { songNumber.Throw().IfOutOfRange(0, 2); return type switch { DanConditionType.SoulGauge => throw new ArgumentException("Soul gauge should not be here"), DanConditionType.GoodCount => data.DanBestStageDataList[songNumber].GoodCount, DanConditionType.OkCount => data.DanBestStageDataList[songNumber].OkCount, DanConditionType.BadCount => data.DanBestStageDataList[songNumber].BadCount, DanConditionType.ComboCount => data.DanBestStageDataList[songNumber].ComboCount, DanConditionType.DrumrollCount => data.DanBestStageDataList[songNumber].DrumrollCount, DanConditionType.Score => data.DanBestStageDataList[songNumber].PlayScore, DanConditionType.TotalHitCount => data.DanBestStageDataList[songNumber].TotalHitCount, _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) }; } private static uint GetSongBorderCondition(DanData.OdaiBorder data, int songNumber, bool isGold) { if (!isGold) { return songNumber switch { 0 => data.RedBorder1, 1 => data.RedBorder2, 2 => data.RedBorder3, _ => 0 }; } return songNumber switch { 0 => data.GoldBorder1, 1 => data.GoldBorder2, 2 => data.GoldBorder3, _ => 0 }; } private string GetDanTitle(string title) { return title switch { "5kyuu" => Localizer["Fifth Kyuu"], "4kyuu" => Localizer["Fourth Kyuu"], "3kyuu" => Localizer["Third Kyuu"], "2kyuu" => Localizer["Second Kyuu"], "1kyuu" => Localizer["First Kyuu"], "1dan" => Localizer["First Dan"], "2dan" => Localizer["Second Dan"], "3dan" => Localizer["Third Dan"], "4dan" => Localizer["Fourth Dan"], "5dan" => Localizer["Fifth Dan"], "6dan" => Localizer["Sixth Dan"], "7dan" => Localizer["Seventh Dan"], "8dan" => Localizer["Eighth Dan"], "9dan" => Localizer["Ninth Dan"], "10dan" => Localizer["Tenth Dan"], "11dan" => Localizer["Kuroto"], "12dan" => Localizer["Meijin"], "13dan" => Localizer["Chojin"], "14dan" => Localizer["Tatsujin"], "15dan" => Localizer["Gaiden"], _ => "" }; } private string GetDanResultIcon(uint danId) { string icon; const string notClearIcon = ""; if (!_bestDataMap.ContainsKey(danId)) { return notClearIcon; } var state = _bestDataMap[danId].ClearState; icon = state is DanClearState.NotClear ? notClearIcon : $""; return icon; } private DanClearState GetDanResultState(uint danId) { return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].ClearState : DanClearState.NotClear; } private static uint GetSoulGauge(DanData data, bool isGold) { var borders = data.OdaiBorderList; var soulBorder = borders.FirstOrDefault(border => (DanConditionType)border.BorderType == DanConditionType.SoulGauge, new DanData.OdaiBorder()); return isGold ? soulBorder.GoldBorderTotal : soulBorder.RedBorderTotal; } private static string GetDanConditionOperator(DanConditionType type) { var conditionOperator = ">"; if (type is DanConditionType.BadCount or DanConditionType.OkCount) { conditionOperator = "<"; } return conditionOperator; } private static long GetTotalScore(uint danId) { return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.HighScore) : 0; } private static long GetTotalGoodHits(uint danId) { return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.GoodCount) : 0; } private static long GetTotalOkHits(uint danId) { return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.OkCount) : 0; } private static long GetTotalBadHits(uint danId) { return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.BadCount) : 0; } private static long GetTotalDrumrollHits(uint danId) { return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.DrumrollCount) : 0; } private static long GetTotalMaxCombo(uint danId) { return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.ComboCount) : 0; } private static long GetTotalHits(uint danId) { return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.TotalHitCount) : 0; } }