dk.dma.ais.abnormal.analyzer.analysis.CloseEncounterAnalysisTest.java Source code

Java tutorial

Introduction

Here is the source code for dk.dma.ais.abnormal.analyzer.analysis.CloseEncounterAnalysisTest.java

Source

/* Copyright (c) 2011 Danish Maritime Authority
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */
package dk.dma.ais.abnormal.analyzer.analysis;

import dk.dma.ais.abnormal.analyzer.AppStatisticsService;
import dk.dma.ais.abnormal.analyzer.behaviour.EventCertainty;
import dk.dma.ais.abnormal.event.db.EventRepository;
import dk.dma.ais.abnormal.event.db.domain.Behaviour;
import dk.dma.ais.abnormal.event.db.domain.CloseEncounterEvent;
import dk.dma.ais.abnormal.event.db.domain.Event;
import dk.dma.ais.packet.AisPacket;
import dk.dma.ais.test.helpers.ArgumentCaptor;
import dk.dma.ais.tracker.eventEmittingTracker.EventEmittingTracker;
import dk.dma.ais.tracker.eventEmittingTracker.Track;
import dk.dma.enav.model.geometry.CoordinateSystem;
import dk.dma.enav.model.geometry.Position;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.jmock.Expectations;
import org.jmock.integration.junit4.JUnit4Mockery;
import org.junit.Before;
import org.junit.Test;

