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); } } }