namespace FozFc.Api.Domain; /// /// Fan-rank tiers and XP model (mirrors the values previously used client-side). /// public static class FanRank { public const int XpPerEuroSpent = 10; public const int XpPerMembershipMonth = 120; public sealed record Tier(string Rank, int MinXp); public static readonly IReadOnlyList Tiers = new List { new("Copper", 0), new("Bronze", 600), new("Silver", 1800), new("Gold", 4200), new("Platinium", 7800), new("Diamond", 12500), }; public sealed record RankProgress(string FanRank, string? NextRank, int XpToNextRank, int XpProgressPercent); public static RankProgress Compute(int xp) { var safeXp = Math.Max(0, xp); Tier current = Tiers[0]; Tier? next = null; for (var i = 0; i < Tiers.Count; i++) { var upcoming = i + 1 < Tiers.Count ? Tiers[i + 1] : null; if (safeXp >= Tiers[i].MinXp) { current = Tiers[i]; next = upcoming; } } if (next is null) { return new RankProgress(current.Rank, null, 0, 100); } var range = Math.Max(1, next.MinXp - current.MinXp); var within = Math.Max(0, safeXp - current.MinXp); var percent = Math.Clamp((int)Math.Round((double)within / range * 100), 0, 100); return new RankProgress(current.Rank, next.Rank, Math.Max(0, next.MinXp - safeXp), percent); } }