#nullable enable using System.Linq; using Demo2.Domain; using NightShiftProtocol; using NUnit.Framework; namespace Demo2.Tests { public sealed class Demo2DomainTests { [Test] public void BuiltInContent_HasFiveCyclesEighteenRulesAndFiveCategories() { var content = Demo2BuiltInContent.Create(); Assert.That(content.Rules.Count, Is.EqualTo(18)); Assert.That(content.Rules.Values.Select(rule => rule.Category).Distinct().Count(), Is.EqualTo(5)); Assert.That(content.Waves.Select(wave => wave.TotalHealth), Is.EqualTo(new long[] { 500, 900, 1620, 2916, 5248 })); Assert.That(content.ComputeContentHash(), Has.Length.EqualTo(64)); } [Test] public void SaturatingMath_ClampsBothDirectionsAndFormatsLargeValues() { Assert.That(SaturatingMath.Add(long.MaxValue, 1), Is.EqualTo(long.MaxValue)); Assert.That(SaturatingMath.Add(long.MinValue, -1), Is.EqualTo(long.MinValue)); Assert.That(SaturatingMath.Multiply(long.MaxValue, 2), Is.EqualTo(long.MaxValue)); Assert.That(SaturatingMath.MultiplyScaled(200, 1500), Is.EqualTo(300)); Assert.That(SaturatingMath.Format(1_250_000_000), Is.EqualTo("1.25e9")); } [Test] public void RuleOrder_IsStrictlyLeftToRight() { var rules = Demo2BuiltInContent.BuildRules().ToDictionary(rule => rule.Id); var initial = new Demo2RuleContext { Payload = 100, MultiplierMilli = 1000 }; var addThenMultiply = Demo2RuleEngine.Evaluate(initial, new[] { rules["production.dense-ammo"], rules["machine.overclock"] }); var multiplyThenAdd = Demo2RuleEngine.Evaluate(initial, new[] { rules["machine.overclock"], rules["production.dense-ammo"] }); Assert.That(addThenMultiply.Payload, Is.EqualTo(420)); Assert.That(multiplyThenAdd.Payload, Is.EqualTo(330)); Assert.That(addThenMultiply.Faults, Is.EqualTo(1)); } [Test] public void ConditionalRule_OnlyRunsWhenEveryFlagMatches() { var content = Demo2BuiltInContent.Create(); var rule = content.Rules["logistics.long-haul"]; var missesFaultCondition = new Demo2RuleContext { Payload = 100, MultiplierMilli = 1000, BeltBelowEightyPercent = true, Faults = 1 }; var matches = missesFaultCondition; matches.Faults = 0; Assert.That(Demo2RuleEngine.Evaluate(missesFaultCondition, new[] { rule }).MultiplierMilli, Is.EqualTo(1000)); Assert.That(Demo2RuleEngine.Evaluate(matches, new[] { rule }).MultiplierMilli, Is.EqualTo(1200)); } [Test] public void NightShiftMod_AddsMachineRecipeAndConditionalRule() { var content = Demo2BuiltInContent.Create(); var before = content.ComputeContentHash(); new NightShiftContent().Register(content); Assert.That(content.Machines.ContainsKey(Demo2MachineKind.NightShiftSmelter), Is.True); Assert.That(content.Recipes.ContainsKey(100), Is.True); Assert.That(content.Rules.ContainsKey("night-shift.continuous-production"), Is.True); Assert.That(content.ComputeContentHash(), Is.Not.EqualTo(before)); } } }