public void processWorkingSolutionDuringMove(
     int uninitializedVariableCount, Score score, AbstractStepScope stepScope) {
   AbstractSolverPhaseScope phaseScope = stepScope.getPhaseScope();
   DefaultSolverScope solverScope = phaseScope.getSolverScope();
   int bestUninitializedVariableCount = solverScope.getBestUninitializedVariableCount();
   Score bestScore = solverScope.getBestScore();
   boolean bestScoreImproved;
   if (uninitializedVariableCount == bestUninitializedVariableCount) {
     bestScoreImproved = score.compareTo(bestScore) > 0;
   } else {
     bestScoreImproved = uninitializedVariableCount < bestUninitializedVariableCount;
   }
   // The method processWorkingSolutionDuringMove() is called 0..* times
   // bestScoreImproved is initialized on false before the first call here
   if (bestScoreImproved) {
     stepScope.setBestScoreImproved(bestScoreImproved);
   }
   if (bestScoreImproved) {
     phaseScope.setBestSolutionStepIndex(stepScope.getStepIndex());
     Solution newBestSolution = solverScope.getScoreDirector().cloneWorkingSolution();
     updateBestSolution(solverScope, newBestSolution, uninitializedVariableCount);
   } else if (assertBestScoreIsUnmodified) {
     solverScope.assertScoreFromScratch(solverScope.getBestSolution());
   }
 }
 @Override
 public void stepEnded(AbstractStepScope stepScope) {
   if (stepScope.isBestSolutionCloningDelayed()) {
     return;
   }
   AbstractSolverPhaseScope phaseScope = stepScope.getPhaseScope();
   int uninitializedVariableCount = stepScope.getUninitializedVariableCount();
   Score score = stepScope.getScore();
   DefaultSolverScope solverScope = phaseScope.getSolverScope();
   int bestUninitializedVariableCount = solverScope.getBestUninitializedVariableCount();
   Score bestScore = solverScope.getBestScore();
   boolean bestScoreImproved;
   if (uninitializedVariableCount == bestUninitializedVariableCount) {
     bestScoreImproved = score.compareTo(bestScore) > 0;
   } else {
     bestScoreImproved = uninitializedVariableCount < bestUninitializedVariableCount;
   }
   stepScope.setBestScoreImproved(bestScoreImproved);
   if (bestScoreImproved) {
     phaseScope.setBestSolutionStepIndex(stepScope.getStepIndex());
     Solution newBestSolution = stepScope.createOrGetClonedSolution();
     updateBestSolution(solverScope, newBestSolution, uninitializedVariableCount);
   } else if (assertBestScoreIsUnmodified) {
     solverScope.assertScoreFromScratch(solverScope.getBestSolution());
   }
 }
 private void initSelectedPlanningValueList(AbstractSolverPhaseScope phaseScope) {
   if (valueRangeDescriptor.isEntityIndependent()) {
     CountableValueRange<?> valueRange =
         (CountableValueRange<?>)
             ((EntityIndependentValueRangeDescriptor) valueRangeDescriptor)
                 .extractValueRange(phaseScope.getWorkingSolution());
     cachedPlanningValues = Lists.newArrayList(valueRange.createOriginalIterator());
   } else {
     cachedPlanningValues = null;
   }
 }
 @Override
 public void phaseStarted(AbstractSolverPhaseScope phaseScope) {
   scoreDirector = phaseScope.getScoreDirector();
   workingRandom = phaseScope.getWorkingRandom();
   initSelectedPlanningValueList(phaseScope);
 }