diff --git a/.idea/codeStyleSettings.xml b/.idea/codeStyleSettings.xml
deleted file mode 100644
index 5352bdf8..00000000
--- a/.idea/codeStyleSettings.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
\ No newline at end of file
diff --git a/racevisionGame/pom.xml b/racevisionGame/pom.xml
index 98ccaf82..20a732be 100644
--- a/racevisionGame/pom.xml
+++ b/racevisionGame/pom.xml
@@ -78,6 +78,18 @@
0.7
+
+ org.apache.httpcomponents
+ httpclient
+ 4.5.3
+
+
+
+ org.json
+ json
+ 20160810
+
+
diff --git a/racevisionGame/src/main/java/mock/app/Event.java b/racevisionGame/src/main/java/mock/app/Event.java
index a9f55a7f..1e1b8966 100644
--- a/racevisionGame/src/main/java/mock/app/Event.java
+++ b/racevisionGame/src/main/java/mock/app/Event.java
@@ -80,6 +80,7 @@ public class Event {
* @throws EventConstructionException Thrown if we cannot create an Event for any reason.
*/
public Event(boolean singlePlayer, int mapIndex) throws EventConstructionException {
+ PolarParser.parseNewPolars("mock/polars/acc_polars.csv");
this.mapIndex = mapIndex;
String raceXMLFile;
String boatsXMLFile = "mock/mockXML/boatTest.xml";
@@ -109,6 +110,7 @@ public class Event {
}
double windAngle = 300;
+ double windSpeed = 12;
//Read XML files.
try {
@@ -119,6 +121,7 @@ public class Event {
this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, -1, true);
} else {
this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, windAngle, false);
+ this.raceXML = RaceXMLCreator.scaleRaceSize(raceXML, windSpeed, 15 * 60 * 1000);
}
this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8);
@@ -131,7 +134,6 @@ public class Event {
this.xmlFileType = XMLFileType.Contents;
this.boatPolars = PolarParser.parse("mock/polars/acc_polars.csv");
- PolarParser.parseNewPolars("mock/polars/acc_polars.csv");
//Parse the XML files into data sources.
@@ -152,7 +154,7 @@ public class Event {
WindGenerator windGenerator = new ShiftingWindGenerator(
Bearing.fromDegrees(windAngle),
- 12
+ windSpeed
);
MockRace mockRace = new MockRace(
diff --git a/racevisionGame/src/main/java/mock/model/RaceServer.java b/racevisionGame/src/main/java/mock/model/RaceServer.java
index 7f213a72..103e4d66 100644
--- a/racevisionGame/src/main/java/mock/model/RaceServer.java
+++ b/racevisionGame/src/main/java/mock/model/RaceServer.java
@@ -24,7 +24,6 @@ import java.util.logging.Logger;
public class RaceServer {
private MockRace race;
private LatestMessages latestMessages;
- private static RaceServer server;
private List collisionEvents = new ArrayList<>();
@@ -50,16 +49,10 @@ public class RaceServer {
public RaceServer(MockRace race, LatestMessages latestMessages) {
- server = this;
this.race = race;
this.latestMessages = latestMessages;
}
- public static void staticUpdateXML() {
- if (server != null) {
- server.updateXMLFiles();
- }
- }
/**
* Parses the race to create a snapshot, and places it in latestMessages.
diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java
index 75024013..2c15e57f 100644
--- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java
+++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java
@@ -1,17 +1,16 @@
package mock.xml;
+import mock.model.NewPolars;
import org.xml.sax.SAXException;
import shared.dataInput.RaceXMLReader;
import shared.enums.XMLFileType;
import shared.exceptions.InvalidRaceDataException;
import shared.exceptions.XMLReaderException;
+import shared.model.Bearing;
import shared.model.CompoundMark;
import shared.model.Constants;
import shared.model.GPSCoordinate;
-import shared.xml.Race.XMLCompoundMark;
-import shared.xml.Race.XMLLimit;
-import shared.xml.Race.XMLMark;
-import shared.xml.Race.XMLRace;
+import shared.xml.Race.*;
import shared.xml.XMLUtilities;
import javax.xml.bind.JAXBException;
@@ -20,6 +19,8 @@ import java.io.IOException;
import java.io.InputStream;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
+import java.util.Collections;
+import java.util.Comparator;
/**
* Helper Class for creating a Race XML
@@ -125,6 +126,140 @@ public class RaceXMLCreator {
}
}
+
+ /**
+ * Rotates the race in a specified direction.
+ * @param s xml file name or contents.
+ * @param windSpeed speed that the wind is at.
+ * @param milliseconds time the race should take at fastest
+ * @return the new xml file as a string
+ * @throws XMLReaderException if the xml is not readable
+ * @throws InvalidRaceDataException if the race is invalid
+ */
+ public static String scaleRaceSize(String s, double windSpeed, double milliseconds) throws XMLReaderException, InvalidRaceDataException {
+
+ try {
+
+ XMLRace race = XMLUtilities.xmlToClass(
+ s,
+ RaceXMLCreator.class.getClassLoader().getResource("mock/mockXML/schema/raceSchema.xsd"),
+ XMLRace.class);
+
+ scaleRace(race, windSpeed, milliseconds);
+
+ return XMLUtilities.classToXML(race);
+
+ } catch (ParserConfigurationException | IOException | SAXException | JAXBException e) {
+ throw new InvalidRaceDataException("Could not parse or marshall race data file.", e);
+ }
+ }
+
+ /**
+ * Gets an estimate of how long a race will take using an average Speed
+ * @param race race to estimate
+ * @param averageSpeed average speed that the boats move at
+ * @return the estimated amount of time it will take a boat to finish the race (skewed to minimum).
+ */
+ public static double getRaceLength(XMLRace race, double averageSpeed){
+ double raceRoundingTime = 5000; //5 seconds to round a mark
+ double totalDistance = 0; //in nautical miles
+ XMLMark prevMark = null;
+ double avgSpeed = averageSpeed / 60 / 60; //knots is /hour
+ for (XMLCorner corner : race.getCompoundMarkSequence().getCorner()){
+ int index = corner.getCompoundMarkID() - 1;
+ XMLCompoundMark cm = race.getCourse().getCompoundMark().get(index);
+ XMLMark mark = cm.getMark().get(0);
+ if (prevMark != null){
+ totalDistance += getDistance(mark, prevMark);
+ }
+ prevMark = mark;
+ }
+ //total time = total dist / average speed + race extra rounding time * number of marks
+ double totalTime = totalDistance / avgSpeed * 1000 +
+ raceRoundingTime * race.getCompoundMarkSequence().getCorner().size();
+ return totalTime;
+ }
+
+ /**
+ * gets the destance between two marks
+ * @param a mark 1
+ * @param b mark 2
+ * @return
+ */
+ private static double getDistance(XMLMark a, XMLMark b){
+ GPSCoordinate coorda = new GPSCoordinate(a.getTargetLat(), a.getTargetLng());
+ GPSCoordinate coordb = new GPSCoordinate(b.getTargetLat(), b.getTargetLng());
+ return GPSCoordinate.calculateDistanceNauticalMiles(coorda, coordb);
+ }
+
+ /**
+ * Scales the race based on the windspeed the race is running at and the amount of time it should be completed in.
+ * @param race Race to scale
+ * @param windSpeed windspeed of the race, this is used with the polars
+ * @param milliseconds milliseconds the race should take.
+ */
+ private static void scaleRace(XMLRace race, double windSpeed, double milliseconds) {
+ GPSCoordinate center = getCenter(race);
+ //sort the compound marks
+ Collections.sort(race.getCompoundMarkSequence().getCorner(), (c1, c2) -> {
+ if (c1.getSeqID() < c2.getSeqID()) return -1;
+ if (c1.getSeqID() > c2.getSeqID()) return 1;
+ return 0;
+ });
+ //sort compound mark id
+ Collections.sort(race.getCourse().getCompoundMark(), (c1, c2) -> {
+ if (c1.getCompoundMarkID() < c2.getCompoundMarkID()) return -1;
+ if (c1.getCompoundMarkID() > c2.getCompoundMarkID()) return 1;
+ return 0;
+ });
+ //get the fastest time it would take.
+ double bestUpWindSpeed = NewPolars.setBestVMG(Bearing.fromDegrees(0), windSpeed, Bearing.fromDegrees(45)).getSpeed();
+ double bestDownWindSpeed = NewPolars.setBestVMG(Bearing.fromDegrees(0), windSpeed, Bearing.fromDegrees(45)).getSpeed();
+ double averageSpeed = (bestDownWindSpeed + bestUpWindSpeed) / 2;
+ double raceApproximateTime = getRaceLength(race, averageSpeed);
+ double scale = milliseconds / raceApproximateTime;
+ for (XMLCorner cm: race.getCompoundMarkSequence().getCorner()){
+ int index = cm.getCompoundMarkID() - 1;
+ XMLCompoundMark mark = race.getCourse().getCompoundMark().get(index);
+ for (XMLMark m: mark.getMark()){
+ scalePoint(m, center, scale);
+ }
+ }
+ for (XMLLimit limit: race.getCourseLimit().getLimit()){
+ scalePoint(limit, center, scale);
+ }
+ }
+
+ /**
+ * Scales a point from the the center(pivot)
+ * @param mark mark the scale
+ * @param center center as pivot
+ * @param scale scale to scale at.
+ */
+ private static void scalePoint(XMLMark mark, GPSCoordinate center, double scale){
+ double latDiff = mark.getTargetLat() - center.getLatitude();
+ double longDiff = mark.getTargetLng() - center.getLongitude();
+ double latScaled = latDiff * scale + center.getLatitude();
+ double longScaled = longDiff * scale + center.getLongitude();
+ mark.setTargetLat(latScaled);
+ mark.setTargetLng(longScaled);
+ }
+
+ /**
+ * Scales a boundary from the center(pivot)
+ * @param limit boundary point
+ * @param center pivot
+ * @param scale scale
+ */
+ private static void scalePoint(XMLLimit limit, GPSCoordinate center, double scale){
+ double latDiff = limit.getLat() - center.getLatitude();
+ double longDiff = limit.getLon() - center.getLongitude();
+ double latScaled = latDiff * scale + center.getLatitude();
+ double longScaled = longDiff * scale + center.getLongitude();
+ limit.setLat(latScaled);
+ limit.setLon(longScaled);
+ }
+
/**
* Converts a Race.CourseLimit.Limit to a GPS coordinate
* @param limit limit to convert
diff --git a/racevisionGame/src/main/java/network/Messages/LatestMessages.java b/racevisionGame/src/main/java/network/Messages/LatestMessages.java
index 86f02d91..8b395b1c 100644
--- a/racevisionGame/src/main/java/network/Messages/LatestMessages.java
+++ b/racevisionGame/src/main/java/network/Messages/LatestMessages.java
@@ -157,11 +157,10 @@ public class LatestMessages extends Observable {
return false;
} else {
- RaceServer.staticUpdateXML();
return true;
}
}
-}
\ No newline at end of file
+}
diff --git a/racevisionGame/src/main/java/shared/dataInput/BoatXMLReader.java b/racevisionGame/src/main/java/shared/dataInput/BoatXMLReader.java
index 25c956d9..d3e77be8 100644
--- a/racevisionGame/src/main/java/shared/dataInput/BoatXMLReader.java
+++ b/racevisionGame/src/main/java/shared/dataInput/BoatXMLReader.java
@@ -183,6 +183,10 @@ public class BoatXMLReader extends XMLReader implements BoatDataSource {
return sequenceNumber;
}
+ public void setSequenceNumber(int sequenceNumber) {
+ this.sequenceNumber = sequenceNumber;
+ }
+
@Override
public void incrementSequenceNumber() {
sequenceNumber++;
diff --git a/racevisionGame/src/main/java/shared/dataInput/EmptyBoatDataSource.java b/racevisionGame/src/main/java/shared/dataInput/EmptyBoatDataSource.java
index 7a8d2151..1579c0f0 100644
--- a/racevisionGame/src/main/java/shared/dataInput/EmptyBoatDataSource.java
+++ b/racevisionGame/src/main/java/shared/dataInput/EmptyBoatDataSource.java
@@ -22,7 +22,7 @@ public class EmptyBoatDataSource implements BoatDataSource {
private final Map markerMap = new HashMap<>();
- private int sequenceNumber = 0;
+ private int sequenceNumber = -1;
public EmptyBoatDataSource() {
diff --git a/racevisionGame/src/main/java/shared/dataInput/EmptyRaceDataSource.java b/racevisionGame/src/main/java/shared/dataInput/EmptyRaceDataSource.java
index 676d7e70..e395e51f 100644
--- a/racevisionGame/src/main/java/shared/dataInput/EmptyRaceDataSource.java
+++ b/racevisionGame/src/main/java/shared/dataInput/EmptyRaceDataSource.java
@@ -84,7 +84,7 @@ public class EmptyRaceDataSource implements RaceDataSource {
private RaceTypeEnum raceType = RaceTypeEnum.NOT_A_RACE_TYPE;
- private int sequenceNumber = 0;
+ private int sequenceNumber = -1;
public EmptyRaceDataSource() {
diff --git a/racevisionGame/src/main/java/shared/dataInput/EmptyRegattaDataSource.java b/racevisionGame/src/main/java/shared/dataInput/EmptyRegattaDataSource.java
index 1546972e..2fdf70c6 100644
--- a/racevisionGame/src/main/java/shared/dataInput/EmptyRegattaDataSource.java
+++ b/racevisionGame/src/main/java/shared/dataInput/EmptyRegattaDataSource.java
@@ -60,7 +60,7 @@ public class EmptyRegattaDataSource implements RegattaDataSource {
- private int sequenceNumber = 0;
+ private int sequenceNumber = -1;
public EmptyRegattaDataSource() {
diff --git a/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java b/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java
index 41d60e5f..af274a9c 100644
--- a/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java
+++ b/racevisionGame/src/main/java/shared/dataInput/RaceXMLReader.java
@@ -499,6 +499,10 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource {
return sequenceNumber;
}
+ public void setSequenceNumber(int sequenceNumber) {
+ this.sequenceNumber = sequenceNumber;
+ }
+
@Override
public void incrementSequenceNumber() {
sequenceNumber++;
diff --git a/racevisionGame/src/main/java/shared/dataInput/RegattaXMLReader.java b/racevisionGame/src/main/java/shared/dataInput/RegattaXMLReader.java
index 36743105..3628c429 100644
--- a/racevisionGame/src/main/java/shared/dataInput/RegattaXMLReader.java
+++ b/racevisionGame/src/main/java/shared/dataInput/RegattaXMLReader.java
@@ -217,6 +217,10 @@ public class RegattaXMLReader extends XMLReader implements RegattaDataSource {
return sequenceNumber;
}
+ public void setSequenceNumber(int sequenceNumber) {
+ this.sequenceNumber = sequenceNumber;
+ }
+
@Override
public void incrementSequenceNumber() {
sequenceNumber++;
diff --git a/racevisionGame/src/main/java/shared/model/RaceState.java b/racevisionGame/src/main/java/shared/model/RaceState.java
index b4a845e2..44debda8 100644
--- a/racevisionGame/src/main/java/shared/model/RaceState.java
+++ b/racevisionGame/src/main/java/shared/model/RaceState.java
@@ -148,9 +148,11 @@ public abstract class RaceState extends Observable{
* @param raceDataSource New race data source.
*/
public void setRaceDataSource(RaceDataSource raceDataSource) {
- this.raceDataSource = raceDataSource;
- this.getRaceClock().setStartingTime(raceDataSource.getStartDateTime());
- useLegsList(raceDataSource.getLegs());
+ if ((this.raceDataSource == null) || (raceDataSource.getSequenceNumber() > this.raceDataSource.getSequenceNumber())) {
+ this.raceDataSource = raceDataSource;
+ this.getRaceClock().setStartingTime(raceDataSource.getStartDateTime());
+ useLegsList(raceDataSource.getLegs());
+ }
}
/**
@@ -158,7 +160,9 @@ public abstract class RaceState extends Observable{
* @param boatDataSource New boat data source.
*/
public void setBoatDataSource(BoatDataSource boatDataSource) {
- this.boatDataSource = boatDataSource;
+ if ((this.boatDataSource == null) || (boatDataSource.getSequenceNumber() > this.boatDataSource.getSequenceNumber())) {
+ this.boatDataSource = boatDataSource;
+ }
}
/**
@@ -166,7 +170,9 @@ public abstract class RaceState extends Observable{
* @param regattaDataSource New regatta data source.
*/
public void setRegattaDataSource(RegattaDataSource regattaDataSource) {
- this.regattaDataSource = regattaDataSource;
+ if ((this.regattaDataSource == null) || (regattaDataSource.getSequenceNumber() > this.regattaDataSource.getSequenceNumber())) {
+ this.regattaDataSource = regattaDataSource;
+ }
}
diff --git a/racevisionGame/src/main/java/shared/utils/JsonReader.java b/racevisionGame/src/main/java/shared/utils/JsonReader.java
new file mode 100644
index 00000000..44e55c98
--- /dev/null
+++ b/racevisionGame/src/main/java/shared/utils/JsonReader.java
@@ -0,0 +1,70 @@
+package shared.utils;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.*;
+import java.net.URL;
+import java.nio.charset.Charset;
+
+/**
+ * A helper class that has functions to read information from a url to json object.
+ */
+public class JsonReader {
+
+ /**
+ * Reads all data from a Reader
+ * @param rd reader to read from
+ * @return string that the reader has currently read
+ * @throws IOException if the reader is invalid
+ */
+ private static String readAll(Reader rd) throws IOException {
+ StringBuilder sb = new StringBuilder();
+ int cp;
+ while ((cp = rd.read()) != -1) {
+ sb.append((char) cp);
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Reads a Json Object from a URL
+ * @param url url to read from
+ * @return JSONObject that has been read
+ * @throws IOException if the reader cannot obtain information
+ * @throws JSONException if the read information is not json parsable.
+ */
+ public static JSONObject readJsonFromUrl(String url) throws IOException, JSONException {
+ InputStream is = new URL(url).openStream();
+ try {
+ BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
+ String jsonText = readAll(rd);
+ JSONObject json = new JSONObject(jsonText);
+ return json;
+ } catch (JSONException e) {
+ return null;
+ } finally {
+ is.close();
+ }
+ }
+
+ /**
+ * Reads a Json Array from a URL
+ * @param url url to read from
+ * @return JSONArray that has been read
+ * @throws IOException if the reader cannot obtain information
+ * @throws JSONException if the read information is not json parsable.
+ */
+ public static JSONArray readJsonFromUrlArray(String url) throws IOException, JSONException {
+ InputStream is = new URL(url).openStream();
+ try {
+ BufferedReader rd = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
+ String jsonText = readAll(rd);
+ JSONArray json = new JSONArray(jsonText);
+ return json;
+ } finally {
+ is.close();
+ }
+ }
+}
diff --git a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatsXMLMessageCommand.java b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatsXMLMessageCommand.java
index 7f56d745..ce58e8a1 100644
--- a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatsXMLMessageCommand.java
+++ b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/BoatsXMLMessageCommand.java
@@ -41,8 +41,8 @@ public class BoatsXMLMessageCommand implements Command {
@Override
public void execute() {
-
- visualiserRace.setBoatDataSource(boatDataSource);
-
+ if (boatDataSource.getSequenceNumber() > visualiserRace.getBoatDataSource().getSequenceNumber()) {
+ visualiserRace.setBoatDataSource(boatDataSource);
+ }
}
}
diff --git a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/RaceXMLMessageCommand.java b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/RaceXMLMessageCommand.java
index 0b194674..dbf20544 100644
--- a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/RaceXMLMessageCommand.java
+++ b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/RaceXMLMessageCommand.java
@@ -38,7 +38,9 @@ public class RaceXMLMessageCommand implements Command {
@Override
public void execute() {
- visualiserRace.setRaceDataSource(raceDataSource);
+ if (raceDataSource.getSequenceNumber() > visualiserRace.getRaceDataSource().getSequenceNumber()) {
+ visualiserRace.setRaceDataSource(raceDataSource);
+ }
}
}
diff --git a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/RegattaXMLMessageCommand.java b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/RegattaXMLMessageCommand.java
index 6597e557..ea146d12 100644
--- a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/RegattaXMLMessageCommand.java
+++ b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/RegattaXMLMessageCommand.java
@@ -37,8 +37,9 @@ public class RegattaXMLMessageCommand implements Command {
@Override
public void execute() {
-
- visualiserRace.setRegattaDataSource(regattaDataSource);
+ if (regattaDataSource.getSequenceNumber() > visualiserRace.getRegattaDataSource().getSequenceNumber()) {
+ visualiserRace.setRegattaDataSource(regattaDataSource);
+ }
}
}
diff --git a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/XMLMessageCommandFactory.java b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/XMLMessageCommandFactory.java
index b9b58f1c..c5e93d8e 100644
--- a/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/XMLMessageCommandFactory.java
+++ b/racevisionGame/src/main/java/visualiser/Commands/VisualiserRaceCommands/XMLMessageCommandFactory.java
@@ -34,17 +34,20 @@ public class XMLMessageCommandFactory {
switch (message.getXmlMsgSubType()) {
case BOAT:
- BoatDataSource boatDataSource = new BoatXMLReader(message.getXmlMessage(), XMLFileType.Contents);
+ BoatXMLReader boatDataSource = new BoatXMLReader(message.getXmlMessage(), XMLFileType.Contents);
+ boatDataSource.setSequenceNumber(message.getSequenceNumber());
return new BoatsXMLMessageCommand(boatDataSource, visualiserRace);
case RACE:
- RaceDataSource raceDataSource = new RaceXMLReader(message.getXmlMessage(), XMLFileType.Contents);
+ RaceXMLReader raceDataSource = new RaceXMLReader(message.getXmlMessage(), XMLFileType.Contents);
+ raceDataSource.setSequenceNumber(message.getSequenceNumber());
return new RaceXMLMessageCommand(raceDataSource, visualiserRace);
case REGATTA:
- RegattaDataSource regattaDataSource = new RegattaXMLReader(message.getXmlMessage(), XMLFileType.Contents);
+ RegattaXMLReader regattaDataSource = new RegattaXMLReader(message.getXmlMessage(), XMLFileType.Contents);
+ regattaDataSource.setSequenceNumber(message.getSequenceNumber());
return new RegattaXMLMessageCommand(regattaDataSource, visualiserRace);
diff --git a/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java b/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java
index b532ded2..33583a38 100644
--- a/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java
+++ b/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java
@@ -11,6 +11,7 @@ import mock.exceptions.EventConstructionException;
import network.Messages.Enums.RequestToJoinEnum;
import visualiser.app.App;
import visualiser.app.MatchBrowserSingleton;
+import visualiser.network.HttpMatchBrowserHost;
import visualiser.network.MatchBrowserInterface;
import java.io.IOException;
@@ -65,8 +66,11 @@ public class HostGameController extends Controller {
try {
App.game = new Event(false, currentMapIndex);
App.gameType = currentMapIndex;
+
+ HttpMatchBrowserHost matchBrowserHost = new HttpMatchBrowserHost();
+ new Thread(matchBrowserHost).start();
connectSocket("localhost", 4942);
- alertMatchBrowser();
+ //alertMatchBrowser();
} catch (EventConstructionException e) {
Logger.getGlobal().log(Level.SEVERE, "Could not create Event.", e);
diff --git a/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java
index e6f6469e..38544ba6 100644
--- a/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java
+++ b/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java
@@ -15,11 +15,13 @@ import javafx.scene.control.Label;
import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane;
+import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.MeshView;
import mock.app.Event;
import network.Messages.Enums.RaceStatusEnum;
import network.Messages.Enums.RequestToJoinEnum;
+import shared.model.Boat;
import visualiser.app.App;
import visualiser.gameController.ControllerClient;
import visualiser.layout.SeaSurface;
@@ -28,6 +30,7 @@ import visualiser.layout.View3D;
import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRaceEvent;
import visualiser.model.VisualiserRaceState;
+import visualiser.network.HttpMatchBrowserHost;
import java.io.IOException;
import java.net.Socket;
@@ -124,61 +127,69 @@ public class InGameLobbyController extends Controller {
@Override
public void onChanged(Change change) {
- Platform.runLater(
- () -> {
- while (change.next()){
- if (change.wasAdded() || change.wasRemoved() || change.wasUpdated()){
- try{
- resetLobby();
- int count = 0;
- int row = 0;
- for (VisualiserBoat boat :visualiserRaceEvent.getVisualiserRaceState().getBoats()) {
- View3D playerBoatToSet = new View3D();
- playerBoatToSet.setItems(subjects);
-
- playerContainer.add(playerBoatToSet, (count % 3) , row);
- playerContainer.setMargin(playerBoatToSet, new Insets(10, 10, 10, 10));
-
- SeaSurface sea = new SeaSurface(750, 200);
- sea.setX(250);
- sea.setZ(210);
- subjects.add(sea);
-
- MeshView mesh = new MeshView(importer.getImport());
- PhongMaterial boatColorMat = new PhongMaterial(boat.getColor());
- mesh.setMaterial(boatColorMat);
- Subject3D subject = new Subject3D(mesh,0);
- subjects.add(subject);
-
- playerBoatToSet.setDistance(50);
- playerBoatToSet.setYaw(45);
- playerBoatToSet.setPitch(20);
-
-
-
- AnimationTimer rotate = new AnimationTimer() {
- @Override
- public void handle(long now) {
- subject.setHeading(subject.getHeading().getAngle() + 0.1);
- }
- };
- rotate.start();
-
- allPlayerLabels.get(count).setText(boat.getName());
- allPlayerLabels.get(count).toFront();
- count += 1;
- if (count > 2){
- row = 1;
- }
- }
- }
- catch(ConcurrentModificationException e){
- }
- }
+ Platform.runLater(() -> {
+ while (change.next()) {
+ if (change.wasAdded() || change.wasRemoved() || change.wasUpdated()) {
+ populateLobby();
+ }
+ }
+ });
+ }
+
+ public void populateLobby() {
+
+ try{
+ resetLobby();
+ int count = 0;
+ int row = 0;
+
+ ArrayList copy = new ArrayList<>(visualiserRaceEvent.getVisualiserRaceState().getBoats());
+
+ for (VisualiserBoat boat : copy) {
+ View3D playerBoatToSet = new View3D();
+ playerBoatToSet.setItems(subjects);
+
+ playerContainer.add(playerBoatToSet, (count % 3) , row);
+ playerContainer.setMargin(playerBoatToSet, new Insets(10, 10, 10, 10));
+
+ SeaSurface sea = new SeaSurface(750, 200);
+ sea.setX(250);
+ sea.setZ(210);
+ subjects.add(sea);
+
+ MeshView mesh = new MeshView(importer.getImport());
+ PhongMaterial boatColorMat = new PhongMaterial(boat.getColor());
+ mesh.setMaterial(boatColorMat);
+ Subject3D subject = new Subject3D(mesh,0);
+ subjects.add(subject);
+
+ playerBoatToSet.setDistance(50);
+ playerBoatToSet.setYaw(45);
+ playerBoatToSet.setPitch(20);
+
+
+
+ AnimationTimer rotate = new AnimationTimer() {
+ @Override
+ public void handle(long now) {
+ subject.setHeading(subject.getHeading().getAngle() + 0.1);
}
+ };
+ rotate.start();
+
+ allPlayerLabels.get(count).setText(boat.getName());
+ allPlayerLabels.get(count).toFront();
+ count += 1;
+ if (count > 2){
+ row = 1;
}
- );
+ }
+ }
+ catch(ConcurrentModificationException e){
+ e.printStackTrace();
+ }
}
+
}
/*
private void populatePlayers(ListChangeListener.Change change){
@@ -191,7 +202,6 @@ public class InGameLobbyController extends Controller {
//Initialises the race clock.
initialiseRaceClock(this.visualiserRaceEvent.getVisualiserRaceState());
-
//Starts the race countdown timer.
countdownTimer();
}
@@ -227,10 +237,9 @@ public class InGameLobbyController extends Controller {
new AnimationTimer() {
@Override
public void handle(long arg0) {
-
//Get the current race status.
RaceStatusEnum raceStatus = visualiserRaceEvent.getVisualiserRaceState().getRaceStatusEnum();
-
+
//Try catch for getting interval times
try {
long interval = ChronoUnit.MILLIS.between(visualiserRaceEvent.getVisualiserRaceState().getRaceClock().getCurrentTime(), visualiserRaceEvent.getVisualiserRaceState().getRaceClock().getStartingTime());
diff --git a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java
index 26d6447e..38816a0e 100644
--- a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java
+++ b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java
@@ -1,6 +1,7 @@
package visualiser.Controllers;
import javafx.collections.FXCollections;
+import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
@@ -11,8 +12,12 @@ import javafx.scene.layout.AnchorPane;
import network.Messages.Enums.RequestToJoinEnum;
import javafx.scene.media.AudioClip;
import network.Messages.HostGame;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import shared.utils.JsonReader;
import visualiser.app.MatchBrowserSingleton;
import visualiser.model.RaceConnection;
+import visualiser.network.HttpMatchBrowserClient;
import visualiser.network.MatchBrowserLobbyInterface;
import java.io.IOException;
@@ -41,17 +46,17 @@ public class LobbyController extends Controller {
private AudioClip sound;
//the socket for match browser
- private DatagramSocket udpSocket;
- private MatchBrowserLobbyInterface matchBrowserLobbyInterface;
+ private HttpMatchBrowserClient httpMatchBrowserClient;
public void initialize() {
+ httpMatchBrowserClient = new HttpMatchBrowserClient();
+ new Thread(httpMatchBrowserClient, "Match Client").start();
// set up the connection table
- connections = FXCollections.observableArrayList();
customConnections = FXCollections.observableArrayList();
//connections.add(new RaceConnection("localhost", 4942, "Local Game"));
- lobbyTable.setItems(connections);
+ lobbyTable.setItems(httpMatchBrowserClient.connections);
gameNameColumn.setCellValueFactory(cellData -> cellData.getValue().gamenameProperty());
hostNameColumn.setCellValueFactory(cellData -> cellData.getValue().hostnameProperty());
statusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty());
@@ -68,7 +73,6 @@ public class LobbyController extends Controller {
joinGameBtn.setDisable(true);
spectateButton.setDisable(true);
- this.udpSocket = MatchBrowserSingleton.getInstance().getUdpSocket();
receiveMatchData();
}
@@ -99,6 +103,7 @@ public class LobbyController extends Controller {
* @throws IOException socket error
*/
public void connectSocket(RequestToJoinEnum joinType) throws IOException {
+ httpMatchBrowserClient.interrupt();
RaceConnection connection = lobbyTable.getSelectionModel().getSelectedItem();
Socket socket = new Socket(connection.getHostname(), connection.getPort());
InGameLobbyController iglc = (InGameLobbyController)loadScene("gameLobby.fxml");
@@ -124,7 +129,7 @@ public class LobbyController extends Controller {
public void menuBtnPressed() throws IOException {
sound = new AudioClip(this.getClass().getResource("/visualiser/sounds/buttonpress.wav").toExternalForm());
sound.play();
- matchBrowserLobbyInterface.closeSocket();
+ httpMatchBrowserClient.interrupt();
loadScene("title.fxml");
}
@@ -148,6 +153,7 @@ public class LobbyController extends Controller {
}
public void receiveMatchData(){
+ /*
matchBrowserLobbyInterface = new MatchBrowserLobbyInterface();
try {
matchBrowserLobbyInterface.startReceivingHostData(new DatagramSocket(4941));
@@ -160,17 +166,24 @@ public class LobbyController extends Controller {
matchBrowserLobbyInterface.addObserver(o);
} catch (SocketException e) {
System.err.println("Socket 4941 in use");
- }
+ }*/
}
/**
* Adds the games received from the server
*/
private void addServerGames() {
- connections.clear();
- connections.addAll(customConnections);
+ httpMatchBrowserClient.connections.addAll(customConnections);
+ httpMatchBrowserClient.connections.addListener(new ListChangeListener() {
+ @Override
+ public void onChanged(Change extends RaceConnection> c) {
+ refreshBtnPressed();
+ }
+ });
+
+ /*
for (HostGame game : matchBrowserLobbyInterface.getGames()) {
connections.add(new RaceConnection(game.getIp(), 4942, "Boat Game"));
- }
+ }*/
}
}
diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java
index 80ca9fa7..29a5bf89 100644
--- a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java
+++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java
@@ -36,10 +36,7 @@ import visualiser.gameController.ControllerClient;
import visualiser.gameController.Keys.ControlKey;
import visualiser.gameController.Keys.KeyFactory;
import visualiser.layout.*;
-import visualiser.model.Sparkline;
-import visualiser.model.VisualiserBoat;
-import visualiser.model.VisualiserRaceEvent;
-import visualiser.model.VisualiserRaceState;
+import visualiser.model.*;
import visualiser.utils.GPSConverter;
import java.io.IOException;
@@ -67,6 +64,8 @@ public class RaceViewController extends Controller {
private String keyToPress;
private View3D view3D;
private ObservableList viewSubjects;
+ private ResizableRaceCanvas raceCanvas;
+ private boolean mapToggle = true;
/**
* Arrow pointing to next mark in third person
@@ -81,6 +80,7 @@ public class RaceViewController extends Controller {
private @FXML ArrowController arrowController;
private @FXML NextMarkController nextMarkController;
private @FXML GridPane canvasBase;
+ private @FXML GridPane canvasBase1;
private @FXML SplitPane racePane;
private @FXML StackPane arrowPane;
private @FXML Pane nextMarkPane;
@@ -115,6 +115,7 @@ public class RaceViewController extends Controller {
tutorialCheck();
initKeypressHandler();
initialiseRaceVisuals();
+ initialiseRaceCanvas();
}
/**
@@ -150,6 +151,9 @@ public class RaceViewController extends Controller {
// tab key
if (codeString.equals("TAB")){toggleTable();}
+ //map key
+ if (codeString.equals("M")){bigMap();}
+
// any key pressed
ControlKey controlKey = keyFactory.getKey(codeString);
if(controlKey != null) {
@@ -604,6 +608,8 @@ public class RaceViewController extends Controller {
e.printStackTrace();
}
} else {
+ raceCanvas.drawRace();
+
boatInfoTable.sort();
}
@@ -731,4 +737,48 @@ public class RaceViewController extends Controller {
}
}
+ /**
+ * Initialises the map
+ */
+ private void initialiseRaceCanvas() {
+
+ //Create canvas.
+ raceCanvas = new ResizableRaceCanvas(raceState);
+
+ //Set properties.
+ raceCanvas.setMouseTransparent(true);
+ raceCanvas.widthProperty().bind(canvasBase1.widthProperty());
+ raceCanvas.heightProperty().bind(canvasBase1.heightProperty());
+
+ //Draw it and show it.
+ raceCanvas.draw();
+ raceCanvas.setVisible(true);
+
+ //Add to scene.
+ canvasBase1.getChildren().add(0, raceCanvas);
+ }
+
+ private void bigMap(){
+ if (mapToggle){
+ raceCanvas.widthProperty().bind(canvasBase.widthProperty());
+ raceCanvas.heightProperty().bind(canvasBase.heightProperty());
+
+ raceCanvas.setFullScreen(true);
+ raceCanvas.setOpacity(0.6);
+
+ canvasBase1.getChildren().remove(raceCanvas);
+ canvasBase.getChildren().add(1, raceCanvas);
+
+ }else{
+ raceCanvas.widthProperty().bind(canvasBase1.widthProperty());
+ raceCanvas.heightProperty().bind(canvasBase1.heightProperty());
+
+ raceCanvas.setFullScreen(false);
+
+ canvasBase.getChildren().remove(raceCanvas);
+ canvasBase1.getChildren().add(0, raceCanvas);
+ }
+ mapToggle = !mapToggle;
+ }
+
}
diff --git a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java
index 4fc39b30..822addbc 100644
--- a/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java
+++ b/racevisionGame/src/main/java/visualiser/model/ResizableRaceCanvas.java
@@ -6,13 +6,11 @@ import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.text.Font;
import javafx.scene.transform.Rotate;
-import network.Messages.Enums.BoatStatusEnum;
import shared.dataInput.RaceDataSource;
import shared.enums.RoundingType;
import shared.model.*;
import java.util.ArrayList;
-import java.util.Comparator;
import java.util.List;
/**
@@ -44,13 +42,15 @@ public class ResizableRaceCanvas extends ResizableCanvas {
private VisualiserRaceState raceState;
- private boolean annoName = true;
+ private boolean annoName = false;
private boolean annoAbbrev = true;
- private boolean annoSpeed = true;
+ private boolean annoSpeed = false;
private boolean annoPath = true;
- private boolean annoEstTime = true;
- private boolean annoTimeSinceLastMark = true;
- private boolean annoGuideLine = false;
+ private boolean annoEstTime = false;
+ private boolean annoTimeSinceLastMark = false;
+ private boolean annoGuideLine = true;
+
+ private boolean isFullScreen = false;
@@ -293,7 +293,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
List boats = new ArrayList<>(raceState.getBoats());
//Sort to ensure we draw boats in consistent order.
- boats.sort(Comparator.comparingInt(Boat::getSourceID));
+// boats.sort(Comparator.comparingInt(Boat::getSourceID));
//Current draw order:
// track points
@@ -302,29 +302,29 @@ public class ResizableRaceCanvas extends ResizableCanvas {
// text
//Track points.
- for (VisualiserBoat boat : boats) {
- drawTrack(boat);
- }
+ if (isFullScreen){
+ for (VisualiserBoat boat : boats) {
+ drawTrack(boat);
+ }
- //Wake.
- for (VisualiserBoat boat : boats) {
- //Only draw wake if they are currently racing.
- if (boat.getStatus() == BoatStatusEnum.RACING) {
- drawWake(boat);
+ //Text.
+ for (VisualiserBoat boat : boats) {
+ drawBoatText(boat);
}
}
+ //Wake.
+// for (VisualiserBoat boat : boats) {
+// //Only draw wake if they are currently racing.
+// if (boat.getStatus() == BoatStatusEnum.RACING) {
+// drawWake(boat);
+// }
+// }
+
//Boat.
for (VisualiserBoat boat : boats) {
drawBoat(boat);
}
-
- //Text.
- for (VisualiserBoat boat : boats) {
- drawBoatText(boat);
- }
-
-
}
/**
@@ -364,9 +364,9 @@ public class ResizableRaceCanvas extends ResizableCanvas {
gc.fillPolygon(x, y, x.length);
gc.restore();
- if (boat.getSourceID() == ThisBoat.getInstance().getSourceID()) {
- drawSails(boat);
- }
+// if (boat.getSourceID() == ThisBoat.getInstance().getSourceID()) {
+// drawSails(boat);
+// }
}
/**
@@ -605,7 +605,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//Prepare to draw.
gc.setLineWidth(1);
- gc.setFill(Color.AQUA);
+ gc.setFill(Color.DEEPSKYBLUE);
//Calculate the screen coordinates of the boundary.
@@ -645,19 +645,23 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//Race boundary.
drawBoundary();
- //Guiding Line
- if (annoGuideLine){
+ //rounding lines
+ if (isFullScreen){
+ drawRoundingLines();
drawRaceLine();
}
+ //Guiding Line
+// if (annoGuideLine){
+// drawRaceLine();
+// }
+
//Boats.
drawBoats();
//Marks.
drawMarks();
- //TEMP
- drawRoundingLines();
}
@@ -752,7 +756,8 @@ public class ResizableRaceCanvas extends ResizableCanvas {
gc.save();
gc.setLineWidth(2);
- gc.setStroke(Color.MEDIUMAQUAMARINE);
+ gc.setStroke(getLineColor(legs.get(index)));
+
gc.beginPath();
gc.moveTo(startPath.getX(), startPath.getY());
@@ -772,7 +777,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
gc.save();
gc.setLineWidth(2);
- gc.setStroke(Color.MEDIUMAQUAMARINE);
+ gc.setStroke(getLineColor(legs.get(index)));
gc.beginPath();
gc.moveTo(startPath.getX(), startPath.getY());
@@ -788,6 +793,21 @@ public class ResizableRaceCanvas extends ResizableCanvas {
}
}
+ private Color getLineColor(Leg leg) {
+ for (VisualiserBoat boat : raceState.getBoats()) {
+ if (boat.isClientBoat()) {
+ if (boat.getCurrentLeg() == leg) {
+ return Color.ORANGE;
+ } else {
+ return Color.MEDIUMAQUAMARINE;
+ }
+ }else{
+ return Color.MEDIUMAQUAMARINE;
+ }
+ }
+ return Color.MEDIUMAQUAMARINE;
+ }
+
private void drawArrowHead(GPSCoordinate start, GPSCoordinate end){
GraphCoordinate lineStart = this.map.convertGPS(start);
@@ -862,6 +882,11 @@ public class ResizableRaceCanvas extends ResizableCanvas {
}
+ public boolean isFullScreen() {
+ return isFullScreen;
+ }
-
+ public void setFullScreen(boolean fullScreen) {
+ isFullScreen = fullScreen;
+ }
}
diff --git a/racevisionGame/src/main/java/visualiser/model/VisualiserBoat.java b/racevisionGame/src/main/java/visualiser/model/VisualiserBoat.java
index 1184197c..f5ce109b 100644
--- a/racevisionGame/src/main/java/visualiser/model/VisualiserBoat.java
+++ b/racevisionGame/src/main/java/visualiser/model/VisualiserBoat.java
@@ -137,6 +137,9 @@ public class VisualiserBoat extends Boat {
//Update the nextValidTime for the next track point.
nextValidTime = currentTimeMilli + trackPointTimeInterval;
+ if (track.size() > trackPointLimit) {
+ track.remove(0);
+ }
}
}
diff --git a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java
index f546ec79..7781d2e3 100644
--- a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java
+++ b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java
@@ -8,6 +8,7 @@ import shared.dataInput.EmptyBoatDataSource;
import shared.dataInput.EmptyRaceDataSource;
import shared.dataInput.EmptyRegattaDataSource;
import visualiser.gameController.ControllerClient;
+import visualiser.network.HttpMatchBrowserHost;
import visualiser.network.ServerConnection;
import java.io.IOException;
@@ -115,5 +116,8 @@ public class VisualiserRaceEvent {
this.visualiserRaceServiceThread.interrupt();
this.serverConnectionThread.interrupt();
serverConnection.terminate();
+ if (HttpMatchBrowserHost.httpMatchBrowserHost != null) {
+ HttpMatchBrowserHost.httpMatchBrowserHost.interrupt();
+ }
}
}
diff --git a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceState.java b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceState.java
index a294d3fd..4a0316ee 100644
--- a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceState.java
+++ b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceState.java
@@ -94,7 +94,7 @@ public class VisualiserRaceState extends RaceState {
super.setRaceDataSource(raceDataSource);
if (getBoatDataSource() != null) {
- this.generateVisualiserBoats(this.boats, getBoatDataSource().getBoats(), raceDataSource.getParticipants(), unassignedColors);
+ this.generateVisualiserBoats(this.boats, getBoatDataSource().getBoats(), getRaceDataSource().getParticipants(), unassignedColors);
}
initialiseLegCompletionOrder();
@@ -109,7 +109,7 @@ public class VisualiserRaceState extends RaceState {
super.setBoatDataSource(boatDataSource);
if (getRaceDataSource() != null) {
- this.generateVisualiserBoats(this.boats, boatDataSource.getBoats(), getRaceDataSource().getParticipants(), unassignedColors);
+ this.generateVisualiserBoats(this.boats, getBoatDataSource().getBoats(), getRaceDataSource().getParticipants(), unassignedColors);
}
}
diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java
new file mode 100644
index 00000000..c4a14bb9
--- /dev/null
+++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java
@@ -0,0 +1,42 @@
+package visualiser.network;
+
+import javafx.collections.FXCollections;
+import javafx.collections.ObservableList;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import shared.utils.JsonReader;
+import visualiser.model.RaceConnection;
+
+import java.io.IOException;
+
+/**
+ * Created by Gondr on 19/09/2017.
+ */
+public class HttpMatchBrowserClient extends Thread {
+ public ObservableList connections = FXCollections.observableArrayList();
+
+ /**
+ * Get all the matches that have been running in the past 5 seconds.
+ */
+ @Override
+ public void run() {
+ while(!Thread.interrupted()) {
+ try {
+ JSONArray cons = JsonReader.readJsonFromUrlArray("http://api.umbrasheep.com/seng/get_matches/");
+ connections.clear();
+
+ for (int i = 0; i < cons.length(); i++) {
+ JSONObject con = (JSONObject) cons.get(i);
+ //using "ip_address" will give their public ip
+ connections.add(new RaceConnection((String) con.get("local_ip"), con.getInt("port"), "Boat Game"));
+ }
+
+ Thread.sleep(5000);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java
new file mode 100644
index 00000000..331cc772
--- /dev/null
+++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java
@@ -0,0 +1,115 @@
+package visualiser.network;
+
+
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
+import java.net.NetworkInterface;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.regex.Pattern;
+
+/**
+ * Creates an Http connection that hosts a game
+ */
+public class HttpMatchBrowserHost extends Thread {
+ private HttpClient httpClient;
+ private List params;
+
+ public static HttpMatchBrowserHost httpMatchBrowserHost = null;
+
+ /**
+ * Constructor, this sends out the creation message of the race.
+ * the thread should be run as soon as possible as the race is only valid for 5 seconds
+ * until it requires a heartbeat from the start function.
+ * @throws IOException if the hosting url is unreachable.
+ */
+ public HttpMatchBrowserHost() throws IOException {
+ httpMatchBrowserHost = this;
+ httpClient = HttpClients.createDefault();
+
+ Enumeration e = NetworkInterface.getNetworkInterfaces();
+ boolean matches = false;
+ String ip = "";
+ Pattern ipPattern = Pattern.compile("192.168.1.*");
+ while(e.hasMoreElements())
+ {
+ if (matches){
+ break;
+ }
+ NetworkInterface n = (NetworkInterface) e.nextElement();
+ Enumeration ee = n.getInetAddresses();
+ while (ee.hasMoreElements())
+ {
+ InetAddress i = ee.nextElement();
+ matches = ipPattern.matcher(i.getHostAddress()).matches();
+ if (matches){
+ ip = i.getHostAddress();
+ //System.out.println(ip);
+ break;
+ }
+ }
+ }
+
+ // Request parameters and other properties.
+ params = new ArrayList<>(2);
+ params.add(new BasicNameValuePair("ip", ip));
+ params.add(new BasicNameValuePair("port", "4942"));
+ params.add(new BasicNameValuePair("magic", "Thomas and Seng"));
+
+ sendHttp("http://api.umbrasheep.com/seng/registermatch/");
+ }
+
+ /**
+ * Sends a post to a server.
+ * @param domain url of to send to
+ * @throws IOException if the url is unreachable.
+ */
+ public void sendHttp(String domain) throws IOException {
+ HttpPost httppost = new HttpPost(domain);
+ httppost.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
+
+ //Execute and get the response.
+ HttpResponse response = httpClient.execute(httppost);
+ HttpEntity entity = response.getEntity();
+
+ if (entity != null) {
+ InputStream instream = entity.getContent();
+ try {
+ // do something useful
+ } finally {
+ instream.close();
+ }
+ } else {
+ throw new IOException("No Response from Host");
+ }
+ }
+
+ /**
+ * THe host starts sending out heartbeat messages every 2 seconds.
+ */
+ @Override
+ public void run() {
+ while(!Thread.interrupted()){
+ try {
+ sendHttp("http://api.umbrasheep.com/seng/keep_match_alive/");
+ Thread.sleep(2000);
+ } catch (IOException e) {
+ e.printStackTrace();
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+}
diff --git a/racevisionGame/src/main/java/visualiser/network/MatchBrowserInterface.java b/racevisionGame/src/main/java/visualiser/network/MatchBrowserInterface.java
index 02440612..e8beae5c 100644
--- a/racevisionGame/src/main/java/visualiser/network/MatchBrowserInterface.java
+++ b/racevisionGame/src/main/java/visualiser/network/MatchBrowserInterface.java
@@ -26,8 +26,9 @@ public class MatchBrowserInterface {
public MatchBrowserInterface() {
try {//132.181.16.13 is the ip of the CI as of 13/9/17
+ //this.IPAddress = InetAddress.getByName("132.181.16.13"); //InetAddress.getLocalHost();
//this.IPAddress = InetAddress.getByName("umbrasheep.com"); //InetAddress.getLocalHost();
- this.IPAddress = InetAddress.getByName("132.181.16.13"); //InetAddress.getLocalHost();
+ this.IPAddress = InetAddress.getByName("191.101.233.116"); //InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
diff --git a/racevisionGame/src/main/resources/visualiser/scenes/newRaceView.fxml b/racevisionGame/src/main/resources/visualiser/scenes/newRaceView.fxml
index 0f044a14..5c681a73 100644
--- a/racevisionGame/src/main/resources/visualiser/scenes/newRaceView.fxml
+++ b/racevisionGame/src/main/resources/visualiser/scenes/newRaceView.fxml
@@ -86,23 +86,23 @@
-