Finish total result and options page, add unlock all music function
This commit is contained in:
parent
4d0e351abd
commit
e5eee66ff2
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Application.Api;
|
||||
|
||||
public record SetFavoriteMusicCommand(MusicDetailDto Data) : IRequestWrapper<bool>;
|
||||
public record SetFavoriteMusicCommand(MusicFavoriteDto Data) : IRequestWrapper<bool>;
|
||||
|
||||
public class SetFavoriteMusicCommandHandler : RequestHandlerBase<SetFavoriteMusicCommand, bool>
|
||||
{
|
||||
|
38
Application/Api/UnlockAllMusicCommand.cs
Normal file
38
Application/Api/UnlockAllMusicCommand.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Application.Api;
|
||||
|
||||
public record UnlockAllMusicCommand(long CardId) : IRequestWrapper<bool>;
|
||||
|
||||
public class UnlockAllMusicCommandHandler : RequestHandlerBase<UnlockAllMusicCommand, bool>
|
||||
{
|
||||
private readonly ILogger<UnlockAllMusicCommandHandler> logger;
|
||||
|
||||
public UnlockAllMusicCommandHandler(ICardDependencyAggregate aggregate,
|
||||
ILogger<UnlockAllMusicCommandHandler> logger) : base(aggregate)
|
||||
{
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
public override async Task<ServiceResult<bool>> Handle(UnlockAllMusicCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var unlocks = await CardDbContext.CardDetails.Where(
|
||||
detail => detail.CardId == request.CardId &&
|
||||
detail.Pcol1 == 10 &&
|
||||
detail.ScoreUi6 == 1).ToListAsync(cancellationToken: cancellationToken);
|
||||
if (unlocks.Count == 0)
|
||||
{
|
||||
logger.LogWarning("Attempt to unlock for card {Card} that does not exist or is empty!", request.CardId);
|
||||
return ServiceResult.Failed<bool>(ServiceError.CustomMessage("Unlock failed"));
|
||||
}
|
||||
|
||||
foreach (var unlock in unlocks)
|
||||
{
|
||||
unlock.ScoreUi2 = 1;
|
||||
}
|
||||
CardDbContext.CardDetails.UpdateRange(unlocks);
|
||||
await CardDbContext.SaveChangesAsync(cancellationToken);
|
||||
|
||||
return new ServiceResult<bool>(true);
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@ public class ProfilesController : BaseController<ProfilesController>
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpGet("{cardId:long}")]
|
||||
[HttpGet("TotalResult/{cardId:long}")]
|
||||
public async Task<ServiceResult<TotalResultData>> GetCardTotalResultById(long cardId)
|
||||
{
|
||||
var result = await Mediator.Send(new GetTotalResultQuery(cardId));
|
||||
@ -24,9 +24,9 @@ public class ProfilesController : BaseController<ProfilesController>
|
||||
}
|
||||
|
||||
[HttpPost("Favorite")]
|
||||
public async Task<ServiceResult<bool>> SetFavoriteMusic(MusicDetailDto detail)
|
||||
public async Task<ServiceResult<bool>> SetFavoriteMusic(MusicFavoriteDto favorite)
|
||||
{
|
||||
var result = await Mediator.Send(new SetFavoriteMusicCommand(detail));
|
||||
var result = await Mediator.Send(new SetFavoriteMusicCommand(favorite));
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -36,4 +36,12 @@ public class ProfilesController : BaseController<ProfilesController>
|
||||
var result = await Mediator.Send(new SetPlayerNameCommand(card));
|
||||
return result;
|
||||
}
|
||||
|
||||
[HttpPost("UnlockAllMusic/{cardId:long}")]
|
||||
public async Task<ServiceResult<bool>> UnlockAllMusic(long cardId)
|
||||
{
|
||||
var result = await Mediator.Send(new UnlockAllMusicCommand(cardId));
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
BIN
MainServer/Database/card.db3-shm
Normal file
BIN
MainServer/Database/card.db3-shm
Normal file
Binary file not shown.
BIN
MainServer/Database/card.db3-wal
Normal file
BIN
MainServer/Database/card.db3-wal
Normal file
Binary file not shown.
@ -11,7 +11,6 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Serilog;
|
||||
using Serilog.Extensions.Logging;
|
||||
using Throw;
|
||||
using Shared.SerializerContexts;
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.WriteTo.Console()
|
||||
@ -58,7 +57,7 @@ try
|
||||
|
||||
builder.Services.AddControllers(options =>
|
||||
options.Filters.Add<ApiExceptionFilterService>())
|
||||
.AddJsonOptions(options => options.JsonSerializerOptions.AddContext<SourceGenerationContext>());
|
||||
.AddJsonOptions(options => options.JsonSerializerOptions.WriteIndented = true);
|
||||
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace Shared.Dto.Api;
|
||||
|
||||
public class MusicDetailDto
|
||||
public class MusicFavoriteDto
|
||||
{
|
||||
public long CardId { get; set; }
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Domain.Enums;
|
||||
using System.Text.Json.Serialization;
|
||||
using Domain.Enums;
|
||||
|
||||
namespace Shared.Models;
|
||||
|
||||
@ -12,9 +13,7 @@ namespace Shared.Models;
|
||||
[Serializable]
|
||||
public class ServiceError
|
||||
{
|
||||
/// <summary>
|
||||
/// CTOR
|
||||
/// </summary>
|
||||
[JsonConstructor]
|
||||
public ServiceError(string message, int code)
|
||||
{
|
||||
Message = message;
|
||||
@ -63,7 +62,8 @@ public class ServiceError
|
||||
|
||||
public static ServiceError DatabaseSaveFailed => new ServiceError("Database save failed", 800);
|
||||
|
||||
public static ServiceError NotReissue => new ServiceError("Not reissue, registering a new card", (int)CardReturnCode.NotReissue);
|
||||
public static ServiceError NotReissue =>
|
||||
new ServiceError("Not reissue, registering a new card", (int)CardReturnCode.NotReissue);
|
||||
|
||||
public static ServiceError UserNotFound => new("Card with this id does not exist", 996);
|
||||
|
||||
|
@ -1,4 +1,6 @@
|
||||
namespace Shared.Models;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Shared.Models;
|
||||
|
||||
/// <summary>
|
||||
/// A standard response for service calls.
|
||||
|
@ -1,16 +0,0 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Shared.Dto.Api;
|
||||
using Shared.Models;
|
||||
|
||||
namespace Shared.SerializerContexts;
|
||||
|
||||
[JsonSourceGenerationOptions(WriteIndented = true, GenerationMode = JsonSourceGenerationMode.Metadata)]
|
||||
[JsonSerializable(typeof(ServiceResult<List<ClientCardDto>>))]
|
||||
[JsonSerializable(typeof(ServiceResult<PlayOptionData>))]
|
||||
[JsonSerializable(typeof(ServiceResult<bool>))]
|
||||
[JsonSerializable(typeof(ServiceResult<TotalResultData>))]
|
||||
[JsonSerializable(typeof(ServiceResult<TotalResultData>))]
|
||||
public partial class SourceGenerationContext : JsonSerializerContext
|
||||
{
|
||||
|
||||
}
|
@ -31,7 +31,7 @@ public enum UnlockType
|
||||
Prefecture = 13,
|
||||
ChainMilestone = 14,
|
||||
Adlibs = 15,
|
||||
ConsequtiveNoMiss = 16,
|
||||
ConsecutiveNoMiss = 16,
|
||||
ClearsUsingItems = 17,
|
||||
Avatars = 18,
|
||||
MultiplayerStarsTotal = 19,
|
||||
|
@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Components;
|
||||
using Shared.Dto.Api;
|
||||
using Shared.Models;
|
||||
using Throw;
|
||||
using Shared.SerializerContexts;
|
||||
using WebUI.Pages.Dialogs;
|
||||
|
||||
namespace WebUI.Pages;
|
||||
@ -26,11 +25,11 @@ public partial class Cards
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
await Task.Delay(3000);
|
||||
|
||||
var result = await Client.GetFromJsonAsync<ServiceResult<List<ClientCardDto>>>("api/Profiles");
|
||||
result.ThrowIfNull();
|
||||
|
||||
Logger.LogInformation("Result: {Result}", result.Data);
|
||||
Logger.LogInformation("Result: {Result}", result.Succeeded);
|
||||
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
@ -52,5 +51,9 @@ public partial class Cards
|
||||
var dialog = await DialogService.ShowAsync<ChangePlayerNameDialog>("Favorite", parameters, options);
|
||||
// ReSharper disable once UnusedVariable
|
||||
var result = await dialog.Result;
|
||||
if (!result.Canceled)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
99
WebUI/Pages/Dialogs/ChangeAvatarDialog.razor
Normal file
99
WebUI/Pages/Dialogs/ChangeAvatarDialog.razor
Normal file
@ -0,0 +1,99 @@
|
||||
@using WebUI.Services
|
||||
@using Shared.Models
|
||||
@using WebUI.Common.Models
|
||||
@inject IDataService DataService
|
||||
|
||||
<MudDialog>
|
||||
<DialogContent>
|
||||
<MudTable Items="@avatars" Filter="@Filter" @bind-SelectedItem="@selectedAvatar" Hover="true"
|
||||
FixedHeader="true" Height="70vh">
|
||||
<ColGroup>
|
||||
<col style="width: 50px;"/>
|
||||
<col/>
|
||||
</ColGroup>
|
||||
<ToolBarContent>
|
||||
<MudTextField @bind-Value="searchString" Placeholder="Search" Adornment="Adornment.Start" Immediate="false"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0">
|
||||
</MudTextField>
|
||||
</ToolBarContent>
|
||||
<HeaderContent>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Avatar, object>(x => x.AvatarId))">
|
||||
Avatar Id
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Avatar, object>(x => x.AvatarName))">
|
||||
Avatar Name
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
@{
|
||||
# pragma warning disable CS8602
|
||||
}
|
||||
<MudTd DataLabel="Id" Class="cursor-pointer">@context.AvatarId</MudTd>
|
||||
<MudTd DataLabel="Title" Class="cursor-pointer">@context.AvatarName</MudTd>
|
||||
@{
|
||||
# pragma warning restore CS8602
|
||||
}
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager PageSizeOptions="new[] { 10, 25, 50, 100 }"/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
<MudText Class="mt-4 d-block" Typo="Typo.caption">
|
||||
<b>Selected Title:</b> @selectedAvatar?.AvatarName
|
||||
</MudText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="Cancel">Cancel</MudButton>
|
||||
<MudButton Color="Color.Primary" OnClick="Submit">Ok</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code{
|
||||
|
||||
[CascadingParameter]
|
||||
public required MudDialogInstance MudDialog { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public required PlayOptionData Data { get; set; }
|
||||
|
||||
private Avatar? selectedAvatar;
|
||||
|
||||
private IReadOnlyList<Avatar> avatars = new List<Avatar>();
|
||||
|
||||
private string searchString = string.Empty;
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
selectedAvatar = DataService.GetAvatarById((uint)Data.OptionPart1.AvatarId);
|
||||
avatars = DataService.GetAvatarsSortedById();
|
||||
}
|
||||
|
||||
|
||||
private bool Filter(Avatar? avatar)
|
||||
{
|
||||
if (avatar is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return string.IsNullOrEmpty(searchString) ||
|
||||
avatar.AvatarName.Contains(searchString, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private void Submit()
|
||||
{
|
||||
if (selectedAvatar is not null)
|
||||
{
|
||||
Data.OptionPart1.AvatarId = (int)selectedAvatar.AvatarId;
|
||||
}
|
||||
MudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
|
||||
private void Cancel() => MudDialog.Cancel();
|
||||
}
|
123
WebUI/Pages/Dialogs/ChangeNavigatorDialog.razor
Normal file
123
WebUI/Pages/Dialogs/ChangeNavigatorDialog.razor
Normal file
@ -0,0 +1,123 @@
|
||||
@using WebUI.Services
|
||||
@using Shared.Models
|
||||
@using WebUI.Common.Models
|
||||
@inject IDataService DataService
|
||||
|
||||
<MudDialog>
|
||||
<DialogContent>
|
||||
<MudTable Items="@navigators" Filter="@Filter" @bind-SelectedItem="@selectedNavigator" Hover="true"
|
||||
FixedHeader="true" Height="70vh">
|
||||
<ColGroup>
|
||||
<col style="width: 50px;"/>
|
||||
<col/>
|
||||
</ColGroup>
|
||||
<ToolBarContent>
|
||||
<MudTextField @bind-Value="searchString" Placeholder="Search" Adornment="Adornment.Start" Immediate="false"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0">
|
||||
</MudTextField>
|
||||
</ToolBarContent>
|
||||
<HeaderContent>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Navigator, object>(x => x.Id))">
|
||||
Navigator Id
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Navigator, object>(x => x.NavigatorName))">
|
||||
Navigator Name
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Navigator, object>(x => x.Genre))">
|
||||
Navigator Genre
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Navigator, object>(x => x.IllustrationCredit))">
|
||||
Illustration Credit
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Navigator, object>(x => x.ToolTipJp))">
|
||||
Tooltip (Japanese)
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Navigator, object>(x => x.ToolTipEn))">
|
||||
Tooltip (English)
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
@{
|
||||
# pragma warning disable CS8602
|
||||
}
|
||||
<MudTd DataLabel="Id" Class="cursor-pointer">@context.Id</MudTd>
|
||||
<MudTd DataLabel="Navigator" Class="cursor-pointer">@context.NavigatorName</MudTd>
|
||||
<MudTd DataLabel="Genre" Class="cursor-pointer">@context.Genre</MudTd>
|
||||
<MudTd DataLabel="IllustrationCredit" Class="cursor-pointer">@context.IllustrationCredit</MudTd>
|
||||
<MudTd DataLabel="ToolTipJp" Class="cursor-pointer">@context.ToolTipJp</MudTd>
|
||||
<MudTd DataLabel="ToolTipEn" Class="cursor-pointer">@context.ToolTipEn</MudTd>
|
||||
@{
|
||||
# pragma warning restore CS8602
|
||||
}
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager PageSizeOptions="new[] { 10, 25, 50, 100 }"/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
<MudText Class="mt-4 d-block" Typo="Typo.caption">
|
||||
<b>Selected Navigator:</b> @selectedNavigator?.NavigatorName
|
||||
</MudText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="Cancel">Cancel</MudButton>
|
||||
<MudButton Color="Color.Primary" OnClick="Submit">Ok</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code{
|
||||
|
||||
[CascadingParameter]
|
||||
public required MudDialogInstance MudDialog { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public required PlayOptionData Data { get; set; }
|
||||
|
||||
private Navigator? selectedNavigator;
|
||||
|
||||
private IReadOnlyList<Navigator> navigators = new List<Navigator>();
|
||||
|
||||
private string searchString = string.Empty;
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
selectedNavigator = DataService.GetNavigatorById((uint)Data.OptionPart2.NavigatorId);
|
||||
navigators = DataService.GetNavigatorsSortedById();
|
||||
}
|
||||
|
||||
|
||||
private bool Filter(Navigator? navigator)
|
||||
{
|
||||
if (navigator is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var aggregate = $"{navigator.NavigatorName}{navigator.IllustrationCredit}{navigator.ToolTipEn}{navigator.ToolTipJp}";
|
||||
return string.IsNullOrEmpty(searchString) ||
|
||||
aggregate.Contains(searchString, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private void Submit()
|
||||
{
|
||||
if (selectedNavigator is not null)
|
||||
{
|
||||
Data.OptionPart2.NavigatorId = (int)selectedNavigator.Id;
|
||||
}
|
||||
MudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
|
||||
private void Cancel() => MudDialog.Cancel();
|
||||
}
|
116
WebUI/Pages/Dialogs/ChangeTitleDialog.razor
Normal file
116
WebUI/Pages/Dialogs/ChangeTitleDialog.razor
Normal file
@ -0,0 +1,116 @@
|
||||
@using WebUI.Services
|
||||
@using Shared.Models
|
||||
@using WebUI.Common.Models
|
||||
@inject IDataService DataService
|
||||
|
||||
<MudDialog>
|
||||
<DialogContent>
|
||||
<MudTable Items="@titles" Filter="@Filter" @bind-SelectedItem="@selectedTitle" Hover="true"
|
||||
FixedHeader="true" Height="70vh">
|
||||
<ColGroup>
|
||||
<col style="width: 50px;" />
|
||||
<col />
|
||||
</ColGroup>
|
||||
<ToolBarContent>
|
||||
<MudTextField @bind-Value="searchString" Placeholder="Search" Adornment="Adornment.Start" Immediate="false"
|
||||
AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0">
|
||||
</MudTextField>
|
||||
</ToolBarContent>
|
||||
<HeaderContent>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Title, object>(x => x.Id))">
|
||||
Title Id
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Title, object>(x => x.TitleName))">
|
||||
Title Name
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
Unlock Condition Type
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Title, object>(x => x.UnlockRequirementJp))">
|
||||
Unlock Requirement (Japanese)
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
<MudTh>
|
||||
<MudTableSortLabel SortBy="@(new Func<Title, object>(x => x.UnlockRequirementEn))">
|
||||
Unlock Requirement (English)
|
||||
</MudTableSortLabel>
|
||||
</MudTh>
|
||||
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
@{
|
||||
# pragma warning disable CS8602
|
||||
}
|
||||
<MudTd DataLabel="Id" Class="cursor-pointer">@context.Id</MudTd>
|
||||
<MudTd DataLabel="Title" Class="cursor-pointer">@context.TitleName</MudTd>
|
||||
<MudTd DataLabel="UnlockType" Class="cursor-pointer">@context.UnlockType</MudTd>
|
||||
<MudTd DataLabel="UnlockRequirementJp" Class="cursor-pointer">@context.UnlockRequirementJp</MudTd>
|
||||
<MudTd DataLabel="UnlockRequirementEn" Class="cursor-pointer">@context.UnlockRequirementEn</MudTd>
|
||||
@{
|
||||
# pragma warning restore CS8602
|
||||
}
|
||||
</RowTemplate>
|
||||
<PagerContent>
|
||||
<MudTablePager PageSizeOptions="new []{10, 25, 50, 100}"/>
|
||||
</PagerContent>
|
||||
</MudTable>
|
||||
<MudText Class="mt-4 d-block" Typo="Typo.caption">
|
||||
<b>Selected Title:</b> @selectedTitle?.TitleName
|
||||
</MudText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="Cancel">Cancel</MudButton>
|
||||
<MudButton Color="Color.Primary" OnClick="Submit">Ok</MudButton>
|
||||
</DialogActions>
|
||||
</MudDialog>
|
||||
|
||||
@code{
|
||||
|
||||
[CascadingParameter]
|
||||
public required MudDialogInstance MudDialog { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public required PlayOptionData Data { get; set; }
|
||||
|
||||
private Title? selectedTitle;
|
||||
|
||||
private IReadOnlyList<Title> titles = new List<Title>();
|
||||
|
||||
private string searchString = string.Empty;
|
||||
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
selectedTitle = DataService.GetTitleById((uint)Data.OptionPart1.TitleId);
|
||||
titles = DataService.GetTitlesSortedById();
|
||||
}
|
||||
|
||||
|
||||
private bool Filter(Title? title)
|
||||
{
|
||||
if (title is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
var aggregate = $"{title.TitleName}{title.UnlockRequirementEn}{title.UnlockRequirementJp}";
|
||||
return string.IsNullOrEmpty(searchString) ||
|
||||
aggregate.Contains(searchString, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private void Submit()
|
||||
{
|
||||
if (selectedTitle is not null)
|
||||
{
|
||||
Data.OptionPart1.TitleId = (int)selectedTitle.Id;
|
||||
}
|
||||
MudDialog.Close(DialogResult.Ok(true));
|
||||
}
|
||||
|
||||
private void Cancel() => MudDialog.Cancel();
|
||||
}
|
@ -6,6 +6,13 @@
|
||||
|
||||
<PageTitle>Option</PageTitle>
|
||||
<h1>Play Options</h1>
|
||||
|
||||
@if (errorMessage is not null)
|
||||
{
|
||||
<MudText Color="Color.Error" Typo="Typo.h3">@errorMessage</MudText>
|
||||
return;
|
||||
}
|
||||
|
||||
@if (playOptionData is null)
|
||||
{
|
||||
<MudStack>
|
||||
@ -19,25 +26,20 @@
|
||||
return;
|
||||
}
|
||||
|
||||
@if (errorMessage != string.Empty)
|
||||
{
|
||||
<MudText Color="Color.Error" Typo="Typo.h3">@errorMessage</MudText>
|
||||
return;
|
||||
}
|
||||
<MudStack>
|
||||
<MudStack Row="true">
|
||||
<MudField Label="Avatar">@GetAvatarName((uint)playOptionData.OptionPart1.AvatarId)</MudField>
|
||||
<MudButton Variant="Variant.Text">Change Avatar</MudButton>
|
||||
<MudButton Variant="Variant.Text" OnClick="OpenChangeAvatarDialog">Change Avatar</MudButton>
|
||||
</MudStack>
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudField Label="Title">@GetTitleName((uint)playOptionData.OptionPart1.TitleId)</MudField>
|
||||
<MudButton Variant="Variant.Text">Change Title</MudButton>
|
||||
<MudButton Variant="Variant.Text" OnClick="OpenChangeTitleDialog">Change Title</MudButton>
|
||||
</MudStack>
|
||||
|
||||
<MudStack Row="true">
|
||||
<MudField Label="Navigator">@GetNavigatorName((uint)playOptionData.OptionPart2.NavigatorId)</MudField>
|
||||
<MudButton Variant="Variant.Text">Change Navigator</MudButton>
|
||||
<MudButton Variant="Variant.Text" OnClick="OpenChangeNavigatorDialog">Change Navigator</MudButton>
|
||||
</MudStack>
|
||||
|
||||
|
||||
@ -57,5 +59,20 @@
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<MudButton Color="Color.Info" Variant="Variant.Filled">Save Options</MudButton>
|
||||
<MudButton Color="Color.Info" Variant="Variant.Filled" OnClick="SaveOptions">
|
||||
@if (isSaving)
|
||||
{
|
||||
<MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true"/>
|
||||
<MudText Class="ms-2">Saving...</MudText>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudIcon Icon="@Icons.Material.Filled.Save"></MudIcon>
|
||||
<MudText>Save</MudText>
|
||||
}
|
||||
</MudButton>
|
||||
<MudButton Color="Color.Default" Variant="Variant.Filled" OnClick="UnlockMusics">
|
||||
<MudIcon Icon="@Icons.Material.Filled.LockOpen"></MudIcon>
|
||||
<MudText>Unlock All Musics</MudText>
|
||||
</MudButton>
|
||||
</MudStack>
|
@ -2,8 +2,8 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Shared.Models;
|
||||
using Throw;
|
||||
using WebUI.Pages.Dialogs;
|
||||
using WebUI.Services;
|
||||
using SourceGenerationContext = Shared.SerializerContexts.SourceGenerationContext;
|
||||
|
||||
namespace WebUI.Pages;
|
||||
|
||||
@ -21,6 +21,8 @@ public partial class Option
|
||||
[Inject]
|
||||
public required IDataService DataService { get; set; }
|
||||
|
||||
private bool isSaving;
|
||||
|
||||
private readonly List<BreadcrumbItem> breadcrumbs = new()
|
||||
{
|
||||
new BreadcrumbItem("Cards", href: "/Cards"),
|
||||
@ -28,7 +30,15 @@ public partial class Option
|
||||
|
||||
private PlayOptionData? playOptionData;
|
||||
|
||||
private string errorMessage = string.Empty;
|
||||
private string? errorMessage;
|
||||
|
||||
private static readonly DialogOptions OPTIONS = new()
|
||||
{
|
||||
CloseOnEscapeKey = false,
|
||||
DisableBackdropClick = true,
|
||||
FullWidth = true,
|
||||
MaxWidth = MaxWidth.ExtraExtraLarge
|
||||
};
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
@ -36,7 +46,6 @@ public partial class Option
|
||||
breadcrumbs.Add(new BreadcrumbItem($"Card: {CardId}", href:null, disabled:true));
|
||||
breadcrumbs.Add(new BreadcrumbItem("Option", href: $"/Cards/Option/{CardId}", disabled: false));
|
||||
|
||||
await Task.Delay(3000);
|
||||
var result = await Client.GetFromJsonAsync<ServiceResult<PlayOptionData>>($"api/PlayOption/{CardId}");
|
||||
result.ThrowIfNull();
|
||||
|
||||
@ -51,22 +60,78 @@ public partial class Option
|
||||
|
||||
private string GetNavigatorName(uint navigatorId)
|
||||
{
|
||||
var navigator = DataService.GetNavigators().GetValueOrDefault(navigatorId);
|
||||
var navigator = DataService.GetNavigatorById(navigatorId);
|
||||
|
||||
return navigator?.NavigatorName ?? "Navigator id unknown";
|
||||
}
|
||||
|
||||
private string GetAvatarName(uint avatarId)
|
||||
{
|
||||
var avatar = DataService.GetAvatars().GetValueOrDefault(avatarId);
|
||||
var avatar = DataService.GetAvatarById(avatarId);
|
||||
|
||||
return avatar?.AvatarName ?? "Avatar id unknown";
|
||||
}
|
||||
|
||||
private string GetTitleName(uint titleId)
|
||||
{
|
||||
var title = DataService.GetTitles().GetValueOrDefault(titleId);
|
||||
var title = DataService.GetTitleById(titleId);
|
||||
|
||||
return title?.TitleName ?? "Title id unknown";
|
||||
}
|
||||
|
||||
private async Task OpenChangeTitleDialog()
|
||||
{
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
["Data"] = playOptionData
|
||||
};
|
||||
|
||||
var dialog = await DialogService.ShowAsync<ChangeTitleDialog>("Change Title", parameters, OPTIONS);
|
||||
var result = await dialog.Result;
|
||||
if (!result.Canceled)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OpenChangeNavigatorDialog()
|
||||
{
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
["Data"] = playOptionData
|
||||
};
|
||||
|
||||
var dialog = await DialogService.ShowAsync<ChangeNavigatorDialog>("Change Navigator", parameters, OPTIONS);
|
||||
var result = await dialog.Result;
|
||||
if (!result.Canceled)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
private async Task OpenChangeAvatarDialog()
|
||||
{
|
||||
var parameters = new DialogParameters
|
||||
{
|
||||
["Data"] = playOptionData
|
||||
};
|
||||
|
||||
var dialog = await DialogService.ShowAsync<ChangeAvatarDialog>("Change Navigator", parameters, OPTIONS);
|
||||
var result = await dialog.Result;
|
||||
if (!result.Canceled)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveOptions()
|
||||
{
|
||||
isSaving = true;
|
||||
var result = await Client.PostAsJsonAsync("api/PlayOption", playOptionData);
|
||||
isSaving = false;
|
||||
}
|
||||
|
||||
private async Task UnlockMusics()
|
||||
{
|
||||
await Client.PostAsync($"api/Profiles/UnlockAllMusic/{CardId}", null);
|
||||
}
|
||||
}
|
47
WebUI/Pages/TotalResult.razor
Normal file
47
WebUI/Pages/TotalResult.razor
Normal file
@ -0,0 +1,47 @@
|
||||
@page "/Cards/TotalResult/{cardId:long}"
|
||||
|
||||
<MudBreadcrumbs Items="breadcrumbs" Class="px-0"></MudBreadcrumbs>
|
||||
|
||||
<PageTitle>Total Result</PageTitle>
|
||||
<h1>Total Result</h1>
|
||||
|
||||
@if (errorMessage is not null)
|
||||
{
|
||||
<MudText Color="Color.Error" Typo="Typo.h3">@errorMessage</MudText>
|
||||
return;
|
||||
}
|
||||
|
||||
@if (totalResultData is null)
|
||||
{
|
||||
<MudStack>
|
||||
<MudSkeleton Width="100%"/>
|
||||
<MudSkeleton Width="100%"/>
|
||||
<MudSkeleton Width="100%"/>
|
||||
<MudSkeleton Width="100%"/>
|
||||
<MudSkeleton Width="100%"/>
|
||||
<MudSkeleton Width="100%"/>
|
||||
</MudStack>
|
||||
return;
|
||||
}
|
||||
|
||||
@if (totalResultData.PlayerData.PlayedSongCount == 0)
|
||||
{
|
||||
<MudText Typo="Typo.h3">
|
||||
No Play Record
|
||||
</MudText>
|
||||
return;
|
||||
}
|
||||
|
||||
<MudList>
|
||||
<MudListSubheader>Player Name: @totalResultData.PlayerName</MudListSubheader>
|
||||
<MudListItem>Total Score: @totalResultData.PlayerData.TotalScore</MudListItem>
|
||||
<MudListItem>Average Score: @totalResultData.PlayerData.AverageScore</MudListItem>
|
||||
<MudListItem>Played Song Count: @totalResultData.PlayerData.PlayedSongCount / @totalResultData.PlayerData.TotalSongCount</MudListItem>
|
||||
<MudListItem>Cleared Stage Count: @totalResultData.StageCountData.Cleared / @totalResultData.StageCountData.Total</MudListItem>
|
||||
<MudListItem>No Miss Stage Count: @totalResultData.StageCountData.NoMiss / @totalResultData.StageCountData.Total</MudListItem>
|
||||
<MudListItem>Full Chain Stage Count: @totalResultData.StageCountData.FullChain / @totalResultData.StageCountData.Total</MudListItem>
|
||||
<MudListItem>Perfect Stage Count: @totalResultData.StageCountData.Perfect / @totalResultData.StageCountData.Total</MudListItem>
|
||||
<MudListItem>S and Above Stage Count: @totalResultData.StageCountData.S / @totalResultData.StageCountData.Total</MudListItem>
|
||||
<MudListItem>S+ and Above Stage Count: @totalResultData.StageCountData.Ss / @totalResultData.StageCountData.Total</MudListItem>
|
||||
<MudListItem>S++ and Above Stage Count: @totalResultData.StageCountData.Sss / @totalResultData.StageCountData.Total</MudListItem>
|
||||
</MudList>
|
43
WebUI/Pages/TotalResult.razor.cs
Normal file
43
WebUI/Pages/TotalResult.razor.cs
Normal file
@ -0,0 +1,43 @@
|
||||
using System.Net.Http.Json;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Shared.Models;
|
||||
using Throw;
|
||||
|
||||
namespace WebUI.Pages;
|
||||
|
||||
public partial class TotalResult
|
||||
{
|
||||
private readonly List<BreadcrumbItem> breadcrumbs = new()
|
||||
{
|
||||
new BreadcrumbItem("Cards", href: "/Cards")
|
||||
};
|
||||
|
||||
[Parameter]
|
||||
public long CardId { get; set; }
|
||||
|
||||
[Inject]
|
||||
public required HttpClient Client { get; set; }
|
||||
|
||||
private string? errorMessage;
|
||||
|
||||
private TotalResultData? totalResultData;
|
||||
|
||||
protected async override Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
breadcrumbs.Add(new BreadcrumbItem($"Card: {CardId}", href:null, disabled:true));
|
||||
breadcrumbs.Add(new BreadcrumbItem("TotalResult", href: $"/Cards/TotalResult/{CardId}", disabled: false));
|
||||
|
||||
var result = await Client.GetFromJsonAsync<ServiceResult<TotalResultData>>($"api/Profiles/TotalResult/{CardId}");
|
||||
result.ThrowIfNull();
|
||||
|
||||
if (!result.Succeeded)
|
||||
{
|
||||
errorMessage = result.Error!.Message;
|
||||
return;
|
||||
}
|
||||
|
||||
totalResultData = result.Data;
|
||||
}
|
||||
}
|
@ -14,6 +14,12 @@ public class DataService : IDataService
|
||||
|
||||
private Dictionary<uint, Title> titles = new();
|
||||
|
||||
private List<Avatar> sortedAvatarList = new();
|
||||
|
||||
private List<Navigator> sortedNavigatorList = new();
|
||||
|
||||
private List<Title> sortedTitleList = new();
|
||||
|
||||
private readonly HttpClient client;
|
||||
|
||||
public DataService(HttpClient client)
|
||||
@ -26,29 +32,47 @@ public class DataService : IDataService
|
||||
var avatarList = await client.GetFromJsonAsync("data/Avatars.json", SourceGenerationContext.Default.ListAvatar);
|
||||
avatarList.ThrowIfNull();
|
||||
avatars = avatarList.ToDictionary(avatar => avatar.AvatarId);
|
||||
sortedAvatarList = avatarList.OrderBy(avatar => avatar.AvatarId).ToList();
|
||||
|
||||
var navigatorList = await client.GetFromJsonAsync("data/Navigators.json", SourceGenerationContext.Default.ListNavigator);
|
||||
navigatorList.ThrowIfNull();
|
||||
navigators = navigatorList.ToDictionary(navigator => navigator.Id);
|
||||
sortedNavigatorList = navigatorList.OrderBy(navigator => navigator.Id).ToList();
|
||||
|
||||
var titleList = await client.GetFromJsonAsync("data/Titles.json", SourceGenerationContext.Default.ListTitle);
|
||||
titleList.ThrowIfNull();
|
||||
titles = titleList.ToDictionary(title => title.Id);
|
||||
sortedTitleList = titleList.OrderBy(title => title.Id).ToList();
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<uint, Avatar> GetAvatars()
|
||||
public IReadOnlyList<Avatar> GetAvatarsSortedById()
|
||||
{
|
||||
return new ReadOnlyDictionary<uint, Avatar>(avatars);
|
||||
return sortedAvatarList;
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<uint, Navigator> GetNavigators()
|
||||
public IReadOnlyList<Navigator> GetNavigatorsSortedById()
|
||||
{
|
||||
return new ReadOnlyDictionary<uint, Navigator>(navigators);
|
||||
return sortedNavigatorList;
|
||||
}
|
||||
|
||||
public IReadOnlyDictionary<uint, Title> GetTitles()
|
||||
public IReadOnlyList<Title> GetTitlesSortedById()
|
||||
{
|
||||
return new ReadOnlyDictionary<uint, Title>(titles);
|
||||
return sortedTitleList;
|
||||
}
|
||||
|
||||
public Avatar? GetAvatarById(uint id)
|
||||
{
|
||||
return avatars.GetValueOrDefault(id);
|
||||
}
|
||||
|
||||
public Title? GetTitleById(uint id)
|
||||
{
|
||||
return titles.GetValueOrDefault(id);
|
||||
}
|
||||
|
||||
public Navigator? GetNavigatorById(uint id)
|
||||
{
|
||||
return navigators.GetValueOrDefault(id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,15 @@ public interface IDataService
|
||||
{
|
||||
public Task InitializeAsync();
|
||||
|
||||
public IReadOnlyDictionary<uint, Avatar> GetAvatars();
|
||||
public IReadOnlyList<Avatar> GetAvatarsSortedById();
|
||||
|
||||
public IReadOnlyDictionary<uint, Navigator> GetNavigators();
|
||||
public IReadOnlyList<Navigator> GetNavigatorsSortedById();
|
||||
|
||||
public IReadOnlyDictionary<uint, Title> GetTitles();
|
||||
public IReadOnlyList<Title> GetTitlesSortedById();
|
||||
|
||||
public Avatar? GetAvatarById(uint id);
|
||||
|
||||
public Title? GetTitleById(uint id);
|
||||
|
||||
public Navigator? GetNavigatorById(uint id);
|
||||
}
|
@ -6,7 +6,7 @@ card_id, pcol1, pcol2, pcol3 are primary keys
|
||||
| :---: | :-----: | :--------: | :----------------------------------------------------------: |
|
||||
| 0 | 0 | 0 | score_i1:**avatar** score_ui1:**fast/slow** score_ui2:**fever/trance** fcol1: fcol2:**title** fcol3:**sound** |
|
||||
| 1 | 0 | 0 | score_i1:**navigator** fcol3:**unknown** |
|
||||
| 10 | song id | 0 | score_i1:**skin** score_ui2s:**Whether the song is unlocked** , core_ui6: **The song need to be unlocked**, fcol1:**Favorite song** |
|
||||
| 10 | song id | 0 | score_i1:**skin**, score_ui2:**Whether the song is unlocked**, score_ui6: **The song need to be unlocked**, fcol1:**Favorite song** |
|
||||
| 20 | song id | difficulty | score_ui1:**play count** score_ui2:**clear count** score_ui3:**no miss or higher count** score_ui4: **full_chain or higher count** score_ui5: **S+ or higher count** score_ui6: **perfect count** |
|
||||
| 21 | song id | difficulty | score_ui1/score_ui5: **highest score**, score_ui2/score_ui6:**highest_score time** score_ui3:**max_chain** score_ui4: **max chain time** fcol1:**max hit adlib count** fcol2:**time for fcol1** |
|
||||
| 30 | 0 | 0 | score_ui2:**Unknown, looks like some sort of count** |
|
||||
|
Loading…
Reference in New Issue
Block a user