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;
|
namespace Application.Api;
|
||||||
|
|
||||||
public record SetFavoriteMusicCommand(MusicDetailDto Data) : IRequestWrapper<bool>;
|
public record SetFavoriteMusicCommand(MusicFavoriteDto Data) : IRequestWrapper<bool>;
|
||||||
|
|
||||||
public class SetFavoriteMusicCommandHandler : RequestHandlerBase<SetFavoriteMusicCommand, 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("{cardId:long}")]
|
[HttpGet("TotalResult/{cardId:long}")]
|
||||||
public async Task<ServiceResult<TotalResultData>> GetCardTotalResultById(long cardId)
|
public async Task<ServiceResult<TotalResultData>> GetCardTotalResultById(long cardId)
|
||||||
{
|
{
|
||||||
var result = await Mediator.Send(new GetTotalResultQuery(cardId));
|
var result = await Mediator.Send(new GetTotalResultQuery(cardId));
|
||||||
@ -24,9 +24,9 @@ public class ProfilesController : BaseController<ProfilesController>
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("Favorite")]
|
[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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,4 +36,12 @@ public class ProfilesController : BaseController<ProfilesController>
|
|||||||
var result = await Mediator.Send(new SetPlayerNameCommand(card));
|
var result = await Mediator.Send(new SetPlayerNameCommand(card));
|
||||||
return result;
|
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;
|
||||||
using Serilog.Extensions.Logging;
|
using Serilog.Extensions.Logging;
|
||||||
using Throw;
|
using Throw;
|
||||||
using Shared.SerializerContexts;
|
|
||||||
|
|
||||||
Log.Logger = new LoggerConfiguration()
|
Log.Logger = new LoggerConfiguration()
|
||||||
.WriteTo.Console()
|
.WriteTo.Console()
|
||||||
@ -58,7 +57,7 @@ try
|
|||||||
|
|
||||||
builder.Services.AddControllers(options =>
|
builder.Services.AddControllers(options =>
|
||||||
options.Filters.Add<ApiExceptionFilterService>())
|
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
|
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
namespace Shared.Dto.Api;
|
namespace Shared.Dto.Api;
|
||||||
|
|
||||||
public class MusicDetailDto
|
public class MusicFavoriteDto
|
||||||
{
|
{
|
||||||
public long CardId { get; set; }
|
public long CardId { get; set; }
|
||||||
|
|
@ -1,4 +1,5 @@
|
|||||||
using Domain.Enums;
|
using System.Text.Json.Serialization;
|
||||||
|
using Domain.Enums;
|
||||||
|
|
||||||
namespace Shared.Models;
|
namespace Shared.Models;
|
||||||
|
|
||||||
@ -12,9 +13,7 @@ namespace Shared.Models;
|
|||||||
[Serializable]
|
[Serializable]
|
||||||
public class ServiceError
|
public class ServiceError
|
||||||
{
|
{
|
||||||
/// <summary>
|
[JsonConstructor]
|
||||||
/// CTOR
|
|
||||||
/// </summary>
|
|
||||||
public ServiceError(string message, int code)
|
public ServiceError(string message, int code)
|
||||||
{
|
{
|
||||||
Message = message;
|
Message = message;
|
||||||
@ -63,7 +62,8 @@ public class ServiceError
|
|||||||
|
|
||||||
public static ServiceError DatabaseSaveFailed => new ServiceError("Database save failed", 800);
|
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);
|
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>
|
/// <summary>
|
||||||
/// A standard response for service calls.
|
/// 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,
|
Prefecture = 13,
|
||||||
ChainMilestone = 14,
|
ChainMilestone = 14,
|
||||||
Adlibs = 15,
|
Adlibs = 15,
|
||||||
ConsequtiveNoMiss = 16,
|
ConsecutiveNoMiss = 16,
|
||||||
ClearsUsingItems = 17,
|
ClearsUsingItems = 17,
|
||||||
Avatars = 18,
|
Avatars = 18,
|
||||||
MultiplayerStarsTotal = 19,
|
MultiplayerStarsTotal = 19,
|
||||||
|
@ -3,7 +3,6 @@ using Microsoft.AspNetCore.Components;
|
|||||||
using Shared.Dto.Api;
|
using Shared.Dto.Api;
|
||||||
using Shared.Models;
|
using Shared.Models;
|
||||||
using Throw;
|
using Throw;
|
||||||
using Shared.SerializerContexts;
|
|
||||||
using WebUI.Pages.Dialogs;
|
using WebUI.Pages.Dialogs;
|
||||||
|
|
||||||
namespace WebUI.Pages;
|
namespace WebUI.Pages;
|
||||||
@ -26,11 +25,11 @@ public partial class Cards
|
|||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await base.OnInitializedAsync();
|
await base.OnInitializedAsync();
|
||||||
await Task.Delay(3000);
|
|
||||||
var result = await Client.GetFromJsonAsync<ServiceResult<List<ClientCardDto>>>("api/Profiles");
|
var result = await Client.GetFromJsonAsync<ServiceResult<List<ClientCardDto>>>("api/Profiles");
|
||||||
result.ThrowIfNull();
|
result.ThrowIfNull();
|
||||||
|
|
||||||
Logger.LogInformation("Result: {Result}", result.Data);
|
Logger.LogInformation("Result: {Result}", result.Succeeded);
|
||||||
|
|
||||||
if (!result.Succeeded)
|
if (!result.Succeeded)
|
||||||
{
|
{
|
||||||
@ -52,5 +51,9 @@ public partial class Cards
|
|||||||
var dialog = await DialogService.ShowAsync<ChangePlayerNameDialog>("Favorite", parameters, options);
|
var dialog = await DialogService.ShowAsync<ChangePlayerNameDialog>("Favorite", parameters, options);
|
||||||
// ReSharper disable once UnusedVariable
|
// ReSharper disable once UnusedVariable
|
||||||
var result = await dialog.Result;
|
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>
|
<PageTitle>Option</PageTitle>
|
||||||
<h1>Play Options</h1>
|
<h1>Play Options</h1>
|
||||||
|
|
||||||
|
@if (errorMessage is not null)
|
||||||
|
{
|
||||||
|
<MudText Color="Color.Error" Typo="Typo.h3">@errorMessage</MudText>
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
@if (playOptionData is null)
|
@if (playOptionData is null)
|
||||||
{
|
{
|
||||||
<MudStack>
|
<MudStack>
|
||||||
@ -19,25 +26,20 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@if (errorMessage != string.Empty)
|
|
||||||
{
|
|
||||||
<MudText Color="Color.Error" Typo="Typo.h3">@errorMessage</MudText>
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
<MudStack>
|
<MudStack>
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudField Label="Avatar">@GetAvatarName((uint)playOptionData.OptionPart1.AvatarId)</MudField>
|
<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>
|
||||||
|
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudField Label="Title">@GetTitleName((uint)playOptionData.OptionPart1.TitleId)</MudField>
|
<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>
|
||||||
|
|
||||||
<MudStack Row="true">
|
<MudStack Row="true">
|
||||||
<MudField Label="Navigator">@GetNavigatorName((uint)playOptionData.OptionPart2.NavigatorId)</MudField>
|
<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>
|
</MudStack>
|
||||||
|
|
||||||
|
|
||||||
@ -57,5 +59,20 @@
|
|||||||
}
|
}
|
||||||
</MudSelect>
|
</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>
|
</MudStack>
|
@ -2,8 +2,8 @@
|
|||||||
using Microsoft.AspNetCore.Components;
|
using Microsoft.AspNetCore.Components;
|
||||||
using Shared.Models;
|
using Shared.Models;
|
||||||
using Throw;
|
using Throw;
|
||||||
|
using WebUI.Pages.Dialogs;
|
||||||
using WebUI.Services;
|
using WebUI.Services;
|
||||||
using SourceGenerationContext = Shared.SerializerContexts.SourceGenerationContext;
|
|
||||||
|
|
||||||
namespace WebUI.Pages;
|
namespace WebUI.Pages;
|
||||||
|
|
||||||
@ -21,6 +21,8 @@ public partial class Option
|
|||||||
[Inject]
|
[Inject]
|
||||||
public required IDataService DataService { get; set; }
|
public required IDataService DataService { get; set; }
|
||||||
|
|
||||||
|
private bool isSaving;
|
||||||
|
|
||||||
private readonly List<BreadcrumbItem> breadcrumbs = new()
|
private readonly List<BreadcrumbItem> breadcrumbs = new()
|
||||||
{
|
{
|
||||||
new BreadcrumbItem("Cards", href: "/Cards"),
|
new BreadcrumbItem("Cards", href: "/Cards"),
|
||||||
@ -28,7 +30,15 @@ public partial class Option
|
|||||||
|
|
||||||
private PlayOptionData? playOptionData;
|
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()
|
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($"Card: {CardId}", href:null, disabled:true));
|
||||||
breadcrumbs.Add(new BreadcrumbItem("Option", href: $"/Cards/Option/{CardId}", disabled: false));
|
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}");
|
var result = await Client.GetFromJsonAsync<ServiceResult<PlayOptionData>>($"api/PlayOption/{CardId}");
|
||||||
result.ThrowIfNull();
|
result.ThrowIfNull();
|
||||||
|
|
||||||
@ -51,22 +60,78 @@ public partial class Option
|
|||||||
|
|
||||||
private string GetNavigatorName(uint navigatorId)
|
private string GetNavigatorName(uint navigatorId)
|
||||||
{
|
{
|
||||||
var navigator = DataService.GetNavigators().GetValueOrDefault(navigatorId);
|
var navigator = DataService.GetNavigatorById(navigatorId);
|
||||||
|
|
||||||
return navigator?.NavigatorName ?? "Navigator id unknown";
|
return navigator?.NavigatorName ?? "Navigator id unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetAvatarName(uint avatarId)
|
private string GetAvatarName(uint avatarId)
|
||||||
{
|
{
|
||||||
var avatar = DataService.GetAvatars().GetValueOrDefault(avatarId);
|
var avatar = DataService.GetAvatarById(avatarId);
|
||||||
|
|
||||||
return avatar?.AvatarName ?? "Avatar id unknown";
|
return avatar?.AvatarName ?? "Avatar id unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetTitleName(uint titleId)
|
private string GetTitleName(uint titleId)
|
||||||
{
|
{
|
||||||
var title = DataService.GetTitles().GetValueOrDefault(titleId);
|
var title = DataService.GetTitleById(titleId);
|
||||||
|
|
||||||
return title?.TitleName ?? "Title id unknown";
|
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 Dictionary<uint, Title> titles = new();
|
||||||
|
|
||||||
|
private List<Avatar> sortedAvatarList = new();
|
||||||
|
|
||||||
|
private List<Navigator> sortedNavigatorList = new();
|
||||||
|
|
||||||
|
private List<Title> sortedTitleList = new();
|
||||||
|
|
||||||
private readonly HttpClient client;
|
private readonly HttpClient client;
|
||||||
|
|
||||||
public DataService(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);
|
var avatarList = await client.GetFromJsonAsync("data/Avatars.json", SourceGenerationContext.Default.ListAvatar);
|
||||||
avatarList.ThrowIfNull();
|
avatarList.ThrowIfNull();
|
||||||
avatars = avatarList.ToDictionary(avatar => avatar.AvatarId);
|
avatars = avatarList.ToDictionary(avatar => avatar.AvatarId);
|
||||||
|
sortedAvatarList = avatarList.OrderBy(avatar => avatar.AvatarId).ToList();
|
||||||
|
|
||||||
var navigatorList = await client.GetFromJsonAsync("data/Navigators.json", SourceGenerationContext.Default.ListNavigator);
|
var navigatorList = await client.GetFromJsonAsync("data/Navigators.json", SourceGenerationContext.Default.ListNavigator);
|
||||||
navigatorList.ThrowIfNull();
|
navigatorList.ThrowIfNull();
|
||||||
navigators = navigatorList.ToDictionary(navigator => navigator.Id);
|
navigators = navigatorList.ToDictionary(navigator => navigator.Id);
|
||||||
|
sortedNavigatorList = navigatorList.OrderBy(navigator => navigator.Id).ToList();
|
||||||
|
|
||||||
var titleList = await client.GetFromJsonAsync("data/Titles.json", SourceGenerationContext.Default.ListTitle);
|
var titleList = await client.GetFromJsonAsync("data/Titles.json", SourceGenerationContext.Default.ListTitle);
|
||||||
titleList.ThrowIfNull();
|
titleList.ThrowIfNull();
|
||||||
titles = titleList.ToDictionary(title => title.Id);
|
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 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** |
|
| 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** |
|
| 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** |
|
| 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** |
|
| 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** |
|
| 30 | 0 | 0 | score_ui2:**Unknown, looks like some sort of count** |
|
||||||
|
Loading…
Reference in New Issue
Block a user