Merge branch 'issue#10_unifying_marks' into Issue#4_boat_movement

# Conflicts:
#	src/main/java/seng302/controllers/CanvasController.java
#	src/main/java/seng302/controllers/Controller.java
#	src/main/java/seng302/controllers/RaceViewController.java
#	src/main/java/seng302/models/stream/StreamPacket.java
#	src/main/java/seng302/models/stream/StreamParser.java
This commit is contained in:
Peter Galloway
2017-05-15 18:09:47 +12:00
23 changed files with 49 additions and 1002 deletions
-198
View File
@@ -1,198 +0,0 @@
package seng302.models;
import seng302.models.mark.Mark;
import java.util.*;
/**
* Race class containing the boats and legs in the race
* Created by mra106 on 8/3/2017.
*/
public class Race {
private ArrayList<Yacht> boats; // The boats in the race
private ArrayList<Yacht> finishingOrder; // The order in which the boats finish the race
private HashMap<Yacht, List> events = new HashMap<>(); // The events that occur in the race
private List<Mark> course; // Marks in the race
private long startTime = 0;
private double timeScale = 1;
private boolean raceFinished = false; // Race is finished
private int raceTime = -2; // Current time in the race
/**
* Race class containing the boats and legs in the race
*/
public Race() {
this.boats = new ArrayList<>();
this.finishingOrder = new ArrayList<>();
this.course = new ArrayList<>();
}
/**
* Add a boat to the race
*
* @param boat, the boat to add
*/
public void addBoat(Yacht boat) {
boats.add(boat);
}
/**
* Returns a list of boats in a random order
*
* @return a list of boats
*/
public Yacht[] getShuffledBoats() {
// Shuffle the list of boats
long seed = System.nanoTime();
Collections.shuffle(this.boats, new Random(seed));
return boats.toArray(new Yacht[boats.size()]);
}
/**
* Returns a list of boats in the order that they
* finished the race (position 0 is first place)
*
* @return a list of boats
*/
public Yacht[] getFinishedBoats() {
return this.finishingOrder.toArray(new Yacht[this.finishingOrder.size()]);
}
/**
* Returns a list of boats in the race
*
* @return a list of the boats competing in the race
*/
public Yacht[] getBoats() {
return boats.toArray(new Yacht[boats.size()]);
}
/**
* Sets time scale
*
* @param timeScale
*/
public void setTimeScale(double timeScale) {
this.timeScale = timeScale;
}
/**
* Generate all events that will happen during the race.
*/
private void generateEvents() {
for (Yacht boat : this.boats) {
double totalDistance = 0;
int numberOfMarks = this.course.size();
for (int i = 0; i < numberOfMarks; i++) {
Double time = (totalDistance / boat.getVelocity() / timeScale);
// If there are singleMarks after this event
if (i < numberOfMarks - 1) {
Event event = new Event(time, boat, course.get(i), course.get(i + 1), i);
try {
events.get(boat).add(event);
} catch (NullPointerException e) {
events.put(boat, new ArrayList<>(Arrays.asList(event)));
}
totalDistance += event.getDistanceBetweenMarks();
//System.out.println(totalDistance);
//System.out.println(boat.getVelocity());
}
// There are no more marks after this event
else{
Event event = new Event(time, boat, course.get(i), i);
events.get(boat).add(event);
}
}
}
}
/**
* Starts a race and generates all events for the race.
*/
public void startRace() {
// record start time.
this.startTime = System.currentTimeMillis();
generateEvents();
}
/**
* Set the race course
* @param course a list of marks in the course
*/
public void addCourse(List<Mark> course) {
this.course = course;
}
/**
* Get a list of marks in the course
* @return
*/
public List<Mark> getCourse() {
return course;
}
/**
* Get a map of the events in the race
* @return
*/
public HashMap<Yacht, List> getEvents() {
return events;
}
/**
* Set a boat as finished
* @param boat The boat that has finished the race/home/cosc/student/wmu16
*/
public void setBoatFinished(Yacht boat){
this.finishingOrder.add(boat);
}
/**
* Set the race as finished
*/
public void setRaceFinished(){
this.raceFinished = true;
}
/**
* Return whether or not the race is finished
* @return true if the race is finished
*/
public boolean isRaceFinished(){
return this.raceFinished;
}
/**
* Set the race time
* @param raceTime the race time in seconds
*/
public void setRaceTime(int raceTime){
this.raceTime = raceTime;
}
/**
* Return the race time
* @return the race time in seconds
*/
public int getRaceTime(){
return this.raceTime;
}
/**
* Increment the race time by one second
*/
public void incrementRaceTime(){
this.raceTime += this.timeScale;
}
}
@@ -53,8 +53,8 @@ public class MarkGroup extends RaceObject {
};
super.getChildren().add(markCircle);
} else {
marks.add(((GateMark) mark).getSingleMark1());
marks.add(((GateMark) mark).getSingleMark2());
// marks.add(((GateMark) mark).getSingleMark1());
// marks.add(((GateMark) mark).getSingleMark2());
nodePixelVelocitiesX = new double[]{0d,0d};
nodePixelVelocitiesY = new double[]{0d,0d};
nodeDestinations = new Point2D[2];
@@ -1,78 +0,0 @@
package seng302.models.parsers;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import java.util.DoubleSummaryStatistics;
public class ConfigParser extends FileParser {
private Document doc;
public ConfigParser(String path) {
super(path);
this.doc = this.parseFile();
}
/**
* Gets wind direction from config file.
*
* @return a double type degree, or 0 if no value or invalid value is found
*/
public double getWindDirection() {
return getDoubleByTagName("wind-direction", 0.0);
}
/**
* Gets a non negative time scale for the race
*
* @return a double type scale, or 0 if no scale or invalid scale is found
*/
public double getTimeScale() {
return getDoubleByTagName("time-scale", 1.0);
}
/**
* Gets a double type number by given tag name found in xml file
*
* @param tagName a string of tag name
* @param defaultVal value returned if no value or invalid value is found
* @return value found
*/
public double getDoubleByTagName(String tagName, double defaultVal) {
double val = defaultVal;
try {
Node node = this.doc.getElementsByTagName(tagName).item(0);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
val = Double.valueOf(element.getTextContent());
}
} catch (Exception e) {
} finally {
return val;
}
}
/**
* Gets a string by given tag name found in xml file
*
* @param tagName a string of tag name
* @param defaultVal a string returned if no value or invalid value is found
* @return string found
*/
public String getStringByTagName(String tagName, String defaultVal) {
String string = defaultVal;
try {
Node node = this.doc.getElementsByTagName(tagName).item(0);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
string = element.getTextContent();
}
} catch (Exception e) {
} finally {
return string;
}
}
}
@@ -1,145 +0,0 @@
package seng302.models.parsers;
import org.w3c.dom.*;
import seng302.models.mark.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.NoSuchElementException;
/**
* parse a course xml file
* Created by Haoming Yin (hyi25) on 16/3/2017
*/
public class CourseParser extends FileParser {
private Document doc;
private HashMap<String, Mark> marks = new HashMap<>();
public CourseParser(String path) {
super(path);
this.doc = this.parseFile();
}
/**
* create a mark by given node
*
* @param node
* @return a mark, or null if fails to create a mark
*/
private SingleMark generateSingleMark(Node node) {
try {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String name = element.getElementsByTagName("name").item(0).getTextContent();
double lat = Double.valueOf(element.getElementsByTagName("latitude").item(0).getTextContent());
double lon = Double.valueOf(element.getElementsByTagName("longitude").item(0).getTextContent());
int id = Integer.valueOf(element.getElementsByTagName("id").item(0).getTextContent());
SingleMark singleMark = new SingleMark(name, lat, lon, id);
return singleMark;
} else {
throw new NoSuchElementException("Cannot generate a mark by given node.");
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* generate an arrayList of gates
*
* @return an arrayList of gates, or null if no gate has been found.
*/
private void generateGateMarks() {
ArrayList<GateMark> gateMarks = new ArrayList<>();
try {
NodeList nodes = doc.getElementsByTagName("gate");
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String name = element.getElementsByTagName("name").item(0).getTextContent();
SingleMark mark1 = generateSingleMark(element.getElementsByTagName("mark").item(0));
SingleMark mark2 = generateSingleMark(element.getElementsByTagName("mark").item(1));
GateMark gateMark;
if (name.equals("Start") || name.equals("Finish"))
gateMark = new GateMark(name, MarkType.CLOSED_GATE, mark1, mark2, mark1.getLatitude(), mark1.getLongitude());
else
gateMark = new GateMark(name, MarkType.OPEN_GATE, mark1, mark2, mark1.getLatitude(), mark1.getLongitude());
marks.put(name, gateMark);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* generate an arrayList of marks
*
* @return an arrayList of marks, or null if no gate has been found.
*/
private void generateSingleMarks() {
ArrayList<SingleMark> singleMarks = new ArrayList<>();
try {
// find the "marks" tag
Node node = doc.getElementsByTagName("marks").item(0);
// iterate all "marks"'s children
for (Node n = node.getFirstChild(); n != null; n = n.getNextSibling()) {
// if node's tag name is "mark"
if (n.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) n;
if (element.getNodeName() == "mark") {
Mark mark = generateSingleMark(n);
marks.put(mark.getName(), mark);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* return the order of all the marks along a course
*
* @return an arrayList of the names of ordered course marks
*/
private ArrayList<String> getOrder() {
ArrayList<String> markOrder = new ArrayList<>();
try {
Node orderNode = doc.getElementsByTagName("order").item(0);
for (Node node = orderNode.getFirstChild(); node != null; node = node.getNextSibling()) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
String name = element.getTextContent();
markOrder.add(name);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return markOrder;
}
public ArrayList<Mark> getCourse() {
generateSingleMarks();
generateGateMarks();
ArrayList<Mark> course = new ArrayList<>();
try {
for (String mark : getOrder()) {
course.add(marks.get(mark));
}
} catch (Exception e) {
e.printStackTrace();
}
return course;
}
}
@@ -1,54 +0,0 @@
package seng302.models.parsers;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
/**
* Created by Haoming Yin (hyi25) on 16/3/2017
*/
public abstract class FileParser {
private String filePath;
public FileParser() {}
public FileParser(String path) {
this.filePath = path;
}
protected Document parseFile() {
try {
InputStream is = getClass().getResourceAsStream(this.filePath);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(is);
// optional, in order to recover info from broken line.
doc.getDocumentElement().normalize();
return doc;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
protected Document parseFile(String xmlString) {
try {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(new InputSource(new StringReader(xmlString)));
// optional, in order to recover info from broken line.
doc.getDocumentElement().normalize();
return doc;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
@@ -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,64 +0,0 @@
//package seng302.models.parsers;
//
//import org.w3c.dom.*;
//import seng302.models.Yacht;
//
//import java.util.ArrayList;
//import java.util.NoSuchElementException;
//
//public class TeamsParser extends FileParser {
//
// private Document doc;
//
// public TeamsParser(String path) {
// super(path);
// this.doc = this.parseFile();
// }
//
// /**
// * Create a boat instance by a given team node
// * @param node a boat node containing name, alias and velocity
// * @return an instance of Boat
// */
// private Yacht parseBoat(Node node) {
// try {
// if (node.getNodeType() == Node.ELEMENT_NODE) {
// Element element = (Element) node;
// String name = element.getElementsByTagName("name").item(0).getTextContent();
// String alias = element.getElementsByTagName("alias").item(0).getTextContent();
// double velocity = Double.valueOf(element.getElementsByTagName("velocity").item(0).getTextContent());
// int id = Integer.valueOf(element.getElementsByTagName("id").item(0).getTextContent());
// Yacht boat = new Yacht(name, velocity, alias, id);
// return boat;
// } else {
// throw new NoSuchElementException("Cannot generate a boat by given node");
// }
// } catch (Exception e) {
// e.printStackTrace();
// return null;
// }
// }
//
// /**
// * Create an arraylist of boats instance.
// * @return an arraylist of boats in teams file
// */
// public ArrayList<Yacht> getBoats() {
// ArrayList<Yacht> boats = new ArrayList<>();
//
// try {
// NodeList nodes = this.doc.getElementsByTagName("team");
// for (int i = 0; i < nodes.getLength(); i++) {
// Node node = nodes.item(i);
// boats.add(parseBoat(node));
// }
// return boats;
// } catch (Exception e) {
// e.printStackTrace();
// return null;
// }
// }
//
//
//}
//
@@ -1,12 +1,12 @@
package seng302.models.parsers;
package seng302.models.stream;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import seng302.models.Yacht;
import seng302.models.parsers.packets.BoatPositionPacket;
import seng302.models.parsers.packets.StreamPacket;
import seng302.models.stream.packets.BoatPositionPacket;
import seng302.models.stream.packets.StreamPacket;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -66,24 +66,9 @@ public class StreamParser extends Thread{
Thread.sleep(1);
}
while (appRunning){
// StreamPacket packet = StreamReceiver.packetBuffer.peek();
//this code adds a delay to reading from the packetBuffer so
//out of order packets have time to order themselves in the queue
// int delayTime = 1000;
// int loopTime = delayTime * 10;
// long transitTime = (System.currentTimeMillis()%loopTime - packet.getTimeStamp()%loopTime);
// if (transitTime < 0){
// transitTime = loopTime + transitTime;
// }
// if (transitTime < delayTime) {
// long sleepTime = delayTime - (transitTime);
// Thread.sleep(sleepTime);
// }
StreamPacket packet = StreamReceiver.packetBuffer.take();
parsePacket(packet);
Thread.sleep(1);
while (StreamReceiver.packetBuffer.peek() == null) {
Thread.sleep(1);
}
}
} catch (Exception e){
@@ -1,13 +1,11 @@
package seng302.models.parsers;
package seng302.models.stream;
import seng302.models.parsers.packets.StreamPacket;
import seng302.models.stream.packets.StreamPacket;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.zip.CRC32;
@@ -1,14 +1,14 @@
package seng302.models.parsers;
package seng302.models.stream;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import seng302.models.Yacht;
import seng302.models.mark.MarkType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@@ -301,6 +301,7 @@ public class XMLParser {
public class CompoundMark {
private Integer markID;
private String cMarkName;
private MarkType markType;
private ArrayList<Mark> marks;
CompoundMark(Node compoundMark) {
@@ -308,6 +309,12 @@ public class XMLParser {
this.markID = getNodeAttributeInt(compoundMark, "CompoundMarkID");
this.cMarkName = getNodeAttributeString(compoundMark, "Name");
NodeList childMarks = compoundMark.getChildNodes();
if (childMarks.getLength() > 1){
markType = MarkType.OPEN_GATE;
} else {
markType = MarkType.SINGLE_MARK;
}
for (int i = 0; i < childMarks.getLength(); i++) {
Node markNode = childMarks.item(i);
if (markNode.getNodeName().equals("Mark")) {
@@ -319,6 +326,7 @@ public class XMLParser {
public Integer getMarkID() { return markID; }
public String getcMarkName() { return cMarkName; }
public MarkType getMarkType() { return markType; }
public ArrayList<Mark> getMarks() { return marks; }
public class Mark {
@@ -1,4 +1,4 @@
package seng302.models.parsers.packets;
package seng302.models.stream.packets;
public class BoatPositionPacket {
private long boatId;
@@ -1,4 +1,4 @@
package seng302.models.parsers.packets;
package seng302.models.stream.packets;
/**
* Created by Kusal on 4/24/2017.
@@ -48,6 +48,4 @@ public enum PacketType {
}
return OTHER;
}
}
@@ -1,4 +1,4 @@
package seng302.models.parsers.packets;
package seng302.models.stream.packets;
/**
* Created by kre39 on 23/04/17.