diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index c3ba9c12..0dc8de48 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -1,14 +1,23 @@ package seng302.controllers; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.PriorityBlockingQueue; import javafx.animation.AnimationTimer; import javafx.beans.property.SimpleDoubleProperty; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; import javafx.geometry.Point2D; import javafx.scene.Group; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; import javafx.scene.paint.Color; import javafx.scene.shape.Polygon; import javafx.scene.text.Text; @@ -89,7 +98,7 @@ public class CanvasController { VERTICAL } - public void setup(RaceViewController raceViewController){ + public void setup(RaceViewController raceViewController) { this.raceViewController = raceViewController; } @@ -111,7 +120,7 @@ public class CanvasController { canvas.heightProperty().bind(new SimpleDoubleProperty(CANVAS_HEIGHT)); } - public void initializeCanvas (){ + public void initializeCanvas() { gc = canvas.getGraphicsContext2D(); gc.setGlobalAlpha(0.5); @@ -161,11 +170,29 @@ public class CanvasController { } if (StreamParser.isRaceFinished()) { this.stop(); + switchToFinishScreen(); } } }; } + private void switchToFinishScreen() { + try { + // canvas view -> anchor pane -> grid pane -> main view + GridPane gridPane = (GridPane) canvasPane.getParent().getParent(); + AnchorPane contentPane = (AnchorPane) gridPane.getParent(); + contentPane.getChildren().removeAll(); + contentPane.getChildren().clear(); + contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString()); + contentPane.getChildren().addAll( + (Pane) FXMLLoader.load(getClass().getResource("/views/FinishScreenView.fxml"))); + } catch (javafx.fxml.LoadException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + /** * First find the top right and bottom left points' geo locations, then retrieve * map from google to display on image view. - Haoming 22/5/2017 @@ -174,19 +201,29 @@ public class CanvasController { findMetersPerPixel(); Point2D topLeftPoint = findScaledXY(maxLatPoint.getLatitude(), minLonPoint.getLongitude()); // distance from top left extreme to panel origin (top left corner) - double distanceFromTopLeftToOrigin = Math.sqrt(Math.pow(topLeftPoint.getX() * metersPerPixelX, 2) + Math.pow(topLeftPoint.getY() * metersPerPixelY, 2)); + double distanceFromTopLeftToOrigin = Math.sqrt( + Math.pow(topLeftPoint.getX() * metersPerPixelX, 2) + Math + .pow(topLeftPoint.getY() * metersPerPixelY, 2)); // angle from top left extreme to panel origin - double bearingFromTopLeftToOrigin = Math.toDegrees(Math.atan2(-topLeftPoint.getX(), topLeftPoint.getY())); + double bearingFromTopLeftToOrigin = Math + .toDegrees(Math.atan2(-topLeftPoint.getX(), topLeftPoint.getY())); // the top left extreme Position topLeftPos = new Position(maxLatPoint.getLatitude(), minLonPoint.getLongitude()); - Position originPos = GeoUtility.getGeoCoordinate(topLeftPos, bearingFromTopLeftToOrigin, distanceFromTopLeftToOrigin); + Position originPos = GeoUtility + .getGeoCoordinate(topLeftPos, bearingFromTopLeftToOrigin, distanceFromTopLeftToOrigin); // distance from origin corner to bottom right corner of the panel - double distanceFromOriginToBottomRight = Math.sqrt(Math.pow(PANEL_HEIGHT* metersPerPixelY, 2) + Math.pow(PANEL_WIDTH * metersPerPixelX, 2)); - double bearingFromOriginToBottomRight = Math.toDegrees(Math.atan2(PANEL_WIDTH, -PANEL_HEIGHT)); - Position bottomRightPos = GeoUtility.getGeoCoordinate(originPos, bearingFromOriginToBottomRight, distanceFromOriginToBottomRight); + double distanceFromOriginToBottomRight = Math.sqrt( + Math.pow(PANEL_HEIGHT * metersPerPixelY, 2) + Math + .pow(PANEL_WIDTH * metersPerPixelX, 2)); + double bearingFromOriginToBottomRight = Math + .toDegrees(Math.atan2(PANEL_WIDTH, -PANEL_HEIGHT)); + Position bottomRightPos = GeoUtility + .getGeoCoordinate(originPos, bearingFromOriginToBottomRight, + distanceFromOriginToBottomRight); - Boundary boundary = new Boundary(originPos.getLat(), bottomRightPos.getLng(), bottomRightPos.getLat(), originPos.getLng()); + Boundary boundary = new Boundary(originPos.getLat(), bottomRightPos.getLng(), + bottomRightPos.getLat(), originPos.getLng()); CanvasMap canvasMap = new CanvasMap(boundary); mapImage.setImage(canvasMap.getMapImage()); } @@ -194,9 +231,10 @@ public class CanvasController { /** * Adds border marks to the canvas, taken from the XML file * - * NOTE: This is quite confusing as objects are grabbed from the XMLParser such as Mark and CompoundMark which are - * named the same as those in the model package but are, however not the same, so they do not have things such as - * a type and must be derived from the number of marks in a compound mark etc.. + * NOTE: This is quite confusing as objects are grabbed from the XMLParser such as Mark and + * CompoundMark which are named the same as those in the model package but are, however not the + * same, so they do not have things such as a type and must be derived from the number of marks + * in a compound mark etc.. */ private void addRaceBorder() { XMLParser.RaceXMLObject raceXMLObject = StreamParser.getXmlObject().getRaceXML(); @@ -213,7 +251,7 @@ public class CanvasController { raceBorder.getPoints().setAll(boundaryPoints); } - private void updateGroups(){ + private void updateGroups() { for (BoatGroup boatGroup : boatGroups) { // some raceObjects will have multiple ID's (for instance gate marks) //checking if the current "ID" has any updates associated with it @@ -243,7 +281,7 @@ public class CanvasController { private void updateBoatGroup(BoatGroup boatGroup) { PriorityBlockingQueue movementQueue = StreamParser.boatLocations.get(boatGroup.getRaceId()); // giving the movementQueue a 5 packet buffer to account for slightly out of order packets - if (movementQueue.size() > 0){ + if (movementQueue.size() > 0) { try { BoatPositionPacket positionPacket = movementQueue.take(); Point2D p2d = findScaledXY(positionPacket.getLat(), positionPacket.getLon()); @@ -265,7 +303,7 @@ public class CanvasController { BoatPositionPacket positionPacket = movementQueue.take(); Point2D p2d = findScaledXY(positionPacket.getLat(), positionPacket.getLon()); markGroup.moveMarkTo(p2d.getX(), p2d.getY(), raceId); - } catch (InterruptedException e){ + } catch (InterruptedException e) { e.printStackTrace(); } } @@ -280,7 +318,8 @@ public class CanvasController { Group trails = new Group(); Group annotations = new Group(); - ArrayList participants = StreamParser.getXmlObject().getRaceXML().getParticipants(); + ArrayList participants = StreamParser.getXmlObject().getRaceXML() + .getParticipants(); ArrayList participantIDs = new ArrayList<>(); for (Participant p : participants) { participantIDs.add(p.getsourceID()); @@ -313,7 +352,8 @@ public class CanvasController { } else { GateMark gMark = (GateMark) mark; - MarkGroup markGroup = new MarkGroup(gMark, findScaledXY(gMark.getSingleMark1()), findScaledXY(gMark.getSingleMark2())); //should be 2 objects in the list. + MarkGroup markGroup = new MarkGroup(gMark, findScaledXY(gMark.getSingleMark1()), + findScaledXY(gMark.getSingleMark2())); //should be 2 objects in the list. markGroups.add(markGroup); } } @@ -345,6 +385,7 @@ public class CanvasController { public double prefWidth(double height) { return getWidth(); } + @Override public double prefHeight(double width) { return getHeight(); @@ -362,7 +403,8 @@ public class CanvasController { } /** - * Calculates x and y location for every marker that fits it to the canvas the race will be drawn on. + * Calculates x and y location for every marker that fits it to the canvas the race will be + * drawn on. */ private void fitMarksToCanvas() { //Check is called once to avoid unnecessarily change the course limits once the race is running @@ -376,8 +418,9 @@ public class CanvasController { /** - * Sets the class variables minLatPoint, maxLatPoint, minLonPoint, maxLonPoint to the marker with the leftmost - * marker, rightmost marker, southern most marker and northern most marker respectively. + * Sets the class variables minLatPoint, maxLatPoint, minLonPoint, maxLonPoint to the marker + * with the leftmost marker, rightmost marker, southern most marker and northern most marker + * respectively. */ private void findMinMaxPoint() { List sortedPoints = new ArrayList<>(); @@ -402,12 +445,13 @@ public class CanvasController { } /** - * Calculates the location of a reference point, this is always the point with minimum latitude, in relation to the - * canvas. + * Calculates the location of a reference point, this is always the point with minimum latitude, + * in relation to the canvas. * - * @param minLonToMaxLon The horizontal distance between the point of minimum longitude to maximum longitude. + * @param minLonToMaxLon The horizontal distance between the point of minimum longitude to + * maximum longitude. */ - private void calculateReferencePointLocation (double minLonToMaxLon) { + private void calculateReferencePointLocation(double minLonToMaxLon) { Mark referencePoint = minLatPoint; double referenceAngle; @@ -436,20 +480,23 @@ public class CanvasController { /** - * 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. + * 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. */ - private double scaleRaceExtremities () { + private double scaleRaceExtremities() { double vertAngle = Math.abs(Mark.calculateHeadingRad(minLatPoint, maxLatPoint)); - double vertDistance = Math.cos(vertAngle) * Mark.calculateDistance(minLatPoint, maxLatPoint); + double vertDistance = + Math.cos(vertAngle) * Mark.calculateDistance(minLatPoint, maxLatPoint); double horiAngle = Mark.calculateHeadingRad(minLonPoint, maxLonPoint); - if (horiAngle <= (Math.PI / 2)) + if (horiAngle <= (Math.PI / 2)) { horiAngle = (Math.PI / 2) - horiAngle; - else + } else { horiAngle = horiAngle - (Math.PI / 2); - double horiDistance = Math.cos(horiAngle) * Mark.calculateDistance(minLonPoint, maxLonPoint); + } + double horiDistance = + Math.cos(horiAngle) * Mark.calculateDistance(minLonPoint, maxLonPoint); double vertScale = (CANVAS_HEIGHT - (BUFFER_SIZE + BUFFER_SIZE)) / vertDistance; @@ -463,8 +510,8 @@ public class CanvasController { return horiDistance; } - private Point2D findScaledXY (Mark unscaled) { - return findScaledXY (unscaled.getLatitude(), unscaled.getLongitude()); + private Point2D findScaledXY(Mark unscaled) { + return findScaledXY(unscaled.getLatitude(), unscaled.getLongitude()); } public Point2D findScaledXY (double unscaledLat, double unscaledLon) { @@ -473,23 +520,35 @@ public class CanvasController { int xAxisLocation = (int) referencePointX; int yAxisLocation = (int) referencePointY; - angleFromReference = Mark.calculateHeadingRad(minLatPoint.getLatitude(), minLatPoint.getLongitude(), unscaledLat, unscaledLon); - distanceFromReference = Mark.calculateDistance(minLatPoint.getLatitude(), minLatPoint.getLongitude(), unscaledLat, unscaledLon); + angleFromReference = Mark + .calculateHeadingRad(minLatPoint.getLatitude(), minLatPoint.getLongitude(), unscaledLat, + unscaledLon); + distanceFromReference = Mark + .calculateDistance(minLatPoint.getLatitude(), minLatPoint.getLongitude(), unscaledLat, + unscaledLon); if (angleFromReference >= 0 && angleFromReference <= Math.PI / 2) { - xAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); - yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + xAxisLocation += (int) Math + .round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); + yAxisLocation -= (int) Math + .round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); } else if (angleFromReference >= 0) { angleFromReference = angleFromReference - Math.PI / 2; - xAxisLocation += (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); - yAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); + xAxisLocation += (int) Math + .round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + yAxisLocation += (int) Math + .round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); } else if (angleFromReference < 0 && angleFromReference >= -Math.PI / 2) { angleFromReference = Math.abs(angleFromReference); - xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); - yAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + xAxisLocation -= (int) Math + .round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); + yAxisLocation -= (int) Math + .round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); } else { angleFromReference = Math.abs(angleFromReference) - Math.PI / 2; - xAxisLocation -= (int) Math.round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); - yAxisLocation += (int) Math.round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); + xAxisLocation -= (int) Math + .round(distanceScaleFactor * Math.cos(angleFromReference) * distanceFromReference); + yAxisLocation += (int) Math + .round(distanceScaleFactor * Math.sin(angleFromReference) * distanceFromReference); } if(horizontalInversion) { xAxisLocation = CANVAS_WIDTH - BUFFER_SIZE - (xAxisLocation - BUFFER_SIZE); @@ -500,7 +559,7 @@ public class CanvasController { /** * Find the number of meters per pixel. */ - private void findMetersPerPixel () { + private void findMetersPerPixel() { Point2D p1, p2; Mark m1, m2; double theta, distance, dx, dy, dHorizontal, dVertical; diff --git a/src/main/java/seng302/controllers/FinishScreenViewController.java b/src/main/java/seng302/controllers/FinishScreenViewController.java new file mode 100644 index 00000000..a2d79f36 --- /dev/null +++ b/src/main/java/seng302/controllers/FinishScreenViewController.java @@ -0,0 +1,97 @@ +package seng302.controllers; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.ResourceBundle; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.fxml.Initializable; +import javafx.scene.control.TableColumn; +import javafx.scene.control.TableView; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.Pane; +import seng302.models.Yacht; +import seng302.models.stream.StreamParser; +import seng302.models.stream.XMLParser.RaceXMLObject.Participant; + +public class FinishScreenViewController implements Initializable { + + @FXML + private GridPane finishScreenGridPane; + @FXML + private TableView finishOrderTable; + @FXML + private TableColumn posCol; + @FXML + private TableColumn boatNameCol; + @FXML + private TableColumn shortNameCol; + @FXML + private TableColumn countryCol; + + @Override + public void initialize(URL location, ResourceBundle resources) { + finishScreenGridPane.getStylesheets() + .add(getClass().getResource("/css/master.css").toString()); + finishOrderTable.getStylesheets().add(getClass().getResource("/css/master.css").toString()); + + // set up data for table + ObservableList data = FXCollections.observableArrayList(); + finishOrderTable.setItems(data); + + // setting table col data + posCol.setCellValueFactory( + new PropertyValueFactory<>("position") + ); + boatNameCol.setCellValueFactory( + new PropertyValueFactory<>("boatName") + ); + shortNameCol.setCellValueFactory( + new PropertyValueFactory<>("shortName") + ); + countryCol.setCellValueFactory( + new PropertyValueFactory<>("country") + ); + + // check if the boat is racing + ArrayList participants = StreamParser.getXmlObject().getRaceXML() + .getParticipants(); + ArrayList participantIDs = new ArrayList<>(); + for (Participant p : participants) { + participantIDs.add(p.getsourceID()); + } + + // add data to table + for (Yacht boat : StreamParser.getBoatsPos().values()) { + if (participantIDs.contains(boat.getSourceID())) { + data.add(boat); + } + } + finishOrderTable.refresh(); + } + + private void setContentPane(String jfxUrl) { + try { + // get the main controller anchor pane (FinishView -> MainView) + AnchorPane contentPane = (AnchorPane) finishScreenGridPane.getParent(); + contentPane.getChildren().removeAll(); + contentPane.getChildren().clear(); + contentPane.getStylesheets().add(getClass().getResource("/css/master.css").toString()); + contentPane.getChildren() + .addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl))); + } catch (javafx.fxml.LoadException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public void switchToStartScreenView() { + setContentPane("/views/StartScreenView.fxml"); + } +} diff --git a/src/main/java/seng302/controllers/StartScreenController.java b/src/main/java/seng302/controllers/StartScreenController.java index b2238826..931874d5 100644 --- a/src/main/java/seng302/controllers/StartScreenController.java +++ b/src/main/java/seng302/controllers/StartScreenController.java @@ -77,6 +77,9 @@ public class StartScreenController implements Initializable { * second. */ public void startStream() { + // reset boolean for switch to race view + switchedToRaceView = false; + if (StreamParser.isStreamStatus()) { streamButton.setVisible(false); realTime.setVisible(true); diff --git a/src/main/resources/views/FinishScreenView.fxml b/src/main/resources/views/FinishScreenView.fxml new file mode 100644 index 00000000..736c8b74 --- /dev/null +++ b/src/main/resources/views/FinishScreenView.fxml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +