namespace HSchool.People;
public readonly record struct StaffOpening(string RoomId, string Position);
public readonly record struct PupilSeat(string ClassId, string RoomId, int Year, string Letter);
///
/// How many pupils and staff a map asks for. Homeroom rooms with pupil slots become roster
/// classes; every entry is a staff opening.
///
public sealed class SchoolDemand
{
internal SchoolDemand(
IReadOnlyList classes,
IReadOnlyList seats,
IReadOnlyList staff)
{
Classes = classes;
Seats = seats;
Staff = staff;
}
public IReadOnlyList Classes { get; }
public IReadOnlyList Seats { get; }
public IReadOnlyList Staff { get; }
public static SchoolDemand From(DefCatalog catalog, MapLayout map)
{
var classrooms = new List<(RoomNode Room, int Slots)>();
var staff = new List();
foreach (var room in map.Rooms)
{
var slots = RoomOccupancy.PupilSlots(catalog, room);
if (catalog.Rooms.TryGetValue(room.Def, out var def))
{
foreach (var position in def.Positions)
{
staff.Add(new StaffOpening(room.Id, position));
}
if (slots > 0 && def.Homeroom)
{
classrooms.Add((room, slots));
}
}
}
const string letters = "АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЭЮЯ";
var classes = new SchoolClass[classrooms.Count];
var seats = new List();
for (var i = 0; i < classrooms.Count; i++)
{
var (room, capacity) = classrooms[i];
var year = (i % 11) + 1;
var letterIndex = i / 11;
var letter = letterIndex < letters.Length ? letters[letterIndex].ToString() : "?";
var classId = $"class-{room.Id}";
classes[i] = new SchoolClass(classId, year, letter, room.Id, capacity, []);
for (var seat = 0; seat < capacity; seat++)
{
seats.Add(new PupilSeat(classId, room.Id, year, letter));
}
}
return new SchoolDemand(classes, seats, staff);
}
}