mirror of
https://github.com/michaelrausch/Party-Parrots-At-Sea.git
synced 2026-05-09 14:28:43 +00:00
Merge branch 'Story47CourseLimits' into 'develop'
Story47 course limits The idea was to have the course canvas update whenever we receive a new xml packet for the race data. Specifically for a few seconds after the race where the course boundaries change, going from a boundary which contains the start line to cutting off the start line as soon as the boats start. See merge request !30
This commit is contained in:
@@ -9,8 +9,8 @@ import seng302.models.parsers.StreamParser;
|
|||||||
import seng302.models.parsers.StreamReceiver;
|
import seng302.models.parsers.StreamReceiver;
|
||||||
import seng302.server.ServerThread;
|
import seng302.server.ServerThread;
|
||||||
|
|
||||||
public class App extends Application
|
public class App extends Application {
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
public void start(Stage primaryStage) throws Exception {
|
public void start(Stage primaryStage) throws Exception {
|
||||||
Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml"));
|
Parent root = FXMLLoader.load(getClass().getResource("/views/MainView.fxml"));
|
||||||
@@ -39,15 +39,15 @@ public class App extends Application
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length == 1 && args[0].equals("-standalone")){
|
if (args.length == 1 && args[0].equals("-standalone")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.length == 3 && args[0].equals("-server")){
|
if (args.length == 3 && args[0].equals("-server")) {
|
||||||
|
|
||||||
sr = new StreamReceiver(args[1], Integer.valueOf(args[2]), "RaceStream");
|
sr = new StreamReceiver(args[1], Integer.valueOf(args[2]), "RaceStream");
|
||||||
|
|
||||||
} else if(args.length == 2 && args[0].equals("-server")){
|
} else if (args.length == 2 && args[0].equals("-server")) {
|
||||||
switch (args[1]) {
|
switch (args[1]) {
|
||||||
case "internal":
|
case "internal":
|
||||||
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
||||||
@@ -62,8 +62,6 @@ public class App extends Application
|
|||||||
}
|
}
|
||||||
//Change the StreamReceiver in this else block to change the default data source.
|
//Change the StreamReceiver in this else block to change the default data source.
|
||||||
else{
|
else{
|
||||||
// sr = new StreamReceiver("livedata.americascup.com", 4941, "RaceStream");
|
|
||||||
|
|
||||||
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
sr = new StreamReceiver("localhost", 4949, "RaceStream");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,8 +71,6 @@ public class App extends Application
|
|||||||
|
|
||||||
launch(args);
|
launch(args);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -240,6 +240,17 @@ public class CanvasController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
checkForCourseChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkForCourseChanges() {
|
||||||
|
if (StreamParser.isNewRaceXmlReceived()){
|
||||||
|
gc.setFill(Color.SKYBLUE);
|
||||||
|
gc.fillRect(0,0, CANVAS_WIDTH, CANVAS_HEIGHT);
|
||||||
|
gc.restore();
|
||||||
|
addRaceBorder();
|
||||||
|
canvas.toBack();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void move(long id, RaceObject raceObject){
|
private void move(long id, RaceObject raceObject){
|
||||||
@@ -345,6 +356,8 @@ public class CanvasController {
|
|||||||
* Calculates x and y location for every marker that fits it to the canvas the race will be drawn on.
|
* Calculates x and y location for every marker that fits it to the canvas the race will be drawn on.
|
||||||
*/
|
*/
|
||||||
private void fitMarksToCanvas() {
|
private void fitMarksToCanvas() {
|
||||||
|
//Check is called once to avoid unnecessarily change the course limits once the race is running
|
||||||
|
StreamParser.isNewRaceXmlReceived();
|
||||||
findMinMaxPoint();
|
findMinMaxPoint();
|
||||||
double minLonToMaxLon = scaleRaceExtremities();
|
double minLonToMaxLon = scaleRaceExtremities();
|
||||||
calculateReferencePointLocation(minLonToMaxLon);
|
calculateReferencePointLocation(minLonToMaxLon);
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
package seng302.models.parsers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by Kusal on 4/24/2017.
|
|
||||||
*/
|
|
||||||
public enum PacketType {
|
|
||||||
HEARTBEAT,
|
|
||||||
RACE_STATUS,
|
|
||||||
DISPLAY_TEXT_MESSAGE,
|
|
||||||
XML_MESSAGE,
|
|
||||||
RACE_START_STATUS,
|
|
||||||
YACHT_EVENT_CODE,
|
|
||||||
YACHT_ACTION_CODE,
|
|
||||||
CHATTER_TEXT,
|
|
||||||
BOAT_LOCATION,
|
|
||||||
MARK_ROUNDING,
|
|
||||||
COURSE_WIND,
|
|
||||||
AVG_WIND,
|
|
||||||
OTHER;
|
|
||||||
|
|
||||||
static PacketType assignPacketType(int packetType){
|
|
||||||
switch(packetType){
|
|
||||||
case 1:
|
|
||||||
return HEARTBEAT;
|
|
||||||
case 12:
|
|
||||||
return RACE_STATUS;
|
|
||||||
case 20:
|
|
||||||
return DISPLAY_TEXT_MESSAGE;
|
|
||||||
case 26:
|
|
||||||
return XML_MESSAGE;
|
|
||||||
case 27:
|
|
||||||
return RACE_START_STATUS;
|
|
||||||
case 29:
|
|
||||||
return YACHT_EVENT_CODE;
|
|
||||||
case 31:
|
|
||||||
return YACHT_ACTION_CODE;
|
|
||||||
case 36:
|
|
||||||
return CHATTER_TEXT;
|
|
||||||
case 37:
|
|
||||||
return BOAT_LOCATION;
|
|
||||||
case 38:
|
|
||||||
return MARK_ROUNDING;
|
|
||||||
case 44:
|
|
||||||
return COURSE_WIND;
|
|
||||||
case 47:
|
|
||||||
return AVG_WIND;
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return OTHER;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package seng302.models.parsers;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by kre39 on 23/04/17.
|
|
||||||
*/
|
|
||||||
public class StreamPacket {
|
|
||||||
|
|
||||||
//Change int to an ENUM for the type
|
|
||||||
private PacketType type;
|
|
||||||
|
|
||||||
private long messageLength;
|
|
||||||
private long timeStamp;
|
|
||||||
private byte[] payload;
|
|
||||||
|
|
||||||
StreamPacket(int type, long messageLength, long timeStamp, byte[] payload) {
|
|
||||||
this.type = PacketType.assignPacketType(type);
|
|
||||||
this.messageLength = messageLength;
|
|
||||||
this.timeStamp = timeStamp;
|
|
||||||
this.payload = payload;
|
|
||||||
// System.out.println("type = " + this.type.toString());
|
|
||||||
//switch the packet type to deal with what ever specific packet you want to deal with
|
|
||||||
// if (this.type == PacketType.XML_MESSAGE){
|
|
||||||
// //System.out.println("--------");
|
|
||||||
// System.out.println(new String(payload));
|
|
||||||
// //StreamParser.parsePacket(this);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
PacketType getType() {
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getMessageLength() {
|
|
||||||
return messageLength;
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] getPayload() {
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getTimeStamp() {
|
|
||||||
return timeStamp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -31,6 +31,7 @@ public class StreamParser extends Thread{
|
|||||||
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> boatPositions = new ConcurrentHashMap<>();
|
public static ConcurrentHashMap<Long, PriorityBlockingQueue<BoatPositionPacket>> boatPositions = new ConcurrentHashMap<>();
|
||||||
private String threadName;
|
private String threadName;
|
||||||
private Thread t;
|
private Thread t;
|
||||||
|
private static boolean newRaceXmlReceived = false;
|
||||||
private static boolean raceStarted = false;
|
private static boolean raceStarted = false;
|
||||||
private static XMLParser xmlObject;
|
private static XMLParser xmlObject;
|
||||||
private static boolean raceFinished = false;
|
private static boolean raceFinished = false;
|
||||||
@@ -123,6 +124,7 @@ public class StreamParser extends Thread{
|
|||||||
extractDisplayMessage(packet);
|
extractDisplayMessage(packet);
|
||||||
break;
|
break;
|
||||||
case XML_MESSAGE:
|
case XML_MESSAGE:
|
||||||
|
newRaceXmlReceived = true;
|
||||||
extractXmlMessage(packet);
|
extractXmlMessage(packet);
|
||||||
break;
|
break;
|
||||||
case RACE_START_STATUS:
|
case RACE_START_STATUS:
|
||||||
@@ -296,9 +298,8 @@ public class StreamParser extends Thread{
|
|||||||
byte[] payload = packet.getPayload();
|
byte[] payload = packet.getPayload();
|
||||||
|
|
||||||
int messageType = payload[9];
|
int messageType = payload[9];
|
||||||
long messagelength = bytesToLong(Arrays.copyOfRange(payload,12,14));
|
long messageLength = bytesToLong(Arrays.copyOfRange(payload,12,14));
|
||||||
String xmlMessage = new String((Arrays.copyOfRange(payload,14,(int) (14 + messagelength)))).trim();
|
String xmlMessage = new String((Arrays.copyOfRange(payload,14,(int) (14 + messageLength)))).trim();
|
||||||
//System.out.println("xmlMessage2 = " + xmlMessage);
|
|
||||||
|
|
||||||
//Create XML document Object
|
//Create XML document Object
|
||||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||||
@@ -315,6 +316,9 @@ public class StreamParser extends Thread{
|
|||||||
if (messageType == 7) { //7 is the boat XML
|
if (messageType == 7) { //7 is the boat XML
|
||||||
boats = xmlObject.getBoatXML().getCompetingBoats();
|
boats = xmlObject.getBoatXML().getCompetingBoats();
|
||||||
}
|
}
|
||||||
|
if (messageType == 6) { //6 is race info xml
|
||||||
|
newRaceXmlReceived = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -593,5 +597,20 @@ public class StreamParser extends Thread{
|
|||||||
appRunning = false;
|
appRunning = false;
|
||||||
System.out.println("[CLIENT] Shutting down stream parser");
|
System.out.println("[CLIENT] Shutting down stream parser");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to check if a new un-processed xml has been found, if so will return true before
|
||||||
|
* toggling off so that the next check will return false.
|
||||||
|
*
|
||||||
|
* @return the status of if new xml has been received
|
||||||
|
*/
|
||||||
|
public static boolean isNewRaceXmlReceived(){
|
||||||
|
if (newRaceXmlReceived){
|
||||||
|
newRaceXmlReceived = false;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -235,6 +235,28 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the post-start race course information
|
||||||
|
*/
|
||||||
|
private void sendPostStartCourseXml(){
|
||||||
|
Timer t = new Timer();
|
||||||
|
t.schedule(new TimerTask() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
Message raceData = getXmlMessage("/server_config/courseLimits.xml", XMLMessageSubType.RACE);
|
||||||
|
if (raceData != null) {
|
||||||
|
server.send(raceData);
|
||||||
|
serverLog("Sending race data", 0);
|
||||||
|
}
|
||||||
|
}catch (IOException e) {
|
||||||
|
serverLog("Couldn't send an XML Message: " + e.getMessage(), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},25000);
|
||||||
|
//Delays the new course xml data for 25 seconds so the boats are able to pass the starting line
|
||||||
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
try{
|
try{
|
||||||
server = new StreamingServerSocket(PORT_NUMBER);
|
server = new StreamingServerSocket(PORT_NUMBER);
|
||||||
@@ -252,12 +274,13 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
sendXml();
|
sendXml();
|
||||||
startSendingRaceStartStatusMessages();
|
startSendingRaceStartStatusMessages();
|
||||||
startSendingRaceStatusMessages();
|
startSendingRaceStatusMessages();
|
||||||
|
sendPostStartCourseXml();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start sending static boat position updates when race has finished
|
* Start sending static boat position updates when race has finished
|
||||||
*/
|
*/
|
||||||
private void startSendingRaceFinishedBoatPostions(){
|
private void startSendingRaceFinishedBoatPositions(){
|
||||||
Timer t = new Timer();
|
Timer t = new Timer();
|
||||||
t.schedule(new TimerTask() {
|
t.schedule(new TimerTask() {
|
||||||
@Override
|
@Override
|
||||||
@@ -316,7 +339,7 @@ public class ServerThread implements Runnable, Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (numOfBoatsFinished == ((List<Boat>) arg).size()) {
|
if (numOfBoatsFinished == ((List<Boat>) arg).size()) {
|
||||||
startSendingRaceFinishedBoatPostions();
|
startSendingRaceFinishedBoatPositions();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Race>
|
||||||
|
<CreationTimeDate>2015-08-29T13:12:40+02:00</CreationTimeDate>
|
||||||
|
<RaceStartTime Start="2015-08-29T13:10:00+02:00" Postpone="False"/>
|
||||||
|
<RaceID>15082901</RaceID>
|
||||||
|
<RaceType>Fleet</RaceType>
|
||||||
|
<Participants>
|
||||||
|
<Yacht SourceID="101"/>
|
||||||
|
<Yacht SourceID="102"/>
|
||||||
|
<Yacht SourceID="103"/>
|
||||||
|
<Yacht SourceID="104"/>
|
||||||
|
<Yacht SourceID="105"/>
|
||||||
|
<Yacht SourceID="106"/>
|
||||||
|
</Participants>
|
||||||
|
<Course>
|
||||||
|
<CompoundMark CompoundMarkID="1" Name="Mark0">
|
||||||
|
<Mark SeqID="1" Name="Start Line 1" TargetLat="57.6703330" TargetLng="11.8278330"
|
||||||
|
SourceID="122"/>
|
||||||
|
<Mark SeqID="2" Name="Start Line 2" TargetLat="57.6703330" TargetLng="11.8278330"
|
||||||
|
SourceID="123"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="2" Name="Mark1">
|
||||||
|
<Mark SeqID="1" Name="Mark1" TargetLat="57.6675700" TargetLng="11.8359880" SourceID="131"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="3" Name="Mark2">
|
||||||
|
<Mark SeqID="1" Name="Lee Gate 1" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="124"/>
|
||||||
|
<Mark SeqID="2" Name="Lee Gate 2" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="125"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="4" Name="Mark3">
|
||||||
|
<Mark SeqID="1" Name="Wind Gate 1" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="126"/>
|
||||||
|
<Mark SeqID="2" Name="Wind Gate 2" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="127"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="5" Name="Mark2">
|
||||||
|
<Mark SeqID="1" Name="Lee Gate 1" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="124"/>
|
||||||
|
<Mark SeqID="2" Name="Lee Gate 2" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="125"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="6" Name="Mark3">
|
||||||
|
<Mark SeqID="1" Name="Wind Gate 1" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="126"/>
|
||||||
|
<Mark SeqID="2" Name="Wind Gate 2" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="127"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="7" Name="Mark2">
|
||||||
|
<Mark SeqID="1" Name="Lee Gate 1" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="124"/>
|
||||||
|
<Mark SeqID="2" Name="Lee Gate 2" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="125"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="8" Name="Mark3">
|
||||||
|
<Mark SeqID="1" Name="Wind Gate 1" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="126"/>
|
||||||
|
<Mark SeqID="2" Name="Wind Gate 2" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="127"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="9" Name="Mark2">
|
||||||
|
<Mark SeqID="1" Name="Lee Gate 1" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="124"/>
|
||||||
|
<Mark SeqID="2" Name="Lee Gate 2" TargetLat="57.6708220" TargetLng="11.8433900"
|
||||||
|
SourceID="125"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="10" Name="Mark3">
|
||||||
|
<Mark SeqID="1" Name="Wind Gate 1" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="126"/>
|
||||||
|
<Mark SeqID="2" Name="Wind Gate 2" TargetLat="57.6650170" TargetLng="11.8279170"
|
||||||
|
SourceID="127"/>
|
||||||
|
</CompoundMark>
|
||||||
|
<CompoundMark CompoundMarkID="11" Name="Mark4">
|
||||||
|
<Mark SeqID="1" Name="Finish Line 1" TargetLat="57.6715240" TargetLng="11.8444950"
|
||||||
|
SourceID="128"/>
|
||||||
|
<Mark SeqID="2" Name="Finish Line 2" TargetLat="57.6715240" TargetLng="11.8444950"
|
||||||
|
SourceID="129"/>
|
||||||
|
</CompoundMark>
|
||||||
|
</Course>
|
||||||
|
<CompoundMarkSequence>
|
||||||
|
<Corner SeqID="1" CompoundMarkID="1" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="2" CompoundMarkID="2" Rounding="Port" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="3" CompoundMarkID="3" Rounding="SP" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="4" CompoundMarkID="4" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="5" CompoundMarkID="5" Rounding="SP" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="6" CompoundMarkID="6" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="7" CompoundMarkID="7" Rounding="SP" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="8" CompoundMarkID="8" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="9" CompoundMarkID="9" Rounding="SP" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="10" CompoundMarkID="10" Rounding="PS" ZoneSize="3"/>
|
||||||
|
<Corner SeqID="11" CompoundMarkID="11" Rounding="PS" ZoneSize="3"/>
|
||||||
|
</CompoundMarkSequence>
|
||||||
|
<CourseLimit>
|
||||||
|
<Limit SeqID="1" Lat="57.6739450" Lon="11.8417100"/>
|
||||||
|
<Limit SeqID="2" Lat="57.6709520" Lon="11.8485010"/>
|
||||||
|
<Limit SeqID="3" Lat="57.6690260" Lon="11.8472790"/>
|
||||||
|
<Limit SeqID="4" Lat="57.6693140" Lon="11.8457610"/>
|
||||||
|
<Limit SeqID="5" Lat="57.6665370" Lon="11.8432910"/>
|
||||||
|
<Limit SeqID="6" Lat="57.6641400" Lon="11.8385840"/>
|
||||||
|
<Limit SeqID="7" Lat="57.6629430" Lon="11.8332030"/>
|
||||||
|
<Limit SeqID="8" Lat="57.6629480" Lon="11.8249660"/>
|
||||||
|
<Limit SeqID="9" Lat="57.6686890" Lon="11.8250920"/>
|
||||||
|
<Limit SeqID="10" Lat="57.6708220" Lon="11.8321340"/>
|
||||||
|
</CourseLimit>
|
||||||
|
</Race>
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<Race>
|
<Race>
|
||||||
<CreationTimeDate>2015-08-29T13:12:40+02:00</CreationTimeDate>
|
<CreationTimeDate>2015-08-29T11:27:15+02:00</CreationTimeDate>
|
||||||
<RaceStartTime Start="2015-08-29T13:10:00+02:00" Postpone="False" />
|
<RaceStartTime Start="2015-08-29T13:10:00+02:00" Postpone="False" />
|
||||||
<RaceID>15082901</RaceID>
|
<RaceID>15082901</RaceID>
|
||||||
<RaceType>Fleet</RaceType>
|
<RaceType>Fleet</RaceType>
|
||||||
@@ -80,6 +80,8 @@
|
|||||||
<Limit SeqID="7" Lat="57.6629430" Lon="11.8332030" />
|
<Limit SeqID="7" Lat="57.6629430" Lon="11.8332030" />
|
||||||
<Limit SeqID="8" Lat="57.6629480" Lon="11.8249660" />
|
<Limit SeqID="8" Lat="57.6629480" Lon="11.8249660" />
|
||||||
<Limit SeqID="9" Lat="57.6686890" Lon="11.8250920" />
|
<Limit SeqID="9" Lat="57.6686890" Lon="11.8250920" />
|
||||||
<Limit SeqID="10" Lat="57.6708220" Lon="11.8321340" />
|
<Limit SeqID="10" Lat="57.6692230" Lon="11.8231430" />
|
||||||
|
<Limit SeqID="11" Lat="57.6725370" Lon="11.8272480" />
|
||||||
|
<Limit SeqID="12" Lat="57.6708220" Lon="11.8321340" />
|
||||||
</CourseLimit>
|
</CourseLimit>
|
||||||
</Race>
|
</Race>
|
||||||
@@ -8,6 +8,7 @@ import java.lang.reflect.Method;
|
|||||||
import java.net.Socket;
|
import java.net.Socket;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.concurrent.PriorityBlockingQueue;
|
import java.util.concurrent.PriorityBlockingQueue;
|
||||||
|
import seng302.models.parsers.packets.StreamPacket;
|
||||||
|
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|||||||
Reference in New Issue
Block a user