Refactored mock.Event to work with MockRace.

Fixed the networking imports.
Race now keeps a reference to its Race, Boat, and Regatta data sources.
VisualiserRace can be provided with new Race/Boat/Regatta data sources during runtime. Currently it updates boundary and legs with a new RaceDataSource, and marker boats with a new BoatDataSource.
main
fjc40 9 years ago
parent 8d36d89570
commit 3a0b81834f

@ -8,6 +8,7 @@ import mock.model.Polars;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import shared.dataInput.XMLReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@ -51,7 +52,7 @@ public class App extends Application {
* Reads the Initial Race XML files that are necessary to run the mock.
* @param path path of the XML
* @param encoding encoding of the xml
* @return
* @return A string containing the contents of the specified file.
* @throws IOException No file etc
* @throws ParserConfigurationException Issue with the XML formatting
* @throws SAXException Issue with XML formatting

@ -1,8 +1,14 @@
package mock.app;
import mock.model.MockRace;
import mock.model.Polars;
import network.Messages.Enums.MessageType;
import org.xml.sax.SAXException;
import shared.dataInput.*;
import shared.exceptions.InvalidBoatDataException;
import shared.exceptions.InvalidRaceDataException;
import shared.exceptions.InvalidRegattaDataException;
import shared.exceptions.XMLReaderException;
import shared.model.Constants;
import javax.xml.parsers.ParserConfigurationException;
@ -17,11 +23,11 @@ import java.time.format.DateTimeFormatter;
*/
public class Event {
String raceXML;
String regattaXML;
String boatXML;
Polars boatPolars;
MockOutput mockOutput;
private String raceXML;
private String regattaXML;
private String boatXML;
private Polars boatPolars;
private MockOutput mockOutput;
public Event(String raceXML, String regattaXML, String boatXML, Polars boatPolars) {
@ -29,6 +35,7 @@ public class Event {
this.boatXML = boatXML;
this.regattaXML = regattaXML;
this.boatPolars = boatPolars;
try {
mockOutput = new MockOutput();
new Thread(mockOutput).start();
@ -43,10 +50,18 @@ public class Event {
public void start() {
try {
sendXMLs();
Race newRace = new Race(new RaceXMLReader(this.raceXML, new BoatXMLReader(boatXML, this.boatPolars)), mockOutput);
new Thread((newRace)).start();
} catch (ParserConfigurationException | IOException | SAXException | ParseException | StreamedCourseXMLException e) {
//Parse the XML files into data sources.
RaceDataSource raceDataSource = new RaceXMLReader(this.raceXML);
BoatDataSource boatDataSource = new BoatXMLReader(this.boatXML);
RegattaDataSource regattaDataSource = new RegattaXMLReader(this.regattaXML);
//Create and start race.
MockRace newRace = new MockRace(boatDataSource, raceDataSource, regattaDataSource, this.boatPolars, this.mockOutput);
new Thread(newRace).start();
} catch (XMLReaderException | InvalidBoatDataException | InvalidRaceDataException | InvalidRegattaDataException e) {
e.printStackTrace();
}
}

@ -1,7 +1,11 @@
package network;
import seng302.Networking.Exceptions.InvalidMessageException;
import seng302.Networking.Messages.Enums.MessageType;
import network.Exceptions.InvalidMessageException;
import network.MessageDecoders.*;
import network.Messages.*;
import network.Messages.Enums.MessageType;
import static network.Utils.ByteConverter.*;
import java.nio.ByteBuffer;
import java.util.Arrays;
@ -69,20 +73,20 @@ public class BinaryMessageDecoder {
this.headerMessageType = this.messageHeader[2];
//Get the header timestamp.
this.headerTimeStamp = ByteConverter.bytesToLong(Arrays.copyOfRange(this.messageHeader, 3, 9));
this.headerTimeStamp = bytesToLong(Arrays.copyOfRange(this.messageHeader, 3, 9));
//Get the source ID for the message.
this.headerSourceID = ByteConverter.bytesToInt(Arrays.copyOfRange(this.messageHeader, 9, 13));
this.headerSourceID = bytesToInt(Arrays.copyOfRange(this.messageHeader, 9, 13));
//Get the length of the message body.
this.messageBodyLength = ByteConverter.bytesToInt(Arrays.copyOfRange(this.messageHeader, 13, 15));
this.messageBodyLength = bytesToInt(Arrays.copyOfRange(this.messageHeader, 13, 15));
//Get the messageBody.
this.messageBody = Arrays.copyOfRange(this.fullMessage, this.headerLength, this.headerLength + this.messageBodyLength);
//Get the CRC value.
this.messageCRCValue = ByteConverter.bytesToLong(Arrays.copyOfRange(this.fullMessage, this.fullMessage.length - CRCLength, this.fullMessage.length));
this.messageCRCValue = bytesToLong(Arrays.copyOfRange(this.fullMessage, this.fullMessage.length - CRCLength, this.fullMessage.length));
//Combine the header and body into a single array.
ByteBuffer headerBodyByteBuffer = ByteBuffer.allocate(messageHeader.length + messageBody.length);
@ -131,7 +135,7 @@ public class BinaryMessageDecoder {
//System.out.println("Decoding HeartBeat Message!");
//TODO maybe use HeartbeatDecoder.decode(message).
//TODO also, decoders for each message type should encapsulate the constructing of the object. E.g., return HeartbeatDecoder.decode(message);.
return new Heartbeat(ByteConverter.bytesToLong(messageBody));
return new Heartbeat(bytesToLong(messageBody));
case RACESTATUS:
//System.out.println("Race Status Message");

@ -1,12 +1,13 @@
package network;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
import static network.Utils.ByteConverter.*;
import java.nio.ByteBuffer;
import java.util.zip.CRC32;
import static seng302.Networking.Utils.ByteConverter.*;
/**
* This class can be used to encode/convert a byte array message body, plus header data into a byte array containing the entire message, ready to send.

@ -1,7 +1,8 @@
package network.MessageDecoders;
import seng302.Networking.Messages.AverageWind;
import seng302.Networking.Utils.ByteConverter;
import network.Messages.AverageWind;
import network.Utils.ByteConverter;
import java.util.Arrays;

@ -1,10 +1,14 @@
package network.MessageDecoders;
import seng302.Networking.Messages.BoatLocation;
import network.Messages.BoatLocation;
import java.util.Arrays;
import static seng302.Networking.Utils.ByteConverter.*;
import static network.Utils.ByteConverter.bytesToInt;
import static network.Utils.ByteConverter.bytesToLong;
import static network.Utils.ByteConverter.bytesToShort;
/**
* Created by hba56 on 21/04/17.

@ -1,11 +1,14 @@
package network.MessageDecoders;
import seng302.Networking.Messages.CourseWind;
import network.Messages.CourseWind;
import java.util.ArrayList;
import java.util.Arrays;
import static seng302.Networking.Utils.ByteConverter.*;
import static network.Utils.ByteConverter.bytesToInt;
import static network.Utils.ByteConverter.bytesToLong;
/**
* Created by hba56 on 23/04/17.

@ -1,7 +1,8 @@
package network.MessageDecoders;
import seng302.Networking.Messages.MarkRounding;
import seng302.Networking.Utils.ByteConverter;
import network.Messages.MarkRounding;
import network.Utils.ByteConverter;
import java.util.Arrays;

@ -3,7 +3,8 @@ package network.MessageDecoders;
import java.util.Arrays;
import static seng302.Networking.Utils.ByteConverter.*;
import static network.Utils.ByteConverter.*;
/**
* Created by hba56 on 21/04/17.

@ -1,11 +1,15 @@
package network.MessageDecoders;
import seng302.Networking.Messages.BoatStatus;
import network.Messages.BoatStatus;
import java.util.ArrayList;
import java.util.Arrays;
import static seng302.Networking.Utils.ByteConverter.*;
import static network.Utils.ByteConverter.bytesToInt;
import static network.Utils.ByteConverter.bytesToLong;
import static network.Utils.ByteConverter.bytesToShort;
/**
* Created by hba56 on 21/04/17.
@ -24,7 +28,7 @@ public class RaceStatusDecoder {
private long time;
private int race;
private int raceState;
private byte raceState;
private long startTime;
private int raceWindDir;
private short raceWindSpeed;
@ -47,7 +51,7 @@ public class RaceStatusDecoder {
time = bytesToLong(timeBytes);
race = bytesToInt(raceID);
raceState = bytesToInt(raceStatus);
raceState = raceStatus;
startTime = bytesToLong(expectedStart);
raceWindDir = bytesToInt(raceWind);
raceWindSpeed = bytesToShort(windSpeed);
@ -87,7 +91,7 @@ public class RaceStatusDecoder {
return race;
}
public int getRaceState() {
public byte getRaceState() {
return raceState;
}

@ -5,8 +5,9 @@ import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import static seng302.Networking.Utils.ByteConverter.bytesToLong;
import static seng302.Networking.Utils.ByteConverter.bytesToShort;
import static network.Utils.ByteConverter.bytesToLong;
import static network.Utils.ByteConverter.bytesToShort;
/**
* Created by hba56 on 20/04/17.

@ -1,11 +1,15 @@
package network.MessageEncoders;
import network.Messages.*;
import static network.Utils.ByteConverter.*;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import static seng302.Networking.Utils.ByteConverter.*;
/**
* Created by fwy13 on 19/04/17.

@ -2,7 +2,8 @@ package network.MessageEncoders;
import java.nio.ByteBuffer;
import static seng302.Networking.Utils.ByteConverter.*;
import static network.Utils.ByteConverter.*;
/**
* Encodes a XML file into a message of AC35 format

@ -1,7 +1,7 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
/**
* The base class for all message types.

@ -1,6 +1,7 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
/**
* Created by fwy13 on 25/04/17.

@ -1,19 +1,18 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import seng302.Networking.Utils.AC35UnitConverter;
import static seng302.Networking.Utils.AC35UnitConverter.convertGPS;
import static seng302.Networking.Utils.AC35UnitConverter.convertGPSToInt;
import network.Messages.Enums.MessageType;
import network.Utils.AC35UnitConverter;
import shared.model.Constants;
import static network.Utils.AC35UnitConverter.convertGPS;
import static network.Utils.AC35UnitConverter.convertGPSToInt;
/**
* Represents the information in a boat location message (AC streaming spec: 4.9).
*/
public class BoatLocation extends AC35Data {
//Knots x this = meters per second.
public static final double KnotsToMetersPerSecondConversionFactor =
0.514444;
public static final byte Unknown = 0;
public static final byte RacingYacht = 1;
public static final byte CommitteeBoat = 2;
@ -263,11 +262,8 @@ public class BoatLocation extends AC35Data {
* @return Speed in millimeters per second, stored as an int (using only the two least significant bytes).
*/
public static int convertBoatSpeedDoubleToInt(double speed) {
//Calculate meters per second.
double metersPerSecond = speed * KnotsToMetersPerSecondConversionFactor;
//Calculate millimeters per second.
double millimetersPerSecond = metersPerSecond * 1000.0;
double millimetersPerSecond = speed * Constants.KnotsToMMPerSecond;
//Convert to an int.
int millimetersPerSecondInt = (int) Math.round(millimetersPerSecond);
@ -282,11 +278,9 @@ public class BoatLocation extends AC35Data {
* @return Speed in knots, stored as a double.
*/
public static double convertBoatSpeedIntToDouble(int speed) {
//Calculate meters per second.
double metersPerSecond = speed / 1000.0;
//Calculate knots.
double knots = metersPerSecond / KnotsToMetersPerSecondConversionFactor;
double knots = speed / Constants.KnotsToMMPerSecond;
return knots;
}

@ -1,6 +1,7 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
/**
* Created by fwy13 on 21/04/17.

@ -1,8 +1,9 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import java.util.ArrayList;
import network.Messages.Enums.MessageType;
import java.util.List;
/**
* Created by fwy13 on 25/04/17.
@ -11,9 +12,9 @@ public class CourseWinds extends AC35Data {
private int msgVerNum;
private int selectedWindID;
private ArrayList<CourseWind> courseWinds;
private List<CourseWind> courseWinds;
public CourseWinds(int msgVerNum, int selectedWindID, ArrayList<CourseWind> courseWinds){
public CourseWinds(int msgVerNum, int selectedWindID, List<CourseWind> courseWinds){
super(MessageType.COURSEWIND);
this.msgVerNum = msgVerNum;
this.selectedWindID = selectedWindID;

@ -1,6 +1,7 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
/**
* Represents a Heartbeat message.

@ -1,6 +1,7 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
/**
* Created by fwy13 on 25/04/17.

@ -1,6 +1,7 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
/**
* Created by fwy13 on 19/04/17.

@ -1,6 +1,7 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
/**
* Created by fwy13 on 25/04/17.

@ -21,7 +21,7 @@ public class RaceStatus extends AC35Data {
private int raceType;
private List<BoatStatus> boatStatuses;
public RaceStatus(long currentTime, int raceID, int raceStatus, long expectedStartTime, int windDirection, int windSpeed, int raceType, List<BoatStatus> boatStatuses){
public RaceStatus(long currentTime, int raceID, byte raceStatus, long expectedStartTime, int windDirection, int windSpeed, int raceType, List<BoatStatus> boatStatuses){
super(MessageType.RACESTATUS);
this.currentTime = currentTime;
this.raceID = raceID;

@ -1,6 +1,7 @@
package network.Messages;
import seng302.Networking.Messages.Enums.MessageType;
import network.Messages.Enums.MessageType;
import java.io.InputStream;

@ -1,8 +1,9 @@
package network.PacketDump;
import seng302.Networking.BinaryMessageDecoder;
import seng302.Networking.Exceptions.InvalidMessageException;
import seng302.Networking.Messages.AC35Data;
import network.BinaryMessageDecoder;
import network.Exceptions.InvalidMessageException;
import network.Messages.AC35Data;
import java.io.IOException;
import java.net.URISyntaxException;

@ -77,25 +77,19 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource {
*/
private RaceTypeEnum raceType;
//TODO maybe remove these?
private Map<Integer, Boat> boats;
private Map<Integer, Mark> marks;
/**
* Constructor for Streamed Race XML
* @param filePath file path to read
* @param boatData data of the boats in race
* @throws XMLReaderException Thrown if an XML reader cannot be constructed for the given file.
* @throws InvalidRaceDataException Thrown if the XML file is invalid in some way.
*/
public RaceXMLReader(String filePath, BoatDataSource boatData) throws XMLReaderException, InvalidRaceDataException {
public RaceXMLReader(String filePath) throws XMLReaderException, InvalidRaceDataException {
super(filePath);
this.boats = boatData.getBoats();
this.marks = boatData.getMarkerBoats();
//Attempt to read race xml file.
try {

@ -7,7 +7,7 @@ import network.Messages.Enums.BoatStatusEnum;
/**
* Boat Model that is used to store information on the boats that are running in the race.
*/
public abstract class Boat {
public class Boat {
/**
* The name of the boat/team.
*/

@ -25,6 +25,21 @@ import static java.lang.Math.cos;
public abstract class Race implements Runnable {
/**
* The source of race related data.
*/
protected RaceDataSource raceDataSource;
/**
* The source of boat related data.
*/
protected BoatDataSource boatDataSource;
/**
* The source of regatta related data.
*/
protected RegattaDataSource regattaDataSource;
/**
* A list of compound marks in the race.
@ -90,15 +105,19 @@ public abstract class Race implements Runnable {
*/
public Race(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource) {
//Keep a reference to data sources.
this.raceDataSource = raceDataSource;
this.boatDataSource = boatDataSource;
this.regattaDataSource = regattaDataSource;
this.compoundMarks = raceDataSource.getCompoundMarks();
this.boundary = raceDataSource.getBoundary();
//We add a "dummy" leg at the end of the race.
this.legs = raceDataSource.getLegs();
this.legs.add(new Leg("Finish", this.legs.size()));
this.useLegsList(raceDataSource.getLegs());
this.raceId = raceDataSource.getRaceId();
@ -126,8 +145,15 @@ public abstract class Race implements Runnable {
protected abstract void initialiseBoats();
/**
* Updates the race to use a new list of legs, and adds a dummy "Finish" leg at the end.
* @param legs The new list of legs to use.
*/
protected void useLegsList(List<Leg> legs) {
//We add a "dummy" leg at the end of the race.
this.legs = legs;
this.legs.add(new Leg("Finish", this.legs.size()));
}
/**
* Determines whether or not a specific leg is the last leg in the race.

@ -14,6 +14,7 @@ import javafx.scene.paint.Color;
import visualiser.model.RaceClock;
import visualiser.model.Sparkline;
import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRace;
import java.net.URL;
import java.util.ArrayList;
@ -69,7 +70,7 @@ public class RaceController extends Controller {
*
* @param race Race to listen to.
*/
public void setInfoTable(StreamedRace race) {
public void setInfoTable(VisualiserRace race) {
boatInfoTable.setItems(race.getStartingBoats());
boatTeamColumn.setCellValueFactory(cellData -> cellData.getValue().getName());
boatSpeedColumn.setCellValueFactory(cellData -> cellData.getValue().getVelocityProp());

@ -41,14 +41,12 @@ public class VisualiserRace extends Race {
/**
* An observable list of marker boats in the race.
*/
private final ObservableList<Mark> boatMarkers;
private ObservableList<Mark> boatMarkers;
//TODO remove these controller references once refactored
private RaceController controller;
protected FinishController finishController;
//TODO remove?
private int lastFPS = 20;
public VisualiserRace(BoatDataSource boatDataSource, RaceDataSource raceDataSource, RegattaDataSource regattaDataSource, List<Color> colors, VisualiserInput visualiserInput, RaceController controller) {
@ -68,6 +66,39 @@ public class VisualiserRace extends Race {
}
/**
* Sets the race data source for this race to a new RaceDataSource.
* Uses the boundary and legs specified by the new RaceDataSource.
* @param raceDataSource The new RaceDataSource to use.
*/
public void setRaceDataSource(RaceDataSource raceDataSource) {
this.raceDataSource = raceDataSource;
this.boundary = raceDataSource.getBoundary();
this.useLegsList(raceDataSource.getLegs());
}
/**
* Sets the boat data source for this race to a new BoatDataSource.
* Uses the marker boats specified by the new BoatDataSource.
* @param boatDataSource The new BoatDataSource to use.
*/
public void setBoatDataSource(BoatDataSource boatDataSource) {
this.boatDataSource = boatDataSource;
this.boatMarkers = FXCollections.observableArrayList(boatDataSource.getMarkerBoats().values());
}
/**
* Sets the regatta data source for this race to a new RegattaDataSource.
* @param regattaDataSource The new RegattaDataSource to use.
*/
public void setRegattaDataSource(RegattaDataSource regattaDataSource) {
this.regattaDataSource = regattaDataSource;
}
/**
* Generates a list of VisualiserBoats given a list of Boats, and a list of participating boats.
* @param boats The map of Boats describing boats that are potentially in the race. Maps boat sourceID to boat.

Loading…
Cancel
Save