Wire sick-teacher stay-home into cancelled lessons.
Heavy flu keeps the assigned teacher off the day plan; pupils get 48/73 no-teacher marks and a one-shot LessonCancelled notice instead of silent empty rooms.
This commit is contained in:
@@ -17,6 +17,7 @@ internal static class EventDefValidator
|
||||
EventTriggers.DirectorSummon,
|
||||
EventTriggers.ParentMeeting,
|
||||
EventTriggers.DiseaseOutbreak,
|
||||
EventTriggers.LessonNoTeacher,
|
||||
};
|
||||
|
||||
private static readonly HashSet<string> Actions = new(StringComparer.Ordinal)
|
||||
|
||||
@@ -15,6 +15,7 @@ public static class EventTriggers
|
||||
public const string DirectorSummon = "directorSummon";
|
||||
public const string ParentMeeting = "parentMeeting";
|
||||
public const string DiseaseOutbreak = "diseaseOutbreak";
|
||||
public const string LessonNoTeacher = "lessonNoTeacher";
|
||||
}
|
||||
|
||||
public static class EventActions
|
||||
|
||||
@@ -47,4 +47,12 @@
|
||||
"trigger": "diseaseOutbreak",
|
||||
"action": "none",
|
||||
},
|
||||
{
|
||||
"defName": "LessonCancelled",
|
||||
"severity": "info",
|
||||
"pause": false,
|
||||
"ttlMs": 8000,
|
||||
"trigger": "lessonNoTeacher",
|
||||
"action": "none",
|
||||
},
|
||||
]
|
||||
|
||||
@@ -237,6 +237,7 @@
|
||||
"DirectorSummoned": "A pupil was summoned to the principal",
|
||||
"ParentMeeting": "A parent meeting is under way",
|
||||
"DiseaseOutbreak": "An illness is spreading at school",
|
||||
"LessonCancelled": "Lesson without a teacher",
|
||||
"GoingToPrincipal": "going to the principal",
|
||||
"WaitForPrincipal": "waiting at the principal's office",
|
||||
"GoingToParentMeeting": "going to a parent meeting",
|
||||
|
||||
@@ -237,6 +237,7 @@
|
||||
"DirectorSummoned": "Ученика вызвали к директору",
|
||||
"ParentMeeting": "Идёт родительское собрание",
|
||||
"DiseaseOutbreak": "В школе распространяется болезнь",
|
||||
"LessonCancelled": "Урок без учителя",
|
||||
"GoingToPrincipal": "идёт к директору",
|
||||
"WaitForPrincipal": "ждёт у кабинета директора",
|
||||
"GoingToParentMeeting": "идёт на собрание",
|
||||
|
||||
@@ -54,6 +54,8 @@ internal static class LessonLearningSystem
|
||||
teacherSkills[identity.Id] = personSkills.Values;
|
||||
});
|
||||
|
||||
RaiseSickTeacherLessons(school, places, weekday, slot.Index);
|
||||
|
||||
world.Query(
|
||||
in People,
|
||||
(ref PersonIdentity identity, ref PersonSkills skills, ref PersonTraits traits, ref PersonNeeds needs, ref PersonRoles roles, ref Presence presence, ref PersonActivity activity) =>
|
||||
@@ -208,6 +210,56 @@ internal static class LessonLearningSystem
|
||||
&& teacher.NodeId is not null
|
||||
&& teacher.NodeId.Equals(roomId, StringComparison.Ordinal);
|
||||
|
||||
/// <summary>
|
||||
/// One school toast per class slot when the assigned teacher stayed home sick (slice 15).
|
||||
/// Uses the morning day plan — re-rolling <see cref="DiseaseEffects.ShouldStayHome"/> at
|
||||
/// lesson time can flip after severity ticks. Toilet trips keep the per-pupil log only.
|
||||
/// </summary>
|
||||
private static void RaiseSickTeacherLessons(
|
||||
School school,
|
||||
Dictionary<string, Presence> places,
|
||||
int weekday,
|
||||
int period)
|
||||
{
|
||||
if (school.Timetable is null || school.Roster is null || school.Catalog is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var lesson in school.Timetable.Lessons)
|
||||
{
|
||||
if (lesson.Day != weekday || lesson.Period != period)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TeacherStandingIn(places, lesson.TeacherId, lesson.RoomId))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!school.Plans.TryGetValue(lesson.TeacherId, out var plan) || plan.Comes)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var teacher = school.Roster.People.FirstOrDefault(row =>
|
||||
row.Id.Equals(lesson.TeacherId, StringComparison.Ordinal));
|
||||
if (teacher is null
|
||||
|| DiseaseEffects.StayHomeChance(teacher, school.Catalog, school.Clock.Time) <= 0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!school.TryClaimLessonNoTeacherEvent(lesson.ClassId, school.Clock.Time.Date, lesson.Period))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
school.RaiseWorldEvent(new WorldEvent(EventTriggers.LessonNoTeacher, lesson.TeacherId));
|
||||
}
|
||||
}
|
||||
|
||||
private static LessonPlacement? CurrentLesson(School school, Person person, int weekday, int period)
|
||||
{
|
||||
foreach (var lesson in Duty.LessonsToday(person, ClassOf(school, person), school.Timetable, weekday))
|
||||
|
||||
@@ -19,6 +19,7 @@ public sealed class School : IDisposable
|
||||
private readonly List<PersonLogEvent> _dayLog = [];
|
||||
private readonly HashSet<string> _lessonLogOnce = new(StringComparer.Ordinal);
|
||||
private readonly HashSet<string> _lessonMarkOnce = new(StringComparer.Ordinal);
|
||||
private readonly HashSet<string> _lessonNoTeacherEventOnce = new(StringComparer.Ordinal);
|
||||
private readonly List<WorldEvent> _worldEvents = [];
|
||||
|
||||
internal School(int id, string name, DateTime startDate, DefCatalog? catalog, MapLayout? map)
|
||||
@@ -176,6 +177,7 @@ public sealed class School : IDisposable
|
||||
LoggedActivity.Clear();
|
||||
_lessonLogOnce.Clear();
|
||||
_lessonMarkOnce.Clear();
|
||||
_lessonNoTeacherEventOnce.Clear();
|
||||
LastAttendanceSlot = null;
|
||||
}
|
||||
|
||||
@@ -205,6 +207,15 @@ public sealed class School : IDisposable
|
||||
return _lessonMarkOnce.Add(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// One school toast per class lesson slot when the assigned teacher stays home sick.
|
||||
/// </summary>
|
||||
internal bool TryClaimLessonNoTeacherEvent(string classId, DateTime day, int period)
|
||||
{
|
||||
var key = string.Concat(classId, "\0", day.ToString("yyyy-MM-dd"), "\0", period.ToString());
|
||||
return _lessonNoTeacherEventOnce.Add(key);
|
||||
}
|
||||
|
||||
public void QueueDecision(string personId)
|
||||
{
|
||||
ObjectDisposedException.ThrowIf(_disposed, this);
|
||||
|
||||
Reference in New Issue
Block a user