""" Symbol Definitions Loader Loads and manages symbol/variable definitions for tooltips """ import json from pathlib import Path from typing import Dict, Optional class SymbolDefinitions: """Manages symbol definitions for variable tooltips""" def __init__(self, json_path: Optional[Path] = None): """ Initialize symbol definitions Args: json_path: Path to symbols JSON file. If None, uses default from config. """ if json_path is None: from app import config json_path = config.RESOURCES_DIR / 'symbols_definitions.json' self.json_path = json_path self.symbols = self._load_symbols() def _load_symbols(self) -> Dict: """Load symbols from JSON file""" try: with open(self.json_path, 'r', encoding='utf-8') as f: data = json.load(f) symbols = data.get('variables', {}) print(f"[Symbols] Loaded {len(symbols)} symbol definitions") return symbols except FileNotFoundError: print(f"[Symbols WARNING] Symbol definitions file not found: {self.json_path}") return {} except json.JSONDecodeError as e: print(f"[Symbols ERROR] Invalid JSON in symbols file: {e}") return {} def get_tooltip(self, symbol: str) -> Optional[str]: """ Get plain text tooltip content for a symbol (no HTML) Args: symbol: The symbol/variable name (e.g., "ω", "C_mut") Returns: Plain text string for tooltip, or None if symbol not defined """ if symbol not in self.symbols: return None s = self.symbols[symbol] # Build tooltip as plain text with line breaks tooltip_parts = [] # Symbol name tooltip_parts.append(f"{symbol}") # Add pronunciation/name if different from symbol if 'name' in s and s['name'] != symbol: tooltip_parts.append(f" ({s['name']})") # Definition if 'definition' in s: tooltip_parts.append(f"\n{s['definition']}") # Formula if 'formula' in s: tooltip_parts.append(f"\nFormula: {s['formula']}") # Units if 'units' in s: tooltip_parts.append(f"\nUnits: {s['units']}") return ''.join(tooltip_parts) def has_symbol(self, symbol: str) -> bool: """Check if a symbol is defined""" return symbol in self.symbols def get_all_symbols(self) -> list: """Get list of all defined symbols""" return list(self.symbols.keys()) # Global singleton instance _symbol_defs_instance = None def get_symbol_definitions() -> SymbolDefinitions: """ Get global SymbolDefinitions instance (singleton pattern) Returns: SymbolDefinitions instance """ global _symbol_defs_instance if _symbol_defs_instance is None: _symbol_defs_instance = SymbolDefinitions() return _symbol_defs_instance