From 9783d417bd24e92c30072fb5039199b932861724 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sat, 14 Mar 2026 20:57:01 -0400 Subject: [PATCH] feat(engine): show running ledger in progress descriptions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Linear phase shows "Linear: 12/36 angles, 45° = 48 parts" with a running count. Pairs phase shows "Pairs: 8/50 candidates, best = 252 parts" tracking the best result seen so far. Reports on every completion so the UI always reflects current state. Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest.Engine/NestEngine.cs | 52 ++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/OpenNest.Engine/NestEngine.cs b/OpenNest.Engine/NestEngine.cs index 51615a4..1eaf05c 100644 --- a/OpenNest.Engine/NestEngine.cs +++ b/OpenNest.Engine/NestEngine.cs @@ -285,7 +285,7 @@ namespace OpenNest var linearBag = new System.Collections.Concurrent.ConcurrentBag<(FillScore score, List parts)>(); var angleBag = new System.Collections.Concurrent.ConcurrentBag(); - long lastLinearReport = 0; + var anglesCompleted = 0; System.Threading.Tasks.Parallel.ForEach(angles, new System.Threading.Tasks.ParallelOptions { CancellationToken = token }, @@ -307,19 +307,14 @@ namespace OpenNest angleBag.Add(new AngleResult { AngleDeg = angleDeg, Direction = NestDirection.Vertical, PartCount = v.Count }); } - var now = linearSw.ElapsedMilliseconds; - if (progress != null && now - Interlocked.Read(ref lastLinearReport) >= 150) + var done = Interlocked.Increment(ref anglesCompleted); + var bestCount = System.Math.Max(h?.Count ?? 0, v?.Count ?? 0); + progress?.Report(new NestProgress { - Interlocked.Exchange(ref lastLinearReport, now); - var bestDir = (h?.Count ?? 0) >= (v?.Count ?? 0) ? "H" : "V"; - var bestCount = System.Math.Max(h?.Count ?? 0, v?.Count ?? 0); - progress.Report(new NestProgress - { - Phase = NestPhase.Linear, - PlateNumber = PlateNumber, - Description = $"Linear: {angleDeg:F0}° {bestDir} - {bestCount} parts" - }); - } + Phase = NestPhase.Linear, + PlateNumber = PlateNumber, + Description = $"Linear: {done}/{angles.Count} angles, {angleDeg:F0}° = {bestCount} parts" + }); }); linearSw.Stop(); AngleResults.AddRange(angleBag); @@ -522,8 +517,8 @@ namespace OpenNest try { - var pairsSw = Stopwatch.StartNew(); - long lastPairsReport = 0; + var pairsCompleted = 0; + var pairsBestCount = 0; System.Threading.Tasks.Parallel.For(0, candidates.Count, new System.Threading.Tasks.ParallelOptions { CancellationToken = token }, @@ -538,17 +533,14 @@ namespace OpenNest if (filled != null && filled.Count > 0) resultBag.Add((FillScore.Compute(filled, workArea), filled)); - var now = pairsSw.ElapsedMilliseconds; - if (progress != null && now - Interlocked.Read(ref lastPairsReport) >= 150) + var done = Interlocked.Increment(ref pairsCompleted); + InterlockedMax(ref pairsBestCount, filled?.Count ?? 0); + progress?.Report(new NestProgress { - Interlocked.Exchange(ref lastPairsReport, now); - progress.Report(new NestProgress - { - Phase = NestPhase.Pairs, - PlateNumber = PlateNumber, - Description = $"Pairs: candidate {i + 1}/{candidates.Count} - {filled?.Count ?? 0} parts" - }); - } + Phase = NestPhase.Pairs, + PlateNumber = PlateNumber, + Description = $"Pairs: {done}/{candidates.Count} candidates, best = {pairsBestCount} parts" + }); }); } catch (OperationCanceledException) @@ -1103,5 +1095,15 @@ namespace OpenNest return result; } + private static void InterlockedMax(ref int location, int value) + { + int current; + do + { + current = location; + if (value <= current) return; + } while (Interlocked.CompareExchange(ref location, value, current) != current); + } + } }