using StandardScene.Magnetic.Tasking; using System.Collections.Generic; using Xunit; namespace StandardScene.Magnetic.Tests.Tasking { public class Fass2ReconnectChainSelectorTests { [Fact] public void PreferGoal_OnRemainingPath_Wins() { var matches = new List { Match(1, start: 6, target: 10, site: 8, index: 1, remain: new[] { 8, 9, 10 }, prio: 9), Match(2, start: 1, target: 5, site: 8, index: 3, remain: new[] { 8, 4, 5 }, prio: 1) }; var ok = Fass2ReconnectChainSelector.TrySelect(matches, preferGoalSiteId: 5, out var selected, out var reason); Assert.True(ok); Assert.Equal(5, selected.TargetSiteId); Assert.Contains("preferGoal=5", reason); } [Fact] public void StartPoint_Beats_Priority_WhenGoalNotOnPath() { var matches = new List { Match(1, start: 8, target: 12, site: 8, index: 0, remain: new[] { 8, 12 }, prio: 1, atStart: true), Match(2, start: 6, target: 10, site: 8, index: 1, remain: new[] { 8, 9, 10 }, prio: 9) }; var ok = Fass2ReconnectChainSelector.TrySelect(matches, preferGoalSiteId: 99, out var selected, out _); Assert.True(ok); Assert.Equal(12, selected.TargetSiteId); Assert.True(selected.IsAtStartPoint); } [Fact] public void Ambiguous_DifferentTargets_SameScore_Fails() { var matches = new List { Match(1, start: 1, target: 5, site: 3, index: 1, remain: new[] { 3, 4, 5 }, prio: 1), Match(2, start: 9, target: 7, site: 3, index: 1, remain: new[] { 3, 6, 7 }, prio: 1) }; var ok = Fass2ReconnectChainSelector.TrySelect(matches, preferGoalSiteId: null, out var selected, out var reason); Assert.False(ok); Assert.Null(selected); Assert.Contains("ambiguous", reason); } [Fact] public void Empty_Fails() { var ok = Fass2ReconnectChainSelector.TrySelect(new List(), null, out _, out var reason); Assert.False(ok); Assert.Equal("no chain", reason); } private static Fass2ChainMatch Match( int taskId, int start, int target, int site, int index, int[] remain, int prio, bool atStart = false) { return new Fass2ChainMatch { TaskId = taskId, TaskPriority = prio, CurrentSiteId = site, TargetSiteId = target, IndexInPath = index, DistanceToTarget = remain.Length > 0 ? remain.Length - 1 : 0, IsAtStartPoint = atStart || index == 0, IsAtEndPoint = remain.Length <= 1, RemainingPath = remain, FullPath = remain }; } } }