Files
bansonic_beta_main/Assets/scripts/_runtimecache/PlayerRksService.cs
T

220 lines
6.0 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
[Serializable]
public class PlayerRksSaveData
{
public float bestOverallRks;
}
public static class PlayerRksService
{
private const string SaveCategory = "player_rks";
private const string SaveKey = "overall";
private const float MaxScorePerChart = 1000000f;
private const int TopChartCount = 20;
public static event Action<float> OnRksChanged;
private static bool loaded;
private static float bestOverallRks;
public static void EnsureLoaded(Player_SO player = null)
{
if (loaded)
{
SyncPlayerSo(player);
return;
}
loaded = true;
bestOverallRks = 0f;
PlayerRksSaveData saveData;
if (SecureSaveVault.TryLoadJson(SaveCategory, SaveKey, out saveData) && saveData != null)
{
bestOverallRks = Mathf.Max(0f, saveData.bestOverallRks);
}
else if (PlayerProgressBackupService.TryRestoreRks(out float backupRks))
{
bestOverallRks = Mathf.Max(0f, backupRks);
}
else if (player != null)
{
bestOverallRks = Mathf.Max(0f, player.URankingScore);
}
SyncPlayerSo(player);
}
public static float GetBestOverallRks(Player_SO player = null)
{
EnsureLoaded(player);
return bestOverallRks;
}
public static float GetNormalizedOverallRks100(Player_SO player = null)
{
EnsureLoaded(player);
float maxConstant = Mathf.Max(1f, GetMaxChartConstant());
return Mathf.Clamp(bestOverallRks / maxConstant * 100f, 0f, 100f);
}
public static float RefreshAndPersist(Player_SO player = null)
{
EnsureLoaded(player);
float calculated = CalculateOverallRksRaw();
if (calculated > bestOverallRks + 0.0001f)
{
bestOverallRks = calculated;
SecureSaveVault.SaveJson(SaveCategory, SaveKey, new PlayerRksSaveData { bestOverallRks = bestOverallRks });
PlayerProgressBackupService.SaveRks(bestOverallRks);
SyncPlayerSo(player);
OnRksChanged?.Invoke(bestOverallRks);
}
else
{
SyncPlayerSo(player);
}
return bestOverallRks;
}
public static void ClearPersistentState(Player_SO player = null)
{
loaded = true;
bestOverallRks = 0f;
SecureSaveVault.Delete(SaveCategory, SaveKey);
PlayerProgressBackupService.ClearRksBackup();
SyncPlayerSo(player);
OnRksChanged?.Invoke(bestOverallRks);
}
private static void SyncPlayerSo(Player_SO player)
{
Player_SO target = player != null ? player : LoadDefaultPlayerSo();
if (target != null && !Mathf.Approximately(target.URankingScore, bestOverallRks))
{
target.SetURankingScore(bestOverallRks);
}
}
private static Player_SO LoadDefaultPlayerSo()
{
Player_SO[] players = RuntimeResourcesCache.LoadAll<Player_SO>(string.Empty);
if (players == null)
{
return null;
}
for (int i = 0; i < players.Length; i++)
{
if (players[i] != null)
{
return players[i];
}
}
return null;
}
private static float CalculateOverallRksRaw()
{
SongData[] songs = RuntimeResourcesCache.LoadAllSongs();
if (songs == null || songs.Length == 0)
{
return 0f;
}
List<float> chartRksValues = new List<float>(64);
for (int i = 0; i < songs.Length; i++)
{
SongData song = songs[i];
if (song == null || song.chartFiles == null)
{
continue;
}
for (int j = 0; j < song.chartFiles.Count; j++)
{
ChartFileEntry entry = song.chartFiles[j];
if (entry == null)
{
continue;
}
int bestTotal = entry.totalPersonalRecordForThisDifficulty;
if (bestTotal <= 0)
{
bestTotal = song.GetPersonalRecord(entry.difficulty) + song.GetIdolRecord(entry.difficulty);
}
float chartRks = CalculateChartRks(entry.difficultyLEVEL, bestTotal);
if (chartRks > 0f)
{
chartRksValues.Add(chartRks);
}
}
}
if (chartRksValues.Count == 0)
{
return 0f;
}
chartRksValues.Sort((a, b) => b.CompareTo(a));
int count = Mathf.Min(TopChartCount, chartRksValues.Count);
float sum = 0f;
for (int i = 0; i < count; i++)
{
sum += chartRksValues[i];
}
return sum / Mathf.Max(1, count);
}
private static float GetMaxChartConstant()
{
SongData[] songs = RuntimeResourcesCache.LoadAllSongs();
float maxConstant = 0f;
if (songs == null)
{
return 1f;
}
for (int i = 0; i < songs.Length; i++)
{
SongData song = songs[i];
if (song == null || song.chartFiles == null)
{
continue;
}
for (int j = 0; j < song.chartFiles.Count; j++)
{
ChartFileEntry entry = song.chartFiles[j];
if (entry != null && entry.difficultyLEVEL > maxConstant)
{
maxConstant = entry.difficultyLEVEL;
}
}
}
return Mathf.Max(1f, maxConstant);
}
private static float CalculateChartRks(float chartConstant, int totalScore)
{
if (chartConstant <= 0f || totalScore <= 0)
{
return 0f;
}
float scoreRate = Mathf.Clamp01(totalScore / MaxScorePerChart);
float quality = Mathf.Pow(scoreRate, 1.35f);
return chartConstant * quality;
}
}