Merge phase 29 country.
ci / server (push) Failing after 3m53s
ci / client (push) Successful in 19s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Leonid Pershin
2026-08-20 02:59:46 +03:00
co-authored by Cursor
59 changed files with 903 additions and 478 deletions
+3 -3
View File
@@ -68,7 +68,7 @@ public class WalkingTests
public void ComesToday_IsFalseOnSundayAndHolidays()
{
var (catalog, map) = Fixtures.Vanilla();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", TuesdayLesson);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", TuesdayLesson);
var pupil = roster.People.First(person => person.IsStudent);
var schoolClass = roster.Classes.First(row => row.Id == pupil.ClassId);
var table = new Timetable(
@@ -90,7 +90,7 @@ public class WalkingTests
public void ClassWithoutLessons_StaysAway_TeacherWithAnotherClassComes()
{
var (catalog, map) = Fixtures.Vanilla();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", TuesdayLesson);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", TuesdayLesson);
var idle = roster.Classes[0];
var busy = roster.Classes[1];
var idlePupil = roster.People.First(person => person.Id == idle.PupilIds[0]);
@@ -117,7 +117,7 @@ public class WalkingTests
{
var (catalog, map) = Fixtures.Vanilla();
var walks = WalkGraph.Build(catalog, map);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 9, "Slavic", TuesdayLesson);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 9, "Russia", TuesdayLesson);
var pupil = roster.People.First(person => person.IsStudent);
var schoolClass = roster.Classes.First(row => row.Id == pupil.ClassId);
var table = new Timetable(
@@ -28,8 +28,8 @@ public class ExamplePackTests(AppHostFixture fixture)
Assert.Equal("Кабинет директора", Assert.Single(ru.Rooms, room => room.DefName == "PrincipalsOffice").Label);
Assert.Equal("Кладовая", Assert.Single(ru.Rooms, room => room.DefName == "ExampleStore").Label);
Assert.Equal("Storeroom", Assert.Single(en.Rooms, room => room.DefName == "ExampleStore").Label);
Assert.Equal("Примерные имена", Assert.Single(ru.NameSets, set => set.DefName == "ExampleNames").Label);
Assert.Equal("Example names", Assert.Single(en.NameSets, set => set.DefName == "ExampleNames").Label);
Assert.Equal("Примерные имена", Assert.Single(ru.Countries, set => set.DefName == "ExampleNames").Label);
Assert.Equal("Example names", Assert.Single(en.Countries, set => set.DefName == "ExampleNames").Label);
Assert.Equal("yard", ru.DefaultMap.Territory?.Id);
}
@@ -139,14 +139,14 @@ public class ExamplePackTests(AppHostFixture fixture)
IReadOnlyList<DefInfoResponse> Floors,
IReadOnlyList<RoomInfoResponse> Rooms,
IReadOnlyList<DefInfoResponse> Things,
IReadOnlyList<NameSetInfoResponse> NameSets,
IReadOnlyList<CountryInfoResponse> Countries,
DayFrameResponse? DayFrame,
IReadOnlyList<HolidayInfoResponse> Holidays,
MapLayoutResponse DefaultMap);
private sealed record DefInfoResponse(string DefName, string Label);
private sealed record NameSetInfoResponse(string DefName, string Label);
private sealed record CountryInfoResponse(string DefName, string Label);
private sealed record RoomInfoResponse(
string DefName,
+88 -13
View File
@@ -278,13 +278,14 @@ public class SchoolApiTests(AppHostFixture fixture)
Assert.Equal("Кабинет директора", Assert.Single(ru.Rooms, room => room.DefName == "PrincipalsOffice").Label);
Assert.Equal("Principal's office", Assert.Single(en.Rooms, room => room.DefName == "PrincipalsOffice").Label);
Assert.Equal("yard", ru.DefaultMap.Territory?.Id);
Assert.Equal("Славянский", Assert.Single(ru.NameSets, set => set.DefName == "Slavic").Label);
Assert.Equal("Slavic", Assert.Single(en.NameSets, set => set.DefName == "Slavic").Label);
var slavic = Assert.Single(ru.NameSets, set => set.DefName == "Slavic");
Assert.Equal("Россия", Assert.Single(ru.Countries, country => country.DefName == "Russia").Label);
Assert.Equal("Russia", Assert.Single(en.Countries, country => country.DefName == "Russia").Label);
var russia = Assert.Single(ru.Countries, country => country.DefName == "Russia");
Assert.Equal(
["RussianLanguage", "BelarusianLanguage", "UkrainianLanguage"],
slavic.NativeLanguages.Select(language => language.DefName).ToArray());
Assert.Equal("Белорусский", Assert.Single(slavic.NativeLanguages, language => language.DefName == "BelarusianLanguage").Label);
russia.NativeLanguages.Select(language => language.DefName).ToArray());
Assert.Equal("Белорусский", Assert.Single(russia.NativeLanguages, language => language.DefName == "BelarusianLanguage").Label);
Assert.Equal(["TemperateContinental", "ContinentalCold"], russia.ClimatePresets);
Assert.Equal("Начальные классы", Assert.Single(ru.Subjects, subject => subject.DefName == "PrimarySchool").Label);
Assert.Equal("Primary", Assert.Single(en.Subjects, subject => subject.DefName == "PrimarySchool").Label);
var classroom = Assert.Single(ru.Rooms, room => room.DefName == "Classroom");
@@ -396,7 +397,7 @@ public class SchoolApiTests(AppHostFixture fixture)
}
[Fact]
public async Task CreateSchool_WithAnUnknownNameSet_IsRejected()
public async Task CreateSchool_WithAnUnknownCountry_IsRejected()
{
using var client = fixture.App.CreateHttpClient("server");
await ResetAsync(client);
@@ -405,14 +406,47 @@ public class SchoolApiTests(AppHostFixture fixture)
"/api/schools",
new
{
name = "Чужие имена",
name = "Чужая страна",
startDate = ExpectedDefaultStart,
nameSetId = "NoSuchNames",
countryId = "NoSuchCountry",
},
TestContext.Current.CancellationToken);
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
Assert.Equal("unknown-name-set", await ProblemCodeAsync(response));
Assert.Equal("unknown-country", await ProblemCodeAsync(response));
}
[Fact]
public async Task CreateSchool_WithRussiaAndNoLanguage_PicksTheSameNativeAsTheSeed()
{
using var client = fixture.App.CreateHttpClient("server");
await ResetAsync(client);
const int seed = 42;
var first = await CreateWithCountryAsync(client, "Страна А", ExpectedDefaultStart, "Russia", seed);
var second = await CreateWithCountryAsync(client, "Страна Б", ExpectedDefaultStart, "Russia", seed);
var firstSave = await ReadSchoolSaveAsync(client, first.Id);
var secondSave = await ReadSchoolSaveAsync(client, second.Id);
Assert.Equal("Russia", firstSave.CountryId);
Assert.Equal(firstSave.NativeLanguage, secondSave.NativeLanguage);
Assert.Contains(firstSave.NativeLanguage, new[] { "RussianLanguage", "BelarusianLanguage", "UkrainianLanguage" });
}
[Fact]
public async Task CreateSchool_WithTheSameSeed_GetsTheSameClimatePreset()
{
using var client = fixture.App.CreateHttpClient("server");
await ResetAsync(client);
const int seed = 20260818;
var first = await CreateWithCountryAsync(client, "Климат А", ExpectedDefaultStart, "Russia", seed);
var second = await CreateWithCountryAsync(client, "Климат Б", ExpectedDefaultStart, "Russia", seed);
var firstSave = await ReadSchoolSaveAsync(client, first.Id);
var secondSave = await ReadSchoolSaveAsync(client, second.Id);
Assert.Equal(firstSave.ClimatePresetId, secondSave.ClimatePresetId);
Assert.Contains(firstSave.ClimatePresetId, new[] { "TemperateContinental", "ContinentalCold" });
}
[Fact]
@@ -427,7 +461,7 @@ public class SchoolApiTests(AppHostFixture fixture)
{
name = "Чужой язык",
startDate = ExpectedDefaultStart,
nameSetId = "Slavic",
countryId = "Russia",
nativeLanguage = "Klingon",
},
TestContext.Current.CancellationToken);
@@ -521,6 +555,46 @@ public class SchoolApiTests(AppHostFixture fixture)
return created;
}
private static async Task<SchoolResponse> CreateWithCountryAsync(
HttpClient client,
string name,
DateTime startDate,
string countryId,
int seed)
{
using var response = await client.PostAsJsonAsync(
"/api/schools",
new { name, startDate, countryId, seed },
TestContext.Current.CancellationToken);
response.EnsureSuccessStatusCode();
var created = await response.Content.ReadFromJsonAsync<SchoolResponse>(TestContext.Current.CancellationToken);
Assert.NotNull(created);
return created;
}
private static async Task<SchoolSaveFile> ReadSchoolSaveAsync(HttpClient client, int id)
{
var directory = await SavesDirectoryAsync(client);
var json = await File.ReadAllTextAsync(Path.Combine(directory, $"{id}.json"), TestContext.Current.CancellationToken);
var save = System.Text.Json.JsonSerializer.Deserialize<SchoolSaveFile>(
json,
new System.Text.Json.JsonSerializerOptions { PropertyNameCaseInsensitive = true });
Assert.NotNull(save);
return save;
}
private static async Task<string> SavesDirectoryAsync(HttpClient client)
{
var payload = await client.GetFromJsonAsync<PathResponse>(
"/api/dev/saves-directory",
TestContext.Current.CancellationToken);
Assert.NotNull(payload);
Assert.False(string.IsNullOrWhiteSpace(payload.Path));
return payload.Path;
}
private sealed record SchoolSaveFile(string? CountryId, string? ClimatePresetId, string? NativeLanguage);
internal static readonly object SimpleCustomMap = new
{
territory = new { id = "yard", def = "SchoolYard" },
@@ -626,7 +700,7 @@ public class SchoolApiTests(AppHostFixture fixture)
IReadOnlyList<DefInfoResponse> Floors,
IReadOnlyList<RoomInfoResponse> Rooms,
IReadOnlyList<DefInfoResponse> Things,
IReadOnlyList<NameSetInfoResponse> NameSets,
IReadOnlyList<CountryInfoResponse> Countries,
IReadOnlyList<SubjectInfoResponse> Subjects,
DayFrameResponse? DayFrame,
IReadOnlyList<HolidayInfoResponse> Holidays,
@@ -634,10 +708,11 @@ public class SchoolApiTests(AppHostFixture fixture)
private sealed record DefInfoResponse(string DefName, string Label);
private sealed record NameSetInfoResponse(
private sealed record CountryInfoResponse(
string DefName,
string Label,
IReadOnlyList<DefInfoResponse> NativeLanguages);
IReadOnlyList<DefInfoResponse> NativeLanguages,
IReadOnlyList<string> ClimatePresets);
private sealed record RoomInfoResponse(
string DefName,
@@ -37,6 +37,34 @@ public class ServiceabilityTests(AppHostFixture fixture)
}
}
[Fact]
public async Task CurrentFormatSave_WithoutCountryId_LeavesTheSchoolUnstartedAndTheFileUntouched()
{
using var client = fixture.App.CreateHttpClient("server");
await SchoolApiTests.ResetAsync(client);
var directory = await SavesDirectoryAsync(client);
try
{
InstallGolden(directory, "current");
var path = Path.Combine(directory, "1.json");
BumpFormat(path, 3);
var before = File.ReadAllBytes(path);
using var reload = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
reload.EnsureSuccessStatusCode();
Assert.Empty((await SchoolApiTests.GetSchoolsAsync(client)).Schools);
Assert.Equal(before, File.ReadAllBytes(path));
}
finally
{
DeleteSchoolFiles(directory, 1);
using var cleanup = await client.PostAsync("/api/dev/reload-schools", content: null, TestContext.Current.CancellationToken);
cleanup.EnsureSuccessStatusCode();
}
}
[Fact]
public async Task CurrentFormatSave_LoadsAsBefore()
{
@@ -0,0 +1,81 @@
namespace HSchool.Content.Tests;
public class CountryDefTests
{
private readonly CatalogLoader _loader = new();
[Fact]
public void VanillaCore_LoadsRussiaAndClimatePresets()
{
var root = Path.Combine(AppContext.BaseDirectory, "vanilla");
var catalog = _loader.Load([CatalogLoader.CorePackId], PackDocuments.FromDirectory(CatalogLoader.CorePackId, root));
Assert.True(catalog.Countries.ContainsKey("Russia"));
Assert.False(catalog.Countries.ContainsKey("Slavic"));
var russia = catalog.Countries["Russia"];
Assert.Equal(
["RussianLanguage", "BelarusianLanguage", "UkrainianLanguage"],
russia.Names.Spoken);
Assert.Equal(0.6f, russia.Names.RelatedLanguageChance);
Assert.Equal(40, russia.Names.RelatedLanguageMax);
Assert.True(russia.Names.MaleGiven.Count >= 20);
Assert.Equal(["TemperateContinental", "ContinentalCold"], russia.ClimatePresets);
Assert.True(catalog.ClimatePresets.ContainsKey("TemperateContinental"));
Assert.True(catalog.ClimatePresets.ContainsKey("ContinentalCold"));
Assert.Equal("Россия", catalog.Label("ru", russia));
Assert.Equal("Russia", catalog.Label("en", russia));
}
[Fact]
public void CountryWithoutNames_FailsTheCatalog()
{
var ex = Assert.Throws<ContentLoadException>(() => _loader.Load(
[CatalogLoader.CorePackId],
[
PackDocuments.Def(
CatalogLoader.CorePackId,
"climates",
"temperate",
"""{ "defName": "TemperateContinental" }"""),
PackDocuments.Def(
CatalogLoader.CorePackId,
"countries",
"ghost",
"""{ "defName": "GhostLand", "climatePresets": ["TemperateContinental"] }"""),
]));
Assert.Contains("GhostLand", ex.Message, StringComparison.Ordinal);
Assert.Contains("names", ex.Message, StringComparison.OrdinalIgnoreCase);
}
[Fact]
public void CountryWithUnknownPreset_FailsTheCatalog()
{
var ex = Assert.Throws<ContentLoadException>(() => _loader.Load(
[CatalogLoader.CorePackId],
[
PackDocuments.Def(
CatalogLoader.CorePackId,
"climates",
"temperate",
"""{ "defName": "TemperateContinental" }"""),
PackDocuments.Def(
CatalogLoader.CorePackId,
"countries",
"ghost",
"""
{
"defName": "GhostLand",
"climatePresets": ["NoSuchClimate"],
"names": {
"maleGiven": [{ "form": "Иван" }],
"femaleGiven": [{ "form": "Анна", "declension": "a" }],
"surnames": [{ "male": "Иванов", "female": "Иванова" }]
}
}
"""),
]));
Assert.Contains("NoSuchClimate", ex.Message, StringComparison.Ordinal);
}
}
@@ -40,12 +40,12 @@ public class ExamplePackTests
Assert.True(catalog.Traits.ContainsKey("ExampleEarlyRiser"));
Assert.True(catalog.Traits.ContainsKey("ExampleNightOwl"));
Assert.True(catalog.NameSets.ContainsKey("ExampleNames"));
Assert.True(catalog.Countries.ContainsKey("ExampleNames"));
Assert.True(catalog.Rooms.ContainsKey("ExampleStore"));
Assert.Equal("Кладовая", catalog.Label("ru", catalog.Rooms["ExampleStore"]));
Assert.Equal("Storeroom", catalog.Label("en", catalog.Rooms["ExampleStore"]));
Assert.Equal("Примерные имена", catalog.Label("ru", catalog.NameSets["ExampleNames"]));
Assert.Equal(["RussianLanguage"], catalog.NameSets["ExampleNames"].Spoken.ToArray());
Assert.Equal("Примерные имена", catalog.Label("ru", catalog.Countries["ExampleNames"]));
Assert.Equal(["RussianLanguage"], catalog.Countries["ExampleNames"].Names.Spoken.ToArray());
Assert.True(catalog.Rooms.ContainsKey("PrincipalsOffice"));
Assert.Equal("Кабинет директора", catalog.Label("ru", catalog.Rooms["PrincipalsOffice"]));
}
+31 -20
View File
@@ -25,15 +25,15 @@ public class PeopleDefTests
Assert.Equal(0.4f, catalog.Skills["English"].AdultChance);
Assert.Equal(
["RussianLanguage", "BelarusianLanguage", "UkrainianLanguage"],
catalog.NameSets["Slavic"].Spoken);
Assert.Equal(0.6f, catalog.NameSets["Slavic"].RelatedLanguageChance);
Assert.Equal(40, catalog.NameSets["Slavic"].RelatedLanguageMax);
catalog.Countries["Russia"].Names.Spoken);
Assert.Equal(0.6f, catalog.Countries["Russia"].Names.RelatedLanguageChance);
Assert.Equal(40, catalog.Countries["Russia"].Names.RelatedLanguageMax);
Assert.Contains(catalog.Subjects["ForeignLanguage"].Skills, share => share.Skill == "English");
Assert.False(catalog.Skills.ContainsKey("ForeignLanguage"));
Assert.True(catalog.NameSets.ContainsKey("Slavic"));
Assert.True(catalog.NameSets["Slavic"].MaleGiven.Count >= 20);
Assert.Equal("Славянский", catalog.Label("ru", catalog.NameSets["Slavic"]));
Assert.Equal("Slavic", catalog.Label("en", catalog.NameSets["Slavic"]));
Assert.True(catalog.Countries.ContainsKey("Russia"));
Assert.True(catalog.Countries["Russia"].Names.MaleGiven.Count >= 20);
Assert.Equal("Россия", catalog.Label("ru", catalog.Countries["Russia"]));
Assert.Equal("Russia", catalog.Label("en", catalog.Countries["Russia"]));
Assert.Equal("Усидчивый", catalog.Label("ru", catalog.Traits["Diligent"]));
Assert.True(catalog.Subjects.ContainsKey("PrimarySchool"));
Assert.NotNull(catalog.StaffingRules);
@@ -213,7 +213,7 @@ public class PeopleDefTests
}
[Fact]
public void ExtraPack_AddsANameSetAndTrait()
public void ExtraPack_AddsACountryAndTrait()
{
var catalog = _loader.Load(
[CatalogLoader.CorePackId, "addon"],
@@ -221,37 +221,48 @@ public class PeopleDefTests
PackDocuments.Def(CatalogLoader.CorePackId, "traits", "kind", """{ "defName": "Kind", "weight": 1 }"""),
PackDocuments.Def(
CatalogLoader.CorePackId,
"namesets",
"slavic",
"climates",
"temperate",
"""{ "defName": "TemperateContinental" }"""),
PackDocuments.Def(
CatalogLoader.CorePackId,
"countries",
"russia",
"""
{
"defName": "Slavic",
"maleGiven": [{ "form": "Иван" }],
"femaleGiven": [{ "form": "Анна", "declension": "a" }],
"surnames": [{ "male": "Иванов", "female": "Иванова" }]
"defName": "Russia",
"climatePresets": ["TemperateContinental"],
"names": {
"maleGiven": [{ "form": "Иван" }],
"femaleGiven": [{ "form": "Анна", "declension": "a" }],
"surnames": [{ "male": "Иванов", "female": "Иванова" }]
}
}
"""),
PackDocuments.Def("addon", "traits", "stoic", """{ "defName": "Stoic", "weight": 3 }"""),
PackDocuments.Def("addon", "traits", "cheerful", """{ "defName": "Cheerful", "weight": 2 }"""),
PackDocuments.Def(
"addon",
"namesets",
"countries",
"nordic",
"""
{
"defName": "Nordic",
"maleGiven": [{ "form": "Lars", "declension": "indeclinable" }],
"femaleGiven": [{ "form": "Ingrid", "declension": "indeclinable" }],
"surnames": [{ "male": "Berg", "female": "Berg", "declension": "indeclinable" }]
"climatePresets": ["TemperateContinental"],
"names": {
"maleGiven": [{ "form": "Lars", "declension": "indeclinable" }],
"femaleGiven": [{ "form": "Ingrid", "declension": "indeclinable" }],
"surnames": [{ "male": "Berg", "female": "Berg", "declension": "indeclinable" }]
}
}
"""),
PackDocuments.Locale("addon", "ru", """{ "Nordic": "Северный", "Stoic": "Стоик", "Cheerful": "Жизнерадостный" }"""),
]);
Assert.True(catalog.NameSets.ContainsKey("Nordic"));
Assert.True(catalog.Countries.ContainsKey("Nordic"));
Assert.True(catalog.Traits.ContainsKey("Stoic"));
Assert.True(catalog.Traits.ContainsKey("Cheerful"));
Assert.Equal("Северный", catalog.Label("ru", catalog.NameSets["Nordic"]));
Assert.Equal("Северный", catalog.Label("ru", catalog.Countries["Nordic"]));
Assert.Equal("Стоик", catalog.Label("ru", catalog.Traits["Stoic"]));
}
}
@@ -128,7 +128,8 @@ public class VanillaCoreTests
keys.AddRange(Names(catalog.Traits.Values));
keys.AddRange(Names(catalog.BodyAttributes.Values));
keys.AddRange(Names(catalog.Needs.Values));
keys.AddRange(Names(catalog.NameSets.Values));
keys.AddRange(Names(catalog.Countries.Values));
keys.AddRange(Names(catalog.ClimatePresets.Values));
keys.AddRange(Names(catalog.Subjects.Values));
keys.AddRange(Names(catalog.Staffing.Values));
keys.AddRange(Names(catalog.DayFrames.Values));
@@ -17,7 +17,7 @@ public class ApplicantPoolTests
{
var roster = Fixtures.Generate(Fixtures.VanillaMap());
var first = Create(roster);
var next = first.Advance(Fixtures.Catalog(), roster, Fixtures.SchoolSeed, "Slavic", Fixtures.AsOf.AddDays(7));
var next = first.Advance(Fixtures.Catalog(), roster, Fixtures.SchoolSeed, "Russia", Fixtures.AsOf.AddDays(7));
Assert.NotEqual(first.Week, next.Week);
var stayed = first.Applicants
@@ -45,12 +45,12 @@ public class ApplicantPoolTests
var roster = Fixtures.Generate(Fixtures.VanillaMap());
var size = catalog.StaffingRules!.PoolSize;
var asOf = Fixtures.AsOf;
var pool = ApplicantPool.Create(catalog, roster, Fixtures.SchoolSeed, "Slavic", asOf);
var pool = ApplicantPool.Create(catalog, roster, Fixtures.SchoolSeed, "Russia", asOf);
for (var week = 0; week < 50; week++)
{
asOf = asOf.AddDays(7);
pool = pool.Advance(catalog, roster, Fixtures.SchoolSeed, "Slavic", asOf);
pool = pool.Advance(catalog, roster, Fixtures.SchoolSeed, "Russia", asOf);
Assert.Equal(size, pool.Applicants.Count);
}
}
@@ -94,7 +94,7 @@ public class ApplicantPoolTests
for (var seed = 1; seed <= 20 && pool is null; seed++)
{
var candidate = Fixtures.Generate(Fixtures.VanillaMap(), seed);
var created = ApplicantPool.Create(Fixtures.Catalog(), candidate, seed, "Slavic", Fixtures.AsOf);
var created = ApplicantPool.Create(Fixtures.Catalog(), candidate, seed, "Russia", Fixtures.AsOf);
if (created.Applicants.Any(applicant => candidate.People.Any(person => person.Id == applicant.Person.Id)))
{
roster = candidate;
@@ -132,7 +132,7 @@ public class ApplicantPoolTests
}
private static ApplicantPool Create(Roster roster) =>
ApplicantPool.Create(Fixtures.Catalog(), roster, Fixtures.SchoolSeed, "Slavic", Fixtures.AsOf);
ApplicantPool.Create(Fixtures.Catalog(), roster, Fixtures.SchoolSeed, "Russia", Fixtures.AsOf);
private static string Snapshot(ApplicantPool pool) =>
string.Join('\n', pool.Applicants.Select(applicant =>
+1 -1
View File
@@ -96,7 +96,7 @@ internal static class Fixtures
}
public static Roster Generate(MapLayout map, int seed = SchoolSeed) =>
RosterGenerator.Generate(Catalog(), map, seed, "Slavic", AsOf, "RussianLanguage");
RosterGenerator.Generate(Catalog(), map, seed, "Russia", AsOf, "RussianLanguage");
public static string RepoRoot()
{
@@ -8,7 +8,7 @@ public class GoldenRosterTests
public void GoldenRoster_MatchesFixture()
{
var roster = Fixtures.Generate(Fixtures.Classrooms(4));
var actual = RosterFingerprint.Format(roster, Fixtures.SchoolSeed, "Slavic", Native);
var actual = RosterFingerprint.Format(roster, Fixtures.SchoolSeed, "Russia", Native);
var relative = Path.Combine("golden", "roster.txt");
var output = Path.Combine(AppContext.BaseDirectory, relative);
var source = Path.Combine(Fixtures.RepoRoot(), "tests", "HSchool.People.Tests", relative);
+2 -2
View File
@@ -21,8 +21,8 @@ public class GoldenSaveDump
var catalog = Fixtures.Catalog();
var map = TwoClassrooms();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", Fixtures.AsOf, "RussianLanguage");
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Slavic", Fixtures.AsOf, "RussianLanguage");
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", Fixtures.AsOf, "RussianLanguage");
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Russia", Fixtures.AsOf, "RussianLanguage");
var people = RosterJson.Serialize(RosterDocument.From(1, roster, pool));
var mapNode = JsonNode.Parse(JsonSerializer.Serialize(map, Jsonc.SerializerOptions));
var current = SchoolJson(mapNode, includeNative: true);
+4 -4
View File
@@ -69,7 +69,7 @@ public class ReviewFixTests
for (var year = 0; year < 4; year++)
{
var before = roster.People.ToDictionary(person => person.Id, StringComparer.Ordinal);
roster = YearlyIntake.Apply(catalog, roster, Fixtures.SchoolSeed, "Slavic", date);
roster = YearlyIntake.Apply(catalog, roster, Fixtures.SchoolSeed, "Russia", date);
date = date.AddYears(1);
foreach (var person in roster.People)
@@ -98,7 +98,7 @@ public class ReviewFixTests
catalog,
roster,
Fixtures.SchoolSeed,
"Slavic",
"Russia",
new DateTime(2012, 9, 1, 0, 0, 0, DateTimeKind.Utc));
// Every seat an intake fills is a first-year seat, so a brand-new family that took two or
@@ -153,7 +153,7 @@ public class ReviewFixTests
public void AChildOfASingleMother_StillCarriesTheFathersSurnameAndPatronymic()
{
var catalog = Fixtures.Catalog();
var names = catalog.NameSets["Slavic"];
var names = catalog.Countries["Russia"].Names;
var roster = Fixtures.Generate(Fixtures.Classrooms(11));
var people = roster.People.ToDictionary(person => person.Id, StringComparer.Ordinal);
@@ -180,7 +180,7 @@ public class ReviewFixTests
public void ASingleMotherFamily_CanStillTakeInAYoungerSibling()
{
var catalog = Fixtures.Catalog();
var names = catalog.NameSets["Slavic"];
var names = catalog.Countries["Russia"].Names;
var roster = Fixtures.Generate(Fixtures.Classrooms(11));
var people = roster.People.ToDictionary(person => person.Id, StringComparer.Ordinal);
var motherOnly = roster.Families
@@ -6,11 +6,11 @@ namespace HSchool.People.Tests;
/// </summary>
internal static class RosterFingerprint
{
public static string Format(Roster roster, int seed, string nameSet, string native)
public static string Format(Roster roster, int seed, string country, string native)
{
var lines = new List<string>
{
$"# seed={seed} nameset={nameSet} native={native} people={roster.People.Count} classes={roster.Classes.Count}",
$"# 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))
@@ -3,7 +3,7 @@ namespace HSchool.People.Tests;
public class RosterGeneratorTests
{
[Fact]
public void SameSeedMapAndNameSet_YieldTheSameRoster()
public void SameSeedMapAndCountry_YieldTheSameRoster()
{
var map = Fixtures.Classrooms(4);
var a = Fixtures.Generate(map);
@@ -70,11 +70,11 @@ public class SkillGrantTests
catalog,
Fixtures.Classrooms(11),
Fixtures.SchoolSeed,
"Slavic",
"Russia",
Fixtures.AsOf,
"BelarusianLanguage");
var max = catalog.NameSets["Slavic"].RelatedLanguageMax;
var max = catalog.Countries["Russia"].Names.RelatedLanguageMax;
Assert.All(
roster.People,
person =>
@@ -97,7 +97,7 @@ public class SkillGrantTests
public void RelatedLanguages_AreCommonAndStayLow()
{
var catalog = Fixtures.Catalog();
var max = catalog.NameSets["Slavic"].RelatedLanguageMax;
var max = catalog.Countries["Russia"].Names.RelatedLanguageMax;
var roster = Fixtures.Generate(Fixtures.Classrooms(11));
Assert.Contains(
roster.People,
@@ -138,7 +138,7 @@ public class SkillGrantTests
[Fact]
public void ReloadWithoutASavedPick_TakesTheFirstLanguageInsteadOfRolling()
{
var names = Fixtures.Catalog().NameSets["Slavic"];
var names = Fixtures.Catalog().Countries["Russia"].Names;
Assert.True(names.Spoken.Count > 1, "this pins behaviour that only matters for a multi-language set");
foreach (var seed in new[] { 1, 2, 7, 20260818 })
@@ -164,8 +164,8 @@ public class SkillGrantTests
public void OmittedNativeLanguage_IsStableForTheSameSeed()
{
var map = Fixtures.Classrooms(2);
var a = RosterGenerator.Generate(Fixtures.Catalog(), map, 7, "Slavic", Fixtures.AsOf);
var b = RosterGenerator.Generate(Fixtures.Catalog(), map, 7, "Slavic", Fixtures.AsOf);
var a = RosterGenerator.Generate(Fixtures.Catalog(), map, 7, "Russia", Fixtures.AsOf);
var b = RosterGenerator.Generate(Fixtures.Catalog(), map, 7, "Russia", Fixtures.AsOf);
Assert.Equal(
a.People.Select(person => string.Join(',', person.Skills.Keys.Order(StringComparer.Ordinal))),
b.People.Select(person => string.Join(',', person.Skills.Keys.Order(StringComparer.Ordinal))));
@@ -195,7 +195,7 @@ public class SkillGrantTests
catalog,
before,
Fixtures.SchoolSeed,
"Slavic",
"Russia",
new DateTime(2012, 9, 1, 0, 0, 0, DateTimeKind.Utc));
var grown = after.People.First(person => person.Id == pupil.Id);
Assert.True(grown.ClassId is { } classId && after.Classes.Any(schoolClass =>
+2 -2
View File
@@ -178,7 +178,7 @@ public class StaffingTests
for (var seed = 1; seed <= 30 && pool is null; seed++)
{
var candidate = Fixtures.Generate(map, seed);
var created = ApplicantPool.Create(catalog, candidate, seed, "Slavic", Fixtures.AsOf);
var created = ApplicantPool.Create(catalog, candidate, seed, "Russia", Fixtures.AsOf);
var rosterIds = candidate.People.Select(person => person.Id).ToHashSet(StringComparer.Ordinal);
var parentHere = created.Applicants.FirstOrDefault(applicant => rosterIds.Contains(applicant.Person.Id));
var generatedHere = created.Applicants.FirstOrDefault(applicant => applicant.Person.Id.StartsWith('a'));
@@ -292,7 +292,7 @@ public class StaffingTests
var catalog = Fixtures.Catalog();
var map = Fixtures.VanillaMap();
var roster = Fixtures.Generate(map);
var pool = ApplicantPool.Create(catalog, roster, Fixtures.SchoolSeed, "Slavic", Fixtures.AsOf);
var pool = ApplicantPool.Create(catalog, roster, Fixtures.SchoolSeed, "Russia", Fixtures.AsOf);
return (catalog, map, roster, pool);
}
@@ -23,7 +23,7 @@ public class YearlyIntakeTests
Assert.Equal(4, before.Classes.Max(schoolClass => schoolClass.Year));
Assert.DoesNotContain(before.Classes, schoolClass => schoolClass.Year == 11);
var after = YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Slavic", September);
var after = YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Russia", September);
var demand = SchoolDemand.From(catalog, map);
Assert.True(RosterFit.Matches(after, demand));
@@ -46,8 +46,8 @@ public class YearlyIntakeTests
var map = Fixtures.Classrooms(4);
var catalog = Fixtures.Catalog();
var before = Fixtures.Generate(map);
var a = Snapshot(YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Slavic", September));
var b = Snapshot(YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Slavic", September));
var a = Snapshot(YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Russia", September));
var b = Snapshot(YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Russia", September));
Assert.Equal(a, b);
}
@@ -57,7 +57,7 @@ public class YearlyIntakeTests
var map = Fixtures.Classrooms(4);
var catalog = Fixtures.Catalog();
var before = Fixtures.Generate(map);
var after = YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Slavic", September);
var after = YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Russia", September);
var people = after.People.ToDictionary(person => person.Id, StringComparer.Ordinal);
var yearOf = after.Classes.ToDictionary(schoolClass => schoolClass.Id, schoolClass => schoolClass.Year, StringComparer.Ordinal);
@@ -106,7 +106,7 @@ public class YearlyIntakeTests
}
}
var after = YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Slavic", September);
var after = YearlyIntake.Apply(catalog, before, Fixtures.SchoolSeed, "Russia", September);
var afterIds = after.People.Select(person => person.Id).ToHashSet(StringComparer.Ordinal);
Assert.NotEmpty(shouldLeave);
Assert.All(shouldLeave, id => Assert.DoesNotContain(id, afterIds));
+1 -1
View File
@@ -1,4 +1,4 @@
# seed=20260818 nameset=Slavic native=RussianLanguage people=130 classes=4
# seed=20260818 country=Russia native=RussianLanguage people=130 classes=4
class class-classroom-00 year=1 letter=А room=classroom-00 capacity=16 pupils=f1.c1,f1.c2,f13.c0,f18.c0,f19.c0,f24.c1,f26.c1,f27.c1,f27.c2,f28.c2,f32.c1,f33.c0,f34.c0,f6.c0,f6.c2,f8.c0
class class-classroom-01 year=2 letter=А room=classroom-01 capacity=16 pupils=f0.c1,f12.c0,f12.c1,f12.c2,f13.c1,f13.c2,f14.c2,f20.c0,f23.c1,f26.c0,f27.c0,f29.c0,f31.c0,f4.c0,f7.c0,f9.c0
class class-classroom-02 year=3 letter=А room=classroom-02 capacity=16 pupils=f10.c0,f14.c0,f16.c0,f17.c1,f2.c0,f21.c0,f22.c1,f23.c0,f25.c0,f28.c0,f3.c0,f3.c1,f32.c0,f32.c2,f5.c0,f6.c1
@@ -172,12 +172,12 @@ public class DecisionTests
private static (School School, string Homeroom, string PupilId) TwoHomeroomLessons()
{
var (catalog, map) = Vanilla();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", TuesdayMorning);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Slavic", TuesdayMorning);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", TuesdayMorning);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Russia", TuesdayMorning);
var schoolClass = roster.Classes.First(row =>
row.RoomId is "classroom-101" or "classroom-102" or "classroom-103" or "classroom-104");
var school = School.Create(1, "Два урока", TuesdayMorning, catalog, map);
school.InstallPeople(roster, seed: 1, "Slavic", pool);
school.InstallPeople(roster, seed: 1, "Russia", pool);
school.SetTimetable(new Timetable(
[
new LessonPlacement(schoolClass.Id, "Mathematics", "t1", schoolClass.RoomId, Day: 1, Period: 1),
@@ -193,12 +193,12 @@ public class DecisionTests
private static School OpenStaffed(DefCatalog catalog, MapLayout map, int seed)
{
var roster = RosterGenerator.Generate(catalog, map, seed, "Slavic", TuesdayMorning);
var pool = ApplicantPool.Create(catalog, roster, seed, "Slavic", TuesdayMorning);
var roster = RosterGenerator.Generate(catalog, map, seed, "Russia", TuesdayMorning);
var pool = ApplicantPool.Create(catalog, roster, seed, "Russia", TuesdayMorning);
var schoolClass = roster.Classes.First(row =>
row.RoomId is "classroom-101" or "classroom-102" or "classroom-103" or "classroom-104");
var school = School.Create(seed, "Решения", TuesdayMorning, catalog, map);
school.InstallPeople(roster, seed, "Slavic", pool);
school.InstallPeople(roster, seed, "Russia", pool);
school.SetTimetable(new Timetable(
[
new LessonPlacement(schoolClass.Id, "Mathematics", "t1", schoolClass.RoomId, Day: 1, Period: 1),
+3 -3
View File
@@ -93,8 +93,8 @@ public class LunchTests
private static School StaffedSchool()
{
var (catalog, map) = Vanilla();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", Tuesday6);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Slavic", Tuesday6);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", Tuesday6);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Russia", Tuesday6);
foreach (var subject in catalog.Subjects.Values.Where(def => !def.Abstract).Select(def => def.DefName))
{
@@ -120,7 +120,7 @@ public class LunchTests
}
var school = School.Create(1, "Столовая", Tuesday6, catalog, map);
school.InstallPeople(roster, seed: 1, "Slavic", pool);
school.InstallPeople(roster, seed: 1, "Russia", pool);
school.SetTimetable(SchoolTimetables.Build(catalog, map, roster, null, weekDays: 5));
school.ConfigurePresence(weekDays: 5, maxDecisionsPerTick: 64);
return school;
@@ -14,11 +14,11 @@ public class PeopleInSchoolTests
{
var (catalog, map) = Vanilla();
var demand = SchoolDemand.From(catalog, map);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", Start);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Slavic", Start);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", Start);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Russia", Start);
using var school = School.Create(1, "Полная", Start, catalog, map);
school.InstallPeople(roster, seed: 1, "Slavic", pool);
school.InstallPeople(roster, seed: 1, "Russia", pool);
school.Tick(1d / 20d, 5d);
Assert.Same(roster, school.Roster);
@@ -39,11 +39,11 @@ public class PeopleInSchoolTests
{
var start = new DateTime(2012, 3, 31, 6, 0, 0, DateTimeKind.Utc);
var (catalog, map) = Vanilla();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", start);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Slavic", start);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", start);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Russia", start);
using var school = School.Create(1, "Неделя", start, catalog, map);
school.InstallPeople(roster, seed: 1, "Slavic", pool);
school.InstallPeople(roster, seed: 1, "Russia", pool);
var monday = new DateTime(2012, 4, 2, 6, 0, 0, DateTimeKind.Utc);
var changed = school.Tick((monday - start).TotalMinutes / 5d, 5d);
@@ -60,7 +60,7 @@ public class PeopleInSchoolTests
public void OffCampusNeeds_DoNotMoveOnTick()
{
var (catalog, map) = Vanilla();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 2, "Slavic", Start);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 2, "Russia", Start);
using var school = School.Create(2, "Нужды", Start, catalog, map);
school.InstallPeople(roster, seed: 2);
@@ -108,8 +108,8 @@ public class PeopleInSchoolTests
public void SameSeed_InstallsTheSameNames()
{
var (catalog, map) = Vanilla();
var first = RosterGenerator.Generate(catalog, map, schoolSeed: 9, "Slavic", Start);
var second = RosterGenerator.Generate(catalog, map, schoolSeed: 9, "Slavic", Start);
var first = RosterGenerator.Generate(catalog, map, schoolSeed: 9, "Russia", Start);
var second = RosterGenerator.Generate(catalog, map, schoolSeed: 9, "Russia", Start);
using var a = School.Create(9, "А", Start, catalog, map);
using var b = School.Create(9, "Б", Start, catalog, map);
@@ -126,7 +126,7 @@ public class PeopleInSchoolTests
{
var catalog = Catalog();
var map = Classrooms(4);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", Start);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", Start);
var demand = SchoolDemand.From(catalog, map);
var oldest = roster.Classes.Max(schoolClass => schoolClass.Year);
var graduated = roster.Classes
@@ -135,7 +135,7 @@ public class PeopleInSchoolTests
.ToHashSet(StringComparer.Ordinal);
using var school = School.Create(1, "Четыре кабинета", Start, catalog, map);
school.InstallPeople(roster, seed: 1, "Slavic");
school.InstallPeople(roster, seed: 1, "Russia");
var sept = new DateTime(2012, 9, 1, 0, 0, 0, DateTimeKind.Utc);
var changed = school.Tick((sept - Start).TotalMinutes / 5d, 5d);
@@ -160,9 +160,9 @@ public class PeopleInSchoolTests
var start = new DateTime(2012, 9, 1, 6, 0, 0, DateTimeKind.Utc);
var catalog = Catalog();
var map = Classrooms(4);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 3, "Slavic", start);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 3, "Russia", start);
using var school = School.Create(3, "Первое сентября", start, catalog, map);
school.InstallPeople(roster, seed: 3, "Slavic");
school.InstallPeople(roster, seed: 3, "Russia");
var years = roster.Classes.Select(schoolClass => schoolClass.Year).OrderBy(year => year).ToArray();
var changed = school.Tick(1d / 20d, 5d);
+13 -13
View File
@@ -30,15 +30,15 @@ public class PresenceTests
public void ClassWithoutLessons_StaysAway_TeacherWithAnotherClassComes()
{
var (catalog, map) = Vanilla();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", TuesdayMorning);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Slavic", TuesdayMorning);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", TuesdayMorning);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Russia", TuesdayMorning);
var idle = roster.Classes[0];
var busy = roster.Classes[1];
var hired = Staffing.Hire(catalog, map, roster, pool, pool.Applicants[0].Person.Id, Staffing.TeacherPosition, Cap);
Assert.Equal(StaffingError.None, hired.Error);
using var school = School.Create(1, "Два класса", TuesdayMorning, catalog, map);
school.InstallPeople(hired.Roster, seed: 1, "Slavic", hired.Pool);
school.InstallPeople(hired.Roster, seed: 1, "Russia", hired.Pool);
school.SetTimetable(new Timetable(
[new LessonPlacement(busy.Id, "Mathematics", hired.Roster.People.First(person => person.IsStaff).Id, busy.RoomId, Day: 1, Period: 1)],
[]));
@@ -108,7 +108,7 @@ public class PresenceTests
Assert.Contains(snapshot, row => row.NodeId is not null && (row.Path.Count > 0 || row.RemainingMinutes > 0));
using var loaded = School.Load(2, "Сейв", live.Clock.Time, running: true, speedIndex: 0, catalog, map);
loaded.InstallPeople(live.Roster!, seed: 4, "Slavic", live.Applicants);
loaded.InstallPeople(live.Roster!, seed: 4, "Russia", live.Applicants);
loaded.SetTimetable(live.Timetable!);
loaded.ConfigurePresence(weekDays: 5, maxDecisionsPerTick: 10_000);
loaded.RestorePresence(snapshot);
@@ -359,12 +359,12 @@ public class PresenceTests
private static School OpenStaffed(DefCatalog catalog, MapLayout map, int seed)
{
var roster = RosterGenerator.Generate(catalog, map, seed, "Slavic", TuesdayMorning);
var pool = ApplicantPool.Create(catalog, roster, seed, "Slavic", TuesdayMorning);
var roster = RosterGenerator.Generate(catalog, map, seed, "Russia", TuesdayMorning);
var pool = ApplicantPool.Create(catalog, roster, seed, "Russia", TuesdayMorning);
var schoolClass = roster.Classes.First(row =>
row.RoomId is "classroom-101" or "classroom-102" or "classroom-103" or "classroom-104");
var school = School.Create(seed, "Присутствие", TuesdayMorning, catalog, map);
school.InstallPeople(roster, seed, "Slavic", pool);
school.InstallPeople(roster, seed, "Russia", pool);
school.SetTimetable(new Timetable(
[
new LessonPlacement(schoolClass.Id, "Mathematics", "t1", schoolClass.RoomId, Day: 1, Period: 1),
@@ -377,11 +377,11 @@ public class PresenceTests
private static School Open(DefCatalog catalog, MapLayout map, DateTime start, int seed)
{
var roster = RosterGenerator.Generate(catalog, map, seed, "Slavic", start);
var pool = ApplicantPool.Create(catalog, roster, seed, "Slavic", start);
var roster = RosterGenerator.Generate(catalog, map, seed, "Russia", start);
var pool = ApplicantPool.Create(catalog, roster, seed, "Russia", start);
var schoolClass = roster.Classes[0];
var school = School.Create(seed, "Присутствие", start, catalog, map);
school.InstallPeople(roster, seed, "Slavic", pool);
school.InstallPeople(roster, seed, "Russia", pool);
school.SetTimetable(new Timetable(
[new LessonPlacement(schoolClass.Id, "Mathematics", "t1", schoolClass.RoomId, Day: 0, Period: 1)],
[]));
@@ -392,10 +392,10 @@ public class PresenceTests
private static School OpenEmpty(DateTime start)
{
var (catalog, map) = Vanilla();
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Slavic", start);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Slavic", start);
var roster = RosterGenerator.Generate(catalog, map, schoolSeed: 1, "Russia", start);
var pool = ApplicantPool.Create(catalog, roster, schoolSeed: 1, "Russia", start);
var school = School.Create(1, "Пустая", start, catalog, map);
school.InstallPeople(roster, seed: 1, "Slavic", pool);
school.InstallPeople(roster, seed: 1, "Russia", pool);
school.ConfigurePresence(weekDays: 5, maxDecisionsPerTick: 10_000);
return school;
}