refactor(engine): route console and MCP nesting through named job engines
Console --engine now names a jobs engine for --autonest (solved once through NestingEngineRegistry.Create and committed onto the plate) or a built-in fill strategy for single-plate fill through the public PlateFillService; unknown names exit with the valid choices instead of consulting the process-global legacy registry. MCP nesting tools take an explicit engine argument per call with the session default, never read process-global active-engine state, and reject whole-job engine names on single-plate fill tools. NestingEngineRegistry gains an explicit Create (name) resolution; PlateFillService gains a public ResolveStrategy and a plate-number Nest overload used by interactive callers.
This commit is contained in:
@@ -53,6 +53,22 @@ public static class NestingEngineRegistry
|
||||
|
||||
public static IReadOnlyList<NestingEngineInfo> AvailableEngines => engines;
|
||||
|
||||
/// <summary>
|
||||
/// Creates the engine registered under <paramref name="name"/> (case-insensitive). The caller's
|
||||
/// explicit choice is the whole selection mechanism: unlike the legacy registry there is no
|
||||
/// process-global active name to consult or mutate. Unknown names throw.
|
||||
/// </summary>
|
||||
public static INestingEngine Create(string name)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(name);
|
||||
var info = engines.FirstOrDefault(e => e.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
|
||||
if (info == null)
|
||||
throw new NotSupportedException(
|
||||
$"Unknown nesting engine: {name}. Available: {string.Join(", ", engines.Select(e => e.Name))}."
|
||||
);
|
||||
return info.Factory();
|
||||
}
|
||||
|
||||
public static void Register(string name, string description, Func<INestingEngine> factory)
|
||||
{
|
||||
if (engines.Any(e => e.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))
|
||||
|
||||
@@ -66,9 +66,28 @@ public static class PlateFillService
|
||||
List<NestItem> items,
|
||||
IProgress<NestProgress> progress,
|
||||
CancellationToken token
|
||||
) => Nest(strategy, plate, items, 0, progress, token);
|
||||
|
||||
/// <summary>
|
||||
/// Whole-plate fill with the strategy's orchestration (fill-vs-pack, compaction). Returns
|
||||
/// proposed parts only; committing them to <paramref name="plate"/> stays with the caller.
|
||||
/// </summary>
|
||||
/// <param name="plateNumber">Plate index reported with progress, as the legacy engine's
|
||||
/// <c>PlateNumber</c> was by interactive multi-plate loops.</param>
|
||||
public static List<Part> Nest(
|
||||
string strategy,
|
||||
Plate plate,
|
||||
List<NestItem> items,
|
||||
int plateNumber,
|
||||
IProgress<NestProgress> progress,
|
||||
CancellationToken token
|
||||
)
|
||||
{
|
||||
return RequireFiller(strategy, plate).Nest(items, progress, token);
|
||||
ArgumentNullException.ThrowIfNull(strategy);
|
||||
ResolveStrategy(strategy, allowEmpty: false);
|
||||
var filler = CreateFiller(strategy, plate);
|
||||
filler.PlateNumber = plateNumber;
|
||||
return filler.Nest(items, progress, token);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -77,7 +96,11 @@ public static class PlateFillService
|
||||
/// ActiveEngineName so tolerant interactive callers keep working. Returns the canonical name;
|
||||
/// unknown names throw <see cref="NotSupportedException"/>.
|
||||
/// </summary>
|
||||
internal static string ResolveStrategy(string strategy, bool allowEmpty = true)
|
||||
public static string ResolveStrategy(string strategy) => ResolveStrategy(strategy, true);
|
||||
|
||||
/// <inheritdoc cref="ResolveStrategy(string)"/>
|
||||
/// <param name="allowEmpty">False rejects null/empty instead of defaulting (explicit service calls).</param>
|
||||
internal static string ResolveStrategy(string strategy, bool allowEmpty)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(strategy))
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user