Editor/Wall/ArchWallExpectedReport.cs

Editor helper that produces a report object describing an ArchWall for the editor. It computes wall height, positions, treatments, openings and other metadata and returns an anonymous POCO suitable for display or serialization.

Reflection
using System.Linq;

namespace Sunless.Architecture;

public sealed class ArchWallExpectedReport : IArchExpectedReport
{
	public ArchKind Kind => ArchKind.Wall;

	public object Describe( object payload, ArchTarget target, ArchTool tool )
	{
		if ( payload is not ArchWall wall || target.Room is null )
		{
			return null;
		}

		var room = target.Room;
		var kit = tool.Kit;
		var height = ArchWallSection.Height( wall, room, kit );

		return new
		{
			wall.Id,
			Start = $"{wall.Start.x:0.#},{wall.Start.y:0.#}",
			End = $"{wall.End.x:0.#},{wall.End.y:0.#}",
			wall.Length,
			Height = height,
			Thickness = wall.Thickness > 0f ? wall.Thickness : kit.WallThickness,
			BaseZ = room.BaseHeight,
			TopZ = room.BaseHeight + height,
			Cladding = wall.Cladding.ToString(),
			wall.Wainscot,
			wall.Baseboard,
			wall.Cap,
			Bands = ArchWallTreatments.Ordered( wall.Bands, height )
				.Select( band => $"{band.At( height ):0.#}{(band.AtHead ? " (head)" : "")} {band.Field}"
					+ $"{(band.Course ? $" {band.Seat.ToString().ToLowerInvariant()} course" : "")}" )
				.ToList(),
			Pilasters = wall.Pilasters.Stands ? $"{wall.Pilasters.Bay:0.#} bay, {wall.Pilasters.Width:0.#} wide" : null,
			Openings = wall.Openings.Select( opening => new
			{
				opening.Id,
				opening.Preset,
				Kind = opening.Kind.ToString(),
				opening.Offset,
				opening.Width,
				opening.Height,
				opening.SillHeight,
				LeftAlong = opening.Left,
				RightAlong = opening.Right,
				BottomZ = room.BaseHeight + opening.SillHeight,
				TopZ = room.BaseHeight + opening.Top,
				Glazed = opening.IsGlazed,
				Hung = opening.IsHung,
				Furniture = opening.Fitted.ToString()
			} ).ToList()
		};
	}
}