1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
# prediction_state.py
from datetime import datetime
from dateutil.relativedelta import relativedelta
from typing import List, Optional, Dict, Any, TYPE_CHECKING
if TYPE_CHECKING:
from calendar_entry import CalendarEntry
import uuid
class PredictionState:
"""Represents the complete state of a prediction including all metadata"""
def __init__(self, launch_date: Optional[datetime] = None,
duration_years: Optional[int] = None,
prediction_date: Optional[datetime] = None,
entries: Optional[List["CalendarEntry"]] = None):
self.launch_date = launch_date
self.duration_years = duration_years
self.prediction_date = prediction_date
self.entries = entries or []
self.created_at = datetime.now()
self.version = "1.0"
def to_dict(self) -> Dict[str, Any]:
"""Convert state to dictionary for serialization"""
return {
'version': self.version,
'created_at': self.created_at.isoformat(),
'launch_date': self.launch_date.strftime('%Y-%m-%d') if self.launch_date else None,
'duration_years': self.duration_years,
'prediction_date': self.prediction_date.strftime('%Y-%m-%d') if self.prediction_date else None,
'entries': [self._entry_to_dict_without_id(entry) for entry in self.entries]
}
def _entry_to_dict_without_id(self, entry: "CalendarEntry") -> Dict[str, Any]:
"""Convert entry to dictionary without ID for better readability"""
return {
'start_date': entry.start_date.strftime('%Y-%m-%d'),
'end_date': entry.end_date.strftime('%Y-%m-%d'),
'keyword': entry.keyword,
'commentary': entry.commentary,
'corrected_start_date': entry.corrected_start_date.strftime('%Y-%m-%d') if entry.corrected_start_date else None,
'corrected_end_date': entry.corrected_end_date.strftime('%Y-%m-%d') if entry.corrected_end_date else None,
'time_period': entry.time_period if hasattr(entry, 'time_period') else None
}
@classmethod
def from_dict(cls, data: Dict[str, Any]) -> 'PredictionState':
"""Create state from dictionary, generating new IDs for entries"""
from calendar_entry import CalendarEntry
state = cls()
state.version = data.get('version', '1.0')
# created_at can include time; others are date-only strings
state.created_at = datetime.fromisoformat(data['created_at']) if data.get('created_at') else datetime.now()
state.launch_date = datetime.fromisoformat(data['launch_date']) if data.get('launch_date') else None
state.duration_years = data.get('duration_years')
state.prediction_date = datetime.fromisoformat(data['prediction_date']) if data.get('prediction_date') else None
# Create entries with new IDs
state.entries = []
for entry_data in data.get('entries', []):
entry = CalendarEntry(
start_date=entry_data['start_date'],
end_date=entry_data['end_date'],
keyword=entry_data['keyword'],
entry_id=str(uuid.uuid4()), # Generate new ID
corrected_start_date=datetime.fromisoformat(entry_data['corrected_start_date']) if entry_data.get('corrected_start_date') else None,
corrected_end_date=datetime.fromisoformat(entry_data['corrected_end_date']) if entry_data.get('corrected_end_date') else None,
commentary=entry_data.get('commentary', '')
)
# Set time_period if available
if entry_data.get('time_period'):
entry.time_period = entry_data['time_period']
state.entries.append(entry)
return state
|