package com.zy.asrs.utils; import com.zy.asrs.entity.BasDevpPosition; import com.zy.asrs.entity.WrkMast; import java.util.*; /** * 任务下发优先级工具: * 基于时间、距离、区域计算最终优先级,并返回排序后的任务分配建议。 */ public final class TaskDispatchPriorityUtil { private TaskDispatchPriorityUtil() { } public static List rankDispatchPlans(List taskPool, Map siteMap, List rgvSnapshots, Map regionPriorityMap, Date now, long distanceThreshold, long perimeter, double timeWeight, double distanceWeight, double regionWeight) { if (taskPool == null || taskPool.isEmpty() || siteMap == null || rgvSnapshots == null || rgvSnapshots.isEmpty()) { return Collections.emptyList(); } Date calcNow = now == null ? new Date() : now; long maxWaitMs = 0L; for (WrkMast task : taskPool) { Date createTime = getTaskCreateTime(task); if (task == null || createTime == null) { continue; } long waitMs = Math.max(0L, calcNow.getTime() - createTime.getTime()); if (waitMs > maxWaitMs) { maxWaitMs = waitMs; } } Set usedSource = new HashSet<>(); List plans = new ArrayList<>(); for (WrkMast task : taskPool) { if (task == null || task.getSourceStaNo() == null || task.getStaNo() == null) { continue; } if (usedSource.contains(task.getSourceStaNo())) { continue; } BasDevpPosition source = siteMap.get(task.getSourceStaNo()); if (source == null) { continue; } RgvChoice choice = chooseBestRgv(source.getPlcPosition(), rgvSnapshots, distanceThreshold, perimeter); if (choice == null) { continue; } double timePriorityByWindow = TimePriorityUtil.calculate(getTaskCreateTime(task), calcNow, maxWaitMs); double timePriorityByCurve = TimePriorityUtil.calculateDynamic(getTaskCreateTime(task), calcNow, 120D, 300D, 0.0083D); double timePriority = Math.max(timePriorityByWindow, timePriorityByCurve); double distancePriority = DistancePriorityUtil.calculate(choice.distance, distanceThreshold, perimeter); double regionPriority = resolveRegionPriority(source.getDevRegion(), regionPriorityMap); double finalPriority = PriorityWeightCalculatorUtil.calculate( timePriority, distancePriority, regionPriority, timeWeight, distanceWeight, regionWeight ); plans.add(new DispatchPlan(task, choice.rgvNo, choice.distance, DistancePriorityUtil.isInRange(choice.distance, distanceThreshold), timePriority, distancePriority, regionPriority, finalPriority)); usedSource.add(task.getSourceStaNo()); } plans.sort( Comparator.comparingDouble(DispatchPlan::getFinalPriority).reversed() .thenComparingDouble(DispatchPlan::getDistancePriority).reversed() .thenComparingDouble(DispatchPlan::getTimePriority).reversed() .thenComparingLong(DispatchPlan::getDistance) .thenComparingLong(p -> p.task.getWrkNo() == null ? Long.MAX_VALUE : p.task.getWrkNo()) ); return plans; } private static RgvChoice chooseBestRgv(long sourcePos, List rgvSnapshots, long distanceThreshold, long perimeter) { RgvChoice best = null; for (RgvSnapshot snapshot : rgvSnapshots) { if (snapshot == null || snapshot.rgvNo == null || snapshot.position == null) { continue; } long distance = ringDistance(sourcePos, snapshot.position, perimeter); double distancePriority = DistancePriorityUtil.calculate(distance, distanceThreshold, perimeter); if (best == null || distancePriority > best.distancePriority || (distancePriority == best.distancePriority && distance < best.distance)) { best = new RgvChoice(snapshot.rgvNo, distance, distancePriority); } } return best; } private static long ringDistance(long sourcePos, long rgvPos, long perimeter) { return SortTheExecutionOfTheCarUtil.LatelyAndLessThan(sourcePos, rgvPos, Math.max(1L, perimeter)).longValue(); } private static Date getTaskCreateTime(WrkMast task) { if (task == null) { return null; } if (task.getAppeTime() != null) { return task.getAppeTime(); } return task.getModiTime(); } private static double resolveRegionPriority(Integer region, Map regionPriorityMap) { if (region == null || regionPriorityMap == null || regionPriorityMap.isEmpty()) { return 0D; } Double score = regionPriorityMap.get(region); if (score == null) { return 0D; } if (score > 1D) { return 1D; } if (score < -1D) { return -1D; } return score; } public static class RgvSnapshot { private final Integer rgvNo; private final Long position; public RgvSnapshot(Integer rgvNo, Long position) { this.rgvNo = rgvNo; this.position = position; } } public static class DispatchPlan { private final WrkMast task; private final Integer rgvNo; private final long distance; private final boolean inRange; private final double timePriority; private final double distancePriority; private final double regionPriority; private final double finalPriority; public DispatchPlan(WrkMast task, Integer rgvNo, long distance, boolean inRange, double timePriority, double distancePriority, double regionPriority, double finalPriority) { this.task = task; this.rgvNo = rgvNo; this.distance = distance; this.inRange = inRange; this.timePriority = timePriority; this.distancePriority = distancePriority; this.regionPriority = regionPriority; this.finalPriority = finalPriority; } public WrkMast getTask() { return task; } public Integer getRgvNo() { return rgvNo; } public long getDistance() { return distance; } public boolean isInRange() { return inRange; } public double getTimePriority() { return timePriority; } public double getDistancePriority() { return distancePriority; } public double getRegionPriority() { return regionPriority; } public double getFinalPriority() { return finalPriority; } } private static class RgvChoice { private final Integer rgvNo; private final long distance; private final double distancePriority; private RgvChoice(Integer rgvNo, long distance, double distancePriority) { this.rgvNo = rgvNo; this.distance = distance; this.distancePriority = distancePriority; } } }