package dk.dma.ais.tracker.eventEmittingTracker;
import dk.dma.ais.packet.AisPacket;
import dk.dma.enav.model.geometry.Position;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.GregorianCalendar;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
public class TrackTest {
Track track;
// GatehouseSourceTag [baseMmsi=2190067, country=DK, region=, timestamp=Thu Apr 10 15:30:29 CEST 2014]
// [msgId=5, repeat=0, userId=219000606, callsign=OWNM@@@, dest=BOEJDEN-FYNSHAV@@@@@, dimBow=12, dimPort=8, dimStarboard=4, dimStern=58, draught=30, dte=0, eta=67584, imo=8222824, name=FRIGG SYDFYEN@@@@@@@, posType=1, shipType=61, spare=0, version=0]
AisPacket msg5 = AisPacket.from(
"$PGHP,1,2014,4,10,13,30,29,165,219,,2190067,1,28*22\r\n" +
"!BSVDM,2,1,1,A,53@ng7P1uN6PuLpl000I8TLN1=T@ITDp0000000u1Pr844@P07PSiBQ1,0*7B\r\n" +
"!BSVDM,2,2,1,A,CcAVCTj0EP00000,2*53");
@Before
public void setUp() throws Exception {
track = new Track(2345);
}
@After
public void tearDown() throws Exception {
}
@Test
public void testGetMmsi() throws Exception {
assertEquals(2345, track.getMmsi());
}
@Test(expected = IllegalArgumentException.class)
public void cannotUpdateTrackWithWrongMMSI() throws Exception {
Track track = new Track(2191000);
track.update(msg5);
}
@Test
public void canGetStaticInformationFromTrack() throws Exception {
Track track = new Track(219000606);
assertNull(track.getCallsign());
assertNull(track.getShipName());
assertNull(track.getIMO());
assertNull(track.getShipDimensionBow());
assertNull(track.getShipDimensionStern());
assertNull(track.getShipDimensionPort());
assertNull(track.getShipDimensionStarboard());
assertNull(track.getVesselLength());
assertNull(track.getVesselBeam());
assertEquals(0, track.getTimeOfLastUpdate());
track.update(msg5);
assertEquals("OWNM@@@", track.getCallsign());
assertEquals("FRIGG SYDFYEN@@@@@@@", track.getShipName());
assertEquals(8222824, track.getIMO().intValue());
assertEquals(12, track.getShipDimensionBow().intValue());
assertEquals(58, track.getShipDimensionStern().intValue());
assertEquals(8, track.getShipDimensionPort().intValue());
assertEquals(4, track.getShipDimensionStarboard().intValue());
assertEquals(12 + 58, track.getVesselLength().intValue());
assertEquals(8 + 4, track.getVesselBeam().intValue());
assertEquals(1397136629165L, track.getTimeOfLastUpdate());
}
@Test
public void testGetNewestTrackingReport() throws Exception {
assertNull(track.getNewestTrackingReport());
track.update(1000000000, Position.create(56, 12), 45.0f, 10.1f, 10.1f);
assertNotNull(track.getNewestTrackingReport());
assertEquals(1000000000, track.getNewestTrackingReport().getTimestamp());
track.update(1000010000, Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertNotNull(track.getNewestTrackingReport());
assertEquals(1000010000, track.getNewestTrackingReport().getTimestamp());
track.update(1000020000, Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertNotNull(track.getNewestTrackingReport());
assertEquals(1000020000, track.getNewestTrackingReport().getTimestamp());
track.update(1000, Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertNotNull(track.getNewestTrackingReport());
assertEquals(1000020000, track.getNewestTrackingReport().getTimestamp());
}
@Test
public void testGetTimeOfLastPositionReport() throws Exception {
assertEquals(0, track.getTimeOfLastPositionReport());
track.update(1000000000, Position.create(56, 12), 45.0f, 10.1f, 10.1f);
assertEquals(1000000000L, track.getTimeOfLastPositionReport());
track.update(1000010000, Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(1000010000L, track.getTimeOfLastPositionReport());
track.update(1000020000, Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(1000020000L, track.getTimeOfLastPositionReport());
track.update(1000, Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(1000020000L, track.getTimeOfLastPositionReport());
}
@Test
public void testPurgeOldPositionReports() {
assertEquals(0, track.getTrackingReports().size());
assertEquals(20, track.MAX_AGE_POSITION_REPORTS_MINUTES);
track.update(new GregorianCalendar(2014, 02, 11, 12, 32, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(1, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 34, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(2, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 36, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(3, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 38, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(4, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 38, 59).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(5, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 40, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(6, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 42, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(7, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 44, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(8, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 46, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(9, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 48, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(10, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 50, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(11, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 52, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(12, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 54, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(12, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 56, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(12, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 12, 58, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(12, track.getTrackingReports().size());
track.update(new GregorianCalendar(2014, 02, 11, 13, 00, 00).getTimeInMillis(), Position.create(56.01, 12.01), 45.0f, 10.1f, 10.1f);
assertEquals(11, track.getTrackingReports().size());
List<TrackingReport> trackingReports = track.getTrackingReports();
assertEquals(11, trackingReports.size());
long oldestKept = new GregorianCalendar(2014, 02, 11, 12, 50-track.MAX_AGE_POSITION_REPORTS_MINUTES, 00).getTimeInMillis();
trackingReports.forEach(p -> assertTrue(p.getTimestamp() >= oldestKept));
}
@Test
public void testPredictEast() {
track.update(new GregorianCalendar(2014, 02, 11, 12, 32, 00).getTimeInMillis(), Position.create(56.00, 12.00), 90.0f, 1.0f, 1.0f);
track.predict(new GregorianCalendar(2014, 02, 11, 12, 33, 00).getTimeInMillis());
assertEquals(56.000000, track.getNewestTrackingReport().getPosition().getLatitude(), 1e-6);
assertEquals(12.000496, track.getNewestTrackingReport().getPosition().getLongitude(), 1e-6);
assertEquals(new GregorianCalendar(2014, 02, 11, 12, 33, 00).getTimeInMillis(), track.getTimeOfLastPositionReport(), 1e-10);
}
@Test
public void testPredictNorth() {
track.update(new GregorianCalendar(2014, 02, 11, 12, 32, 00).getTimeInMillis(), Position.create(56.00, 12.00), 0.0f, 1.0f, 1.0f);
track.predict(new GregorianCalendar(2014, 02, 11, 12, 33, 00).getTimeInMillis());
assertEquals(56.000277, track.getNewestTrackingReport().getPosition().getLatitude(), 1e-6);
assertEquals(12.000000, track.getNewestTrackingReport().getPosition().getLongitude(), 1e-6);
assertEquals(new GregorianCalendar(2014, 02, 11, 12, 33, 00).getTimeInMillis(), track.getTimeOfLastPositionReport(), 1e-10);
}
@Test
public void testPredictLongAndFastNE() {
track.update(new GregorianCalendar(2014, 02, 11, 12, 32, 00).getTimeInMillis(), Position.create(56.00, 12.00), 45.0f, 20.0f, 20.0f);
track.predict(new GregorianCalendar(2014, 02, 11, 12, 42, 00).getTimeInMillis());
assertEquals(56.039237, track.getNewestTrackingReport().getPosition().getLatitude(), 1e-6);
assertEquals(12.070274, track.getNewestTrackingReport().getPosition().getLongitude(), 1e-6);
assertEquals(new GregorianCalendar(2014, 02, 11, 12, 42, 00).getTimeInMillis(), track.getTimeOfLastPositionReport(), 1e-10);
}
@Test
public void testPredictLongAndFastSW() {
track.update(new GregorianCalendar(2014, 02, 11, 12, 32, 00).getTimeInMillis(), Position.create(56.00, 12.00), 180.0f+45.0f, 20.0f, 20.0f);
track.predict(new GregorianCalendar(2014, 02, 11, 12, 42, 00).getTimeInMillis());
assertEquals(55.960722, track.getNewestTrackingReport().getPosition().getLatitude(), 1e-6);
assertEquals(11.929867, track.getNewestTrackingReport().getPosition().getLongitude(), 1e-6);
assertEquals(new GregorianCalendar(2014, 02, 11, 12, 42, 00).getTimeInMillis(), track.getTimeOfLastPositionReport(), 1e-10);
}
@Test
public void testGetTimeOfLastAisTrackingReport() throws Exception {
final String[] NMEA_TEST_STRINGS = {
// GatehouseSourceTag [baseMmsi=2190067, country=DK, region=, timestamp=Thu Apr 10 15:30:28 CEST 2014]
// [msgId=1, repeat=0, userId=219000606, cog=2010, navStatus=0, pos=(33024811,6011092) = (33024811,6011092), posAcc=1, raim=0, specialManIndicator=0, rot=0, sog=108, spare=0, syncState=1, trueHeading=200, utcSec=60, slotTimeout=6, subMessage=1063]
"$PGHP,1,2014,4,10,13,30,28,385,219,,2190067,1,12*26\r\n" +
"!BSVDM,1,1,,A,13@ng7P01dPeo6`OOc:onVAp0p@W,0*12",
// GatehouseSourceTag [baseMmsi=2190067, country=DK, region=, timestamp=Thu Apr 10 15:30:38 CEST 2014]
// [msgId=1, repeat=0, userId=219000606, cog=2010, navStatus=0, pos=(33024530,6010902) = (33024530,6010902), posAcc=1, raim=0, specialManIndicator=0, rot=0, sog=108, spare=0, syncState=1, trueHeading=200, utcSec=60, slotTimeout=2, subMessage=1427]
"$PGHP,1,2014,4,10,13,30,38,88,219,,2190067,1,26*1E\r\n" +
"!BSVDM,1,1,,B,13@ng7P01dPeo0dOOb4WnVAp0`FC,0*26",
// GatehouseSourceTag [baseMmsi=2190075, country=DK, region=, timestamp=Thu Apr 10 15:30:49 CEST 2014]
// [msgId=1, repeat=0, userId=219000606, cog=2010, navStatus=0, pos=(33024198,6010667) = (33024198,6010667), posAcc=1, raim=0, specialManIndicator=0, rot=0, sog=108, spare=0, syncState=1, trueHeading=200, utcSec=60, slotTimeout=4, subMessage=1852]
"$PGHP,1,2014,4,10,13,30,49,429,219,,2190075,1,2D*56\r\n" +
"!BSVDM,1,1,,A,13@ng7P01dPenqFOO`iWnVAp0hLt,0*2D",
// GatehouseSourceTag [baseMmsi=2190067, country=DK, region=, timestamp=Thu Apr 10 15:30:59 CEST 2014]
// [msgId=1, repeat=0, userId=219000606, cog=2010, navStatus=0, pos=(33023918,6010471) = (33023918,6010471), posAcc=1, raim=0, specialManIndicator=0, rot=0, sog=108, spare=0, syncState=1, trueHeading=200, utcSec=60, slotTimeout=1, subMessage=12528]
"$PGHP,1,2014,4,10,13,30,59,428,219,,2190067,1,2D*55\r\n" +
"!BSVDM,1,1,,B,13@ng7P01dPenk>OOWcWnVAp0W3h,0*2D",
// GatehouseSourceTag [baseMmsi=2190067, country=DK, region=, timestamp=Thu Apr 10 15:31:09 CEST 2014]
// [msgId=1, repeat=0, userId=219000606, cog=2020, navStatus=0, pos=(33023639,6010274) = (33023639,6010274), posAcc=1, raim=0, specialManIndicator=0, rot=0, sog=108, spare=0, syncState=1, trueHeading=200, utcSec=60, slotTimeout=2, subMessage=348]
"$PGHP,1,2014,4,10,13,31,9,318,219,,2190067,1,4F*61\r\n" +
"!BSVDM,1,1,,A,13@ng7P01dPene4OOVUoq6Ap0`5L,0*4F",
// GatehouseSourceTag [baseMmsi=2190067, country=DK, region=, timestamp=Thu Apr 10 15:31:18 CEST 2014]
// [msgId=1, repeat=0, userId=219000606, cog=2010, navStatus=0, pos=(33023417,6010117) = (33023417,6010117), posAcc=1, raim=0, specialManIndicator=0, rot=0, sog=108, spare=0, syncState=1, trueHeading=199, utcSec=60, slotTimeout=0, subMessage=2263]
"$PGHP,1,2014,4,10,13,31,18,678,219,,2190067,1,03*23\r\n" +
"!BSVDM,1,1,,B,13@ng7P01dPen`:OOUfGnV?p0PSG,0*03"
};
AisPacket[] packets = new AisPacket[NMEA_TEST_STRINGS.length];
for (int i = 0; i < NMEA_TEST_STRINGS.length; i++) {
packets[i] = AisPacket.from(NMEA_TEST_STRINGS[i]);
}
// ---
// No updates yet
Track track = new Track(219000606);
assertEquals(-1, track.getTimeOfLastAisTrackingReport());
// AIS update
track.update(packets[0]);
assertEquals(LocalDateTime.of(2014, 4, 10, 13, 30, 28, 385).toEpochSecond(ZoneOffset.UTC), track.getTimeOfLastAisTrackingReport() / 1000);
// Predicted update
track.update(packets[0].getBestTimestamp() + 5000, Position.create(55, 11), 22f, 2.4f, 25f);
assertEquals(packets[0].getTimestamp().getTime(), track.getTimeOfLastAisTrackingReport());
// AIS update
track.update(packets[1]);
assertEquals(packets[1].getTimestamp().getTime(), track.getTimeOfLastAisTrackingReport());
// AIS update
track.update(packets[2]);
assertEquals(packets[2].getTimestamp().getTime(), track.getTimeOfLastAisTrackingReport());
// Predicted updates
for (int i = 0; i < 100; i++) {
track.update(packets[2].getBestTimestamp() + i*5000, Position.create(55, 11), 22f, 2.4f, 25f);
assertEquals(packets[2].getTimestamp().getTime(), track.getTimeOfLastAisTrackingReport());
}
}
@Test
public void testClone() throws CloneNotSupportedException {
Track track = new Track(219000606);
track.update(msg5);
track.update(1000000000, Position.create(56, 12), 45.0f, 10.1f, 10.1f);
Track clone = track.clone();
assertNotSame(clone, track);
assertEquals(clone.toString(), track.toString());
assertEquals(clone.getTrackingReports().size(), track.getTrackingReports().size());
assertEquals(clone.getNewestTrackingReport(), track.getNewestTrackingReport());
track.update(1000001000, Position.create(56.1, 12.1), 45.1f, 10.2f, 10.2f);
assertNotEquals(clone.toString(), track.toString());
assertEquals(clone.getTrackingReports().size() + 1, track.getTrackingReports().size());
assertNotEquals(clone.getNewestTrackingReport(), track.getNewestTrackingReport());
}
}