namespace HSchool.Content;
/// One school's map instance: tree grouping plus a walkable graph of territory and rooms.
public sealed class MapLayout
{
public TerritoryNode? Territory { get; init; }
public IReadOnlyList Buildings { get; init; } = [];
public IReadOnlyList Floors { get; init; } = [];
public IReadOnlyList Rooms { get; init; } = [];
public IReadOnlyList Links { get; init; } = [];
public static MapLayout Parse(string jsonc, string? source = null) =>
Jsonc.Deserialize(Jsonc.Parse(jsonc, source));
/// RoomDef or TerritoryDef of this node, or null when the id is not on the map.
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; }
/// Optional designation such as a classroom number. The def label still supplies the noun.
public string? Label { get; init; }
///
/// Homeroom seat count. Capacity is SeatThing.PupilSlots × Seats. Named
/// stay on rooms whose furnishing actually varies.
///
public int Seats { get; init; }
public IReadOnlyList Slots { get; init; } = [];
}
public sealed class SlotFill
{
public required string Key { get; init; }
public required string Thing { get; init; }
///
/// How many of occupy this slot. Missing or non-positive JSON is 1, so
/// older maps without a count still round-trip.
///
public int Count { get; init; } = 1;
}
public sealed class MapLink
{
public required string A { get; init; }
public required string B { get; init; }
}