Enhance school creation and staffing management with native language support
ci / server (push) Failing after 3m44s
ci / client (push) Successful in 14s

- Updated protocol documentation to include `nativeLanguages` in `nameSets` and added `nativeLanguage` to school creation options.
- Enhanced the UI for school creation to allow selection of native languages, improving user experience.
- Revised API interfaces to accommodate new native language features, ensuring proper data handling.
- Improved localization strings to support new native language functionalities in both English and Russian.
- Updated tests to validate the new native language features and ensure robust functionality in staffing scenarios.
This commit is contained in:
Leonid Pershin
2026-08-19 22:22:31 +03:00
parent 21d79cb49b
commit 5a00ad7746
48 changed files with 2064 additions and 312 deletions
+7 -3
View File
@@ -78,6 +78,9 @@ public sealed class School : IDisposable
/// <summary>Name pack used to generate this school's people. Needed again on 1 September.</summary>
public string? NameSetId { get; private set; }
/// <summary>Skill everyone generated for this school speaks natively.</summary>
public string? NativeLanguage { get; private set; }
/// <summary>Last built table. Null until the worker installs people.</summary>
public Timetable? Timetable { get; private set; }
@@ -115,7 +118,7 @@ public sealed class School : IDisposable
/// <summary>
/// Installs a roster that already matches the map. Spawns entities; does not write to disk.
/// </summary>
public void InstallPeople(Roster roster, int seed, string? nameSetId = null, ApplicantPool? applicants = null)
public void InstallPeople(Roster roster, int seed, string? nameSetId = null, ApplicantPool? applicants = null, string? nativeLanguage = null)
{
ObjectDisposedException.ThrowIf(_disposed, this);
ArgumentNullException.ThrowIfNull(roster);
@@ -123,6 +126,7 @@ public sealed class School : IDisposable
Roster = roster;
PeopleSeed = seed;
NameSetId = nameSetId;
NativeLanguage = nativeLanguage;
Applicants = applicants;
RosterSpawner.Spawn(World, roster);
PlanDay = null;
@@ -282,7 +286,7 @@ public sealed class School : IDisposable
var changed = false;
foreach (var date in YearlyIntake.DatesBetween(before, after))
{
Roster = YearlyIntake.Apply(Catalog, Roster, PeopleSeed, NameSetId, date);
Roster = YearlyIntake.Apply(Catalog, Roster, PeopleSeed, NameSetId, date, NativeLanguage);
changed = true;
}
@@ -304,7 +308,7 @@ public sealed class School : IDisposable
return false;
}
var next = Applicants.Advance(Catalog, Roster, PeopleSeed, NameSetId, Clock.Time);
var next = Applicants.Advance(Catalog, Roster, PeopleSeed, NameSetId, Clock.Time, NativeLanguage);
if (next.Week == Applicants.Week)
{
return false;