/* * Copyright 2010 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.optaplanner.examples.dinnerparty.solver.solution.initializer; import java.util.ArrayList; import java.util.List; import org.optaplanner.core.api.score.Score; import org.optaplanner.core.api.score.buildin.simple.SimpleScore; import org.optaplanner.core.impl.phase.custom.AbstractCustomPhaseCommand; import org.optaplanner.core.impl.score.director.ScoreDirector; import org.optaplanner.examples.dinnerparty.domain.DinnerParty; import org.optaplanner.examples.dinnerparty.domain.Seat; import org.optaplanner.examples.dinnerparty.domain.SeatDesignation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class DinnerPartySolutionInitializer extends AbstractCustomPhaseCommand<DinnerParty> { protected final transient Logger logger = LoggerFactory.getLogger(getClass()); @Override public void changeWorkingSolution(ScoreDirector<DinnerParty> scoreDirector) { DinnerParty dinnerParty = scoreDirector.getWorkingSolution(); initializeSeatDesignationList(scoreDirector, dinnerParty); } private void initializeSeatDesignationList(ScoreDirector<DinnerParty> scoreDirector, DinnerParty dinnerParty) { // Assign one guest at a time List<Seat> undesignatedSeatList = new ArrayList<>(dinnerParty.getSeatList()); for (SeatDesignation seatDesignation : dinnerParty.getSeatDesignationList()) { Score bestScore = SimpleScore.valueOf(Integer.MIN_VALUE); Seat bestSeat = null; // Try every seat for that guest // TODO by reordening the seats so index 0 has a different table then index 1 and so on, // this will probably be faster because perfectMatch will be true sooner for (Seat seat : undesignatedSeatList) { if (seatDesignation.getGuest().getGender() == seat.getRequiredGender()) { scoreDirector.beforeVariableChanged(seatDesignation, "seat"); seatDesignation.setSeat(seat); scoreDirector.afterVariableChanged(seatDesignation, "seat"); scoreDirector.triggerVariableListeners(); Score score = scoreDirector.calculateScore(); if (score.toInitializedScore().compareTo(bestScore.toInitializedScore()) > 0) { bestScore = score; bestSeat = seat; } } } if (bestSeat == null) { throw new IllegalStateException("The bestSeat (" + bestSeat + ") cannot be null."); } scoreDirector.beforeVariableChanged(seatDesignation, "seat"); seatDesignation.setSeat(bestSeat); scoreDirector.afterVariableChanged(seatDesignation, "seat"); scoreDirector.triggerVariableListeners(); // There will always be enough allowed seats: ok to do this for this problem, but not ok for most problems undesignatedSeatList.remove(bestSeat); } } }