diff --git a/doc/examples/config.json b/doc/examples/config.json deleted file mode 100644 index 856bac25..00000000 --- a/doc/examples/config.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "race-name": "AC35", - "time-scale": 1.0, - "race-size": 6, - "teams": [ - { - "team-name": "Oracle Team USA", - "velocity": 60.0 - }, - { - "team-name": "Artemis Racing", - "velocity": 10.0 - }, - { - "team-name": "Emirates Team New Zealand", - "velocity": 90.0 - }, - { - "team-name": "Groupama Team France", - "velocity": 15.0 - }, - { - "team-name": "Land Rover BAR", - "velocity": 70.0 - }, - { - "team-name": "SoftBank Team Japan", - "velocity": 45.0 - } - ] -} \ No newline at end of file diff --git a/doc/examples/teams.xml b/doc/examples/teams.xml index 21908ccf..ed8cfcf1 100644 --- a/doc/examples/teams.xml +++ b/doc/examples/teams.xml @@ -4,31 +4,31 @@ Oracle Team USA USA - 10.0 + 30.9 Artemis Racing ART - 10.0 + 59.3 Emirates Team New Zealand NZL - 10.0 + 51.5 Land Rover BAR BAR - 10.0 + 29.9 SoftBank Team Japan JAP - 10.0 + 99.6 Groupama Team France FRC - 10 + 45.6 \ No newline at end of file diff --git a/src/main/java/seng302/App.java b/src/main/java/seng302/App.java index b2dd4250..b88f607b 100644 --- a/src/main/java/seng302/App.java +++ b/src/main/java/seng302/App.java @@ -14,9 +14,6 @@ public class App extends Application primaryStage.setTitle("RaceVision"); primaryStage.setScene(new Scene(root)); -// seng302.models.OldApp.main(); // Run this to show how positions are updated -// seng302.controllers.RaceController.initializeRace(); - primaryStage.show(); } diff --git a/src/main/java/seng302/controllers/BoatPositionController.java b/src/main/java/seng302/controllers/BoatPositionController.java index 4a82e28a..4e95ae81 100644 --- a/src/main/java/seng302/controllers/BoatPositionController.java +++ b/src/main/java/seng302/controllers/BoatPositionController.java @@ -39,7 +39,7 @@ public class BoatPositionController { positionVbox.getChildren().removeAll(); for (Boat boat: boatOrder){ - positionVbox.getChildren().add(new Text(boat.getTeamName() + " " + boat.getVelocity())); + positionVbox.getChildren().add(new Text(boat.getTeamName() + " " + boat.getSpeedInKnots() + " Knots")); } } diff --git a/src/main/java/seng302/controllers/CanvasController.java b/src/main/java/seng302/controllers/CanvasController.java index 16ac28e6..7e1caf3f 100644 --- a/src/main/java/seng302/controllers/CanvasController.java +++ b/src/main/java/seng302/controllers/CanvasController.java @@ -3,10 +3,13 @@ package seng302.controllers; import javafx.animation.*; 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.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; +import javafx.scene.control.CheckBox; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.Pane; import javafx.scene.paint.Color; @@ -36,6 +39,16 @@ import java.util.List; public class CanvasController { @FXML private Canvas canvas; + @FXML + private AnchorPane contentAnchorPane; + @FXML + private Text windArrowText, windDirectionText; + @FXML + private Pane raceTimer; + @FXML + private BoatPositionController teamPositionsController; + @FXML + private CheckBox toggleAnnotation; private Race race; private GraphicsContext gc; @@ -46,87 +59,11 @@ public class CanvasController { private final double ORIGIN_LAT = 32.320504; private final double ORIGIN_LON = -64.857063; - @FXML - private AnchorPane contentAnchorPane; - - @FXML - private Text windArrowText, windDirectionText; - - @FXML Pane raceTimer; - - @FXML - BoatPositionController teamPositionsController; - private Animation.Status raceStatus = Animation.Status.PAUSED; private final int SCALE = 16000; - /** - * Display the list of boats in the order they finished the race - */ - private void loadRaceResultView() { - FXMLLoader loader = new FXMLLoader(getClass().getResource("/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); - } - } - - /** - * Load the race timer - */ - private void loadTimerView(){ - FXMLLoader loader = new FXMLLoader(getClass().getResource("/raceTimer.fxml")); - loader.setController(new RaceTimerController(race)); - - try{ - raceTimer.getChildren().clear(); - raceTimer.getChildren().removeAll(); - raceTimer.getChildren().addAll((Pane) loader.load()); - } - catch(javafx.fxml.LoadException e){ - System.out.println(e); - } - catch(IOException e){ - System.out.println(e); - } - } - - /** - * Play each boats timeline - */ - private void playTimelines(){ - for (TimelineInfo timelineInfo : timelineInfos.values()){ - Timeline timeline = timelineInfo.getTimeline(); - - if (timeline.getStatus() == Animation.Status.PAUSED){ - timeline.play(); - } - } - raceStatus = Animation.Status.RUNNING; - } - - /** - * Pause each boats timeline - */ - private void pauseTimelines(){ - for (TimelineInfo timelineInfo : timelineInfos.values()){ - Timeline timeline = timelineInfo.getTimeline(); - - if (timeline.getStatus() == Animation.Status.RUNNING){ - timeline.pause(); - } - } - raceStatus = Animation.Status.PAUSED; - } + private boolean annotationCheck = true; /** * Initialize the controller @@ -196,12 +133,86 @@ public class CanvasController { loadRaceResultView(); }); + toggleAnnotation.selectedProperty().addListener(new ChangeListener() { + @Override + public void changed(ObservableValue observable, Boolean oldValue, Boolean newValue) { + annotationCheck = !annotationCheck; + } + }); + //set wind direction!!!!!!! can't find another place to put my code --haoming - double windDirection = new ConfigParser("doc/examples/config.xml").getWindDirection(); + double windDirection = new ConfigParser("/config.xml").getWindDirection(); windDirectionText.setText(String.format("%.1f°", windDirection)); windArrowText.setRotate(windDirection); } + /** + * Display the list of boats in the order they finished the race + */ + private void loadRaceResultView() { + FXMLLoader loader = new FXMLLoader(getClass().getResource("/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); + } + } + + /** + * Load the race timer + */ + private void loadTimerView(){ + FXMLLoader loader = new FXMLLoader(getClass().getResource("/raceTimer.fxml")); + loader.setController(new RaceTimerController(race)); + + try{ + raceTimer.getChildren().clear(); + raceTimer.getChildren().removeAll(); + raceTimer.getChildren().addAll((Pane) loader.load()); + } + catch(javafx.fxml.LoadException e){ + System.out.println(e); + } + catch(IOException e){ + System.out.println(e); + } + } + + /** + * Play each boats timeline + */ + private void playTimelines(){ + for (TimelineInfo timelineInfo : timelineInfos.values()){ + Timeline timeline = timelineInfo.getTimeline(); + + if (timeline.getStatus() == Animation.Status.PAUSED){ + timeline.play(); + } + } + raceStatus = Animation.Status.RUNNING; + } + + /** + * Pause each boats timeline + */ + private void pauseTimelines(){ + for (TimelineInfo timelineInfo : timelineInfos.values()){ + Timeline timeline = timelineInfo.getTimeline(); + + if (timeline.getStatus() == Animation.Status.RUNNING){ + timeline.pause(); + } + } + raceStatus = Animation.Status.PAUSED; + } + /** * Generates time line for each boat, and stores time time into timelineInfos hash map */ @@ -285,6 +296,8 @@ public class CanvasController { * @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 @@ -293,12 +306,15 @@ public class CanvasController { double diameter = 9; - // Set boat text - gc.setFont(new Font(14)); gc.setFill(color); - gc.setLineWidth(3); - gc.setFontSmoothingType(FontSmoothingType.GRAY); - gc.fillText(name + ", " + speed + " knots",x+15,y+15); + + if (annotationCheck) { + // Set boat text + gc.setFont(new Font(14)); + gc.setLineWidth(3); + gc.setFontSmoothingType(FontSmoothingType.GRAY); + gc.fillText(name + ", " + speed + " knots", x + 15, y + 15); + } gc.fillOval(x, y, diameter, diameter); drawWake(gc, x, y, speed, color, heading); diff --git a/src/main/java/seng302/controllers/RaceController.java b/src/main/java/seng302/controllers/RaceController.java index e8471426..a079440d 100644 --- a/src/main/java/seng302/controllers/RaceController.java +++ b/src/main/java/seng302/controllers/RaceController.java @@ -1,15 +1,14 @@ package seng302.controllers; import seng302.models.Boat; -import seng302.models.OldFileParser; import seng302.models.Race; +import seng302.models.parsers.ConfigParser; import seng302.models.parsers.CourseParser; +import seng302.models.parsers.TeamsParser; -import java.io.FileNotFoundException; import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collections; -import java.util.Map; import java.util.Random; /** @@ -21,11 +20,11 @@ public class RaceController { Race race = null; public void initializeRace() { - String raceConfigFile; - raceConfigFile = "doc/examples/config.json"; + String raceConfigFile = "/config.xml"; + String teamsConfigFile = "/teams.xml"; try { - race = createRace(raceConfigFile); + race = createRace(raceConfigFile, teamsConfigFile); } catch (Exception e) { System.out.println("There was an error creating the race."); } @@ -37,36 +36,28 @@ public class RaceController { } } - public Race createRace(String configFile) throws Exception { + public Race createRace(String configFile, String teamsConfigFile) throws Exception { Race race = new Race(); - OldFileParser fp; // Read team names from file - try{ - fp = new OldFileParser(configFile); - } - catch (FileNotFoundException e){ - System.out.println("Config file does not exist"); - return null; - } + TeamsParser tp = new TeamsParser(teamsConfigFile); + + // Read course from file + ConfigParser config = new ConfigParser(configFile); ArrayList boatNames = new ArrayList<>(); - ArrayList> teams = fp.getTeams(); + ArrayList teams = tp.getBoats(); //get race size - int numberOfBoats = (int) fp.getRaceSize(); - int boatsAdded = 0; + int numberOfBoats = teams.size(); //get time scale - double timeScale = fp.getTimeScale(); + double timeScale = config.getTimeScale(); race.setTimeScale(timeScale); - for (Map team : teams) { - if (boatsAdded < numberOfBoats){ - boatNames.add((String) team.get("team-name")); - race.addBoat(new Boat(team.get("team-name").toString(), (Double) (team.get("velocity")))); - } - boatsAdded++; + for (Boat boat : teams) { + boatNames.add(boat.getTeamName()); + race.addBoat(boat); } // Shuffle team names @@ -77,8 +68,8 @@ public class RaceController { return null; } - CourseParser cp = new CourseParser("doc/examples/course.xml"); - race.addCourse(cp.getCourse()); + CourseParser course = new CourseParser("/course.xml"); + race.addCourse(course.getCourse()); return race; } diff --git a/src/main/java/seng302/models/OldApp.java b/src/main/java/seng302/models/OldApp.java deleted file mode 100644 index aed658be..00000000 --- a/src/main/java/seng302/models/OldApp.java +++ /dev/null @@ -1,105 +0,0 @@ -package seng302.models; - -import seng302.models.mark.SingleMark; - -import java.lang.reflect.Array; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Map; -import java.util.Random; -import java.io.FileNotFoundException; - -public class OldApp { - - /** - * Builds a race object for the AC35 course - * - * @return a Race object for the AC35 course - */ - public static Race createRace(String configFile) throws Exception { - Race race = new Race(); - OldFileParser fp; - - // Read team names from file - try{ - fp = new OldFileParser(configFile); - } - catch (FileNotFoundException e){ - System.out.println("Config file does not exist"); - return null; - } - - ArrayList boatNames = new ArrayList<>(); - ArrayList> teams = fp.getTeams(); - - //get race size - int numberOfBoats = (int) fp.getRaceSize(); - - //get time scale - double timeScale = fp.getTimeScale(); - race.setTimeScale(timeScale); - - for (Map team : teams) { - boatNames.add((String) team.get("team-name")); - } - - // Shuffle team names - long seed = System.nanoTime(); - Collections.shuffle(boatNames, new Random(seed)); - - if (numberOfBoats > Array.getLength(boatNames.toArray())) { - return null; - } - - // Add boats to the race - for (int i = 0; i < numberOfBoats; i++) { - race.addBoat(new Boat(boatNames.get(i), (Double) (teams.get(i).get("velocity")))); - } - - // Add marks to race in order -// race.addMark(new SingleMark("Start", 32.296038,-64.854401 )); -// race.addMark(new SingleMark("Mid SingleMark", 32.292881,-64.843231 )); -// race.addMark(new SingleMark("Leeward Gate", 32.283808,-64.850012 )); -// race.addMark(new SingleMark("Windward Gate", 32.309908,-64.833665 )); -// race.addMark(new SingleMark("Finish", 32.318439,-64.837367 )); - - return race; - } - - public static void main() { - Race race = null; - String raceConfigFile; - - raceConfigFile = "doc/examples/config.json"; - - - try { - race = createRace(raceConfigFile); - } catch (Exception e) { - System.out.println("There was an error creating the race."); - } - - // If race was created - if (race != null) { - //race.displayStartingBoats(); - - System.out.println("\n\n"); - System.out.println("######################"); - System.out.println("# Live Race Updates "); - System.out.println("######################"); - - race.startRace(); - - System.out.println("\n\n"); - System.out.println("######################"); - System.out.println("# Race Results "); - System.out.println("######################"); - - //race.showRaceMarkerResults(); - //race.displayFinishingOrder(); - - } else { - System.out.println("There was an error creating the race. Exiting."); - } - } -} \ No newline at end of file diff --git a/src/main/java/seng302/models/OldFileParser.java b/src/main/java/seng302/models/OldFileParser.java deleted file mode 100644 index e9447b8e..00000000 --- a/src/main/java/seng302/models/OldFileParser.java +++ /dev/null @@ -1,132 +0,0 @@ -package seng302.models; - -import org.json.simple.JSONObject; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Map; - - -/** - * Read team name from a given Json file. So that user can extract information - * efficiently from external files. - */ - -public class OldFileParser { - - private String filePath; - private JSONObject content; - - /** - * used to construct an instance of file parser - * - * @param filePath a string like path to show location of desired file to - * be parsed - */ - public OldFileParser(String filePath) throws Exception { - this.filePath = filePath; - this.readFile(); - } - - /** - * Reads content from a given file, and return the content as JSONObject. - * Throws FileNotFoundException, if the given file cannot be found. - */ - private void readFile() throws FileNotFoundException { - JSONParser parser = new JSONParser(); - try { - this.content = (JSONObject) parser.parse(new FileReader(filePath)); - - } catch (FileNotFoundException e) { - throw e; - } catch (IOException e) { - e.printStackTrace(); - } catch (ParseException e) { - e.printStackTrace(); - } - } - - /** - * Gets time scale setting parameter. - * - * @return long time scale. -1 if parameter is invalid (eg. scale is - * negative number, or containing non numeric character) or cannot be found. - */ - @SuppressWarnings("unchecked") - public double getTimeScale() { - try { - double timeScale = (double) this.content.get("time-scale"); - return timeScale >= 0 ? timeScale : -1; - } catch (Exception e) { - e.printStackTrace(); - return 1; - } - } - - /** - * Gets race name in the setting file. - * - * @return a string of race name. null if race name is invalid or cannot - * be found. - */ - @SuppressWarnings("unchecked") - public String getRaceName() { - try { - return (String) this.content.get("race-name"); - } catch (Exception e) { - return null; - } - } - - /** - * Gets an array of teams who participate the race. - * - * @return an ArrayList containing strings of team names. null if teams - * setting is invalid or there is no team. - */ - @SuppressWarnings("unchecked") - public ArrayList> getTeams() { - try { - return (ArrayList>) this.content.get("teams"); - } catch (Exception e) { - return null; - } - } - - /** - * Gets the total number of teams. - * - * @return the number of teams. 0 if no teams or anything goes wrong. - */ - @SuppressWarnings("unchecked") - public long getTotalNumberOfTeams() { - ArrayList> teams = getTeams(); - try { - return teams.size(); - } catch (Exception e) { - return 0; - } - } - - /** - * Gets the number of boats that would compete during a race. Returns the - * total number of race size if parameter is invalid or cannot be found. - * - * @return an int of the race size. - */ - @SuppressWarnings("unchecked") - public long getRaceSize() { - long totalTeams = this.getTotalNumberOfTeams(); - try { - long raceSize = (long) this.content.get("race-size"); - return raceSize >= 0 && raceSize <= totalTeams ? raceSize : totalTeams; - } catch (Exception e) { - e.printStackTrace(); - return totalTeams; - } - } -} \ No newline at end of file diff --git a/src/main/java/seng302/models/parsers/FileParser.java b/src/main/java/seng302/models/parsers/FileParser.java index ac4f65c3..b3d66b05 100644 --- a/src/main/java/seng302/models/parsers/FileParser.java +++ b/src/main/java/seng302/models/parsers/FileParser.java @@ -1,35 +1,37 @@ package seng302.models.parsers; -import org.w3c.dom.*; -import javax.xml.parsers.*; -import java.io.*; +import org.w3c.dom.Document; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; /** - * - * * Created by Haoming Yin (hyi25) on 16/3/2017 */ public abstract class FileParser { - private String filePath; + private String filePath; - public FileParser(String path) { - this.filePath = path; - } + public FileParser(String path) { + this.filePath = path; + } - protected Document parseFile () { - try { - File file = new File(this.filePath); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(file); - // optional, in order to recover info from broken line. - doc.getDocumentElement().normalize(); - return doc; - } catch (Exception e) { - e.printStackTrace(); - return null; - } + protected Document parseFile() { + try { + InputStream is = getClass().getResourceAsStream(this.filePath); + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document doc = builder.parse(is); + // optional, in order to recover info from broken line. + doc.getDocumentElement().normalize(); + return doc; + } catch (Exception e) { + e.printStackTrace(); + return null; + } - } + } } diff --git a/src/main/resources/RaceView.fxml b/src/main/resources/RaceView.fxml index 9534d08d..9c8b7add 100644 --- a/src/main/resources/RaceView.fxml +++ b/src/main/resources/RaceView.fxml @@ -25,12 +25,9 @@