fangpy 5 месяцев назад
Родитель
Сommit
3e8f391c7c

Разница между файлами не показана из-за своего большого размера
+ 3189 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/aps/score/ApsConstraintListProvider.java


+ 30 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/test/AbstractPersistable.java

@@ -0,0 +1,30 @@
+package com.rongwei.rwapsserver.test;
+
+import org.optaplanner.core.api.domain.lookup.PlanningId;
+
+public abstract class AbstractPersistable {
+
+    protected Long id;
+
+    protected AbstractPersistable() {
+    }
+
+    protected AbstractPersistable(long id) {
+        this.id = id;
+    }
+
+    @PlanningId
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    @Override
+    public String toString() {
+        return getClass().getName().replaceAll(".*\\.", "") + "-" + id;
+    }
+
+}

+ 122 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/test/Employee.java

@@ -0,0 +1,122 @@
+package com.rongwei.rwapsserver.test;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import org.optaplanner.core.api.domain.entity.PlanningEntity;
+import org.optaplanner.core.api.domain.variable.InverseRelationShadowVariable;
+import org.optaplanner.core.api.domain.variable.PlanningListVariable;
+//import org.optaplanner.examples.common.persistence.jackson.KeySerializer;
+//import org.optaplanner.examples.common.swingui.components.Labeled;
+
+import java.util.*;
+
+@PlanningEntity
+//@JsonIdentityInfo(generator = JacksonUniqueIdGenerator.class)
+public class Employee extends AbstractPersistable {
+
+    private String fullName;
+
+    private int employeeType;
+
+
+    private List<Task> tasks;
+
+    // TODO pinning: https://issues.redhat.com/browse/PLANNER-2633.
+
+    public Employee() {
+    }
+
+    public Employee(long id, String fullName,int employeeType) {
+        super(id);
+        this.fullName = fullName;
+        tasks = new ArrayList<>();
+        this.employeeType = employeeType;
+    }
+
+    public String getFullName() {
+        return fullName;
+    }
+
+    public void setFullName(String fullName) {
+        this.fullName = fullName;
+    }
+
+    /*public Set<Skill> getSkillSet() {
+        return skillSet;
+    }
+
+    public void setSkillSet(Set<Skill> skillSet) {
+        this.skillSet = skillSet;
+    }
+
+    public Map<Customer, Affinity> getAffinityMap() {
+        return affinityMap;
+    }
+
+    @JsonSerialize(keyUsing = KeySerializer.class)
+    @JsonDeserialize(keyUsing = CustomerKeyDeserializer.class)
+    public void setAffinityMap(Map<Customer, Affinity> affinityMap) {
+        this.affinityMap = affinityMap;
+    }*/
+
+    @PlanningListVariable
+//    @InverseRelationShadowVariable(sourceVariableName = "employee")
+    public List<Task> getTasks() {
+        return tasks;
+    }
+
+    public void setTasks(List<Task> tasks) {
+        this.tasks = tasks;
+    }
+
+    public int getEmployeeType() {
+        return employeeType;
+    }
+
+    public void setEmployeeType(int employeeType) {
+        this.employeeType = employeeType;
+    }
+
+    // ************************************************************************
+    // Complex methods
+    // ************************************************************************
+
+
+    /*@JsonIgnore
+    public Affinity getAffinity(Customer customer) {
+        Affinity affinity = affinityMap.get(customer);
+        if (affinity == null) {
+            affinity = Affinity.NONE;
+        }
+        return affinity;
+    }*/
+
+    @JsonIgnore
+    public Integer getEndTime() {
+        return tasks.isEmpty() ? 0 : tasks.get(tasks.size() - 1).getStartTime()+10;
+    }
+
+    /*@Override
+    public String getLabel() {
+        return fullName;
+    }*/
+
+    /*@JsonIgnore
+    public String getToolText() {
+        StringBuilder toolText = new StringBuilder();
+        toolText.append("<html><center><b>").append(fullName).append("</b><br/><br/>");
+        toolText.append("Skills:<br/>");
+        for (Skill skill : skillSet) {
+            toolText.append(skill.getLabel()).append("<br/>");
+        }
+        toolText.append("</center></html>");
+        return toolText.toString();
+    }*/
+
+    @Override
+    public String toString() {
+        return fullName;
+    }
+
+}

