Files
h-school/src/HSchool.People/FamilyPlanner.cs
T

67 lines
2.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
namespace HSchool.People;
internal readonly record struct FamilyPlan(int FamilyIndex, IReadOnlyList<PupilSeat> Seats);
/// <summary>
/// Walks seats in order and groups them into families of 13, taking a run of consecutive seats
/// per family. Callers hand in a shuffled seat list — a run of *adjacent* seats is one classroom,
/// which would put every sibling in the same class.
///
/// A family whose intended size does not fit the remainder takes one seat instead of shrinking,
/// so growing the seat list only disturbs the tail.
/// </summary>
internal static class FamilyPlanner
{
/// <summary>
/// One child per family. Used by the yearly intake: every seat there is a first-year seat, so
/// grouping would hand a family two or three same-age children at once. An arriving pupil who
/// does have an older sibling gets attached to that family instead.
/// </summary>
public static IReadOnlyList<FamilyPlan> Singletons(IReadOnlyList<PupilSeat> seats, int startIndex)
{
var plans = new FamilyPlan[seats.Count];
for (var i = 0; i < seats.Count; i++)
{
plans[i] = new FamilyPlan(startIndex + i, [seats[i]]);
}
return plans;
}
public static IReadOnlyList<FamilyPlan> Plan(int schoolSeed, IReadOnlyList<PupilSeat> seats, int startIndex = 0)
{
var plans = new List<FamilyPlan>();
var offset = 0;
var index = startIndex;
while (offset < seats.Count)
{
var remaining = seats.Count - offset;
var want = ChildCount(schoolSeed, index);
var take = want <= remaining ? want : 1;
var slice = new PupilSeat[take];
for (var i = 0; i < take; i++)
{
slice[i] = seats[offset + i];
}
plans.Add(new FamilyPlan(index, slice));
offset += take;
index++;
}
return plans;
}
public static int ChildCount(int schoolSeed, int familyIndex)
{
var rng = new Random(Seed.Mix(schoolSeed, familyIndex, Seed.ChildCountSalt));
var roll = rng.Next(100);
if (roll < 50)
{
return 1;
}
return roll < 85 ? 2 : 3;
}
}