diff --git a/src/main/java/seng302/server/messages/BoatLocationMessage.java b/src/main/java/seng302/server/messages/BoatLocationMessage.java index a475128b..4b914699 100644 --- a/src/main/java/seng302/server/messages/BoatLocationMessage.java +++ b/src/main/java/seng302/server/messages/BoatLocationMessage.java @@ -65,11 +65,66 @@ public class BoatLocationMessage extends Message { setHeader(new Header(MessageType.BOAT_LOCATION, 1, (short) getSize())); } + /** + * Convert binary latitude or longitude to floating point number + * @param binaryPackedLatLon Binary packed lat OR lon + * @return Floating point lat/lon + */ + public static double binaryPackedToLatLon(long binaryPackedLatLon){ + return (double)binaryPackedLatLon * 180.0 / 2147483648.0; + } + + /** + * Convert binary packed heading to floating point number + * @param binaryPackedHeading Binary packed heading + * @return heading as a decimal + */ + public static double binaryPackedHeadingToDouble(long binaryPackedHeading){ + return (double)binaryPackedHeading * 360.0 / 65536.0; + } + + /** + * Convert binary packed wind angle to floating point number + * @param binaryPackedWindAngle Binary packed wind angle + * @return wind angle as a decimal + */ + public static double binaryPackedWindAngleToDouble(long binaryPackedWindAngle){ + return (double)binaryPackedWindAngle*180.0/32768.0; + } + + /** + * Convert a latitude or longitude to a binary packed long + * @param latLon A floating point latitude/longitude + * @return A binary packed lat/lon + */ + public static long latLonToBinaryPackedLong(double latLon){ + return (long)((536870912 * latLon) / 45); + } + + /** + * Convert a heading to a binary packed long + * @param heading A floating point heading + * @return A binary packed heading + */ + public static long headingToBinaryPackedLong(double heading){ + return (long)((8192*heading)/45); + } + + /** + * Convert a wind angle to a binary packed long + * @param windAngle Floating point wind angle + * @return A binary packed wind angle + */ + public static long windAngleToBinaryPackedLong(double windAngle){ + return (long)((8192*windAngle)/45); + } + @Override public int getSize() { - return 56; + return MESSAGE_SIZE; } + @Override public void send(DataOutputStream outputStream) { allocateBuffer(); diff --git a/src/main/java/seng302/server/messages/MarkRoundingMessage.java b/src/main/java/seng302/server/messages/MarkRoundingMessage.java new file mode 100644 index 00000000..405c46ff --- /dev/null +++ b/src/main/java/seng302/server/messages/MarkRoundingMessage.java @@ -0,0 +1,62 @@ +package seng302.server.messages; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class MarkRoundingMessage extends Message{ + private final long MESSAGE_VERSION_NUMBER = 1; + private final int MESSAGE_SIZE = 21; + + private long time; + private long ackNumber; + private long raceId; + private long sourceId; + private RoundingBoatStatus boatStatus; + private RoundingSide roundingSide; + private long markId; + + /** + * This message is sent when a boat passes a mark, start line, or finish line + * The purpose of this is to record the time when yachts cross marks + */ + public MarkRoundingMessage(int ackNumber, int raceId, int sourceId, RoundingBoatStatus roundingBoatStatus, + RoundingSide roundingSide, int markId){ + this.time = System.currentTimeMillis() / 1000L; + this.ackNumber = ackNumber; + this.raceId = raceId; + this.sourceId = sourceId; + this.boatStatus = roundingBoatStatus; + this.roundingSide = roundingSide; + this.markId = markId; + + setHeader(new Header(MessageType.MARK_ROUNDING, 1, (short) getSize())); + } + + @Override + public int getSize() { + return MESSAGE_SIZE; + } + + @Override + public void send(DataOutputStream outputStream) { + allocateBuffer(); + writeHeaderToBuffer(); + + putByte((byte) MESSAGE_VERSION_NUMBER); + putInt((int) time, 6); + putInt((int) ackNumber, 2); + putInt((int) raceId, 4); + putInt((int) sourceId, 4); + putByte((byte) boatStatus.getCode()); + putByte((byte) roundingSide.getCode()); + putByte((byte) markId); + + writeCRC(); + + try { + outputStream.write(getBuffer().array()); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/seng302/server/messages/MarkType.java b/src/main/java/seng302/server/messages/MarkType.java new file mode 100644 index 00000000..abbacc6f --- /dev/null +++ b/src/main/java/seng302/server/messages/MarkType.java @@ -0,0 +1,20 @@ +package seng302.server.messages; + +/** + * Types of marks boats can round + */ +public enum MarkType { + UNKNOWN(0), + ROUNDING_MARK(1), + GATE(2); + + private long code; + + MarkType(long code) { + this.code = code; + } + + public long getCode(){ + return code; + } +} diff --git a/src/main/java/seng302/server/messages/RoundingBoatStatus.java b/src/main/java/seng302/server/messages/RoundingBoatStatus.java new file mode 100644 index 00000000..32eb2447 --- /dev/null +++ b/src/main/java/seng302/server/messages/RoundingBoatStatus.java @@ -0,0 +1,21 @@ +package seng302.server.messages; + +/** + * The status of a boat rounding a mark + */ +public enum RoundingBoatStatus { + UNKNOWN(0), + RACING(1), + DSQ(2), + WITHDRAWN(3); + + private long code; + + RoundingBoatStatus(long code) { + this.code = code; + } + + public long getCode(){ + return code; + } +} diff --git a/src/main/java/seng302/server/messages/RoundingSide.java b/src/main/java/seng302/server/messages/RoundingSide.java new file mode 100644 index 00000000..5cc4097c --- /dev/null +++ b/src/main/java/seng302/server/messages/RoundingSide.java @@ -0,0 +1,20 @@ +package seng302.server.messages; + +/** + * The side the boat rounded the mark + */ +public enum RoundingSide { + UNKNOWN(0), + PORT(1), + STARBOARD(2); + + private long code; + + RoundingSide(long code) { + this.code = code; + } + + public long getCode(){ + return code; + } +} diff --git a/src/test/java/seng302/server/TestConversions.java b/src/test/java/seng302/server/TestConversions.java new file mode 100644 index 00000000..91bf44b3 --- /dev/null +++ b/src/test/java/seng302/server/TestConversions.java @@ -0,0 +1,35 @@ +package seng302.server; + +import org.junit.Test; +import seng302.server.messages.BoatLocationMessage; + +import static junit.framework.TestCase.assertEquals; + +/** + * Test conversions used by the boat location messages + */ +public class TestConversions { + @Test + public void testLatLonConversion(){ + long binaryPacked = BoatLocationMessage.latLonToBinaryPackedLong(3232.323); + double original = BoatLocationMessage.binaryPackedToLatLon(binaryPacked); + + assertEquals(3232.323, original, 0.01); + } + + @Test + public void testWindAngleConversion(){ + long binaryPacked = BoatLocationMessage.windAngleToBinaryPackedLong(3232.323); + double original = BoatLocationMessage.binaryPackedWindAngleToDouble(binaryPacked); + + assertEquals(3232.323, original, 0.01); + } + + @Test + public void testHeadingConversion(){ + long binaryPacked = BoatLocationMessage.headingToBinaryPackedLong(3232.323); + double original = BoatLocationMessage.binaryPackedHeadingToDouble(binaryPacked); + + assertEquals(3232.323, original, 0.01); + } +}