# prediction_state_service.py import json import os from typing import Optional, List from datetime import datetime from prediction_state import PredictionState from calendar_manager import CalendarManager from typing import TYPE_CHECKING if TYPE_CHECKING: from prediction_controller import PredictionController class PredictionStateService: """Service for saving and loading complete prediction states""" DEFAULT_STATE_EXTENSION = '.prediction.json' @staticmethod def save_prediction_state(calendar_manager: CalendarManager, prediction_controller, filename: str) -> bool: """Save complete prediction state to file""" try: # Ensure proper extension if not filename.endswith(PredictionStateService.DEFAULT_STATE_EXTENSION): filename += PredictionStateService.DEFAULT_STATE_EXTENSION # Create prediction state state = PredictionState( launch_date=prediction_controller.get_launch_date(), duration_years=prediction_controller.get_duration().years if prediction_controller.get_duration() else None, prediction_date=prediction_controller.get_prediction(), entries=calendar_manager.list_entries() ) # Ensure directory exists os.makedirs(os.path.dirname(filename) if os.path.dirname(filename) else '.', exist_ok=True) # Save to file with pretty formatting with open(filename, 'w', encoding='utf-8') as f: json.dump(state.to_dict(), f, indent=4, ensure_ascii=False) return True except Exception as e: print(f"Error saving prediction state to file {filename}: {e}") return False @staticmethod def load_prediction_state(filename: str) -> Optional[PredictionState]: """Load prediction state from file""" try: if not os.path.exists(filename): print(f"File {filename} does not exist") return None with open(filename, 'r', encoding='utf-8') as f: data = json.load(f) return PredictionState.from_dict(data) except (FileNotFoundError, json.JSONDecodeError) as e: print(f"Error loading prediction state from file {filename}: {e}") return None except Exception as e: print(f"Unexpected error loading prediction state from file {filename}: {e}") return None @staticmethod def restore_from_state(state: PredictionState, calendar_manager: CalendarManager, prediction_controller) -> bool: """Restore calendar manager and prediction controller from state""" try: # Clear current entries and load from state calendar_manager.clear_entries() calendar_manager.entries.extend(state.entries) # Restore prediction controller state if available if state.launch_date and state.duration_years: success = prediction_controller.set_parameters( state.launch_date.isoformat(), state.duration_years ) if not success: print("Warning: Could not restore prediction parameters") return True except Exception as e: print(f"Error restoring from state: {e}") return False @staticmethod def get_state_summary(filename: str): """Get summary information about a state file without loading entries""" try: if not os.path.exists(filename): return None with open(filename, 'r', encoding='utf-8') as f: data = json.load(f) return { 'version': data.get('version', 'Unknown'), 'created_at': data.get('created_at'), 'launch_date': data.get('launch_date'), 'duration_years': data.get('duration_years'), 'prediction_date': data.get('prediction_date'), 'entry_count': len(data.get('entries', [])) } except Exception as e: print(f"Error getting state summary from {filename}: {e}") return None @staticmethod def list_state_files(directory: str = '.') -> List[str]: """List all prediction state files in a directory""" try: files = [] for filename in os.listdir(directory): if filename.endswith(PredictionStateService.DEFAULT_STATE_EXTENSION): files.append(os.path.join(directory, filename)) return sorted(files) except Exception as e: print(f"Error listing state files in {directory}: {e}") return []