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 optimizeSort(List 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 reorderWithoutTurnCorner(List actionList, int takeFromIdx) { List 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 reorderWithTurnCorner(List actionList, int takeFromIdx, int turnCornerIdx) { // 拷贝一份,准备重排 List 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 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 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; } }