zhang
2025-05-20 1313906bb1eb983d3beece810035e7fc28d6a92f
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
package com.zy.acs.manager.manager.utils;
 
import com.zy.acs.manager.manager.entity.Action;
import com.zy.acs.manager.manager.enums.ActionTypeType;
import org.springframework.stereotype.Service;
 
import java.util.ArrayList;
import java.util.List;
 
@Service
public class ActionSorter {
 
    /**
     * 对传入的 actionList 进行排序或重新排列
     * 规则:
     * 1. 寻找第一个 ReadyTakeFromAgvSite 的动作(取货动作)。
     * 2. 如果找到,则寻找最后一个 TurnCorner 的动作。
     *    - 若找到 TurnCorner,则在其后插入取货动作(并将取货动作的 code 替换为 TurnCorner 动作的 code)。
     *    - 若没找到 TurnCorner,则将取货动作放在列表最前面(同时替换为第一个动作的 code)。
     * 3. 如果没有 ReadyTakeFromAgvSite,则直接返回原列表。
     *
     * @param actionList 原始动作列表
     * @return 排序后的动作列表
     */
    public List<Action> optimizeSort(List<Action> actionList) {
        if (actionList == null || actionList.isEmpty()) {
            return actionList;
        }
 
        // 获取关键信息
        final long readyTakeFromAgvSite  = ActionTypeType.ReadyTakeFromAgvSite.val();
        final long readyReleaseToAgvSite = ActionTypeType.ReadyReleaseToAgvSite.val();
        final long turnCorner            = ActionTypeType.TurnCorner.val();
 
        // 找到第一个 readyTakeFromAgvSite 动作的下标
        int takeFromIdx = findFirstActionIndex(actionList, readyTakeFromAgvSite);
        if (takeFromIdx == -1) {
            // 如果没有取货动作,直接返回原列表
            return actionList;
        }
 
        // 找到最后一个 readyReleaseToAgvSite 动作的下标
        int releaseToAgvSiteIdx = findLastActionIndex(actionList, readyReleaseToAgvSite);
        // 如果同时存在 readyTakeFromAgvSite 和 readyReleaseToAgvSite,说明 取货 - 放货 肯定是在一个地面码上,这时候没必要再调整位置
        if (releaseToAgvSiteIdx != -1) {
            return actionList;
        }
 
        // 找到最后一个 turnCorner 动作的下标
        int turnCornerIdx = findLastActionIndex(actionList, turnCorner);
 
        // 根据是否找到 turnCorner 来选择不同的重新排序逻辑
        if (turnCornerIdx == -1) {
            return reorderWithoutTurnCorner(actionList, takeFromIdx);
        } else {
            return reorderWithTurnCorner(actionList, takeFromIdx, turnCornerIdx);
        }
    }
 
    /**
     * 如果没有找到 TurnCorner,则将取货动作放到列表最前面(并使用原来第一个动作的 code)
     */
    private List<Action> reorderWithoutTurnCorner(List<Action> actionList, int takeFromIdx) {
        List<Action> sortedList = new ArrayList<>(actionList.size());
        Action takeFromAction = actionList.get(takeFromIdx);
 
        for (int i = 0; i < actionList.size(); i++) {
            // 在处理第一个元素之前,先把取货动作加进去
            if (i == 0) {
                // 用第一个动作的 code 替换取货动作
                takeFromAction.setCode(actionList.get(0).getCode());
                sortedList.add(takeFromAction);
            }
            // 跳过取货动作本身
            if (i == takeFromIdx) {
                continue;
            }
            // 加入原动作
            sortedList.add(actionList.get(i));
        }
        return sortedList;
    }
 
    /**
     * 如果找到 TurnCorner,则在 turnCorner 动作后插入取货动作(并使用 turnCorner 的 code)
     */
    private List<Action> reorderWithTurnCorner(List<Action> actionList, int takeFromIdx, int turnCornerIdx) {
        // 拷贝一份,准备重排
        List<Action> sortedList = new ArrayList<>(actionList.size());
        Action takeFromAction = actionList.get(takeFromIdx);
 
        for (int i = 0; i < actionList.size(); i++) {
            // 跳过原先的取货动作
            if (i == takeFromIdx) {
                continue;
            }
            // 先将当前动作加到列表
            Action curr = actionList.get(i);
            sortedList.add(curr);
 
            // 若当前动作是 turnCorner 动作,则替换取货动作 code 并插入
            if (i == turnCornerIdx) {
                takeFromAction.setCode(curr.getCode());
                sortedList.add(takeFromAction);
            }
        }
        return sortedList;
    }
 
    /**
     * 在 actionList 中找到第一个指定 actionType 的下标
     */
    private int findFirstActionIndex(List<Action> actionList, long actionType) {
        for (int i = 0; i < actionList.size(); i++) {
            if (actionList.get(i).getActionType().equals(actionType)) {
                return i;
            }
        }
        return -1;
    }
 
    /**
     * 在 actionList 中找到最后一个指定 actionType 的下标
     */
    private int findLastActionIndex(List<Action> actionList, long actionType) {
        int index = -1;
        for (int i = 0; i < actionList.size(); i++) {
            if (actionList.get(i).getActionType().equals(actionType)) {
                index = i;
            }
        }
        return index;
    }
 
}