mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Stripped down the boatgroup to the basic movement components and then tried to adjust how position updates are being dealt with to make everything more logically understandable. I made some progress in terms of understanding but the position update is still not as reliable as I would like. I will be explaining to other team members how this part of the code is working so the time I have spent is not completely wasted #story[923]
This commit is contained in:
@@ -10,24 +10,13 @@ import javafx.scene.canvas.GraphicsContext;
|
|||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.text.Font;
|
import javafx.scene.text.Font;
|
||||||
import seng302.models.BoatGroup;
|
|
||||||
import seng302.models.Colors;
|
|
||||||
import seng302.models.RaceObject;
|
|
||||||
import seng302.models.Yacht;
|
|
||||||
import seng302.models.*;
|
import seng302.models.*;
|
||||||
import seng302.models.mark.*;
|
import seng302.models.mark.*;
|
||||||
import seng302.models.parsers.StreamParser;
|
|
||||||
import seng302.models.parsers.XMLParser;
|
|
||||||
import seng302.models.parsers.XMLParser.RaceXMLObject.CompoundMark;
|
|
||||||
import seng302.models.parsers.XMLParser.RaceXMLObject.Limit;
|
|
||||||
import seng302.models.parsers.packets.BoatPositionPacket;
|
|
||||||
import seng302.models.stream.StreamParser;
|
import seng302.models.stream.StreamParser;
|
||||||
import seng302.models.stream.packets.BoatPositionPacket;
|
import seng302.models.stream.packets.BoatPositionPacket;
|
||||||
import seng302.models.stream.XMLParser;
|
import seng302.models.stream.XMLParser;
|
||||||
import seng302.models.stream.XMLParser.RaceXMLObject.Limit;
|
import seng302.models.stream.XMLParser.RaceXMLObject.Limit;
|
||||||
import seng302.models.mark.Mark;
|
import seng302.models.mark.Mark;
|
||||||
|
|
||||||
import java.text.DecimalFormat;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.PriorityBlockingQueue;
|
import java.util.concurrent.PriorityBlockingQueue;
|
||||||
|
|
||||||
@@ -62,16 +51,13 @@ public class CanvasController {
|
|||||||
private Mark maxLonPoint;
|
private Mark maxLonPoint;
|
||||||
private double referencePointX;
|
private double referencePointX;
|
||||||
private double referencePointY;
|
private double referencePointY;
|
||||||
private List<RaceObject> raceObjects = new ArrayList<>();
|
private List<MarkGroup> markGroups = new ArrayList<>();
|
||||||
private List<Mark> raceMarks = new ArrayList<>();
|
private List<BoatGroup> boatGroups = new ArrayList<>();
|
||||||
|
|
||||||
//FRAME RATE
|
//FRAME RATE
|
||||||
private static final double UPDATE_TIME = 0.016666; // 1 / 60 ie 60fps
|
|
||||||
private final long[] frameTimes = new long[30];
|
private final long[] frameTimes = new long[30];
|
||||||
private int frameTimeIndex = 0;
|
private int frameTimeIndex = 0;
|
||||||
private boolean arrayFilled = false;
|
private boolean arrayFilled = false;
|
||||||
private DecimalFormat decimalFormat2dp = new DecimalFormat("0.00");
|
|
||||||
private double lastPacketTime = 0;
|
|
||||||
|
|
||||||
public AnimationTimer timer;
|
public AnimationTimer timer;
|
||||||
|
|
||||||
@@ -94,8 +80,6 @@ public class CanvasController {
|
|||||||
// Bind canvas size to stack pane size.
|
// Bind canvas size to stack pane size.
|
||||||
canvas.widthProperty().bind(new SimpleDoubleProperty(CANVAS_WIDTH));
|
canvas.widthProperty().bind(new SimpleDoubleProperty(CANVAS_WIDTH));
|
||||||
canvas.heightProperty().bind(new SimpleDoubleProperty(CANVAS_HEIGHT));
|
canvas.heightProperty().bind(new SimpleDoubleProperty(CANVAS_HEIGHT));
|
||||||
//group.minWidth(CANVAS_WIDTH);
|
|
||||||
//group.minHeight(CANVAS_HEIGHT);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void initializeCanvas (){
|
public void initializeCanvas (){
|
||||||
@@ -109,7 +93,7 @@ public class CanvasController {
|
|||||||
|
|
||||||
|
|
||||||
// TODO: 1/05/17 wmu16 - Change this call to now draw the marks as from the xml
|
// TODO: 1/05/17 wmu16 - Change this call to now draw the marks as from the xml
|
||||||
initializeBoats();
|
drawBoats();
|
||||||
timer = new AnimationTimer() {
|
timer = new AnimationTimer() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -132,7 +116,7 @@ public class CanvasController {
|
|||||||
|
|
||||||
// TODO: 1/05/17 cir27 - Make the RaceObjects update on the actual delay.
|
// TODO: 1/05/17 cir27 - Make the RaceObjects update on the actual delay.
|
||||||
elapsedNanos = 1000 / 60;
|
elapsedNanos = 1000 / 60;
|
||||||
updateRaceObjects();
|
updateGroups();
|
||||||
if (StreamParser.isRaceFinished()) {
|
if (StreamParser.isRaceFinished()) {
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
@@ -160,10 +144,10 @@ public class CanvasController {
|
|||||||
SingleMark thisMark1 = new SingleMark("", thisPoint1.getLat(), thisPoint1.getLng(), thisPoint1.getSeqID());
|
SingleMark thisMark1 = new SingleMark("", thisPoint1.getLat(), thisPoint1.getLng(), thisPoint1.getSeqID());
|
||||||
Limit thisPoint2 = courseLimits.get(i+1);
|
Limit thisPoint2 = courseLimits.get(i+1);
|
||||||
SingleMark thisMark2 = new SingleMark("", thisPoint2.getLat(), thisPoint2.getLng(), thisPoint2.getSeqID());
|
SingleMark thisMark2 = new SingleMark("", thisPoint2.getLat(), thisPoint2.getLng(), thisPoint2.getSeqID());
|
||||||
Point2D borderPoint1 = latLonToXY(thisMark1.getLatitude(), thisMark1.getLongitude());
|
Point2D borderPoint1 = findScaledXY(thisMark1);
|
||||||
Point2D borderPoint2 = latLonToXY(thisMark2.getLatitude(), thisMark2.getLongitude());
|
Point2D borderPoint2 = findScaledXY(thisMark2);
|
||||||
gc.strokeLine(borderPoint1.getX(), borderPoint1.getY(),
|
gc.strokeLine(borderPoint1.getX(), borderPoint1.getY(),
|
||||||
borderPoint2.getX(), borderPoint2.getY());
|
borderPoint2.getX(), borderPoint2.getY());
|
||||||
xBoundaryPoints[i] = borderPoint1.getX();
|
xBoundaryPoints[i] = borderPoint1.getX();
|
||||||
yBoundaryPoints[i] = borderPoint1.getY();
|
yBoundaryPoints[i] = borderPoint1.getY();
|
||||||
}
|
}
|
||||||
@@ -171,52 +155,42 @@ public class CanvasController {
|
|||||||
SingleMark thisMark1 = new SingleMark("", thisPoint1.getLat(), thisPoint1.getLng(), thisPoint1.getSeqID());
|
SingleMark thisMark1 = new SingleMark("", thisPoint1.getLat(), thisPoint1.getLng(), thisPoint1.getSeqID());
|
||||||
Limit thisPoint2 = courseLimits.get(0);
|
Limit thisPoint2 = courseLimits.get(0);
|
||||||
SingleMark thisMark2 = new SingleMark("", thisPoint2.getLat(), thisPoint2.getLng(), thisPoint2.getSeqID());
|
SingleMark thisMark2 = new SingleMark("", thisPoint2.getLat(), thisPoint2.getLng(), thisPoint2.getSeqID());
|
||||||
Point2D borderPoint1 = latLonToXY(thisMark1.getLatitude(), thisMark1.getLongitude());
|
Point2D borderPoint1 = findScaledXY(thisMark1);
|
||||||
Point2D borderPoint2 = latLonToXY(thisMark2.getLatitude(), thisMark2.getLongitude());
|
Point2D borderPoint2 = findScaledXY(thisMark2);
|
||||||
gc.strokeLine(borderPoint1.getX(), borderPoint1.getY(),
|
gc.strokeLine(borderPoint1.getX(), borderPoint1.getY(),
|
||||||
borderPoint2.getX(), borderPoint2.getY());
|
borderPoint2.getX(), borderPoint2.getY());
|
||||||
xBoundaryPoints[courseLimits.size()-1] = borderPoint1.getX();
|
xBoundaryPoints[courseLimits.size()-1] = borderPoint1.getX();
|
||||||
yBoundaryPoints[courseLimits.size()-1] = borderPoint1.getY();
|
yBoundaryPoints[courseLimits.size()-1] = borderPoint1.getY();
|
||||||
gc.setFill(Color.LIGHTBLUE);
|
gc.setFill(Color.LIGHTBLUE);
|
||||||
gc.fillPolygon(xBoundaryPoints,yBoundaryPoints,yBoundaryPoints.length);
|
gc.fillPolygon(xBoundaryPoints,yBoundaryPoints,yBoundaryPoints.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRaceObjects(){
|
private void updateGroups(){
|
||||||
for (RaceObject raceObject : raceObjects) {
|
for (BoatGroup boatGroup : boatGroups) {
|
||||||
raceObject.updatePosition(1000 / 60);
|
boatGroup.updatePosition();
|
||||||
// some raceObjects will have multiply ID's (for instance gate marks)
|
// some raceObjects will have multiple ID's (for instance gate marks)
|
||||||
for (long id : raceObject.getRaceIds()) {
|
//checking if the current "ID" has any updates associated with it
|
||||||
//checking if the current "ID" has any updates associated with it
|
if (StreamParser.boatPositions.containsKey(boatGroup.getRaceId())) {
|
||||||
|
moveBoatGroup(boatGroup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (MarkGroup markGroup : markGroups) {
|
||||||
|
for (int id : markGroup.getRaceIds()) {
|
||||||
if (StreamParser.boatPositions.containsKey(id)) {
|
if (StreamParser.boatPositions.containsKey(id)) {
|
||||||
move(id, raceObject);
|
moveMarkGroup(id, markGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void move(long id, RaceObject raceObject){
|
private void moveBoatGroup(BoatGroup boatGroup) {
|
||||||
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.boatPositions.get(id);
|
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.boatPositions.get(boatGroup.getRaceId());
|
||||||
if (movementQueue.size() > 0){
|
if (movementQueue.size() > 0){
|
||||||
// BoatPositionPacket positionPacket = movementQueue.peek();
|
|
||||||
//
|
|
||||||
// //this code adds a delay to reading from the movementQueue
|
|
||||||
// //in case things being put into the movement queue are slightly
|
|
||||||
// //out of order
|
|
||||||
// int delayTime = 1000;
|
|
||||||
// int loopTime = delayTime * 10;
|
|
||||||
// long timeDiff = (System.currentTimeMillis()%loopTime - positionPacket.getTimeValid()%loopTime);
|
|
||||||
// if (timeDiff < 0){
|
|
||||||
// timeDiff = loopTime + timeDiff;
|
|
||||||
// }
|
|
||||||
// if (timeDiff > delayTime) {
|
|
||||||
try {
|
try {
|
||||||
BoatPositionPacket positionPacket = movementQueue.take();
|
BoatPositionPacket positionPacket = movementQueue.take();
|
||||||
if (id == 104){
|
Point2D p2d = findScaledXY(positionPacket.getLat(), positionPacket.getLon());
|
||||||
System.out.println(positionPacket.getTimeValid());
|
|
||||||
}
|
|
||||||
Point2D p2d = latLonToXY(positionPacket.getLat(), positionPacket.getLon());
|
|
||||||
double heading = 360.0 / 0xffff * positionPacket.getHeading();
|
double heading = 360.0 / 0xffff * positionPacket.getHeading();
|
||||||
raceObject.setDestination(p2d.getX(), p2d.getY(), heading, positionPacket.getGroundSpeed(), (int) id);
|
boatGroup.setDestination(p2d.getX(), p2d.getY(), heading, positionPacket.getGroundSpeed(), boatGroup.getRaceId());
|
||||||
} catch (InterruptedException e){
|
} catch (InterruptedException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -224,6 +198,19 @@ public class CanvasController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void moveMarkGroup (int raceId, MarkGroup markGroup) {
|
||||||
|
PriorityBlockingQueue<BoatPositionPacket> movementQueue = StreamParser.boatPositions.get(raceId);
|
||||||
|
if (movementQueue.size() > 0){
|
||||||
|
try {
|
||||||
|
BoatPositionPacket positionPacket = movementQueue.take();
|
||||||
|
Point2D p2d = findScaledXY(positionPacket.getLat(), positionPacket.getLon());
|
||||||
|
markGroup.moveMarkTo(p2d.getX(), p2d.getY(), raceId);
|
||||||
|
} catch (InterruptedException e){
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ResizableCanvas extends Canvas {
|
class ResizableCanvas extends Canvas {
|
||||||
|
|
||||||
ResizableCanvas() {
|
ResizableCanvas() {
|
||||||
@@ -275,18 +262,18 @@ public class CanvasController {
|
|||||||
/**
|
/**
|
||||||
* Draws all the boats.
|
* Draws all the boats.
|
||||||
*/
|
*/
|
||||||
private void initializeBoats() {
|
private void drawBoats() {
|
||||||
Map<Integer, Yacht> boats = StreamParser.getBoats();
|
Map<Integer, Yacht> boats = StreamParser.getBoats();
|
||||||
Group boatAnnotations = new Group();
|
Group boatAnnotations = new Group();
|
||||||
|
|
||||||
for (Yacht boat : boats.values()) {
|
for (Yacht boat : boats.values()) {
|
||||||
boat.setColour(Colors.getColor());
|
boat.setColour(Colors.getColor());
|
||||||
BoatGroup boatGroup = new BoatGroup(boat, boat.getColour());
|
BoatGroup boatGroup = new BoatGroup(boat, boat.getColour());
|
||||||
raceObjects.add(boatGroup);
|
boatGroups.add(boatGroup);
|
||||||
boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations());
|
boatAnnotations.getChildren().add(boatGroup.getLowPriorityAnnotations());
|
||||||
}
|
}
|
||||||
group.getChildren().add(boatAnnotations);
|
group.getChildren().add(boatAnnotations);
|
||||||
group.getChildren().addAll(raceObjects);
|
group.getChildren().addAll(boatGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -362,6 +349,7 @@ public class CanvasController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the scale factor necessary to fit all race markers within the onscreen map and assigns it to distanceScaleFactor
|
* Finds the scale factor necessary to fit all race markers within the onscreen map and assigns it to distanceScaleFactor
|
||||||
* Returns the max horizontal distance of the map.
|
* Returns the max horizontal distance of the map.
|
||||||
@@ -395,36 +383,37 @@ public class CanvasController {
|
|||||||
* are scaled according to the distanceScaleFactor variable.
|
* are scaled according to the distanceScaleFactor variable.
|
||||||
*/
|
*/
|
||||||
private void givePointsXY() {
|
private void givePointsXY() {
|
||||||
List<XMLParser.RaceXMLObject.CompoundMark> allPoints = StreamParser.getXmlObject().getRaceXML().getCompoundMarks();
|
// List<XMLParser.RaceXMLObject.CompoundMark> allPoints = StreamParser.getXmlObject().getRaceXML().getCompoundMarks();
|
||||||
List<XMLParser.RaceXMLObject.CompoundMark> processed = new ArrayList<>();
|
// List<XMLParser.RaceXMLObject.CompoundMark> processed = new ArrayList<>();
|
||||||
RaceObject markGroup;
|
// MarkGroup markGroup;
|
||||||
|
//
|
||||||
for (XMLParser.RaceXMLObject.CompoundMark mark : allPoints) {
|
// for (XMLParser.RaceXMLObject.CompoundMark mark : allPoints) {
|
||||||
if (!processed.contains(mark)) {
|
// if (!processed.contains(mark)) {
|
||||||
if (mark.getMarkType() != MarkType.SINGLE_MARK) {
|
// if (mark.getMarkType() != MarkType.SINGLE_MARK) {
|
||||||
markGroup = new MarkGroup(mark, findScaledXY(mark.getMarks().get(0)), findScaledXY(mark.getMarks().get(1)));
|
// markGroup = new MarkGroup(mark, findScaledXY(mark.getMarks().get(0)), findScaledXY(mark.getMarks().get(1)));
|
||||||
raceObjects.add(markGroup);
|
// markGroups.add(markGroup);
|
||||||
} else {
|
// } else {
|
||||||
markGroup = new MarkGroup(mark, findScaledXY(mark.getMarks().get(0)));
|
// markGroup = new MarkGroup(mark, findScaledXY(mark.getMarks().get(0)));
|
||||||
raceObjects.add(markGroup);
|
// markGroups.add(markGroup);
|
||||||
}
|
// }
|
||||||
processed.add(mark);
|
// processed.add(mark);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
group.getChildren().addAll(boatGroups);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Point2D findScaledXY (Mark unscaled) {
|
||||||
|
return findScaledXY (unscaled.getLatitude(), unscaled.getLongitude());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D findScaledXY (double unscaledLat, double unscaledLon) {
|
||||||
private Point2D latLonToXY (double latitude, double longitude){
|
|
||||||
double distanceFromReference;
|
double distanceFromReference;
|
||||||
double angleFromReference;
|
double angleFromReference;
|
||||||
int xAxisLocation = (int) referencePointX;
|
int xAxisLocation = (int) referencePointX;
|
||||||
int yAxisLocation = (int) referencePointY;
|
int yAxisLocation = (int) referencePointY;
|
||||||
|
|
||||||
double minLat = minLatPoint.getLatitude();
|
angleFromReference = Mark.calculateHeadingRad(minLatPoint.getLatitude(), minLatPoint.getLongitude(), unscaledLat, unscaledLon);
|
||||||
double minLon = minLatPoint.getLongitude();
|
distanceFromReference = Mark.calculateDistance(minLatPoint.getLatitude(), minLatPoint.getLongitude(), unscaledLat, unscaledLon);
|
||||||
angleFromReference = Mark.calculateHeadingRad(minLat, minLon, latitude, longitude);
|
|
||||||
distanceFromReference = Mark.calculateDistance(minLat, minLon, latitude, longitude);
|
|
||||||
if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) {
|
if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) {
|
||||||
xAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
xAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference);
|
||||||
yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference);
|
||||||
@@ -444,12 +433,7 @@ public class CanvasController {
|
|||||||
return new Point2D(xAxisLocation, yAxisLocation);
|
return new Point2D(xAxisLocation, yAxisLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<BoatGroup> getBoatGroups() {
|
||||||
private Point2D latLonToXY (double latitude, double longitude) {
|
return boatGroups;
|
||||||
return findScaledXY(minLatPoint.getLatitude(), minLatPoint.getLongitude(), latitude, longitude);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<RaceObject> getRaceObjects() {
|
|
||||||
return raceObjects;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -15,14 +15,13 @@ import javafx.scene.layout.AnchorPane;
|
|||||||
import javafx.scene.layout.Pane;
|
import javafx.scene.layout.Pane;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import seng302.models.Yacht;
|
import seng302.models.Yacht;
|
||||||
import seng302.models.parsers.StreamParser;
|
|
||||||
import seng302.models.parsers.XMLParser;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
import java.util.TimerTask;
|
||||||
|
import seng302.models.stream.StreamParser;
|
||||||
|
|
||||||
public class Controller implements Initializable {
|
public class Controller implements Initializable {
|
||||||
@FXML
|
@FXML
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package seng302.controllers;
|
package seng302.controllers;
|
||||||
|
|
||||||
import javafx.animation.Animation;
|
import java.io.IOException;
|
||||||
import javafx.animation.KeyFrame;
|
import javafx.animation.KeyFrame;
|
||||||
import javafx.animation.Timeline;
|
import javafx.animation.Timeline;
|
||||||
import javafx.beans.value.ChangeListener;
|
import javafx.beans.value.ChangeListener;
|
||||||
@@ -12,7 +12,6 @@ import javafx.scene.control.Button;
|
|||||||
import javafx.scene.control.CheckBox;
|
import javafx.scene.control.CheckBox;
|
||||||
import javafx.scene.control.Slider;
|
import javafx.scene.control.Slider;
|
||||||
import javafx.scene.layout.AnchorPane;
|
import javafx.scene.layout.AnchorPane;
|
||||||
import javafx.scene.layout.Pane;
|
|
||||||
import javafx.scene.layout.VBox;
|
import javafx.scene.layout.VBox;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.paint.Paint;
|
import javafx.scene.paint.Paint;
|
||||||
@@ -25,16 +24,16 @@ import seng302.controllers.annotations.Annotation;
|
|||||||
import seng302.controllers.annotations.ImportantAnnotationController;
|
import seng302.controllers.annotations.ImportantAnnotationController;
|
||||||
import seng302.controllers.annotations.ImportantAnnotationDelegate;
|
import seng302.controllers.annotations.ImportantAnnotationDelegate;
|
||||||
import seng302.controllers.annotations.ImportantAnnotationsState;
|
import seng302.controllers.annotations.ImportantAnnotationsState;
|
||||||
import seng302.models.*;
|
import seng302.models.BoatGroup;
|
||||||
import seng302.models.parsers.StreamParser;
|
import seng302.models.RaceObject;
|
||||||
|
import seng302.models.Yacht;
|
||||||
import java.io.IOException;
|
import seng302.models.stream.StreamParser;
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by ptg19 on 29/03/17.
|
* Created by ptg19 on 29/03/17.
|
||||||
*/
|
*/
|
||||||
public class RaceViewController extends Thread implements ImportantAnnotationDelegate{
|
public class RaceViewController extends Thread implements ImportantAnnotationDelegate {
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private VBox positionVbox;
|
private VBox positionVbox;
|
||||||
@FXML
|
@FXML
|
||||||
@@ -52,12 +51,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
@FXML
|
@FXML
|
||||||
private CanvasController includedCanvasController;
|
private CanvasController includedCanvasController;
|
||||||
|
|
||||||
private ArrayList<Yacht> startingBoats = new ArrayList<>();
|
|
||||||
private boolean displayFps;
|
private boolean displayFps;
|
||||||
private Timeline timerTimeline;
|
private Timeline timerTimeline;
|
||||||
private Map<Yacht, TimelineInfo> timelineInfos = new HashMap<>();
|
|
||||||
private ArrayList<Yacht> boatOrder = new ArrayList<>();
|
|
||||||
private Race race;
|
|
||||||
private Stage stage;
|
private Stage stage;
|
||||||
private ImportantAnnotationsState importantAnnotations;
|
private ImportantAnnotationsState importantAnnotations;
|
||||||
|
|
||||||
@@ -65,24 +60,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
// Load a default important annotation state
|
// Load a default important annotation state
|
||||||
importantAnnotations = new ImportantAnnotationsState();
|
importantAnnotations = new ImportantAnnotationsState();
|
||||||
|
|
||||||
RaceController raceController = new RaceController();
|
|
||||||
raceController.initializeRace();
|
|
||||||
race = raceController.getRace();
|
|
||||||
|
|
||||||
for (Yacht boat : race.getBoats()) {
|
|
||||||
startingBoats.add(boat);
|
|
||||||
}
|
|
||||||
|
|
||||||
includedCanvasController.setup(this);
|
includedCanvasController.setup(this);
|
||||||
includedCanvasController.initializeCanvas();
|
includedCanvasController.initializeCanvas();
|
||||||
initializeTimer();
|
initializeTimer();
|
||||||
initializeSettings();
|
initializeSettings();
|
||||||
initialiseWindDirection();
|
initialiseWindDirection();
|
||||||
initialisePositionVBox();
|
initialisePositionVBox();
|
||||||
//set wind direction!!!!!!! can't find another place to put my code --haoming
|
|
||||||
// double windDirection = new ConfigParser("/config/config.xml").getWindDirection();
|
|
||||||
// windDirectionText.setText(String.format("%.1f°", windDirection));
|
|
||||||
// windArrowText.setRotate(windDirection);
|
|
||||||
includedCanvasController.timer.start();
|
includedCanvasController.timer.start();
|
||||||
|
|
||||||
selectAnnotationBtn.setOnAction(event -> {
|
selectAnnotationBtn.setOnAction(event -> {
|
||||||
@@ -92,11 +75,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The important annotations have been changed, update this view
|
* The important annotations have been changed, update this view
|
||||||
|
*
|
||||||
* @param importantAnnotationsState The current state of the selected annotations
|
* @param importantAnnotationsState The current state of the selected annotations
|
||||||
*/
|
*/
|
||||||
public void importantAnnotationsChanged(ImportantAnnotationsState importantAnnotationsState){
|
public void importantAnnotationsChanged(ImportantAnnotationsState importantAnnotationsState) {
|
||||||
this.importantAnnotations = importantAnnotationsState;
|
this.importantAnnotations = importantAnnotationsState;
|
||||||
setAnnotations((int)annotationSlider.getValue()); // Refresh the displayed annotations
|
setAnnotations((int) annotationSlider.getValue()); // Refresh the displayed annotations
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -108,11 +92,13 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
Stage stage = new Stage();
|
Stage stage = new Stage();
|
||||||
|
|
||||||
// Set controller
|
// Set controller
|
||||||
ImportantAnnotationController controller = new ImportantAnnotationController(this, stage);
|
ImportantAnnotationController controller = new ImportantAnnotationController(this,
|
||||||
|
stage);
|
||||||
fxmlLoader.setController(controller);
|
fxmlLoader.setController(controller);
|
||||||
|
|
||||||
// Load FXML and set CSS
|
// Load FXML and set CSS
|
||||||
fxmlLoader.setLocation(getClass().getResource("/views/importantAnnotationSelectView.fxml"));
|
fxmlLoader
|
||||||
|
.setLocation(getClass().getResource("/views/importantAnnotationSelectView.fxml"));
|
||||||
Scene scene = new Scene(fxmlLoader.load(), 469, 248);
|
Scene scene = new Scene(fxmlLoader.load(), 469, 248);
|
||||||
scene.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
scene.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||||
stage.initStyle(StageStyle.UNDECORATED);
|
stage.initStyle(StageStyle.UNDECORATED);
|
||||||
@@ -132,7 +118,8 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
|
|
||||||
toggleFps.selectedProperty().addListener(new ChangeListener<Boolean>() {
|
toggleFps.selectedProperty().addListener(new ChangeListener<Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
|
public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue,
|
||||||
|
Boolean newValue) {
|
||||||
displayFps = !displayFps;
|
displayFps = !displayFps;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -141,10 +128,18 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
annotationSlider.setLabelFormatter(new StringConverter<Double>() {
|
annotationSlider.setLabelFormatter(new StringConverter<Double>() {
|
||||||
@Override
|
@Override
|
||||||
public String toString(Double n) {
|
public String toString(Double n) {
|
||||||
if (n == 0) return "None";
|
if (n == 0) {
|
||||||
if (n == 1) return "Low";
|
return "None";
|
||||||
if (n == 2) return "Important";
|
}
|
||||||
if (n == 3) return "All";
|
if (n == 1) {
|
||||||
|
return "Low";
|
||||||
|
}
|
||||||
|
if (n == 2) {
|
||||||
|
return "Important";
|
||||||
|
}
|
||||||
|
if (n == 3) {
|
||||||
|
return "All";
|
||||||
|
}
|
||||||
|
|
||||||
return "All";
|
return "All";
|
||||||
}
|
}
|
||||||
@@ -168,25 +163,25 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
});
|
});
|
||||||
|
|
||||||
annotationSlider.valueProperty().addListener((obs, oldval, newVal) ->
|
annotationSlider.valueProperty().addListener((obs, oldval, newVal) ->
|
||||||
setAnnotations((int)annotationSlider.getValue()));
|
setAnnotations((int) annotationSlider.getValue()));
|
||||||
|
|
||||||
annotationSlider.setValue(3);
|
annotationSlider.setValue(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeTimer(){
|
private void initializeTimer() {
|
||||||
timerTimeline = new Timeline();
|
timerTimeline = new Timeline();
|
||||||
timerTimeline.setCycleCount(Timeline.INDEFINITE);
|
timerTimeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
// Run timer update every second
|
// Run timer update every second
|
||||||
timerTimeline.getKeyFrames().add(
|
timerTimeline.getKeyFrames().add(
|
||||||
new KeyFrame(Duration.seconds(1),
|
new KeyFrame(Duration.seconds(1),
|
||||||
event -> {
|
event -> {
|
||||||
if (StreamParser.isRaceFinished()) {
|
if (StreamParser.isRaceFinished()) {
|
||||||
timerLabel.setFill(Color.RED);
|
timerLabel.setFill(Color.RED);
|
||||||
timerLabel.setText("Race Finished!");
|
timerLabel.setText("Race Finished!");
|
||||||
} else {
|
} else {
|
||||||
timerLabel.setText(currentTimer());
|
timerLabel.setText(currentTimer());
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// Start the timer
|
// Start the timer
|
||||||
@@ -197,11 +192,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
Timeline windDirTimeline = new Timeline();
|
Timeline windDirTimeline = new Timeline();
|
||||||
windDirTimeline.setCycleCount(Timeline.INDEFINITE);
|
windDirTimeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
windDirTimeline.getKeyFrames().add(
|
windDirTimeline.getKeyFrames().add(
|
||||||
new KeyFrame(Duration.seconds(1),
|
new KeyFrame(Duration.seconds(1),
|
||||||
event -> {
|
event -> {
|
||||||
windDirectionText.setText(String.format("%.1f°", StreamParser.getWindDirection()));
|
windDirectionText
|
||||||
windArrowText.setRotate(StreamParser.getWindDirection());
|
.setText(String.format("%.1f°", StreamParser.getWindDirection()));
|
||||||
})
|
windArrowText.setRotate(StreamParser.getWindDirection());
|
||||||
|
})
|
||||||
);
|
);
|
||||||
windDirTimeline.playFromStart();
|
windDirTimeline.playFromStart();
|
||||||
}
|
}
|
||||||
@@ -211,137 +207,12 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
Timeline posVBoxTimeline = new Timeline();
|
Timeline posVBoxTimeline = new Timeline();
|
||||||
posVBoxTimeline.setCycleCount(Timeline.INDEFINITE);
|
posVBoxTimeline.setCycleCount(Timeline.INDEFINITE);
|
||||||
posVBoxTimeline.getKeyFrames().add(
|
posVBoxTimeline.getKeyFrames().add(
|
||||||
new KeyFrame(Duration.seconds(1),
|
new KeyFrame(Duration.seconds(1),
|
||||||
event -> {
|
event -> {
|
||||||
showOrder();
|
showOrder();
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
posVBoxTimeline.playFromStart();
|
posVBoxTimeline.playFromStart();
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates time line for each boat, and stores time time into timelineInfos hash map
|
|
||||||
*/
|
|
||||||
private void initializeTimelines() {
|
|
||||||
HashMap<Yacht, List> boat_events = race.getEvents();
|
|
||||||
for (Yacht boat : boat_events.keySet()) {
|
|
||||||
startingBoats.add(boat);
|
|
||||||
// // x, y are the real time coordinates
|
|
||||||
// DoubleProperty x = new SimpleDoubleProperty();
|
|
||||||
// DoubleProperty y = new SimpleDoubleProperty();
|
|
||||||
//
|
|
||||||
// List<KeyFrame> keyFrames = new ArrayList<>();
|
|
||||||
// List<Event> events = boat_events.get(boat);
|
|
||||||
//
|
|
||||||
// // iterates all events and convert each event to keyFrame, then add them into a list
|
|
||||||
// for (Event event : events) {
|
|
||||||
// if (event.getIsFinishingEvent()) {
|
|
||||||
// keyFrames.add(
|
|
||||||
// new KeyFrame(Duration.seconds(event.getTime()),
|
|
||||||
// onFinished -> {race.setBoatFinished(boat); handleEvent(event);},
|
|
||||||
// new KeyValue(x, event.getThisMark().getLatitude()),
|
|
||||||
// new KeyValue(y, event.getThisMark().getLongitude())
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// } else {
|
|
||||||
// keyFrames.add(
|
|
||||||
// new KeyFrame(Duration.seconds(event.getTime()),
|
|
||||||
// onFinished ->{
|
|
||||||
// handleEvent(event);
|
|
||||||
// boat.setHeading(event.getBoatHeading());
|
|
||||||
// },
|
|
||||||
// new KeyValue(x, event.getThisMark().getLatitude()),
|
|
||||||
// new KeyValue(y, event.getThisMark().getLongitude())
|
|
||||||
// )
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// timelineInfos.put(boat, new TimelineInfo(new Timeline(keyFrames.toArray(new KeyFrame[keyFrames.size()])), x, y));
|
|
||||||
}
|
|
||||||
setRaceDuration();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setRaceDuration(){
|
|
||||||
Double maxDuration = 0.0;
|
|
||||||
Timeline maxTimeline = null;
|
|
||||||
|
|
||||||
for (TimelineInfo timelineInfo : timelineInfos.values()) {
|
|
||||||
|
|
||||||
Timeline timeline = timelineInfo.getTimeline();
|
|
||||||
if (timeline.getTotalDuration().toMillis() >= maxDuration) {
|
|
||||||
maxDuration = timeline.getTotalDuration().toMillis();
|
|
||||||
maxTimeline = timeline;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Timelines are paused by default
|
|
||||||
timeline.play();
|
|
||||||
timeline.pause();
|
|
||||||
}
|
|
||||||
|
|
||||||
maxTimeline.setOnFinished(event -> {
|
|
||||||
race.setRaceFinished();
|
|
||||||
loadRaceResultView();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Play each boats timerTimeline
|
|
||||||
*/
|
|
||||||
public void playTimelines(){
|
|
||||||
for (TimelineInfo timelineInfo : timelineInfos.values()){
|
|
||||||
Timeline timeline = timelineInfo.getTimeline();
|
|
||||||
|
|
||||||
if (timeline.getStatus() == Animation.Status.PAUSED){
|
|
||||||
timeline.play();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pause each boats timerTimeline
|
|
||||||
*/
|
|
||||||
public void pauseTimelines(){
|
|
||||||
for (TimelineInfo timelineInfo : timelineInfos.values()){
|
|
||||||
Timeline timeline = timelineInfo.getTimeline();
|
|
||||||
|
|
||||||
if (timeline.getStatus() == Animation.Status.RUNNING){
|
|
||||||
timeline.pause();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Display the list of boats in the order they finished the race
|
|
||||||
*/
|
|
||||||
private void loadRaceResultView() {
|
|
||||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/views/FinishView.fxml"));
|
|
||||||
loader.setController(new RaceResultController(race));
|
|
||||||
|
|
||||||
try {
|
|
||||||
contentAnchorPane.getChildren().removeAll();
|
|
||||||
contentAnchorPane.getChildren().clear();
|
|
||||||
contentAnchorPane.getChildren().addAll((Pane) loader.load());
|
|
||||||
|
|
||||||
} catch (javafx.fxml.LoadException e) {
|
|
||||||
System.err.println(e.getCause());
|
|
||||||
} catch (IOException e) {
|
|
||||||
System.err.println(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleEvent(Event event) {
|
|
||||||
Yacht boat = event.getBoat();
|
|
||||||
boatOrder.remove(boat);
|
|
||||||
boat.setMarkLastPast(event.getMarkPosInRace());
|
|
||||||
boatOrder.add(boat);
|
|
||||||
boatOrder.sort(new Comparator<Yacht>() {
|
|
||||||
@Override
|
|
||||||
public int compare(Yacht b1, Yacht b2) {
|
|
||||||
return b2.getMarkLastPast() - b1.getMarkLastPast();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
showOrder();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showOrder() {
|
private void showOrder() {
|
||||||
@@ -349,20 +220,16 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
positionVbox.getChildren().removeAll();
|
positionVbox.getChildren().removeAll();
|
||||||
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
positionVbox.getStylesheets().add(getClass().getResource("/css/master.css").toString());
|
||||||
|
|
||||||
// for (Boat boat : boatOrder) {
|
|
||||||
// positionVbox.getChildren().add(new Text(boat.getShortName() + " " + boat.getSpeedInKnots() + " Knots"));
|
|
||||||
// }
|
|
||||||
|
|
||||||
for (Yacht boat : StreamParser.getBoatsPos().values()) {
|
for (Yacht boat : StreamParser.getBoatsPos().values()) {
|
||||||
if (boat.getBoatStatus() == 3) { // 3 is finish status
|
if (boat.getBoatStatus() == 3) { // 3 is finish status
|
||||||
Text textToAdd = new Text(boat.getPosition() + ". " +
|
Text textToAdd = new Text(boat.getPosition() + ". " +
|
||||||
boat.getShortName() + " (Finished)");
|
boat.getShortName() + " (Finished)");
|
||||||
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
||||||
positionVbox.getChildren().add(textToAdd);
|
positionVbox.getChildren().add(textToAdd);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Text textToAdd = new Text(boat.getPosition() + ". " +
|
Text textToAdd = new Text(boat.getPosition() + ". " +
|
||||||
boat.getShortName() + " ");
|
boat.getShortName() + " ");
|
||||||
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
textToAdd.setFill(Paint.valueOf("#d3d3d3"));
|
||||||
textToAdd.setStyle("");
|
textToAdd.setStyle("");
|
||||||
positionVbox.getChildren().add(textToAdd);
|
positionVbox.getChildren().add(textToAdd);
|
||||||
@@ -404,118 +271,83 @@ public class RaceViewController extends Thread implements ImportantAnnotationDel
|
|||||||
return timerString;
|
return timerString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stopTimer() {
|
|
||||||
timerTimeline.stop();
|
|
||||||
}
|
|
||||||
public void startTimer() {
|
|
||||||
timerTimeline.play();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDisplayFps() {
|
public boolean isDisplayFps() {
|
||||||
return displayFps;
|
return displayFps;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Race getRace() {
|
|
||||||
return race;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<Yacht, TimelineInfo> getTimelineInfos() {
|
|
||||||
return timelineInfos;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ArrayList<Yacht> getStartingBoats(){
|
|
||||||
return startingBoats;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the important annotations for a specific BoatGroup
|
* Display the important annotations for a specific BoatGroup
|
||||||
|
*
|
||||||
* @param bg The boat group to set the annotations for
|
* @param bg The boat group to set the annotations for
|
||||||
*/
|
*/
|
||||||
private void setBoatGroupImportantAnnotations(BoatGroup bg){
|
private void setBoatGroupImportantAnnotations(BoatGroup bg) {
|
||||||
if (importantAnnotations.getAnnotationState(Annotation.NAME)){
|
if (importantAnnotations.getAnnotationState(Annotation.NAME)) {
|
||||||
bg.setTeamNameObjectVisible(true);
|
bg.setTeamNameObjectVisible(true);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
bg.setTeamNameObjectVisible(false);
|
bg.setTeamNameObjectVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (importantAnnotations.getAnnotationState(Annotation.SPEED)){
|
if (importantAnnotations.getAnnotationState(Annotation.SPEED)) {
|
||||||
bg.setVelocityObjectVisible(true);
|
bg.setVelocityObjectVisible(true);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
bg.setVelocityObjectVisible(false);
|
bg.setVelocityObjectVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (importantAnnotations.getAnnotationState(Annotation.TRACK)){
|
if (importantAnnotations.getAnnotationState(Annotation.TRACK)) {
|
||||||
bg.setLineGroupVisible(true);
|
bg.setLineGroupVisible(true);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
bg.setLineGroupVisible(false);
|
bg.setLineGroupVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (importantAnnotations.getAnnotationState(Annotation.WAKE)){
|
if (importantAnnotations.getAnnotationState(Annotation.WAKE)) {
|
||||||
bg.setWakeVisible(true);
|
bg.setWakeVisible(true);
|
||||||
}
|
} else {
|
||||||
else{
|
|
||||||
bg.setWakeVisible(false);
|
bg.setWakeVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setAnnotations(Integer annotationLevel) {
|
private void setAnnotations(Integer annotationLevel) {
|
||||||
switch (annotationLevel) {
|
switch (annotationLevel) {
|
||||||
// No Annotations
|
|
||||||
case 0:
|
case 0:
|
||||||
for (RaceObject ro : includedCanvasController.getRaceObjects()) {
|
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
||||||
if(ro instanceof BoatGroup) {
|
bg.setTeamNameObjectVisible(false);
|
||||||
BoatGroup bg = (BoatGroup) ro;
|
bg.setVelocityObjectVisible(false);
|
||||||
bg.setTeamNameObjectVisible(false);
|
bg.setLineGroupVisible(false);
|
||||||
bg.setVelocityObjectVisible(false);
|
bg.setWakeVisible(false);
|
||||||
bg.setLineGroupVisible(false);
|
|
||||||
bg.setWakeVisible(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Low Annotations
|
|
||||||
case 1:
|
case 1:
|
||||||
for (RaceObject ro : includedCanvasController.getRaceObjects()) {
|
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
||||||
if(ro instanceof BoatGroup) {
|
bg.setTeamNameObjectVisible(true);
|
||||||
BoatGroup bg = (BoatGroup) ro;
|
bg.setVelocityObjectVisible(false);
|
||||||
bg.setTeamNameObjectVisible(true);
|
bg.setLineGroupVisible(false);
|
||||||
bg.setVelocityObjectVisible(false);
|
bg.setWakeVisible(false);
|
||||||
bg.setLineGroupVisible(false);
|
|
||||||
bg.setWakeVisible(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// Important Annotations
|
|
||||||
case 2:
|
case 2:
|
||||||
for (RaceObject ro : includedCanvasController.getRaceObjects()) {
|
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
||||||
if(ro instanceof BoatGroup) {
|
bg.setTeamNameObjectVisible(true);
|
||||||
BoatGroup bg = (BoatGroup) ro;
|
bg.setVelocityObjectVisible(false);
|
||||||
setBoatGroupImportantAnnotations(bg);
|
bg.setLineGroupVisible(true);
|
||||||
}
|
bg.setWakeVisible(false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
// All Annotations
|
|
||||||
case 3:
|
case 3:
|
||||||
for (RaceObject ro : includedCanvasController.getRaceObjects()) {
|
for (BoatGroup bg : includedCanvasController.getBoatGroups()) {
|
||||||
if(ro instanceof BoatGroup) {
|
bg.setTeamNameObjectVisible(true);
|
||||||
BoatGroup bg = (BoatGroup) ro;
|
bg.setVelocityObjectVisible(true);
|
||||||
bg.setTeamNameObjectVisible(true);
|
bg.setLineGroupVisible(true);
|
||||||
bg.setVelocityObjectVisible(true);
|
bg.setWakeVisible(true);
|
||||||
bg.setLineGroupVisible(true);
|
|
||||||
bg.setWakeVisible(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setStage (Stage stage) {
|
void setStage(Stage stage) {
|
||||||
this.stage = stage;
|
this.stage = stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
Stage getStage () {
|
Stage getStage() {
|
||||||
return stage;
|
return stage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,7 +19,7 @@ import java.util.List;
|
|||||||
* UpdatePosition is called unless the window is minimized in which case it attempts to store animations and apply them
|
* UpdatePosition is called unless the window is minimized in which case it attempts to store animations and apply them
|
||||||
* when the window is maximised.
|
* when the window is maximised.
|
||||||
*/
|
*/
|
||||||
public class BoatGroup extends RaceObject{
|
public class BoatGroup extends Group{
|
||||||
|
|
||||||
//Constants for drawing
|
//Constants for drawing
|
||||||
private static final double TEAMNAME_X_OFFSET = 10d;
|
private static final double TEAMNAME_X_OFFSET = 10d;
|
||||||
@@ -30,8 +30,15 @@ public class BoatGroup extends RaceObject{
|
|||||||
private static final double BOAT_WIDTH = 10d;
|
private static final double BOAT_WIDTH = 10d;
|
||||||
//Variables for boat logic.
|
//Variables for boat logic.
|
||||||
private Point2D lastPoint;
|
private Point2D lastPoint;
|
||||||
private int wakeGenerationDelay = 10;
|
double oldTime;
|
||||||
private double distanceTravelled;
|
double newTime;
|
||||||
|
double lastYValue = 0;
|
||||||
|
double lastXValue = 0;
|
||||||
|
private double dx;
|
||||||
|
private double dy;
|
||||||
|
private double pixelVelocityX;
|
||||||
|
private double pixelVelocityY;
|
||||||
|
private static final int expectedUpdateInterval = 200;
|
||||||
//Graphical objects
|
//Graphical objects
|
||||||
private Yacht boat;
|
private Yacht boat;
|
||||||
private Group lineGroup = new Group();
|
private Group lineGroup = new Group();
|
||||||
@@ -39,14 +46,6 @@ public class BoatGroup extends RaceObject{
|
|||||||
private Text teamNameObject;
|
private Text teamNameObject;
|
||||||
private Text velocityObject;
|
private Text velocityObject;
|
||||||
private Wake wake;
|
private Wake wake;
|
||||||
//Handles boat moving when connecting to a stream
|
|
||||||
private boolean setToInitialLocation = false;
|
|
||||||
private boolean destinationSet;
|
|
||||||
//Variables for handling minimization
|
|
||||||
private Stage stage;
|
|
||||||
private boolean isMaximized= true;
|
|
||||||
private List<Line> lineStorage = new ArrayList<>();
|
|
||||||
private int setCallCount = 5;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a BoatGroup with the default triangular boat polygon.
|
* Creates a BoatGroup with the default triangular boat polygon.
|
||||||
@@ -91,7 +90,6 @@ public class BoatGroup extends RaceObject{
|
|||||||
velocityObject.setX(VELOCITY_X_OFFSET);
|
velocityObject.setX(VELOCITY_X_OFFSET);
|
||||||
velocityObject.setY(VELOCITY_Y_OFFSET);
|
velocityObject.setY(VELOCITY_Y_OFFSET);
|
||||||
velocityObject.relocate(velocityObject.getX(), velocityObject.getY());
|
velocityObject.relocate(velocityObject.getX(), velocityObject.getY());
|
||||||
destinationSet = false;
|
|
||||||
|
|
||||||
wake = new Wake(0, -BOAT_HEIGHT);
|
wake = new Wake(0, -BOAT_HEIGHT);
|
||||||
super.getChildren().addAll(teamNameObject, velocityObject, boatPoly);
|
super.getChildren().addAll(teamNameObject, velocityObject, boatPoly);
|
||||||
@@ -103,9 +101,9 @@ public class BoatGroup extends RaceObject{
|
|||||||
*/
|
*/
|
||||||
private void initChildren (Color color) {
|
private void initChildren (Color color) {
|
||||||
initChildren(color,
|
initChildren(color,
|
||||||
-BOAT_WIDTH / 2, BOAT_HEIGHT / 2,
|
-BOAT_WIDTH / 2, BOAT_HEIGHT / 2,
|
||||||
0.0, -BOAT_HEIGHT / 2,
|
0.0, -BOAT_HEIGHT / 2,
|
||||||
BOAT_WIDTH / 2, BOAT_HEIGHT / 2);
|
BOAT_WIDTH / 2, BOAT_HEIGHT / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -113,7 +111,7 @@ public class BoatGroup extends RaceObject{
|
|||||||
* @param dx The amount to move the X coordinate by
|
* @param dx The amount to move the X coordinate by
|
||||||
* @param dy The amount to move the Y coordinate by
|
* @param dy The amount to move the Y coordinate by
|
||||||
*/
|
*/
|
||||||
public void moveGroupBy(double dx, double dy, double rotation) {
|
public void moveGroupBy(double dx, double dy) {
|
||||||
boatPoly.setLayoutX(boatPoly.getLayoutX() + dx);
|
boatPoly.setLayoutX(boatPoly.getLayoutX() + dx);
|
||||||
boatPoly.setLayoutY(boatPoly.getLayoutY() + dy);
|
boatPoly.setLayoutY(boatPoly.getLayoutY() + dy);
|
||||||
teamNameObject.setLayoutX(teamNameObject.getLayoutX() + dx);
|
teamNameObject.setLayoutX(teamNameObject.getLayoutX() + dx);
|
||||||
@@ -122,19 +120,16 @@ public class BoatGroup extends RaceObject{
|
|||||||
velocityObject.setLayoutY(velocityObject.getLayoutY() + dy);
|
velocityObject.setLayoutY(velocityObject.getLayoutY() + dy);
|
||||||
wake.setLayoutX(wake.getLayoutX() + dx);
|
wake.setLayoutX(wake.getLayoutX() + dx);
|
||||||
wake.setLayoutY(wake.getLayoutY() + dy);
|
wake.setLayoutY(wake.getLayoutY() + dy);
|
||||||
currentRotation = rotation + currentRotation;
|
|
||||||
boatPoly.getTransforms().setAll(new Rotate(rotation));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the boat and its children annotations to coordinates specified
|
* Moves the boat and its children annotations to coordinates specified
|
||||||
* @param x The X coordinate to move the boat to
|
* @param x The X coordinate to move the boat to
|
||||||
* @param y The Y coordinate to move the boat to
|
* @param y The Y coordinate to move the boat to
|
||||||
* @param rotation The heading in degrees from north the boat should rotate to.
|
|
||||||
*/
|
*/
|
||||||
public void moveTo (double x, double y, double rotation) {
|
public void moveTo (double x, double y, double rotation) {
|
||||||
currentRotation = rotation;
|
rotateTo(rotation);
|
||||||
boatPoly.getTransforms().setAll(new Rotate(rotation));
|
|
||||||
boatPoly.setLayoutX(x);
|
boatPoly.setLayoutX(x);
|
||||||
boatPoly.setLayoutY(y);
|
boatPoly.setLayoutY(y);
|
||||||
teamNameObject.setLayoutX(x);
|
teamNameObject.setLayoutX(x);
|
||||||
@@ -143,42 +138,14 @@ public class BoatGroup extends RaceObject{
|
|||||||
velocityObject.setLayoutY(y);
|
velocityObject.setLayoutY(y);
|
||||||
wake.setLayoutX(x);
|
wake.setLayoutX(x);
|
||||||
wake.setLayoutY(y);
|
wake.setLayoutY(y);
|
||||||
wake.rotate(currentRotation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public void rotateTo (double rotation) {
|
||||||
* Updates the position of all graphics in the BoatGroup based off of the given time interval.
|
boatPoly.getTransforms().setAll(new Rotate(rotation));
|
||||||
* @param timeInterval The interval, in milliseconds, the boat should update it's position based on.
|
}
|
||||||
*/
|
|
||||||
public void updatePosition (long timeInterval) {
|
|
||||||
//Calculate the movement of the boat.
|
|
||||||
if (isMaximized) {
|
|
||||||
double dx = pixelVelocityX * timeInterval;
|
|
||||||
double dy = pixelVelocityY * timeInterval;
|
|
||||||
double rotation = rotationalVelocity * timeInterval;
|
|
||||||
distanceTravelled += Math.abs(dx) + Math.abs(dy);
|
|
||||||
moveGroupBy(dx, dy, rotation);
|
|
||||||
|
|
||||||
//Draw a new section of the trail every 20 pixels of movement.
|
public void updatePosition () {
|
||||||
if (distanceTravelled > 20) {
|
moveGroupBy(dx, dy);
|
||||||
distanceTravelled = 0;
|
|
||||||
if (lastPoint != null) {
|
|
||||||
Line l = new Line(
|
|
||||||
lastPoint.getX(),
|
|
||||||
lastPoint.getY(),
|
|
||||||
boatPoly.getLayoutX(),
|
|
||||||
boatPoly.getLayoutY()
|
|
||||||
);
|
|
||||||
l.getStrokeDashArray().setAll(3d, 7d);
|
|
||||||
l.setStroke(boatPoly.getFill());
|
|
||||||
lineGroup.getChildren().add(l);
|
|
||||||
}
|
|
||||||
if (destinationSet) { //Only begin drawing after the first destination is set
|
|
||||||
lastPoint = new Point2D(boatPoly.getLayoutX(), boatPoly.getLayoutY());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wake.updatePosition(timeInterval);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -188,59 +155,26 @@ public class BoatGroup extends RaceObject{
|
|||||||
* @param rotation Rotation to move graphics to.
|
* @param rotation Rotation to move graphics to.
|
||||||
* @param raceIds RaceID of the object to move.
|
* @param raceIds RaceID of the object to move.
|
||||||
*/
|
*/
|
||||||
public void setDestination (double newXValue, double newYValue, double rotation, double groundSpeed, int... raceIds) {
|
public void setDestination (double newXValue, double newYValue, double rotation, double groundSpeed, long raceIds) {
|
||||||
if (hasRaceId(raceIds)) {
|
System.currentTimeMillis();
|
||||||
if (setToInitialLocation) {
|
moveTo(lastXValue, lastYValue, rotation);
|
||||||
destinationSet = true;
|
|
||||||
boat.setVelocity(groundSpeed);
|
|
||||||
if (currentRotation < 0)
|
|
||||||
currentRotation = 360 - currentRotation;
|
|
||||||
double dx = newXValue - boatPoly.getLayoutX();
|
|
||||||
double dy = newYValue - boatPoly.getLayoutY();
|
|
||||||
|
|
||||||
pixelVelocityX = dx / expectedUpdateInterval;
|
dx = (newXValue - lastXValue)/12;
|
||||||
pixelVelocityY = dy / expectedUpdateInterval;
|
dy = (newYValue - lastYValue)/12;
|
||||||
rotationalGoal = rotation;
|
|
||||||
calculateRotationalVelocity();
|
|
||||||
|
|
||||||
if (wakeGenerationDelay > 0) {
|
lastXValue = newXValue;
|
||||||
wake.rotate(rotationalGoal);
|
lastYValue = newYValue;
|
||||||
rotationalVelocity = 0;
|
|
||||||
wakeGenerationDelay--;
|
boat.setVelocity(groundSpeed);
|
||||||
} else {
|
velocityObject.setText(String.format("%.2f m/s", boat.getVelocity()));
|
||||||
wake.setRotationalVelocity(rotationalVelocity, rotationalGoal, boat.getVelocity());
|
|
||||||
}
|
|
||||||
velocityObject.setText(String.format("%.2f m/s", boat.getVelocity()));
|
|
||||||
} else {
|
|
||||||
setToInitialLocation = true;
|
|
||||||
rotationalGoal = rotation;
|
|
||||||
moveTo(newXValue, newYValue, rotation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//If minimized generate lines every 5 calls to set destination.
|
|
||||||
if (!isMaximized) {
|
|
||||||
setToInitialLocation = false;
|
|
||||||
wakeGenerationDelay = 2;
|
|
||||||
if(setCallCount-- == 0) {
|
|
||||||
setCallCount = 5;
|
|
||||||
if (lastPoint != null) {
|
|
||||||
Line l = new Line(
|
|
||||||
lastPoint.getX(),
|
|
||||||
lastPoint.getY(),
|
|
||||||
newXValue,
|
|
||||||
newYValue
|
|
||||||
);
|
|
||||||
l.getStrokeDashArray().setAll(3d, 7d);
|
|
||||||
l.setStroke(boatPoly.getFill());
|
|
||||||
lineStorage.add(l);
|
|
||||||
}
|
|
||||||
if (destinationSet) { //Only begin drawing after the first destination is set
|
|
||||||
lastPoint = new Point2D(newXValue, newYValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void setTeamNameObjectVisible(Boolean visible) {
|
public void setTeamNameObjectVisible(Boolean visible) {
|
||||||
teamNameObject.setVisible(visible);
|
teamNameObject.setVisible(visible);
|
||||||
}
|
}
|
||||||
@@ -261,27 +195,27 @@ public class BoatGroup extends RaceObject{
|
|||||||
return boat;
|
return boat;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// /**
|
||||||
* Returns true if this BoatGroup contains at least one of the given IDs.
|
// * Returns true if this BoatGroup contains at least one of the given IDs.
|
||||||
*
|
// *
|
||||||
* @param raceIds The ID's to check the BoatGroup for.
|
// * @param raceIds The ID's to check the BoatGroup for.
|
||||||
* @return True if the BoatGroup contains at east one of the given IDs, false otherwise.
|
// * @return True if the BoatGroup contains at east one of the given IDs, false otherwise.
|
||||||
*/
|
// */
|
||||||
public boolean hasRaceId (int... raceIds) {
|
// public boolean hasRaceId (long... raceIds) {
|
||||||
for (int id : raceIds) {
|
// for (long id : raceIds) {
|
||||||
if (id == boat.getSourceID())
|
// if (id == boat.getSourceID())
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns all raceIds associated with this group. For BoatGroups the ID's are for the boat.
|
* Returns all raceIds associated with this group. For BoatGroups the ID's are for the boat.
|
||||||
*
|
*
|
||||||
* @return An array containing all ID's associated with this RaceObject.
|
* @return An array containing all ID's associated with this RaceObject.
|
||||||
*/
|
*/
|
||||||
public int[] getRaceIds () {
|
public long getRaceId() {
|
||||||
return new int[] {boat.getSourceID()};
|
return boat.getSourceID();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -296,25 +230,4 @@ public class BoatGroup extends RaceObject{
|
|||||||
group.getChildren().addAll(wake, lineGroup);
|
group.getChildren().addAll(wake, lineGroup);
|
||||||
return group;
|
return group;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Use this function to let the BoatGroup know about the stage it is in. If it knows about it's stage then it will
|
|
||||||
* listen to the iconified property of that stage and change it's behaviour upon minimization. Without setting the
|
|
||||||
* Stage there is guarantee that the BoatGroup will draw properly when the stage is minimized.
|
|
||||||
*
|
|
||||||
* @param stage The stage that the BoatGroup is added to.
|
|
||||||
*/
|
|
||||||
public void setStage (Stage stage) {
|
|
||||||
/* TODO: 4/05/17 cir27 - Find a way to get the stage to this point. Need to pass it through multiple controllers.
|
|
||||||
App.start() -> Controller.setContentPane -> RaceViewController -> CanvasController
|
|
||||||
*/
|
|
||||||
this.stage = stage;
|
|
||||||
this.stage.iconifiedProperty().addListener(e -> {
|
|
||||||
isMaximized = !stage.isIconified();
|
|
||||||
if (!lineStorage.isEmpty()) {
|
|
||||||
lineGroup.getChildren().addAll(lineStorage);
|
|
||||||
lineStorage.clear();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
package seng302.models.mark;
|
package seng302.models.mark;
|
||||||
|
|
||||||
import javafx.geometry.Point2D;
|
import javafx.geometry.Point2D;
|
||||||
import javafx.scene.Node;
|
import javafx.scene.Group;
|
||||||
import javafx.scene.paint.Color;
|
import javafx.scene.paint.Color;
|
||||||
import javafx.scene.shape.Circle;
|
import javafx.scene.shape.Circle;
|
||||||
import javafx.scene.shape.Line;
|
import javafx.scene.shape.Line;
|
||||||
import javafx.scene.transform.Rotate;
|
import javafx.scene.transform.Rotate;
|
||||||
import seng302.models.RaceObject;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -14,7 +13,7 @@ import java.util.List;
|
|||||||
/**
|
/**
|
||||||
* Created by CJIRWIN on 26/04/2017.
|
* Created by CJIRWIN on 26/04/2017.
|
||||||
*/
|
*/
|
||||||
public class MarkGroup extends RaceObject {
|
public class MarkGroup extends Group {
|
||||||
|
|
||||||
private static int MARK_RADIUS = 5;
|
private static int MARK_RADIUS = 5;
|
||||||
private static int LINE_THICKNESS = 2;
|
private static int LINE_THICKNESS = 2;
|
||||||
@@ -23,14 +22,8 @@ public class MarkGroup extends RaceObject {
|
|||||||
|
|
||||||
private List<Mark> marks = new ArrayList<>();
|
private List<Mark> marks = new ArrayList<>();
|
||||||
private Mark mainMark;
|
private Mark mainMark;
|
||||||
private double[] nodePixelVelocitiesX;
|
|
||||||
private double[] nodePixelVelocitiesY;
|
|
||||||
private Point2D[] nodeDestinations;
|
|
||||||
|
|
||||||
public MarkGroup (Mark mark, Point2D... points) {
|
public MarkGroup (Mark mark, Point2D... points) {
|
||||||
nodePixelVelocitiesX = new double[points.length];
|
|
||||||
nodePixelVelocitiesY = new double[points.length];
|
|
||||||
nodeDestinations = new Point2D[points.length];
|
|
||||||
marks.add(mark);
|
marks.add(mark);
|
||||||
mainMark = mark;
|
mainMark = mark;
|
||||||
Color color = Color.BLACK;
|
Color color = Color.BLACK;
|
||||||
@@ -42,45 +35,33 @@ public class MarkGroup extends RaceObject {
|
|||||||
Circle markCircle;
|
Circle markCircle;
|
||||||
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
|
if (mark.getMarkType() == MarkType.SINGLE_MARK) {
|
||||||
markCircle = new Circle(
|
markCircle = new Circle(
|
||||||
points[0].getX(),
|
points[0].getX(),
|
||||||
points[0].getY(),
|
points[0].getY(),
|
||||||
MARK_RADIUS,
|
MARK_RADIUS,
|
||||||
color
|
color
|
||||||
);
|
);
|
||||||
nodeDestinations = new Point2D[]{
|
|
||||||
new Point2D(markCircle.getCenterX(), markCircle.getCenterY()
|
|
||||||
)
|
|
||||||
};
|
|
||||||
super.getChildren().add(markCircle);
|
super.getChildren().add(markCircle);
|
||||||
} else {
|
} else {
|
||||||
// marks.add(((GateMark) mark).getSingleMark1());
|
|
||||||
// marks.add(((GateMark) mark).getSingleMark2());
|
|
||||||
nodePixelVelocitiesX = new double[]{0d,0d};
|
|
||||||
nodePixelVelocitiesY = new double[]{0d,0d};
|
|
||||||
nodeDestinations = new Point2D[2];
|
|
||||||
|
|
||||||
markCircle = new Circle(
|
markCircle = new Circle(
|
||||||
points[0].getX(),
|
points[0].getX(),
|
||||||
points[0].getY(),
|
points[0].getY(),
|
||||||
MARK_RADIUS,
|
MARK_RADIUS,
|
||||||
color
|
color
|
||||||
);
|
);
|
||||||
nodeDestinations[0] = new Point2D(markCircle.getCenterX(), markCircle.getCenterY());
|
|
||||||
super.getChildren().add(markCircle);
|
super.getChildren().add(markCircle);
|
||||||
|
|
||||||
markCircle = new Circle(
|
markCircle = new Circle(
|
||||||
points[1].getX(),
|
points[1].getX(),
|
||||||
points[1].getY(),
|
points[1].getY(),
|
||||||
MARK_RADIUS,
|
MARK_RADIUS,
|
||||||
color
|
color
|
||||||
);
|
);
|
||||||
nodeDestinations[1] = new Point2D(markCircle.getCenterX(), markCircle.getCenterY());
|
|
||||||
super.getChildren().add(markCircle);
|
super.getChildren().add(markCircle);
|
||||||
Line line = new Line(
|
Line line = new Line(
|
||||||
points[0].getX(),
|
points[0].getX(),
|
||||||
points[0].getY(),
|
points[0].getY(),
|
||||||
points[1].getX(),
|
points[1].getX(),
|
||||||
points[1].getY()
|
points[1].getY()
|
||||||
);
|
);
|
||||||
line.setStrokeWidth(LINE_THICKNESS);
|
line.setStrokeWidth(LINE_THICKNESS);
|
||||||
line.setStroke(color);
|
line.setStroke(color);
|
||||||
@@ -91,132 +72,38 @@ public class MarkGroup extends RaceObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDestination (double x, double y, double rotation, double groundSpeed, int... raceIds) {
|
public void moveMarkTo (double x, double y, int raceId)
|
||||||
for (int i = 0; i < marks.size(); i++)
|
{
|
||||||
for (int id : raceIds)
|
if (mainMark.getMarkType() == MarkType.SINGLE_MARK) {
|
||||||
if (id == marks.get(i).getId())
|
Circle markCircle = (Circle) super.getChildren().get(0);
|
||||||
setDestinationChild(x, y, 0, Math.max(0, i-1));
|
|
||||||
this.rotationalGoal = rotation;
|
|
||||||
calculateRotationalVelocity();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void setDestinationChild (double x, double y, double speed, int childIndex) {
|
|
||||||
//double relativeX = x - super.getLayoutX();
|
|
||||||
//double relativeY = y - super.getLayoutY();
|
|
||||||
Circle markCircle = (Circle) super.getChildren().get(childIndex);
|
|
||||||
this.nodeDestinations[childIndex] = new Point2D(x, y);
|
|
||||||
//if (Math.abs(relativeX - markCircle.getCenterX()) > 30 && Math.abs(relativeY - markCircle.getCenterY()) > 30) {
|
|
||||||
this.nodePixelVelocitiesX[childIndex] = (x - markCircle.getCenterX()) / expectedUpdateInterval;
|
|
||||||
this.nodePixelVelocitiesY[childIndex] = (y - markCircle.getCenterY()) / expectedUpdateInterval;
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void rotateTo (double rotation) {
|
|
||||||
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
|
|
||||||
Line line = (Line) super.getChildren().get(2);
|
|
||||||
double xCenter = Math.abs(line.getEndX() - line.getStartX());
|
|
||||||
double yCenter = Math.abs(line.getEndY() - line.getStartY());
|
|
||||||
super.getTransforms().setAll(new Rotate(rotation, xCenter, yCenter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updatePosition (long timeInterval) {
|
|
||||||
Circle markCircle = (Circle) super.getChildren().get(0);
|
|
||||||
|
|
||||||
if (nodePixelVelocitiesX[0] > 0 && markCircle.getCenterX() > nodeDestinations[0].getX() ||
|
|
||||||
nodePixelVelocitiesX[0] < 0 && markCircle.getCenterX() < nodeDestinations[0].getY())
|
|
||||||
nodePixelVelocitiesX[0] = 0;
|
|
||||||
else if (nodePixelVelocitiesX[0] != 0)
|
|
||||||
markCircle.setCenterX(markCircle.getCenterX() + nodePixelVelocitiesX[0] * timeInterval);
|
|
||||||
|
|
||||||
if (nodePixelVelocitiesY[0] > 0 && markCircle.getCenterY() > nodeDestinations[0].getY() ||
|
|
||||||
nodePixelVelocitiesY[0] < 0 && markCircle.getCenterY() < nodeDestinations[0].getY())
|
|
||||||
nodePixelVelocitiesY[0] = 0;
|
|
||||||
else if (nodePixelVelocitiesY[0] != 0)
|
|
||||||
markCircle.setCenterY(markCircle.getCenterY() + nodePixelVelocitiesY[0] * timeInterval);
|
|
||||||
|
|
||||||
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
|
|
||||||
|
|
||||||
Line line = (Line) super.getChildren().get(2);
|
|
||||||
line.setStartX(markCircle.getCenterX());
|
|
||||||
line.setStartY(markCircle.getCenterY());
|
|
||||||
|
|
||||||
markCircle = (Circle) super.getChildren().get(1);
|
|
||||||
|
|
||||||
if (nodePixelVelocitiesX[1] > 0 && markCircle.getCenterX() >= nodeDestinations[1].getX() ||
|
|
||||||
nodePixelVelocitiesX[1] < 0 && markCircle.getCenterX() <= nodeDestinations[1].getX())
|
|
||||||
nodePixelVelocitiesX[1] = 0;
|
|
||||||
else if (nodePixelVelocitiesX[1] != 0)
|
|
||||||
markCircle.setCenterX(markCircle.getCenterX() + nodePixelVelocitiesX[1] * timeInterval);
|
|
||||||
|
|
||||||
if (nodePixelVelocitiesY[1] > 0 && markCircle.getCenterY() > nodeDestinations[1].getY() ||
|
|
||||||
nodePixelVelocitiesY[1] < 0 && markCircle.getCenterY() < nodeDestinations[1].getY())
|
|
||||||
nodePixelVelocitiesY[1] = 0;
|
|
||||||
else if (nodePixelVelocitiesY[1] != 0)
|
|
||||||
markCircle.setCenterY(markCircle.getCenterY() + nodePixelVelocitiesY[1] * timeInterval);
|
|
||||||
line.setEndX(markCircle.getCenterX());
|
|
||||||
line.setEndY(markCircle.getCenterY());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void moveGroupBy (double x, double y, double rotation) {
|
|
||||||
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
|
|
||||||
Line line = (Line) super.getChildren().get(2);
|
|
||||||
for (int childIndex = 0; childIndex < 2; childIndex++){
|
|
||||||
Circle mark = (Circle) super.getChildren().get(childIndex);
|
|
||||||
mark.setCenterY(mark.getCenterY() + y);
|
|
||||||
mark.setCenterX(mark.getCenterX() + x);
|
|
||||||
}
|
|
||||||
line.setStartX(line.getStartX() + x);
|
|
||||||
line.setStartY(line.getStartY() + y);
|
|
||||||
line.setEndX(line.getEndX() + x);
|
|
||||||
line.setEndY(line.getEndY() + y);
|
|
||||||
} else {
|
|
||||||
Circle mark = (Circle) super.getChildren().get(0);
|
|
||||||
mark.setCenterY(mark.getCenterY() + y);
|
|
||||||
mark.setCenterX(mark.getCenterX() + x);
|
|
||||||
}
|
|
||||||
rotateTo(currentRotation + rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void moveTo (double x, double y, double rotation) {
|
|
||||||
moveTo(x, y);
|
|
||||||
rotateTo(rotation);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void moveTo (double x, double y) {
|
|
||||||
Circle markCircle = (Circle) super.getChildren().get(0);
|
|
||||||
markCircle.setCenterX(x);
|
|
||||||
markCircle.setCenterY(y);
|
|
||||||
if (mainMark.getMarkType() != MarkType.SINGLE_MARK) {
|
|
||||||
markCircle = (Circle) super.getChildren().get(1);
|
|
||||||
markCircle.setCenterX(x);
|
markCircle.setCenterX(x);
|
||||||
markCircle.setCenterY(y);
|
markCircle.setCenterY(y);
|
||||||
Line line = (Line) super.getChildren().get(2);
|
} else {
|
||||||
line.setStartX(x);
|
Circle markCircle1 = (Circle) super.getChildren().get(0);
|
||||||
line.setStartY(y);
|
Circle markCircle2 = (Circle) super.getChildren().get(1);
|
||||||
line.setEndX(x);
|
Line connectingLine = (Line) super.getChildren().get(2);
|
||||||
line.setEndY(y);
|
if (marks.get(1).getId() == raceId) {
|
||||||
|
markCircle1.setCenterX(x);
|
||||||
|
markCircle1.setCenterY(y);
|
||||||
|
connectingLine.setStartX(markCircle1.getCenterX());
|
||||||
|
connectingLine.setStartY(markCircle1.getCenterY());
|
||||||
|
} else if (marks.get(2).getId() == raceId) {
|
||||||
|
markCircle2.setCenterX(x);
|
||||||
|
markCircle2.setCenterY(y);
|
||||||
|
connectingLine.setEndX(markCircle2.getCenterX());
|
||||||
|
connectingLine.setEndY(markCircle2.getCenterY());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasRaceId (int... raceIds) {
|
public boolean hasRaceId (int... raceIds) {
|
||||||
for (int id : raceIds)
|
for (int id : raceIds)
|
||||||
for (Mark mark : marks)
|
for (Mark mark : marks)
|
||||||
if (id == mark.getId())
|
if (id == mark.getId())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int getMarkRadius() {
|
|
||||||
return MARK_RADIUS;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setMarkRadius(int markRadius) {
|
|
||||||
MARK_RADIUS = markRadius;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int[] getRaceIds () {
|
public int[] getRaceIds () {
|
||||||
int[] idArray = new int[marks.size()];
|
int[] idArray = new int[marks.size()];
|
||||||
int i = 0;
|
int i = 0;
|
||||||
@@ -224,4 +111,4 @@ public class MarkGroup extends RaceObject {
|
|||||||
idArray[i++] = mark.getId();
|
idArray[i++] = mark.getId();
|
||||||
return idArray;
|
return idArray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -205,7 +205,6 @@ public class StreamParser extends Thread{
|
|||||||
raceFinished = false;
|
raceFinished = false;
|
||||||
System.out.println("[CLIENT] Race has started");
|
System.out.println("[CLIENT] Race has started");
|
||||||
}
|
}
|
||||||
//System.out.println("Time since start: " + -1 * timeTillStart + " Seconds");
|
|
||||||
timeSinceStart = timeTillStart;
|
timeSinceStart = timeTillStart;
|
||||||
}
|
}
|
||||||
long windDir = bytesToLong(Arrays.copyOfRange(payload,18,20));
|
long windDir = bytesToLong(Arrays.copyOfRange(payload,18,20));
|
||||||
@@ -214,11 +213,10 @@ public class StreamParser extends Thread{
|
|||||||
long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22));
|
long windSpeed = bytesToLong(Arrays.copyOfRange(payload,20,22));
|
||||||
int noBoats = payload[22];
|
int noBoats = payload[22];
|
||||||
int raceType = payload[23];
|
int raceType = payload[23];
|
||||||
// ArrayList<String> boatStatuses = new ArrayList<>();
|
|
||||||
boatsPos = new TreeMap<>();
|
boatsPos = new TreeMap<>();
|
||||||
for (int i = 0; i < noBoats; i++){
|
for (int i = 0; i < noBoats; i++){
|
||||||
Long boatStatusSourceID = bytesToLong(Arrays.copyOfRange(payload,24 + (i * 20),28+ (i * 20)));
|
long boatStatusSourceID = bytesToLong(Arrays.copyOfRange(payload,24 + (i * 20),28+ (i * 20)));
|
||||||
Yacht boat = boats.get((int)(long) boatStatusSourceID);
|
Yacht boat = boats.get((int) boatStatusSourceID);
|
||||||
boat.setBoatStatus((int)payload[28 + (i * 20)]);
|
boat.setBoatStatus((int)payload[28 + (i * 20)]);
|
||||||
boat.setLegNumber((int)payload[29 + (i * 20)]);
|
boat.setLegNumber((int)payload[29 + (i * 20)]);
|
||||||
boat.setPenaltiesAwarded((int)payload[29 + (i * 20)]);
|
boat.setPenaltiesAwarded((int)payload[29 + (i * 20)]);
|
||||||
@@ -281,7 +279,6 @@ public class StreamParser extends Thread{
|
|||||||
int messageType = payload[9];
|
int messageType = payload[9];
|
||||||
long messagelength = bytesToLong(Arrays.copyOfRange(payload,12,14));
|
long messagelength = bytesToLong(Arrays.copyOfRange(payload,12,14));
|
||||||
String xmlMessage = new String((Arrays.copyOfRange(payload,14,(int) (14 + messagelength)))).trim();
|
String xmlMessage = new String((Arrays.copyOfRange(payload,14,(int) (14 + messagelength)))).trim();
|
||||||
//System.out.println("xmlMessage2 = " + xmlMessage);
|
|
||||||
|
|
||||||
//Create XML document Object
|
//Create XML document Object
|
||||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||||
@@ -344,7 +341,6 @@ public class StreamParser extends Thread{
|
|||||||
long subjectId = bytesToLong(Arrays.copyOfRange(payload,9,13));
|
long subjectId = bytesToLong(Arrays.copyOfRange(payload,9,13));
|
||||||
long incidentId = bytesToLong(Arrays.copyOfRange(payload,13,17));
|
long incidentId = bytesToLong(Arrays.copyOfRange(payload,13,17));
|
||||||
int eventId = payload[17];
|
int eventId = payload[17];
|
||||||
// System.out.println("eventId = " + eventId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -382,19 +378,18 @@ public class StreamParser extends Thread{
|
|||||||
double groundSpeed = bytesToLong(Arrays.copyOfRange(payload,38,40))/1000.0;
|
double groundSpeed = bytesToLong(Arrays.copyOfRange(payload,38,40))/1000.0;
|
||||||
|
|
||||||
//type 1 is a racing yacht and type 3 is a mark, needed for updating positions of the mark and boat
|
//type 1 is a racing yacht and type 3 is a mark, needed for updating positions of the mark and boat
|
||||||
if (deviceType == 1 || deviceType == 3){
|
if (deviceType == 1){
|
||||||
BoatPositionPacket boatPacket = new BoatPositionPacket(boatId, timeValid, lat, lon, heading, groundSpeed);
|
BoatPositionPacket boatPacket = new BoatPositionPacket(boatId, timeValid, lat, lon, heading, groundSpeed);
|
||||||
|
|
||||||
//add a new priority que to the boatPositions HashMap
|
//add a new priority que to the boatPositions HashMap
|
||||||
if (!boatPositions.containsKey(boatId)){
|
if (!boatPositions.containsKey(boatId)){
|
||||||
boatPositions.put(boatId, new PriorityBlockingQueue<BoatPositionPacket>(256, new Comparator<BoatPositionPacket>() {
|
boatPositions.put(boatId, new PriorityBlockingQueue<>(256, new Comparator<BoatPositionPacket>() {
|
||||||
@Override
|
@Override
|
||||||
public int compare(BoatPositionPacket p1, BoatPositionPacket p2) {
|
public int compare(BoatPositionPacket p1, BoatPositionPacket p2) {
|
||||||
return (int) (p1.getTimeValid() - p2.getTimeValid());
|
return (int) (p1.getTimeValid() - p2.getTimeValid());
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
//Adding the boatPacket to the priority que
|
|
||||||
boatPositions.get(boatId).put(boatPacket);
|
boatPositions.get(boatId).put(boatPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,13 +2,13 @@ package seng302.models.stream;
|
|||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import seng302.models.parsers.packets.StreamPacket;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.concurrent.PriorityBlockingQueue;
|
import java.util.concurrent.PriorityBlockingQueue;
|
||||||
|
import seng302.models.stream.packets.StreamPacket;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|||||||
Reference in New Issue
Block a user