using OpenNest.Geometry; using OpenNest.IO; using System; using System.Collections.Generic; using System.IO; using System.Linq; namespace OpenNest.Benchmark { /// /// Builds BenchmarkJobs from .nest files on disk. Fully generic: works on any /// valid .nest file, using whatever drawings/quantities/plate settings it contains. /// Optionally sweeps a fixed list of sheet sizes instead of the sizes embedded /// in the file, so the same drawing set can be benchmarked across a standard /// sheet-size lineup. /// public static class JobLoader { public static List Load(string inputPath, IReadOnlyList sheetSizeOverrides = null, double? partSpacingOverride = null) { var files = ResolveFiles(inputPath); var jobs = new List(); foreach (var file in files) { Nest nest; try { nest = new NestReader(file).Read(); } catch (Exception ex) { Console.Error.WriteLine($"[JobLoader] Skipping '{file}': failed to read ({ex.Message})"); continue; } var requests = BuildRequests(nest); if (requests.Count == 0) { Console.Error.WriteLine($"[JobLoader] Skipping '{file}': no drawings with quantity > 0"); continue; } var template = ResolvePlateTemplate(nest); var sizes = sheetSizeOverrides != null && sheetSizeOverrides.Count > 0 ? sheetSizeOverrides : ResolveSheetSizes(nest); foreach (var size in sizes) { jobs.Add(new BenchmarkJob { SourceFile = file, SheetSizeLabel = size.ToString(1), PlateSize = size, EdgeSpacing = template.EdgeSpacing, PartSpacing = partSpacingOverride ?? template.PartSpacing, Quadrant = template.Quadrant, Requests = requests, }); } } return jobs; } private static List ResolveFiles(string inputPath) { if (Directory.Exists(inputPath)) { return Directory.GetFiles(inputPath, "*.nest", SearchOption.AllDirectories) .OrderBy(f => f, StringComparer.OrdinalIgnoreCase) .ToList(); } if (File.Exists(inputPath)) return new List { inputPath }; throw new FileNotFoundException($"Benchmark input not found: {inputPath}"); } private static List BuildRequests(Nest nest) { var requests = new List(); foreach (var drawing in nest.Drawings) { var qty = drawing.Quantity.Required; if (qty <= 0) continue; var constraints = drawing.Constraints; requests.Add(new DrawingRequest { Drawing = drawing, Quantity = qty, Priority = drawing.Priority, StepAngle = constraints?.StepAngle ?? 0, RotationStart = constraints?.StartAngle ?? 0, RotationEnd = constraints?.EndAngle ?? 0, }); } return requests; } private static (Spacing EdgeSpacing, double PartSpacing, int Quadrant) ResolvePlateTemplate(Nest nest) { var source = nest.Plates?.FirstOrDefault(); if (source != null) return (source.EdgeSpacing, source.PartSpacing, source.Quadrant); var defaults = nest.PlateDefaults; return (defaults.EdgeSpacing, defaults.PartSpacing, defaults.Quadrant); } private static List ResolveSheetSizes(Nest nest) { var sizes = (nest.Plates ?? Enumerable.Empty()) .Select(p => p.Size) .Distinct() .ToList(); if (sizes.Count == 0) sizes.Add(nest.PlateDefaults.Size); return sizes; } } }