Merge remote-tracking branch 'origin/master' into story1299_next_mark_direction

# Conflicts:
#	racevisionGame/src/main/java/visualiser/Controllers/RaceViewController.java
main
Joseph 8 years ago
commit 4cf9b67db8

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</component>
</project>

@ -78,6 +78,18 @@
<version>0.7</version> <version>0.7</version>
</dependency> </dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20160810</version>
</dependency>
</dependencies> </dependencies>

@ -80,6 +80,7 @@ public class Event {
* @throws EventConstructionException Thrown if we cannot create an Event for any reason. * @throws EventConstructionException Thrown if we cannot create an Event for any reason.
*/ */
public Event(boolean singlePlayer, int mapIndex) throws EventConstructionException { public Event(boolean singlePlayer, int mapIndex) throws EventConstructionException {
PolarParser.parseNewPolars("mock/polars/acc_polars.csv");
this.mapIndex = mapIndex; this.mapIndex = mapIndex;
String raceXMLFile; String raceXMLFile;
String boatsXMLFile = "mock/mockXML/boatTest.xml"; String boatsXMLFile = "mock/mockXML/boatTest.xml";
@ -109,6 +110,7 @@ public class Event {
} }
double windAngle = 300; double windAngle = 300;
double windSpeed = 12;
//Read XML files. //Read XML files.
try { try {
@ -119,6 +121,7 @@ public class Event {
this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, -1, true); this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, -1, true);
} else { } else {
this.raceXML = RaceXMLCreator.alterRaceToWind(this.raceXML, XMLFileType.Contents, windAngle, false); 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); this.boatXML = XMLReader.readXMLFileToString(boatsXMLFile, StandardCharsets.UTF_8);
@ -131,7 +134,6 @@ public class Event {
this.xmlFileType = XMLFileType.Contents; this.xmlFileType = XMLFileType.Contents;
this.boatPolars = PolarParser.parse("mock/polars/acc_polars.csv"); this.boatPolars = PolarParser.parse("mock/polars/acc_polars.csv");
PolarParser.parseNewPolars("mock/polars/acc_polars.csv");
//Parse the XML files into data sources. //Parse the XML files into data sources.
@ -152,7 +154,7 @@ public class Event {
WindGenerator windGenerator = new ShiftingWindGenerator( WindGenerator windGenerator = new ShiftingWindGenerator(
Bearing.fromDegrees(windAngle), Bearing.fromDegrees(windAngle),
12 windSpeed
); );
MockRace mockRace = new MockRace( MockRace mockRace = new MockRace(

@ -24,7 +24,6 @@ import java.util.logging.Logger;
public class RaceServer { public class RaceServer {
private MockRace race; private MockRace race;
private LatestMessages latestMessages; private LatestMessages latestMessages;
private static RaceServer server;
private List<YachtEvent> collisionEvents = new ArrayList<>(); private List<YachtEvent> collisionEvents = new ArrayList<>();
@ -50,16 +49,10 @@ public class RaceServer {
public RaceServer(MockRace race, LatestMessages latestMessages) { public RaceServer(MockRace race, LatestMessages latestMessages) {
server = this;
this.race = race; this.race = race;
this.latestMessages = latestMessages; this.latestMessages = latestMessages;
} }
public static void staticUpdateXML() {
if (server != null) {
server.updateXMLFiles();
}
}
/** /**
* Parses the race to create a snapshot, and places it in latestMessages. * Parses the race to create a snapshot, and places it in latestMessages.

@ -1,17 +1,16 @@
package mock.xml; package mock.xml;
import mock.model.NewPolars;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import shared.dataInput.RaceXMLReader; import shared.dataInput.RaceXMLReader;
import shared.enums.XMLFileType; import shared.enums.XMLFileType;
import shared.exceptions.InvalidRaceDataException; import shared.exceptions.InvalidRaceDataException;
import shared.exceptions.XMLReaderException; import shared.exceptions.XMLReaderException;
import shared.model.Bearing;
import shared.model.CompoundMark; import shared.model.CompoundMark;
import shared.model.Constants; import shared.model.Constants;
import shared.model.GPSCoordinate; import shared.model.GPSCoordinate;
import shared.xml.Race.XMLCompoundMark; import shared.xml.Race.*;
import shared.xml.Race.XMLLimit;
import shared.xml.Race.XMLMark;
import shared.xml.Race.XMLRace;
import shared.xml.XMLUtilities; import shared.xml.XMLUtilities;
import javax.xml.bind.JAXBException; import javax.xml.bind.JAXBException;
@ -20,6 +19,8 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.Comparator;
/** /**
* Helper Class for creating a Race XML * 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 * Converts a Race.CourseLimit.Limit to a GPS coordinate
* @param limit limit to convert * @param limit limit to convert

@ -157,7 +157,6 @@ public class LatestMessages extends Observable {
return false; return false;
} else { } else {
RaceServer.staticUpdateXML();
return true; return true;
} }

@ -183,6 +183,10 @@ public class BoatXMLReader extends XMLReader implements BoatDataSource {
return sequenceNumber; return sequenceNumber;
} }
public void setSequenceNumber(int sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
@Override @Override
public void incrementSequenceNumber() { public void incrementSequenceNumber() {
sequenceNumber++; sequenceNumber++;

@ -22,7 +22,7 @@ public class EmptyBoatDataSource implements BoatDataSource {
private final Map<Integer, Mark> markerMap = new HashMap<>(); private final Map<Integer, Mark> markerMap = new HashMap<>();
private int sequenceNumber = 0; private int sequenceNumber = -1;
public EmptyBoatDataSource() { public EmptyBoatDataSource() {

@ -84,7 +84,7 @@ public class EmptyRaceDataSource implements RaceDataSource {
private RaceTypeEnum raceType = RaceTypeEnum.NOT_A_RACE_TYPE; private RaceTypeEnum raceType = RaceTypeEnum.NOT_A_RACE_TYPE;
private int sequenceNumber = 0; private int sequenceNumber = -1;
public EmptyRaceDataSource() { public EmptyRaceDataSource() {

@ -60,7 +60,7 @@ public class EmptyRegattaDataSource implements RegattaDataSource {
private int sequenceNumber = 0; private int sequenceNumber = -1;
public EmptyRegattaDataSource() { public EmptyRegattaDataSource() {

@ -499,6 +499,10 @@ public class RaceXMLReader extends XMLReader implements RaceDataSource {
return sequenceNumber; return sequenceNumber;
} }
public void setSequenceNumber(int sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
@Override @Override
public void incrementSequenceNumber() { public void incrementSequenceNumber() {
sequenceNumber++; sequenceNumber++;

@ -217,6 +217,10 @@ public class RegattaXMLReader extends XMLReader implements RegattaDataSource {
return sequenceNumber; return sequenceNumber;
} }
public void setSequenceNumber(int sequenceNumber) {
this.sequenceNumber = sequenceNumber;
}
@Override @Override
public void incrementSequenceNumber() { public void incrementSequenceNumber() {
sequenceNumber++; sequenceNumber++;

@ -148,9 +148,11 @@ public abstract class RaceState extends Observable{
* @param raceDataSource New race data source. * @param raceDataSource New race data source.
*/ */
public void setRaceDataSource(RaceDataSource raceDataSource) { public void setRaceDataSource(RaceDataSource raceDataSource) {
this.raceDataSource = raceDataSource; if ((this.raceDataSource == null) || (raceDataSource.getSequenceNumber() > this.raceDataSource.getSequenceNumber())) {
this.getRaceClock().setStartingTime(raceDataSource.getStartDateTime()); this.raceDataSource = raceDataSource;
useLegsList(raceDataSource.getLegs()); this.getRaceClock().setStartingTime(raceDataSource.getStartDateTime());
useLegsList(raceDataSource.getLegs());
}
} }
/** /**
@ -158,7 +160,9 @@ public abstract class RaceState extends Observable{
* @param boatDataSource New boat data source. * @param boatDataSource New boat data source.
*/ */
public void setBoatDataSource(BoatDataSource boatDataSource) { 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. * @param regattaDataSource New regatta data source.
*/ */
public void setRegattaDataSource(RegattaDataSource regattaDataSource) { public void setRegattaDataSource(RegattaDataSource regattaDataSource) {
this.regattaDataSource = regattaDataSource; if ((this.regattaDataSource == null) || (regattaDataSource.getSequenceNumber() > this.regattaDataSource.getSequenceNumber())) {
this.regattaDataSource = regattaDataSource;
}
} }

@ -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();
}
}
}

@ -41,8 +41,8 @@ public class BoatsXMLMessageCommand implements Command {
@Override @Override
public void execute() { public void execute() {
if (boatDataSource.getSequenceNumber() > visualiserRace.getBoatDataSource().getSequenceNumber()) {
visualiserRace.setBoatDataSource(boatDataSource); visualiserRace.setBoatDataSource(boatDataSource);
}
} }
} }

@ -38,7 +38,9 @@ public class RaceXMLMessageCommand implements Command {
@Override @Override
public void execute() { public void execute() {
visualiserRace.setRaceDataSource(raceDataSource); if (raceDataSource.getSequenceNumber() > visualiserRace.getRaceDataSource().getSequenceNumber()) {
visualiserRace.setRaceDataSource(raceDataSource);
}
} }
} }

@ -37,8 +37,9 @@ public class RegattaXMLMessageCommand implements Command {
@Override @Override
public void execute() { public void execute() {
if (regattaDataSource.getSequenceNumber() > visualiserRace.getRegattaDataSource().getSequenceNumber()) {
visualiserRace.setRegattaDataSource(regattaDataSource); visualiserRace.setRegattaDataSource(regattaDataSource);
}
} }
} }

@ -34,17 +34,20 @@ public class XMLMessageCommandFactory {
switch (message.getXmlMsgSubType()) { switch (message.getXmlMsgSubType()) {
case BOAT: 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); return new BoatsXMLMessageCommand(boatDataSource, visualiserRace);
case RACE: 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); return new RaceXMLMessageCommand(raceDataSource, visualiserRace);
case REGATTA: 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); return new RegattaXMLMessageCommand(regattaDataSource, visualiserRace);

@ -11,6 +11,7 @@ import mock.exceptions.EventConstructionException;
import network.Messages.Enums.RequestToJoinEnum; import network.Messages.Enums.RequestToJoinEnum;
import visualiser.app.App; import visualiser.app.App;
import visualiser.app.MatchBrowserSingleton; import visualiser.app.MatchBrowserSingleton;
import visualiser.network.HttpMatchBrowserHost;
import visualiser.network.MatchBrowserInterface; import visualiser.network.MatchBrowserInterface;
import java.io.IOException; import java.io.IOException;
@ -65,8 +66,11 @@ public class HostGameController extends Controller {
try { try {
App.game = new Event(false, currentMapIndex); App.game = new Event(false, currentMapIndex);
App.gameType = currentMapIndex; App.gameType = currentMapIndex;
HttpMatchBrowserHost matchBrowserHost = new HttpMatchBrowserHost();
new Thread(matchBrowserHost).start();
connectSocket("localhost", 4942); connectSocket("localhost", 4942);
alertMatchBrowser(); //alertMatchBrowser();
} catch (EventConstructionException e) { } catch (EventConstructionException e) {
Logger.getGlobal().log(Level.SEVERE, "Could not create Event.", e); Logger.getGlobal().log(Level.SEVERE, "Could not create Event.", e);

@ -15,11 +15,13 @@ import javafx.scene.control.Label;
import javafx.scene.image.ImageView; import javafx.scene.image.ImageView;
import javafx.scene.layout.AnchorPane; import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.GridPane; import javafx.scene.layout.GridPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial; import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.MeshView; import javafx.scene.shape.MeshView;
import mock.app.Event; import mock.app.Event;
import network.Messages.Enums.RaceStatusEnum; import network.Messages.Enums.RaceStatusEnum;
import network.Messages.Enums.RequestToJoinEnum; import network.Messages.Enums.RequestToJoinEnum;
import shared.model.Boat;
import visualiser.app.App; import visualiser.app.App;
import visualiser.gameController.ControllerClient; import visualiser.gameController.ControllerClient;
import visualiser.layout.SeaSurface; import visualiser.layout.SeaSurface;
@ -28,6 +30,7 @@ import visualiser.layout.View3D;
import visualiser.model.VisualiserBoat; import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRaceEvent; import visualiser.model.VisualiserRaceEvent;
import visualiser.model.VisualiserRaceState; import visualiser.model.VisualiserRaceState;
import visualiser.network.HttpMatchBrowserHost;
import java.io.IOException; import java.io.IOException;
import java.net.Socket; import java.net.Socket;
@ -124,61 +127,69 @@ public class InGameLobbyController extends Controller {
@Override @Override
public void onChanged(Change change) { public void onChanged(Change change) {
Platform.runLater( Platform.runLater(() -> {
() -> { while (change.next()) {
while (change.next()){ if (change.wasAdded() || change.wasRemoved() || change.wasUpdated()) {
if (change.wasAdded() || change.wasRemoved() || change.wasUpdated()){ populateLobby();
try{ }
resetLobby(); }
int count = 0; });
int row = 0; }
for (VisualiserBoat boat :visualiserRaceEvent.getVisualiserRaceState().getBoats()) {
View3D playerBoatToSet = new View3D(); public void populateLobby() {
playerBoatToSet.setItems(subjects);
try{
playerContainer.add(playerBoatToSet, (count % 3) , row); resetLobby();
playerContainer.setMargin(playerBoatToSet, new Insets(10, 10, 10, 10)); int count = 0;
int row = 0;
SeaSurface sea = new SeaSurface(750, 200);
sea.setX(250); ArrayList<VisualiserBoat> copy = new ArrayList<>(visualiserRaceEvent.getVisualiserRaceState().getBoats());
sea.setZ(210);
subjects.add(sea); for (VisualiserBoat boat : copy) {
View3D playerBoatToSet = new View3D();
MeshView mesh = new MeshView(importer.getImport()); playerBoatToSet.setItems(subjects);
PhongMaterial boatColorMat = new PhongMaterial(boat.getColor());
mesh.setMaterial(boatColorMat); playerContainer.add(playerBoatToSet, (count % 3) , row);
Subject3D subject = new Subject3D(mesh,0); playerContainer.setMargin(playerBoatToSet, new Insets(10, 10, 10, 10));
subjects.add(subject);
SeaSurface sea = new SeaSurface(750, 200);
playerBoatToSet.setDistance(50); sea.setX(250);
playerBoatToSet.setYaw(45); sea.setZ(210);
playerBoatToSet.setPitch(20); subjects.add(sea);
MeshView mesh = new MeshView(importer.getImport());
PhongMaterial boatColorMat = new PhongMaterial(boat.getColor());
AnimationTimer rotate = new AnimationTimer() { mesh.setMaterial(boatColorMat);
@Override Subject3D subject = new Subject3D(mesh,0);
public void handle(long now) { subjects.add(subject);
subject.setHeading(subject.getHeading().getAngle() + 0.1);
} playerBoatToSet.setDistance(50);
}; playerBoatToSet.setYaw(45);
rotate.start(); playerBoatToSet.setPitch(20);
allPlayerLabels.get(count).setText(boat.getName());
allPlayerLabels.get(count).toFront();
count += 1; AnimationTimer rotate = new AnimationTimer() {
if (count > 2){ @Override
row = 1; public void handle(long now) {
} subject.setHeading(subject.getHeading().getAngle() + 0.1);
}
}
catch(ConcurrentModificationException e){
}
}
} }
};
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){ private void populatePlayers(ListChangeListener.Change change){
@ -191,7 +202,6 @@ public class InGameLobbyController extends Controller {
//Initialises the race clock. //Initialises the race clock.
initialiseRaceClock(this.visualiserRaceEvent.getVisualiserRaceState()); initialiseRaceClock(this.visualiserRaceEvent.getVisualiserRaceState());
//Starts the race countdown timer. //Starts the race countdown timer.
countdownTimer(); countdownTimer();
} }
@ -227,7 +237,6 @@ public class InGameLobbyController extends Controller {
new AnimationTimer() { new AnimationTimer() {
@Override @Override
public void handle(long arg0) { public void handle(long arg0) {
//Get the current race status. //Get the current race status.
RaceStatusEnum raceStatus = visualiserRaceEvent.getVisualiserRaceState().getRaceStatusEnum(); RaceStatusEnum raceStatus = visualiserRaceEvent.getVisualiserRaceState().getRaceStatusEnum();

@ -1,6 +1,7 @@
package visualiser.Controllers; package visualiser.Controllers;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Button; import javafx.scene.control.Button;
@ -11,8 +12,12 @@ import javafx.scene.layout.AnchorPane;
import network.Messages.Enums.RequestToJoinEnum; import network.Messages.Enums.RequestToJoinEnum;
import javafx.scene.media.AudioClip; import javafx.scene.media.AudioClip;
import network.Messages.HostGame; import network.Messages.HostGame;
import org.json.JSONArray;
import org.json.JSONObject;
import shared.utils.JsonReader;
import visualiser.app.MatchBrowserSingleton; import visualiser.app.MatchBrowserSingleton;
import visualiser.model.RaceConnection; import visualiser.model.RaceConnection;
import visualiser.network.HttpMatchBrowserClient;
import visualiser.network.MatchBrowserLobbyInterface; import visualiser.network.MatchBrowserLobbyInterface;
import java.io.IOException; import java.io.IOException;
@ -41,17 +46,17 @@ public class LobbyController extends Controller {
private AudioClip sound; private AudioClip sound;
//the socket for match browser //the socket for match browser
private DatagramSocket udpSocket; private HttpMatchBrowserClient httpMatchBrowserClient;
private MatchBrowserLobbyInterface matchBrowserLobbyInterface;
public void initialize() { public void initialize() {
httpMatchBrowserClient = new HttpMatchBrowserClient();
new Thread(httpMatchBrowserClient, "Match Client").start();
// set up the connection table // set up the connection table
connections = FXCollections.observableArrayList();
customConnections = FXCollections.observableArrayList(); customConnections = FXCollections.observableArrayList();
//connections.add(new RaceConnection("localhost", 4942, "Local Game")); //connections.add(new RaceConnection("localhost", 4942, "Local Game"));
lobbyTable.setItems(connections); lobbyTable.setItems(httpMatchBrowserClient.connections);
gameNameColumn.setCellValueFactory(cellData -> cellData.getValue().gamenameProperty()); gameNameColumn.setCellValueFactory(cellData -> cellData.getValue().gamenameProperty());
hostNameColumn.setCellValueFactory(cellData -> cellData.getValue().hostnameProperty()); hostNameColumn.setCellValueFactory(cellData -> cellData.getValue().hostnameProperty());
statusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty()); statusColumn.setCellValueFactory(cellData -> cellData.getValue().statusProperty());
@ -68,7 +73,6 @@ public class LobbyController extends Controller {
joinGameBtn.setDisable(true); joinGameBtn.setDisable(true);
spectateButton.setDisable(true); spectateButton.setDisable(true);
this.udpSocket = MatchBrowserSingleton.getInstance().getUdpSocket();
receiveMatchData(); receiveMatchData();
} }
@ -99,6 +103,7 @@ public class LobbyController extends Controller {
* @throws IOException socket error * @throws IOException socket error
*/ */
public void connectSocket(RequestToJoinEnum joinType) throws IOException { public void connectSocket(RequestToJoinEnum joinType) throws IOException {
httpMatchBrowserClient.interrupt();
RaceConnection connection = lobbyTable.getSelectionModel().getSelectedItem(); RaceConnection connection = lobbyTable.getSelectionModel().getSelectedItem();
Socket socket = new Socket(connection.getHostname(), connection.getPort()); Socket socket = new Socket(connection.getHostname(), connection.getPort());
InGameLobbyController iglc = (InGameLobbyController)loadScene("gameLobby.fxml"); InGameLobbyController iglc = (InGameLobbyController)loadScene("gameLobby.fxml");
@ -124,7 +129,7 @@ public class LobbyController extends Controller {
public void menuBtnPressed() throws IOException { public void menuBtnPressed() throws IOException {
sound = new AudioClip(this.getClass().getResource("/visualiser/sounds/buttonpress.wav").toExternalForm()); sound = new AudioClip(this.getClass().getResource("/visualiser/sounds/buttonpress.wav").toExternalForm());
sound.play(); sound.play();
matchBrowserLobbyInterface.closeSocket(); httpMatchBrowserClient.interrupt();
loadScene("title.fxml"); loadScene("title.fxml");
} }
@ -148,6 +153,7 @@ public class LobbyController extends Controller {
} }
public void receiveMatchData(){ public void receiveMatchData(){
/*
matchBrowserLobbyInterface = new MatchBrowserLobbyInterface(); matchBrowserLobbyInterface = new MatchBrowserLobbyInterface();
try { try {
matchBrowserLobbyInterface.startReceivingHostData(new DatagramSocket(4941)); matchBrowserLobbyInterface.startReceivingHostData(new DatagramSocket(4941));
@ -160,17 +166,24 @@ public class LobbyController extends Controller {
matchBrowserLobbyInterface.addObserver(o); matchBrowserLobbyInterface.addObserver(o);
} catch (SocketException e) { } catch (SocketException e) {
System.err.println("Socket 4941 in use"); System.err.println("Socket 4941 in use");
} }*/
} }
/** /**
* Adds the games received from the server * Adds the games received from the server
*/ */
private void addServerGames() { private void addServerGames() {
connections.clear(); httpMatchBrowserClient.connections.addAll(customConnections);
connections.addAll(customConnections); httpMatchBrowserClient.connections.addListener(new ListChangeListener<RaceConnection>() {
@Override
public void onChanged(Change<? extends RaceConnection> c) {
refreshBtnPressed();
}
});
/*
for (HostGame game : matchBrowserLobbyInterface.getGames()) { for (HostGame game : matchBrowserLobbyInterface.getGames()) {
connections.add(new RaceConnection(game.getIp(), 4942, "Boat Game")); connections.add(new RaceConnection(game.getIp(), 4942, "Boat Game"));
} }*/
} }
} }

@ -36,10 +36,7 @@ import visualiser.gameController.ControllerClient;
import visualiser.gameController.Keys.ControlKey; import visualiser.gameController.Keys.ControlKey;
import visualiser.gameController.Keys.KeyFactory; import visualiser.gameController.Keys.KeyFactory;
import visualiser.layout.*; import visualiser.layout.*;
import visualiser.model.Sparkline; import visualiser.model.*;
import visualiser.model.VisualiserBoat;
import visualiser.model.VisualiserRaceEvent;
import visualiser.model.VisualiserRaceState;
import visualiser.utils.GPSConverter; import visualiser.utils.GPSConverter;
import java.io.IOException; import java.io.IOException;
@ -67,6 +64,8 @@ public class RaceViewController extends Controller {
private String keyToPress; private String keyToPress;
private View3D view3D; private View3D view3D;
private ObservableList<Subject3D> viewSubjects; private ObservableList<Subject3D> viewSubjects;
private ResizableRaceCanvas raceCanvas;
private boolean mapToggle = true;
/** /**
* Arrow pointing to next mark in third person * Arrow pointing to next mark in third person
@ -81,6 +80,7 @@ public class RaceViewController extends Controller {
private @FXML ArrowController arrowController; private @FXML ArrowController arrowController;
private @FXML NextMarkController nextMarkController; private @FXML NextMarkController nextMarkController;
private @FXML GridPane canvasBase; private @FXML GridPane canvasBase;
private @FXML GridPane canvasBase1;
private @FXML SplitPane racePane; private @FXML SplitPane racePane;
private @FXML StackPane arrowPane; private @FXML StackPane arrowPane;
private @FXML Pane nextMarkPane; private @FXML Pane nextMarkPane;
@ -115,6 +115,7 @@ public class RaceViewController extends Controller {
tutorialCheck(); tutorialCheck();
initKeypressHandler(); initKeypressHandler();
initialiseRaceVisuals(); initialiseRaceVisuals();
initialiseRaceCanvas();
} }
/** /**
@ -150,6 +151,9 @@ public class RaceViewController extends Controller {
// tab key // tab key
if (codeString.equals("TAB")){toggleTable();} if (codeString.equals("TAB")){toggleTable();}
//map key
if (codeString.equals("M")){bigMap();}
// any key pressed // any key pressed
ControlKey controlKey = keyFactory.getKey(codeString); ControlKey controlKey = keyFactory.getKey(codeString);
if(controlKey != null) { if(controlKey != null) {
@ -604,6 +608,8 @@ public class RaceViewController extends Controller {
e.printStackTrace(); e.printStackTrace();
} }
} else { } else {
raceCanvas.drawRace();
boatInfoTable.sort(); 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;
}
} }

@ -6,13 +6,11 @@ import javafx.scene.paint.Color;
import javafx.scene.paint.Paint; import javafx.scene.paint.Paint;
import javafx.scene.text.Font; import javafx.scene.text.Font;
import javafx.scene.transform.Rotate; import javafx.scene.transform.Rotate;
import network.Messages.Enums.BoatStatusEnum;
import shared.dataInput.RaceDataSource; import shared.dataInput.RaceDataSource;
import shared.enums.RoundingType; import shared.enums.RoundingType;
import shared.model.*; import shared.model.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.List; import java.util.List;
/** /**
@ -44,13 +42,15 @@ public class ResizableRaceCanvas extends ResizableCanvas {
private VisualiserRaceState raceState; private VisualiserRaceState raceState;
private boolean annoName = true; private boolean annoName = false;
private boolean annoAbbrev = true; private boolean annoAbbrev = true;
private boolean annoSpeed = true; private boolean annoSpeed = false;
private boolean annoPath = true; private boolean annoPath = true;
private boolean annoEstTime = true; private boolean annoEstTime = false;
private boolean annoTimeSinceLastMark = true; private boolean annoTimeSinceLastMark = false;
private boolean annoGuideLine = false; private boolean annoGuideLine = true;
private boolean isFullScreen = false;
@ -293,7 +293,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
List<VisualiserBoat> boats = new ArrayList<>(raceState.getBoats()); List<VisualiserBoat> boats = new ArrayList<>(raceState.getBoats());
//Sort to ensure we draw boats in consistent order. //Sort to ensure we draw boats in consistent order.
boats.sort(Comparator.comparingInt(Boat::getSourceID)); // boats.sort(Comparator.comparingInt(Boat::getSourceID));
//Current draw order: //Current draw order:
// track points // track points
@ -302,29 +302,29 @@ public class ResizableRaceCanvas extends ResizableCanvas {
// text // text
//Track points. //Track points.
for (VisualiserBoat boat : boats) { if (isFullScreen){
drawTrack(boat); for (VisualiserBoat boat : boats) {
} drawTrack(boat);
}
//Wake. //Text.
for (VisualiserBoat boat : boats) { for (VisualiserBoat boat : boats) {
//Only draw wake if they are currently racing. drawBoatText(boat);
if (boat.getStatus() == BoatStatusEnum.RACING) {
drawWake(boat);
} }
} }
//Wake.
// for (VisualiserBoat boat : boats) {
// //Only draw wake if they are currently racing.
// if (boat.getStatus() == BoatStatusEnum.RACING) {
// drawWake(boat);
// }
// }
//Boat. //Boat.
for (VisualiserBoat boat : boats) { for (VisualiserBoat boat : boats) {
drawBoat(boat); 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.fillPolygon(x, y, x.length);
gc.restore(); gc.restore();
if (boat.getSourceID() == ThisBoat.getInstance().getSourceID()) { // if (boat.getSourceID() == ThisBoat.getInstance().getSourceID()) {
drawSails(boat); // drawSails(boat);
} // }
} }
/** /**
@ -605,7 +605,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//Prepare to draw. //Prepare to draw.
gc.setLineWidth(1); gc.setLineWidth(1);
gc.setFill(Color.AQUA); gc.setFill(Color.DEEPSKYBLUE);
//Calculate the screen coordinates of the boundary. //Calculate the screen coordinates of the boundary.
@ -645,19 +645,23 @@ public class ResizableRaceCanvas extends ResizableCanvas {
//Race boundary. //Race boundary.
drawBoundary(); drawBoundary();
//Guiding Line //rounding lines
if (annoGuideLine){ if (isFullScreen){
drawRoundingLines();
drawRaceLine(); drawRaceLine();
} }
//Guiding Line
// if (annoGuideLine){
// drawRaceLine();
// }
//Boats. //Boats.
drawBoats(); drawBoats();
//Marks. //Marks.
drawMarks(); drawMarks();
//TEMP
drawRoundingLines();
} }
@ -752,7 +756,8 @@ public class ResizableRaceCanvas extends ResizableCanvas {
gc.save(); gc.save();
gc.setLineWidth(2); gc.setLineWidth(2);
gc.setStroke(Color.MEDIUMAQUAMARINE); gc.setStroke(getLineColor(legs.get(index)));
gc.beginPath(); gc.beginPath();
gc.moveTo(startPath.getX(), startPath.getY()); gc.moveTo(startPath.getX(), startPath.getY());
@ -772,7 +777,7 @@ public class ResizableRaceCanvas extends ResizableCanvas {
gc.save(); gc.save();
gc.setLineWidth(2); gc.setLineWidth(2);
gc.setStroke(Color.MEDIUMAQUAMARINE); gc.setStroke(getLineColor(legs.get(index)));
gc.beginPath(); gc.beginPath();
gc.moveTo(startPath.getX(), startPath.getY()); 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){ private void drawArrowHead(GPSCoordinate start, GPSCoordinate end){
GraphCoordinate lineStart = this.map.convertGPS(start); 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;
}
} }

@ -137,6 +137,9 @@ public class VisualiserBoat extends Boat {
//Update the nextValidTime for the next track point. //Update the nextValidTime for the next track point.
nextValidTime = currentTimeMilli + trackPointTimeInterval; nextValidTime = currentTimeMilli + trackPointTimeInterval;
if (track.size() > trackPointLimit) {
track.remove(0);
}
} }
} }

@ -8,6 +8,7 @@ import shared.dataInput.EmptyBoatDataSource;
import shared.dataInput.EmptyRaceDataSource; import shared.dataInput.EmptyRaceDataSource;
import shared.dataInput.EmptyRegattaDataSource; import shared.dataInput.EmptyRegattaDataSource;
import visualiser.gameController.ControllerClient; import visualiser.gameController.ControllerClient;
import visualiser.network.HttpMatchBrowserHost;
import visualiser.network.ServerConnection; import visualiser.network.ServerConnection;
import java.io.IOException; import java.io.IOException;
@ -115,5 +116,8 @@ public class VisualiserRaceEvent {
this.visualiserRaceServiceThread.interrupt(); this.visualiserRaceServiceThread.interrupt();
this.serverConnectionThread.interrupt(); this.serverConnectionThread.interrupt();
serverConnection.terminate(); serverConnection.terminate();
if (HttpMatchBrowserHost.httpMatchBrowserHost != null) {
HttpMatchBrowserHost.httpMatchBrowserHost.interrupt();
}
} }
} }

@ -94,7 +94,7 @@ public class VisualiserRaceState extends RaceState {
super.setRaceDataSource(raceDataSource); super.setRaceDataSource(raceDataSource);
if (getBoatDataSource() != null) { if (getBoatDataSource() != null) {
this.generateVisualiserBoats(this.boats, getBoatDataSource().getBoats(), raceDataSource.getParticipants(), unassignedColors); this.generateVisualiserBoats(this.boats, getBoatDataSource().getBoats(), getRaceDataSource().getParticipants(), unassignedColors);
} }
initialiseLegCompletionOrder(); initialiseLegCompletionOrder();
@ -109,7 +109,7 @@ public class VisualiserRaceState extends RaceState {
super.setBoatDataSource(boatDataSource); super.setBoatDataSource(boatDataSource);
if (getRaceDataSource() != null) { if (getRaceDataSource() != null) {
this.generateVisualiserBoats(this.boats, boatDataSource.getBoats(), getRaceDataSource().getParticipants(), unassignedColors); this.generateVisualiserBoats(this.boats, getBoatDataSource().getBoats(), getRaceDataSource().getParticipants(), unassignedColors);
} }
} }

@ -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<RaceConnection> 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();
}
}
}
}

@ -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<NameValuePair> 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<NetworkInterface> 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<InetAddress> 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();
}
}
}
}

@ -26,8 +26,9 @@ public class MatchBrowserInterface {
public MatchBrowserInterface() { public MatchBrowserInterface() {
try {//132.181.16.13 is the ip of the CI as of 13/9/17 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("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) { } catch (UnknownHostException e) {
e.printStackTrace(); e.printStackTrace();
} }

@ -86,23 +86,23 @@
</Accordion> </Accordion>
</children> </children>
</Pane> </Pane>
<Label fx:id="timer" maxHeight="20.0" text="0:0" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0"> <Label fx:id="timer" alignment="CENTER" maxHeight="20.0" mouseTransparent="true" text="0:0">
<font> <font>
<Font name="System Bold" size="15.0" /> <Font name="System Bold" size="15.0" />
</font> </font>
</Label> </Label>
<Label fx:id="FPS" text="FPS: 0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0"> <Label fx:id="FPS" mouseTransparent="true" text="FPS: 0" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<font> <font>
<Font name="System Bold" size="15.0" /> <Font name="System Bold" size="15.0" />
</font> </font>
<padding>
<Insets top="20.0" />
</padding>
</Label> </Label>
<Label fx:id="timeZone" text="Label" AnchorPane.bottomAnchor="0.0" AnchorPane.rightAnchor="0.0"> <Label fx:id="timeZone" mouseTransparent="true" text="Label" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0">
<font> <font>
<Font name="System Bold" size="15.0" /> <Font name="System Bold" size="15.0" />
</font> </font>
<padding>
<Insets bottom="20.0" />
</padding>
</Label> </Label>
<StackPane fx:id="arrowPane" alignment="TOP_RIGHT" mouseTransparent="true" prefHeight="150.0" prefWidth="150.0" snapToPixel="false" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"> <StackPane fx:id="arrowPane" alignment="TOP_RIGHT" mouseTransparent="true" prefHeight="150.0" prefWidth="150.0" snapToPixel="false" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<children> <children>
@ -110,6 +110,65 @@
</children> </children>
</StackPane> </StackPane>
<Label fx:id="tutorialText" alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" style="-fx-border-color: orange; -fx-border-radius: 5px; -fx-background-color: #ffffcc; -fx-text-fill: #3399ff; -fx-border-width: 3; -fx-border-insets: -3;" text="This is the tutorial text" visible="false" AnchorPane.leftAnchor="150.0" AnchorPane.rightAnchor="150.0" AnchorPane.topAnchor="100.0" /> <Label fx:id="tutorialText" alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" style="-fx-border-color: orange; -fx-border-radius: 5px; -fx-background-color: #ffffcc; -fx-text-fill: #3399ff; -fx-border-width: 3; -fx-border-insets: -3;" text="This is the tutorial text" visible="false" AnchorPane.leftAnchor="150.0" AnchorPane.rightAnchor="150.0" AnchorPane.topAnchor="100.0" />
<AnchorPane maxHeight="200.0" maxWidth="200.0" mouseTransparent="true" opacity="0.6" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0">
<children>
<AnchorPane maxHeight="200.0" maxWidth="200.0" prefHeight="200.0" prefWidth="216.0">
<children>
<GridPane fx:id="canvasBase1" maxHeight="200.0" maxWidth="200.0" prefHeight="200.0" prefWidth="216.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" vgrow="SOMETIMES" />
</rowConstraints>
</GridPane>
<Pane maxHeight="200.0" maxWidth="200.0" prefHeight="200.0" prefWidth="216.0" visible="false">
<children>
<Accordion>
<panes>
<TitledPane animated="false" prefHeight="395.0" prefWidth="222.0" text="Annotation Control">
<content>
<AnchorPane fx:id="annotationPane1" minHeight="0.0" minWidth="0.0">
<children>
<CheckBox fx:id="showName1" layoutY="39.0" mnemonicParsing="false" selected="true" text="Show Boat Name" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
<CheckBox fx:id="showAbbrev1" layoutY="61.0" mnemonicParsing="false" selected="true" text="Show Boat Abbreviation" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="25.0" />
<CheckBox fx:id="showSpeed1" layoutY="90.0" mnemonicParsing="false" selected="true" text="Show Boat Speed" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="50.0" />
<CheckBox fx:id="showBoatPath1" mnemonicParsing="false" selected="true" text="Show Boat Paths" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="75.0" />
<CheckBox fx:id="showTime1" mnemonicParsing="false" selected="true" text="Show Boat Leg Time" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="100.0" />
<CheckBox fx:id="showEstTime1" mnemonicParsing="false" selected="true" text="Show Est. Time to Next Mark" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="125.0" />
<CheckBox fx:id="showGuideline1" mnemonicParsing="false" text="Show Guideline" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="150.0" />
<Separator layoutX="19.6" layoutY="175.6" prefHeight="0.0" prefWidth="200.0" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="175.0" />
<Label text="Annotations" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="175.0" />
<RadioButton fx:id="hideAnnoRBtn1" mnemonicParsing="false" text="Hidden" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="200.0">
<toggleGroup>
<ToggleGroup fx:id="annoToggleGroup1" />
</toggleGroup>
</RadioButton>
<RadioButton fx:id="showAnnoRBtn1" mnemonicParsing="false" text="Visible" toggleGroup="$annoToggleGroup1" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="225.0" />
<RadioButton fx:id="partialAnnoRBtn1" mnemonicParsing="false" text="Partial" toggleGroup="$annoToggleGroup1" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="250.0" />
<RadioButton fx:id="importantAnnoRBtn1" mnemonicParsing="false" text="Important" toggleGroup="$annoToggleGroup1" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="275.0" />
<Button fx:id="saveAnno1" layoutX="11.0" layoutY="126.0" mnemonicParsing="false" text="Save Important Annotations" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="300.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
<TitledPane animated="false" text="FPS Control">
<content>
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
<children>
<CheckBox fx:id="showFPS1" layoutX="-14.0" layoutY="13.0" mnemonicParsing="false" selected="true" text="Show FPS" AnchorPane.leftAnchor="0.0" AnchorPane.topAnchor="0.0" />
</children>
</AnchorPane>
</content>
</TitledPane>
</panes>
</Accordion>
</children>
</Pane>
</children>
</AnchorPane>
</children>
</AnchorPane>
</children> </children>
</AnchorPane> </AnchorPane>
<AnchorPane fx:id="infoWrapper" focusTraversable="true" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="200.0" visible="false"> <AnchorPane fx:id="infoWrapper" focusTraversable="true" minHeight="0.0" minWidth="0.0" prefHeight="160.0" prefWidth="200.0" visible="false">

Loading…
Cancel
Save