using System.Collections.Generic; using System.Linq; namespace OpenNest.IO.Bom { public class BomAnalysis { public List Groups { get; set; } = new List(); public List Skipped { get; set; } = new List(); public List Unmatched { get; set; } = new List(); } public class MaterialGroup { public string Material { get; set; } public double Thickness { get; set; } public List Parts { get; set; } = new List(); } public class MatchedPart { public BomItem Item { get; set; } public string DxfPath { get; set; } } public static class BomAnalyzer { public static BomAnalysis Analyze(List items, string dxfFolder) { var result = new BomAnalysis(); // Case-insensitive lookup of the drawing files in the folder (if it exists) var drawings = DrawingFileIndex.Load(dxfFolder); // Partition items into: skipped, unmatched, or matched (grouped) var matched = new List(); foreach (var item in items) { if (string.IsNullOrWhiteSpace(item.FileName) || !item.Thickness.HasValue) { result.Skipped.Add(item); continue; } if (!drawings.FolderExists) { // No folder to search — group items without a DXF path matched.Add(new MatchedPart { Item = item, DxfPath = null }); } else if (drawings.Find(item.FileName) is { } dxfPath) { matched.Add(new MatchedPart { Item = item, DxfPath = dxfPath }); } else { result.Unmatched.Add(item); } } // Group matched parts by material + thickness var groups = matched .GroupBy(p => new { Material = (p.Item.Material ?? "").ToUpperInvariant(), Thickness = p.Item.Thickness.Value, }) .Select(g => new MaterialGroup { Material = g.First().Item.Material ?? "", Thickness = g.Key.Thickness, Parts = g.ToList(), }) .OrderBy(g => g.Material) .ThenBy(g => g.Thickness) .ToList(); result.Groups = groups; return result; } } }