using System; using System.Collections.Generic; using System.Linq; using OpenNest.Engine.Jobs; namespace OpenNest.Engine.Tests.NestingEngines; /// Checks an engine's whole-job plan reports (). internal static class PlanAssert { /// /// Solves with and without a progress sink and asserts that plans are reported as proposals /// with no committed counts, before any commit; that the last plan is the returned layout; /// and that reporting does not change the layout. Returns the reported plans in order. /// public static IReadOnlyList ReportedAndEndWithTheResult(Func engine, NestJob job) { var reports = new List(); var result = engine().Solve(job, new Capture(reports.Add)); var silent = engine().Solve(job); var plans = reports.Where(r => r.Stage == NestJobStage.PlanImproved).ToList(); Assert.NotEmpty(plans); Assert.All(plans, p => Assert.Equal((0, 0), (p.CommittedPlates, p.CommittedParts))); Assert.All(plans, p => Assert.NotNull(p.Plan)); var firstCommit = reports.FindIndex(r => r.Stage == NestJobStage.PlateCommitted); if (firstCommit >= 0) Assert.True(reports.FindLastIndex(r => r.Stage == NestJobStage.PlanImproved) < firstCommit); Assert.Equal(Layout(result), Layout(plans[^1].Plan)); Assert.Equal(Layout(silent), Layout(result)); return plans.Select(p => p.Plan).ToList(); } public static IEnumerable<(int Plate, string StockId, NestJobPlacement Pose)> Layout(NestJobResult result) => result.Plates.SelectMany(p => p.Placements.Select(pose => (p.PlateIndex, p.StockId, pose))); private sealed class Capture(Action report) : IProgress { public void Report(NestJobProgress value) => report(value); } }