+ 70 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/test/StartTimeListUpdatingVariableListener.java

@@ -0,0 +1,70 @@
+package com.rongwei.rwapsserver.test;
+
+import org.optaplanner.core.api.domain.variable.ListVariableListener;
+import org.optaplanner.core.api.score.director.ScoreDirector;
+
+import java.util.List;
+import java.util.Objects;
+
+public class StartTimeListUpdatingVariableListener implements ListVariableListener<TaskAssigningSolution,Employee, Task> {
+
+    @Override
+    public void afterListVariableElementUnassigned(ScoreDirector<TaskAssigningSolution> scoreDirector, Task task) {
+        scoreDirector.beforeVariableChanged(task, "startTime");
+        task.setStartTime(null);
+        scoreDirector.afterVariableChanged(task, "startTime");
+    }
+
+    @Override
+    public void beforeListVariableChanged(ScoreDirector<TaskAssigningSolution> scoreDirector, Employee employee, int fromIndex, int toIndex) {
+
+    }
+
+    @Override
+    public void afterListVariableChanged(ScoreDirector<TaskAssigningSolution> scoreDirector, Employee employee, int startIndex,int endIndex) {
+        updateStartTime(scoreDirector, employee, startIndex);
+    }
+
+    @Override
+    public void beforeEntityAdded(ScoreDirector<TaskAssigningSolution> scoreDirector, Employee employee) {
+
+    }
+
+    @Override
+    public void afterEntityAdded(ScoreDirector<TaskAssigningSolution> scoreDirector, Employee employee) {
+
+    }
+
+    @Override
+    public void beforeEntityRemoved(ScoreDirector<TaskAssigningSolution> scoreDirector, Employee employee) {
+
+    }
+
+    @Override
+    public void afterEntityRemoved(ScoreDirector<TaskAssigningSolution> scoreDirector, Employee employee) {
+
+    }
+
+    protected void updateStartTime(ScoreDirector<TaskAssigningSolution> scoreDirector, Employee employee, int index) {
+        List<Task> tasks = employee.getTasks();
+        Integer previousEndTime = index == 0 ? Integer.valueOf(0) : tasks.get(index - 1).getEndTime();
+
+        for (int i = index; i < tasks.size(); i++) {
+            Task t = tasks.get(i);
+            Integer startTime = calculateStartTime(t, previousEndTime);
+            if (!Objects.equals(t.getStartTime(), startTime)) {
+                scoreDirector.beforeVariableChanged(t, "startTime");
+                t.setStartTime(startTime);
+                scoreDirector.afterVariableChanged(t, "startTime");
+            }
+            previousEndTime = t.getEndTime();
+        }
+    }
+
+    private Integer calculateStartTime(Task task, Integer previousEndTime) {
+        if (previousEndTime == null) {
+            return null;
+        }
+        return Math.max(task.getReadyTime(), previousEndTime);
+    }
+}

+ 67 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/test/StartTimeUpdatingVariableListener.java

