using System;
using System.Threading;
using OpenNest.Engine.Jobs.Cutouts;
namespace OpenNest.Engine.Jobs.Remote;
///
/// Passes every solve to another engine and records what it was asked and what it returned
/// in . A solve that throws records nothing. The nest server's worker
/// wraps the selected engine in one, so the client can replay the run ().
///
public sealed class RecordingNestingEngine : INestingEngine
{
private readonly INestingEngine inner;
public RecordingNestingEngine(INestingEngine inner)
{
this.inner = inner ?? throw new ArgumentNullException(nameof(inner));
}
public NestSolveTranscript Transcript { get; } = new();
///
/// Also receives each solve's own progress, before the pipeline turns plans into sheets:
/// the worker's live reports. A bundled cutout trial's commits count proxies, so it passes
/// only candidates and plans, as the pipeline's own progress does.
///
public IProgress Progress { get; init; }
public NestJobResult Solve(NestJob job, IProgress progress = null, CancellationToken token = default)
{
if (Progress != null)
{
var tap = CutoutPipelinePrepass.HasProxies(job) ? new NestPipeline.PreviewProgress(Progress) : Progress;
progress = progress == null ? tap : new BothProgress(progress, tap);
}
var result = inner.Solve(job, progress, token);
if (result != null)
{
lock (Transcript)
Transcript.Add(job, result);
}
return result;
}
private sealed class BothProgress(IProgress first, IProgress second)
: IProgress
{
public void Report(NestJobProgress value)
{
first.Report(value);
second.Report(value);
}
}
}