S1005403_RisCC/target_simulator/analysis/simulation_archive.py

92 lines
3.6 KiB
Python

# target_simulator/analysis/simulation_archive.py
import os
import json
import time
from datetime import datetime
from typing import Dict, List, Any, Tuple
from target_simulator.core.models import Scenario
# Definisci la struttura per uno stato registrato
RecordedState = Tuple[float, float, float, float] # (timestamp, x_ft, y_ft, z_ft)
class SimulationArchive:
"""
Gestisce la raccolta dei dati per una singola esecuzione di simulazione e la salva su file.
"""
ARCHIVE_FOLDER = "archive_simulations"
def __init__(self, scenario: Scenario):
"""
Inizializza una nuova sessione di archivio per un dato scenario.
"""
self.start_time = time.monotonic()
self.scenario_name = scenario.name
self.scenario_data = scenario.to_dict()
# Struttura dati per contenere gli eventi registrati, indicizzati per target_id
# self.recorded_data[target_id]['simulated'] = [(ts, x, y, z), ...]
# self.recorded_data[target_id]['real'] = [(ts, x, y, z), ...]
self.recorded_data: Dict[int, Dict[str, List[RecordedState]]] = {}
self._ensure_archive_directory()
def _ensure_archive_directory(self):
"""Crea la directory principale dell'archivio se non esiste."""
if not os.path.exists(self.ARCHIVE_FOLDER):
try:
os.makedirs(self.ARCHIVE_FOLDER)
except OSError as e:
print(f"Errore nella creazione della directory di archivio: {e}")
def add_simulated_state(self, target_id: int, timestamp: float, state: Tuple[float, ...]):
"""Aggiunge uno stato simulato all'archivio."""
if target_id not in self.recorded_data:
self.recorded_data[target_id] = {"simulated": [], "real": []}
full_state: RecordedState = (timestamp, state[0], state[1], state[2])
self.recorded_data[target_id]["simulated"].append(full_state)
def add_real_state(self, target_id: int, timestamp: float, state: Tuple[float, ...]):
"""Aggiunge uno stato reale (dal server) all'archivio."""
if target_id not in self.recorded_data:
self.recorded_data[target_id] = {"simulated": [], "real": []}
full_state: RecordedState = (timestamp, state[0], state[1], state[2])
self.recorded_data[target_id]["real"].append(full_state)
def save(self) -> str:
"""
Salva l'archivio completo della simulazione in un file JSON.
Il nome del file è generato dal timestamp e dal nome dello scenario.
Ritorna:
Il percorso del file salvato.
"""
end_time = time.monotonic()
archive_content = {
"metadata": {
"scenario_name": self.scenario_name,
"start_timestamp_utc": datetime.utcnow().isoformat(),
"duration_seconds": end_time - self.start_time,
},
"scenario_definition": self.scenario_data,
"simulation_results": self.recorded_data,
}
ts_str = datetime.now().strftime("%Y%m%d_%H%M%S")
safe_scenario_name = "".join(c for c in self.scenario_name if c.isalnum() or c in (' ', '_')).rstrip()
filename = f"{ts_str}_{safe_scenario_name}.json"
filepath = os.path.join(self.ARCHIVE_FOLDER, filename)
try:
with open(filepath, 'w', encoding='utf-8') as f:
json.dump(archive_content, f, indent=4)
print(f"Archivio di simulazione salvato in: {filepath}")
return filepath
except IOError as e:
print(f"Errore durante il salvataggio dell'archivio di simulazione: {e}")
return ""