优先级排序

parent 9c65aa9d
...@@ -183,4 +183,9 @@ public class Order { ...@@ -183,4 +183,9 @@ public class Order {
private double changeoverCost; private double changeoverCost;
private int changeoverPriority; private int changeoverPriority;
/**
* 多级排序路径(用于精确字典序排序,避免浮点精度问题)
*/
private List<Integer> sortKey;
} }
\ No newline at end of file
...@@ -87,6 +87,11 @@ public class OrderSortService { ...@@ -87,6 +87,11 @@ public class OrderSortService {
return; return;
} }
log.debug("[OrderSort] assignPriority start: orderCount={}, enabled={}, conditionCount={}",
orders.size(),
rule.isEnabled(),
rule.getConditions() == null ? 0 : rule.getConditions().size());
List<Order> sortedOrders = assignPriorityValues(new ArrayList<>(orders), rule); List<Order> sortedOrders = assignPriorityValues(new ArrayList<>(orders), rule);
orders.clear(); orders.clear();
orders.addAll(sortedOrders); orders.addAll(sortedOrders);
...@@ -442,7 +447,7 @@ public class OrderSortService { ...@@ -442,7 +447,7 @@ public class OrderSortService {
private void processConditionsWithMinimizeChangeover(List<Order> orders, private void processConditionsWithMinimizeChangeover(List<Order> orders,
List<OrderSortRule.SortCondition> conditions, List<OrderSortRule.SortCondition> conditions,
int conditionIndex, int conditionIndex,
Map<Integer, List<Integer>> priorityPaths) { Map<String, List<Integer>> priorityPaths) {
// 递归终止:处理完所有条件后停止 // 递归终止:处理完所有条件后停止
if (conditionIndex >= conditions.size() || CollectionUtils.isEmpty(orders)) { if (conditionIndex >= conditions.size() || CollectionUtils.isEmpty(orders)) {
return; return;
...@@ -455,20 +460,48 @@ public class OrderSortService { ...@@ -455,20 +460,48 @@ public class OrderSortService {
// 应用最小化换线策略 // 应用最小化换线策略
List<Order> optimizedOrders = sortByMinimizeChangeover(orders); List<Order> optimizedOrders = sortByMinimizeChangeover(orders);
// ========== 换线明细日志 ==========
double totalCost = 0.0;
StringBuilder costLog = new StringBuilder();
costLog.append("[换线明细] 序列顺序:\n");
for (int i = 0; i < optimizedOrders.size(); i++) {
Order order = optimizedOrders.get(i);
double costToPrev = (i == 0) ? 0.0 : calculateChangeoverCost(optimizedOrders.get(i - 1), order);
StringBuilder flags = new StringBuilder();
if (i > 0) {
Order prev = optimizedOrders.get(i - 1);
if (!Objects.equals(prev.getRoutingId(), order.getRoutingId())) flags.append("routing变 ");
if (!Objects.equals(prev.getSerie(), order.getSerie())) flags.append("serie变 ");
if (!Objects.equals(prev.getMaterialCode(), order.getMaterialCode())) flags.append("material变");
}
costLog.append(String.format(" %2d. %s, routingId=%s, serie=%s, materialCode=%s, cost=%.0f %s\n",
(i + 1),
order.getOrderCode(),
order.getRoutingId(),
order.getSerie(),
order.getMaterialCode(),
costToPrev,
flags.toString()));
totalCost += costToPrev;
}
costLog.append(String.format("[换线明细] 总换线成本 = %.0f\n", totalCost));
log.debug(costLog.toString());
// ==================================
// 为最小化换线后的订单分配层级序号 // 为最小化换线后的订单分配层级序号
// 相同成本的订单分配相同的序号 // 相同成本的订单分配相同的序号
for (Order order : optimizedOrders) { for (Order order : optimizedOrders) {
priorityPaths.get(order.getId()).add(order.getChangeoverPriority()); priorityPaths.get(order.getOrderId()).add(order.getChangeoverPriority());
} }
// 按优先级分组顺序处理
Map<Integer, List<Order>> priorityGroups = new HashMap<>(); Map<Integer, List<Order>> priorityGroups = new HashMap<>();
for (Order order : optimizedOrders) { for (Order order : optimizedOrders) {
int priority = order.getChangeoverPriority(); int priority = order.getChangeoverPriority();
priorityGroups.computeIfAbsent(priority, k -> new ArrayList<>()).add(order); priorityGroups.computeIfAbsent(priority, k -> new ArrayList<>()).add(order);
} }
// 按优先级分组顺序处理
List<Integer> sortedPriorities = priorityGroups.keySet().stream() List<Integer> sortedPriorities = priorityGroups.keySet().stream()
.sorted() .sorted()
.collect(Collectors.toList()); .collect(Collectors.toList());
...@@ -509,7 +542,7 @@ public class OrderSortService { ...@@ -509,7 +542,7 @@ public class OrderSortService {
// 分配当前层级序号(1、2、3...) // 分配当前层级序号(1、2、3...)
int levelNumber = groupIndex + 1; int levelNumber = groupIndex + 1;
groupOrders.forEach(order -> priorityPaths.get(order.getId()).add(levelNumber)); groupOrders.forEach(order -> priorityPaths.get(order.getOrderId()).add(levelNumber));
// 递归处理下一级条件 // 递归处理下一级条件
processConditionsWithMinimizeChangeover(groupOrders, conditions, conditionIndex + 1, priorityPaths); processConditionsWithMinimizeChangeover(groupOrders, conditions, conditionIndex + 1, priorityPaths);
...@@ -529,19 +562,13 @@ public class OrderSortService { ...@@ -529,19 +562,13 @@ public class OrderSortService {
.collect(Collectors.toList()); .collect(Collectors.toList());
// 为每个订单初始化优先级路径 // 为每个订单初始化优先级路径
Map<Integer, List<Integer>> priorityPaths = new HashMap<>(); Map<String, List<Integer>> priorityPaths = new HashMap<>();
currentOrders.forEach(order -> priorityPaths.put(order.getId(), new ArrayList<>())); currentOrders.forEach(order -> priorityPaths.put(order.getOrderId(), new ArrayList<>()));
// 处理排序条件 // 处理排序条件
processConditionsWithMinimizeChangeover(currentOrders, conditions, 0, priorityPaths); processConditionsWithMinimizeChangeover(currentOrders, conditions, 0, priorityPaths);
// 将路径转换为最终格式 return applyPriorityFromPaths(currentOrders, priorityPaths);
convertPriorityPathsToNumeric(currentOrders, priorityPaths);
// 按优先级升序排序(数值越小越优先)
return currentOrders.stream()
.sorted(Comparator.comparingDouble(Order::getActualPriority))
.collect(Collectors.toList());
} }
/** /**
...@@ -596,6 +623,7 @@ public class OrderSortService { ...@@ -596,6 +623,7 @@ public class OrderSortService {
if (hasMinimizeChangeover) { if (hasMinimizeChangeover) {
// 仅使用最小化换线策略 // 仅使用最小化换线策略
return sortWithConfiguredStrategy(orders,rule); return sortWithConfiguredStrategy(orders,rule);
} else { } else {
...@@ -605,19 +633,28 @@ public class OrderSortService { ...@@ -605,19 +633,28 @@ public class OrderSortService {
.collect(Collectors.toList()); .collect(Collectors.toList());
// 为每个订单初始化优先级路径 // 为每个订单初始化优先级路径
Map<Integer, List<Integer>> priorityPaths = new HashMap<>(); Map<String, List<Integer>> priorityPaths = new HashMap<>();
orders.forEach(order -> priorityPaths.put(order.getId(), new ArrayList<>())); orders.forEach(order -> priorityPaths.put(order.getOrderId(), new ArrayList<>()));
// 递归分配层级化优先级(核心逻辑) // 递归分配层级化优先级(核心逻辑)
assignHierarchicalPriority(orders, sortedConditions, 0, priorityPaths); assignHierarchicalPriority(orders, sortedConditions, 0, priorityPaths);
// 将路径转换为最终格式 List<Order> orders1 = applyPriorityFromPaths(orders, priorityPaths);
convertPriorityPathsToNumeric(orders, priorityPaths);
// 按优先级升序排序(数值越小越优先) // ========== 订单优先级信息(debug)==========
return orders.stream() log.debug("[OrderSort] ========== 订单优先级信息 ==========");
.sorted(Comparator.comparingDouble(Order::getActualPriority)) for (Order order : orders1) {
.collect(Collectors.toList()); log.debug("[OrderSort] 订单编码:{}, 开始时间:{}, 结束时间:{}, 真实优先级:{}, sortKey:{}",
order.getOrderCode(),
order.getStartDate(),
order.getDueDate(),
order.getActualPriority(),
order.getSortKey());
}
log.debug("[OrderSort] ====================================");
// ==========================================
return orders1;
} }
} }
...@@ -627,7 +664,7 @@ public class OrderSortService { ...@@ -627,7 +664,7 @@ public class OrderSortService {
private void assignHierarchicalPriority(List<Order> orders, private void assignHierarchicalPriority(List<Order> orders,
List<OrderSortRule.SortCondition> conditions, List<OrderSortRule.SortCondition> conditions,
int conditionIndex, int conditionIndex,
Map<Integer, List<Integer>> priorityPaths) { Map<String, List<Integer>> priorityPaths) {
// 递归终止:处理完所有条件后停止,不再添加额外序号 // 递归终止:处理完所有条件后停止,不再添加额外序号
if (conditionIndex >= conditions.size() || CollectionUtils.isEmpty(orders)) { if (conditionIndex >= conditions.size() || CollectionUtils.isEmpty(orders)) {
return; return;
...@@ -660,7 +697,7 @@ public class OrderSortService { ...@@ -660,7 +697,7 @@ public class OrderSortService {
// 分配当前层级序号(1、2、3...) // 分配当前层级序号(1、2、3...)
int levelNumber = groupIndex + 1; int levelNumber = groupIndex + 1;
groupOrders.forEach(order -> priorityPaths.get(order.getId()).add(levelNumber)); groupOrders.forEach(order -> priorityPaths.get(order.getOrderId()).add(levelNumber));
// 递归处理下一级条件 // 递归处理下一级条件
assignHierarchicalPriority(groupOrders, conditions, conditionIndex + 1, priorityPaths); assignHierarchicalPriority(groupOrders, conditions, conditionIndex + 1, priorityPaths);
...@@ -668,13 +705,17 @@ public class OrderSortService { ...@@ -668,13 +705,17 @@ public class OrderSortService {
} }
/** /**
* 路径转数值:严格匹配条件数格式 * 路径转数值:拼接式小数编码
* 3个条件 → [1,1,1] → 1.11 * [1, 1, 1] → 1.11
* 4个条件 → [1,1,1,1] → 1.111 * [1, 1, 20] → 1.120
* [1, 20, 20] → 1.2020
*
* 注意:此编码假设每层分组数不超过9(或不会连续出现导致歧义的组合)
* 如 [1,12,3] 和 [1,1,23] 都会变成 1.123,会冲突!
*/ */
private void convertPriorityPathsToNumeric(List<Order> orders, Map<Integer, List<Integer>> priorityPaths) { private void convertPriorityPathsToNumeric(List<Order> orders, Map<String, List<Integer>> priorityPaths) {
for (Order order : orders) { for (Order order : orders) {
List<Integer> path = priorityPaths.get(order.getId()); List<Integer> path = priorityPaths.get(order.getOrderId());
if (CollectionUtils.isEmpty(path)) { if (CollectionUtils.isEmpty(path)) {
order.setActualPriority(0.0); order.setActualPriority(0.0);
continue; continue;
...@@ -685,7 +726,7 @@ public class OrderSortService { ...@@ -685,7 +726,7 @@ public class OrderSortService {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(path.get(0)); sb.append(path.get(0));
// 后续部分作为小数(严格按照路径长度) // 后续部分直接拼接,不补零
if (path.size() > 1) { if (path.size() > 1) {
sb.append("."); sb.append(".");
for (int i = 1; i < path.size(); i++) { for (int i = 1; i < path.size(); i++) {
...@@ -703,6 +744,42 @@ public class OrderSortService { ...@@ -703,6 +744,42 @@ public class OrderSortService {
} }
} }
/**
* 将 priorityPaths 应用到订单:写入 sortKey,字典序排序,赋整数 actualPriority
*/
private List<Order> applyPriorityFromPaths(List<Order> orders, Map<String, List<Integer>> priorityPaths) {
// Step1: 写入 sortKey
orders.forEach(order -> order.setSortKey(priorityPaths.get(order.getOrderId())));
// Step2: 按 sortKey 字典序排序
orders.sort((o1, o2) -> {
List<Integer> p1 = o1.getSortKey();
List<Integer> p2 = o2.getSortKey();
if (p1 == null && p2 == null) return 0;
if (p1 == null) return 1;
if (p2 == null) return -1;
for (int i = 0; i < Math.min(p1.size(), p2.size()); i++) {
int cmp = Integer.compare(p1.get(i), p2.get(i));
if (cmp != 0) return cmp;
}
return Integer.compare(p1.size(), p2.size());
});
// Step3: 赋整数排名,相同 sortKey 赋相同值
int rank = 1;
for (int i = 0; i < orders.size(); i++) {
if (i > 0) {
List<Integer> prevKey = orders.get(i - 1).getSortKey();
List<Integer> currKey = orders.get(i).getSortKey();
boolean same = (prevKey == null && currKey == null)
|| (prevKey != null && currKey != null && prevKey.equals(currKey));
if (!same) {
rank++;
}
}
orders.get(i).setActualPriority(rank);
}
return orders;
}
/** /**
* 创建单个条件的比较器 * 创建单个条件的比较器
*/ */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment