Merge branch 'review/slice-9-cd'

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 14:39:07 +03:00
co-authored by Cursor
6 changed files with 115 additions and 1 deletions
@@ -104,6 +104,24 @@ public class AffinityTests
Assert.Equal(third.Id, left.Bonds.PartnerId);
}
[Fact]
public void PupilTalkWithTeacherCrush_WritesRebuffAndDropsOpinion()
{
var catalog = Fixtures.RomanceCatalog();
var teacher = Staff("t", female: false, "Bisexual");
var pupil = Pupil("p", year: 8, age: 14, female: true, "Bisexual");
SetOpinion(pupil, teacher.Id, 80);
var roster = RosterOf(teacher, pupil, classYear: 8);
Affinity.Refresh(catalog, roster, AsOf);
Assert.Contains(teacher.Id, pupil.Bonds!.Crushes);
var before = OpinionStore.Get(pupil, teacher.Id) ?? 0;
var events = Affinity.RebuffTalk(catalog, roster, [pupil.Id, teacher.Id], AsOf);
Assert.Contains(events, row => row.Type == Affinity.Rebuff && row.PersonId == pupil.Id);
Assert.True((OpinionStore.Get(pupil, teacher.Id) ?? 0) < before);
}
[Fact]
public void AdjacentYearStudents_CanHaveSympathy()
{
@@ -66,6 +66,22 @@ public class OpinionGeneratorTests
Assert.Equal(before, loadedChild.Opinions[parentId]);
}
[Fact]
public void RosterJson_RoundTripsBullyVictimId()
{
var roster = Fixtures.Generate(Fixtures.Classrooms(4));
var bully = roster.People.First(person => person.IsStudent && !person.IsParent);
var victim = roster.People.First(person =>
person.IsStudent && !person.Id.Equals(bully.Id, StringComparison.Ordinal));
bully.BullyVictimId = victim.Id;
var json = RosterJson.Serialize(RosterDocument.From(1, roster));
Assert.Contains("\"bullyVictimId\"", json, StringComparison.Ordinal);
var loaded = RosterJson.Parse(json).ToRoster();
var loadedBully = loaded.People.First(person => person.Id.Equals(bully.Id, StringComparison.Ordinal));
Assert.Equal(victim.Id, loadedBully.BullyVictimId);
}
[Fact]
public void SaveWithoutOpinionsField_SeedsFamilyOnLoad()
{
@@ -50,6 +50,51 @@ public class QuarrelFightTests
}
}
[Fact]
public void QuarrelFinish_MarksTickPeopleChangedSoSaveWritesOpinions()
{
var (school, first, second) = TwoPupilsOnBreak();
using (school)
{
const int baseline = -55;
OpinionStore.Set(first, second.Id, baseline);
OpinionStore.Set(second, first.Id, baseline);
PlaceAt(school, first.Id, "yard");
PlaceAt(school, second.Id, "yard");
Assert.True(school.TryStartAction(first.Id, TalkActions.QuarrelYard));
var peopleChanged = false;
for (var i = 0; i < 12 && ActivityOf(school, first.Id) == TalkActions.QuarrelYard; i++)
{
peopleChanged |= school.Tick(0.2d, 5d);
}
Assert.True(peopleChanged);
Assert.True((OpinionStore.Get(first, second.Id) ?? 0) < baseline);
}
}
[Fact]
public void BullyPickingAVictim_DirtiesRosterSoSaveKeepsTheId()
{
var (school, first, second) = TwoPupilsOnBreak();
using (school)
{
GiveTrait(school, first.Id, "Bully");
var bully = school.Roster!.People.First(person => person.Id == first.Id);
var other = school.Roster.People.First(person => person.Id == second.Id);
OpinionStore.Set(bully, other.Id, -55);
OpinionStore.Set(other, bully.Id, -55);
PlaceAt(school, bully.Id, "yard");
PlaceAt(school, other.Id, "yard");
school.RosterTalkDirty = false;
Assert.True(school.TryStartAction(bully.Id, TalkActions.QuarrelYard));
Assert.NotNull(bully.BullyVictimId);
Assert.True(school.RosterTalkDirty);
}
}
[Fact]
public void Apology_RaisesOpinion_ButNotAbovePreQuarrel()
{