You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.7 KiB

package visualiser.Commands.VisualiserRaceCommands;
import mock.model.commandFactory.Command;
import network.Messages.BoatStatus;
import network.Messages.Enums.BoatStatusEnum;
import network.Messages.RaceStatus;
import shared.exceptions.BoatNotFoundException;
import shared.model.Leg;
import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRaceEvent;
import visualiser.model.VisualiserRaceState;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Command created when a {@link RaceStatus} message is received.
*/
public class RaceStatusCommand implements Command {
/**
* The message to operate on.
*/
private RaceStatus raceStatus;
/**
* The context to operate on.
*/
private VisualiserRaceState visualiserRace;
/**
* Creates a new {@link RaceStatusCommand}, which operates on a given {@link VisualiserRaceState}.
* @param raceStatus The message to operate on.
* @param visualiserRace The context to operate on.
*/
public RaceStatusCommand(RaceStatus raceStatus, VisualiserRaceState visualiserRace) {
this.raceStatus = raceStatus;
this.visualiserRace = visualiserRace;
}
@Override
public void execute() {
//Race status enum.
visualiserRace.setRaceStatusEnum(raceStatus.getRaceStatus());
//Wind.
visualiserRace.setWind(
raceStatus.getWindDirection(),
raceStatus.getWindSpeed() );
//Current race time.
visualiserRace.getRaceClock().setUTCTime(raceStatus.getCurrentTime());
for (BoatStatus boatStatus : raceStatus.getBoatStatuses()) {
updateBoatStatus(boatStatus);
}
visualiserRace.updateBoatPositions(visualiserRace.getBoats());
}
/**
* Updates a single boat's status using the boatStatus message.
* @param boatStatus BoatStatus message to get data from.
*/
private void updateBoatStatus(BoatStatus boatStatus) {
try {
VisualiserBoat boat = visualiserRace.getBoat(boatStatus.getSourceID());
//Time at next mark.
updateEstimatedTimeAtNextMark(boatStatus, boat);
BoatStatusEnum newBoatStatusEnum = boatStatus.getBoatStatus();
//Time at last mark.
initialiseTimeAtLastMark(boat, boat.getStatus(), newBoatStatusEnum);
//Status.
boat.setStatus(newBoatStatusEnum);
List<Leg> legs = visualiserRace.getLegs();
//Leg.
updateLeg(boatStatus.getLegNumber(), boat, legs);
//Set finish time if boat finished.
attemptUpdateFinishTime(boatStatus, boat, legs);
} catch (BoatNotFoundException e) {
//Logger.getGlobal().log(Level.WARNING, "RaceStatusCommand.updateBoatStatus: " + this + " could not execute. Boat with sourceID: " + boatStatus.getSourceID() + " not found.", e);
return;
}
}
/**
* Attempts to update the finish time of the boat. Only works if the boat has actually finished the race.
* @param boatStatus BoatStatus to read data from.
* @param boat Boat to update.
* @param legs Legs of the race.
*/
private void attemptUpdateFinishTime(BoatStatus boatStatus, VisualiserBoat boat, List<Leg> legs) {
if (boat.getStatus() == BoatStatusEnum.FINISHED || boatStatus.getLegNumber() == legs.size()) {
boat.setTimeFinished(visualiserRace.getRaceClock().getCurrentTimeMilli());
boat.setStatus(BoatStatusEnum.FINISHED);
}
}
/**
* Updates a boat's leg.
* @param legNumber The new leg number.
* @param boat The boat to update.
* @param legs The legs in the race.
*/
private void updateLeg(int legNumber, VisualiserBoat boat, List<Leg> legs) {
if (legNumber >= 1 && legNumber < legs.size()) {
if (boat.getCurrentLeg() != legs.get(legNumber)) {
boatFinishedLeg(boat, legs.get(legNumber));
}
}
}
/**
* Initialises the time at last mark for a boat. Only changes if the boat's status is changing from non-racing to racing.
* @param boat The boat to update.
* @param currentBoatStatus The current status of the boat.
* @param newBoatStatusEnum The new status of the boat, from the BoatStatus message.
*/
private void initialiseTimeAtLastMark(VisualiserBoat boat, BoatStatusEnum currentBoatStatus, BoatStatusEnum newBoatStatusEnum) {
//If we are changing from non-racing to racing, we need to initialise boat with their time at last mark.
if ((currentBoatStatus != BoatStatusEnum.RACING) && (newBoatStatusEnum == BoatStatusEnum.RACING)) {
boat.setTimeAtLastMark(visualiserRace.getRaceClock().getCurrentTime());
}
}
/**
* Updates the estimated time at next mark for a given boat.
* @param boatStatus BoatStatus to read data from.
* @param boat Boat to update.
*/
private void updateEstimatedTimeAtNextMark(BoatStatus boatStatus, VisualiserBoat boat) {
boat.setEstimatedTimeAtNextMark(visualiserRace.getRaceClock().getLocalTime(boatStatus.getEstTimeAtNextMark()));
}
/**
* Updates a boat's leg to a specified leg. Also records the order in which the boat passed the leg.
* @param boat The boat to update.
* @param leg The leg to use.
*/
private void boatFinishedLeg(VisualiserBoat boat, Leg leg) {
//Record order in which boat finished leg.
visualiserRace.getLegCompletionOrder().get(boat.getCurrentLeg()).add(boat);
//Update boat.
boat.setCurrentLeg(leg);
boat.setTimeAtLastMark(visualiserRace.getRaceClock().getCurrentTime());
}
}