From 3054eb8c0de880655a3a01bf4c2da154e6c3ab42 Mon Sep 17 00:00:00 2001 From: matin Date: Tue, 30 Sep 2025 15:13:08 +0200 Subject: save + load includes the launch date and duration. also, increased readability of the json output --- prediction_state_service.py | 127 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 prediction_state_service.py (limited to 'prediction_state_service.py') diff --git a/prediction_state_service.py b/prediction_state_service.py new file mode 100644 index 0000000..a84ae8d --- /dev/null +++ b/prediction_state_service.py @@ -0,0 +1,127 @@ +# 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 [] \ No newline at end of file -- cgit v1.1