131 lines
4.1 KiB
C#
131 lines
4.1 KiB
C#
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<string>(),
|
|
primaryChannel = "Behavioural",
|
|
secondaryChannel = "None",
|
|
clueYield = "Low",
|
|
startingRank = startingRank,
|
|
accentColor = Color.white,
|
|
};
|
|
}
|
|
|
|
SkillDefinition Make(string id, int startingRank)
|
|
{
|
|
var def = ScriptableObject.CreateInstance<SkillDefinition>();
|
|
def.EditorSet(Entry(id, startingRank));
|
|
return def;
|
|
}
|
|
|
|
PlayerSkills SkillsFor(params (string id, int rank)[] ranks)
|
|
{
|
|
var db = ScriptableObject.CreateInstance<SkillDatabase>();
|
|
var list = new List<SkillDefinition>();
|
|
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<SkillDefinition>(),
|
|
skills,
|
|
new List<string>(),
|
|
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<SkillDefinition> { low, high },
|
|
skills,
|
|
new List<string>(),
|
|
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<SkillDefinition> { a, b },
|
|
skills,
|
|
new List<string> { "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));
|
|
}
|
|
}
|
|
}
|