import streamlit as st from datetime import datetime from typing import Dict, List, Optional import json class LearningPaths: def __init__(self): self.initialize_session_state() self.load_curriculum() @staticmethod def initialize_session_state(): """Initialize session state for learning paths if not already present""" if 'learning_state' not in st.session_state: st.session_state.learning_state = { 'current_path': None, 'current_module': None, 'completed_modules': set(), 'achievements': [], 'quiz_scores': {}, 'learning_streak': 0, 'last_active': None, 'mastery_levels': {} # Track concept mastery levels } 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 display(self): """Display the learning paths interface""" st.header("Learning Paths") # Path selection selected_path = st.selectbox( "Select Learning Path", options=list(self.curriculum.keys()), format_func=lambda x: self.curriculum[x]['name'], key="path_selector" ) # Display selected path details if selected_path: self.display_path_details(selected_path) def display_path_details(self, path_id: str): """Display detailed view of a learning path""" path = self.curriculum[path_id] # Path header and description st.subheader(path['name']) st.write(path['description']) # Prerequisites check if path['prerequisites']: prereq_met = self.check_prerequisites(path['prerequisites']) if not prereq_met: st.warning("⚠️ Please complete the prerequisite paths first: " + ", ".join([self.curriculum[p]['name'] for p in path['prerequisites']])) return # Progress overview total_modules = len(path['modules']) completed_modules = len([m for m in path['modules'] if m['id'] in st.session_state.learning_state['completed_modules']]) progress = completed_modules / total_modules st.progress(progress, f"Progress: {completed_modules}/{total_modules} modules completed") # Display modules for module in path['modules']: self.display_module(module, path_id) def display_module(self, module: Dict, path_id: str): """Display individual module with its details and status""" completed = module['id'] in st.session_state.learning_state['completed_modules'] with st.expander( f"{'✅' if completed else '📝'} {module['name']} " f"({module['difficulty']} • {module['estimated_hours']}h)", expanded=not completed ): # Module description and concepts st.write("**Key Concepts:**") for concept in module['concepts']: mastery = self.get_concept_mastery(concept) st.write(f"- {concept.replace('_', ' ').title()}: {self.format_mastery(mastery)}") # Module actions cols = st.columns([1, 1, 1]) with cols[0]: if st.button("Start Learning", key=f"start_{module['id']}", disabled=completed): self.start_module(module['id'], path_id) with cols[1]: if st.button("Take Quiz", key=f"quiz_{module['id']}"): self.launch_quiz(module['id']) with cols[2]: if st.button("Mark Complete", key=f"complete_{module['id']}", disabled=completed): self.complete_module(module['id'], path_id) def start_module(self, module_id: str, path_id: str): """Handle module start action""" st.session_state.learning_state['current_module'] = module_id st.session_state.learning_state['current_path'] = path_id self.update_learning_streak() st.rerun() def complete_module(self, module_id: str, path_id: str): """Handle module completion""" state = st.session_state.learning_state # 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() st.success(f"🎉 Congratulations! You've completed {module['name']}!") st.rerun() def launch_quiz(self, module_id: str): """Initialize and launch module quiz""" st.session_state.quiz_active = True st.session_state.current_quiz_module = module_id st.rerun() def check_prerequisites(self, prerequisites: List[str]) -> bool: """Check if prerequisites are met""" for prereq in prerequisites: prereq_modules = {m['id'] for m in self.curriculum[prereq]['modules']} if not prereq_modules.issubset(st.session_state.learning_state['completed_modules']): return False return True def update_concept_mastery(self, concept: str, score: float = 0.8): """Update mastery level for a concept""" current = st.session_state.learning_state['mastery_levels'].get(concept, 0.0) st.session_state.learning_state['mastery_levels'][concept] = min(1.0, current + score) def get_concept_mastery(self, concept: str) -> float: """Get current mastery level for a concept""" return st.session_state.learning_state['mastery_levels'].get(concept, 0.0) @staticmethod def format_mastery(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 update_learning_streak(self): """Update the user's learning streak""" state = st.session_state.learning_state 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 = st.session_state.learning_state achievements = [] # First module completion if len(state['completed_modules']) == 1: achievements.append({ 'name': 'First Steps! 🎉', 'description': 'Completed your first module', 'date': datetime.now().strftime("%Y-%m-%d") }) # Path completion path_modules = {m['id'] for m in self.curriculum[path_id]['modules']} if path_modules.issubset(state['completed_modules']): 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: achievements.append({ 'name': name, 'description': f'Maintained a {days}-day learning streak', 'date': datetime.now().strftime("%Y-%m-%d") }) # Add new achievements state['achievements'].extend(achievements) # Display new achievements for achievement in achievements: st.balloons() st.success(f"🏆 New Achievement: {achievement['name']} - {achievement['description']}")