2024-06-05 17:42:45 +02:00
|
|
|
|
using System.Collections.Immutable;
|
|
|
|
|
using Microsoft.JSInterop;
|
2024-03-08 21:11:54 +01:00
|
|
|
|
|
|
|
|
|
namespace TaikoWebUI.Pages;
|
2022-09-11 18:33:58 +02:00
|
|
|
|
|
|
|
|
|
public partial class DaniDojo
|
|
|
|
|
{
|
|
|
|
|
[Parameter]
|
|
|
|
|
public int Baid { get; set; }
|
2024-05-27 00:06:51 +02:00
|
|
|
|
|
|
|
|
|
private string? SongNameLanguage { get; set; }
|
2024-03-08 21:11:54 +01:00
|
|
|
|
|
2022-09-11 18:33:58 +02:00
|
|
|
|
private DanBestDataResponse? response;
|
2024-03-09 07:07:34 +01:00
|
|
|
|
private UserSetting? userSetting;
|
2022-09-11 18:33:58 +02:00
|
|
|
|
|
2024-05-27 00:06:51 +02:00
|
|
|
|
private static Dictionary<uint, DanBestData> _bestDataMap = new();
|
2024-05-25 19:12:30 +02:00
|
|
|
|
private Dictionary<uint, MusicDetail> musicDetailDictionary = new();
|
2024-06-05 17:42:45 +02:00
|
|
|
|
private ImmutableDictionary<uint, DanData> danMap = ImmutableDictionary<uint, DanData>.Empty;
|
2022-09-11 18:33:58 +02:00
|
|
|
|
|
|
|
|
|
protected override async Task OnInitializedAsync()
|
|
|
|
|
{
|
|
|
|
|
await base.OnInitializedAsync();
|
2024-08-13 17:07:39 +02:00
|
|
|
|
|
2024-05-25 19:12:30 +02:00
|
|
|
|
if (AuthService.LoginRequired && !AuthService.IsLoggedIn)
|
|
|
|
|
{
|
|
|
|
|
await AuthService.LoginWithAuthToken();
|
|
|
|
|
}
|
2024-03-08 21:11:54 +01:00
|
|
|
|
|
2022-09-11 18:33:58 +02:00
|
|
|
|
response = await Client.GetFromJsonAsync<DanBestDataResponse>($"api/DanBestData/{Baid}");
|
|
|
|
|
response.ThrowIfNull();
|
2022-09-12 16:17:15 +02:00
|
|
|
|
response.DanBestDataList.ForEach(data => data.DanBestStageDataList
|
|
|
|
|
.Sort((stageData, otherStageData) => stageData.SongNumber.CompareTo(otherStageData.SongNumber)));
|
2024-05-27 00:06:51 +02:00
|
|
|
|
_bestDataMap = response.DanBestDataList.ToDictionary(data => data.DanId);
|
2022-09-11 18:33:58 +02:00
|
|
|
|
|
2024-06-05 17:42:45 +02:00
|
|
|
|
danMap = GameDataService.GetDanMap();
|
|
|
|
|
|
2024-05-27 00:06:51 +02:00
|
|
|
|
SongNameLanguage = await LocalStorage.GetItemAsync<string>("songNameLanguage");
|
2024-03-08 21:11:54 +01:00
|
|
|
|
|
2024-03-09 07:07:34 +01:00
|
|
|
|
userSetting = await Client.GetFromJsonAsync<UserSetting>($"api/UserSettings/{Baid}");
|
2024-08-13 17:07:39 +02:00
|
|
|
|
|
2024-05-25 19:12:30 +02:00
|
|
|
|
musicDetailDictionary = await GameDataService.GetMusicDetailDictionary();
|
2024-03-09 07:07:34 +01:00
|
|
|
|
|
2024-08-13 17:07:39 +02:00
|
|
|
|
// 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();
|
2022-09-11 18:33:58 +02:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 17:13:47 +02:00
|
|
|
|
private string GetDanClearStateString(DanClearState danClearState)
|
2022-09-12 23:15:27 +02:00
|
|
|
|
{
|
|
|
|
|
return danClearState switch
|
|
|
|
|
{
|
2024-06-05 15:29:46 +02:00
|
|
|
|
DanClearState.NotClear => Localizer["Not Passed"],
|
2024-05-01 17:13:47 +02:00
|
|
|
|
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"],
|
2022-09-12 23:15:27 +02:00
|
|
|
|
_ => ""
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 17:13:47 +02:00
|
|
|
|
private string GetDanRequirementString(DanConditionType danConditionType)
|
2022-09-12 17:49:28 +02:00
|
|
|
|
{
|
|
|
|
|
return danConditionType switch
|
|
|
|
|
{
|
2024-05-01 17:13:47 +02:00
|
|
|
|
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"],
|
2022-09-12 17:49:28 +02:00
|
|
|
|
_ => ""
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 17:13:47 +02:00
|
|
|
|
private string GetDanRequirementTitle(DanData.OdaiBorder data)
|
2022-09-11 18:33:58 +02:00
|
|
|
|
{
|
|
|
|
|
var danConditionType = (DanConditionType)data.OdaiType;
|
2022-09-12 17:49:28 +02:00
|
|
|
|
|
2022-09-13 02:25:27 +02:00
|
|
|
|
return GetDanRequirementString(danConditionType);
|
2022-09-12 16:17:15 +02:00
|
|
|
|
}
|
2022-10-15 23:45:01 +02:00
|
|
|
|
|
2022-09-13 02:25:27 +02:00
|
|
|
|
private static long GetAllBestFromData(DanConditionType type, DanBestData data)
|
2022-09-12 16:17:15 +02:00
|
|
|
|
{
|
|
|
|
|
return type switch
|
|
|
|
|
{
|
|
|
|
|
DanConditionType.SoulGauge => throw new ArgumentException("Soul gauge should not be here"),
|
2022-09-13 02:25:27 +02:00
|
|
|
|
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),
|
2022-09-12 16:17:15 +02:00
|
|
|
|
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
2022-09-13 02:50:33 +02:00
|
|
|
|
private static uint GetSongBestFromData(DanConditionType type, DanBestData data, int songNumber)
|
2022-09-12 16:17:15 +02:00
|
|
|
|
{
|
|
|
|
|
songNumber.Throw().IfOutOfRange(0, 2);
|
2024-08-13 17:07:39 +02:00
|
|
|
|
|
2022-09-12 16:17:15 +02:00
|
|
|
|
return type switch
|
|
|
|
|
{
|
|
|
|
|
DanConditionType.SoulGauge => throw new ArgumentException("Soul gauge should not be here"),
|
2022-09-13 02:50:33 +02:00
|
|
|
|
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,
|
2022-09-12 16:17:15 +02:00
|
|
|
|
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
2022-09-11 18:33:58 +02:00
|
|
|
|
};
|
|
|
|
|
}
|
2022-09-11 23:32:24 +02:00
|
|
|
|
|
2022-09-13 03:12:40 +02:00
|
|
|
|
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
|
|
|
|
|
};
|
|
|
|
|
}
|
2022-09-13 14:43:08 +02:00
|
|
|
|
|
|
|
|
|
return songNumber switch
|
2022-09-13 03:12:40 +02:00
|
|
|
|
{
|
2022-09-13 14:43:08 +02:00
|
|
|
|
0 => data.GoldBorder1,
|
|
|
|
|
1 => data.GoldBorder2,
|
|
|
|
|
2 => data.GoldBorder3,
|
|
|
|
|
_ => 0
|
|
|
|
|
};
|
2022-09-13 03:12:40 +02:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-01 17:13:47 +02:00
|
|
|
|
private string GetDanTitle(string title)
|
2022-09-11 23:32:24 +02:00
|
|
|
|
{
|
|
|
|
|
return title switch
|
|
|
|
|
{
|
2024-05-01 17:13:47 +02:00
|
|
|
|
"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"],
|
2022-09-11 23:32:24 +02:00
|
|
|
|
_ => ""
|
|
|
|
|
};
|
|
|
|
|
}
|
2022-09-12 04:15:03 +02:00
|
|
|
|
|
|
|
|
|
private string GetDanResultIcon(uint danId)
|
|
|
|
|
{
|
2022-09-13 14:43:08 +02:00
|
|
|
|
string icon;
|
2024-10-25 10:06:14 +02:00
|
|
|
|
const string notClearIcon = "<image href='/images/dani_NotClear.webp' width='24' height='24' style='filter: contrast(0.65)'/>";
|
2022-09-12 04:15:03 +02:00
|
|
|
|
|
2024-05-27 00:06:51 +02:00
|
|
|
|
if (!_bestDataMap.ContainsKey(danId))
|
2022-09-12 04:15:03 +02:00
|
|
|
|
{
|
2022-10-15 23:45:01 +02:00
|
|
|
|
return notClearIcon;
|
2022-09-12 16:17:15 +02:00
|
|
|
|
}
|
2022-10-15 23:45:01 +02:00
|
|
|
|
|
2024-05-27 00:06:51 +02:00
|
|
|
|
var state = _bestDataMap[danId].ClearState;
|
2022-10-15 23:45:01 +02:00
|
|
|
|
|
2024-10-25 10:06:14 +02:00
|
|
|
|
icon = state is DanClearState.NotClear ? notClearIcon : $"<image href='/images/dani_{state}.webp' width='24' height='24' />";
|
2022-09-12 04:15:03 +02:00
|
|
|
|
|
|
|
|
|
return icon;
|
|
|
|
|
}
|
2022-09-12 16:17:15 +02:00
|
|
|
|
|
2022-09-12 23:15:27 +02:00
|
|
|
|
private DanClearState GetDanResultState(uint danId)
|
|
|
|
|
{
|
2024-05-27 00:06:51 +02:00
|
|
|
|
return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].ClearState : DanClearState.NotClear;
|
2022-09-12 23:15:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
2022-09-12 17:49:28 +02:00
|
|
|
|
private static uint GetSoulGauge(DanData data, bool isGold)
|
2022-09-12 16:17:15 +02:00
|
|
|
|
{
|
|
|
|
|
var borders = data.OdaiBorderList;
|
|
|
|
|
var soulBorder =
|
|
|
|
|
borders.FirstOrDefault(border => (DanConditionType)border.BorderType == DanConditionType.SoulGauge,
|
|
|
|
|
new DanData.OdaiBorder());
|
|
|
|
|
|
2022-09-13 14:43:08 +02:00
|
|
|
|
return isGold ? soulBorder.GoldBorderTotal : soulBorder.RedBorderTotal;
|
2022-09-12 16:17:15 +02:00
|
|
|
|
}
|
2022-10-03 01:27:06 +02:00
|
|
|
|
|
|
|
|
|
private static string GetDanConditionOperator(DanConditionType type)
|
|
|
|
|
{
|
|
|
|
|
var conditionOperator = ">";
|
|
|
|
|
|
|
|
|
|
if (type is DanConditionType.BadCount or DanConditionType.OkCount)
|
|
|
|
|
{
|
|
|
|
|
conditionOperator = "<";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return conditionOperator;
|
|
|
|
|
}
|
2022-10-15 23:45:01 +02:00
|
|
|
|
|
|
|
|
|
private static long GetTotalScore(uint danId)
|
|
|
|
|
{
|
2024-05-27 00:06:51 +02:00
|
|
|
|
return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.HighScore) : 0;
|
2022-10-15 23:45:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static long GetTotalGoodHits(uint danId)
|
|
|
|
|
{
|
2024-05-27 00:06:51 +02:00
|
|
|
|
return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.GoodCount) : 0;
|
2022-10-15 23:45:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static long GetTotalOkHits(uint danId)
|
|
|
|
|
{
|
2024-05-27 00:06:51 +02:00
|
|
|
|
return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.OkCount) : 0;
|
2022-10-15 23:45:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static long GetTotalBadHits(uint danId)
|
|
|
|
|
{
|
2024-05-27 00:06:51 +02:00
|
|
|
|
return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.BadCount) : 0;
|
2022-10-15 23:45:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static long GetTotalDrumrollHits(uint danId)
|
|
|
|
|
{
|
2024-05-27 00:06:51 +02:00
|
|
|
|
return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.DrumrollCount) : 0;
|
2022-10-15 23:45:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static long GetTotalMaxCombo(uint danId)
|
|
|
|
|
{
|
2024-05-27 00:06:51 +02:00
|
|
|
|
return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.ComboCount) : 0;
|
2022-10-15 23:45:01 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static long GetTotalHits(uint danId)
|
|
|
|
|
{
|
2024-05-27 00:06:51 +02:00
|
|
|
|
return _bestDataMap.ContainsKey(danId) ? _bestDataMap[danId].DanBestStageDataList.Sum(stageData => stageData.TotalHitCount) : 0;
|
2022-10-15 23:45:01 +02:00
|
|
|
|
}
|
2022-09-11 18:33:58 +02:00
|
|
|
|
}
|