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