@@ -0,0 +1,67 @@
+package com.rongwei.rwapsserver.test;
+
+import org.optaplanner.core.api.domain.variable.ListVariableListener;
+import org.optaplanner.core.api.domain.variable.VariableListener;
+import org.optaplanner.core.api.score.director.ScoreDirector;
+//import org.optaplanner.examples.taskassigning.domain.TaskAssigningSolution;
+
+import java.util.List;
+import java.util.Objects;
+
+public class StartTimeUpdatingVariableListener implements VariableListener<TaskAssigningSolution, Task> {
+
+
+    @Override
+    public void beforeVariableChanged(ScoreDirector<TaskAssigningSolution> scoreDirector, Task task) {
+
+    }
+
+    @Override
+    public void afterVariableChanged(ScoreDirector<TaskAssigningSolution> scoreDirector, Task task) {
+        updateStartTime(scoreDirector, task);
+    }
+
+    @Override
+    public void beforeEntityAdded(ScoreDirector<TaskAssigningSolution> scoreDirector, Task task) {
+
+    }
+
+    @Override
+    public void afterEntityAdded(ScoreDirector<TaskAssigningSolution> scoreDirector, Task task) {
+        updateStartTime(scoreDirector, task);
+    }
+
+    @Override
+    public void beforeEntityRemoved(ScoreDirector<TaskAssigningSolution> scoreDirector, Task task) {
+
+    }
+
+    @Override
+    public void afterEntityRemoved(ScoreDirector<TaskAssigningSolution> scoreDirector, Task task) {
+
+    }
+
+    protected void updateStartTime(ScoreDirector<TaskAssigningSolution> scoreDirector, Task task) {
+        task.setStartTime(0);
+        /*List<Task> tasks = employee.getTasks();
+        Integer previousEndTime = index == 0 ? Integer.valueOf(0) : tasks.get(index - 1).getEndTime();
+
+        for (int i = index; i < tasks.size(); i++) {
+            Task t = tasks.get(i);
+            Integer startTime = calculateStartTime(t, previousEndTime);
+            if (!Objects.equals(t.getStartTime(), startTime)) {
+                scoreDirector.beforeVariableChanged(t, "startTime");
+                t.setStartTime(startTime);
+                scoreDirector.afterVariableChanged(t, "startTime");
+            }
+            previousEndTime = t.getEndTime();
+        }*/
+    }
+
+    private Integer calculateStartTime(Task task, Integer previousEndTime) {
+        if (previousEndTime == null) {
+            return null;
+        }
+        return Math.max(task.getReadyTime(), previousEndTime);
+    }
+}

+ 194 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/test/Task.java

