package solutions;
import de.tu_darmstadt.es.sopra.exercises.Game;
import de.tu_darmstadt.es.sopra.model.external.factories.CommandFactory;
import de.tu_darmstadt.es.sopra.model.external.interfaces.scenario.IScenario;
import de.tu_darmstadt.es.sopra.model.external.interfaces.scenario.ILocation;
import de.tu_darmstadt.es.sopra.model.external.interfaces.scenario.ITransporter;
import de.tu_darmstadt.es.sopra.model.external.interfaces.scenario.IProductionFacility;
import de.tu_darmstadt.es.sopra.model.external.interfaces.scenario.IScenarioElement;
import de.tu_darmstadt.es.sopra.model.external.implementations.type.GoodType;
import de.tu_darmstadt.es.sopra.model.external.implementations.type.LocationType;
import de.tu_darmstadt.es.sopra.model.external.interfaces.command.ITransporterCommand;
import java.util.Vector;
/**
* This class implements a solution of AB4.1.<p>
*
* @author Markus Schmidt
* @version 1.2
*/
public class Solution09 extends Game {
private final String[] strAuthors = { "Markus", "Lukas", "Paulus", "Loddar" };
/**
* A single command factory object for the whole runtime.
*/
private CommandFactory cmdFactory;
/**
* The object to compute shortest paths.
*/
private Solution08 impAPSP;
/**
* a flag to indicate the end of the exercise
*/
private boolean bolFinished;
/**
* transporter t1
*/
private ITransporter traT1;
/**
* location of type pump
*/
private ILocation locPump;
/**
* location of type mill
*/
private ILocation locMill;
/**
* shortest path to solve exercise (Vector of location names).
*/
private Vector<String> vecPath;
/**
* Constructor with no arguments.<p>
*
*/
public Solution09() {
super();
// Create command factory object, APSP object and Vector to store path.
impAPSP = new Solution08();
cmdFactory = new CommandFactory();
vecPath = new Vector<String>();
// init variables
bolFinished = true;
locPump = null;
locMill = null;
}
/**
* Returns informations of the team.<p>
*
* @return text with team information
*/
public String getTeam() {
return "G1T9";
}
/**
* Returns version of this implementation.<p>
*
* @return version as text.
*/
public String getVersion() {
return "1.0";
}
/**
* Returns authors of this solution.<p>
*
* @return String array with author names
*/
public String[] getAuthors() {
return strAuthors;
}
/**
* This method is called once before the first round.<p>
* This is a good place to do some initialization for the whole game.
*
* @param scenario the scenario
* @see #planningPhase
*/
public void preparationPhase(IScenario scenario) {
Solution04 impSol4;
IScenarioElement locT1;
Vector<ILocation> vecPumps, vecMills;
String strLoc1, strLoc2, strLocs[];
// create array of location names
strLocs = (String[]) scenario.getLocations().keySet().toArray(new String[0]);
// try to get location of transporter t1 and the transporter itself
try {
traT1 = scenario.getTransporter("t1");
locT1 = traT1.getVisitedScenarioElement();
} catch (Exception e) { traT1 = null; locT1 = null; }
// try to get all pump locations and mill locations
impSol4 = new Solution04();
vecPumps = impSol4.getLocationsOfType(scenario, LocationType.PUMP);
vecMills = impSol4.getLocationsOfType(scenario, LocationType.MILL);
// calculate if all necessary parts are available
bolFinished = ((locT1 == null) || (traT1 == null) ||
(vecPumps == null) || (vecMills == null) ||
(vecPumps.size() == 0) || (vecMills.size() == 0));
if (!bolFinished) {
// compute APSP
impAPSP.computeAPSP(scenario, strLocs);
// compute minimal duration out of all possible combinations
computeShortestDuration(locT1, vecPumps, vecMills);
// create Vector containing the whole path.
strLoc1 = locT1.getId();
strLoc2 = locPump.getId();
if (strLoc1.equals(strLoc2))
vecPath.add(strLoc1);
else
vecPath.addAll(impAPSP.getShortestPath(strLoc1, strLoc2));
vecPath.addAll(impAPSP.getShortestPath(strLoc2, locMill.getId()));
}
}
/**
* This method is called at the start of every round.<p>
*
*
* @param scenario the scenario
* @param round the current round (first round is 1).
* @see #preparationPhase
*/
public void planningPhase(IScenario scenario, int round) {
// check scenario
if (bolFinished)
finished();
else {
if (round == 1)
doRound1(scenario);
else
doRounds2_N(scenario);
}
}
/**
* Do all actions for round 1.<p>
*
* @param scenario a scenario
*/
private void doRound1(IScenario scenario) {
IProductionFacility proPump;
String strLocation;
try {
// create command to produce water and start production
proPump = (IProductionFacility) locPump;
proPump.assignCommand(cmdFactory.getProduceCommand(proPump));
// start transporter if not at pump location
strLocation = vecPath.remove(0);
if (!strLocation.equals(locPump.getId()))
// send transporter to first destination
travel(scenario);
} catch (Exception e) { }
}
/**
* Do all actions for rounds greater than 1.<p>
*
* @param scenario a scenario
*/
private void doRounds2_N(IScenario scenario) {
ITransporterCommand cmdTrans;
String strLocation;
int intTransportedLoad;
// get current location and transporter load
strLocation = traT1.getVisitedScenarioElement().getId();
intTransportedLoad = traT1.getTransportedGoodSet().getTotalQuantity();
try {
// check for upload: location must be pump
if (strLocation.equals(locPump.getId())) {
// check transporter load
if (intTransportedLoad == 0) {
// production must be finished
if (!((IProductionFacility)locPump).hasCommand()) {
cmdTrans = cmdFactory.getUploadCommand(traT1, 20,
GoodType.WATER);
traT1.assignCommand(cmdTrans);
}
} else {
// upload finished.
// remove current location and travel to next location
vecPath.remove(0);
travel(scenario);
}
}
// check for unload: location must be mill AND good loaded
else if ((strLocation.equals(locMill.getId())) &&
(intTransportedLoad == 20)) {
// unload 20 units of water
cmdTrans = cmdFactory.getUnloadCommand(traT1, 20,
GoodType.WATER);
traT1.assignCommand(cmdTrans);
// set flag to finish
bolFinished = true;
}
// on the road. try to travel to next location
else {
if ((traT1.getCommand() == null) && (!vecPath.isEmpty()))
travel(scenario);
}
} catch (Exception e) { }
}
/**
* create and assign a command to travel to next destination.<p>
*
* @param scenario a scenario
*/
private void travel(IScenario scenario) {
ILocation locTemp;
try {
// create and assign travel command to next destination
locTemp = scenario.getLocation(vecPath.get(0));
traT1.assignCommand(cmdFactory.getTravelCommand(traT1, locTemp));
// remove used destination
vecPath.remove(0);
} catch (Exception e) { }
}
/**
* Computes the whole duration to solve the exercise with the given locations.<p>
*
* @param trans location of transporter
* @param pump location of pump
* @param mill location of mill
*/
private void computeShortestDuration(IScenarioElement transporter,
Vector<ILocation> pumps,
Vector<ILocation> mills) {
int intI, intJ, intMinDuration, intDuration;
// init minimal duration
intMinDuration = Integer.MAX_VALUE;
// calculate duration of all possible combinations
for (intI = 0; intI < pumps.size(); intI++)
for (intJ = 0; intJ < mills.size(); intJ++) {
// get duration for the current combination
intDuration = getDuration(transporter,
pumps.get(intI),
mills.get(intJ));
// shorter duration found?
if (intDuration < intMinDuration) {
// set combination with shortest duration
locPump = pumps.get(intI);
locMill = mills.get(intJ);
intMinDuration = intDuration;
}
}
}
/**
* Returns the whole duration to solve the exercise with the given locations.<p>
*
* @param trans location of transporter
* @param pump location of pump
* @param mill location of mill
* @return duration
*/
private int getDuration(IScenarioElement trans, ILocation pump, ILocation mill) {
int intT2P, intP2M;
// get durations to travel between two locations
intT2P = impAPSP.getShortestPathDuration(trans.getId(), pump.getId());
intP2M = impAPSP.getShortestPathDuration(pump.getId(), mill.getId());
// is duration to reach pump higher than production time?
if (intT2P > 2)
return intT2P + 1 + intP2M + 1;
else
return 2 + 1 + intP2M + 1;
}
}