using Newtonsoft.Json;
using System.Diagnostics.CodeAnalysis;
using WIDESEA_Core;
using WIDESEAWCS_Common.HttpEnum;
using WIDESEAWCS_Common.TaskEnum;
using WIDESEAWCS_Core;
using WIDESEAWCS_ITaskInfoService;
using WIDESEAWCS_Model.Models;
using WIDESEAWCS_QuartzJob;
using WIDESEAWCS_QuartzJob.Models;
using WIDESEAWCS_QuartzJob.Service;
namespace WIDESEAWCS_Tasks
{
///
/// 堆垛机任务选择器:封装任务挑选与站台可用性判断。
///
public class StackerCraneTaskSelector
{
private readonly ITaskService _taskService;
private readonly IRouterService _routerService;
private readonly Func _transferCheck;
public StackerCraneTaskSelector(ITaskService taskService, IRouterService routerService, HttpClientHelper httpClientHelper)
: this(taskService, routerService, taskNum => QueryTransferTask(httpClientHelper, taskNum))
{
}
public StackerCraneTaskSelector(ITaskService taskService, IRouterService routerService, Func transferCheck)
{
_taskService = taskService;
_routerService = routerService;
_transferCheck = transferCheck;
}
public Dt_Task? SelectTask(IStackerCrane commonStackerCrane)
{
Dt_Task? candidateTask;
if (commonStackerCrane.LastTaskType == null)
{
candidateTask = _taskService.QueryStackerCraneTask(commonStackerCrane.DeviceCode);
}
else if (commonStackerCrane.LastTaskType.GetValueOrDefault().GetTaskTypeGroup() == TaskTypeGroup.OutbondGroup)
{
candidateTask = _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode);
candidateTask ??= _taskService.QueryStackerCraneOutTask(commonStackerCrane.DeviceCode);
}
else
{
candidateTask = _taskService.QueryStackerCraneOutTask(commonStackerCrane.DeviceCode);
}
if (candidateTask == null)
{
return null;
}
if (candidateTask.TaskType.GetTaskTypeGroup() != TaskTypeGroup.OutbondGroup)
{
return candidateTask;
}
Dt_Task? selectedTask = TrySelectOutboundTask(candidateTask);
if (selectedTask != null)
{
return selectedTask;
}
var otherOutStationCodes = _routerService
.QueryNextRoutes(commonStackerCrane.DeviceCode, candidateTask.NextAddress, candidateTask.TaskType)
.Select(x => x.ChildPosi)
.ToList();
var tasks = _taskService.QueryStackerCraneOutTasks(commonStackerCrane.DeviceCode, otherOutStationCodes);
foreach (var alternativeTask in tasks)
{
selectedTask = TrySelectOutboundTask(alternativeTask);
if (selectedTask != null)
{
return selectedTask;
}
}
return _taskService.QueryStackerCraneInTask(commonStackerCrane.DeviceCode);
}
private Dt_Task? TrySelectOutboundTask(Dt_Task outboundTask)
{
// 只要是出库任务,必须先调用WMS判断是否需要移库。
var taskAfterTransferCheck = _transferCheck(outboundTask.TaskNum) ?? outboundTask;
var taskGroup = taskAfterTransferCheck.TaskType.GetTaskTypeGroup();
if (taskGroup == TaskTypeGroup.RelocationGroup || taskGroup == TaskTypeGroup.OutbondGroup)
{
TryAddTaskFromWms(taskAfterTransferCheck);
}
if (taskGroup == TaskTypeGroup.RelocationGroup)
{
return taskAfterTransferCheck;
}
if (taskGroup != TaskTypeGroup.OutbondGroup)
{
return taskAfterTransferCheck;
}
return IsOutTaskStationAvailable(taskAfterTransferCheck) ? taskAfterTransferCheck : null;
}
private static Dt_Task? QueryTransferTask(HttpClientHelper httpClientHelper, int taskNum)
{
var response = httpClientHelper.Post(
nameof(ConfigKey.TransferCheck),
taskNum.ToString());
if (response == null || !response.IsSuccess || response.Data == null || !response.Data.Status || response.Data.Data == null)
{
return null;
}
var taskJson = response.Data.Data.ToString();
return string.IsNullOrWhiteSpace(taskJson) ? null : JsonConvert.DeserializeObject(taskJson);
}
private void TryAddTaskFromWms(Dt_Task task)
{
if (task.TaskNum <= 0)
{
return;
}
var existingTask = _taskService.QueryByTaskNum(task.TaskNum);
if (existingTask != null)
{
return;
}
_taskService.AddData(task);
}
private bool IsOutTaskStationAvailable([NotNull] Dt_Task task)
{
Dt_Router? router = _routerService.QueryNextRoute(task.Roadway, task.NextAddress, task.TaskType);
if (router == null)
{
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到站台【{task.NextAddress}】信息,无法校验站台");
return false;
}
IDevice? device = Storage.Devices.FirstOrDefault(x => x.DeviceCode == router.ChildPosiDeviceCode);
if (device == null)
{
_taskService.UpdateTaskExceptionMessage(task.TaskNum, $"未找到出库站台【{router.ChildPosiDeviceCode}】对应的通讯对象,无法判断出库站台是否被占用");
return false;
}
CommonConveyorLine conveyorLine = (CommonConveyorLine)device;
return conveyorLine.IsOccupied(router.ChildPosi);
}
}
}