|
@@ -10,6 +10,8 @@ import com.rongwei.rwapsserver.aps.domain.ProductionProcesses;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.optaplanner.core.api.domain.variable.VariableListener;
|
|
|
import org.optaplanner.core.api.score.director.ScoreDirector;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.ZoneId;
|
|
|
import java.time.temporal.ChronoUnit;
|
|
@@ -88,15 +90,16 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
|
|
|
/*if(process.getId().equals("abdcff89d0164cd5a2b57e1bfaf3bc1d")){
|
|
|
process.getId();
|
|
|
}*/
|
|
|
- LocalDateTime startDateTime = startTimeSet(process,scoreDirector);
|
|
|
- if(process.getDelay() != null && process.getDelay()>0){
|
|
|
+ LocalDateTime startDateTime = startTimeNewSet(process,scoreDirector);
|
|
|
+
|
|
|
+ /*if(process.getDelay() != null && process.getDelay()>0){
|
|
|
if(process.getProduceTime()>1000){
|
|
|
int bc = (int) Math.ceil((double) process.getProduceTime() / 20);
|
|
|
startDateTime = startDateTime.plusMinutes(process.getDelay() * bc);
|
|
|
}else{
|
|
|
startDateTime = startDateTime.plusMinutes(process.getDelay() * 30);
|
|
|
}
|
|
|
- }
|
|
|
+ }*/
|
|
|
scoreDirector.beforeVariableChanged(process, "startTime");
|
|
|
process.setStartTime(startDateTime);
|
|
|
scoreDirector.afterVariableChanged(process, "startTime");
|
|
@@ -469,6 +472,164 @@ public class TaskStartTimeListener implements VariableListener<ApsSolution, Prod
|
|
|
return toUpdateStartTime;
|
|
|
}
|
|
|
|
|
|
+ private LocalDateTime startTimeNewSet(ProductionProcesses process,ScoreDirector<ApsSolution> scoreDirector){
|
|
|
+ // 时间设定
|
|
|
+ LocalDateTime toUpdateStartTime = null;
|
|
|
+ if(process.getEquipment() != null){
|
|
|
+ LocalDateTime endTime = process.getApsOverallConfig().getStartTime();
|
|
|
+ ProductionProcesses preProcess = null;
|
|
|
+ if(process.getPreviousProcesses() != null && process.getPreviousProcesses().size()>0){
|
|
|
+ // 单卷情况下前道工序只有一个
|
|
|
+ preProcess = process.getPreviousProcesses().get(0);
|
|
|
+ // 前道工序结束时间
|
|
|
+ endTime = preProcess.getEndTime();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 流转时间
|
|
|
+ Integer lzTimes = 0;
|
|
|
+ if(preProcess != null){
|
|
|
+ if(preProcess.getEquipment().getWorkshopid() != null && preProcess.getEquipment().getWorkshopid().equals(process.getEquipment().getWorkshopid())){
|
|
|
+ lzTimes = process.getApsOverallConfig().getRoamTime().get("WORKSHOP_IN");
|
|
|
+ }else{
|
|
|
+ lzTimes = process.getApsOverallConfig().getRoamTime().get("WORKSHOP_CROSS");
|
|
|
+ }
|
|
|
+ // 最小等待时间对比流转时间
|
|
|
+ if(preProcess.getMinWaitTime() != null && lzTimes<preProcess.getMinWaitTime()){
|
|
|
+ lzTimes = preProcess.getMinWaitTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 当前工序最小开始时间、结束时间
|
|
|
+ LocalDateTime proStartTime = endTime.plusMinutes(lzTimes);
|
|
|
+ LocalDateTime proEndTime = proStartTime.plusMinutes(process.getProduceTime());
|
|
|
+ // 随机延时时间处理
|
|
|
+ if(process.getProcessType().equals("成退") || process.getProcessType().equals("中退")
|
|
|
+ || process.getProcessType().equals("铸轧") || process.getProcessType().equals("冷轧")){
|
|
|
+ proStartTime = proStartTime.plusMinutes(process.getDelay() * 60);
|
|
|
+ }else{
|
|
|
+ proStartTime = proStartTime.plusMinutes(process.getDelay() * 10);
|
|
|
+ }
|
|
|
+ // 当前工序设备已占用时间
|
|
|
+ List<EquipmentRunTime> equipmentRunTimes = new ArrayList<>();
|
|
|
+ if(process.getEquipment().getEquipmentRunTimes() != null && process.getEquipment().getEquipmentRunTimes().size()>0){
|
|
|
+ for (EquipmentRunTime equipmentRunTime : process.getEquipment().getEquipmentRunTimes()) {
|
|
|
+ EquipmentRunTime copy = new EquipmentRunTime();
|
|
|
+ copy.setStartRunTime(equipmentRunTime.getStartRunTime());
|
|
|
+ copy.setEndRunTime(equipmentRunTime.getEndRunTime());
|
|
|
+ copy.setLocked(true);
|
|
|
+ equipmentRunTimes.add(copy);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 排程中当前设备其它作业占用时间
|
|
|
+ // 过滤同一设备存在开始时间不是当前工序的其它所有工序
|
|
|
+ // 获取所有规划实体对象数据
|
|
|
+ ApsSolution workingSolution = scoreDirector.getWorkingSolution();
|
|
|
+ Equipment pe = process.getEquipment();
|
|
|
+ List<ProductionProcesses> allProcessesList = workingSolution.getProcessesList();
|
|
|
+ List<ProductionProcesses> filterProcess = allProcessesList.stream().filter(v -> {
|
|
|
+ return v.getEquipment() != null && v.getEquipment().getId().equals(pe.getId()) && v.getStartTime() != null && !v.getId().equals(process.getId());
|
|
|
+ }).sorted(Comparator.comparing(ProductionProcesses::getProduceTime)).collect(Collectors.toList());
|
|
|
+ if(filterProcess != null && filterProcess.size()>0){
|
|
|
+ for (ProductionProcesses productionProcesses : filterProcess) {
|
|
|
+ if(equipmentRunTimes == null || equipmentRunTimes.size() == 0){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ boolean merged = false;
|
|
|
+ if(process.getProcessType().equals("成退") || process.getProcessType().equals("中退")){
|
|
|
+ for (EquipmentRunTime equipmentRunTime : equipmentRunTimes) {
|
|
|
+ // 判断当前排程的退火作业哪些是合并工序,只要开始时间到结束时间是包含关系即认为是合并工序
|
|
|
+ if(equipmentRunTime.getStartRunTime().compareTo(productionProcesses.getStartTime())<=0
|
|
|
+ && equipmentRunTime.getEndRunTime().compareTo(productionProcesses.getEndTime())>=0){
|
|
|
+ // 合并退火作业总宽度、承重
|
|
|
+ equipmentRunTime.setTotalVolumeWidth(equipmentRunTime.getTotalVolumeWidth().add(productionProcesses.getVolumeWidth()));
|
|
|
+ equipmentRunTime.setTotalSinglerollweight(equipmentRunTime.getTotalSinglerollweight().add(productionProcesses.getSinglerollweight()));
|
|
|
+ merged = true;
|
|
|
+ break;
|
|
|
+ }else{
|
|
|
+ // 未锁定的是排程中的作业占用时间段,可以合并更大的加工时间
|
|
|
+ if(!equipmentRunTime.isLocked()){
|
|
|
+ if(equipmentRunTime.getStartRunTime().compareTo(productionProcesses.getStartTime())>=0
|
|
|
+ && equipmentRunTime.getEndRunTime().compareTo(productionProcesses.getEndTime())<=0){
|
|
|
+ // 合并退火作业总宽度、承重
|
|
|
+ equipmentRunTime.setTotalVolumeWidth(equipmentRunTime.getTotalVolumeWidth().add(productionProcesses.getVolumeWidth()));
|
|
|
+ equipmentRunTime.setTotalSinglerollweight(equipmentRunTime.getTotalSinglerollweight().add(productionProcesses.getSinglerollweight()));
|
|
|
+ equipmentRunTime.setStartRunTime(productionProcesses.getStartTime());
|
|
|
+ equipmentRunTime.setEndRunTime(productionProcesses.getEndTime());
|
|
|
+ merged = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 新增设备占用时间段
|
|
|
+ if(!merged){
|
|
|
+ EquipmentRunTime copy = new EquipmentRunTime();
|
|
|
+ copy.setStartRunTime(productionProcesses.getStartTime());
|
|
|
+ copy.setEndRunTime(productionProcesses.getEndTime());
|
|
|
+ copy.setLocked(false);
|
|
|
+ equipmentRunTimes.add(copy);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 过滤
|
|
|
+ // 按照开始时间排序
|
|
|
+ equipmentRunTimes.sort(Comparator.comparing(EquipmentRunTime::getStartRunTime));
|
|
|
+ // 有交叉的时间直接跳过
|
|
|
+ if(equipmentRunTimes.size()>0){
|
|
|
+ for (EquipmentRunTime equipmentRunTime : equipmentRunTimes) {
|
|
|
+ if(proStartTime.compareTo(equipmentRunTime.getEndRunTime())>0 || proEndTime.compareTo(equipmentRunTime.getStartRunTime())<0){
|
|
|
+ continue;
|
|
|
+ }else{
|
|
|
+ boolean jumpMark = false;
|
|
|
+ // 退火工序特殊处理
|
|
|
+ if(process.getProcessType().equals("成退") || process.getProcessType().equals("中退")){
|
|
|
+ if(equipmentRunTime.getStartRunTime().compareTo(proStartTime)<=0
|
|
|
+ && equipmentRunTime.getEndRunTime().compareTo(proEndTime)>=0){
|
|
|
+ // 宽度余量
|
|
|
+ if (pe.getEquipmentParameter().getEquipmentWidth().subtract(equipmentRunTime.getTotalVolumeWidth()).compareTo(process.getVolumeWidth()) < 0) {
|
|
|
+ jumpMark = true;
|
|
|
+ }
|
|
|
+ // 重量余量
|
|
|
+ if (pe.getEquipmentParameter().getEquipmentBearing().subtract(equipmentRunTime.getTotalSinglerollweight()).compareTo(process.getSinglerollweight()) < 0) {
|
|
|
+ jumpMark = true;
|
|
|
+ }
|
|
|
+ }else if(equipmentRunTime.getStartRunTime().compareTo(proStartTime)>=0 && equipmentRunTime.getEndRunTime().compareTo(proEndTime)<=0){
|
|
|
+ // 未锁定的是排程中的作业占用时间段,可以合并更大的加工时间
|
|
|
+ if(!equipmentRunTime.isLocked()){
|
|
|
+ // 宽度余量
|
|
|
+ if (pe.getEquipmentParameter().getEquipmentWidth().subtract(equipmentRunTime.getTotalVolumeWidth()).compareTo(process.getVolumeWidth()) < 0) {
|
|
|
+ jumpMark = true;
|
|
|
+ }
|
|
|
+ // 重量余量
|
|
|
+ if (pe.getEquipmentParameter().getEquipmentBearing().subtract(equipmentRunTime.getTotalSinglerollweight()).compareTo(process.getSinglerollweight()) < 0) {
|
|
|
+ jumpMark = true;
|
|
|
+ }
|
|
|
+ equipmentRunTime.setStartRunTime(proStartTime);
|
|
|
+ equipmentRunTime.setEndRunTime(proEndTime);
|
|
|
+ }else{
|
|
|
+ jumpMark = true;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ jumpMark = true;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ jumpMark = true;
|
|
|
+ }
|
|
|
+ // 跳过当前占用时间
|
|
|
+ if(jumpMark){
|
|
|
+ proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(1);
|
|
|
+ proEndTime = proStartTime.plusMinutes(process.getProduceTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ toUpdateStartTime = proStartTime;
|
|
|
+ }
|
|
|
+ return toUpdateStartTime;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 汇总所有下道工序的加工时间
|
|
|
* @param nextProcess
|