Refactored MarkRoundingDecoder - it now implements MessageDecoder. Tidied up MarkRounding - it is now documented and has getters. Also Created MarkRoundingBoatStatusEnum, MarkRoundingIDEnum, MarkRoundingSideEnum, MarkRoundingTypeEnum. Added MarkRoundingDecoderTest. issue #35 #36 #story[1095]main
parent
da800e659a
commit
9c64b678e3
@ -1,52 +1,90 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.Enums.MarkRoundingBoatStatusEnum;
|
||||
import network.Messages.Enums.MarkRoundingSideEnum;
|
||||
import network.Messages.Enums.MarkRoundingTypeEnum;
|
||||
import network.Messages.MarkRounding;
|
||||
import network.Utils.ByteConverter;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
* Decoder for {@link MarkRounding} messages.
|
||||
*/
|
||||
public class MarkRoundingDecoder {
|
||||
byte messageVersionNumber;
|
||||
byte[] byteTime;
|
||||
byte[] byteAck;
|
||||
byte[] byteRaceID;
|
||||
byte[] byteSourceID;
|
||||
byte byteBoatStatus;
|
||||
byte byteRoundingSide;
|
||||
byte byteMarkType;
|
||||
byte byteMarkID;
|
||||
|
||||
MarkRounding markRounding;
|
||||
|
||||
public MarkRoundingDecoder(byte[] encodedMarkRounding) {
|
||||
messageVersionNumber = encodedMarkRounding[0];
|
||||
byteTime = Arrays.copyOfRange(encodedMarkRounding, 1, 7);
|
||||
byteAck = Arrays.copyOfRange(encodedMarkRounding, 7, 9);
|
||||
byteRaceID = Arrays.copyOfRange(encodedMarkRounding, 9, 13);
|
||||
byteSourceID = Arrays.copyOfRange(encodedMarkRounding, 13, 17);
|
||||
byteBoatStatus = encodedMarkRounding[17];
|
||||
byteRoundingSide = encodedMarkRounding[18];
|
||||
byteMarkType = encodedMarkRounding[19];
|
||||
byteMarkID = encodedMarkRounding[20];
|
||||
|
||||
int intMsgVer = ByteConverter.bytesToInt(messageVersionNumber);
|
||||
long lngTime = ByteConverter.bytesToLong(byteTime);
|
||||
int intAck = ByteConverter.bytesToInt(byteAck);
|
||||
int intRaceID = ByteConverter.bytesToInt(byteRaceID);
|
||||
int intSourceID = ByteConverter.bytesToInt(byteSourceID);
|
||||
int intBoatState = ByteConverter.bytesToInt(byteBoatStatus);
|
||||
int intRoundingSide = ByteConverter.bytesToInt(byteRoundingSide);
|
||||
int intMarkType = ByteConverter.bytesToInt(byteMarkType);
|
||||
int intMarkID = ByteConverter.bytesToInt(byteMarkID);
|
||||
|
||||
markRounding = new MarkRounding(intMsgVer, lngTime, intAck, intRaceID, intSourceID, intBoatState, intRoundingSide, intMarkType, intMarkID);
|
||||
public class MarkRoundingDecoder implements MessageDecoder {
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private MarkRounding message;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public MarkRoundingDecoder() {
|
||||
}
|
||||
|
||||
public MarkRounding getMarkRounding() {
|
||||
return markRounding;
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
byte messageVersionNumber = encodedMessage[0];
|
||||
|
||||
byte[] byteTime = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||
long time = ByteConverter.bytesToLong(byteTime);
|
||||
|
||||
byte[] byteAck = Arrays.copyOfRange(encodedMessage, 7, 9);
|
||||
int ackNumber = ByteConverter.bytesToInt(byteAck);
|
||||
|
||||
byte[] byteRaceID = Arrays.copyOfRange(encodedMessage, 9, 13);
|
||||
int raceID = ByteConverter.bytesToInt(byteRaceID);
|
||||
|
||||
byte[] byteSourceID = Arrays.copyOfRange(encodedMessage, 13, 17);
|
||||
int sourceID = ByteConverter.bytesToInt(byteSourceID);
|
||||
|
||||
byte byteBoatStatus = encodedMessage[17];
|
||||
MarkRoundingBoatStatusEnum boatStatus = MarkRoundingBoatStatusEnum.fromByte(byteBoatStatus);
|
||||
|
||||
byte byteRoundingSide = encodedMessage[18];
|
||||
MarkRoundingSideEnum roundingSide = MarkRoundingSideEnum.fromByte(byteRoundingSide);
|
||||
|
||||
byte byteMarkType = encodedMessage[19];
|
||||
MarkRoundingTypeEnum markType = MarkRoundingTypeEnum.fromByte(byteMarkType);
|
||||
|
||||
byte byteMarkID = encodedMessage[20];
|
||||
|
||||
|
||||
message = new MarkRounding(
|
||||
messageVersionNumber,
|
||||
time,
|
||||
ackNumber,
|
||||
raceID,
|
||||
sourceID,
|
||||
boatStatus,
|
||||
roundingSide,
|
||||
markType,
|
||||
byteMarkID);
|
||||
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
*
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public MarkRounding getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
package network.MessageEncoders;
|
||||
|
||||
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.MarkRounding;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static network.Utils.ByteConverter.intToBytes;
|
||||
import static network.Utils.ByteConverter.longToBytes;
|
||||
|
||||
/**
|
||||
* This encoder can encode a {@link MarkRounding} message.
|
||||
*/
|
||||
public class MarkRoundingEncoder implements MessageEncoder {
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public MarkRoundingEncoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] encode(AC35Data message) {
|
||||
|
||||
//Downcast.
|
||||
MarkRounding markRounding = (MarkRounding) message;
|
||||
|
||||
byte messageVersionNumber = markRounding.getMessageVersionNumber();
|
||||
byte[] byteTime = longToBytes(markRounding.getTime(), 6);
|
||||
byte[] byteAck = intToBytes(markRounding.getAckNum(), 2);
|
||||
byte[] byteRaceID = intToBytes(markRounding.getRaceID(), 4);
|
||||
byte[] byteSourceID = intToBytes(markRounding.getSourceID(), 4);
|
||||
byte[] byteBoatStatus = intToBytes(markRounding.getBoatStatus().getValue(), 1);
|
||||
byte[] byteRoundingSide = intToBytes(markRounding.getRoundingSide().getValue(), 1);
|
||||
byte[] byteMarkType = intToBytes(markRounding.getMarkType().getValue(), 1);
|
||||
byte[] byteMarkID = intToBytes(markRounding.getMarkID(), 1);
|
||||
|
||||
|
||||
ByteBuffer result = ByteBuffer.allocate(21);
|
||||
|
||||
result.put(messageVersionNumber);
|
||||
result.put(byteTime);
|
||||
result.put(byteAck);
|
||||
result.put(byteRaceID);
|
||||
result.put(byteSourceID);
|
||||
result.put(byteBoatStatus);
|
||||
result.put(byteRoundingSide);
|
||||
result.put(byteMarkType);
|
||||
result.put(byteMarkID);
|
||||
|
||||
return result.array();
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package network.Messages.Enums;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumeration that encapsulates the various statuses a boat can have when rounding a mark.
|
||||
*/
|
||||
public enum MarkRoundingBoatStatusEnum {
|
||||
|
||||
UNKNOWN(0),
|
||||
|
||||
/**
|
||||
* The boat is actively racing.
|
||||
*/
|
||||
RACING(1),
|
||||
|
||||
/**
|
||||
* The boat has been disqualified.
|
||||
*/
|
||||
DSQ(2),
|
||||
|
||||
/**
|
||||
* The boat has withdrawn from the race.
|
||||
*/
|
||||
WITHDRAWN(3),
|
||||
|
||||
NOT_A_STATUS(-1);
|
||||
|
||||
|
||||
/**
|
||||
* Primitive value of the enum.
|
||||
*/
|
||||
private byte value;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Creates a {@link MarkRoundingBoatStatusEnum} from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private MarkRoundingBoatStatusEnum(int value) {
|
||||
this.value = (byte)value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive value of the enum.
|
||||
* @return Primitive value of the enum.
|
||||
*/
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
///Stores a mapping between Byte values and MarkRoundingBoatStatusEnum values.
|
||||
private static final Map<Byte, MarkRoundingBoatStatusEnum> byteToStatusMap = new HashMap<>();
|
||||
|
||||
|
||||
/*
|
||||
Static initialization block. Initializes the byteToStatusMap.
|
||||
*/
|
||||
static {
|
||||
for (MarkRoundingBoatStatusEnum type : MarkRoundingBoatStatusEnum.values()) {
|
||||
byteToStatusMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the enumeration value which corresponds to a given byte value.
|
||||
* @param boatStatusByte Byte value to convert to a {@link MarkRoundingBoatStatusEnum} value.
|
||||
* @return The {@link MarkRoundingBoatStatusEnum} value which corresponds to the given byte value.
|
||||
*/
|
||||
public static MarkRoundingBoatStatusEnum fromByte(byte boatStatusByte) {
|
||||
//Gets the corresponding MarkRoundingBoatStatusEnum from the map.
|
||||
MarkRoundingBoatStatusEnum type = byteToStatusMap.get(boatStatusByte);
|
||||
|
||||
if (type == null) {
|
||||
//If the byte value wasn't found, return the NOT_A_STATUS MarkRoundingBoatStatusEnum.
|
||||
return MarkRoundingBoatStatusEnum.NOT_A_STATUS;
|
||||
}
|
||||
else {
|
||||
//Otherwise, return the MarkRoundingBoatStatusEnum.
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,88 @@
|
||||
package network.Messages.Enums;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumeration that encapsulates the various mark identities.
|
||||
*/
|
||||
public enum MarkRoundingIDEnum {
|
||||
|
||||
UNKNOWN(0),
|
||||
|
||||
|
||||
ENTRY_LIMIT_LINE(100),
|
||||
|
||||
ENTRY_LINE(101),
|
||||
|
||||
START_LINE(102),
|
||||
|
||||
FINISH_LINE(103),
|
||||
|
||||
SPEED_TEST_START(104),
|
||||
|
||||
SPEED_TEST_FINISH(105),
|
||||
|
||||
CLEAR_START(106),
|
||||
|
||||
NOT_AN_ID(-1);
|
||||
|
||||
|
||||
/**
|
||||
* Primitive value of the enum.
|
||||
*/
|
||||
private byte value;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Creates a {@link MarkRoundingIDEnum} from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private MarkRoundingIDEnum(int value) {
|
||||
this.value = (byte)value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive value of the enum.
|
||||
* @return Primitive value of the enum.
|
||||
*/
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
///Stores a mapping between Byte values and MarkRoundingIDEnum values.
|
||||
private static final Map<Byte, MarkRoundingIDEnum> byteToIDMap = new HashMap<>();
|
||||
|
||||
|
||||
/*
|
||||
Static initialization block. Initializes the byteToIDMap.
|
||||
*/
|
||||
static {
|
||||
for (MarkRoundingIDEnum type : MarkRoundingIDEnum.values()) {
|
||||
byteToIDMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the enumeration value which corresponds to a given byte value.
|
||||
* @param sideByte Byte value to convert to a {@link MarkRoundingIDEnum} value.
|
||||
* @return The {@link MarkRoundingIDEnum} value which corresponds to the given byte value.
|
||||
*/
|
||||
public static MarkRoundingIDEnum fromByte(byte sideByte) {
|
||||
//Gets the corresponding MarkRoundingIDEnum from the map.
|
||||
MarkRoundingIDEnum type = byteToIDMap.get(sideByte);
|
||||
|
||||
if (type == null) {
|
||||
//If the byte value wasn't found, return the NOT_AN_ID MarkRoundingIDEnum.
|
||||
return MarkRoundingIDEnum.NOT_AN_ID;
|
||||
}
|
||||
else {
|
||||
//Otherwise, return the MarkRoundingIDEnum.
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package network.Messages.Enums;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumeration that encapsulates the various sides around which a boat may pass a mark.
|
||||
*/
|
||||
public enum MarkRoundingSideEnum {
|
||||
|
||||
UNKNOWN(0),
|
||||
|
||||
/**
|
||||
* Boat rounded around port side of mark.
|
||||
*/
|
||||
PORT(1),
|
||||
|
||||
/**
|
||||
* Boat rounded around starboard side of mark.
|
||||
*/
|
||||
STARBOARD(2),
|
||||
|
||||
NOT_A_SIDE(-1);
|
||||
|
||||
/**
|
||||
* Primitive value of the enum.
|
||||
*/
|
||||
private byte value;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Creates a {@link MarkRoundingSideEnum} from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private MarkRoundingSideEnum(int value) {
|
||||
this.value = (byte)value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive value of the enum.
|
||||
* @return Primitive value of the enum.
|
||||
*/
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
///Stores a mapping between Byte values and MarkRoundingSideEnum values.
|
||||
private static final Map<Byte, MarkRoundingSideEnum> byteToSideMap = new HashMap<>();
|
||||
|
||||
|
||||
/*
|
||||
Static initialization block. Initializes the byteToSideMap.
|
||||
*/
|
||||
static {
|
||||
for (MarkRoundingSideEnum type : MarkRoundingSideEnum.values()) {
|
||||
byteToSideMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the enumeration value which corresponds to a given byte value.
|
||||
* @param sideByte Byte value to convert to a {@link MarkRoundingSideEnum} value.
|
||||
* @return The {@link MarkRoundingSideEnum} value which corresponds to the given byte value.
|
||||
*/
|
||||
public static MarkRoundingSideEnum fromByte(byte sideByte) {
|
||||
//Gets the corresponding MarkRoundingSideEnum from the map.
|
||||
MarkRoundingSideEnum type = byteToSideMap.get(sideByte);
|
||||
|
||||
if (type == null) {
|
||||
//If the byte value wasn't found, return the NOT_A_SIDE MarkRoundingSideEnum.
|
||||
return MarkRoundingSideEnum.NOT_A_SIDE;
|
||||
}
|
||||
else {
|
||||
//Otherwise, return the MarkRoundingSideEnum.
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,82 @@
|
||||
package network.Messages.Enums;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Enumeration that encapsulates the various types of marks that may be passed.
|
||||
*/
|
||||
public enum MarkRoundingTypeEnum {
|
||||
|
||||
UNKNOWN(0),
|
||||
|
||||
/**
|
||||
* The mark is a singular mark.
|
||||
*/
|
||||
MARK(1),
|
||||
|
||||
/**
|
||||
* The mark is a gate (windward, leeward, start, finish, etc...).
|
||||
*/
|
||||
GATE(2),
|
||||
|
||||
NOT_A_TYPE(-1);
|
||||
|
||||
/**
|
||||
* Primitive value of the enum.
|
||||
*/
|
||||
private byte value;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Creates a {@link MarkRoundingTypeEnum} from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private MarkRoundingTypeEnum(int value) {
|
||||
this.value = (byte)value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the primitive value of the enum.
|
||||
* @return Primitive value of the enum.
|
||||
*/
|
||||
public byte getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
///Stores a mapping between Byte values and MarkRoundingTypeEnum values.
|
||||
private static final Map<Byte, MarkRoundingTypeEnum> byteToTypeMap = new HashMap<>();
|
||||
|
||||
|
||||
/*
|
||||
Static initialization block. Initializes the byteToTypeMap.
|
||||
*/
|
||||
static {
|
||||
for (MarkRoundingTypeEnum type : MarkRoundingTypeEnum.values()) {
|
||||
byteToTypeMap.put(type.value, type);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the enumeration value which corresponds to a given byte value.
|
||||
* @param sideByte Byte value to convert to a {@link MarkRoundingTypeEnum} value.
|
||||
* @return The {@link MarkRoundingTypeEnum} value which corresponds to the given byte value.
|
||||
*/
|
||||
public static MarkRoundingTypeEnum fromByte(byte sideByte) {
|
||||
//Gets the corresponding MarkRoundingTypeEnum from the map.
|
||||
MarkRoundingTypeEnum type = byteToTypeMap.get(sideByte);
|
||||
|
||||
if (type == null) {
|
||||
//If the byte value wasn't found, return the NOT_A_TYPE MarkRoundingTypeEnum.
|
||||
return MarkRoundingTypeEnum.NOT_A_TYPE;
|
||||
}
|
||||
else {
|
||||
//Otherwise, return the MarkRoundingTypeEnum.
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.MessageEncoders.RaceVisionByteEncoder;
|
||||
import network.Messages.Enums.MarkRoundingBoatStatusEnum;
|
||||
import network.Messages.Enums.MarkRoundingSideEnum;
|
||||
import network.Messages.Enums.MarkRoundingTypeEnum;
|
||||
import network.Messages.MarkRounding;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Test for the MarkRounding encoder and decoder
|
||||
*/
|
||||
public class MarkRoundingDecoderTest {
|
||||
|
||||
|
||||
/**
|
||||
* Creates a MarkRounding message, encodes it, decodes it, and checks that the result matches the starting message.
|
||||
* @throws Exception if test fails.
|
||||
*/
|
||||
@Test
|
||||
public void markRoundingEncodeDecodeTest() throws Exception {
|
||||
|
||||
MarkRounding markRounding = new MarkRounding(
|
||||
MarkRounding.currentMessageVersionNumber,
|
||||
System.currentTimeMillis(),
|
||||
567,
|
||||
42,
|
||||
125,
|
||||
MarkRoundingBoatStatusEnum.RACING,
|
||||
MarkRoundingSideEnum.PORT,
|
||||
MarkRoundingTypeEnum.MARK,
|
||||
(byte)45
|
||||
);
|
||||
|
||||
byte[] encodedMessage = RaceVisionByteEncoder.encode(markRounding);
|
||||
|
||||
MarkRoundingDecoder markRoundingDecoder = new MarkRoundingDecoder();
|
||||
markRoundingDecoder.decode(encodedMessage);
|
||||
MarkRounding markRoundingDecoded = markRoundingDecoder.getMessage();
|
||||
|
||||
compareMarkRoundingMessages(markRounding, markRoundingDecoded);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two MarkRounding messages to check that they are equal.
|
||||
* @param original The original MarkRounding message.
|
||||
* @param decoded The decoded MarkRounding message.
|
||||
*/
|
||||
public static void compareMarkRoundingMessages(MarkRounding original, MarkRounding decoded) {
|
||||
|
||||
|
||||
assertEquals(original.getMessageVersionNumber(), decoded.getMessageVersionNumber());
|
||||
assertEquals(original.getTime(), decoded.getTime());
|
||||
assertEquals(original.getAckNum(), decoded.getAckNum());
|
||||
assertEquals(original.getRaceID(), decoded.getRaceID());
|
||||
assertEquals(original.getSourceID(), decoded.getSourceID());
|
||||
assertEquals(original.getBoatStatus(), decoded.getBoatStatus());
|
||||
assertEquals(original.getRoundingSide(), decoded.getRoundingSide());
|
||||
assertEquals(original.getMarkType(), decoded.getMarkType());
|
||||
assertEquals(original.getMarkID(), decoded.getMarkID());
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in new issue