- Updated protocol documentation to include new `activity` and `activityLabel` fields in the person card response, reflecting real-time activity status. - Introduced `BehaviorDef` to define behavior rules, including need thresholds and lesson skill gains, enhancing AI decision-making. - Revised the `DefCatalog` to incorporate behavior definitions and updated validation logic to ensure proper behavior handling. - Enhanced the simulation to manage presence and activity states, allowing for more dynamic interactions within the school environment. - Updated tests to validate the new activity tracking and behavior functionalities, ensuring robust performance and reliability. - Improved localization strings to support new activity and behavior features, enhancing user experience.
105 lines
2.7 KiB
C#
105 lines
2.7 KiB
C#
namespace HSchool.Content;
|
||
|
||
/// <summary>One school's map instance: tree grouping plus a walkable graph of territory and rooms.</summary>
|
||
public sealed class MapLayout
|
||
{
|
||
public TerritoryNode? Territory { get; init; }
|
||
|
||
public IReadOnlyList<BuildingNode> Buildings { get; init; } = [];
|
||
|
||
public IReadOnlyList<FloorNode> Floors { get; init; } = [];
|
||
|
||
public IReadOnlyList<RoomNode> Rooms { get; init; } = [];
|
||
|
||
public IReadOnlyList<MapLink> Links { get; init; } = [];
|
||
|
||
public static MapLayout Parse(string jsonc, string? source = null) =>
|
||
Jsonc.Deserialize<MapLayout>(Jsonc.Parse(jsonc, source));
|
||
|
||
/// <summary>RoomDef or TerritoryDef of this node, or null when the id is not on the map.</summary>
|
||
public string? NodeDef(string nodeId)
|
||
{
|
||
if (Territory is { } territory && territory.Id.Equals(nodeId, StringComparison.Ordinal))
|
||
{
|
||
return territory.Def;
|
||
}
|
||
|
||
foreach (var room in Rooms)
|
||
{
|
||
if (room.Id.Equals(nodeId, StringComparison.Ordinal))
|
||
{
|
||
return room.Def;
|
||
}
|
||
}
|
||
|
||
return null;
|
||
}
|
||
}
|
||
|
||
public sealed class TerritoryNode
|
||
{
|
||
public required string Id { get; init; }
|
||
|
||
public required string Def { get; init; }
|
||
}
|
||
|
||
public sealed class BuildingNode
|
||
{
|
||
public required string Id { get; init; }
|
||
|
||
public required string Def { get; init; }
|
||
}
|
||
|
||
public sealed class FloorNode
|
||
{
|
||
public required string Id { get; init; }
|
||
|
||
public required string Def { get; init; }
|
||
|
||
public required string Building { get; init; }
|
||
|
||
public string? Label { get; init; }
|
||
}
|
||
|
||
public sealed class RoomNode
|
||
{
|
||
public required string Id { get; init; }
|
||
|
||
public required string Def { get; init; }
|
||
|
||
public required string Building { get; init; }
|
||
|
||
public required string Floor { get; init; }
|
||
|
||
/// <summary>Optional designation such as a classroom number. The def label still supplies the noun.</summary>
|
||
public string? Label { get; init; }
|
||
|
||
/// <summary>
|
||
/// Homeroom seat count. Capacity is <c>SeatThing.PupilSlots × Seats</c>. Named
|
||
/// <see cref="Slots"/> stay on rooms whose furnishing actually varies.
|
||
/// </summary>
|
||
public int Seats { get; init; }
|
||
|
||
public IReadOnlyList<SlotFill> Slots { get; init; } = [];
|
||
}
|
||
|
||
public sealed class SlotFill
|
||
{
|
||
public required string Key { get; init; }
|
||
|
||
public required string Thing { get; init; }
|
||
|
||
/// <summary>
|
||
/// How many of <see cref="Thing"/> occupy this slot. Missing or non-positive JSON is 1, so
|
||
/// older maps without a count still round-trip.
|
||
/// </summary>
|
||
public int Count { get; init; } = 1;
|
||
}
|
||
|
||
public sealed class MapLink
|
||
{
|
||
public required string A { get; init; }
|
||
|
||
public required string B { get; init; }
|
||
}
|