Merge branch 'develop' into Story80_BoatCustomization

This commit is contained in:
Alistair McIntyre
2017-08-16 13:06:31 +12:00
47 changed files with 1912 additions and 2172 deletions
@@ -1,5 +1,7 @@
package seng302.gameServer.server.messages;
import seng302.gameServer.GameState;
public class MarkRoundingMessage extends Message{
private final long MESSAGE_VERSION_NUMBER = 1;
private final int MESSAGE_SIZE = 21;
@@ -18,14 +20,14 @@ public class MarkRoundingMessage extends Message{
* The purpose of this is to record the time when yachts cross marks
* @param ackNumber ackNumber
* @param raceId raceId
* @param sourceId sourceId
* @param sourceId boatSourceId
* @param roundingBoatStatus roundingBoatStatus
* @param roundingSide roundingSide
* @param markId markId
*/
public MarkRoundingMessage(int ackNumber, int raceId, int sourceId, RoundingBoatStatus roundingBoatStatus,
RoundingSide roundingSide, int markId){
this.time = System.currentTimeMillis() / 1000L;
RoundingSide roundingSide, MarkType markType, int markId) {
this.time = System.currentTimeMillis();
this.ackNumber = ackNumber;
this.raceId = raceId;
this.sourceId = sourceId;
@@ -44,6 +46,7 @@ public class MarkRoundingMessage extends Message{
putInt((int) sourceId, 4);
putByte((byte) boatStatus.getCode());
putByte((byte) roundingSide.getCode());
putByte((byte) markType.getCode());
putByte((byte) markId);
writeCRC();
@@ -4,17 +4,49 @@ package seng302.gameServer.server.messages;
* The side the boat rounded the mark
*/
public enum RoundingSide {
UNKNOWN(0),
PORT(1),
STARBOARD(2);
UNKNOWN(0, "Unknown"),
PORT(1, "Port"),
STARBOARD(2, "Stbd"),
SP(3, "SP"),
PS(4, "PS");
private long code;
private String name;
RoundingSide(long code) {
RoundingSide(long code, String name) {
this.code = code;
this.name = name;
}
public long getCode(){
return code;
}
public String getName() {
return name;
}
public static RoundingSide getRoundingSide(String identifier) {
RoundingSide roundingSide = UNKNOWN;
switch (identifier) {
case "Unknown":
roundingSide = UNKNOWN;
break;
case "Port":
roundingSide = PORT;
break;
case "Stbd":
roundingSide = STARBOARD;
break;
case "SP":
roundingSide = SP;
break;
case "PS":
roundingSide = PS;
break;
}
return roundingSide;
}
}
@@ -0,0 +1,52 @@
package seng302.gameServer.server.messages;
/**
* Created by zyt10 on 10/08/17.
*/
public class YachtEventCodeMessage extends Message {
private final MessageType MESSAGE_TYPE = MessageType.YACHT_EVENT_CODE;
private final int MESSAGE_VERSION = 1; //Always set to 1
private final int MESSAGE_SIZE = 22;
// Message fields
private long timeStamp;
private long ack = 0x00; //Unused
private int raceId;
private int destSourceId;
private int incidentId;
private int eventId;
public YachtEventCodeMessage(Integer subjectId) {
timeStamp = System.currentTimeMillis() / 1000L;
ack = 0;
raceId = 1;
destSourceId = subjectId; // collision boat source id
incidentId = 0;
eventId = 33;
setHeader(new Header(MESSAGE_TYPE, 0x01, (short) getSize()));
allocateBuffer();
writeHeaderToBuffer();
// Write message fields
putUnsignedByte((byte) MESSAGE_VERSION);
putInt((int) timeStamp, 6);
putInt((int) ack, 2);
putInt((int) raceId, 4);
putInt((int) destSourceId, 4);
putInt((int) incidentId, 4);
putInt((int) eventId, 1);
writeCRC();
rewind();
}
/**
* @return The length of this message
*/
public int getSize() {
return MESSAGE_SIZE;
}
}
@@ -1,125 +0,0 @@
package seng302.gameServer.server.simulator;
import seng302.model.GeoPoint;
import seng302.utilities.GeoUtility;
public class Boat {
private int sourceID;
private double lat;
private double lng;
private double speed; // in mm/sec
private String boatName, shortName, shorterName;
private boolean isFinished;
private long estimatedTimeTillFinish;
private Corner lastPassedCorner, headingCorner;
public Boat(int sourceID, String boatName) {
this.sourceID = sourceID;
this.boatName = boatName;
this.isFinished = false;
estimatedTimeTillFinish = 0;
}
/**
* Moves boat to the heading direction for a given time duration
* @param heading moving direction in degree.
* @param duration moving duration in millisecond.
*/
public void move(double heading, double duration) {
Double distance = speed * duration / 1000000; // convert mm to meter
GeoPoint originPos = new GeoPoint(lat, lng);
GeoPoint newPos = GeoUtility.getGeoCoordinate(originPos, heading, distance);
this.lat = newPos.getLat();
this.lng = newPos.getLng();
}
public String toString() {
return String.format("Boat (%d): lat: %f, lng: %f", sourceID, lat, lng);
}
public int getSourceID() {
return sourceID;
}
public void setSourceID(int sourceID) {
this.sourceID = sourceID;
}
public double getLat() {
return lat;
}
public void setLat(double lat) {
this.lat = lat;
}
public double getLng() {
return lng;
}
public void setLng(double lng) {
this.lng = lng;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public String getBoatName() {
return boatName;
}
public void setBoatName(String boatName) {
this.boatName = boatName;
}
public String getShortName() {
return shortName;
}
public void setShortName(String shortName) {
this.shortName = shortName;
}
public String getShorterName() {
return shorterName;
}
public void setShorterName(String shorterName) {
this.shorterName = shorterName;
}
public Corner getLastPassedCorner() {
return lastPassedCorner;
}
public void setLastPassedCorner(Corner lastPassedCorner) {
this.lastPassedCorner = lastPassedCorner;
}
public Corner getHeadingCorner() {
return headingCorner;
}
public void setHeadingCorner(Corner headingCorner) {
this.headingCorner = headingCorner;
}
public boolean isFinished() {
return isFinished;
}
public void setFinished(boolean finished) {
isFinished = finished;
}
public long getEstimatedTimeTillFinish(){
return (long) (-getSpeed()) + System.currentTimeMillis();
}
}
@@ -1,91 +0,0 @@
package seng302.gameServer.server.simulator;
import seng302.model.mark.CompoundMark;
public class Corner {
private int seqID;
private CompoundMark compoundMark;
//private int CompoundMarkID;
private RoundingType roundingType;
private int zoneSize; // size of the zone around a mark in boat-lengths.
// TODO: this shouldn't be used in the future!!!!
private double bearingToNextCorner, distanceToNextCorner;
private Corner nextCorner;
public Corner(int seqID, CompoundMark compoundMark, RoundingType roundingType, int zoneSize) {
this.seqID = seqID;
this.compoundMark = compoundMark;
this.roundingType = roundingType;
this.zoneSize = zoneSize;
}
/**
* Prints out corner's info and its compound mark, good for testing
* @return a string showing its details
*/
@Override
public String toString() {
return String.format("Corner: %d - %s - %d, %s\n",
seqID, roundingType.getType(), zoneSize, compoundMark.toString());
}
public int getSeqID() {
return seqID;
}
public void setSeqID(int seqID) {
this.seqID = seqID;
}
public CompoundMark getCompoundMark() {
return compoundMark;
}
public void setCompoundMark(CompoundMark compoundMark) {
this.compoundMark = compoundMark;
}
public RoundingType getRoundingType() {
return roundingType;
}
public void setRoundingType(RoundingType roundingType) {
this.roundingType = roundingType;
}
public int getZoneSize() {
return zoneSize;
}
public void setZoneSize(int zoneSize) {
this.zoneSize = zoneSize;
}
// TODO: next six setters & getters shouldn't be used in the future.
public double getBearingToNextCorner() {
return bearingToNextCorner;
}
public void setBearingToNextCorner(double bearingToNextCorner) {
this.bearingToNextCorner = bearingToNextCorner;
}
public double getDistanceToNextCorner() {
return distanceToNextCorner;
}
public void setDistanceToNextCorner(double distanceToNextCorner) {
this.distanceToNextCorner = distanceToNextCorner;
}
public Corner getNextCorner() {
return nextCorner;
}
public void setNextCorner(Corner nextCorner) {
this.nextCorner = nextCorner;
}
}
@@ -1,43 +0,0 @@
package seng302.gameServer.server.simulator;
public enum RoundingType {
// the mark should be rounded to port (boat's left)
PORT("Port"),
// the mark should be rounded to starboard (boat's right)
STARBOARD("Stbd"),
// the boat within the compound mark with the SeqID of 1 should be rounded
// to starboard and the boat within the compound mark with the SeqID of 2
// should be rounded to port.
SP("SP"),
// the opposite of SP
PS("PS");
private String type;
RoundingType(String type) {
this.type = type;
}
public String getType() {
return this.type;
}
public static RoundingType typeOf(String type) {
switch (type) {
case "Port":
return PORT;
case "Stbd":
return STARBOARD;
case "SP":
return SP;
case "PS":
return PS;
default:
return null;
}
}
}
@@ -1,19 +0,0 @@
package seng302.gameServer.server.simulator.parsers;
import org.w3c.dom.Document;
/**
* Parses the race xml file to get course details
* Created by Haoming Yin (hyi25) on 16/3/2017
*/
public class BoatsParser extends FileParser {
private Document doc;
public BoatsParser(String path) {
super(path);
this.doc = this.parseFile();
}
}
@@ -1,118 +0,0 @@
package seng302.gameServer.server.simulator.parsers;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import seng302.gameServer.server.simulator.Corner;
import seng302.gameServer.server.simulator.RoundingType;
import seng302.model.mark.CompoundMark;
import seng302.model.mark.Mark;
/**
* Parses the race xml file to get course details
* Created by Haoming Yin (hyi25) on 16/3/2017
*/
public class CourseParser extends FileParser {
private Document doc;
private Map<Integer, CompoundMark> compoundMarksMap;
public CourseParser(String path) {
super(path);
this.doc = this.parseFile();
}
// TODO: should handle error / invalid file gracefully
protected List<Corner> getCourse() {
compoundMarksMap = getCompoundMarks(doc.getDocumentElement());
List<Corner> corners = new ArrayList<>();
NodeList cMarksSequence = doc.getElementsByTagName("Corner");
for (int i = 0; i < cMarksSequence.getLength(); i++) {
corners.add(getCorner(cMarksSequence.item(i)));
}
return corners;
}
private Corner getCorner(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
Integer seqId = Integer.valueOf(e.getAttribute("SeqID"));
Integer cMarkId = Integer.valueOf(e.getAttribute("CompoundMarkID"));
CompoundMark cMark = compoundMarksMap.get(cMarkId);
RoundingType roundingType = RoundingType.typeOf(e.getAttribute("Rounding"));
Integer zoneSize = Integer.valueOf(e.getAttribute("ZoneSize"));
return new Corner(seqId, cMark, roundingType, zoneSize);
}
return null;
}
private Map<Integer, CompoundMark> getCompoundMarks(Node node) {
Map<Integer, CompoundMark> compoundMarksMap = new HashMap<>();
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element element = (Element) node;
NodeList cMarks = element.getElementsByTagName("CompoundMark");
// loop through all compound marks who are the children of course node
for (int i = 0; i < cMarks.getLength(); i++) {
CompoundMark cMark = getCompoundMark(cMarks.item(i));
if (cMark != null)
compoundMarksMap.put(cMark.getId(), cMark);
}
return compoundMarksMap;
}
return null;
}
private CompoundMark getCompoundMark(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
Integer markID = Integer.valueOf(e.getAttribute("CompoundMarkID"));
String name = e.getAttribute("Name");
NodeList marks = e.getElementsByTagName("Mark");
List<Mark> subMarks = new ArrayList<>();
for (int i = 0; i < marks.getLength(); i++) {
Mark mark = getMark(marks.item(i));
if (mark != null) {
subMarks.add(mark);
}
}
return new CompoundMark(markID, name, subMarks);
}
System.out.println("Failed to create compound mark.");
return null;
}
private Mark getMark(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
Integer seqId = Integer.valueOf(e.getAttribute("SeqID"));
String name = e.getAttribute("Name");
Double lat = Double.valueOf(e.getAttribute("TargetLat"));
Double lng = Double.valueOf(e.getAttribute("TargetLng"));
Integer sourceId = Integer.valueOf(e.getAttribute("SourceID"));
Mark mark = new Mark(name, lat, lng, sourceId);
mark.setSeqID(seqId);
return mark;
}
System.out.println("Failed to create mark.");
return null;
}
}
@@ -1,51 +0,0 @@
package seng302.gameServer.server.simulator.parsers;
import java.io.InputStream;
import java.io.StringReader;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
/**
* 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) {
System.out.println("[FileParser] Exception");
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) {
System.out.println("[FileParser] Exception");
}
return null;
}
}
@@ -1,65 +0,0 @@
package seng302.gameServer.server.simulator.parsers;
import java.util.ArrayList;
import java.util.List;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import seng302.gameServer.server.simulator.Boat;
import seng302.gameServer.server.simulator.Corner;
/**
* Parses the race xml file to get course details
* Created by Haoming Yin (hyi25) on 16/3/2017
*/
public class RaceParser extends FileParser {
private Document doc;
private String path;
public RaceParser(String path) {
super(path);
this.path = path;
this.doc = this.parseFile();
}
/**
* Parses race.xml file and returns a list of corner which is the race course.
* @return a list of ordered corner to represent the course.
*/
public List<Corner> getCourse() {
CourseParser cp = new CourseParser(path);
return cp.getCourse();
}
/**
* Parses race.xml file and return a list of boats which will compete in the
* race.
* @return a list of boats that are going to compete in the race.
*/
public List<Boat> getBoats() {
NodeList yachts = doc.getDocumentElement().getElementsByTagName("Yacht");
List<Boat> boats = new ArrayList<>();
for (int i = 0; i < yachts.getLength(); i++) {
boats.add(getBoat(yachts.item(i)));
}
return boats;
}
/**
* Parses a single boat from the given node
* @param node a node within a boat tag
* @return a boat instance parsed from the given node
*/
private Boat getBoat(Node node) {
if (node.getNodeType() == Node.ELEMENT_NODE) {
Element e = (Element) node;
Integer sourceId = Integer.valueOf(e.getAttribute("SourceID"));
return new Boat(sourceId, "Test Boat");
}
return null;
}
}