diff --git a/src/main/java/seng302/gameServer/GameState.java b/src/main/java/seng302/gameServer/GameState.java index 16eb8050..918cd210 100644 --- a/src/main/java/seng302/gameServer/GameState.java +++ b/src/main/java/seng302/gameServer/GameState.java @@ -1,13 +1,14 @@ package seng302.gameServer; +import seng302.client.ClientPacketParser; +import seng302.models.Player; +import seng302.models.Yacht; +import seng302.server.messages.BoatActionType; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; -import seng302.client.ClientPacketParser; -import seng302.models.Player; -import seng302.models.Yacht; -import seng302.server.messages.BoatActionType; /** * A Static class to hold information about the current state of the game (model) @@ -43,7 +44,6 @@ public class GameState implements Runnable { yachts = new HashMap<>(); new Thread(this).start(); - } public static String getHostIpAddress() { diff --git a/src/main/java/seng302/models/map/CanvasMap.java b/src/main/java/seng302/models/map/CanvasMap.java index e6a00cfa..de6403c7 100644 --- a/src/main/java/seng302/models/map/CanvasMap.java +++ b/src/main/java/seng302/models/map/CanvasMap.java @@ -7,8 +7,6 @@ import seng302.utilities.GeoPoint; import javax.net.ssl.HttpsURLConnection; import java.net.URL; -import java.lang.Math; - /** * CanvasMap retrieves a map image with given geo boundary from Google Map server. * By passing a rectangle like geo boundary, it returns a map image with the diff --git a/src/main/java/seng302/models/mark/Mark.java b/src/main/java/seng302/models/mark/Mark.java index 027bf6d3..362c77fd 100644 --- a/src/main/java/seng302/models/mark/Mark.java +++ b/src/main/java/seng302/models/mark/Mark.java @@ -145,4 +145,42 @@ public abstract class Mark { public int getCompoundMarkID() { return compoundMarkID; } + + @Override + public boolean equals(Object other) { + if (other == null) { + return false; + } + + if (!(other instanceof Mark)){ + return false; + } + + Mark otherMark = (Mark) other; + + if (otherMark.getLatitude() != getLatitude() || otherMark.getLongitude() != getLongitude()) { + return false; + } + + if (otherMark.getCompoundMarkID() != getCompoundMarkID()){ + return false; + } + + if (otherMark.getId() != getId()){ + return false; + } + + if (!otherMark.getName().equals(name)){ + return false; + } + + return true; + } + + @Override + public int hashCode() { + return getName().hashCode() + getMarkType().hashCode() + + Integer.hashCode(getCompoundMarkID()) + Double.hashCode(getLatitude()) + + Double.hashCode(getLongitude()); + } } diff --git a/src/main/java/seng302/models/mark/MarkOrder.java b/src/main/java/seng302/models/mark/MarkOrder.java new file mode 100644 index 00000000..bf6f5f40 --- /dev/null +++ b/src/main/java/seng302/models/mark/MarkOrder.java @@ -0,0 +1,116 @@ +package seng302.models.mark; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; +import seng302.models.stream.XMLParser; +import seng302.models.xml.Race; +import seng302.models.xml.XMLGenerator; +import seng302.server.messages.XMLMessageSubType; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.StringReader; +import java.util.Collections; +import java.util.List; + +/** + * Class to hold the order of the marks in the race. + */ +public class MarkOrder { + private List raceMarkOrder; + private Logger logger = LoggerFactory.getLogger(MarkOrder.class); + + public MarkOrder(){ + loadRaceProperties(); + } + + /** + * @return An ordered list of marks in the race + * OR null if the mark order could not be loaded + */ + public List getMarkOrder(){ + if (raceMarkOrder == null){ + logger.warn("Race order accessed but not instantiated"); + return null; + } + + return Collections.unmodifiableList(raceMarkOrder); + } + + /** + * Returns the mark in the race after the previous mark + * @param previous The previous mark + * @return the next mark + * OR null if there is no next mark + */ + public Mark getNextMark(Mark previous){ + for (int i = 0; i < raceMarkOrder.size(); i++){ + Mark mark = raceMarkOrder.get(i); + + if (i + 1 >= raceMarkOrder.size()){ + return null; + } + + if (mark.equals(previous)){ + return raceMarkOrder.get(i+1); + } + } + + return null; + } + + /** + * Loads the race order from an XML string + * @param xml An AC35 RaceXML + * @return An ordered list of marks in the race + */ + private List loadRaceOrderFromXML(String xml){ + XMLParser xmlParser = new XMLParser(); + XMLParser.RaceXMLObject raceXMLObject; + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db; + Document doc; + + try { + db = dbf.newDocumentBuilder(); + doc = db.parse(new InputSource(new StringReader(xml))); + } catch (ParserConfigurationException | IOException | SAXException e) { + logger.error("Failed to read generated race XML"); + return null; + } + + xmlParser.constructXML(doc , XMLMessageSubType.RACE.getType()); + raceXMLObject = xmlParser.getRaceXML(); + + if (raceXMLObject != null){ + logger.debug("Loaded RaceXML for mark order"); + return raceXMLObject.getNonDupCompoundMarks(); + } + + return null; + } + + /** + * Load the raceXML and mark order + */ + private void loadRaceProperties(){ + XMLGenerator generator = new XMLGenerator(); + + generator.setRace(new Race()); + + String raceXML = generator.getRaceAsXml(); + + if (raceXML == null){ + logger.error("Failed to generate raceXML (for race properties)"); + return; + } + + raceMarkOrder = loadRaceOrderFromXML(raceXML); + } +} diff --git a/src/main/java/seng302/server/messages/Message.java b/src/main/java/seng302/server/messages/Message.java index 398628ab..10afb8e5 100644 --- a/src/main/java/seng302/server/messages/Message.java +++ b/src/main/java/seng302/server/messages/Message.java @@ -1,7 +1,5 @@ package seng302.server.messages; -import java.io.IOException; -import java.io.OutputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Arrays; diff --git a/src/test/java/seng302/models/MarkOrderTest.java b/src/test/java/seng302/models/MarkOrderTest.java new file mode 100644 index 00000000..97db018c --- /dev/null +++ b/src/test/java/seng302/models/MarkOrderTest.java @@ -0,0 +1,95 @@ +package seng302.models; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import seng302.models.mark.Mark; +import seng302.models.mark.MarkOrder; +import seng302.models.mark.SingleMark; + +import static junit.framework.TestCase.*; +import static org.junit.Assert.assertNotEquals; + +public class MarkOrderTest { + private static MarkOrder markOrder; + + @BeforeClass + public static void setup(){ + markOrder = new MarkOrder(); + } + + /** + * Test to ensure marks are loaded from XML + */ + @Test + public void testMarkOrderLoadedFromXML(){ + assertTrue(markOrder != null); + } + + /** + * Test if .equals() method on returns true on two marks that are equal + */ + @Test + public void testMarkEqualsTrue(){ + Mark mark1 = new SingleMark("asd", 1.1, 2.2, 1, 2); + Mark mark2 = new SingleMark("asd", 1.1, 2.2, 1, 2); + + assertEquals(mark1, mark2); + } + + /** + * Test if .equals() method on returns false on two marks that are NOT equal + */ + @Test + public void testMarkNotEquals(){ + Mark mark1 = new SingleMark("asf", 1.1, 2.2, 2, 2); + Mark mark2 = new SingleMark("asd", 1.1, 2.2, 1, 2); + + assertNotEquals(mark1, mark2); + } + + /** + * Test if .getNextMark() returns null if it is called with the final mark in the race + */ + @Test + public void testNextMarkAtEnd(){ + // There are no marks in the XML, therefore this can't be tested + if (markOrder.getMarkOrder().size() == 0){ + return; + } + + Mark lastMark = markOrder.getMarkOrder().get(markOrder.getMarkOrder().size() - 1); + + assertEquals(null, markOrder.getNextMark(lastMark)); + } + + /** + * Test if .getNextMark() method on returns null if the mark does not exist in the race + */ + @Test + public void testNextMarkNotExists(){ + Mark someMark = new SingleMark("0-0-0-0-0-0-0", 0.0, 0.1, 2, 1); + + assertEquals(null, markOrder.getNextMark(someMark)); + } + + /** + * Test if .getNextMark() method returns the next mark in the race + */ + @Test + public void testNextMark(){ + // There are not enough marks for this to be tested + if (markOrder.getMarkOrder().size() < 2){ + return; + } + + Mark firstMark = markOrder.getMarkOrder().get(0); + + assertEquals(markOrder.getMarkOrder().get(1), markOrder.getNextMark(firstMark)); + } + + @AfterClass + public static void tearDown(){ + markOrder = null; + } +}