Quellcode durchsuchen

算法beta版,继续需要优化

yejian016332 vor 4 Jahren
Ursprung
Commit
d05378baec
23 geänderte Dateien mit 3192 neuen und 9 gelöschten Zeilen
  1. 81 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/algorithm/ga/GAScheduleManager.java
  2. 87 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/algorithm/ga/GAScheduler.java
  3. 50 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/algorithm/ga/problem/GAPriorityScheduleProblem.java
  4. 115 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/CandidateProcess.java
  5. 313 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/Instance.java
  6. 116 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/Machine.java
  7. 428 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/Operation.java
  8. 232 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/Part.java
  9. 58 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/objective/Objective.java
  10. 30 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/objective/ObjectiveCmax.java
  11. 98 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/solution/InstanceSolution.java
  12. 119 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/solution/InstanceSolutionStep.java
  13. 241 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/manager/AssignManager.java
  14. 89 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/manager/ScheduleManager.java
  15. 22 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/manager/iface/AssignManagerIface.java
  16. 52 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/manager/iface/ScheduleManagerIface.java
  17. 49 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/rule/OperationPriority.java
  18. 52 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/rule/basic/OperationRule.java
  19. 741 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/util/InstanceUtil.java
  20. 3 0
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/operationManagementCenter/service/TaskService.java
  21. 2 2
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/operationManagementCenter/service/impl/OrderServiceImpl.java
  22. 8 2
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/operationManagementCenter/service/impl/PlanServiceImpl.java
  23. 206 5
      imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/operationManagementCenter/service/impl/TaskServiceImpl.java

+ 81 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/algorithm/ga/GAScheduleManager.java

