From 75c15d492e8c7ca247eb10c212d72df2c2fcb37a Mon Sep 17 00:00:00 2001 From: fjc40 Date: Fri, 15 Sep 2017 11:24:55 +1200 Subject: [PATCH 01/12] There was a null pointer exception when finishing the race, as the finish leg doesn't have compound marks. --- .../visualiser/Controllers/RaceViewController.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java index c2153c1f..e04c5290 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java @@ -429,12 +429,14 @@ public class RaceViewController extends Controller { @Override public void handle(long now) { CompoundMark target = boat.getCurrentLeg().getEndCompoundMark(); - Bearing headingToMark = GPSCoordinate.calculateBearing(boat.getPosition(), target.getAverageGPSCoordinate()); + if (target != null) { + Bearing headingToMark = GPSCoordinate.calculateBearing(boat.getPosition(), target.getAverageGPSCoordinate()); - nextMarkArrow.setX(view3D.getPivot().getX()); - nextMarkArrow.setY(view3D.getPivot().getY()); - nextMarkArrow.setZ(view3D.getPivot().getZ() + 15); - nextMarkArrow.setHeading(headingToMark.degrees()); + nextMarkArrow.setX(view3D.getPivot().getX()); + nextMarkArrow.setY(view3D.getPivot().getY()); + nextMarkArrow.setZ(view3D.getPivot().getZ() + 15); + nextMarkArrow.setHeading(headingToMark.degrees()); + } } }; arrowToNextMark.start(); From 424cd63c59c8bf689f8196764bf21195b91242a4 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Mon, 18 Sep 2017 12:44:10 +1200 Subject: [PATCH 02/12] Should fix the race xml issues where boats get unassigned sometimes. This removes the static raceServer stuff. The Race/Boat/Regatta XML commands only execute if they contain newer data (it checks the sequence number). --- racevisionGame/src/main/java/mock/model/RaceServer.java | 7 ------- .../src/main/java/network/Messages/LatestMessages.java | 3 +-- .../src/main/java/shared/dataInput/BoatXMLReader.java | 4 ++++ .../src/main/java/shared/dataInput/RaceXMLReader.java | 4 ++++ .../src/main/java/shared/dataInput/RegattaXMLReader.java | 4 ++++ .../VisualiserRaceCommands/BoatsXMLMessageCommand.java | 6 +++--- .../VisualiserRaceCommands/RaceXMLMessageCommand.java | 4 +++- .../VisualiserRaceCommands/RegattaXMLMessageCommand.java | 5 +++-- .../VisualiserRaceCommands/XMLMessageCommandFactory.java | 9 ++++++--- 9 files changed, 28 insertions(+), 18 deletions(-) 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/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/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/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); From f7da4977433935dded8f3eba1c94539e505ac983 Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Mon, 18 Sep 2017 18:22:20 +1200 Subject: [PATCH 03/12] Resizing maps to time taking now works #story[1323] --- .../src/main/java/mock/app/Event.java | 6 +- .../main/java/mock/xml/RaceXMLCreator.java | 117 +++++++++++++++++- .../network/MatchBrowserInterface.java | 3 +- 3 files changed, 119 insertions(+), 7 deletions(-) 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/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index 75024013..cb508aff 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,114 @@ 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); + } + } + + 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){ + System.out.println(getDistance(mark, prevMark)); + 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; + } + + 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); + } + + + 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); + } + } + + + + 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); + } + + 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/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(); } From 928f5e31f0a417be2742655c75d542bce2052ddd Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Tue, 19 Sep 2017 02:15:34 +1200 Subject: [PATCH 04/12] Hopefully final version of Hosting #story[1188] --- racevisionGame/pom.xml | 12 +++ .../main/java/shared/utils/JsonReader.java | 50 +++++++++++++ .../Controllers/HostGameController.java | 6 +- .../Controllers/InGameLobbyController.java | 1 + .../Controllers/LobbyController.java | 34 ++++++--- .../visualiser/model/VisualiserRaceEvent.java | 2 + .../network/HttpMatchBrowserClient.java | 38 ++++++++++ .../network/HttpMatchBrowserHost.java | 75 +++++++++++++++++++ 8 files changed, 207 insertions(+), 11 deletions(-) create mode 100644 racevisionGame/src/main/java/shared/utils/JsonReader.java create mode 100644 racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java create mode 100644 racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java 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/shared/utils/JsonReader.java b/racevisionGame/src/main/java/shared/utils/JsonReader.java new file mode 100644 index 00000000..476c3fed --- /dev/null +++ b/racevisionGame/src/main/java/shared/utils/JsonReader.java @@ -0,0 +1,50 @@ +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; + +/** + * Created by Gondr on 23/05/2017. + */ +public class JsonReader { + + 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(); + } + + 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(); + } + } + + 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/Controllers/HostGameController.java b/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java index abd681f5..232e3361 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/HostGameController.java @@ -10,6 +10,7 @@ import mock.app.Event; import mock.exceptions.EventConstructionException; import visualiser.app.App; import visualiser.app.MatchBrowserSingleton; +import visualiser.network.HttpMatchBrowserHost; import visualiser.network.MatchBrowserInterface; import java.io.IOException; @@ -64,8 +65,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 733d20e0..3fd5a377 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java @@ -28,6 +28,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; diff --git a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java index ef8a5350..8657152a 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; @@ -10,8 +11,12 @@ import javafx.scene.control.TextField; import javafx.scene.layout.AnchorPane; 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; @@ -39,17 +44,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()); @@ -63,7 +68,6 @@ public class LobbyController extends Controller { }); joinGameBtn.setDisable(true); - this.udpSocket = MatchBrowserSingleton.getInstance().getUdpSocket(); receiveMatchData(); } @@ -91,6 +95,7 @@ public class LobbyController extends Controller { * @throws IOException socket error */ public void connectSocket() throws IOException { + httpMatchBrowserClient.interrupt(); RaceConnection connection = lobbyTable.getSelectionModel().getSelectedItem(); Socket socket = new Socket(connection.getHostname(), connection.getPort()); InGameLobbyController iglc = (InGameLobbyController)loadScene("gameLobby.fxml"); @@ -100,7 +105,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"); } @@ -124,6 +129,7 @@ public class LobbyController extends Controller { } public void receiveMatchData(){ + /* matchBrowserLobbyInterface = new MatchBrowserLobbyInterface(); try { matchBrowserLobbyInterface.startReceivingHostData(new DatagramSocket(4941)); @@ -136,17 +142,25 @@ 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.clear(); + httpMatchBrowserClient.connections.addAll(customConnections); + httpMatchBrowserClient.connections.addListener(new ListChangeListener() { + @Override + public void onChanged(Change c) { + refreshBtnPressed(); + } + }); + + /* for (HostGame game : matchBrowserLobbyInterface.getGames()) { connections.add(new RaceConnection(game.getIp(), 4942, "Boat Game")); - } + }*/ } } diff --git a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java index f546ec79..5d786d90 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,6 @@ public class VisualiserRaceEvent { this.visualiserRaceServiceThread.interrupt(); this.serverConnectionThread.interrupt(); serverConnection.terminate(); + HttpMatchBrowserHost.httpMatchBrowserHost.interrupt(); } } 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..d6e41530 --- /dev/null +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java @@ -0,0 +1,38 @@ +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(); + + @Override + public void run() { + while(!Thread.interrupted()) { + try { + JSONArray cons = JsonReader.readJsonFromUrlArray("http://api.umbrasheep.com/seng/get_matches/"); + System.out.println("Got stuff"); + System.out.println(cons.toString()); + for (int i = 0; i < cons.length(); i++) { + JSONObject con = (JSONObject) cons.get(i); + connections.add(new RaceConnection((String) con.get("ip_address"), 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..c0ad21d1 --- /dev/null +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java @@ -0,0 +1,75 @@ +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.util.ArrayList; +import java.util.List; + +/** + * Created by Gondr on 19/09/2017. + */ +public class HttpMatchBrowserHost extends Thread { + private HttpClient httpClient; + private List params; + + public static HttpMatchBrowserHost httpMatchBrowserHost = null; + + public HttpMatchBrowserHost() throws IOException { + httpMatchBrowserHost = this; + httpClient = HttpClients.createDefault(); + + // Request parameters and other properties. + params = new ArrayList<>(2); + params.add(new BasicNameValuePair("port", "4942")); + params.add(new BasicNameValuePair("magic", "Thomas and Seng")); + + sendHttp("http://api.umbrasheep.com/seng/registermatch/"); + System.out.println("Register Match"); + } + + 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"); + } + } + + @Override + public void run() { + while(!Thread.interrupted()){ + try { + sendHttp("http://api.umbrasheep.com/seng/keep_match_alive/"); + System.out.println("Keep match ALive"); + Thread.sleep(2000); + } catch (IOException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } +} From db27d673deec1a2647e7e6f9d75848b0ec2e7dc5 Mon Sep 17 00:00:00 2001 From: fjc40 Date: Tue, 19 Sep 2017 13:38:07 +1200 Subject: [PATCH 05/12] Another fix for race xml stuff - the xml was fine, but the data sources would sometimes be overridden by empty ones, due to threading stuff. --- .../shared/dataInput/EmptyBoatDataSource.java | 2 +- .../shared/dataInput/EmptyRaceDataSource.java | 2 +- .../dataInput/EmptyRegattaDataSource.java | 2 +- .../src/main/java/shared/model/RaceState.java | 16 ++- .../Controllers/InGameLobbyController.java | 116 +++++++++--------- .../visualiser/model/VisualiserRaceState.java | 4 +- 6 files changed, 77 insertions(+), 65 deletions(-) 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/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/visualiser/Controllers/InGameLobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java index 733d20e0..57efb862 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; @@ -124,61 +126,67 @@ 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; + + 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){ + e.printStackTrace(); + } } + } /* private void populatePlayers(ListChangeListener.Change change){ @@ -191,7 +199,6 @@ public class InGameLobbyController extends Controller { //Initialises the race clock. initialiseRaceClock(this.visualiserRaceEvent.getVisualiserRaceState()); - //Starts the race countdown timer. countdownTimer(); } @@ -227,10 +234,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/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); } } From b550afcca7a06b6508b7cc3fa9bc8332f4eb1198 Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 20 Sep 2017 15:05:08 +1200 Subject: [PATCH 06/12] Merged race scaling with Http Match Discovery. --- .../main/java/mock/xml/RaceXMLCreator.java | 27 ++++++++++++++++--- .../main/java/shared/utils/JsonReader.java | 22 ++++++++++++++- .../network/HttpMatchBrowserClient.java | 3 +++ .../network/HttpMatchBrowserHost.java | 16 ++++++++++- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index cb508aff..b7b17319 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -154,6 +154,12 @@ public class RaceXMLCreator { } } + /** + * 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 @@ -175,13 +181,24 @@ public class RaceXMLCreator { 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 @@ -214,8 +231,12 @@ public class RaceXMLCreator { } } - - + /** + * 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(); diff --git a/racevisionGame/src/main/java/shared/utils/JsonReader.java b/racevisionGame/src/main/java/shared/utils/JsonReader.java index 476c3fed..44e55c98 100644 --- a/racevisionGame/src/main/java/shared/utils/JsonReader.java +++ b/racevisionGame/src/main/java/shared/utils/JsonReader.java @@ -9,10 +9,16 @@ import java.net.URL; import java.nio.charset.Charset; /** - * Created by Gondr on 23/05/2017. + * 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; @@ -22,6 +28,13 @@ public class JsonReader { 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 { @@ -36,6 +49,13 @@ public class JsonReader { } } + /** + * 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 { diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java index d6e41530..6384025f 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java @@ -15,6 +15,9 @@ import java.io.IOException; 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()) { diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java index c0ad21d1..1e32e46c 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java @@ -17,7 +17,7 @@ import java.util.ArrayList; import java.util.List; /** - * Created by Gondr on 19/09/2017. + * Creates an Http connection that hosts a game */ public class HttpMatchBrowserHost extends Thread { private HttpClient httpClient; @@ -25,6 +25,12 @@ public class HttpMatchBrowserHost extends Thread { 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(); @@ -38,6 +44,11 @@ public class HttpMatchBrowserHost extends Thread { System.out.println("Register Match"); } + /** + * 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")); @@ -58,6 +69,9 @@ public class HttpMatchBrowserHost extends Thread { } } + /** + * THe host starts sending out heartbeat messages every 2 seconds. + */ @Override public void run() { while(!Thread.interrupted()){ From 3c9e520d9ff8e073605721d37ece7eb53e07c8fa Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 20 Sep 2017 15:07:22 +1200 Subject: [PATCH 07/12] Merged in null pointer issue. --- racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index b7b17319..6cf3689c 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -246,6 +246,12 @@ public class RaceXMLCreator { 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(); From fec421da00d1ac74e512c752376160931231ae1d Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 20 Sep 2017 15:16:32 +1200 Subject: [PATCH 08/12] Removed println messages --- racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java | 1 - .../main/java/visualiser/network/HttpMatchBrowserClient.java | 2 -- .../src/main/java/visualiser/network/HttpMatchBrowserHost.java | 2 -- 3 files changed, 5 deletions(-) diff --git a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java index 6cf3689c..2c15e57f 100644 --- a/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java +++ b/racevisionGame/src/main/java/mock/xml/RaceXMLCreator.java @@ -170,7 +170,6 @@ public class RaceXMLCreator { XMLCompoundMark cm = race.getCourse().getCompoundMark().get(index); XMLMark mark = cm.getMark().get(0); if (prevMark != null){ - System.out.println(getDistance(mark, prevMark)); totalDistance += getDistance(mark, prevMark); } prevMark = mark; diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java index 6384025f..7e287f7c 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java @@ -23,8 +23,6 @@ public class HttpMatchBrowserClient extends Thread { while(!Thread.interrupted()) { try { JSONArray cons = JsonReader.readJsonFromUrlArray("http://api.umbrasheep.com/seng/get_matches/"); - System.out.println("Got stuff"); - System.out.println(cons.toString()); for (int i = 0; i < cons.length(); i++) { JSONObject con = (JSONObject) cons.get(i); connections.add(new RaceConnection((String) con.get("ip_address"), con.getInt("port"), "Boat Game")); diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java index 1e32e46c..1550e407 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java @@ -41,7 +41,6 @@ public class HttpMatchBrowserHost extends Thread { params.add(new BasicNameValuePair("magic", "Thomas and Seng")); sendHttp("http://api.umbrasheep.com/seng/registermatch/"); - System.out.println("Register Match"); } /** @@ -77,7 +76,6 @@ public class HttpMatchBrowserHost extends Thread { while(!Thread.interrupted()){ try { sendHttp("http://api.umbrasheep.com/seng/keep_match_alive/"); - System.out.println("Keep match ALive"); Thread.sleep(2000); } catch (IOException e) { e.printStackTrace(); From 3d292f784b60fd09dba185ac2fc48de2ebaf82da Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 20 Sep 2017 18:46:33 +1200 Subject: [PATCH 09/12] Users can now resee the lobby after exit and reentering, and fixed concurrent alteration issue which was stopping players from exiting the lobby. --- .../java/visualiser/Controllers/InGameLobbyController.java | 4 +++- .../src/main/java/visualiser/Controllers/LobbyController.java | 1 - .../src/main/java/visualiser/model/VisualiserRaceEvent.java | 4 +++- .../main/java/visualiser/network/HttpMatchBrowserClient.java | 2 ++ 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java index 763680e2..38544ba6 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/InGameLobbyController.java @@ -143,7 +143,9 @@ public class InGameLobbyController extends Controller { int count = 0; int row = 0; - for (VisualiserBoat boat :visualiserRaceEvent.getVisualiserRaceState().getBoats()) { + ArrayList copy = new ArrayList<>(visualiserRaceEvent.getVisualiserRaceState().getBoats()); + + for (VisualiserBoat boat : copy) { View3D playerBoatToSet = new View3D(); playerBoatToSet.setItems(subjects); diff --git a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java index 40857437..38816a0e 100644 --- a/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java +++ b/racevisionGame/src/main/java/visualiser/Controllers/LobbyController.java @@ -173,7 +173,6 @@ public class LobbyController extends Controller { * Adds the games received from the server */ private void addServerGames() { - httpMatchBrowserClient.connections.clear(); httpMatchBrowserClient.connections.addAll(customConnections); httpMatchBrowserClient.connections.addListener(new ListChangeListener() { @Override diff --git a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java index 5d786d90..7781d2e3 100644 --- a/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java +++ b/racevisionGame/src/main/java/visualiser/model/VisualiserRaceEvent.java @@ -116,6 +116,8 @@ public class VisualiserRaceEvent { this.visualiserRaceServiceThread.interrupt(); this.serverConnectionThread.interrupt(); serverConnection.terminate(); - HttpMatchBrowserHost.httpMatchBrowserHost.interrupt(); + if (HttpMatchBrowserHost.httpMatchBrowserHost != null) { + HttpMatchBrowserHost.httpMatchBrowserHost.interrupt(); + } } } diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java index 7e287f7c..25b28ac7 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java @@ -23,6 +23,8 @@ public class HttpMatchBrowserClient extends Thread { 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); connections.add(new RaceConnection((String) con.get("ip_address"), con.getInt("port"), "Boat Game")); From 52271d580f9c4208b3280ed0dc6088585dd83356 Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 20 Sep 2017 21:38:49 +1200 Subject: [PATCH 10/12] CHanged ip to local ip because port forwarding may be subjective to change. --- .../network/HttpMatchBrowserClient.java | 3 ++- .../network/HttpMatchBrowserHost.java | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java index 25b28ac7..c4a14bb9 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserClient.java @@ -27,7 +27,8 @@ public class HttpMatchBrowserClient extends Thread { for (int i = 0; i < cons.length(); i++) { JSONObject con = (JSONObject) cons.get(i); - connections.add(new RaceConnection((String) con.get("ip_address"), con.getInt("port"), "Boat Game")); + //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); diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java index 1550e407..bd91c5f9 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java @@ -13,7 +13,10 @@ 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; /** @@ -35,8 +38,32 @@ public class HttpMatchBrowserHost extends Thread { httpMatchBrowserHost = this; httpClient = HttpClients.createDefault(); + Enumeration e = NetworkInterface.getNetworkInterfaces(); + int count = 0; + String ip = ""; + while(e.hasMoreElements()) + { + if (count > 3){ + break; + } + NetworkInterface n = (NetworkInterface) e.nextElement(); + Enumeration ee = n.getInetAddresses(); + while (ee.hasMoreElements()) + { + InetAddress i = ee.nextElement(); + if (count == 3){ + ip = i.getHostAddress(); + System.out.println(ip); + count++; + break; + } + count++; + } + } + // 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")); From ffa1d8b0c47e80c146576187c1621367d6764acf Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 20 Sep 2017 21:39:33 +1200 Subject: [PATCH 11/12] Deleted Print Statement --- .../src/main/java/visualiser/network/HttpMatchBrowserHost.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java index bd91c5f9..1a4792e1 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java @@ -53,7 +53,7 @@ public class HttpMatchBrowserHost extends Thread { InetAddress i = ee.nextElement(); if (count == 3){ ip = i.getHostAddress(); - System.out.println(ip); + //System.out.println(ip); count++; break; } From 1ffef51d7c8583df2d98235189aefc8ad830ffc4 Mon Sep 17 00:00:00 2001 From: Fan-Wu Yang Date: Wed, 20 Sep 2017 22:07:46 +1200 Subject: [PATCH 12/12] Changed local ip detection to use regex --- .../java/visualiser/network/HttpMatchBrowserHost.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java index 1a4792e1..331cc772 100644 --- a/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java +++ b/racevisionGame/src/main/java/visualiser/network/HttpMatchBrowserHost.java @@ -18,6 +18,7 @@ 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 @@ -39,11 +40,12 @@ public class HttpMatchBrowserHost extends Thread { httpClient = HttpClients.createDefault(); Enumeration e = NetworkInterface.getNetworkInterfaces(); - int count = 0; + boolean matches = false; String ip = ""; + Pattern ipPattern = Pattern.compile("192.168.1.*"); while(e.hasMoreElements()) { - if (count > 3){ + if (matches){ break; } NetworkInterface n = (NetworkInterface) e.nextElement(); @@ -51,13 +53,12 @@ public class HttpMatchBrowserHost extends Thread { while (ee.hasMoreElements()) { InetAddress i = ee.nextElement(); - if (count == 3){ + matches = ipPattern.matcher(i.getHostAddress()).matches(); + if (matches){ ip = i.getHostAddress(); //System.out.println(ip); - count++; break; } - count++; } }