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(StringComparer.Ordinal), Choices = new Dictionary(StringComparer.Ordinal), Skills = new Dictionary(StringComparer.Ordinal), Traits = [], Needs = new Dictionary(StringComparer.Ordinal), Opinions = new Dictionary(StringComparer.Ordinal), Orientation = orientation, Bonds = new PersonBonds(), }; } }