Enhance school day structure and decision-making for lunch breaks
- Updated `ai.md` to clarify the mechanics of hunger restoration and the importance of lunch breaks in the school schedule. - Revised `schedule.md` to detail the new lunch break structure, allowing for separate sittings for different grade levels. - Enhanced `Decision.cs` and `DecisionPlanner.cs` to incorporate logic for lunch breaks, ensuring that students only leave lessons during their designated lunch windows. - Updated `DayFrameDef` and related classes to support multiple lunch breaks and validate their configurations. - Adjusted tests to validate the new decision-making logic regarding lunch breaks and hunger management, ensuring robust functionality. - Improved localization strings to reflect changes in the school day structure and lunch functionalities.
This commit is contained in:
@@ -204,12 +204,17 @@ public class GameSocketTests(AppHostFixture fixture)
|
||||
Assert.NotNull(directory);
|
||||
Assert.Contains(directory.People, person => person.Id == applicant.Id && person.FullName == applicant.FullName);
|
||||
|
||||
// Resume and check that people ride the frame at all — that is what "occupancy is on
|
||||
// presence, not the snapshot" means. Do not wait for the freshly hired teacher in
|
||||
// particular: whether somebody hired mid-day comes in today depends on their day plan,
|
||||
// and the frozen moment drifts with however long this test's own HTTP calls took (the
|
||||
// school runs at five game minutes per real second until it is paused). Waiting for that
|
||||
// one person made this test fail under load.
|
||||
await SendAsync(socket, buffer =>
|
||||
ProtocolCodec.WriteSetRunning(buffer, new ClientSetRunningMessage(Running: true)));
|
||||
presence = await ReceivePresenceWhereAsync(
|
||||
socket,
|
||||
frame => frame.People.Any(person => person.Id == applicant.Id));
|
||||
Assert.Contains(presence.People, person => person.Id == applicant.Id);
|
||||
presence = await ReceivePresenceWhereAsync(socket, frame => frame.People.Count > 0);
|
||||
Assert.All(presence.People, person => Assert.False(string.IsNullOrWhiteSpace(person.NodeId)));
|
||||
Assert.Contains(presence.People, person => directory.People.Any(row => row.Id == person.Id));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -179,25 +179,10 @@ public class StaffingApiTests(AppHostFixture fixture)
|
||||
Assert.True(assigned.Payroll > hired.Payroll);
|
||||
Assert.Equal(2, assigned.Staff.Single().Subjects.Count);
|
||||
|
||||
using var over = await client.PostAsJsonAsync(
|
||||
$"/api/schools/{school.Id}/staff/{Uri.EscapeDataString(teacher.Id)}/subjects",
|
||||
new { subject = "Literature" },
|
||||
TestContext.Current.CancellationToken);
|
||||
// Cheap asks may still fit; only the numbers matter when the cap actually bites.
|
||||
if (over.StatusCode == HttpStatusCode.Conflict)
|
||||
{
|
||||
var problem = await over.Content.ReadFromJsonAsync<ProblemResponse>(TestContext.Current.CancellationToken);
|
||||
Assert.Equal("payroll-exceeded", problem?.Code);
|
||||
Assert.True(problem?.Attempted > problem?.Allocated);
|
||||
Assert.Equal(assigned.Payroll, problem?.Payroll);
|
||||
}
|
||||
else
|
||||
{
|
||||
over.EnsureSuccessStatusCode();
|
||||
assigned = await over.Content.ReadFromJsonAsync<StaffingResponse>(TestContext.Current.CancellationToken);
|
||||
Assert.NotNull(assigned);
|
||||
}
|
||||
|
||||
// A third subject used to be tried here with an if/else around the cap, which meant the
|
||||
// test passed whichever way it went. The refusal has its own test now
|
||||
// (AssigningPastTheCap_IsRejectedWithTheNumbers); this one is about assign, unassign and
|
||||
// what survives a restart.
|
||||
var payrollWithSubjects = assigned.Payroll;
|
||||
using var unassign = await client.DeleteAsync(
|
||||
$"/api/schools/{school.Id}/staff/{Uri.EscapeDataString(teacher.Id)}/subjects/RussianLanguage",
|
||||
|
||||
Reference in New Issue
Block a user