Files
h-school/tests/HSchool.Server.Tests/PortraitVisibleWornTests.cs
T
Leonid Pershin 81fd3f6181 Split SwarmUI portraits into a model catalog and layered prompts.
Picker is Swarm intersect config, preset style/shot inherit model defaults, and living saves lift the old preset shape.
2026-08-20 14:08:11 +03:00

161 lines
5.1 KiB
C#

using HSchool.Content;
using HSchool.Server.Api;
using HSchool.Server.Game;
namespace HSchool.Server.Tests;
public class PortraitVisibleWornTests
{
[Fact]
public void Filter_ExcludesUnderwearUnderIntactPants()
{
var visible = PortraitVisibleWorn.Filter(
[
Item("Underwear", ApparelLayers.Underwear, covers: []),
Item("Pants", ApparelLayers.Bottom, covers: [ApparelLayers.Underwear]),
]).Select(item => item.DefName).ToList();
Assert.Equal(["Pants"], visible);
}
[Fact]
public void Filter_KeepsUnderwearWhenPantsAreTorn()
{
var visible = PortraitVisibleWorn.Filter(
[
Item("Underwear", ApparelLayers.Underwear, covers: [], condition: 1f),
Item("Pants", ApparelLayers.Bottom, covers: [ApparelLayers.Underwear], condition: 0.2f),
]).Select(item => item.DefName).ToList();
Assert.Contains("Underwear", visible);
Assert.Contains("Pants", visible);
}
[Fact]
public void Filter_ExcludesBraUnderIntactShirt()
{
var visible = PortraitVisibleWorn.Filter(
[
Item("Bra", ApparelLayers.UpperUnderwear, covers: []),
Item("Shirt", ApparelLayers.Top, covers: [ApparelLayers.Underwear, ApparelLayers.UpperUnderwear]),
]).Select(item => item.DefName).ToList();
Assert.Equal(["Shirt"], visible);
}
[Fact]
public void Filter_KeepsBraWhenShirtIsTorn()
{
var visible = PortraitVisibleWorn.Filter(
[
Item("Bra", ApparelLayers.UpperUnderwear, covers: [], condition: 1f),
Item("Shirt", ApparelLayers.Top, covers: [ApparelLayers.Underwear, ApparelLayers.UpperUnderwear], condition: 0.2f),
]).Select(item => item.DefName).ToList();
Assert.Contains("Bra", visible);
Assert.Contains("Shirt", visible);
}
[Fact]
public void Filter_KeepsBraWhenOnlyPantsCoverUnderwear()
{
var visible = PortraitVisibleWorn.Filter(
[
Item("Panties", ApparelLayers.Underwear, covers: []),
Item("Bra", ApparelLayers.UpperUnderwear, covers: []),
Item("Pants", ApparelLayers.Bottom, covers: [ApparelLayers.Underwear]),
]).Select(item => item.DefName).ToList();
Assert.DoesNotContain("Panties", visible);
Assert.Contains("Bra", visible);
Assert.Contains("Pants", visible);
}
[Fact]
public void Filter_KeepsShirtWithPants()
{
var visible = PortraitVisibleWorn.Filter(
[
Item("Shirt", ApparelLayers.Top, covers: [ApparelLayers.Underwear]),
Item("Pants", ApparelLayers.Bottom, covers: [ApparelLayers.Underwear]),
]).Select(item => item.DefName).ToList();
Assert.Contains("Shirt", visible);
Assert.Contains("Pants", visible);
}
[Fact]
public void Filter_ExcludesShirtUnderSweater()
{
var visible = PortraitVisibleWorn.Filter(
[
Item("Shirt", ApparelLayers.Top, covers: [ApparelLayers.Underwear]),
Item("Sweater", ApparelLayers.OverTop, covers: [ApparelLayers.Underwear, ApparelLayers.Top]),
]).Select(item => item.DefName).ToList();
Assert.Equal(["Sweater"], visible);
}
[Fact]
public void Build_OmitsCoveredShirtFromPrompt()
{
var preset = SwarmUiPresetDefinition.CreateDefault();
preset.Style = "School photo.";
var card = SampleCard(
[
Item("Shirt", ApparelLayers.Top, covers: [ApparelLayers.Underwear], color: "White", colorLabel: "White"),
Item("Coat", ApparelLayers.Outer, covers: [ApparelLayers.Underwear, ApparelLayers.Top, ApparelLayers.OverTop, ApparelLayers.Bottom], color: "Black", colorLabel: "Black"),
]);
var (positive, _) = PortraitPromptBuilder.Build(card, preset.ToProfile(PortraitKind.Avatar), PortraitKind.Avatar);
Assert.Contains("coat", positive, StringComparison.OrdinalIgnoreCase);
Assert.DoesNotContain("shirt", positive, StringComparison.OrdinalIgnoreCase);
}
private static WornItemResponse Item(
string defName,
string layer,
IReadOnlyList<string> covers,
string? color = null,
string? colorLabel = null,
float condition = 1f) =>
new(
defName,
defName,
color,
colorLabel,
[new DefLabelResponse(layer, layer)],
condition,
"new",
covers);
private static PersonCardResponse SampleCard(IReadOnlyList<WornItemResponse> worn) =>
new(
"f0.c0",
"Maria Ivanova",
"Ivanova",
"Maria",
"",
true,
12,
new DateTime(2000, 3, 14, 0, 0, 0, DateTimeKind.Utc),
["student"],
5,
"A",
"class-1",
null,
null,
[],
[],
[],
[],
null,
null,
new PersonFamilyResponse([], [], [], []),
worn,
[],
0f,
0f);
}