namespace HSchool.People; internal readonly record struct FamilyPlan(int FamilyIndex, IReadOnlyList Seats); /// /// 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. /// internal static class FamilyPlanner { public static IReadOnlyList Plan(int schoolSeed, IReadOnlyList seats, int startIndex = 0) { var plans = new List(); 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; } }