Added RaceStartTypeEnum. Refactored RaceStartStatusDecoder to implement the MessageDecoder interface. Documented RaceStartStatus, and it actually exposes its properties now. Updated RaceStartStatusDecoderTest. issue #35 #36 #story[1095]main
parent
e99ad00294
commit
ce63f58429
@ -1,66 +1,81 @@
|
|||||||
package network.MessageDecoders;
|
package network.MessageDecoders;
|
||||||
|
|
||||||
|
|
||||||
|
import network.Messages.AC35Data;
|
||||||
|
import network.Messages.Enums.RaceStartTypeEnum;
|
||||||
|
import network.Messages.RaceStartStatus;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import static network.Utils.ByteConverter.*;
|
import static network.Utils.ByteConverter.*;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by hba56 on 21/04/17.
|
* Decodes {@link RaceStartStatus} messages.
|
||||||
*/
|
*/
|
||||||
public class RaceStartStatusDecoder {
|
public class RaceStartStatusDecoder implements MessageDecoder {
|
||||||
private byte messageVersion;
|
|
||||||
private byte[] timestamp;
|
|
||||||
private byte[] ackNumber;
|
|
||||||
private byte[] raceStartTime;
|
|
||||||
private byte[] raceIdentifier;
|
|
||||||
private byte notificationType;
|
|
||||||
|
|
||||||
private long time;
|
|
||||||
private short ack;
|
|
||||||
private long startTime;
|
|
||||||
private int raceID;
|
|
||||||
private char notification;
|
|
||||||
|
|
||||||
|
|
||||||
public RaceStartStatusDecoder(byte[] encodedRaceStartStatus) {
|
|
||||||
messageVersion = encodedRaceStartStatus[0];
|
|
||||||
timestamp = Arrays.copyOfRange(encodedRaceStartStatus, 1, 7);
|
|
||||||
ackNumber = Arrays.copyOfRange(encodedRaceStartStatus, 7, 9);
|
|
||||||
raceStartTime = Arrays.copyOfRange(encodedRaceStartStatus, 9, 15);
|
|
||||||
raceIdentifier = Arrays.copyOfRange(encodedRaceStartStatus, 15, 19);
|
|
||||||
notificationType = encodedRaceStartStatus[19];
|
|
||||||
|
|
||||||
time = bytesToLong(timestamp);
|
|
||||||
ack = bytesToShort(ackNumber);
|
|
||||||
startTime = bytesToLong(raceStartTime);
|
|
||||||
raceID = bytesToInt(raceIdentifier);
|
|
||||||
notification = bytesToChar(notificationType);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The encoded message.
|
||||||
|
*/
|
||||||
|
private byte[] encodedMessage;
|
||||||
|
|
||||||
public byte getMessageVersion() {
|
/**
|
||||||
return messageVersion;
|
* The decoded message.
|
||||||
}
|
*/
|
||||||
|
private RaceStartStatus message;
|
||||||
|
|
||||||
public long getTime() {
|
|
||||||
return time;
|
|
||||||
}
|
|
||||||
|
|
||||||
public short getAck() {
|
|
||||||
return ack;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getStartTime() {
|
/**
|
||||||
return startTime;
|
* Constructs a decoder to decode a given message.
|
||||||
|
*/
|
||||||
|
public RaceStartStatusDecoder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRaceID() {
|
|
||||||
return raceID;
|
@Override
|
||||||
|
public AC35Data decode(byte[] encodedMessage) {
|
||||||
|
this.encodedMessage = encodedMessage;
|
||||||
|
|
||||||
|
|
||||||
|
byte messageVersion = encodedMessage[0];
|
||||||
|
|
||||||
|
byte[] timestamp = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||||
|
long time = bytesToLong(timestamp);
|
||||||
|
|
||||||
|
byte[] ackNumber = Arrays.copyOfRange(encodedMessage, 7, 9);
|
||||||
|
short ack = bytesToShort(ackNumber);
|
||||||
|
|
||||||
|
byte[] raceStartTime = Arrays.copyOfRange(encodedMessage, 9, 15);
|
||||||
|
long startTime = bytesToLong(raceStartTime);
|
||||||
|
|
||||||
|
byte[] raceIdentifier = Arrays.copyOfRange(encodedMessage, 15, 19);
|
||||||
|
int raceID = bytesToInt(raceIdentifier);
|
||||||
|
|
||||||
|
byte notificationType = encodedMessage[19];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
message = new RaceStartStatus(
|
||||||
|
messageVersion,
|
||||||
|
time,
|
||||||
|
ack,
|
||||||
|
startTime,
|
||||||
|
raceID,
|
||||||
|
RaceStartTypeEnum.fromByte(notificationType)
|
||||||
|
);
|
||||||
|
|
||||||
|
return message;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public char getNotification() {
|
|
||||||
return notification;
|
/**
|
||||||
|
* Returns the decoded message.
|
||||||
|
* @return The decoded message.
|
||||||
|
*/
|
||||||
|
public RaceStartStatus getMessage() {
|
||||||
|
return message;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,51 @@
|
|||||||
|
package network.MessageEncoders;
|
||||||
|
|
||||||
|
|
||||||
|
import network.Messages.AC35Data;
|
||||||
|
import network.Messages.RaceStartStatus;
|
||||||
|
import network.Utils.ByteConverter;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import static network.Utils.ByteConverter.intToBytes;
|
||||||
|
import static network.Utils.ByteConverter.longToBytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This encoder can encode a {@link RaceStartStatus} message.
|
||||||
|
*/
|
||||||
|
public class RaceStartStatusEncoder implements MessageEncoder {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*/
|
||||||
|
public RaceStartStatusEncoder() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] encode(AC35Data message) {
|
||||||
|
|
||||||
|
//Downcast.
|
||||||
|
RaceStartStatus raceStartStatus = (RaceStartStatus) message;
|
||||||
|
|
||||||
|
|
||||||
|
byte messageVersion = raceStartStatus.getMessageVersionNumber();
|
||||||
|
byte[] timestamp = longToBytes(raceStartStatus.getTimestamp(), 6);
|
||||||
|
byte[] ackNumber = intToBytes(raceStartStatus.getAckNum(), 2);
|
||||||
|
byte[] raceStartTime = longToBytes(raceStartStatus.getRaceStartTime(), 6);
|
||||||
|
byte[] raceIdentifier = intToBytes(raceStartStatus.getRaceID());
|
||||||
|
byte[] notificationType = intToBytes(raceStartStatus.getNotificationType().getValue(), 1);
|
||||||
|
|
||||||
|
ByteBuffer result = ByteBuffer.allocate(20);
|
||||||
|
result.put(messageVersion);
|
||||||
|
result.put(timestamp);
|
||||||
|
result.put(ackNumber);
|
||||||
|
result.put(raceStartTime);
|
||||||
|
result.put(raceIdentifier);
|
||||||
|
result.put(notificationType);
|
||||||
|
|
||||||
|
return result.array();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,97 @@
|
|||||||
|
package network.Messages.Enums;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enumeration that encapsulates the various types race start status notifications. See AC35 streaming spec, 4.5.
|
||||||
|
*/
|
||||||
|
public enum RaceStartTypeEnum {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The race start time is being set.
|
||||||
|
*/
|
||||||
|
SET_RACE_START(1),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The race has been postponed.
|
||||||
|
*/
|
||||||
|
RACE_POSTPONED(2),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The race has been abandoned.
|
||||||
|
*/
|
||||||
|
RACE_ABANDONED(3),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The race has been terminated.
|
||||||
|
*/
|
||||||
|
RACE_TERMINATED(4),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to indicate that a given byte value is invalid.
|
||||||
|
*/
|
||||||
|
NOT_A_TYPE(-1);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primitive value of the enum.
|
||||||
|
*/
|
||||||
|
private byte value;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ctor. Creates a RaceStartTypeEnum from a given primitive integer value, cast to a byte.
|
||||||
|
* @param value Integer, which is cast to byte, to construct from.
|
||||||
|
*/
|
||||||
|
private RaceStartTypeEnum(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 RaceStartTypeEnum values.
|
||||||
|
*/
|
||||||
|
private static final Map<Byte, RaceStartTypeEnum> byteToTypeMap = new HashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Static initialization block. Initializes the byteToTypeMap.
|
||||||
|
*/
|
||||||
|
static {
|
||||||
|
for (RaceStartTypeEnum type : RaceStartTypeEnum.values()) {
|
||||||
|
RaceStartTypeEnum.byteToTypeMap.put(type.value, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the enumeration value which corresponds to a given byte value.
|
||||||
|
* @param startTypeEnum Byte value to convert to a RaceStartTypeEnum value.
|
||||||
|
* @return The RaceStartTypeEnum value which corresponds to the given byte value.
|
||||||
|
*/
|
||||||
|
public static RaceStartTypeEnum fromByte(byte startTypeEnum) {
|
||||||
|
//Gets the corresponding MessageType from the map.
|
||||||
|
RaceStartTypeEnum type = RaceStartTypeEnum.byteToTypeMap.get(startTypeEnum);
|
||||||
|
|
||||||
|
if (type == null) {
|
||||||
|
//If the byte value wasn't found, return the NOT_A_TYPE RaceStartTypeEnum.
|
||||||
|
return RaceStartTypeEnum.NOT_A_TYPE;
|
||||||
|
} else {
|
||||||
|
//Otherwise, return the RaceStartTypeEnum.
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,29 +1,62 @@
|
|||||||
package network.MessageDecoders;
|
package network.MessageDecoders;
|
||||||
|
|
||||||
import network.MessageEncoders.RaceVisionByteEncoder;
|
import network.MessageEncoders.RaceVisionByteEncoder;
|
||||||
|
import network.Messages.Enums.RaceStartTypeEnum;
|
||||||
|
import network.Messages.RaceStartStatus;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by hba56 on 23/04/17.
|
* Tests for the RaceStartStatus encoder and decoder.
|
||||||
*/
|
*/
|
||||||
public class RaceStartStatusDecoderTest {
|
public class RaceStartStatusDecoderTest {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if a RaceStartStatus message can be encoded and decoded correctly.
|
||||||
|
* @throws Exception Thrown when an error occurs.
|
||||||
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void getByteArrayTest(){
|
public void raceStartStatusEncodeDecodeTest() throws Exception {
|
||||||
long time = System.currentTimeMillis();
|
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
|
||||||
long time2 = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis() + 10 * 1000;
|
||||||
byte[] encodedRaceStartStatus = RaceVisionByteEncoder.raceStartStatus(time, (short)1,
|
|
||||||
time2, 2, (char)3);
|
|
||||||
|
|
||||||
RaceStartStatusDecoder testDecoder = new RaceStartStatusDecoder(encodedRaceStartStatus);
|
RaceStartStatus raceStartStatus = new RaceStartStatus(
|
||||||
|
RaceStartStatus.currentMessageVersionNumber,
|
||||||
|
timestamp,
|
||||||
|
55,
|
||||||
|
startTime,
|
||||||
|
35,
|
||||||
|
RaceStartTypeEnum.SET_RACE_START
|
||||||
|
);
|
||||||
|
|
||||||
Assert.assertEquals(0b1, testDecoder.getMessageVersion());
|
byte[] encodedRaceStartStatus = RaceVisionByteEncoder.encode(raceStartStatus);
|
||||||
Assert.assertEquals(time, testDecoder.getTime());
|
|
||||||
Assert.assertEquals(1, testDecoder.getAck());
|
RaceStartStatusDecoder testDecoder = new RaceStartStatusDecoder();
|
||||||
Assert.assertEquals(time2, testDecoder.getStartTime());
|
testDecoder.decode(encodedRaceStartStatus);
|
||||||
Assert.assertEquals(2, testDecoder.getRaceID());
|
RaceStartStatus raceStartStatusDecoded = testDecoder.getMessage();
|
||||||
Assert.assertEquals((char)3, testDecoder.getNotification());
|
|
||||||
|
compareRaceStartStatusMessages(raceStartStatus, raceStartStatusDecoded);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two RaceStartStatus messages to check that they are the same.
|
||||||
|
* @param original The original message.
|
||||||
|
* @param decoded The decoded message.
|
||||||
|
*/
|
||||||
|
public static void compareRaceStartStatusMessages(RaceStartStatus original, RaceStartStatus decoded) {
|
||||||
|
|
||||||
|
Assert.assertEquals(original.getMessageVersionNumber(), decoded.getMessageVersionNumber());
|
||||||
|
Assert.assertEquals(original.getTimestamp(), decoded.getTimestamp());
|
||||||
|
Assert.assertEquals(original.getAckNum(), decoded.getAckNum());
|
||||||
|
Assert.assertEquals(original.getRaceStartTime(), decoded.getRaceStartTime());
|
||||||
|
Assert.assertEquals(original.getRaceID(), decoded.getRaceID());
|
||||||
|
Assert.assertEquals(original.getNotificationType(), decoded.getNotificationType());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in new issue