""" Coverage result aggregation and statistics. """ from dataclasses import dataclass from typing import List @dataclass class PointResult: lat: float lon: float rsrp: float distance: float path_loss: float terrain_loss: float building_loss: float diffraction_loss: float has_los: bool model_used: str def to_dict(self) -> dict: return { "lat": self.lat, "lon": self.lon, "rsrp": self.rsrp, "distance": self.distance, "path_loss": self.path_loss, "terrain_loss": self.terrain_loss, "building_loss": self.building_loss, "diffraction_loss": self.diffraction_loss, "has_los": self.has_los, "model_used": self.model_used, } @dataclass class CoverageResult: points: List[PointResult] stats: dict computation_time: float models_used: List[str] def to_dict(self) -> dict: return { "points": [p.to_dict() for p in self.points], "count": len(self.points), "stats": self.stats, "computation_time": round(self.computation_time, 2), "models_used": self.models_used, } def compute_stats(points: List[PointResult]) -> dict: if not points: return {"min_rsrp": 0, "max_rsrp": 0, "avg_rsrp": 0, "los_percentage": 0, "total_points": 0} rsrp_values = [p.rsrp for p in points] los_count = sum(1 for p in points if p.has_los) return { "min_rsrp": min(rsrp_values), "max_rsrp": max(rsrp_values), "avg_rsrp": sum(rsrp_values) / len(rsrp_values), "los_percentage": los_count / len(points) * 100, "total_points": len(points), "points_with_buildings": sum(1 for p in points if p.building_loss > 0), "points_with_terrain_loss": sum(1 for p in points if p.terrain_loss > 0), }