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.

265 lines
7.2 KiB

package shared.model;
import shared.xml.Race.XMLCompoundMark;
import shared.enums.RoundingType;
/**
* Represents a compound mark - that is, either one or two individual marks which form a single compound mark.
*/
public class CompoundMark extends XMLCompoundMark{
/**
* The ID of the compound mark.
*/
private int id;
/**
* The name of the compound mark.
*/
private String name;
/**
* The first mark in the compound mark.
*/
private Mark mark1;
/**
* The second mark in the compound mark.
*/
private Mark mark2;
/**
* The average coordinate of the compound mark.
*/
private GPSCoordinate averageGPSCoordinate;
/**
* The side that the mark must be rounded on
*/
private RoundingType roundingType;
/**
* Constructs a compound mark from a single mark.
* @param id the id of the compound mark
* @param name name of the compound mark
* @param mark1 The individual mark that comprises this compound mark.
*/
public CompoundMark(int id, String name, Mark mark1) {
this(id, name, mark1, null);
}
/**
* Constructs a compound mark from a pair of marks.
* @param id the id of the compound mark
* @param name name of the compound mark
* @param mark1 The first individual mark that comprises this compound mark.
* @param mark2 The second individual mark that comprises this compound mark.
*/
public CompoundMark(int id, String name, Mark mark1, Mark mark2) {
//parent set up
super();
setName(name);
setCompoundMarkID(id);
getMark().add(mark1);
if (mark2 != null) getMark().add(mark2);
this.id = id;
this.name = name;
this.mark1 = mark1;
this.mark2 = mark2;
this.averageGPSCoordinate = calculateAverage();
}
/**
* Returns the ID of this compound mark.
* @return The ID of this compound mark.
*/
public int getId() {
return id;
}
/**
* Returns the first mark of the compound mark.
* @return The first mark of the compound mark.
*/
public Mark getMark1() {
return mark1;
}
/**
* Returns the second mark of the compound mark.
* @return The second mark of the compound mark.
*/
public Mark getMark2() {
return mark2;
}
/**
* Returns the position of the first mark in the compound mark.
* @return The position of the first mark in the compound mark.
*/
public GPSCoordinate getMark1Position() {
return mark1.getPosition();
}
/**
* Returns the position of the second mark in the compound mark.
* @return The position of the second mark in the compound mark.
*/
public GPSCoordinate getMark2Position() {
return mark2.getPosition();
}
/**
* Returns the average coordinate of the compound mark.
* @return The average coordinate of the compound mark.
*/
public GPSCoordinate getAverageGPSCoordinate() {
return averageGPSCoordinate;
}
/**
* Calculates the average coordinate of the compound mark.
* @return The average coordinate of the compound mark.
*/
private GPSCoordinate calculateAverage() {
//If the compound mark only contains one mark, the average is simply the first mark's position.
if (this.mark2 == null) {
return this.getMark1Position();
}
//Otherwise, calculate the average of both marks.
GPSCoordinate averageCoordinate = GPSCoordinate.calculateAverageCoordinate(this.getMark1Position(), this.getMark2Position());
return averageCoordinate;
}
/**
* Used to find how far apart the marks that make up this gate are
* If this compound mark is only one point return base length of 250m
* @return the acceptable distance to round a mark
*/
public double getRoundingDistance(){
if (mark2 != null){
return GPSCoordinate.calculateDistanceMeters(mark1.getPosition(), mark2.getPosition());
}else{
return 400;
}
}
/**
* Used to get how this mark should be rounded
* @return rounding type for mark
*/
public RoundingType getRoundingType() {
return roundingType;
}
/**
* Used to set the type of rounding for this mark
* @param roundingType rounding type to set
*/
public void setRoundingType(RoundingType roundingType) {
this.roundingType = roundingType;
}
/**
* Used to find the mark that is to be rounded at a gate when approaching from the south
* will also give the single mark if there is only one
* @param bearing the bearing a boat will approach form
* @return the mark to round
*/
public Mark getMarkForRounding(Bearing bearing){
Mark westMostMark;
Mark eastMostMark;
Mark northMostMark;
Mark southMostMark;
//check to see if there are two marks
if (mark2 == null){
return mark1;
}
//finds the mark furthest west and east
if(this.getMark1Position().getLatitude() > this.getMark2Position().getLatitude()){
westMostMark = this.mark1;
eastMostMark = this.mark2;
}else{
westMostMark = this.mark2;
eastMostMark = this.mark1;
}
//finds the mark furthest north and south
if(this.getMark1Position().getLongitude() > this.getMark2Position().getLongitude()){
northMostMark = this.mark1;
southMostMark = this.mark2;
}else{
northMostMark = this.mark2;
southMostMark = this.mark1;
}
if (bearing.degrees() > 315 || bearing.degrees() <= 45){
//north
switch (this.getRoundingType()){
case SP:
case Port:
return westMostMark;
case PS:
case Starboard:
return eastMostMark;
default:return null;
}
}else if(bearing.degrees() > 45 && bearing.degrees() <= 135){
//east
switch (this.getRoundingType()){
case SP:
case Port:
return northMostMark;
case PS:
case Starboard:
return southMostMark;
default:return null;
}
}else if(bearing.degrees() > 135 && bearing.degrees() <= 225){
//south
switch (this.getRoundingType()){
case SP:
case Port:
return eastMostMark;
case PS:
case Starboard:
return westMostMark;
default:return null;
}
}else if(bearing.degrees() > 225 && bearing.degrees() <= 315){
//west
switch (this.getRoundingType()){
case SP:
case Port:
return southMostMark;
case PS:
case Starboard:
return northMostMark;
default:return null;
}
}else{
return null;
}
}
}