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.
ci / server (push) Failing after 3m49s
ci / client (push) Successful in 24s

This commit is contained in:
Leonid Pershin
2026-08-18 21:13:16 +03:00
parent 7f6852548d
commit 3366e8e44b
19 changed files with 766 additions and 90 deletions
+35 -1
View File
@@ -55,10 +55,44 @@ public sealed record PersonName(
public string Full => string.Join(' ', new[] { Surname, Given, Patronymic }.Where(part => part.Length > 0));
}
/// <summary>
/// A household. <see cref="ParentIds"/> holds one adult or two — a child keeps the father's
/// surname and patronymic whether or not the father lives with them, so both are recorded here
/// rather than read off a parent who may not be in the roster.
/// </summary>
public sealed record Family(
string Id,
IReadOnlyList<string> ParentIds,
IReadOnlyList<string> ChildIds);
IReadOnlyList<string> ChildIds,
int NextChild = 0,
string FatherGiven = "",
string Surname = "")
{
/// <summary>
/// Id suffix for the next child of this family. It is a counter and not
/// <c>ChildIds.Count</c>, because a graduate leaves the roster: deriving the suffix from the
/// children still present would hand a newcomer the id of the person who just left, and every
/// family link and open card pointing at that id would silently follow the wrong person.
///
/// Rosters written before the counter existed fall back to the highest suffix still present.
/// </summary>
public int NextChildIndex => Math.Max(NextChild, HighestChildSuffix() + 1);
private int HighestChildSuffix()
{
var highest = -1;
foreach (var id in ChildIds)
{
var marker = id.LastIndexOf(".c", StringComparison.Ordinal);
if (marker >= 0 && int.TryParse(id.AsSpan(marker + 2), out var index) && index > highest)
{
highest = index;
}
}
return highest;
}
}
public sealed record SchoolClass(
string Id,