using System.Collections.Generic; using NUnit.Framework; using NightclubArcadia.Skills; using UnityEngine; namespace NightclubArcadia.Skills.Tests { public class CommentaryPickerTests { sealed class FixedRollSource : IRollSource { readonly int _value; public FixedRollSource(int value) => _value = value; public int Roll(int sides) => _value; } static SkillBibleEntry Entry(string id, int startingRank) { return new SkillBibleEntry { id = id, displayName = id.ToUpperInvariant(), axis = "Self", domain = string.Empty, notes = string.Empty, targetFiringsPerHour = 5f, opposedTo = string.Empty, alliedWith = System.Array.Empty(), primaryChannel = "Behavioural", secondaryChannel = "None", clueYield = "Low", startingRank = startingRank, accentColor = Color.white, }; } SkillDefinition Make(string id, int startingRank) { var def = ScriptableObject.CreateInstance(); def.EditorSet(Entry(id, startingRank)); return def; } PlayerSkills SkillsFor(params (string id, int rank)[] ranks) { var db = ScriptableObject.CreateInstance(); var list = new List(); foreach (var (id, rank) in ranks) { list.Add(Make(id, rank)); } db.EditorSetSkills(list); return new PlayerSkills(db); } [Test] public void Pick_EmptyCandidates_ReturnsNull() { var skills = SkillsFor(("house_pour", 2)); var result = CommentarySystem.Pick( new List(), skills, new List(), 3, new FixedRollSource(1)); Assert.IsNull(result); } [Test] public void Pick_HigherRankPreferred_GivenLowRoll() { // ranks 1 and 3 → weights 1 and 3 → total 4 // roll 1 maps to pick index 0 of cumulative: only weight-1 skill // roll 2..4 maps to higher-ranked skill var low = Make("facework", 1); var high = Make("house_pour", 3); var skills = SkillsFor(("facework", 1), ("house_pour", 3)); var highPick = CommentarySystem.Pick( new List { low, high }, skills, new List(), 3, new FixedRollSource(2)); Assert.AreEqual("house_pour", highPick.Id); } [Test] public void Pick_RecentSpeaker_HasHalvedWeight() { // Without recency: weights 2 and 2, total 4 // With "a" recent: weights 1 and 2, total 3 → roll 1 picks a, roll 2+ picks b var a = Make("a", 2); var b = Make("b", 2); var skills = SkillsFor(("a", 2), ("b", 2)); var pick = CommentarySystem.Pick( new List { a, b }, skills, new List { "a" }, 3, new FixedRollSource(2)); Assert.AreEqual("b", pick.Id); } [Test] public void IsOffCooldown_HighFirings_EligibleImmediately() { // 3600 firings/hour → 1 second interval Assert.IsTrue(CommentarySystem.IsOffCooldown(10f, 11f, 3600f)); } [Test] public void IsOffCooldown_OnePerHour_NotEligibleAfterOneSecond() { Assert.IsFalse(CommentarySystem.IsOffCooldown(10f, 11f, 1f)); } [Test] public void IsOffCooldown_ZeroOrNegative_NeverFires() { Assert.IsFalse(CommentarySystem.IsOffCooldown(float.NegativeInfinity, 100f, 0f)); Assert.IsFalse(CommentarySystem.IsOffCooldown(float.NegativeInfinity, 100f, -1f)); } } }