Commit 993afbe6 authored by Tong Li's avatar Tong Li

优化速度

parent 4e4ca06f
...@@ -182,12 +182,8 @@ public class MachineCalculator { ...@@ -182,12 +182,8 @@ public class MachineCalculator {
List<ScheduleResultDetail> times = new ArrayList<>(); List<ScheduleResultDetail> times = new ArrayList<>();
List<ScheduleResultDetail> oldTimes = new ArrayList<>(); List<ScheduleResultDetail> oldTimes = new ArrayList<>();
List<TimeSegment> timeSegments= findAvailableSegments(machine, currentTime, machineTasks, remainingTime, isInterrupt); List<TimeSegment> timeSegments= findAvailableSegments(machine, currentTime, machineTasks, remainingTime, isInterrupt);
int i=0; int i=0;
while (remainingTime > 0) { while (remainingTime > 0) {
TimeSegment shift= timeSegments.get(i); TimeSegment shift= timeSegments.get(i);
...@@ -220,9 +216,9 @@ public class MachineCalculator { ...@@ -220,9 +216,9 @@ public class MachineCalculator {
i++; i++;
} }
return times; return times;
} }
/** /**
* 查找满足时长要求的无冲突可用时段 * 查找满足时长要求的无冲突可用时段
* @param machine 设备 * @param machine 设备
...@@ -323,6 +319,97 @@ i++; ...@@ -323,6 +319,97 @@ i++;
} }
} }
} }
private static final int ONE_DAY_MINUTES = 24 * 60; // 固定锚点:一天1440分钟,永不改变
/**
* 按预估索引快速获取满足时长的时段数组
* @param availableSegments 有序的可用时段列表(必须按Start升序,业务中天然满足)
* @param currentTime 排程开始时间
* @param requiredMinutes 需要的总分钟数(支持超大值:几万/几十万分钟)
* @return 刚好满足时长的片段数组
* @throws IllegalArgumentException 总时长不足时抛出
*/
public TimeSegment[] getEnoughSegmentsByEstimateIndex(
List<TimeSegment> availableSegments,
LocalDateTime currentTime,
int requiredMinutes) {
// 基础校验
if (availableSegments == null || availableSegments.isEmpty()) {
throw new IllegalArgumentException("可用时段列表不能为空");
}
if (requiredMinutes <= 0) {
return new TimeSegment[0];
}
int totalSegmentCount = availableSegments.size();
// ========== 步骤1:核心!快速预估索引,一步到位,跳过几千个片段 ==========
// 预估逻辑:需求时长/每天分钟数 + 5(冗余值,防止预估不足,可根据业务调整,实际班次不是24小时),
int estimateIndex= (int) Math.ceil(requiredMinutes / (double) ONE_DAY_MINUTES);
estimateIndex =estimateIndex + 5;
// 边界保护:预估索引不能超过总片段数,也不能小于0
estimateIndex = Math.min(estimateIndex, totalSegmentCount - 1);
estimateIndex = Math.max(estimateIndex, 0);
// ========== 步骤2:双向逼近,小范围循环增减索引,循环次数≤20次 ==========
int targetIndex = estimateIndex;
while (true) {
// 计算当前索引的总有效时长
double currentTotal = calculateTotalMinutesByIndex(availableSegments, currentTime, targetIndex);
if (currentTotal >= requiredMinutes) {
// ✔️ 总时长满足,尝试往前减索引,找「最小满足索引」(减少后续裁剪的工作量)
if (targetIndex > 0) {
double prevTotal = calculateTotalMinutesByIndex(availableSegments, currentTime, targetIndex - 1);
if (prevTotal >= requiredMinutes) {
targetIndex--;
continue;
}
}
break; // 找到最小满足索引,退出循环
} else {
// ❌ 总时长不足,往后加索引(每次加5,大步前进,加快逼近速度)
targetIndex += 5;
if (targetIndex >= totalSegmentCount) {
// 所有片段总时长不足,抛出异常
double allTotal = calculateTotalMinutesByIndex(availableSegments, currentTime, totalSegmentCount - 1);
if(allTotal>requiredMinutes)
{
double prevTotal = calculateTotalMinutesByIndex(availableSegments, currentTime, targetIndex - 1);
if (prevTotal >= requiredMinutes) {
targetIndex--;
continue;
}
break;
}
else if(allTotal==requiredMinutes)
{
return availableSegments.toArray(new TimeSegment[0]);
}else {
return null;
}
}
}
}
// ========== 步骤3:精准裁剪片段,返回最终结果 ==========
List<TimeSegment> resultList = availableSegments.subList(0,targetIndex);
return resultList.toArray(new TimeSegment[0]);
}
/**
* 计算从0到指定索引的所有时段的总有效分钟数
*/
private double calculateTotalMinutesByIndex(List<TimeSegment> segments, LocalDateTime currentTime, int endIndex) {
return calculateTotalAvailableSecond(segments.subList(0,endIndex), currentTime);
}
/** /**
* 统一过滤有效可用片段 * 统一过滤有效可用片段
*/ */
......
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