|
@@ -0,0 +1,281 @@
|
|
|
+package com.rongwei.rwapsserver.aps.listener;
|
|
|
+
|
|
|
+import com.rongwei.rwapsserver.aps.domain.ApsSolution;
|
|
|
+import com.rongwei.rwapsserver.aps.domain.EquipmentRunTime;
|
|
|
+import com.rongwei.rwapsserver.aps.domain.ProductionProcesses;
|
|
|
+import org.optaplanner.core.api.domain.variable.VariableListener;
|
|
|
+import org.optaplanner.core.api.score.director.ScoreDirector;
|
|
|
+import java.time.LocalDateTime;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Map;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 设备赋值后任务起止时间自动计算
|
|
|
+ */
|
|
|
+public class TaskStartTimeListener implements VariableListener<ApsSolution, ProductionProcesses> {
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void beforeEntityAdded(ScoreDirector<ApsSolution> scoreDirector, ProductionProcesses process) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterEntityAdded(ScoreDirector<ApsSolution> scoreDirector, ProductionProcesses process) {
|
|
|
+ updateResponseTime(scoreDirector, process);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void beforeVariableChanged(ScoreDirector<ApsSolution> scoreDirector, ProductionProcesses process) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterVariableChanged(ScoreDirector<ApsSolution> scoreDirector, ProductionProcesses process) {
|
|
|
+ updateResponseTime(scoreDirector, process);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void beforeEntityRemoved(ScoreDirector<ApsSolution> scoreDirector, ProductionProcesses process) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void afterEntityRemoved(ScoreDirector<ApsSolution> scoreDirector, ProductionProcesses process) {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ protected void updateResponseTime(ScoreDirector<ApsSolution> scoreDirector, ProductionProcesses process) {
|
|
|
+ if(process.getEquipment() != null){
|
|
|
+// System.out.println(process.getEquipment().getId()+"-"+process.getEquipment().getEquipmentType());
|
|
|
+ /*scoreDirector.beforeVariableChanged(process, "startTime");
|
|
|
+ // 时间设定
|
|
|
+ LocalDateTime toUpdateStartTime = startTimeSet(process);
|
|
|
+ process.setStartTime(toUpdateStartTime);
|
|
|
+ scoreDirector.afterVariableChanged(process, "startTime");*/
|
|
|
+
|
|
|
+ setNextAllStartTime(scoreDirector,process);
|
|
|
+ }
|
|
|
+
|
|
|
+ /*PreviousCallOrAgent previous = call.getPreviousCallOrAgent();
|
|
|
+ Call shadowCall = call;
|
|
|
+ Duration previousDurationTillPickUp = (previous == null ? null : previous.getDurationTillPickUp());
|
|
|
+ Duration estimatedWaiting = calculateWaitingTimeEstimate(shadowCall, previousDurationTillPickUp);
|
|
|
+ while (shadowCall != null) {
|
|
|
+ scoreDirector.beforeVariableChanged(shadowCall, "estimatedWaiting");
|
|
|
+ shadowCall.setEstimatedWaiting(estimatedWaiting);
|
|
|
+ scoreDirector.afterVariableChanged(shadowCall, "estimatedWaiting");
|
|
|
+ previousDurationTillPickUp = shadowCall.getDurationTillPickUp();
|
|
|
+ shadowCall = shadowCall.getNextCall();
|
|
|
+ estimatedWaiting = calculateWaitingTimeEstimate(shadowCall, previousDurationTillPickUp);
|
|
|
+ }*/
|
|
|
+ }
|
|
|
+
|
|
|
+ private void setNextAllStartTime(ScoreDirector<ApsSolution> scoreDirector,ProductionProcesses process){
|
|
|
+ LocalDateTime startDateTime = startTimeSet(process);
|
|
|
+ scoreDirector.beforeVariableChanged(process, "startTime");
|
|
|
+ process.setStartTime(startDateTime);
|
|
|
+ scoreDirector.afterVariableChanged(process, "startTime");
|
|
|
+ if(process.getNextProcesses() != null && process.getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses nextProcess : process.getNextProcesses()) {
|
|
|
+ setNextAllStartTime(scoreDirector,nextProcess);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置开始时间
|
|
|
+ * @param process
|
|
|
+ */
|
|
|
+ private LocalDateTime startTimeSet(ProductionProcesses process){
|
|
|
+ // 时间设定
|
|
|
+ LocalDateTime toUpdateStartTime = null;
|
|
|
+ if(process.getEquipment() != null){
|
|
|
+ // 最大单批次生产时间
|
|
|
+ Integer maxUnitProduceTime = 0;
|
|
|
+ // 最大流转时间
|
|
|
+ Integer lzMaxTimes = 0;
|
|
|
+ // 前道工序最小首批加工最大等待时间
|
|
|
+ LocalDateTime lastFirstMaxWaitTime = null;
|
|
|
+ if(process.getPreviousProcesses() != null && process.getPreviousProcesses().size()>0){
|
|
|
+ // 瓶颈工序,简化为等待前道工序全部完成才加工后道工序
|
|
|
+ if((process.getBottleneck() != null && process.getBottleneck())
|
|
|
+ || (process.getPreviousProcesses().get(0).getBottleneck() != null && process.getPreviousProcesses().get(0).getBottleneck())){
|
|
|
+ LocalDateTime lastMaxStartTime = null;
|
|
|
+ LocalDateTime lastMinMaxWaitTime = null;
|
|
|
+ for (ProductionProcesses previousProcess : process.getPreviousProcesses()) {
|
|
|
+ // 流转时间
|
|
|
+ Integer lzTimes = 0;
|
|
|
+ if(previousProcess.getEquipment().getWorkshopid() != null && previousProcess.getEquipment().getWorkshopid().equals(process.getEquipment().getWorkshopid())){
|
|
|
+ lzTimes = process.getApsOverallConfig().getRoamTime().get("WORKSHOP_IN");
|
|
|
+ }else{
|
|
|
+ lzTimes = process.getApsOverallConfig().getRoamTime().get("WORKSHOP_CROSS");
|
|
|
+ }
|
|
|
+ if(lzMaxTimes<lzTimes){
|
|
|
+ lzMaxTimes = lzTimes;
|
|
|
+ }
|
|
|
+ // 最小等待时间
|
|
|
+ Integer minWaitTime = previousProcess.getMinWaitTime() == null ? 0 : previousProcess.getMinWaitTime();
|
|
|
+ if(lzTimes>minWaitTime){
|
|
|
+ minWaitTime = lzTimes;
|
|
|
+ }
|
|
|
+ if(lastMaxStartTime == null){
|
|
|
+ lastMaxStartTime = previousProcess.getEndTime().plusMinutes(minWaitTime);
|
|
|
+ }else {
|
|
|
+ if(lastMaxStartTime.compareTo(previousProcess.getEndTime().plusMinutes(minWaitTime))<0){
|
|
|
+ lastMaxStartTime = previousProcess.getEndTime().plusMinutes(minWaitTime);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 如有最大等待时间,计算首批次加工等待时间不能超过最大等待时间
|
|
|
+ if(previousProcess.getMaxWaitTime() != null){
|
|
|
+ if(lastMinMaxWaitTime == null){
|
|
|
+ lastMinMaxWaitTime = previousProcess.getEndTime().plusMinutes(previousProcess.getMaxWaitTime());
|
|
|
+ }else{
|
|
|
+ if(previousProcess.getEndTime().plusMinutes(previousProcess.getMaxWaitTime()).compareTo(lastMinMaxWaitTime)<0){
|
|
|
+ lastMinMaxWaitTime = previousProcess.getEndTime().plusMinutes(previousProcess.getMaxWaitTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // 开始时间不小于最大的最小等待时间、不大于最小的最大等待时间
|
|
|
+ toUpdateStartTime = lastMaxStartTime;
|
|
|
+
|
|
|
+ /*if(process.getStartTime().compareTo(lastMaxStartTime)<0){
|
|
|
+ bln = true;
|
|
|
+ }else if(process.getStartTime().compareTo(lastMinMaxWaitTime)>0){
|
|
|
+ bln = true;
|
|
|
+ }*/
|
|
|
+ }
|
|
|
+ // 非瓶颈工序,非瓶颈工序,默认前道工序只有一个
|
|
|
+ else{
|
|
|
+ // 此种情况简化为前道工序只有一个
|
|
|
+ ProductionProcesses preProcess = process.getPreviousProcesses().get(0);
|
|
|
+ if(preProcess.getStartTime() != null){
|
|
|
+ maxUnitProduceTime = preProcess.getUnitProduceTime();
|
|
|
+ // 前道工序的所有下道工序
|
|
|
+ List<ProductionProcesses> nextProcesses = preProcess.getNextProcesses();
|
|
|
+ Map<String,Integer> map = new HashMap<>();
|
|
|
+ for (ProductionProcesses nextProcess : nextProcesses) {
|
|
|
+ map.put(nextProcess.getId(),0);
|
|
|
+ allNextProduceTime(nextProcess,map,nextProcess.getId());
|
|
|
+ nextProcess.setNextAllProduceTime(map.get(nextProcess.getId()));
|
|
|
+ }
|
|
|
+ nextProcesses.sort((o1, o2) -> o1.getNextAllProduceTime().compareTo(o2.getNextAllProduceTime()));
|
|
|
+ // 前道工序
|
|
|
+ LocalDateTime startTime = preProcess.getStartTime();
|
|
|
+ LocalDateTime endTime = preProcess.getStartTime();
|
|
|
+ for (ProductionProcesses nextProcess : nextProcesses) {
|
|
|
+ int i = preProcess.getUnitProduceTime() * nextProcess.getProducePcNum();
|
|
|
+ if(!nextProcess.getId().equals(process.getId())){
|
|
|
+ startTime = startTime.plusMinutes(i);
|
|
|
+ }else{
|
|
|
+ endTime = startTime.plusMinutes(i);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 流转时间
|
|
|
+ Integer lzTimes = 0;
|
|
|
+ if(preProcess.getEquipment().getWorkshopid() != null && preProcess.getEquipment().getWorkshopid().equals(process.getEquipment().getWorkshopid())){
|
|
|
+ lzTimes = process.getApsOverallConfig().getRoamTime().get("WORKSHOP_IN");
|
|
|
+ }else{
|
|
|
+ lzTimes = process.getApsOverallConfig().getRoamTime().get("WORKSHOP_CROSS");
|
|
|
+ }
|
|
|
+ // 最小等待时间对比流转时间
|
|
|
+ if(preProcess.getMinWaitTime() != null && lzTimes<preProcess.getMinWaitTime()){
|
|
|
+ lzTimes = preProcess.getMinWaitTime();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 后道工序批次生产时间大于等于前道工序批次生产时间
|
|
|
+ * 从第一批次开始往后排程
|
|
|
+ */
|
|
|
+
|
|
|
+ if(preProcess.getMaxWaitTime() != null){
|
|
|
+ lastFirstMaxWaitTime = startTime.plusMinutes(preProcess.getUnitProduceTime()).plusMinutes(preProcess.getMaxWaitTime());
|
|
|
+ }
|
|
|
+ LocalDateTime lastStartTime = null;
|
|
|
+ if(process.getUnitProduceTime()>=maxUnitProduceTime){
|
|
|
+ lastStartTime = startTime.plusMinutes(preProcess.getUnitProduceTime()).plusMinutes(lzTimes);
|
|
|
+ /*if(process.getStartTime().compareTo(startTime.plusMinutes(preProcess.getUnitProduceTime()).plusMinutes(lzTimes))<0){
|
|
|
+ bln = true;
|
|
|
+ }else{
|
|
|
+ if(lastFirstMaxWaitTime != null){
|
|
|
+ if(process.getStartTime().compareTo(lastFirstMaxWaitTime)>0){
|
|
|
+ bln = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ process.setEndTime(lastStartTime.plusMinutes(process.getProduceTime()));
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 后道工序批次生产时间小于前道工序批次生产时间
|
|
|
+ * 从最后批次开始往前排程
|
|
|
+ */
|
|
|
+ else{
|
|
|
+ // 开始时间:最后一批次结束时间加流转时间,再往前倒排批次数减一乘以单批次生产时间
|
|
|
+ lastStartTime = endTime.plusMinutes(lzTimes).minusMinutes(process.getUnitProduceTime() * (process.getProducePcNum() - 1));
|
|
|
+ /*if(process.getStartTime().compareTo(startTime1)<0){
|
|
|
+ bln = true;
|
|
|
+ }
|
|
|
+ // 存在最大等待时间时
|
|
|
+ if(preProcess.getMaxWaitTime() != null){
|
|
|
+ // 超过最大等待时间
|
|
|
+ if(process.getStartTime().compareTo(startTime1.plusMinutes(preProcess.getMaxWaitTime()))>0){
|
|
|
+ bln = true;
|
|
|
+ }
|
|
|
+ }*/
|
|
|
+ // 结束时间重新赋值
|
|
|
+ process.setEndTime(endTime.plusMinutes(lzTimes).plusMinutes(process.getUnitProduceTime()));
|
|
|
+ }
|
|
|
+ // 对比设备已运行时间段来修正时间
|
|
|
+ LocalDateTime proStartTime = lastStartTime;
|
|
|
+ LocalDateTime proEndTime = process.getEndTime();
|
|
|
+ List<EquipmentRunTime> equipmentRunTimes = process.getEquipment().getEquipmentRunTimes();
|
|
|
+ if(equipmentRunTimes != null && equipmentRunTimes.size()>0){
|
|
|
+ for (EquipmentRunTime equipmentRunTime : equipmentRunTimes) {
|
|
|
+ if((proStartTime.compareTo(equipmentRunTime.getStartRunTime())>=0 && proStartTime.compareTo(equipmentRunTime.getEndRunTime())<=0)
|
|
|
+ || (proEndTime.compareTo(equipmentRunTime.getStartRunTime())>=0 && proEndTime.compareTo(equipmentRunTime.getEndRunTime())<=0)
|
|
|
+ || (proStartTime.compareTo(equipmentRunTime.getStartRunTime())<=0 && proEndTime.compareTo(equipmentRunTime.getEndRunTime())>=0)){
|
|
|
+ proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(1);
|
|
|
+ proEndTime = proStartTime.plusMinutes(process.getProduceTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ toUpdateStartTime = proStartTime;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ LocalDateTime proStartTime = process.getApsOverallConfig().getStartTime();
|
|
|
+ LocalDateTime proEndTime = proStartTime.plusMinutes(process.getProduceTime());
|
|
|
+ List<EquipmentRunTime> equipmentRunTimes = process.getEquipment().getEquipmentRunTimes();
|
|
|
+ if(equipmentRunTimes != null && equipmentRunTimes.size()>0){
|
|
|
+ for (EquipmentRunTime equipmentRunTime : equipmentRunTimes) {
|
|
|
+ if((proStartTime.compareTo(equipmentRunTime.getStartRunTime())>=0 && proStartTime.compareTo(equipmentRunTime.getEndRunTime())<=0)
|
|
|
+ || (proEndTime.compareTo(equipmentRunTime.getStartRunTime())>=0 && proEndTime.compareTo(equipmentRunTime.getEndRunTime())<=0)
|
|
|
+ || (proStartTime.compareTo(equipmentRunTime.getStartRunTime())<=0 && proEndTime.compareTo(equipmentRunTime.getEndRunTime())>=0)){
|
|
|
+ proStartTime = equipmentRunTime.getEndRunTime().plusMinutes(1);
|
|
|
+ proEndTime = proStartTime.plusMinutes(process.getProduceTime());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ toUpdateStartTime = proStartTime;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return toUpdateStartTime;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 汇总所有下道工序的加工时间
|
|
|
+ * @param nextProcess
|
|
|
+ * @param map
|
|
|
+ */
|
|
|
+ private void allNextProduceTime(ProductionProcesses nextProcess,Map<String,Integer> map,String proId){
|
|
|
+ map.put(proId,map.get(proId)+nextProcess.getProduceTime());
|
|
|
+ if(nextProcess.getNextProcesses() != null && nextProcess.getNextProcesses().size()>0){
|
|
|
+ for (ProductionProcesses process : nextProcess.getNextProcesses()) {
|
|
|
+ allNextProduceTime(process,map,proId);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+}
|