Added RaceStatusEncoder.
Refactored RaceStatusDecoder to be more consistent with other decoders - it now has a getMessage() function. Added BoatStatus encoder and decoder - the RaceStatus encoder and decoder uses this for BoatStatuses. The BoatStatus encoder doesn't implement the MessageEncoder interface as BoatStatus is not a proper message type (doesn't inherit from AC35Data). Added remaining cases to EncoderFactory, but commented them out. BoatStatus now uses BoatStatusEnum instead of a byte. Added some comments to RaceStatus, and it uses enums instead of bytes. MockOutput logs a warning if a RaceStatus cannot be encoded. Added a BoatStatusDecoderTest. Updated RaceStatusDecoder to use new encoders/decoders. issue #35 #36 #story[1095]
This commit is contained in:
@@ -185,11 +185,12 @@ public class MockOutput implements Runnable
|
||||
* Encodes/serialises a RaceStatus message, and returns it.
|
||||
* @param raceStatus The RaceStatus message to serialise.
|
||||
* @return The RaceStatus message in a serialised form.
|
||||
* @throws InvalidMessageException Thrown if the message cannot be encoded.
|
||||
*/
|
||||
private synchronized byte[] parseRaceStatus(RaceStatus raceStatus){
|
||||
private synchronized byte[] parseRaceStatus(RaceStatus raceStatus) throws InvalidMessageException {
|
||||
|
||||
//Encodes the messages.
|
||||
byte[] encodedRaceStatus = RaceVisionByteEncoder.raceStatus(raceStatus);
|
||||
byte[] encodedRaceStatus = RaceVisionByteEncoder.encode(raceStatus);
|
||||
|
||||
//Encodes the full message with header.
|
||||
BinaryMessageEncoder binaryMessageEncoder = new BinaryMessageEncoder(
|
||||
@@ -284,9 +285,15 @@ public class MockOutput implements Runnable
|
||||
|
||||
//Sends the RaceStatus message.
|
||||
if (this.latestMessages.getRaceStatus() != null) {
|
||||
byte[] raceStatusBlob = this.parseRaceStatus(this.latestMessages.getRaceStatus());
|
||||
|
||||
this.outToVisualiser.write(raceStatusBlob);
|
||||
try {
|
||||
byte[] raceStatusBlob = this.parseRaceStatus(this.latestMessages.getRaceStatus());
|
||||
|
||||
this.outToVisualiser.write(raceStatusBlob);
|
||||
|
||||
} catch (InvalidMessageException e) {
|
||||
Logger.getGlobal().log(Level.WARNING, "Could not encode RaceStatus: " + latestMessages.getRaceStatus(), e);
|
||||
}
|
||||
}
|
||||
|
||||
//Send all of the BoatLocation messages.
|
||||
|
||||
@@ -139,13 +139,14 @@ public class RaceServer {
|
||||
|
||||
//Create race status object, and send it.
|
||||
RaceStatus raceStatus = new RaceStatus(
|
||||
RaceStatus.currentMessageVersionNumber,
|
||||
System.currentTimeMillis(),
|
||||
race.getRaceId(),
|
||||
race.getRaceStatusEnum().getValue(),
|
||||
race.getRaceStatusEnum(),
|
||||
race.getRaceClock().getStartingTimeMilli(),
|
||||
windDirectionInt,
|
||||
windSpeedInt,
|
||||
race.getRaceType().getValue(),
|
||||
race.getRaceType(),
|
||||
boatStatuses);
|
||||
|
||||
this.latestMessages.setRaceStatus(raceStatus);
|
||||
|
||||
@@ -139,7 +139,7 @@ public class BinaryMessageDecoder {
|
||||
case RACESTATUS:
|
||||
//System.out.println("Race Status Message");
|
||||
RaceStatusDecoder rsdecoder = new RaceStatusDecoder(messageBody);
|
||||
return new RaceStatus(rsdecoder.getTime(), rsdecoder.getRace(), rsdecoder.getRaceState(), rsdecoder.getStartTime(), rsdecoder.getRaceWindDir(), rsdecoder.getRaceWindSpeed(), rsdecoder.getRaceType(), rsdecoder.getBoats());
|
||||
return rsdecoder.getMessage();
|
||||
|
||||
case DISPLAYTEXTMESSAGE:
|
||||
//System.out.println("Display Text Message");
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.Enums.BoatStatusEnum;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static network.Utils.ByteConverter.*;
|
||||
|
||||
|
||||
/**
|
||||
* Decodes {@link BoatStatus} messages.
|
||||
*/
|
||||
public class BoatStatusDecoder {
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private BoatStatus message;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
* @param encodedMessage The message to decode.
|
||||
*/
|
||||
public BoatStatusDecoder(byte[] encodedMessage) {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
decode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Decodes the contained message.
|
||||
*/
|
||||
private void decode() {
|
||||
|
||||
|
||||
byte[] sourceIDBytes = Arrays.copyOfRange(encodedMessage, 0, 4);
|
||||
int sourceID = bytesToInt(sourceIDBytes);
|
||||
|
||||
byte[] boatStatusBytes = Arrays.copyOfRange(encodedMessage, 4, 5);
|
||||
BoatStatusEnum boatStatus = BoatStatusEnum.fromByte(boatStatusBytes[0]);
|
||||
|
||||
byte[] legNumberBytes = Arrays.copyOfRange(encodedMessage, 5, 6);
|
||||
byte legNumber = legNumberBytes[0];
|
||||
|
||||
byte[] numPenaltiesAwardedBytes = Arrays.copyOfRange(encodedMessage, 6, 7);
|
||||
byte numPenaltiesAwarded = numPenaltiesAwardedBytes[0];
|
||||
|
||||
byte[] numPenaltiesServedBytes = Arrays.copyOfRange(encodedMessage, 7, 8);
|
||||
byte numPenaltiesServed = numPenaltiesServedBytes[0];
|
||||
|
||||
byte[] estTimeAtNextMarkBytes = Arrays.copyOfRange(encodedMessage, 8, 14);
|
||||
long estTimeAtNextMark = bytesToLong(estTimeAtNextMarkBytes);
|
||||
|
||||
byte[] estTimeAtFinishBytes = Arrays.copyOfRange(encodedMessage, 14, 20);
|
||||
long estTimeAtFinish = bytesToLong(estTimeAtFinishBytes);
|
||||
|
||||
message = new BoatStatus(
|
||||
sourceID,
|
||||
boatStatus,
|
||||
legNumber,
|
||||
numPenaltiesAwarded,
|
||||
numPenaltiesServed,
|
||||
estTimeAtNextMark,
|
||||
estTimeAtFinish );
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public BoatStatus getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@@ -2,9 +2,13 @@ package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import network.Messages.Enums.RaceTypeEnum;
|
||||
import network.Messages.RaceStatus;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static network.Utils.ByteConverter.bytesToInt;
|
||||
import static network.Utils.ByteConverter.bytesToLong;
|
||||
@@ -12,110 +16,101 @@ import static network.Utils.ByteConverter.bytesToShort;
|
||||
|
||||
|
||||
/**
|
||||
* Created by hba56 on 21/04/17.
|
||||
* Decodes {@link RaceStatus} messages.
|
||||
*/
|
||||
public class RaceStatusDecoder {
|
||||
private byte versionNum;
|
||||
private byte[] timeBytes;
|
||||
private byte[] raceID;
|
||||
private byte raceStatus;
|
||||
private byte[] expectedStart;
|
||||
private byte[] raceWind;
|
||||
private byte[] windSpeed;
|
||||
private byte numBoats;
|
||||
private byte bytesRaceType;
|
||||
private byte[] boatsBytes;
|
||||
|
||||
private long time;
|
||||
private int race;
|
||||
private byte raceState;
|
||||
private long startTime;
|
||||
private int raceWindDir;
|
||||
private short raceWindSpeed;
|
||||
private int numberOfBoats;
|
||||
private int raceType;
|
||||
private ArrayList<BoatStatus> boats = new ArrayList<>();
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private RaceStatus message;
|
||||
|
||||
|
||||
public RaceStatusDecoder(byte[] encodedRaceStatus){
|
||||
versionNum = encodedRaceStatus[0];
|
||||
timeBytes = Arrays.copyOfRange(encodedRaceStatus, 1, 7);
|
||||
raceID = Arrays.copyOfRange(encodedRaceStatus, 7, 11);
|
||||
raceStatus = encodedRaceStatus[11];
|
||||
expectedStart = Arrays.copyOfRange(encodedRaceStatus, 12, 18);
|
||||
raceWind = Arrays.copyOfRange(encodedRaceStatus, 18, 20);
|
||||
windSpeed = Arrays.copyOfRange(encodedRaceStatus, 20, 22);
|
||||
numBoats = encodedRaceStatus[22];
|
||||
bytesRaceType = encodedRaceStatus[23];
|
||||
boatsBytes = Arrays.copyOfRange(encodedRaceStatus, 24, 25+20*this.numBoats);
|
||||
|
||||
time = bytesToLong(timeBytes);
|
||||
race = bytesToInt(raceID);
|
||||
raceState = raceStatus;
|
||||
startTime = bytesToLong(expectedStart);
|
||||
raceWindDir = bytesToInt(raceWind);
|
||||
raceWindSpeed = bytesToShort(windSpeed);
|
||||
numberOfBoats = bytesToInt(numBoats);
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
* @param encodedMessage The message to decode.
|
||||
*/
|
||||
public RaceStatusDecoder(byte[] encodedMessage) {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
int boatLoopIndex = 0;
|
||||
decode();
|
||||
}
|
||||
|
||||
for (int i=0; i < numberOfBoats; i++) {
|
||||
byte[] boatBytes = Arrays.copyOfRange(boatsBytes, boatLoopIndex, boatLoopIndex+20);
|
||||
|
||||
byte[] sourceID = Arrays.copyOfRange(boatBytes, 0, 3);
|
||||
byte boatStatus = boatBytes[4];
|
||||
byte legNumber = boatBytes[5];
|
||||
byte numPenaltiesAwarded = boatBytes[6];
|
||||
byte numPenaltiesServed = boatBytes[7];
|
||||
byte[] estTimeAtNextMark = Arrays.copyOfRange(boatBytes, 8, 14);
|
||||
byte[] estTimeAtFinish = Arrays.copyOfRange(boatBytes, 14, 20);
|
||||
/**
|
||||
* Decodes the contained message.
|
||||
*/
|
||||
private void decode() {
|
||||
|
||||
BoatStatus boat = new BoatStatus(bytesToInt(sourceID),boatStatus,
|
||||
legNumber, numPenaltiesAwarded, numPenaltiesServed,
|
||||
bytesToLong(estTimeAtNextMark), bytesToLong(estTimeAtFinish));
|
||||
|
||||
boats.add(boat);
|
||||
boatLoopIndex += 20;
|
||||
byte[] versionNumBytes = Arrays.copyOfRange(encodedMessage, 0, 1);
|
||||
byte versionNum = versionNumBytes[0];
|
||||
|
||||
byte[] timeBytes = Arrays.copyOfRange(encodedMessage, 1, 7);
|
||||
long time = bytesToLong(timeBytes);
|
||||
|
||||
byte[] raceIDBytes = Arrays.copyOfRange(encodedMessage, 7, 11);
|
||||
int raceID = bytesToInt(raceIDBytes);
|
||||
|
||||
byte[] raceStatusBytes = Arrays.copyOfRange(encodedMessage, 11, 12);
|
||||
RaceStatusEnum raceStatus = RaceStatusEnum.fromByte(raceStatusBytes[0]);
|
||||
|
||||
byte[] expectedStartBytes = Arrays.copyOfRange(encodedMessage, 12, 18);
|
||||
long expectedStart = bytesToLong(expectedStartBytes);
|
||||
|
||||
byte[] windDirectionBytes = Arrays.copyOfRange(encodedMessage, 18, 20);
|
||||
int windDirection = bytesToInt(windDirectionBytes);
|
||||
|
||||
byte[] windSpeedBytes = Arrays.copyOfRange(encodedMessage, 20, 22);
|
||||
short windSpeed = bytesToShort(windSpeedBytes);
|
||||
|
||||
byte[] numberOfBoatsBytes = Arrays.copyOfRange(encodedMessage, 22, 23);
|
||||
int numberOfBoats = bytesToInt(numberOfBoatsBytes);
|
||||
|
||||
byte[] raceTypeBytes = Arrays.copyOfRange(encodedMessage, 23, 24);
|
||||
RaceTypeEnum raceType = RaceTypeEnum.fromByte(raceTypeBytes[0]);
|
||||
|
||||
byte[] boatStatusesBytes = Arrays.copyOfRange(encodedMessage, 24, 25 + 20 * numberOfBoats);
|
||||
List<BoatStatus> boatStatuses = new ArrayList<>();
|
||||
|
||||
|
||||
|
||||
//Decode each BoatStatus.
|
||||
for (int boatLoopIndex=0; boatLoopIndex < (numberOfBoats * 20); boatLoopIndex += 20) {
|
||||
|
||||
byte[] boatStatusBytes = Arrays.copyOfRange(boatStatusesBytes, boatLoopIndex, boatLoopIndex + 20);
|
||||
|
||||
BoatStatusDecoder boatStatusDecoder = new BoatStatusDecoder(boatStatusBytes);
|
||||
|
||||
boatStatuses.add(boatStatusDecoder.getMessage());
|
||||
}
|
||||
|
||||
|
||||
message = new RaceStatus(
|
||||
versionNum,
|
||||
time,
|
||||
raceID,
|
||||
raceStatus,
|
||||
expectedStart,
|
||||
windDirection,
|
||||
windSpeed,
|
||||
raceType,
|
||||
boatStatuses );
|
||||
}
|
||||
|
||||
public byte getVersionNum() {
|
||||
return versionNum;
|
||||
}
|
||||
|
||||
public long getTime() {
|
||||
return time;
|
||||
}
|
||||
|
||||
public int getRace() {
|
||||
return race;
|
||||
}
|
||||
|
||||
public byte getRaceState() {
|
||||
return raceState;
|
||||
}
|
||||
|
||||
public long getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
public int getRaceWindDir() {
|
||||
return raceWindDir;
|
||||
}
|
||||
|
||||
public short getRaceWindSpeed() {
|
||||
return raceWindSpeed;
|
||||
}
|
||||
|
||||
public int getNumberOfBoats() {
|
||||
return numberOfBoats;
|
||||
}
|
||||
|
||||
public int getRaceType() {
|
||||
return raceType;
|
||||
}
|
||||
|
||||
public ArrayList<BoatStatus> getBoats() {
|
||||
return boats;
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public RaceStatus getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
package network.MessageEncoders;
|
||||
|
||||
|
||||
import network.Messages.BoatStatus;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static network.Utils.ByteConverter.intToBytes;
|
||||
import static network.Utils.ByteConverter.longToBytes;
|
||||
|
||||
/**
|
||||
* This encoder can encode a {@link BoatStatus} message.
|
||||
*/
|
||||
public class BoatStatusEncoder {
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public BoatStatusEncoder() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encodes a given BoatStatus message.
|
||||
* @param message The message to encode.
|
||||
* @return The encoded message.
|
||||
*/
|
||||
public byte[] encode(BoatStatus message) {
|
||||
|
||||
//Downcast.
|
||||
BoatStatus boatStatus = (BoatStatus) message;
|
||||
|
||||
//BoatStatus is 20 bytes.
|
||||
ByteBuffer boatStatusBuffer = ByteBuffer.allocate(20);
|
||||
|
||||
byte[] sourceID = intToBytes(boatStatus.getSourceID());
|
||||
byte[] boatStatusBytes = intToBytes(boatStatus.getBoatStatus().getValue(), 1);
|
||||
byte[] legNum = intToBytes(boatStatus.getLegNumber(), 1);
|
||||
byte[] numPenalties = intToBytes(boatStatus.getNumPenaltiesAwarded(), 1);
|
||||
byte[] numPenaltiesServed = intToBytes(boatStatus.getNumPenaltiesServed(), 1);
|
||||
byte[] estNextMarkTime = longToBytes(boatStatus.getEstTimeAtNextMark(), 6);
|
||||
byte[] estFinishTime = longToBytes(boatStatus.getEstTimeAtFinish(), 6);
|
||||
|
||||
boatStatusBuffer.put(sourceID);
|
||||
boatStatusBuffer.put(boatStatusBytes);
|
||||
boatStatusBuffer.put(legNum);
|
||||
boatStatusBuffer.put(numPenalties);
|
||||
boatStatusBuffer.put(numPenaltiesServed);
|
||||
boatStatusBuffer.put(estNextMarkTime);
|
||||
boatStatusBuffer.put(estFinishTime);
|
||||
|
||||
return boatStatusBuffer.array();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -31,10 +31,28 @@ public class EncoderFactory {
|
||||
|
||||
case HEARTBEAT: return new HeartBeatEncoder();
|
||||
|
||||
case RACESTATUS: return new RaceStatusEncoder();
|
||||
|
||||
//case DISPLAYTEXTMESSAGE: return new DisplayTextMessageEncoder();//TODO
|
||||
|
||||
case XMLMESSAGE: return new XMLMessageEncoder();
|
||||
|
||||
//case RACESTARTSTATUS: return new RaceStartStatusEncoder();//TODO
|
||||
|
||||
//case YACHTEVENTCODE: return new YachtEventCodeEncoder();//TODO
|
||||
|
||||
//case YACHTACTIONCODE: return new YachtActionCodeEncoder();//TODO
|
||||
|
||||
//case CHATTERTEXT: return new ChatterTextEncoder();//TODO
|
||||
|
||||
case BOATLOCATION: return new BoatLocationEncoder();
|
||||
|
||||
//case MARKROUNDING: return new MarkRoundingEncoder();//TODO
|
||||
|
||||
//case COURSEWIND: return new CourseWindEncoder();//TODO
|
||||
|
||||
//case AVGWIND: return new AverageWindEncoder();//TODO
|
||||
|
||||
case REQUEST_TO_JOIN: return new RequestToJoinEncoder();
|
||||
|
||||
case JOIN_ACCEPTANCE: return new JoinAcceptanceEncoder();
|
||||
|
||||
@@ -6,7 +6,6 @@ import network.Messages.HeartBeat;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static network.Utils.ByteConverter.intToBytes;
|
||||
import static network.Utils.ByteConverter.longToBytes;
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package network.MessageEncoders;
|
||||
|
||||
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.RaceStatus;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.List;
|
||||
|
||||
import static network.Utils.ByteConverter.intToBytes;
|
||||
import static network.Utils.ByteConverter.longToBytes;
|
||||
|
||||
/**
|
||||
* This encoder can encode a {@link RaceStatus} message.
|
||||
*/
|
||||
public class RaceStatusEncoder implements MessageEncoder {
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public RaceStatusEncoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] encode(AC35Data message) {
|
||||
|
||||
//Downcast.
|
||||
RaceStatus raceStatus = (RaceStatus) message;
|
||||
|
||||
|
||||
List<BoatStatus> boatStatuses = raceStatus.getBoatStatuses();
|
||||
|
||||
//24 byte header, plus 20 bytes per boat status.
|
||||
ByteBuffer raceStatusMessage = ByteBuffer.allocate(24 + 20 * boatStatuses.size());
|
||||
|
||||
//Version Number 1 bytes. this changes with the pdf. (2)
|
||||
byte versionNum = 0b10;
|
||||
|
||||
//time (6 bytes)
|
||||
byte[] timeBytes = longToBytes(raceStatus.getCurrentTime(), 6);
|
||||
|
||||
//race identifier in case multiple races are going at once.
|
||||
byte[] raceID = intToBytes(raceStatus.getRaceID());
|
||||
|
||||
//race status 0 - 10
|
||||
byte[] raceStatusByte = intToBytes(raceStatus.getRaceStatus().getValue(), 1);
|
||||
|
||||
//number of milliseconds from Jan 1, 1970 for when the data is valid
|
||||
byte[] expectedStart = longToBytes(raceStatus.getExpectedStartTime(), 6);
|
||||
|
||||
//North = 0x0000 East = 0x4000 South = 0x8000.
|
||||
byte[] raceWind = intToBytes(raceStatus.getWindDirection(), 2);
|
||||
|
||||
//mm/sec
|
||||
byte[] windSpeed = intToBytes(raceStatus.getWindSpeed(), 2);
|
||||
|
||||
|
||||
byte[] numBoats = intToBytes(boatStatuses.size(), 1);
|
||||
|
||||
//1 match race, 2 fleet race
|
||||
byte[] bytesRaceType = intToBytes(raceStatus.getRaceType().getValue(), 1);
|
||||
|
||||
|
||||
raceStatusMessage.put(versionNum);
|
||||
raceStatusMessage.put(timeBytes);
|
||||
raceStatusMessage.put(raceID);
|
||||
raceStatusMessage.put(raceStatusByte);
|
||||
raceStatusMessage.put(expectedStart);
|
||||
raceStatusMessage.put(raceWind);
|
||||
raceStatusMessage.put(windSpeed);
|
||||
raceStatusMessage.put(numBoats);
|
||||
raceStatusMessage.put(bytesRaceType);
|
||||
|
||||
//Encode each BoatStatus.
|
||||
for (BoatStatus boatStatus : boatStatuses) {
|
||||
|
||||
BoatStatusEncoder boatStatusEncoder = new BoatStatusEncoder();
|
||||
|
||||
byte[] boatStatusEncoded = boatStatusEncoder.encode(boatStatus);
|
||||
|
||||
raceStatusMessage.put(boatStatusEncoded);
|
||||
}
|
||||
|
||||
return raceStatusMessage.array();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -21,57 +21,6 @@ public class RaceVisionByteEncoder {
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Serializes a RaceStatus message.
|
||||
* @param raceStatus Message to serialize.
|
||||
* @return Serialized (byte array) message, ready to be written to a socket.
|
||||
*/
|
||||
public static byte[] raceStatus(RaceStatus raceStatus){
|
||||
|
||||
List<BoatStatus> boatStatuses = raceStatus.getBoatStatuses();
|
||||
|
||||
ByteBuffer raceStatusMessage = ByteBuffer.allocate(24 + 20* boatStatuses.size());
|
||||
//Version Number 1 bytes
|
||||
byte versionNum = 0b10; //this changes with the pdf. (2)
|
||||
byte[] timeBytes = longToBytes(raceStatus.getCurrentTime(), 6);//time (6 bytes)
|
||||
byte[] raceID = ByteBuffer.allocate(4).put(intToBytes(raceStatus.getRaceID())).array();//race identifier incase multiple races are going at once.
|
||||
byte[] raceStatusByte = intToBytes(raceStatus.getRaceStatus(), 1);//race status 0 - 10
|
||||
byte[] expectedStart = longToBytes(raceStatus.getExpectedStartTime(), 6);//number of milliseconds from Jan 1, 1970 for when the data is valid
|
||||
byte[] raceWind = ByteBuffer.allocate(2).put(intToBytes(raceStatus.getWindDirection(), 2)).array();//North = 0x0000 East = 0x4000 South = 0x8000.
|
||||
byte[] windSpeed = ByteBuffer.allocate(2).put(intToBytes(raceStatus.getWindSpeed(), 2)).array();//mm/sec
|
||||
byte[] numBoats = intToBytes(boatStatuses.size(), 1);
|
||||
byte[] bytesRaceType = intToBytes(raceStatus.getRaceType(), 1);//1 match race, 2 fleet race
|
||||
|
||||
raceStatusMessage.put(versionNum);
|
||||
raceStatusMessage.put(timeBytes);
|
||||
raceStatusMessage.put(raceID);
|
||||
raceStatusMessage.put(raceStatusByte);
|
||||
raceStatusMessage.put(expectedStart);
|
||||
raceStatusMessage.put(raceWind);
|
||||
raceStatusMessage.put(windSpeed);
|
||||
raceStatusMessage.put(numBoats);
|
||||
raceStatusMessage.put(bytesRaceType);
|
||||
|
||||
for (int i = 0; i < boatStatuses.size(); i++){
|
||||
byte[] sourceID = intToBytes(boatStatuses.get(i).getSourceID());
|
||||
byte[] boatStatus = intToBytes(boatStatuses.get(i).getBoatStatus(), 1);
|
||||
byte[] legNum = intToBytes(boatStatuses.get(i).getLegNumber(), 1);
|
||||
byte[] numPenalties = intToBytes(boatStatuses.get(i).getNumPenaltiesAwarded(), 1);
|
||||
byte[] numPenaltiesServed = intToBytes(boatStatuses.get(i).getNumPenaltiesServed(), 1);
|
||||
byte[] estNextMarkTime = longToBytes(boatStatuses.get(i).getEstTimeAtNextMark(), 6);
|
||||
byte[] estFinishTime = longToBytes( boatStatuses.get(i).getEstTimeAtFinish(), 6);
|
||||
|
||||
raceStatusMessage.put(sourceID);
|
||||
raceStatusMessage.put(boatStatus);
|
||||
raceStatusMessage.put(legNum);
|
||||
raceStatusMessage.put(numPenalties);
|
||||
raceStatusMessage.put(numPenaltiesServed);
|
||||
raceStatusMessage.put(estNextMarkTime);
|
||||
raceStatusMessage.put(estFinishTime);
|
||||
}
|
||||
|
||||
return raceStatusMessage.array();
|
||||
}
|
||||
|
||||
public static byte[] displayTextMessage(RaceMessage[] message){
|
||||
//ByteBuffer result = ByteBuffer.allocate(4 + numLines * 32);
|
||||
|
||||
@@ -29,8 +29,14 @@ public class BoatLocation extends AC35Data {
|
||||
public static final byte Helicopter = 12;
|
||||
public static final byte DataProcessingApplication = 13;
|
||||
|
||||
///Version number of the message - is always 1.
|
||||
private byte messageVersionNumber = 1;
|
||||
|
||||
/**
|
||||
* The current messageVersionNumber according to the API spec.
|
||||
*/
|
||||
public static final byte currentMessageVersionNumber = 1;
|
||||
|
||||
///Version number of the message.
|
||||
private byte messageVersionNumber;
|
||||
///Time of the event - milliseconds since jan 1 1970. Proper type is 6 byte int.
|
||||
private long time;
|
||||
///Source ID of the boat.
|
||||
@@ -91,12 +97,6 @@ public class BoatLocation extends AC35Data {
|
||||
private short rudderAngle;
|
||||
|
||||
|
||||
/**
|
||||
* Ctor. Default.
|
||||
*/
|
||||
public BoatLocation() {
|
||||
super(MessageType.BOATLOCATION);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ctor, with all parameters.
|
||||
@@ -154,7 +154,7 @@ public class BoatLocation extends AC35Data {
|
||||
public BoatLocation(int sourceID, double lat, double lon, long sequenceNumber, double heading, double boatSpeed, long time) {
|
||||
super(MessageType.BOATLOCATION);
|
||||
|
||||
this.messageVersionNumber = (byte) 1;
|
||||
this.messageVersionNumber = BoatLocation.currentMessageVersionNumber;
|
||||
this.time = time;
|
||||
this.sourceID = sourceID;
|
||||
this.sequenceNumber = sequenceNumber;
|
||||
|
||||
@@ -10,14 +10,14 @@ import network.Utils.ByteConverter;
|
||||
public class BoatStatus {
|
||||
|
||||
private int sourceID;
|
||||
private byte boatStatus;
|
||||
private BoatStatusEnum boatStatus;
|
||||
private byte legNumber;
|
||||
private byte numPenaltiesAwarded;
|
||||
private byte numPenaltiesServed;
|
||||
private long estTimeAtNextMark;
|
||||
private long estTimeAtFinish;
|
||||
|
||||
public BoatStatus(int sourceID, byte boatStatus, byte legNumber, byte numPenaltiesAwarded, byte numPenaltiesServed, long estTimeAtNextMark, long estTimeAtFinish) {
|
||||
public BoatStatus(int sourceID, BoatStatusEnum boatStatus, byte legNumber, byte numPenaltiesAwarded, byte numPenaltiesServed, long estTimeAtNextMark, long estTimeAtFinish) {
|
||||
this.sourceID = sourceID;
|
||||
this.boatStatus = boatStatus;
|
||||
this.legNumber = legNumber;
|
||||
@@ -30,7 +30,7 @@ public class BoatStatus {
|
||||
|
||||
public BoatStatus(int sourceID, BoatStatusEnum boatStatusEnum, int legNum, long estTimeAtNextMark) {
|
||||
this.sourceID = sourceID;
|
||||
this.boatStatus = boatStatusEnum.getValue();
|
||||
this.boatStatus = boatStatusEnum;
|
||||
this.legNumber = ByteConverter.intToBytes(legNum)[0];
|
||||
this.numPenaltiesAwarded = 0;
|
||||
this.numPenaltiesServed = 0;
|
||||
@@ -43,7 +43,7 @@ public class BoatStatus {
|
||||
return sourceID;
|
||||
}
|
||||
|
||||
public byte getBoatStatus() {
|
||||
public BoatStatusEnum getBoatStatus() {
|
||||
return boatStatus;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,11 +33,15 @@ public enum MessageType {
|
||||
BOATACTION(100),
|
||||
NOTAMESSAGE(0);
|
||||
|
||||
///Primitive value of the enum.
|
||||
private byte value;
|
||||
|
||||
/**
|
||||
* Ctor. Creates a MessageType enum from a given primitive integer value, cast to a byte.
|
||||
* Primitive value of the enum.
|
||||
*/
|
||||
private byte value;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a MessageType enum from a given primitive integer value, cast to a byte.
|
||||
* @param value Integer, which is cast to byte, to construct from.
|
||||
*/
|
||||
private MessageType(int value) {
|
||||
|
||||
@@ -2,27 +2,89 @@ package network.Messages;
|
||||
|
||||
|
||||
import network.Messages.Enums.MessageType;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import network.Messages.Enums.RaceTypeEnum;
|
||||
import network.Utils.AC35UnitConverter;
|
||||
import shared.model.Constants;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by fwy13 on 25/04/17.
|
||||
* Represents the information in a RaceStatus message (AC streaming spec: 4.2).
|
||||
*/
|
||||
public class RaceStatus extends AC35Data {
|
||||
|
||||
|
||||
/**
|
||||
* The current messageVersionNumber according to the API spec.
|
||||
*/
|
||||
public static final byte currentMessageVersionNumber = 2;
|
||||
|
||||
|
||||
/**
|
||||
* Version number of the message.
|
||||
*/
|
||||
private byte messageVersionNumber;
|
||||
|
||||
/**
|
||||
* Time the message was generated at.
|
||||
* Milliseconds since unix epoch.
|
||||
*/
|
||||
private long currentTime;
|
||||
|
||||
/**
|
||||
* ID number of the race.
|
||||
*/
|
||||
private int raceID;
|
||||
private byte raceStatus;
|
||||
|
||||
/**
|
||||
* The status of the race.
|
||||
*/
|
||||
private RaceStatusEnum raceStatus;
|
||||
|
||||
/**
|
||||
* The expected race start time.
|
||||
* Milliseconds since unix epoch.
|
||||
*/
|
||||
private long expectedStartTime;
|
||||
|
||||
/**
|
||||
* The wind direction of the course.
|
||||
*/
|
||||
private int windDirection;
|
||||
|
||||
/**
|
||||
* The wind speed of the course.
|
||||
*/
|
||||
private int windSpeed;
|
||||
private int raceType;
|
||||
|
||||
/**
|
||||
* The type of race this is.
|
||||
*/
|
||||
private RaceTypeEnum raceType;
|
||||
|
||||
/**
|
||||
* A list of boat statuses.
|
||||
* One for each boat.
|
||||
*/
|
||||
private List<BoatStatus> boatStatuses;
|
||||
|
||||
public RaceStatus(long currentTime, int raceID, byte raceStatus, long expectedStartTime, int windDirection, int windSpeed, int raceType, List<BoatStatus> boatStatuses){
|
||||
|
||||
/**
|
||||
* Constructs a RaceStatus message with the given parameters.
|
||||
* @param messageVersionNumber The version number of the message.
|
||||
* @param currentTime Time at which the message was generated.
|
||||
* @param raceID The ID of the race.
|
||||
* @param raceStatus The status of the race.
|
||||
* @param expectedStartTime The expected start time of the race.
|
||||
* @param windDirection The current wind direction in the race.
|
||||
* @param windSpeed The current wind speed in the race.
|
||||
* @param raceType The type of race this is.
|
||||
* @param boatStatuses A list of BoatStatuses. One for each boat.
|
||||
*/
|
||||
public RaceStatus(byte messageVersionNumber, long currentTime, int raceID, RaceStatusEnum raceStatus, long expectedStartTime, int windDirection, int windSpeed, RaceTypeEnum raceType, List<BoatStatus> boatStatuses) {
|
||||
super(MessageType.RACESTATUS);
|
||||
this.messageVersionNumber = messageVersionNumber;
|
||||
this.currentTime = currentTime;
|
||||
this.raceID = raceID;
|
||||
this.raceStatus = raceStatus;
|
||||
@@ -30,37 +92,58 @@ public class RaceStatus extends AC35Data {
|
||||
this.windDirection = windDirection;
|
||||
this.windSpeed = windSpeed;
|
||||
this.raceType = raceType;
|
||||
this.boatStatuses = boatStatuses;//note this is not a copy so any alterations to the parent will affect this.
|
||||
this.boatStatuses = boatStatuses;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the version number of this message.
|
||||
* @return The version number of the message.
|
||||
*/
|
||||
public byte getMessageVersionNumber() {
|
||||
return messageVersionNumber;
|
||||
}
|
||||
|
||||
///Getters.
|
||||
|
||||
/**
|
||||
* Returns the current time at which this message was generated. Milliseconds since unix epoch.
|
||||
* @return Time this message was generated at.
|
||||
*/
|
||||
public long getCurrentTime()
|
||||
{
|
||||
return currentTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the RaceID.
|
||||
* @return The raceID.
|
||||
*/
|
||||
public int getRaceID()
|
||||
{
|
||||
return raceID;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return race status number
|
||||
* Returns the race status.
|
||||
* @return The current race status.
|
||||
*/
|
||||
public byte getRaceStatus()
|
||||
public RaceStatusEnum getRaceStatus()
|
||||
{
|
||||
return raceStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the expected start time for the race. Milliseconds since unix epoch.
|
||||
* @return Expected start time for the race.
|
||||
*/
|
||||
public long getExpectedStartTime()
|
||||
{
|
||||
return expectedStartTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current direction of the wind in the race.
|
||||
* @return Current wind direction.
|
||||
*/
|
||||
public int getWindDirection()
|
||||
{
|
||||
return windDirection;
|
||||
@@ -75,60 +158,70 @@ public class RaceStatus extends AC35Data {
|
||||
return windSpeed;
|
||||
}
|
||||
|
||||
public int getRaceType()
|
||||
/**
|
||||
* Retrusn the type of race this is.
|
||||
* @return The type of race this is.
|
||||
*/
|
||||
public RaceTypeEnum getRaceType()
|
||||
{
|
||||
return raceType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of BoatStatuses. One for each boat.
|
||||
* @return List of BoatStatuses.
|
||||
*/
|
||||
public List<BoatStatus> getBoatStatuses()
|
||||
{
|
||||
return boatStatuses;
|
||||
}
|
||||
|
||||
|
||||
public boolean isNotActive() {
|
||||
return raceStatus == 0;
|
||||
return raceStatus == RaceStatusEnum.NOT_ACTIVE;
|
||||
}
|
||||
|
||||
public boolean isWarning() {
|
||||
return raceStatus == 1;
|
||||
return raceStatus == RaceStatusEnum.WARNING;
|
||||
}
|
||||
|
||||
public boolean isPreparatory() {
|
||||
return raceStatus == 2;
|
||||
return raceStatus == RaceStatusEnum.PREPARATORY;
|
||||
}
|
||||
|
||||
public boolean isStarted() {
|
||||
return raceStatus == 3;
|
||||
return raceStatus == RaceStatusEnum.STARTED;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return raceStatus == 4;
|
||||
return raceStatus == RaceStatusEnum.FINISHED;
|
||||
}
|
||||
|
||||
public boolean isRetired() {
|
||||
return raceStatus == 5;
|
||||
return raceStatus == RaceStatusEnum.RETIRED;
|
||||
}
|
||||
|
||||
public boolean isAbandoned() {
|
||||
return raceStatus == 6;
|
||||
return raceStatus == RaceStatusEnum.ABANDONED;
|
||||
}
|
||||
|
||||
public boolean isPostponed() {
|
||||
return raceStatus == 7;
|
||||
return raceStatus == RaceStatusEnum.POSTPONED;
|
||||
}
|
||||
|
||||
public boolean isTerminated() {
|
||||
return raceStatus == 8;
|
||||
return raceStatus == RaceStatusEnum.TERMINATED;
|
||||
}
|
||||
|
||||
public boolean isStartTimeSet() {
|
||||
return raceStatus != 9;
|
||||
return raceStatus != RaceStatusEnum.RACE_START_TIME_NOT_SET;
|
||||
}
|
||||
|
||||
public boolean isPrestart() {
|
||||
return raceStatus == 10;
|
||||
return raceStatus == RaceStatusEnum.PRESTART;
|
||||
}
|
||||
|
||||
|
||||
public double getScaledWindDirection() {
|
||||
return AC35UnitConverter.convertHeading(windDirection);
|
||||
}
|
||||
|
||||
@@ -215,7 +215,7 @@ public class VisualiserRace extends Race implements Runnable {
|
||||
|
||||
|
||||
//Boat status.
|
||||
BoatStatusEnum newBoatStatusEnum = BoatStatusEnum.fromByte(boatStatus.getBoatStatus());
|
||||
BoatStatusEnum newBoatStatusEnum = boatStatus.getBoatStatus();
|
||||
|
||||
//If we are changing from non-racing to racing, we need to initialise boat with their time at last mark.
|
||||
if ((boat.getStatus() != BoatStatusEnum.RACING) && (newBoatStatusEnum == BoatStatusEnum.RACING)) {
|
||||
@@ -309,7 +309,7 @@ public class VisualiserRace extends Race implements Runnable {
|
||||
private void updateRaceStatus(RaceStatus raceStatus) {
|
||||
|
||||
//Race status enum.
|
||||
this.raceStatusEnum = RaceStatusEnum.fromByte(raceStatus.getRaceStatus());
|
||||
this.raceStatusEnum = raceStatus.getRaceStatus();
|
||||
|
||||
//Wind.
|
||||
this.setWind(
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.MessageEncoders.BoatStatusEncoder;
|
||||
import network.MessageEncoders.RaceVisionByteEncoder;
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.Enums.BoatStatusEnum;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Test for the BoatStatus encoder and decoder
|
||||
*/
|
||||
public class BoatStatusDecoderTest {
|
||||
|
||||
|
||||
/**
|
||||
* Creates a BoatStatus message, encodes it, decodes it, and checks that the result matches the starting message.
|
||||
* @throws Exception if test fails.
|
||||
*/
|
||||
@Test
|
||||
public void boatStatusEncodeDecodeTest() throws Exception {
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
//Create data to serialize.
|
||||
int boatSourceID = 5;
|
||||
BoatStatusEnum boatStatusEnum = BoatStatusEnum.RACING;
|
||||
byte boatLegNumber = 5;
|
||||
byte boatPenaltiesAwarded = 4;
|
||||
byte boatPenaltiesServed = 2;
|
||||
long boatTimeAtNextMark = time + (1000 * 3);
|
||||
long boatTimeAtFinish = boatTimeAtNextMark + (1000 * 15);
|
||||
|
||||
BoatStatus boatStatus = new BoatStatus(
|
||||
boatSourceID,
|
||||
boatStatusEnum,
|
||||
boatLegNumber,
|
||||
boatPenaltiesAwarded,
|
||||
boatPenaltiesServed,
|
||||
boatTimeAtNextMark,
|
||||
boatTimeAtFinish );
|
||||
|
||||
|
||||
BoatStatus boatStatusDecoded = encodeDecodeBoatStatus(boatStatus);
|
||||
|
||||
compareBoatStatusMessages(boatStatus, boatStatusDecoded);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Encodes and decodes a BoatStatus, and returns it.
|
||||
* @param boatStatus The BoatStatus to encode and decode.
|
||||
* @return The decoded BoatStatus.
|
||||
*/
|
||||
private static BoatStatus encodeDecodeBoatStatus(BoatStatus boatStatus) {
|
||||
|
||||
BoatStatusEncoder boatStatusEncoder = new BoatStatusEncoder();
|
||||
|
||||
byte[] boatStatusEncoded = boatStatusEncoder.encode(boatStatus);
|
||||
|
||||
BoatStatusDecoder boatStatusDecoder = new BoatStatusDecoder(boatStatusEncoded);
|
||||
|
||||
BoatStatus boatStatusDecoded = boatStatusDecoder.getMessage();
|
||||
|
||||
return boatStatusDecoded;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two BoatStatus messages to check that they are equal.
|
||||
* @param original The original BoatStatus message.
|
||||
* @param decoded The decoded BoatStatus message.
|
||||
*/
|
||||
public static void compareBoatStatusMessages(BoatStatus original, BoatStatus decoded) {
|
||||
|
||||
Assert.assertEquals(original.getSourceID(), decoded.getSourceID());
|
||||
Assert.assertEquals(original.getBoatStatus(), decoded.getBoatStatus());
|
||||
Assert.assertEquals(original.getLegNumber(), decoded.getLegNumber());
|
||||
Assert.assertEquals(original.getNumPenaltiesAwarded(), decoded.getNumPenaltiesAwarded());
|
||||
Assert.assertEquals(original.getNumPenaltiesServed(), decoded.getNumPenaltiesServed());
|
||||
Assert.assertEquals(original.getEstTimeAtNextMark(), decoded.getEstTimeAtNextMark());
|
||||
Assert.assertEquals(original.getEstTimeAtFinish(), decoded.getEstTimeAtFinish());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +1,39 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.Exceptions.InvalidMessageException;
|
||||
import network.MessageEncoders.RaceVisionByteEncoder;
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.Enums.BoatStatusEnum;
|
||||
import network.Messages.Enums.RaceStatusEnum;
|
||||
import network.Messages.Enums.RaceTypeEnum;
|
||||
import network.Messages.RaceStatus;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
* Test for the RaceStatus encoder and decoder
|
||||
*/
|
||||
public class RaceStatusDecoderTest {
|
||||
|
||||
|
||||
/**
|
||||
* Creates a RaceStatus message, encodes it, decodes it, and checks that the result matches the starting message.
|
||||
* @throws Exception if test fails.
|
||||
*/
|
||||
@Test
|
||||
public void getByteArrayTest(){
|
||||
public void raceStatusEncodeDecodeTest() throws Exception {
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
|
||||
//Create data to serialize.
|
||||
int boat1SourceID = 5;
|
||||
int boat2SourceID = 8;
|
||||
byte boat1Status = 2;
|
||||
byte boat2Status = 2;
|
||||
BoatStatusEnum boat1Status = BoatStatusEnum.RACING;
|
||||
BoatStatusEnum boat2Status = BoatStatusEnum.RACING;
|
||||
byte boat1LegNumber = 5;
|
||||
byte boat2LegNumber = 3;
|
||||
byte boat1PenaltiesAwarded = 4;
|
||||
@@ -33,44 +45,85 @@ public class RaceStatusDecoderTest {
|
||||
long boat1TimeAtFinish = boat1TimeAtNextMark + (1000 * 15);
|
||||
long boat2TimeAtFinish = boat2TimeAtNextMark + (1000 * 7);
|
||||
|
||||
BoatStatus boatStatus1 = new BoatStatus(boat1SourceID, boat1Status, boat1LegNumber, boat1PenaltiesAwarded, boat1PenaltiesServed, boat1TimeAtNextMark, boat1TimeAtFinish);
|
||||
BoatStatus boatStatus2 = new BoatStatus(boat2SourceID, boat2Status, boat2LegNumber, boat2PenaltiesAwarded, boat2PenaltiesServed, boat2TimeAtNextMark, boat2TimeAtFinish);
|
||||
BoatStatus boatStatus1 = new BoatStatus(
|
||||
boat1SourceID,
|
||||
boat1Status,
|
||||
boat1LegNumber,
|
||||
boat1PenaltiesAwarded,
|
||||
boat1PenaltiesServed,
|
||||
boat1TimeAtNextMark,
|
||||
boat1TimeAtFinish );
|
||||
|
||||
BoatStatus boatStatus2 = new BoatStatus(
|
||||
boat2SourceID,
|
||||
boat2Status,
|
||||
boat2LegNumber,
|
||||
boat2PenaltiesAwarded,
|
||||
boat2PenaltiesServed,
|
||||
boat2TimeAtNextMark,
|
||||
boat2TimeAtFinish );
|
||||
|
||||
|
||||
int raceID = 585;
|
||||
byte raceStatus = 3;
|
||||
RaceStatusEnum raceStatus = RaceStatusEnum.STARTED;
|
||||
long raceStartTime = time - (1000 * 31);
|
||||
int windDirection = 2341;
|
||||
int windSpeed = 10201;
|
||||
int raceType = 1;
|
||||
RaceTypeEnum raceType = RaceTypeEnum.MATCH_RACE;
|
||||
List<BoatStatus> boatStatuses = new ArrayList<>(2);
|
||||
boatStatuses.add(boatStatus1);
|
||||
boatStatuses.add(boatStatus2);
|
||||
|
||||
RaceStatus raceStatusObject = new RaceStatus(time, raceID, raceStatus, raceStartTime, windDirection, windSpeed, raceType, boatStatuses);
|
||||
RaceStatus raceStatusOriginal = new RaceStatus(
|
||||
RaceStatus.currentMessageVersionNumber,
|
||||
time,
|
||||
raceID,
|
||||
raceStatus,
|
||||
raceStartTime,
|
||||
windDirection,
|
||||
windSpeed,
|
||||
raceType,
|
||||
boatStatuses );
|
||||
|
||||
|
||||
byte[] encodedRaceStatus = RaceVisionByteEncoder.raceStatus(raceStatusObject);
|
||||
byte[] encodedRaceStatus = RaceVisionByteEncoder.encode(raceStatusOriginal);
|
||||
|
||||
RaceStatusDecoder decoderTest = new RaceStatusDecoder(encodedRaceStatus);
|
||||
|
||||
Assert.assertEquals(0b10, decoderTest.getVersionNum());
|
||||
Assert.assertEquals(time, decoderTest.getTime());
|
||||
Assert.assertEquals(raceID, decoderTest.getRace());
|
||||
Assert.assertEquals(raceStatus, decoderTest.getRaceState());
|
||||
Assert.assertEquals(raceStartTime, decoderTest.getStartTime());
|
||||
Assert.assertEquals(windDirection, decoderTest.getRaceWindDir());
|
||||
Assert.assertEquals(windSpeed, decoderTest.getRaceWindSpeed());
|
||||
RaceStatus decodedMessage = decoderTest.getMessage();
|
||||
|
||||
|
||||
BoatStatus boat1 = decoderTest.getBoats().get(0);
|
||||
|
||||
Assert.assertEquals(boat1SourceID, boat1.getSourceID());
|
||||
Assert.assertEquals(boat1Status, boat1.getBoatStatus());
|
||||
Assert.assertEquals(boat1LegNumber, boat1.getLegNumber());
|
||||
Assert.assertEquals(boat1PenaltiesAwarded, boat1.getNumPenaltiesAwarded());
|
||||
Assert.assertEquals(boat1PenaltiesServed, boat1.getNumPenaltiesServed());
|
||||
Assert.assertEquals(boat1TimeAtNextMark, boat1.getEstTimeAtNextMark());
|
||||
Assert.assertEquals(boat1TimeAtFinish, boat1.getEstTimeAtFinish());
|
||||
compareRaceStatusMessages(raceStatusOriginal, decodedMessage);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two RaceStatus messages to check that they are equal.
|
||||
* @param original The original RaceStatus message.
|
||||
* @param decoded The decoded RaceStatus message.
|
||||
*/
|
||||
public static void compareRaceStatusMessages(RaceStatus original, RaceStatus decoded) {
|
||||
|
||||
//Compare RaceStatus body.
|
||||
Assert.assertEquals(original.getMessageVersionNumber(), decoded.getMessageVersionNumber());
|
||||
Assert.assertEquals(original.getCurrentTime(), decoded.getCurrentTime());
|
||||
Assert.assertEquals(original.getRaceID(), decoded.getRaceID());
|
||||
Assert.assertEquals(original.getRaceStatus(), decoded.getRaceStatus());
|
||||
Assert.assertEquals(original.getExpectedStartTime(), decoded.getExpectedStartTime());
|
||||
Assert.assertEquals(original.getWindDirection(), decoded.getWindDirection());
|
||||
Assert.assertEquals(original.getWindSpeed(), decoded.getWindSpeed());
|
||||
|
||||
//Compare all BoatStatuses
|
||||
Iterator<BoatStatus> originalIterator = original.getBoatStatuses().iterator();
|
||||
Iterator<BoatStatus> decodedIterator = decoded.getBoatStatuses().iterator();
|
||||
|
||||
while (originalIterator.hasNext() && decodedIterator.hasNext()) {
|
||||
|
||||
BoatStatusDecoderTest.compareBoatStatusMessages(originalIterator.next(), decodedIterator.next());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user