@@ -0,0 +1,194 @@
+package com.rongwei.rwapsserver.test;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import org.optaplanner.core.api.domain.entity.PlanningEntity;
+import org.optaplanner.core.api.domain.variable.InverseRelationShadowVariable;
+import org.optaplanner.core.api.domain.variable.PlanningVariable;
+import org.optaplanner.core.api.domain.variable.ShadowVariable;
+//import org.optaplanner.examples.common.swingui.components.Labeled;
+//import org.optaplanner.examples.taskassigning.domain.solver.StartTimeUpdatingVariableListener;
+
+import javax.annotation.Priority;
+import java.util.List;
+
+@PlanningEntity
+//@JsonIdentityInfo(generator = JacksonUniqueIdGenerator.class)
+public class Task extends AbstractPersistable {
+
+    private int indexInTaskType;
+    private int readyTime;
+    private Priority priority;
+
+    // Shadow variables
+
+    private Employee employee;
+
+    private Integer startTime;
+
+    private Integer endTime;
+
+    private Integer produceTime;
+
+    private List<Task> preTasks;
+
+    public Task() {
+    }
+
+    public Task(long id, int readyTime, Priority priority) {
+        super(id);
+        this.indexInTaskType = indexInTaskType;
+        this.readyTime = readyTime;
+        this.priority = priority;
+    }
+
+    public int getIndexInTaskType() {
+        return indexInTaskType;
+    }
+
+    public void setIndexInTaskType(int indexInTaskType) {
+        this.indexInTaskType = indexInTaskType;
+    }
+
+    public int getReadyTime() {
+        if(preTasks != null && preTasks.size()>0){
+            Integer preEndTime = preTasks.get(0).getEndTime();
+            if(preEndTime != null && preEndTime>readyTime){
+                return preEndTime;
+            }
+        }
+        return readyTime;
+    }
+
+    public void setReadyTime(int readyTime) {
+        this.readyTime = readyTime;
+    }
+
+    public Priority getPriority() {
+        return priority;
+    }
+
+    public void setPriority(Priority priority) {
+        this.priority = priority;
+    }
+
+//    @PlanningVariable
+    @InverseRelationShadowVariable(sourceVariableName = "tasks")
+    public Employee getEmployee() {
+        return employee;
+    }
+
+    public void setEmployee(Employee employee) {
+        this.employee = employee;
+    }
+
+    @ShadowVariable(variableListenerClass = StartTimeListUpdatingVariableListener.class,sourceEntityClass = Employee.class, sourceVariableName = "tasks")
+    public Integer getStartTime() {
+        return startTime;
+    }
+
+    public void setStartTime(Integer startTime) {
+        this.startTime = startTime;
+    }
+
+    public Integer getEndTime() {
+        return startTime + (produceTime == null ? 0 : produceTime);
+    }
+
+    public void setEndTime(Integer endTime) {
+        this.endTime = endTime;
+    }
+
+    public Integer getProduceTime() {
+        return produceTime;
+    }
+
+    public void setProduceTime(Integer produceTime) {
+        this.produceTime = produceTime;
+    }
+
+    public List<Task> getPreTasks() {
+        return preTasks;
+    }
+
+    public void setPreTasks(List<Task> preTasks) {
+        this.preTasks = preTasks;
+    }
+
+    // ************************************************************************
+    // Complex methods
+    // ************************************************************************
+
+    @JsonIgnore
+    public int getMissingSkillCount() {
+        if (employee == null) {
+            return 0;
+        }
+        int count = 10;
+        /*for (Skill skill : taskType.getRequiredSkillList()) {
+            if (!employee.getSkillSet().contains(skill)) {
+                count++;
+            }
+        }*/
+        return count;
+    }
+
+    /**
+     * In minutes
+     *
+     * @return at least 1 minute
+     */
+    /*@JsonIgnore
+    public int getDuration() {
+        Affinity affinity = getAffinity();
+        return taskType.getBaseDuration() * affinity.getDurationMultiplier();
+    }
+
+    @JsonIgnore
+    public Affinity getAffinity() {
+        return (employee == null) ? Affinity.NONE : employee.getAffinity(customer);
+    }*/
+
+    /*@JsonIgnore
+    public Integer getEndTime() {
+        if (startTime == null) {
+            return null;
+        }
+        return startTime + getDuration();
+    }*/
+
+    /*@JsonIgnore
+    public String getCode() {
+        return taskType + "-" + indexInTaskType;
+    }
+
+    @JsonIgnore
+    public String getTitle() {
+        return taskType.getTitle();
+    }
+
+    @Override
+    public String getLabel() {
+        return getCode() + ": " + taskType.getTitle();
+    }*/
+
+    /*@JsonIgnore
+    public String getToolText() {
+        StringBuilder toolText = new StringBuilder();
+        toolText.append("<html><center><b>").append(getLabel()).append("</b><br/>")
+                .append(priority.getLabel()).append("<br/><br/>");
+        toolText.append("Required skills:<br/>");
+        for (Skill skill : taskType.getRequiredSkillList()) {
+            toolText.append(skill.getLabel()).append("<br/>");
+        }
+        toolText.append("<br/>Customer:<br/>").append(customer.getName()).append("<br/>(")
+                .append(getAffinity().getLabel()).append(")<br/>");
+        toolText.append("</center></html>");
+        return toolText.toString();
+    }*/
+
+    /*@Override
+    public String toString() {
+        return getCode();
+    }*/
+
+}

+ 100 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/test/TaskAssigningConstraintProvider.java

