using StandardScene.Magnetic.Protocol; using StandardScene.Magnetic.Tasking; using System.Collections.Generic; using Xunit; namespace StandardScene.Magnetic.Tests.Tasking { public class Fass2ControlAreaGateTests { [Fact] public void Resolve_WithoutArea_UsesCurrentSite() { var info = Fass2ControlAreaGate.Resolve(new Fass2SiteActionData(), 17); Assert.Equal(new[] { 17 }, info.AreaSiteIds); Assert.Equal("17", info.AreaId); Assert.Equal(1, info.Capacity); Assert.Equal(Fass2TaskBuilder.StartStopControlStart, info.ReleaseStartStop); } [Fact] public void Resolve_ParsesSiteArray_AndReleasePass() { var info = Fass2ControlAreaGate.Resolve(new Fass2SiteActionData { ControlArea = "[10, 11, 12]", ControlCapacity = 2, ControlReleaseStartStop = Fass2TaskBuilder.StartStopPass }, 8); Assert.Equal(new[] { 10, 11, 12 }, info.AreaSiteIds); Assert.Equal("10,11,12", info.AreaId); Assert.Equal(2, info.Capacity); Assert.Equal(Fass2TaskBuilder.StartStopPass, info.ReleaseStartStop); } [Fact] public void ParseSiteIds_CommaAndSemicolon() { var ids = Fass2ControlAreaGate.ParseSiteIds("10;11|12", 8); Assert.Equal(new[] { 10, 11, 12 }, ids); } [Fact] public void LimitWindow_StopsAtFirstUnreleasedControlStop() { var nodes = new[] { Node(1, Fass2TaskBuilder.StartStopPass), Node(2, Fass2TaskBuilder.StartStopControlStop), Node(3, Fass2TaskBuilder.StartStopPass), Node(4, Fass2TaskBuilder.StartStopPass) }; var count = Fass2ControlAreaGate.LimitWindowCount(nodes, 0, 4, releasedIndex: -1); Assert.Equal(2, count); } [Fact] public void LimitWindow_AfterRelease_IncludesFollowingNodes() { var nodes = new[] { Node(1, Fass2TaskBuilder.StartStopPass), Node(2, Fass2TaskBuilder.StartStopControlStart), Node(3, Fass2TaskBuilder.StartStopPass) }; var count = Fass2ControlAreaGate.LimitWindowCount(nodes, 1, 3, releasedIndex: 1); Assert.Equal(2, count); } [Fact] public void Evaluate_ExcludesSelf_AllowsFirstCar() { var area = Area(1, 10, 11); var occupancies = new List { new Fass2ControlOccupancy(1, new[] { 10, 11 }) }; var check = Fass2ControlAreaGate.Evaluate(1, area, occupancies); Assert.True(check.CanRelease); Assert.Equal(0, check.OthersInArea); } [Fact] public void Evaluate_OtherCarOnListedSite_EqualsCapacity_Blocks() { var area = Area(1, 10, 11); var occupancies = new List { new Fass2ControlOccupancy(1, new[] { 8 }), new Fass2ControlOccupancy(2, new[] { 11 }) }; var check = Fass2ControlAreaGate.Evaluate(1, area, occupancies); Assert.False(check.CanRelease); Assert.Equal(1, check.OthersInArea); Assert.Contains("capacity=1", check.Reason); } [Fact] public void Evaluate_OtherCarOutsideList_DoesNotBlock() { var area = Area(1, 10, 11); var occupancies = new List { new Fass2ControlOccupancy(2, new[] { 99 }) }; var check = Fass2ControlAreaGate.Evaluate(1, area, occupancies); Assert.True(check.CanRelease); Assert.Equal(0, check.OthersInArea); } [Fact] public void Evaluate_CapacityTwo_AllowsSecondCar() { var area = Area(2, 10, 11); var occupancies = new List { new Fass2ControlOccupancy(1, new[] { 10 }), new Fass2ControlOccupancy(2, new[] { 11 }) }; var check = Fass2ControlAreaGate.Evaluate(2, area, occupancies); Assert.True(check.CanRelease); Assert.Equal(1, check.OthersInArea); } [Fact] public void ActionResolver_ControlStop_IsNeverComplete() { var expected = Node(5, Fass2TaskBuilder.StartStopControlStop); var actual = Node(5, Fass2TaskBuilder.StartStopControlStop); Assert.True(Fass2ActionResolver.RequiresActionWait(expected)); Assert.False(Fass2ActionResolver.IsStationActionComplete(expected, actual, vehicleState: 2)); } private static Fass2ControlAreaInfo Area(int capacity, params int[] siteIds) { return new Fass2ControlAreaInfo { AreaSiteIds = siteIds, AreaId = string.Join(",", siteIds), Capacity = capacity, ReleaseStartStop = 11 }; } private static Fass2NodeMessage Node(ushort id, byte startStop) { return new Fass2NodeMessage { Node = id, StartStop = startStop }; } } }