48 lines
1.4 KiB
C#
48 lines
1.4 KiB
C#
namespace HSchool.People;
|
||
|
||
internal readonly record struct FamilyPlan(int FamilyIndex, IReadOnlyList<PupilSeat> Seats);
|
||
|
||
/// <summary>
|
||
/// Walks seats in order and groups them into families of 1–3. A short remainder becomes
|
||
/// singleton families rather than shrinking an earlier family's intended size, so a longer
|
||
/// seat list only appends families.
|
||
/// </summary>
|
||
internal static class FamilyPlanner
|
||
{
|
||
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;
|
||
}
|
||
}
|