|
@@ -0,0 +1,985 @@
|
|
|
+package com.rongwei.rwapsserver.aps.service.impl;
|
|
|
+
|
|
|
+import cn.hutool.core.collection.CollUtil;
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.rongwei.rwapsserver.aps.domain.ApsSolution;
|
|
|
+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.vo.ProductionScheduleVo;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.optaplanner.core.api.score.ScoreExplanation;
|
|
|
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
|
|
|
+import org.optaplanner.core.api.solver.SolutionManager;
|
|
|
+import org.optaplanner.core.api.solver.Solver;
|
|
|
+import org.optaplanner.core.api.solver.SolverFactory;
|
|
|
+import org.optaplanner.core.config.solver.EnvironmentMode;
|
|
|
+import org.optaplanner.core.config.solver.SolverConfig;
|
|
|
+import org.optaplanner.core.config.solver.termination.TerminationConfig;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+@Slf4j
|
|
|
+@Service
|
|
|
+public class DdApsServiceImpl implements DdApsService {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 冷轧同一道工序分组提前合并
|
|
|
+ * @param mergeprocesses
|
|
|
+ * @param otherThproces
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<ProductionProcesses> thOtherAllMerge(List<ProductionProcesses> mergeprocesses, List<ProductionProcesses> otherThproces){
|
|
|
+ List<ProductionProcesses> lzmergeprocesses = new ArrayList<>();
|
|
|
+ // 根据订单分组
|
|
|
+ Map<String, List<ProductionProcesses>> orderProcess = mergeprocesses.stream().collect(Collectors.groupingBy(ProductionProcesses::getOrderId));
|
|
|
+ orderProcess.forEach((k,processes)->{
|
|
|
+ // 所有单卷作业集合
|
|
|
+ Map<String,ProductionProcesses> allProMap = new HashMap<>();
|
|
|
+ // 按作业分组
|
|
|
+ Map<String,List<ProductionProcesses>> bsProceses = new HashMap<>();
|
|
|
+ // 根节点集合
|
|
|
+ List<ProductionProcesses> rootProces = new ArrayList<>();
|
|
|
+ // 缓存数据处理
|
|
|
+ for (ProductionProcesses mergeprocess : processes) {
|
|
|
+ // 根据作业ID缓存数据
|
|
|
+ if(bsProceses.containsKey(mergeprocess.getUniqueBsProcessesId())){
|
|
|
+ bsProceses.get(mergeprocess.getUniqueBsProcessesId()).add(mergeprocess);
|
|
|
+ }else{
|
|
|
+ List<ProductionProcesses> bsProcese = new ArrayList<>();
|
|
|
+ bsProcese.add(mergeprocess);
|
|
|
+ bsProceses.put(mergeprocess.getUniqueBsProcessesId(),bsProcese);
|
|
|
+ }
|
|
|
+ // 根据作业明细ID缓存数据
|
|
|
+ allProMap.put(mergeprocess.getId(),mergeprocess);
|
|
|
+ // 根节点缓存
|
|
|
+ if(mergeprocess.getPreviousProcesses() == null || mergeprocess.getPreviousProcesses().size() == 0){
|
|
|
+ rootProces.add(mergeprocess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(rootProces != null && rootProces.size()>0){
|
|
|
+ thOtherAllMergeDg(rootProces,lzmergeprocesses,otherThproces,allProMap);
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ return lzmergeprocesses;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void thOtherAllMergeDg(List<ProductionProcesses> rootPreProces,List<ProductionProcesses> lzmergeprocesses,List<ProductionProcesses> otherThproces,Map<String,ProductionProcesses> allProMap){
|
|
|
+ if(rootPreProces != null && rootPreProces.size()>0){
|
|
|
+ if(rootPreProces.get(0).getUniqueBsProcessesId().equals("e802cc0ae1154bd0b977b74a07c97b3e")){
|
|
|
+ int m = 1;
|
|
|
+ }
|
|
|
+ Map<String, List<ProductionProcesses>> orderProcess = rootPreProces.stream().collect(Collectors.groupingBy(ProductionProcesses::getUniqueBsProcessesId));
|
|
|
+ for (String bsid:orderProcess.keySet()){
|
|
|
+ List<ProductionProcesses> rootProces = orderProcess.get(bsid);
|
|
|
+ if(rootProces != null && rootProces.size()>0){
|
|
|
+ if((rootProces.get(0).getMaxWaitTime() != null && rootProces.get(0).getMaxWaitTime()>0)
|
|
|
+ || "成退,中退,小卷成退".contains(rootProces.get(0).getProcessType())){
|
|
|
+ lzmergeprocesses.addAll(rootProces);
|
|
|
+ }else{
|
|
|
+ // 未锁定的作业
|
|
|
+ List<ProductionProcesses> notLocks = rootProces.stream().filter(v -> !v.getIfLock()).collect(Collectors.toList());
|
|
|
+ // 锁定的作业
|
|
|
+ List<ProductionProcesses> locks = rootProces.stream().filter(v -> v.getIfLock()).collect(Collectors.toList());
|
|
|
+ // 锁定的不做任何处理
|
|
|
+ if(locks != null && locks.size()>0){
|
|
|
+ lzmergeprocesses.addAll(locks);
|
|
|
+ }
|
|
|
+ // 没锁定的合并一个作业
|
|
|
+ if(notLocks != null && notLocks.size()>0){
|
|
|
+ if(notLocks.size()>1){
|
|
|
+ boolean ifnull = false;
|
|
|
+ for (ProductionProcesses notLock : notLocks) {
|
|
|
+ if(notLock.getRooprocess() == null || notLock.getRooprocess().getStartTime() == null){
|
|
|
+ ifnull = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 根据根节点开始时间排序
|
|
|
+ if(!ifnull){
|
|
|
+ Collections.sort(notLocks,Comparator.comparing(pro -> pro.getRooprocess().getStartTime()));
|
|
|
+ }
|
|
|
+ if(notLocks.size()>0){
|
|
|
+ // 合并作业
|
|
|
+ List<ProductionProcesses> mergePres = new ArrayList<>();
|
|
|
+ mergePres.addAll(notLocks);
|
|
|
+ Map<String,ProductionProcesses> mergeProNexts = new HashMap<>();
|
|
|
+ ProductionProcesses mergePro = mergePres.get(0);
|
|
|
+ List<String> mergeProOrders = new ArrayList<>();
|
|
|
+ mergeProOrders.add(mergePro.getId());
|
|
|
+ mergePro.setMergeProOrders(mergeProOrders);
|
|
|
+ for (int i = 0; i < mergePres.size(); i++) {
|
|
|
+ if(i>0){
|
|
|
+ // 设置待合并退火的主ID
|
|
|
+ mergePres.get(i).setMergeThMainId(mergePres.get(0).getId());
|
|
|
+ mergePro.getMergeProOrders().add(mergePres.get(i).getId());
|
|
|
+ otherThproces.add(mergePres.get(i));
|
|
|
+ if(mergePres.get(i).getNextProcesses() != null && mergePres.get(i).getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : mergePres.get(i).getNextProcesses()) {
|
|
|
+ mergeProNexts.put(nextProcess.getId(),nextProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(mergePro.getPreviousProcesses() != null && mergePro.getPreviousProcesses().size()>0){
|
|
|
+ // 合并作业的上一道工序
|
|
|
+ CollUtil.addAllIfNotContains(mergePro.getPreviousProcesses(),mergePres.get(i).getPreviousProcesses());
|
|
|
+ CollUtil.addAllIfNotContains(mergePro.getPreviousProcessesIds(),mergePres.get(i).getPreviousProcessesIds());
|
|
|
+ // 合并作业上一道工序的下一道工序设置为当前合并作业
|
|
|
+ for (ProductionProcesses previousProcess : mergePres.get(i).getPreviousProcesses()) {
|
|
|
+ String preiId = mergePres.get(i).getId();
|
|
|
+ List<ProductionProcesses> merNextprocesses = previousProcess.getNextProcesses().stream().filter(v -> !preiId.equals(v.getId())).collect(Collectors.toList());
|
|
|
+ if(merNextprocesses == null){
|
|
|
+ merNextprocesses = new ArrayList<>();
|
|
|
+ }
|
|
|
+ List<ProductionProcesses> merMainPros = merNextprocesses.stream().filter(v -> mergePro.getId().equals(v.getId())).collect(Collectors.toList());
|
|
|
+ if(merMainPros == null || merMainPros.size() == 0){
|
|
|
+ merNextprocesses.add(mergePro);
|
|
|
+ }
|
|
|
+ List<String> merNextprocessesIds = merNextprocesses.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
|
|
|
+ previousProcess.setNextProcesses(merNextprocesses);
|
|
|
+ previousProcess.setNextProcessesIds(merNextprocessesIds);
|
|
|
+
|
|
|
+ /*previousProcess.getNextProcesses().clear();
|
|
|
+ previousProcess.getNextProcesses().add(mergePro);
|
|
|
+ previousProcess.getNextProcessesIds().clear();
|
|
|
+ previousProcess.getNextProcessesIds().add(mergePro.getId());*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 取第一个作业作为合并作业
|
|
|
+ mergePro.setProduceTime(mergePro.getProduceTime()*mergePres.size());
|
|
|
+ mergePro.setOpeProducePcNum(mergePres.size());
|
|
|
+ // 合并作业的下一道工序
|
|
|
+ if(mergeProNexts.size()>0){
|
|
|
+ for (String proid:mergeProNexts.keySet()){
|
|
|
+ if(mergePro.getNextProcessesIds() == null){
|
|
|
+ int a = 1;
|
|
|
+ }
|
|
|
+ if(!mergePro.getNextProcessesIds().contains(proid)){
|
|
|
+ ProductionProcesses propro = mergeProNexts.get(proid);
|
|
|
+ mergePro.getNextProcessesIds().add(proid);
|
|
|
+ mergePro.getNextProcesses().add(propro);
|
|
|
+ // 合并作业下道工序的上道作业设置
|
|
|
+ List<ProductionProcesses> nextPrePros = new ArrayList<>();
|
|
|
+ nextPrePros.add(mergePro);
|
|
|
+ List<String> nextPreProIds = new ArrayList<>();
|
|
|
+ nextPreProIds.add(mergePro.getId());
|
|
|
+ propro.setPreviousProcessesIds(nextPreProIds);
|
|
|
+ propro.setPreviousProcesses(nextPrePros);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lzmergeprocesses.add(mergePro);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ lzmergeprocesses.addAll(notLocks);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 递归合并
|
|
|
+ List<ProductionProcesses> nextrootProces = new ArrayList<>();
|
|
|
+ for (ProductionProcesses rootProce : rootProces) {
|
|
|
+ if(rootProce.getNextProcesses() != null && rootProce.getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : rootProce.getNextProcesses()) {
|
|
|
+ List<ProductionProcesses> hasPro = nextrootProces.stream().filter(v -> v.getId().equals(nextProcess.getId())).collect(Collectors.toList());
|
|
|
+ if(hasPro == null || hasPro.size() == 0){
|
|
|
+// nextrootProces.addAll(rootProce.getNextProcesses());
|
|
|
+ nextrootProces.add(nextProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ thOtherAllMergeDg(nextrootProces,lzmergeprocesses,otherThproces,allProMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 冷轧同一道工序分组提前合并
|
|
|
+ * @param mergeprocesses
|
|
|
+ * @param otherThproces
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<ProductionProcesses> thOtherMerge(List<ProductionProcesses> mergeprocesses, List<ProductionProcesses> otherThproces){
|
|
|
+ List<ProductionProcesses> lzmergeprocesses = new ArrayList<>();
|
|
|
+ // 根据订单分组
|
|
|
+ Map<String, List<ProductionProcesses>> orderProcess = mergeprocesses.stream().collect(Collectors.groupingBy(ProductionProcesses::getOrderId));
|
|
|
+ orderProcess.forEach((k,processes)->{
|
|
|
+ // 退火工序过滤
|
|
|
+ List<ProductionProcesses> thpros = new ArrayList<>();
|
|
|
+ // 所有单卷作业集合
|
|
|
+ Map<String,ProductionProcesses> allProMap = new HashMap<>();
|
|
|
+ // 按作业分组
|
|
|
+ Map<String,List<ProductionProcesses>> bsProceses = new HashMap<>();
|
|
|
+ // 合并后的作业集合
|
|
|
+ List<ProductionProcesses> othermergeprocesses = new ArrayList<>();
|
|
|
+ // 未合并的作业集合
|
|
|
+ List<ProductionProcesses> notMergeProces = new ArrayList<>();
|
|
|
+ // 根节点集合
|
|
|
+ List<ProductionProcesses> rootProces = new ArrayList<>();
|
|
|
+ // 已分组合并作业
|
|
|
+ List<String> hasMerge = new ArrayList<>();
|
|
|
+ for (ProductionProcesses mergeprocess : processes) {
|
|
|
+ if(mergeprocess.getProcessType().equals("成退") || mergeprocess.getProcessType().equals("中退") || mergeprocess.getProcessType().equals("小卷成退")){
|
|
|
+ thpros.add(mergeprocess);
|
|
|
+ othermergeprocesses.add(mergeprocess);
|
|
|
+ }else{
|
|
|
+ if(mergeprocess.getIfLock()){
|
|
|
+ othermergeprocesses.add(mergeprocess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 根据作业ID缓存数据
|
|
|
+ if(bsProceses.containsKey(mergeprocess.getUniqueBsProcessesId())){
|
|
|
+ bsProceses.get(mergeprocess.getUniqueBsProcessesId()).add(mergeprocess);
|
|
|
+ }else{
|
|
|
+ List<ProductionProcesses> bsProcese = new ArrayList<>();
|
|
|
+ bsProcese.add(mergeprocess);
|
|
|
+ bsProceses.put(mergeprocess.getUniqueBsProcessesId(),bsProcese);
|
|
|
+ }
|
|
|
+ // 根据作业明细ID缓存数据
|
|
|
+ allProMap.put(mergeprocess.getId(),mergeprocess);
|
|
|
+ // 根节点缓存
|
|
|
+ if(mergeprocess.getPreviousProcesses() == null || mergeprocess.getPreviousProcesses().size() == 0){
|
|
|
+ rootProces.add(mergeprocess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 退火后道未锁定工序合并
|
|
|
+ if(thpros != null && thpros.size()>0){
|
|
|
+ for (ProductionProcesses thpro : thpros) {
|
|
|
+ thNextHb(thpro,notMergeProces,othermergeprocesses,bsProceses,hasMerge,allProMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 剩下的数据从根据节点开始如果上道工序有锁定的按照锁定合并、没有锁定的按照4卷合并
|
|
|
+ if(rootProces != null && rootProces.size()>0){
|
|
|
+ // 首先递归到存在未合并的作业
|
|
|
+ List<ProductionProcesses> notLockProces = new ArrayList<>();
|
|
|
+ hasNotLockHb(rootProces,notLockProces,bsProceses);
|
|
|
+ if(notLockProces != null && notLockProces.size()>0){
|
|
|
+ // 作业合并
|
|
|
+ notThHb(notLockProces,notMergeProces,othermergeprocesses,bsProceses,hasMerge,allProMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 最终数据汇总
|
|
|
+ otherThproces.addAll(notMergeProces);
|
|
|
+ lzmergeprocesses.addAll(othermergeprocesses);
|
|
|
+ });
|
|
|
+ return lzmergeprocesses;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void notThHb(List<ProductionProcesses> notLockProces,List<ProductionProcesses> notMergeProces,List<ProductionProcesses> mergeprocesses
|
|
|
+ ,Map<String,List<ProductionProcesses>> bsProceses,List<String> hasMerge,Map<String,ProductionProcesses> allProMap){
|
|
|
+ // 未锁定的作业
|
|
|
+ List<ProductionProcesses> notLocks = notLockProces.stream().filter(v -> !v.getIfLock()).collect(Collectors.toList());
|
|
|
+ // 锁定的作业
|
|
|
+ List<ProductionProcesses> locks = notLockProces.stream().filter(v -> v.getIfLock()).collect(Collectors.toList());
|
|
|
+ // 锁定的作业合并
|
|
|
+ if(locks != null && locks.size()>0){
|
|
|
+ Map<String, List<ProductionProcesses>> equass = locks.stream().collect(Collectors.groupingBy(ProductionProcesses::getEquipmentId));
|
|
|
+ equass.forEach((k,vps)->{
|
|
|
+ // 按照开始时间排序
|
|
|
+ Collections.sort(vps,Comparator.comparing(pro -> pro.getStartTime()));
|
|
|
+ List<List<ProductionProcesses>> lockgroups = new ArrayList<>();
|
|
|
+ for (ProductionProcesses lock : vps) {
|
|
|
+ if(lockgroups.size() == 0){
|
|
|
+ List<ProductionProcesses> pps = new ArrayList<>();
|
|
|
+ pps.add(lock);
|
|
|
+ lockgroups.add(pps);
|
|
|
+ }else{
|
|
|
+ // 前一道锁定工序和后一道锁定工序如果相隔时间小于11分钟则认为是可以合并的
|
|
|
+ if(lockgroups.get(lockgroups.size()-1).get(lockgroups.get(lockgroups.size()-1).size()-1).getEndTime().plusMinutes(11).compareTo(lock.getStartTime())>0){
|
|
|
+ lockgroups.get(lockgroups.size()-1).add(lock);
|
|
|
+ }else{
|
|
|
+ List<ProductionProcesses> pps = new ArrayList<>();
|
|
|
+ pps.add(lock);
|
|
|
+ lockgroups.add(pps);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (List<ProductionProcesses> lockgroup : lockgroups) {
|
|
|
+ lockNextHb(lockgroup,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ }
|
|
|
+ // 未锁定的作业合并
|
|
|
+ if(notLocks != null && notLocks.size()>0 && !hasMerge.contains(notLocks.get(0).getId())){
|
|
|
+ if(notLocks.get(0).getRooprocess() != null && notLocks.get(0).getRooprocess().getStartTime() != null){
|
|
|
+ boolean ifnull = false;
|
|
|
+ for (ProductionProcesses notLock : notLocks) {
|
|
|
+ if(notLock.getRooprocess() == null || notLock.getRooprocess().getStartTime() == null){
|
|
|
+ ifnull = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 根据根节点开始时间排序
|
|
|
+ if(!ifnull){
|
|
|
+ Collections.sort(notLocks,Comparator.comparing(pro -> pro.getRooprocess().getStartTime()));
|
|
|
+ }
|
|
|
+ if(notLocks.size()>0){
|
|
|
+ // 根据承重计算最大几卷
|
|
|
+ int a = 4;
|
|
|
+ List<List<ProductionProcesses>> chunks = new ArrayList<>();
|
|
|
+ int listSize = notLocks.size();
|
|
|
+ for (int i = 0; i < listSize; i += a) {
|
|
|
+ chunks.add(notLocks.subList(i, Math.min(i + a, listSize)));
|
|
|
+ }
|
|
|
+ // 合并作业
|
|
|
+ for (List<ProductionProcesses> mergePres : chunks) {
|
|
|
+ Map<String,ProductionProcesses> mergeProNexts = new HashMap<>();
|
|
|
+ ProductionProcesses mergePro = mergePres.get(0);
|
|
|
+ List<String> mergeProOrders = new ArrayList<>();
|
|
|
+ mergeProOrders.add(mergePro.getId());
|
|
|
+ mergePro.setMergeProOrders(mergeProOrders);
|
|
|
+ for (int i = 0; i < mergePres.size(); i++) {
|
|
|
+ if(i>0){
|
|
|
+ // 设置待合并退火的主ID
|
|
|
+ mergePres.get(i).setMergeThMainId(mergePres.get(0).getId());
|
|
|
+ mergePro.getMergeProOrders().add(mergePres.get(i).getId());
|
|
|
+ notMergeProces.add(mergePres.get(i));
|
|
|
+ if(mergePres.get(i).getNextProcesses() != null && mergePres.get(i).getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : mergePres.get(i).getNextProcesses()) {
|
|
|
+ mergeProNexts.put(nextProcess.getId(),nextProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(mergePro.getPreviousProcesses() != null && mergePro.getPreviousProcesses().size()>0){
|
|
|
+ // 合并作业的上一道工序
|
|
|
+ mergePro.getPreviousProcesses().addAll(mergePres.get(i).getPreviousProcesses());
|
|
|
+ mergePro.getPreviousProcessesIds().addAll(mergePres.get(i).getPreviousProcessesIds());
|
|
|
+ // 合并作业上一道工序的下一道工序设置为当前合并作业
|
|
|
+ for (ProductionProcesses previousProcess : mergePres.get(i).getPreviousProcesses()) {
|
|
|
+ previousProcess.getNextProcesses().clear();
|
|
|
+ previousProcess.getNextProcesses().add(mergePro);
|
|
|
+ previousProcess.getNextProcessesIds().clear();
|
|
|
+ previousProcess.getNextProcessesIds().add(mergePro.getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 取第一个作业作为合并作业
|
|
|
+ mergePro.setProduceTime(mergePro.getProduceTime()*mergePres.size());
|
|
|
+ mergePro.setOpeProducePcNum(mergePres.size());
|
|
|
+ // 合并作业的上一道工序
|
|
|
+ if(mergeProNexts.size()>0){
|
|
|
+ for (String proid:mergeProNexts.keySet()){
|
|
|
+ if(!mergePro.getNextProcessesIds().contains(proid)){
|
|
|
+ ProductionProcesses propro = mergeProNexts.get(proid);
|
|
|
+ mergePro.getNextProcessesIds().add(proid);
|
|
|
+ mergePro.getNextProcesses().add(propro);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ mergeprocesses.add(mergePro);
|
|
|
+
|
|
|
+ // 记录已合并的作业
|
|
|
+ if(!hasMerge.contains(mergePres.get(0).getId())){
|
|
|
+ List<String> proids = mergePres.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
|
|
|
+ hasMerge.addAll(proids);
|
|
|
+ }
|
|
|
+ // 递归按照退火合并
|
|
|
+ nextLockHb(mergePro,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ mergeprocesses.addAll(notLocks);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 锁定作业下道工序递归合并
|
|
|
+ * @param lockgroup
|
|
|
+ * @param notMergeProces
|
|
|
+ * @param mergeprocesses
|
|
|
+ * @param bsProceses
|
|
|
+ * @param hasMerge
|
|
|
+ * @param allProMap
|
|
|
+ */
|
|
|
+ private void lockNextHb(List<ProductionProcesses> lockgroup,List<ProductionProcesses> notMergeProces,List<ProductionProcesses> mergeprocesses
|
|
|
+ ,Map<String,List<ProductionProcesses>> bsProceses,List<String> hasMerge,Map<String,ProductionProcesses> allProMap){
|
|
|
+ if(!lockgroup.get(0).getIfLock() && !hasMerge.contains(lockgroup.get(0).getId())){
|
|
|
+ // 合并
|
|
|
+ List<ProductionProcesses> mergePres = new ArrayList<>();
|
|
|
+ mergePres.addAll(lockgroup);
|
|
|
+ // 按照铸轧时间排序
|
|
|
+ if(mergePres.get(0).getRooprocess() != null && mergePres.get(0).getRooprocess().getStartTime() != null){
|
|
|
+ Collections.sort(mergePres,Comparator.comparing(pro -> pro.getRooprocess().getStartTime()));
|
|
|
+ }
|
|
|
+ ProductionProcesses mergePro = mergePres.get(0);
|
|
|
+ Map<String,ProductionProcesses> mergeProNexts = new HashMap<>();
|
|
|
+ if(mergePres.size()>1){
|
|
|
+ List<String> mergeProOrders = new ArrayList<>();
|
|
|
+ mergeProOrders.add(mergePro.getId());
|
|
|
+ mergePro.setMergeProOrders(mergeProOrders);
|
|
|
+ for (int i = 0; i < mergePres.size(); i++) {
|
|
|
+ if(i>0){
|
|
|
+ // 设置待合并退火的主ID
|
|
|
+ mergePres.get(i).setMergeThMainId(mergePres.get(0).getId());
|
|
|
+ mergePro.getMergeProOrders().add(mergePres.get(i).getId());
|
|
|
+ notMergeProces.add(mergePres.get(i));
|
|
|
+ if(mergePres.get(i).getNextProcesses() != null && mergePres.get(i).getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : mergePres.get(i).getNextProcesses()) {
|
|
|
+ mergeProNexts.put(nextProcess.getId(),nextProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(mergePro.getPreviousProcesses() != null && mergePro.getPreviousProcesses().size()>0){
|
|
|
+ // 合并作业的上一道工序
|
|
|
+ mergePro.getPreviousProcesses().addAll(mergePres.get(i).getPreviousProcesses());
|
|
|
+ mergePro.getPreviousProcessesIds().addAll(mergePres.get(i).getPreviousProcessesIds());
|
|
|
+ // 合并作业上一道工序的下一道工序设置为当前合并作业
|
|
|
+ for (ProductionProcesses previousProcess : mergePres.get(i).getPreviousProcesses()) {
|
|
|
+ previousProcess.getNextProcesses().clear();
|
|
|
+ previousProcess.getNextProcesses().add(mergePro);
|
|
|
+ previousProcess.getNextProcessesIds().clear();
|
|
|
+ previousProcess.getNextProcessesIds().add(mergePro.getId());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 取第一个作业作为合并作业
|
|
|
+ mergePro.setProduceTime(mergePro.getProduceTime()*mergePres.size());
|
|
|
+ mergePro.setOpeProducePcNum(mergePres.size());
|
|
|
+ // 合并作业的上一道工序
|
|
|
+ if(mergeProNexts.size()>0){
|
|
|
+ for (String proid:mergeProNexts.keySet()){
|
|
|
+ if(!mergePro.getNextProcessesIds().contains(proid)){
|
|
|
+ ProductionProcesses propro = mergeProNexts.get(proid);
|
|
|
+ mergePro.getNextProcessesIds().add(proid);
|
|
|
+ mergePro.getNextProcesses().add(propro);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ mergeprocesses.add(mergePro);
|
|
|
+ }else{
|
|
|
+ mergeprocesses.addAll(mergePres);
|
|
|
+ }
|
|
|
+ // 记录已合并的作业
|
|
|
+ if(!hasMerge.contains(mergePres.get(0).getId())){
|
|
|
+ List<String> proids = mergePres.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
|
|
|
+ hasMerge.addAll(proids);
|
|
|
+ }
|
|
|
+ // 递归按照退火合并
|
|
|
+ nextLockHb(mergePro,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
|
|
|
+ }else{
|
|
|
+ List<ProductionProcesses> nexts = new ArrayList<>();
|
|
|
+ for (ProductionProcesses productionProcesses : lockgroup) {
|
|
|
+ if(productionProcesses.getNextProcesses() != null && productionProcesses.getNextProcesses().size()>0){
|
|
|
+ nexts.addAll(productionProcesses.getNextProcesses());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(nexts != null && nexts.size()>0){
|
|
|
+ lockNextHb(nexts,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 递归下一道工序合并
|
|
|
+ * @param thps
|
|
|
+ * @param notMergeProces
|
|
|
+ * @param mergeprocesses
|
|
|
+ * @param bsProceses
|
|
|
+ * @param hasMerge
|
|
|
+ * @param allProMap
|
|
|
+ */
|
|
|
+ private void nextLockHb(ProductionProcesses thps,List<ProductionProcesses> notMergeProces,List<ProductionProcesses> mergeprocesses
|
|
|
+ ,Map<String,List<ProductionProcesses>> bsProceses,List<String> hasMerge,Map<String,ProductionProcesses> allProMap){
|
|
|
+ List<ProductionProcesses> nextProcesses = thps.getNextProcesses();
|
|
|
+ if(nextProcesses != null && nextProcesses.size()>0){
|
|
|
+ List<ProductionProcesses> mergePres = new ArrayList<>();
|
|
|
+ mergePres.addAll(nextProcesses);
|
|
|
+ // 按照铸轧时间排序
|
|
|
+ if(mergePres.get(0).getRooprocess() != null && mergePres.get(0).getRooprocess().getStartTime() != null){
|
|
|
+ Collections.sort(mergePres,Comparator.comparing(pro -> pro.getRooprocess().getStartTime()));
|
|
|
+ }
|
|
|
+ if(!hasMerge.contains(mergePres.get(0).getId())){
|
|
|
+ ProductionProcesses mergePro = mergePres.get(0);
|
|
|
+ Map<String,ProductionProcesses> mergeProNexts = new HashMap<>();
|
|
|
+ if(mergePres.size()>1){
|
|
|
+ List<String> mergeProOrders = new ArrayList<>();
|
|
|
+ mergeProOrders.add(mergePro.getId());
|
|
|
+ mergePro.setMergeProOrders(mergeProOrders);
|
|
|
+ for (int i = 0; i < mergePres.size(); i++) {
|
|
|
+ if(i>0){
|
|
|
+ // 设置待合并退火的主ID
|
|
|
+ mergePres.get(i).setMergeThMainId(mergePres.get(0).getId());
|
|
|
+ mergePro.getMergeProOrders().add(mergePres.get(i).getId());
|
|
|
+ notMergeProces.add(mergePres.get(i));
|
|
|
+ if(mergePres.get(i).getNextProcesses() != null && mergePres.get(i).getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : mergePres.get(i).getNextProcesses()) {
|
|
|
+ mergeProNexts.put(nextProcess.getId(),nextProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 取第一个作业作为合并作业
|
|
|
+ mergePro.setProduceTime(mergePro.getProduceTime()*mergePres.size());
|
|
|
+ mergePro.setOpeProducePcNum(mergePres.size());
|
|
|
+ List<String> nextids = new ArrayList<>();
|
|
|
+ List<String> preids = new ArrayList<>();
|
|
|
+ List<ProductionProcesses> nextpss = new ArrayList<>();
|
|
|
+ List<ProductionProcesses> prepss = new ArrayList<>();
|
|
|
+ nextpss.add(thps);
|
|
|
+ nextids.add(thps.getId());
|
|
|
+ mergePro.setPreviousProcesses(nextpss);
|
|
|
+ mergePro.setPreviousProcessesIds(nextids);
|
|
|
+ preids.add(mergePro.getId());
|
|
|
+ prepss.add(mergePro);
|
|
|
+ thps.setNextProcessesIds(preids);
|
|
|
+ thps.setNextProcesses(prepss);
|
|
|
+ // 合并作业的上一道工序
|
|
|
+ if(mergeProNexts.size()>0){
|
|
|
+ for (String proid:mergeProNexts.keySet()){
|
|
|
+ if(!mergePro.getNextProcessesIds().contains(proid)){
|
|
|
+ ProductionProcesses propro = mergeProNexts.get(proid);
|
|
|
+ mergePro.getNextProcessesIds().add(proid);
|
|
|
+ mergePro.getNextProcesses().add(propro);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ mergeprocesses.add(mergePro);
|
|
|
+ }else{
|
|
|
+ mergeprocesses.addAll(mergePres);
|
|
|
+ }
|
|
|
+ // 记录已合并的作业
|
|
|
+ if(!hasMerge.contains(mergePres.get(0).getId())){
|
|
|
+ List<String> proids = mergePres.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
|
|
|
+ hasMerge.addAll(proids);
|
|
|
+ }
|
|
|
+ // 递归下一道工序合并
|
|
|
+ nextLockHb(mergePro,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 首先递归到存在未合并的作业
|
|
|
+ * @param rootProces
|
|
|
+ * @param notLockProces
|
|
|
+ * @param bsProceses
|
|
|
+ */
|
|
|
+ private void hasNotLockHb(List<ProductionProcesses> rootProces,List<ProductionProcesses> notLockProces,Map<String,List<ProductionProcesses>> bsProceses){
|
|
|
+ // 未锁定的作业
|
|
|
+ List<ProductionProcesses> notLocks = rootProces.stream().filter(v -> !v.getIfLock()).collect(Collectors.toList());
|
|
|
+ // 存在未锁定的作业时从这道工序开始合并下道工序
|
|
|
+ if(notLocks.size()>0){
|
|
|
+ notLockProces.addAll(bsProceses.get(notLocks.get(0).getUniqueBsProcessesId()));
|
|
|
+ }else{
|
|
|
+ List<ProductionProcesses> nextProces = new ArrayList<>();
|
|
|
+ for (ProductionProcesses rootProce : rootProces) {
|
|
|
+ if(rootProce.getNextProcesses() != null && rootProce.getNextProcesses().size()>0){
|
|
|
+ nextProces.addAll(rootProce.getNextProcesses());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(nextProces != null && nextProces.size()>0){
|
|
|
+ hasNotLockHb(nextProces,notLockProces,bsProceses);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 退火后道工序合并处理
|
|
|
+ * @param prePro
|
|
|
+ */
|
|
|
+ private void thNextHb(ProductionProcesses prePro,List<ProductionProcesses> notMergeProces,List<ProductionProcesses> mergeprocesses
|
|
|
+ ,Map<String,List<ProductionProcesses>> bsProceses,List<String> hasMerge,Map<String,ProductionProcesses> allProMap){
|
|
|
+ List<ProductionProcesses> nextProcesses = prePro.getNextProcesses();
|
|
|
+ if(nextProcesses != null && nextProcesses.size()>0){
|
|
|
+ // 没有锁定的就需要合并
|
|
|
+ if(!nextProcesses.get(0).getIfLock()){
|
|
|
+ List<ProductionProcesses> mergePres = new ArrayList<>();
|
|
|
+ mergePres.addAll(nextProcesses);
|
|
|
+ // 按照铸轧时间排序
|
|
|
+ if(mergePres.get(0).getRooprocess() != null && mergePres.get(0).getRooprocess().getStartTime() != null){
|
|
|
+ Collections.sort(mergePres,Comparator.comparing(pro -> pro.getRooprocess().getStartTime()));
|
|
|
+ }
|
|
|
+ ProductionProcesses mergePro = mergePres.get(0);
|
|
|
+ Map<String,ProductionProcesses> mergeProNexts = new HashMap<>();
|
|
|
+ if(mergePres.size()>1){
|
|
|
+ List<String> mergeProOrders = new ArrayList<>();
|
|
|
+ mergeProOrders.add(mergePro.getId());
|
|
|
+ mergePro.setMergeProOrders(mergeProOrders);
|
|
|
+ for (int i = 0; i < mergePres.size(); i++) {
|
|
|
+ if(i>0){
|
|
|
+ // 设置待合并退火的主ID
|
|
|
+ mergePres.get(i).setMergeThMainId(mergePres.get(0).getId());
|
|
|
+ mergePro.getMergeProOrders().add(mergePres.get(i).getId());
|
|
|
+ notMergeProces.add(mergePres.get(i));
|
|
|
+ if(mergePres.get(i).getNextProcesses() != null && mergePres.get(i).getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : mergePres.get(i).getNextProcesses()) {
|
|
|
+ mergeProNexts.put(nextProcess.getId(),nextProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 取第一个作业作为合并作业
|
|
|
+ mergePro.setProduceTime(mergePro.getProduceTime()*mergePres.size());
|
|
|
+ mergePro.setOpeProducePcNum(mergePres.size());
|
|
|
+ List<String> nextids = new ArrayList<>();
|
|
|
+ List<String> preids = new ArrayList<>();
|
|
|
+ List<ProductionProcesses> nextpss = new ArrayList<>();
|
|
|
+ List<ProductionProcesses> prepss = new ArrayList<>();
|
|
|
+ nextpss.add(prePro);
|
|
|
+ nextids.add(prePro.getId());
|
|
|
+ mergePro.setPreviousProcesses(nextpss);
|
|
|
+ mergePro.setPreviousProcessesIds(nextids);
|
|
|
+ preids.add(mergePro.getId());
|
|
|
+ prepss.add(mergePro);
|
|
|
+ prePro.setNextProcessesIds(preids);
|
|
|
+ prePro.setNextProcesses(prepss);
|
|
|
+ // 合并作业的上一道工序
|
|
|
+ if(mergeProNexts.size()>0){
|
|
|
+ for (String proid:mergeProNexts.keySet()){
|
|
|
+ if(!mergePro.getNextProcessesIds().contains(proid)){
|
|
|
+ ProductionProcesses propro = mergeProNexts.get(proid);
|
|
|
+ mergePro.getNextProcessesIds().add(proid);
|
|
|
+ mergePro.getNextProcesses().add(propro);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ mergeprocesses.add(mergePro);
|
|
|
+ }else{
|
|
|
+ mergeprocesses.addAll(mergePres);
|
|
|
+ }
|
|
|
+ // 记录已合并的作业
|
|
|
+ if(!hasMerge.contains(mergePres.get(0).getId())){
|
|
|
+ List<String> proids = mergePres.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
|
|
|
+ hasMerge.addAll(proids);
|
|
|
+ }
|
|
|
+ // 递归按照退火合并
|
|
|
+ thNextHb(mergePro,notMergeProces,mergeprocesses,bsProceses,hasMerge,allProMap);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连续冷轧箔轧作业合并
|
|
|
+ * @param mergeprocesses
|
|
|
+ * @param otherSerProces
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public List<ProductionProcesses> seriesLzBzMerge(List<ProductionProcesses> mergeprocesses,List<ProductionProcesses> otherSerProces){
|
|
|
+ List<ProductionProcesses> retPros = new ArrayList<>();
|
|
|
+ // 根据订单分组
|
|
|
+ Map<String, List<ProductionProcesses>> orderProcess = mergeprocesses.stream().collect(Collectors.groupingBy(ProductionProcesses::getOrderId));
|
|
|
+ orderProcess.forEach((pk,processes)->{
|
|
|
+ // 被合并的作业
|
|
|
+ List<ProductionProcesses> lzbzMergeOthers = new ArrayList<>();
|
|
|
+ try{
|
|
|
+ if(processes != null && processes.size()>0){
|
|
|
+ // 获取所有根节点
|
|
|
+ List<ProductionProcesses> rootPros = new ArrayList<>();
|
|
|
+ for (ProductionProcesses mergeprocess : processes) {
|
|
|
+ if(mergeprocess.getPreviousProcesses() == null || mergeprocess.getPreviousProcesses().size() == 0){
|
|
|
+ rootPros.add(mergeprocess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 获取第一道未锁定工序数据
|
|
|
+ List<ProductionProcesses> firstNotLockPros = new ArrayList<>();
|
|
|
+ getFirstNotLockPros(rootPros,firstNotLockPros);
|
|
|
+ // 根据根节点逐级查询是否可合并的作业
|
|
|
+ if(firstNotLockPros != null && firstNotLockPros.size()>0){
|
|
|
+ Map<String,List<ProductionProcesses>> lzbzMerges = new HashMap<>();
|
|
|
+ // 已合并处理过作业ID
|
|
|
+ List<String> hasMid = new ArrayList<>();
|
|
|
+ for (ProductionProcesses rootPro : firstNotLockPros) {
|
|
|
+ getNotLockLzBzSeries(rootPro,lzbzMerges,hasMid);
|
|
|
+ }
|
|
|
+ if(lzbzMerges != null && lzbzMerges.size()>0){
|
|
|
+ for (String k:lzbzMerges.keySet()){
|
|
|
+ List<ProductionProcesses> serPros = lzbzMerges.get(k);
|
|
|
+ // 连续冷轧或箔轧超过1个,则合并
|
|
|
+ if(serPros != null && serPros.size()>1){
|
|
|
+ ProductionProcesses fMergePro = serPros.get(0);
|
|
|
+ if(fMergePro.getMergeProOrders() == null){
|
|
|
+ fMergePro.setMergeProOrders(new ArrayList<>());
|
|
|
+ fMergePro.getMergeProOrders().add(fMergePro.getId());
|
|
|
+ }
|
|
|
+ // 按顺序依次合并
|
|
|
+ for (int i = 0; i < serPros.size(); i++) {
|
|
|
+ if(i>0){
|
|
|
+ serPros.get(i).setMergeThMainId(fMergePro.getId());
|
|
|
+ if(serPros.get(i).getMergeProOrders() == null){
|
|
|
+ fMergePro.getMergeProOrders().add(serPros.get(i).getId());
|
|
|
+ }else{
|
|
|
+ fMergePro.getMergeProOrders().addAll(serPros.get(i).getMergeProOrders());
|
|
|
+ }
|
|
|
+ fMergePro.setProduceTime(fMergePro.getProduceTime()+serPros.get(i).getProduceTime());
|
|
|
+ // 连续生产合并作业设置下道工序,以及合并后下道作业的上道工序
|
|
|
+ if(i == serPros.size()-1){
|
|
|
+ fMergePro.setNextProcesses(serPros.get(i).getNextProcesses());
|
|
|
+ fMergePro.setNextProcessesIds(serPros.get(i).getNextProcessesIds());
|
|
|
+ if(fMergePro.getNextProcesses() != null && fMergePro.getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : fMergePro.getNextProcesses()) {
|
|
|
+ int iindex = nextProcess.getPreviousProcessesIds().indexOf(serPros.get(i).getId());
|
|
|
+ if(iindex>=0){
|
|
|
+ List<ProductionProcesses> pres = new ArrayList<>();
|
|
|
+ pres.add(fMergePro);
|
|
|
+ for (ProductionProcesses previousProcess : nextProcess.getPreviousProcesses()) {
|
|
|
+ if(!previousProcess.getId().equals(serPros.get(i).getId())){
|
|
|
+ pres.add(previousProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ nextProcess.setPreviousProcesses(pres);
|
|
|
+ List<String> nextPreIds = nextProcess.getPreviousProcesses().stream().map(ProductionProcesses::getId).collect(Collectors.toList());
|
|
|
+ nextProcess.setPreviousProcessesIds(nextPreIds);
|
|
|
+ }
|
|
|
+ /*List<ProductionProcesses> pres = new ArrayList<>();
|
|
|
+ List<String> preids = new ArrayList<>();
|
|
|
+ pres.add(fMergePro);
|
|
|
+ preids.add(fMergePro.getId());
|
|
|
+ nextProcess.setPreviousProcesses(pres);
|
|
|
+ nextProcess.setPreviousProcessesIds(preids);*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ lzbzMergeOthers.add(serPros.get(i));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ log.error("连续冷轧箔轧作业合并",e);
|
|
|
+ }finally {
|
|
|
+ // 除去被合并的作业
|
|
|
+ if(lzbzMergeOthers != null && lzbzMergeOthers.size()>0){
|
|
|
+ List<String> lzbzMergeOtherIds = lzbzMergeOthers.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
|
|
|
+ for (ProductionProcesses mergeprocess : processes) {
|
|
|
+ if(!lzbzMergeOtherIds.contains(mergeprocess.getId())){
|
|
|
+ retPros.add(mergeprocess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ retPros.addAll(processes);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return retPros;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取第一道未锁定工序作业
|
|
|
+ * @param rootPros
|
|
|
+ */
|
|
|
+ private void getFirstNotLockPros(List<ProductionProcesses> rootPros,List<ProductionProcesses> firstNotLockPros){
|
|
|
+ if(rootPros != null && rootPros.size()>0){
|
|
|
+ List<ProductionProcesses> notlocks = rootPros.stream().filter(v -> !v.getIfLock()).collect(Collectors.toList());
|
|
|
+ if(notlocks != null && notlocks.size()>0){
|
|
|
+ firstNotLockPros.addAll(notlocks);
|
|
|
+ }else{
|
|
|
+ List<ProductionProcesses> nextRootPros = new ArrayList<>();
|
|
|
+ for (ProductionProcesses rootPro : rootPros) {
|
|
|
+ if(rootPro.getNextProcesses() != null && rootPro.getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : rootPro.getNextProcesses()) {
|
|
|
+ List<ProductionProcesses> haspros = nextRootPros.stream().filter(v -> v.getId().equals(nextProcess.getId())).collect(Collectors.toList());
|
|
|
+ if(haspros == null || haspros.size() == 0){
|
|
|
+ nextRootPros.add(nextProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(nextRootPros != null &&nextRootPros.size()>0){
|
|
|
+ getFirstNotLockPros(nextRootPros,firstNotLockPros);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void getNotLockLzBzSeries(ProductionProcesses rootPro,Map<String,List<ProductionProcesses>> lzbzMerges,List<String> hasMid){
|
|
|
+ if(rootPro.getIfLock()){
|
|
|
+ if(rootPro.getNextProcesses() != null && rootPro.getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : rootPro.getNextProcesses()) {
|
|
|
+ getNotLockLzBzSeries(nextProcess,lzbzMerges,hasMid);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ getLzBzSeries(rootPro,lzbzMerges,null,null,null,hasMid);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void getLzBzSeries(ProductionProcesses rootPro,Map<String,List<ProductionProcesses>> lzbzMerges
|
|
|
+ ,String seriesKey,String protype,List<String> commonEqus,List<String> hasMid){
|
|
|
+ if(!hasMid.contains(rootPro.getId())){
|
|
|
+ hasMid.add(rootPro.getId());
|
|
|
+ List<ProductionProcesses> nextProcesses = rootPro.getNextProcesses();
|
|
|
+ // 冷轧或箔轧前后辊不一样不能合并
|
|
|
+ boolean issameg = true;
|
|
|
+ if(nextProcesses != null && nextProcesses.size()>0){
|
|
|
+ if(rootPro.getProZg() != null && nextProcesses.get(0).getProZg() != null){
|
|
|
+ if(rootPro.getProZg().equals(nextProcesses.get(0).getProZg())){
|
|
|
+ issameg = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if("否".equals(rootPro.getIssubsection()) && ("冷轧".equals(rootPro.getProcessType()) || "箔轧".equals(rootPro.getProcessType()))
|
|
|
+ && !rootPro.getIfLock() && issameg){
|
|
|
+ // 是否连续冷轧、箔轧
|
|
|
+ boolean hasSeries = false;
|
|
|
+ if(StrUtil.isNotBlank(seriesKey) && StrUtil.isNotBlank(protype) && protype.equals(rootPro.getProcessType())
|
|
|
+ && (rootPro.getMinWaitTime() == null || rootPro.getMinWaitTime()<=0)){
|
|
|
+ if(commonEqus != null && commonEqus.size()>0){
|
|
|
+ List<String> commonEqusNext = new ArrayList<>();
|
|
|
+ for (String optionalEquipment : rootPro.getOptionalEquipments()) {
|
|
|
+ if(commonEqus.contains(optionalEquipment)){
|
|
|
+ commonEqusNext.add(optionalEquipment);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(commonEqusNext != null && commonEqusNext.size()>0){
|
|
|
+ hasSeries = true;
|
|
|
+ lzbzMerges.get(seriesKey).add(rootPro);
|
|
|
+ commonEqus = commonEqusNext;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(nextProcesses != null && nextProcesses.size()>0){
|
|
|
+ // 不能和上一道工序连续,则作为第一道连续工序
|
|
|
+ if(!hasSeries){
|
|
|
+ List<ProductionProcesses> serPros = new ArrayList<>();
|
|
|
+ serPros.add(rootPro);
|
|
|
+ lzbzMerges.put(rootPro.getId(),serPros);
|
|
|
+ // 上下道工序共用的可选设备
|
|
|
+ commonEqus = new ArrayList<>();
|
|
|
+ commonEqus.addAll(rootPro.getOptionalEquipments());
|
|
|
+ }
|
|
|
+ for (ProductionProcesses nextProcess : nextProcesses) {
|
|
|
+ if(hasSeries){
|
|
|
+ getLzBzSeries(nextProcess,lzbzMerges,seriesKey,rootPro.getProcessType(),commonEqus,hasMid);
|
|
|
+ }else{
|
|
|
+ getLzBzSeries(nextProcess,lzbzMerges,rootPro.getId(),rootPro.getProcessType(),commonEqus,hasMid);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(nextProcesses != null && nextProcesses.size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : nextProcesses) {
|
|
|
+ getLzBzSeries(nextProcess,lzbzMerges,null,null,null,hasMid);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 调度排程退火
|
|
|
+ * @param apsSolution
|
|
|
+ * @param otherThproces
|
|
|
+ * @param otherNotZzFirstProces
|
|
|
+ * @param productionScheduleVo
|
|
|
+ * @param ordergrous
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void tuihuoApsSch(ApsSolution apsSolution, List<ProductionProcesses> otherThproces, List<ProductionProcesses> otherNotZzFirstProces, ProductionScheduleVo productionScheduleVo, Map<String, List<String>> ordergrous) {
|
|
|
+ ApsSolution apsSolutionTh = new ApsSolution();
|
|
|
+ // 过滤所有待排程的退火工序
|
|
|
+ List<ProductionProcesses> tuihuos = new ArrayList<>();
|
|
|
+ for (ProductionProcesses process : apsSolution.getProcessesList()) {
|
|
|
+ if((process.getProcessType().equals("成退") || process.getProcessType().equals("中退") || process.getProcessType().equals("小卷成退")) && !process.getIfLock()){
|
|
|
+ tuihuos.add(process);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 按照上道工序排程时间过滤
|
|
|
+ if(tuihuos != null && tuihuos.size()>0){
|
|
|
+ // 过滤出有前端工序结束时间的退火工序
|
|
|
+ List<ProductionProcesses> hasPreTimePps = tuihuos.stream().filter(v -> {
|
|
|
+ boolean hasPreTime = false;
|
|
|
+ if (v.getPreviousProcesses() != null && v.getPreviousProcesses().size() > 0) {
|
|
|
+ for (ProductionProcesses previousProcess : v.getPreviousProcesses()) {
|
|
|
+ if (previousProcess.getEndTime() != null) {
|
|
|
+ hasPreTime = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return hasPreTime;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ // 有上道工序结束时间的退火按照上道工序结束时间从晚到早排序
|
|
|
+ Collections.sort(hasPreTimePps,(v1,v2)->{
|
|
|
+ LocalDateTime presLatestEndTime1 = getPresLatestEndTime(v1);
|
|
|
+ LocalDateTime presLatestEndTime2 = getPresLatestEndTime(v2);
|
|
|
+ return presLatestEndTime2.compareTo(presLatestEndTime1);
|
|
|
+ });
|
|
|
+ // 剩下没有前道工序结束时间的任务
|
|
|
+ List<String> hasPreTimePpIds = hasPreTimePps.stream().map(ProductionProcesses::getId).collect(Collectors.toList());
|
|
|
+ List<ProductionProcesses> notPreTimes = tuihuos.stream().filter(v -> !hasPreTimePpIds.contains(v.getId())).collect(Collectors.toList());
|
|
|
+ if(notPreTimes != null && notPreTimes.size()>0){
|
|
|
+ hasPreTimePps.addAll(notPreTimes);
|
|
|
+ }
|
|
|
+ // 排程数据组装
|
|
|
+ apsSolutionTh.setProcessesList(hasPreTimePps);
|
|
|
+ apsSolutionTh.setEquipmentList(apsSolution.getEquipmentList());
|
|
|
+ // 开始排程
|
|
|
+ String cores = Runtime.getRuntime().availableProcessors() + "";
|
|
|
+ SolverFactory<ApsSolution> solverFactory = SolverFactory.create(new SolverConfig()
|
|
|
+ .withEnvironmentMode(EnvironmentMode.REPRODUCIBLE)
|
|
|
+ .withSolutionClass(ApsSolution.class)
|
|
|
+ .withEntityClasses(ProductionProcesses.class)
|
|
|
+ .withConstraintProviderClass(ApsConstraintProvider.class)
|
|
|
+// .withTerminationSpentLimit(Duration.ofSeconds(runPlanSeconds1))
|
|
|
+ .withTerminationConfig(new TerminationConfig().withUnimprovedSecondsSpentLimit(60L))
|
|
|
+ .withMoveThreadCount(cores)
|
|
|
+ );
|
|
|
+ Solver<ApsSolution> solver = solverFactory.buildSolver();
|
|
|
+ ApsSolution solvedBalance = solver.solve(apsSolutionTh);
|
|
|
+ log.info("**************退火排程评分分析***************");
|
|
|
+ SolutionManager<ApsSolution, HardSoftScore> scoreManager = SolutionManager.create(solverFactory);
|
|
|
+ ScoreExplanation<ApsSolution, HardSoftScore> explain = scoreManager.explain(solvedBalance);
|
|
|
+ log.info(explain.toString());
|
|
|
+ log.info("**************退火排程评分分析***************");
|
|
|
+ ApsUtils apsUtils = new ApsUtils();
|
|
|
+ apsUtils.softExplain(explain,solvedBalance.getProcessesList());
|
|
|
+ // 排程结束数据锁定
|
|
|
+ for (ProductionProcesses productionProcesses : solvedBalance.getProcessesList()) {
|
|
|
+ for (ProductionProcesses processes : apsSolution.getProcessesList()) {
|
|
|
+ if(processes.getId().equals(productionProcesses.getId())){
|
|
|
+ processes.setStartTime(productionProcesses.getStartTime());
|
|
|
+ processes.setEndTime(productionProcesses.getEndTime());
|
|
|
+ processes.setDelay(productionProcesses.getDelay());
|
|
|
+ processes.setEquipment(productionProcesses.getEquipment());
|
|
|
+ processes.setEquipmentId(productionProcesses.getEquipmentId());
|
|
|
+ processes.setIfLock(true);
|
|
|
+ processes.setHasConflict(productionProcesses.getHasConflict());
|
|
|
+ processes.setConflictDes(productionProcesses.getConflictDes());
|
|
|
+ processes.setSoftconflictdes(productionProcesses.getSoftconflictdes());
|
|
|
+ processes.setConflictRoptions(productionProcesses.getConflictRoptions());
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前任务的前道任务最晚结束时间
|
|
|
+ * @param pps
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private LocalDateTime getPresLatestEndTime(ProductionProcesses pps){
|
|
|
+ List<ProductionProcesses> previousProcesses = pps.getPreviousProcesses();
|
|
|
+ LocalDateTime endTime = null;
|
|
|
+ if(previousProcesses != null && previousProcesses.size()>0){
|
|
|
+ for (ProductionProcesses previousProcess : previousProcesses) {
|
|
|
+ if(endTime == null){
|
|
|
+ endTime = previousProcess.getEndTime();
|
|
|
+ }else{
|
|
|
+ if(previousProcess.getEndTime().compareTo(endTime)>0){
|
|
|
+ endTime = previousProcess.getEndTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return endTime;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|