Files
h-school/tests/HSchool.People.Tests/DiseaseEffectTests.cs
T
Leonid Pershin 2d633411e4 Add DiseaseDef diseases with weather vectors and excused absence.
Vanilla ships several diseases whose stages drive lesson gain, stay-home
rolls, and illness attendance; cold/rain/snow raise onset via BehaviorDef scale.
2026-08-21 13:28:57 +03:00

162 lines
5.6 KiB
C#

using HSchool.Content;
namespace HSchool.People.Tests;
public class DiseaseEffectTests
{
[Fact]
public void TwoDiseaseDefs_YieldDifferentSeverityCurves()
{
var catalog = LoadVanilla();
var cold = catalog.Diseases["CommonCold"];
var flu = catalog.Diseases["Influenza"];
var started = new DateTime(2012, 4, 3, 8, 0, 0, DateTimeKind.Utc);
var a = Blank("p1");
var b = Blank("p1");
HealthConditions.Add(a, Onset(cold.DefName, started, severity: 0.1f));
HealthConditions.Add(b, Onset(flu.DefName, started, severity: 0.1f));
Assert.True(HealthConditions.Tick(a, peopleSeed: 7, dayNumber: 100, gameMinutes: 24 * 60, catalog, started));
Assert.True(HealthConditions.Tick(b, peopleSeed: 7, dayNumber: 100, gameMinutes: 24 * 60, catalog, started));
Assert.NotEqual(a.Conditions![0].Severity, b.Conditions![0].Severity);
Assert.True(a.Conditions[0].Severity > 0.1f);
Assert.True(b.Conditions[0].Severity > 0.1f);
}
[Fact]
public void HeavyStage_StaysHomeMoreOftenThanMild()
{
var catalog = LoadVanilla();
var started = new DateTime(2012, 1, 1, 6, 0, 0, DateTimeKind.Utc);
var mild = Blank("pupil");
var heavy = Blank("pupil");
HealthConditions.Add(mild, Onset("Influenza", started, severity: 0.1f));
HealthConditions.Add(heavy, Onset("Influenza", started, severity: 0.8f));
// Past incubation so stage effects apply. Same person, different days — the day salt varies the roll.
var day = started.AddDays(2);
var mildHome = 0;
var heavyHome = 0;
for (var i = 0; i < 200; i++)
{
var when = day.AddDays(i);
if (DiseaseEffects.ShouldStayHome(mild, catalog, peopleSeed: 11, when))
{
mildHome++;
}
if (DiseaseEffects.ShouldStayHome(heavy, catalog, peopleSeed: 11, when))
{
heavyHome++;
}
}
Assert.True(heavyHome > mildHome);
Assert.True(heavyHome > 100);
}
[Fact]
public void Attendance_IllnessReason_IsNotTruancy()
{
var person = Blank("p1");
var rules = new BehaviorDef { DefName = "Behavior", AttendanceMax = 10 };
var time = new DateTime(2012, 4, 3, 9, 15, 0, DateTimeKind.Utc);
Assert.True(AttendanceMemory.Record(
person,
"Mathematics",
AttendanceStatuses.Absent,
time,
period: 1,
rules,
AbsenceReasons.Illness));
Assert.Equal(AbsenceReasons.Illness, person.Attendance![0].AbsenceReason);
Assert.NotEqual(AbsenceReasons.Truancy, person.Attendance[0].AbsenceReason);
var json = RosterJson.Serialize(RosterDocument.From(1, new Roster([person], [], [])));
var loaded = RosterJson.Parse(json).ToRoster().People[0];
Assert.Equal(AbsenceReasons.Illness, loaded.Attendance![0].AbsenceReason);
}
[Fact]
public void Recovery_GrantsTemporaryImmunity()
{
var catalog = LoadVanilla();
var started = new DateTime(2012, 4, 3, 8, 0, 0, DateTimeKind.Utc);
var person = Blank("p1");
HealthConditions.Add(
person,
new HealthCondition
{
DefName = "CommonCold",
Severity = 0.2f,
Progress = 0.99f,
Source = "cold",
StartedAt = started,
});
Assert.True(HealthConditions.Tick(
person,
peopleSeed: 3,
dayNumber: 50,
gameMinutes: 24 * 60 * 3,
catalog,
started.AddDays(1)));
Assert.Null(person.Conditions);
Assert.NotNull(person.DiseaseImmunities);
Assert.Equal("CommonCold", person.DiseaseImmunities![0].DefName);
Assert.True(person.DiseaseImmunities[0].Until > started);
Assert.True(DiseaseImmunities.IsImmune(person, "CommonCold", started.AddDays(2)));
}
private static HealthCondition Onset(string defName, DateTime started, float severity) =>
new()
{
DefName = defName,
Severity = severity,
Progress = 0f,
Source = "cold",
StartedAt = DateTime.SpecifyKind(started, DateTimeKind.Utc),
};
private static DefCatalog LoadVanilla()
{
var root = Path.Combine(AppContext.BaseDirectory, "vanilla");
return new CatalogLoader().Load(
[CatalogLoader.CorePackId],
PackDocuments.FromDirectory(CatalogLoader.CorePackId, root));
}
private static Person Blank(string id)
{
var cases = new CaseTable
{
Nom = id,
Gen = id,
Dat = id,
Acc = id,
Ins = id,
Pre = id,
};
return new Person
{
Id = id,
FamilyId = "f",
Female = false,
BirthDate = new DateTime(2000, 1, 1, 0, 0, 0, DateTimeKind.Utc),
Name = new PersonName(id, id, id, cases, cases, cases),
IsStudent = true,
IsStaff = false,
IsParent = false,
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),
};
}
}