Просмотр исходного кода

退火超出装炉量bug修改

fangpy 4 месяцев назад
Родитель
Сommit
40c10ba198

+ 20 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/DdApsService.java

@@ -0,0 +1,20 @@
+package com.rongwei.rwapsserver.aps.service;
+
+import com.rongwei.rwapsserver.aps.domain.ApsSolution;
+import com.rongwei.rwapsserver.aps.domain.ProductionProcesses;
+import com.rongwei.rwapsserver.aps.vo.ProductionScheduleVo;
+
+import java.util.List;
+import java.util.Map;
+
+public interface DdApsService {
+
+    List<ProductionProcesses> thOtherAllMerge(List<ProductionProcesses> mergeprocesses, List<ProductionProcesses> otherThproces);
+    
+    List<ProductionProcesses> thOtherMerge(List<ProductionProcesses> mergeprocesses, List<ProductionProcesses> otherThproces);
+
+    List<ProductionProcesses> seriesLzBzMerge(List<ProductionProcesses> mergeprocesses, List<ProductionProcesses> otherSerProces);
+
+    void tuihuoApsSch(ApsSolution apsSolution, List<ProductionProcesses> otherThproces, List<ProductionProcesses> otherNotZzFirstProces
+            , ProductionScheduleVo productionScheduleVo, Map<String,List<String>> ordergrous);
+}

+ 985 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/service/impl/DdApsServiceImpl.java

@@ -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;
+    }
+
+}