100 lines
4.8 KiB
C#
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}";
|
|
|
|
}
|
|
}
|