196 lines
8.4 KiB
C#
196 lines
8.4 KiB
C#
|
|
using MaxwellFramework.Core.Attributes;
|
||
|
|
using MainShell.Common;
|
||
|
|
using MainShell.ProcessResult;
|
||
|
|
using MW.WorkFlow;
|
||
|
|
using System;
|
||
|
|
using System.Threading.Tasks;
|
||
|
|
|
||
|
|
namespace MainShell.Process
|
||
|
|
{
|
||
|
|
[Singleton]
|
||
|
|
public class DieTransferMotionService
|
||
|
|
{
|
||
|
|
private readonly AutoProductionRuntimeStateService _autoProductionRuntimeStateService;
|
||
|
|
private readonly IDieTransferPathGenerator _dieTransferPathGenerator;
|
||
|
|
|
||
|
|
public DieTransferMotionService(AutoProductionRuntimeStateService autoProductionRuntimeStateService, IDieTransferPathGenerator dieTransferPathGenerator)
|
||
|
|
{
|
||
|
|
_autoProductionRuntimeStateService = autoProductionRuntimeStateService ?? throw new ArgumentNullException(nameof(autoProductionRuntimeStateService));
|
||
|
|
_dieTransferPathGenerator = dieTransferPathGenerator ?? throw new ArgumentNullException(nameof(dieTransferPathGenerator));
|
||
|
|
}
|
||
|
|
|
||
|
|
public async Task ExecuteAsync(WorkflowContext context, ActivityControl activityControl)
|
||
|
|
{
|
||
|
|
if (context == null)
|
||
|
|
{
|
||
|
|
throw new ArgumentNullException(nameof(context));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (activityControl == null)
|
||
|
|
{
|
||
|
|
throw new ArgumentNullException(nameof(activityControl));
|
||
|
|
}
|
||
|
|
|
||
|
|
TryGeneratePathPlan(context);
|
||
|
|
|
||
|
|
for (var i = 0; i < 20; i++)
|
||
|
|
{
|
||
|
|
activityControl.ThrowIfCancellationRequested();
|
||
|
|
await activityControl.CheckPauseAsync().ConfigureAwait(false);
|
||
|
|
await Task.Delay(100, activityControl.CancellationToken).ConfigureAwait(false);
|
||
|
|
}
|
||
|
|
|
||
|
|
DieTransferDecisionResult decisionResult = ResolveDecisionResult(context);
|
||
|
|
context.SetData(WorkflowContextKeys.DieTransferDecisionResult, decisionResult);
|
||
|
|
context.SetRoute(WorkflowContextKeys.AutoProductionRoute, decisionResult.SuggestedRoute);
|
||
|
|
|
||
|
|
bool hasCurrentChipStateService = context.TryGetData<CurrentChipStateService>(WorkflowContextKeys.CurrentChipStateService, out CurrentChipStateService currentChipStateService) && currentChipStateService != null;
|
||
|
|
|
||
|
|
if (decisionResult.SuggestedRoute == AutoProductionRoute.ChipExhausted ||
|
||
|
|
decisionResult.SuggestedRoute == AutoProductionRoute.BothExhausted)
|
||
|
|
{
|
||
|
|
context.SetData(WorkflowContextKeys.PendingChipLoad, true);
|
||
|
|
context.SetData(WorkflowContextKeys.CurrentChipState, CurrentChipLifecycleState.PendingUnload);
|
||
|
|
if (hasCurrentChipStateService)
|
||
|
|
{
|
||
|
|
currentChipStateService.SetState(CurrentChipLifecycleState.PendingUnload);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
context.SetData(WorkflowContextKeys.PendingChipLoad, false);
|
||
|
|
context.SetData(WorkflowContextKeys.CurrentChipState, CurrentChipLifecycleState.InUse);
|
||
|
|
if (hasCurrentChipStateService)
|
||
|
|
{
|
||
|
|
currentChipStateService.SetState(CurrentChipLifecycleState.InUse);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
if (decisionResult.IsSubstrateComplete)
|
||
|
|
{
|
||
|
|
context.SetData(WorkflowContextKeys.SubstrateProcessState, SubstrateLifecycleState.Complete);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
context.SetData(WorkflowContextKeys.SubstrateProcessState, SubstrateLifecycleState.InProcess);
|
||
|
|
}
|
||
|
|
|
||
|
|
SyncRuntimeStateToContext(context);
|
||
|
|
}
|
||
|
|
|
||
|
|
public DieTransferPathPlan GeneratePathPlan(DieTransferPathRequest request)
|
||
|
|
{
|
||
|
|
return _dieTransferPathGenerator.Generate(request);
|
||
|
|
}
|
||
|
|
|
||
|
|
private DieTransferDecisionResult ResolveDecisionResult(WorkflowContext context)
|
||
|
|
{
|
||
|
|
bool needsRecheck = ConsumeBooleanFlag(context, WorkflowContextKeys.TransferNeedsRecheck) || _autoProductionRuntimeStateService.ConsumeTransferNeedsRecheck();
|
||
|
|
bool explicitChipExhausted = ConsumeBooleanFlag(context, WorkflowContextKeys.TransferChipExhausted) || _autoProductionRuntimeStateService.ConsumeTransferChipExhausted();
|
||
|
|
|
||
|
|
if (needsRecheck)
|
||
|
|
{
|
||
|
|
return CreateDecisionFromRoute(AutoProductionRoute.Recheck);
|
||
|
|
}
|
||
|
|
|
||
|
|
AutoProductionRoute autoRoute;
|
||
|
|
if (context.TryGetRoute<AutoProductionRoute>(WorkflowContextKeys.AutoProductionRoute, out autoRoute))
|
||
|
|
{
|
||
|
|
if (autoRoute == AutoProductionRoute.Recheck)
|
||
|
|
{
|
||
|
|
return CreateDecisionFromRoute(autoRoute);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
DieTransferRoute legacyRoute;
|
||
|
|
if (context.TryGetRoute<DieTransferRoute>(WorkflowContextKeys.DieTransferRoute, out legacyRoute) &&
|
||
|
|
legacyRoute == DieTransferRoute.Recheck)
|
||
|
|
{
|
||
|
|
return CreateDecisionFromRoute(AutoProductionRoute.Recheck);
|
||
|
|
}
|
||
|
|
|
||
|
|
bool isSubstrateComplete = UpdateSubstrateProgress(context);
|
||
|
|
bool isChipExhausted = explicitChipExhausted || UpdateCurrentChipBudget(context);
|
||
|
|
|
||
|
|
if (isSubstrateComplete && isChipExhausted)
|
||
|
|
{
|
||
|
|
return CreateDecisionFromRoute(AutoProductionRoute.BothExhausted);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isSubstrateComplete)
|
||
|
|
{
|
||
|
|
return CreateDecisionFromRoute(AutoProductionRoute.SubstrateComplete);
|
||
|
|
}
|
||
|
|
|
||
|
|
if (isChipExhausted)
|
||
|
|
{
|
||
|
|
return CreateDecisionFromRoute(AutoProductionRoute.ChipExhausted);
|
||
|
|
}
|
||
|
|
|
||
|
|
return CreateDecisionFromRoute(AutoProductionRoute.ContinueCurrentSubstrate);
|
||
|
|
}
|
||
|
|
|
||
|
|
private void TryGeneratePathPlan(WorkflowContext context)
|
||
|
|
{
|
||
|
|
DieTransferPathRequest pathRequest;
|
||
|
|
if (!context.TryGetData<DieTransferPathRequest>(WorkflowContextKeys.DieTransferPathRequest, out pathRequest) || pathRequest == null)
|
||
|
|
{
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
DieTransferPathPlan pathPlan = _dieTransferPathGenerator.Generate(pathRequest);
|
||
|
|
context.SetData(WorkflowContextKeys.DieTransferPathPlan, pathPlan);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool UpdateSubstrateProgress(WorkflowContext context)
|
||
|
|
{
|
||
|
|
if (_autoProductionRuntimeStateService.CurrentSubstratePendingCount <= 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return _autoProductionRuntimeStateService.ConsumeSubstrateTarget();
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool UpdateCurrentChipBudget(WorkflowContext context)
|
||
|
|
{
|
||
|
|
if (_autoProductionRuntimeStateService.CurrentChipRemainingCount <= 0)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
return _autoProductionRuntimeStateService.ConsumeCurrentChip();
|
||
|
|
}
|
||
|
|
|
||
|
|
private static bool ConsumeBooleanFlag(WorkflowContext context, string key)
|
||
|
|
{
|
||
|
|
bool flagValue;
|
||
|
|
if (!context.TryGetData<bool>(key, out flagValue) || !flagValue)
|
||
|
|
{
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
context.SetData(key, false);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
private void SyncRuntimeStateToContext(WorkflowContext context)
|
||
|
|
{
|
||
|
|
context.SetData(WorkflowContextKeys.CurrentSubstratePendingCount, _autoProductionRuntimeStateService.CurrentSubstratePendingCount);
|
||
|
|
context.SetData(WorkflowContextKeys.CurrentSubstrateProcessedCount, _autoProductionRuntimeStateService.CurrentSubstrateProcessedCount);
|
||
|
|
context.SetData(WorkflowContextKeys.CurrentChipRemainingCount, _autoProductionRuntimeStateService.CurrentChipRemainingCount);
|
||
|
|
context.SetData(WorkflowContextKeys.TransferNeedsRecheck, _autoProductionRuntimeStateService.TransferNeedsRecheck);
|
||
|
|
context.SetData(WorkflowContextKeys.TransferChipExhausted, _autoProductionRuntimeStateService.TransferChipExhausted);
|
||
|
|
}
|
||
|
|
|
||
|
|
private static DieTransferDecisionResult CreateDecisionFromRoute(AutoProductionRoute route)
|
||
|
|
{
|
||
|
|
DieTransferDecisionResult decisionResult = new DieTransferDecisionResult();
|
||
|
|
decisionResult.SuggestedRoute = route;
|
||
|
|
decisionResult.NeedsRecheck = route == AutoProductionRoute.Recheck;
|
||
|
|
decisionResult.IsChipExhausted = route == AutoProductionRoute.ChipExhausted || route == AutoProductionRoute.BothExhausted;
|
||
|
|
decisionResult.IsSubstrateComplete = route == AutoProductionRoute.SubstrateComplete || route == AutoProductionRoute.BothExhausted;
|
||
|
|
return decisionResult;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|