/* 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.stat.statistics; import com.google.common.eventbus.AllowConcurrentEvents; import com.google.common.eventbus.Subscribe; import com.google.inject.Inject; import dk.dma.ais.abnormal.stat.AppStatisticsService; import dk.dma.ais.abnormal.stat.db.StatisticDataRepository; import dk.dma.ais.abnormal.stat.db.data.CourseOverGroundStatisticData; import dk.dma.ais.abnormal.stat.db.data.ShipTypeAndSizeStatisticData; import dk.dma.ais.abnormal.stat.db.data.StatisticData; import dk.dma.ais.abnormal.util.Categorizer; import dk.dma.ais.tracker.eventEmittingTracker.EventEmittingTracker; import dk.dma.ais.tracker.eventEmittingTracker.Track; import dk.dma.ais.tracker.eventEmittingTracker.events.CellChangedEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.concurrent.atomic.AtomicBoolean; public class CourseOverGroundStatistic implements TrackingEventListener { /** * The logger */ private static final transient Logger LOG = LoggerFactory.getLogger(CourseOverGroundStatistic.class); private final transient AppStatisticsService appStatisticsService; private final transient StatisticDataRepository statisticsRepository; private final transient EventEmittingTracker trackingService; private final transient AtomicBoolean started = new AtomicBoolean(false); static final String STATISTIC_NAME = CourseOverGroundStatistic.class.getSimpleName(); @Inject public CourseOverGroundStatistic(AppStatisticsService appStatisticsService, EventEmittingTracker trackingService, StatisticDataRepository statisticsRepository) { this.appStatisticsService = appStatisticsService; this.trackingService = trackingService; this.statisticsRepository = statisticsRepository; } /** * Start listening to tracking events. */ public void start() { if (!started.get()) { trackingService.registerSubscriber(this); started.getAndSet(true); } } /* * This statistic is only updated once per cell; i.e. when a cell is entered. */ @AllowConcurrentEvents @Subscribe public void onCellIdChanged(CellChangedEvent event) { appStatisticsService.incStatisticStatistics(STATISTIC_NAME, "Events processed"); Track track = event.getTrack(); Float sog = track.getSpeedOverGround(); if (sog != null && sog >= 2.0) { Long cellId = (Long) track.getProperty(Track.CELL_ID); Integer shipType = track.getShipType(); Integer shipLength = track.getVesselLength(); Float cog = track.getCourseOverGround(); if (isInputValid(cellId, shipType, shipLength, cog)) { short shipTypeBucket = Categorizer.mapShipTypeToCategory(shipType); short shipSizeBucket = Categorizer.mapShipLengthToCategory(shipLength); short cogBucket = Categorizer.mapCourseOverGroundToCategory(cog); incrementStatisticStatistics(cellId, shipTypeBucket, shipSizeBucket, cogBucket); appStatisticsService.incStatisticStatistics(this.getClass().getSimpleName(), "Events processed ok"); } } } private boolean isInputValid(Long cellId, Integer shipType, Integer shipLength, Float cog) { boolean valid = true; if (cellId == null) { appStatisticsService.incStatisticStatistics(STATISTIC_NAME, "Unknown mmsi"); valid = false; } if (shipType == null) { appStatisticsService.incStatisticStatistics(STATISTIC_NAME, "Unknown ship type"); valid = false; } if (shipLength == null) { appStatisticsService.incStatisticStatistics(STATISTIC_NAME, "Unknown ship length"); valid = false; } if (cog == null) { appStatisticsService.incStatisticStatistics(STATISTIC_NAME, "Unknown course over ground"); valid = false; } return valid; } private void incrementStatisticStatistics(long cellId, int shipTypeBucket, int shipSizeBucket, int cogBucket) { StatisticData statisticsTmp = statisticsRepository.getStatisticData(STATISTIC_NAME, cellId); if (!(statisticsTmp instanceof CourseOverGroundStatisticData)) { LOG.debug("No suitable statistic data for cell id " + cellId + " found in repo. Creating new."); statisticsTmp = CourseOverGroundStatisticData.create(); } CourseOverGroundStatisticData statistics = (CourseOverGroundStatisticData) statisticsTmp; // Increment ship count statistics.incrementValue(shipTypeBucket-1, shipSizeBucket-1, cogBucket-1, ShipTypeAndSizeStatisticData.STAT_SHIP_COUNT); LOG.debug("Storing statistic data for cellId " + cellId + ", statisticName " + STATISTIC_NAME); statisticsRepository.putStatisticData(STATISTIC_NAME, cellId, statistics); LOG.debug("TrackingEventListener data for cellId " + cellId + ", statisticName " + STATISTIC_NAME + " stored."); } }