1
0
mirror of synced 2025-02-17 11:18:32 +01:00

Update dani dojo page

This commit is contained in:
asesidaa 2022-09-12 22:17:15 +08:00
parent 7e43b44e24
commit 847332581d
7 changed files with 243 additions and 80 deletions

View File

@ -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>

View File

@ -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}%";
}
}

View File

@ -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)
};
}
}

View File

@ -13,4 +13,6 @@ public interface IGameDataService
public int GetMusicIndexBySongId(uint songId);
public DanData GetDanDataById(uint danId);
public int GetMusicStarLevel(uint songId, Difficulty difficulty);
}

View File

@ -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; }
}

View File

@ -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; }
}

View File

@ -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>