|
@@ -0,0 +1,862 @@
|
|
|
+package com.rongwei.rwapsserver.aps.taskassigning.tado;
|
|
|
+
|
|
|
+import cn.hutool.core.util.StrUtil;
|
|
|
+import com.rongwei.rwapsserver.aps.domain.*;
|
|
|
+import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
|
|
|
+import org.optaplanner.core.api.score.stream.*;
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.time.ZoneId;
|
|
|
+import java.time.format.DateTimeFormatter;
|
|
|
+import java.time.temporal.ChronoUnit;
|
|
|
+import java.util.*;
|
|
|
+import java.util.stream.Collectors;
|
|
|
+
|
|
|
+public class ApsConstraintListProvider implements ConstraintProvider {
|
|
|
+
|
|
|
+ private ZoneId zoneId = ZoneId.systemDefault();
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
|
|
|
+
|
|
|
+ return new Constraint[]{
|
|
|
+ theEquipmentCanOnlyProcessOneProcessAtTheSameTime(constraintFactory),
|
|
|
+ optionalEquipment(constraintFactory),
|
|
|
+ // HARD
|
|
|
+ hasOnePreGbAfterNowNew(constraintFactory),
|
|
|
+// nextLockProNew(constraintFactory),
|
|
|
+// eqTimeCross(constraintFactory),
|
|
|
+// seriesProduceTimeWait(constraintFactory),
|
|
|
+// seriesProduceWashTimeWait(constraintFactory),
|
|
|
+// equipmentRunTime(constraintFactory),
|
|
|
+// eqTimeCrossTuihuo(constraintFactory),
|
|
|
+// eqTimeCrossTuihuoType(constraintFactory),
|
|
|
+// eqTimeCrossMinTuihuo(constraintFactory),
|
|
|
+// maxStartTime(constraintFactory),
|
|
|
+ // MEDIUM
|
|
|
+ deliveryDate(constraintFactory),
|
|
|
+// expecteddays(constraintFactory),
|
|
|
+ seriesProduce(constraintFactory),
|
|
|
+// seriesProduceWashingFurnace(constraintFactory),
|
|
|
+// mergeTuihuo(constraintFactory),
|
|
|
+// tuihuoSp(constraintFactory),
|
|
|
+// sameEquipment(constraintFactory),
|
|
|
+// seriesZzLb(constraintFactory),
|
|
|
+//
|
|
|
+// preNextProcessSameWorkShop(constraintFactory),
|
|
|
+ // SOFT
|
|
|
+// processNear(constraintFactory),
|
|
|
+// lzbzSp(constraintFactory),
|
|
|
+// eqTimeCrossMinTuihuoSoft(constraintFactory),
|
|
|
+// preNextProcessSameEq(constraintFactory),
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备生产的任务都在可选设备范围内
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint optionalEquipment(ConstraintFactory constraintFactory) {
|
|
|
+ return constraintFactory.forEach(EquipmentTa.class)
|
|
|
+ .filter((equipment) -> {
|
|
|
+ return true;
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_HARD,(equipment) -> {
|
|
|
+ int b = 0;
|
|
|
+ List<ProductionProcessesTa> tasks = equipment.getTasks();
|
|
|
+ if(tasks != null && tasks.size()>0){
|
|
|
+ for (ProductionProcessesTa task : tasks) {
|
|
|
+ if(!task.getOptionalEquipments().contains(equipment.getId())){
|
|
|
+ b++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return b*100;
|
|
|
+ })
|
|
|
+ .asConstraint("optionalEquipment");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每个任务都要分配资源
|
|
|
+ * @param factory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public Constraint theEquipmentCanOnlyProcessOneProcessAtTheSameTime(ConstraintFactory factory) {
|
|
|
+ return factory.forEach(ProductionProcessesTa.class)
|
|
|
+ .filter(job -> job.getEquipment() == null || job.getStartTime() == null || job.getEndTime() == null)
|
|
|
+ .penalize(HardMediumSoftScore.ONE_HARD,(productionProcesses) -> 100)
|
|
|
+ .asConstraint("theEquipmentCanOnlyProcessOneProcessAtTheSameTime");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 单卷模式下前后道工序时间约束(新的等待时间调整)
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint hasOnePreGbAfterNowNew(ConstraintFactory constraintFactory) {
|
|
|
+ return constraintFactory.forEach(ProductionProcessesTa.class)
|
|
|
+ .filter(productionProcesses -> {
|
|
|
+ boolean bln = false;
|
|
|
+ if(productionProcesses.getEquipment() != null && productionProcesses.getPreviousProcesses() != null && productionProcesses.getPreviousProcesses().size()>0){
|
|
|
+ // 此种情况简化为前道工序只有一个
|
|
|
+ for (ProductionProcessesTa previousProcess : productionProcesses.getPreviousProcesses()) {
|
|
|
+ ProductionProcessesTa preProcess = previousProcess;
|
|
|
+ // 流转时间(最小等待时间)
|
|
|
+ Integer lzTimes = 0;
|
|
|
+ if(preProcess.getEquipment() != null){
|
|
|
+ if(preProcess.getEquipment().getWorkshopid() != null && preProcess.getEquipment().getWorkshopid().equals(productionProcesses.getEquipment().getWorkshopid())){
|
|
|
+ lzTimes = productionProcesses.getApsOverallConfig().getRoamTime().get("WORKSHOP_IN");
|
|
|
+ }else{
|
|
|
+ lzTimes = productionProcesses.getApsOverallConfig().getRoamTime().get("WORKSHOP_CROSS");
|
|
|
+ }
|
|
|
+ // 最小等待时间对比流转时间
|
|
|
+ if(productionProcesses.getMinWaitTime() != null && lzTimes<productionProcesses.getMinWaitTime()){
|
|
|
+ lzTimes = productionProcesses.getMinWaitTime();
|
|
|
+ }
|
|
|
+ // 最大等待时间
|
|
|
+ Integer maxWaitTime = productionProcesses.getMaxWaitTime();
|
|
|
+ if(productionProcesses.getStartTime().compareTo(preProcess.getEndTime().plusMinutes(lzTimes))<0){
|
|
|
+ bln = true;
|
|
|
+ }
|
|
|
+ if(maxWaitTime != null && maxWaitTime>0){
|
|
|
+ if(productionProcesses.getStartTime().compareTo(preProcess.getEndTime().plusMinutes(maxWaitTime))>0){
|
|
|
+ bln = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return bln;
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_HARD,(productionProcesses) -> 40)
|
|
|
+ .asConstraint("hasOnePreGbAfterNow");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 递归计算是否比所有下道工序开始时间晚
|
|
|
+ * @param productionProcesses
|
|
|
+ * @param nextStartTimes
|
|
|
+ * @param totalMinWaitTime
|
|
|
+ */
|
|
|
+ private void getAllNextProTime(ProductionProcessesTa productionProcesses, List<LocalDateTime> nextStartTimes, Integer totalMinWaitTime){
|
|
|
+ List<ProductionProcessesTa> nextProcesses = productionProcesses.getNextProcesses();
|
|
|
+ if(nextProcesses != null && nextProcesses.size()>0){
|
|
|
+ Integer nowTotalMinWaitTime = totalMinWaitTime;
|
|
|
+ for (ProductionProcessesTa nextProcess : nextProcesses) {
|
|
|
+ if(nextProcess.getStartTime() != null){
|
|
|
+ LocalDateTime startTime = nextProcess.getStartTime();
|
|
|
+ if(nextProcess.getMinWaitTime() != null && nextProcess.getMinWaitTime()>0){
|
|
|
+ nowTotalMinWaitTime = totalMinWaitTime + nextProcess.getMinWaitTime();
|
|
|
+ startTime = startTime.minusMinutes(nowTotalMinWaitTime);
|
|
|
+ }
|
|
|
+ nextStartTimes.add(startTime);
|
|
|
+ }
|
|
|
+ getAllNextProTime(nextProcess,nextStartTimes,nowTotalMinWaitTime);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设备运行时间段,不可再排产
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint equipmentRunTime(ConstraintFactory constraintFactory) {
|
|
|
+ return constraintFactory.forEach(ProductionProcessesTa.class)
|
|
|
+ .filter(pro->{
|
|
|
+ return !pro.getProcessType().equals("成退") && !pro.getProcessType().equals("中退") && !pro.getProcessType().equals("小卷成退");
|
|
|
+ })
|
|
|
+ .filter(productionProcesses -> {
|
|
|
+ if(productionProcesses.getEquipment().getId().equals("0001be252874536843730b100024")){
|
|
|
+ int abc = 1;
|
|
|
+ if(productionProcesses.getDelay() == 270){
|
|
|
+ int abcd = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ boolean bol = false;
|
|
|
+ if(productionProcesses.getEquipment() != null && productionProcesses.getEquipment().getEquipmentRunTimes() != null &&
|
|
|
+ productionProcesses.getEquipment().getEquipmentRunTimes().size()>0
|
|
|
+ && productionProcesses.getStartTime() != null && productionProcesses.getEndTime() != null){
|
|
|
+ for (EquipmentRunTime equipmentRunTime : productionProcesses.getEquipment().getEquipmentRunTimes()) {
|
|
|
+ LocalDateTime startTime = equipmentRunTime.getStartRunTime();
|
|
|
+ LocalDateTime endRunTime = equipmentRunTime.getEndRunTime();
|
|
|
+ if(equipmentRunTime.getStartRunTime() != null && equipmentRunTime.getEndRunTime() != null){
|
|
|
+ if(productionProcesses.getStartTime().compareTo(endRunTime)>=0 || productionProcesses.getEndTime().compareTo(startTime)<=0){
|
|
|
+ continue;
|
|
|
+ }else{
|
|
|
+ bol = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(startTime != null && endRunTime == null){
|
|
|
+ if(productionProcesses.getEndTime().compareTo(startTime)>0){
|
|
|
+ bol = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return bol;
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_HARD,(proc1)->80)
|
|
|
+ .asConstraint("equipmentRunTime");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 软约束:交货日期,根据延迟交货日期的天数来做惩罚分数计算
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint deliveryDate(ConstraintFactory constraintFactory) {
|
|
|
+ return constraintFactory.forEach(ProductionProcessesTa.class)
|
|
|
+ .filter(productionProcesses -> {
|
|
|
+ /*
|
|
|
+ 获取最后一步工步的结束时间(最后一步工步的结束时间即此产品生产的实际结束时间)
|
|
|
+ 并且获取结束时间大于生产订单的交货日期
|
|
|
+ */
|
|
|
+ if(productionProcesses.getEndTime() == null){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // 取最小订单交货日期
|
|
|
+ Date deliveryMinDate = null;
|
|
|
+ for (ProduceOrder produceOrder : productionProcesses.getProduceOrder()) {
|
|
|
+ if(deliveryMinDate == null){
|
|
|
+ deliveryMinDate = produceOrder.getDeliveryDate();
|
|
|
+ }else{
|
|
|
+ if(deliveryMinDate.compareTo(produceOrder.getDeliveryDate())>0){
|
|
|
+ deliveryMinDate = produceOrder.getDeliveryDate();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(deliveryMinDate == null){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ Boolean bol = productionProcesses.getEndTime().atZone(zoneId).toInstant().toEpochMilli()>deliveryMinDate.getTime();
|
|
|
+ return bol;
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_MEDIUM,(productionProcesses) ->{
|
|
|
+ /*Date deliveryMinDate = null;
|
|
|
+ for (ProduceOrder produceOrder : productionProcesses.getProduceOrder()) {
|
|
|
+ if(deliveryMinDate == null){
|
|
|
+ deliveryMinDate = produceOrder.getDeliveryDate();
|
|
|
+ }else{
|
|
|
+ if(deliveryMinDate.compareTo(produceOrder.getDeliveryDate())>0){
|
|
|
+ deliveryMinDate = produceOrder.getDeliveryDate();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ int i = (int) (DateUtil.between(deliveryMinDate, Date.from(productionProcesses.getEndTime().atZone(zoneId).toInstant()), DateUnit.MINUTE) + 1) * 10;
|
|
|
+ if(i<0){
|
|
|
+ int aa = 0;
|
|
|
+ }
|
|
|
+ return i;*/
|
|
|
+ return 100;
|
|
|
+ })
|
|
|
+ .asConstraint("deliveryDate");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 软约束:交货日期,根据延迟交货日期的天数来做惩罚分数计算
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint expecteddays(ConstraintFactory constraintFactory) {
|
|
|
+ return constraintFactory.forEach(ProductionProcessesTa.class)
|
|
|
+// .filter(productionProcesses -> productionProcesses.getNextProcesses() == null || productionProcesses.getNextProcesses().size() == 0)
|
|
|
+ .filter(productionProcesses -> {
|
|
|
+ // 非最后一道工序或者最后一道工序没有排程时间的工序直接跳过
|
|
|
+ if(productionProcesses.getEndTime() == null){
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ Long expecteddays = expecteddaysCount(productionProcesses);
|
|
|
+ if(expecteddays>0){
|
|
|
+ return true;
|
|
|
+ }else{
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_MEDIUM,(productionProcesses) ->{
|
|
|
+ Long expecteddays = expecteddaysCount(productionProcesses);
|
|
|
+ return (int)(expecteddays*10000);
|
|
|
+ })
|
|
|
+ .asConstraint("expecteddays");
|
|
|
+ }
|
|
|
+
|
|
|
+ private Long expecteddaysCount(ProductionProcessesTa productionProcesses){
|
|
|
+ // 取最小订单交货天数
|
|
|
+ Integer deliveryMinDate = null;
|
|
|
+ for (ProduceOrder produceOrder : productionProcesses.getProduceOrder()) {
|
|
|
+ if(deliveryMinDate == null){
|
|
|
+ deliveryMinDate = produceOrder.getExpecteddays();
|
|
|
+ }else{
|
|
|
+ if(produceOrder.getExpecteddays() != null && produceOrder.getExpecteddays()<deliveryMinDate){
|
|
|
+ deliveryMinDate = produceOrder.getExpecteddays();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(deliveryMinDate == null){
|
|
|
+ deliveryMinDate = 15;
|
|
|
+ }
|
|
|
+ // 有铸轧的工序取铸轧后第一道工序开始时间,没有铸轧的直接取第一道工序开始时间
|
|
|
+ LocalDateTime startTime = null;
|
|
|
+ ProductionProcessesTa rooprocess = productionProcesses.getRooprocess();
|
|
|
+ if(rooprocess != null){
|
|
|
+ if("铸轧".equals(rooprocess.getProcessType())){
|
|
|
+ if("成退".equals(rooprocess.getNextProcesses().get(0).getProcessType()) || "中退".equals(rooprocess.getNextProcesses().get(0).getProcessType())
|
|
|
+ || "小卷成退".equals(rooprocess.getNextProcesses().get(0).getProcessType())){
|
|
|
+ startTime = null;
|
|
|
+ }else{
|
|
|
+ startTime = rooprocess.getNextProcesses().get(0).getStartTime();
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if ("成退".equals(rooprocess.getProcessType()) || "中退".equals(rooprocess.getProcessType()) || "小卷成退".equals(rooprocess.getProcessType())){
|
|
|
+ if(rooprocess.getNextProcesses() != null && rooprocess.getNextProcesses().size()>0){
|
|
|
+ startTime = rooprocess.getNextProcesses().get(0).getStartTime();
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ startTime = rooprocess.getStartTime();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ return 0L;
|
|
|
+ }
|
|
|
+ if(startTime == null){
|
|
|
+ return 0L;
|
|
|
+ }
|
|
|
+ long daysBetween = ChronoUnit.DAYS.between(startTime, productionProcesses.getEndTime());
|
|
|
+ return daysBetween-deliveryMinDate;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连续生产约束条件,同一设备的连续生产标识一样的工序、尽量排在一起
|
|
|
+ * 铸轧考虑换辊和立板
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint seriesProduce(ConstraintFactory constraintFactory){
|
|
|
+ return constraintFactory.forEach(EquipmentTa.class)
|
|
|
+ .filter((equipment) -> {
|
|
|
+ if(equipment.getTasks() != null && equipment.getTasks().size()>0){
|
|
|
+ String processType = equipment.getTasks().get(0).getProcessType();
|
|
|
+ if(processType.equals("冷轧") || processType.equals("箔轧")){
|
|
|
+ for (ProductionProcessesTa process : equipment.getTasks()) {
|
|
|
+ process.getConflictRoptions().remove("soft-seriesProduceZz");
|
|
|
+ process.getConflictRoptions().remove("soft-seriesProduceLz");
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }else{
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ /*int countNum = seriesProduceCount(processes);
|
|
|
+ if(countNum>0){
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;*/
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_MEDIUM,(equipment)->{
|
|
|
+ int countNum = seriesProduceCount(equipment.getTasks());
|
|
|
+ return countNum;
|
|
|
+ })
|
|
|
+ .asConstraint("seriesProduce");
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ private int seriesProduceCount(List<ProductionProcessesTa> processes){
|
|
|
+ int b = 0;
|
|
|
+ EquipmentTa equipment = null;
|
|
|
+ List<ApsNochangeRollerDo> apsNochangeRollerDos = null;
|
|
|
+ if(processes != null && processes.size()>0){
|
|
|
+ equipment = processes.get(0).getEquipment();
|
|
|
+ apsNochangeRollerDos = processes.get(0).getApsOverallConfig().getApsNochangeRollerDos();
|
|
|
+ }
|
|
|
+ if(equipment.getId().equals("0001be252874536843730b100024")){
|
|
|
+ int abc = 1;
|
|
|
+ if(processes.get(0).getDelay() == 270){
|
|
|
+ int abcd = 1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 设置作业辊
|
|
|
+ for (ProductionProcessesTa process : processes) {
|
|
|
+ if(process.getOptionalEquipmentZg() != null && process.getOptionalEquipmentZg().size()>0){
|
|
|
+ process.setProZg(process.getOptionalEquipmentZg().get(equipment.getId()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ List<ProductionProcessesTa> hasStartTimeProcess = processes.stream().filter(v -> v.getStartTime() != null).collect(Collectors.toList());
|
|
|
+ if(hasStartTimeProcess != null && hasStartTimeProcess.size()>0){
|
|
|
+ /*if(hasStartTimeProcess.get(0).getApsStatus().equals("CH") && hasStartTimeProcess.get(0).getProcessType().equals("冷轧")){
|
|
|
+ return b;
|
|
|
+ }*/
|
|
|
+ // 设备占用时间参与连续生产排程
|
|
|
+ if(equipment != null && equipment.getEquipmentRunTimes() != null && equipment.getEquipmentRunTimes().size()>0){
|
|
|
+ for (EquipmentRunTime equipmentRunTime : equipment.getEquipmentRunTimes()) {
|
|
|
+ if(equipmentRunTime.getOccupyType().equals("process")){
|
|
|
+ ProductionProcessesTa pp = new ProductionProcessesTa();
|
|
|
+ pp.setStartTime(equipmentRunTime.getStartRunTime());
|
|
|
+ pp.setSeriesProduceMark(equipmentRunTime.getSeriesProduceMark());
|
|
|
+ pp.setProcessType(equipmentRunTime.getProcessType());
|
|
|
+ pp.setSinglerollweight(equipmentRunTime.getTotalSinglerollweight());
|
|
|
+ pp.setLastSerialLbWeight(equipmentRunTime.getLastSerialLbWeight());
|
|
|
+ pp.setBsProcessesId(Arrays.asList(new String[]{"haspcprocess"}));
|
|
|
+ pp.setConflictRoptions(new HashMap<>());
|
|
|
+ pp.setProZg(equipmentRunTime.getZjgid());
|
|
|
+ hasStartTimeProcess.add(pp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 按照开始时间排序
|
|
|
+ Collections.sort(hasStartTimeProcess, Comparator.comparing(ProductionProcessesTa::getSeriSort));
|
|
|
+ // 获取设备已排程好的最后一个作业,计算连续加工
|
|
|
+ if(equipment.getLastProcessType() != null && equipment.getLastSeriesProduceMark() != null){
|
|
|
+ ProductionProcessesTa pp = new ProductionProcessesTa();
|
|
|
+ pp.setSeriesProduceMark(equipment.getLastSeriesProduceMark());
|
|
|
+ pp.setProcessType(equipment.getLastProcessType());
|
|
|
+ pp.setSinglerollweight(equipment.getLastSinglerollweight());
|
|
|
+ pp.setLastSerialLbWeight(equipment.getLastSerialLbWeight());
|
|
|
+ pp.setBsProcessesId(Arrays.asList(new String[]{"lastprocess"}));
|
|
|
+ pp.setConflictRoptions(new HashMap<>());
|
|
|
+ pp.setProZg(equipment.getLastZjgid());
|
|
|
+ hasStartTimeProcess.add(0,pp);
|
|
|
+ }else{
|
|
|
+ if(equipment.getEquipmentRunTimes() == null || equipment.getEquipmentRunTimes().size() == 0){
|
|
|
+ b = b+2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 周期铸轧立板已连续生产吨数
|
|
|
+ BigDecimal zqlb = new BigDecimal("0");
|
|
|
+ for(int i=0;i<hasStartTimeProcess.size();i++){
|
|
|
+ if(i == hasStartTimeProcess.size()-1){
|
|
|
+ if(hasStartTimeProcess.get(i).getId() == null){
|
|
|
+ continue;
|
|
|
+ }else{
|
|
|
+ if("铸轧".equals(hasStartTimeProcess.get(i).getProcessType())){
|
|
|
+// b = b+15;
|
|
|
+ }else if ("冷轧".equals(hasStartTimeProcess.get(i).getProcessType())) {
|
|
|
+ b = b+10;
|
|
|
+ }else if ("箔轧".equals(hasStartTimeProcess.get(i).getProcessType())) {
|
|
|
+ b = b+5;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(hasStartTimeProcess.get(i).getId() == null && hasStartTimeProcess.get(i+1).getId() == null){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if(hasStartTimeProcess.get(i).getSeriesProduceMark() != null && hasStartTimeProcess.get(i+1).getSeriesProduceMark() != null){
|
|
|
+ Map<String, String> conflictRoptions1 = hasStartTimeProcess.get(i).getConflictRoptions();
|
|
|
+ Map<String, String> conflictRoptions2 = hasStartTimeProcess.get(i+1).getConflictRoptions();
|
|
|
+ if("铸轧".equals(hasStartTimeProcess.get(i).getProcessType())){
|
|
|
+ if(hasStartTimeProcess.get(i+1).getId() == null){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ String[] serspre = hasStartTimeProcess.get(i).getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ String[] sersafter = hasStartTimeProcess.get(i+1).getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ // 获取产品类型二级
|
|
|
+ String bfcplx = serspre[1].split("-")[0];
|
|
|
+ // 获取产品类型二级
|
|
|
+ String afcplx = sersafter[1].split("-")[0];
|
|
|
+ // 周期立板总重量统计
|
|
|
+ if(zqlb.compareTo(new BigDecimal("0")) == 0){
|
|
|
+ if(hasStartTimeProcess.get(i).getLastSerialLbWeight() != null){
|
|
|
+ zqlb = hasStartTimeProcess.get(i).getLastSerialLbWeight();
|
|
|
+ }else{
|
|
|
+ zqlb = hasStartTimeProcess.get(i).getSinglerollweight();
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ zqlb = zqlb.add(hasStartTimeProcess.get(i).getSinglerollweight());
|
|
|
+ }
|
|
|
+ // 铸轧立板是否连续
|
|
|
+ boolean lbserice = true;
|
|
|
+ if(serspre.length == 5 && sersafter.length == 5){
|
|
|
+ // 铸轧换辊兼容规则
|
|
|
+ if(!zzSeriesJr(hasStartTimeProcess.get(i),hasStartTimeProcess.get(i+1),apsNochangeRollerDos)){
|
|
|
+ b = b+15;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceZz",conflictRoptions1.get("soft-seriesProduceZz") == null ? "和后一道工序违反换辊和立板的连续约束" : conflictRoptions1.get("soft-seriesProduceZz")+";和后一道工序违反换辊和立板的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceZz","和前一道工序违反换辊和立板的连续约束");
|
|
|
+ }
|
|
|
+ zqlb = new BigDecimal("0");
|
|
|
+ lbserice = false;
|
|
|
+ }else{
|
|
|
+ // 合金相同情况下后面的宽度大于前面的宽度需要换辊和立板
|
|
|
+ // 合金相同情况下后面的宽度小于前面的宽度需要立板
|
|
|
+ // 合金相同情况下后面的宽度等于前面的宽度换辊和立板都不需要
|
|
|
+ String s1 = serspre[2];
|
|
|
+ String s2 = sersafter[2];
|
|
|
+ try{
|
|
|
+ BigDecimal i1 = new BigDecimal(s1);
|
|
|
+ BigDecimal i2 = new BigDecimal(s2);
|
|
|
+ if(i1.compareTo(i2)<0){
|
|
|
+ b = b+15;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceZz",conflictRoptions1.get("soft-seriesProduceZz") == null ? "和后一道工序违反换辊和立板的连续约束" : conflictRoptions1.get("soft-seriesProduceZz")+";和后一道工序违反换辊和立板的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceZz","和前一道工序违反换辊和立板的连续约束");
|
|
|
+ }
|
|
|
+ zqlb = new BigDecimal("0");
|
|
|
+ lbserice = false;
|
|
|
+ }else if(i1.compareTo(i2)>0){
|
|
|
+ b = b+8;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceZz",conflictRoptions1.get("soft-seriesProduceZz") == null ? "和后一道工序违反立板的连续约束" : conflictRoptions1.get("soft-seriesProduceZz")+";和后一道工序违反立板的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceZz","和前一道工序违反立板的连续约束");
|
|
|
+ }
|
|
|
+ zqlb = new BigDecimal("0");
|
|
|
+ lbserice = false;
|
|
|
+ }else{
|
|
|
+ // 二级产品类型不一样的也需要立板
|
|
|
+ if(!bfcplx.equals(afcplx)){
|
|
|
+ b = b+8;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceZz",conflictRoptions1.get("soft-seriesProduceZz") == null ? "和后一道工序违反立板的连续约束" : conflictRoptions1.get("soft-seriesProduceZz")+";和后一道工序违反立板的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceZz","和前一道工序违反立板的连续约束");
|
|
|
+ }
|
|
|
+ zqlb = new BigDecimal("0");
|
|
|
+ lbserice = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if ("冷轧".equals(hasStartTimeProcess.get(i).getProcessType()) || "箔轧".equals(hasStartTimeProcess.get(i).getProcessType())) {
|
|
|
+ ProductionProcessesTa prepro = hasStartTimeProcess.get(i);
|
|
|
+ ProductionProcessesTa nextpro = hasStartTimeProcess.get(i+1);
|
|
|
+ String[] serspre = hasStartTimeProcess.get(i).getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ String[] sersafter = hasStartTimeProcess.get(i+1).getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ // 前道工序宽度、输入物料厚度、输出物料厚度
|
|
|
+ String s1 = serspre[2];
|
|
|
+ BigDecimal t1 = new BigDecimal(serspre[3]);
|
|
|
+ BigDecimal to1 = new BigDecimal(serspre[4]);
|
|
|
+ // 后道工序宽度、输入物料厚度、输出物料厚度
|
|
|
+ String s2 = sersafter[2];
|
|
|
+ BigDecimal t2 = new BigDecimal(sersafter[3]);
|
|
|
+ BigDecimal to2 = new BigDecimal(sersafter[4]);
|
|
|
+ BigDecimal i1 = new BigDecimal(s1);
|
|
|
+ BigDecimal i2 = new BigDecimal(s2);
|
|
|
+ // 前后道所属作业ID
|
|
|
+ String processId1 = hasStartTimeProcess.get(i).getBsProcessesId().get(0);
|
|
|
+ String processId2 = hasStartTimeProcess.get(i+1).getBsProcessesId().get(0);
|
|
|
+ // 判断原有前后两道历史工序是否连续
|
|
|
+ boolean ispreafterLx = false;
|
|
|
+ if(prepro.getId() == null && nextpro.getId() != null && hasStartTimeProcess.size()>i+2
|
|
|
+ && hasStartTimeProcess.get(i+2).getId() == null){
|
|
|
+ ProductionProcessesTa nextnextpro = hasStartTimeProcess.get(i + 2);
|
|
|
+ if(StrUtil.isNotBlank(prepro.getProZg()) && StrUtil.isNotBlank(nextnextpro.getProZg())){
|
|
|
+ if(prepro.getProZg().equals(nextnextpro.getProZg())){
|
|
|
+ String[] sersafterafter = nextnextpro.getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ BigDecimal i3 = new BigDecimal(sersafterafter[2]);
|
|
|
+ if(i1.compareTo(i3)>=0){
|
|
|
+ ispreafterLx = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else if (prepro.getId() != null && nextpro.getId() == null && i>0
|
|
|
+ && hasStartTimeProcess.get(i-1).getId() == null) {
|
|
|
+ ProductionProcessesTa preprepro = hasStartTimeProcess.get(i-1);
|
|
|
+ if(StrUtil.isNotBlank(preprepro.getProZg()) && StrUtil.isNotBlank(nextpro.getProZg())){
|
|
|
+ if(preprepro.getProZg().equals(nextpro.getProZg())){
|
|
|
+ String[] sersprepre = preprepro.getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ BigDecimal i0 = new BigDecimal(sersprepre[2]);
|
|
|
+ if(i0.compareTo(i2)>=0){
|
|
|
+ ispreafterLx = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(StrUtil.isNotBlank(prepro.getProZg()) && StrUtil.isNotBlank(nextpro.getProZg())){
|
|
|
+ String preZg = prepro.getProZg();
|
|
|
+ String nextZg = nextpro.getProZg();
|
|
|
+ if(!preZg.equals(nextZg)){
|
|
|
+ b = b+10;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if((i1.add(new BigDecimal("30"))).compareTo(i2)<0){
|
|
|
+ b = b+8;
|
|
|
+ if(ispreafterLx){
|
|
|
+ b = b+8;
|
|
|
+ }
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }
|
|
|
+ }else if(i1.compareTo(i2)<0 && (i1.add(new BigDecimal("30"))).compareTo(i2)>=0){
|
|
|
+ b = b+7;
|
|
|
+ if(ispreafterLx){
|
|
|
+ b = b+8;
|
|
|
+ }
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }
|
|
|
+ }else if(i1.compareTo(i2)>0){
|
|
|
+ b = b+3;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(serspre.length == 5 && sersafter.length == 5){
|
|
|
+ try{
|
|
|
+ // 后端工序大于前道工序,并且大于30mm
|
|
|
+ if((i1.add(new BigDecimal("30"))).compareTo(i2)<0){
|
|
|
+ b = b+10;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 后端工序大于前道工序,并且小于30mm
|
|
|
+ else if(i1.compareTo(i2)<0 && (i1.add(new BigDecimal("30"))).compareTo(i2)>=0){
|
|
|
+ b = b+8;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 后端工序小于前道工序
|
|
|
+ /*else if(i1.compareTo(i2)>0){
|
|
|
+ b = b+5;
|
|
|
+ }*/
|
|
|
+ // 后端工序小于等于前道工序的情况下
|
|
|
+ else{
|
|
|
+ if(!serspre[1].equals(sersafter[1])){
|
|
|
+ b = b+5;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(i1.compareTo(i2)>0){
|
|
|
+ b = b+2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 输入厚度不同
|
|
|
+ /*if(t1.compareTo(t2) != 0){
|
|
|
+ b = b+4;
|
|
|
+ }else{
|
|
|
+ // 输出厚度不同
|
|
|
+ if(to1.compareTo(to2) != 0){
|
|
|
+ b = b+3;
|
|
|
+ }else{
|
|
|
+ // 不属于同一作业
|
|
|
+ if(!processId1.equals(processId2)){
|
|
|
+ b = b+1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ /*else if ("箔轧".equals(hasStartTimeProcess.get(i).getProcessType())) {
|
|
|
+ // 宽度从大到小
|
|
|
+ String[] serspre = hasStartTimeProcess.get(i).getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ String[] sersafter = hasStartTimeProcess.get(i+1).getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ if(serspre.length == 5 && sersafter.length == 5){
|
|
|
+ String s1 = serspre[2];
|
|
|
+ String s2 = sersafter[2];
|
|
|
+ try {
|
|
|
+ BigDecimal volumeWidth = new BigDecimal(s1);
|
|
|
+ BigDecimal volumeWidth1 = new BigDecimal(s2);
|
|
|
+ if(volumeWidth.compareTo(volumeWidth1)<0){
|
|
|
+ b = b+5;
|
|
|
+ if(hasStartTimeProcess.get(i).getId() != null){
|
|
|
+ conflictRoptions1.put("soft-seriesProduceLz",conflictRoptions1.get("soft-seriesProduceLz") == null ? "和后一道工序违反换辊的连续约束" : conflictRoptions1.get("soft-seriesProduceLz")+";和后一道工序违反换辊的连续约束");
|
|
|
+ }else{
|
|
|
+ conflictRoptions2.put("soft-seriesProduceLz","和前一道工序违反换辊的连续约束");
|
|
|
+ }
|
|
|
+ } else if (volumeWidth.compareTo(volumeWidth1)<0) {
|
|
|
+ b = b+1;
|
|
|
+ }
|
|
|
+ }catch (Exception e){
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return b;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 铸轧判断合金产品类型是否兼容
|
|
|
+ * @param beforePro
|
|
|
+ * @param afterPro
|
|
|
+ * @param apsNochangeRollerDos
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private boolean zzSeriesJr(ProductionProcessesTa beforePro, ProductionProcessesTa afterPro, List<ApsNochangeRollerDo> apsNochangeRollerDos){
|
|
|
+ boolean ifJr = false;
|
|
|
+ String[] serspre = beforePro.getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ String[] sersafter = afterPro.getSeriesProduceMark().split("\\^_\\^");
|
|
|
+ if(serspre.length == 5 && sersafter.length == 5){
|
|
|
+ // 合金和产品类型
|
|
|
+ // 前一道作业合金、产品类型
|
|
|
+ String bfhj = serspre[0];
|
|
|
+ // 获取产品类型二级
|
|
|
+ String bfcplx = serspre[1].split("-")[0];
|
|
|
+ // 后一道作业合金、产品类型
|
|
|
+ String afhj = sersafter[0];
|
|
|
+ // 获取产品类型二级
|
|
|
+ String afcplx = sersafter[1].split("-")[0];
|
|
|
+ // 合金和二级产品类型一样的无需换辊
|
|
|
+ if(bfhj.equals(afhj) && bfcplx.equals(afcplx)){
|
|
|
+ ifJr = true;
|
|
|
+ }else{
|
|
|
+ // 铸轧合金兼容配置
|
|
|
+ if(apsNochangeRollerDos != null && apsNochangeRollerDos.size()>0){
|
|
|
+ for (ApsNochangeRollerDo apsNochangeRollerDo : apsNochangeRollerDos) {
|
|
|
+ // 判断合金是否都包含,且相同
|
|
|
+ if(bfhj.equals(afhj)){
|
|
|
+ if(StrUtil.isNotBlank(apsNochangeRollerDo.getWorkingalloy())){
|
|
|
+ if(apsNochangeRollerDo.getWorkingalloy().contains(bfhj) && apsNochangeRollerDo.getWorkingalloy().contains(afhj)){
|
|
|
+ // 判断产品类型是包含还是不包含的关系
|
|
|
+ if("包含".equals(apsNochangeRollerDo.getCompatibilityrules())){
|
|
|
+ // 产品类型不为空
|
|
|
+ if(StrUtil.isNotBlank(apsNochangeRollerDo.getJobproducttype())){
|
|
|
+ if(apsNochangeRollerDo.getJobproducttype().contains(bfcplx) && apsNochangeRollerDo.getJobproducttype().contains(afcplx)){
|
|
|
+ ifJr = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 产品类型为空
|
|
|
+ else{
|
|
|
+ ifJr = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ } else if ("不包含".equals(apsNochangeRollerDo.getCompatibilityrules())) {
|
|
|
+ // 产品类型不为空
|
|
|
+ if(StrUtil.isNotBlank(apsNochangeRollerDo.getJobproducttype())){
|
|
|
+ if(!apsNochangeRollerDo.getJobproducttype().contains(bfcplx) && !apsNochangeRollerDo.getJobproducttype().contains(afcplx)){
|
|
|
+ ifJr = true;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 产品类型为空
|
|
|
+ else{
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ifJr;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 排程时间尽量靠前
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint processNear(ConstraintFactory constraintFactory){
|
|
|
+ return constraintFactory.forEach(ProductionProcessesTa.class)
|
|
|
+ .filter((process)->{
|
|
|
+ if(process.getPreviousProcesses() == null || process.getPreviousProcesses().size() == 0){
|
|
|
+ if(process.getStartTime().compareTo(process.getApsOverallConfig().getStartTime())>0){
|
|
|
+ return true;
|
|
|
+ }else{
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ if(process.getStartTime() != null){
|
|
|
+ return true;
|
|
|
+ }else{
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_SOFT,(process) -> {
|
|
|
+ int processNearNum = 0;
|
|
|
+ processNearNum = (int)ChronoUnit.MINUTES.between(process.getApsOverallConfig().getStartTime(), process.getStartTime());
|
|
|
+ if(processNearNum<=0){
|
|
|
+ processNearNum = 0;
|
|
|
+ }
|
|
|
+ return processNearNum;
|
|
|
+ })
|
|
|
+ .asConstraint("processNear");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 前后工序可以在一个设备上的尽量在一个设备上
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint preNextProcessSameEq(ConstraintFactory constraintFactory) {
|
|
|
+ return constraintFactory.forEach(ProductionProcessesTa.class)
|
|
|
+ .filter(pro->{
|
|
|
+ boolean a = false;
|
|
|
+ if(pro.getPreviousProcesses() != null && pro.getPreviousProcesses().size()>0){
|
|
|
+ a = true;
|
|
|
+ }
|
|
|
+ return a;
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_SOFT,(processes)->{
|
|
|
+ int a = 0;
|
|
|
+ EquipmentTa equipmentthis = processes.getEquipment();
|
|
|
+ EquipmentTa equipmentpre = processes.getPreviousProcesses().get(0).getEquipment();
|
|
|
+ if(!equipmentpre.getId().equals(equipmentthis.getId())){
|
|
|
+ a = a + 10000;
|
|
|
+ }
|
|
|
+ /*if(!equipmentpre.getWorkshopid().equals(equipmentthis.getWorkshopid())){
|
|
|
+ a = a + 10000;
|
|
|
+ }*/
|
|
|
+ return a;
|
|
|
+ })
|
|
|
+ .asConstraint("preNextProcessSameEq");
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 前后工序可以在一个设备上的尽量在一个设备上
|
|
|
+ * @param constraintFactory
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private Constraint preNextProcessSameWorkShop(ConstraintFactory constraintFactory) {
|
|
|
+ return constraintFactory.forEach(ProductionProcessesTa.class)
|
|
|
+ .filter(pro->{
|
|
|
+ boolean a = false;
|
|
|
+ if(pro.getPreviousProcesses() != null && pro.getPreviousProcesses().size()>0){
|
|
|
+ a = true;
|
|
|
+ }
|
|
|
+ return a;
|
|
|
+ })
|
|
|
+ .penalize(HardMediumSoftScore.ONE_MEDIUM,(processes)->{
|
|
|
+ int a = 0;
|
|
|
+ EquipmentTa equipmentthis = processes.getEquipment();
|
|
|
+ EquipmentTa equipmentpre = processes.getPreviousProcesses().get(0).getEquipment();
|
|
|
+ if(!equipmentpre.getWorkshopid().equals(equipmentthis.getWorkshopid())){
|
|
|
+ a = a + 5000;
|
|
|
+ }
|
|
|
+ return a;
|
|
|
+ })
|
|
|
+ .asConstraint("preNextProcessSameWorkShop");
|
|
|
+ }
|
|
|
+
|
|
|
+}
|