diff --git a/src/main/java/seng302/gameServer/MainServerThread.java b/src/main/java/seng302/gameServer/MainServerThread.java index 6e827d95..dca712f3 100644 --- a/src/main/java/seng302/gameServer/MainServerThread.java +++ b/src/main/java/seng302/gameServer/MainServerThread.java @@ -82,7 +82,7 @@ public class MainServerThread extends Observable implements Runnable, ClientConn public void updateClients() { for (ServerToClientThread serverToClientThread : serverToClientThreads) { - serverToClientThread.updateClient(); + serverToClientThread.sendBoatLocationPackets(); } } diff --git a/src/main/java/seng302/gameServer/ServerToClientThread.java b/src/main/java/seng302/gameServer/ServerToClientThread.java index c77607e3..223598bd 100644 --- a/src/main/java/seng302/gameServer/ServerToClientThread.java +++ b/src/main/java/seng302/gameServer/ServerToClientThread.java @@ -18,6 +18,8 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.stream.Collectors; import java.util.zip.CRC32; import java.util.zip.Checksum; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import seng302.gameServer.server.messages.BoatActionType; import seng302.gameServer.server.messages.BoatLocationMessage; import seng302.gameServer.server.messages.BoatStatus; @@ -46,8 +48,7 @@ import seng302.utilities.XMLGenerator; */ public class ServerToClientThread implements Runnable, Observer { - private static final Integer LOG_LEVEL = 1; - private static final Integer MAX_ID_ATTEMPTS = 10; + private Logger logger = LoggerFactory.getLogger(ServerToClientThread.class); private Thread thread; @@ -57,11 +58,6 @@ public class ServerToClientThread implements Runnable, Observer { private ByteArrayOutputStream crcBuffer; - private Boolean userIdentified = false; - private Boolean connected = true; - private Boolean updateClient = true; -// private Boolean initialisedRace = true; - private Integer seqNo; private Integer sourceId; @@ -120,13 +116,6 @@ public class ServerToClientThread implements Runnable, Observer { GameState.addPlayer(new Player(socket, yacht)); } - static void serverLog(String message, int logLevel) { - if (logLevel <= LOG_LEVEL) { - System.out.println( - "[SERVER " + LocalDateTime.now().toLocalTime().toString() + "] " + message); - } - } - @Override public void update(Observable o, Object arg) { if (arg != null) { @@ -172,20 +161,6 @@ public class ServerToClientThread implements Runnable, Observer { while (socket.isConnected()) { try { - //Perform a write if it is time to as delegated by the MainServerThread - if (updateClient) { - // TODO: 13/07/17 wmu16 - Write out game state - some function that would write all appropriate messages to this output stream -// ChatterMessage chatterMessage = new ChatterMessage(4, 14, "Hello, it's me"); -// sendMessage(chatterMessage); -// try { -// GameState.outputState(os); -// } catch (IOException e) { -// System.out.println("IO error in server thread upon writing to output stream"); -// } -// sendBoatLocationPackets(); - updateClient = false; - } - crcBuffer = new ByteArrayOutputStream(); sync1 = readByte(); sync2 = readByte(); @@ -219,7 +194,7 @@ public class ServerToClientThread implements Runnable, Observer { break; } } else { - serverLog("Packet has been dropped", 1); + logger.warn("Packet has been dropped", 1); } } } catch (Exception e) { @@ -257,27 +232,6 @@ public class ServerToClientThread implements Runnable, Observer { sendMessage(xmlMessage); } - public void updateClient() { - sendBoatLocationPackets(); - updateClient = true; - } - - - /** - * Tries to confirm the connection just accepted. - * Sends ID, expects that ID echoed for confirmation, - * if so, sends a confirmation packet back to that connection - * Creates a player instance with that ID and this thread and adds it to the GameState - * If not, close the socket and end the threads execution - * - * @param id the id to try and assign to the connection - * @return A boolean indicating if it was a successful handshake - */ - private Boolean threeWayHandshake(Integer id) { - - return true; - } - private void closeSocket() { try { socket.close(); @@ -295,7 +249,7 @@ public class ServerToClientThread implements Runnable, Observer { crcBuffer.write(currentByte); } catch (IOException e) { e.printStackTrace(); - serverLog("Socket read failed", 1); + logger.warn("Socket read failed", 1); } if (currentByte == -1) { throw new Exception(); @@ -324,7 +278,7 @@ public class ServerToClientThread implements Runnable, Observer { //serverLog("Player " + sourceId + " side socket disconnected", 1); return; } catch (IOException e) { - serverLog("Message send failed", 1); + logger.warn("Message send failed", 1); } } @@ -334,7 +288,7 @@ public class ServerToClientThread implements Runnable, Observer { } - private void sendBoatLocationPackets() { + public void sendBoatLocationPackets() { ArrayList yachts = new ArrayList<>(GameState.getYachts().values()); for (Yacht yacht : yachts) { // System.out.println("[SERVER] Lat: " + yacht.getLocation().getLat() + " Lon: " + yacht.getLocation().getLng()); diff --git a/src/main/java/seng302/gameServer/server/messages/MarkRoundingMessage.java b/src/main/java/seng302/gameServer/server/messages/MarkRoundingMessage.java index b683930e..c2223f5d 100644 --- a/src/main/java/seng302/gameServer/server/messages/MarkRoundingMessage.java +++ b/src/main/java/seng302/gameServer/server/messages/MarkRoundingMessage.java @@ -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; @@ -24,7 +26,7 @@ public class MarkRoundingMessage extends Message{ * @param markId markId */ public MarkRoundingMessage(int ackNumber, int raceId, int sourceId, RoundingBoatStatus roundingBoatStatus, - RoundingSide roundingSide, int markId){ + RoundingSide roundingSide, MarkType markType, int markId) { this.time = System.currentTimeMillis() / 1000L; this.ackNumber = ackNumber; this.raceId = raceId; @@ -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(); diff --git a/src/main/java/seng302/gameServer/server/messages/RoundingSide.java b/src/main/java/seng302/gameServer/server/messages/RoundingSide.java index 6bb4c553..efb4c929 100644 --- a/src/main/java/seng302/gameServer/server/messages/RoundingSide.java +++ b/src/main/java/seng302/gameServer/server/messages/RoundingSide.java @@ -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; + } } diff --git a/src/main/java/seng302/gameServer/server/simulator/Boat.java b/src/main/java/seng302/gameServer/server/simulator/Boat.java deleted file mode 100644 index c083dbf2..00000000 --- a/src/main/java/seng302/gameServer/server/simulator/Boat.java +++ /dev/null @@ -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(); - } -} diff --git a/src/main/java/seng302/gameServer/server/simulator/Corner.java b/src/main/java/seng302/gameServer/server/simulator/Corner.java deleted file mode 100644 index 11c26104..00000000 --- a/src/main/java/seng302/gameServer/server/simulator/Corner.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/java/seng302/gameServer/server/simulator/RoundingType.java b/src/main/java/seng302/gameServer/server/simulator/RoundingType.java deleted file mode 100644 index aa1bca8e..00000000 --- a/src/main/java/seng302/gameServer/server/simulator/RoundingType.java +++ /dev/null @@ -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; - } - } -} diff --git a/src/main/java/seng302/gameServer/server/simulator/parsers/BoatsParser.java b/src/main/java/seng302/gameServer/server/simulator/parsers/BoatsParser.java deleted file mode 100644 index 17a46eae..00000000 --- a/src/main/java/seng302/gameServer/server/simulator/parsers/BoatsParser.java +++ /dev/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(); - } - -} diff --git a/src/main/java/seng302/gameServer/server/simulator/parsers/CourseParser.java b/src/main/java/seng302/gameServer/server/simulator/parsers/CourseParser.java deleted file mode 100644 index 36164af2..00000000 --- a/src/main/java/seng302/gameServer/server/simulator/parsers/CourseParser.java +++ /dev/null @@ -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 compoundMarksMap; - - public CourseParser(String path) { - super(path); - this.doc = this.parseFile(); - } - - // TODO: should handle error / invalid file gracefully - protected List getCourse() { - compoundMarksMap = getCompoundMarks(doc.getDocumentElement()); - List 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 getCompoundMarks(Node node) { - Map 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 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; - } - -} diff --git a/src/main/java/seng302/gameServer/server/simulator/parsers/FileParser.java b/src/main/java/seng302/gameServer/server/simulator/parsers/FileParser.java deleted file mode 100644 index 87021893..00000000 --- a/src/main/java/seng302/gameServer/server/simulator/parsers/FileParser.java +++ /dev/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; - } -} diff --git a/src/main/java/seng302/gameServer/server/simulator/parsers/RaceParser.java b/src/main/java/seng302/gameServer/server/simulator/parsers/RaceParser.java deleted file mode 100644 index 960ff8fc..00000000 --- a/src/main/java/seng302/gameServer/server/simulator/parsers/RaceParser.java +++ /dev/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 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 getBoats() { - NodeList yachts = doc.getDocumentElement().getElementsByTagName("Yacht"); - List 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; - } -} diff --git a/src/main/java/seng302/model/Yacht.java b/src/main/java/seng302/model/Yacht.java index d395df2b..da1b434f 100644 --- a/src/main/java/seng302/model/Yacht.java +++ b/src/main/java/seng302/model/Yacht.java @@ -16,6 +16,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import seng302.gameServer.GameState; import seng302.gameServer.server.messages.MarkRoundingMessage; +import seng302.gameServer.server.messages.MarkType; import seng302.gameServer.server.messages.Message; import seng302.gameServer.server.messages.RoundingBoatStatus; import seng302.gameServer.server.messages.RoundingSide; @@ -70,6 +71,7 @@ public class Yacht extends Observable { //MARK ROUNDING INFO private GeoPoint lastLocation; //For purposes of mark rounding calculations private Boolean hasEnteredRoundingZone; //The distance that the boat must be from the mark to round + private Mark closestCurrentMark; private Boolean hasPassedLine; private Boolean hasPassedThroughGate; private Boolean finishedRace; @@ -113,7 +115,7 @@ public class Yacht extends Observable { Double windSpeedKnots = GameState.getWindSpeedKnots(); Double trueWindAngle = Math.abs(GameState.getWindDirection() - heading); Double boatSpeedInKnots = PolarTable.getBoatSpeed(windSpeedKnots, trueWindAngle); - Double maxBoatSpeed = boatSpeedInKnots / 1.943844492 * 1000; + Double maxBoatSpeed = boatSpeedInKnots / 1.943844492 * 1000 * 2; if (sailIn && velocity <= maxBoatSpeed && maxBoatSpeed != 0d) { if (velocity < maxBoatSpeed) { @@ -160,14 +162,39 @@ public class Yacht extends Observable { super.addObserver(o); } - private void sendMarkRoundingMessage(Integer passedMarkSeqID) { + private void sendMarkRoundingMessage() { + CompoundMark currentMark = GameState.getMarkOrder().getCurrentMark(currentMarkSeqID); + MarkType markType = (currentMark.isGate()) ? MarkType.GATE : MarkType.ROUNDING_MARK; + // TODO: 13/8/17 figure out the rounding side, rounded mark source ID and boat status. Message markRoundingMessage = new MarkRoundingMessage(0, 0, - getSourceId(), RoundingBoatStatus.RACING, RoundingSide.UNKNOWN, - GameState.getMarkOrder().getCurrentMark(passedMarkSeqID).getSubMark(1).getSourceID()); - logger.debug("Sending mark rounding message..."); + sourceId, RoundingBoatStatus.RACING, closestCurrentMark.getRoundingSide(), markType, + closestCurrentMark.getSourceID()); setChanged(); notifyObservers(markRoundingMessage); + logMarkRounding(currentMark); + + hasPassedLine = false; + hasEnteredRoundingZone = false; + hasPassedThroughGate = false; + currentMarkSeqID++; + } + + private void logMarkRounding(CompoundMark currentMark) { + logger.debug( + String.format("Sending Mark Rounding Message:\n" + + "AckNumber %d\n" + + "RaceID %d\n" + + "BoatSourceID %d\n" + + "BoatStatus %s\n" + + "Rounding Side %s\n" + + "MarkSeqID %d", + 0, + 0, + sourceId, + RoundingBoatStatus.RACING.name(), + closestCurrentMark.getRoundingSide().getName(), + currentMark.getSubMark(1).getSourceID())); } /** @@ -186,8 +213,15 @@ public class Yacht extends Observable { Mark sub2 = nextMark.getSubMark(2); Double distance1 = GeoUtility.getDistance(location, sub1); Double distance2 = GeoUtility.getDistance(location, sub2); - return (distance1 < distance2) ? distance1 : distance2; + if (distance1 < distance2) { + closestCurrentMark = sub1; + return distance1; + } else { + closestCurrentMark = sub2; + return distance2; + } } else { + closestCurrentMark = nextMark.getSubMark(1); return GeoUtility.getDistance(location, nextMark.getSubMark(1)); } } @@ -224,9 +258,8 @@ public class Yacht extends Observable { if (crossedLine > 0) { Boolean isClockwiseCross = GeoUtility.isClockwise(mark1, mark2, nextMark.getMidPoint()); if (crossedLine == 2 && isClockwiseCross || crossedLine == 1 && !isClockwiseCross) { - sendMarkRoundingMessage(currentMarkSeqID); - currentMarkSeqID++; - logMarkRounding(currentMark); + closestCurrentMark = mark1; + sendMarkRoundingMessage(); } } } @@ -257,11 +290,7 @@ public class Yacht extends Observable { } if (hasPassedLine && hasEnteredRoundingZone) { - currentMarkSeqID++; - hasPassedLine = false; - hasEnteredRoundingZone = false; - hasPassedThroughGate = false; - logMarkRounding(currentMark); + sendMarkRoundingMessage(); } } @@ -297,9 +326,7 @@ public class Yacht extends Observable { if (prevMarkSide == nextMarkSide) { checkMarkRounding(currentMark); } else { - sendMarkRoundingMessage(currentMarkSeqID); - currentMarkSeqID++; - logMarkRounding(currentMark); + sendMarkRoundingMessage(); } } } @@ -318,12 +345,10 @@ public class Yacht extends Observable { if (crossedLine > 0) { Boolean isClockwiseCross = GeoUtility.isClockwise(mark1, mark2, prevMark.getMidPoint()); if (crossedLine == 1 && isClockwiseCross || crossedLine == 2 && !isClockwiseCross) { - sendMarkRoundingMessage(currentMarkSeqID); - currentMarkSeqID++; + closestCurrentMark = mark1; + sendMarkRoundingMessage(); finishedRace = true; - logMarkRounding(currentMark); logger.debug(sourceId + " finished"); - // TODO: 8/08/17 wmu16 - Do something! } } } @@ -683,20 +708,6 @@ public class Yacht extends Observable { } } - private void logMarkRounding(CompoundMark currentMark) { - String typeString = "mark"; - if (currentMark.isGate()) { - typeString = "gate"; - } - logger.debug( - String.format("BoatID %d passed %s %s with id %d. Now on leg %d", - sourceId, - typeString, - currentMark.getMarks().get(0).getName(), - currentMark.getId(), - currentMarkSeqID)); - } - public void addLocationListener(YachtLocationListener listener) { locationListeners.add(listener); } diff --git a/src/main/java/seng302/model/mark/CompoundMark.java b/src/main/java/seng302/model/mark/CompoundMark.java index fe5147de..70cd114f 100644 --- a/src/main/java/seng302/model/mark/CompoundMark.java +++ b/src/main/java/seng302/model/mark/CompoundMark.java @@ -2,6 +2,7 @@ package seng302.model.mark; import java.util.ArrayList; import java.util.List; +import seng302.gameServer.server.messages.RoundingSide; import seng302.model.GeoPoint; import seng302.utilities.GeoUtility; @@ -9,7 +10,6 @@ public class CompoundMark { private int compoundMarkId; private String name; - private List marks = new ArrayList<>(); private GeoPoint midPoint; @@ -55,6 +55,27 @@ public class CompoundMark { this.name = name; } + public void setRoundingSide(RoundingSide roundingSide) { + switch (roundingSide) { + case SP: + getSubMark(1).setRoundingSide(RoundingSide.STARBOARD); + getSubMark(2).setRoundingSide(RoundingSide.PORT); + break; + case PS: + getSubMark(1).setRoundingSide(RoundingSide.PORT); + getSubMark(2).setRoundingSide(RoundingSide.STARBOARD); + break; + case PORT: + getSubMark(1).setRoundingSide(RoundingSide.PORT); + break; + case STARBOARD: + getSubMark(1).setRoundingSide(RoundingSide.STARBOARD); + break; + + + } + } + /** * Returns the mark contained in the compound mark. Marks are numbered 1 to n; * @param singleMarkId the id of the desired mark contained in this compound mark. diff --git a/src/main/java/seng302/model/mark/Mark.java b/src/main/java/seng302/model/mark/Mark.java index 57d04974..de66166c 100644 --- a/src/main/java/seng302/model/mark/Mark.java +++ b/src/main/java/seng302/model/mark/Mark.java @@ -2,6 +2,7 @@ package seng302.model.mark; import java.util.ArrayList; import java.util.List; +import seng302.gameServer.server.messages.RoundingSide; import seng302.model.GeoPoint; /** @@ -19,11 +20,13 @@ public class Mark extends GeoPoint { private String name; private int sourceID; private List positionListeners = new ArrayList<>(); + private RoundingSide roundingSide; - public Mark(String name, double lat, double lng, int sourceID) { + public Mark(String name, int seqID, double lat, double lng, int sourceID) { super(lat, lng); this.name = name; this.sourceID = sourceID; + this.seqID = seqID; } /** @@ -39,10 +42,6 @@ public class Mark extends GeoPoint { return seqID; } - public void setSeqID(int seqID) { - this.seqID = seqID; - } - public String getName() { return name; } @@ -55,6 +54,14 @@ public class Mark extends GeoPoint { return sourceID; } + public RoundingSide getRoundingSide() { + return roundingSide; + } + + public void setRoundingSide(RoundingSide roundingSide) { + this.roundingSide = roundingSide; + } + public void setSourceID(int sourceID) { this.sourceID = sourceID; } diff --git a/src/main/java/seng302/model/mark/MarkOrder.java b/src/main/java/seng302/model/mark/MarkOrder.java index 1b744fc2..800e4e76 100644 --- a/src/main/java/seng302/model/mark/MarkOrder.java +++ b/src/main/java/seng302/model/mark/MarkOrder.java @@ -14,6 +14,7 @@ import org.slf4j.LoggerFactory; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; +import seng302.gameServer.server.messages.RoundingSide; import seng302.model.stream.xml.generator.Race; import seng302.model.stream.xml.parser.RaceXMLData; import seng302.utilities.XMLGenerator; @@ -104,6 +105,7 @@ public class MarkOrder { for (Corner corner : corners){ CompoundMark compoundMark = marks.get(corner.getCompoundMarkID()); + compoundMark.setRoundingSide(RoundingSide.getRoundingSide(corner.getRounding())); course.add(compoundMark); } diff --git a/src/main/java/seng302/utilities/XMLParser.java b/src/main/java/seng302/utilities/XMLParser.java index c4c4348b..a88af9b4 100644 --- a/src/main/java/seng302/utilities/XMLParser.java +++ b/src/main/java/seng302/utilities/XMLParser.java @@ -277,11 +277,12 @@ public class XMLParser { for (int i = 0; i < childMarks.getLength(); i++) { Node markNode = childMarks.item(i); if (markNode.getNodeName().equals("Mark")) { + Integer seqID = XMLParser.getNodeAttributeInt(markNode, "SeqID"); Integer sourceID = XMLParser.getNodeAttributeInt(markNode, "SourceID"); String markName = XMLParser.getNodeAttributeString(markNode, "Name"); Double targetLat = XMLParser.getNodeAttributeDouble(markNode, "TargetLat"); Double targetLng = XMLParser.getNodeAttributeDouble(markNode, "TargetLng"); - Mark mark = new Mark(markName, targetLat, targetLng, sourceID); + Mark mark = new Mark(markName, seqID, targetLat, targetLng, sourceID); subMarks.add(mark); } } diff --git a/src/main/java/seng302/visualiser/GameView.java b/src/main/java/seng302/visualiser/GameView.java index 73d49b89..14c8a319 100644 --- a/src/main/java/seng302/visualiser/GameView.java +++ b/src/main/java/seng302/visualiser/GameView.java @@ -201,6 +201,16 @@ public class GameView extends Pane { for (Mark mark : cMark.getMarks()) { makeAndBindMarker(mark, colour); } + + //UNCOMMENT THIS TO HIGHLIGHT SUBMARKS 1 and 2 RED AND GREEN RESPECTIVELY FOR DEBUG + //(instead of above for loop) +// for (Mark mark : cMark.getMarks()) { +// if (mark.getSeqID() == 1) { +// makeAndBindMarker(mark, Color.RED); +// } else { +// makeAndBindMarker(mark, Color.GREEN); +// } +// } //Create gate line if (cMark.isGate()) { for (int i = 1; i < cMark.getMarks().size(); i++) { diff --git a/src/test/java/seng302/model/mark/CompoundMarkTest.java b/src/test/java/seng302/model/mark/CompoundMarkTest.java index 83b2b2bb..90d5c099 100644 --- a/src/test/java/seng302/model/mark/CompoundMarkTest.java +++ b/src/test/java/seng302/model/mark/CompoundMarkTest.java @@ -26,8 +26,8 @@ public class CompoundMarkTest { @Before public void setUp() throws Exception { - mark1 = new Mark("Mark1", 57.670333, 11.842833, 0); - mark2 = new Mark("Mark2", 57.671524, 11.844495, 1); + mark1 = new Mark("Mark1", 1, 57.670333, 11.842833, 0); + mark2 = new Mark("Mark2", 2, 57.671524, 11.844495, 1); List gateMarks = new ArrayList(); gateMarks.add(mark1);