diff --git a/simulation_tool/src/simulation_tool/models.py b/simulation_tool/src/simulation_tool/models.py new file mode 100644 index 0000000..cb3f78a --- /dev/null +++ b/simulation_tool/src/simulation_tool/models.py @@ -0,0 +1,63 @@ +from __future__ import annotations + +import json +import logging +from dataclasses import dataclass, field, asdict +from typing import List, Dict, Any + + +logger = logging.getLogger(__name__) +if not logger.handlers: + handler = logging.StreamHandler() + formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(name)s - %(message)s') + handler.setFormatter(formatter) + logger.addHandler(handler) + logger.setLevel(logging.INFO) + + +class SimulationResultsValidationError(Exception): + """Custom exception for validation errors in SimulationResults.""" + + +@dataclass +class SimulationResults: + """Repräsentiert die Ergebnisse einer Simulation. + + Attributes: + time_distributions: Liste der simulierten Zeitverteilungen (z. B. Reaktionszeiten oder Latenzen). + outlier_occurrences: Anzahl erkannter Ausreißer in der Simulation. + """ + + time_distributions: List[float] = field(default_factory=list) + outlier_occurrences: int = 0 + + def __post_init__(self) -> None: + """Validiert die Eingabedaten gemäß data_models und Constraints.""" + logger.debug("Validating SimulationResults instance...") + if not isinstance(self.time_distributions, list): + raise SimulationResultsValidationError("time_distributions must be a list of floats.") + if not all(isinstance(v, (float, int)) for v in self.time_distributions): + raise SimulationResultsValidationError("All elements in time_distributions must be floats or ints.") + if not isinstance(self.outlier_occurrences, int): + raise SimulationResultsValidationError("outlier_occurrences must be an integer.") + if self.outlier_occurrences < 0: + raise SimulationResultsValidationError("outlier_occurrences must be non-negative.") + logger.info( + "SimulationResults validated: %d distributions, %d outliers.", + len(self.time_distributions), + self.outlier_occurrences + ) + + def to_json(self) -> Dict[str, Any]: + """Serialisiert die Simulationsergebnisse als Dictionary, bereit für JSON-Ausgabe.""" + logger.debug("Serializing SimulationResults to JSON-compatible dict.") + result = asdict(self) + # Ensure numeric type consistency (floats) + result["time_distributions"] = [float(v) for v in self.time_distributions] + return result + + def __repr__(self) -> str: + return ( + f"SimulationResults(time_distributions={len(self.time_distributions)} entries, " + f"outlier_occurrences={self.outlier_occurrences})" + ) \ No newline at end of file