/* * Copyright 2015 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.coachshuttlegathering.domain; import java.util.List; import com.thoughtworks.xstream.annotations.XStreamAlias; import org.optaplanner.core.api.domain.entity.PlanningEntity; import org.optaplanner.core.api.domain.variable.AnchorShadowVariable; import org.optaplanner.core.api.domain.variable.CustomShadowVariable; import org.optaplanner.core.api.domain.variable.PlanningVariable; import org.optaplanner.core.api.domain.variable.PlanningVariableGraphType; import org.optaplanner.core.api.domain.variable.PlanningVariableReference; import org.optaplanner.examples.coachshuttlegathering.domain.location.RoadLocation; import org.optaplanner.examples.coachshuttlegathering.domain.solver.DepotAngleBusStopDifficultyWeightFactory; import org.optaplanner.examples.coachshuttlegathering.domain.solver.TransportTimeToHubUpdatingVariableListener; import org.optaplanner.examples.common.domain.AbstractPersistable; @PlanningEntity(difficultyWeightFactoryClass = DepotAngleBusStopDifficultyWeightFactory.class) @XStreamAlias("CsgBusStop") public class BusStop extends AbstractPersistable implements BusOrStop, StopOrHub { protected String name; protected RoadLocation location; protected int passengerQuantity; protected int transportTimeLimit; // Planning variables: changes during planning, between score calculations. protected BusOrStop previousBusOrStop; // Shadow variables protected BusStop nextStop; protected Bus bus; protected List<Shuttle> transferShuttleList; protected Integer transportTimeToHub; @Override public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public RoadLocation getLocation() { return location; } public void setLocation(RoadLocation location) { this.location = location; } public int getPassengerQuantity() { return passengerQuantity; } public void setPassengerQuantity(int passengerQuantity) { this.passengerQuantity = passengerQuantity; } public int getTransportTimeLimit() { return transportTimeLimit; } public void setTransportTimeLimit(int transportTimeLimit) { this.transportTimeLimit = transportTimeLimit; } @PlanningVariable(valueRangeProviderRefs = {"coachRange", "shuttleRange", "stopRange"}, graphType = PlanningVariableGraphType.CHAINED) public BusOrStop getPreviousBusOrStop() { return previousBusOrStop; } public void setPreviousBusOrStop(BusOrStop previousBusOrStop) { this.previousBusOrStop = previousBusOrStop; } @Override public BusStop getNextStop() { return nextStop; } @Override public void setNextStop(BusStop nextStop) { this.nextStop = nextStop; } @AnchorShadowVariable(sourceVariableName = "previousBusOrStop") @Override public Bus getBus() { return bus; } public void setBus(Bus bus) { this.bus = bus; } @Override public List<Shuttle> getTransferShuttleList() { return transferShuttleList; } @Override public void setTransferShuttleList(List<Shuttle> transferShuttleList) { this.transferShuttleList = transferShuttleList; } @CustomShadowVariable(variableListenerClass = TransportTimeToHubUpdatingVariableListener.class, sources = {@PlanningVariableReference(variableName = "nextStop"), @PlanningVariableReference(variableName = "bus"), @PlanningVariableReference(entityClass = Shuttle.class, variableName = "destination")}) @Override public Integer getTransportTimeToHub() { return transportTimeToHub; } public void setTransportTimeToHub(Integer transportTimeToHub) { this.transportTimeToHub = transportTimeToHub; } // ************************************************************************ // Complex methods // ************************************************************************ public int getDistanceFromPreviousCost() { if (previousBusOrStop == null) { return 0; } return getDistanceFrom(previousBusOrStop) * bus.getMileageCost(); } public int getDistanceFrom(BusOrStop busOrStop) { return bus.getDistanceFromTo(busOrStop.getLocation(), location); } public int getDistanceToDestinationCost(StopOrHub destination) { return bus.getDistanceFromTo(location, destination.getLocation()) * bus.getMileageCost(); } @Override public boolean isVisitedByCoach() { return bus != null && bus instanceof Coach; } public Integer getTransportTimeRemainder() { if (transportTimeToHub == null) { return null; } if (passengerQuantity <= 0) { return 0; } return transportTimeLimit - transportTimeToHub; } public String getTransportLabel() { if (passengerQuantity <= 0) { return null; } return (transportTimeToHub == null ? "inf" : transportTimeToHub.toString()) + "/" + transportTimeLimit; } @Override public String toString() { return name; } }