import '../waypoint/flat_waypoint_list.dart'; import 'drone_profile.dart'; import 'route_geometry.dart'; import 'terrain_math.dart'; /// Auf welchen Screen eine Warnung verweist, um sie zu beheben (Doku 3.10, /// analog dem `action`-Feld der Warnungs-Items im HTML-Demonstrator). enum WarningAction { map, altitude, speed } /// Eine einzelne aktive Warnung zur aktuellen Mission. class MissionWarning { const MissionWarning({required this.text, required this.action}); final String text; final WarningAction action; } /// Sammelt alle aktuell zutreffenden Warnungen zur Mission (Doku 3.10, /// analog dem `warnItems`-Aufbau in redraw() im HTML-Demonstrator) - reine /// Funktion aus bereits andernorts berechneten Zwischenergebnissen /// (RouteGeometry, Windkomponenten, Gelaendeprofil), damit sie unabhaengig /// von Riverpod/Widgets testbar bleibt. /// /// [legWindBad] kommt aus computeLegWindBad() (wind_math.dart). [terrain] /// ist null, solange noch kein Gelaendeprofil geladen wurde, oder wenn das /// geladene Profil nicht mehr zur aktuellen Route passt (siehe /// TerrainProfile.routeKey) - die Gelaende-Warnung wird dann uebersprungen, /// statt faelschlich "sicher" oder "gefaehrlich" zu behaupten. List computeMissionWarnings({ required List waypoints, required RouteGeometry routeGeometry, required List legWindBad, required DroneProfile droneProfile, required double totalDistanceM, required double totalDurationSec, TerrainProfile? terrain, }) { final warnings = []; final anyBad = routeGeometry.vertexBad.any((bad) => bad) || routeGeometry.segments.any((s) => s.bad); if (anyBad) { warnings.add(const MissionWarning( text: 'Route exceeds drone capabilities at highlighted point', action: WarningAction.map, )); } if (legWindBad.any((bad) => bad)) { warnings.add(const MissionWarning( text: 'Wind too strong for safe ground speed on one or more legs', action: WarningAction.speed, )); } if (terrain != null && terrain.routeKey == routeKeyForTerrain(waypoints) && terrainDangerRanges(waypoints, terrain).isNotEmpty) { warnings.add(MissionWarning( text: 'Terrain clearance below ${minTerrainClearanceM.round()}m ' 'minimum on part of the route', action: WarningAction.altitude, )); } if (droneProfile.maxRangeM > 0 && totalDistanceM > droneProfile.maxRangeM) { warnings.add(MissionWarning( text: 'Mission distance exceeds max range ' '(${droneProfile.maxRangeM.round()} m)', action: WarningAction.map, )); } if (droneProfile.maxEnduranceMin > 0 && (totalDurationSec / 60) > droneProfile.maxEnduranceMin) { warnings.add(MissionWarning( text: 'Mission duration exceeds max endurance ' '(${droneProfile.maxEnduranceMin.round()} min)', action: WarningAction.map, )); } return warnings; }