using System; using System.Collections.Generic; using UnityEngine; public sealed class ScoringSystem : MonoBehaviour { [Header("Modifiers")] [SerializeField] private List activeModifiers = new(); public event Action OnCategoryScored; public event Action OnAllCategoriesScored; private readonly Dictionary scorecard = new(); private readonly HashSet usedCategories = new(); public bool IsCategoryUsed(YachtCategory category) => usedCategories.Contains(category); public int GetCategoryScore(YachtCategory category) { return scorecard.TryGetValue(category, out int score) ? score : -1; } public int TotalScore { get { int total = 0; foreach (var kvp in scorecard) total += kvp.Value; return total; } } public int CategoriesFilledCount => usedCategories.Count; public int TotalCategoryCount => Enum.GetValues(typeof(YachtCategory)).Length; public bool IsComplete => CategoriesFilledCount >= TotalCategoryCount; public void AddModifier(ScoreModifier modifier) { if (modifier != null && !activeModifiers.Contains(modifier)) activeModifiers.Add(modifier); } public void RemoveModifier(ScoreModifier modifier) { activeModifiers.Remove(modifier); } public IReadOnlyList ActiveModifiers => activeModifiers; public ScoreResult PreviewScore(int[] diceValues, YachtCategory category) { int baseScore = CategoryScorer.Calculate(diceValues, category); ScoreResult result = ScoreResult.Create(baseScore, diceValues, category); ApplyModifiers(ref result); return result; } public ScoreResult ScoreCategory(int[] diceValues, YachtCategory category) { if (usedCategories.Contains(category)) throw new InvalidOperationException($"Category {category} has already been scored."); ScoreResult result = PreviewScore(diceValues, category); int finalScore = result.FinalScore; scorecard[category] = finalScore; usedCategories.Add(category); OnCategoryScored?.Invoke(category, finalScore); if (IsComplete) OnAllCategoriesScored?.Invoke(TotalScore); return result; } private void ApplyModifiers(ref ScoreResult result) { // Pass 1: Additive for (int i = 0; i < activeModifiers.Count; i++) { if (activeModifiers[i] == null) continue; if (activeModifiers[i].Phase == ScoreModifier.ModifierPhase.Additive) activeModifiers[i].Apply(ref result); } // Pass 2: Multiplicative for (int i = 0; i < activeModifiers.Count; i++) { if (activeModifiers[i] == null) continue; if (activeModifiers[i].Phase == ScoreModifier.ModifierPhase.Multiplicative) activeModifiers[i].Apply(ref result); } } public void ResetScorecard() { scorecard.Clear(); usedCategories.Clear(); } }