滚动排产修改

parent 503590db
......@@ -2,10 +2,7 @@ package com.aps.service.plan;
import com.aps.common.util.ProductionDeepCopyUtil;
import com.aps.common.util.redis.RedisUtils;
import com.aps.entity.Algorithm.Chromosome;
import com.aps.entity.Algorithm.GAScheduleResult;
import com.aps.entity.Algorithm.GlobalOperationInfo;
import com.aps.entity.Algorithm.ScheduleResultDetail;
import com.aps.entity.Algorithm.*;
import com.aps.entity.ApsTimeConfig;
import com.aps.entity.Dispatch;
import com.aps.entity.MesShiftWorkSched;
......@@ -546,10 +543,12 @@ public class LockedOrderProcessorService {
.orElse(0);
int nextAvailableId = maxExistingId + 1;
Map<Integer, Integer> lockedEntryIdMapping = new HashMap<>();
// 为锁定期Entry重新分配ID
for (Entry lockedEntry : data.entries.values()) {
int oldId = lockedEntry.getId();
lockedEntryIdMapping.put(oldId, nextAvailableId);
lockedEntry.setId(nextAvailableId);
// 更新对应的GAScheduleResult的operationId(包括result和resultOld)
......@@ -577,6 +576,76 @@ public class LockedOrderProcessorService {
nextAvailableId++;
}
// 同步更新锁定期Entry内部依赖中的工序ID引用(仅修正本批次重分配的ID)
for (Entry lockedEntry : data.entries.values()) {
if (lockedEntry.getPrevEntryIds() != null) {
for (OperationDependency dep : lockedEntry.getPrevEntryIds()) {
if (dep == null) {
continue;
}
Integer newPrev = lockedEntryIdMapping.get(dep.getPrevOperationId());
if (newPrev != null) {
dep.setPrevOperationId(newPrev);
}
Integer newNext = lockedEntryIdMapping.get(dep.getNextOperationId());
if (newNext != null) {
dep.setNextOperationId(newNext);
}
}
}
if (lockedEntry.getNextEntryIds() != null) {
for (OperationDependency dep : lockedEntry.getNextEntryIds()) {
if (dep == null) {
continue;
}
Integer newPrev = lockedEntryIdMapping.get(dep.getPrevOperationId());
if (newPrev != null) {
dep.setPrevOperationId(newPrev);
}
Integer newNext = lockedEntryIdMapping.get(dep.getNextOperationId());
if (newNext != null) {
dep.setNextOperationId(newNext);
}
}
}
}
// 同步更新锁定期Entry内部依赖中的工序ID引用(仅修正本批次重分配的ID)
for (Entry lockedEntry : data.entries.values()) {
if (lockedEntry.getPrevEntryIds() != null) {
for (OperationDependency dep : lockedEntry.getPrevEntryIds()) {
if (dep == null) {
continue;
}
Integer newPrev = lockedEntryIdMapping.get(dep.getPrevOperationId());
if (newPrev != null) {
dep.setPrevOperationId(newPrev);
}
Integer newNext = lockedEntryIdMapping.get(dep.getNextOperationId());
if (newNext != null) {
dep.setNextOperationId(newNext);
}
}
}
if (lockedEntry.getNextEntryIds() != null) {
for (OperationDependency dep : lockedEntry.getNextEntryIds()) {
if (dep == null) {
continue;
}
Integer newPrev = lockedEntryIdMapping.get(dep.getPrevOperationId());
if (newPrev != null) {
dep.setPrevOperationId(newPrev);
}
Integer newNext = lockedEntryIdMapping.get(dep.getNextOperationId());
if (newNext != null) {
dep.setNextOperationId(newNext);
}
}
}
}
chromosome.getAllOperations().addAll(data.entries.values());
log.debug("成功添加 {} 个锁定期Entry到allOperations中,大小从{}变为{},ID范围: {}-{}",
data.entries.size(), beforeEntrySize, chromosome.getAllOperations().size(),
......
......@@ -125,10 +125,10 @@ public class PlanResultService {
private MaterialRequirementService materialRequirementService;
@Autowired
private EquipMaintainTaskService _equipMaintainTaskService;
@Autowired
private DispatchService dispatchService;
@Autowired
private ApsTimeConfigService apsTimeConfigService;
......@@ -231,7 +231,7 @@ public class PlanResultService {
KpiCalculator kpiCalculator=new KpiCalculator(chromosome);
kpiCalculator.calculatekpi();
// 添加锁定期工单到调度结果中
// 这里会从 Dispatch 表加载锁定期工单,并添加到 chromosome.result 中
lockedOrderProcessorService.addLockedOrdersToResult(chromosome);
......@@ -1095,16 +1095,16 @@ public class PlanResultService {
if (chromosome == null || chromosome.getAllOperations() == null) {
return chromosome;
}
List<Entry> operations = chromosome.getAllOperations();
int position = IntStream.range(0, operations.size())
.filter(i -> operations.get(i).getId() == operation.getId())
.findFirst()
.orElse(-1);
if (position != -1) {
Entry oldEntry = operations.set(position, operation);
List<GlobalOperationInfo> globalOpList = chromosome.getGlobalOpList();
if (globalOpList != null) {
globalOpList.stream()
......@@ -1115,27 +1115,27 @@ public class PlanResultService {
// _sceneService.saveChromosomeToFile(chromosome, SceneId);
return redecodeChromosome(chromosome, SceneId);
}
public Chromosome EditOrder(String SceneId, Order order) {
Chromosome chromosome = _sceneService.loadChromosomeFromFile(SceneId);
if (chromosome == null || chromosome.getOrders() == null) {
return chromosome;
}
List<Order> orders = chromosome.getOrders();
int position = IntStream.range(0, orders.size())
.filter(i -> orders.get(i).getId() == order.getId())
.findFirst()
.orElse(-1);
if (position != -1) {
orders.set(position, order);
}
orderSortService.initializeFieldExtractors();
OrderSortRule rule = createMultiConditionRule(orders);
orderSortService.assignPriority(orders, rule);
updateOrderRelatedEntries(chromosome, order);
// _sceneService.saveChromosomeToFile(chromosome, SceneId);
return redecodeChromosome(chromosome,SceneId);
......@@ -1231,7 +1231,7 @@ public class PlanResultService {
entry.setPriority(order.getActualPriority());
});
}
// 更新GlobalOperationInfo中的Entry
List<GlobalOperationInfo> globalOpList = chromosome.getGlobalOpList();
if (globalOpList != null) {
......@@ -1243,7 +1243,7 @@ public class PlanResultService {
entry.setPriority(order.getActualPriority());
});
}
// 更新调度结果中的数量(关键:处理锁定期工单)
List<GAScheduleResult> results = chromosome.getResult();
if (results != null) {
......@@ -1255,7 +1255,7 @@ public class PlanResultService {
});
}
}
/**
* 重新解码染色体
*/
......@@ -1288,6 +1288,10 @@ public class PlanResultService {
GlobalParam globalParam=new GlobalParam();
Chromosome chromosome= _sceneService.loadChromosomeFromFile(SceneId);
// 拖拽前清理历史工单在设备上的静态占位段,确保历史工单移动后可释放产能
int releasedCount = releaseLockedOccupancyForDrag(chromosome);
// WriteScheduleSummary(chromosome);
ScheduleOperationService ScheduleOperation=new ScheduleOperationService(materialRequirementService,this);
......@@ -1298,6 +1302,114 @@ public class PlanResultService {
_sceneService.saveChromosomeToFile(chromosome, SceneId);
return chromosome;
}
/**
* 释放历史工单占用段(拖拽前调用)
*/
private int releaseLockedOccupancyForDrag(Chromosome chromosome) {
if (chromosome == null || chromosome.getInitMachines() == null || chromosome.getInitMachines().isEmpty()) {
return 0;
}
int releasedCount = 0;
for (Machine machine : chromosome.getInitMachines()) {
if (machine == null || machine.getAvailability() == null || machine.getAvailability().isEmpty()) {
continue;
}
for (TimeSegment segment : machine.getAvailability()) {
if (segment == null) {
continue;
}
boolean lockedOccupyKey = segment.getKey() != null && segment.getKey().startsWith("LOCKED_OCCUPY_");
boolean usedRegularOrMaintenance = segment.isUsed()
&& (segment.getType() == SegmentType.REGULAR || segment.getType() == SegmentType.MAINTENANCE);
if (lockedOccupyKey || usedRegularOrMaintenance) {
releasedCount++;
segment.setUsed(false);
segment.setType(SegmentType.REGULAR);
if (lockedOccupyKey) {
segment.setKey(UUID.randomUUID().toString());
}
}
}
machine.getAvailability().sort(Comparator.comparing(TimeSegment::getStart));
}
return releasedCount;
}
private long countMachineAvailabilitySegments(Chromosome chromosome, Long machineId) {
if (chromosome == null || machineId == null || chromosome.getInitMachines() == null) {
return 0;
}
return chromosome.getInitMachines().stream()
.filter(Objects::nonNull)
.filter(m -> m.getId() == machineId)
.findFirst()
.map(m -> m.getAvailability() == null ? 0L : (long) m.getAvailability().size())
.orElse(0L);
}
private long countMachineUsedMaintenanceSegments(Chromosome chromosome, Long machineId) {
if (chromosome == null || machineId == null || chromosome.getInitMachines() == null) {
return 0;
}
return chromosome.getInitMachines().stream()
.filter(Objects::nonNull)
.filter(m -> m.getId() == machineId)
.findFirst()
.map(m -> m.getAvailability() == null ? 0L : m.getAvailability().stream()
.filter(Objects::nonNull)
.filter(seg -> seg.getType() == SegmentType.MAINTENANCE && seg.isUsed())
.count())
.orElse(0L);
}
private long countMachineUsedSegments(Chromosome chromosome, Long machineId, SegmentType type) {
if (chromosome == null || machineId == null || chromosome.getInitMachines() == null) {
return 0;
}
return chromosome.getInitMachines().stream()
.filter(Objects::nonNull)
.filter(m -> m.getId() == machineId)
.findFirst()
.map(m -> m.getAvailability() == null ? 0L : m.getAvailability().stream()
.filter(Objects::nonNull)
.filter(TimeSegment::isUsed)
.filter(seg -> type == null || seg.getType() == type)
.count())
.orElse(0L);
}
private String machineSegmentSnapshot(Chromosome chromosome, Long machineId, int limit) {
if (chromosome == null || machineId == null || chromosome.getInitMachines() == null) {
return "[]";
}
Machine machine = chromosome.getInitMachines().stream()
.filter(Objects::nonNull)
.filter(m -> m.getId() == machineId)
.findFirst()
.orElse(null);
if (machine == null || machine.getAvailability() == null || machine.getAvailability().isEmpty()) {
return "[]";
}
return machine.getAvailability().stream()
.filter(Objects::nonNull)
.sorted(Comparator.comparing(TimeSegment::getStart))
.limit(Math.max(limit, 1))
.map(seg -> String.format("%s|used=%s|%s~%s", seg.getType(), seg.isUsed(), seg.getStart(), seg.getEnd()))
.collect(Collectors.joining("; "));
}
public Chromosome Move(String SceneId,List<Integer> opId, LocalDateTime newStartTime,
Long newMachineId,int lockStartTime) {
......@@ -2337,19 +2449,19 @@ private GlobalParam InitGlobalParam()
List<Entry> orderEntries = entries.stream()
.filter(e -> e.getOrderId() != null && e.getOrderId().equals(targetOrder.getOrderId()))
.collect(Collectors.toList());
if (!orderEntries.isEmpty()) {
// 找到该订单的最后一道工序(按Sequence排序)
Entry lastEntry = orderEntries.stream()
.max(Comparator.comparingInt(Entry::getSequence))
.orElse(null);
if (lastEntry != null) {
// 找到当前工序的开始时间
LocalDateTime currentStartTime = getEntryStartTime(currentEntry, results, baseTime);
// 找到上一道工序的结束时间
LocalDateTime lastEntryEndTime = getEntryEndTime(lastEntry, results, baseTime);
Order fromOrder1 = orders != null ? orders.stream().filter(o -> o.getOrderId() != null && o.getOrderId().equals(lastEntry.getOrderId())).findFirst().orElse(null) : null;
Order toOrder1 = orders != null ? orders.stream().filter(o -> o.getOrderId() != null && o.getOrderId().equals(currentEntry.getOrderId())).findFirst().orElse(null) : null;
long fromEquipId1 = results.stream().filter(r -> r.getOperationId() == lastEntry.getId()).mapToLong(r -> r.getMachineId()).findFirst().orElse(-1L);
......@@ -2364,7 +2476,7 @@ private GlobalParam InitGlobalParam()
item.put("toEquipId", String.valueOf(toEquipId1));
item.put("toTime", currentStartTime != null ? currentStartTime.toString() : "2026-12-13");
supplyRelations.add(item);
// 递归检查上一个订单的依赖关系
checkAndAddDependentRelations(entries, orders, results, baseTime, lastEntry, supplyRelations);
}
......@@ -2381,7 +2493,7 @@ private GlobalParam InitGlobalParam()
LocalDateTime currentEndTime = getEntryEndTime(currentEntry, results, baseTime);
// 找到目标工序的开始时间
LocalDateTime targetStartTime = getEntryStartTime(targetEntry, results, baseTime);
Order fromOrder2 = orders != null ? orders.stream().filter(o -> o.getOrderId() != null && o.getOrderId().equals(currentEntry.getOrderId())).findFirst().orElse(null) : null;
Order toOrder2 = orders != null ? orders.stream().filter(o -> o.getOrderId() != null && o.getOrderId().equals(targetEntry.getOrderId())).findFirst().orElse(null) : null;
long fromEquipId2 = results.stream().filter(r -> r.getOperationId() == currentEntry.getId()).mapToLong(r -> r.getMachineId()).findFirst().orElse(-1L);
......@@ -2426,7 +2538,7 @@ private GlobalParam InitGlobalParam()
}
return null;
}
/**
* 获取工单的结束时间
* @param entry 工单
......@@ -2472,19 +2584,19 @@ private GlobalParam InitGlobalParam()
List<Entry> orderEntries = entries.stream()
.filter(e -> e.getOrderId() != null && e.getOrderId().equals(targetOrder.getOrderId()))
.collect(Collectors.toList());
if (!orderEntries.isEmpty()) {
// 找到该订单的最后一道工序(按Sequence排序)
Entry lastEntry = orderEntries.stream()
.max(Comparator.comparingInt(Entry::getSequence))
.orElse(null);
if (lastEntry != null) {
// 找到当前工序的开始时间
LocalDateTime currentStartTime = getEntryStartTime(currentEntry, results, baseTime);
// 找到上一道工序的结束时间
LocalDateTime lastEntryEndTime = getEntryEndTime(lastEntry, results, baseTime);
Order fromOrder3 = orders != null ? orders.stream().filter(o -> o.getOrderId() != null && o.getOrderId().equals(lastEntry.getOrderId())).findFirst().orElse(null) : null;
Order toOrder3 = orders != null ? orders.stream().filter(o -> o.getOrderId() != null && o.getOrderId().equals(currentEntry.getOrderId())).findFirst().orElse(null) : null;
long fromEquipId3 = results.stream().filter(r -> r.getOperationId() == lastEntry.getId()).mapToLong(r -> r.getMachineId()).findFirst().orElse(-1L);
......@@ -2499,7 +2611,7 @@ private GlobalParam InitGlobalParam()
item.put("toEquipId", String.valueOf(toEquipId3));
item.put("toTime", currentStartTime != null ? currentStartTime.toString() : "2026-12-13");
supplyRelations.add(item);
// 递归调用,处理上一个订单的最后一道工序的依赖关系
checkAndAddDependentRelations(entries, orders, results, baseTime, lastEntry, supplyRelations);
}
......@@ -2886,7 +2998,7 @@ private GlobalParam InitGlobalParam()
taskVO.setEquipType(resourceGanttVO.getType());
taskVO.setEquipName(resourceGanttVO.getName());
taskVO.setLocked(gene.isIsLocked()); // 设置锁定状态
// 处理锁定期工单(entry为null的情况)
if (entry != null) {
taskVO.setSeq(Math.toIntExact(entry.getTaskSeq()));
......@@ -2995,10 +3107,10 @@ private GlobalParam InitGlobalParam()
for (int i = 0; i < genes.size(); i++) {
GAScheduleResult gene = genes.get(i);
Entry entry1 = allOperations.stream()
.filter(t -> t.getId() == gene.getOperationId()).findFirst().orElse(null);
TaskVO taskVO = new TaskVO();
taskVO.setId(String.valueOf(gene.getOperationId()));
taskVO.setPlanId(gene.getOrderId());
......@@ -3014,7 +3126,7 @@ private GlobalParam InitGlobalParam()
taskVO.setEquipChange(gene.getChangeOverTime());
taskVO.setEquipCooling(0);
taskVO.setLocked(gene.isIsLocked());
if (entry1 != null) {
taskVO.setSeq(Math.toIntExact(entry1.getTaskSeq()));
taskVO.setSeqName(entry1.getRoutingDetailName());
......@@ -3031,13 +3143,13 @@ private GlobalParam InitGlobalParam()
taskVO.setShopId(gene.getMachineId());
taskVO.setShopName(gene.getMachineId()+"车间");
taskVO.setStatus(0);
if (entry1 != null) {
taskVO.setDetailId(entry1.getRoutingDetailId());
taskVO.setHeaderId(entry1.getRoutingId());
taskVO.setHeaderName(entry1.getRoutingName());
}
taskVO.setProcessingTime(gene.getProcessingTime());
taskVO.setAbsolutePreparationTime(gene.getTeardownTime());
......@@ -3094,19 +3206,19 @@ private GlobalParam InitGlobalParam()
Set<Long> machineIdSet = ProdEquipments.stream()
.map(ProdEquipment::getEquipId)
.collect(Collectors.toSet());
// 添加锁定期工单使用的设备ID
try {
ApsTimeConfig timeConfig = apsTimeConfigService.getOne(new LambdaQueryWrapper<>());
if (timeConfig != null && timeConfig.getBaseTime() != null && timeConfig.getFreezeDate() != null) {
LocalDateTime baseTime = timeConfig.getBaseTime();
long freezeSeconds = timeConfig.getFreezeDate().longValue();
if (freezeSeconds > 0) {
// 锁定期计算:baseTime 到 baseTime + freezeSeconds
LocalDateTime lockStartTime = baseTime;
LocalDateTime lockEndTime = baseTime.plusSeconds(freezeSeconds);
// 查询锁定期内的工单使用的设备ID
List<Dispatch> frozenDispatches = dispatchService.lambdaQuery()
.ge(Dispatch::getBeginTime, lockStartTime)
......@@ -3114,21 +3226,21 @@ private GlobalParam InitGlobalParam()
.eq(Dispatch::getIsDeleted, 0L)
.isNotNull(Dispatch::getEquipId)
.list();
// 提取设备ID并添加到Set中
for (Dispatch dispatch : frozenDispatches) {
if (dispatch.getEquipId() != null) {
machineIdSet.add(dispatch.getEquipId());
}
}
log.info("锁定期工单使用的所有设备ID: {}", machineIdSet);
}
}
} catch (Exception e) {
log.error("加载锁定期设备ID时发生错误: {}", e.getMessage(), e);
}
// 转换为排序后的List
List<Long> MachineIds = machineIdSet.stream()
.sorted()
......@@ -3334,12 +3446,12 @@ private GlobalParam InitGlobalParam()
public List<Machine> InitCalendarToAllMachines3(Chromosome chromosome) {
List<Machine> machines = chromosome.getInitMachines();
// 如果initMachines为空,返回空列表
if (machines == null || machines.isEmpty()) {
return new ArrayList<>();
}
Set<Long> machineIds = chromosome.getResult().stream()
.map(GAScheduleResult::getMachineId)
.collect(Collectors.toSet());
......@@ -3390,7 +3502,7 @@ private GlobalParam InitGlobalParam()
}
/**
* 获取指定场景ID的文件数字
* @param sceneId 场景ID
......@@ -3411,29 +3523,29 @@ private GlobalParam InitGlobalParam()
if (!resultDir.exists() || !resultDir.isDirectory()) {
return numbers;
}
// 获取目录中的所有文件
File[] files = resultDir.listFiles();
if (files == null) {
return numbers;
}
// 定义要查找的前缀
String prefix = "chromosome_result_" + sceneId + "_";
String suffix = "_.json";
for (File file : files) {
if (file.isFile()) {
String fileName = file.getName();
// 检查文件名是否以指定前缀开始,并以指定后缀结束
if (fileName.startsWith(prefix) && fileName.endsWith(suffix)) {
// 提取前缀和后缀之间的部分
String middlePart = fileName.substring(
prefix.length(),
prefix.length(),
fileName.length() - suffix.length()
);
// 尝试将中间部分解析为数字
try {
int number = Integer.parseInt(middlePart);
......@@ -3448,7 +3560,7 @@ private GlobalParam InitGlobalParam()
}
}
}
// 对数字列表进行排序(从小到大)
Collections.sort(numbers);
return numbers;
......
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