using System;
using OpenNest;
namespace OpenNest.Engine.Jobs;
/// Immutable per-job options; selection never changes the legacy global registry.
public sealed class NestJobOptions
{
public NestJobOptions(
string placementStrategy = "Lattice",
int? maxPlates = null,
double salvageRate = 0,
double minimumSalvageDimension = 0,
bool searchUntilCancelled = false,
CutOffAxis? offcutCut = null
)
{
if (offcutCut is { } axis && !Enum.IsDefined(axis))
throw new ArgumentOutOfRangeException(nameof(offcutCut));
ArgumentException.ThrowIfNullOrWhiteSpace(placementStrategy);
if (maxPlates <= 0)
throw new ArgumentOutOfRangeException(nameof(maxPlates));
if (!double.IsFinite(salvageRate) || salvageRate < 0 || salvageRate > 1)
throw new ArgumentOutOfRangeException(nameof(salvageRate));
if (!double.IsFinite(minimumSalvageDimension) || minimumSalvageDimension < 0)
throw new ArgumentOutOfRangeException(nameof(minimumSalvageDimension));
PlacementStrategy = placementStrategy;
MaxPlates = maxPlates;
SalvageRate = salvageRate;
MinimumSalvageDimension = minimumSalvageDimension;
SearchUntilCancelled = searchUntilCancelled;
OffcutCut = offcutCut;
}
///
/// When set, only the edge strips one cut along this axis frees count as a sheet's offcut, for
/// salvage credit and for the compactness tie-break between equal-cost plans:
/// keeps full-width strips at the bottom or top (the drop
/// off the end of a sheet), full-length ones at the sides.
/// Null (the default) counts the largest of all four.
///
public CutOffAxis? OffcutCut { get; }
///
/// Asks engines that support it to keep searching after their normal search, reporting
/// each better plan () until the solve's token is
/// cancelled, which then ends the solve with .
/// Meant for a caller that keeps the best reported plan at a time limit, such as
/// . Ignored when the token cannot be
/// cancelled. Results then depend on how long the search ran.
///
public bool SearchUntilCancelled { get; }
/// A copy of these options with set.
public NestJobOptions WithSearchUntilCancelled(bool value) =>
new(PlacementStrategy, MaxPlates, SalvageRate, MinimumSalvageDimension, value, OffcutCut);
/// Fraction of eligible edge-offcut area credited by (0..1).
public double SalvageRate { get; }
/// Both offcut dimensions must meet this caller-supplied minimum in job units.
/// Zero disables credit; scraps and holes are never credited.
public double MinimumSalvageDimension { get; }
public string PlacementStrategy { get; }
/// Maximum physical sheets to commit, or null for no explicit cap.
public int? MaxPlates { get; }
}