Update dani dojo page
This commit is contained in:
parent
7e43b44e24
commit
847332581d
@ -19,11 +19,12 @@
|
||||
|
||||
<MudTabPanel Text="@GetDanTitle(danData.Title)" Icon="@GetDanResultIcon(danId)">
|
||||
<MudGrid Class="pa-8 d-block">
|
||||
@for (uint i = 0; i <= 2; i++)
|
||||
@for (uint j = 0; j <= 2; j++)
|
||||
{
|
||||
var index = i;
|
||||
var danDataOdaiSong = danData.OdaiSongList[(int)i];
|
||||
var stageNumber = i + 1;
|
||||
var index = (int)j;
|
||||
var danDataOdaiSong = danData.OdaiSongList[index];
|
||||
var stageNumber = j + 1;
|
||||
var difficulty = (Difficulty)danDataOdaiSong.Level;
|
||||
<MudItem xs="12" Class="pb-1">
|
||||
<MudCard Outlined="true" Class="pa-4">
|
||||
<MudGrid Style="display:flex; align-items: center; justify-content: flex-start;">
|
||||
@ -32,8 +33,9 @@
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="2" md="1" Style="display:flex;flex-direction:column;align-items:center;">
|
||||
<img src=@($"/images/difficulty_{(Difficulty)danDataOdaiSong.Level}.png") style="width:40px;height:40px;" />
|
||||
<MudText Typo="Typo.caption">@((Difficulty)danDataOdaiSong.Level)</MudText>
|
||||
<img src=@($"/images/difficulty_{difficulty}.png") style="width:40px;height:40px;" alt="@difficulty"/>
|
||||
<MudText Typo="Typo.caption">@difficulty</MudText>
|
||||
<MudText Typo="Typo.caption">Level star: @GameDataService.GetMusicStarLevel(danDataOdaiSong.SongNo, difficulty)</MudText>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="9" md="4" Style="display:flex;flex-direction:column;" Class="pl-4">
|
||||
@ -41,12 +43,14 @@
|
||||
<MudText Typo="Typo.caption">@GameDataService.GetMusicArtistBySongId(danDataOdaiSong.SongNo)</MudText>
|
||||
</MudItem>
|
||||
|
||||
|
||||
@if (bestDataMap.ContainsKey(danId))
|
||||
|
||||
@if (bestDataMap.ContainsKey(danId))
|
||||
{
|
||||
var danBestData = bestDataMap[danId];
|
||||
var bestStage = danBestData.DanBestStageDataList[(int)index];
|
||||
<MudItem xs="12" md="6" Style="display:flex;flex-direction:column;">
|
||||
if (danBestData.DanBestStageDataList.Count > index)
|
||||
{
|
||||
var bestStage = danBestData.DanBestStageDataList[index];
|
||||
<MudItem xs="12" md="6" Style="display:flex;flex-direction:column;">
|
||||
<MudStack Row="true" Spacing="4" Justify="Justify.SpaceEvenly">
|
||||
<MudCard Elevation="0">
|
||||
<MudText Typo="Typo.caption">Good</MudText>
|
||||
@ -74,8 +78,8 @@
|
||||
</MudCard>
|
||||
</MudStack>
|
||||
</MudItem>
|
||||
}
|
||||
}
|
||||
|
||||
</MudGrid>
|
||||
</MudCard>
|
||||
</MudItem>
|
||||
@ -85,61 +89,88 @@
|
||||
<MudGrid>
|
||||
<MudItem xs="12" md="3">
|
||||
<MudCard Outlined="true" Class="pa-4">
|
||||
<h4>Soul Gauge</h4>
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h6">Soul Gauge</MudText>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudText>
|
||||
Soul gauge needed to pass: @GetSoulGauge(danData, false)
|
||||
</MudText>
|
||||
<MudText>
|
||||
Soul gauge needed to gold clear: @GetSoulGauge(danData, true)
|
||||
</MudText>
|
||||
@if (bestDataMap.ContainsKey(danId))
|
||||
{
|
||||
var danBestData = bestDataMap[danId];
|
||||
<MudText>
|
||||
Best Soul gauge: @(danBestData.SoulGaugeTotal)%
|
||||
</MudText>
|
||||
}
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</MudItem>
|
||||
|
||||
<MudItem xs="12" md="9">
|
||||
<MudStack>
|
||||
<MudCard Outlined="true" Class="pa-4">
|
||||
<h4>Requirement Placeholder</h4>
|
||||
</MudCard>
|
||||
<MudCard Outlined="true" Class="pa-4">
|
||||
<h4>Requirement Placeholder</h4>
|
||||
</MudCard>
|
||||
<MudCard Outlined="true" Class="pa-4">
|
||||
<h4>Requirement Placeholder</h4>
|
||||
</MudCard>
|
||||
</MudStack>
|
||||
@for (var j = 1; j < danData.OdaiBorderList.Count; j++)
|
||||
{
|
||||
var border = danData.OdaiBorderList[j];
|
||||
<MudStack>
|
||||
<MudCard Outlined="true" Class="pa-4">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudText Typo="Typo.h4">
|
||||
@GetDanRequirementTitle(border)
|
||||
</MudText>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
|
||||
@{
|
||||
var borderType = (DanBorderType)border.BorderType;
|
||||
}
|
||||
@if (borderType == DanBorderType.All)
|
||||
{
|
||||
<MudText>@GetDanRequirementAll(border)</MudText>
|
||||
@if (bestDataMap.ContainsKey(danId))
|
||||
{
|
||||
var bestData = bestDataMap[danId];
|
||||
<MudText>
|
||||
Best: @GetAllBestFromData((DanConditionType)border.OdaiType, bestData)
|
||||
</MudText>
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudStack Row="true">
|
||||
@for (var k = 0; k < 3; k++)
|
||||
{
|
||||
var songNumber = k;
|
||||
<MudText>
|
||||
@GetDanRequirementPerSong(border, songNumber)
|
||||
</MudText>
|
||||
@if (!bestDataMap.ContainsKey(danId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
var bestData = bestDataMap[danId];
|
||||
if (k >= bestData.DanBestStageDataList.Count)
|
||||
{
|
||||
break;
|
||||
}
|
||||
<MudText>
|
||||
Best: @GetSongBestFromData((DanConditionType)border.OdaiType, bestData, songNumber)
|
||||
</MudText>
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
</MudCardContent>
|
||||
</MudCard>
|
||||
</MudStack>
|
||||
}
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
|
||||
@foreach (var data in danData.OdaiBorderList)
|
||||
{
|
||||
<MudText>@DanRequirementToString(data)</MudText>
|
||||
}
|
||||
@if (bestDataMap.ContainsKey(danId))
|
||||
{
|
||||
var danBestData = bestDataMap[danId];
|
||||
<MudText>Clear state: @danBestData.ClearState </MudText>
|
||||
<MudText>Best Soul gauge: @danBestData.SoulGaugeTotal </MudText>
|
||||
<MudText>Best Total Combo: @danBestData.ComboCountTotal </MudText>
|
||||
<MudGrid>
|
||||
@foreach (var bestStage in danBestData.DanBestStageDataList)
|
||||
{
|
||||
var songNumber = bestStage.SongNumber;
|
||||
var danDataOdaiSong = danData.OdaiSongList[(int)songNumber];
|
||||
<MudItem>
|
||||
<MudText>Song Number: @songNumber</MudText>
|
||||
<MudText>
|
||||
Song Name:
|
||||
@GameDataService.GetMusicNameBySongId(danDataOdaiSong.SongNo)
|
||||
</MudText>
|
||||
<MudText>Song Difficulty: @((Difficulty)danDataOdaiSong.Level)</MudText>
|
||||
<MudText>
|
||||
Song play detail <br />
|
||||
Good : @bestStage.GoodCount <br />
|
||||
Ok : @bestStage.OkCount <br />
|
||||
Bad : @bestStage.BadCount <br />
|
||||
Combo : @bestStage.ComboCount<br />
|
||||
Drumroll : @bestStage.DrumrollCount <br />
|
||||
Total hit : @bestStage.TotalHitCount
|
||||
</MudText>
|
||||
</MudItem>
|
||||
}
|
||||
</MudGrid>
|
||||
|
||||
}
|
||||
</MudItem>
|
||||
</MudGrid>
|
||||
</MudTabPanel>
|
||||
|
@ -19,22 +19,98 @@ public partial class DaniDojo
|
||||
await base.OnInitializedAsync();
|
||||
response = await Client.GetFromJsonAsync<DanBestDataResponse>($"api/DanBestData/{Baid}");
|
||||
response.ThrowIfNull();
|
||||
response.DanBestDataList.ForEach(data => data.DanBestStageDataList
|
||||
.Sort((stageData, otherStageData) => stageData.SongNumber.CompareTo(otherStageData.SongNumber)));
|
||||
bestDataMap = response.DanBestDataList.ToDictionary(data => data.DanId);
|
||||
|
||||
breadcrumbs.Add(new BreadcrumbItem($"Card: {Baid}", href: null, disabled: true));
|
||||
breadcrumbs.Add(new BreadcrumbItem("Dani Dojo", href: $"/Cards/{Baid}/DaniDojo", disabled: false));
|
||||
}
|
||||
|
||||
private static string DanRequirementToString(DanData.OdaiBorder data)
|
||||
private static string GetDanRequirementTitle(DanData.OdaiBorder data)
|
||||
{
|
||||
var danConditionType = (DanConditionType)data.OdaiType;
|
||||
return (DanBorderType)data.BorderType switch
|
||||
{
|
||||
DanBorderType.All => $"{danConditionType}, Pass: {data.RedBorderTotal}, Gold: {data.GoldBorderTotal} ",
|
||||
DanBorderType.PerSong => $"{danConditionType}, " +
|
||||
$"Pass 1: {data.RedBorder1}, Pass 2: {data.RedBorder2}, Pass 3: {data.RedBorder3}" +
|
||||
$"Gold 1: {data.GoldBorder1}, Gold 2: {data.GoldBorder1}, Pass 3: {data.GoldBorder1}",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
DanBorderType.All => $"{danConditionType}, All song",
|
||||
DanBorderType.PerSong => $"{danConditionType}, Per song",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(data))
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetDanRequirementAll(DanData.OdaiBorder odaiBorder)
|
||||
{
|
||||
((DanBorderType)odaiBorder.BorderType).Throw().IfNotEquals(DanBorderType.All);
|
||||
var type = (DanConditionType)odaiBorder.OdaiType;
|
||||
var template =
|
||||
$"Pass when {{0}} {{1}} {odaiBorder.RedBorderTotal}, gold when {{1}} {odaiBorder.GoldBorderTotal}";
|
||||
return type switch
|
||||
{
|
||||
DanConditionType.SoulGauge => throw new ArgumentException("Soul gauge should not be here"),
|
||||
DanConditionType.GoodCount => string.Format(template, "good count", "exceeds"),
|
||||
DanConditionType.OkCount => string.Format(template, "ok count", "exceeds"),
|
||||
DanConditionType.BadCount => string.Format(template, "bad count", "below"),
|
||||
DanConditionType.ComboCount => string.Format(template, "combo count", "exceeds"),
|
||||
DanConditionType.DrumrollCount => string.Format(template, "drum roll count", "exceeds"),
|
||||
DanConditionType.Score => string.Format(template, "score", "exceeds"),
|
||||
DanConditionType.TotalHitCount => string.Format(template, "hit count", "exceeds"),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(odaiBorder))
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetDanRequirementPerSong(DanData.OdaiBorder odaiBorder, int songNumber)
|
||||
{
|
||||
songNumber.Throw().IfOutOfRange(0, 2);
|
||||
((DanBorderType)odaiBorder.BorderType).Throw().IfNotEquals(DanBorderType.PerSong);
|
||||
var type = (DanConditionType)odaiBorder.OdaiType;
|
||||
var template =
|
||||
$"Pass when song{songNumber}'s {{0}} {{1}} {odaiBorder.RedBorderTotal}, gold when {{1}} {odaiBorder.GoldBorderTotal}";
|
||||
return type switch
|
||||
{
|
||||
DanConditionType.SoulGauge => throw new ArgumentException("Soul gauge should not be here"),
|
||||
DanConditionType.GoodCount => string.Format(template, "good count", "exceeds"),
|
||||
DanConditionType.OkCount => string.Format(template, "ok count", "exceeds"),
|
||||
DanConditionType.BadCount => string.Format(template, "bad count", "below"),
|
||||
DanConditionType.ComboCount => string.Format(template, "combo count", "exceeds"),
|
||||
DanConditionType.DrumrollCount => string.Format(template, "drum roll count", "exceeds"),
|
||||
DanConditionType.Score => string.Format(template, "score", "exceeds"),
|
||||
DanConditionType.TotalHitCount => string.Format(template, "hit count", "exceeds"),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(odaiBorder))
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetAllBestFromData(DanConditionType type, DanBestData data)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
DanConditionType.SoulGauge => throw new ArgumentException("Soul gauge should not be here"),
|
||||
DanConditionType.GoodCount => data.DanBestStageDataList.Sum(stageData => stageData.GoodCount).ToString(),
|
||||
DanConditionType.OkCount => data.DanBestStageDataList.Sum(stageData => stageData.OkCount).ToString(),
|
||||
DanConditionType.BadCount => data.DanBestStageDataList.Sum(stageData => stageData.BadCount).ToString(),
|
||||
DanConditionType.ComboCount => data.ComboCountTotal.ToString(),
|
||||
DanConditionType.DrumrollCount => data.DanBestStageDataList.Sum(stageData => stageData.DrumrollCount)
|
||||
.ToString(),
|
||||
DanConditionType.Score => data.DanBestStageDataList.Sum(stageData => stageData.PlayScore).ToString(),
|
||||
DanConditionType.TotalHitCount => data.DanBestStageDataList.Sum(stageData => stageData.TotalHitCount)
|
||||
.ToString(),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
||||
};
|
||||
}
|
||||
|
||||
private static string GetSongBestFromData(DanConditionType type, DanBestData data, int songNumber)
|
||||
{
|
||||
songNumber.Throw().IfOutOfRange(0, 2);
|
||||
return type switch
|
||||
{
|
||||
DanConditionType.SoulGauge => throw new ArgumentException("Soul gauge should not be here"),
|
||||
DanConditionType.GoodCount => data.DanBestStageDataList[songNumber].GoodCount.ToString(),
|
||||
DanConditionType.OkCount => data.DanBestStageDataList[songNumber].OkCount.ToString(),
|
||||
DanConditionType.BadCount => data.DanBestStageDataList[songNumber].BadCount.ToString(),
|
||||
DanConditionType.ComboCount => data.DanBestStageDataList[songNumber].ComboCount.ToString(),
|
||||
DanConditionType.DrumrollCount => data.DanBestStageDataList[songNumber].DrumrollCount.ToString(),
|
||||
DanConditionType.Score => data.DanBestStageDataList[songNumber].PlayScore.ToString(),
|
||||
DanConditionType.TotalHitCount => data.DanBestStageDataList[songNumber].TotalHitCount.ToString(),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type), type, null)
|
||||
};
|
||||
}
|
||||
|
||||
@ -68,18 +144,35 @@ public partial class DaniDojo
|
||||
|
||||
private string GetDanResultIcon(uint danId)
|
||||
{
|
||||
string icon = "";
|
||||
var icon = "";
|
||||
|
||||
if (bestDataMap.ContainsKey(danId))
|
||||
if (!bestDataMap.ContainsKey(danId))
|
||||
{
|
||||
var state = bestDataMap[danId].ClearState;
|
||||
return icon;
|
||||
}
|
||||
|
||||
var state = bestDataMap[danId].ClearState;
|
||||
|
||||
if (state is not DanClearState.NotClear)
|
||||
{
|
||||
icon = $"<image href='/images/dani_{state}.png' width='24' height='24'/>";
|
||||
}
|
||||
if (state is not DanClearState.NotClear)
|
||||
{
|
||||
icon = $"<image href='/images/dani_{state}.png' width='24' height='24'/>";
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private static string GetSoulGauge(DanData data, bool isGold)
|
||||
{
|
||||
var borders = data.OdaiBorderList;
|
||||
var soulBorder =
|
||||
borders.FirstOrDefault(border => (DanConditionType)border.BorderType == DanConditionType.SoulGauge,
|
||||
new DanData.OdaiBorder());
|
||||
|
||||
if (isGold)
|
||||
{
|
||||
return $"{soulBorder.GoldBorderTotal}%";
|
||||
}
|
||||
|
||||
return $"{soulBorder.RedBorderTotal}%";
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
using System.Collections.Immutable;
|
||||
using Swan.Mapping;
|
||||
using TaikoWebUI.Shared.Models;
|
||||
|
||||
namespace TaikoWebUI.Services;
|
||||
@ -42,13 +43,9 @@ public class GameDataService : IGameDataService
|
||||
var musicArtist = dict.GetValueOrDefault(songArtistKey, new WordListEntry());
|
||||
|
||||
var musicSongId = music.SongId;
|
||||
var musicDetail = new MusicDetail
|
||||
{
|
||||
SongId = musicSongId,
|
||||
SongName = musicName.JapaneseText,
|
||||
ArtistName = musicArtist.JapaneseText,
|
||||
Genre = music.Genre
|
||||
};
|
||||
var musicDetail = music.CopyPropertiesToNew<MusicDetail>();
|
||||
musicDetail.SongName = musicName.JapaneseText;
|
||||
musicDetail.ArtistName = musicArtist.JapaneseText;
|
||||
|
||||
musicMap.TryAdd(musicSongId, musicDetail);
|
||||
}
|
||||
@ -87,4 +84,18 @@ public class GameDataService : IGameDataService
|
||||
return danMap.GetValueOrDefault(danId, new DanData());
|
||||
}
|
||||
|
||||
public int GetMusicStarLevel(uint songId, Difficulty difficulty)
|
||||
{
|
||||
var success = musicMap.TryGetValue(songId, out var musicDetail);
|
||||
return difficulty switch
|
||||
{
|
||||
Difficulty.None => throw new ArgumentException("Difficulty cannot be none"),
|
||||
Difficulty.Easy => success ? musicDetail!.StarEasy : 0,
|
||||
Difficulty.Normal => success ? musicDetail!.StarNormal : 0,
|
||||
Difficulty.Hard => success ? musicDetail!.StarHard : 0,
|
||||
Difficulty.Oni => success ? musicDetail!.StarOni : 0,
|
||||
Difficulty.UraOni => success ? musicDetail!.StarUra : 0,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(difficulty), difficulty, null)
|
||||
};
|
||||
}
|
||||
}
|
@ -13,4 +13,6 @@ public interface IGameDataService
|
||||
public int GetMusicIndexBySongId(uint songId);
|
||||
|
||||
public DanData GetDanDataById(uint danId);
|
||||
|
||||
public int GetMusicStarLevel(uint songId, Difficulty difficulty);
|
||||
}
|
@ -11,4 +11,14 @@ public class MusicDetail
|
||||
public string ArtistName { get; set; } = string.Empty;
|
||||
|
||||
public SongGenre Genre { get; set; }
|
||||
|
||||
public int StarEasy { get; set; }
|
||||
|
||||
public int StarNormal { get; set; }
|
||||
|
||||
public int StarHard { get; set; }
|
||||
|
||||
public int StarOni { get; set; }
|
||||
|
||||
public int StarUra { get; set; }
|
||||
}
|
@ -12,4 +12,19 @@ public class MusicInfoEntry
|
||||
|
||||
[JsonPropertyName("genreNo")]
|
||||
public SongGenre Genre { get; set; }
|
||||
|
||||
[JsonPropertyName("starEasy")]
|
||||
public int StarEasy { get; set; }
|
||||
|
||||
[JsonPropertyName("starNormal")]
|
||||
public int StarNormal { get; set; }
|
||||
|
||||
[JsonPropertyName("starHard")]
|
||||
public int StarHard { get; set; }
|
||||
|
||||
[JsonPropertyName("starMania")]
|
||||
public int StarOni { get; set; }
|
||||
|
||||
[JsonPropertyName("starUra")]
|
||||
public int StarUra { get; set; }
|
||||
}
|
@ -10,6 +10,7 @@
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.7" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.7" PrivateAssets="all" />
|
||||
<PackageReference Include="MudBlazor" Version="6.0.15" />
|
||||
<PackageReference Include="Swan.Core" Version="6.0.2-beta.90" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
Loading…
x
Reference in New Issue
Block a user