@@ -0,0 +1,100 @@
+package com.rongwei.rwapsserver.test;
+
+import org.optaplanner.core.api.score.buildin.bendable.BendableScore;
+import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
+import org.optaplanner.core.api.score.stream.Constraint;
+import org.optaplanner.core.api.score.stream.ConstraintFactory;
+import org.optaplanner.core.api.score.stream.ConstraintProvider;
+import org.optaplanner.core.api.score.stream.uni.UniConstraintStream;
+
+import java.util.List;
+//import org.optaplanner.examples.taskassigning.domain.Priority;
+
+public final class TaskAssigningConstraintProvider implements ConstraintProvider {
+
+    private static final int BENDABLE_SCORE_HARD_LEVELS_SIZE = 1;
+    private static final int BENDABLE_SCORE_SOFT_LEVELS_SIZE = 4;
+
+    @Override
+    public Constraint[] defineConstraints(ConstraintFactory constraintFactory) {
+        return new Constraint[] {
+                noMissingSkills(constraintFactory),
+                earlyTime(constraintFactory),
+        };
+    }
+
+    /*private UniConstraintStream<Task> getTaskWithPriority(ConstraintFactory constraintFactory, Priority priority) {
+        return constraintFactory.forEach(Task.class)
+                .filter(task -> task.getEmployee() != null && task.getPriority() == priority);
+    }*/
+
+    private Constraint noMissingSkills(ConstraintFactory constraintFactory) {
+        return constraintFactory.forEach(Employee.class)
+                .filter(employee -> {
+//                    System.out.println(task.getId());
+//                    return task.getIndexInTaskType() != task.getEmployee().getEmployeeType();
+                    return true;
+                })
+                .penalize(HardMediumSoftScore.ONE_HARD,(employee)->{
+                    int b = 0;
+                    List<Task> tasks = employee.getTasks();
+                    if(tasks != null && tasks.size()>0){
+                        for (Task task : tasks) {
+                            if(task.getIndexInTaskType() != employee.getEmployeeType()){
+                                b++;
+                            }
+                        }
+                    }
+                    return b*10;
+                })
+                .asConstraint("No missing skills");
+    }
+
+    private Constraint earlyTime(ConstraintFactory constraintFactory) {
+        return constraintFactory.forEach(Employee.class)
+                .filter(employee -> {
+//                    System.out.println(task.getId());
+//                    return task.getIndexInTaskType() != task.getEmployee().getEmployeeType();
+                    return true;
+                })
+                .penalize(HardMediumSoftScore.ONE_SOFT,(employee)->{
+                    int b = 0;
+                    List<Task> tasks = employee.getTasks();
+                    if(tasks != null && tasks.size()>0){
+                        for (Task task : tasks) {
+                            b = b + task.getStartTime();
+                        }
+                    }
+                    return b;
+                })
+                .asConstraint("earlyTime");
+    }
+
+    /*private Constraint criticalPriorityBasedTaskEndTime(ConstraintFactory constraintFactory) {
+        return getTaskWithPriority(constraintFactory, Priority.CRITICAL)
+                .penalize(BendableScore.ofSoft(BENDABLE_SCORE_HARD_LEVELS_SIZE, BENDABLE_SCORE_SOFT_LEVELS_SIZE, 0, 1),
+                        Task::getEndTime)
+                .asConstraint("Critical priority task end time");
+    }*/
+
+    /*private Constraint minimizeMakespan(ConstraintFactory constraintFactory) {
+        return constraintFactory.forEach(Employee.class)
+                .penalize(BendableScore.ofSoft(BENDABLE_SCORE_HARD_LEVELS_SIZE, BENDABLE_SCORE_SOFT_LEVELS_SIZE, 1, 1),
+                        employee -> employee.getEndTime() * employee.getEndTime())
+                .asConstraint("Minimize makespan, latest ending employee first");
+    }
+
+    private Constraint majorPriorityTaskEndTime(ConstraintFactory constraintFactory) {
+        return getTaskWithPriority(constraintFactory, Priority.MAJOR)
+                .penalize(BendableScore.ofSoft(BENDABLE_SCORE_HARD_LEVELS_SIZE, BENDABLE_SCORE_SOFT_LEVELS_SIZE, 2, 1),
+                        Task::getEndTime)
+                .asConstraint("Major priority task end time");
+    }
+
+    private Constraint minorPriorityTaskEndTime(ConstraintFactory constraintFactory) {
+        return getTaskWithPriority(constraintFactory, Priority.MINOR)
+                .penalize(BendableScore.ofSoft(BENDABLE_SCORE_HARD_LEVELS_SIZE, BENDABLE_SCORE_SOFT_LEVELS_SIZE, 3, 1),
+                        Task::getEndTime)
+                .asConstraint("Minor priority task end time");
+    }*/
+}

+ 89 - 0
rw-aps-server/src/main/java/com/rongwei/rwapsserver/test/TaskAssigningSolution.java

