mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
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:
@@ -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,70 +160,139 @@ 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.
|
||||||
* The algorithm works by using the last mark, the current mark, the next mark and the change in
|
* The algorithm works by using the last mark, the current mark, the next mark and the change in
|
||||||
* boats location, like so:
|
* boats location, like so:
|
||||||
* -Condition 1:
|
* -Condition 1:
|
||||||
* The boat has entered the mark rounding distance
|
* The boat has entered the mark rounding distance
|
||||||
* -Condition 2:
|
* -Condition 2:
|
||||||
* The boat has passed the line extending from the last mark to the current mark
|
* The boat has passed the line extending from the last mark to the current mark
|
||||||
* -Condition 3:
|
* -Condition 3:
|
||||||
* The boat has passed the line extending from the next mark to the current mark
|
* The boat has passed the line extending from the next mark to the current mark
|
||||||
*
|
*
|
||||||
* 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);
|
distanceToNextMark = calcDistanceToNextMark();
|
||||||
|
CompoundMark nextMark = GameState.getMarkOrder().getNextMark(currentMarkSeqID);
|
||||||
|
CompoundMark prevMark = GameState.getMarkOrder().getPreviousMark(currentMarkSeqID);
|
||||||
|
|
||||||
if (GameState.getMarkOrder().isLastMark(currentMarkSeqID) || currentMarkSeqID == 0) {
|
//1 TEST FOR ENTERING THE ROUNDING DISTANCE
|
||||||
if (GeoUtility.checkCrossedLine(currentMark.getSubMark(1),
|
if (distanceToNextMark < ROUNDING_DISTANCE) {
|
||||||
currentMark.getSubMark(2), lastLocation, location) > 0) {
|
hasEnteredRoundingZone = true;
|
||||||
System.out.println(
|
}
|
||||||
"(" + currentMarkSeqID + ") Passed gate: " + currentMark.getMarks().get(0)
|
|
||||||
.getName()
|
//If the current mark is a gate mark we need to check both its marks for rounding, thus
|
||||||
+ " ID(" + currentMark.getId() + ")");
|
//we loop
|
||||||
currentMarkSeqID++;
|
for (Mark thisCurrentMark : currentMark.getMarks()) {
|
||||||
|
//2 TEST FOR CROSSING NEXT - CURRENT LINE FIRST
|
||||||
|
if (GeoUtility
|
||||||
|
.isPointInTriangle(lastLocation, location, nextMark.getMarks().get(0),
|
||||||
|
thisCurrentMark)) {
|
||||||
|
hasPassedFirstLine = true;
|
||||||
}
|
}
|
||||||
} else {
|
//3 TEST FOR CROSSING PREV - CURRENT LINE SECOND
|
||||||
//ALL OTHER MARKS
|
if (GeoUtility
|
||||||
distanceToNextMark = calcDistanceToNextMark();
|
.isPointInTriangle(lastLocation, location, prevMark.getMarks().get(0),
|
||||||
// System.out.println("distanceToNextMark = " + distanceToNextMark);
|
thisCurrentMark)) {
|
||||||
CompoundMark nextMark = GameState.getMarkOrder().getNextMark(currentMarkSeqID);
|
if (hasPassedFirstLine && hasEnteredRoundingZone) {
|
||||||
|
currentMarkSeqID++;
|
||||||
|
hasPassedFirstLine = false;
|
||||||
|
hasEnteredRoundingZone = false;
|
||||||
|
hasPassedThroughGate = false;
|
||||||
|
logMarkRounding(currentMark);
|
||||||
|
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);
|
CompoundMark prevMark = GameState.getMarkOrder().getPreviousMark(currentMarkSeqID);
|
||||||
|
Boolean isClockwiseCross = GeoUtility.isClockwise(currentMark.getSubMark(1),
|
||||||
//1 TEST FOR ENTERING THE ROUDNING DISTANCE
|
currentMark.getSubMark(2),
|
||||||
if (distanceToNextMark < ROUNDING_DISTANCE) {
|
prevMark.getSubMark(1));
|
||||||
hasEnteredRoundingZone = true;
|
if (crossedLine == 1 && isClockwiseCross || crossedLine == 2 && !isClockwiseCross) {
|
||||||
// System.out.println("Entered rounding zone!");
|
hasPassedThroughGate = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//If the current mark is a gate mark we need to check both its marks for rounding, thus
|
if (hasPassedThroughGate) {
|
||||||
//we loop
|
checkMarkRounding(currentMark);
|
||||||
for (Mark thisCurrentMark : currentMark.getMarks()) {
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//2 TEST FOR CROSSING NEXT - CURRENT LINE FIRST
|
/**
|
||||||
if (GeoUtility.isPointInTriangle(lastLocation, location, nextMark.getMarks().get(0),
|
* If we pass the finish gate in the correct direction // TODO: 8/08/17 wmu16 - do something
|
||||||
thisCurrentMark)) {
|
*
|
||||||
hasPassedFirstLine = true;
|
* @param currentMark The current gate
|
||||||
}
|
*/
|
||||||
|
private void checkFinishLineCrossing(CompoundMark currentMark) {
|
||||||
//3 TEST FOR CROSSING PREV - CURRENT LINE SECOND
|
Integer crossedLine = GeoUtility.checkCrossedLine(currentMark.getSubMark(1),
|
||||||
if (GeoUtility.isPointInTriangle(lastLocation, location, prevMark.getMarks().get(0),
|
currentMark.getSubMark(2), lastLocation, location);
|
||||||
thisCurrentMark)) {
|
if (crossedLine > 0) {
|
||||||
if (hasPassedFirstLine && hasEnteredRoundingZone) {
|
CompoundMark previousMark = GameState.getMarkOrder().getPreviousMark(currentMarkSeqID);
|
||||||
currentMarkSeqID++;
|
Boolean isClockwiseCross = GeoUtility.isClockwise(currentMark.getSubMark(1),
|
||||||
hasPassedFirstLine = false;
|
currentMark.getSubMark(2),
|
||||||
hasEnteredRoundingZone = false;
|
previousMark.getSubMark(1));
|
||||||
System.out.println(
|
if (crossedLine == 1 && isClockwiseCross || crossedLine == 2 && !isClockwiseCross) {
|
||||||
"(" + currentMarkSeqID + ") Passed mark: " + currentMark.getMarks()
|
logMarkRounding(currentMark);
|
||||||
.get(0).getName()
|
// TODO: 8/08/17 wmu16 - Do something!
|
||||||
+ " ID(" + currentMark.getId() + ")");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user