Added race data source interface to abstract sources of race data.

- Refactored controllers to send data source to consumers (Race, ResizeableRaceCanvas)

#story[782]
main
Connor Taylor-Brown 9 years ago
parent 028cb33509
commit 764eb9089f

@ -4,6 +4,7 @@ import javafx.fxml.FXML;
import javafx.scene.control.SplitPane; import javafx.scene.control.SplitPane;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import seng302.RaceDataSource;
import seng302.RaceXMLReader; import seng302.RaceXMLReader;
import java.net.URL; import java.net.URL;
@ -16,8 +17,8 @@ public class MainController extends Controller {
@FXML StartController startController; @FXML StartController startController;
@FXML RaceController raceController; @FXML RaceController raceController;
public void beginRace(int scaleFactor) { public void beginRace(int scaleFactor, RaceDataSource raceData) {
raceController.startRace(scaleFactor); raceController.startRace(scaleFactor, raceData);
} }

@ -4,6 +4,7 @@ package seng302.Controllers;
import javafx.beans.property.ReadOnlyObjectWrapper; import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.beans.value.ChangeListener; import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue; import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.event.ActionEvent; import javafx.event.ActionEvent;
import javafx.event.EventHandler; import javafx.event.EventHandler;
@ -12,12 +13,15 @@ import javafx.scene.control.*;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import seng302.Model.*; import seng302.Model.*;
import seng302.RaceDataSource;
import seng302.RaceXMLReader; import seng302.RaceXMLReader;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
/** /**
@ -76,8 +80,7 @@ public class RaceController extends Controller {
* @see ResizableRaceCanvas * @see ResizableRaceCanvas
*/ */
public void updateMap(ObservableList<BoatInRace> boats) { public void updateMap(ObservableList<BoatInRace> boats) {
BoatInRace[] boatInRaces = new BoatInRace[boats.size()]; raceMap.setBoats(boats);
raceMap.setBoats(boats.toArray(boatInRaces));
raceMap.update(); raceMap.update();
} }
@ -118,44 +121,16 @@ public class RaceController extends Controller {
* *
* @param scaleFactor scale value of race * @param scaleFactor scale value of race
*/ */
public void startRace(int scaleFactor) { public void startRace(int scaleFactor, RaceDataSource raceData) {
ConstantVelocityRace newRace = new ConstantVelocityRace(raceData, this, 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<Leg> legs = raceXMLReader.getLegs();
ConstantVelocityRace newRace = new ConstantVelocityRace(boats, legs, this, scaleFactor);
newRace.initialiseBoats(); newRace.initialiseBoats();
BoatInRace[] startingBoats = new BoatInRace[newRace.getStartingBoats().size()]; raceMap = new ResizableRaceCanvas(raceData);
int i = 0;
for (BoatInRace boat : newRace.getStartingBoats()) {
startingBoats[i] = boat;
i++;
}
raceMap = new ResizableRaceCanvas(lat1, long1, lat2, long2);
raceMap.setMouseTransparent(true); raceMap.setMouseTransparent(true);
raceMap.widthProperty().bind(canvasBase.widthProperty()); raceMap.widthProperty().bind(canvasBase.widthProperty());
raceMap.heightProperty().bind(canvasBase.heightProperty()); raceMap.heightProperty().bind(canvasBase.heightProperty());
raceMap.setBoats(startingBoats); raceMap.setBoats(newRace.getStartingBoats());
raceMap.setRaceBoundaries(raceXMLReader.getBoundary()); raceMap.setRaceBoundaries(raceData.getBoundary());
raceMap.drawRaceMap(); raceMap.drawRaceMap();
raceMap.setVisible(true); raceMap.setVisible(true);
@ -164,7 +139,7 @@ public class RaceController extends Controller {
//Initialize save annotation array, fps listener, and annotation listeners //Initialize save annotation array, fps listener, and annotation listeners
//timezone //timezone
RaceClock raceClock = new RaceClock(raceXMLReader.getMark()); RaceClock raceClock = new RaceClock(raceData.getMark());
timeZone.setText(raceClock.getTimeZone()); timeZone.setText(raceClock.getTimeZone());
initializeFPS(); initializeFPS();

@ -15,11 +15,13 @@ import javafx.scene.layout.GridPane;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import seng302.Model.BoatInRace; import seng302.Model.BoatInRace;
import seng302.Model.RaceClock; import seng302.Model.RaceClock;
import seng302.RaceDataSource;
import seng302.RaceXMLReader; import seng302.RaceXMLReader;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.util.List;
import java.util.ResourceBundle; import java.util.ResourceBundle;
/** /**
@ -43,6 +45,8 @@ public class StartController extends Controller {
private RaceClock raceClock; private RaceClock raceClock;
private RaceDataSource raceData;
/** /**
* Begins the race with a scale factor of 15 * Begins the race with a scale factor of 15
*/ */
@ -74,19 +78,9 @@ public class StartController extends Controller {
@Override @Override
public void initialize(URL location, ResourceBundle resources){ public void initialize(URL location, ResourceBundle resources){
initialiseTables(); raceData = null;
}
public AnchorPane startWrapper(){
return startWrapper;
}
private void initialiseTables() {
RaceXMLReader raceXMLReader = null;
try { try {
raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml"); raceData = new RaceXMLReader("raceXML/bermuda_AC35.xml");
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} catch (SAXException e) { } catch (SAXException e) {
@ -94,17 +88,23 @@ public class StartController extends Controller {
} catch (ParserConfigurationException e) { } catch (ParserConfigurationException e) {
e.printStackTrace(); e.printStackTrace();
} }
initialiseTables();
}
public AnchorPane startWrapper(){
return startWrapper;
}
BoatInRace[] boats = new BoatInRace[raceXMLReader.getBoats().size()]; private void initialiseTables() {
boats = raceXMLReader.getBoats().toArray(boats); List<BoatInRace> boats = raceData.getBoats();
ObservableList<BoatInRace> observableBoats = FXCollections.observableArrayList(boats); ObservableList<BoatInRace> observableBoats = FXCollections.observableArrayList(boats);
boatNameTable.setItems(observableBoats); boatNameTable.setItems(observableBoats);
boatNameColumn.setCellValueFactory(cellData -> cellData.getValue().getName()); boatNameColumn.setCellValueFactory(cellData -> cellData.getValue().getName());
boatCodeColumn.setCellValueFactory(new PropertyValueFactory<>("abbrev")); boatCodeColumn.setCellValueFactory(new PropertyValueFactory<>("abbrev"));
//timezone //timezone
raceClock = new RaceClock(raceXMLReader.getMark()); raceClock = new RaceClock(raceData.getMark());
timeZoneTime.textProperty().bind(raceClock.timeProperty()); timeZoneTime.textProperty().bind(raceClock.timeProperty());
} }
@ -138,7 +138,7 @@ public class StartController extends Controller {
if (timeLeft <= 0) { if (timeLeft <= 0) {
updateTime("Race is starting..."); updateTime("Race is starting...");
stop(); stop();
parent.beginRace(scaleFactor); parent.beginRace(scaleFactor, raceData);
startWrapper.setVisible(false); startWrapper.setVisible(false);
} else { } else {

@ -4,9 +4,12 @@ import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants; import seng302.Constants;
import seng302.Controllers.RaceController; import seng302.Controllers.RaceController;
import seng302.GPSCoordinate; import seng302.GPSCoordinate;
import seng302.RaceDataSource;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** /**
* Created by cbt24 on 6/03/17. * Created by cbt24 on 6/03/17.
@ -14,17 +17,41 @@ import java.util.ArrayList;
public class ConstantVelocityRace extends Race { 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 startingBoats in race
* @param legs in race * @param legs in race
* @param controller of race * @param controller for graphics
* @param scaleFactor of race * @param scaleFactor of timer
*/ */
public ConstantVelocityRace(BoatInRace[] startingBoats, ArrayList<Leg> legs, RaceController controller, int scaleFactor) { public ConstantVelocityRace(List<BoatInRace> startingBoats, List<Leg> legs, RaceController controller, int scaleFactor) {
super(startingBoats, legs, controller, 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<Leg> 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. * Calculates the distance a boat has travelled and updates its current position according to this value.

@ -8,9 +8,12 @@ import javafx.collections.ObservableList;
import org.geotools.referencing.GeodeticCalculator; import org.geotools.referencing.GeodeticCalculator;
import seng302.Controllers.RaceController; import seng302.Controllers.RaceController;
import seng302.GPSCoordinate; import seng302.GPSCoordinate;
import seng302.RaceDataSource;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random; import java.util.Random;
/** /**
@ -20,7 +23,7 @@ import java.util.Random;
public abstract class Race implements Runnable { public abstract class Race implements Runnable {
//protected BoatInRace[] startingBoats; //protected BoatInRace[] startingBoats;
protected ObservableList<BoatInRace> startingBoats; protected ObservableList<BoatInRace> startingBoats;
protected ArrayList<Leg> legs; protected List<Leg> legs;
protected RaceController controller; protected RaceController controller;
protected int boatsFinished = 0; protected int boatsFinished = 0;
protected long totalTimeElapsed; protected long totalTimeElapsed;
@ -43,7 +46,7 @@ public abstract class Race implements Runnable {
* @param controller race controller * @param controller race controller
* @param scaleFactor for race * @param scaleFactor for race
*/ */
public Race(BoatInRace[] boats, ArrayList<Leg> legs, RaceController controller, int scaleFactor) { public Race(List<BoatInRace> boats, List<Leg> legs, RaceController controller, int scaleFactor) {
this.startingBoats = FXCollections.observableArrayList(boats); this.startingBoats = FXCollections.observableArrayList(boats);
this.legs = legs; this.legs = legs;
@ -55,6 +58,14 @@ public abstract class Race implements Runnable {
} }
} }
public Race(BoatInRace[] startingBoats, List<Leg> 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 * Sets the chance each boat has of failing at a gate or marker
* @param chance percentage chance a boat has of failing per checkpoint. * @param chance percentage chance a boat has of failing per checkpoint.

@ -6,14 +6,12 @@ import javafx.scene.canvas.GraphicsContext;
import javafx.scene.paint.Color; import javafx.scene.paint.Color;
import javafx.scene.paint.Paint; import javafx.scene.paint.Paint;
import javafx.scene.transform.Rotate; import javafx.scene.transform.Rotate;
import seng302.Constants; import seng302.*;
import seng302.Controllers.RaceController; import seng302.Controllers.RaceController;
import seng302.GPSCoordinate;
import seng302.GraphCoordinate;
import seng302.RaceMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
/** /**
* This creates a JavaFX Canvas that is fills it's parent. * This creates a JavaFX Canvas that is fills it's parent.
@ -23,8 +21,7 @@ import java.util.Arrays;
public class ResizableRaceCanvas extends Canvas { public class ResizableRaceCanvas extends Canvas {
private GraphicsContext gc; private GraphicsContext gc;
private RaceMap map; private RaceMap map;
private BoatInRace[] boats; private List<BoatInRace> boats;
private RaceController controller;
private boolean raceAnno = true; private boolean raceAnno = true;
private boolean annoName = true; private boolean annoName = true;
private boolean annoAbbrev = true; private boolean annoAbbrev = true;
@ -33,35 +30,26 @@ public class ResizableRaceCanvas extends Canvas {
private ArrayList<GPSCoordinate> raceBoundaries; private ArrayList<GPSCoordinate> raceBoundaries;
double[] xpoints = {}, ypoints = {}; double[] xpoints = {}, ypoints = {};
/** public ResizableRaceCanvas(RaceDataSource raceData) {
* 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;
gc = this.getGraphicsContext2D(); gc = this.getGraphicsContext2D();
// Redraw canvas when size changes. // Redraw canvas when size changes.
widthProperty().addListener(evt -> drawRaceMap()); widthProperty().addListener(evt -> drawRaceMap());
heightProperty().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() { public void setBoats(List<BoatInRace> boats) {
this(null); this.boats = boats;
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()));
} }
/** /**
@ -369,7 +357,7 @@ public class ResizableRaceCanvas extends Canvas {
} }
} }
public void setRaceBoundaries(ArrayList<GPSCoordinate> boundaries) { public void setRaceBoundaries(List<GPSCoordinate> boundaries) {
this.raceBoundaries = new ArrayList<>(); this.raceBoundaries = new ArrayList<>();
for (GPSCoordinate bound : boundaries) { for (GPSCoordinate bound : boundaries) {
raceBoundaries.add(bound); raceBoundaries.add(bound);

@ -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<BoatInRace> getBoats();
List<Leg> getLegs();
List<GPSCoordinate> getBoundary();
GPSCoordinate getMark();
GPSCoordinate getMapTopLeft();
GPSCoordinate getMapBottomRight();
}

@ -11,17 +11,18 @@ import seng302.Model.Marker;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
/** /**
* Created by fwy13 on 26/03/2017. * Created by fwy13 on 26/03/2017.
*/ */
public class RaceXMLReader extends XMLReader { public class RaceXMLReader extends XMLReader implements RaceDataSource {
private ArrayList<BoatInRace> boats = new ArrayList<>(); private List<BoatInRace> 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 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<Leg> legs = new ArrayList<>(); private List<Leg> legs = new ArrayList<>();
private GPSCoordinate mark, startPt1, startPt2, finishPt1, finishPt2, leewardPt1, leewardPt2, windwardPt1, windwardPt2; private GPSCoordinate mark, startPt1, startPt2, finishPt1, finishPt2, leewardPt1, leewardPt2, windwardPt1, windwardPt2;
private GPSCoordinate mapTopLeft, mapBottomRight; private GPSCoordinate mapTopLeft, mapBottomRight;
private ArrayList<GPSCoordinate> boundary = new ArrayList<>(); private List<GPSCoordinate> boundary = new ArrayList<>();
private static double COORDINATEPADDING = 0.0005; private static double COORDINATEPADDING = 0.0005;
/** /**
@ -263,11 +264,11 @@ public class RaceXMLReader extends XMLReader {
return new GPSCoordinate(startLat, startLong); return new GPSCoordinate(startLat, startLong);
} }
public ArrayList<BoatInRace> getBoats() { public List<BoatInRace> getBoats() {
return boats; return boats;
} }
public ArrayList<Leg> getLegs() { public List<Leg> getLegs() {
return legs; return legs;
} }
@ -307,7 +308,7 @@ public class RaceXMLReader extends XMLReader {
return windwardPt2; return windwardPt2;
} }
public ArrayList<GPSCoordinate> getBoundary() { public List<GPSCoordinate> getBoundary() {
return boundary; return boundary;
} }

@ -11,6 +11,7 @@ import seng302.RaceXMLReader;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
public class RaceXMLTest { public class RaceXMLTest {
RaceXMLReader raceXMLReader; RaceXMLReader raceXMLReader;
@ -29,7 +30,7 @@ public class RaceXMLTest {
try { try {
RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false); RaceXMLReader raceXMLReader = new RaceXMLReader("raceXML/bermuda_AC35.xml", false);
raceXMLReader.readBoats(); raceXMLReader.readBoats();
ArrayList<BoatInRace> boats = raceXMLReader.getBoats(); List<BoatInRace> boats = raceXMLReader.getBoats();
assertTrue(boats.size() == 6); assertTrue(boats.size() == 6);
//test boat 1 //test boat 1
assertEquals(boats.get(0).getName().getValue(), "ORACLE TEAM USA"); assertEquals(boats.get(0).getName().getValue(), "ORACLE TEAM USA");

Loading…
Cancel
Save