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.
This commit is contained in:
@@ -0,0 +1,195 @@
|
||||
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(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,19 @@ internal static class Fixtures
|
||||
PackDocuments.FromDirectory(CatalogLoader.CorePackId, root));
|
||||
}
|
||||
|
||||
public static DefCatalog RomanceCatalog()
|
||||
{
|
||||
var vanilla = Path.Combine(AppContext.BaseDirectory, "vanilla");
|
||||
var romance = Path.Combine(AppContext.BaseDirectory, "romance");
|
||||
Assert.True(Directory.Exists(romance), $"Romance pack was not copied to {romance}.");
|
||||
return new CatalogLoader().Load(
|
||||
[CatalogLoader.CorePackId, "romance"],
|
||||
[
|
||||
.. PackDocuments.FromDirectory(CatalogLoader.CorePackId, vanilla),
|
||||
.. PackDocuments.FromDirectory("romance", romance),
|
||||
]);
|
||||
}
|
||||
|
||||
public static MapLayout Classrooms(int count, int desks = 16)
|
||||
{
|
||||
var rooms = new RoomNode[count];
|
||||
|
||||
@@ -30,6 +30,10 @@
|
||||
<Link>example\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\..\src\HSchool.Server\mods\romance\**\*">
|
||||
<Link>romance\%(RecursiveDir)%(Filename)%(Extension)</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="golden\**\*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
namespace HSchool.People.Tests;
|
||||
|
||||
public class OrientationGeneratorTests
|
||||
{
|
||||
[Fact]
|
||||
public void VanillaGenerate_DoesNotWriteOrientation()
|
||||
{
|
||||
var roster = Fixtures.Generate(Fixtures.Classrooms(2));
|
||||
Assert.All(roster.People, person => Assert.Null(person.Orientation));
|
||||
Assert.All(roster.People, person => Assert.Null(person.Bonds));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void RomanceGenerate_WritesOrientationToEveryone()
|
||||
{
|
||||
var catalog = Fixtures.RomanceCatalog();
|
||||
var roster = RosterGenerator.Generate(catalog, Fixtures.Classrooms(2), Fixtures.SchoolSeed, "Russia", Fixtures.AsOf, "RussianLanguage");
|
||||
Assert.NotEmpty(roster.People);
|
||||
Assert.All(roster.People, person =>
|
||||
{
|
||||
Assert.False(string.IsNullOrWhiteSpace(person.Orientation));
|
||||
Assert.True(catalog.Orientations.ContainsKey(person.Orientation!));
|
||||
Assert.NotNull(person.Bonds);
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SameSeed_YieldsTheSameOrientations()
|
||||
{
|
||||
var catalog = Fixtures.RomanceCatalog();
|
||||
var a = RosterGenerator.Generate(catalog, Fixtures.Classrooms(2), Fixtures.SchoolSeed, "Russia", Fixtures.AsOf, "RussianLanguage");
|
||||
var b = RosterGenerator.Generate(catalog, Fixtures.Classrooms(2), Fixtures.SchoolSeed, "Russia", Fixtures.AsOf, "RussianLanguage");
|
||||
Assert.Equal(
|
||||
a.People.Select(person => (person.Id, person.Orientation)),
|
||||
b.People.Select(person => (person.Id, person.Orientation)));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user