From 764eb9089feb818042acc8f2bbd1f0b14d4e0b69 Mon Sep 17 00:00:00 2001 From: Connor Taylor-Brown Date: Wed, 19 Apr 2017 16:53:31 +1200 Subject: [PATCH] Added race data source interface to abstract sources of race data. - Refactored controllers to send data source to consumers (Race, ResizeableRaceCanvas) #story[782] --- .../seng302/Controllers/MainController.java | 5 +- .../seng302/Controllers/RaceController.java | 47 +++++-------------- .../seng302/Controllers/StartController.java | 34 +++++++------- .../seng302/Model/ConstantVelocityRace.java | 35 ++++++++++++-- src/main/java/seng302/Model/Race.java | 15 +++++- .../seng302/Model/ResizableRaceCanvas.java | 44 +++++++---------- src/main/java/seng302/RaceDataSource.java | 19 ++++++++ src/main/java/seng302/RaceXMLReader.java | 15 +++--- src/test/java/seng302/Model/RaceXMLTest.java | 3 +- 9 files changed, 120 insertions(+), 97 deletions(-) create mode 100644 src/main/java/seng302/RaceDataSource.java diff --git a/src/main/java/seng302/Controllers/MainController.java b/src/main/java/seng302/Controllers/MainController.java index ea65001a..796c47b4 100644 --- a/src/main/java/seng302/Controllers/MainController.java +++ b/src/main/java/seng302/Controllers/MainController.java @@ -4,6 +4,7 @@ import javafx.fxml.FXML; import javafx.scene.control.SplitPane; import javafx.scene.layout.AnchorPane; import javafx.scene.layout.GridPane; +import seng302.RaceDataSource; import seng302.RaceXMLReader; import java.net.URL; @@ -16,8 +17,8 @@ public class MainController extends Controller { @FXML StartController startController; @FXML RaceController raceController; - public void beginRace(int scaleFactor) { - raceController.startRace(scaleFactor); + public void beginRace(int scaleFactor, RaceDataSource raceData) { + raceController.startRace(scaleFactor, raceData); } diff --git a/src/main/java/seng302/Controllers/RaceController.java b/src/main/java/seng302/Controllers/RaceController.java index 88556461..78c257d0 100644 --- a/src/main/java/seng302/Controllers/RaceController.java +++ b/src/main/java/seng302/Controllers/RaceController.java @@ -4,6 +4,7 @@ package seng302.Controllers; import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; +import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; import javafx.event.EventHandler; @@ -12,12 +13,15 @@ import javafx.scene.control.*; import javafx.scene.layout.GridPane; import org.xml.sax.SAXException; import seng302.Model.*; +import seng302.RaceDataSource; import seng302.RaceXMLReader; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.net.URL; import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.ResourceBundle; /** @@ -76,8 +80,7 @@ public class RaceController extends Controller { * @see ResizableRaceCanvas */ public void updateMap(ObservableList boats) { - BoatInRace[] boatInRaces = new BoatInRace[boats.size()]; - raceMap.setBoats(boats.toArray(boatInRaces)); + raceMap.setBoats(boats); raceMap.update(); } @@ -118,44 +121,16 @@ public class RaceController extends Controller { * * @param scaleFactor scale value of race */ - public void startRace(int scaleFactor) { - - RaceXMLReader raceXMLReader = null; - try { - raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml"); - } catch (IOException e) { - e.printStackTrace(); - } catch (SAXException e) { - e.printStackTrace(); - } catch (ParserConfigurationException e) { - e.printStackTrace(); - } - - BoatInRace[] boats = new BoatInRace[raceXMLReader.getBoats().size()]; - boats = raceXMLReader.getBoats().toArray(boats); - double lat1 = raceXMLReader.getMapTopLeft().getLatitude(); - double long1 = raceXMLReader.getMapTopLeft().getLongitude(); - double lat2 = raceXMLReader.getMapBottomRight().getLatitude(); - double long2 = raceXMLReader.getMapBottomRight().getLongitude(); - - - ArrayList legs = raceXMLReader.getLegs(); - ConstantVelocityRace newRace = new ConstantVelocityRace(boats, legs, this, scaleFactor); + public void startRace(int scaleFactor, RaceDataSource raceData) { + ConstantVelocityRace newRace = new ConstantVelocityRace(raceData, this, scaleFactor); newRace.initialiseBoats(); - BoatInRace[] startingBoats = new BoatInRace[newRace.getStartingBoats().size()]; - int i = 0; - for (BoatInRace boat : newRace.getStartingBoats()) { - startingBoats[i] = boat; - i++; - } - - raceMap = new ResizableRaceCanvas(lat1, long1, lat2, long2); + raceMap = new ResizableRaceCanvas(raceData); raceMap.setMouseTransparent(true); raceMap.widthProperty().bind(canvasBase.widthProperty()); raceMap.heightProperty().bind(canvasBase.heightProperty()); - raceMap.setBoats(startingBoats); - raceMap.setRaceBoundaries(raceXMLReader.getBoundary()); + raceMap.setBoats(newRace.getStartingBoats()); + raceMap.setRaceBoundaries(raceData.getBoundary()); raceMap.drawRaceMap(); raceMap.setVisible(true); @@ -164,7 +139,7 @@ public class RaceController extends Controller { //Initialize save annotation array, fps listener, and annotation listeners //timezone - RaceClock raceClock = new RaceClock(raceXMLReader.getMark()); + RaceClock raceClock = new RaceClock(raceData.getMark()); timeZone.setText(raceClock.getTimeZone()); initializeFPS(); diff --git a/src/main/java/seng302/Controllers/StartController.java b/src/main/java/seng302/Controllers/StartController.java index 7e1ab4e9..f62fb6ea 100644 --- a/src/main/java/seng302/Controllers/StartController.java +++ b/src/main/java/seng302/Controllers/StartController.java @@ -15,11 +15,13 @@ import javafx.scene.layout.GridPane; import org.xml.sax.SAXException; import seng302.Model.BoatInRace; import seng302.Model.RaceClock; +import seng302.RaceDataSource; import seng302.RaceXMLReader; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.net.URL; +import java.util.List; import java.util.ResourceBundle; /** @@ -43,6 +45,8 @@ public class StartController extends Controller { private RaceClock raceClock; + private RaceDataSource raceData; + /** * Begins the race with a scale factor of 15 */ @@ -74,19 +78,9 @@ public class StartController extends Controller { @Override public void initialize(URL location, ResourceBundle resources){ - initialiseTables(); - - } - - public AnchorPane startWrapper(){ - return startWrapper; - } - - private void initialiseTables() { - - RaceXMLReader raceXMLReader = null; + raceData = null; try { - raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml"); + raceData = new RaceXMLReader("raceXML/bermuda_AC35.xml"); } catch (IOException e) { e.printStackTrace(); } catch (SAXException e) { @@ -94,17 +88,23 @@ public class StartController extends Controller { } catch (ParserConfigurationException e) { e.printStackTrace(); } + initialiseTables(); + } + + public AnchorPane startWrapper(){ + return startWrapper; + } - BoatInRace[] boats = new BoatInRace[raceXMLReader.getBoats().size()]; - boats = raceXMLReader.getBoats().toArray(boats); + private void initialiseTables() { + List boats = raceData.getBoats(); ObservableList observableBoats = FXCollections.observableArrayList(boats); + boatNameTable.setItems(observableBoats); boatNameColumn.setCellValueFactory(cellData -> cellData.getValue().getName()); boatCodeColumn.setCellValueFactory(new PropertyValueFactory<>("abbrev")); //timezone - raceClock = new RaceClock(raceXMLReader.getMark()); + raceClock = new RaceClock(raceData.getMark()); timeZoneTime.textProperty().bind(raceClock.timeProperty()); - } @@ -138,7 +138,7 @@ public class StartController extends Controller { if (timeLeft <= 0) { updateTime("Race is starting..."); stop(); - parent.beginRace(scaleFactor); + parent.beginRace(scaleFactor, raceData); startWrapper.setVisible(false); } else { diff --git a/src/main/java/seng302/Model/ConstantVelocityRace.java b/src/main/java/seng302/Model/ConstantVelocityRace.java index f352308b..cacdb10f 100644 --- a/src/main/java/seng302/Model/ConstantVelocityRace.java +++ b/src/main/java/seng302/Model/ConstantVelocityRace.java @@ -4,9 +4,12 @@ import org.geotools.referencing.GeodeticCalculator; import seng302.Constants; import seng302.Controllers.RaceController; import seng302.GPSCoordinate; +import seng302.RaceDataSource; import java.awt.geom.Point2D; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; /** * Created by cbt24 on 6/03/17. @@ -14,17 +17,41 @@ import java.util.ArrayList; public class ConstantVelocityRace extends Race { /** - * Initialiser for a constant velocity race + * Initialiser for a constant velocity race without standard data source * * @param startingBoats in race * @param legs in race - * @param controller of race - * @param scaleFactor of race + * @param controller for graphics + * @param scaleFactor of timer */ - public ConstantVelocityRace(BoatInRace[] startingBoats, ArrayList legs, RaceController controller, int scaleFactor) { + public ConstantVelocityRace(List startingBoats, List legs, RaceController controller, int scaleFactor) { super(startingBoats, legs, controller, scaleFactor); } + /** + * Initialiser for legacy tests + * + * @param startingBoats in race + * @param legs in race + * @param controller for graphics + * @param scaleFactor of timer + * + * @deprecated Please use {@link #ConstantVelocityRace(List, List, RaceController, int) } for future tests. + */ + public ConstantVelocityRace(BoatInRace[] startingBoats, List legs, RaceController controller, int scaleFactor) { + super(Arrays.asList(startingBoats), legs, controller, scaleFactor); + } + + /** + * Initialiser for constant velocity race with standard data source + * @param raceData for race + * @param controller for graphics + * @param scaleFactor of timer + */ + public ConstantVelocityRace(RaceDataSource raceData, RaceController controller, int scaleFactor) { + super(raceData, controller, scaleFactor); + } + /** * Calculates the distance a boat has travelled and updates its current position according to this value. diff --git a/src/main/java/seng302/Model/Race.java b/src/main/java/seng302/Model/Race.java index 54e14245..46d2ff1b 100644 --- a/src/main/java/seng302/Model/Race.java +++ b/src/main/java/seng302/Model/Race.java @@ -8,9 +8,12 @@ import javafx.collections.ObservableList; import org.geotools.referencing.GeodeticCalculator; import seng302.Controllers.RaceController; import seng302.GPSCoordinate; +import seng302.RaceDataSource; import java.awt.geom.Point2D; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.Random; /** @@ -20,7 +23,7 @@ import java.util.Random; public abstract class Race implements Runnable { //protected BoatInRace[] startingBoats; protected ObservableList startingBoats; - protected ArrayList legs; + protected List legs; protected RaceController controller; protected int boatsFinished = 0; protected long totalTimeElapsed; @@ -43,7 +46,7 @@ public abstract class Race implements Runnable { * @param controller race controller * @param scaleFactor for race */ - public Race(BoatInRace[] boats, ArrayList legs, RaceController controller, int scaleFactor) { + public Race(List boats, List legs, RaceController controller, int scaleFactor) { this.startingBoats = FXCollections.observableArrayList(boats); this.legs = legs; @@ -55,6 +58,14 @@ public abstract class Race implements Runnable { } } + public Race(BoatInRace[] startingBoats, List legs, RaceController controller, int scaleFactor) { + this(Arrays.asList(startingBoats), legs, controller, scaleFactor); + } + + public Race(RaceDataSource raceData, RaceController controller, int scaleFactor) { + this(raceData.getBoats(), raceData.getLegs(), controller, scaleFactor); + } + /** * Sets the chance each boat has of failing at a gate or marker * @param chance percentage chance a boat has of failing per checkpoint. diff --git a/src/main/java/seng302/Model/ResizableRaceCanvas.java b/src/main/java/seng302/Model/ResizableRaceCanvas.java index 5966464b..5dda2197 100644 --- a/src/main/java/seng302/Model/ResizableRaceCanvas.java +++ b/src/main/java/seng302/Model/ResizableRaceCanvas.java @@ -6,14 +6,12 @@ import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; import javafx.scene.paint.Paint; import javafx.scene.transform.Rotate; -import seng302.Constants; +import seng302.*; import seng302.Controllers.RaceController; -import seng302.GPSCoordinate; -import seng302.GraphCoordinate; -import seng302.RaceMap; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; /** * This creates a JavaFX Canvas that is fills it's parent. @@ -23,8 +21,7 @@ import java.util.Arrays; public class ResizableRaceCanvas extends Canvas { private GraphicsContext gc; private RaceMap map; - private BoatInRace[] boats; - private RaceController controller; + private List boats; private boolean raceAnno = true; private boolean annoName = true; private boolean annoAbbrev = true; @@ -33,35 +30,26 @@ public class ResizableRaceCanvas extends Canvas { private ArrayList raceBoundaries; double[] xpoints = {}, ypoints = {}; - /** - * Sets the boats that are to be displayed in this race. - * - * @param boats in race - */ - public void setBoats(BoatInRace[] boats) { - this.boats = boats; - } - - public ResizableRaceCanvas(RaceMap map) { - super(); - this.map = map; + public ResizableRaceCanvas(RaceDataSource raceData) { gc = this.getGraphicsContext2D(); // Redraw canvas when size changes. widthProperty().addListener(evt -> drawRaceMap()); heightProperty().addListener(evt -> drawRaceMap()); + + double lat1 = raceData.getMapTopLeft().getLatitude(); + double long1 = raceData.getMapTopLeft().getLongitude(); + double lat2 = raceData.getMapBottomRight().getLatitude(); + double long2 = raceData.getMapBottomRight().getLongitude(); + setMap(new RaceMap(lat1, long1, lat2, long2, (int) getWidth(), (int) getHeight())); } /** - * Constructor + * Sets the boats that are to be displayed in this race. + * + * @param boats in race */ - public ResizableRaceCanvas() { - this(null); - setMap(new RaceMap(32.278, -64.863, 32.320989, -64.821, (int) getWidth(), (int) getHeight())); - } - - public ResizableRaceCanvas(double lat1, double long1, double lat2, double long2) { - this(null); - setMap(new RaceMap(lat1, long1, lat2, long2, (int) getWidth(), (int) getHeight())); + public void setBoats(List boats) { + this.boats = boats; } /** @@ -369,7 +357,7 @@ public class ResizableRaceCanvas extends Canvas { } } - public void setRaceBoundaries(ArrayList boundaries) { + public void setRaceBoundaries(List boundaries) { this.raceBoundaries = new ArrayList<>(); for (GPSCoordinate bound : boundaries) { raceBoundaries.add(bound); diff --git a/src/main/java/seng302/RaceDataSource.java b/src/main/java/seng302/RaceDataSource.java new file mode 100644 index 00000000..2f562766 --- /dev/null +++ b/src/main/java/seng302/RaceDataSource.java @@ -0,0 +1,19 @@ +package seng302; + +import seng302.Model.BoatInRace; +import seng302.Model.Leg; + +import java.util.List; + +/** + * Created by connortaylorbrown on 19/04/17. + */ +public interface RaceDataSource { + List getBoats(); + List getLegs(); + List getBoundary(); + + GPSCoordinate getMark(); + GPSCoordinate getMapTopLeft(); + GPSCoordinate getMapBottomRight(); +} diff --git a/src/main/java/seng302/RaceXMLReader.java b/src/main/java/seng302/RaceXMLReader.java index d99102ce..f10da6ef 100644 --- a/src/main/java/seng302/RaceXMLReader.java +++ b/src/main/java/seng302/RaceXMLReader.java @@ -11,17 +11,18 @@ import seng302.Model.Marker; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.util.ArrayList; +import java.util.List; /** * Created by fwy13 on 26/03/2017. */ -public class RaceXMLReader extends XMLReader { - private ArrayList boats = new ArrayList<>(); +public class RaceXMLReader extends XMLReader implements RaceDataSource { + private List boats = new ArrayList<>(); private Color[] colors = {Color.BLUEVIOLET, Color.BLACK, Color.RED, Color.ORANGE, Color.DARKOLIVEGREEN, Color.LIMEGREEN};//TODO make this established in xml or come up with a better system. - private ArrayList legs = new ArrayList<>(); + private List legs = new ArrayList<>(); private GPSCoordinate mark, startPt1, startPt2, finishPt1, finishPt2, leewardPt1, leewardPt2, windwardPt1, windwardPt2; private GPSCoordinate mapTopLeft, mapBottomRight; - private ArrayList boundary = new ArrayList<>(); + private List boundary = new ArrayList<>(); private static double COORDINATEPADDING = 0.0005; /** @@ -263,11 +264,11 @@ public class RaceXMLReader extends XMLReader { return new GPSCoordinate(startLat, startLong); } - public ArrayList getBoats() { + public List getBoats() { return boats; } - public ArrayList getLegs() { + public List getLegs() { return legs; } @@ -307,7 +308,7 @@ public class RaceXMLReader extends XMLReader { return windwardPt2; } - public ArrayList getBoundary() { + public List getBoundary() { return boundary; } diff --git a/src/test/java/seng302/Model/RaceXMLTest.java b/src/test/java/seng302/Model/RaceXMLTest.java index ea43e6dd..e53c9085 100644 --- a/src/test/java/seng302/Model/RaceXMLTest.java +++ b/src/test/java/seng302/Model/RaceXMLTest.java @@ -11,6 +11,7 @@ import seng302.RaceXMLReader; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.util.ArrayList; +import java.util.List; public class RaceXMLTest { RaceXMLReader raceXMLReader; @@ -29,7 +30,7 @@ public class RaceXMLTest { try { RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false); raceXMLReader.readBoats(); - ArrayList boats = raceXMLReader.getBoats(); + List boats = raceXMLReader.getBoats(); assertTrue(boats.size() == 6); //test boat 1 assertEquals(boats.get(0).getName().getValue(), "ORACLE TEAM USA");