Fixed gate passing algorithm

boats now must pass through the correct way. This works for start in-race and finish gates
Refactored yacht algorithm code for better readability
Logging function added or seeing mark roundings occur

tags: #story[1124] #pair[hyi25, wmu16]
This commit is contained in:
William Muir
2017-08-08 15:58:13 +12:00
parent ed0a783374
commit b0e7dddaf3
2 changed files with 131 additions and 48 deletions
+109 -26
View File
@@ -58,10 +58,12 @@ public class Yacht {
private GeoPoint location; private GeoPoint location;
private Integer boatStatus; private Integer boatStatus;
private Double velocity; private Double velocity;
//MARK ROUNDING INFO //MARK ROUNDING INFO
private GeoPoint lastLocation; //For purposes of mark rounding calculations private GeoPoint lastLocation; //For purposes of mark rounding calculations
private Boolean hasEnteredRoundingZone; //The distance that the boat must be from the mark to round private Boolean hasEnteredRoundingZone; //The distance that the boat must be from the mark to round
private Boolean hasPassedFirstLine; //The line extrapolated from the next mark to the current mark private Boolean hasPassedFirstLine; //The line extrapolated from the next mark to the current mark
private Boolean hasPassedThroughGate;
//CLIENT SIDE //CLIENT SIDE
private List<YachtLocationListener> locationListeners = new ArrayList<>(); private List<YachtLocationListener> locationListeners = new ArrayList<>();
@@ -88,6 +90,7 @@ public class Yacht {
this.hasEnteredRoundingZone = false; this.hasEnteredRoundingZone = false;
this.hasPassedFirstLine = false; this.hasPassedFirstLine = false;
this.hasPassedThroughGate = false;
} }
/** /**
@@ -129,7 +132,7 @@ public class Yacht {
//CHECK FOR MARK ROUNDING //CHECK FOR MARK ROUNDING
//Algorithm wont currently work on last gate and start gate //Algorithm wont currently work on last gate and start gate
checkForMarkRounding(); checkForLegProgression();
// TODO: 3/08/17 wmu16 - Implement line cross check here // TODO: 3/08/17 wmu16 - Implement line cross check here
} }
@@ -157,6 +160,47 @@ public class Yacht {
} }
/**
* 4 Different cases of progression in the race
* 1 - Passing the start line
* 2 - Passing any in-race Gate
* 3 - Passing any in-race Mark
* 4 - Passing the finish line
*/
private void checkForLegProgression() {
CompoundMark currentMark = GameState.getMarkOrder().getCurrentMark(currentMarkSeqID);
if (currentMarkSeqID == 0) {
checkStartLineCrossing(currentMark);
} else if (GameState.getMarkOrder().isLastMark(currentMarkSeqID)) {
checkFinishLineCrossing(currentMark);
} else if (currentMark.isGate()) {
checkGateRounding(currentMark);
} else {
checkMarkRounding(currentMark);
}
}
/**
* If we pass the start line gate in the correct direction, progress
*
* @param currentMark The current gate
*/
private void checkStartLineCrossing(CompoundMark currentMark) {
Integer crossedLine = GeoUtility.checkCrossedLine(currentMark.getSubMark(1),
currentMark.getSubMark(2), lastLocation, location);
if (crossedLine > 0) {
CompoundMark nextMark = GameState.getMarkOrder().getNextMark(currentMarkSeqID);
Boolean isClockwiseCross = GeoUtility.isClockwise(currentMark.getSubMark(1),
currentMark.getSubMark(2),
nextMark.getSubMark(1));
if (crossedLine == 2 && isClockwiseCross || crossedLine == 1 && !isClockwiseCross) {
logMarkRounding(currentMark);
currentMarkSeqID++;
}
}
}
/** /**
* This algorithm checks for mark rounding. And increments the currentMarSeqID number attribute * This algorithm checks for mark rounding. And increments the currentMarSeqID number attribute
* of the yacht if so. * of the yacht if so.
@@ -172,57 +216,85 @@ public class Yacht {
* A more visual representation of this algorithm can be seen on the Wiki under * A more visual representation of this algorithm can be seen on the Wiki under
* 'mark passing algorithm' * 'mark passing algorithm'
*/ */
private void checkForMarkRounding() { private void checkMarkRounding(CompoundMark currentMark) {
CompoundMark currentMark = GameState.getMarkOrder().getCurrentMark(currentMarkSeqID);
if (GameState.getMarkOrder().isLastMark(currentMarkSeqID) || currentMarkSeqID == 0) {
if (GeoUtility.checkCrossedLine(currentMark.getSubMark(1),
currentMark.getSubMark(2), lastLocation, location) > 0) {
System.out.println(
"(" + currentMarkSeqID + ") Passed gate: " + currentMark.getMarks().get(0)
.getName()
+ " ID(" + currentMark.getId() + ")");
currentMarkSeqID++;
}
} else {
//ALL OTHER MARKS
distanceToNextMark = calcDistanceToNextMark(); distanceToNextMark = calcDistanceToNextMark();
// System.out.println("distanceToNextMark = " + distanceToNextMark);
CompoundMark nextMark = GameState.getMarkOrder().getNextMark(currentMarkSeqID); CompoundMark nextMark = GameState.getMarkOrder().getNextMark(currentMarkSeqID);
CompoundMark prevMark = GameState.getMarkOrder().getPreviousMark(currentMarkSeqID); CompoundMark prevMark = GameState.getMarkOrder().getPreviousMark(currentMarkSeqID);
//1 TEST FOR ENTERING THE ROUDNING DISTANCE //1 TEST FOR ENTERING THE ROUNDING DISTANCE
if (distanceToNextMark < ROUNDING_DISTANCE) { if (distanceToNextMark < ROUNDING_DISTANCE) {
hasEnteredRoundingZone = true; hasEnteredRoundingZone = true;
// System.out.println("Entered rounding zone!");
} }
//If the current mark is a gate mark we need to check both its marks for rounding, thus //If the current mark is a gate mark we need to check both its marks for rounding, thus
//we loop //we loop
for (Mark thisCurrentMark : currentMark.getMarks()) { for (Mark thisCurrentMark : currentMark.getMarks()) {
//2 TEST FOR CROSSING NEXT - CURRENT LINE FIRST //2 TEST FOR CROSSING NEXT - CURRENT LINE FIRST
if (GeoUtility.isPointInTriangle(lastLocation, location, nextMark.getMarks().get(0), if (GeoUtility
.isPointInTriangle(lastLocation, location, nextMark.getMarks().get(0),
thisCurrentMark)) { thisCurrentMark)) {
hasPassedFirstLine = true; hasPassedFirstLine = true;
} }
//3 TEST FOR CROSSING PREV - CURRENT LINE SECOND //3 TEST FOR CROSSING PREV - CURRENT LINE SECOND
if (GeoUtility.isPointInTriangle(lastLocation, location, prevMark.getMarks().get(0), if (GeoUtility
.isPointInTriangle(lastLocation, location, prevMark.getMarks().get(0),
thisCurrentMark)) { thisCurrentMark)) {
if (hasPassedFirstLine && hasEnteredRoundingZone) { if (hasPassedFirstLine && hasEnteredRoundingZone) {
currentMarkSeqID++; currentMarkSeqID++;
hasPassedFirstLine = false; hasPassedFirstLine = false;
hasEnteredRoundingZone = false; hasEnteredRoundingZone = false;
System.out.println( hasPassedThroughGate = false;
"(" + currentMarkSeqID + ") Passed mark: " + currentMark.getMarks() logMarkRounding(currentMark);
.get(0).getName()
+ " ID(" + currentMark.getId() + ")");
break; break;
} }
} }
} }
} }
/**
* Checks if a gate line has been crossed and in the correct direction
*
* @param currentMark The current gate
*/
private void checkGateRounding(CompoundMark currentMark) {
Integer crossedLine = GeoUtility.checkCrossedLine(currentMark.getSubMark(1),
currentMark.getSubMark(2), lastLocation, location);
//We have crossed the line
if (crossedLine > 0) {
CompoundMark prevMark = GameState.getMarkOrder().getPreviousMark(currentMarkSeqID);
Boolean isClockwiseCross = GeoUtility.isClockwise(currentMark.getSubMark(1),
currentMark.getSubMark(2),
prevMark.getSubMark(1));
if (crossedLine == 1 && isClockwiseCross || crossedLine == 2 && !isClockwiseCross) {
hasPassedThroughGate = true;
}
}
if (hasPassedThroughGate) {
checkMarkRounding(currentMark);
}
}
/**
* If we pass the finish gate in the correct direction // TODO: 8/08/17 wmu16 - do something
*
* @param currentMark The current gate
*/
private void checkFinishLineCrossing(CompoundMark currentMark) {
Integer crossedLine = GeoUtility.checkCrossedLine(currentMark.getSubMark(1),
currentMark.getSubMark(2), lastLocation, location);
if (crossedLine > 0) {
CompoundMark previousMark = GameState.getMarkOrder().getPreviousMark(currentMarkSeqID);
Boolean isClockwiseCross = GeoUtility.isClockwise(currentMark.getSubMark(1),
currentMark.getSubMark(2),
previousMark.getSubMark(1));
if (crossedLine == 1 && isClockwiseCross || crossedLine == 2 && !isClockwiseCross) {
logMarkRounding(currentMark);
// TODO: 8/08/17 wmu16 - Do something!
}
}
} }
@@ -508,6 +580,17 @@ public class Yacht {
} }
} }
private void logMarkRounding(CompoundMark currentMark) {
String typeString = "mark";
if (currentMark.isGate()) {
typeString = "gate";
}
System.out.println(
"(" + currentMarkSeqID + ") Passed " + typeString + ": " + currentMark.getMarks().get(0)
.getName()
+ " ID(" + currentMark.getId() + ")");
}
public void addLocationListener (YachtLocationListener listener) { public void addLocationListener (YachtLocationListener listener) {
locationListeners.add(listener); locationListeners.add(listener);
} }
@@ -193,7 +193,7 @@ public class GeoUtility {
* @param point the point to be tested * @param point the point to be tested
* @return true if the point is on the RHS of the line * @return true if the point is on the RHS of the line
*/ */
private static Boolean isClockwise(GeoPoint v1, GeoPoint v2, GeoPoint point) { public static Boolean isClockwise(GeoPoint v1, GeoPoint v2, GeoPoint point) {
return getBearingDiff(getBearing(v1, v2), getBearing(v1, point)) < 180; return getBearingDiff(getBearing(v1, v2), getBearing(v1, point)) < 180;
} }