Files
ProjectQuint/Assets/ProjectQuint/Runtime/Unity/Features/Profile/ProfileRatingContextBuilder.cs
T

100 lines
4.8 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using ProjectQuint.Core.Progression;
using ProjectQuint.Library;
namespace ProjectQuint.Features.Profile
{
internal static class ProfileRatingContextBuilder
{
public static IReadOnlyList<RatingSummary> Build(
IReadOnlyList<RatingSummary> recordedContexts,
IReadOnlyList<BmsDifficultyTableDefinition> registeredTables,
IReadOnlyList<SongLibraryEntry> activeSongs,
string activeTableId,
ProfileProgressSnapshot profile,
Func<string, string, int, bool, RatingSummary> resolveRating)
{
var contexts = new Dictionary<string, RatingSummary>(StringComparer.OrdinalIgnoreCase);
var tableNames = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var table in registeredTables ?? Array.Empty<BmsDifficultyTableDefinition>())
{
if (table == null || string.IsNullOrWhiteSpace(table.Id))
continue;
tableNames[table.Id.Trim()] = string.IsNullOrWhiteSpace(table.DisplayName)
? table.Id.Trim()
: table.DisplayName.Trim();
}
void AddResolved(string providerId, string providerName, int keyCount, bool hasScratch)
{
if (string.IsNullOrWhiteSpace(providerId) || keyCount < 4 || keyCount > 7)
return;
var normalizedId = providerId.Trim();
var key = RatingContextIdentity(normalizedId, keyCount, hasScratch);
if (contexts.ContainsKey(key))
return;
var displayName = string.IsNullOrWhiteSpace(providerName)
? tableNames.TryGetValue(normalizedId, out var registeredName)
? registeredName
: normalizedId
: providerName.Trim();
contexts[key] = resolveRating?.Invoke(normalizedId, displayName, keyCount, hasScratch) ??
new RatingSummary(normalizedId, displayName, keyCount, hasScratch, 0.0, 0);
}
foreach (var recorded in recordedContexts ?? Array.Empty<RatingSummary>())
{
if (!recorded.HasContext)
continue;
contexts[RatingContextIdentity(recorded.ProviderId, recorded.KeyCount, recorded.HasScratch)] = recorded;
}
foreach (var table in registeredTables ?? Array.Empty<BmsDifficultyTableDefinition>())
{
if (table == null)
continue;
var preset = BmsDifficultyTablePresets.Find(table.Id, table.HeaderUrl);
if (preset?.DefaultKeyCount >= 4)
AddResolved(table.Id, table.DisplayName, preset.Value.DefaultKeyCount,
preset.Value.DefaultHasScratch);
}
if (!string.IsNullOrWhiteSpace(activeTableId))
{
var activeName = tableNames.TryGetValue(activeTableId, out var registeredName)
? registeredName
: activeTableId;
foreach (var form in (activeSongs ?? Array.Empty<SongLibraryEntry>())
.Where(song => song?.Metadata != null &&
song.EffectiveKeyCount >= 4 && song.EffectiveKeyCount <= 7 &&
song.Catalog?.HasDifficulty == true &&
string.Equals(song.Catalog.ProviderId, activeTableId,
StringComparison.OrdinalIgnoreCase))
.Select(song => new { KeyCount = song.EffectiveKeyCount, song.Metadata.HasScratch })
.Distinct())
AddResolved(activeTableId, activeName, form.KeyCount, form.HasScratch);
}
AddResolved(
profile.LastRatingProviderId,
profile.LastRatingProviderDisplayName,
profile.LastRatingKeyCount,
profile.LastRatingHasScratch);
return contexts.Values
.OrderByDescending(summary => summary.ActivityPlayCount)
.ThenByDescending(summary => summary.FilledSlots)
.ThenBy(summary => summary.ProviderDisplayName, StringComparer.OrdinalIgnoreCase)
.ThenBy(summary => summary.KeyCount)
.ThenBy(summary => summary.HasScratch)
.ToArray();
}
private static string RatingContextIdentity(string providerId, int keyCount, bool hasScratch) =>
$"{(providerId ?? string.Empty).Trim().ToLowerInvariant()}:{keyCount}:{hasScratch}";
}
}