1
0
mirror of synced 2025-01-19 00:04:05 +01:00

Add High Scores page

This commit is contained in:
shiibe 2024-03-17 15:46:47 -04:00
parent 9144dacf8d
commit 57b0390322
8 changed files with 264 additions and 17 deletions

View File

@ -26,4 +26,17 @@ public class FavoriteSongsController : BaseController<FavoriteSongsController>
await userDatumService.UpdateFavoriteSong(request.Baid, request.SongId, request.IsFavorite);
return NoContent();
}
[HttpGet("{baid}")]
public async Task<IActionResult> GetFavoriteSongs(uint baid)
{
var user = await userDatumService.GetFirstUserDatumOrNull(baid);
if (user is null)
{
return NotFound();
}
return Ok(user.FavoriteSongsArray);
}
}

View File

@ -104,7 +104,8 @@
FullWidth="true"
AnchorOrigin="Origin.BottomCenter"
TransformOrigin="Origin.TopCenter">
<MudMenuItem Href="@($"Users/{user.Baid}/Songs")">@Localizer["high scores"]</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/HighScores")">@Localizer["High Scores"]</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/Songs")">@Localizer["Song List"]</MudMenuItem>
<MudMenuItem Href="@($"Users/{user.Baid}/DaniDojo")">@Localizer["dani dojo"]</MudMenuItem>
</MudMenu>
</MudStack>

View File

@ -0,0 +1,136 @@
@inject IGameDataService GameDataService
@inject HttpClient Client
@inject LoginService LoginService
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@using TaikoWebUI.Utilities;
@page "/Users/{baid:int}/HighScores"
<MudBreadcrumbs Items="breadcrumbs" Class="p-0 mb-2"></MudBreadcrumbs>
<MudText Typo="Typo.h4">@Localizer["High Scores"]</MudText>
<MudText Typo="Typo.caption">User ID: @Baid</MudText>
<MudGrid Class="my-8">
@if (response is null)
{
<MudItem xs="12">
<MudText Align="Align.Center">
@Localizer["No data."]
</MudText>
</MudItem>
}
else
{
@if (LoginService.LoginRequired && (!LoginService.IsLoggedIn || (LoginService.GetLoggedInUser().Baid != Baid && !LoginService.IsAdmin)))
{
if (!LoginService.IsLoggedIn)
{
NavigationManager.NavigateTo("/Login");
}
else
{
NavigationManager.NavigateTo("/");
}
}
else
{
<MudItem xs="12">
<MudTabs Elevation="0" Border="true" Rounded="true" ApplyEffectsToContainer="true" Outlined="true" Class="mb-10">
@foreach (var difficulty in Enum.GetValues<Difficulty>())
{
@if (difficulty is not Difficulty.None)
{
<MudTabPanel Text="@ScoreUtils.GetDifficultyTitle(difficulty)"
Icon="@ScoreUtils.GetDifficultyIconSvg(difficulty)">
@if (songBestDataMap.TryGetValue(difficulty, out var value))
{
<MudDataGrid Items="@value"
ColumnResizeMode="ResizeMode.None" RowsPerPage="25" Elevation="0">
<Columns>
<TemplateColumn T="SongBestData" Title=@Localizer["Song"] StickyLeft="true">
<CellTemplate>
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
<div style="width:300px">
<a href="@($"/Users/{Baid}/Songs/{context.Item.SongId}")">
<MudText Typo="Typo.body2" Style="font-weight:bold">@context.Item.MusicName</MudText>
<MudText Typo="Typo.caption">@context.Item.MusicArtist</MudText>
</a>
</div>
<div>
<MudToggleIconButton Toggled="@context.Item.IsFavorite"
ToggledChanged="@(async () => await OnFavoriteToggled(context.Item))"
Icon="@Icons.Material.Filled.FavoriteBorder" Color="@Color.Secondary"
ToggledIcon="@Icons.Material.Filled.Favorite" ToggledColor="@Color.Secondary"
Size="Size.Small"
ToggledSize="Size.Small"
Title="Add to favorites" ToggledTitle="Remove from favorites" />
</div>
</MudStack>
</CellTemplate>
</TemplateColumn>
<TemplateColumn T="SongBestData" Title=@Localizer["Level"] Sortable="false">
<CellTemplate>
<MudStack Row="true" Spacing="1" AlignItems="AlignItems.Center">
<MudIcon Icon="@Icons.Material.Filled.Star" Size="Size.Small" />
<MudText Typo="Typo.caption" Style="line-height:1;margin-top:2px;margin-right:2px;">@GameDataService.GetMusicStarLevel(@context.Item.SongId, difficulty)</MudText>
</MudStack>
</CellTemplate>
</TemplateColumn>
<TemplateColumn T="SongBestData" Title=@Localizer["Genre"]
Sortable="false" Filterable="true">
<CellTemplate>
<MudChip Style="@ScoreUtils.GetGenreStyle(context.Item.Genre)"
Size="Size.Small">
@ScoreUtils.GetGenreTitle(context.Item.Genre)
</MudChip>
</CellTemplate>
</TemplateColumn>
<PropertyColumn Property="data => data.BestScore" Title=@Localizer["Best Score"] />
<TemplateColumn T="SongBestData" Title=@Localizer["Best Crown"]>
<CellTemplate>
<img src="@($"/images/crown_{context.Item.BestCrown}.png")" alt="@(ScoreUtils.GetCrownText(context.Item.BestCrown))" title="@(ScoreUtils.GetCrownText(context.Item.BestCrown))" style="@IconStyle" />
</CellTemplate>
</TemplateColumn>
<TemplateColumn T="SongBestData" Title=@Localizer["Best Rank"] Sortable="false">
<CellTemplate>
@if (context.Item.BestScoreRank is not ScoreRank.None)
{
<img src="@($"/images/rank_{context.Item.BestScoreRank}.png")" alt="@(ScoreUtils.GetRankText(context.Item.BestScoreRank))" title="@(ScoreUtils.GetRankText(context.Item.BestScoreRank))" style="@IconStyle" />
}
</CellTemplate>
</TemplateColumn>
<PropertyColumn Property="data => data.GoodCount" Title=@Localizer["Good"] Sortable="false" />
<PropertyColumn Property="data => data.OkCount" Title=@Localizer["OK"] Sortable="false" />
<PropertyColumn Property="data => data.MissCount" Title=@Localizer["Bad"] Sortable="false" />
<PropertyColumn Property="data => data.DrumrollCount" Title=@Localizer["Drumroll"] Sortable="false" />
<PropertyColumn Property="data => data.ComboCount" Title=@Localizer["MAX Combo"] Sortable="false" />
<PropertyColumn Property="data => data.LastPlayTime" Title=@Localizer["Last Played"] Hideable="true" />
<PropertyColumn Property="data => data.PlayCount" Title=@Localizer["Total Plays"] Hideable="true" />
<PropertyColumn Property="data => data.ClearCount" Title=@Localizer["Total Clears"] Hideable="true" />
<PropertyColumn Property="data => data.FullComboCount" Title=@Localizer["Total Full Combos"] Hideable="true" />
<PropertyColumn Property="data => data.PerfectCount" Title=@Localizer["Total Donderful Combos"] Hideable="true" />
</Columns>
<PagerContent>
<MudDataGridPager T="SongBestData" />
</PagerContent>
</MudDataGrid>
}
else
{
<MudGrid>
<MudItem xs="12">
<MudText Align="Align.Center" Class="my-16">
No data for selected difficulty.
</MudText>
</MudItem>
</MudGrid>
}
</MudTabPanel>
}
}
</MudTabs>
</MudItem>
}
}
</MudGrid>

