using System.Collections.Immutable;
namespace OpenNest.Reporting;
public sealed record ReportPoint(double X, double Y);
public sealed record ReportBounds(double Left, double Bottom, double Right, double Top)
{
public double Length => Right - Left;
public double Width => Top - Bottom;
}
/// Native line or arc; angles are radians and a null center denotes a line.
public sealed record ReportSegment(ReportPoint Start, ReportPoint End, ReportPoint? Center,
double Radius, double StartAngle, double SweepAngle);
public sealed record ReportContour(ImmutableArray Segments, bool Closed);
public sealed record ReportGeometry(ImmutableArray Contours, ReportBounds Bounds)
{
public bool StrokeOnly => Contours.Any(contour => !contour.Closed);
}
public sealed record ReportDrawing(string Id, string Name, long Required, long Nested,
long Shortage, long Extra, ImmutableArray Plates, ReportGeometry Geometry)
{
///
/// Net weight of one part in ; null when the nest
/// has no thickness or the material has no density.
///
public double? Weight { get; init; }
}
public sealed record ReportPlacement(string ReportId, ReportGeometry Geometry);
///
/// A machine clamp footprint in the parts' placement frame. marks a
/// rail clamp taken off this sheet (by Auto Nest or by hand), which the operator pulls before cutting.
///
public sealed record ReportClamp(string Id, ReportBounds Bounds, bool Removed);
public sealed record ReportPlate(int Number, ReportBounds Bounds, int Copies, double PartSpacing,
double Utilization, ImmutableArray Parts, ImmutableArray Cutoffs)
{
/// Estimated time to cut one copy of this plate; null when no estimate was requested.
public TimeSpan? CutTime { get; init; }
///
/// Weight of one full sheet (outline area x nest thickness x the nest material's density) in
/// ; null when the thickness or density is unknown.
///
public double? Weight { get; init; }
/// Clamps on this sheet, active and removed; display only, never material.
public ImmutableArray Clamps { get; init; } = ImmutableArray.Empty;
}
/// A detached value snapshot. No domain objects or mutable geometry are retained.
public sealed record NestReportSnapshot(string Name, string Customer, string Notes, string Material,
string Grade, double Thickness, string Units, DateTimeOffset GeneratedAt,
ImmutableArray Drawings, ImmutableArray Plates)
{
public long TotalSheets => Plates.Aggregate(0L, (total, plate) => checked(total + plate.Copies));
///
/// The name the nest machine's config gives this thickness ("16 ga"), shown before the
/// decimal; empty when it has none. Reporting does not read machine configs, so the caller
/// supplies it.
///
public string ThicknessName { get; init; } = "";
/// "lb" for inch jobs, "kg" for millimeter jobs.
public string WeightUnits => Units == "mm" ? "kg" : "lb";
/// True when the report carries estimated cut times.
public bool HasCutTimes { get; init; }
/// Every plate's estimate times its copies; null when the report has no estimates.
public TimeSpan? TotalCutTime => !HasCutTimes
? null
: Plates.Aggregate(TimeSpan.Zero, (total, plate) => total + (plate.CutTime ?? TimeSpan.Zero) * plate.Copies);
}