Update wire protocol to version 6 and enhance timetable functionality
- 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:
@@ -129,6 +129,18 @@ public static class ProtocolCodec
|
||||
{
|
||||
size += StringSize(position);
|
||||
}
|
||||
|
||||
size += sizeof(byte);
|
||||
if (HasActivity(node))
|
||||
{
|
||||
size += StringSize(node.ActivitySubject) + StringSize(node.ActivityClass);
|
||||
}
|
||||
|
||||
size += sizeof(byte);
|
||||
foreach (var person in node.Present)
|
||||
{
|
||||
size += StringSize(person);
|
||||
}
|
||||
}
|
||||
|
||||
return size;
|
||||
@@ -148,9 +160,9 @@ public static class ProtocolCodec
|
||||
|
||||
foreach (var node in message.Nodes)
|
||||
{
|
||||
if (node.Items.Count > byte.MaxValue || node.Positions.Count > byte.MaxValue)
|
||||
if (node.Items.Count > byte.MaxValue || node.Positions.Count > byte.MaxValue || node.Present.Count > byte.MaxValue)
|
||||
{
|
||||
throw new ProtocolException($"Map node '{node.Id}' has too many items or positions for a u8 count.");
|
||||
throw new ProtocolException($"Map node '{node.Id}' has too many items, positions or people for a u8 count.");
|
||||
}
|
||||
|
||||
writer.WriteByte(node.Kind);
|
||||
@@ -170,6 +182,23 @@ public static class ProtocolCodec
|
||||
{
|
||||
writer.WriteString(position);
|
||||
}
|
||||
|
||||
if (HasActivity(node))
|
||||
{
|
||||
writer.WriteByte(1);
|
||||
writer.WriteString(node.ActivitySubject);
|
||||
writer.WriteString(node.ActivityClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.WriteByte(0);
|
||||
}
|
||||
|
||||
writer.WriteByte((byte)node.Present.Count);
|
||||
foreach (var person in node.Present)
|
||||
{
|
||||
writer.WriteString(person);
|
||||
}
|
||||
}
|
||||
|
||||
return writer.Position;
|
||||
@@ -283,12 +312,41 @@ public static class ProtocolCodec
|
||||
positions[position] = reader.ReadString();
|
||||
}
|
||||
|
||||
nodes[i] = new MapSnapshotNode(kind, id, parentId, name, pupilSlots, items, positions);
|
||||
var hasActivity = reader.ReadByte() != 0;
|
||||
var activitySubject = "";
|
||||
var activityClass = "";
|
||||
if (hasActivity)
|
||||
{
|
||||
activitySubject = reader.ReadString();
|
||||
activityClass = reader.ReadString();
|
||||
}
|
||||
|
||||
var characterCount = reader.ReadByte();
|
||||
var characters = new string[characterCount];
|
||||
for (var person = 0; person < characterCount; person++)
|
||||
{
|
||||
characters[person] = reader.ReadString();
|
||||
}
|
||||
|
||||
nodes[i] = new MapSnapshotNode(
|
||||
kind,
|
||||
id,
|
||||
parentId,
|
||||
name,
|
||||
pupilSlots,
|
||||
items,
|
||||
positions,
|
||||
activitySubject,
|
||||
activityClass,
|
||||
characters);
|
||||
}
|
||||
|
||||
return new ServerMapSnapshotMessage(schoolId, nodes);
|
||||
}
|
||||
|
||||
private static bool HasActivity(MapSnapshotNode node) =>
|
||||
node.ActivitySubject.Length > 0 || node.ActivityClass.Length > 0;
|
||||
|
||||
/// <summary>Matches <see cref="PacketWriter.WriteString"/>: a <c>u16</c> length plus UTF-8.</summary>
|
||||
private static int StringSize(string value) => sizeof(ushort) + Encoding.UTF8.GetByteCount(value);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user