View File

@ -0,0 +1,81 @@
using static MudBlazor.Colors;
using System;
using Microsoft.JSInterop;
namespace TaikoWebUI.Pages;
public partial class HighScores
{
[Parameter]
public int Baid { get; set; }
private const string IconStyle = "width:25px; height:25px;";
private SongBestResponse? response;
private UserSetting? userSetting;
private Dictionary<Difficulty, List<SongBestData>> songBestDataMap = new();
private readonly List<BreadcrumbItem> breadcrumbs = new();
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
response = await Client.GetFromJsonAsync<SongBestResponse>($"api/PlayData/{Baid}");
response.ThrowIfNull();
userSetting = await Client.GetFromJsonAsync<UserSetting>($"api/UserSettings/{Baid}");
var language = await JSRuntime.InvokeAsync<string>("blazorCulture.get");
response.SongBestData.ForEach(data =>
{
var songId = data.SongId;
data.Genre = GameDataService.GetMusicGenreBySongId(songId);
data.MusicName = GameDataService.GetMusicNameBySongId(songId, string.IsNullOrEmpty(language) ? "ja" : language);
data.MusicArtist = GameDataService.GetMusicArtistBySongId(songId, string.IsNullOrEmpty(language) ? "ja" : language);
});
songBestDataMap = response.SongBestData.GroupBy(data => data.Difficulty)
.ToDictionary(data => data.Key,
data => data.ToList());
foreach (var songBestDataList in songBestDataMap.Values)
{
songBestDataList.Sort((data1, data2) => GameDataService.GetMusicIndexBySongId(data1.SongId)
.CompareTo(GameDataService.GetMusicIndexBySongId(data2.SongId)));
}
if (LoginService.IsLoggedIn && !LoginService.IsAdmin)
{
breadcrumbs.Add(new BreadcrumbItem("Dashboard", href: "/"));
}
else
{
breadcrumbs.Add(new BreadcrumbItem("Users", href: "/Users"));
};
breadcrumbs.Add(new BreadcrumbItem($"{userSetting?.MyDonName}", href: null, disabled: true));
breadcrumbs.Add(new BreadcrumbItem("High Scores", href: $"/Users/{Baid}/HighScores", disabled: false));
}
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;
}
}
private static bool IsAiDataPresent(SongBestData data)
{
var aiData = data.AiSectionBestData;
return aiData.Count > 0;
}
}

