wanshenmean
2026-03-13 0dbc8273bdfbcabcc4b770546245f6b17d787de9
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
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
{
    /// <summary>
    /// 堆垛机任务选择器:封装任务挑选与站台可用性判断。
    /// </summary>
    public class StackerCraneTaskSelector
    {
        private readonly ITaskService _taskService;
        private readonly IRouterService _routerService;
        private readonly Func<int, Dt_Task?> _transferCheck;
 
        public StackerCraneTaskSelector(ITaskService taskService, IRouterService routerService, HttpClientHelper httpClientHelper)
            : this(taskService, routerService, taskNum => QueryTransferTask(httpClientHelper, taskNum))
        {
        }
 
        public StackerCraneTaskSelector(ITaskService taskService, IRouterService routerService, Func<int, Dt_Task?> 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<WebResponseContent>(
                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<Dt_Task>(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);
        }
    }
}