Browse Source

Implement HardMediumSoft Score

tripeur 4 years ago
parent
commit
b65f5850f5

+ 3 - 0
.gitignore

@@ -31,3 +31,6 @@ build/
 
 ### VS Code ###
 .vscode/
+
+### Front End ###
+!**/src/main/resources/static/

+ 2 - 2
src/main/java/fr/jaquin/bdlg/planner/PlanningController.java

@@ -7,7 +7,7 @@ import fr.jaquin.bdlg.planner.domain.Planning;
 import fr.jaquin.bdlg.planner.domain.PlanningInput;
 import fr.jaquin.bdlg.planner.domain.PlanningSolution;
 import org.optaplanner.core.api.score.ScoreManager;
-import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
 import org.optaplanner.core.api.solver.SolverJob;
 import org.optaplanner.core.api.solver.SolverManager;
 
@@ -24,7 +24,7 @@ public class PlanningController {
   @Autowired
   private SolverManager<Planning, UUID> solverManager;
   @Autowired
-    private ScoreManager<Planning, HardSoftScore> scoreManager;
+    private ScoreManager<Planning, HardMediumSoftScore> scoreManager;
 
   @PostMapping("/solve")
   public PlanningSolution solve(@RequestBody PlanningInput inputs) {

+ 3 - 3
src/main/java/fr/jaquin/bdlg/planner/domain/Planning.java

@@ -7,7 +7,7 @@ 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.hardsoft.HardSoftScore;
+import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
 
 @PlanningSolution
 public class Planning {
@@ -30,7 +30,7 @@ public class Planning {
   private ArrayList<Assignement> assignements;
 
   @PlanningScore
-  private HardSoftScore score;
+  private HardMediumSoftScore score;
 
   public Planning() {}
 
@@ -66,7 +66,7 @@ public class Planning {
   public ArrayList<MealAssignement> getMealAssignements() {
     return mealAssignements;
   }
-  public HardSoftScore getScore() {
+  public HardMediumSoftScore getScore() {
     return this.score;
   }
 

+ 4 - 4
src/main/java/fr/jaquin/bdlg/planner/domain/PlanningSolution.java

@@ -1,12 +1,12 @@
 package fr.jaquin.bdlg.planner.domain;
 
 import java.util.ArrayList;
-import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
 
 public class PlanningSolution {
   private ArrayList<AssignementPair> assignements;
   private String message = "";
-  private HardSoftScore score;
+  private HardMediumSoftScore score;
 
   public PlanningSolution() {
     assignements = new ArrayList<AssignementPair>();
@@ -32,11 +32,11 @@ public class PlanningSolution {
   }
 
 
-  public HardSoftScore getScore() {
+  public HardMediumSoftScore getScore() {
     return score;
   }
 
-  public void setScore(HardSoftScore score) {
+  public void setScore(HardMediumSoftScore score) {
     this.score = score;
   }
 

+ 12 - 11
src/main/java/fr/jaquin/bdlg/planner/solver/PlanningConstraintProvider.java

@@ -3,7 +3,7 @@ package fr.jaquin.bdlg.planner.solver;
 import fr.jaquin.bdlg.planner.domain.Assignement;
 import fr.jaquin.bdlg.planner.domain.MealAssignement;
 
-import org.optaplanner.core.api.score.buildin.hardsoft.HardSoftScore;
+import org.optaplanner.core.api.score.buildin.hardmediumsoft.HardMediumSoftScore;
 import org.optaplanner.core.api.score.stream.Constraint;
 import org.optaplanner.core.api.score.stream.ConstraintCollectors;
 import org.optaplanner.core.api.score.stream.ConstraintFactory;
@@ -35,13 +35,13 @@ public class PlanningConstraintProvider implements ConstraintProvider {
   private Constraint completeAllTimeslot(ConstraintFactory constraintFactory) {
     return constraintFactory.from(Assignement.class)
         .filter((assignment) -> assignment.getVolonteer() == null)
-        .penalize("Timeslot not initialized ", HardSoftScore.ONE_HARD);
+        .penalize("Timeslot not initialized ", HardMediumSoftScore.ONE_HARD);
   }
 
   private Constraint feedAllVolunteer(ConstraintFactory constraintFactory) {
     return constraintFactory.from(MealAssignement.class)
         .filter((assignment) -> assignment.getMealSlot() == null)
-        .penalize("Meal not initialized ", HardSoftScore.ONE_HARD);
+        .penalize("Meal not initialized ", HardMediumSoftScore.ONE_HARD);
   }
 
   private Constraint volunteerConflict(ConstraintFactory constraintFactory) {
@@ -59,7 +59,7 @@ public class PlanningConstraintProvider implements ConstraintProvider {
             Joiners.lessThan(Assignement::getStartDateTime, Assignement::getEndDateTime),
             Joiners.greaterThan(Assignement::getEndDateTime, Assignement::getStartDateTime))
         // then penalize each pair with a hard weight.
-        .penalize("Volonteer conflict", HardSoftScore.ONE_HARD);
+        .penalize("Volonteer conflict", HardMediumSoftScore.ONE_HARD);
   }
 
   private Constraint volunteerMinRestTime(ConstraintFactory constraintFactory) {
@@ -77,7 +77,7 @@ public class PlanningConstraintProvider implements ConstraintProvider {
             Joiners.lessThan(Assignement::getStartDateTime, Assignement::getRestEndDateTime),
             Joiners.greaterThan(Assignement::getRestEndDateTime, Assignement::getStartDateTime))
         // then penalize each pair with a hard weight.
-        .penalize("Volonteer rest time", HardSoftScore.ONE_SOFT);
+        .penalize("Volonteer rest time", HardMediumSoftScore.ONE_MEDIUM);
   }
 
   private Constraint volunteerMealConflict(ConstraintFactory constraintFactory) {
@@ -93,26 +93,27 @@ public class PlanningConstraintProvider implements ConstraintProvider {
             Joiners.lessThan(Assignement::getStartDateTime, MealAssignement::getEndDateTime),
             Joiners.greaterThan(Assignement::getEndDateTime, MealAssignement::getStartDateTime))
         // then penalize each pair with a hard weight.
-        .penalize("Volonteer Meal conflict", HardSoftScore.ONE_HARD);
+        .penalize("Volonteer Meal conflict", HardMediumSoftScore.ONE_HARD);
   }
 
   private Constraint competencyConflict(ConstraintFactory constraintFactory) {
     // a volonteer must match required competencies.
     return getAssignedSlotStream(constraintFactory).penalize("Competence conflict",
-        HardSoftScore.ONE_HARD, Assignement::getCompetenceLackScore);
+        HardMediumSoftScore.ONE_HARD, Assignement::getCompetenceLackScore);
   }
 
   private Constraint competencyTeachingEffort(ConstraintFactory constraintFactory) {
     // We favor volonteer that already have required competencies.
+    // TODO: Idealy you should group by per volonteer and computed missing teachable competencies
     return getAssignedSlotStream(constraintFactory).penalize(
-        "Avoid teaching competences to volunteer", HardSoftScore.ONE_SOFT,
+        "Avoid teaching competences to volunteer", HardMediumSoftScore.ONE_SOFT,
         Assignement::getSoftCompetenceLackScore);
   }
 
   private Constraint preferenceApplication(ConstraintFactory constraintFactory) {
     // The system should favor timeslots selected by user.
     return getAssignedSlotStream(constraintFactory).reward("Preference application",
-        HardSoftScore.ONE_SOFT, Assignement::getPreferenceScore);
+        HardMediumSoftScore.ONE_SOFT, Assignement::getPreferenceScore);
   }
 
   private Constraint balanceLoad(ConstraintFactory constraintFactory) {
@@ -122,7 +123,7 @@ public class PlanningConstraintProvider implements ConstraintProvider {
         // ... look at volunteer and count nulber of associated slots ...
         .groupBy(Assignement::getVolonteer, ConstraintCollectors.count())
         // then penalize each pair with a hard weight.
-        .penalize("Fair workload balance", HardSoftScore.ONE_SOFT,
+        .penalize("Fair workload balance", HardMediumSoftScore.ONE_SOFT,
             (volonteer, slotCount) -> slotCount * slotCount);
   }
 
@@ -133,7 +134,7 @@ public class PlanningConstraintProvider implements ConstraintProvider {
         .groupBy(MealAssignement::getMealSlot, ConstraintCollectors.count())
         .filter((slot, volonteerCount) -> slot.getMaxAttendee() < volonteerCount)
         // then penalize each pair with a hard weight.
-        .penalize("Meal max attendee", HardSoftScore.ONE_HARD,
+        .penalize("Meal max attendee", HardMediumSoftScore.ONE_HARD,
             (slot, volonteerCount) -> (slot.getMaxAttendee() - volonteerCount)
                 * (slot.getMaxAttendee() - volonteerCount));
   }