import java.util.HashSet;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class CloseEncounterAnalysisTest {

    JUnit4Mockery context;
    CloseEncounterAnalysis analysis;
    EventEmittingTracker trackingService;
    AppStatisticsService statisticsService;
    EventRepository eventRepository;

    Track track, closeTrack, distantTrack, oldNearbyTrack, newNearbyTrack, distantNearbyTrack;
    Set<Track> tracks;

    int maxTimestampDeviationMillis = 60 * 1000;
    int maxDistanceDeviationMeters = 1852;

    // 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]
    final AisPacket vessel1StaticPacket = 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");

    // GatehouseSourceTag [baseMmsi=2190074, country=DK, region=, timestamp=Tue Nov 12 13:04:58 CET 2013]
    // [msgId=5, repeat=0, userId=219002827, callsign=5QRJ   , dest=SKAGEN              , dimBow=2, dimPort=2, dimStarboard=3, dimStern=13, draught=28, dte=0, eta=576864, imo=0, name=MIE MALENE          , posType=1, shipType=30, spare=0, version=0]
    final AisPacket vessel2StaticPacket = AisPacket.from("$PGHP,1,2013,11,12,12,4,58,279,219,,2190074,1,54*24\r\n"
            + "!BSVDM,2,1,0,B,53@nojh00003E58b220lTF0l4hDpF2222222220N0@=236<mP74jhAiC,0*32\r\n"
            + "!BSVDM,2,2,0,B,`88888888888880,2*66");

    @Before
    public void setUp() throws Exception {
        context = new JUnit4Mockery();
        trackingService = context.mock(EventEmittingTracker.class);
        statisticsService = context.mock(AppStatisticsService.class);
        eventRepository = context.mock(EventRepository.class);
        analysis = new CloseEncounterAnalysis(new PropertiesConfiguration(), statisticsService, trackingService,
                eventRepository);

        long timestamp = System.currentTimeMillis();
        long tooOld = timestamp - maxTimestampDeviationMillis - 1;
        long old = timestamp - maxTimestampDeviationMillis + 1;
        long tooNew = timestamp + maxTimestampDeviationMillis + 1;
        long nyw = timestamp + maxTimestampDeviationMillis - 1;

        Position position = Position.create(56, 12);
        Position tooFarAway = Position.create(56.1, 12.1);
        assertTrue(position.distanceTo(tooFarAway, CoordinateSystem.CARTESIAN) > maxDistanceDeviationMeters);
        Position farAway = Position.create(56.014, 12.014);
        assertTrue(position.distanceTo(farAway, CoordinateSystem.CARTESIAN) < maxDistanceDeviationMeters);

        track = new Track(219000606);
        track.update(vessel1StaticPacket);
        track.update(timestamp, position, 90.0f, 10.0f, 90.0f);

        closeTrack = new Track(219002827);
        closeTrack.update(vessel2StaticPacket);
        closeTrack.update(timestamp - 40000, Position.create(56.1000, 12.0010), 180.0f, 10.0f, 180.0f);
        closeTrack.update(timestamp - 30000, Position.create(56.0800, 12.0010), 180.0f, 10.0f, 180.0f);
        closeTrack.update(timestamp - 20000, Position.create(56.0600, 12.0010), 180.0f, 10.0f, 180.0f);
        closeTrack.update(timestamp - 10000, Position.create(56.0400, 12.0010), 180.0f, 10.0f, 180.0f);
        closeTrack.update(timestamp, Position.create(56.00001, 12.0000), 180.0f, 10.0f, 180.0f);
        closeTrack.getTrackingReports().forEach(tr -> {
            tr.setProperty("event-certainty-CloseEncounterEvent", EventCertainty.LOWERED);
        });
        assertTrue(closeTrack.getPosition().equals(Position.create(56.00001, 12.0000)));
        assertTrue(track.getPosition().distanceTo(closeTrack.getPosition(), CoordinateSystem.CARTESIAN) < 200);

        distantTrack = new Track(219000606);
        distantTrack.update(vessel1StaticPacket);
        distantTrack.update(timestamp, Position.create(57, 13), 90.0f, 10.0f, 90.0f);

        Track track1 = new Track(1);
        track1.update(tooOld, position, 90.0f, 10.0f, 90.0f);

        oldNearbyTrack = new Track(2);
        oldNearbyTrack.update(old, position, 90.0f, 10.0f, 90.0f);

        Track track3 = new Track(3);
        track3.update(tooNew, position, 90.0f, 10.0f, 90.0f);

        newNearbyTrack = new Track(3);
        newNearbyTrack.update(nyw, position, 90.0f, 10.0f, 90.0f);

        Track track4 = new Track(4);
        track4.update(timestamp, tooFarAway, 90.0f, 10.0f, 90.0f);

        distantNearbyTrack = new Track(5);
        distantNearbyTrack.update(timestamp, farAway, 90.0f, 10.0f, 90.0f);

        tracks = new HashSet<>();
        tracks.add(track);
        tracks.add(track1);
        tracks.add(oldNearbyTrack);
        tracks.add(track3);
        tracks.add(track4);
        tracks.add(distantNearbyTrack);
        tracks.add(newNearbyTrack);
    }

    @Test
    public void testFindNearByTracks() throws Exception {
        Set<Track> nearByTracks = analysis.findNearByTracks(tracks, track, maxTimestampDeviationMillis,
                maxDistanceDeviationMeters);

        assertEquals(3, nearByTracks.size());
        assertTrue(nearByTracks.contains(oldNearbyTrack));
        assertTrue(nearByTracks.contains(newNearbyTrack));
        assertTrue(nearByTracks.contains(distantNearbyTrack));
    }

    @Test
    public void testIsTrackPairAnalyzed() throws Exception {
        analysis.clearTrackPairsAnalyzed();
        assertFalse(analysis.isTrackPairAnalyzed(track, track));
        assertFalse(analysis.isTrackPairAnalyzed(track, distantNearbyTrack));
        assertFalse(analysis.isTrackPairAnalyzed(newNearbyTrack, distantNearbyTrack));
        assertFalse(analysis.isTrackPairAnalyzed(track, oldNearbyTrack));
        assertFalse(analysis.isTrackPairAnalyzed(track, newNearbyTrack));

        analysis.markTrackPairAnalyzed(track, distantNearbyTrack);
        assertFalse(analysis.isTrackPairAnalyzed(track, track));
        assertTrue(analysis.isTrackPairAnalyzed(track, distantNearbyTrack));
        assertFalse(analysis.isTrackPairAnalyzed(newNearbyTrack, distantNearbyTrack));
        assertFalse(analysis.isTrackPairAnalyzed(track, oldNearbyTrack));
        assertFalse(analysis.isTrackPairAnalyzed(track, newNearbyTrack));

        analysis.markTrackPairAnalyzed(newNearbyTrack, distantNearbyTrack);
        assertFalse(analysis.isTrackPairAnalyzed(track, track));
        assertTrue(analysis.isTrackPairAnalyzed(track, distantNearbyTrack));
        assertTrue(analysis.isTrackPairAnalyzed(newNearbyTrack, distantNearbyTrack));
        assertFalse(analysis.isTrackPairAnalyzed(track, oldNearbyTrack));
        assertFalse(analysis.isTrackPairAnalyzed(track, newNearbyTrack));
    }

    @Test
    public void closeEncounterCausesEventRaised() throws Exception {
        analysis.clearTrackPairsAnalyzed();
        context.checking(new Expectations() {
            {
                ignoring(statisticsService).incAnalysisStatistics(
                        with(CloseEncounterAnalysis.class.getSimpleName()), with(any(String.class)));
                ignoring(statisticsService).setAnalysisStatistics(
                        with(CloseEncounterAnalysis.class.getSimpleName()), with(any(String.class)),
                        with(any(Long.class)));
                oneOf(eventRepository).findOngoingEventByVessel(track.getMmsi(), CloseEncounterEvent.class);
                oneOf(eventRepository).save(with(any(Event.class)));
            }
        });
        analysis.analyseCloseEncounter(track, closeTrack);
    }

    @Test
    public void noCloseEncounterCausesNoEventRaised() throws Exception {
        analysis.clearTrackPairsAnalyzed();
        context.checking(new Expectations() {
            {
                ignoring(statisticsService).incAnalysisStatistics(
                        with(CloseEncounterAnalysis.class.getSimpleName()), with(any(String.class)));
                ignoring(statisticsService).setAnalysisStatistics(
                        with(CloseEncounterAnalysis.class.getSimpleName()), with(any(String.class)),
                        with(any(Long.class)));
                oneOf(eventRepository).findOngoingEventByVessel(track.getMmsi(), CloseEncounterEvent.class);
                never(eventRepository).save(with(any(Event.class)));
            }
        });
        analysis.analyseCloseEncounter(track, distantTrack);
    }

    @Test
    public void closeEncounterEventContainsTwoVesselBehaviours() throws Exception {
        analysis.clearTrackPairsAnalyzed();

        final ArgumentCaptor<Event> eventCaptor = ArgumentCaptor.forClass(Event.class);

        context.checking(new Expectations() {
            {
                ignoring(statisticsService).incAnalysisStatistics(
                        with(CloseEncounterAnalysis.class.getSimpleName()), with(any(String.class)));
                ignoring(statisticsService).setAnalysisStatistics(
                        with(CloseEncounterAnalysis.class.getSimpleName()), with(any(String.class)),
                        with(any(Long.class)));
                oneOf(eventRepository).findOngoingEventByVessel(track.getMmsi(), CloseEncounterEvent.class);
                oneOf(eventRepository).save(with(eventCaptor.getMatcher()));
            }
        });

        analysis.analyseCloseEncounter(track, closeTrack);

        Event event = eventCaptor.getCapturedObject();
        Set<Behaviour> behaviours = event.getBehaviours();
        assertEquals(2, behaviours.size());
        assertEquals(1, behaviours.stream().filter(t -> t.getVessel().getMmsi() == track.getMmsi()).count());
        assertEquals(1, behaviours.stream().filter(t -> t.getVessel().getMmsi() == closeTrack.getMmsi()).count());

        behaviours.forEach(b -> {
            if (b.getVessel().getMmsi() == track.getMmsi()) {
                assertEquals(1, b.getTrackingPoints().size()); // No. of previous tracking points in event
            } else if (b.getVessel().getMmsi() == closeTrack.getMmsi()) {
                assertEquals(5, b.getTrackingPoints().size()); // No. of previous tracking points in event
            }
        });
    }

}