@@ -0,0 +1,89 @@
+package com.rongwei.rwapsserver.test;
+
+import org.optaplanner.core.api.domain.solution.PlanningEntityCollectionProperty;
+import org.optaplanner.core.api.domain.solution.PlanningScore;
+import org.optaplanner.core.api.domain.solution.PlanningSolution;
+import org.optaplanner.core.api.domain.solution.ProblemFactCollectionProperty;
+import org.optaplanner.core.api.domain.valuerange.ValueRangeProvider;
+import org.optaplanner.core.api.score.buildin.bendable.BendableScore;
+import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+
+import java.util.List;
+
+@PlanningSolution
+public class TaskAssigningSolution extends AbstractPersistable {
+
+//    @ProblemFactCollectionProperty
+//    private List<Skill> skillList;
+//    @ProblemFactCollectionProperty
+//    private List<TaskType> taskTypeList;
+//    @ProblemFactCollectionProperty
+//    private List<Customer> customerList;
+
+    @ValueRangeProvider
+    @ProblemFactCollectionProperty
+    private List<Task> taskList;
+
+    @PlanningEntityCollectionProperty
+    private List<Employee> employeeList;
+
+    @PlanningScore
+    private HardMediumSoftScore score;
+
+    /** Relates to {@link Task#getStartTime()}. */
+    private int frozenCutoff; // In minutes
+
+    public TaskAssigningSolution() {
+    }
+
+    public TaskAssigningSolution(long id) {
+        super(id);
+    }
+
+    public TaskAssigningSolution(long id, List<Employee> employeeList, List<Task> taskList) {
+        this(id);
+//        this.skillList = skillList;
+//        this.taskTypeList = taskTypeList;
+//        this.customerList = customerList;
+        this.employeeList = employeeList;
+        this.taskList = taskList;
+    }
+
+    public List<Employee> getEmployeeList() {
+        return employeeList;
+    }
+
+    public void setEmployeeList(List<Employee> employeeList) {
+        this.employeeList = employeeList;
+    }
+
+    public List<Task> getTaskList() {
+        return taskList;
+    }
+
+    public void setTaskList(List<Task> taskList) {
+        this.taskList = taskList;
+    }
+
+    public HardMediumSoftScore getScore() {
+        return score;
+    }
+
+    public void setScore(HardMediumSoftScore score) {
+        this.score = score;
+    }
+
+    public int getFrozenCutoff() {
+        return frozenCutoff;
+    }
+
+    public void setFrozenCutoff(int frozenCutoff) {
+        this.frozenCutoff = frozenCutoff;
+    }
+
+    // ************************************************************************
+    // Complex methods
+    // ************************************************************************
+
+}

+ 98 - 2
rw-aps-server/src/test/java/com/rongwei/rwapsserver/RwApsServerApplicationTests.java

@@ -6,17 +6,35 @@ import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
 import cn.hutool.json.JSONUtil;
+import com.rongwei.rwapsserver.aps.domain.ApsSolution;
+import com.rongwei.rwapsserver.aps.domain.Equipment;
 import com.rongwei.rwapsserver.aps.domain.ProductionProcesses;
+import com.rongwei.rwapsserver.aps.score.ApsConstraintProvider;
+import com.rongwei.rwapsserver.test.Employee;
+import com.rongwei.rwapsserver.test.Task;
+import com.rongwei.rwapsserver.test.TaskAssigningConstraintProvider;
+import com.rongwei.rwapsserver.test.TaskAssigningSolution;
 import org.drools.util.DateUtils;
 import org.junit.jupiter.api.Test;
+import org.optaplanner.core.api.score.ScoreExplanation;
+import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.optaplanner.core.api.solver.SolutionManager;
+import org.optaplanner.core.api.solver.Solver;
+import org.optaplanner.core.api.solver.SolverFactory;
+import org.optaplanner.core.api.solver.event.BestSolutionChangedEvent;
+import org.optaplanner.core.api.solver.event.SolverEventListener;
+import org.optaplanner.core.config.solver.EnvironmentMode;
+import org.optaplanner.core.config.solver.SolverConfig;
+import org.optaplanner.core.config.solver.termination.TerminationConfig;
 import org.springframework.boot.test.context.SpringBootTest;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.stream.Collectors;
 