@@ -0,0 +1,81 @@
+package com.github.zuihou.business.aps.algorithm.ga;
+
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Operation;
+import com.github.zuihou.business.aps.instance.manager.ScheduleManager;
+import com.github.zuihou.business.aps.rule.OperationPriority;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Comparator;
+import java.util.TreeSet;
+
+/**
+ * @author: igen
+ * @description:遗传算法的调度管理类,实现了自己的调度方法
+ * @date: 2021年11月29日
+ *
+ */
+public class GAScheduleManager extends ScheduleManager {
+	private final static Log log = LogFactory.getLog(GAScheduleManager.class);
+
+	/**
+	 *
+	 * @author: igen
+	 * @description: 按照工序优先级进行调度
+	 * @param instance
+	 * @param priorityArray
+	 *            优先级序列
+	 * @return
+	 * @date: 2021年11月29日
+	 *
+	 */
+	public double schedulePriority(Instance instance, int[] priorityArray) {
+		int i = 0;
+		try {
+			this.beforeSchedule(instance, 0);
+
+			for (Operation operation : instance.getOperationMap().values()) {
+				operation.setOpPriority(priorityArray[i]);
+				i++;
+			}
+			instance.setOperationComparator(new OperationPriority());
+			this.schedule(instance, 0);
+			this.afterSchedule(instance, 0);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return instance.getObjective().getObjectiveValue();
+	}
+
+	@Override
+	public void beforeSchedule(Instance instance, int mode) {
+		instance.reset();
+	}
+
+	@Override
+	public void schedule(Instance instance, int mode) throws Exception {
+		this.initReadyTasks(instance);
+		// 只要就绪任务集合不为空,则继续安排
+		while (!instance.getReadyTaskS().isEmpty()) {
+			// 获得最优先的任务
+			Operation operation = instance.getReadyTaskS().first();
+			// 分派任务
+			assignManager.assignTask(instance, operation);
+		}
+	}
+
+	@Override
+	public void initReadyTasks(Instance instance) throws Exception {
+		// TODO Auto-generated method stub
+		Comparator<Operation> operationTaskComparator = instance.getOperationComparator();
+		if (operationTaskComparator == null) {
+            operationTaskComparator = new OperationPriority();
+        }
+		// 设置工序优先级比较器
+		TreeSet<Operation> readyTaskS = new TreeSet<Operation>(operationTaskComparator);
+		// 重新排序
+		readyTaskS.addAll(instance.getReadyTaskS());
+		instance.setReadyTaskS(readyTaskS);
+	}
+}

+ 87 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/algorithm/ga/GAScheduler.java

@@ -0,0 +1,87 @@
+package com.github.zuihou.business.aps.algorithm.ga;
+
+import cn.hutool.core.date.DateUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.github.zuihou.business.aps.algorithm.ga.problem.GAPriorityScheduleProblem;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Operation;
+import io.jenetics.*;
+import io.jenetics.engine.Engine;
+import io.jenetics.engine.EvolutionResult;
+import io.jenetics.engine.Problem;
+
+import java.util.*;
+
+/**
+ * @author: igen
+ * @description:
+ * @date: 2021年11月29日
+ *
+ */
+public class GAScheduler {
+	/**
+	 * 优先级编码(PriorityCode,PC):每道工序对应一个优先级数值
+	 */
+	public static final String PRIORITY_CODE = "PRIORITY_CODE";
+	private Instance instance;
+	private Problem problem;
+	private String codeType;
+
+	public GAScheduler(Instance instance, String code) {
+		super();
+		this.instance = instance;
+		this.codeType = code;
+		if (code.equals(GAScheduler.PRIORITY_CODE)) {
+			problem = new GAPriorityScheduleProblem(instance);
+			System.out.println("开始执行优先级编码的遗传算法!");
+		}
+	}
+
+	/**
+	 *
+	 * @author: igen
+	 * @description: 执行调度
+	 * @throws Exception
+	 * @date: 2021年11月29日
+	 *
+	 */
+	public void schedule() throws Exception {
+		long start = System.currentTimeMillis();
+		List<Double> results = new ArrayList<Double>();
+		// 独立运行次数
+		int runTimes = 1;
+		try {
+			for (int runTime = 1; runTime <= runTimes; runTime++) {
+				Engine<IntegerGene, Double> engine = Engine.builder(this.problem).executor(Runnable::run)
+						.optimize(Optimize.MINIMUM).populationSize(100).selector(new RouletteWheelSelector<>())
+						.alterers(new Mutator<>(0.2), new SinglePointCrossover<>(0.9)).build();
+
+				Phenotype<IntegerGene, Double> best = engine.stream()
+						.limit(500)
+						.peek(r -> System.out.println( DateUtil.format(new Date(r.getGeneration()),"yyyy-MM-dd HH:mm:ss") + " : " + r.getBestPhenotype()))
+						.collect(EvolutionResult.toBestPhenotype());
+				results.add(best.getFitness());
+				System.out.println("Found min objective: " + DateUtil.format(new Date(best.getFitness().longValue()),"yyyy-MM-dd HH:mm:ss"));
+				System.out.println("Found min chromosome: " + best.getGenotype().getChromosome());
+			}
+		} catch (RuntimeException e) {
+			e.printStackTrace();
+		}
+		System.out.println("平均" + instance.getObjective().getObjectiveName() + ":"
+				+ results.stream().mapToDouble(Double::doubleValue).average().orElse(0D));
+		System.out.println("最大" + instance.getObjective().getObjectiveName() + ":"
+				+ results.stream().mapToDouble(Double::doubleValue).max().orElse(0D));
+		System.out.println("最小" + instance.getObjective().getObjectiveName() + ":"
+				+ results.stream().mapToDouble(Double::doubleValue).min().orElse(0D));
+		long end = System.currentTimeMillis();
+		instance.getObjective().setObjectiveValue(results.stream().mapToDouble(Double::doubleValue).min().orElse(0D));
+		Iterator<Map.Entry<String, Operation>> it = instance.getOperationMap().entrySet().iterator();
+		while(it.hasNext()){
+			Operation operation = it.next().getValue();
+			System.out.println("[" + operation.getPartId() + "]" + operation.getName() + "[" + operation.getMachineId() + "]" + ":"+ DateUtil.format(new Date(operation.getStart()),"yyyy-MM-dd HH:mm:ss") + "-" + DateUtil.format(new Date(operation.getFinish()),"yyyy-MM-dd HH:mm:ss"));
+		}
+		System.out.println(JSONObject.toJSONString(instance.getPartMap()));
+		System.out.println("调度用时:" + (end - start) / 1000.0 / 60.0 + "分钟");
+	}
+
+}

+ 50 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/algorithm/ga/problem/GAPriorityScheduleProblem.java

@@ -0,0 +1,50 @@
+package com.github.zuihou.business.aps.algorithm.ga.problem;
+
+import cn.hutool.core.date.DateUtil;
+import com.github.zuihou.business.aps.algorithm.ga.GAScheduleManager;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+import io.jenetics.EnumGene;
+import io.jenetics.engine.Codec;
+import io.jenetics.engine.Codecs;
+import io.jenetics.engine.Problem;
+
+import java.util.function.Function;
+
+/**
+ *
+ * @author: igen
+ * @description:GA算法中的调度问题定义(优先级编码)
+ * @date: 2021年11月29日
+ *
+ */
+public class GAPriorityScheduleProblem implements Problem<int[], EnumGene<Integer>, Double> {
+	private Instance instance;
+	private GAScheduleManager gaScheduleManager = new GAScheduleManager();
+
+	public GAPriorityScheduleProblem(Instance instance) {
+		super();
+		instance.setCalcBeginDate(DateUtil.current(false));
+		this.instance = instance;
+		this.instance.init();
+	}
+
+	@Override
+	/**
+	 * 适应度函数评估,单步执行编码
+	 */
+	public Function<int[], Double> fitness() {
+		// 计算适应度函数,实际上就是解码,将编码进行调度得到制造期
+		return p -> {
+			return gaScheduleManager.schedulePriority(instance, p);
+		};
+	}
+
+	@Override
+	/**
+	 * 用规则编码进行编码
+	 */
+	public Codec<int[], EnumGene<Integer>> codec() {
+		return Codecs.ofPermutation((int) instance.getTotalOpNum());
+	}
+
+}

+ 115 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/CandidateProcess.java

@@ -0,0 +1,115 @@
+package com.github.zuihou.business.aps.instance.domain.basicdata;
+
+import java.io.Serializable;
+
+/**
+ *
+ * @author: yejian
+ * @description: 用于描述可选设备(可选工艺),machine是机床,duration是对应在机床上的加工时间,
+ *               将准备时间和加工时间设置在此的原因是,在柔性作业车间调度中,由于机床能力不同,所以同一道工序在不同的机床上加工时间是不同的
+ * @date: 2021年11月29日
+ *
+ */
+public class CandidateProcess implements Serializable {
+	/**
+	 * 设备编号
+	 */
+	private long machineId;
+
+	/**
+	 * 总工时
+	 */
+	private int duration;
+
+	/**
+	 * 准备时间
+	 */
+	private double setupTime;
+
+	/**
+	 * 加工时间
+	 */
+	private double runTime;
+
+	/**
+	 * 设备名称
+	 */
+	private String machineName;
+
+	/**
+	 * 工艺ID
+	 */
+	private long procedureId;
+
+	public String getMachineName() {
+		return machineName;
+	}
+
+	public void setMachineName(String machineName) {
+		this.machineName = machineName;
+	}
+
+	public int getDuration() {
+		return duration;
+	}
+
+	public void setDuration(int duration) {
+		this.duration = duration;
+	}
+
+	public long getMachineId() {
+		return machineId;
+	}
+
+	public void setMachineId(long machineId) {
+		this.machineId = machineId;
+	}
+
+	/**
+	 * @return the setupTime
+	 */
+	public double getSetupTime() {
+		return setupTime;
+	}
+
+	/**
+	 * @param setupTime
+	 *            the setupTime to set
+	 */
+	public void setSetupTime(double setupTime) {
+		this.setupTime = setupTime;
+	}
+
+	/**
+	 * @return the runTime
+	 */
+	public double getRunTime() {
+		return runTime;
+	}
+
+	/**
+	 * @param runTime
+	 *            the runTime to set
+	 */
+	public void setRunTime(double runTime) {
+		this.runTime = runTime;
+	}
+
+	public long getProcedureId() {
+		return procedureId;
+	}
+
+	public void setProcedureId(long procedureId) {
+		this.procedureId = procedureId;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		CandidateProcess candidateProcess = (CandidateProcess)obj;
+		if(machineId == candidateProcess.getMachineId() && procedureId == candidateProcess.getProcedureId()){
+			return true;
+		}else{
+			return false;
+		}
+	}
+}

+ 313 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/Instance.java

@@ -0,0 +1,313 @@
+package com.github.zuihou.business.aps.instance.domain.basicdata;
+
+
+import com.github.zuihou.business.aps.instance.domain.objective.Objective;
+import com.github.zuihou.business.aps.instance.domain.objective.ObjectiveCmax;
+import com.github.zuihou.business.aps.rule.OperationPriority;
+import com.github.zuihou.business.aps.rule.basic.OperationRule;
+
+import java.io.Serializable;
+import java.util.*;
+
+/**
+ * @author: igen
+ * @description: 调度案例类,包含了所有和调度相关的信息:工件、工序、可选工艺、工时等
+ * @date: 2021年11月29日
+ */
+public class Instance implements Serializable {
+
+	/**
+	 * 总工时
+	 */
+	public double totalWorkTime;
+	/**
+	 * 总工序数
+	 */
+	public double totalOpNum;
+	/**
+	 * 零件数
+	 */
+	public int partNum;
+
+	/**
+	 * 可选设备集合(工序名称+可选设备列表)
+	 */
+	protected Map<String, List<CandidateProcess>> candidateProMap = new HashMap<>(); // 可选处理集合(可选设备以及对应的加工时间)
+	/**
+	 * 工序集合(工序名+工序)
+	 */
+	protected Map<String, Operation> operationMap = new HashMap<>();
+	/**
+	 * 设备集合(设备名+设备)
+	 */
+	protected Map<String, Machine> machineMap = new HashMap<>();
+	/**
+	 * 零件集合(零件名称+零件)
+	 */
+	protected Map<String, Part> partMap = new HashMap<>();
+
+	/**
+	 * 上一步的调度目标值
+	 */
+	protected double lastObjectiveValue;
+
+	/**
+	 * 就绪任务集合
+	 */
+	protected TreeSet<Operation> readyTaskS = new TreeSet<Operation>(new OperationPriority());
+	/**
+	 * 工序任务比较器
+	 */
+	protected OperationRule operationComparator = new OperationPriority();
+
+	/**
+	 * 已分派的总工时(计算奖励时使用)
+	 */
+	protected double totalAssignedTaskWork;
+	/**
+	 * 调度目标
+	 */
+	protected Objective objective;
+
+	public long calcBeginDate;
+
+	public int getPartNum() {
+		return partNum;
+	}
+
+	public void setPartNum(int partNum) {
+		this.partNum = partNum;
+	}
+
+	/**
+	 * @return the candidateProMap
+	 */
+	public Map<String, List<CandidateProcess>> getCandidateProMap() {
+		return candidateProMap;
+	}
+
+	/**
+	 * @param candidateProMap
+	 *            the candidateProMap to set
+	 */
+	public void setCandidateProMap(Map<String, List<CandidateProcess>> candidateProMap) {
+		this.candidateProMap = candidateProMap;
+	}
+
+	/**
+	 * @return the operationMap
+	 */
+	public Map<String, Operation> getOperationMap() {
+		return operationMap;
+	}
+
+	/**
+	 * @param operationMap
+	 *            the operationMap to set
+	 */
+	public void setOperationMap(Map<String, Operation> operationMap) {
+		this.operationMap = operationMap;
+	}
+
+	/**
+	 * @return the machineMap
+	 */
+	public Map<String, Machine> getMachineMap() {
+		return machineMap;
+	}
+
+	/**
+	 * @param machineMap
+	 *            the machineMap to set
+	 */
+	public void setMachineMap(Map<String, Machine> machineMap) {
+		this.machineMap = machineMap;
+	}
+
+	/**
+	 * @return the partMap
+	 */
+	public Map<String, Part> getPartMap() {
+		return partMap;
+	}
+
+	/**
+	 * @param partMap
+	 *            the partMap to set
+	 */
+	public void setPartMap(Map<String, Part> partMap) {
+		this.partMap = partMap;
+	}
+
+	/**
+	 * igen
+	 * 计算之前初始化数据
+	 */
+	public void reset() {
+		this.lastObjectiveValue = 0;
+		this.getObjective().setObjectiveValue(0);
+		this.totalAssignedTaskWork = 0;
+		// 括号内可设置比较器
+		readyTaskS = new TreeSet<Operation>(new OperationPriority());
+		for (Part part : partMap.values()) {
+			part.setCurrOp(part.getOpList().get(0));
+			readyTaskS.add(part.getCurrOp());
+		}
+		for (Operation operation : operationMap.values()) {
+			// 清除计划时间
+			operation.setStart(0);
+			operation.setFinish(0);
+			// 清除已安排设备
+			operation.setMachineId(-1);
+			operation.setMachineName("");
+			// 初始为未调度状态
+			operation.setState(Operation.Unassigned_state);
+			if(operation.getFixedMachineID() == -1 ){
+				operation.setFixedMachineID(-1);
+			}
+		}
+		for (Machine machine : machineMap.values()) {
+			// 清除设备已安排任务
+			machine.getQueueList().clear();
+
+			// 清除工时
+			machine.setAssignedTaskWork(0);
+			// 清除负荷率和利用率
+			machine.setLoadRation(0);
+			machine.setUtilRation(0);
+
+			for(String noUseTime : machine.getNoUseTime()){
+				Operation operation = new Operation();
+				String[] noUseTimeScope = noUseTime.split("-");
+				long noUseTimeStart = Long.parseLong(noUseTimeScope[0]);
+				long noUseTimeEnd = Long.parseLong(noUseTimeScope[1]);
+				operation.setStart(noUseTimeStart);
+				operation.setFinish(noUseTimeEnd);
+				machine.getQueueList().add(operation);
+			}
+
+		}
+		for (Part part : partMap.values()) {
+            part.setStart(0);
+            part.setFinish(0);
+        }
+	}
+
+	/**
+	 * 对工件和工序进行初始化
+	 */
+	public void init() {
+		// 默认目标为制造期
+		this.objective = new ObjectiveCmax();
+		operationMap.clear();
+		for (Part part : partMap.values()) {
+			double remainWork = 0d;
+			int iSize = part.getOpList().size();
+			for (int j = iSize - 1; j >= 0; j--) {
+				Operation operation = part.getOpList().get(j);
+				remainWork += operation.getWorkTime();
+				operation.setRemainWorkTime(remainWork);
+				// 刷新剩余工序数
+				operation.setRemainOpNum(iSize - j);
+				operation.setPart(part);
+				// System.out.println("工序:" +
+				// operationMap.get(operation.getName()).getName());
+				if (iSize > 1) {
+					if (j == iSize - 1) {
+						operation.setPrepOp(part.getOpList().get(j - 1));
+					} else if (j == 0) {
+						operation.setSuccOp(part.getOpList().get(j + 1));
+					} else {
+						operation.setPrepOp(part.getOpList().get(j - 1));
+						operation.setSuccOp(part.getOpList().get(j + 1));
+					}
+				}
+				operationMap.put(operation.getPartId() + "_" + operation.getName(), operation);
+			}
+			part.setTotalWorkTime(remainWork);
+		}
+		class AssginedOpComp implements Comparator<Operation>, Serializable {
+			@Override
+			public int compare(Operation o1, Operation o2) {
+				// TODO Auto-generated method stub
+				if (o1.getStart() > o2.getStart()) {
+					return 1;
+				} else if (o1.getStart() < o2.getStart()) {
+					return -1;
+				} else {
+					return 0;
+				}
+			}
+		}
+		// 设置机床上已安排任务的比较器
+		for (Machine machine : machineMap.values()) {
+			TreeSet<Operation> queueList = new TreeSet<Operation>(new AssginedOpComp());
+			machine.setQueueList(queueList);
+		}
+	}
+
+	public TreeSet<Operation> getReadyTaskS() {
+		return readyTaskS;
+	}
+
+	public void setReadyTaskS(TreeSet<Operation> readyTaskS) {
+		this.readyTaskS = readyTaskS;
+	}
+
+	public OperationRule getOperationComparator() {
+		return operationComparator;
+	}
+
+	public void setOperationComparator(OperationRule operationComparator) {
+		this.operationComparator = operationComparator;
+	}
+
+	public double getTotalWorkTime() {
+		return totalWorkTime;
+	}
+
+	public void setTotalWorkTime(double totalWorkTime) {
+		this.totalWorkTime = totalWorkTime;
+	}
+
+	public double getTotalOpNum() {
+		return totalOpNum;
+	}
+
+	public void setTotalOpNum(double totalOpNum) {
+		this.totalOpNum = totalOpNum;
+	}
+
+
+	public double getTotalAssignedTaskWork() {
+		return totalAssignedTaskWork;
+	}
+
+	public void setTotalAssignedTaskWork(double totalAssignedTaskWork) {
+		this.totalAssignedTaskWork = totalAssignedTaskWork;
+	}
+
+	public void setObjective(Objective objective) {
+		this.objective = objective;
+	}
+
+	public double getLastObjectiveValue() {
+		return lastObjectiveValue;
+	}
+
+	public void setLastObjectiveValue(double lastObjectiveValue) {
+		this.lastObjectiveValue = lastObjectiveValue;
+	}
+
+	public Objective getObjective() {
+		return objective;
+	}
+
+	public long getCalcBeginDate() {
+		return calcBeginDate;
+	}
+
+	public void setCalcBeginDate(long calcBeginDate) {
+		this.calcBeginDate = calcBeginDate;
+	}
+}

+ 116 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/Machine.java

@@ -0,0 +1,116 @@
+package com.github.zuihou.business.aps.instance.domain.basicdata;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ * @author: igen
+ * @description: 机床类
+ * @date: 2021年11月29日
+ */
+public class Machine implements Serializable {
+	private long id;
+	private String name;
+	// 查询系统当前最新的设备维保信息
+	private List<String> noUseTime = new ArrayList<String>();
+	/**
+	 * 机床缓存,需要根据学习到的策略确定比较器
+	 */
+	transient private TreeSet<Operation> buffer = new TreeSet<Operation>();
+
+	class AssginedOpComp implements Comparator<Operation>, Serializable {
+		@Override
+		public int compare(Operation o1, Operation o2) {
+			// TODO Auto-generated method stub
+			if (o1.getStart() > o2.getStart()) {
+				return 1;
+			} else if (o1.getStart() < o2.getStart()) {
+				return -1;
+			} else {
+				return 0;
+			}
+		}
+	}
+
+	// 队列结果
+	private TreeSet<Operation> queueList = new TreeSet<Operation>(new AssginedOpComp());
+	public Machine() {
+	}
+
+	public Machine(long id, String name) {
+		this.id = id;
+		this.name = name;
+	}
+
+	/**
+	 * 机床已安排的工时
+	 */
+	private double assignedTaskWork;
+	/**
+	 * 利用率
+	 */
+	private double utilRation;
+	/**
+	 * 负荷率
+	 */
+	private double loadRation;
+
+	public String getName() {
+		return name;
+	}
+
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public void setId(long id) {
+		this.id = id;
+	}
+
+	public double getUtilRation() {
+		return utilRation;
+	}
+
+	public void setUtilRation(double utilRation) {
+		this.utilRation = utilRation;
+	}
+
+	public double getLoadRation() {
+		return loadRation;
+	}
+
+	public void setLoadRation(double loadRation) {
+		this.loadRation = loadRation;
+	}
+
+	public TreeSet<Operation> getQueueList() {
+		return queueList;
+	}
+
+	public void setQueueList(TreeSet<Operation> queueList) {
+		this.queueList = queueList;
+	}
+
+	public double getAssignedTaskWork() {
+		return assignedTaskWork;
+	}
+
+	public void setAssignedTaskWork(double assignedTaskWork) {
+		this.assignedTaskWork = assignedTaskWork;
+	}
+
+	public List<String> getNoUseTime() {
+		return noUseTime;
+	}
+
+	public void setNoUseTime(List<String> noUseTime) {
+		this.noUseTime = noUseTime;
+	}
+}

+ 428 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/Operation.java

@@ -0,0 +1,428 @@
+package com.github.zuihou.business.aps.instance.domain.basicdata;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ *
+ * @author: igen
+ * @description: 工序类
+ * @date: 2021年11月29日
+ *
+ */
+public class Operation implements Serializable {
+	/**
+	 * 已分派状态
+	 */
+	public static final int Assigned_State = 1;
+	/**
+	 * 未分派状态
+	 */
+	public static final int Unassigned_state = 0;
+	/**
+	 * 工序号
+	 */
+	private String id;
+	/**
+	 * 零件号
+	 */
+	private String partId;
+	/**
+	 * 零件
+	 */
+	private Part part;
+	/**
+	 * 工序名称
+	 */
+	private String name;
+	/**
+	 * 工序顺序(排序用)
+	 */
+	private int seq;
+	/**
+	 * 准备时间
+	 */
+	private double preTime;
+	/**
+	 * 单件时间
+	 */
+	private double runTime; // 选择工时
+	/**
+	 * 设备编号
+	 */
+	private long machineId; // 选择设备
+	/**
+	 * 固定的机床编号,用于解码时确定已安排的机床(-1表示未被安排机床)
+	 */
+	private int fixedMachineID = -1;
+	/**
+	 * 设备名称
+	 */
+	private String machineName; // 选择设备
+	/**
+	 * 可选设备数量
+	 */
+	private int candidateProNum; // 可选设备数量
+	/**
+	 * 权重
+	 */
+	private double weight;// 权重
+	/**
+	 * 交货期
+	 */
+	private long dueDate;
+	/**
+	 * 最早开始
+	 */
+	private long earlyStart;
+	/**
+	 * 开始
+	 */
+	private long start;
+	/**
+	 * 结束
+	 */
+	private long finish;
+	/**
+	 * 工序预计开始
+	 */
+	private Date earlyStartTime;
+	/**
+	 * 工序预计结束
+	 */
+	private Date earlyEndTime;
+	/**
+	 * 开始
+	 */
+	private Date expectStartTime;
+	/**
+	 * 结束
+	 */
+	private Date expectEndTime;
+	/**
+	 * 计划数,默认为1
+	 */
+	private int planQty = 1;
+	/**
+	 * 前置工序
+	 */
+	private Operation prepOp;
+	/**
+	 * 后置工序
+	 */
+	private Operation SuccOp;
+	/**
+	 * 状态0未调度 1已调度
+	 */
+	private int state;
+	/**
+	 * 剩余工序数
+	 */
+	private int remainOpNum;
+	/**
+	 * 剩余工时
+	 */
+	private double remainWorkTime;
+
+	/**
+	 * 工序优先级
+	 */
+	private double opPriority;
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	/**
+	 * @return the partId
+	 */
+	public String getPartId() {
+		return partId;
+	}
+
+	/**
+	 * @param partId
+	 *            the partId to set
+	 */
+	public void setPartId(String partId) {
+		this.partId = partId;
+	}
+
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @param name
+	 *            the name to set
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return the seq
+	 */
+	public int getSeq() {
+		return seq;
+	}
+
+	/**
+	 * @param seq
+	 *            the seq to set
+	 */
+	public void setSeq(int seq) {
+		this.seq = seq;
+	}
+
+	/**
+	 * @return the preTime
+	 */
+	public double getPreTime() {
+		return preTime;
+	}
+
+	/**
+	 * @param preTime
+	 *            the preTime to set
+	 */
+	public void setPreTime(double preTime) {
+		this.preTime = preTime;
+	}
+
+	/**
+	 * @return the runTime
+	 */
+	public double getRunTime() {
+		return runTime;
+	}
+
+	/**
+	 * @param runTime
+	 *            the runTime to set
+	 */
+	public void setRunTime(double runTime) {
+		this.runTime = runTime;
+	}
+
+	public long getMachineId() {
+		return machineId;
+	}
+
+	public void setMachineId(long machineId) {
+		this.machineId = machineId;
+	}
+
+	/**
+	 * @return the machineName
+	 */
+	public String getMachineName() {
+		return machineName;
+	}
+
+	/**
+	 * @param machineName
+	 *            the machineName to set
+	 */
+	public void setMachineName(String machineName) {
+		this.machineName = machineName;
+	}
+
+	/**
+	 * @return the candidateProNum
+	 */
+	public int getCandidateProNum() {
+		return candidateProNum;
+	}
+
+	/**
+	 * @param candidateProNum
+	 *            the candidateProNum to set
+	 */
+	public void setCandidateProNum(int candidateProNum) {
+		this.candidateProNum = candidateProNum;
+	}
+
+	/**
+	 * @return the dueDate
+	 */
+	public long getDueDate() {
+		return dueDate;
+	}
+
+	/**
+	 * @param dueDate
+	 *            the dueDate to set
+	 */
+	public void setDueDate(long dueDate) {
+		this.dueDate = dueDate;
+	}
+
+	public long getStart() {
+		return start;
+	}
+
+	public void setStart(long start) {
+		this.start = start;
+	}
+
+	public long getFinish() {
+		return finish;
+	}
+
+	public void setFinish(long finish) {
+		this.finish = finish;
+	}
+
+	public double getWeight() {
+		return weight;
+	}
+
+	public void setWeight(double weight) {
+		this.weight = weight;
+	}
+
+	public int getPlanQty() {
+		return planQty;
+	}
+
+	/**
+	 * 临时使用,因为可能对于不同的设备工时不同
+	 *
+	 * @return 下午3:42:57
+	 */
+	public double getWorkTime() {
+		return this.planQty * this.runTime + this.preTime;
+	}
+
+	public void setPlanQty(int planQty) {
+		this.planQty = planQty;
+	}
+
+	public Operation getPrepOp() {
+		return prepOp;
+	}
+
+	public void setPrepOp(Operation prepOp) {
+		this.prepOp = prepOp;
+	}
+
+	public Operation getSuccOp() {
+		return SuccOp;
+	}
+
+	public void setSuccOp(Operation succOp) {
+		SuccOp = succOp;
+	}
+
+	public long getEarlyStart() {
+		return earlyStart;
+	}
+
+	public void setEarlyStart(long earlyStart) {
+		this.earlyStart = earlyStart;
+	}
+
+	public int getState() {
+		return state;
+	}
+
+	public void setState(int state) {
+		this.state = state;
+	}
+
+	public int getRemainOpNum() {
+		return remainOpNum;
+	}
+
+	public void setRemainOpNum(int remainOpNum) {
+		this.remainOpNum = remainOpNum;
+	}
+
+	public double getRemainWorkTime() {
+		return remainWorkTime;
+	}
+
+	public void setRemainWorkTime(double remainWorkTime) {
+		this.remainWorkTime = remainWorkTime;
+	}
+
+	public double getOpPriority() {
+		return opPriority;
+	}
+
+	public void setOpPriority(double opPriority) {
+		this.opPriority = opPriority;
+	}
+
+	public Part getPart() {
+		return part;
+	}
+
+	public void setPart(Part part) {
+		this.part = part;
+	}
+
+	public int getFixedMachineID() {
+		return fixedMachineID;
+	}
+
+	public void setFixedMachineID(int fixedMachineID) {
+		this.fixedMachineID = fixedMachineID;
+	}
+
+	public Date getEarlyStartTime() {
+		return earlyStartTime;
+	}
+
+	public void setEarlyStartTime(Date earlyStartTime) {
+		this.earlyStartTime = earlyStartTime;
+	}
+
+	public Date getEarlyEndTime() {
+		return earlyEndTime;
+	}
+
+	public void setEarlyEndTime(Date earlyEndTime) {
+		this.earlyEndTime = earlyEndTime;
+	}
+
+	public Date getExpectStartTime() {
+		return expectStartTime;
+	}
+
+	public void setExpectStartTime(Date expectStartTime) {
+		this.expectStartTime = expectStartTime;
+	}
+
+	public Date getExpectEndTime() {
+		return expectEndTime;
+	}
+
+	public void setExpectEndTime(Date expectEndTime) {
+		this.expectEndTime = expectEndTime;
+	}
+
+	@Override
+	public String toString() {
+		return "Operation{" +
+				"partId=" + partId +
+				", earlyStart=" + earlyStart +
+				", start=" + start +
+				", finish=" + finish +
+				", expectStartTime=" + expectStartTime +
+				", expectEndTime=" + expectEndTime +
+				", remainOpNum=" + remainOpNum +
+				", remainWorkTime=" + remainWorkTime +
+				", opPriority=" + opPriority +
+				", machineId=" + machineId +
+				'}';
+	}
+}

+ 232 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/basicdata/Part.java

@@ -0,0 +1,232 @@
+package com.github.zuihou.business.aps.instance.domain.basicdata;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @author: igen
+ * @description: 工件类
+ * @date: 2021年11月29日
+ */
+public class Part implements Serializable {
+	/**
+	 * 零件号
+	 */
+	private String id;
+	/**
+	 * 零件名称
+	 */
+	private String name;
+	/**
+	 * 工序总数
+	 */
+	private int operationNum; // 工序数量
+
+	/**
+	 * 紧急插单标记 0 紧急插单 1 正常
+	 */
+	private int rushOrderFlag;
+
+	/**
+	 * 工序列表
+	 */
+	private List<Operation> opList; // 工艺路线
+	/**
+	 * 计划开始
+	 */
+	private double start;
+	/**
+	 * 计划结束
+	 */
+	private double finish;
+	/**
+	 * 权重
+	 */
+	private double weight;// 权重
+	/**
+	 * 交货期
+	 */
+	private double dueDate;// 交货期
+	/**
+	 * 计划数,默认为1
+	 */
+	private int planQty = 1;
+	/**
+	 * 当前工序
+	 */
+	private Operation currOp;
+	/**
+	 * 总工时
+	 */
+	private double totalWorkTime;
+
+	public String getId() {
+		return id;
+	}
+
+	public void setId(String id) {
+		this.id = id;
+	}
+
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @param name
+	 *            the name to set
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * @return the operationNum
+	 */
+	public int getOperationNum() {
+		return operationNum;
+	}
+
+	/**
+	 * @param operationNum
+	 *            the operationNum to set
+	 */
+	public void setOperationNum(int operationNum) {
+		this.operationNum = operationNum;
+	}
+
+	public int getRushOrderFlag() {
+		return rushOrderFlag;
+	}
+
+	public void setRushOrderFlag(int rushOrderFlag) {
+		this.rushOrderFlag = rushOrderFlag;
+	}
+
+	/**
+	 * @return the opList
+	 */
+	public List<Operation> getOpList() {
+		return opList;
+	}
+
+	/**
+	 * @param opList
+	 *            the opList to set
+	 */
+	public void setOpList(List<Operation> opList) {
+		this.opList = opList;
+	}
+
+	/**
+	 * @return the start
+	 */
+	public double getStart() {
+		return start;
+	}
+
+	/**
+	 * @param start
+	 *            the start to set
+	 */
+	public void setStart(double start) {
+		this.start = start;
+	}
+
+	/**
+	 * @return the finish
+	 */
+	public double getFinish() {
+		return finish;
+	}
+
+	/**
+	 * @param finish
+	 *            the finish to set
+	 */
+	public void setFinish(double finish) {
+		this.finish = finish;
+	}
+
+	/**
+	 * @return the weight
+	 */
+	public double getWeight() {
+		return weight;
+	}
+
+	/**
+	 * @param weight
+	 *            the weight to set
+	 */
+	public void setWeight(double weight) {
+		this.weight = weight;
+	}
+
+	/**
+	 * @return the dueDate
+	 */
+	public double getDueDate() {
+		return dueDate;
+	}
+
+	/**
+	 * @param dueDate
+	 *            the dueDate to set
+	 */
+	public void setDueDate(double dueDate) {
+		this.dueDate = dueDate;
+	}
+
+	/**
+	 * @return the planQty
+	 */
+	public int getPlanQty() {
+		return planQty;
+	}
+
+	/**
+	 * @param planQty
+	 *            the planQty to set
+	 */
+	public void setPlanQty(int planQty) {
+		this.planQty = planQty;
+	}
+
+	public Operation getCurrOp() {
+		return currOp;
+	}
+
+	public void setCurrOp(Operation currOp) {
+		this.currOp = currOp;
+	}
+
+	public double getTotalWorkTime() {
+		return totalWorkTime;
+	}
+
+	public void setTotalWorkTime(double totalWorkTime) {
+		this.totalWorkTime = totalWorkTime;
+	}
+
+	@Override
+	public String toString() {
+		return "Part{" +
+				"id=" + id +
+				", name='" + name + '\'' +
+				", operationNum=" + operationNum +
+				", rushOrderFlag=" + rushOrderFlag +
+				", opList=" + opList +
+				", start=" + start +
+				", finish=" + finish +
+				", weight=" + weight +
+				", dueDate=" + dueDate +
+				", planQty=" + planQty +
+				", currOp=" + currOp +
+				", totalWorkTime=" + totalWorkTime +
+				'}';
+	}
+}

+ 58 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/objective/Objective.java

@@ -0,0 +1,58 @@
+package com.github.zuihou.business.aps.instance.domain.objective;
+
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+
+/**
+ * @author: igen
+ * @description:调度目标基类
+ * @date: 2021年11月29日
+ */
+public class Objective {
+	/**
+	 * 目标名称
+	 */
+	public String objectiveName;
+	/**
+	 * 目标值
+	 */
+	public double objectiveValue;
+	/**
+	 * 上次目标值(用于单步调度)
+	 */
+	public double lastObjectiveValue;
+
+	/**
+	 * @author: igen
+	 * @description:计算目标值
+	 * @param instance
+	 * @date: 2021年11月29日
+	 * @return
+	 */
+	public double calcValue(Instance instance) {
+		return this.objectiveValue;
+	}
+
+	public String getObjectiveName() {
+		return objectiveName;
+	}
+
+	public void setObjectiveName(String objectiveName) {
+		this.objectiveName = objectiveName;
+	}
+
+	public double getObjectiveValue() {
+		return objectiveValue;
+	}
+
+	public void setObjectiveValue(double objectiveValue) {
+		this.objectiveValue = objectiveValue;
+	}
+
+	public double getLastObjectiveValue() {
+		return lastObjectiveValue;
+	}
+
+	public void setLastObjectiveValue(double lastObjectiveValue) {
+		this.lastObjectiveValue = lastObjectiveValue;
+	}
+}

+ 30 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/objective/ObjectiveCmax.java

@@ -0,0 +1,30 @@
+package com.github.zuihou.business.aps.instance.domain.objective;
+
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Operation;
+
+/**
+ * @author: igen
+ * @description:制造期目标
+ * @date: 2021年11月29日
+ *
+ */
+public class ObjectiveCmax extends Objective {
+
+	@Override
+	public double calcValue(Instance instance) {
+		double value = 0;
+		for (Operation operation : instance.getOperationMap().values()) {
+			if (operation.getFinish() > value) {
+				value = operation.getFinish();
+			}
+		}
+		this.objectiveValue = value;
+		return value;
+	}
+
+	public ObjectiveCmax() {
+		super();
+		this.objectiveName = "制造期(Cmax)";
+	}
+}

+ 98 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/solution/InstanceSolution.java

@@ -0,0 +1,98 @@
+package com.github.zuihou.business.aps.instance.domain.solution;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @author: igen
+ * @description: 案例调度结果类
+ * @date: 2021年11月29日
+ */
+public class InstanceSolution {
+	SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+	/**
+	 * 创建时间
+	 */
+	private String creteTime = formatter.format(new Date());
+	/**
+	 * 案例名称
+	 */
+	private String instanceName;
+	/**
+	 * 算法名称
+	 */
+	private String algorithmName;
+	/**
+	 * 目标数量,默认为单目标
+	 */
+	private int objectiveNum = 1;
+	/**
+	 * 调度结果数组
+	 */
+	private double[] objectives = new double[objectiveNum];
+	/**
+	 * 求解时间(分钟)
+	 */
+	private double calcTime;
+
+	/**
+	 * 默认构造函数
+	 */
+	public InstanceSolution() {
+
+	}
+
+	/**
+	 * 设置目标个数的构造函数
+	 *
+	 * @param objectiveNum
+	 */
+	public InstanceSolution(int objectiveNum) {
+		this.objectiveNum = objectiveNum;
+	}
+
+	public String getInstanceName() {
+		return instanceName;
+	}
+
+	public void setInstanceName(String instanceName) {
+		this.instanceName = instanceName;
+	}
+
+	public String getAlgorithmName() {
+		return algorithmName;
+	}
+
+	public void setAlgorithmName(String algorithmName) {
+		this.algorithmName = algorithmName;
+	}
+
+	public int getObjectiveNum() {
+		return objectiveNum;
+	}
+
+	public void setObjectiveNum(int objectiveNum) {
+		this.objectiveNum = objectiveNum;
+		objectives = new double[objectiveNum];
+	}
+
+	public double[] getObjectives() {
+		return objectives;
+	}
+
+	public void setObjectives(double[] objectives) {
+		this.objectives = objectives;
+	}
+
+	public double getCalcTime() {
+		return calcTime;
+	}
+
+	public void setCalcTime(double calcTime) {
+		this.calcTime = calcTime;
+	}
+
+	public String getCreteTime() {
+		return creteTime;
+	}
+}

+ 119 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/domain/solution/InstanceSolutionStep.java

@@ -0,0 +1,119 @@
+package com.github.zuihou.business.aps.instance.domain.solution;
+
+import java.util.List;
+
+/**
+ * @author: igen
+ * @description: 调度案例单步调度结果,即已安排的什么任务,在什么机床上,开始和结束时间是多少
+ * @date: 2021年11月29日
+ */
+public class InstanceSolutionStep {
+	/**
+	 * 任务号
+	 */
+	private String taskUid;
+	/**
+	 * 任务名称
+	 */
+	private String taskName;
+	/**
+	 * 开始时间
+	 */
+	private double start;
+	/**
+	 * 结束时间
+	 */
+	private double end;
+	/**
+	 * 设备索引
+	 */
+	private int deviceIndex;
+	/**
+	 * 机床总数
+	 */
+	private int machineNum;
+	/**
+	 * 颜色
+	 */
+	private String color;
+	/**
+	 * 状态值
+	 */
+	private List state;
+	/**
+	 * 当前目标值
+	 */
+	private double currObjective;
+
+	public String getTaskUid() {
+		return taskUid;
+	}
+
+	public void setTaskUid(String taskUid) {
+		this.taskUid = taskUid;
+	}
+
+	public String getTaskName() {
+		return taskName;
+	}
+
+	public void setTaskName(String taskName) {
+		this.taskName = taskName;
+	}
+
+	public double getStart() {
+		return start;
+	}
+
+	public void setStart(double start) {
+		this.start = start;
+	}
+
+	public double getEnd() {
+		return end;
+	}
+
+	public void setEnd(double end) {
+		this.end = end;
+	}
+
+	public int getDeviceIndex() {
+		return deviceIndex;
+	}
+
+	public void setDeviceIndex(int deviceIndex) {
+		this.deviceIndex = deviceIndex;
+	}
+
+	public String getColor() {
+		return color;
+	}
+
+	public void setColor(String color) {
+		this.color = color;
+	}
+
+	public int getMachineNum() {
+		return machineNum;
+	}
+
+	public void setMachineNum(int machineNum) {
+		this.machineNum = machineNum;
+	}
+
+	public double getCurrObjective() {
+		return currObjective;
+	}
+
+	public void setCurrObjective(double currObjective) {
+		this.currObjective = currObjective;
+	}
+
+	public List getState() {
+		return state;
+	}
+
+	public void setState(List state) {
+		this.state = state;
+	}
+}

+ 241 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/manager/AssignManager.java

@@ -0,0 +1,241 @@
+package com.github.zuihou.business.aps.instance.manager;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.github.zuihou.business.aps.instance.domain.basicdata.*;
+import com.github.zuihou.business.aps.instance.manager.iface.AssignManagerIface;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.List;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author: igen
+ * @description: 工序分配管理器
+ * @date: 2021年11月29日
+ *
+ */
+public class AssignManager implements AssignManagerIface {
+	private final static Log log = LogFactory.getLog(AssignManager.class);
+
+	/**
+	 *
+	 * @author: igen
+	 * @description:将工序安排到机床,默认采用插空方式
+	 * @param instance
+	 * @param operation
+	 * @param insert
+	 * @throws Exception
+	 * @date: 2021年11月29日
+	 *
+	 */
+	protected void assignOrderOperation(Instance instance, Operation operation, boolean insert) throws Exception {
+		// 寻找可选机床
+		List<CandidateProcess> candidateProcesses = instance.getCandidateProMap().get(operation.getPartId() + "_" + operation.getName());
+		Machine machine = null;
+		CandidateProcess candidateProcess = null;
+		// 只有一台可用机床或者优先指定了一台使用的情况,则直接分派
+		if (candidateProcesses.size() == 1) {
+			machine = instance.getMachineMap().get("M" + candidateProcesses.get(0).getMachineId());
+			candidateProcess = candidateProcesses.get(0);
+		} else {
+			// 多于一台机床的情况(如并行机或柔性作业车间调度,每次随机取一台)
+			candidateProcess = candidateProcesses.get((int)(Math.random() * candidateProcesses.size()));
+			machine = instance.getMachineMap().get("M" + candidateProcess.getMachineId());
+		}
+		operation.setMachineId(machine.getId());
+		operation.setMachineName(machine.getName());
+		// 如果机床没有安排任何任务,则直接安排
+		if (machine.getQueueList().size() == 0) {
+			// 计划开始为最早开始
+			operation.setStart(operation.getEarlyStart());
+			operation.setFinish(DateUtil.offsetMinute(new DateTime(DateUtil.current(false)),new Long(candidateProcess.getDuration()).intValue()).getTime());
+		} else {
+			findMachineSpace(operation, candidateProcess, machine,instance.getCalcBeginDate(), insert);
+		}
+		// 将工序添加到机床的队列中
+		machine.getQueueList().add(operation);
+		machine.setAssignedTaskWork(machine.getAssignedTaskWork() + candidateProcess.getDuration());
+		instance.setTotalAssignedTaskWork(instance.getTotalAssignedTaskWork() + candidateProcess.getDuration());
+		afterAssign(instance, operation);
+		if (machine == null) {
+			log.error("无可选机床!");
+			throw new Exception(operation.getName() + "无可选机床");
+		}
+	}
+
+
+	/**
+	 *
+	 * @author: igen
+	 * @description: 任务分派后处理,将任务从就绪任务集合中移除,设置工件的当前工序
+	 * @param instance
+	 * @param operation
+	 * @date: 2021年11月29日
+	 *
+	 */
+	@Override
+	public void afterAssign(Instance instance, Operation operation) throws Exception {
+		TreeSet<Operation> readyTasks = instance.getReadyTaskS();
+		operation.setState(Operation.Assigned_State);
+		// if (readyTasks.contains(operation)) {
+		readyTasks.remove(operation);
+		Operation nextOp = operation.getSuccOp();
+		Part part = instance.getPartMap().get(operation.getPartId());
+		part.setCurrOp(nextOp);
+		if (nextOp != null) {
+			readyTasks.add(nextOp);
+		} else {
+			// 设置工序结束时间为工件结束时间
+			part.setFinish(operation.getFinish());
+		}
+		// }
+		instance.getObjective().calcValue(instance);
+	}
+
+	/**
+	 *
+	 * @author: igen
+	 * @description:判断机床的空隙是否可以放下当前空虚
+	 * @param operation
+	 * @param formerOp
+	 *            机床上的前一道工序
+	 * @param latterOp
+	 *            机床上的后一道工序
+	 * @param machine
+	 *            设备信息
+	 * @return boolean
+	 * @date: 2021年11月29日
+	 *
+	 */
+	private boolean insertMachineOepration(Operation operation, Operation formerOp, Operation latterOp, Machine machine) {
+		// TODO Auto-generated method stub
+		long start = 0;
+		long finish = 0;
+		long workTime = operation.getFinish() - operation.getStart();
+		if (latterOp == null) {
+			start = operation.getStart() > formerOp.getFinish() ? operation.getStart() : formerOp.getFinish();
+			finish = start + workTime;
+			operation.setStart(start);
+			operation.setFinish(finish);
+			return true;
+		}
+		if (latterOp.getStart() < operation.getFinish()) {
+			return false;
+		}
+		start = operation.getStart() > formerOp.getFinish() ? operation.getStart() : formerOp.getFinish();
+		if (latterOp.getStart() - start >= workTime) {
+			operation.setStart(start);
+			operation.setFinish(start + workTime);
+			return true;
+		} else {
+			return false;
+		}
+	}
+
+	/**
+	 * @author: igen
+	 * @description:插空处理,如果机床上没有安排任务,则工序可以从最早开始加工,如果有任务,则从第一个任务开始一次寻找空隙
+	 * @param operation
+	 * @param candidateProcess
+	 * @param machine
+	 * @param insert
+	 * @date: 2021年11月29日
+	 */
+	private void findMachineSpace(Operation operation, CandidateProcess candidateProcess, Machine machine, long calcBeginDate, boolean insert) {
+		// 如果有任务了则需要判断插空
+		long earlyStart = operation.getEarlyStart();
+		long earlyFinish = DateUtil.offsetMinute(new DateTime(DateUtil.current(false)),new Double(candidateProcess.getDuration()).intValue()).getTime();
+		boolean findSpace = false;
+		Operation tempOp = new Operation();
+		Operation formerOp = null;
+		Operation latterOp = null;
+		tempOp.setStart(earlyStart);
+		tempOp.setFinish(earlyFinish);
+		int findIndex = 0;
+		// 只有需要插空时才寻找空隙
+		if (insert) {
+			while (!findSpace) {
+				if (findIndex == 0) {
+					// 第一次查找时使用一个虚拟工序
+					Operation virOp = new Operation();
+					virOp.setStart(calcBeginDate);
+					virOp.setFinish(calcBeginDate);
+					formerOp = virOp;
+					latterOp = machine.getQueueList().first();
+				}
+				findSpace = insertMachineOepration(tempOp, formerOp, latterOp, machine);
+				if (!findSpace) {
+					tempOp.setStart(latterOp.getFinish() > earlyStart ? latterOp.getFinish() : earlyStart);
+					tempOp.setFinish(DateUtil.offsetMinute(new DateTime(tempOp.getStart()),new Double(candidateProcess.getDuration()).intValue()).getTime());
+					formerOp = latterOp;
+					latterOp = machine.getQueueList().higher(latterOp);
+				} else {
+					operation.setStart(tempOp.getStart());
+					operation.setFinish(DateUtil.offsetMinute(new DateTime(operation.getStart()),new Double(candidateProcess.getDuration()).intValue()).getTime());
+				}
+				findIndex++;
+			}
+		} else {
+			// 不插空则直接选择机床上最后一道工序和工序前置工序的完成时间的较大值作为开始
+			latterOp = machine.getQueueList().last();
+			long startTime = latterOp.getFinish() > operation.getEarlyStart() ? latterOp.getFinish()
+					: operation.getEarlyStart();
+			operation.setStart(startTime);
+			operation.setFinish(DateUtil.offsetMinute(new DateTime(startTime),new Double(candidateProcess.getDuration()).intValue()).getTime());
+		}
+	}
+
+	/**
+	 * @author: yejian
+	 * @description: 计算工序的最早开始
+	 * @param instance
+	 * @param operation
+	 * @date: 2021年11月29日
+	 */
+	private void calOperationEarlyStart(Instance instance, Operation operation) {
+		// 计算最早开始,目的是从该时间起在设备上寻找插空,如果是工件的首道工序,则为0
+		if (null == operation.getPrepOp()) {
+			operation.setEarlyStart(instance.getCalcBeginDate());
+		} else {
+			Operation predOp = operation.getPrepOp();
+			operation.setEarlyStart(predOp.getFinish());
+			if (predOp.getMachineId() == -1) {
+				log.error("前置工序" + predOp.getName() + "未分派成功!");
+			}
+		}
+	}
+
+	/**
+	 * @author: yejian
+	 * @description 不考虑插空的分派
+	 * @param instance
+	 * @param operation
+	 * @param insert
+	 * @date: 2021年11月29日
+	 */
+	public void assignTask(Instance instance, Operation operation, boolean insert) {
+		// 计算最早开始
+		calOperationEarlyStart(instance, operation);
+		// 分派任务
+		try {
+			assignOrderOperation(instance, operation, insert);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+
+	/**
+	 * @author: igen
+	 * @description: 默认执行插空
+	 * @param instance
+	 * @param operation
+	 * @date: 2021年11月29日
+	 *
+	 */
+	public void assignTask(Instance instance, Operation operation) {
+		assignTask(instance, operation, true);
+	}
+}

+ 89 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/manager/ScheduleManager.java

@@ -0,0 +1,89 @@
+package com.github.zuihou.business.aps.instance.manager;
+
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Machine;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Operation;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Part;
+import com.github.zuihou.business.aps.instance.manager.iface.ScheduleManagerIface;
+import com.github.zuihou.business.aps.rule.OperationPriority;
+import com.github.zuihou.business.aps.util.InstanceUtil;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.util.Comparator;
+import java.util.TreeSet;
+
+/**
+ *
+ * @author: igen
+ * @description: 案例调度管理器,所有的算法均以此为入口
+ * @date: 2021年11月29日
+ *
+ */
+public class ScheduleManager implements ScheduleManagerIface {
+	public AssignManager assignManager = new AssignManager();
+
+	private final static Log log = LogFactory.getLog(ScheduleManager.class);
+
+	@Override
+	public void schedule(Instance instance, int mode) throws Exception {
+		this.initReadyTasks(instance);
+		// 只要就绪任务集合不为空,则继续安排
+		while (!instance.getReadyTaskS().isEmpty()) {
+			// 获得最优先的任务
+			Operation operation = instance.getReadyTaskS().first();
+			// 分派任务
+			assignManager.assignTask(instance, operation);
+		}
+	}
+
+	@Override
+	public void beforeSchedule(Instance instance, int mode) throws Exception {
+		instance.init();
+		instance.reset();
+	}
+
+
+	@Override
+	public void afterSchedule(Instance instance, int mode) throws Exception {
+		// 设置工件的开始和结束
+		for (Part part : instance.getPartMap().values()) {
+			if (part.getOpList().size() > 0) {
+				int opNum = part.getOpList().size();
+				part.setStart(part.getOpList().get(0).getStart());
+				part.setFinish(part.getOpList().get(opNum - 1).getFinish());
+			}
+		}
+		double cmax = InstanceUtil.calcCmax(instance);
+
+		// 结果输出
+		// 利用率计算
+		for (Machine machine : instance.getMachineMap().values()) {
+			double util = 0;
+			double load = 0;
+			for (Operation operation : machine.getQueueList()) {
+				load += operation.getWorkTime();
+				util += operation.getRunTime() * operation.getPlanQty();
+			}
+			double loadRation = load / cmax;
+			double utilRation = util / cmax;
+			machine.setUtilRation(utilRation);
+			machine.setLoadRation(loadRation);
+		}
+		instance.getObjective().calcValue(instance);
+	}
+
+	@Override
+	public void initReadyTasks(Instance instance) throws Exception {
+		Comparator<Operation> operationTaskComparator = instance.getOperationComparator();
+		if (operationTaskComparator == null) {
+			operationTaskComparator = new OperationPriority();
+		}
+		// 设置工序优先级比较器
+		TreeSet<Operation> readyTaskS = new TreeSet<Operation>(operationTaskComparator);
+		// 重新排序
+		readyTaskS.addAll(instance.getReadyTaskS());
+		instance.setReadyTaskS(readyTaskS);
+	}
+
+}

+ 22 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/manager/iface/AssignManagerIface.java

@@ -0,0 +1,22 @@
+package com.github.zuihou.business.aps.instance.manager.iface;
+
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Operation;
+
+/**
+ * @author: igen
+ * @description: 工序分派管理器接口
+ * @date: 2021年11月29日
+ */
+public interface AssignManagerIface {
+
+	/**
+	 * @author: igen
+	 * @description: 工序分派后处理
+	 * @param operation
+	 * @throws Exception
+	 * @date: 2021年11月29日
+	 */
+	public void afterAssign(Instance instance, Operation operation) throws Exception;
+
+}

+ 52 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/instance/manager/iface/ScheduleManagerIface.java

@@ -0,0 +1,52 @@
+package com.github.zuihou.business.aps.instance.manager.iface;
+
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+
+/**
+ * @author: igen
+ * @description: 调度管理器接口
+ * @date: 2021年11月29日
+ */
+public interface ScheduleManagerIface {
+	/**
+	 *
+	 * @author: igen
+	 * @description: 按照不同的模式进行调度
+	 * @param instance
+	 * @param mode 模式(针对具有学习功能的算法,通过该值可以确定是离线训练还是在线应用)
+	 * @date: 2021年11月29日
+	 */
+	public void schedule(Instance instance, int mode) throws Exception;
+
+	/**
+	 * @author: igen
+	 * @description: 调度前处理
+	 * @param instance
+	 * @param mode
+	 * @throws Exception
+	 * @date: 2021年11月29日
+	 *
+	 */
+	public void beforeSchedule(Instance instance, int mode) throws Exception;
+
+	/**
+	 * @author: igen
+	 * @description: 调度后处理
+	 * @param instance
+	 * @param mode
+	 * @throws Exception
+	 * @date: 2021年11月29日
+	 *
+	 */
+	public void afterSchedule(Instance instance, int mode) throws Exception;
+
+	/**
+	 * @author: igen
+	 * @description:调度就绪任务初始化
+	 * @param instance
+	 * @throws Exception
+	 * @date: 2021年11月29日
+	 *
+	 */
+	public void initReadyTasks(Instance instance) throws Exception;
+}

+ 49 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/rule/OperationPriority.java

@@ -0,0 +1,49 @@
+package com.github.zuihou.business.aps.rule;
+
+import com.github.zuihou.business.aps.instance.domain.basicdata.Operation;
+import com.github.zuihou.business.aps.rule.basic.OperationRule;
+
+import java.io.Serializable;
+import java.util.Comparator;
+
+/**
+ * 优先级规则,工件优先级越小越优先
+ *
+ * @author igen
+ *
+ */
+public class OperationPriority extends OperationRule implements Comparator<Operation>, Serializable {
+	public OperationPriority() {
+		super(0, "PRIORITY");
+	}
+
+	@Override
+	public int compare(Operation operTask1, Operation operTask2) {
+		if (operTask1.equals(operTask2)) {
+			return 0;
+		}
+		int i = -1;
+		try {
+			// 优先级数值越小越优先
+			// 先根据是否插单的排序,在根据交期排序,最后按照遗传算法基因(优先级)排序
+			if(operTask1.getPart().getRushOrderFlag() > operTask2.getPart().getRushOrderFlag()){
+				i = 1;
+			}else if(operTask1.getPart().getRushOrderFlag() == operTask2.getPart().getRushOrderFlag()){
+				if (operTask1.getPart().getDueDate() > operTask2.getPart().getDueDate()) {
+					i = 1;
+				}else if(operTask1.getPart().getDueDate() == operTask2.getPart().getDueDate()){
+					if (operTask1.getOpPriority() > operTask2.getOpPriority()) {
+						i = 1;
+					}else if (operTask1.getOpPriority() == operTask2.getOpPriority()) {
+						if (operTask1.getWorkTime() > operTask2.getWorkTime()) {
+							i = 1;
+						}
+					}
+				}
+			}
+		} catch (RuntimeException e) {
+			e.printStackTrace();
+		}
+		return i;
+	}
+}

+ 52 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/rule/basic/OperationRule.java

@@ -0,0 +1,52 @@
+package com.github.zuihou.business.aps.rule.basic;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Operation;
+import java.util.Comparator;
+
+/**
+ * @author: igen
+ * @description: 工序排序规则接口
+ * @date: 2019年12月18日
+ *
+ */
+public class OperationRule implements Comparator<Operation> {
+	/**
+	 * 规则序号
+	 */
+	public int ruleID;
+	/**
+	 * 规则名称
+	 */
+	public String ruleName;
+
+	public OperationRule() {
+		super();
+	}
+
+	public OperationRule(int ruleID, String ruleName) {
+		super();
+		this.ruleID = ruleID;
+		this.ruleName = ruleName;
+	}
+
+	public int getRuleID() {
+		return ruleID;
+	}
+
+	public void setRuleID(int ruleID) {
+		this.ruleID = ruleID;
+	}
+
+	public String getRuleName() {
+		return ruleName;
+	}
+
+	public void setRuleName(String ruleName) {
+		this.ruleName = ruleName;
+	}
+
+	@Override
+	public int compare(Operation o1, Operation o2) {
+		return 0;
+	}
+
+}

+ 741 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/aps/util/InstanceUtil.java

@@ -0,0 +1,741 @@
+package com.github.zuihou.business.aps.util;
+
+import com.alibaba.fastjson.JSON;
+import com.github.zuihou.business.aps.algorithm.ga.GAScheduler;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Instance;
+import com.github.zuihou.business.aps.instance.domain.basicdata.Part;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * @author: igen
+ * @description: 案例相关工具类,用于设置案例规则,获取调度规则使用的特征等。
+ * @date: 2021年11月29日
+ *
+ */
+public class InstanceUtil {
+	private final static Log log = LogFactory.getLog(InstanceUtil.class);
+
+	/**
+	 *
+	 * @author: igen
+	 * @description: 计算制造期
+	 * @param instance
+	 * @return
+	 * @date: 2021年11月29日
+	 *
+	 */
+	public static double calcCmax(Instance instance) {
+		double cmax = 0;
+		for (Part part : instance.getPartMap().values()) {
+			if (part.getFinish() > cmax) {
+				cmax = part.getFinish();
+			}
+		}
+		return cmax;
+	}
+
+	public static void main(String[] args) throws Exception {
+		String data = "{\n" +
+				"    \"index\": 1,\n" +
+				"    \"instanceUid\": null,\n" +
+				"    \"instanceType\": 0,\n" +
+				"    \"name\": null,\n" +
+				"    \"totalWorkTime\": null,\n" +
+				"    \"totalOpNum\": 9.0,\n" +
+				"    \"partNum\": 3,\n" +
+				"    \"machineNum\": 3,\n" +
+				"    \"meanOpMachineNum\": 0.0,\n" +
+				"    \"candidateProMap\": {\n" +
+				"        \"P1_OP10\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 1,\n" +
+				"                \"duration\": 5.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 5.0,\n" +
+				"                \"machineName\": \"M1\"\n" +
+				"            },\n" +
+				"            {\n" +
+				"                \"machineID\": 4,\n" +
+				"                \"duration\": 4.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 4.0,\n" +
+				"                \"machineName\": \"M4\"\n" +
+				"            }\n" +
+				"        ],\n" +
+				"        \"P1_OP20\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 2,\n" +
+				"                \"duration\": 9.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 9.0,\n" +
+				"                \"machineName\": \"M2\"\n" +
+				"            }\n" +
+				"        ],\n" +
+				"        \"P1_OP30\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 3,\n" +
+				"                \"duration\": 4.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 4.0,\n" +
+				"                \"machineName\": \"M3\"\n" +
+				"            }\n" +
+				"        ],\n" +
+				"        \"P2_OP10\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 1,\n" +
+				"                \"duration\": 3.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 3.0,\n" +
+				"                \"machineName\": \"M1\"\n" +
+				"            },\n" +
+				"            {\n" +
+				"                \"machineID\": 4,\n" +
+				"                \"duration\": 4.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 4.0,\n" +
+				"                \"machineName\": \"M4\"\n" +
+				"            }\n" +
+				"        ],\n" +
+				"        \"P2_OP20\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 2,\n" +
+				"                \"duration\": 4.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 4.0,\n" +
+				"                \"machineName\": \"M2\"\n" +
+				"            }\n" +
+				"        ],\n" +
+				"        \"P2_OP30\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 3,\n" +
+				"                \"duration\": 11.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 11.0,\n" +
+				"                \"machineName\": \"M3\"\n" +
+				"            }\n" +
+				"        ],\n" +
+				"        \"P3_OP10\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 1,\n" +
+				"                \"duration\": 8.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 8.0,\n" +
+				"                \"machineName\": \"M1\"\n" +
+				"            },\n" +
+				"            {\n" +
+				"                \"machineID\": 4,\n" +
+				"                \"duration\": 4.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 4.0,\n" +
+				"                \"machineName\": \"M4\"\n" +
+				"            }\n" +
+				"        ],\n" +
+				"        \"P3_OP20\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 2,\n" +
+				"                \"duration\": 5.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 5.0,\n" +
+				"                \"machineName\": \"M2\"\n" +
+				"            }\n" +
+				"        ],\n" +
+				"        \"P3_OP30\": [\n" +
+				"            {\n" +
+				"                \"machineID\": 3,\n" +
+				"                \"duration\": 2.0,\n" +
+				"                \"setupTime\": 0.0,\n" +
+				"                \"runTime\": 2.0,\n" +
+				"                \"machineName\": \"M3\"\n" +
+				"            }\n" +
+				"        ]\n" +
+				"    },\n" +
+				"    \"operationMap\": {\n" +
+				"        \"P1_OP10\": {\n" +
+				"            \"partID\": 1,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P1\",\n" +
+				"            \"seq\": 1,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        },\n" +
+				"        \"P1_OP20\": {\n" +
+				"            \"partID\": 1,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P1\",\n" +
+				"            \"seq\": 2,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        },\n" +
+				"        \"P1_OP30\": {\n" +
+				"            \"partID\": 1,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P1\",\n" +
+				"            \"seq\": 3,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        },\n" +
+				"        \"P2_OP10\": {\n" +
+				"            \"partID\": 2,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P2\",\n" +
+				"            \"seq\": 1,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        },\n" +
+				"        \"P2_OP20\": {\n" +
+				"            \"partID\": 2,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P2\",\n" +
+				"            \"seq\": 2,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        },\n" +
+				"        \"P2_OP30\": {\n" +
+				"            \"partID\": 2,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P2\",\n" +
+				"            \"seq\": 3,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        },\n" +
+				"        \"P3_OP10\": {\n" +
+				"            \"partID\": 3,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P3\",\n" +
+				"            \"seq\": 1,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        },\n" +
+				"        \"P3_OP20\": {\n" +
+				"            \"partID\": 3,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P3\",\n" +
+				"            \"seq\": 2,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        },\n" +
+				"        \"P3_OP30\": {\n" +
+				"            \"partID\": 3,\n" +
+				"            \"part\": null,\n" +
+				"            \"name\": \"P3\",\n" +
+				"            \"seq\": 3,\n" +
+				"            \"preTime\": 0.0,\n" +
+				"            \"runTime\": 0.0,\n" +
+				"            \"machineID\": 0,\n" +
+				"            \"fixedMachineID\": -1,\n" +
+				"            \"machineName\": null,\n" +
+				"            \"candidateProNum\": 1,\n" +
+				"            \"weight\": 0.0,\n" +
+				"            \"dueDate\": 0,\n" +
+				"            \"earlyStart\": 0.0,\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"prepOp\": null,\n" +
+				"            \"state\": 0,\n" +
+				"            \"remainOpNum\": 0,\n" +
+				"            \"remainWorkTime\": 0.0,\n" +
+				"            \"opPriority\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"workTime\": 0.0,\n" +
+				"            \"succOp\": null\n" +
+				"        }\n" +
+				"    },\n" +
+				"    \"machineMap\": {\n" +
+				"        \"M1\": {\n" +
+				"            \"name\": \"M1\",\n" +
+				"            \"queueList\": [\n" +
+				"                \n" +
+				"            ],\n" +
+				"            \"assignedTaskWork\": 0.0,\n" +
+				"            \"utilRation\": 0.0,\n" +
+				"            \"loadRation\": 0.0,\n" +
+				"            \"id\": 1,\n" +
+				"            \"noUseTime\": [\n" +
+				"                \n" +
+				"            ]\n" +
+				"        },\n" +
+				"        \"M2\": {\n" +
+				"            \"name\": \"M2\",\n" +
+				"            \"queueList\": [\n" +
+				"                \n" +
+				"            ],\n" +
+				"            \"assignedTaskWork\": 0.0,\n" +
+				"            \"utilRation\": 0.0,\n" +
+				"            \"loadRation\": 0.0,\n" +
+				"            \"id\": 2,\n" +
+				"            \"noUseTime\": [\n" +
+				"                \n" +
+				"            ]\n" +
+				"        },\n" +
+				"        \"M3\": {\n" +
+				"            \"name\": \"M3\",\n" +
+				"            \"queueList\": [\n" +
+				"                \n" +
+				"            ],\n" +
+				"            \"assignedTaskWork\": 0.0,\n" +
+				"            \"utilRation\": 0.0,\n" +
+				"            \"loadRation\": 0.0,\n" +
+				"            \"id\": 3,\n" +
+				"            \"noUseTime\": [\n" +
+				"                \n" +
+				"            ]\n" +
+				"        },\n" +
+				"        \"M4\": {\n" +
+				"            \"name\": \"M4\",\n" +
+				"            \"queueList\": [\n" +
+				"                \n" +
+				"            ],\n" +
+				"            \"assignedTaskWork\": 0.0,\n" +
+				"            \"utilRation\": 0.0,\n" +
+				"            \"loadRation\": 0.0,\n" +
+				"            \"id\": 4,\n" +
+				"            \"noUseTime\": [\n" +
+				"                \n" +
+				"            ]\n" +
+				"        }\n" +
+				"    },\n" +
+				"    \"partMap\": {\n" +
+				"        \"P1\": {\n" +
+				"            \"id\": 1,\n" +
+				"            \"name\": \"P1\",\n" +
+				"            \"operationNum\": 3,\n" +
+				"            \"rushOrderFlag\": 1,\n" +
+				"            \"opList\": [\n" +
+				"                {\n" +
+				"                    \"partID\": 1,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P1_OP10\",\n" +
+				"                    \"seq\": 1,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": 4,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 1,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                },\n" +
+				"                {\n" +
+				"                    \"partID\": 1,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P1_OP20\",\n" +
+				"                    \"seq\": 2,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": -1,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 2,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                },\n" +
+				"                {\n" +
+				"                    \"partID\": 1,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P1_OP30\",\n" +
+				"                    \"seq\": 3,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": -1,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 3,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                }\n" +
+				"            ],\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"weight\": 2.0,\n" +
+				"            \"dueDate\": 15,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"currOp\": null,\n" +
+				"            \"totalWorkTime\": 0.0\n" +
+				"        },\n" +
+				"        \"P2\": {\n" +
+				"            \"id\": 2,\n" +
+				"            \"name\": \"P2\",\n" +
+				"            \"operationNum\": 3,\n" +
+				"            \"rushOrderFlag\": 1,\n" +
+				"            \"opList\": [\n" +
+				"                {\n" +
+				"                    \"partID\": 2,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P2_OP10\",\n" +
+				"                    \"seq\": 1,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": 1,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 1,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                },\n" +
+				"                {\n" +
+				"                    \"partID\": 2,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P2_OP20\",\n" +
+				"                    \"seq\": 2,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": -1,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 2,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                },\n" +
+				"                {\n" +
+				"                    \"partID\": 2,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P2_OP30\",\n" +
+				"                    \"seq\": 3,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": -1,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 3,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                }\n" +
+				"            ],\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"weight\": 5.0,\n" +
+				"            \"dueDate\": 8,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"currOp\": null,\n" +
+				"            \"totalWorkTime\": 0.0\n" +
+				"        },\n" +
+				"        \"P3\": {\n" +
+				"            \"id\": 3,\n" +
+				"            \"name\": \"P3\",\n" +
+				"            \"operationNum\": 3,\n" +
+				"            \"rushOrderFlag\": 0,\n" +
+				"            \"opList\": [\n" +
+				"                {\n" +
+				"                    \"partID\": 3,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P3_OP10\",\n" +
+				"                    \"seq\": 1,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": 4,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 1,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                },\n" +
+				"                {\n" +
+				"                    \"partID\": 3,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P3_OP20\",\n" +
+				"                    \"seq\": 2,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": -1,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 2,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                },\n" +
+				"                {\n" +
+				"                    \"partID\": 3,\n" +
+				"                    \"part\": null,\n" +
+				"                    \"name\": \"P3_OP30\",\n" +
+				"                    \"seq\": 3,\n" +
+				"                    \"preTime\": 0.0,\n" +
+				"                    \"runTime\": 0.0,\n" +
+				"                    \"machineID\": 0,\n" +
+				"                    \"fixedMachineID\": -1,\n" +
+				"                    \"machineName\": null,\n" +
+				"                    \"candidateProNum\": 1,\n" +
+				"                    \"weight\": 0.0,\n" +
+				"                    \"dueDate\": 0,\n" +
+				"                    \"earlyStart\": 0.0,\n" +
+				"                    \"start\": 0.0,\n" +
+				"                    \"finish\": 0.0,\n" +
+				"                    \"planQty\": 1,\n" +
+				"                    \"prepOp\": null,\n" +
+				"                    \"state\": 0,\n" +
+				"                    \"remainOpNum\": 0,\n" +
+				"                    \"remainWorkTime\": 0.0,\n" +
+				"                    \"opPriority\": 0.0,\n" +
+				"                    \"id\": 3,\n" +
+				"                    \"workTime\": 0.0,\n" +
+				"                    \"succOp\": null\n" +
+				"                }\n" +
+				"            ],\n" +
+				"            \"start\": 0.0,\n" +
+				"            \"finish\": 0.0,\n" +
+				"            \"weight\": 3.0,\n" +
+				"            \"dueDate\": 10,\n" +
+				"            \"planQty\": 1,\n" +
+				"            \"currOp\": null,\n" +
+				"            \"totalWorkTime\": 0.0\n" +
+				"        }\n" +
+				"    },\n" +
+				"    \"lastObjectiveValue\": 0.0,\n" +
+				"    \"readyTaskS\": [\n" +
+				"        \n" +
+				"    ],\n" +
+				"    \"altorighmName\": null,\n" +
+				"    \"wirteDynamic\": false,\n" +
+				"    \"totalAssignedTaskWork\": 0.0,\n" +
+				"    \"objective\": null,\n" +
+				"    \"operationRules\": [\n" +
+				"        \n" +
+				"    ],\n" +
+				"    \"instanceCategory\": \"0_40x1sample\"\n" +
+				"}";
+		Instance instance = JSON.parseObject(data, Instance.class);
+		GAScheduler gaScheduler = new GAScheduler(instance, GAScheduler.PRIORITY_CODE);
+		gaScheduler.schedule();
+	}
+}

