Enhance family and roster management in school simulation by implementing support for incomplete families, ensuring proper handling of absent parents while maintaining surname consistency. Update family creation logic to account for single-parent households and revise child identification to prevent ID conflicts. Introduce seat shuffling to prevent siblings from being placed in the same class, improving the realism of student distribution. Update related tests to validate these new functionalities and ensure robustness in family and roster handling.
This commit is contained in:
@@ -30,7 +30,7 @@ public static class RosterGenerator
|
||||
var when = DateTime.SpecifyKind(asOf ?? DefaultAsOf, DateTimeKind.Utc);
|
||||
var yearStart = SchoolYears.StartOn(when);
|
||||
var demand = SchoolDemand.From(catalog, map);
|
||||
var plans = FamilyPlanner.Plan(schoolSeed, demand.Seats);
|
||||
var plans = FamilyPlanner.Plan(schoolSeed, ShuffleSeats(demand.Seats, schoolSeed));
|
||||
|
||||
var people = new List<Person>();
|
||||
var families = new List<Family>(plans.Count);
|
||||
@@ -42,12 +42,14 @@ public static class RosterGenerator
|
||||
}
|
||||
|
||||
var nextFamily = plans.Count;
|
||||
while (people.Count(person => !person.IsStudent) < demand.Staff.Count)
|
||||
var adults = people.Count(person => !person.IsStudent);
|
||||
while (adults < demand.Staff.Count)
|
||||
{
|
||||
var (family, members) = FamilyFactory.CreateStaffOnly(catalog, names, schoolSeed, nextFamily, when);
|
||||
var (family, member) = FamilyFactory.CreateStaffOnly(catalog, names, schoolSeed, nextFamily, when);
|
||||
families.Add(family);
|
||||
people.AddRange(members);
|
||||
people.Add(member);
|
||||
nextFamily++;
|
||||
adults++;
|
||||
}
|
||||
|
||||
var staffed = AssignStaff(people, demand.Staff);
|
||||
@@ -55,6 +57,25 @@ public static class RosterGenerator
|
||||
return new Roster(staffed, families, classes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Seats leave <see cref="SchoolDemand"/> grouped by classroom, and a family takes a run of
|
||||
/// consecutive seats — so without this every pair of siblings landed in the same class, the
|
||||
/// same year and the same twelve-month birth window. Shuffling is seeded, so the roster stays
|
||||
/// reproducible.
|
||||
/// </summary>
|
||||
private static IReadOnlyList<PupilSeat> ShuffleSeats(IReadOnlyList<PupilSeat> seats, int schoolSeed)
|
||||
{
|
||||
var shuffled = seats.ToArray();
|
||||
var rng = new Random(Seed.ForSchool(schoolSeed, Seed.SeatShuffleSalt));
|
||||
for (var i = shuffled.Length - 1; i > 0; i--)
|
||||
{
|
||||
var j = rng.Next(i + 1);
|
||||
(shuffled[i], shuffled[j]) = (shuffled[j], shuffled[i]);
|
||||
}
|
||||
|
||||
return shuffled;
|
||||
}
|
||||
|
||||
private static IReadOnlyList<Person> AssignStaff(List<Person> people, IReadOnlyList<StaffOpening> openings)
|
||||
{
|
||||
if (openings.Count == 0)
|
||||
|
||||
Reference in New Issue
Block a user