using System; using System.Collections.Generic; namespace OpenNest; public enum NestJobStatus { Complete, Incomplete } public enum NestJobStopReason { Completed, StockExhausted, NoPlacementFound, PlateLimitReached } /// /// Rotate about the snapshot origin, then translate by X/Y into the selected plate quadrant frame. /// Rotation is in radians. InstanceIndex is zero-based and unique within a part requirement across the job. /// The runner assigns final instance indices when committing a candidate. /// public sealed record NestJobPlacement(string PartId, int InstanceIndex, double X, double Y, double Rotation); /// Requested = Placed + Unplaced for a requirement ID. public sealed record PartFulfillment(string PartId, int Requested, int Placed, int Unplaced); /// Used counts physical sheets; Remaining is null only for unlimited stock. public sealed record StockUsage(string StockId, int Used, int? Remaining); /// One physical sheet, with owned ordered placements and immutable stock/settings snapshot. public sealed class NestJobPlateResult { public NestJobPlateResult(int plateIndex, NestPlateStock stock, IEnumerable placements) { ArgumentNullException.ThrowIfNull(stock); PlateIndex = plateIndex; Stock = stock; Placements = NestJob.Own(placements); } public int PlateIndex { get; } public string StockId => Stock.Id; public NestPlateStock Stock { get; } public IReadOnlyList Placements { get; } } /// Detached result values in commit/input order; no mutable Drawing, Plate, or NestItem escapes. public sealed class NestJobResult { public NestJobResult(NestJobStatus status, NestJobStopReason stopReason, IEnumerable plates, IEnumerable fulfillment, IEnumerable stockUsage) { Status = status; StopReason = stopReason; Plates = NestJob.Own(plates); Fulfillment = NestJob.Own(fulfillment); StockUsage = NestJob.Own(stockUsage); } public NestJobStatus Status { get; } public NestJobStopReason StopReason { get; } public IReadOnlyList Plates { get; } public IReadOnlyList Fulfillment { get; } public IReadOnlyList StockUsage { get; } }