diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java deleted file mode 100644 index c0b20e26..00000000 --- a/src/main/java/seng302/controllers/CanvasController.java +++ /dev/null @@ -1,283 +0,0 @@ -package seng302.controllers; - -import javafx.animation.*; -import javafx.fxml.FXML; -import javafx.scene.canvas.Canvas; -import javafx.scene.canvas.GraphicsContext; -import javafx.scene.layout.AnchorPane; -import javafx.scene.paint.Color; -import javafx.scene.text.Font; -import seng302.models.Boat; -import seng302.models.TimelineInfo; -import seng302.models.mark.GateMark; -import seng302.models.mark.Mark; -import seng302.models.mark.MarkType; -import seng302.models.mark.SingleMark; - -import java.util.*; - -/** - * Created by ptg19 on 15/03/17. - * Modified by Haoming Yin (hyi25) on 20/3/2017. - */ -public class CanvasController { - - @FXML - private AnchorPane canvasPane; - - private RaceViewController raceViewController; - private ResizableCanvas canvas; - private GraphicsContext gc; - - private final double ORIGIN_LAT = 32.321504; - private final double ORIGIN_LON = -64.857063; - private final int SCALE = 16000; - - public void setup(RaceViewController raceViewController){ - this.raceViewController = raceViewController; - } - - public void initialize() { - canvas = new ResizableCanvas(); - canvasPane.getChildren().add(canvas); - // Bind canvas size to stack pane size. - canvas.widthProperty().bind(canvasPane.widthProperty()); - canvas.heightProperty().bind(canvasPane.heightProperty()); - gc = canvas.getGraphicsContext2D(); - - - // overriding the handle so that it can clean canvas and redraw boats and course marks - AnimationTimer timer = new AnimationTimer() { - private long lastUpdate = 0; - private long lastFpsUpdate = 0; - private int lastFpsCount = 0; - private int fpsCount = 0; - - @Override - public void handle(long now) { - if (true){ //if statement for limiting refresh rate if needed - gc.clearRect(0, 0, canvas.getWidth(),canvas.getHeight()); - gc.setFill(Color.SKYBLUE); - gc.fillRect(0,0,canvas.getWidth(),canvas.getHeight()); - drawCourse(); - drawBoats(); - drawFps(lastFpsCount); - - // If race has started, draw the boats and play the timeline - if (raceViewController.getRace().getRaceTime() > 1){ - raceViewController.playTimelines(); - } - // Race has not started, pause the timelines - else { - raceViewController.pauseTimelines(); - } - lastUpdate = now; - fpsCount ++; - if (now - lastFpsUpdate >= 1000000000){ - lastFpsCount = fpsCount; - fpsCount = 0; - lastFpsUpdate = now; - } - } - } - }; - timer.start(); - } - - class ResizableCanvas extends Canvas { - - public ResizableCanvas() { - // Redraw canvas when size changes. - widthProperty().addListener(evt -> draw()); - heightProperty().addListener(evt -> draw()); - } - - private void draw() { - double width = getWidth(); - double height = getHeight(); - - GraphicsContext gc = getGraphicsContext2D(); - gc.clearRect(0, 0, width, height); - } - - @Override - public boolean isResizable() { - return true; - } - - @Override - public double prefWidth(double height) { - return getWidth(); - } - - @Override - public double prefHeight(double width) { - return getHeight(); - } - } - - private void drawFps(int fps){ - if (raceViewController.isDisplayFps()){ - gc.setFill(Color.BLACK); - gc.setFont(new Font(14)); - gc.setLineWidth(3); - gc.fillText(fps + " FPS", 5, 20); - } - } - - /** - * Draws all the boats. - */ - private void drawBoats() { - Map timelineInfos = raceViewController.getTimelineInfos(); - for (Boat boat : timelineInfos.keySet()) { - TimelineInfo timelineInfo = timelineInfos.get(boat); - - boat.setLocation(timelineInfo.getY().doubleValue(), timelineInfo.getX().doubleValue()); - - drawBoat(boat.getLongitude(), boat.getLatitude(), boat.getColor(), boat.getShortName(), boat.getSpeedInKnots(), boat.getHeading()); - } - } - - /** - * Draw the wake line behind a boat - * @param gc The graphics context used for drawing the wake - * @param x the x position of the boat - * @param y the y position of the boat - * @param speed the speed of the boat - * @param color the color of the wake line - * @param heading the heading of the boat - */ - private void drawWake(GraphicsContext gc, double x, double y, double speed, Color color, double heading){ - double angle = Math.toRadians(heading); - speed = speed * 2; - Point newP = new Point(0, speed); - newP.rotate(angle); - - gc.setStroke(color); - gc.setLineWidth(1.0); - gc.strokeLine(x, y, newP.x + x, newP.y + y); - } - - /** - * Draws a boat with given (x, y) position in the given color - * - * @param lat - * @param lon - * @param color - * @param name - * @param speed - */ - private void drawBoat(double lat, double lon, Color color, String name, double speed, double heading) { - // Latitude - double x = (lon - ORIGIN_LON) * SCALE; - double y = (ORIGIN_LAT - lat) * SCALE; - - gc.setFill(color); - - if (raceViewController.isDisplayAnnotations()) { - // Set boat text - gc.setFont(new Font(14)); - gc.setLineWidth(3); - gc.fillText(name + ", " + speed + " knots", x + 15, y + 15); - } -// double diameter = 9; -// gc.fillOval(x, y, diameter, diameter); - double angle = Math.toRadians(heading); - - Point p1 = new Point(0, -15); // apex point - Point p2 = new Point(7, 4); // base point - Point p3 = new Point(-7, 4); // base point - p1.rotate(angle); - p2.rotate(angle); - p3.rotate(angle); - double[] xx = new double[] {p1.x + x, p2.x + x, x, p3.x + x}; - double[] yy = new double[] {p1.y + y, p2.y + y, y, p3.y + y}; - gc.fillPolygon(xx, yy, 4); - - if (raceViewController.isDisplayAnnotations()){ - drawWake(gc, x, y, speed, color, heading); - } - } - - /** - * Inner class for creating point so that you can rotate it around origin point. - */ - class Point { - - double x, y; - - Point (double x, double y) { - this.x = x; - this.y = y; - } - - void rotate(double angle) { - double oldX = x; - double oldY = y; - this.x = oldX * Math.cos(angle) - oldY * Math.sin(angle); - this.y = oldX * Math.sin(angle) + oldY * Math.cos(angle); - - } - } - - /** - * Draws the course. - */ - private void drawCourse() { - for (Mark mark : raceViewController.getRace().getCourse()) { - if (mark.getMarkType() == MarkType.SINGLE_MARK) { - drawSingleMark((SingleMark) mark, Color.BLACK); - } else if (mark.getMarkType() == MarkType.GATE_MARK) { - drawGateMark((GateMark) mark); - } - } - } - - /** - * Draw a given mark on canvas - * - * @param singleMark - */ - private void drawSingleMark(SingleMark singleMark, Color color) { - double x = (singleMark.getLongitude() - ORIGIN_LON) * SCALE; - double y = (ORIGIN_LAT - singleMark.getLatitude()) * SCALE; - - gc.setFill(color); - gc.fillRect(x,y,5.5,5.5); - } - - /** - * Draw a gate mark which contains two single marks - * - * @param gateMark - */ - private void drawGateMark(GateMark gateMark) { - Color color = Color.BLUE; - - if (gateMark.getName().equals("Start")){ - color = Color.RED; - } - - if (gateMark.getName().equals("Finish")){ - color = Color.GREEN; - } - - drawSingleMark(gateMark.getSingleMark1(), color); - drawSingleMark(gateMark.getSingleMark2(), color); - - GraphicsContext gc = canvas.getGraphicsContext2D(); - - gc.setStroke(color); - - // Convert lat/lon to x,y - double x1 = (gateMark.getSingleMark1().getLongitude()- ORIGIN_LON) * SCALE; - double y1 = (ORIGIN_LAT - gateMark.getSingleMark1().getLatitude()) * SCALE; - - double x2 = (gateMark.getSingleMark2().getLongitude() - ORIGIN_LON) * SCALE; - double y2 = (ORIGIN_LAT - gateMark.getSingleMark2().getLatitude()) * SCALE; - - gc.setLineWidth(1); - gc.strokeLine(x1, y1, x2, y2); - } -} \ No newline at end of file diff --git a/src/main/java/seng302/controllers/Controller.java b/src/main/java/seng302/controllers/Controller.java index 1892d472..080e06ab 100644 --- a/src/main/java/seng302/controllers/Controller.java +++ b/src/main/java/seng302/controllers/Controller.java @@ -1,38 +1,176 @@ package seng302.controllers; import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; import javafx.fxml.Initializable; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.Pane; +import javafx.scene.Group; +import javafx.scene.canvas.Canvas; +import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.Button; +import javafx.scene.paint.Color; +import seng302.models.Boat; +import seng302.models.Course; +import seng302.models.Race; +import seng302.models.mark.Mark; +import seng302.models.mark.MarkType; +import seng302.models.parsers.ConfigParser; +import seng302.models.parsers.CourseParser; +import seng302.models.parsers.TeamsParser; -import java.io.IOException; import java.net.URL; +import java.util.ArrayList; import java.util.ResourceBundle; /** - * Created by michaelrausch on 21/03/17. + * Controller for main window for RaceVision + * Created by Kusal on 3/22/2017. */ public class Controller implements Initializable { - @FXML - private AnchorPane contentPane; - private void setContentPane(String jfxUrl){ - try{ - contentPane.getChildren().removeAll(); - contentPane.getChildren().clear(); - contentPane.getChildren().addAll((Pane) FXMLLoader.load(getClass().getResource(jfxUrl))); - } - catch(javafx.fxml.LoadException e){ - System.err.println(e.getCause()); - } - catch(IOException e){ - System.err.println(e); - } - } + private static final int MARKER_WIDTH = 10; + private static final int MARKER_HEIGHT = 10; + private static final double ORIGINAL_LAT = 32.321504; + private static final double ORIGINAL_LON = -64.857063; + + + @FXML + private Canvas courseCanvas; + + @FXML + private Group boatGroup; + + @FXML + private Button playPauseButton; + + + private Course thisCourse; + private ArrayList startingBoats; + private int raceDuration; + private Race race; + private boolean raceRunning = false; + + private CourseParser cp; + private TeamsParser tp; + private ConfigParser cop; @Override public void initialize(URL location, ResourceBundle resources) { - setContentPane("/views/RaceView.fxml"); + cp = new CourseParser("/config/course.xml"); + tp = new TeamsParser("/config/teams.xml"); + cop = new ConfigParser("/config/config.xml"); + + thisCourse = new Course(cp.getCourse()); + startingBoats = tp.getBoats(); + race = new Race(thisCourse.getMarks(), startingBoats, cop.getTimeScale(), this); + init(); + } + + /** + * Initialises a race on the screen after it has been loaded + */ + private void init() { + initMap(); + initBoats(); + playPauseButton.setDisable(false); + } + + /** + * Initialise the map by drawing it onto courseCanvas. + */ + private void initMap() { + //Create the boundary of the course displayed on the map + drawCourse(); + } + + + /** + * Draw the markers and gates onto the courseCanvas. + */ + private void drawCourse() { + GraphicsContext gc = courseCanvas.getGraphicsContext2D(); + gc.save(); + + for(Mark rp : thisCourse.getMarks()) { + if (rp.getMarkType().equals(MarkType.SINGLE_MARK)) { + gc.setFill(Color.GRAY); + gc.fillOval(convertLongToX(rp.getLongitude()), convertLatToY(rp.getLatitude()), MARKER_WIDTH, MARKER_HEIGHT); + } else if (rp.getMarkType().equals(MarkType.GATE_MARK)) { + gc.setFill(Color.GRAY); + gc.fillOval(convertLongToX(rp.getLongitude()), convertLatToY(rp.getLatitude()), MARKER_WIDTH, MARKER_HEIGHT); +// gc.fillOval(((OpenGate) rp).getDrawX2(), ((OpenGate) rp).getDrawY2(), MARKER_WIDTH, MARKER_HEIGHT); + + gc.setLineWidth(2); + gc.setFill(Color.GREEN); + gc.setStroke(Color.GREEN); + } + gc.fillOval(convertLongToX(rp.getLongitude()), convertLatToY(rp.getLatitude()), MARKER_WIDTH, MARKER_HEIGHT); +// gc.fillOval(((ClosedGate) rp).getDrawX2(), ((ClosedGate) rp).getDrawY2(), MARKER_WIDTH, MARKER_HEIGHT); +// gc.strokeLine(convertLongToX(rp.getLongitude()) + 5, convertLatToY(rp.getLatitude()) + 5, ((ClosedGate) rp).getDrawX2() + 5, ((ClosedGate) rp).getDrawY2() + 5); + } + gc.restore(); + } + + /** + * Places boats at starting line + */ + private void initBoats() { + +// int startingX = (convertLongToX(thisCourse.getMarks().get(0).getLongitude())).intValue(); +// int startingY = (convertLatToY(thisCourse.getMarks().get(0).getLongitude())).intValue(); + + int startingX = 50; + int startingY = 100; + + for(Boat boat : startingBoats) { + boat.moveBoatTo(startingX, startingY); + boatGroup.getChildren().add(boat.getBoatObject()); + boat.setCurrentLeg(race.getRaceLegs().get(0)); + boat.setHeading(race.getRaceLegs().get(0).getHeading()); + boat.setLegDistance(0d); + } + } + + + /** + * Starts and stops the race depending on whether or not it is already running + */ + public void playPause() { + if (!raceRunning) { + play(); + } else { + pause(); + } + } + + /** + * Plays the race and updates the play / pause button + */ + private void play() { + race.run(); + raceRunning = true; + playPauseButton.setText("Pause"); + + } + + /** + * Pauses the race and updates the play / pause button + */ + private void pause() { + race.pause(); + raceRunning = false; + playPauseButton.setText("Play"); + } + + + + private Double convertLongToX(Double lon) { + return (lon - ORIGINAL_LON) * thisCourse.getDistanceScaleFactor(); + } + + private Double convertLatToY(Double lat) { + return (ORIGINAL_LAT - lat) * thisCourse.getDistanceScaleFactor(); + } + + public Button getPlayPauseButton() { + return playPauseButton; } } diff --git a/src/main/java/seng302/controllers/RaceController.java b/src/main/java/seng302/controllers/RaceController.java deleted file mode 100644 index b5fa2847..00000000 --- a/src/main/java/seng302/controllers/RaceController.java +++ /dev/null @@ -1,80 +0,0 @@ -package seng302.controllers; - -import seng302.models.Boat; -import seng302.models.Race; -import seng302.models.parsers.ConfigParser; -import seng302.models.parsers.CourseParser; -import seng302.models.parsers.TeamsParser; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Random; - -/** - * Created by zyt10 on 17/03/17. - * run before CanvasController to initialize race events - * the CanvasController then uses the event data to make the animations - */ -public class RaceController { - Race race = null; - - public void initializeRace() { - String raceConfigFile = "/config/config.xml"; - String teamsConfigFile = "/config/teams.xml"; - - try { - race = createRace(raceConfigFile, teamsConfigFile); - } catch (Exception e) { - System.out.println("There was an error creating the race."); - } - - if (race != null) { - race.startRace(); - } else { - System.out.println("There was an error creating the race. Exiting."); - } - } - - public Race createRace(String configFile, String teamsConfigFile) throws Exception { - Race race = new Race(); - - // Read team names from file - TeamsParser tp = new TeamsParser(teamsConfigFile); - - // Read course from file - ConfigParser config = new ConfigParser(configFile); - - ArrayList boatNames = new ArrayList<>(); - ArrayList teams = tp.getBoats(); - - //get race size - int numberOfBoats = teams.size(); - - //get time scale - double timeScale = config.getTimeScale(); - race.setTimeScale(timeScale); - - for (Boat boat : teams) { - boatNames.add(boat.getTeamName()); - race.addBoat(boat); - } - - // Shuffle team names - long seed = System.nanoTime(); - Collections.shuffle(boatNames, new Random(seed)); - - if (numberOfBoats > Array.getLength(boatNames.toArray())) { - return null; - } - - CourseParser course = new CourseParser("/config/course.xml"); - race.addCourse(course.getCourse()); - - return race; - } - - public Race getRace() { - return race; - } -} diff --git a/src/main/java/seng302/controllers/RaceResultController.java b/src/main/java/seng302/controllers/RaceResultController.java deleted file mode 100644 index 7378fa68..00000000 --- a/src/main/java/seng302/controllers/RaceResultController.java +++ /dev/null @@ -1,37 +0,0 @@ -package seng302.controllers; - -import javafx.fxml.FXML; -import javafx.fxml.Initializable; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.VBox; -import javafx.scene.text.Text; -import seng302.models.Race; - -import java.net.URL; -import java.util.ResourceBundle; - -/** - * Created by ptg19 on 20/03/17. - */ -public class RaceResultController implements Initializable{ - @FXML private AnchorPane window; - @FXML private VBox resultsVBox; - private Race race; - - RaceResultController(Race race){ - this.race = race; - } - - @Override - public void initialize(URL location, ResourceBundle resources) { - int boatPosition = this.race.getFinishedBoats().length; - - for (int i = this.race.getFinishedBoats().length - 1; i >= 0; i--){ - resultsVBox.getChildren().add(0, new Text(boatPosition + ": " + this.race.getFinishedBoats()[i].getTeamName())); - boatPosition--; - } - - - - } -} diff --git a/src/main/java/seng302/controllers/RaceViewController.java b/src/main/java/seng302/controllers/RaceViewController.java deleted file mode 100644 index 965fbc7d..00000000 --- a/src/main/java/seng302/controllers/RaceViewController.java +++ /dev/null @@ -1,280 +0,0 @@ -package seng302.controllers; - -import javafx.animation.Animation; -import javafx.animation.KeyFrame; -import javafx.animation.KeyValue; -import javafx.animation.Timeline; -import javafx.beans.property.DoubleProperty; -import javafx.beans.property.SimpleDoubleProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.fxml.FXML; -import javafx.fxml.FXMLLoader; -import javafx.scene.control.CheckBox; -import javafx.scene.layout.AnchorPane; -import javafx.scene.layout.Pane; -import javafx.scene.layout.VBox; -import javafx.scene.text.Text; -import javafx.util.Duration; -import seng302.models.Boat; -import seng302.models.Event; -import seng302.models.Race; -import seng302.models.TimelineInfo; -import seng302.models.parsers.ConfigParser; - -import java.io.IOException; -import java.util.*; - -/** - * Created by ptg19 on 29/03/17. - */ -public class RaceViewController { - @FXML - private VBox positionVbox; - @FXML - private CheckBox toggleAnnotation, toggleFps; - @FXML - private Text timerLabel; - @FXML - private AnchorPane contentAnchorPane; - @FXML - private Text windArrowText, windDirectionText; - @FXML - private CanvasController includedCanvasController; - - private boolean displayAnnotations; - private boolean displayFps; - private Timeline timerTimeline; - private Map timelineInfos = new HashMap<>(); - private ArrayList boatOrder = new ArrayList<>(); - private Race race; - - public void initialize() { - includedCanvasController.setup(this); - RaceController raceController = new RaceController(); - raceController.initializeRace(); - race = raceController.getRace(); - - initializeTimer(); - initializeSettings(); - try{ - initializeTimelines(); - } - catch (Exception e){ - e.printStackTrace(); - } - - //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); - } - - private void initializeSettings(){ - displayAnnotations = true; - displayFps = true; - - toggleAnnotation.selectedProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { - displayAnnotations = !displayAnnotations; - } - }); - toggleFps.selectedProperty().addListener(new ChangeListener() { - @Override - public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { - displayFps = !displayFps; - } - }); - } - - private void initializeTimer(){ - timerTimeline = new Timeline(); - timerTimeline.setCycleCount(Timeline.INDEFINITE); - // Run timer update every second - timerTimeline.getKeyFrames().add( - new KeyFrame(Duration.seconds(1), - event -> { - // Stop timer if race is finished - if (this.race.isRaceFinished()) { - this.timerTimeline.stop(); - } else { - timerLabel.setText(convertTimeToMinutesSeconds(race.getRaceTime())); - this.race.incrementRaceTime(); - } - }) - ); - - // Start the timer - timerTimeline.playFromStart(); - } - - /** - * Generates time line for each boat, and stores time time into timelineInfos hash map - */ - private void initializeTimelines() { - HashMap boat_events = race.getEvents(); - - for (Boat boat : boat_events.keySet()) { - // x, y are the real time coordinates - DoubleProperty x = new SimpleDoubleProperty(); - DoubleProperty y = new SimpleDoubleProperty(); - - List keyFrames = new ArrayList<>(); - List 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) { - Boat boat = event.getBoat(); - boatOrder.remove(boat); - boat.setMarkLastPast(event.getMarkPosInRace()); - boatOrder.add(boat); - boatOrder.sort(new Comparator() { - @Override - public int compare(Boat b1, Boat b2) { - return b2.getMarkLastPast() - b1.getMarkLastPast(); - } - }); - showOrder(); - } - - private void showOrder() { - positionVbox.getChildren().clear(); - positionVbox.getChildren().removeAll(); - - for (Boat boat : boatOrder) { - positionVbox.getChildren().add(new Text(boat.getShortName() + " " + boat.getSpeedInKnots() + " Knots")); - } - } - - /** - * Convert seconds to a string of the format mm:ss - * - * @param time the time in seconds - * @return a formatted string - */ - public String convertTimeToMinutesSeconds(int time) { - if (time < 0) { - return String.format("-%02d:%02d", (time * -1) / 60, (time * -1) % 60); - } - return String.format("%02d:%02d", time / 60, time % 60); - } - - public void stopTimer() { - timerTimeline.stop(); - } - public void startTimer() { - timerTimeline.play(); - } - - public boolean isDisplayFps() { - return displayFps; - } - - public boolean isDisplayAnnotations() { - return displayAnnotations; - } - - public Race getRace() { - return race; - } - - public Map getTimelineInfos() { - return timelineInfos; - } -} \ No newline at end of file diff --git a/src/main/java/seng302/models/Boat.java b/src/main/java/seng302/models/Boat.java index 0973ad38..e081efb9 100644 --- a/src/main/java/seng302/models/Boat.java +++ b/src/main/java/seng302/models/Boat.java @@ -1,28 +1,36 @@ package seng302.models; import javafx.scene.paint.Color; +import javafx.scene.shape.Polygon; +import javafx.scene.text.Text; /** * Represents a boat in the race. */ public class Boat { + private static final double BOAT_HEIGHT = 15d; + private static final double BOAT_WIDTH = 10d; + private static final double VELOCITY_WAKE_RATIO = 1/2d; //Ratio for deciding how long the wake will be wrt velocity + private String teamName; // The name of the team, this is also the name of the boat - private double velocity; // In meters/second - private double lat; // Boats position - private double lon; // - - private double distanceToNextMark; + private Double velocity; // In meters/second + private Double lat; // Boats position + private Double lon; // - + private Double legDistance; private Color color; - private int markLastPast; - private double heading; + private Leg currentLeg; + private Double heading; private String shortName; + private Polygon boatObject = new Polygon(); + public Boat(String teamName) { this.teamName = teamName; - this.velocity = 10; // Default velocity + this.velocity = 10d; // Default velocity this.lat = 0.0; this.lon = 0.0; - this.distanceToNextMark = 0.0; + this.legDistance = 0.0; this.shortName = ""; } @@ -36,9 +44,12 @@ public class Boat { public Boat(String teamName, double boatVelocity, String shortName) { this.teamName = teamName; this.velocity = boatVelocity; - this.distanceToNextMark = 0.0; + this.legDistance = 0.0; this.color = Colors.getColor(); this.shortName = shortName; + this.boatObject.getPoints().addAll(BOAT_WIDTH /2,0.0, + BOAT_WIDTH, BOAT_HEIGHT, + 0.0, BOAT_HEIGHT); } /** @@ -88,8 +99,12 @@ public class Boat { this.lon = lon; } - public void setDistanceToNextMark(double distance){ - this.distanceToNextMark = distance; + public Double getLegDistance() { + return legDistance; + } + + public void setLegDistance(double legDistance){ + this.legDistance = legDistance; } public double getLatitude(){ @@ -108,12 +123,12 @@ public class Boat { return Math.round((this.velocity * 1.94384) * 100d) / 100d; } - public void setMarkLastPast(int markLastPast) { - this.markLastPast = markLastPast; + public Leg getCurrentLeg() { + return currentLeg; } - public int getMarkLastPast() { - return markLastPast; + public void setCurrentLeg(Leg currentLeg) { + this.currentLeg = currentLeg; } public void setHeading(double heading){ @@ -127,4 +142,33 @@ public class Boat { public String getShortName(){ return this.shortName; } + + + /** + * Moves the boat and its children annotations from its current coordinates by specified amounts. + * @param x The amount to move the X coordinate by + * @param y The amount to move the Y coordinate by + */ + void moveBoatBy(Double x, Double y) { + boatObject.setLayoutX(boatObject.getLayoutX() + x); + boatObject.setLayoutY(boatObject.getLayoutY() + y); + boatObject.relocate(boatObject.getLayoutX(), boatObject.getLayoutY()); + + } + + /** + * Moves the boat and its children annotations to coordinates specified + * @param x The X coordinate to move the boat to + * @param y The Y coordinate to move the boat to + */ + public void moveBoatTo(int x, int y) { + boatObject.setLayoutX(x); + boatObject.setLayoutY(y); + boatObject.relocate(boatObject.getLayoutX(), boatObject.getLayoutY()); + + } + + public Polygon getBoatObject() { + return boatObject; + } } \ No newline at end of file diff --git a/src/main/java/seng302/models/Course.java b/src/main/java/seng302/models/Course.java new file mode 100644 index 00000000..d6647a02 --- /dev/null +++ b/src/main/java/seng302/models/Course.java @@ -0,0 +1,54 @@ +package seng302.models; + +/** + * Created by wmu16 on 4/8/17. + */ +import javafx.scene.canvas.Canvas; +import javafx.util.Pair; +import seng302.models.mark.Mark; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +/** + * Class for describing the course information for the canvas + * Created by wmu16 on 22/03/17. + */ +public class Course { + + private ArrayList Legs; + private ArrayList marks; + public static final Integer SCALE = 160000; + + + public Course(ArrayList marks) { + this.marks = marks; + this.Legs = makeLegs(); + } + + /** + * Makes the race legs out of all the marker marks for the course + * @return ArrayList of Legs + */ + private ArrayList makeLegs() { + ArrayList Legs = new ArrayList<>(); + for (int i = 0; i < marks.size()-1; i++) { + Legs.add(new Leg(marks.get(i), marks.get(i+1))); + } + return Legs; + } + + + public ArrayList getMarks() { + return marks; + } + + public double getDistanceScaleFactor() { + return SCALE; + } + + public ArrayList getLegs() { + return Legs; + } +} \ No newline at end of file diff --git a/src/main/java/seng302/models/Event.java b/src/main/java/seng302/models/Event.java deleted file mode 100644 index e803845d..00000000 --- a/src/main/java/seng302/models/Event.java +++ /dev/null @@ -1,148 +0,0 @@ -package seng302.models; - -import seng302.models.mark.Mark; - -import java.text.SimpleDateFormat; -import java.util.Date; - -/** -* Event class containing the time of specific event, related team/boat, and -* event location such as leg. -*/ -public class Event { - private Double time; // Time the event occurs - private Boat boat; - private boolean isFinishingEvent = false; // This event occurs when a boat finishes the race - private Mark mark1; // This mark - private Mark mark2; // Next mark - private int markPosInRace; // the position of the current mark in the race course - - private final double ORIGIN_LAT = 32.320504; - private final double ORIGIN_LON = -64.857063; - private final double SCALE = 16000; - - - - /** - * Event class containing the time of specific event, related team/boat, and - * event location such as leg. - * - * @param eventTime, what time the event happens - * @param eventBoat, the boat that the event belongs to - */ - public Event(Double eventTime, Boat eventBoat, Mark mark1, Mark mark2, int markPosInRace) { - this.time = eventTime; - this.boat = eventBoat; - this.mark1 = mark1; - this.mark2 = mark2; - this.markPosInRace = markPosInRace; - } - - /** - * Event class containing the time of specific event, related team/boat, and - * event location such as leg. - * - * @param eventTime, what time the event happens - * @param eventBoat, the boat that the event belongs to - */ - public Event(Double eventTime, Boat eventBoat, Mark mark1, int markPosInRace) { - this.time = eventTime; - this.boat = eventBoat; - this.mark1 = mark1; - this.markPosInRace = markPosInRace; - this.isFinishingEvent = true; - } - - public double getTime() { - return this.time; - } - - public void setTime(double eventTime) { - this.time = eventTime; - } - - /** - * Gets the time in a formatted string - * - * @return the string of time - */ - public String getTimeString() { - return (new SimpleDateFormat("mm:ss:SSS")).format(new Date(time.longValue())); - } - - public Boat getBoat() { - return this.boat; - } - - public void setBoat(Boat eventBoat) { - this.boat = eventBoat; - } - - public boolean getIsFinishingEvent() { - return this.isFinishingEvent; - } - - /** - * Get a string that contains the timestamp and course information for this event - * - * @return A string that details what happened in this event - */ - public String getEventString() { - // This event is a boat finishing the race - if (this.isFinishingEvent) { - return (this.getTimeString() + ", " + this.getBoat().getTeamName() + " finished the race"); - } - System.out.println(this.getDistanceBetweenMarks()); - return (this.getTimeString() + ", " + this.getBoat().getTeamName() + " passed " + this.mark1.getName() + " going heading " + this.getBoatHeading() + "°"); - } - - /** - * @return the distance between the two marks - */ - public double getDistanceBetweenMarks() { - double earth_radius = 6378.137; - double dLat = this.mark2.getLatitude() * Math.PI / 180 - this.mark1.getLatitude() * Math.PI / 180; - double dLon = this.mark2.getLongitude() * Math.PI / 180 - this.mark1.getLongitude() * Math.PI / 180; - - double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(this.mark1.getLatitude() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2); - - double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); - double d = earth_radius * c; - - return d * 1000; - } - - /** - * Calculates current boat heading direction. - * @return the boats heading as degree. vertical upward is 0 degree, and degree goes up clockwise. - */ - public double getBoatHeading() { - if (mark2 == null){ - return 0.0; - } - - double x1 = (mark1.getLongitude() - ORIGIN_LON) * SCALE; - double y1 = (ORIGIN_LAT - mark1.getLatitude()) * SCALE; - double x2 = (mark2.getLongitude() - ORIGIN_LON) * SCALE; - double y2 = (ORIGIN_LAT - mark2.getLatitude()) * SCALE; - - double headingRadians = Math.atan2(y2-y1, x2-x1); - - if (headingRadians < 0){ - headingRadians += 2 * Math.PI; - } - - // Convert back to degrees, and flip 180 degrees -// return ((headingRadians) * 180) / Math.PI; - return (Math.toDegrees(headingRadians) + 90) % 360; - - } - - public Mark getThisMark() { - return this.mark1; - } - - public int getMarkPosInRace() { - return markPosInRace; - } -} \ No newline at end of file diff --git a/src/main/java/seng302/models/Leg.java b/src/main/java/seng302/models/Leg.java index 8f21a6ea..7e03e195 100644 --- a/src/main/java/seng302/models/Leg.java +++ b/src/main/java/seng302/models/Leg.java @@ -1,116 +1,97 @@ package seng302.models; -import seng302.models.mark.SingleMark; + +import seng302.models.mark.Mark; /** -* Represents the leg of a race. -*/ + * Class for defining the leg of a race between two markers + * Created by cir27 on 3/03/17. + */ public class Leg { - private int heading; - private int distance; - private boolean isFinishingLeg; - private SingleMark startingSingleMark; + + private final double ORIGIN_LAT = 32.320504; + private final double ORIGIN_LON = -64.857063; + private final double SCALE = 16000; + + private Double distance; + private Double heading; + private Mark end; + private Mark start; + + Leg(Mark start, Mark end) { + this.distance = calculateMarkerDistance(start, end); + this.heading = angleFromCoordinate(start, end); + this.start = start; + this.end = end; + } /** - * Create a new leg + * Calculates the euclidian distance between two markers on the canvas using xy coordinates * - * @param heading, the magnetic heading of this leg - * @param distance, the total distance of this leg in meters - * @param singleMark, the singleMark this leg starts on + * @param geoPointOne first geographical point + * @param geoPointTwo second geographical point + * @return the distance between two points in meters */ - public Leg(int heading, int distance, SingleMark singleMark) { - this.heading = heading; - this.distance = distance; - this.startingSingleMark = singleMark; - this.isFinishingLeg = false; + private Double calculateMarkerDistance(Mark geoPointOne, Mark geoPointTwo) { + + double earth_radius = 6378.137; + double dLat = geoPointTwo.getLatitude() * Math.PI / 180 - geoPointOne.getLatitude() * Math.PI / 180; + double dLon = geoPointTwo.getLongitude() * Math.PI / 180 - geoPointOne.getLongitude() * Math.PI / 180; + + double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(geoPointOne.getLatitude() * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2); + + double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + double d = earth_radius * c; + + return d * 1000; } /** - * Create a new leg + * Calculates the angle between to angular co-ordinates on a sphere. * - * @param heading, the magnetic heading of this leg - * @param distance, the total distance of this leg in meters - * @param markerName, the name of the marker this leg starts on + * @param geoPointOne first geographical location + * @param geoPointTwo second geographical location + * @return the angle from point one to point two */ - public Leg(int heading, int distance, String markerName) { - this.heading = heading; - this.distance = distance; - this.startingSingleMark = new SingleMark(markerName); - this.isFinishingLeg = false; + private Double angleFromCoordinate(Mark geoPointOne, Mark geoPointTwo) { + + if (geoPointTwo == null){ + return 0.0; + } + + double x1 = (geoPointOne.getLongitude() - ORIGIN_LON) * SCALE; + double y1 = (ORIGIN_LAT - geoPointOne.getLatitude()) * SCALE; + double x2 = (geoPointTwo.getLongitude() - ORIGIN_LON) * SCALE; + double y2 = (ORIGIN_LAT - geoPointTwo.getLatitude()) * SCALE; + + double headingRadians = Math.atan2(y2-y1, x2-x1); + + if (headingRadians < 0){ + headingRadians += 2 * Math.PI; + } + + // Convert back to degrees, and flip 180 degrees +// return ((headingRadians) * 180) / Math.PI; + return (Math.toDegrees(headingRadians) + 90) % 360; + } - /** - * Get the heading of this leg - * @return int - */ - public int getHeading() { - return this.heading; - } - - /** - * Set the heading for this leg - * @param heading - */ - public void setHeading(int heading) { - this.heading = heading; - } - - /** - * Get the total distance of this leg in meters - * @return int - */ - public int getDistance() { + Double getDistance() + { return this.distance; } - /** - * Set the distance of this leg in meters - * @param distance - */ - public void setDistance(int distance) { - this.distance = distance; + Mark getEnd() + { + return this.end; } - /** - * Returns the marker this leg started on - * @return SingleMark - */ - public SingleMark getMarker() { - return this.startingSingleMark; + public Mark getStart() { + return start; } - /** - * Set the singleMark this leg starts on - * @param singleMark - */ - public void setMarker(SingleMark singleMark) { - this.startingSingleMark = singleMark; + public Double getHeading() + { + return this.heading; } - - /** - * Returns the name of the marker this leg started on - * @return String - */ - public String getMarkerLabel() { - return this.startingSingleMark.getName(); - } - - - - /** - * Specify whether or not the race finishes on this leg - * - * @param isFinishingLeg whether or not the race finishes on this leg - */ - public void setFinishingLeg(boolean isFinishingLeg) { - this.isFinishingLeg = isFinishingLeg; - } - - /** - * Returns whether or not the race finishes after this leg - * @return true if this the race finishes after this leg - */ - public boolean getIsFinishingLeg() { - return this.isFinishingLeg; - } -} \ No newline at end of file +} diff --git a/src/main/java/seng302/models/Race.java b/src/main/java/seng302/models/Race.java index 165d9468..a396b508 100644 --- a/src/main/java/seng302/models/Race.java +++ b/src/main/java/seng302/models/Race.java @@ -1,5 +1,7 @@ package seng302.models; +import javafx.animation.AnimationTimer; +import seng302.controllers.Controller; import seng302.models.mark.Mark; import java.util.*; @@ -8,47 +10,137 @@ import java.util.*; * Race class containing the boats and legs in the race * Created by mra106 on 8/3/2017. */ -public class Race { +public class Race extends Thread { + + private static final double UPDATE_TIME = 0.016666; // 1 / 60 ie 60fps + + private ArrayList boats; // The boats in the race private ArrayList finishingOrder; // The order in which the boats finish the race - private HashMap events = new HashMap<>(); // The events that occur in the race - private List course; // Marks in the race - private long startTime = 0; - private double timeScale = 1; + private List markers; // Marks in the race + private List raceLegs; private boolean raceFinished = false; // Race is finished private int raceTime = -2; // Current time in the race + private Double timeScale = null; + private boolean raceStarted = false; + private Controller controller; /** * Race class containing the boats and legs in the race */ - public Race() { - this.boats = new ArrayList<>(); + public Race(List markers, ArrayList boats, Double timescale, Controller controller) { + this.boats = boats; + this.markers = markers; + this.raceLegs = makeRaceLegs(); + this.controller = controller; + + this.timeScale = timescale; this.finishingOrder = new ArrayList<>(); - this.course = new ArrayList<>(); + } + + + /** + * Makes the race legs out of all the marker points for the course + * @return ArrayList of raceLegs + */ + private ArrayList makeRaceLegs() { + ArrayList raceLegs = new ArrayList<>(); + for (int i=0; i < markers.size()-1; i++) { + raceLegs.add(new Leg(markers.get(i), markers.get(i+1))); + } + return raceLegs; + } + + + /** + * A timer that is called every frame to call the action of moving the boats + */ + private AnimationTimer at = new AnimationTimer() { + @Override + public void handle(long now) { + + //Updating Boat positions + if(finishingOrder.size() != boats.size()) { + // update the time + boats.stream().filter(boat -> !finishingOrder.contains(boat)).forEach(boat -> { + updateBoatPosition(boat); + }); + } else { + at.stop(); + } + } + + }; + + + /** + * Begins the race simulation + */ + @Override + public void run() { + if (!raceStarted) { +// controller.getPlayPauseButton().setDisable(true); + at.start(); + } + } + + + /** + * Moves the coordinates of the boats. + * @param boat The boat to update the position of + */ + private void updateBoatPosition(Boat boat) { + Double thisHeading = boat.getHeading(); + // TODO: 4/8/17 wmu16 - Add a distance scale factor from lat long distance in Metres to xy equivalent + Double hypMove = boat.getVelocity() * UPDATE_TIME * timeScale; //* distanceScaleFactor + boat.setLegDistance(boat.getLegDistance() + hypMove); + moveBoat(boat, thisHeading, hypMove); } /** - * Add a boat to the race - * - * @param boat, the boat to add + * Moves a boat along coordinates by breaking down the distance moved along the hypotenuse into x and y components + * @param boat The Boat to move + * @param heading The heading the boat is moving at + * @param hypMove The distance moved along the hypotenuse (absolute distance) */ - public void addBoat(Boat boat) { - boats.add(boat); + private void moveBoat(Boat boat, Double heading, Double hypMove) { + //If the boat has not yet passed the marker at the end of the leg increase its (x,y) as per normal + // TODO: 4/8/17 wmu16 - Initialising boat positions and legs and headings etc. + if(boat.getLegDistance() <= boat.getCurrentLeg().getDistance()) { + Double xMove = hypMove * Math.sin(Math.toRadians(heading)); + Double yMove = - hypMove * Math.cos(Math.toRadians(heading)); + boat.moveBoatBy(xMove, yMove); + + //If the boat has finished... + } else if (getNextRaceLeg(boat.getCurrentLeg()).equals(boat.getCurrentLeg())) { + finishingOrder.add(boat); + //Otherwise apply the overflow distance of the leg to the next leg + } else { + Double overflowDistance = boat.getLegDistance() - boat.getCurrentLeg().getDistance(); + boat.setCurrentLeg(getNextRaceLeg(boat.getCurrentLeg())); + boat.setHeading(boat.getCurrentLeg().getHeading()); + boat.setLegDistance(overflowDistance); + moveBoat(boat, boat.getHeading(), overflowDistance); + } + } /** - * Returns a list of boats in a random order - * - * @return a list of boats + * Returns the next leg in the race + * @param currentRaceLeg The leg that you are currently on + * @return The next race leg or the same race leg if it has reached the end */ - public Boat[] getShuffledBoats() { - // Shuffle the list of boats - long seed = System.nanoTime(); - Collections.shuffle(this.boats, new Random(seed)); - - return boats.toArray(new Boat[boats.size()]); + private Leg getNextRaceLeg(Leg currentRaceLeg) { + Leg nextRaceLeg = currentRaceLeg; + for(int i = 0; i< raceLegs.size() - 1; i++) { + if (raceLegs.get(i).equals(currentRaceLeg)) { + nextRaceLeg = raceLegs.get(i + 1); + } + } + return nextRaceLeg; } + /** * Returns a list of boats in the order that they * finished the race (position 0 is first place) @@ -69,85 +161,28 @@ public class Race { return boats.toArray(new Boat[boats.size()]); } - /** - * Sets time scale - * - * @param timeScale - */ - public void setTimeScale(double timeScale) { - this.timeScale = timeScale; - } - - /** - * Generate all events that will happen during the race. - */ - private void generateEvents() { - - for (Boat boat : this.boats) { - double totalDistance = 0; - int numberOfMarks = this.course.size(); - - for (int i = 0; i < numberOfMarks; i++) { - Double time = (totalDistance / boat.getVelocity() / timeScale); - - // If there are singleMarks after this event - if (i < numberOfMarks - 1) { - Event event = new Event(time, boat, course.get(i), course.get(i + 1), i); - - try { - events.get(boat).add(event); - - } catch (NullPointerException e) { - events.put(boat, new ArrayList<>(Arrays.asList(event))); - } - totalDistance += event.getDistanceBetweenMarks(); - System.out.println(totalDistance); - System.out.println(boat.getVelocity()); - } - - // There are no more marks after this event - - else{ - Event event = new Event(time, boat, course.get(i), i); - events.get(boat).add(event); - } - } - } - } - - /** * Starts a race and generates all events for the race. */ public void startRace() { // record start time. - this.startTime = System.currentTimeMillis(); - generateEvents(); + + + + } + + public void pause() { + at.stop(); } /** - * Set the race course - * @param course a list of marks in the course - */ - public void addCourse(List course) { - this.course = course; - } - - /** - * Get a list of marks in the course + * Get a list of marks in the markers * @return */ - public List getCourse() { - return course; + public List getMarkers() { + return markers; } - /** - * Get a map of the events in the race - * @return - */ - public HashMap getEvents() { - return events; - } /** * Set a boat as finished @@ -191,7 +226,11 @@ public class Race { /** * Increment the race time by one second */ - public void incrementRaceTime(){ + public void incrementRaceTime() { this.raceTime += this.timeScale; } + + public List getRaceLegs() { + return raceLegs; + } } \ No newline at end of file diff --git a/src/main/java/seng302/models/TimelineInfo.java b/src/main/java/seng302/models/TimelineInfo.java deleted file mode 100644 index 867ce67b..00000000 --- a/src/main/java/seng302/models/TimelineInfo.java +++ /dev/null @@ -1,31 +0,0 @@ -package seng302.models; - -import javafx.animation.Timeline; -import javafx.beans.property.DoubleProperty; - - -/** - * Created by zyt10 on 17/03/17. - * this class is literally just to associate a timeline with a DoubleProperty x and y - */ -public class TimelineInfo { - private Timeline timeline; - private DoubleProperty x; - private DoubleProperty y; - - public TimelineInfo(Timeline timeline, DoubleProperty x, DoubleProperty y) { - this.timeline = timeline; - this.x = x; - this.y = y; - } - - public Timeline getTimeline() { - return timeline; - } - public DoubleProperty getX() { - return x; - } - public DoubleProperty getY() { - return y; - } -} diff --git a/src/main/resources/config/course.xml b/src/main/resources/config/course.xml index f8bfa00e..2886ff77 100644 --- a/src/main/resources/config/course.xml +++ b/src/main/resources/config/course.xml @@ -1,6 +1,6 @@ - + Start @@ -68,4 +68,4 @@ Leeward Gate Finish - + diff --git a/src/main/resources/views/CanvasView.fxml b/src/main/resources/views/CanvasView.fxml deleted file mode 100644 index bc16ad7e..00000000 --- a/src/main/resources/views/CanvasView.fxml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/src/main/resources/views/FinishView.fxml b/src/main/resources/views/FinishView.fxml deleted file mode 100644 index debdea26..00000000 --- a/src/main/resources/views/FinishView.fxml +++ /dev/null @@ -1,55 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/resources/views/MainView.fxml b/src/main/resources/views/MainView.fxml index ac0b944e..a89478b6 100644 --- a/src/main/resources/views/MainView.fxml +++ b/src/main/resources/views/MainView.fxml @@ -1,11 +1,47 @@ - + + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/views/RaceView.fxml b/src/main/resources/views/RaceView.fxml deleted file mode 100644 index f7fcbfeb..00000000 --- a/src/main/resources/views/RaceView.fxml +++ /dev/null @@ -1,59 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/test/java/seng302/BoatTest.java b/src/test/java/seng302/BoatTest.java deleted file mode 100644 index 0160bb8d..00000000 --- a/src/test/java/seng302/BoatTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package seng302; - -import org.junit.Test; -import seng302.models.Boat; - -import static org.junit.Assert.assertEquals; - -/** - * Unit test for the Team class. - */ -public class BoatTest { - - @Test - public void testBoatCreation() { - Boat boat1 = new Boat("Team 1"); - assertEquals(boat1.getTeamName(), "Team 1"); - assertEquals(boat1.getVelocity(), (double) 10.0, 1e-15); - } - - @Test - public void testChangeTeamName() { - Boat boat1 = new Boat("Team 1"); - boat1.setTeamName("Team 2"); - assertEquals(boat1.getTeamName(), "Team 2"); - } - - @Test - public void testSetVelocity() { - Boat boat1 = new Boat("Team 1", 29.0, ""); - assertEquals(boat1.getVelocity(), (double) 29.0, 1e-15); - - boat1.setVelocity(12.0); - assertEquals(boat1.getVelocity(), (double)12.0, 1e-15); - } -} diff --git a/src/test/java/seng302/ColorsTest.java b/src/test/java/seng302/ColorsTest.java deleted file mode 100644 index a6681b26..00000000 --- a/src/test/java/seng302/ColorsTest.java +++ /dev/null @@ -1,45 +0,0 @@ -package seng302; - -import javafx.scene.paint.Color; -import org.junit.Test; -import seng302.models.Boat; -import seng302.models.Colors; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertEquals; - -/** - * Created by ryan_ on 16/03/2017. - */ -public class ColorsTest { - //@Test - public void testNextColor() { - List boats = new ArrayList<>(); - boats.add(new Boat("Team 1")); - boats.add(new Boat("Team 2")); - boats.add(new Boat("Team 3")); - boats.add(new Boat("Team 4")); - boats.add(new Boat("Team 5")); - boats.add(new Boat("Team 6")); - - int count = 0; - List enumColors = new ArrayList<>(); - while (count < 6) { - Color color = Colors.getColor(); - enumColors.add(color); - count++; - } - - List boatColors = new ArrayList<>(); - for (Boat boat : boats) { - Color color = boat.getColor(); - boatColors.add(color); - } - - assertEquals(enumColors, boatColors); - } -} diff --git a/src/test/java/seng302/EventTest.java b/src/test/java/seng302/EventTest.java deleted file mode 100644 index 0be0fc98..00000000 --- a/src/test/java/seng302/EventTest.java +++ /dev/null @@ -1,38 +0,0 @@ -package seng302; - -import org.junit.Test; -import seng302.models.Boat; -import seng302.models.Event; -import seng302.models.mark.SingleMark; - -import static org.junit.Assert.assertEquals; - -/** - * Test for Event class - * Created by Haoming on 7/03/17. - */ -public class EventTest { - - @Test - public void getTimeString() throws Exception { - Boat boat = new Boat("testBoat"); - Event event = new Event(1231242.2, boat, new SingleMark("mark1"), new SingleMark("mark2"), 0); - assertEquals("20:31:242", event.getTimeString()); - } - - @Test - public void testBoatHeading() throws Exception { - Boat boat = new Boat("testBoat"); - Event event = new Event(1231242.2, boat, new SingleMark("mark1", 142.5, 122.1), new SingleMark("mark2", 121.9,99.2), 0); - - assertEquals(event.getBoatHeading(), 228.0266137055349, 1e-15); - } - - @Test - public void testDistanceBetweenMarks() throws Exception { - Boat boat = new Boat("testBoat"); - Event event = new Event(1231242.2, boat, new SingleMark("mark1", 142.5, 122.1), new SingleMark("mark2", 121.9,99.2), 0); - - assertEquals(event.getDistanceBetweenMarks(), 339059.653830461, 1e-15); - } -} \ No newline at end of file diff --git a/src/test/java/seng302/LegTest.java b/src/test/java/seng302/LegTest.java deleted file mode 100644 index 9bb64b6c..00000000 --- a/src/test/java/seng302/LegTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package seng302; - -import org.junit.Test; -import seng302.models.Leg; -import seng302.models.mark.SingleMark; - -import static org.junit.Assert.assertEquals; - -/** - * Unit test for the Leg class. - */ -public class LegTest { - - /** - * Test creation of the leg by specifying a string - * for the marker label - */ - @Test - public void testLegCreationUsingMarkerLabel() { - Leg leg = new Leg(010, 100, "SingleMark"); - - assertEquals(leg.getHeading(), 010); - assertEquals(leg.getDistance(), 100); - assertEquals(leg.getMarkerLabel(), "SingleMark"); - assertEquals(leg.getIsFinishingLeg(), false); - } - - /** - * Test creation of the leg by providing a - * SingleMark object - */ - @Test - public void testLegCreation() { - Leg leg = new Leg(010, 100, new SingleMark("SingleMark")); - - assertEquals(leg.getHeading(), 010); - assertEquals(leg.getDistance(), 100); - assertEquals(leg.getMarkerLabel(), "SingleMark"); - assertEquals(leg.getIsFinishingLeg(), false); - } - - /** - * Test changing whether or not a - * leg is the finishing leg - */ - @Test - public void testSetFinishLeg() { - Leg leg = new Leg(010, 100, "SingleMark"); - - leg.setFinishingLeg(true); - assertEquals(leg.getIsFinishingLeg(), true); - } - -} diff --git a/src/test/java/seng302/RaceTest.java b/src/test/java/seng302/RaceTest.java deleted file mode 100644 index ab318331..00000000 --- a/src/test/java/seng302/RaceTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package seng302; - -import org.junit.Test; -import seng302.models.Boat; -import seng302.models.Race; - -import java.lang.reflect.Array; - -import static org.junit.Assert.assertEquals; - -/** - * Unit test for the Race class. - */ -public class RaceTest { - /** - * Test that all boats were added to the race - */ - @Test - public void testAddingBoatsToRace() { - Boat boat1 = new Boat("Team 1"); - Boat boat2 = new Boat("Team 2"); - - Race race = new Race(); - race.addBoat(boat1); - race.addBoat(boat2); - - assertEquals(Array.getLength(race.getBoats()), 2); - } - - @Test - public void testGetShuffledBoats(){ - Boat boat1 = new Boat("Team 1"); - Boat boat2 = new Boat("Team 2"); - - Race race = new Race(); - race.addBoat(boat1); - race.addBoat(boat2); - - assertEquals(Array.getLength(race.getShuffledBoats()), 2); - } -} diff --git a/src/test/java/seng302/TestRaceTimer.java b/src/test/java/seng302/TestRaceTimer.java deleted file mode 100644 index 542405b1..00000000 --- a/src/test/java/seng302/TestRaceTimer.java +++ /dev/null @@ -1,25 +0,0 @@ -package seng302; - -import org.junit.Test; -import seng302.controllers.RaceViewController; - -import static org.junit.Assert.assertTrue; - - -public class TestRaceTimer { - @Test - public void testPositiveTimeString(){ - RaceViewController controller = new RaceViewController(); - String result = controller.convertTimeToMinutesSeconds(61); - - assertTrue(result.equals("01:01")); - } - - @Test - public void testNegativeTimeString(){ - RaceViewController controller = new RaceViewController(); - String result = controller.convertTimeToMinutesSeconds(-61); - - assertTrue(result.equals("-01:01")); - } -} diff --git a/src/test/java/seng302/models/mark/MarkTest.java b/src/test/java/seng302/models/mark/MarkTest.java deleted file mode 100644 index f1943c64..00000000 --- a/src/test/java/seng302/models/mark/MarkTest.java +++ /dev/null @@ -1,44 +0,0 @@ -package seng302.models.mark; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by Haoming on 17/3/17. - */ -public class MarkTest { - - private SingleMark singleMark1; - private SingleMark singleMark2; - private GateMark gateMark; - - @Before - public void setUp() throws Exception { - this.singleMark1 = new SingleMark("testMark_SM1", 12.23234, -34.342); - this.singleMark2 = new SingleMark("testMark_SM2", 12.23239, -34.352); - this.gateMark = new GateMark("testMark_GM", singleMark1, singleMark2, singleMark1.getLatitude(), singleMark2.getLongitude()); - } - - @Test - public void getName() throws Exception { - assertEquals("testMark_SM1", this.singleMark1.getName()); - assertEquals("testMark_GM", this.gateMark.getName()); - } - - @Test - public void getMarkType() throws Exception { - assertTrue(this.singleMark2.getMarkType() == MarkType.SINGLE_MARK); - assertTrue(this.gateMark.getMarkType() == MarkType.GATE_MARK); - } - - @Test - public void getMarkContent() throws Exception { - assertEquals(12.23234, this.singleMark1.getLatitude(), 1e-10); - assertEquals(-34.342, this.singleMark1.getLongitude(), 1e-10); - assertEquals("testMark_SM1", this.gateMark.getSingleMark1().getName()); - assertEquals(-34.352, this.gateMark.getSingleMark2().getLongitude(), 1e-10); - } - -} \ No newline at end of file diff --git a/src/test/java/seng302/models/parsers/ConfigParserTest.java b/src/test/java/seng302/models/parsers/ConfigParserTest.java deleted file mode 100644 index 8a0c0c8c..00000000 --- a/src/test/java/seng302/models/parsers/ConfigParserTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package seng302.models.parsers; - -import org.junit.Before; -import org.junit.Test; - -import static org.junit.Assert.*; - -/** - * Created by Haoming on 23/03/17. - */ -public class ConfigParserTest { - - private ConfigParser cp; - - @Before - public void initializeParser() throws Exception { - cp = new ConfigParser("/config/config.xml"); - } - - @Test - public void getWindDirection() throws Exception { - assertEquals(135, cp.getWindDirection(), 1e-10); - } - - @Test - public void getTimeScale() throws Exception { - assertEquals(10.0, cp.getTimeScale(), 1e-10); - } - - @Test - public void getDoubleByTagName() throws Exception { - assertEquals(6, cp.getDoubleByTagName("race-size", 0), 1e-10); - assertEquals(100, cp.getDoubleByTagName("noTag", 100), 1e-10); - } - - @Test - public void getStringByTagName() throws Exception { - assertEquals("AC35", cp.getStringByTagName("race-name", "11")); - assertEquals("oops", cp.getStringByTagName("noTag", "oops")); - } - -} \ No newline at end of file diff --git a/src/test/java/seng302/models/parsers/CourseParserTest.java b/src/test/java/seng302/models/parsers/CourseParserTest.java deleted file mode 100644 index 865caec6..00000000 --- a/src/test/java/seng302/models/parsers/CourseParserTest.java +++ /dev/null @@ -1,60 +0,0 @@ -package seng302.models.parsers; - -import org.junit.Before; -import org.junit.Test; -import seng302.models.mark.*; - -import java.util.ArrayList; - -import static org.junit.Assert.*; - -/** - * To test if course parser works as expected. - * Created by Haoming on 17/03/17. - */ -public class CourseParserTest { - - private CourseParser cp; - - @Before - public void initializeParser() throws Exception { - cp = new CourseParser("/config/course.xml"); - } - - @Test - public void getGates() throws Exception { - ArrayList course = cp.getCourse(); - - assertTrue(MarkType.GATE_MARK == course.get(0).getMarkType()); - - GateMark gateMark1 = (GateMark) course.get(0); - assertEquals(32.293771, gateMark1.getSingleMark2().getLatitude(), 0.00000001); - assertEquals(-64.855242, gateMark1.getSingleMark2().getLongitude(), 0.00000001); - - GateMark gateMark2 = (GateMark) course.get(5); - - assertEquals("Finish1", gateMark2.getSingleMark1().getName()); - assertEquals("Finish2", gateMark2.getSingleMark2().getName()); - assertEquals(32.317257, gateMark2.getSingleMark2().getLatitude(), 0.00000001); - assertEquals(-64.83626, gateMark2.getSingleMark2().getLongitude(), 0.00000001); - } - - @Test - public void getMarks() throws Exception { - ArrayList course = cp.getCourse(); - assertEquals("Mid Mark", course.get(1).getName()); - } - - @Test - public void getOrder() { - ArrayList course = cp.getCourse(); - assertEquals(6, course.size()); - assertEquals("Start", course.get(0).getName()); - assertEquals("Mid Mark", course.get(1).getName()); - assertEquals("Leeward Gate", course.get(2).getName()); - assertEquals("Windward Gate", course.get(3).getName()); - assertEquals("Leeward Gate", course.get(4).getName()); - assertEquals("Finish", course.get(5).getName()); - } - -} \ No newline at end of file diff --git a/src/test/java/seng302/models/parsers/TeamsParserTest.java b/src/test/java/seng302/models/parsers/TeamsParserTest.java deleted file mode 100644 index 3c31b519..00000000 --- a/src/test/java/seng302/models/parsers/TeamsParserTest.java +++ /dev/null @@ -1,35 +0,0 @@ -package seng302.models.parsers; - -import org.junit.Before; -import org.junit.Test; -import seng302.models.Boat; - -import java.util.ArrayList; - -import static org.junit.Assert.*; - -/** - * Created by Haoming on 18/03/17. - */ -public class TeamsParserTest { - - private TeamsParser tp; - @Before - public void readFile() { - tp = new TeamsParser("/config/teams.xml"); - } - - @Test - public void getBoats() throws Exception { - ArrayList boats = tp.getBoats(); - - assertEquals(6, boats.size(), 1e-10); - - assertEquals("Oracle Team USA", boats.get(0).getTeamName()); - //assertEquals(30.9, boats.get(0).getVelocity(), 1e-10); - - assertEquals("Groupama Team France", boats.get(5).getTeamName()); - //assertEquals(45.6, boats.get(5).getVelocity(), 1e-10); - } - -} \ No newline at end of file