Update staffing management to enhance payroll and hiring functionalities
- Increased the `MonthlyPayrollCap` from 10,000 to 40,000, allowing for greater flexibility in hiring and subject assignments. - Revised payroll calculation logic to ensure that staff members are compensated based on their actual weekly hours, with a minimum payment reflecting one full rate. - Updated documentation to clarify the new payroll structure and its implications for hiring and subject assignments. - Enhanced tests to validate the new payroll cap and ensure proper functionality in staffing scenarios, including the handling of uncovered subjects. - Improved localization strings to reflect changes in staffing and payroll terminology.
This commit is contained in:
@@ -56,14 +56,7 @@ public static class TimetablePlanner
|
||||
demand.Hours,
|
||||
placed);
|
||||
|
||||
if (leftover > 0)
|
||||
{
|
||||
demand.Hours = leftover;
|
||||
}
|
||||
else
|
||||
{
|
||||
demand.Hours = 0;
|
||||
}
|
||||
demand.Hours = leftover;
|
||||
}
|
||||
|
||||
var uncovered = remaining
|
||||
@@ -162,6 +155,14 @@ public static class TimetablePlanner
|
||||
return leftover;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Picks the slot, and the order days are tried in is the whole difference between a timetable
|
||||
/// and a pile of lessons. Scanning day 0 upwards and taking the first free slot produced blocks
|
||||
/// of the same subject and a week that ran out by Thursday: Monday held 77 lessons, Friday 16.
|
||||
///
|
||||
/// So days are ranked instead: first those that do not have this subject yet, then the emptiest
|
||||
/// one for this class. Periods stay ascending inside the chosen day, so a day has no holes.
|
||||
/// </summary>
|
||||
private static bool TryPlaceOne(
|
||||
Occupancy occupancy,
|
||||
string classId,
|
||||
@@ -172,7 +173,26 @@ public static class TimetablePlanner
|
||||
int lessonCount,
|
||||
List<LessonPlacement> placed)
|
||||
{
|
||||
var days = new int[weekDays];
|
||||
for (var day = 0; day < weekDays; day++)
|
||||
{
|
||||
days[day] = day;
|
||||
}
|
||||
|
||||
Array.Sort(days, (left, right) =>
|
||||
{
|
||||
var bySubject = occupancy.SubjectLoad(classId, subject, left)
|
||||
.CompareTo(occupancy.SubjectLoad(classId, subject, right));
|
||||
if (bySubject != 0)
|
||||
{
|
||||
return bySubject;
|
||||
}
|
||||
|
||||
var byDay = occupancy.DayLoad(classId, left).CompareTo(occupancy.DayLoad(classId, right));
|
||||
return byDay != 0 ? byDay : left.CompareTo(right);
|
||||
});
|
||||
|
||||
foreach (var day in days)
|
||||
{
|
||||
for (var period = 1; period <= lessonCount; period++)
|
||||
{
|
||||
@@ -313,17 +333,33 @@ public static class TimetablePlanner
|
||||
private readonly HashSet<(string Id, int Day, int Period)> _classes = [];
|
||||
private readonly HashSet<(string Id, int Day, int Period)> _teachers = [];
|
||||
private readonly HashSet<(string Id, int Day, int Period)> _rooms = [];
|
||||
private readonly Dictionary<(string ClassId, int Day), int> _dayLoad = [];
|
||||
private readonly Dictionary<(string ClassId, string Subject, int Day), int> _subjectLoad = [];
|
||||
|
||||
public bool IsFree(string classId, string teacherId, string roomId, int day, int period) =>
|
||||
!_classes.Contains((classId, day, period))
|
||||
&& !_teachers.Contains((teacherId, day, period))
|
||||
&& !_rooms.Contains((roomId, day, period));
|
||||
|
||||
/// <summary>How many lessons this class already has that day — counted, not recomputed.</summary>
|
||||
public int DayLoad(string classId, int day) =>
|
||||
_dayLoad.TryGetValue((classId, day), out var count) ? count : 0;
|
||||
|
||||
/// <summary>How many lessons of this subject this class already has that day.</summary>
|
||||
public int SubjectLoad(string classId, string subject, int day) =>
|
||||
_subjectLoad.TryGetValue((classId, subject, day), out var count) ? count : 0;
|
||||
|
||||
public void Add(LessonPlacement lesson)
|
||||
{
|
||||
_classes.Add((lesson.ClassId, lesson.Day, lesson.Period));
|
||||
_teachers.Add((lesson.TeacherId, lesson.Day, lesson.Period));
|
||||
_rooms.Add((lesson.RoomId, lesson.Day, lesson.Period));
|
||||
|
||||
var day = (lesson.ClassId, lesson.Day);
|
||||
_dayLoad[day] = (_dayLoad.TryGetValue(day, out var lessons) ? lessons : 0) + 1;
|
||||
|
||||
var subject = (lesson.ClassId, lesson.Subject, lesson.Day);
|
||||
_subjectLoad[subject] = (_subjectLoad.TryGetValue(subject, out var same) ? same : 0) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user