# Диаграмма классов AIS Map Application (Финальная архитектура) ```mermaid classDiagram %% Основные Activity и UI компоненты class MainActivity { -AppCoordinator appCoordinator -MenuBinder menuBinder -BottomSheetsBinder bottomSheetsBinder -PermissionsBinder permissionsBinder -MapController mapController -CompassController compassController -UIRenderingCoordinator uiCoordinator -MapView mapView -SettingsManager settingsManager -CompassView compassView -CoordinatesDockWidget coordinatesWidget -BottomSheetsManager bottomSheetsManager +onCreate() +onResume() +onPause() +onDestroy() +onCreateOptionsMenu() +onOptionsItemSelected() } 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() +isAndroidNMEAEnabled() +isUDPEnabled() } %% Фабрика контроллеров class ControllersFactory { <> +createAppCoordinator() AppCoordinator } class DefaultControllersFactory { +createAppCoordinator() AppCoordinator } %% Специализированные контроллеры 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() } %% UI Binders (новая архитектура) class MenuBinder { -AppCoordinator appCoordinator -SettingsManager settingsManager -MenuActions actions +onCreateOptionsMenu() +onPrepareOptionsMenu() +onOptionsItemSelected() } class BottomSheetsBinder { -Context context -BottomSheetDialog ownVesselBottomSheet -BottomSheetDialog aisVesselBottomSheet -View ownBottomSheetView -View aisBottomSheetView -AISVessel currentAISVessel -Handler updateHandler -Runnable updateRunnable +init() +initAIS() +showOwnVesselSheet() +showAISVesselSheet() +startAutoUpdate() +stopAutoUpdate() } class BottomSheetsManager { -Context context -AppCoordinator appCoordinator -BottomSheetDialog ownVesselBottomSheet -BottomSheetDialog aisVesselBottomSheet -View bottomSheetView -View aisBottomSheetView -AISVessel currentAISVessel -Handler timeUpdateHandler -Handler bottomSheetUpdateHandler +init() +showOwnVesselSheet() +showAISVesselSheet() +updateOwnVesselUI() +updateAISBottomSheetUI() +stopAutoUpdate() } class PermissionsBinder { -Activity activity +ensurePermission() +handleOnRequestPermissionsResult() } %% Базовые компоненты 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 MapForgeImpl { -Context context -MapView mapView -MarkerClickListener markerClickListener -CursorOverlay cursorOverlay -Vessel ownVessel +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 -CompassListener 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 -AppCoordinator appCoordinator -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 --> MenuBinder : uses MainActivity --> BottomSheetsBinder : uses MainActivity --> PermissionsBinder : uses MainActivity --> MapController : uses MainActivity --> CompassController : uses MainActivity --> UIRenderingCoordinator : uses MainActivity --> CompassView : uses MainActivity --> CoordinatesDockWidget : uses MainActivity --> BottomSheetsManager : uses %% Фабрика контроллеров ControllersFactory <|.. DefaultControllersFactory : implements MainActivity --> ControllersFactory : uses DefaultControllersFactory --> AppCoordinator : creates %% AppCoordinator координирует все контроллеры 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 %% UI Binders MenuBinder --> AppCoordinator : uses MenuBinder --> SettingsManager : uses BottomSheetsBinder --> Context : uses BottomSheetsManager --> AppCoordinator : uses PermissionsBinder --> Activity : uses %% Карты MapController --> MapInterface : manages MapController --> YandexMapImpl : creates MapController --> MapLibreMapImpl : creates MapController --> MapForgeImpl : creates MapController --> MapInterfaceChangeListener : notifies YandexMapImpl ..|> MapInterface : implements MapLibreMapImpl ..|> MapInterface : implements MapForgeImpl ..|> MapInterface : implements YandexMapImpl --> YandexMarkerManager : uses MapLibreMapImpl --> MarkerManager : uses %% База данных Repository --> AppDatabase : uses Repository --> AISVesselDao : uses Repository --> VesselDao : uses AppDatabase --> AISVesselEntity : contains AppDatabase --> VesselEntity : contains %% UI координация 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. Разделение ответственности (Single Responsibility Principle)** - Каждый контроллер отвечает за одну конкретную область функциональности - UI компоненты разделены на специализированные Binder'ы - Четкое разделение между слоями данных, бизнес-логики и представления #### **2. Координаторный паттерн (Coordinator Pattern)** - **AppCoordinator** - центральный координатор всех контроллеров - Управляет жизненным циклом и взаимодействием между компонентами - Единая точка входа для всех событий и состояний #### **3. Фабричный паттерн (Factory Pattern)** - **ControllersFactory** - интерфейс для создания контроллеров - **DefaultControllersFactory** - базовая реализация фабрики - Позволяет легко тестировать и заменять компоненты ### 📦 **Специализированные контроллеры:** 1. **NMEAController** - парсинг и обработка NMEA сообщений 2. **NetworkController** - UDP слушание и сетевые операции 3. **DataController** - операции с базой данных 4. **NotificationController** - управление уведомлениями 5. **CompassController** - управление магнитным компасом 6. **MapController** - управление картами и переключение между ними ### 🎨 **UI Binders (новая архитектура):** 1. **MenuBinder** - управление меню и обработка действий 2. **BottomSheetsBinder** - базовое управление BottomSheet'ами 3. **BottomSheetsManager** - полное управление BottomSheet'ами с автообновлением 4. **PermissionsBinder** - управление разрешениями ### 🗺️ **Система карт:** - **MapInterface** - единый интерфейс для всех карт - **YandexMapImpl** - реализация для Яндекс.Карт - **MapLibreMapImpl** - реализация для MapLibre GL - **MapForgeImpl** - реализация для MapForge - **Strategy Pattern** для переключения между картами ### 💾 **Слой данных:** - **Repository Pattern** для работы с данными - **Room Database** для персистентности - **Entity/Model** разделение для чистоты архитектуры - **Mapper** для преобразования между слоями ### 🔄 **Паттерны взаимодействия:** - **Observer Pattern** - для уведомлений об изменениях - **Command Pattern** - для отложенного выполнения UI операций - **Throttling** - для оптимизации производительности - **Auto-update** - для автоматического обновления UI ### ✅ **Преимущества финальной архитектуры:** 1. **Модульность** - каждый компонент можно тестировать и развивать независимо 2. **Расширяемость** - легко добавлять новые контроллеры и UI компоненты 3. **Поддерживаемость** - четкое разделение ответственности упрощает поддержку 4. **Тестируемость** - каждый компонент можно тестировать изолированно 5. **Производительность** - оптимизированные обновления UI и управление ресурсами 6. **Гибкость** - возможность переключения между различными реализациями карт ### 🎯 **Особенности реализации:** - Гибридный режим GPS (Location API + NMEA) - Throttling UI обновлений для производительности - Автоматическое управление жизненным циклом компонентов - Централизованная обработка ошибок и логирования - Поддержка множественных источников данных - Система уведомлений с вибрацией и звуком