# target_simulator/utils/config_manager.py """ Manages loading and saving of application settings and scenarios to a single JSON file. """ import json import os import sys from typing import Dict, Any, Optional, List from enum import Enum class EnumEncoder(json.JSONEncoder): """A custom JSON encoder to handle Enum objects by encoding them as their values.""" def default(self, o: Any) -> Any: if isinstance(o, Enum): return o.value return super().default(o) class ConfigManager: def save_connection_settings(self, config: Dict[str, Any]): """ Save both target and lru connection configs in the settings file. """ if "general" not in self._settings: self._settings["general"] = {} self._settings["general"]["connection"] = config self._save_settings() def get_connection_settings(self) -> Dict[str, Any]: """ Returns the connection settings from the 'general' section. """ general = self._settings.get("general", {}) return general.get("connection", {}) """Handles reading and writing application settings and scenarios from a JSON file.""" def __init__(self, filename: str = "settings.json"): """ Initializes the ConfigManager. Args: filename: The name of the settings file. It will be stored in the project root directory. """ if getattr(sys, 'frozen', False): application_path = os.path.dirname(sys.executable) else: application_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) self.filepath = os.path.join(application_path, filename) self._settings = self._load_or_initialize_settings() def _load_or_initialize_settings(self) -> Dict[str, Any]: """Loads settings from the JSON file or initializes with a default structure.""" if not os.path.exists(self.filepath): return {"general": {}, "scenarios": {}} try: with open(self.filepath, 'r', encoding='utf-8') as f: settings = json.load(f) if not isinstance(settings, dict) or "general" not in settings or "scenarios" not in settings: return {"general": settings, "scenarios": {}} return settings except (json.JSONDecodeError, IOError): return {"general": {}, "scenarios": {}} def _save_settings(self): """Saves the current settings to the JSON file.""" try: with open(self.filepath, 'w', encoding='utf-8') as f: json.dump(self._settings, f, indent=4, cls=EnumEncoder) except IOError as e: print(f"Error saving settings to {self.filepath}: {e}") def get_general_settings(self) -> Dict[str, Any]: """Returns the general settings.""" return self._settings.get("general", {}) def save_general_settings(self, data: Dict[str, Any]): """Saves the general settings.""" self._settings["general"] = data self._save_settings() def get_scenario_names(self) -> List[str]: """Returns a list of all scenario names.""" return list(self._settings.get("scenarios", {}).keys()) def get_scenario(self, name: str) -> Optional[Dict[str, Any]]: """ Retrieves a specific scenario by name. Args: name: The name of the scenario to retrieve. Returns: A dictionary with the scenario data, or None if not found. """ return self._settings.get("scenarios", {}).get(name) def save_scenario(self, name: str, data: Dict[str, Any]): """ Saves or updates a scenario. Args: name: The name of the scenario to save. data: The dictionary of scenario data to save. """ if "scenarios" not in self._settings: self._settings["scenarios"] = {} self._settings["scenarios"][name] = data self._save_settings() def delete_scenario(self, name: str): """ Deletes a scenario by name. Args: name: The name of the scenario to delete. """ if "scenarios" in self._settings and name in self._settings["scenarios"]: del self._settings["scenarios"][name] self._save_settings()