-@SpringBootTest
+//@SpringBootTest
 class RwApsServerApplicationTests {
 
     @Test
@@ -34,7 +52,85 @@ class RwApsServerApplicationTests {
         sources.sort(Comparator.comparing(ProductionProcesses::getOrderMark));
         System.out.println(sources);*/
 
-        test1(3);
+//        test1(3);
+//        System.out.println(1111);
+        test2();
+    }
+
+    private void test2(){
+        String cores = Runtime.getRuntime().availableProcessors() + "";
+        SolverFactory<TaskAssigningSolution> solverFactory = SolverFactory.create(new SolverConfig()
+                        .withEnvironmentMode(EnvironmentMode.REPRODUCIBLE)
+                        .withSolutionClass(TaskAssigningSolution.class)
+                        .withEntityClasses(Task.class, Employee.class)
+                        .withConstraintProviderClass(TaskAssigningConstraintProvider.class)
+                        .withTerminationConfig(new TerminationConfig().withUnimprovedSecondsSpentLimit(30L))
+//                    .withTerminationSpentLimit(Duration.ofSeconds(runPlanSeconds))
+                        .withMoveThreadCount(cores)
+        );
+        Solver<TaskAssigningSolution> solver = solverFactory.buildSolver();
+        solver.addEventListener(new SolverEventListener<TaskAssigningSolution>() {
+            public void bestSolutionChanged(BestSolutionChangedEvent<TaskAssigningSolution> event) {
+                if(solver.isEveryProblemChangeProcessed()) {
+                    System.out.println("************"+event.getNewBestScore()+"************");
+                }
+            }
+        });
+        TaskAssigningSolution apsSolution = getTestData();
+        TaskAssigningSolution solvedBalance  = solver.solve(apsSolution);
+        System.out.println("**************排程评分分析***************");
+        SolutionManager<TaskAssigningSolution, HardSoftScore> scoreManager = SolutionManager.create(solverFactory);
+        ScoreExplanation<TaskAssigningSolution, HardSoftScore> explain = scoreManager.explain(solvedBalance);
+        System.out.println(explain.toString());
+        System.out.println("**************排程评分分析***************");
+        for (Employee employee : solvedBalance.getEmployeeList()) {
+            String str = employee.getFullName()+":";
+            List<Task> tasks = employee.getTasks();
+            if(tasks != null && tasks.size()>0){
+                for (Task task : tasks) {
+                    str = str + "  task" + task.getId() + "("+task.getStartTime()+"-"+task.getEndTime()+")";
+                }
+            }
+            System.out.println(str);
+        }
+    }
+
+    private TaskAssigningSolution getTestData(){
+        TaskAssigningSolution apsSolution = new TaskAssigningSolution();
+        List<Employee> es = new ArrayList<>();
+        List<Task> tasks = new ArrayList<>();
+        for (int i = 0; i < 10; i++) {
+            Task task = new Task();
+            task.setId(i);
+            if(i<3){
+                task.setIndexInTaskType(10);
+                task.setProduceTime(7);
+            } else if (i>=3 && i<5) {
+                task.setIndexInTaskType(20);
+                task.setProduceTime(15);
+            }else{
+                task.setIndexInTaskType(30);
+                task.setProduceTime(9);
+            }
+            task.setPreTasks(new ArrayList<>());
+            tasks.add(task);
+        }
+        Task t0 = tasks.get(0);Task t1 = tasks.get(1);Task t2 = tasks.get(2);
+        Task t3 = tasks.get(3);Task t4 = tasks.get(4);
+        Task t5 = tasks.get(5);Task t6 = tasks.get(6);Task t7 = tasks.get(7);Task t8 = tasks.get(8);Task t9 = tasks.get(9);
+        t5.getPreTasks().add(t3);t6.getPreTasks().add(t4);
+        t3.getPreTasks().add(t0);t4.getPreTasks().add(t1);
+        t7.getPreTasks().add(t2);
+
+        Employee e1 = new Employee(1,"设备1",10);
+        Employee e2 = new Employee(2,"设备2",20);
+        Employee e3 = new Employee(3,"设备3",30);
+        Employee e4 = new Employee(4,"设备4",30);
+        es.add(e1);es.add(e2);es.add(e3);es.add(e4);
+
+        apsSolution.setEmployeeList(es);
+        apsSolution.setTaskList(tasks);
+        return apsSolution;
     }
 
     private void test1(Integer inta){