Added DecoderFactory. This creates an appropriate decoder based on a MessageType. BoatActionDecoder implements MessageDecoder. BoatLocationDecoder implements MessageDecoder. HeartBeatDecoder implements MessageDecoder. JoinAcceptance implements MessageDecoder. RaceStatusDecoder implements MessageDecoder. RequestToJoinDecoder implements MessageDecoder. XMLMessageDecoder implements MessageDecoder. Refactored CourseWind decoder/encoder. CourseWind decoder/encoder is for an individual CourseWind. CourseWinds decoder/encoder is for the combined message from the API. Documented BoatAction, and it now contains a BoatActionEnum instead of a byte. Refactored CourseWind and CourseWinds classes. They now expose correct units, instead of packed units. Added CourseWindDecoderTest, and updated CourseWindsDecoderTest. issue #35 #36 #story[1095]main
parent
1fbdd09d70
commit
750ea5c141
@ -1,20 +1,50 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.BoatAction;
|
||||
import network.Messages.Enums.BoatActionEnum;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class BoatActionDecoder {
|
||||
byte byteBoatAction;
|
||||
BoatActionEnum boatAction;
|
||||
/**
|
||||
* Decodes {@link BoatAction} messages.
|
||||
*/
|
||||
public class BoatActionDecoder implements MessageDecoder {
|
||||
|
||||
public BoatActionDecoder(byte[] encodedBoatAction) {
|
||||
byteBoatAction = encodedBoatAction[0];
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
boatAction = BoatActionEnum.fromByte(byteBoatAction);
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private BoatAction message;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public BoatActionDecoder() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
BoatActionEnum boatActionEnum = BoatActionEnum.fromByte(encodedMessage[0]);
|
||||
|
||||
message = new BoatAction(boatActionEnum);
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
public BoatActionEnum getBoatAction() {
|
||||
return boatAction;
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public BoatAction getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,87 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.CourseWind;
|
||||
import network.Messages.CourseWinds;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static network.Utils.ByteConverter.bytesToInt;
|
||||
import static network.Utils.ByteConverter.bytesToLong;
|
||||
|
||||
|
||||
/**
|
||||
* Decodes {@link CourseWinds} messages.
|
||||
*/
|
||||
public class CourseWindsDecoder implements MessageDecoder {
|
||||
|
||||
/**
|
||||
* The encoded message.
|
||||
*/
|
||||
private byte[] encodedMessage;
|
||||
|
||||
/**
|
||||
* The decoded message.
|
||||
*/
|
||||
private CourseWinds message;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a decoder to decode a given message.
|
||||
*/
|
||||
public CourseWindsDecoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AC35Data decode(byte[] encodedMessage) {
|
||||
this.encodedMessage = encodedMessage;
|
||||
|
||||
//The header is three bytes.
|
||||
byte messageVersionNumber = encodedMessage[0];
|
||||
byte byteWindID = encodedMessage[1];
|
||||
byte loopCount = encodedMessage[2];
|
||||
|
||||
|
||||
//A CourseWind object is 20 bytes.
|
||||
final int courseWindByteLength = 20;
|
||||
|
||||
List<CourseWind> loopMessages = new ArrayList();
|
||||
|
||||
//The header is 3 bytes, so we need the remaining bytes.
|
||||
byte[] loopMessagesBytes = Arrays.copyOfRange(encodedMessage, 3, courseWindByteLength * loopCount + 3);
|
||||
|
||||
for (int messageLoopIndex = 0; messageLoopIndex < (loopCount * courseWindByteLength); messageLoopIndex += courseWindByteLength) {
|
||||
|
||||
byte[] messageBytes = Arrays.copyOfRange(loopMessagesBytes, messageLoopIndex, messageLoopIndex + courseWindByteLength);
|
||||
|
||||
CourseWindDecoder courseWindDecoder = new CourseWindDecoder();
|
||||
CourseWind courseWind = courseWindDecoder.decode(messageBytes);
|
||||
|
||||
loopMessages.add(courseWind);
|
||||
}
|
||||
|
||||
|
||||
|
||||
message = new CourseWinds(
|
||||
messageVersionNumber,
|
||||
byteWindID,
|
||||
loopMessages );
|
||||
|
||||
return message;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the decoded message.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public CourseWinds getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,70 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Exceptions.InvalidMessageTypeException;
|
||||
import network.Messages.Enums.MessageType;
|
||||
|
||||
/**
|
||||
* Factory to create the appropriate decoder for a given message.
|
||||
*/
|
||||
public class DecoderFactory {
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor. Currently doesn't need to be constructed.
|
||||
*/
|
||||
private DecoderFactory(){
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates the correct type of decoder for a given message type.
|
||||
* @param type Type of message you want a decoder for.
|
||||
* @return The decoder.
|
||||
* @throws InvalidMessageTypeException If you pass in a {@link MessageType} that isn't recognised.
|
||||
*/
|
||||
public static MessageDecoder create(MessageType type) throws InvalidMessageTypeException {
|
||||
|
||||
|
||||
switch (type) {
|
||||
|
||||
case HEARTBEAT: return new HeartBeatDecoder();
|
||||
|
||||
case RACESTATUS: return new RaceStatusDecoder();
|
||||
|
||||
//case DISPLAYTEXTMESSAGE: return new DisplayTextMessageDecoder();//TODO
|
||||
|
||||
case XMLMESSAGE: return new XMLMessageDecoder();
|
||||
|
||||
//case RACESTARTSTATUS: return new RaceStartStatusDecoder();//TODO
|
||||
|
||||
//case YACHTEVENTCODE: return new YachtEventCodeDecoder();//TODO
|
||||
|
||||
//case YACHTACTIONCODE: return new YachtActionCodeDecoder();//TODO
|
||||
|
||||
//case CHATTERTEXT: return new ChatterTextDecoder();//TODO
|
||||
|
||||
case BOATLOCATION: return new BoatLocationDecoder();
|
||||
|
||||
//case MARKROUNDING: return new MarkRoundingDecoder()//TODO;
|
||||
|
||||
case COURSEWIND: return new CourseWindsDecoder();
|
||||
|
||||
//case AVGWIND: return new AverageWindDecoder()//TODO;
|
||||
|
||||
case REQUEST_TO_JOIN: return new RequestToJoinDecoder();
|
||||
|
||||
case JOIN_ACCEPTANCE: return new JoinAcceptanceDecoder();
|
||||
|
||||
case BOATACTION: return new BoatActionDecoder();
|
||||
|
||||
|
||||
default: throw new InvalidMessageTypeException("Unrecognised message type: " + type);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
|
||||
import network.Messages.AC35Data;
|
||||
|
||||
|
||||
/**
|
||||
* This is the interface that all message decoders must implement.
|
||||
* It allows for {@link #decode(byte[])}ing messages.
|
||||
*/
|
||||
public interface MessageDecoder {
|
||||
|
||||
|
||||
/**
|
||||
* Decodes a given message.
|
||||
* @param encodedMessage The message to decode.
|
||||
* @return The decoded message.
|
||||
*/
|
||||
public AC35Data decode(byte[] encodedMessage);
|
||||
|
||||
}
|
||||
@ -0,0 +1,73 @@
|
||||
package network.MessageEncoders;
|
||||
|
||||
|
||||
import network.Messages.CourseWind;
|
||||
import shared.model.Bearing;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Arrays;
|
||||
|
||||
import static network.Utils.AC35UnitConverter.*;
|
||||
import static network.Utils.ByteConverter.*;
|
||||
import static network.Utils.ByteConverter.bytesToInt;
|
||||
|
||||
/**
|
||||
* This encoder can encode a {@link CourseWind} message.
|
||||
*/
|
||||
public class CourseWindEncoder {
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public CourseWindEncoder() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Encodes a given CourseWind message.
|
||||
* @param message The message to encode.
|
||||
* @return The encoded message.
|
||||
*/
|
||||
public byte[] encode(CourseWind message) {
|
||||
|
||||
CourseWind courseWind = message;
|
||||
|
||||
|
||||
//CourseWind is 20 bytes.
|
||||
ByteBuffer courseWindBuffer = ByteBuffer.allocate(20);
|
||||
|
||||
|
||||
byte[] windId = intToBytes(courseWind.getID(), 1);
|
||||
|
||||
byte[] timeBytes = longToBytes(courseWind.getTime(), 6);
|
||||
|
||||
byte[] raceIDBytes = intToBytes(courseWind.getRaceID(), 4);
|
||||
|
||||
int windDirectionInt = packHeading(courseWind.getWindDirection().degrees());
|
||||
byte[] windDirectionBytes = intToBytes(windDirectionInt, 2);
|
||||
|
||||
int windSpeedInt = packKnotsToMMperSec(courseWind.getWindSpeedKnots());
|
||||
byte[] windSpeedBytes = intToBytes(windSpeedInt, 2);
|
||||
|
||||
int bestUpwindAngleInt = packHeading(courseWind.getBestUpwindAngle().degrees());
|
||||
byte[] bestUpwindAngleBytes = intToBytes(bestUpwindAngleInt, 2);
|
||||
|
||||
int bestDownwindAngleInt = packHeading(courseWind.getBestDownwindAngle().degrees());
|
||||
byte[] bestDownwindAngleBytes = intToBytes(bestDownwindAngleInt, 2);
|
||||
|
||||
byte[] flags = intToBytes(courseWind.getFlags(), 1);
|
||||
|
||||
courseWindBuffer.put(windId);
|
||||
courseWindBuffer.put(timeBytes);
|
||||
courseWindBuffer.put(raceIDBytes);
|
||||
courseWindBuffer.put(windDirectionBytes);
|
||||
courseWindBuffer.put(windSpeedBytes);
|
||||
courseWindBuffer.put(bestUpwindAngleBytes);
|
||||
courseWindBuffer.put(bestDownwindAngleBytes);
|
||||
courseWindBuffer.put(flags);
|
||||
|
||||
return courseWindBuffer.array();
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,57 @@
|
||||
package network.MessageEncoders;
|
||||
|
||||
|
||||
import network.Messages.AC35Data;
|
||||
import network.Messages.BoatAction;
|
||||
import network.Messages.CourseWind;
|
||||
import network.Messages.CourseWinds;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static network.Utils.ByteConverter.intToBytes;
|
||||
|
||||
/**
|
||||
* This encoder can encode a {@link CourseWinds} message.
|
||||
*/
|
||||
public class CourseWindsEncoder implements MessageEncoder {
|
||||
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public CourseWindsEncoder() {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public byte[] encode(AC35Data message) {
|
||||
|
||||
//Downcast.
|
||||
CourseWinds courseWinds = (CourseWinds) message;
|
||||
|
||||
|
||||
byte messageVersionNumber = CourseWinds.currentMessageVersionNumber;
|
||||
|
||||
byte byteWindID = courseWinds.getSelectedWindID();
|
||||
|
||||
byte[] loopcount = intToBytes(courseWinds.getCourseWinds().size(), 1);
|
||||
|
||||
ByteBuffer result = ByteBuffer.allocate(3 + 20 * courseWinds.getCourseWinds().size());
|
||||
|
||||
result.put(messageVersionNumber);
|
||||
result.put(byteWindID);
|
||||
result.put(loopcount);
|
||||
|
||||
//Encode each CourseWind.
|
||||
for (CourseWind wind: courseWinds.getCourseWinds()){
|
||||
|
||||
CourseWindEncoder courseWindEncoder = new CourseWindEncoder();
|
||||
byte[] encodedCourseWind = courseWindEncoder.encode(wind);
|
||||
|
||||
result.put(encodedCourseWind);
|
||||
}
|
||||
return result.array();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,57 +1,77 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.MessageEncoders.RaceVisionByteEncoder;
|
||||
import network.MessageEncoders.CourseWindEncoder;
|
||||
import network.Messages.BoatStatus;
|
||||
import network.Messages.CourseWind;
|
||||
import network.Messages.Enums.BoatStatusEnum;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import shared.model.Bearing;
|
||||
|
||||
/**
|
||||
* Created by hba56 on 23/04/17.
|
||||
* Test for the CourseWind encoder and decoder
|
||||
*/
|
||||
public class CourseWindDecoderTest {
|
||||
|
||||
|
||||
/**
|
||||
* Creates a CourseWind 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 courseWindEncodeDecodeTest() throws Exception {
|
||||
|
||||
long time = System.currentTimeMillis();
|
||||
CourseWind testCourseWind1 = new CourseWind(1, time, 2,
|
||||
3, 4, 5,
|
||||
7, 6);
|
||||
CourseWind courseWind = new CourseWind(
|
||||
1,
|
||||
time,
|
||||
2,
|
||||
Bearing.fromDegrees(45),
|
||||
4,
|
||||
Bearing.fromDegrees(70),
|
||||
Bearing.fromDegrees(160),
|
||||
(byte) 0x13 );
|
||||
|
||||
|
||||
long time2 = System.currentTimeMillis();
|
||||
CourseWind testCourseWind2 = new CourseWind(2, time2, 2,
|
||||
3, 4, 5,
|
||||
7, 6);
|
||||
CourseWind courseWindDecoded = encodeDecodeCourseWind(courseWind);
|
||||
|
||||
ArrayList<CourseWind> testCourseWinds = new ArrayList<CourseWind>();
|
||||
testCourseWinds.add(testCourseWind1);
|
||||
testCourseWinds.add(testCourseWind2);
|
||||
compareCourseWindMessages(courseWind, courseWindDecoded);
|
||||
|
||||
}
|
||||
|
||||
byte[] testEncodedCourseWind = RaceVisionByteEncoder.courseWind((byte) 1, testCourseWinds);
|
||||
/**
|
||||
* Encodes and decodes a CourseWind, and returns it.
|
||||
* @param courseWind The CourseWind to encode and decode.
|
||||
* @return The decoded CourseWind.
|
||||
*/
|
||||
private static CourseWind encodeDecodeCourseWind(CourseWind courseWind) {
|
||||
|
||||
CourseWindDecoder testDecoder = new CourseWindDecoder(testEncodedCourseWind);
|
||||
CourseWindEncoder courseWindEncoder = new CourseWindEncoder();
|
||||
byte[] courseWindEncoded = courseWindEncoder.encode(courseWind);
|
||||
|
||||
ArrayList<CourseWind> testDecodedCourseWinds = testDecoder.getLoopMessages();
|
||||
CourseWindDecoder courseWindDecoder = new CourseWindDecoder();
|
||||
CourseWind courseWindDecoded = courseWindDecoder.decode(courseWindEncoded);
|
||||
|
||||
Assert.assertEquals(testCourseWinds.get(0).getID(), testDecodedCourseWinds.get(0).getID());
|
||||
Assert.assertEquals(testCourseWinds.get(0).getTime(), testDecodedCourseWinds.get(0).getTime());
|
||||
Assert.assertEquals(testCourseWinds.get(0).getRaceID(), testDecodedCourseWinds.get(0).getRaceID());
|
||||
Assert.assertEquals(testCourseWinds.get(0).getWindDirection(), testDecodedCourseWinds.get(0).getWindDirection());
|
||||
Assert.assertEquals(testCourseWinds.get(0).getWindSpeed(), testDecodedCourseWinds.get(0).getWindSpeed());
|
||||
Assert.assertEquals(testCourseWinds.get(0).getBestUpwindAngle(), testDecodedCourseWinds.get(0).getBestUpwindAngle());
|
||||
Assert.assertEquals(testCourseWinds.get(0).getBestDownwindAngle(), testDecodedCourseWinds.get(0).getBestDownwindAngle());
|
||||
Assert.assertEquals(testCourseWinds.get(0).getFlags(), testDecodedCourseWinds.get(0).getFlags());
|
||||
return courseWindDecoded;
|
||||
}
|
||||
|
||||
Assert.assertEquals(testCourseWinds.get(1).getID(), testDecodedCourseWinds.get(1).getID());
|
||||
Assert.assertEquals(testCourseWinds.get(1).getTime(), testDecodedCourseWinds.get(1).getTime());
|
||||
Assert.assertEquals(testCourseWinds.get(1).getRaceID(), testDecodedCourseWinds.get(1).getRaceID());
|
||||
Assert.assertEquals(testCourseWinds.get(1).getWindDirection(), testDecodedCourseWinds.get(1).getWindDirection());
|
||||
Assert.assertEquals(testCourseWinds.get(1).getWindSpeed(), testDecodedCourseWinds.get(1).getWindSpeed());
|
||||
Assert.assertEquals(testCourseWinds.get(1).getBestUpwindAngle(), testDecodedCourseWinds.get(1).getBestUpwindAngle());
|
||||
Assert.assertEquals(testCourseWinds.get(1).getBestDownwindAngle(), testDecodedCourseWinds.get(1).getBestDownwindAngle());
|
||||
Assert.assertEquals(testCourseWinds.get(1).getFlags(), testDecodedCourseWinds.get(1).getFlags());
|
||||
|
||||
/**
|
||||
* Compares two CourseWind messages to check that they are equal.
|
||||
* @param original The original CourseWind message.
|
||||
* @param decoded The decoded CourseWind message.
|
||||
*/
|
||||
public static void compareCourseWindMessages(CourseWind original, CourseWind decoded) {
|
||||
|
||||
Assert.assertEquals(original.getID(), decoded.getID());
|
||||
Assert.assertEquals(original.getTime(), decoded.getTime());
|
||||
Assert.assertEquals(original.getRaceID(), decoded.getRaceID());
|
||||
Assert.assertEquals(original.getWindDirection().degrees(), decoded.getWindDirection().degrees(), 0.01);
|
||||
Assert.assertEquals(original.getWindSpeedKnots(), decoded.getWindSpeedKnots(), 0.01);
|
||||
Assert.assertEquals(original.getBestUpwindAngle().degrees(), decoded.getBestUpwindAngle().degrees(), 0.01);
|
||||
Assert.assertEquals(original.getBestDownwindAngle().degrees(), decoded.getBestDownwindAngle().degrees(), 0.01);
|
||||
Assert.assertEquals(original.getFlags(), decoded.getFlags());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,96 @@
|
||||
package network.MessageDecoders;
|
||||
|
||||
import network.MessageEncoders.RaceVisionByteEncoder;
|
||||
import network.Messages.CourseWind;
|
||||
import network.Messages.CourseWinds;
|
||||
import org.junit.Test;
|
||||
import shared.model.Bearing;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
|
||||
/**
|
||||
* Tests for CourseWinds encoder and decoder.
|
||||
*/
|
||||
public class CourseWindsDecoderTest {
|
||||
|
||||
/**
|
||||
* Tests if a CourseWinds message can be encoded and decoded correctly.
|
||||
* @throws Exception Thrown if an error occurs.
|
||||
*/
|
||||
@Test
|
||||
public void courseWindsEncodeDecodeTest() throws Exception {
|
||||
|
||||
long time1 = System.currentTimeMillis();
|
||||
CourseWind testCourseWind1 = new CourseWind(
|
||||
1,
|
||||
time1,
|
||||
2,
|
||||
Bearing.fromDegrees(45),
|
||||
4,
|
||||
Bearing.fromDegrees(70),
|
||||
Bearing.fromDegrees(160),
|
||||
(byte) 0xCE );
|
||||
|
||||
long time2 = System.currentTimeMillis();
|
||||
CourseWind testCourseWind2 = new CourseWind(
|
||||
2,
|
||||
time2,
|
||||
2,
|
||||
Bearing.fromDegrees(55),
|
||||
4,
|
||||
Bearing.fromDegrees(80),
|
||||
Bearing.fromDegrees(180),
|
||||
(byte) 0x0D );
|
||||
|
||||
List<CourseWind> testCourseWinds = new ArrayList<>();
|
||||
testCourseWinds.add(testCourseWind1);
|
||||
testCourseWinds.add(testCourseWind2);
|
||||
|
||||
CourseWinds courseWinds = new CourseWinds(CourseWinds.currentMessageVersionNumber, (byte) 2, testCourseWinds);
|
||||
|
||||
|
||||
byte[] testEncodedCourseWind = RaceVisionByteEncoder.encode(courseWinds);
|
||||
|
||||
CourseWindsDecoder courseWindsDecoder = new CourseWindsDecoder();
|
||||
courseWindsDecoder.decode(testEncodedCourseWind);
|
||||
CourseWinds courseWindsDecoded = courseWindsDecoder.getMessage();
|
||||
|
||||
compareCourseWindsMessages(courseWinds, courseWindsDecoded);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Compares two course winds messages to ensure they are the same.
|
||||
* @param original The original message.
|
||||
* @param decoded The decoded message.
|
||||
*/
|
||||
public static void compareCourseWindsMessages(CourseWinds original, CourseWinds decoded) {
|
||||
|
||||
//Compare header.
|
||||
assertEquals(original.getMessageVersionNumber(), decoded.getMessageVersionNumber());
|
||||
assertEquals(original.getSelectedWindID(), decoded.getSelectedWindID());
|
||||
assertEquals(original.getCourseWinds().size(), decoded.getCourseWinds().size());
|
||||
|
||||
//Compare each CourseWind.
|
||||
List<CourseWind> originalWinds = original.getCourseWinds();
|
||||
List<CourseWind> decodedWinds = decoded.getCourseWinds();
|
||||
|
||||
Iterator<CourseWind> originalIterator = originalWinds.iterator();
|
||||
Iterator<CourseWind> decodedIterator = decodedWinds.iterator();
|
||||
|
||||
while (originalIterator.hasNext() && decodedIterator.hasNext()) {
|
||||
|
||||
CourseWindDecoderTest.compareCourseWindMessages(originalIterator.next(), decodedIterator.next());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Reference in new issue