diagram_ph/app/models/diagram.py

188 lines
5.1 KiB
Python

"""
Modèles Pydantic pour les diagrammes PH.
"""
from typing import Optional, List, Dict, Any
from pydantic import BaseModel, Field, field_validator
class DiagramPointRequest(BaseModel):
"""Point personnalisé à tracer sur le diagramme."""
pressure: float = Field(
...,
description="Pression (bar)",
gt=0
)
enthalpy: float = Field(
...,
description="Enthalpie (kJ/kg)"
)
temperature: Optional[float] = Field(
None,
description="Température (Celsius) - optionnel"
)
entropy: Optional[float] = Field(
None,
description="Entropie (kJ/kg.K) - optionnel"
)
quality: Optional[float] = Field(
None,
description="Titre vapeur (0-1) - optionnel",
ge=0,
le=1
)
label: Optional[str] = Field(
None,
description="Label du point - optionnel"
)
class PressureRange(BaseModel):
"""Plage de pression."""
min: float = Field(..., gt=0, description="Pression minimale (bar)")
max: float = Field(..., gt=0, description="Pression maximale (bar)")
class EnthalpyRange(BaseModel):
"""Plage d'enthalpie."""
min: float = Field(..., description="Enthalpie minimale (kJ/kg)")
max: float = Field(..., description="Enthalpie maximale (kJ/kg)")
class DiagramRequest(BaseModel):
"""Requête pour générer un diagramme PH."""
refrigerant: str = Field(
...,
description="Code du réfrigérant (ex: R134a, R410A)",
examples=["R134a", "R410A", "R744"]
)
pressure_range: PressureRange = Field(
...,
description="Plage de pression du diagramme"
)
enthalpy_range: Optional[EnthalpyRange] = Field(
None,
description="Plage d'enthalpie - auto si non fourni"
)
include_isotherms: bool = Field(
True,
description="Inclure les isothermes"
)
isotherm_values: Optional[List[float]] = Field(
None,
description="Températures isothermes spécifiques (Celsius)"
)
cycle_points: Optional[List[Dict[str, float]]] = Field(
None,
description="Points du cycle [(enthalpy, pressure), ...]"
)
title: Optional[str] = Field(
None,
description="Titre personnalisé du diagramme"
)
format: str = Field(
"both",
description="Format: 'png', 'json', ou 'both'",
pattern="^(png|json|both)$"
)
width: int = Field(1400, gt=0, description="Largeur image (pixels)")
height: int = Field(900, gt=0, description="Hauteur image (pixels)")
dpi: int = Field(100, gt=0, description="DPI de l'image")
class SaturationPoint(BaseModel):
"""Point sur la courbe de saturation."""
enthalpy: float = Field(..., description="Enthalpie (kJ/kg)")
pressure: float = Field(..., description="Pression (bar)")
class IsothermCurve(BaseModel):
"""Courbe isotherme."""
temperature: float = Field(..., description="Température (Celsius)")
unit: str = Field("°C", description="Unité de température")
points: List[SaturationPoint] = Field(
...,
description="Points de la courbe"
)
class DiagramPointResponse(BaseModel):
"""Point personnalisé dans la réponse."""
enthalpy: float = Field(..., description="Enthalpie (kJ/kg)")
pressure: float = Field(..., description="Pression (bar)")
temperature: Optional[float] = Field(None, description="Température (Celsius)")
entropy: Optional[float] = Field(None, description="Entropie (kJ/kg.K)")
quality: Optional[float] = Field(None, description="Titre vapeur (0-1)")
class DiagramDataResponse(BaseModel):
"""Données JSON du diagramme."""
refrigerant: str = Field(..., description="Code du réfrigérant")
ranges: Dict[str, Optional[float]] = Field(
...,
description="Plages de valeurs du diagramme"
)
saturation_curve: Dict[str, List[SaturationPoint]] = Field(
...,
description="Courbe de saturation (liquide et vapeur)"
)
isotherms: Optional[List[IsothermCurve]] = Field(
None,
description="Courbes isothermes"
)
custom_points: Optional[List[DiagramPointResponse]] = Field(
None,
description="Points personnalisés"
)
class DiagramResponse(BaseModel):
"""Réponse complète de génération de diagramme."""
success: bool = Field(True, description="Succès")
image: Optional[str] = Field(
None,
description="Image PNG base64"
)
data: Optional[Dict[str, Any]] = Field(
None,
description="Données JSON"
)
metadata: Dict[str, Any] = Field(
default_factory=dict,
description="Métadonnées"
)
message: Optional[str] = Field(
None,
description="Message"
)
class DiagramError(BaseModel):
"""Erreur lors de la génération de diagramme."""
success: bool = Field(False, description="Échec de l'opération")
error: str = Field(..., description="Message d'erreur")
details: Optional[str] = Field(None, description="Détails supplémentaires")