fix(diagnostics): tolerate missing cut-offs and zones in overlap freshness

The desktop captures the overlap freshness stamp before its error
boundary, and a null cut-off or clamp zone in the plate's lists threw
NullReferenceException there. Stamp missing entries as a distinct empty
state so the whole-plate capture can report the malformed input as a
failed check instead.

Project Memory: opennest cdbe2629-b562-46ee-9509-2b120a511654
This commit is contained in:
aj committed 2026-10-13 18:15:49 -04:00
1 parent c18db3f896
commit 3e9e336072
2 files changed
+37 -13

No files matched your search

@@ -24,20 +24,23 @@ public sealed class OverlapGeometryStamp
entries[i] = new Entry(plate.Parts[i]);
zones = new (string, long, long, long, long)[plate.ClampZones.Count];
for (var i = 0; i < zones.Length; i++)
{
var zone = plate.ClampZones[i];
var box = zone.Bounds;
zones[i] = (zone.Id, Bits(box.X), Bits(box.Y), Bits(box.Length), Bits(box.Width));
}
zones[i] = ZoneState(plate.ClampZones[i]);
cutoffs = new (CutOff, CutOffAxis, long, long, long?, long?)[plate.CutOffs.Count];
for (var i = 0; i < cutoffs.Length; i++)
cutoffs[i] = CutOffState(plate.CutOffs[i]);
}
// Missing entries are malformed input the analysis itself reports; freshness must not
// throw first (the desktop captures it before its error boundary).
private static (string, long, long, long, long) ZoneState(ClampZone zone) =>
zone?.Bounds is not { } box ? default
: (zone.Id, Bits(box.X), Bits(box.Y), Bits(box.Length), Bits(box.Width));
private static (CutOff, CutOffAxis, long, long, long?, long?) CutOffState(CutOff cut) =>
(cut, cut.Axis, Bits(cut.Position.X), Bits(cut.Position.Y),
cut.StartLimit.HasValue ? Bits(cut.StartLimit.Value) : null,
cut.EndLimit.HasValue ? Bits(cut.EndLimit.Value) : null);
cut == null ? default
: (cut, cut.Axis, Bits(cut.Position.X), Bits(cut.Position.Y),
cut.StartLimit.HasValue ? Bits(cut.StartLimit.Value) : null,
cut.EndLimit.HasValue ? Bits(cut.EndLimit.Value) : null);
private static long Bits(double value) => BitConverter.DoubleToInt64Bits(value);
@@ -54,12 +57,8 @@ public sealed class OverlapGeometryStamp
|| sheet != SheetState(current))
return false;
for (var i = 0; i < zones.Length; i++)
{
var zone = current.ClampZones[i];
var box = zone.Bounds;
if (zones[i] != (zone.Id, Bits(box.X), Bits(box.Y), Bits(box.Length), Bits(box.Width)))
if (zones[i] != ZoneState(current.ClampZones[i]))
return false;
}
return true;
}
@@ -273,6 +273,31 @@ public class ClampZonePlacementFrameTests
Assert.Throws<ArgumentException>(() => PlateOverlapAnalyzer.CapturePlate(plate));
}
[Fact]
public void FreshnessCaptureToleratesMissingCutOffsAndZones()
{
var plate = new Plate(24, 48);
plate.CutOffs.Add(null!);
plate.ClampZones.Add(null!);
var stamp = OverlapGeometryStamp.Capture(plate);
var state = new OverlapReportState();
state.Begin(plate);
Assert.True(stamp.Matches(plate));
// The whole-plate capture refuses the malformed input inside the desktop's error boundary.
Assert.Throws<ArgumentException>(() => PlateOverlapAnalyzer.CapturePlate(plate));
plate.CutOffs.Clear();
plate.CutOffs.Add(new CutOff(new Vector(5, 0), CutOffAxis.Vertical));
Assert.False(stamp.Matches(plate));
plate.CutOffs.Clear();
plate.CutOffs.Add(null!);
Assert.True(stamp.Matches(plate));
plate.ClampZones.Clear();
plate.ClampZones.Add(new ClampZone("front", new Box(10, 0, 1.5, 0.625)));
Assert.False(stamp.Matches(plate));
}
[Fact]
public void QuadrantChangeMovesExplicitZonesAndStalesDisplayedClampFindings()
{