|
@@ -9,6 +9,7 @@ import com.rongwei.rwapsserver.aps.domain.Equipment;
|
|
|
import com.rongwei.rwapsserver.aps.domain.ProductionProcesses;
|
|
|
import com.rongwei.rwapsserver.aps.score.ApsConstraintProvider;
|
|
|
import com.rongwei.rwapsserver.aps.service.DdApsService;
|
|
|
+import com.rongwei.rwapsserver.aps.util.ApsException;
|
|
|
import com.rongwei.rwapsserver.aps.util.ApsUtils;
|
|
|
import com.rongwei.rwapsserver.aps.vo.ProductionScheduleVo;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
@@ -23,6 +24,7 @@ import org.optaplanner.core.config.solver.termination.TerminationConfig;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
import java.time.LocalDateTime;
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
import java.util.*;
|
|
@@ -1006,4 +1008,280 @@ public class DdApsServiceImpl implements DdApsService {
|
|
|
return endTime;
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 调度退火提前合并
|
|
|
+ * @param productionScheduleVo
|
|
|
+ * @param apsSolution
|
|
|
+ * @param otherThproces
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public List<ProductionProcesses> thProcessMerge(ProductionScheduleVo productionScheduleVo,ApsSolution apsSolution,List<ProductionProcesses> otherThproces){
|
|
|
+ List<ProductionProcesses> processes = apsSolution.getProcessesList();
|
|
|
+ // 设备集合
|
|
|
+ List<Equipment> equipmentList = apsSolution.getEquipmentList();
|
|
|
+ List<ProductionProcesses> mergeprocesses = new ArrayList<>();
|
|
|
+ // 所有作业集合
|
|
|
+ Map<String,ProductionProcesses> allProMap = new HashMap<>();
|
|
|
+
|
|
|
+ // 其它作业集合
|
|
|
+ Map<String,List<ProductionProcesses>> notthproMap = new HashMap<>();
|
|
|
+ // 按订单分组
|
|
|
+ Map<String, List<ProductionProcesses>> orderProcess = processes.stream().collect(Collectors.groupingBy(ProductionProcesses::getOrderId));
|
|
|
+ orderProcess.forEach((orderId,orderpss)->{
|
|
|
+ if("6639310eb2204f77ac9d36a2f289039c".equals(orderId)){
|
|
|
+ int a = 1;
|
|
|
+ }
|
|
|
+ // 退火作业集合
|
|
|
+ Map<String,List<ProductionProcesses>> thproMap = new HashMap<>();
|
|
|
+ for (ProductionProcesses process : orderpss) {
|
|
|
+ if("成退".equals(process.getProcessType()) || "中退".equals(process.getProcessType()) || "小卷成退".equals(process.getProcessType())){
|
|
|
+ // 锁定的不参与合并
|
|
|
+ /*if(process.getIfLock()){
|
|
|
+ mergeprocesses.add(process);
|
|
|
+ }else{*/
|
|
|
+ String bsproid = process.getBsProcessesId().get(0);
|
|
|
+ List<ProductionProcesses> bsprocess = thproMap.get(bsproid);
|
|
|
+ if(bsprocess == null){
|
|
|
+ bsprocess = new ArrayList<>();
|
|
|
+ }
|
|
|
+ bsprocess.add(process);
|
|
|
+ thproMap.put(bsproid,bsprocess);
|
|
|
+// }
|
|
|
+ }else{
|
|
|
+ mergeprocesses.add(process);
|
|
|
+
|
|
|
+ String bsproid = process.getBsProcessesId().get(0);
|
|
|
+ List<ProductionProcesses> bsprocess = thproMap.get(bsproid);
|
|
|
+ if(bsprocess == null){
|
|
|
+ bsprocess = new ArrayList<>();
|
|
|
+ }
|
|
|
+ bsprocess.add(process);
|
|
|
+ notthproMap.put(bsproid,bsprocess);
|
|
|
+ }
|
|
|
+ allProMap.put(process.getId(),process);
|
|
|
+ }
|
|
|
+ // 退火合并
|
|
|
+ if(thproMap != null && thproMap.size()>0){
|
|
|
+ thproMap.forEach((k,v)->{
|
|
|
+ // 未锁定的退火合并
|
|
|
+ if(v.size()>1){
|
|
|
+ // 作业卷数大于1,合并退火
|
|
|
+ List<Equipment> equipments = equipmentList.stream().filter(eq -> eq.getId().equals(v.get(0).getOptionalEquipments().get(0))).collect(Collectors.toList());
|
|
|
+ if(equipments != null && equipments.size()>0){
|
|
|
+ Equipment equipment = equipments.get(0);
|
|
|
+ // 根据承重计算最大几卷
|
|
|
+ int a = equipment.getEquipmentParameter().getEquipmentBearing().divide(v.get(0).getSinglerollweight(), 2, RoundingMode.HALF_UP).intValue();
|
|
|
+ // 根据宽度计算最大几卷
|
|
|
+ if("成退".equals(v.get(0).getProcessType()) || "中退".equals(v.get(0).getProcessType())){
|
|
|
+ int b = equipment.getEquipmentParameter().getEquipmentWidth().divide(v.get(0).getVolumeWidth().add(equipment.getEquipmentParameter().getFurnace()), 2, RoundingMode.HALF_UP).intValue();
|
|
|
+ if(b<a){
|
|
|
+ a = b;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 最大装炉卷数
|
|
|
+ Integer maxheatroll = v.get(0).getProduceOrder().get(0).getMaxheatroll();
|
|
|
+ if(maxheatroll != null && maxheatroll < a){
|
|
|
+ a = maxheatroll;
|
|
|
+ }
|
|
|
+ if(equipment.getEquipmentParameter() != null && equipment.getEquipmentParameter().getMaxfurance() != null && equipment.getEquipmentParameter().getMaxfurance()>0){
|
|
|
+ if(equipment.getEquipmentParameter().getMaxfurance() < a){
|
|
|
+ a = equipment.getEquipmentParameter().getMaxfurance();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 作业计划加工卷数是否大于一炉最大卷数
|
|
|
+ if(v.get(0).getPreviousProcesses() != null && v.get(0).getPreviousProcesses().size()>0){
|
|
|
+ Collections.sort(v,(p1,p2)->{
|
|
|
+ return p1.getPreviousProcesses().get(0).getEndTime().compareTo(p2.getPreviousProcesses().get(0).getEndTime());
|
|
|
+ });
|
|
|
+ }else{
|
|
|
+ if(v.get(0).getRooprocess() != null && v.get(0).getRooprocess().getStartTime() != null){
|
|
|
+ Collections.sort(v,(p1,p2)->{
|
|
|
+ if(p1.getRooprocess() == null || p1.getRooprocess().getStartTime() == null){
|
|
|
+ return 1;
|
|
|
+ } else if (p2.getRooprocess() == null || p2.getRooprocess().getStartTime() == null) {
|
|
|
+ return -1;
|
|
|
+ }else{
|
|
|
+ return p1.getRooprocess().getStartTime().compareTo(p2.getRooprocess().getStartTime());
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(a == 0){
|
|
|
+ throw new ApsException(v.get(0).getUniqueBsProcessesId()+"作业单卷重超过设备承重或最大装炉卷数设置为0");
|
|
|
+ }
|
|
|
+
|
|
|
+ List<List<ProductionProcesses>> chunks = new ArrayList<>();
|
|
|
+
|
|
|
+ List<ProductionProcesses> lockpps = v.stream().filter(m -> m.getIfLock()).collect(Collectors.toList());
|
|
|
+ List<ProductionProcesses> notlockpps = v.stream().filter(m -> !m.getIfLock()).collect(Collectors.toList());
|
|
|
+ if(lockpps != null && lockpps.size()>0){
|
|
|
+ /*Collections.sort(lockpps,(p1,p2)->{
|
|
|
+ return p1.getStartTime().compareTo(p2.getStartTime());
|
|
|
+ });
|
|
|
+ Map<String, List<ProductionProcesses>> map = new TreeMap<>();
|
|
|
+ for (ProductionProcesses productionProcesses : lockpps) {
|
|
|
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
+ String startStr = productionProcesses.getStartTime().format(formatter);
|
|
|
+ if(map.containsKey(startStr)){
|
|
|
+ map.get(startStr).add(productionProcesses);
|
|
|
+ }else{
|
|
|
+ List<ProductionProcesses> b = new ArrayList<>();
|
|
|
+ b.add(productionProcesses);
|
|
|
+ map.put(startStr,b);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(map != null && map.size()>0){
|
|
|
+ for (Map.Entry<String, List<ProductionProcesses>> entry : map.entrySet()) {
|
|
|
+ chunks.add(entry.getValue());
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ mergeprocesses.addAll(lockpps);
|
|
|
+ }
|
|
|
+ if(notlockpps != null && notlockpps.size()>0) {
|
|
|
+ int listSize = notlockpps.size();
|
|
|
+ /*for (int i = 0; i < listSize; i += a) {
|
|
|
+ chunks.add(notlockpps.subList(i, Math.min(i + a, listSize)));
|
|
|
+ }*/
|
|
|
+ // 根据最大装炉卷数以及最大等待时间来判断是否合并
|
|
|
+ LocalDateTime minpreendTime = null;
|
|
|
+ for (int i = 0; i < listSize; i++) {
|
|
|
+ ProductionProcesses processes1 = notlockpps.get(i);
|
|
|
+ // 是否新组炉
|
|
|
+ boolean newList = true;
|
|
|
+ if(!chunks.isEmpty()){
|
|
|
+ int lastsize = chunks.get(chunks.size() - 1).size();
|
|
|
+ // 最大装炉卷数限制
|
|
|
+ if(lastsize<a){
|
|
|
+ // 有最大等待时间则判断前道工序时间差是否小于最大等待时间
|
|
|
+ if(processes1.getMaxWaitTime() != null && processes1.getMaxWaitTime()>0){
|
|
|
+ if(processes1.getPreviousProcesses() != null && processes1.getPreviousProcesses().size()>0){
|
|
|
+ // 待合并的退火前道工序结束时间最大差不能大于最大等待时间
|
|
|
+ if(processes1.getPreviousProcesses().get(0).getEndTime().compareTo(minpreendTime.plusMinutes(processes1.getMaxWaitTime()))<0){
|
|
|
+ newList = false;
|
|
|
+ }
|
|
|
+ }else {
|
|
|
+ newList = false;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ newList = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(newList){
|
|
|
+ minpreendTime = processes1.getPreviousProcesses().get(0).getEndTime();
|
|
|
+ List<ProductionProcesses> thps = new ArrayList<>();
|
|
|
+ thps.add(processes1);
|
|
|
+ chunks.add(thps);
|
|
|
+ }else{
|
|
|
+ chunks.get(chunks.size() - 1).add(processes1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 合并退火作业
|
|
|
+ for(int j = 0;j < chunks.size();j++){
|
|
|
+ List<ProductionProcesses> thps = chunks.get(j);
|
|
|
+ for (int i = 0; i < thps.size(); i++) {
|
|
|
+ if(i>0){
|
|
|
+ // 设置待合并退火的主ID
|
|
|
+ thps.get(i).setMergeThMainId(thps.get(0).getId());
|
|
|
+ // 设置合并作业的根节点
|
|
|
+ thps.get(0).getMergeRooprocess().add(thps.get(i).getRooprocess());
|
|
|
+ otherThproces.add(thps.get(i));
|
|
|
+ // 退火前一道作业设置下一作业ID
|
|
|
+ if(thps.get(i).getPreviousProcessesIds() == null){
|
|
|
+ int a12 = 111;
|
|
|
+ }
|
|
|
+ if(thps.get(i).getPreviousProcessesIds() != null && thps.get(i).getPreviousProcessesIds().size()>0){
|
|
|
+ ProductionProcesses prepro = allProMap.get(thps.get(i).getPreviousProcessesIds().get(0));
|
|
|
+ // 历史关联关系备份
|
|
|
+ List<String> oldNextProcessesIds = new ArrayList<>();
|
|
|
+ oldNextProcessesIds.addAll(prepro.getNextProcessesIds());
|
|
|
+// prepro.setOldNextProcessesIds(oldNextProcessesIds);
|
|
|
+ // 合并后关联关系重置
|
|
|
+ if(!prepro.getNextProcessesIds().contains(thps.get(0).getId())){
|
|
|
+ int i1 = prepro.getNextProcessesIds().indexOf(thps.get(i).getId());
|
|
|
+ prepro.getNextProcessesIds().set(i1,thps.get(0).getId());
|
|
|
+ }
|
|
|
+ List<String> list = new ArrayList<>();
|
|
|
+ Set<String> set = new LinkedHashSet<>();
|
|
|
+ for (String nextProcessesId : prepro.getNextProcessesIds()) {
|
|
|
+ set.add(nextProcessesId);
|
|
|
+ }
|
|
|
+ list.addAll(set);
|
|
|
+ prepro.setNextProcessesIds(list);
|
|
|
+ List<ProductionProcesses> nextpros = new ArrayList<>();
|
|
|
+ for (String nextProcessesId : prepro.getNextProcessesIds()) {
|
|
|
+ nextpros.add(allProMap.get(nextProcessesId));
|
|
|
+ }
|
|
|
+ prepro.setNextProcesses(nextpros);
|
|
|
+ // 当前合并退火作业设置前一道作业
|
|
|
+ if(!thps.get(0).getPreviousProcessesIds().contains(prepro.getId())){
|
|
|
+ thps.get(0).getPreviousProcessesIds().add(prepro.getId());
|
|
|
+ }
|
|
|
+ List<ProductionProcesses> previousProces = new ArrayList<>();
|
|
|
+ for (String pid : thps.get(0).getPreviousProcessesIds()) {
|
|
|
+ previousProces.add(allProMap.get(pid));
|
|
|
+ }
|
|
|
+ thps.get(0).setPreviousProcesses(previousProces);
|
|
|
+ }
|
|
|
+ // 退火后一道作业设置上一道作业ID
|
|
|
+ if(thps.get(i).getNextProcessesIds() != null && thps.get(i).getNextProcessesIds().size()>0){
|
|
|
+ for (String nextProcessesId : thps.get(i).getNextProcessesIds()) {
|
|
|
+ ProductionProcesses nextpro = allProMap.get(nextProcessesId);
|
|
|
+ // 历史关联关系备份
|
|
|
+ List<String> oldpreids = new ArrayList<>();
|
|
|
+ if(nextpro == null){
|
|
|
+ int aaa = 11;
|
|
|
+ }
|
|
|
+ oldpreids.addAll(nextpro.getPreviousProcessesIds());
|
|
|
+// nextpro.setOldPreviousProcessesIds(oldpreids);
|
|
|
+ // 合并后关联关系重置
|
|
|
+ List<String> preids = new ArrayList<>();
|
|
|
+ preids.add(thps.get(0).getId());
|
|
|
+ nextpro.setPreviousProcessesIds(preids);
|
|
|
+
|
|
|
+ List<ProductionProcesses> nextprepros = new ArrayList<>();
|
|
|
+ for (String pid : nextpro.getPreviousProcessesIds()) {
|
|
|
+ nextprepros.add(allProMap.get(pid));
|
|
|
+ }
|
|
|
+ nextpro.setPreviousProcesses(nextprepros);
|
|
|
+ }
|
|
|
+ // 设置合并退火作业下一道工序
|
|
|
+ thps.get(0).getNextProcessesIds().addAll(thps.get(i).getNextProcessesIds());
|
|
|
+ List<ProductionProcesses> thnexts = new ArrayList<>();
|
|
|
+ for (String pid : thps.get(0).getNextProcessesIds()) {
|
|
|
+ thnexts.add(allProMap.get(pid));
|
|
|
+ }
|
|
|
+ thps.get(0).setNextProcesses(thnexts);
|
|
|
+ }
|
|
|
+ // 小卷退火卷数合并
|
|
|
+ if(thps.get(i).getProcessType().equals("小卷成退")){
|
|
|
+ thps.get(0).setMinThPcNum(thps.get(0).getMinThPcNum()+thps.get(i).getMinThPcNum());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 取第一个作业作为合并作业
|
|
|
+ ProductionProcesses mergePro = thps.get(0);
|
|
|
+ mergePro.setTotalVolumeWidth(mergePro.getVolumeWidth().multiply(new BigDecimal(thps.size())));
|
|
|
+ mergePro.setTotalSinglerollweight(mergePro.getTotalSinglerollweight().multiply(new BigDecimal(thps.size())));
|
|
|
+ mergePro.setOpeProducePcNum(thps.size());
|
|
|
+ // 设置是否满炉
|
|
|
+ if(thps.size() == a){
|
|
|
+ mergePro.setIffullth("y");
|
|
|
+ }
|
|
|
+ mergeprocesses.add(mergePro);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ mergeprocesses.addAll(v);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return mergeprocesses;
|
|
|
+ }
|
|
|
+
|
|
|
}
|