Merge branch 'splitIntoTwoModules' of https://eng-git.canterbury.ac.nz/seng302-2017/team-7 into splitIntoTwoModules

main
Erika Savell 9 years ago
commit 7f2d8107b8

@ -16,4 +16,5 @@
# https://www.kernel.org/pub/software/scm/git/docs/git-shortlog.html # https://www.kernel.org/pub/software/scm/git/docs/git-shortlog.html
# http://stacktoheap.com/blog/2013/01/06/using-mailmap-to-fix-authors-list-in-git/ # http://stacktoheap.com/blog/2013/01/06/using-mailmap-to-fix-authors-list-in-git/
Erika Savell <esa46@uclive.ac.nz> Erika Savell <esa46@uclive.ac.nz>
Connor Taylor-Brown <cbt24@cs17086jp.canterbury.ac.nz> <cbt24@uclive.canterbury.ac.nz> Connor Taylor-Brown <cbt24@cs17086jp.canterbury.ac.nz> <cbt24@uclive.canterbury.ac.nz>
Fraser Cope <fjc40@uclive.ac.nz>

@ -10,6 +10,7 @@ import seng302.Model.Event;
import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream;
public class App extends Application { public class App extends Application {
@ -25,9 +26,10 @@ public class App extends Application {
@Override @Override
public void start(Stage primaryStage) { public void start(Stage primaryStage) {
try { try {
OutputStream outputStream = System.out;//TEMP currently using System.out, but should replace this with tcp socket we are sending over.
RaceDataSource raceData = new RaceXMLReader("raceXML/bermuda_AC35.xml"); RaceDataSource raceData = new RaceXMLReader("raceXML/bermuda_AC35.xml");
RegattaDataSource regattaData = new RegattaXMLReader("mockXML/regattaTest.xml"); RegattaDataSource regattaData = new RegattaXMLReader("mockXML/regattaTest.xml");
Event raceEvent = new Event(raceData, regattaData); Event raceEvent = new Event(raceData, regattaData, outputStream);
raceEvent.start(); raceEvent.start();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();

@ -11,6 +11,9 @@ public class Constants {
public static final int NMToMetersConversion = 1852; // 1 nautical mile = 1852 meters public static final int NMToMetersConversion = 1852; // 1 nautical mile = 1852 meters
//Knots x this = meters per second.
public static final double KnotsToMetersPerSecondConversionFactor = 0.514444;
public static final GPSCoordinate startLineMarker1 = new GPSCoordinate(32.296577, -64.854304); public static final GPSCoordinate startLineMarker1 = new GPSCoordinate(32.296577, -64.854304);
public static final GPSCoordinate startLineMarker2 = new GPSCoordinate(32.293771, -64.855242); public static final GPSCoordinate startLineMarker2 = new GPSCoordinate(32.293771, -64.855242);
public static final GPSCoordinate mark1 = new GPSCoordinate(32.293039, -64.843983); public static final GPSCoordinate mark1 = new GPSCoordinate(32.293039, -64.843983);

@ -18,6 +18,7 @@ import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
import java.io.StringWriter;
import java.time.OffsetDateTime; import java.time.OffsetDateTime;
import java.util.List; import java.util.List;
@ -47,7 +48,7 @@ public class RaceData {
} }
public void createXML() { public String createXML() {
try { try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
@ -148,14 +149,13 @@ public class RaceData {
TransformerFactory transformerFactory = TransformerFactory.newInstance(); TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer(); Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc); DOMSource source = new DOMSource(doc);
StreamResult result = new StreamResult(System.out);
// Output to console for testing //Serialize document.
// StreamResult result = new StreamResult(System.out); StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
transformer.transform(source,result);
transformer.transform(source, result); return stringWriter.toString();
System.out.println("File saved!");
} catch (ParserConfigurationException pce) { } catch (ParserConfigurationException pce) {
@ -164,6 +164,7 @@ public class RaceData {
tfe.printStackTrace(); tfe.printStackTrace();
} }
return "";//TEMP this is probably bad. This shouldn't really be reached, but seems necessary due to the use of catches above.
} }

@ -0,0 +1,21 @@
package seng302.Exceptions;
/**
* Created by f123 on 25-Apr-17.
*/
/**
* An exception thrown when we cannot generate Boats.xml and send an XML message.
*/
public class InvalidBoatDataException extends RuntimeException
{
public InvalidBoatDataException()
{
}
public InvalidBoatDataException(String message)
{
super(message);
}
}

@ -0,0 +1,20 @@
package seng302.Exceptions;
/**
* Created by f123 on 25-Apr-17.
*/
/**
* Exception thrown when we cannot generate Race.xml data, and send an XML message.
*/
public class InvalidRaceDataException extends RuntimeException
{
public InvalidRaceDataException()
{
}
public InvalidRaceDataException(String message)
{
super(message);
}
}

@ -0,0 +1,20 @@
package seng302.Exceptions;
/**
* Created by f123 on 25-Apr-17.
*/
/**
* An exception thrown when a Regatta.xml message cannot be generated and sent.
*/
public class InvalidRegattaDataException extends RuntimeException
{
public InvalidRegattaDataException()
{
}
public InvalidRegattaDataException(String message)
{
super(message);
}
}

@ -29,6 +29,9 @@ public class BoatInRace extends Boat {
private StringProperty position; private StringProperty position;
private double heading; private double heading;
///While generating BoatLocationMessages, each one needs a sequence number relating to each boat.
private long sequenceNumber = 0;
private boolean trackVisible = true; private boolean trackVisible = true;
/** /**
@ -263,4 +266,18 @@ public class BoatInRace extends Boat {
this.position.set(position); this.position.set(position);
} }
/**
* Returns the current sequence number, and increments the internal value, such that that next call will return a value 1 larger than the current call.
* @return Current sequence number.
*/
public long getNextSequenceNumber(){
//Make a copy of current value.
long oldNumber = this.sequenceNumber;
//Increment.
this.sequenceNumber += 1;
//Return the previous value.
return oldNumber;
}
} }

@ -6,15 +6,24 @@ import org.w3c.dom.Element;
import seng302.Data.RaceData; import seng302.Data.RaceData;
import seng302.Mock.Regatta; import seng302.Mock.Regatta;
import seng302.Mock.RegattaDataSource; import seng302.Mock.RegattaDataSource;
import seng302.Exceptions.InvalidBoatDataException;
import seng302.Exceptions.InvalidRaceDataException;
import seng302.Exceptions.InvalidRegattaDataException;
import seng302.Model.Race; import seng302.Model.Race;
import seng302.RaceDataSource; import seng302.RaceDataSource;
import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer; import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory; import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource; import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamResult;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.util.List; import java.util.List;
/** /**
@ -24,34 +33,50 @@ public class Event {
RaceDataSource raceDataSource; RaceDataSource raceDataSource;
RegattaDataSource regattaDataSource; RegattaDataSource regattaDataSource;
///The stream to which we send all data.
private OutputStream outputStream;
public Event(RaceDataSource raceData, RegattaDataSource regattaData) { public Event(RaceDataSource raceData, RegattaDataSource regattaData, OutputStream outputStream) {
this.raceDataSource = raceData; this.raceDataSource = raceData;
this.regattaDataSource = regattaData; this.regattaDataSource = regattaData;
this.outputStream = outputStream;
} }
public void start() { public void start()
{
System.out.println("\nREGATTA DATA\n");//TEMP REMOVE debug
sendRegattaData(); sendRegattaData();
System.out.println("\nRACE DATA\n");//TEMP REMOVE debug
sendRaceData(); sendRaceData();
System.out.println("\nBOAT DATA\n");//TEMP REMOVE debug
sendBoatData(); sendBoatData();
Race newRace = new Race(raceDataSource, 15); System.out.println("RACE STARTING!!\n\n");//TEMP REMOVE debug
Race newRace = new Race(raceDataSource, 15, this.outputStream);
new Thread((newRace)).start(); new Thread((newRace)).start();
} }
public void sendRegattaData() { public void sendRegattaData() throws InvalidRegattaDataException {
try {
Regatta regatta = regattaDataSource.getRegatta(); Regatta regatta = regattaDataSource.getRegatta();
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance(); DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); DocumentBuilder docBuilder = null;
try
{
docBuilder = docFactory.newDocumentBuilder();
}
catch (ParserConfigurationException e)
{
throw new InvalidRegattaDataException();
}
//root element //root element
Document doc = docBuilder.newDocument(); Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("RegattaConfig"); Element rootElement = doc.createElement("RegattaConfig");
doc.appendChild(rootElement); doc.appendChild(rootElement);
//regattaID element //regattaID element
Element regattaID = doc.createElement("RegattaID"); Element regattaID = doc.createElement("RegattaID");
@ -93,121 +118,199 @@ public class Event {
magneticVariation.appendChild(doc.createTextNode(Double.toString(regatta.getMagneticVariation()))); magneticVariation.appendChild(doc.createTextNode(Double.toString(regatta.getMagneticVariation())));
rootElement.appendChild(magneticVariation); rootElement.appendChild(magneticVariation);
TransformerFactory trasformerFactory = TransformerFactory.newInstance(); TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = trasformerFactory.newTransformer(); Transformer transformer = null;
DOMSource source = new DOMSource(doc); try
{
transformer = transformerFactory.newTransformer();
}
catch (TransformerConfigurationException e)
{
throw new InvalidRegattaDataException();
}
DOMSource source = new DOMSource(doc);
//print XML object to check for correctness //Serialize document.
StreamResult result = new StreamResult(System.out); StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
try
{
transformer.transform(source,result); transformer.transform(source,result);
}
catch (TransformerException e)
{
throw new InvalidRegattaDataException();
}
//TODO now we should place in XML message object.
//TODO now we should serialize xml message object.
//TODO now we should write serialized xml message over this.outputStream.
} catch (Exception e){ try
e.printStackTrace(); {
this.outputStream.write(stringWriter.toString().getBytes());//TEMP currently we output the XML doc, not the serialized message.
} }
catch (IOException e)
{
throw new InvalidRegattaDataException();
}
} }
public void sendRaceData() { public void sendRaceData() throws InvalidRaceDataException
{
RaceData raceData = new RaceData(raceDataSource); RaceData raceData = new RaceData(raceDataSource);
raceData.createXML(); //Serialize race data to an XML as a string.
String xmlString = raceData.createXML();
//TODO now we should place in XML message object.
//TODO now we should serialize xml message object.
//TODO now we should write serialized xml message over this.outputStream.
try
{
this.outputStream.write(xmlString.getBytes());//TEMP currently we output the XML doc, not the serialized message.
}
catch (IOException e)
{
throw new InvalidRaceDataException();
}
} }
public void sendBoatData() { public void sendBoatData() throws InvalidBoatDataException
{
List<BoatInRace> boatData = raceDataSource.getBoats(); List<BoatInRace> boatData = raceDataSource.getBoats();
try {
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
//root element DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
Document doc = docBuilder.newDocument(); DocumentBuilder docBuilder = null;
Element rootElement = doc.createElement("BoatConfig");
doc.appendChild(rootElement);
//Boats element try
Element boats = doc.createElement("Boats"); {
rootElement.appendChild(boats); docBuilder = docFactory.newDocumentBuilder();
}
catch (ParserConfigurationException e)
{
throw new InvalidBoatDataException();
}
for (int i=0; i < boatData.size(); i++) { //root element
Document doc = docBuilder.newDocument();
Element rootElement = doc.createElement("BoatConfig");
doc.appendChild(rootElement);
//Boat element //Boats element
Element boat = doc.createElement("Boat"); Element boats = doc.createElement("Boats");
rootElement.appendChild(boats);
//Type attribute for (int i=0; i < boatData.size(); i++) {
Attr attrType = doc.createAttribute("Type");
attrType.setValue("Mark");
boat.setAttributeNode(attrType);
//SourceID attribute //Boat element
Attr attrSourceID = doc.createAttribute("SourceID"); Element boat = doc.createElement("Boat");
attrSourceID.setValue(Integer.toString(boatData.get(i).getSourceID()));
boat.setAttributeNode(attrSourceID);
//ShapeID attribute //Type attribute
Attr attrShapeID = doc.createAttribute("ShapeID"); Attr attrType = doc.createAttribute("Type");
attrShapeID.setValue("0"); attrType.setValue("Mark");
boat.setAttributeNode(attrShapeID); boat.setAttributeNode(attrType);
//HullNum attribute //SourceID attribute
Attr attrHullNum = doc.createAttribute("HullNum"); Attr attrSourceID = doc.createAttribute("SourceID");
attrHullNum.setValue("RG01"); attrSourceID.setValue(Integer.toString(boatData.get(i).getSourceID()));
boat.setAttributeNode(attrHullNum); boat.setAttributeNode(attrSourceID);
//StoweName attribute //ShapeID attribute
Attr attrStoweName = doc.createAttribute("StoweName"); Attr attrShapeID = doc.createAttribute("ShapeID");
attrStoweName.setValue(boatData.get(i).getAbbrev()); attrShapeID.setValue("0");
boat.setAttributeNode(attrStoweName); boat.setAttributeNode(attrShapeID);
//ShortName attribute //HullNum attribute
Attr attrShortName = doc.createAttribute("ShortName"); Attr attrHullNum = doc.createAttribute("HullNum");
attrShortName.setValue(boatData.get(i).getAbbrev()); attrHullNum.setValue("RG01");
boat.setAttributeNode(attrShortName); boat.setAttributeNode(attrHullNum);
//BoatName attribute //StoweName attribute
Attr attrBoatName = doc.createAttribute("BoatName"); Attr attrStoweName = doc.createAttribute("StoweName");
attrBoatName.setValue(boatData.get(i).toString()); attrStoweName.setValue(boatData.get(i).getAbbrev());
boat.setAttributeNode(attrBoatName); boat.setAttributeNode(attrStoweName);
//GPSCoord for element //ShortName attribute
Element GPSCoord = doc.createElement("GPSposition"); Attr attrShortName = doc.createAttribute("ShortName");
attrShortName.setValue(boatData.get(i).getAbbrev());
boat.setAttributeNode(attrShortName);
//Z axis attribute //BoatName attribute
Attr attrZCoord = doc.createAttribute("Z"); Attr attrBoatName = doc.createAttribute("BoatName");
attrZCoord.setValue("0"); attrBoatName.setValue(boatData.get(i).toString());
GPSCoord.setAttributeNode(attrZCoord); boat.setAttributeNode(attrBoatName);
//Y axis attribute //GPSCoord for element
Attr attrYCoord = doc.createAttribute("Y"); Element GPSCoord = doc.createElement("GPSposition");
attrYCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLatitude()));
GPSCoord.setAttributeNode(attrYCoord);
//X axis attribute //Z axis attribute
Attr attrXCoord = doc.createAttribute("X"); Attr attrZCoord = doc.createAttribute("Z");
attrXCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLongitude())); attrZCoord.setValue("0");
GPSCoord.setAttributeNode(attrXCoord); GPSCoord.setAttributeNode(attrZCoord);
//Write GPSCoord to boat //Y axis attribute
boat.appendChild(GPSCoord); Attr attrYCoord = doc.createAttribute("Y");
attrYCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLatitude()));
GPSCoord.setAttributeNode(attrYCoord);
//Write boat to boats //X axis attribute
boats.appendChild(boat); Attr attrXCoord = doc.createAttribute("X");
attrXCoord.setValue(Double.toString(boatData.get(i).getCurrentPosition().getLongitude()));
GPSCoord.setAttributeNode(attrXCoord);
} //Write GPSCoord to boat
boat.appendChild(GPSCoord);
TransformerFactory trasformerFactory = TransformerFactory.newInstance(); //Write boat to boats
Transformer transformer = trasformerFactory.newTransformer(); boats.appendChild(boat);
DOMSource source = new DOMSource(doc);
//print XML object to check for correctness }
StreamResult result = new StreamResult(System.out);
TransformerFactory trasformerFactory = TransformerFactory.newInstance();
Transformer transformer = null;
try
{
transformer = trasformerFactory.newTransformer();
}
catch (TransformerConfigurationException e)
{
throw new InvalidBoatDataException();
}
DOMSource source = new DOMSource(doc);
//Serialize document.
StringWriter stringWriter = new StringWriter();
StreamResult result = new StreamResult(stringWriter);
try
{
transformer.transform(source,result); transformer.transform(source,result);
}
catch (TransformerException e)
{
throw new InvalidBoatDataException();
}
//TODO now we should place in XML message object.
//TODO now we should serialize xml message object.
//TODO now we should write serialized xml message over this.outputStream.
} catch (Exception e) { try
e.printStackTrace(); {
this.outputStream.write(stringWriter.toString().getBytes());//TEMP currently we output the XML doc, not the serialized message.
}
catch (IOException e)
{
throw new InvalidBoatDataException();
} }
} }
} }

@ -11,9 +11,12 @@ import org.geotools.referencing.GeodeticCalculator;
import seng302.Constants; import seng302.Constants;
import seng302.GPSCoordinate; import seng302.GPSCoordinate;
import seng302.RaceDataSource; import seng302.RaceDataSource;
import seng302.RaceEventMessages.BoatLocationMessage;
import java.awt.geom.Point2D; import java.awt.geom.Point2D;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@ -38,26 +41,33 @@ public class Race implements Runnable {
protected int PRERACE_TIME = 120000; //time in milliseconds to pause during pre-race protected int PRERACE_TIME = 120000; //time in milliseconds to pause during pre-race
//Outputstream to write messages to.
private OutputStream outputStream;
/** /**
* Initailiser for Race * Initailiser for Race
* *
* @param boats Takes in an array of boats that are participating in the race. * @param boats Takes in an array of boats that are participating in the race.
* @param legs Number of marks in order that the boats pass in order to complete the race. * @param legs Number of marks in order that the boats pass in order to complete the race.
* @param scaleFactor for race * @param scaleFactor for race
* @param outputStream Outputstream to write messages to.
*/ */
public Race(List<BoatInRace> boats, List<Leg> legs, int scaleFactor) { public Race(List<BoatInRace> boats, List<Leg> legs, int scaleFactor, OutputStream outputStream) {
this.startingBoats = FXCollections.observableArrayList(boats); this.startingBoats = FXCollections.observableArrayList(boats);
this.legs = legs; this.legs = legs;
this.legs.add(new Leg("Finish", this.legs.size())); this.legs.add(new Leg("Finish", this.legs.size()));
this.scaleFactor = scaleFactor; this.scaleFactor = scaleFactor;
this.outputStream = outputStream;
if (startingBoats != null && startingBoats.size() > 0) { if (startingBoats != null && startingBoats.size() > 0) {
initialiseBoats(); initialiseBoats();
} }
} }
public Race(RaceDataSource raceData, int scaleFactor) { public Race(RaceDataSource raceData, int scaleFactor, OutputStream outputStream) {
this(raceData.getBoats(), raceData.getLegs(), scaleFactor); this(raceData.getBoats(), raceData.getLegs(), scaleFactor, outputStream);
} }
/** /**
@ -158,20 +168,70 @@ public class Race implements Runnable {
} }
new AnimationTimer() { new AnimationTimer() {
//Start time of loop.
long timeRaceStarted = System.currentTimeMillis(); //start time of loop long timeRaceStarted = System.currentTimeMillis();
@Override @Override
public void handle(long arg0) { public void handle(long arg0) {
if (boatsFinished < startingBoats.size()) { if (boatsFinished < startingBoats.size()) {
totalTimeElapsed = System.currentTimeMillis() - timeRaceStarted; //Get the current time.
long currentTime = System.currentTimeMillis();
//Update the total elapsed time.
totalTimeElapsed = currentTime - timeRaceStarted;
//For each boat, we update it's position, and generate a BoatLocationMessage.
for (BoatInRace boat : startingBoats) { for (BoatInRace boat : startingBoats) {
if (boat != null && !boat.isFinished()) { if (boat != null && !boat.isFinished()) {
//Update position.
updatePosition(boat, Math.round(1000 / lastFPS) > 20 ? 15 : Math.round(1000 / lastFPS)); updatePosition(boat, Math.round(1000 / lastFPS) > 20 ? 15 : Math.round(1000 / lastFPS));
checkPosition(boat, totalTimeElapsed); checkPosition(boat, totalTimeElapsed);
//Generate a boat location message for the updated boat.
BoatLocationMessage boatLocationMessage = new BoatLocationMessage();
boatLocationMessage.setTime(currentTime);
boatLocationMessage.setSourceID(boat.getSourceID());
boatLocationMessage.setSequenceNumber(boat.getNextSequenceNumber());
boatLocationMessage.setDeviceType(BoatLocationMessage.RacingYacht);
boatLocationMessage.setLatitude(BoatLocationMessage.convertCoordinateDoubleToInt(boat.getCurrentPosition().getLatitude()));
boatLocationMessage.setLongitude(BoatLocationMessage.convertCoordinateDoubleToInt(boat.getCurrentPosition().getLongitude()));
boatLocationMessage.setAltitude(0);//Junk value.
boatLocationMessage.setHeading(BoatLocationMessage.convertHeadingDoubleToInt(boat.getHeading()));
boatLocationMessage.setPitch((short)0);//Junk value.
boatLocationMessage.setRoll((short)0);//Junk value.
boatLocationMessage.setBoatSpeed(BoatLocationMessage.convertBoatSpeedDoubleToInt(boat.getVelocity()));
boatLocationMessage.setBoatCOG(0);//Junk value.
boatLocationMessage.setBoatSOG(0);//Junk value.
boatLocationMessage.setApparentWindSpeed(0);//Junk value.
boatLocationMessage.setApparentWindAngle((short)0);//Junk value.
boatLocationMessage.setTrueWindSpeed(0);//Junk value.
boatLocationMessage.setTrueWindAngle((short)0);//Junk value.
boatLocationMessage.setCurrentDrift(0);//Junk value.
boatLocationMessage.setCurrentSet(0);//Junk value.
boatLocationMessage.setRudderAngle((short)0);//Junk value.
//We have finished creating the message.
//TODO at this point, we need to send the event to the visualiser.
//System.out.println(boatLocationMessage);//TEMP debug print
try
{
//TODO we should actually serialize the boat message before writing to output.
outputStream.write(boatLocationMessage.toString().getBytes());
}
catch (IOException e)
{
e.printStackTrace();
}
} else { } else {
System.out.println("Race is over"); System.out.println("Race is over");//TEMP debug print
//raceFinish = true; //raceFinish = true;
stop(); stop();
} }
@ -194,7 +254,7 @@ public class Race implements Runnable {
boat.setPosition("-"); boat.setPosition("-");
} }
} }
System.out.println("====="); System.out.println("=====");//TEMP debug print
} }
public void initialiseBoats() { public void initialiseBoats() {

@ -4,6 +4,8 @@ package seng302.RaceEventMessages;
* Created by f123 on 21-Apr-17. * Created by f123 on 21-Apr-17.
*/ */
import seng302.Constants;
/** /**
* Represents the information in a boat location message (AC streaming spec: 4.9). * Represents the information in a boat location message (AC streaming spec: 4.9).
*/ */
@ -442,4 +444,112 @@ public class BoatLocationMessage
return angleShort; return angleShort;
} }
/**
* Converts a double representing the speed of a boat in knots to an int in millimeters per second, as required by the streaming spec format.
* @param speed Speed in knots, stored as a double.
* @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 * Constants.KnotsToMetersPerSecondConversionFactor;
//Calculate millimeters per second.
double millimetersPerSecond = metersPerSecond * 1000.0;
//Convert to an int.
int millimetersPerSecondInt = (int)Math.round(millimetersPerSecond);
return millimetersPerSecondInt;
}
/**
* Converts an int representing the speed of a boat in millimeters per second to a double in knots, as required by the streaming spec format.
* @param speed Speed in millimeters per second, stored as an int.
* @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 / Constants.KnotsToMetersPerSecondConversionFactor;
return knots;
}
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("Message version number: ");
builder.append(this.getMessageVersionNumber());
builder.append("\nTime: ");
builder.append(this.getTime());
builder.append("\nSource ID: ");
builder.append(this.getSourceID());
builder.append("\nSequence number: ");
builder.append(this.getSequenceNumber());
builder.append("\nDevice type: ");
builder.append(this.getDeviceType());
builder.append("\nLatitude: ");
builder.append(this.getLatitude());
builder.append("\nLongitude: ");
builder.append(this.getLongitude());
builder.append("\nAltitude: ");
builder.append(this.getAltitude());
builder.append("\nHeading: ");
builder.append(this.getHeading());
builder.append("\nPitch: ");
builder.append(this.getPitch());
builder.append("\nRoll: ");
builder.append(this.getRoll());
builder.append("\nBoat speed (mm/sec): ");
builder.append(this.getBoatSpeed());
builder.append("\nBoat COG: ");
builder.append(this.getBoatCOG());
builder.append("\nBoat SOG: ");
builder.append(this.getBoatSOG());
builder.append("\nApparent wind speed: ");
builder.append(this.getApparentWindSpeed());
builder.append("\nApparent wind angle: ");
builder.append(this.getApparentWindAngle());
builder.append("\nTrue wind speed: ");
builder.append(this.getTrueWindSpeed());
builder.append("\nTrue wind angle: ");
builder.append(this.getTrueWindAngle());
builder.append("\nCurrent drift: ");
builder.append(this.getCurrentDrift());
builder.append("\nCurrent set: ");
builder.append(this.getCurrentSet());
builder.append("\nRudder angle: ");
builder.append(this.getRudderAngle());
return builder.toString();
}
} }

Loading…
Cancel
Save