using HSchool.Content; using HSchool.Server.Game; using HSchool.Simulation; namespace HSchool.Server.Tests; public class PortraitSceneCollectorTests { private static readonly SimulationOptions Budget = new(); private readonly CatalogLoader _loader = new(); [Fact] public void Classroom_IncludesBlackboardPhrase_OfficeWithoutBoardDoesNot() { var catalog = LoadCatalog(); var map = SampleMap(); var withBoard = PortraitSceneCollector.Collect( catalog, map, "class-1", Precipitation.None, "TestClimate", [], [], Budget); var withoutBoard = PortraitSceneCollector.Collect( catalog, map, "chairs", Precipitation.None, "TestClimate", [], [], Budget); Assert.Contains(withBoard.PositiveFragments, fragment => fragment.Contains("blackboard", StringComparison.OrdinalIgnoreCase)); Assert.DoesNotContain(withoutBoard.PositiveFragments, fragment => fragment.Contains("blackboard", StringComparison.OrdinalIgnoreCase)); Assert.DoesNotContain(withoutBoard.PositiveFragments, fragment => fragment.Contains("chair", StringComparison.OrdinalIgnoreCase)); } [Fact] public void FillBlackboard_IsIncluded_ChairFillIsSilent() { var catalog = LoadCatalog(); var map = SampleMap(); var office = PortraitSceneCollector.Collect( catalog, map, "office", Precipitation.None, "TestClimate", [], [], Budget); Assert.Contains(office.PositiveFragments, fragment => fragment.Contains("blackboard", StringComparison.OrdinalIgnoreCase)); Assert.DoesNotContain(office.PositiveFragments, fragment => fragment.Contains("chair", StringComparison.OrdinalIgnoreCase)); } [Fact] public void Snow_OnlyOutdoors() { var catalog = LoadCatalog(); var map = SampleMap(); var yard = PortraitSceneCollector.Collect( catalog, map, "yard", Precipitation.Snow, "TestClimate", [], [], Budget); var indoor = PortraitSceneCollector.Collect( catalog, map, "class-1", Precipitation.Snow, "TestClimate", [], [], Budget); Assert.Contains(yard.PositiveFragments, fragment => fragment.Contains("snow", StringComparison.OrdinalIgnoreCase)); Assert.DoesNotContain(indoor.PositiveFragments, fragment => fragment.Contains("snow", StringComparison.OrdinalIgnoreCase)); } [Fact] public void MoreThanSixCandidates_KeepsTopWeightsThenDefName() { var catalog = LoadCatalog(); var map = SampleMap(); var options = new SimulationOptions { PortraitSceneFragmentLimit = 6 }; var scene = PortraitSceneCollector.Collect( catalog, map, "ranked", Precipitation.None, "TestClimate", [], [], options); Assert.Equal(6, scene.PositiveFragments.Count); Assert.Contains("frag-w7", scene.PositiveFragments); Assert.Contains("frag-w2", scene.PositiveFragments); Assert.DoesNotContain("frag-w1", scene.PositiveFragments); Assert.Equal( ["frag-w7", "frag-w6", "frag-w5", "frag-w4", "frag-w3", "frag-w2"], scene.PositiveFragments); } [Fact] public void EqualWeight_BreaksTiesByDefName() { var catalog = LoadCatalog(); var map = SampleMap(); var options = new SimulationOptions { PortraitSceneFragmentLimit = 1 }; var scene = PortraitSceneCollector.Collect( catalog, map, "tie", Precipitation.None, "TestClimate", [], [], options); Assert.Equal(["alpha-tie"], scene.PositiveFragments); Assert.DoesNotContain("zeta-tie", scene.PositiveFragments); } [Fact] public void SceneLora_GoesToLoras_EmbeddingGoesToTextTags() { var catalog = LoadCatalog(); var map = SampleMap(); var scene = PortraitSceneCollector.Collect( catalog, map, "props", Precipitation.None, "TestClimate", [], [], Budget); Assert.Equal(["snow.safetensors"], scene.PositiveLoras.Select(entry => entry.Name)); Assert.Equal(["winter-embed"], scene.PositiveEmbeddings.Select(entry => entry.Name)); Assert.DoesNotContain(scene.PositiveFragments, fragment => fragment.Contains("snow.safetensors", StringComparison.Ordinal)); Assert.DoesNotContain(scene.PositiveFragments, fragment => fragment.Contains(" new() { Territory = new TerritoryNode { Id = "yard", Def = "SchoolYard" }, Rooms = [ new RoomNode { Id = "class-1", Def = "Classroom", Building = "main", Floor = "f1", Seats = 16, }, new RoomNode { Id = "office", Def = "Office", Building = "main", Floor = "f1", Slots = [new SlotFill { Key = "board", Thing = "Blackboard" }], }, new RoomNode { Id = "chairs", Def = "Office", Building = "main", Floor = "f1", Slots = [new SlotFill { Key = "seat", Thing = "Chair" }], }, new RoomNode { Id = "ranked", Def = "Office", Building = "main", Floor = "f1", Slots = [ new SlotFill { Key = "a", Thing = "W7" }, new SlotFill { Key = "b", Thing = "W6" }, new SlotFill { Key = "c", Thing = "W5" }, new SlotFill { Key = "d", Thing = "W4" }, new SlotFill { Key = "e", Thing = "W3" }, new SlotFill { Key = "f", Thing = "W2" }, new SlotFill { Key = "g", Thing = "W1" }, ], }, new RoomNode { Id = "tie", Def = "Office", Building = "main", Floor = "f1", Slots = [ new SlotFill { Key = "zeta", Thing = "ZetaTie" }, new SlotFill { Key = "alpha", Thing = "AlphaTie" }, ], }, new RoomNode { Id = "props", Def = "Office", Building = "main", Floor = "f1", Slots = [new SlotFill { Key = "prop", Thing = "Prop" }], }, ], }; }