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.

373 lines
8.9 KiB

package shared.model;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import network.Messages.Enums.RaceStatusEnum;
import network.Messages.Enums.RaceTypeEnum;
import shared.dataInput.BoatDataSource;
import shared.dataInput.RaceDataSource;
import shared.dataInput.RegattaDataSource;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.List;
/**
* Represents a yacht race.
* This is a base class inherited by {@link mock.model.MockRace} and {@link visualiser.model.VisualiserRaceState}.
* Has a course, state, wind, boundaries, etc.... Boats are added by inheriting classes (see {@link Boat}, {@link mock.model.MockBoat}, {@link visualiser.model.VisualiserBoat}.
*/
public abstract class RaceState {
/**
* Data source for race information.
*/
private RaceDataSource raceDataSource;
/**
* Data source for boat information.
*/
private BoatDataSource boatDataSource;
/**
* Data source for regatta information.
*/
private RegattaDataSource regattaDataSource;
/**
* Legs in the race.
* We have this in a separate list so that it can be observed.
*/
private ObservableList<Leg> legs;
/**
* The clock which tracks the race's start time, current time, and elapsed duration.
*/
private RaceClock raceClock;
/**
* The current status of the race.
*/
private RaceStatusEnum raceStatusEnum;
/**
* The race's wind.
*/
private Property<Wind> raceWind = new SimpleObjectProperty<>();
/**
* Constructs an empty race object.
* This is initialised into a "default" state, with no data.
*/
public RaceState() {
//Legs.
this.legs = FXCollections.observableArrayList();
//Race clock.
this.raceClock = new RaceClock(ZonedDateTime.now());
//Race status.
this.setRaceStatusEnum(RaceStatusEnum.NOT_ACTIVE);
//Wind.
this.setWind(Bearing.fromDegrees(0), 0);
}
/**
* Initialise the boats in the race.
* This sets their starting positions and current legs.
*/
protected abstract void initialiseBoats();
/**
* Updates the race to use a new list of legs, and adds a dummy "Finish" leg at the end.
* @param legs The new list of legs to use.
*/
protected void useLegsList(List<Leg> legs) {
this.legs.setAll(legs);
//We add a "dummy" leg at the end of the race.
if (getLegs().size() > 0) {
getLegs().add(new Leg("Finish", getLegs().size()));
}
}
/**
* Determines whether or not a specific leg is the last leg in the race.
* @param leg The leg to check.
* @return Returns true if it is the last, false otherwise.
*/
protected boolean isLastLeg(Leg leg) {
//Get the last leg.
Leg lastLeg = getLegs().get(getLegs().size() - 1);
//Check its ID.
int lastLegID = lastLeg.getLegNumber();
//Get the specified leg's ID.
int legID = leg.getLegNumber();
//Check if they are the same.
return legID == lastLegID;
}
/**
* Sets the race data source for the race.
* @param raceDataSource New race data source.
*/
public void setRaceDataSource(RaceDataSource raceDataSource) {
this.raceDataSource = raceDataSource;
this.getRaceClock().setStartingTime(raceDataSource.getStartDateTime());
useLegsList(raceDataSource.getLegs());
}
/**
* Sets the boat data source for the race.
* @param boatDataSource New boat data source.
*/
public void setBoatDataSource(BoatDataSource boatDataSource) {
this.boatDataSource = boatDataSource;
}
/**
* Sets the regatta data source for the race.
* @param regattaDataSource New regatta data source.
*/
public void setRegattaDataSource(RegattaDataSource regattaDataSource) {
this.regattaDataSource = regattaDataSource;
}
/**
* Returns the race data source for the race.
* @return Race data source.
*/
public RaceDataSource getRaceDataSource() {
return raceDataSource;
}
/**
* Returns the race data source for the race.
* @return Race data source.
*/
public BoatDataSource getBoatDataSource() {
return boatDataSource;
}
/**
* Returns the race data source for the race.
* @return Race data source.
*/
public RegattaDataSource getRegattaDataSource() {
return regattaDataSource;
}
/**
* Returns a list of {@link Mark} boats.
* @return List of mark boats.
*/
public List<Mark> getMarks() {
//BoatDataSource contains a collection of Marks, and RaceDataSource contains a collection of Compound marks (which contain marks). RaceDataSource is the "definitive" source of mark data.
List<Mark> marks = new ArrayList<>(getCompoundMarks().size() * 2);
for (CompoundMark compoundMark : getCompoundMarks()) {
if (compoundMark.getMark1() != null) {
marks.add(compoundMark.getMark1());
}
if (compoundMark.getMark2() != null) {
marks.add(compoundMark.getMark2());
}
}
return marks;
}
/**
* Returns a list of sourceIDs participating in the race.
* @return List of sourceIDs participating in the race.
*/
public List<Integer> getParticipants() {
return raceDataSource.getParticipants();
}
/**
* Returns the current race status.
* @return The current race status.
*/
public RaceStatusEnum getRaceStatusEnum() {
return raceStatusEnum;
}
/**
* Sets the current race status.
* @param raceStatusEnum The new status of the race.
*/
public void setRaceStatusEnum(RaceStatusEnum raceStatusEnum) {
this.raceStatusEnum = raceStatusEnum;
}
/**
* Returns the type of race this is.
* @return The type of race this is.
*/
public RaceTypeEnum getRaceType() {
return raceDataSource.getRaceType();
}
/**
* Returns the name of the regatta.
* @return The name of the regatta.
*/
public String getRegattaName() {
return regattaDataSource.getRegattaName();
}
/**
* Updates the race to have a specified wind bearing and speed.
* @param windBearing New wind bearing.
* @param windSpeedKnots New wind speed, in knots.
*/
public void setWind(Bearing windBearing, double windSpeedKnots) {
Wind wind = new Wind(windBearing, windSpeedKnots);
setWind(wind);
}
/**
* Updates the race to have a specified wind (bearing and speed).
* @param wind New wind.
*/
public void setWind(Wind wind) {
this.raceWind.setValue(wind);
}
/**
* Returns the wind bearing.
* @return The wind bearing.
*/
public Bearing getWindDirection() {
return raceWind.getValue().getWindDirection();
}
/**
* Returns the wind speed.
* Measured in knots.
* @return The wind speed.
*/
public double getWindSpeed() {
return raceWind.getValue().getWindSpeed();
}
/**
* Returns the race's wind.
* @return The race's wind.
*/
public Property<Wind> windProperty() {
return raceWind;
}
/**
* Returns the RaceClock for this race.
* This is used to track the start time, current time, and elapsed duration of the race.
* @return The RaceClock for the race.
*/
public RaceClock getRaceClock() {
return raceClock;
}
/**
* Returns the number of legs in the race.
* @return The number of legs in the race.
*/
public int getLegCount() {
//We minus one, as we have added an extra "dummy" leg.
return getLegs().size() - 1;
}
/**
* Returns the race boundary.
* @return The race boundary.
*/
public List<GPSCoordinate> getBoundary() {
return raceDataSource.getBoundary();
}
/**
* Returns the marks of the race.
* @return Marks of the race.
*/
public List<CompoundMark> getCompoundMarks() {
return raceDataSource.getCompoundMarks();
}
/**
* Returns the legs of the race.
* @return Legs of the race.
*/
public ObservableList<Leg> getLegs() {
return legs;
}
/**
* Returns the ID of the race.
* @return ID of the race.
*/
public int getRaceId() {
return raceDataSource.getRaceId();
}
/**
* Returns the ID of the regatta.
* @return The ID of the regatta.
*/
public int getRegattaID() {
return regattaDataSource.getRegattaID();
}
/**
* Returns the name of the course.
* @return Name of the course.
*/
public String getCourseName() {
return regattaDataSource.getCourseName();
}
}