using HSchool.Ai; using HSchool.Content; using HSchool.People; using HSchool.Schedule; namespace HSchool.Simulation; /// Builds apparel goal inputs for the decision planner. internal static class ApparelPresence { public static ApparelActor Build(School school, Person person, SchoolClass? schoolClass) { if (school.Catalog is null || !person.IsStudent && !person.IsStaff) { return default; } var mode = ModeAt(school, person, schoolClass); var issues = ApparelDresser.CurrentIssues(school, person, mode); var kind = ApparelGoals.Classify(issues); var room = ChangingRoomNode(school, person); return new ApparelActor(person.Female, issues, kind, room); } public static void EnqueueOnWeatherChange(School school, OutdoorWeather before, OutdoorWeather after) { if (before.Tenths == after.Tenths && before.Precipitation == after.Precipitation) { return; } foreach (var person in school.Roster!.People.OrderBy(row => row.Id, StringComparer.Ordinal)) { school.DecisionQueue.Enqueue(person.Id); } } internal static ApparelMode ModeAt(School school, Person person, SchoolClass? schoolClass) { if (school.Catalog is null || school.Timetable is null) { return ApparelMode.Everyday; } var slot = SchoolDay.At(school.Catalog, school.Clock.Time, school.SchoolWeekDays); var day = SchoolDay.WeekdayIndex(school.Clock.Time); var lessons = Duty.LessonsToday(person, schoolClass, school.Timetable, day); if (lessons.Count == 0) { return ApparelMode.Everyday; } if (slot.Kind == DaySlotKind.Lesson) { var current = lessons.FirstOrDefault(lesson => lesson.Period == slot.Index); return ApparelDresser.ModeForLesson(current?.Subject); } if (slot.Kind == DaySlotKind.Break) { var justEnded = lessons.FirstOrDefault(lesson => lesson.Period == slot.Index); if (justEnded is not null && ApparelDresser.ModeForLesson(justEnded.Subject) == ApparelMode.Pe) { return ApparelMode.Everyday; } var next = lessons.Where(lesson => lesson.Period > slot.Index).OrderBy(lesson => lesson.Period).FirstOrDefault(); if (next is not null) { return ApparelDresser.ModeForLesson(next.Subject); } return ApparelMode.Everyday; } var nextLesson = lessons.Where(lesson => lesson.Period > slot.Index).OrderBy(lesson => lesson.Period).FirstOrDefault(); if (nextLesson is not null) { return ApparelDresser.ModeForLesson(nextLesson.Subject); } var previous = lessons.Where(lesson => lesson.Period < slot.Index).OrderByDescending(lesson => lesson.Period).FirstOrDefault(); if (previous is not null && ApparelDresser.ModeForLesson(previous.Subject) == ApparelMode.Pe) { return ApparelMode.Everyday; } return ApparelMode.Everyday; } internal static string? ChangingRoomNode(School school, Person person) { if (person.LockerRoomId is { } assigned) { return assigned; } if (school.Map is null || school.Catalog is null) { return null; } var want = ApparelDresser.ChangingRoomDef(person.Female); if (want is null) { return null; } return school.Map.Rooms .FirstOrDefault(room => room.Def.Equals(want, StringComparison.Ordinal)) ?.Id; } }