style: apply CSharpier formatting to all C# sources

Repo-wide sweep with the pinned CSharpier 1.3.0 tool. Whitespace and
line-wrapping only; OpenNest.Engine.Tests (109) and OpenNest.IO.Tests
pass after reformat, full solution builds 0 errors.

Added .csharpierignore so csproj/config XML keeps its existing layout
(CSharpier's XML wrapping churns attributes with zero benefit).

Formatting is now enforceable: dotnet csharpier check . passes.
This commit is contained in:
aj
2026-09-20 16:41:50 -04:00
parent 8e6fa677fb
commit aec0523062
476 changed files with 16592 additions and 7800 deletions
+3
View File
@@ -6,17 +6,20 @@ namespace OpenNest.Api;
public class NestRequest
{
public IReadOnlyList<NestRequestPart> Parts { get; init; } = [];
/// <summary>
/// Explicit available physical stock. Null keeps the legacy unlimited SheetSize fallback;
/// an empty list deliberately means no stock is available.
/// </summary>
public IReadOnlyList<NestRequestPlate> Plates { get; init; }
public Size SheetSize { get; init; } = new(60, 120);
/// <summary>Built-in whole-job placement strategy. Explicit values take precedence over legacy Strategy.</summary>
public string PlacementStrategy { get; init; } = "Default";
public string Material { get; init; } = "Steel, A1011 HR";
public double Thickness { get; init; } = 0.06;
public double Spacing { get; init; } = 0.1;
/// <summary>Legacy compatibility setting; Auto maps to the Default whole-job strategy.</summary>
public NestStrategy Strategy { get; init; } = NestStrategy.Auto;
public CutParameters Cutting { get; init; } = CutParameters.Default;
+1
View File
@@ -7,6 +7,7 @@ public class NestRequestPlate
{
public string Id { get; init; }
public Size Size { get; init; }
/// <summary>Available physical sheets; null means unlimited.</summary>
public int? Quantity { get; init; }
public double PartSpacing { get; init; }
+41 -25
View File
@@ -25,10 +25,12 @@ public class NestResponse
/// <summary>Zero identifies an archive written before response metadata was versioned.</summary>
public int SchemaVersion { get; init; } = CurrentSchemaVersion;
public int SheetCount { get; init; }
/// <summary>Placed-part area divided by total materialized physical-sheet area, as a 0.0–1.0 ratio.</summary>
public double Utilization { get; init; }
public TimeSpan CutTime { get; init; }
public TimeSpan Elapsed { get; init; }
/// <summary>Null means an older archive did not record whole-job fulfillment status.</summary>
public NestJobStatus? Status { get; init; }
public NestJobStopReason? StopReason { get; init; }
@@ -43,7 +45,7 @@ public class NestResponse
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
IncludeFields = true, // Required for OpenNest.Geometry.Size and Spacing public fields.
Converters = { new JsonStringEnumConverter() }
Converters = { new JsonStringEnumConverter() },
};
public async Task SaveAsync(string path)
@@ -61,19 +63,27 @@ public class NestResponse
var responseEntry = zip.CreateEntry("response.json");
await using (var stream = responseEntry.Open())
{
await JsonSerializer.SerializeAsync(stream, new NestResponseArchiveDto
{
SchemaVersion = CurrentSchemaVersion,
SheetCount = SheetCount,
Utilization = Utilization,
CutTimeTicks = CutTime.Ticks,
ElapsedTicks = Elapsed.Ticks,
Status = Status,
StopReason = StopReason,
Fulfillment = Fulfillment is null ? [] : new List<NestPartFulfillment>(Fulfillment),
StockUsage = StockUsage is null ? [] : new List<NestStockUsage>(StockUsage),
PlateStockMappings = PlateStockMappings is null ? [] : new List<NestPlateStockMapping>(PlateStockMappings)
}, JsonOptions);
await JsonSerializer.SerializeAsync(
stream,
new NestResponseArchiveDto
{
SchemaVersion = CurrentSchemaVersion,
SheetCount = SheetCount,
Utilization = Utilization,
CutTimeTicks = CutTime.Ticks,
ElapsedTicks = Elapsed.Ticks,
Status = Status,
StopReason = StopReason,
Fulfillment = Fulfillment is null
? []
: new List<NestPartFulfillment>(Fulfillment),
StockUsage = StockUsage is null ? [] : new List<NestStockUsage>(StockUsage),
PlateStockMappings = PlateStockMappings is null
? []
: new List<NestPlateStockMapping>(PlateStockMappings),
},
JsonOptions
);
}
var nestEntry = zip.CreateEntry("nest.nest");
@@ -91,16 +101,19 @@ public class NestResponse
using var fs = new FileStream(path, FileMode.Open, FileAccess.Read);
using var zip = new ZipArchive(fs, ZipArchiveMode.Read);
var requestEntry = zip.GetEntry("request.json")
var requestEntry =
zip.GetEntry("request.json")
?? throw new InvalidOperationException("Missing request.json in .nestquote file");
NestRequest request;
await using (var stream = requestEntry.Open())
{
request = await JsonSerializer.DeserializeAsync<NestRequest>(stream, JsonOptions)
request =
await JsonSerializer.DeserializeAsync<NestRequest>(stream, JsonOptions)
?? throw new InvalidOperationException("Invalid request.json in .nestquote file");
}
var responseEntry = zip.GetEntry("response.json")
var responseEntry =
zip.GetEntry("response.json")
?? throw new InvalidOperationException("Missing response.json in .nestquote file");
NestResponseArchiveDto archive;
var hasSchemaVersion = false;
@@ -110,16 +123,19 @@ public class NestResponse
{
var root = document.RootElement;
hasSchemaVersion = root.TryGetProperty("schemaVersion", out _);
hasStatusMetadata = root.TryGetProperty("status", out _) ||
root.TryGetProperty("stopReason", out _) ||
root.TryGetProperty("fulfillment", out _) ||
root.TryGetProperty("stockUsage", out _) ||
root.TryGetProperty("plateStockMappings", out _);
archive = root.Deserialize<NestResponseArchiveDto>(JsonOptions)
hasStatusMetadata =
root.TryGetProperty("status", out _)
|| root.TryGetProperty("stopReason", out _)
|| root.TryGetProperty("fulfillment", out _)
|| root.TryGetProperty("stockUsage", out _)
|| root.TryGetProperty("plateStockMappings", out _);
archive =
root.Deserialize<NestResponseArchiveDto>(JsonOptions)
?? throw new InvalidOperationException("Invalid response.json in .nestquote file");
}
var nestEntry = zip.GetEntry("nest.nest")
var nestEntry =
zip.GetEntry("nest.nest")
?? throw new InvalidOperationException("Missing nest.nest in .nestquote file");
Nest nest;
using (var nestMs = new MemoryStream())
@@ -145,7 +161,7 @@ public class NestResponse
StockUsage = hasStatusMetadata ? archive.StockUsage ?? [] : [],
PlateStockMappings = hasStatusMetadata ? archive.PlateStockMappings ?? [] : [],
Nest = nest,
Request = request
Request = request,
};
}
+104 -46
View File
@@ -16,10 +16,13 @@ public static class NestRunner
public static Task<NestResponse> RunAsync(
NestRequest request,
IProgress<NestProgress> progress = null,
CancellationToken token = default)
CancellationToken token = default
)
{
ArgumentNullException.ThrowIfNull(request);
var requestParts = request.Parts ?? throw new ArgumentException("Request parts must not be null.", nameof(request));
var requestParts =
request.Parts
?? throw new ArgumentException("Request parts must not be null.", nameof(request));
if (requestParts.Count == 0)
throw new ArgumentException("Request must contain at least one part.", nameof(request));
@@ -32,22 +35,32 @@ public static class NestRunner
{
token.ThrowIfCancellationRequested();
if (!File.Exists(part.Request.DxfPath))
throw new FileNotFoundException($"DXF file not found: {part.Request.DxfPath}", part.Request.DxfPath);
throw new FileNotFoundException(
$"DXF file not found: {part.Request.DxfPath}",
part.Request.DxfPath
);
if (!importedByPath.TryGetValue(part.Request.DxfPath, out var drawing))
{
try
{
drawing = CadImporter.ImportDrawing(part.Request.DxfPath,
new CadImportOptions { Quantity = part.Request.Quantity });
drawing = CadImporter.ImportDrawing(
part.Request.DxfPath,
new CadImportOptions { Quantity = part.Request.Quantity }
);
}
catch (Exception exception)
{
throw new InvalidOperationException($"Failed to import DXF: {part.Request.DxfPath}", exception);
throw new InvalidOperationException(
$"Failed to import DXF: {part.Request.DxfPath}",
exception
);
}
if (drawing.Program == null || drawing.Program.Codes.Count == 0)
throw new InvalidOperationException($"Failed to import DXF: {part.Request.DxfPath}");
throw new InvalidOperationException(
$"Failed to import DXF: {part.Request.DxfPath}"
);
importedByPath.Add(part.Request.DxfPath, drawing);
}
@@ -56,8 +69,11 @@ public static class NestRunner
jobParts.Add(DrawingJobMapper.FromDrawing(part.Id, drawing, part.Request.Quantity));
}
var job = new NestJob(jobParts, CreateStock(request),
new NestJobOptions(ResolvePlacementStrategy(request)));
var job = new NestJob(
jobParts,
CreateStock(request),
new NestJobOptions(ResolvePlacementStrategy(request))
);
var jobProgress = progress == null ? null : new JobProgressBridge(progress);
var result = new NestJobRunner(PlateNesterFactory.Create).Solve(job, jobProgress, token);
@@ -71,35 +87,56 @@ public static class NestRunner
var cutTime = Timing.CalculateTime(timingInfo, request.Cutting);
sw.Stop();
return Task.FromResult(new NestResponse
{
SheetCount = nest.Plates.Count,
Utilization = CalculateUtilization(nest),
CutTime = cutTime,
Elapsed = sw.Elapsed,
Status = result.Status,
StopReason = result.StopReason,
Fulfillment = result.Fulfillment
.Select(value => new NestPartFulfillment(value.PartId, value.Requested, value.Placed, value.Unplaced))
.ToArray(),
StockUsage = result.StockUsage
.Select(value => new NestStockUsage(value.StockId, value.Used, value.Remaining))
.ToArray(),
PlateStockMappings = result.Plates
.Select(value => new NestPlateStockMapping(value.PlateIndex, value.StockId))
.ToArray(),
Nest = nest,
Request = request
});
return Task.FromResult(
new NestResponse
{
SheetCount = nest.Plates.Count,
Utilization = CalculateUtilization(nest),
CutTime = cutTime,
Elapsed = sw.Elapsed,
Status = result.Status,
StopReason = result.StopReason,
Fulfillment = result
.Fulfillment.Select(value => new NestPartFulfillment(
value.PartId,
value.Requested,
value.Placed,
value.Unplaced
))
.ToArray(),
StockUsage = result
.StockUsage.Select(value => new NestStockUsage(
value.StockId,
value.Used,
value.Remaining
))
.ToArray(),
PlateStockMappings = result
.Plates.Select(value => new NestPlateStockMapping(
value.PlateIndex,
value.StockId
))
.ToArray(),
Nest = nest,
Request = request,
}
);
}
private static IReadOnlyList<IdentifiedRequestPart> IdentifyParts(IReadOnlyList<NestRequestPart> requestParts)
private static IReadOnlyList<IdentifiedRequestPart> IdentifyParts(
IReadOnlyList<NestRequestPart> requestParts
)
{
var identified = new List<IdentifiedRequestPart>(requestParts.Count);
var ids = new HashSet<string>(StringComparer.Ordinal);
for (var index = 0; index < requestParts.Count; index++)
{
var part = requestParts[index] ?? throw new ArgumentException("Request parts must not contain null entries.", nameof(requestParts));
var part =
requestParts[index]
?? throw new ArgumentException(
"Request parts must not contain null entries.",
nameof(requestParts)
);
var id = part.Id ?? $"part-{index}";
if (string.IsNullOrWhiteSpace(id))
throw new ArgumentException("Part IDs must not be blank.", nameof(requestParts));
@@ -117,8 +154,12 @@ public static class NestRunner
{
return
[
new NestPlateStock(LegacyStockId, request.SheetSize, quantity: null,
partSpacing: request.Spacing)
new NestPlateStock(
LegacyStockId,
request.SheetSize,
quantity: null,
partSpacing: request.Spacing
),
];
}
@@ -126,9 +167,20 @@ public static class NestRunner
foreach (var plate in request.Plates)
{
if (plate is null)
throw new ArgumentException("Request plates must not contain null entries.", nameof(request));
stock.Add(new NestPlateStock(plate.Id, plate.Size, plate.Quantity, plate.PartSpacing,
plate.EdgeSpacing, plate.Quadrant));
throw new ArgumentException(
"Request plates must not contain null entries.",
nameof(request)
);
stock.Add(
new NestPlateStock(
plate.Id,
plate.Size,
plate.Quantity,
plate.PartSpacing,
plate.EdgeSpacing,
plate.Quadrant
)
);
}
return stock;
@@ -147,25 +199,31 @@ public static class NestRunner
}
}
private static string ResolvePlacementStrategy(NestRequest request) => request.PlacementStrategy ?? request.Strategy switch
{
NestStrategy.Auto => "Default",
_ => throw new NotSupportedException($"Unknown legacy nesting strategy: {request.Strategy}.")
};
private static string ResolvePlacementStrategy(NestRequest request) =>
request.PlacementStrategy
?? request.Strategy switch
{
NestStrategy.Auto => "Default",
_ => throw new NotSupportedException(
$"Unknown legacy nesting strategy: {request.Strategy}."
),
};
private static double CalculateUtilization(Nest nest)
{
var sheetArea = nest.Plates.Sum(plate => plate.Area());
if (sheetArea == 0) return 0;
var placedArea = nest.Plates.Sum(plate => plate.Parts
.Where(part => !part.BaseDrawing.IsCutOff)
.Sum(part => part.BaseDrawing.Area));
if (sheetArea == 0)
return 0;
var placedArea = nest.Plates.Sum(plate =>
plate.Parts.Where(part => !part.BaseDrawing.IsCutOff).Sum(part => part.BaseDrawing.Area)
);
return placedArea / sheetArea;
}
private sealed record IdentifiedRequestPart(string Id, NestRequestPart Request);
private sealed class JobProgressBridge(IProgress<NestProgress> progress) : IProgress<NestJobProgress>
private sealed class JobProgressBridge(IProgress<NestProgress> progress)
: IProgress<NestJobProgress>
{
public void Report(NestJobProgress value)
{
+4 -1
View File
@@ -1,3 +1,6 @@
namespace OpenNest.Api;
public enum NestStrategy { Auto }
public enum NestStrategy
{
Auto,
}