# Диаграмма классов AIS Map Application (Обновленная архитектура) ```mermaid classDiagram %% Основные Activity и UI компоненты class MainActivity { -AppCoordinator appCoordinator -MapController mapController -CompassController compassController -UIRenderingCoordinator uiCoordinator -MapView mapView -SettingsManager settingsManager -CompassView compassView -CoordinatesDockWidget coordinatesWidget +onCreate() +onResume() +onPause() +onDestroy() } class AisTargetsActivity { -AisTargetsAdapter adapter -List~AISVessel~ aisVessels +onCreate() +updateAISList() } class SettingsActivity { -SettingsManager settingsManager +onCreate() +saveSettings() } %% Главный координатор приложения (новая архитектура) class AppCoordinator { -Context context -NMEAController nmeaController -NetworkController networkController -DataController dataController -NotificationController notificationController -CompassController compassController -MapController mapController -Vessel ownVessel -List~AISVessel~ aisVessels -Map~String, VesselPathController~ aisPathControllers -SettingsManager settingsManager -VesselPathController pathController -UIDataChangeNotifier uiDataNotifier -Handler uiHandler -AppCoordinatorListener listener +initializeControllers() +startServices() +stopServices() +onVesselUpdated() +onAISVesselUpdated() +onDOPUpdated() +onDataReceived() +onNotificationShown() +onCompassChanged() } %% Специализированные контроллеры (новая архитектура) class NMEAController { -Context context -NMEAParser nmeaParser -AndroidNMEAListener androidNmeaListener -GPSLocationListener gpsLocationListener -ExecutorService executor -NMEAControllerListener listener +startAndroidNMEAListener() +stopAndroidNMEAListener() +startGPSLocationListener() +stopGPSLocationListener() +parseNMEAData() +onVesselUpdated() +onAISVesselUpdated() +onDOPUpdated() } class NetworkController { -Context context -UDPListener udpListener -ExecutorService executor -int udpPort -boolean isUDPEnabled -boolean isUDPNMEAEnabled -NetworkControllerListener listener +setUDPEnabled() +startUDPListener() +stopUDPListener() +onDataReceived() +onUDPError() } class DataController { -Context context -Repository repository -SettingsManager settingsManager -ExecutorService executor -Handler dbCleanupHandler -Runnable dbCleanupRunnable -DataControllerListener listener +restoreDataAsync() +saveVesselData() +saveAISData() +performDatabaseCleanup() +onDataRestored() +onDataSaved() +onDataCleaned() } class NotificationController { -Context context -NotificationService notificationService -NotificationControllerListener listener +notifyNewAISTarget() +notifySafetyMessage() +notifyGPSStatus() +onNotificationShown() +onNotificationError() } class CompassController { -Context context -CompassSensor compassSensor -Handler uiHandler -CompassControllerListener listener +startCompass() +stopCompass() +isCompassAvailable() +isCompassActive() +getCompassStatus() +onCompassChanged() +onCompassError() } %% Контроллеры class MapController { -Context context -MapInterface currentMapInterface -MapView mapView -org.maplibre.android.maps.MapView mapLibreView -List~MapInterfaceChangeListener~ listeners +addMapInterfaceChangeListener() +removeMapInterfaceChangeListener() +switchToYandexMaps() +switchToMapLibre() +getCurrentMapInterface() } class NMEAParser { -Vessel ownVessel -List~AISVessel~ aisVessels -NMEAParserListener listener -GPSLocationListener gpsLocationListener -Map~String, Map~Integer, String~~ aisFragments -boolean hybridMode +parseNMEA() +setHybridMode() +setGPSLocationListener() } class UDPListener { -int port -DatagramSocket socket -ExecutorService executor -AtomicBoolean isRunning -UDPListenerCallback callback +start() +stop() +setCallback() } class AndroidNMEAListener { -LocationManager locationManager -NMEAMessageCallback callback -boolean isListening +startListening() +stopListening() +setCallback() } class GPSLocationListener { -Context context -LocationManager locationManager -LocationCallback callback -boolean isListening -int satelliteCount -int activeSatellites -double pdop -double hdop -double vdop +startListening() +stopListening() +setCallback() } class VesselPathController { -Context context -SettingsManager settingsManager -SharedPreferences prefs -String vesselId -Handler uiHandler -List~VesselPathPoint~ pathPoints -VesselPathPoint lastPoint +addPathPoint() +getPathPoints() +clearPath() +savePath() +loadPath() } %% Интерфейсы карт class MapInterface { <> +initialize() +cleanup() +addOwnVesselMarker() +updateOwnVesselPosition() +addAISVesselMarker() +updateAISVesselPosition() +removeAISVesselMarker() +clearAISVesselMarkers() +centerOnPosition() +setZoom() +getZoom() +setBearing() +getBearing() +addLayer() +removeLayer() +setMarkerClickListener() +clearVesselPath() +showCursor() +hideCursor() +updateCursorCoordinates() +updateCursorFromMapCenter() +setAisVesselInfo() +clearAisVesselInfo() } class MapInterfaceChangeListener { <> +onMapInterfaceChanged() } class MarkerClickListener { <> +onOwnVesselClick() +onAISVesselClick() } %% Реализации карт class YandexMapImpl { -Context context -MapView mapView -MapObjectCollection mapObjects -MarkerClickListener markerClickListener -YandexMarkerManager markerManager -CursorOverlay cursorOverlay -Vessel ownVessel +initialize() +cleanup() +addOwnVesselMarker() +updateOwnVesselPosition() +addAISVesselMarker() +updateAISVesselPosition() +removeAISVesselMarker() +clearAISVesselMarkers() +centerOnPosition() +setZoom() +getZoom() +setBearing() +getBearing() } class MapLibreMapImpl { -Context context -MapView mapView -MapLibreMap mapLibreMap -MarkerClickListener markerClickListener -CursorOverlay cursorOverlay -Vessel ownVessel -Map~String, AISVessel~ aisVessels +initialize() +cleanup() +addOwnVesselMarker() +updateOwnVesselPosition() +addAISVesselMarker() +updateAISVesselPosition() +removeAISVesselMarker() +clearAISVesselMarkers() +centerOnPosition() +setZoom() +getZoom() +setBearing() +getBearing() } %% Менеджеры маркеров class YandexMarkerManager { -MapObjectCollection mapObjects -Map~String, YandexMarkerWrapper~ ownVesselMarkers -Map~String, YandexMarkerWrapper~ aisVesselMarkers +addOwnVesselMarker() +updateOwnVesselMarker() +addAISVesselMarker() +updateAISVesselMarker() +removeAISVesselMarker() +clearAllMarkers() } class MarkerManager { -MapLibreMap mapLibreMap -Map~String, MarkerWrapper~ ownVesselMarkers -Map~String, MarkerWrapper~ aisVesselMarkers +addOwnVesselMarker() +updateOwnVesselMarker() +addAISVesselMarker() +updateAISVesselMarker() +removeAISVesselMarker() +clearAllMarkers() } %% Модели данных class Vessel { -double latitude -double longitude -double course -double speed -double heading -double magneticCompass -int signalStrength -LocalDateTime lastUpdate -String vesselName -String mmsi -String callSign -double altitude -int satellites -int activeSatellites -double pdop -double hdop -double vdop -float accuracy -long fixTime -String fixQuality +updatePosition() +updateGPSQuality() +getGPSQualityPercentage() +getGPSQualityDescription() } class AISVessel { -String mmsi -String vesselName -String callSign -int imo -String vesselType -double latitude -double longitude -double course -double speed -double heading -double rateOfTurn -double length -double width -double draft -String destination -LocalDateTime eta -LocalDateTime lastUpdate -int signalStrength -boolean isActive -String navigationalStatus -String lastSafetyMessage -boolean positionAccuracy -String vesselClass -String vendorId -boolean selected +updatePosition() +isDataStale() +shouldBeRemoved() +getMinutesSinceLastUpdate() } class VesselPathPoint { -double latitude -double longitude -double course -double speed -long timestamp +VesselPathPoint() +toJSON() +fromJSON() } %% База данных и репозиторий class AppDatabase { <> +aisVesselDao() AISVesselDao +vesselDao() VesselDao +getInstance() AppDatabase } class Repository { -AISVesselDao aisVesselDao -VesselDao vesselDao -ExecutorService ioExecutor +upsertAIS() +deleteStaleAIS() +getAllAISSync() +observeAllAIS() +getAISByMmsiSync() +upsertOwnVessel() +getLatestOwnVesselSync() +getLatestOwnVesselAsync() } class AISVesselDao { <> +upsert() +deleteStale() +getAll() +observeAll() +getByMmsi() } class VesselDao { <> +upsert() +getLatest() } class AISVesselEntity { -String mmsi -String vesselName -String callSign -int imo -String vesselType -double latitude -double longitude -double course -double speed -double heading -double rateOfTurn -double length -double width -double draft -String destination -long etaEpochMs -long lastUpdateEpochMs -int signalStrength -boolean isActive -String navigationalStatus -String lastSafetyMessage -boolean positionAccuracy -String vesselClass -String vendorId } class VesselEntity { -double latitude -double longitude -double course -double speed -double heading -double magneticCompass -int signalStrength -long lastUpdateEpochMs -String vesselName -String mmsi -String callSign -double altitude -int satellites -int activeSatellites -double pdop -double hdop -double vdop -float accuracy -long fixTime -String fixQuality } %% UI компоненты class UIRenderingCoordinator { -MapInterface mapInterface -Handler uiHandler -Vessel pendingVesselUpdate -Map~String, AISVessel~ pendingAISUpdates -Set~String~ pendingAISRemovals -Runnable vesselUpdateRunnable -Runnable aisUpdateRunnable -Runnable pathUpdateRunnable -boolean vesselUpdatePending -boolean aisUpdatePending -boolean pathUpdatePending +requestVesselUpdate() +requestAISUpdate() +requestAISRemoval() +flushPendingOperations() +cleanup() } class UIDataChangeNotifier { <> +onVesselPositionChanged() +onGPSQualityChanged() +onAISVesselChanged() +onAISVesselRemoved() +onVesselPathChanged() +onRequestCenterMap() +onCompassUpdate() } class CompassView { -float azimuth -Paint compassPaint -Paint needlePaint -Paint textPaint -List~AISVessel~ nearbyVessels +setAzimuth() +setNearbyVessels() +onDraw() } class CompassSensor { -SensorManager sensorManager -Sensor magnetometer -Sensor accelerometer -CompassCallback callback -float[] lastAccelerometer -float[] lastMagnetometer -boolean lastAccelerometerSet -boolean lastMagnetometerSet -float[] rotationMatrix -float[] orientation +startListening() +stopListening() +setCallback() } class CoordinatesDockWidget { -TextView latitudeText -TextView longitudeText -TextView accuracyText -TextView satellitesText -TextView qualityText +updateCoordinates() +updateGPSQuality() } class CursorOverlay { -ViewGroup parentView -TextView coordinatesText -TextView vesselInfoText -boolean isVisible +show() +hide() +updateCoordinates() +setVesselInfo() +clearVesselInfo() } %% Сервисы class NotificationService { -Context context -SettingsManager settingsManager -Vibrator vibrator -ToneGenerator toneGenerator -boolean isInitialized +showSafetyAlert() +showNewVesselNotification() +clearNotifications() +setVibrationEnabled() +setSoundEnabled() } class AISForegroundService { -Context context -AppController appController -NotificationManager notificationManager -boolean isRunning +startForeground() +stopForeground() +onStartCommand() +onDestroy() } %% Утилиты class SettingsManager { -Context context -SharedPreferences prefs +getUDPPort() +setUDPPort() +isUDPEnabled() +setUDPEnabled() +isAndroidNMEAEnabled() +setAndroidNMEAEnabled() +isUDPNMEAEnabled() +setUDPNMEAEnabled() +getDataMode() +setDataMode() +getDataStaleWarningMinutes() +setDataStaleWarningMinutes() +getDataStaleRemoveMinutes() +setDataStaleRemoveMinutes() +isPathTrackingEnabled() +setPathTrackingEnabled() +getPathColor() +setPathColor() +getPredictionColor() +setPredictionColor() +getPathWidth() +setPathWidth() +getPredictionWidth() +setPredictionWidth() +getPathMaxPoints() +setPathMaxPoints() +getPredictionHorizonSec() +setPredictionHorizonSec() +isVibrationEnabled() +setVibrationEnabled() +isSoundEnabled() +setSoundEnabled() +isKeepScreenOnEnabled() +setKeepScreenOnEnabled() +isCursorEnabled() +setCursorEnabled() } class GeoUtils { <> +calculateDistance() +calculateBearing() +isValidCoordinate() +formatCoordinate() +convertToDecimalDegrees() } class LogSender { <> +sendLog() +sendError() +sendWarning() +sendInfo() } class MIDToCountry { <> +getCountryByMID() +getCountryName() +isValidMID() } class NavigationUtils { <> +calculateCourse() +calculateSpeed() +calculateETA() +isCollisionRisk() } %% Связи между классами (новая архитектура) MainActivity --> AppCoordinator : uses MainActivity --> MapController : uses MainActivity --> CompassController : uses MainActivity --> UIRenderingCoordinator : uses MainActivity --> CompassView : uses MainActivity --> CoordinatesDockWidget : uses AppCoordinator --> NMEAController : coordinates AppCoordinator --> NetworkController : coordinates AppCoordinator --> DataController : coordinates AppCoordinator --> NotificationController : coordinates AppCoordinator --> CompassController : coordinates AppCoordinator --> MapController : coordinates AppCoordinator --> VesselPathController : uses AppCoordinator --> SettingsManager : uses AppCoordinator --> UIRenderingCoordinator : uses NMEAController --> NMEAParser : uses NMEAController --> AndroidNMEAListener : uses NMEAController --> GPSLocationListener : uses NetworkController --> UDPListener : uses DataController --> Repository : uses DataController --> SettingsManager : uses NotificationController --> NotificationService : uses CompassController --> CompassSensor : uses MapController --> MapInterface : manages MapController --> YandexMapImpl : creates MapController --> MapLibreMapImpl : creates MapController --> MapInterfaceChangeListener : notifies YandexMapImpl ..|> MapInterface : implements MapLibreMapImpl ..|> MapInterface : implements AppController ..|> MapInterfaceChangeListener : implements AppController ..|> MarkerClickListener : implements YandexMapImpl --> YandexMarkerManager : uses MapLibreMapImpl --> MarkerManager : uses Repository --> AppDatabase : uses Repository --> AISVesselDao : uses Repository --> VesselDao : uses AppDatabase --> AISVesselEntity : contains AppDatabase --> VesselEntity : contains UIRenderingCoordinator ..|> UIDataChangeNotifier : implements UIRenderingCoordinator ..|> MapInterfaceChangeListener : implements NMEAParser --> Vessel : creates/updates NMEAParser --> AISVessel : creates/updates NMEAParser --> GPSLocationListener : uses VesselPathController --> VesselPathPoint : manages VesselPathController --> SettingsManager : uses NotificationService --> SettingsManager : uses CompassSensor --> CompassView : updates CompassView --> AISVessel : displays %% Интерфейсы и их реализации (новая архитектура) AppCoordinator ..|> NMEAControllerListener : implements AppCoordinator ..|> NetworkControllerListener : implements AppCoordinator ..|> DataControllerListener : implements AppCoordinator ..|> NotificationControllerListener : implements AppCoordinator ..|> CompassControllerListener : implements AppCoordinator ..|> MarkerClickListener : implements AppCoordinator ..|> MapInterfaceChangeListener : implements NMEAController ..|> NMEAParserListener : implements NMEAController ..|> NMEAMessageCallback : implements NetworkController ..|> UDPListenerCallback : implements CompassController ..|> CompassListener : implements NMEAParser ..|> NMEAParserListener : implements UDPListener ..|> UDPListenerCallback : implements AndroidNMEAListener ..|> NMEAMessageCallback : implements GPSLocationListener ..|> LocationCallback : implements CompassSensor ..|> CompassListener : implements ``` ## Описание обновленной архитектуры ### Основные компоненты: 1. **MainActivity** - главная активность приложения, координирует UI компоненты 2. **AppCoordinator** - главный координатор, управляет всеми специализированными контроллерами 3. **NMEAController** - специализированный контроллер для обработки NMEA сообщений 4. **NetworkController** - контроллер для сетевых операций (UDP) 5. **DataController** - контроллер для операций с базой данных 6. **NotificationController** - контроллер для управления уведомлениями 7. **CompassController** - контроллер для управления магнитным компасом 8. **MapController** - управляет переключением между различными реализациями карт 9. **UIRenderingCoordinator** - координирует обновления UI с throttling 10. **VesselPathController** - управляет путями судов ### Новая архитектура - Разделение ответственности: #### **AppCoordinator** (Главный координатор): - Координирует работу всех специализированных контроллеров - Управляет общим состоянием приложения - Обрабатывает события от контроллеров и передает их в UI #### **Специализированные контроллеры**: - **NMEAController** - только парсинг и обработка NMEA данных - **NetworkController** - только сетевые операции (UDP слушание) - **DataController** - только операции с базой данных - **NotificationController** - только показ уведомлений - **CompassController** - только работа с магнитным компасом ### Паттерны архитектуры: - **Coordinator Pattern** - AppCoordinator координирует работу контроллеров - **Single Responsibility Principle** - каждый контроллер отвечает за одну область - **Strategy Pattern** - для переключения между различными реализациями карт - **Observer Pattern** - для уведомлений об изменениях данных - **Repository Pattern** - для работы с данными - **Command Pattern** - для отложенного выполнения UI операций ### Преимущества новой архитектуры: 1. **Разделение ответственности** - каждый контроллер отвечает за свою область 2. **Лучшая тестируемость** - контроллеры можно тестировать независимо 3. **Упрощенная поддержка** - изменения в одной области не влияют на другие 4. **Масштабируемость** - легко добавлять новые контроллеры 5. **Чистая архитектура** - четкое разделение между слоями ### Особенности: - Гибридный режим получения GPS данных (через Location API + NMEA) - Throttling UI обновлений для производительности - Поддержка множественных источников данных (UDP, Android NMEA, GPS) - Модульная архитектура с возможностью переключения карт - Система уведомлений с вибрацией и звуком - Централизованная координация через AppCoordinator