from datetime import datetime from typing import Dict, List, Set import streamlit as st from src.utils.session import get_user_progress class LearningService: def __init__(self): self.load_curriculum() def load_curriculum(self): """Load the complete curriculum structure""" self.curriculum = { 'python_basics': { 'name': 'Python Programming Basics', 'description': 'Master the fundamental concepts of Python programming.', 'prerequisites': [], 'modules': [ { 'id': 'intro_python', 'name': 'Introduction to Python', 'concepts': ['programming_basics', 'python_environment', 'basic_syntax'], 'difficulty': 'beginner', 'estimated_hours': 2 }, { 'id': 'variables_types', 'name': 'Variables and Data Types', 'concepts': ['variables', 'numbers', 'strings', 'type_conversion'], 'difficulty': 'beginner', 'estimated_hours': 3 }, { 'id': 'control_flow', 'name': 'Control Flow', 'concepts': ['conditionals', 'loops', 'break_continue'], 'difficulty': 'beginner', 'estimated_hours': 4 }, { 'id': 'functions_basics', 'name': 'Functions', 'concepts': ['function_definition', 'parameters', 'return_values'], 'difficulty': 'beginner', 'estimated_hours': 4 } ] }, 'data_structures': { 'name': 'Data Structures', 'description': 'Learn essential Python data structures and their operations.', 'prerequisites': ['python_basics'], 'modules': [ { 'id': 'lists_tuples', 'name': 'Lists and Tuples', 'concepts': ['list_operations', 'tuple_basics', 'sequence_types'], 'difficulty': 'intermediate', 'estimated_hours': 4 }, { 'id': 'dictionaries', 'name': 'Dictionaries', 'concepts': ['dict_operations', 'key_value_pairs', 'dict_methods'], 'difficulty': 'intermediate', 'estimated_hours': 3 }, { 'id': 'sets', 'name': 'Sets', 'concepts': ['set_operations', 'set_methods', 'set_theory'], 'difficulty': 'intermediate', 'estimated_hours': 3 }, { 'id': 'advanced_ops', 'name': 'Advanced Operations', 'concepts': ['comprehensions', 'generators', 'iterators'], 'difficulty': 'intermediate', 'estimated_hours': 5 } ] } } def check_prerequisites(self, prerequisites: List[str]) -> bool: """Check if prerequisites are met""" state = get_user_progress() for prereq in prerequisites: prereq_modules = {m['id'] for m in self.curriculum[prereq]['modules']} if not prereq_modules.issubset(state['completed_modules']): return False return True def get_path_progress(self, path_id: str) -> float: """Get progress percentage for a path""" state = get_user_progress() path_modules = {m['id'] for m in self.curriculum[path_id]['modules']} completed = path_modules.intersection(state['completed_modules']) return len(completed) / len(path_modules) def is_module_completed(self, module_id: str) -> bool: """Check if a module is completed""" state = get_user_progress() return module_id in state['completed_modules'] def get_concept_mastery(self, concept: str) -> float: """Get mastery level for a concept""" state = get_user_progress() return state['mastery_levels'].get(concept, 0.0) def format_mastery(self, mastery: float) -> str: """Format mastery level for display""" if mastery >= 0.8: return "🌟 Mastered" elif mastery >= 0.5: return "📈 In Progress" else: return "🔸 Not Started" def start_module(self, module_id: str, path_id: str): """Start a learning module""" state = get_user_progress() state['current_module'] = module_id state['current_path'] = path_id self.update_learning_streak() def complete_module(self, module_id: str, path_id: str): """Complete a learning module""" state = get_user_progress() # Mark module as completed state['completed_modules'].add(module_id) # Update concept mastery module = next(m for m in self.curriculum[path_id]['modules'] if m['id'] == module_id) for concept in module['concepts']: self.update_concept_mastery(concept) # Check for achievements self.check_achievements(module_id, path_id) # Update streak self.update_learning_streak() def update_concept_mastery(self, concept: str, score: float = 0.8): """Update mastery level for a concept""" state = get_user_progress() current = state['mastery_levels'].get(concept, 0.0) state['mastery_levels'][concept] = min(1.0, current + score) def launch_quiz(self, module_id: str): """Initialize module quiz""" st.session_state.quiz_active = True st.session_state.current_quiz_module = module_id def update_learning_streak(self): """Update learning streak""" state = get_user_progress() today = datetime.now().date() if state['last_active'] is None: state['learning_streak'] = 1 else: last_active = datetime.strptime(state['last_active'], "%Y-%m-%d").date() if (today - last_active).days == 1: state['learning_streak'] += 1 elif (today - last_active).days > 1: state['learning_streak'] = 1 state['last_active'] = today.strftime("%Y-%m-%d") def check_achievements(self, module_id: str, path_id: str): """Check and award achievements""" state = get_user_progress() new_achievements = [] # First module achievement if len(state['completed_modules']) == 1: new_achievements.append({ 'name': 'First Steps! 🎉', 'description': 'Completed your first module', 'date': datetime.now().strftime("%Y-%m-%d") }) # Path completion achievement path_modules = {m['id'] for m in self.curriculum[path_id]['modules']} if path_modules.issubset(state['completed_modules']): new_achievements.append({ 'name': f'Path Master: {self.curriculum[path_id]["name"]} 🏆', 'description': f'Completed the entire {self.curriculum[path_id]["name"]} path', 'date': datetime.now().strftime("%Y-%m-%d") }) # Learning streak achievements streak_achievements = { 7: 'Week Warrior! 🗓️', 30: 'Monthly Master! 📅', 100: 'Centurion! 💯' } for days, name in streak_achievements.items(): if state['learning_streak'] >= days: achievement_exists = any(a['name'] == name for a in state['achievements']) if not achievement_exists: new_achievements.append({ 'name': name, 'description': f'Maintained a {days}-day learning streak', 'date': datetime.now().strftime("%Y-%m-%d") }) # Add and display new achievements for achievement in new_achievements: if achievement not in state['achievements']: state['achievements'].append(achievement) st.balloons() st.success(f"🏆 New Achievement: {achievement['name']} - {achievement['description']}")