- Updated Encoder and Decoder factories for the new message type - Added an enum for handling yacht event types #story[1100]main
parent
f7d0e9d466
commit
f8150ef449
@ -0,0 +1,47 @@
|
|||||||
|
package network.MessageDecoders;
|
||||||
|
|
||||||
|
import network.Exceptions.InvalidMessageException;
|
||||||
|
import network.Messages.AC35Data;
|
||||||
|
import network.Messages.Enums.YachtEventEnum;
|
||||||
|
import network.Messages.YachtEvent;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import static network.Utils.ByteConverter.bytesToInt;
|
||||||
|
import static network.Utils.ByteConverter.bytesToLong;
|
||||||
|
import static network.Utils.ByteConverter.bytesToShort;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes {@link YachtEvent} messages.
|
||||||
|
*/
|
||||||
|
public class YachtEventCodeDecoder implements MessageDecoder {
|
||||||
|
private YachtEvent message;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AC35Data decode(byte[] encodedMessage) throws InvalidMessageException {
|
||||||
|
// Deserialise message
|
||||||
|
byte[] timestamp = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||||
|
byte[] ackNum = Arrays.copyOfRange(encodedMessage, 7, 9);
|
||||||
|
byte[] raceID = Arrays.copyOfRange(encodedMessage, 9, 13);
|
||||||
|
byte[] sourceID = Arrays.copyOfRange(encodedMessage, 13, 17);
|
||||||
|
byte[] incidentID = Arrays.copyOfRange(encodedMessage, 17, 21);
|
||||||
|
byte eventID = encodedMessage[21];
|
||||||
|
|
||||||
|
// Unpack bytes into YachtEvent
|
||||||
|
this.message = new YachtEvent(
|
||||||
|
bytesToLong(timestamp),
|
||||||
|
bytesToShort(ackNum),
|
||||||
|
bytesToInt(raceID),
|
||||||
|
bytesToInt(sourceID),
|
||||||
|
bytesToInt(incidentID),
|
||||||
|
YachtEventEnum.fromByte(eventID)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Return YachtEvent
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YachtEvent getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package network.MessageEncoders;
|
||||||
|
|
||||||
|
import network.Exceptions.InvalidMessageException;
|
||||||
|
import network.Messages.AC35Data;
|
||||||
|
import network.Messages.YachtEvent;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import static network.Utils.ByteConverter.intToBytes;
|
||||||
|
import static network.Utils.ByteConverter.longToBytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes a {@link YachtEvent} message.
|
||||||
|
*/
|
||||||
|
public class YachtEventCodeEncoder implements MessageEncoder {
|
||||||
|
@Override
|
||||||
|
public byte[] encode(AC35Data message) throws InvalidMessageException {
|
||||||
|
// Downcast message
|
||||||
|
YachtEvent yachtEvent = (YachtEvent)message;
|
||||||
|
|
||||||
|
// Serialise message
|
||||||
|
byte messageVersion = 0b10;
|
||||||
|
byte[] timestamp = longToBytes(yachtEvent.getCurrentTime(), 6);
|
||||||
|
byte[] ackNum = intToBytes(yachtEvent.getAckNum(), 2);
|
||||||
|
byte[] raceID = intToBytes(yachtEvent.getRaceID());
|
||||||
|
byte[] sourceID = intToBytes(yachtEvent.getSourceID());
|
||||||
|
byte[] incidentID = intToBytes(yachtEvent.getIncidentID());
|
||||||
|
byte eventID = yachtEvent.getYachtEvent().getValue();
|
||||||
|
|
||||||
|
// Pack bytes into string
|
||||||
|
ByteBuffer yachtEventMessage = ByteBuffer.allocate(22);
|
||||||
|
yachtEventMessage.put(messageVersion);
|
||||||
|
yachtEventMessage.put(timestamp);
|
||||||
|
yachtEventMessage.put(ackNum);
|
||||||
|
yachtEventMessage.put(raceID);
|
||||||
|
yachtEventMessage.put(sourceID);
|
||||||
|
yachtEventMessage.put(incidentID);
|
||||||
|
yachtEventMessage.put(eventID);
|
||||||
|
|
||||||
|
// Return byte string
|
||||||
|
return yachtEventMessage.array();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,24 @@
|
|||||||
|
package network.Messages.Enums;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Yacht event codes
|
||||||
|
*/
|
||||||
|
public enum YachtEventEnum {
|
||||||
|
NOT_AN_EVENT(-1),
|
||||||
|
COLLISION(1);
|
||||||
|
|
||||||
|
private byte value;
|
||||||
|
|
||||||
|
YachtEventEnum(int value) { this.value = (byte)value; }
|
||||||
|
|
||||||
|
public byte getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static YachtEventEnum fromByte(byte value) {
|
||||||
|
switch(value) {
|
||||||
|
case 1: return COLLISION;
|
||||||
|
default: return NOT_AN_EVENT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,51 @@
|
|||||||
|
package network.Messages;
|
||||||
|
|
||||||
|
import network.Messages.Enums.MessageType;
|
||||||
|
import network.Messages.Enums.YachtEventEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a Yacht Event Code message defined in the AC35 spec, with Event IDs amended for the purposes of
|
||||||
|
* a game.
|
||||||
|
*/
|
||||||
|
public class YachtEvent extends AC35Data {
|
||||||
|
private long currentTime;
|
||||||
|
private int ackNum;
|
||||||
|
private int raceID;
|
||||||
|
private int sourceID;
|
||||||
|
private int incidentID;
|
||||||
|
private YachtEventEnum yachtEvent;
|
||||||
|
|
||||||
|
public YachtEvent(long currentTime, int ackNum, int raceID, int sourceID, int incidentID, YachtEventEnum yachtEvent) {
|
||||||
|
super(MessageType.YACHTEVENTCODE);
|
||||||
|
this.currentTime = currentTime;
|
||||||
|
this.ackNum = ackNum;
|
||||||
|
this.raceID = raceID;
|
||||||
|
this.sourceID = sourceID;
|
||||||
|
this.incidentID = incidentID;
|
||||||
|
this.yachtEvent = yachtEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YachtEventEnum getYachtEvent() {
|
||||||
|
return yachtEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSourceID() {
|
||||||
|
return sourceID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIncidentID() {
|
||||||
|
return incidentID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCurrentTime() {
|
||||||
|
return currentTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAckNum() {
|
||||||
|
return ackNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRaceID() {
|
||||||
|
return raceID;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,47 @@
|
|||||||
|
package network.MessageDecoders;
|
||||||
|
|
||||||
|
import network.MessageEncoders.RaceVisionByteEncoder;
|
||||||
|
import network.Messages.Enums.YachtEventEnum;
|
||||||
|
import network.Messages.YachtEvent;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.testng.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for the YachtEvent decoder and encoder
|
||||||
|
*/
|
||||||
|
public class YachtEventCodeDecoderTest {
|
||||||
|
private YachtEvent decodedMessage;
|
||||||
|
private YachtEvent originalMessage;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
long timestamp = System.currentTimeMillis();
|
||||||
|
|
||||||
|
originalMessage = new YachtEvent(
|
||||||
|
timestamp,
|
||||||
|
55,
|
||||||
|
35,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
YachtEventEnum.COLLISION
|
||||||
|
);
|
||||||
|
|
||||||
|
byte[] encodedMessage = RaceVisionByteEncoder.encode(originalMessage);
|
||||||
|
|
||||||
|
YachtEventCodeDecoder testDecoder = new YachtEventCodeDecoder();
|
||||||
|
testDecoder.decode(encodedMessage);
|
||||||
|
decodedMessage = testDecoder.getMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void decodingEqualsOriginal() {
|
||||||
|
assertEquals(originalMessage.getCurrentTime(), decodedMessage.getCurrentTime());
|
||||||
|
assertEquals(originalMessage.getAckNum(), decodedMessage.getAckNum());
|
||||||
|
assertEquals(originalMessage.getRaceID(), decodedMessage.getRaceID());
|
||||||
|
assertEquals(originalMessage.getSourceID(), decodedMessage.getSourceID());
|
||||||
|
assertEquals(originalMessage.getIncidentID(), decodedMessage.getIncidentID());
|
||||||
|
assertEquals(originalMessage.getYachtEvent(), decodedMessage.getYachtEvent());
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in new issue