Files
h-school/tests/HSchool.People.Tests/AffinityTests.cs
T
Leonid Pershin d2911c3daf Complete phase 47 romance pack on generic orientation and affinity hooks.
Vanilla catalogs stay without crushes; a content pack ships the overlay so later mods can reuse it.
2026-08-20 10:42:42 +03:00

196 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace HSchool.People.Tests;
public class AffinityTests
{
private static readonly DateTime AsOf = new(2012, 3, 31, 6, 0, 0, DateTimeKind.Utc);
[Fact]
public void SixteenYearOlds_NeverPair_AtAnyOpinion()
{
var catalog = Fixtures.RomanceCatalog();
var boy = Pupil("a", year: 10, age: 16, female: false, "Bisexual");
var girl = Pupil("b", year: 10, age: 16, female: true, "Bisexual");
SetOpinion(boy, girl.Id, 100);
SetOpinion(girl, boy.Id, 100);
var roster = RosterOf(boy, girl, classYear: 10);
Affinity.Refresh(catalog, roster, AsOf);
Assert.Contains("b", boy.Bonds!.Crushes);
Assert.Contains("a", girl.Bonds!.Crushes);
Assert.Null(boy.Bonds.PartnerId);
Assert.Null(girl.Bonds.PartnerId);
Assert.False(Affinity.CanFormPair(catalog, roster, boy, girl, AsOf));
}
[Fact]
public void FirstYear_DoesNotCrushEleventh()
{
var catalog = Fixtures.RomanceCatalog();
var young = Pupil("c1", year: 1, age: 7, female: true, "Bisexual", classId: "y1");
var old = Pupil("c11", year: 11, age: 17, female: false, "Bisexual", classId: "y11");
SetOpinion(young, old.Id, 100);
var roster = new Roster(
[young, old],
[],
[
new SchoolClass("y1", 1, "А", "r1", 16, [young.Id]),
new SchoolClass("y11", 11, "А", "r11", 16, [old.Id]),
]);
Affinity.Refresh(catalog, roster, AsOf);
Assert.DoesNotContain("c11", young.Bonds!.Crushes);
Assert.False(Affinity.CanHaveSympathy(catalog, roster, young, old, AsOf));
}
[Fact]
public void Staff_NeverGetsCrushOnStudent()
{
var catalog = Fixtures.RomanceCatalog();
var teacher = Staff("t", female: false, "Bisexual");
var pupil = Pupil("p", year: 8, age: 14, female: true, "Bisexual");
SetOpinion(teacher, pupil.Id, 100);
SetOpinion(pupil, teacher.Id, 100);
var roster = RosterOf(teacher, pupil, classYear: 8);
Affinity.Refresh(catalog, roster, AsOf);
Assert.DoesNotContain(pupil.Id, teacher.Bonds!.Crushes);
Assert.Contains(teacher.Id, pupil.Bonds!.Crushes);
Assert.Null(teacher.Bonds.PartnerId);
Assert.Null(pupil.Bonds.PartnerId);
Assert.False(Affinity.CanHaveSympathy(catalog, roster, teacher, pupil, AsOf));
Assert.True(Affinity.CanHaveSympathy(catalog, roster, pupil, teacher, AsOf));
}
[Fact]
public void StaffPair_IsAllowedWhenBothAdults()
{
var catalog = Fixtures.RomanceCatalog();
var left = Staff("s1", female: false, "Bisexual");
var right = Staff("s2", female: true, "Bisexual");
SetOpinion(left, right.Id, 80);
SetOpinion(right, left.Id, 80);
var roster = new Roster([left, right], [], []);
var events = Affinity.Refresh(catalog, roster, AsOf);
Assert.Equal(right.Id, left.Bonds!.PartnerId);
Assert.Equal(left.Id, right.Bonds!.PartnerId);
Assert.Contains(events, row => row.Type == Affinity.Pair);
}
[Fact]
public void PairBreak_BlocksNewPairUntilNextDay()
{
var catalog = Fixtures.RomanceCatalog();
var left = Staff("s1", female: false, "Bisexual");
var right = Staff("s2", female: true, "Bisexual");
var third = Staff("s3", female: true, "Bisexual");
SetOpinion(left, right.Id, 80);
SetOpinion(right, left.Id, 80);
var roster = new Roster([left, right, third], [], []);
Affinity.Refresh(catalog, roster, AsOf);
Assert.Equal(right.Id, left.Bonds!.PartnerId);
SetOpinion(left, right.Id, 0);
Affinity.Refresh(catalog, roster, AsOf);
Assert.Null(left.Bonds.PartnerId);
Assert.NotNull(left.Bonds.PairEndedOn);
SetOpinion(left, third.Id, 80);
SetOpinion(third, left.Id, 80);
Affinity.Refresh(catalog, roster, AsOf);
Assert.Null(left.Bonds.PartnerId);
Affinity.Refresh(catalog, roster, AsOf.AddDays(1));
Assert.Equal(third.Id, left.Bonds.PartnerId);
}
[Fact]
public void AdjacentYearStudents_CanHaveSympathy()
{
var catalog = Fixtures.RomanceCatalog();
var younger = Pupil("y", year: 9, age: 15, female: true, "Bisexual", classId: "c9");
var older = Pupil("o", year: 10, age: 18, female: false, "Bisexual", classId: "c10");
SetOpinion(younger, older.Id, 80);
var roster = new Roster(
[younger, older],
[],
[
new SchoolClass("c9", 9, "А", "r9", 16, [younger.Id]),
new SchoolClass("c10", 10, "А", "r10", 16, [older.Id]),
]);
Assert.True(Affinity.CanHaveSympathy(catalog, roster, younger, older, AsOf));
Affinity.Refresh(catalog, roster, AsOf);
Assert.Contains(older.Id, younger.Bonds!.Crushes);
}
private static void SetOpinion(Person person, string targetId, int value)
{
if (value == 0)
{
OpinionStore.Remove(person, targetId);
return;
}
OpinionStore.Set(person, targetId, value);
}
private static Roster RosterOf(Person first, Person second, int classYear)
{
var pupils = new[] { first, second }.Where(person => person.IsStudent).Select(person => person.Id).ToArray();
return new Roster(
[first, second],
[],
[new SchoolClass("c", classYear, "А", "room", 16, pupils)]);
}
private static Person Pupil(string id, int year, int age, bool female, string orientation, string? classId = null)
{
_ = year;
var birth = AsOf.AddYears(-age);
return AdultLike(id, female, orientation, isStudent: true, isStaff: false, birth, classId ?? "c");
}
private static Person Staff(string id, bool female, string orientation) =>
AdultLike(id, female, orientation, isStudent: false, isStaff: true, AsOf.AddYears(-30), classId: null);
private static Person AdultLike(
string id,
bool female,
string orientation,
bool isStudent,
bool isStaff,
DateTime birth,
string? classId)
{
var cases = new CaseTable
{
Nom = id,
Gen = id,
Dat = id,
Acc = id,
Ins = id,
Pre = id,
};
return new Person
{
Id = id,
FamilyId = "f",
Female = female,
BirthDate = DateTime.SpecifyKind(birth, DateTimeKind.Utc),
Name = new PersonName(id, id, id, cases, cases, cases),
IsStudent = isStudent,
IsStaff = isStaff,
IsParent = false,
ClassId = classId,
Numbers = new Dictionary<string, int>(StringComparer.Ordinal),
Choices = new Dictionary<string, string>(StringComparer.Ordinal),
Skills = new Dictionary<string, int>(StringComparer.Ordinal),
Traits = [],
Needs = new Dictionary<string, float>(StringComparer.Ordinal),
Opinions = new Dictionary<string, int>(StringComparer.Ordinal),
Orientation = orientation,
Bonds = new PersonBonds(),
};
}
}