# Диаграмма классов AIS Map Application (PlantUML - Упрощенная версия) ```plantuml @startuml AIS_Map_Architecture_Simple skinparam classAttributeIconSize 0 skinparam classFontSize 9 skinparam packageFontSize 11 skinparam backgroundColor white skinparam classBackgroundColor white skinparam packageBackgroundColor lightblue skinparam packageBorderColor black skinparam classBorderColor black skinparam interfaceBackgroundColor lightgreen skinparam interfaceBorderColor black package "Main Activity" { class MainActivity { - AppCoordinator appCoordinator - MenuBinder menuBinder - BottomSheetsBinder bottomSheetsBinder - PermissionsBinder permissionsBinder - MapController mapController - CompassController compassController - UIRenderingCoordinator uiCoordinator + onCreate() + onResume() + onPause() + onDestroy() } class AisTargetsActivity { - AisTargetsAdapter adapter - List aisVessels + onCreate() + updateAISList() } class SettingsActivity { - SettingsManager settingsManager + onCreate() + saveSettings() } } package "Controllers Factory" { interface ControllersFactory { + createAppCoordinator() : AppCoordinator } class DefaultControllersFactory { + createAppCoordinator() : AppCoordinator } } package "Core Controllers" { class AppCoordinator { - Context context - NMEAController nmeaController - NetworkController networkController - DataController dataController - NotificationController notificationController - CompassController compassController - MapController mapController - Vessel ownVessel - List aisVessels - SettingsManager settingsManager + initializeControllers() + startServices() + stopServices() + onVesselUpdated() + onAISVesselUpdated() + onDOPUpdated() + onDataReceived() + onNotificationShown() + onCompassChanged() } class NMEAController { - Context context - NMEAParser nmeaParser - AndroidNMEAListener androidNmeaListener - GPSLocationListener gpsLocationListener - ExecutorService executor + startAndroidNMEAListener() + stopAndroidNMEAListener() + startGPSLocationListener() + stopGPSLocationListener() + parseNMEAData() } class NetworkController { - Context context - UDPListener udpListener - ExecutorService executor - int udpPort - boolean isUDPEnabled + setUDPEnabled() + startUDPListener() + stopUDPListener() } class DataController { - Context context - Repository repository - SettingsManager settingsManager - ExecutorService executor + restoreDataAsync() + saveVesselData() + saveAISData() + performDatabaseCleanup() } class NotificationController { - Context context - NotificationService notificationService + notifyNewAISTarget() + notifySafetyMessage() + notifyGPSStatus() } class CompassController { - Context context - CompassSensor compassSensor - Handler uiHandler + startCompass() + stopCompass() + isCompassAvailable() : boolean + isCompassActive() : boolean + getCompassStatus() : String } class MapController { - Context context - MapInterface currentMapInterface - MapView mapView - MapLibreMapView mapLibreView - List listeners + addMapInterfaceChangeListener() + removeMapInterfaceChangeListener() + switchToYandexMaps() + switchToMapLibre() + getCurrentMapInterface() : MapInterface } } package "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 + init() + initAIS() + showOwnVesselSheet() + showAISVesselSheet() + startAutoUpdate() + stopAutoUpdate() } class BottomSheetsManager { - Context context - AppCoordinator appCoordinator - BottomSheetDialog ownVesselBottomSheet - BottomSheetDialog aisVesselBottomSheet - View bottomSheetView - View aisBottomSheetView - AISVessel currentAISVessel + init() + showOwnVesselSheet() + showAISVesselSheet() + updateOwnVesselUI() + updateAISBottomSheetUI() + stopAutoUpdate() } class PermissionsBinder { - Activity activity + ensurePermission() : boolean + handleOnRequestPermissionsResult() : boolean } } package "Data Processing" { class NMEAParser { - Vessel ownVessel - List aisVessels - NMEAParserListener listener - GPSLocationListener gpsLocationListener - Map> 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() : boolean + stopListening() + setCallback() } class GPSLocationListener { - Context context - LocationManager locationManager - LocationCallback callback - boolean isListening - int satelliteCount - int activeSatellites - double pdop - double hdop - double vdop + startListening() : boolean + stopListening() + setCallback() } class VesselPathController { - Context context - SettingsManager settingsManager - SharedPreferences prefs - String vesselId - Handler uiHandler - List pathPoints - VesselPathPoint lastPoint + addPathPoint() + getPathPoints() : List + clearPath() + savePath() + loadPath() } } package "Maps" { interface MapInterface { + initialize() + cleanup() + addOwnVesselMarker() + updateOwnVesselPosition() + addAISVesselMarker() + updateAISVesselPosition() + removeAISVesselMarker() + clearAISVesselMarkers() + centerOnPosition() + setZoom() + getZoom() : float + setBearing() + getBearing() : float } 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() : float + setBearing() + getBearing() : float } class MapLibreMapImpl { - Context context - MapView mapView - MapLibreMap mapLibreMap - MarkerClickListener markerClickListener - CursorOverlay cursorOverlay - Vessel ownVessel - Map aisVessels + initialize() + cleanup() + addOwnVesselMarker() + updateOwnVesselPosition() + addAISVesselMarker() + updateAISVesselPosition() + removeAISVesselMarker() + clearAISVesselMarkers() + centerOnPosition() + setZoom() + getZoom() : float + setBearing() + getBearing() : float } class MapForgeImpl { - Context context - MapView mapView - MarkerClickListener markerClickListener - CursorOverlay cursorOverlay - Vessel ownVessel + initialize() + cleanup() + addOwnVesselMarker() + updateOwnVesselPosition() + addAISVesselMarker() + updateAISVesselPosition() + removeAISVesselMarker() + clearAISVesselMarkers() + centerOnPosition() + setZoom() + getZoom() : float + setBearing() + getBearing() : float } } package "Data Models" { 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() : int + getGPSQualityDescription() : String } 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() : boolean + shouldBeRemoved() : boolean + getMinutesSinceLastUpdate() : long } class VesselPathPoint { - double latitude - double longitude - double course - double speed - long timestamp + VesselPathPoint() + toJSON() : String + fromJSON() } } package "Database" { abstract class AppDatabase { + aisVesselDao() : AISVesselDao + vesselDao() : VesselDao + getInstance() : AppDatabase } class Repository { - AISVesselDao aisVesselDao - VesselDao vesselDao - ExecutorService ioExecutor + upsertAIS() + deleteStaleAIS() + getAllAISSync() : List + observeAllAIS() : LiveData> + getAISByMmsiSync() : AISVesselEntity + upsertOwnVessel() + getLatestOwnVesselSync() : VesselEntity + getLatestOwnVesselAsync() } interface AISVesselDao { + upsert() + deleteStale() + getAll() : List + observeAll() : LiveData> + getByMmsi() : AISVesselEntity } interface VesselDao { + upsert() + getLatest() : VesselEntity } 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 } } package "UI Components" { class UIRenderingCoordinator { - MapInterface mapInterface - Handler uiHandler - Vessel pendingVesselUpdate - Map pendingAISUpdates - Set pendingAISRemovals - Runnable vesselUpdateRunnable - Runnable aisUpdateRunnable - Runnable pathUpdateRunnable - boolean vesselUpdatePending - boolean aisUpdatePending - boolean pathUpdatePending + requestVesselUpdate() + requestAISUpdate() + requestAISRemoval() + flushPendingOperations() + cleanup() } interface UIDataChangeNotifier { + onVesselPositionChanged() + onGPSQualityChanged() + onAISVesselChanged() + onAISVesselRemoved() + onVesselPathChanged() + onRequestCenterMap() + onCompassUpdate() } class CompassView { - float azimuth - Paint compassPaint - Paint needlePaint - Paint textPaint - List 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() } } package "Services" { 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() } } package "Utils" { class SettingsManager { - Context context - SharedPreferences prefs + getUDPPort() : int + setUDPPort() + isUDPEnabled() : boolean + setUDPEnabled() + isAndroidNMEAEnabled() : boolean + setAndroidNMEAEnabled() + isUDPNMEAEnabled() : boolean + setUDPNMEAEnabled() + getDataMode() : String + setDataMode() + getDataStaleWarningMinutes() : int + setDataStaleWarningMinutes() + getDataStaleRemoveMinutes() : int + setDataStaleRemoveMinutes() + isPathTrackingEnabled() : boolean + setPathTrackingEnabled() + getPathColor() : int + setPathColor() + getPredictionColor() : int + setPredictionColor() + getPathWidth() : float + setPathWidth() + getPredictionWidth() : float + setPredictionWidth() + getPathMaxPoints() : int + setPathMaxPoints() + getPredictionHorizonSec() : int + setPredictionHorizonSec() + isVibrationEnabled() : boolean + setVibrationEnabled() + isSoundEnabled() : boolean + setSoundEnabled() + isKeepScreenOnEnabled() : boolean + setKeepScreenOnEnabled() + isCursorEnabled() : boolean + setCursorEnabled() } class GeoUtils { + calculateDistance() : double + calculateBearing() : double + isValidCoordinate() : boolean + formatCoordinate() : String + convertToDecimalDegrees() : double } class LogSender { + sendLog() + sendError() + sendWarning() + sendInfo() } class MIDToCountry { + getCountryByMID() : String + getCountryName() : String + isValidMID() : boolean } class NavigationUtils { + calculateCourse() : double + calculateSpeed() : double + calculateETA() : LocalDateTime + isCollisionRisk() : boolean } } ' Основные связи 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 --> 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 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 YandexMapImpl ..|> MapInterface : implements MapLibreMapImpl ..|> MapInterface : implements MapForgeImpl ..|> MapInterface : implements Repository --> AppDatabase : uses Repository --> AISVesselDao : uses Repository --> VesselDao : uses AppDatabase --> AISVesselEntity : contains AppDatabase --> VesselEntity : contains UIRenderingCoordinator ..|> UIDataChangeNotifier : 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 @enduml ``` ## Описание упрощенной PlantUML диаграммы ### 🎯 **Исправления для совместимости:** 1. **Убрана тема** - удалена `!theme plain` которая могла вызывать проблемы 2. **Упрощены настройки** - оставлены только базовые skinparam 3. **Убраны сложные элементы** - удалены некоторые методы для упрощения 4. **Оптимизированы связи** - оставлены только основные связи ### 📦 **Структура пакетов:** - **Main Activity** - основные активности приложения - **Controllers Factory** - фабрика для создания контроллеров - **Core Controllers** - основные контроллеры системы - **UI Binders** - компоненты для управления UI - **Data Processing** - обработка данных и парсинг - **Maps** - система карт и маркеров - **Data Models** - модели данных - **Database** - слой базы данных - **UI Components** - UI компоненты - **Services** - сервисы приложения - **Utils** - утилиты и вспомогательные классы ### 🔧 **Как использовать:** 1. **Онлайн редакторы:** PlantUML Online Server, PlantText 2. **IDE плагины:** IntelliJ IDEA, VS Code, Eclipse 3. **Командная строка:** PlantUML jar файл 4. **Документация:** GitLab, GitHub поддерживают PlantUML ### ✅ **Преимущества упрощенной версии:** - Более совместима с различными PlantUML редакторами - Меньше вероятность ошибок с Graphviz - Сохраняет всю основную архитектуру - Легче для понимания и презентации Эта упрощенная версия должна работать без проблем с Graphviz и показывать всю архитектуру вашего приложения.