from typing import Literal from pydantic import BaseModel, Field from app.models.coverage import LinkRx, LinkTx from app.models.terrain import Obstruction class LinkBudgetRequest(BaseModel): tx: LinkTx rx: LinkRx frequency_mhz: float = Field(gt=0) model: Literal["p452", "itm", "manual"] = "manual" include_buildings: bool = True include_vegetation: bool = True k_factor: float = Field(default=1.333, gt=0) class LinkBudgetResponse(BaseModel): distance_km: float fspl_db: float diffraction_db: float vegetation_db: float atmospheric_db: float total_loss_db: float rx_power_dbm: float fade_margin_db: float fresnel_clear: bool link_viable: bool los_clear: bool geometric_los: bool first_fresnel_clearance_pct: float fresnel_violations_count: int geometric_obstructions_count: int building_obstructions_count: int worst_obstruction: Obstruction | None