Files
Leonid PershinandCursor 37501c506a Dress people at generation from a separate apparel stream.
Wardrobes live on the person in people.json: everyday layers, textbooks per parallel, and chance-based bags from catalog data. Hauling and the carry cap are defs, not constants. The golden roster gains an items column; later family members shift because Hauling consumes extra appearance rolls. Old saves without items are dressed on load.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-20 03:24:54 +03:00

83 lines
2.9 KiB
C#

namespace HSchool.People.Tests;
/// <summary>
/// One line per class and person, sorted, so a generator change shows up as the first
/// mismatched line instead of "the snapshots differ".
/// </summary>
internal static class RosterFingerprint
{
public static string Format(Roster roster, int seed, string country, string native)
{
var lines = new List<string>
{
$"# seed={seed} country={country} native={native} people={roster.People.Count} classes={roster.Classes.Count}",
};
foreach (var schoolClass in roster.Classes.OrderBy(row => row.Id, StringComparer.Ordinal))
{
var pupils = string.Join(',', schoolClass.PupilIds.Order(StringComparer.Ordinal));
lines.Add(
$"class {schoolClass.Id} year={schoolClass.Year} letter={schoolClass.Letter} room={schoolClass.RoomId} capacity={schoolClass.Capacity} pupils={pupils}");
}
foreach (var person in roster.People.OrderBy(row => row.Id, StringComparer.Ordinal))
{
lines.Add(PersonLine(person));
}
return string.Join('\n', lines) + '\n';
}
public static void AssertEqual(string expected, string actual)
{
var left = expected.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n');
var right = actual.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n');
var count = Math.Min(left.Length, right.Length);
for (var i = 0; i < count; i++)
{
if (!string.Equals(left[i], right[i], StringComparison.Ordinal))
{
Assert.Fail($"first mismatch at line {i + 1}\nexpected: {left[i]}\nactual: {right[i]}");
}
}
if (left.Length != right.Length)
{
Assert.Fail($"line count {left.Length} vs {right.Length}");
}
}
private static string PersonLine(Person person)
{
var roles = string.Join(',', Roles(person));
var traits = string.Join(',', person.Traits.Order(StringComparer.Ordinal));
var skills = string.Join(
',',
person.Skills.OrderBy(pair => pair.Key, StringComparer.Ordinal).Select(pair => $"{pair.Key}={pair.Value}"));
var items = string.Join(
',',
person.Items.Select(item =>
$"{item.Def}:{item.Color ?? "-"}:{item.Location}{(item.Subject is { } subject ? $":{subject}" : "")}"));
return
$"person {person.Id} {person.Name.Full} female={person.Female} roles={roles} class={person.ClassId ?? "-"} born={person.BirthDate:yyyy-MM-dd} traits={traits} skills={skills} items={items}";
}
private static IEnumerable<string> Roles(Person person)
{
if (person.IsStudent)
{
yield return "student";
}
if (person.IsStaff)
{
yield return "staff";
}
if (person.IsParent)
{
yield return "parent";
}
}
}