Files
h-school/src/HSchool.Ai/Duty.cs
T
Leonid Pershin 4137400621
ci / server (push) Failing after 3m39s
ci / client (push) Successful in 14s
Enhance AI and simulation components with presence management and routing capabilities
- Introduced the `HSchool.Ai` project, responsible for routing, day plans, and presence management.
- Updated the `HSchool.Simulation` project to integrate with the new AI functionalities, improving decision-making and presence tracking.
- Added `travelMinutes` to room and territory definitions, ensuring accurate movement calculations within the simulation.
- Enhanced the `School` class to manage presence and implement empty-time skipping functionality.
- Updated documentation to reflect the new AI features and their impact on school simulation.
- Added tests for presence management and routing to ensure robust functionality and reliability.
2026-08-19 16:33:52 +03:00

158 lines
4.3 KiB
C#

using HSchool.Content;
using HSchool.People;
using HSchool.Schedule;
namespace HSchool.Ai;
/// <summary>
/// Where this person ought to be right now. The timetable and the job, not the walk graph.
/// </summary>
public static class Duty
{
/// <summary>
/// The room of the current obligation, or <see langword="null"/> when they should be off campus.
/// A hole in the class table sends the pupil to their homeroom.
/// </summary>
public static string? RoomAt(
Person person,
SchoolClass? schoolClass,
Timetable? timetable,
DefCatalog catalog,
DateTime time,
int weekDays)
{
ArgumentNullException.ThrowIfNull(person);
ArgumentNullException.ThrowIfNull(catalog);
if (!ComesToday(person, timetable, catalog, time, weekDays))
{
return null;
}
if (IsOtherStaff(person))
{
return person.WorkplaceRoomId;
}
var utc = DateTime.SpecifyKind(time, DateTimeKind.Utc);
if (!SchoolDay.IsWorkday(catalog, utc, weekDays))
{
return null;
}
var slot = SchoolDay.At(catalog, utc, weekDays);
var day = SchoolDay.WeekdayIndex(utc);
var lessons = LessonsToday(person, schoolClass, timetable, day);
if (lessons.Count == 0)
{
return person.WorkplaceRoomId;
}
if (slot.Kind == DaySlotKind.Lesson)
{
var current = lessons.FirstOrDefault(lesson => lesson.Period == slot.Index);
if (current is not null)
{
return current.RoomId;
}
return schoolClass?.RoomId ?? person.WorkplaceRoomId;
}
if (slot.Kind == DaySlotKind.Break)
{
var next = lessons.Where(lesson => lesson.Period > slot.Index).OrderBy(lesson => lesson.Period).FirstOrDefault();
return next?.RoomId ?? schoolClass?.RoomId ?? person.WorkplaceRoomId;
}
var frame = catalog.DayFrame;
if (frame is not null
&& SchoolDay.TryParseTime(frame.FirstLesson, out var first)
&& utc.TimeOfDay < first.ToTimeSpan())
{
return lessons[0].RoomId;
}
if (frame is not null
&& SchoolDay.TryLastBell(catalog, out var last)
&& utc.TimeOfDay >= last.ToTimeSpan())
{
return null;
}
return lessons[0].RoomId;
}
public static bool ComesToday(
Person person,
Timetable? timetable,
DefCatalog catalog,
DateTime time,
int weekDays)
{
if (person.IsParent && !person.IsStaff && !person.IsStudent)
{
return false;
}
if (!SchoolDay.IsWorkday(catalog, time, weekDays))
{
return false;
}
if (IsOtherStaff(person))
{
return true;
}
var day = SchoolDay.WeekdayIndex(time);
if (person.IsStudent)
{
return timetable?.Lessons.Any(lesson =>
lesson.ClassId == person.ClassId && lesson.Day == day) == true;
}
if (person.IsStaff)
{
return timetable?.Lessons.Any(lesson =>
lesson.TeacherId == person.Id && lesson.Day == day) == true;
}
return false;
}
public static bool IsOtherStaff(Person person) =>
person.IsStaff && !Staffing.TeacherPosition.Equals(person.Position, StringComparison.Ordinal);
public static IReadOnlyList<LessonPlacement> LessonsToday(
Person person,
SchoolClass? schoolClass,
Timetable? timetable,
int day)
{
if (timetable is null)
{
return [];
}
if (person.IsStudent)
{
var classId = person.ClassId ?? schoolClass?.Id;
return timetable.Lessons
.Where(lesson => lesson.ClassId == classId && lesson.Day == day)
.OrderBy(lesson => lesson.Period)
.ToArray();
}
if (person.IsStaff)
{
return timetable.Lessons
.Where(lesson => lesson.TeacherId == person.Id && lesson.Day == day)
.OrderBy(lesson => lesson.Period)
.ToArray();
}
return [];
}
}