Task 6 of the whole-job engine API: adapt the public NestRequest/NestRunner/
NestResponse surface to delegate to the whole-job runner instead of a manual
quantity loop.
- NestRequest: optional explicit Plates stock list (null keeps the legacy
unlimited SheetSize fallback; empty list means no available stock),
optional per-part Id (derived as part-{index} when absent), and an explicit
PlacementStrategy that takes precedence over the legacy Strategy.
- NestRequestPlate: one physical-stock type (id, size, quantity, spacing,
quadrant).
- NestRunner: imports each DXF once, propagates priority/rotation constraints,
runs a single NestJobRunner solve, materializes ID/pose placements exactly
once, and reports aggregate utilization as total placed part area over total
physical sheet area.
- NestResponse: exposes status, stop reason, part fulfillment, stock usage,
and plate-to-stock mapping; .nestquote save/load gains a schema version and
reports completion as unknown for old archives lacking fulfillment metadata.
- Tests: extend the Api request/runner/persistence suites for legacy SheetSize,
explicit mixed finite stock, stock exhaustion, weighted utilization, old
archive loading, and new-archive round trips.
Verification: cross-compiles clean on net8.0-windows (Linux). The Api tests
require a Windows runner (net8.0-windows) and are NOT executed here; the
delegated engine logic is covered by the 70-test net8.0 Engine.Tests suite
(committed in Task 5). Windows runtime verification remains outstanding.
78 lines
2.2 KiB
C#
78 lines
2.2 KiB
C#
using OpenNest.Api;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.Tests.Api;
|
|
|
|
public class NestRequestTests
|
|
{
|
|
[Fact]
|
|
public void Default_Request_HasSensibleDefaults()
|
|
{
|
|
var request = new NestRequest();
|
|
|
|
Assert.Empty(request.Parts);
|
|
Assert.Equal(60, request.SheetSize.Width);
|
|
Assert.Equal(120, request.SheetSize.Length);
|
|
Assert.Null(request.Plates);
|
|
Assert.Equal("Default", request.PlacementStrategy);
|
|
Assert.Equal("Steel, A1011 HR", request.Material);
|
|
Assert.Equal(0.06, request.Thickness);
|
|
Assert.Equal(0.1, request.Spacing);
|
|
Assert.Equal(NestStrategy.Auto, request.Strategy);
|
|
Assert.NotNull(request.Cutting);
|
|
}
|
|
|
|
[Fact]
|
|
public void Parts_Accessible_AfterConstruction()
|
|
{
|
|
var request = new NestRequest
|
|
{
|
|
Parts = [new NestRequestPart { DxfPath = "test.dxf", Quantity = 5 }]
|
|
};
|
|
|
|
Assert.Single(request.Parts);
|
|
Assert.Equal("test.dxf", request.Parts[0].DxfPath);
|
|
Assert.Equal(5, request.Parts[0].Quantity);
|
|
}
|
|
|
|
[Fact]
|
|
public void NestRequestPart_Defaults()
|
|
{
|
|
var part = new NestRequestPart { DxfPath = "part.dxf" };
|
|
|
|
Assert.Null(part.Id);
|
|
Assert.Equal(1, part.Quantity);
|
|
Assert.True(part.AllowRotation);
|
|
Assert.Equal(0, part.Priority);
|
|
}
|
|
|
|
[Fact]
|
|
public void ExplicitPlates_PreserveStockSettings()
|
|
{
|
|
var request = new NestRequest
|
|
{
|
|
Plates =
|
|
[
|
|
new NestRequestPlate
|
|
{
|
|
Id = "remnant",
|
|
Size = new Size(24, 48),
|
|
Quantity = 3,
|
|
PartSpacing = 0.2,
|
|
EdgeSpacing = new Spacing(1, 2, 3, 4),
|
|
Quadrant = 3
|
|
}
|
|
]
|
|
};
|
|
|
|
var plate = Assert.Single(request.Plates!);
|
|
Assert.Equal("remnant", plate.Id);
|
|
Assert.Equal(24, plate.Size.Width);
|
|
Assert.Equal(48, plate.Size.Length);
|
|
Assert.Equal(3, plate.Quantity);
|
|
Assert.Equal(0.2, plate.PartSpacing);
|
|
Assert.Equal(new Spacing(1, 2, 3, 4), plate.EdgeSpacing);
|
|
Assert.Equal(3, plate.Quadrant);
|
|
}
|
|
}
|