Enhance staffing management with uncovered teacher tracking
- Updated `protocol.md` to clarify the concept of uncovered subjects and the number of additional teachers required. - Introduced `teachersShort` property in the `StaffingSubject` interface to indicate how many more teachers are needed for a subject. - Enhanced localization strings to reflect the new uncovered teacher information in both English and Russian. - Updated the management panel UI to display the number of teachers short for each uncovered subject. - Revised the `Uncovered` method in the staffing logic to return detailed information about uncovered subjects, including the shortfall of teachers. - Added tests to validate the new uncovered teacher tracking functionality and ensure accurate reporting in the staffing API. - Marked related tasks as complete in the documentation for the golden fixtures phase.
This commit is contained in:
@@ -18,6 +18,14 @@ public enum StaffingError
|
||||
NoOpening,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A subject the school cannot actually teach, and how many more teachers would cover it.
|
||||
/// </summary>
|
||||
public sealed record UncoveredSubject(SubjectDef Subject, int Assigned, int TeachersShort)
|
||||
{
|
||||
public string DefName => Subject.DefName;
|
||||
}
|
||||
|
||||
public sealed record StaffingOutcome(
|
||||
StaffingError Error,
|
||||
Roster Roster,
|
||||
@@ -130,12 +138,32 @@ public static class Staffing
|
||||
return Round(total);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// How many people a subject needs at the weekly cap. Primary school on a vanilla map is
|
||||
/// eighty hours: one person cannot carry it, and the uncovered row has to say so.
|
||||
/// </summary>
|
||||
public static int TeachersToCover(float hours, float maxWeeklyHours)
|
||||
{
|
||||
if (hours <= 0f)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (maxWeeklyHours <= 0f)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
return (int)Math.Ceiling(hours / maxWeeklyHours);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subjects the school cannot actually teach: nobody is assigned them, or the people who are
|
||||
/// cannot between them carry the curriculum hours. Both read the same way to a player — the
|
||||
/// lessons will not happen — so both belong in one list.
|
||||
/// lessons will not happen — so both belong in one list. <see cref="UncoveredSubject.TeachersShort"/>
|
||||
/// is how many more people it still needs.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<SubjectDef> Uncovered(DefCatalog catalog, Roster roster)
|
||||
public static IReadOnlyList<UncoveredSubject> Uncovered(DefCatalog catalog, Roster roster)
|
||||
{
|
||||
var years = new HashSet<int>();
|
||||
foreach (var schoolClass in roster.Classes)
|
||||
@@ -158,7 +186,7 @@ public static class Staffing
|
||||
}
|
||||
|
||||
var cap = catalog.StaffingRules?.MaxWeeklyHours ?? 0f;
|
||||
var uncovered = new List<SubjectDef>();
|
||||
var uncovered = new List<UncoveredSubject>();
|
||||
foreach (var subject in catalog.Subjects.Values)
|
||||
{
|
||||
if (subject.Abstract || !TouchesYears(subject, years))
|
||||
@@ -167,9 +195,12 @@ public static class Staffing
|
||||
}
|
||||
|
||||
var assigned = teachers.GetValueOrDefault(subject.DefName);
|
||||
if (assigned == 0 || (cap > 0f && SubjectHours(catalog, roster, subject.DefName) > assigned * cap))
|
||||
var hours = SubjectHours(catalog, roster, subject.DefName);
|
||||
var needed = TeachersToCover(hours, cap);
|
||||
var shortfall = Math.Max(0, needed - assigned);
|
||||
if (shortfall > 0)
|
||||
{
|
||||
uncovered.Add(subject);
|
||||
uncovered.Add(new UncoveredSubject(subject, assigned, shortfall));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user