+ 3 - 0
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/operationManagementCenter/service/TaskService.java

@@ -2,6 +2,7 @@ package com.github.zuihou.business.operationManagementCenter.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.github.zuihou.base.service.SuperService;
+import com.github.zuihou.business.operationManagementCenter.entity.OrderProduct;
 import com.github.zuihou.business.operationManagementCenter.entity.PlanProduct;
 import com.github.zuihou.business.operationManagementCenter.entity.TTask;
 import com.github.zuihou.business.productionReadyCenter.entity.BomProcedure;
@@ -24,6 +25,8 @@ public interface TaskService extends SuperService<TTask> {
 
      List<TTask> createTaskByPlan(List<PlanProduct>planProductList, Map<Long,List<BomProcedure>> bomProcedureMap,String taskBatchNo);
 
+    List<TTask> createNewTaskByPlan(List<OrderProduct> orderProductList, List<PlanProduct>planProductList, Map<Long,List<BomProcedure>> bomProcedureMap, String taskBatchNo);
+
      Map<String,Object>scheduleTaskpageList(Map<String,Object>map);
 
     /**

+ 2 - 2
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/operationManagementCenter/service/impl/OrderServiceImpl.java

@@ -280,7 +280,7 @@ public class OrderServiceImpl extends SuperServiceImpl<OrderMapper, Order> imple
         }
         List<Long>idList = list.stream().map(p -> Long.parseLong(p.get("id").toString())).collect(Collectors.toList());
         List<Order> oriOrderList = baseMapper.selectList(Wraps.<Order>lbQ().in(Order::getId,idList));
-
+        List<OrderProduct> orderProductList = orderProductService.list(Wraps.<OrderProduct>lbQ().in(OrderProduct::getOrderId,idList));
         //重复点击验证
         String ids = StringUtil.changeIdsListToSubQueryStr(idList);
         Object obj = redisTemplate.opsForValue().get(RepeatCacheKey.ONETOUCHSCHEDULE_UNION_KEY+"_"+ids);
@@ -320,7 +320,7 @@ public class OrderServiceImpl extends SuperServiceImpl<OrderMapper, Order> imple
             //查出所有的计划产品
             List<PlanProduct> planProductList = planProductService.list(Wraps.<PlanProduct>lbQ().in(PlanProduct::getOrderId, idList));
             //生成任务
-            List<TTask> taskList = taskService.createTaskByPlan(planProductList, bomProcedureMap, taskBatchNo);
+            List<TTask> taskList = taskService.createNewTaskByPlan(orderProductList, planProductList, bomProcedureMap, taskBatchNo);
 
             map.put("taskBatchNo", taskBatchNo);
         }finally {

+ 8 - 2
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/operationManagementCenter/service/impl/PlanServiceImpl.java

@@ -63,9 +63,12 @@ public class PlanServiceImpl extends SuperServiceImpl<PlanMapper, Plan> implemen
 
     @Autowired
     private TaskNodeService taskNodeService;
+    @Autowired
+    private OrderProductService orderProductService;
     /**
      * 根据订单默认生成计划,用于一键
-     * @param order
+     * @param map
+     * @param bomNum
      * @return
      */
     @Override
@@ -146,7 +149,10 @@ public class PlanServiceImpl extends SuperServiceImpl<PlanMapper, Plan> implemen
 
         List<Long>idList = list.stream().map(p -> Long.parseLong(p.get("id").toString())).collect(Collectors.toList());
         //查出数据,进行验证
+        List<OrderProduct> orderProductList = orderProductService.list(Wraps.<OrderProduct>lbQ().in(OrderProduct::getOrderId,idList));
         List<Plan> oirList = baseMapper.selectList(Wraps.<Plan>lbQ().in(Plan::getId,idList));
+
+
         for(Plan plan:oirList){
             isFalse(!"2".equals(plan.getAuditStatus()),"请选择审核通过的数据");
             isFalse(!"1".equals(plan.getSchedulingStatus()),"请选择尚未排产的数据");
@@ -165,7 +171,7 @@ public class PlanServiceImpl extends SuperServiceImpl<PlanMapper, Plan> implemen
         String taskBatchNo = UUID.randomUUID().toString();
 
         //生成任务
-        taskService.createTaskByPlan(planProductList,bomProcedureMap,taskBatchNo);
+        taskService.createNewTaskByPlan(orderProductList,planProductList,bomProcedureMap,taskBatchNo);
         map.put("taskBatchNo",taskBatchNo);
         return map;
     }

+ 206 - 5
imcs-admin-boot/imcs-business-biz/src/main/java/com/github/zuihou/business/operationManagementCenter/service/impl/TaskServiceImpl.java

@@ -1,23 +1,27 @@
 package com.github.zuihou.business.operationManagementCenter.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.github.zuihou.base.service.SuperServiceImpl;
 import com.github.zuihou.business.DemoLine.DemoCacheKey;
 import com.github.zuihou.business.DemoLine.DemoLineConstant;
+import com.github.zuihou.business.aps.algorithm.ga.GAScheduler;
+import com.github.zuihou.business.aps.instance.domain.basicdata.*;
 import com.github.zuihou.business.classSchedule.dao.ScheduleUserDateMapper;
 import com.github.zuihou.business.edgeLibrary.entity.Storge;
 import com.github.zuihou.business.edgeLibrary.service.StorgeService;
 import com.github.zuihou.business.operationManagementCenter.dao.OrderMapper;
 import com.github.zuihou.business.operationManagementCenter.dao.TTaskMapper;
 import com.github.zuihou.business.operationManagementCenter.dao.WorkpieceMapper;
-import com.github.zuihou.business.operationManagementCenter.entity.Order;
-import com.github.zuihou.business.operationManagementCenter.entity.PlanProduct;
-import com.github.zuihou.business.operationManagementCenter.entity.TTask;
-import com.github.zuihou.business.operationManagementCenter.entity.TWorkpiece;
+import com.github.zuihou.business.operationManagementCenter.entity.*;
 import com.github.zuihou.business.operationManagementCenter.service.TaskService;
 import com.github.zuihou.business.operationManagementCenter.service.WorkpieceService;
 import com.github.zuihou.business.productionReadyCenter.dao.AutoNodeMapper;
+import com.github.zuihou.business.productionReadyCenter.dao.BomProcedureProgramMapper;
 import com.github.zuihou.business.productionReadyCenter.entity.*;
+import com.github.zuihou.business.productionResourceCenter.entity.Repair;
+import com.github.zuihou.business.productionResourceCenter.entity.ResourceAutoCode;
+import com.github.zuihou.business.productionResourceCenter.service.RepairService;
 import com.github.zuihou.common.constant.CacheKey;
 import com.github.zuihou.common.constant.CodeRuleModule;
 import com.github.zuihou.common.util.DateUtil;
@@ -31,6 +35,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
 import org.springframework.stereotype.Service;
 
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+import java.time.temporal.ChronoField;
 import java.util.*;
 import java.util.stream.Collectors;
 
@@ -61,8 +68,16 @@ public class TaskServiceImpl extends SuperServiceImpl<TTaskMapper, TTask> implem
     private WorkpieceMapper workpieceMapper;
     @Autowired
     private RedisTemplate<String,Object> redisTemplate;
+    @Autowired
+    private RepairService repairService;
+    @Autowired
+    private TTaskMapper tTaskMapper;
+    @Autowired
+    private BomProcedureProgramMapper bomProcedureProgramMapper;
+
     @Override
     public List<TTask> createTaskByPlan(List<PlanProduct> planProductList, Map<Long,List<BomProcedure>> bomProcedureMap,String taskBatchNo) {
+
         //获取生产资源最大结束时间
         List<TTask> tList = baseMapper.getTaskResource();
         Map<Long,TTask>resourceTimemap = tList.stream().collect(Collectors.toMap(TTask::getResourceId, t->t));
@@ -99,7 +114,7 @@ public class TaskServiceImpl extends SuperServiceImpl<TTaskMapper, TTask> implem
 
                             TWorkpiece workpiece = new TWorkpiece();
                             workpiece.setBomId(bomProcedure.getBomId()).setCompleteBatchNo(task.getCompleteBatchNo()).setOrderId(planProduct.getOrderId()).setOrderNo(planProduct.getOrderNo())
-                            .setPlanId(planProduct.getPlanId()).setPlanNo(planProduct.getPlanNo());
+                                    .setPlanId(planProduct.getPlanId()).setPlanNo(planProduct.getPlanNo());
                             workpieceMapper.insert(workpiece);
                         }
                         task.setProcedureSort(j);
@@ -156,6 +171,192 @@ public class TaskServiceImpl extends SuperServiceImpl<TTaskMapper, TTask> implem
     }
 
 
