Update wire protocol to version 6 and enhance timetable functionality
ci / server (push) Failing after 3m53s
ci / client (push) Successful in 15s

- Bumped the wire protocol version to 6, reflecting changes in the communication structure.
- Expanded the timetable API with new endpoints for fetching and managing lesson schedules, including `GET /api/schools/{id}/timetable` and `POST /api/schools/{id}/timetable/pin`.
- Updated the protocol documentation to include detailed descriptions of the new timetable features and message structures.
- Enhanced the client-side implementation to support the new timetable functionalities, including lesson pinning and unpinning.
- Revised server-side logic to handle timetable operations and ensure proper integration with existing school management features.
- Added tests to validate the new timetable functionalities and ensure robustness in handling lesson data.
This commit is contained in:
Leonid Pershin
2026-08-19 10:05:05 +03:00
parent 2011d12b1d
commit cad3068bac
30 changed files with 1621 additions and 43 deletions
+35 -2
View File
@@ -1,6 +1,7 @@
using HSchool.Content;
using HSchool.People;
using HSchool.Protocol;
using HSchool.Schedule;
using HSchool.Server.Api;
using HSchool.Server.Net;
using HSchool.Simulation;
@@ -64,7 +65,12 @@ internal sealed class GameLoopService(
{
if (worker.Id == schoolId)
{
return new PublishedSchoolPeople(worker.Snapshot, worker.RosterSnapshot, worker.ApplicantSnapshot, worker.CatalogSnapshot);
return new PublishedSchoolPeople(
worker.Snapshot,
worker.RosterSnapshot,
worker.ApplicantSnapshot,
worker.CatalogSnapshot,
worker.TimetableSnapshot);
}
}
@@ -192,6 +198,20 @@ internal sealed class GameLoopService(
new WorkerCommand.UnassignSubject(unassign.PersonId, unassign.Subject, unassign.Result),
unassign.Result);
break;
case GameCommand.PinLesson pin:
HandleTimetable(
pin.SchoolId,
new WorkerCommand.PinLesson(pin.ClassId, pin.Subject, pin.RoomId, pin.Day, pin.Period, pin.Result),
pin.Result);
break;
case GameCommand.UnpinLesson unpin:
HandleTimetable(
unpin.SchoolId,
new WorkerCommand.UnpinLesson(unpin.ClassId, unpin.Subject, unpin.Day, unpin.Period, unpin.Result),
unpin.Result);
break;
}
}
@@ -212,6 +232,14 @@ internal sealed class GameLoopService(
}
}
private void HandleTimetable(int schoolId, WorkerCommand command, TaskCompletionSource<TimetableOutcome> result)
{
if (!_workers.TryGetValue(schoolId, out var worker) || !worker.Post(command))
{
result.TrySetResult(TimetableOutcome.Fail(TimetableError.UnknownSchool));
}
}
/// <summary>
/// A school's thread died. Drop it from the table so the menu stops drawing a card whose clock
/// never moves again, and tell anybody watching it to go back to the menu. The save file stays
@@ -610,4 +638,9 @@ internal sealed class GameLoopService(
}
}
internal sealed record PublishedSchoolPeople(SchoolState School, Roster? Roster, ApplicantPool? Applicants, DefCatalog? Catalog);
internal sealed record PublishedSchoolPeople(
SchoolState School,
Roster? Roster,
ApplicantPool? Applicants,
DefCatalog? Catalog,
Timetable? Timetable);