import json from datetime import datetime class UserState: def __init__(self, topic=None, claimed_level=None): self.topic = topic self.claimed_level = claimed_level # e.g., 'novice', 'intermediate', 'advanced' self.actual_level = None # Set after assessment self.progress = { 'modules_completed': {}, # {chapter_name: {module_name: status}} 'chapters_completed': {}, # {chapter_name: completion_status} 'bloom_assessments': {}, # {chapter_name: assessment_results} 'overall_progress': { 'total_modules': 0, 'completed_modules': 0, 'total_chapters': 0, 'completed_chapters': 0, 'average_bloom_score': 0 }, 'session_data': { 'start_time': datetime.now().isoformat(), 'last_activity': datetime.now().isoformat() } } def set_actual_level(self, level): self.actual_level = level @property def display_level(self): """Returns the actual level if set, otherwise the claimed level""" return self.actual_level or self.claimed_level def update_module_progress(self, chapter_name, module_name, status="completed"): """Update the completion status of a module""" if chapter_name not in self.progress['modules_completed']: self.progress['modules_completed'][chapter_name] = {} self.progress['modules_completed'][chapter_name][module_name] = { 'status': status, 'completed_at': datetime.now().isoformat() } self.progress['session_data']['last_activity'] = datetime.now().isoformat() def update_chapter_progress(self, chapter_name, status="completed"): """Update the completion status of a chapter""" self.progress['chapters_completed'][chapter_name] = { 'status': status, 'completed_at': datetime.now().isoformat() } self.progress['session_data']['last_activity'] = datetime.now().isoformat() def update_bloom_assessment(self, chapter_name, assessment_results): """Store Bloom's assessment results for a chapter""" # Store the assessment results directly without wrapping in 'results' self.progress['bloom_assessments'][chapter_name] = assessment_results self.progress['bloom_assessments'][chapter_name]['completed_at'] = datetime.now().isoformat() self.progress['session_data']['last_activity'] = datetime.now().isoformat() def calculate_overall_progress(self, curriculum): """Calculate overall progress based on curriculum""" total_modules = sum(len(chapter.modules) for chapter in curriculum.chapters) completed_modules = sum( len([m for m in modules.values() if m.get('status') == 'completed']) for modules in self.progress['modules_completed'].values() ) total_chapters = len(curriculum.chapters) completed_chapters = len([ c for c in self.progress['chapters_completed'].values() if c.get('status') == 'completed' ]) # Calculate average Bloom's score bloom_scores = [ assessment.get('average_score', 0) for assessment in self.progress['bloom_assessments'].values() ] average_bloom_score = sum(bloom_scores) / len(bloom_scores) if bloom_scores else 0 self.progress['overall_progress'] = { 'total_modules': total_modules, 'completed_modules': completed_modules, 'total_chapters': total_chapters, 'completed_chapters': completed_chapters, 'average_bloom_score': average_bloom_score, 'completion_percentage': (completed_modules / total_modules * 100) if total_modules > 0 else 0 } def get_progress_summary(self, curriculum=None): """Get a formatted progress summary""" if curriculum: self.calculate_overall_progress(curriculum) overall = self.progress['overall_progress'] summary = f""" PROGRESS SUMMARY =============== Topic: {self.topic} Level: {self.actual_level or self.claimed_level} Overall Progress: - Modules: {overall['completed_modules']}/{overall['total_modules']} ({overall['completion_percentage']:.1f}%) - Chapters: {overall['completed_chapters']}/{overall['total_chapters']} - Average Bloom's Score: {overall['average_bloom_score']:.1f}/10 Chapter Progress: """ for chapter_name, chapter_data in self.progress['chapters_completed'].items(): status = chapter_data.get('status', 'not_started') summary += f"- {chapter_name}: {status}\n" return summary def __repr__(self): return f"UserState(topic={self.topic}, claimed_level={self.claimed_level}, actual_level={self.actual_level})"