+    @Override
+    public List<TTask> createNewTaskByPlan(List<OrderProduct> orderProductList, List<PlanProduct> planProductList, Map<Long,List<BomProcedure>> bomProcedureMap, String taskBatchNo) {
+
+        // 可选设备集合(工序名称+可选设备列表)
+        Map<String, List<CandidateProcess>> candidateProMap = new HashMap<>(); // 可选处理集合(可选设备以及对应的加工时间)
+        // 工序集合(工序名+工序)
+        Map<String, Operation> operationMap = new HashMap<>();
+        // 设备集合(设备名+设备)
+        Map<String, Machine> machineMap = new HashMap<>();
+        // 零件集合(零件名称+零件)
+        Map<String, Part> partMap = new HashMap<>();
+
+        Map<Long,OrderProduct> orderProductMap = orderProductList.stream().collect(Collectors.toMap(OrderProduct::getId, t->t));
+
+        List<TTask> taskList = new ArrayList<TTask>();
+        //设置completeBatchNo
+        Map<String,String> completeBatchNoMap = new HashMap<String,String>();
+        double totalOpNum = 0.0;
+        for(int partIndex = 1;partIndex <= planProductList.size(); partIndex++){
+            PlanProduct planProduct = planProductList.get(partIndex - 1);
+            OrderProduct orderProduct = orderProductMap.get(planProduct.getOrderProductId());
+            Long bomId = planProduct.getBomId();
+            List<BomProcedure> bomProcedureList = bomProcedureMap.get(bomId);
+            Map<Long,BomProcedure> bpMap = bomProcedureList.stream().collect(Collectors.toMap(BomProcedure::getId, t->t));
+            //产品批次号,用于产品分解任务关联
+            String bomBatchNo = UUID.randomUUID().toString().replace("-", "");
+
+            if(bomProcedureList == null || (bomProcedureList != null && bomProcedureList.size() == 0)) {
+                break;
+            }
+            for(int partNum = 0; partNum < planProduct.getPlanBomNum(); partNum++){
+                Part part = new Part();
+                TWorkpiece workpiece = new TWorkpiece();
+                List<Operation> opList = new ArrayList<Operation>();
+                for(int bomProcedureIndex = 0; bomProcedureIndex < bomProcedureList.size(); bomProcedureIndex++){
+                    // 工序可用设备
+                    List<CandidateProcess> candidateProcesses = new ArrayList<CandidateProcess>();
+
+                    BomProcedure bomProcedure = bomProcedureList.get(bomProcedureIndex);
+
+                    TTask task = new TTask();
+                    task.setFirstProcedureFlag("0");
+                    if(bomProcedureIndex==0){
+                        task.setFirstProcedureFlag("1");
+                    }
+                    if(bomProcedureIndex==bomProcedureList.size()-1){
+                        task.setLastProcedureFlag("1");
+                    }
+                    String key = planProduct.getId().longValue() + partNum + "";
+                    if(completeBatchNoMap.containsKey(key)){
+                        task.setCompleteBatchNo(completeBatchNoMap.get(key));
+                    }else{
+                        task.setCompleteBatchNo(UUID.randomUUID().toString().replace("-", ""));
+                        completeBatchNoMap.put(key,task.getCompleteBatchNo());
+
+                        workpiece.setBomId(bomProcedure.getBomId()).setCompleteBatchNo(task.getCompleteBatchNo()).setOrderId(planProduct.getOrderId()).setOrderNo(planProduct.getOrderNo())
+                                .setPlanId(planProduct.getPlanId()).setPlanNo(planProduct.getPlanNo());
+                        workpieceMapper.insert(workpiece);
+                    }
+                    task.setProcedureSort(bomProcedureIndex);
+                    task.setDraftFlag("1");
+                    task.setPlanId(planProduct.getPlanId());
+                    task.setPlanNo(planProduct.getPlanNo());
+                    task.setOrderId(planProduct.getOrderId());
+                    task.setOrderNo(planProduct.getOrderNo());
+                    task.setProcedureId(bomProcedure.getId());
+                    task.setProcedureName(bomProcedure.getName());
+                    task.setProcedureNo(bomProcedure.getNo());
+                    task.setBomId(bomProcedure.getBomId());
+                    task.setStatus("1");
+                    task.setTaskNo(codeRuleService.getBillCode(CodeRuleModule.CODE_RULE_TASK)) ;
+                    task.setTaskBatchNo(taskBatchNo);
+                    task.setBomBatchNo(bomBatchNo);
+                    task.setPrority(bomProcedure.getSort());
+                    //根据算法分配资源、托盘等等
+                    assignResource(task,bpMap);
+                    //准备计算
+                    //assignResourcePrepare(task,bpMap);
+                    //侯莫安人员序加上判断
+                    task.setExecutorId(task.getResourceId());
+                    task.setExecutorType("1");
+                    task.setExecutorName("");
+                    task.setTmpId(UUID.randomUUID().toString().replace("-", ""));
+                    taskList.add(task);
+
+                    if (bomProcedure.getProductionresourceList().size() > 0){
+                        Machine machine = new Machine();
+                        CandidateProcess candidateProcess = new CandidateProcess();
+                        for(BomProcedureProductionresource bomProcedureProductionresource : bomProcedure.getProductionresourceList()){
+                            if(!machineMap.containsKey(bomProcedureProductionresource.getResourceId())){
+                                machine.setId(bomProcedureProductionresource.getResourceId().longValue());
+                                // 添加设备维保时间片
+                                LbqWrapper<Repair> repairWrapper = new LbqWrapper<Repair>().eq(Repair::getProductionresourceId, bomProcedureProductionresource.getResourceId()).gt(Repair::getRepairStartTime, cn.hutool.core.date.DateUtil.toLocalDateTime(cn.hutool.core.date.DateUtil.date()));
+                                List<Repair> repairs = repairService.list(repairWrapper);
+                                for(Repair repair : repairs){
+                                    machine.getNoUseTime().add(Timestamp.valueOf(repair.getRepairStartTime()).getTime() + "-" + Timestamp.valueOf(repair.getRepairEndTime()).getTime());
+                                }
+                                // 添加设备已经分配的时间片(从当前系统时间开始计算)
+                                LbqWrapper<TTask> tTaskWrapper = new LbqWrapper<TTask>().eq(TTask::getResourceId, bomProcedureProductionresource.getResourceId()).gt(TTask::getExpectStartTime, cn.hutool.core.date.DateUtil.current(false)).orderByAsc(TTask::getExpectStartTime);
+                                List<TTask> resourseTasks = tTaskMapper.selectList(tTaskWrapper);
+                                for(TTask tTask : resourseTasks){
+                                    machine.getNoUseTime().add(tTask.getExpectStartTime().getTime() + "-" + tTask.getExpectEndTime().getTime());
+                                }
+                                machineMap.put("M" + bomProcedureProductionresource.getResourceId(), machine);
+                            }
+
+                            if(!candidateProMap.containsKey(workpiece.getCompleteBatchNo() + "_" + bomProcedure.getNo())){
+                                candidateProcess.setMachineId(bomProcedureProductionresource.getResourceId());
+                                LbqWrapper<BomProcedureProgram> bomProcedureProgramWrapper = new LbqWrapper<BomProcedureProgram>().eq(BomProcedureProgram::getResourceId, bomProcedureProductionresource.getResourceId()).eq(BomProcedureProgram::getProcedureId,bomProcedureProductionresource.getProcedureId());
+                                BomProcedureProgram bomProcedureProgram = bomProcedureProgramMapper.selectOne(bomProcedureProgramWrapper);
+                                // 人工上下料没有程序的情况直接用工序时间
+                                if(null != bomProcedureProgram && null != bomProcedureProgram.getRunTime()){
+                                    candidateProcess.setProcedureId(bomProcedureProgram.getProcedureId());
+                                    candidateProcess.setDuration(bomProcedureProgram.getRunTime().intValue());
+                                    candidateProcess.setRunTime(bomProcedureProgram.getRunTime());
+                                }else{
+                                    candidateProcess.setProcedureId(bomProcedure.getId());
+                                    candidateProcess.setDuration(bomProcedure.getPrepareWorkhours().intValue() + bomProcedure.getRatedWorkhours().intValue());
+                                    candidateProcess.setRunTime(bomProcedure.getPrepareWorkhours() + bomProcedure.getRatedWorkhours());
+                                }
+                                if(!candidateProcesses.contains(candidateProcess)){
+                                    candidateProcesses.add(candidateProcess);
+                                }
+                                candidateProMap.put(workpiece.getCompleteBatchNo() + "_" + bomProcedure.getNo(),candidateProcesses);
+                            }
+                        }
+                    }
+
+                    // 组装排产所以的工序信息
+                    // TODO 可优化成直接用task对象
+                    Operation operation = new Operation();
+                    operation.setId(task.getTmpId());
+                    operation.setPartId(workpiece.getCompleteBatchNo());
+                    operation.setName(bomProcedure.getNo());
+                    operation.setSeq(bomProcedureIndex+1);
+                    operation.setDueDate(orderProduct.getDeliveryTime().getTime());
+                    operation.setPlanQty(1);
+                    String operationLey = task.getCompleteBatchNo() + "_" + bomProcedure.getNo();
+                    operationMap.put(operationLey,operation);
+                    opList.add(operation);
+                    totalOpNum ++;
+                }
+                part.setId(workpiece.getCompleteBatchNo());
+                part.setName(orderProduct.getName());
+                part.setOperationNum(bomProcedureList.size());
+                part.setOpList(opList);
+                part.setDueDate(orderProduct.getDeliveryTime().getTime());
+                partMap.put(workpiece.getCompleteBatchNo(),part);
+            }
+        }
+
+        // 调用java简易排产
+        Instance instance = new Instance();
+        instance.setTotalOpNum(totalOpNum);
+        // 赋值设备map
+        instance.setMachineMap(machineMap);
+        // 创造零件map
+        instance.setPartMap(partMap);
+        // 创造工序map
+        instance.setOperationMap(operationMap);
+        // 创造工序可选设备集合map
+        instance.setCandidateProMap(candidateProMap);
+
+        GAScheduler gaScheduler = new GAScheduler(instance, GAScheduler.PRIORITY_CODE);
+        try{
+            gaScheduler.schedule();
+        }catch(Exception e){
+            e.printStackTrace();
+        }
+        // 更新task表人工序任务的预计开始时间及结束时间
+        Iterator<Map.Entry<String, Operation>> it = instance.getOperationMap().entrySet().iterator();
+        while(it.hasNext()){
+            Operation operation = it.next().getValue();
+            for(TTask task : taskList){
+                if(task.getTmpId().equals(operation.getId())){
+                    task.setExpectStartTime(new Date(operation.getStart()));
+                    task.setExpectEndTime(new Date(operation.getFinish()));
+                    task.setResourceId(operation.getMachineId());
+                    break;
+                }
+            }
+        }
+        saveBatch(taskList);
+        return taskList;
+    }
+
 //    private List<TTask> preHandMatlab(List<TTask> taskList,List<TTask> tList){
 //        List<TTask> returnList = new ArrayList<TTask>();
 //        String taskJSon = JSONArray.toJSONString(taskList,SerializerFeature.WriteNullListAsEmpty,SerializerFeature.WriteNullStringAsEmpty