View File

@ -35,7 +35,7 @@
else
{
<MudItem xs="12">
<MudTable Items="musicMap" Elevation="0" Outlined="true" Filter="@FilterSongs" Striped="true">
<MudTable Items="musicMap" Elevation="0" Outlined="true" Filter="@FilterSongs">
<ToolBarContent>
<MudGrid Spacing="2">
<MudItem xs="12" md="8">
@ -54,7 +54,7 @@
var genreValue = (SongGenre)genre;
<MudSelectItem Value="@genreValue.ToString()" Label="@Localizer[$"Key_{genreValue}"]">
@ScoreUtils.GetGenreTitle(genreValue)
</MudSelectItem>
</MudSelectItem>
}
</MudSelect>
</MudItem>
@ -69,14 +69,27 @@
</HeaderContent>
<RowTemplate>
<MudTd>
<a href="@($"/Users/{Baid}/Songs/{context.SongId}")">
<MudText Typo="Typo.body2">
@GameDataService.GetMusicNameBySongId(context.SongId, CurrentLanguage)
</MudText>
<MudText Typo="Typo.caption">
@GameDataService.GetMusicArtistBySongId(context.SongId, CurrentLanguage)
</MudText>
</a>
<MudStack Row="true" Justify="Justify.SpaceBetween" AlignItems="AlignItems.Center">
<div>
<a href="@($"/Users/{Baid}/Songs/{context.SongId}")">
<MudText Typo="Typo.body2">
@GameDataService.GetMusicNameBySongId(context.SongId, CurrentLanguage)
</MudText>
<MudText Typo="Typo.caption">
@GameDataService.GetMusicArtistBySongId(context.SongId, CurrentLanguage)
</MudText>
</a>
</div>
<div>
<MudToggleIconButton
Icon="@Icons.Material.Filled.FavoriteBorder" Color="@Color.Secondary"
ToggledIcon="@Icons.Material.Filled.Favorite" ToggledColor="@Color.Secondary"
Size="Size.Small"
ToggledSize="Size.Small"
Title="Add to favorites"
ToggledTitle="Remove from favorites" />
</div>
</MudStack>
</MudTd>
</RowTemplate>
<PagerContent>

View File

@ -3,7 +3,6 @@
public class MusicDetail
{
public uint SongId { get; set; }
public int Index { get; set; }
public string SongName { get; set; } = string.Empty;
@ -17,14 +16,11 @@ public class MusicDetail
public string ArtistNameKO { get; set; } = string.Empty;
public SongGenre Genre { get; set; }
public int StarEasy { get; set; }
public int StarNormal { get; set; }
public int StarHard { get; set; }
public int StarOni { get; set; }
public int StarUra { get; set; }
public bool IsFavorite { get; set; } = false;
}

View File

@ -0,0 +1,6 @@
namespace TaikoWebUI.Shared.Models
{
public class SongListEntry
{
}
}

View File

@ -26,6 +26,7 @@
<MudNavLink Href="@($"Users/{currentUser.Baid}/Profile")" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Person">@Localizer["Profile"]</MudNavLink>
<MudNavGroup Title="Play Data" Expanded="true" Icon="@Icons.Material.Filled.EmojiEvents">
<MudNavLink Href="@($"Users/{currentUser.Baid}/Songs")" Match="NavLinkMatch.All">@Localizer["Key_01"]</MudNavLink>
<MudNavLink Href="@($"Users/{currentUser.Baid}/HighScores")" Match="NavLinkMatch.All">@Localizer["High Scores"]</MudNavLink>
<MudNavLink Href="@($"Users/{currentUser.Baid}/DaniDojo")" Match="NavLinkMatch.All">@Localizer["Key_03"]</MudNavLink>
</MudNavGroup>
<MudNavGroup Title="Settings" Expanded="_settingsOpen" Icon="@Icons.Material.Filled.Settings">