Add last play time support
Support setting avatar, navigator and titles on web interface (unoptimized)
This commit is contained in:
parent
95d9d0be5f
commit
4cd290aedc
@ -1,3 +1,6 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Adlibs/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Keynum/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Keynum/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=unlockable/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Touhou/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=unlockable/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Vocaloid/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
@ -126,7 +126,8 @@ public static class Configs
|
|||||||
|
|
||||||
public const string RANK_STATUS_XPATH = $"{ROOT_XPATH}/ranking_status";
|
public const string RANK_STATUS_XPATH = $"{ROOT_XPATH}/ranking_status";
|
||||||
|
|
||||||
public const int CONFIG_PCOL1 = 0;
|
public const int FIRST_CONFIG_PCOL1 = 0;
|
||||||
|
public const int SECOND_CONFIG_PCOL1 = 1;
|
||||||
public const int CONFIG_PCOL2 = 0;
|
public const int CONFIG_PCOL2 = 0;
|
||||||
public const int CONFIG_PCOL3 = 0;
|
public const int CONFIG_PCOL3 = 0;
|
||||||
|
|
||||||
|
@ -65,26 +65,38 @@ public class ApiController : WebApiController
|
|||||||
// ReSharper disable once UnusedMember.Global
|
// ReSharper disable once UnusedMember.Global
|
||||||
public bool SetPlayOption([JsonData] PlayOption data)
|
public bool SetPlayOption([JsonData] PlayOption data)
|
||||||
{
|
{
|
||||||
var existing = cardSqLiteConnection.Table<CardDetail>()
|
var firstConfig = cardSqLiteConnection.Table<CardDetail>()
|
||||||
.Where(detail => detail.CardId == data.CardId
|
.Where(detail => detail.CardId == data.CardId
|
||||||
&& detail.Pcol1 == Configs.CONFIG_PCOL1
|
&& detail.Pcol1 == Configs.FIRST_CONFIG_PCOL1
|
||||||
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
||||||
&& detail.Pcol3 == Configs.CONFIG_PCOL3);
|
&& detail.Pcol3 == Configs.CONFIG_PCOL3);
|
||||||
|
|
||||||
if (!existing.Any())
|
var secondConfig = cardSqLiteConnection.Table<CardDetail>()
|
||||||
|
.Where(detail => detail.CardId == data.CardId
|
||||||
|
&& detail.Pcol1 == Configs.SECOND_CONFIG_PCOL1
|
||||||
|
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
||||||
|
&& detail.Pcol3 == Configs.CONFIG_PCOL3);
|
||||||
|
|
||||||
|
if (!firstConfig.Any() || !secondConfig.Any())
|
||||||
{
|
{
|
||||||
$"Trying to update non existing card's config! Card id {data.CardId}".Warn();
|
$"Trying to update non existing card's config! Card id {data.CardId}".Warn();
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cardDetail = existing.First();
|
var firstDetail = firstConfig.First();
|
||||||
cardDetail.ScoreUi1 = (long)data.FastSlowIndicator;
|
firstDetail.ScoreUi1 = (long)data.FastSlowIndicator;
|
||||||
cardDetail.ScoreUi2 = (long)data.FeverTrance;
|
firstDetail.ScoreUi2 = (long)data.FeverTrance;
|
||||||
|
firstDetail.ScoreI1 = data.AvatarId;
|
||||||
|
firstDetail.Fcol2 = (int)data.TitleId;
|
||||||
|
|
||||||
var result = cardSqLiteConnection.Update(cardDetail);
|
var secondDetail = secondConfig.First();
|
||||||
|
secondDetail.ScoreI1 = data.NavigatorId;
|
||||||
|
|
||||||
return result == 1;
|
var firstResult = cardSqLiteConnection.Update(firstDetail);
|
||||||
|
var secondResult = cardSqLiteConnection.Update(secondDetail);
|
||||||
|
|
||||||
|
return firstResult == 1 && secondResult == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Route(HttpVerbs.Get, "/UserDetail/{cardId}")]
|
[Route(HttpVerbs.Get, "/UserDetail/{cardId}")]
|
||||||
@ -125,16 +137,26 @@ public class ApiController : WebApiController
|
|||||||
|
|
||||||
private void ProcessCardDetail(UserDetail userDetail, IDictionary<int, SongPlayData> songPlayDataDict)
|
private void ProcessCardDetail(UserDetail userDetail, IDictionary<int, SongPlayData> songPlayDataDict)
|
||||||
{
|
{
|
||||||
var option = cardSqLiteConnection.Table<CardDetail>()
|
var firstOption = cardSqLiteConnection.Table<CardDetail>()
|
||||||
.FirstOrDefault(detail => detail.CardId == userDetail.CardId
|
.FirstOrDefault(detail => detail.CardId == userDetail.CardId
|
||||||
&& detail.Pcol1 == Configs.CONFIG_PCOL1
|
&& detail.Pcol1 == Configs.FIRST_CONFIG_PCOL1
|
||||||
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
||||||
&& detail.Pcol3 == Configs.CONFIG_PCOL3
|
&& detail.Pcol3 == Configs.CONFIG_PCOL3
|
||||||
, new CardDetail
|
, new CardDetail
|
||||||
{
|
{
|
||||||
CardId = userDetail.CardId
|
CardId = userDetail.CardId
|
||||||
});
|
});
|
||||||
SetOptions(option, userDetail);
|
var secondOption = cardSqLiteConnection.Table<CardDetail>()
|
||||||
|
.FirstOrDefault(detail => detail.CardId == userDetail.CardId
|
||||||
|
&& detail.Pcol1 == Configs.SECOND_CONFIG_PCOL1
|
||||||
|
&& detail.Pcol2 == Configs.CONFIG_PCOL2
|
||||||
|
&& detail.Pcol3 == Configs.CONFIG_PCOL3
|
||||||
|
, new CardDetail
|
||||||
|
{
|
||||||
|
CardId = userDetail.CardId
|
||||||
|
});
|
||||||
|
|
||||||
|
SetOptions(firstOption, secondOption, userDetail);
|
||||||
|
|
||||||
var songCounts = cardSqLiteConnection.Table<CardDetail>()
|
var songCounts = cardSqLiteConnection.Table<CardDetail>()
|
||||||
.Where(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == Configs.COUNT_PCOL1);
|
.Where(detail => detail.CardId == userDetail.CardId && detail.Pcol1 == Configs.COUNT_PCOL1);
|
||||||
@ -162,10 +184,10 @@ public class ApiController : WebApiController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetOptions(CardDetail cardDetail, UserDetail userDetail)
|
private static void SetOptions(CardDetail firstOptionCardDetail, CardDetail secondOptionCardDetail, UserDetail userDetail)
|
||||||
{
|
{
|
||||||
var fastSlow = (int)cardDetail.ScoreUi1;
|
var fastSlow = (int)firstOptionCardDetail.ScoreUi1;
|
||||||
var feverTrance = (int)cardDetail.ScoreUi2;
|
var feverTrance = (int)firstOptionCardDetail.ScoreUi2;
|
||||||
|
|
||||||
if (!Enum.IsDefined(typeof(PlayOptions.FastSlowIndicator), fastSlow))
|
if (!Enum.IsDefined(typeof(PlayOptions.FastSlowIndicator), fastSlow))
|
||||||
{
|
{
|
||||||
@ -179,9 +201,12 @@ public class ApiController : WebApiController
|
|||||||
|
|
||||||
userDetail.PlayOption = new PlayOption
|
userDetail.PlayOption = new PlayOption
|
||||||
{
|
{
|
||||||
CardId = cardDetail.CardId,
|
CardId = firstOptionCardDetail.CardId,
|
||||||
FastSlowIndicator = (PlayOptions.FastSlowIndicator)fastSlow,
|
FastSlowIndicator = (PlayOptions.FastSlowIndicator)fastSlow,
|
||||||
FeverTrance = (PlayOptions.FeverTranceShow)feverTrance
|
FeverTrance = (PlayOptions.FeverTranceShow)feverTrance,
|
||||||
|
AvatarId = firstOptionCardDetail.ScoreI1,
|
||||||
|
TitleId = firstOptionCardDetail.Fcol2,
|
||||||
|
NavigatorId = secondOptionCardDetail.ScoreI1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
private void SetDetails(CardDetail cardDetail, IDictionary<int, SongPlayData> songPlayDataDict,
|
private void SetDetails(CardDetail cardDetail, IDictionary<int, SongPlayData> songPlayDataDict,
|
||||||
@ -241,6 +266,7 @@ public class ApiController : WebApiController
|
|||||||
}
|
}
|
||||||
|
|
||||||
songPlayDetailData.PlayCount = (int)cardDetail.ScoreUi1;
|
songPlayDetailData.PlayCount = (int)cardDetail.ScoreUi1;
|
||||||
|
songPlayDetailData.LastPlayTime = cardDetail.LastPlayTime;
|
||||||
songPlayDetailData.ClearState = ClearState.Failed;
|
songPlayDetailData.ClearState = ClearState.Failed;
|
||||||
userDetail.PlayedStageCount++;
|
userDetail.PlayedStageCount++;
|
||||||
|
|
||||||
|
@ -40,14 +40,14 @@ public class CardServiceController : WebApiController
|
|||||||
{
|
{
|
||||||
if (!Enum.IsDefined(typeof(Command), cmdType))
|
if (!Enum.IsDefined(typeof(Command), cmdType))
|
||||||
{
|
{
|
||||||
throw new ArgumentOutOfRangeException(nameof(cmdType), cmdType, "Cmd type is unknown!");
|
throw new ArgumentOutOfRangeException(nameof(cmdType), cmdType, $"Cmd type is unknown!\n Data is {xmlData}");
|
||||||
}
|
}
|
||||||
|
|
||||||
var command = (Command)cmdType;
|
var command = (Command)cmdType;
|
||||||
|
|
||||||
return command switch
|
return command switch
|
||||||
{
|
{
|
||||||
Command.CardRequest => ProcessCardRequest(mac, cardId, xmlData, type),
|
Command.CardReadRequest or Command.CardWriteRequest => ProcessCardRequest(mac, cardId, xmlData, type),
|
||||||
Command.ReissueRequest => ProcessReissueRequest(),
|
Command.ReissueRequest => ProcessReissueRequest(),
|
||||||
Command.RegisterRequest => ProcessRegisterRequest(cardId, xmlData),
|
Command.RegisterRequest => ProcessRegisterRequest(cardId, xmlData),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(command), command, "Command unknown, should never happen!")
|
_ => throw new ArgumentOutOfRangeException(nameof(command), command, "Command unknown, should never happen!")
|
||||||
@ -534,35 +534,56 @@ public class CardServiceController : WebApiController
|
|||||||
$"Updated card play count, current count is {data.PlayCount}".Info();
|
$"Updated card play count, current count is {data.PlayCount}".Info();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteCardDetail(long cardId, string xmlData)
|
private void WriteCardDetail(long cardId, string xmlData)
|
||||||
{
|
{
|
||||||
var result = cardSqLiteConnection.Table<CardDetail>()
|
var result = cardSqLiteConnection.Table<CardDetail>()
|
||||||
.Where(detail => detail.CardId == cardId);
|
.Where(detail => detail.CardId == cardId);
|
||||||
|
|
||||||
// Unlock all unlockable songs in card details table when write for the first time
|
// Unlock all unlockable songs in card details table when write card detail for the first time
|
||||||
if (!result.Any())
|
if (!result.Any())
|
||||||
{
|
{
|
||||||
var unlockableSongIds = Configs.SETTINGS.UnlockableSongIds;
|
UnlockSongs(cardId);
|
||||||
|
|
||||||
if (unlockableSongIds is null)
|
|
||||||
{
|
|
||||||
unlockableSongIds = Configs.DEFAULT_UNLOCKABLE_SONGS;
|
|
||||||
}
|
|
||||||
var detailList = unlockableSongIds.Select(id => new CardDetail
|
|
||||||
{
|
|
||||||
CardId = cardId,
|
|
||||||
Pcol1 = 10,
|
|
||||||
Pcol2 = id,
|
|
||||||
Pcol3 = 0,
|
|
||||||
ScoreUi2 = 1,
|
|
||||||
ScoreUi6 = 1
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
cardSqLiteConnection.InsertOrIgnoreAll(detailList);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Write<CardDetail>(cardId, xmlData);
|
var reader = new ChoXmlReader<CardDetail>(new StringReader(xmlData)).WithXPath(Configs.DATA_XPATH);
|
||||||
|
var cardDetail = reader.Read();
|
||||||
|
|
||||||
|
if (cardDetail is null)
|
||||||
|
{
|
||||||
|
throw new HttpRequestException("Write object is null");
|
||||||
|
}
|
||||||
|
|
||||||
|
cardDetail.SetCardId(cardId);
|
||||||
|
cardDetail.LastPlayTime = DateTime.Now;
|
||||||
|
var rowsAffected = cardSqLiteConnection.InsertOrReplace(cardDetail);
|
||||||
|
if (rowsAffected == 0)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("Update database failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
"Updated card detail".Info();
|
||||||
|
}
|
||||||
|
private void UnlockSongs(long cardId)
|
||||||
|
{
|
||||||
|
var unlockableSongIds = Configs.SETTINGS.UnlockableSongIds;
|
||||||
|
|
||||||
|
if (unlockableSongIds is null)
|
||||||
|
{
|
||||||
|
unlockableSongIds = Configs.DEFAULT_UNLOCKABLE_SONGS;
|
||||||
|
}
|
||||||
|
var detailList = unlockableSongIds.Select(id => new CardDetail
|
||||||
|
{
|
||||||
|
CardId = cardId,
|
||||||
|
Pcol1 = 10,
|
||||||
|
Pcol2 = id,
|
||||||
|
Pcol3 = 0,
|
||||||
|
ScoreUi2 = 1,
|
||||||
|
ScoreUi6 = 1,
|
||||||
|
LastPlayTime = DateTime.Now
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
cardSqLiteConnection.InsertOrIgnoreAll(detailList);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -612,7 +633,8 @@ public class CardServiceController : WebApiController
|
|||||||
|
|
||||||
private enum Command
|
private enum Command
|
||||||
{
|
{
|
||||||
CardRequest = 256,
|
CardReadRequest = 256,
|
||||||
|
CardWriteRequest = 768,
|
||||||
RegisterRequest = 512,
|
RegisterRequest = 512,
|
||||||
ReissueRequest = 1536
|
ReissueRequest = 1536
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,10 @@ public class CardDetail : Record, ICardIdModel
|
|||||||
[XmlElement("fcol3")]
|
[XmlElement("fcol3")]
|
||||||
public int Fcol3 { get; set; }
|
public int Fcol3 { get; set; }
|
||||||
|
|
||||||
|
[Column("last_play_time")]
|
||||||
|
[XmlIgnore]
|
||||||
|
public DateTime LastPlayTime { get; set; } = DateTime.MinValue;
|
||||||
|
|
||||||
public void SetCardId(long cardId)
|
public void SetCardId(long cardId)
|
||||||
{
|
{
|
||||||
CardId = cardId;
|
CardId = cardId;
|
||||||
|
@ -36,5 +36,9 @@
|
|||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Utils" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
@ -1,209 +1,206 @@
|
|||||||
@page "/user/{CardId:long}"
|
@page "/user/{CardId:long}"
|
||||||
@using SharedProject.models
|
@using SharedProject.models
|
||||||
@using SharedProject.enums
|
@using SharedProject.enums
|
||||||
@using SharedProject.common
|
|
||||||
@inject HttpClient Client
|
|
||||||
@inject IDialogService DialogService
|
|
||||||
@inject ILogger<User> Logger
|
|
||||||
|
|
||||||
<PageTitle>User</PageTitle>
|
<PageTitle>User</PageTitle>
|
||||||
<MudContainer>
|
<MudContainer>
|
||||||
@if (userDetail == null)
|
@if (pageLoading)
|
||||||
{
|
{
|
||||||
<MudSkeleton Width="1184px" Height="57px"/>
|
<MudSkeleton Width="1184px" Height="57px"/>
|
||||||
<MudSkeleton Width="1184px" Height="57px"/>
|
<MudSkeleton Width="1184px" Height="57px"/>
|
||||||
<MudSkeleton Width="1184px" Height="57px"/>
|
<MudSkeleton Width="1184px" Height="57px"/>
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
<MudExpansionPanels>
|
if (userDetail is null)
|
||||||
<MudExpansionPanel Text="Total Result">
|
{
|
||||||
<MudList>
|
<MudText Typo="Typo.h3">No Data</MudText>
|
||||||
<MudListSubheader>Player Name: @userDetail.PlayerName</MudListSubheader>
|
}
|
||||||
<MudListItem>Total Score: @userDetail.TotalScore</MudListItem>
|
else
|
||||||
<MudListItem>Average Score: @userDetail.AverageScore</MudListItem>
|
{
|
||||||
<MudListItem>Played Song Count: @userDetail.PlayedSongCount / @userDetail.TotalSongCount</MudListItem>
|
<MudExpansionPanels>
|
||||||
<MudListItem>Cleared Stage Count: @userDetail.ClearedStageCount / @userDetail.TotalStageCount</MudListItem>
|
<MudExpansionPanel Text="Total Result">
|
||||||
<MudListItem>No Miss Stage Count: @userDetail.NoMissStageCount / @userDetail.TotalStageCount</MudListItem>
|
<MudList>
|
||||||
<MudListItem>Full Chain Stage Count: @userDetail.FullChainStageCount / @userDetail.TotalStageCount</MudListItem>
|
<MudListSubheader>Player Name: @userDetail.PlayerName</MudListSubheader>
|
||||||
<MudListItem>Perfect Stage Count: @userDetail.PerfectStageCount / @userDetail.TotalStageCount</MudListItem>
|
<MudListItem>Total Score: @userDetail.TotalScore</MudListItem>
|
||||||
<MudListItem>S and Above Stage Count: @userDetail.SAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
<MudListItem>Average Score: @userDetail.AverageScore</MudListItem>
|
||||||
<MudListItem>S+ and Above Stage Count: @userDetail.SPlusAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
<MudListItem>Played Song Count: @userDetail.PlayedSongCount / @userDetail.TotalSongCount</MudListItem>
|
||||||
<MudListItem>S++ and Above Stage Count: @userDetail.SPlusPlusAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
<MudListItem>Cleared Stage Count: @userDetail.ClearedStageCount / @userDetail.TotalStageCount</MudListItem>
|
||||||
</MudList>
|
<MudListItem>No Miss Stage Count: @userDetail.NoMissStageCount / @userDetail.TotalStageCount</MudListItem>
|
||||||
</MudExpansionPanel>
|
<MudListItem>Full Chain Stage Count: @userDetail.FullChainStageCount / @userDetail.TotalStageCount</MudListItem>
|
||||||
<MudExpansionPanel Text="PlayOptions">
|
<MudListItem>Perfect Stage Count: @userDetail.PerfectStageCount / @userDetail.TotalStageCount</MudListItem>
|
||||||
<MudSelect @bind-Value="@fastSlowIndicator" Label="FAST/SLOW show setting">
|
<MudListItem>S and Above Stage Count: @userDetail.SAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
||||||
@foreach (var item in Enum.GetValues<PlayOptions.FastSlowIndicator>())
|
<MudListItem>S+ and Above Stage Count: @userDetail.SPlusAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
||||||
{
|
<MudListItem>S++ and Above Stage Count: @userDetail.SPlusPlusAboveStageCount / @userDetail.TotalStageCount</MudListItem>
|
||||||
<MudSelectItem Value="@item">@item.GetHelpText()</MudSelectItem>
|
</MudList>
|
||||||
}
|
</MudExpansionPanel>
|
||||||
</MudSelect>
|
<MudExpansionPanel Text="PlayOptions">
|
||||||
|
<MudSelect @bind-Value="@playOption.FastSlowIndicator"
|
||||||
|
Label="FAST/SLOW show setting">
|
||||||
|
@foreach (var item in Enum.GetValues<PlayOptions.FastSlowIndicator>())
|
||||||
|
{
|
||||||
|
<MudSelectItem Value="@item">@item.GetHelpText()</MudSelectItem>
|
||||||
|
}
|
||||||
|
</MudSelect>
|
||||||
|
|
||||||
<MudSelect @bind-Value="@feverTranceShow" Label="FEVER/TRANCE show setting">
|
<MudSelect @bind-Value="@playOption.FeverTrance"
|
||||||
@foreach (var item in Enum.GetValues<PlayOptions.FeverTranceShow>())
|
Label="FEVER/TRANCE show setting">
|
||||||
{
|
@foreach (var item in Enum.GetValues<PlayOptions.FeverTranceShow>())
|
||||||
<MudSelectItem Value="@item">@item.GetHelpText()</MudSelectItem>
|
{
|
||||||
}
|
<MudSelectItem Value="@item">@item.GetHelpText()</MudSelectItem>
|
||||||
</MudSelect>
|
}
|
||||||
|
</MudSelect>
|
||||||
|
|
||||||
<MudButton Disabled="@isSavingOptions" OnClick="SaveOptions" Variant="Variant.Filled" Color="Color.Info">
|
<MudAutocomplete T="long" Label="Avatar setting"
|
||||||
@if (isSavingOptions)
|
@bind-Value="@playOption.AvatarId"
|
||||||
{
|
CoerceText="true" SearchFunc="@SearchAvatar"
|
||||||
<MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true"/>
|
ToStringFunc="@AvatarIdToString"
|
||||||
<MudText Class="ms-2">Saving...</MudText>
|
Dense="true"
|
||||||
}
|
MaxItems="@avatarMaxItems">
|
||||||
else
|
<MoreItemsTemplate>
|
||||||
{
|
@*<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true"
|
||||||
<MudIcon Icon="@Icons.Filled.Save"></MudIcon>
|
OnClick="() => { avatarMaxItems += 10; AvatarAutoComplete.Clear();}">
|
||||||
<MudText>Save</MudText>
|
Load more options
|
||||||
}
|
</MudButton>*@
|
||||||
</MudButton>
|
<MudText Align="Align.Center">
|
||||||
</MudExpansionPanel>
|
Only first 50 items are displayed
|
||||||
<MudExpansionPanel Text="SongPlayData">
|
</MudText>
|
||||||
<MudDataGrid T="SongPlayData" Items="@songPlayDataList" Sortable="true" Filterable="true">
|
</MoreItemsTemplate>
|
||||||
<ToolBarContent>
|
</MudAutocomplete>
|
||||||
<MudText Typo="Typo.h6">Played Songs</MudText>
|
|
||||||
</ToolBarContent>
|
<MudAutocomplete T="long" Label="Navigator setting"
|
||||||
<Columns>
|
@bind-Value="@playOption.NavigatorId"
|
||||||
<Column T="SongPlayData" Sortable="false" Filterable="false">
|
CoerceText="true" SearchFunc="@SearchNavigator"
|
||||||
<CellTemplate>
|
ToStringFunc="@NavigatorIdToString"
|
||||||
<MudButton Variant="Variant.Outlined" Size="Size.Small"
|
Dense="true"
|
||||||
OnClick="@(() => OnShowDetailsClick(context.Item))">
|
MaxItems="@avatarMaxItems">
|
||||||
@(context.Item.ShowDetails ? "Hide" : "Show") Song Play Details
|
<MoreItemsTemplate>
|
||||||
</MudButton>
|
@*<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true"
|
||||||
</CellTemplate>
|
OnClick="() => { avatarMaxItems += 10; AvatarAutoComplete.Clear();}">
|
||||||
</Column>
|
Load more options
|
||||||
<Column T="SongPlayData" Field="IsFavorite" Sortable="false" Title="Favorite">
|
</MudButton>*@
|
||||||
<CellTemplate>
|
<MudText Align="Align.Center">
|
||||||
<MudToggleIconButton Toggled="@context.Item.IsFavorite"
|
Only first 50 items are displayed
|
||||||
ToggledChanged="@(()=>OnFavoriteToggled(context.Item))"
|
</MudText>
|
||||||
Icon="@Icons.Material.Filled.FavoriteBorder" Color="@Color.Secondary" Title="Add to favorite"
|
</MoreItemsTemplate>
|
||||||
ToggledIcon="@Icons.Material.Filled.Favorite" ToggledColor="@Color.Secondary" ToggledTitle="Remove from favorite"/>
|
</MudAutocomplete>
|
||||||
</CellTemplate>
|
|
||||||
</Column>
|
<MudAutocomplete T="long" Label="Title setting"
|
||||||
<Column T="SongPlayData" Field="Title" Title="Song Title"/>
|
@bind-Value="@playOption.TitleId"
|
||||||
<Column T="SongPlayData" Field="Artist" Title="Artist"/>
|
CoerceText="true" SearchFunc="@SearchTitle"
|
||||||
<Column T="SongPlayData" Field="TotalPlayCount" Title="Total Play Count" />
|
ToStringFunc="@TitleIdToString"
|
||||||
</Columns>
|
Dense="true"
|
||||||
<ChildRowContent>
|
MaxItems="@avatarMaxItems">
|
||||||
@if (context.ShowDetails)
|
<MoreItemsTemplate>
|
||||||
{
|
@*<MudButton Variant="Variant.Filled" Color="Color.Primary" FullWidth="true"
|
||||||
<MudTr>
|
OnClick="() => { avatarMaxItems += 10; AvatarAutoComplete.Clear();}">
|
||||||
<td colspan="5">
|
Load more options
|
||||||
<MudCard Elevation="0">
|
</MudButton>*@
|
||||||
<MudCardHeader>
|
<MudText Align="Align.Center">
|
||||||
<CardHeaderContent>
|
Only first 50 items are displayed
|
||||||
<MudText Typo="Typo.body1">Song Play Details</MudText>
|
</MudText>
|
||||||
</CardHeaderContent>
|
</MoreItemsTemplate>
|
||||||
</MudCardHeader>
|
</MudAutocomplete>
|
||||||
<MudCardContent Class="pa-0">
|
|
||||||
<MudTable Items="@context.SongPlaySubDataList" Context="SongPlayDetail" Elevation="0" Filter="data => data.ClearState != ClearState.NotPlayed">
|
<MudButton Disabled="@isSavingOptions"
|
||||||
<HeaderContent>
|
OnClick="SaveOptions"
|
||||||
<MudTh>Difficulty</MudTh>
|
Variant="Variant.Filled"
|
||||||
<MudTh>Clear State</MudTh>
|
Color="Color.Info">
|
||||||
<MudTh>Play Count</MudTh>
|
@if (isSavingOptions)
|
||||||
<MudTh>Rating</MudTh>
|
{
|
||||||
<MudTh>Score</MudTh>
|
<MudProgressCircular Class="ms-n1" Size="Size.Small" Indeterminate="true"/>
|
||||||
<MudTh>Max Chain</MudTh>
|
<MudText Class="ms-2">Saving...</MudText>
|
||||||
</HeaderContent>
|
}
|
||||||
<RowTemplate>
|
else
|
||||||
<MudTd DataLabel="Difficulty">@SongPlayDetail.Difficulty</MudTd>
|
{
|
||||||
<MudTd DataLabel="Clear State">
|
<MudIcon Icon="@Icons.Filled.Save"></MudIcon>
|
||||||
@(SongPlayDetail.Score != 1000000 ? SongPlayDetail.ClearState : ClearState.Perfect)
|
<MudText>Save</MudText>
|
||||||
</MudTd>
|
}
|
||||||
<MudTd DataLabel="Play Count">@SongPlayDetail.PlayCount</MudTd>
|
</MudButton>
|
||||||
<MudTd DataLabel="Rating">@CalculateRating(SongPlayDetail.Score)</MudTd>
|
</MudExpansionPanel>
|
||||||
<MudTd DataLabel="Score">@SongPlayDetail.Score</MudTd>
|
<MudExpansionPanel Text="SongPlayData">
|
||||||
<MudTd DataLabel="Max Chain">@SongPlayDetail.MaxChain</MudTd>
|
<MudDataGrid T="SongPlayData"
|
||||||
</RowTemplate>
|
Items="@songPlayDataList"
|
||||||
</MudTable>
|
Sortable="true"
|
||||||
</MudCardContent>
|
Filterable="true">
|
||||||
</MudCard>
|
<ToolBarContent>
|
||||||
</td>
|
<MudText Typo="Typo.h6">Played Songs</MudText>
|
||||||
</MudTr>
|
</ToolBarContent>
|
||||||
}
|
<Columns>
|
||||||
</ChildRowContent>
|
<Column T="SongPlayData" Sortable="false" Filterable="false">
|
||||||
<PagerContent>
|
<CellTemplate>
|
||||||
<MudDataGridPager T="SongPlayData"/>
|
<MudButton Variant="Variant.Outlined" Size="Size.Small"
|
||||||
</PagerContent>
|
OnClick="@(() => OnShowDetailsClick(context.Item))">
|
||||||
</MudDataGrid>
|
@(context.Item.ShowDetails ? "Hide" : "Show") Song Play Details
|
||||||
</MudExpansionPanel>
|
</MudButton>
|
||||||
</MudExpansionPanels>
|
</CellTemplate>
|
||||||
}
|
</Column>
|
||||||
|
<Column T="SongPlayData" Field="IsFavorite" Sortable="false" Title="Favorite">
|
||||||
|
<CellTemplate>
|
||||||
|
<MudToggleIconButton Toggled="@context.Item.IsFavorite"
|
||||||
|
ToggledChanged="@(() => OnFavoriteToggled(context.Item))"
|
||||||
|
Icon="@Icons.Material.Filled.FavoriteBorder"
|
||||||
|
Color="@Color.Secondary"
|
||||||
|
Title="Add to favorite"
|
||||||
|
ToggledIcon="@Icons.Material.Filled.Favorite"
|
||||||
|
ToggledColor="@Color.Secondary"
|
||||||
|
ToggledTitle="Remove from favorite"/>
|
||||||
|
</CellTemplate>
|
||||||
|
</Column>
|
||||||
|
<Column T="SongPlayData" Field="Title" Title="Song Title"/>
|
||||||
|
<Column T="SongPlayData" Field="Artist" Title="Artist"/>
|
||||||
|
<Column T="SongPlayData" Field="TotalPlayCount" Title="Total Play Count"/>
|
||||||
|
<Column T="SongPlayData" Field="LastPlayTime" Title="Last Play Time"/>
|
||||||
|
</Columns>
|
||||||
|
<ChildRowContent>
|
||||||
|
@if (context.ShowDetails)
|
||||||
|
{
|
||||||
|
<MudTr>
|
||||||
|
<td colspan="5">
|
||||||
|
<MudCard Elevation="0">
|
||||||
|
<MudCardHeader>
|
||||||
|
<CardHeaderContent>
|
||||||
|
<MudText Typo="Typo.body1">Song Play Details</MudText>
|
||||||
|
</CardHeaderContent>
|
||||||
|
</MudCardHeader>
|
||||||
|
<MudCardContent Class="pa-0">
|
||||||
|
<MudTable Items="@context.SongPlaySubDataList"
|
||||||
|
Context="SongPlayDetail"
|
||||||
|
Elevation="0"
|
||||||
|
Filter="data => data.ClearState != ClearState.NotPlayed">
|
||||||
|
<HeaderContent>
|
||||||
|
<MudTh>Difficulty</MudTh>
|
||||||
|
<MudTh>Clear State</MudTh>
|
||||||
|
<MudTh>Play Count</MudTh>
|
||||||
|
<MudTh>Rating</MudTh>
|
||||||
|
<MudTh>Score</MudTh>
|
||||||
|
<MudTh>Max Chain</MudTh>
|
||||||
|
<MudTh>Last Play Time</MudTh>
|
||||||
|
</HeaderContent>
|
||||||
|
<RowTemplate>
|
||||||
|
<MudTd DataLabel="Difficulty">@SongPlayDetail.Difficulty</MudTd>
|
||||||
|
<MudTd DataLabel="Clear State">
|
||||||
|
@(SongPlayDetail.Score != 1000000 ? SongPlayDetail.ClearState : ClearState.Perfect)
|
||||||
|
</MudTd>
|
||||||
|
<MudTd DataLabel="Play Count">@SongPlayDetail.PlayCount</MudTd>
|
||||||
|
<MudTd DataLabel="Rating">@CalculateRating(SongPlayDetail.Score)</MudTd>
|
||||||
|
<MudTd DataLabel="Score">@SongPlayDetail.Score</MudTd>
|
||||||
|
<MudTd DataLabel="Max Chain">@SongPlayDetail.MaxChain</MudTd>
|
||||||
|
<MudTd DataLabel="Last Play Time">@SongPlayDetail.LastPlayTime</MudTd>
|
||||||
|
</RowTemplate>
|
||||||
|
</MudTable>
|
||||||
|
</MudCardContent>
|
||||||
|
</MudCard>
|
||||||
|
</td>
|
||||||
|
</MudTr>
|
||||||
|
}
|
||||||
|
</ChildRowContent>
|
||||||
|
<PagerContent>
|
||||||
|
<MudDataGridPager T="SongPlayData"/>
|
||||||
|
</PagerContent>
|
||||||
|
</MudDataGrid>
|
||||||
|
</MudExpansionPanel>
|
||||||
|
</MudExpansionPanels>
|
||||||
|
}
|
||||||
|
}
|
||||||
</MudContainer>
|
</MudContainer>
|
||||||
|
|
||||||
@code {
|
|
||||||
|
|
||||||
[Parameter]
|
|
||||||
public long CardId { get; set; }
|
|
||||||
|
|
||||||
private PlayOptions.FeverTranceShow feverTranceShow;
|
|
||||||
|
|
||||||
private PlayOptions.FastSlowIndicator fastSlowIndicator;
|
|
||||||
|
|
||||||
private UserDetail? userDetail;
|
|
||||||
|
|
||||||
private List<SongPlayData> songPlayDataList = new();
|
|
||||||
|
|
||||||
private bool isSavingOptions;
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
|
||||||
{
|
|
||||||
await base.OnInitializedAsync();
|
|
||||||
userDetail = await Client.GetFromJsonAsync<UserDetail>($"api/UserDetail/{CardId}") ?? new();
|
|
||||||
songPlayDataList = userDetail.SongPlayDataList ?? new List<SongPlayData>();
|
|
||||||
feverTranceShow = userDetail.PlayOption.FeverTrance;
|
|
||||||
fastSlowIndicator = userDetail.PlayOption.FastSlowIndicator;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnShowDetailsClick(SongPlayData data)
|
|
||||||
{
|
|
||||||
data.ShowDetails = !data.ShowDetails;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SaveOptions()
|
|
||||||
{
|
|
||||||
isSavingOptions = true;
|
|
||||||
var postData = new PlayOption
|
|
||||||
{
|
|
||||||
CardId = CardId,
|
|
||||||
FastSlowIndicator = fastSlowIndicator,
|
|
||||||
FeverTrance = feverTranceShow
|
|
||||||
};
|
|
||||||
var result = await Client.PostAsJsonAsync("api/UserDetail/SetPlayOption", postData);
|
|
||||||
isSavingOptions = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string CalculateRating(int score)
|
|
||||||
{
|
|
||||||
var grade = SharedConstants.GRADES.Where(g => g.Score <= score).Select(g => g.Grade).Last();
|
|
||||||
return grade;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task OnFavoriteToggled(SongPlayData data)
|
|
||||||
{
|
|
||||||
var options = new DialogOptions
|
|
||||||
{
|
|
||||||
CloseOnEscapeKey = false,
|
|
||||||
DisableBackdropClick = true,
|
|
||||||
FullWidth = true
|
|
||||||
};
|
|
||||||
var parameters = new DialogParameters();
|
|
||||||
parameters.Add("Data", data);
|
|
||||||
parameters.Add("CardId", CardId);
|
|
||||||
var dialog = DialogService.Show<FavoriteDialog>("Favorite", parameters, options);
|
|
||||||
var result = await dialog.Result;
|
|
||||||
|
|
||||||
if (result.Cancelled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((bool)result.Data)
|
|
||||||
{
|
|
||||||
Logger.LogInformation("Changed!");
|
|
||||||
data.IsFavorite = !data.IsFavorite;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
163
MudAdmin/Pages/User.razor.cs
Normal file
163
MudAdmin/Pages/User.razor.cs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
using System.Net.Http.Json;
|
||||||
|
using Microsoft.AspNetCore.Components;
|
||||||
|
using MudBlazor;
|
||||||
|
using SharedProject.common;
|
||||||
|
using SharedProject.models;
|
||||||
|
|
||||||
|
namespace MudAdmin.Pages;
|
||||||
|
|
||||||
|
public partial class User
|
||||||
|
{
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public HttpClient Client { get; set; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public IDialogService DialogService { get; set; } = null!;
|
||||||
|
|
||||||
|
[Inject]
|
||||||
|
public ILogger<User> Logger { get; set; } = null!;
|
||||||
|
|
||||||
|
[Parameter]
|
||||||
|
public long CardId { get; set; }
|
||||||
|
|
||||||
|
private PlayOption playOption = new();
|
||||||
|
|
||||||
|
private UserDetail? userDetail;
|
||||||
|
|
||||||
|
private List<SongPlayData> songPlayDataList = new();
|
||||||
|
|
||||||
|
private Dictionary<long, Navigator> navigatorDictionary = new();
|
||||||
|
|
||||||
|
private Dictionary<long, Title> titleDictionary = new();
|
||||||
|
|
||||||
|
private Dictionary<long, Avatar> avatarDictionary = new();
|
||||||
|
|
||||||
|
private bool isSavingOptions;
|
||||||
|
|
||||||
|
private int avatarMaxItems = 50;
|
||||||
|
|
||||||
|
private bool pageLoading = true;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await base.OnInitializedAsync();
|
||||||
|
userDetail = await Client.GetFromJsonAsync<UserDetail>($"api/UserDetail/{CardId}");
|
||||||
|
if (userDetail is null)
|
||||||
|
{
|
||||||
|
pageLoading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
songPlayDataList = userDetail.SongPlayDataList ?? new List<SongPlayData>();
|
||||||
|
playOption = userDetail.PlayOption;
|
||||||
|
|
||||||
|
var navigators = await Client.GetFromJsonAsync<Navigators>("data/navigator.json");
|
||||||
|
if (navigators?.NavigatorList != null)
|
||||||
|
{
|
||||||
|
this.navigatorDictionary = navigators.NavigatorList.ToDictionary(navigator => (long)navigator.Id);
|
||||||
|
}
|
||||||
|
var avatars = await Client.GetFromJsonAsync<Avatar[]>("data/avatar.json");
|
||||||
|
if (avatars != null)
|
||||||
|
{
|
||||||
|
this.avatarDictionary = avatars.ToDictionary(avatar => (long)avatar.Id);
|
||||||
|
}
|
||||||
|
var titles = await Client.GetFromJsonAsync<Title[]>("data/title.json");
|
||||||
|
if (titles != null)
|
||||||
|
{
|
||||||
|
this.titleDictionary = titles.ToDictionary(title => (long)title.Id);
|
||||||
|
}
|
||||||
|
pageLoading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnShowDetailsClick(SongPlayData data)
|
||||||
|
{
|
||||||
|
data.ShowDetails = !data.ShowDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task SaveOptions()
|
||||||
|
{
|
||||||
|
isSavingOptions = true;
|
||||||
|
var postData = new PlayOption
|
||||||
|
{
|
||||||
|
CardId = CardId,
|
||||||
|
FastSlowIndicator = playOption.FastSlowIndicator,
|
||||||
|
FeverTrance = playOption.FeverTrance,
|
||||||
|
AvatarId = playOption.AvatarId,
|
||||||
|
NavigatorId = playOption.NavigatorId,
|
||||||
|
TitleId = playOption.TitleId
|
||||||
|
};
|
||||||
|
var result = await Client.PostAsJsonAsync("api/UserDetail/SetPlayOption", postData);
|
||||||
|
isSavingOptions = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CalculateRating(int score)
|
||||||
|
{
|
||||||
|
var grade = SharedConstants.GRADES.Where(g => g.Score <= score).Select(g => g.Grade).Last();
|
||||||
|
return grade;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnFavoriteToggled(SongPlayData data)
|
||||||
|
{
|
||||||
|
var options = new DialogOptions
|
||||||
|
{
|
||||||
|
CloseOnEscapeKey = false,
|
||||||
|
DisableBackdropClick = true,
|
||||||
|
FullWidth = true
|
||||||
|
};
|
||||||
|
var parameters = new DialogParameters();
|
||||||
|
parameters.Add("Data", data);
|
||||||
|
parameters.Add("CardId", CardId);
|
||||||
|
var dialog = DialogService.Show<FavoriteDialog>("Favorite", parameters, options);
|
||||||
|
var result = await dialog.Result;
|
||||||
|
|
||||||
|
if (result.Cancelled)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((bool)result.Data)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Changed!");
|
||||||
|
data.IsFavorite = !data.IsFavorite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<IEnumerable<long>> SearchAvatar(string value)
|
||||||
|
{
|
||||||
|
var result = string.IsNullOrEmpty(value) ?
|
||||||
|
avatarDictionary.Keys :
|
||||||
|
avatarDictionary.Where(pair => pair.Value.ToString().Contains(value, StringComparison.InvariantCultureIgnoreCase)).Select(pair => pair.Key);
|
||||||
|
return Task.FromResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<IEnumerable<long>> SearchTitle(string value)
|
||||||
|
{
|
||||||
|
var result = string.IsNullOrEmpty(value) ?
|
||||||
|
titleDictionary.Keys :
|
||||||
|
titleDictionary.Where(pair => pair.Value.ToString().Contains(value, StringComparison.InvariantCultureIgnoreCase)).Select(pair => pair.Key);
|
||||||
|
return Task.FromResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task<IEnumerable<long>> SearchNavigator(string value)
|
||||||
|
{
|
||||||
|
var result = string.IsNullOrEmpty(value) ?
|
||||||
|
navigatorDictionary.Keys :
|
||||||
|
navigatorDictionary.Where(pair => pair.Value.ToString().Contains(value, StringComparison.InvariantCultureIgnoreCase)).Select(pair => pair.Key);
|
||||||
|
return Task.FromResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private string AvatarIdToString(long id)
|
||||||
|
{
|
||||||
|
return avatarDictionary.ContainsKey(id) ? avatarDictionary[id].ToString() : $"No Data for {id}!";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string NavigatorIdToString(long id)
|
||||||
|
{
|
||||||
|
return navigatorDictionary.ContainsKey(id) ? navigatorDictionary[id].ToString() : $"No Data for {id}!";
|
||||||
|
}
|
||||||
|
|
||||||
|
private string TitleIdToString(long id)
|
||||||
|
{
|
||||||
|
return titleDictionary.ContainsKey(id) ? titleDictionary[id].ToString() : $"No Data for {id}!";
|
||||||
|
}
|
||||||
|
}
|
@ -30,7 +30,7 @@
|
|||||||
}
|
}
|
||||||
</MudGrid>
|
</MudGrid>
|
||||||
}
|
}
|
||||||
else if (!(users.Count == 0))
|
else if (users.Count != 0)
|
||||||
{
|
{
|
||||||
<MudGrid>
|
<MudGrid>
|
||||||
@foreach (var user in users)
|
@foreach (var user in users)
|
||||||
|
@ -1,105 +0,0 @@
|
|||||||
using SharedProject.models;
|
|
||||||
using GenFu;
|
|
||||||
using SharedProject.enums;
|
|
||||||
|
|
||||||
namespace MudAdmin.Utils;
|
|
||||||
|
|
||||||
public class MockDataRepo
|
|
||||||
{
|
|
||||||
private static readonly MockDataRepo INSTANCE = new MockDataRepo();
|
|
||||||
|
|
||||||
public List<User> Users { get; }
|
|
||||||
|
|
||||||
public List<UserDetail> UserDetails { get; private set; } = null!;
|
|
||||||
|
|
||||||
public List<SongPlayData> SongPlayDataList { get; private set; } = null!;
|
|
||||||
|
|
||||||
private MockDataRepo()
|
|
||||||
{
|
|
||||||
ConfigureGenFu();
|
|
||||||
Users = GenFu.GenFu.ListOf<User>(10);
|
|
||||||
GenerateUserDetails();
|
|
||||||
GenerateSongPlayData();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GenerateSongPlayData()
|
|
||||||
{
|
|
||||||
SongPlayDataList = GenFu.GenFu.ListOf<SongPlayData>();
|
|
||||||
|
|
||||||
foreach (var songPlayData in SongPlayDataList)
|
|
||||||
{
|
|
||||||
var subDataList = new List<SongPlayDetailData>();
|
|
||||||
var random = new Random();
|
|
||||||
|
|
||||||
foreach (var difficulty in Enum.GetValues<Difficulty>())
|
|
||||||
{
|
|
||||||
if (random.Next() <= int.MaxValue / 2)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var subData = GenFu.GenFu.New<SongPlayDetailData>();
|
|
||||||
subData.Difficulty = difficulty;
|
|
||||||
|
|
||||||
if (subData.ClearState == ClearState.Perfect)
|
|
||||||
{
|
|
||||||
subData.ClearState = ClearState.FullChain;
|
|
||||||
}
|
|
||||||
subDataList.Add(subData);
|
|
||||||
}
|
|
||||||
|
|
||||||
songPlayData.SongPlaySubDataList = subDataList.ToArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GenerateUserDetails()
|
|
||||||
{
|
|
||||||
UserDetails = new List<UserDetail>();
|
|
||||||
|
|
||||||
foreach (var user in Users)
|
|
||||||
{
|
|
||||||
var detail = GenFu.GenFu.New<UserDetail>();
|
|
||||||
detail.CardId = user.CardId;
|
|
||||||
detail.PlayerName = user.PlayerName;
|
|
||||||
detail.PlayOption = new PlayOption
|
|
||||||
{
|
|
||||||
CardId = user.CardId,
|
|
||||||
FeverTrance = PlayOptions.FeverTranceShow.Show,
|
|
||||||
FastSlowIndicator = PlayOptions.FastSlowIndicator.NotUsed
|
|
||||||
};
|
|
||||||
detail.AverageScore = 900000;
|
|
||||||
detail.TotalScore = 10000000;
|
|
||||||
detail.TotalSongCount = 123;
|
|
||||||
detail.TotalStageCount = 390;
|
|
||||||
UserDetails.Add(detail);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static MockDataRepo GetMockDataRepo()
|
|
||||||
{
|
|
||||||
return INSTANCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ConfigureGenFu()
|
|
||||||
{
|
|
||||||
GenFu.GenFu.Configure<User>()
|
|
||||||
.Fill(user => user.CardId, () => new Random().NextInt64(7000000000000000, 8000000000000000));
|
|
||||||
|
|
||||||
GenFu.GenFu.Configure<UserDetail>()
|
|
||||||
.Fill(detail => detail.PlayedSongCount).WithinRange(100, 123)
|
|
||||||
.Fill(detail => detail.ClearedStageCount).WithinRange(300, 390)
|
|
||||||
.Fill(detail => detail.NoMissStageCount).WithinRange(200, 300)
|
|
||||||
.Fill(detail => detail.FullChainStageCount).WithinRange(100, 200)
|
|
||||||
.Fill(detail => detail.PerfectStageCount).WithinRange(0, 100)
|
|
||||||
.Fill(detail => detail.SAboveStageCount).WithinRange(200, 300)
|
|
||||||
.Fill(detail => detail.SPlusAboveStageCount).WithinRange(100, 200)
|
|
||||||
.Fill(detail => detail.SPlusPlusAboveStageCount).WithinRange(0, 100);
|
|
||||||
|
|
||||||
GenFu.GenFu.Configure<SongPlayDetailData>()
|
|
||||||
.Fill(data => data.Score).WithinRange(0, 1000001);
|
|
||||||
GenFu.GenFu.Configure<SongPlayData>()
|
|
||||||
.Fill(data => data.ShowDetails, false);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
2850
MudAdmin/wwwroot/data/avatar.json
Normal file
2850
MudAdmin/wwwroot/data/avatar.json
Normal file
File diff suppressed because it is too large
Load Diff
2483
MudAdmin/wwwroot/data/navigator.json
Normal file
2483
MudAdmin/wwwroot/data/navigator.json
Normal file
File diff suppressed because it is too large
Load Diff
49772
MudAdmin/wwwroot/data/title.json
Normal file
49772
MudAdmin/wwwroot/data/title.json
Normal file
File diff suppressed because it is too large
Load Diff
8
SharedProject/enums/NavigatorDefaultAvailability.cs
Normal file
8
SharedProject/enums/NavigatorDefaultAvailability.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace SharedProject.enums;
|
||||||
|
|
||||||
|
public enum NavigatorDefaultAvailability
|
||||||
|
{
|
||||||
|
NotAvailable = 0,
|
||||||
|
Available = 1,
|
||||||
|
AvailableWithVoice = 2,
|
||||||
|
}
|
11
SharedProject/enums/NavigatorGenre.cs
Normal file
11
SharedProject/enums/NavigatorGenre.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace SharedProject.enums;
|
||||||
|
|
||||||
|
public enum NavigatorGenre
|
||||||
|
{
|
||||||
|
Default = 1,
|
||||||
|
Original = 2,
|
||||||
|
Game = 3,
|
||||||
|
Touhou = 4,
|
||||||
|
Vocaloid = 5,
|
||||||
|
Collab = 6,
|
||||||
|
}
|
36
SharedProject/enums/TitleUnlockType.cs
Normal file
36
SharedProject/enums/TitleUnlockType.cs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
namespace SharedProject.enums;
|
||||||
|
|
||||||
|
public enum TitleUnlockType
|
||||||
|
{
|
||||||
|
Invalid = 0,
|
||||||
|
Default = 1,
|
||||||
|
Clear = 2,
|
||||||
|
NoMiss = 3,
|
||||||
|
FullChain = 4,
|
||||||
|
SRankSimpleStages = 5,
|
||||||
|
SRankNormalStages = 6,
|
||||||
|
SRankHardStages = 7,
|
||||||
|
SRankExtraStages = 8,
|
||||||
|
SRankAllDifficulties = 9,
|
||||||
|
SPlusRankAllDifficulties = 10,
|
||||||
|
SPlusPlusRankAllDifficulties = 11,
|
||||||
|
Event = 12,
|
||||||
|
Prefecture = 13,
|
||||||
|
ChainMilestone = 14,
|
||||||
|
Adlibs = 15,
|
||||||
|
ConsecutiveNoMiss = 16,
|
||||||
|
ClearsUsingItems = 17,
|
||||||
|
Avatars = 18,
|
||||||
|
MultiplayerStarsTotal = 19,
|
||||||
|
SongSet20 = 20,
|
||||||
|
SongSet21 = 21,
|
||||||
|
SongSet22 = 22,
|
||||||
|
SongSet23 = 23,
|
||||||
|
SongSet24 = 24,
|
||||||
|
SongSet25 = 25,
|
||||||
|
SongSet26 = 26,
|
||||||
|
ProfileLevel = 27,
|
||||||
|
Perfect = 28,
|
||||||
|
OnlineMatching = 29,
|
||||||
|
Trophies = 30,
|
||||||
|
}
|
15
SharedProject/models/Avatar.cs
Normal file
15
SharedProject/models/Avatar.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace SharedProject.models;
|
||||||
|
|
||||||
|
public class Avatar
|
||||||
|
{
|
||||||
|
public uint Id { get; set; }
|
||||||
|
public string? IdString { get; set; }
|
||||||
|
public string? FullName { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Variant { get; set; }
|
||||||
|
public string? AcquireMethod { get; set; }
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
return $"{Id}: {FullName}, {AcquireMethod}";
|
||||||
|
}
|
||||||
|
}
|
12
SharedProject/models/NameEntry.cs
Normal file
12
SharedProject/models/NameEntry.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
namespace SharedProject.models;
|
||||||
|
|
||||||
|
public class NameEntry
|
||||||
|
{
|
||||||
|
public string? NameWithVariant { get; set; }
|
||||||
|
public string? NameWithoutVariant{ get; set; }
|
||||||
|
public string? Variant{ get; set; }
|
||||||
|
public string? IllustrationCredit{ get; set; }
|
||||||
|
public override string ToString() {
|
||||||
|
return $"{NameWithVariant}";
|
||||||
|
}
|
||||||
|
}
|
25
SharedProject/models/Navigator.cs
Normal file
25
SharedProject/models/Navigator.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using SharedProject.enums;
|
||||||
|
|
||||||
|
namespace SharedProject.models;
|
||||||
|
|
||||||
|
public class Navigator
|
||||||
|
{
|
||||||
|
public uint Id { get; set; }
|
||||||
|
|
||||||
|
public string? IdString { get; set; }
|
||||||
|
|
||||||
|
public string? FileName { get; set; }
|
||||||
|
|
||||||
|
public NameEntry? NameEntry0 { get; set; }
|
||||||
|
public NameEntry? NameEntry1 { get; set; }
|
||||||
|
|
||||||
|
public NavigatorGenre Genre { get; set; }
|
||||||
|
|
||||||
|
public NavigatorDefaultAvailability DefaultAvailability { get; set; }
|
||||||
|
|
||||||
|
public string? ToolTipJp { get; set; }
|
||||||
|
public string? ToolTipEn { get; set; }
|
||||||
|
public override string ToString() {
|
||||||
|
return $"{Id}: {NameEntry1}, {ToolTipEn}";
|
||||||
|
}
|
||||||
|
}
|
8
SharedProject/models/Navigators.cs
Normal file
8
SharedProject/models/Navigators.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace SharedProject.models;
|
||||||
|
|
||||||
|
public class Navigators
|
||||||
|
{
|
||||||
|
public int Count { get; set; }
|
||||||
|
|
||||||
|
public List<Navigator>? NavigatorList { get; set; }
|
||||||
|
}
|
@ -13,4 +13,13 @@ public class PlayOption
|
|||||||
|
|
||||||
[JsonPropertyName(nameof(FeverTrance))]
|
[JsonPropertyName(nameof(FeverTrance))]
|
||||||
public PlayOptions.FeverTranceShow FeverTrance { get; set; }
|
public PlayOptions.FeverTranceShow FeverTrance { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName(nameof(AvatarId))]
|
||||||
|
public long AvatarId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName(nameof(NavigatorId))]
|
||||||
|
public long NavigatorId { get; set; }
|
||||||
|
|
||||||
|
[JsonPropertyName(nameof(TitleId))]
|
||||||
|
public long TitleId { get; set; }
|
||||||
}
|
}
|
@ -1,5 +1,6 @@
|
|||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
using SharedProject.common;
|
using SharedProject.common;
|
||||||
|
using SharedProject.enums;
|
||||||
|
|
||||||
namespace SharedProject.models;
|
namespace SharedProject.models;
|
||||||
|
|
||||||
@ -25,4 +26,15 @@ public class SongPlayData
|
|||||||
return SongPlaySubDataList.Sum(data => data.PlayCount);
|
return SongPlaySubDataList.Sum(data => data.PlayCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
|
public DateTime LastPlayTime
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var songPlayDetailData = SongPlaySubDataList.Where(data => data.ClearState != ClearState.NotPlayed)
|
||||||
|
.MinBy(data => data.LastPlayTime);
|
||||||
|
return songPlayDetailData?.LastPlayTime ?? DateTime.MaxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -13,4 +13,6 @@ public class SongPlayDetailData
|
|||||||
public Difficulty Difficulty { get; set; }
|
public Difficulty Difficulty { get; set; }
|
||||||
|
|
||||||
public ClearState ClearState { get; set; }
|
public ClearState ClearState { get; set; }
|
||||||
|
|
||||||
|
public DateTime LastPlayTime { get; set; }
|
||||||
}
|
}
|
17
SharedProject/models/Title.cs
Normal file
17
SharedProject/models/Title.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using SharedProject.enums;
|
||||||
|
|
||||||
|
namespace SharedProject.models;
|
||||||
|
|
||||||
|
public class Title
|
||||||
|
{
|
||||||
|
public uint Id { get; set; }
|
||||||
|
public string? IdString { get; set; }
|
||||||
|
public string? NameJp { get; set; }
|
||||||
|
public string? NameEng { get; set; }
|
||||||
|
public string? UnlockRequirementJp { get; set; }
|
||||||
|
public string? UnlockRequirementEng { get; set; }
|
||||||
|
public TitleUnlockType Type { get; set; }
|
||||||
|
public override string ToString() {
|
||||||
|
return $"{Id}: {NameEng}, {UnlockRequirementEng}";
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user