Implement phase 35 dress appropriateness and school rules.

Adds outfit evaluation, morning home dressing, locker-room ChangeClothes with day-log events, PE/weather AI goals, dress-rules API, and tests.
This commit is contained in:
Leonid Pershin
2026-08-20 05:16:52 +03:00
parent 5b63c72806
commit 6a0d5a9886
32 changed files with 1894 additions and 25 deletions
+40
View File
@@ -37,6 +37,7 @@ internal sealed class SchoolWorker
private string? _nativeLanguage;
private readonly int? _createSeed;
private readonly IReadOnlyList<PresenceSnapshot>? _savedPresence;
private readonly SchoolDressRules? _savedDressRules;
private readonly Action<int> _onFailed;
private readonly int _id;
@@ -72,6 +73,7 @@ internal sealed class SchoolWorker
string? nativeLanguage,
int? createSeed,
IReadOnlyList<PresenceSnapshot>? savedPresence,
SchoolDressRules? savedDressRules,
SimulationOptions options,
ClientRegistry clients,
GameMetrics metrics,
@@ -93,6 +95,7 @@ internal sealed class SchoolWorker
_nativeLanguage = nativeLanguage;
_createSeed = createSeed;
_savedPresence = savedPresence;
_savedDressRules = savedDressRules;
_options = options;
_clients = clients;
_metrics = metrics;
@@ -248,6 +251,7 @@ internal sealed class SchoolWorker
}
_school = school;
school.DressRules = _savedDressRules ?? new SchoolDressRules();
PublishSnapshot();
if (_isNew)
@@ -458,6 +462,29 @@ internal sealed class SchoolWorker
unpin.Result.TrySetResult(
ApplyUnpin(school, unpin.ClassId, unpin.Subject, unpin.Day, unpin.Period));
break;
case WorkerCommand.GetDressRules getRules:
getRules.Result.TrySetResult(DressRulesOutcome.Ok(school.DressRules));
break;
case WorkerCommand.SetDressRules setRules:
{
var next = school.DressRules;
if (setRules.PendingStudents is { } students)
{
next = next with { PendingStudents = students };
}
if (setRules.PendingStaff is { } staff)
{
next = next with { PendingStaff = staff };
}
school.DressRules = next;
setRules.Result.TrySetResult(DressRulesOutcome.Ok(school.DressRules));
dirty = true;
break;
}
}
}
catch (Exception ex)
@@ -511,6 +538,12 @@ internal sealed class SchoolWorker
case WorkerCommand.UnpinLesson unpin:
unpin.Result.TrySetResult(TimetableOutcome.Fail(TimetableError.UnknownSchool));
break;
case WorkerCommand.GetDressRules getRules:
getRules.Result.TrySetResult(DressRulesOutcome.Fail(DressRulesError.UnknownSchool));
break;
case WorkerCommand.SetDressRules setRules:
setRules.Result.TrySetResult(DressRulesOutcome.Fail(DressRulesError.UnknownSchool));
break;
}
}
@@ -542,6 +575,12 @@ internal sealed class SchoolWorker
case WorkerCommand.UnpinLesson unpin:
unpin.Result.TrySetException(exception);
break;
case WorkerCommand.GetDressRules getRules:
getRules.Result.TrySetException(exception);
break;
case WorkerCommand.SetDressRules setRules:
setRules.Result.TrySetException(exception);
break;
}
}
@@ -1014,6 +1053,7 @@ internal sealed class SchoolWorker
ClimatePresetId = school.ClimatePresetId,
NativeLanguage = _nativeLanguage,
Presence = school.CapturePresence(),
DressRules = school.DressRules,
});
}
catch (Exception ex)