Spaces:
Configuration error
Configuration error
| import streamlit as st | |
| import os | |
| from groq import Groq | |
| import json | |
| import re | |
| from typing import List, Dict, Optional | |
| import time | |
| import plotly.express as px | |
| import plotly.graph_objects as go | |
| import pandas as pd | |
| from datetime import datetime, timedelta | |
| import streamlit.components.v1 as components | |
| # Configure page | |
| st.set_page_config( | |
| page_title="🧮 MathGenius Academy", | |
| page_icon="🧮", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Custom CSS for enhanced UI | |
| def load_custom_css(): | |
| st.markdown(""" | |
| <style> | |
| /* Comprehensive Streamlit branding removal */ | |
| #MainMenu {visibility: hidden !important;} | |
| footer {visibility: hidden !important;} | |
| header {visibility: hidden !important;} | |
| .stDeployButton {display: none !important;} | |
| .stDecoration {display: none !important;} | |
| .stActionButton {display: none !important;} | |
| [data-testid="stToolbar"] {display: none !important;} | |
| [data-testid="stDecoration"] {display: none !important;} | |
| [data-testid="stStatusWidget"] {display: none !important;} | |
| [data-testid="manage-app-button"] {display: none !important;} | |
| [data-testid="deployButton"] {display: none !important;} | |
| /* Hide hamburger menu */ | |
| .css-14xtw13.e8zbici0 {display: none !important;} | |
| .css-vk3wp9 {display: none !important;} | |
| .css-1inwz65 {display: none !important;} | |
| /* Hide footer */ | |
| .css-h5rgaw.egzxvld1 {display: none !important;} | |
| .css-cio0dv.egzxvld1 {display: none !important;} | |
| footer.css-164nlkn.egzxvld1 {display: none !important;} | |
| /* Hide "Made with Streamlit" */ | |
| .viewerBadge_container__1QSob {display: none !important;} | |
| .styles_viewerBadge__1yB5_ {display: none !important;} | |
| .viewerBadge_link__1S137 {display: none !important;} | |
| .viewerBadge_text__1JaDK {display: none !important;} | |
| /* Hide deploy button and related elements */ | |
| .css-1rs6os {display: none !important;} | |
| .css-17eq0hr {display: none !important;} | |
| .css-1vbkxwb {display: none !important;} | |
| .css-1dp5vir {display: none !important;} | |
| /* Hide GitHub icon and deploy related buttons */ | |
| [title="View source on GitHub"] {display: none !important;} | |
| [title="Deploy this app"] {display: none !important;} | |
| .css-1avcm0n {display: none !important;} | |
| /* Hide top padding */ | |
| #root > div:nth-child(1) > div > div > div > div > section > div {padding-top: 0rem !important;} | |
| /* Import Google Fonts */ | |
| @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&family=Nunito:wght@300;400;500;600;700&display=swap'); | |
| /* Global Styles */ | |
| .main { | |
| font-family: 'Poppins', sans-serif; | |
| } | |
| /* Header Styling */ | |
| .hero-header { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| padding: 2rem; | |
| border-radius: 20px; | |
| color: white; | |
| text-align: center; | |
| margin-bottom: 2rem; | |
| box-shadow: 0 20px 40px rgba(102, 126, 234, 0.3); | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .hero-header::before { | |
| content: ''; | |
| position: absolute; | |
| top: -50%; | |
| left: -50%; | |
| width: 200%; | |
| height: 200%; | |
| background: radial-gradient(circle, rgba(255,255,255,0.1) 0%, transparent 70%); | |
| animation: float 6s ease-in-out infinite; | |
| } | |
| @keyframes float { | |
| 0%, 100% { transform: translate(0, 0) rotate(0deg); } | |
| 50% { transform: translate(20px, -20px) rotate(180deg); } | |
| } | |
| .hero-title { | |
| font-size: 3.5rem; | |
| font-weight: 700; | |
| margin-bottom: 0.5rem; | |
| text-shadow: 2px 2px 4px rgba(0,0,0,0.3); | |
| position: relative; | |
| z-index: 1; | |
| } | |
| .hero-subtitle { | |
| font-size: 1.2rem; | |
| opacity: 0.9; | |
| margin-bottom: 1rem; | |
| position: relative; | |
| z-index: 1; | |
| } | |
| /* Card Styling */ | |
| .custom-card { | |
| background: white; | |
| padding: 2rem; | |
| border-radius: 20px; | |
| box-shadow: 0 15px 35px rgba(0,0,0,0.1); | |
| border: 1px solid #e1e8ed; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| overflow: hidden; | |
| color: #333; | |
| } | |
| .custom-card:hover { | |
| transform: translateY(-10px); | |
| box-shadow: 0 25px 50px rgba(0,0,0,0.15); | |
| } | |
| .custom-card::before { | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 4px; | |
| background: linear-gradient(90deg, #667eea, #764ba2); | |
| } | |
| .custom-card h4 { | |
| color: #667eea !important; | |
| margin-bottom: 1rem; | |
| font-weight: 600; | |
| } | |
| .custom-card p, .custom-card li { | |
| color: #444 !important; | |
| line-height: 1.6; | |
| } | |
| .custom-card ul { | |
| padding-left: 1.5rem; | |
| } | |
| .custom-card ol { | |
| padding-left: 1.5rem; | |
| } | |
| /* Question Card */ | |
| .question-card { | |
| background: linear-gradient(145deg, #f8fafc 0%, #e2e8f0 100%); | |
| border-radius: 20px; | |
| padding: 2rem; | |
| margin: 1rem 0; | |
| border-left: 6px solid #667eea; | |
| box-shadow: 0 10px 30px rgba(0,0,0,0.1); | |
| transition: all 0.3s ease; | |
| } | |
| .question-card:hover { | |
| transform: translateX(10px); | |
| box-shadow: 0 15px 40px rgba(0,0,0,0.15); | |
| } | |
| /* Stats Cards */ | |
| .stat-card { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| padding: 1.5rem; | |
| border-radius: 15px; | |
| text-align: center; | |
| box-shadow: 0 10px 30px rgba(102, 126, 234, 0.3); | |
| transition: all 0.3s ease; | |
| } | |
| .stat-card:hover { | |
| transform: scale(1.05); | |
| } | |
| .stat-number { | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| margin-bottom: 0.5rem; | |
| } | |
| .stat-label { | |
| font-size: 0.9rem; | |
| opacity: 0.9; | |
| } | |
| /* Buttons */ | |
| .custom-button { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| border: none; | |
| padding: 0.75rem 2rem; | |
| border-radius: 50px; | |
| font-weight: 600; | |
| font-size: 1rem; | |
| cursor: pointer; | |
| transition: all 0.3s ease; | |
| box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3); | |
| } | |
| .custom-button:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4); | |
| } | |
| /* Progress Bar */ | |
| .progress-container { | |
| background: #e2e8f0; | |
| border-radius: 50px; | |
| padding: 0.5rem; | |
| margin: 1rem 0; | |
| } | |
| .progress-bar { | |
| background: linear-gradient(90deg, #667eea, #764ba2); | |
| height: 20px; | |
| border-radius: 50px; | |
| transition: width 1s ease; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: white; | |
| font-weight: 600; | |
| font-size: 0.8rem; | |
| } | |
| /* Animations */ | |
| @keyframes slideInUp { | |
| from { | |
| opacity: 0; | |
| transform: translateY(30px); | |
| } | |
| to { | |
| opacity: 1; | |
| transform: translateY(0); | |
| } | |
| } | |
| .slide-in-up { | |
| animation: slideInUp 0.6s ease-out; | |
| } | |
| @keyframes pulse { | |
| 0% { transform: scale(1); } | |
| 50% { transform: scale(1.05); } | |
| 100% { transform: scale(1); } | |
| } | |
| .pulse-animation { | |
| animation: pulse 2s infinite; | |
| } | |
| /* Sidebar Styling */ | |
| .sidebar .sidebar-content { | |
| background: linear-gradient(180deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| } | |
| /* Toast Notifications */ | |
| .toast { | |
| position: fixed; | |
| top: 20px; | |
| right: 20px; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| padding: 1rem 2rem; | |
| border-radius: 10px; | |
| box-shadow: 0 10px 30px rgba(0,0,0,0.3); | |
| z-index: 1000; | |
| animation: slideInRight 0.5s ease; | |
| } | |
| @keyframes slideInRight { | |
| from { transform: translateX(100%); } | |
| to { transform: translateX(0); } | |
| } | |
| /* Mobile Responsive */ | |
| @media (max-width: 768px) { | |
| .hero-title { | |
| font-size: 2.5rem; | |
| } | |
| .custom-card { | |
| padding: 1rem; | |
| } | |
| .question-card { | |
| padding: 1rem; | |
| } | |
| } | |
| body, .main, .block-container { | |
| background: #f7f9fb !important; | |
| } | |
| .custom-card { | |
| margin-bottom: 2rem; | |
| padding: 2.5rem; | |
| border-radius: 24px; | |
| box-shadow: 0 8px 32px rgba(102, 126, 234, 0.08); | |
| } | |
| .question-card { | |
| background: #fff; | |
| border-radius: 20px; | |
| box-shadow: 0 4px 24px rgba(102, 126, 234, 0.10); | |
| margin-bottom: 2rem; | |
| padding: 2rem 2.5rem; | |
| } | |
| .question-card:hover { | |
| box-shadow: 0 8px 32px rgba(102, 126, 234, 0.15); | |
| } | |
| .question-card .stRadio > div { | |
| gap: 1.5rem; | |
| } | |
| .stRadio label { | |
| background: #f0f4fa; | |
| border-radius: 16px; | |
| padding: 0.75rem 1.5rem; | |
| margin-bottom: 0.5rem; | |
| font-size: 1.1rem; | |
| transition: background 0.2s, color 0.2s; | |
| cursor: pointer; | |
| } | |
| .stRadio label:hover { | |
| background: #e3e9f7; | |
| color: #667eea; | |
| } | |
| .stRadio input:checked + label { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: #fff; | |
| } | |
| .stButton > button { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: #fff; | |
| border-radius: 30px; | |
| font-weight: 600; | |
| font-size: 1.1rem; | |
| padding: 0.75rem 2.5rem; | |
| margin: 0.5rem 0; | |
| box-shadow: 0 4px 16px rgba(102, 126, 234, 0.10); | |
| transition: background 0.2s, box-shadow 0.2s; | |
| } | |
| .stButton > button:hover { | |
| background: linear-gradient(135deg, #764ba2 0%, #667eea 100%); | |
| box-shadow: 0 8px 32px rgba(102, 126, 234, 0.15); | |
| } | |
| .stMarkdown h2, .stMarkdown h3, .stMarkdown h4 { | |
| font-weight: 700; | |
| margin-top: 2rem; | |
| margin-bottom: 1rem; | |
| color: #667eea; | |
| } | |
| .stMarkdown hr { | |
| border: none; | |
| border-top: 2px solid #e1e8ed; | |
| margin: 2rem 0; | |
| } | |
| .progress-container { | |
| margin-bottom: 1.5rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| class MathOlympiadExam: | |
| def __init__(self): | |
| self.client = self._initialize_groq_client() | |
| self.grade_levels = { | |
| 1: {"name": "Grade 1 (Ages 6-7)", "emoji": "🌱", "color": "#FF6B6B"}, | |
| 2: {"name": "Grade 2 (Ages 7-8)", "emoji": "🌿", "color": "#4ECDC4"}, | |
| 3: {"name": "Grade 3 (Ages 8-9)", "emoji": "🍃", "color": "#45B7D1"}, | |
| 4: {"name": "Grade 4 (Ages 9-10)", "emoji": "🌳", "color": "#96CEB4"}, | |
| 5: {"name": "Grade 5 (Ages 10-11)", "emoji": "🎯", "color": "#FECA57"}, | |
| 6: {"name": "Grade 6 (Ages 11-12)", "emoji": "🚀", "color": "#FF9FF3"}, | |
| 7: {"name": "Grade 7 (Ages 12-13)", "emoji": "⭐", "color": "#54A0FF"}, | |
| 8: {"name": "Grade 8 (Ages 13-14)", "emoji": "💎", "color": "#5F27CD"}, | |
| 9: {"name": "Grade 9 (Ages 14-15)", "emoji": "🏆", "color": "#00D2D3"}, | |
| 10: {"name": "Grade 10 (Ages 15-16)", "emoji": "👑", "color": "#FF6348"} | |
| } | |
| def _initialize_groq_client(self) -> Optional[Groq]: | |
| """Initialize Groq client with API key""" | |
| try: | |
| # Use Streamlit secrets for secure API key management | |
| api_key = st.secrets["GROQ_API_KEY"] | |
| if not api_key: | |
| st.error("⚠️ GROQ_API_KEY not found in secrets!") | |
| return None | |
| return Groq(api_key=api_key) | |
| except Exception as e: | |
| st.error(f"Failed to initialize Groq client: {e}") | |
| return None | |
| def generate_questions(self, grade: int, num_questions: int, difficulty: str = "medium") -> List[Dict]: | |
| """Generate math olympiad questions with enhanced difficulty options""" | |
| if not self.client: | |
| return [] | |
| try: | |
| difficulty_map = { | |
| 1: "very basic arithmetic, counting 1-20, simple shapes recognition, basic patterns", | |
| 2: "addition and subtraction within 100, simple word problems, basic time and money", | |
| 3: "multiplication tables up to 10, basic division, simple fractions, pattern recognition", | |
| 4: "advanced multiplication and division, fractions, basic decimals, area and perimeter", | |
| 5: "advanced arithmetic, introduction to algebra, geometry, data interpretation", | |
| 6: "pre-algebra, ratios and proportions, percentages, coordinate geometry, statistics", | |
| 7: "algebra fundamentals, advanced geometry, probability, scientific notation", | |
| 8: "linear equations, quadratic basics, trigonometry introduction, advanced geometry", | |
| 9: "advanced algebra, geometry proofs, probability and statistics, trigonometry", | |
| 10: "pre-calculus, advanced trigonometry, complex numbers, advanced problem solving" | |
| } | |
| difficulty_modifiers = { | |
| "easy": "Make questions slightly easier than typical olympiad level, focusing on fundamental concepts", | |
| "medium": "Standard olympiad difficulty with moderate complexity", | |
| "hard": "Advanced olympiad level with complex multi-step problems" | |
| } | |
| topics = difficulty_map.get(grade, "general math concepts") | |
| modifier = difficulty_modifiers.get(difficulty, "") | |
| prompt = f"""Generate exactly {num_questions} Math Olympiad-style multiple choice questions for Grade {grade} students. | |
| Topics focus: {topics} | |
| Difficulty: {modifier} | |
| Format each question EXACTLY as follows: | |
| **Question X:** [Question text here] | |
| A) [Option A] | |
| B) [Option B] | |
| C) [Option C] | |
| D) [Option D] | |
| **Correct Answer:** [Letter only - A, B, C, or D] | |
| **Explanation:** [Clear step-by-step solution] | |
| **Hint:** [Helpful hint for students] | |
| Make questions engaging and educational. Include varied problem types: word problems, visual problems, logical reasoning, and computational challenges.""" | |
| response = self.client.chat.completions.create( | |
| model="llama-3.3-70b-versatile", | |
| messages=[ | |
| {"role": "system", "content": "You are an expert Math Olympiad coach creating engaging, educational questions."}, | |
| {"role": "user", "content": prompt} | |
| ], | |
| temperature=0.7, | |
| max_tokens=3000 | |
| ) | |
| return self._parse_questions(response.choices[0].message.content) | |
| except Exception as e: | |
| st.error(f"Failed to generate questions: {e}") | |
| return [] | |
| def _parse_questions(self, content: str) -> List[Dict]: | |
| """Enhanced question parsing with hints""" | |
| questions = [] | |
| question_blocks = re.split(r'\*\*Question \d+:\*\*', content)[1:] | |
| for i, block in enumerate(question_blocks, 1): | |
| try: | |
| lines = [line.strip() for line in block.strip().split('\n') if line.strip()] | |
| if len(lines) < 6: | |
| continue | |
| question_text = lines[0] | |
| options = [] | |
| correct_answer = None | |
| explanation = "" | |
| hint = "" | |
| for line in lines[1:]: | |
| if line.startswith(('A)', 'B)', 'C)', 'D)')): | |
| options.append(line) | |
| elif line.startswith('**Correct Answer:**'): | |
| correct_answer = line.replace('**Correct Answer:**', '').strip() | |
| elif line.startswith('**Explanation:**'): | |
| explanation = line.replace('**Explanation:**', '').strip() | |
| elif line.startswith('**Hint:**'): | |
| hint = line.replace('**Hint:**', '').strip() | |
| if len(options) == 4 and correct_answer: | |
| questions.append({ | |
| 'question_number': i, | |
| 'question_text': question_text, | |
| 'options': options, | |
| 'correct_answer': correct_answer, | |
| 'explanation': explanation, | |
| 'hint': hint, | |
| 'user_answer': None, | |
| 'time_taken': 0, | |
| 'difficulty': self._estimate_difficulty(question_text) | |
| }) | |
| except Exception as e: | |
| st.warning(f"Error parsing question {i}: {e}") | |
| continue | |
| return questions | |
| def _estimate_difficulty(self, question_text: str) -> str: | |
| """Estimate question difficulty based on content""" | |
| hard_keywords = ['prove', 'complex', 'advanced', 'multiple steps', 'system of'] | |
| easy_keywords = ['basic', 'simple', 'find', 'calculate', 'what is'] | |
| text_lower = question_text.lower() | |
| if any(keyword in text_lower for keyword in hard_keywords): | |
| return "Hard" | |
| elif any(keyword in text_lower for keyword in easy_keywords): | |
| return "Easy" | |
| else: | |
| return "Medium" | |
| # Initialize session state | |
| def initialize_session_state(): | |
| if 'questions' not in st.session_state: | |
| st.session_state.questions = [] | |
| if 'exam_completed' not in st.session_state: | |
| st.session_state.exam_completed = False | |
| if 'grade_selected' not in st.session_state: | |
| st.session_state.grade_selected = None | |
| if 'exam_history' not in st.session_state: | |
| st.session_state.exam_history = [] | |
| if 'current_question' not in st.session_state: | |
| st.session_state.current_question = 0 | |
| if 'exam_mode' not in st.session_state: | |
| st.session_state.exam_mode = 'practice' | |
| if 'start_time' not in st.session_state: | |
| st.session_state.start_time = None | |
| if 'user_profile' not in st.session_state: | |
| st.session_state.user_profile = { | |
| 'name': 'Math Explorer', | |
| 'total_exams': 0, | |
| 'total_questions': 0, | |
| 'correct_answers': 0, | |
| 'favorite_grade': 5, | |
| 'badges': [], | |
| 'streak': 0 | |
| } | |
| if 'seen_questions' not in st.session_state: | |
| st.session_state.seen_questions = set() | |
| def get_exam_system(): | |
| return MathOlympiadExam() | |
| def render_hero_section(): | |
| """Render the hero section with animations""" | |
| st.markdown(""" | |
| <div class="hero-header slide-in-up"> | |
| <div class="hero-title">🧮 MathGenius Academy</div> | |
| <div class="hero-subtitle">Master Mathematics Through Interactive Olympiad Training</div> | |
| <div style="margin-top: 1rem;"> | |
| <span style="background: rgba(255,255,255,0.2); padding: 0.5rem 1rem; border-radius: 25px; margin: 0 0.5rem;">🎯 Adaptive Learning</span> | |
| <span style="background: rgba(255,255,255,0.2); padding: 0.5rem 1rem; border-radius: 25px; margin: 0 0.5rem;">📊 Progress Tracking</span> | |
| <span style="background: rgba(255,255,255,0.2); padding: 0.5rem 1rem; border-radius: 25px; margin: 0 0.5rem;">🏆 Achievement System</span> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| def render_dashboard(): | |
| """Render user dashboard with statistics""" | |
| profile = st.session_state.user_profile | |
| st.markdown("### 📊 Your Learning Dashboard") | |
| col1, col2, col3, col4 = st.columns(4) | |
| with col1: | |
| st.markdown(f""" | |
| <div class="stat-card"> | |
| <div class="stat-number">{profile['total_exams']}</div> | |
| <div class="stat-label">Exams Taken</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with col2: | |
| accuracy = (profile['correct_answers'] / max(profile['total_questions'], 1)) * 100 | |
| st.markdown(f""" | |
| <div class="stat-card"> | |
| <div class="stat-number">{accuracy:.1f}%</div> | |
| <div class="stat-label">Accuracy</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with col3: | |
| st.markdown(f""" | |
| <div class="stat-card"> | |
| <div class="stat-number">{profile['streak']}</div> | |
| <div class="stat-label">Day Streak</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with col4: | |
| st.markdown(f""" | |
| <div class="stat-card"> | |
| <div class="stat-number">{len(profile['badges'])}</div> | |
| <div class="stat-label">Badges Earned</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Progress Chart | |
| if st.session_state.exam_history: | |
| df = pd.DataFrame(st.session_state.exam_history) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown("#### 📈 Performance Trend") | |
| fig = px.line(df, x='date', y='percentage', | |
| title='Your Progress Over Time', | |
| color_discrete_sequence=['#667eea']) | |
| fig.update_layout( | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| with col2: | |
| st.markdown("#### 🎯 Grade Distribution") | |
| grade_counts = df['grade'].value_counts().sort_index() | |
| fig = px.bar(x=grade_counts.index, y=grade_counts.values, | |
| title='Exams by Grade Level', | |
| color_discrete_sequence=['#764ba2']) | |
| fig.update_layout( | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)', | |
| ) | |
| st.plotly_chart(fig, use_container_width=True) | |
| def render_question_card(question, question_index, total_questions): | |
| """Render an individual question with enhanced UI""" | |
| progress = ((question_index + 1) / total_questions) * 100 | |
| st.markdown(f""" | |
| <div class="progress-container"> | |
| <div class="progress-bar" style="width: {progress}%;"> | |
| Question {question_index + 1} of {total_questions} | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown(f""" | |
| <div class="question-card slide-in-up"> | |
| <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;"> | |
| <h3 style="color: #667eea; margin: 0;">Question {question['question_number']}</h3> | |
| <span style="background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 0.25rem 0.75rem; border-radius: 15px; font-size: 0.8rem;"> | |
| {question.get('difficulty', 'Medium')} Level | |
| </span> | |
| </div> | |
| <div style="font-size: 1.1rem; font-weight: 500; margin-bottom: 1.5rem; line-height: 1.6; color: #222;"> | |
| {question['question_text']} | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Options with enhanced styling | |
| option_labels = [opt.split(')', 1)[1].strip() for opt in question['options']] | |
| option_keys = [opt.split(')', 1)[0].strip() for opt in question['options']] | |
| selected = st.radio( | |
| "Choose your answer:", | |
| options=option_keys, | |
| format_func=lambda x, labels=option_labels, keys=option_keys: f"{x}) {labels[keys.index(x)]}", | |
| key=f"q_{question_index}", | |
| index=None | |
| ) | |
| # Hint system | |
| if st.button(f"💡 Need a hint?", key=f"hint_{question_index}"): | |
| if question.get('hint'): | |
| st.info(f"💡 **Hint:** {question['hint']}") | |
| else: | |
| st.info("💡 **Hint:** Try breaking down the problem step by step!") | |
| return selected | |
| def render_exam_interface(): | |
| """Render the main exam interface""" | |
| questions = st.session_state.questions | |
| total_questions = len(questions) | |
| if st.session_state.exam_mode == 'timed': | |
| # Timer display | |
| if st.session_state.start_time: | |
| elapsed = time.time() - st.session_state.start_time | |
| remaining = max(0, (total_questions * 120) - elapsed) # 2 minutes per question | |
| mins, secs = divmod(int(remaining), 60) | |
| st.markdown(f""" | |
| <div style="text-align: center; margin-bottom: 1rem;"> | |
| <div style="background: linear-gradient(135deg, #FF6B6B, #FF8E8E); color: white; | |
| padding: 1rem; border-radius: 15px; display: inline-block; font-size: 1.5rem; font-weight: 600;"> | |
| ⏰ {mins:02d}:{secs:02d} | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| if remaining <= 0: | |
| st.error("⏰ Time's up! Submitting your exam...") | |
| st.session_state.exam_completed = True | |
| st.rerun() | |
| # Question navigation | |
| if total_questions > 1: | |
| st.markdown("#### 📍 Question Navigation") | |
| cols = st.columns(min(10, total_questions)) | |
| for i in range(total_questions): | |
| with cols[i % 10]: | |
| status = "✅" if questions[i]['user_answer'] else "⭕" | |
| if st.button(f"{status} Q{i+1}", key=f"nav_{i}"): | |
| st.session_state.current_question = i | |
| # Current question | |
| current_q = st.session_state.current_question | |
| if current_q < total_questions: | |
| selected = render_question_card(questions[current_q], current_q, total_questions) | |
| questions[current_q]['user_answer'] = selected | |
| # Navigation buttons | |
| col1, col2, col3 = st.columns([1, 2, 1]) | |
| with col1: | |
| if current_q > 0: | |
| if st.button("⬅️ Previous", key="prev_btn"): | |
| st.session_state.current_question -= 1 | |
| st.rerun() | |
| with col3: | |
| if current_q < total_questions - 1: | |
| if st.button("Next ➡️", key="next_btn"): | |
| st.session_state.current_question += 1 | |
| st.rerun() | |
| else: | |
| if st.button("🎯 Submit Exam", key="submit_btn", type="primary"): | |
| unanswered = [i+1 for i, q in enumerate(questions) if not q['user_answer']] | |
| if unanswered: | |
| st.error(f"⚠️ Please answer all questions. Missing: {', '.join(map(str, unanswered))}") | |
| else: | |
| st.session_state.exam_completed = True | |
| st.rerun() | |
| def calculate_badges(score, total, grade): | |
| """Calculate badges earned based on performance""" | |
| percentage = (score / total) * 100 | |
| badges = [] | |
| if percentage == 100: | |
| badges.append("🏆 Perfect Score") | |
| elif percentage >= 90: | |
| badges.append("⭐ Excellence") | |
| elif percentage >= 80: | |
| badges.append("🎯 High Achiever") | |
| elif percentage >= 70: | |
| badges.append("📚 Good Progress") | |
| if grade >= 8: | |
| badges.append("🚀 Advanced Level") | |
| return badges | |
| def render_results_section(): | |
| """Render enhanced results with animations and insights - REMOVED ACTION BUTTONS""" | |
| st.markdown("---") | |
| st.markdown("### 🎉 Exam Results") | |
| questions = st.session_state.questions | |
| correct_count = sum(1 for q in questions if q['user_answer'] == q['correct_answer']) | |
| total_questions = len(questions) | |
| percentage = (correct_count / total_questions) * 100 | |
| # Update user profile | |
| profile = st.session_state.user_profile | |
| profile['total_exams'] += 1 | |
| profile['total_questions'] += total_questions | |
| profile['correct_answers'] += correct_count | |
| # Add to history | |
| st.session_state.exam_history.append({ | |
| 'date': datetime.now(), | |
| 'grade': st.session_state.grade_selected, | |
| 'score': correct_count, | |
| 'total': total_questions, | |
| 'percentage': percentage | |
| }) | |
| # Calculate badges | |
| new_badges = calculate_badges(correct_count, total_questions, st.session_state.grade_selected) | |
| profile['badges'].extend(new_badges) | |
| # Animated score reveal | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.markdown(f""" | |
| <div class="stat-card pulse-animation"> | |
| <div class="stat-number">{correct_count}/{total_questions}</div> | |
| <div class="stat-label">Final Score</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with col2: | |
| st.markdown(f""" | |
| <div class="stat-card pulse-animation"> | |
| <div class="stat-number">{percentage:.1f}%</div> | |
| <div class="stat-label">Accuracy</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with col3: | |
| if percentage >= 90: | |
| grade_emoji = "🏆" | |
| grade_text = "Excellent!" | |
| elif percentage >= 80: | |
| grade_emoji = "⭐" | |
| grade_text = "Great Job!" | |
| elif percentage >= 70: | |
| grade_emoji = "👍" | |
| grade_text = "Good Work!" | |
| else: | |
| grade_emoji = "📚" | |
| grade_text = "Keep Practicing!" | |
| st.markdown(f""" | |
| <div class="stat-card pulse-animation"> | |
| <div class="stat-number">{grade_emoji}</div> | |
| <div class="stat-label">{grade_text}</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # New badges notification | |
| if new_badges: | |
| st.success(f"🎉 New badges earned: {', '.join(new_badges)}") | |
| # Detailed question review | |
| st.markdown("#### 📝 Question Review") | |
| for i, question in enumerate(questions): | |
| is_correct = question['user_answer'] == question['correct_answer'] | |
| with st.expander(f"Question {i+1} - {'✅ Correct' if is_correct else '❌ Incorrect'} ({question.get('difficulty', 'Medium')} Level)"): | |
| st.markdown(f"**Question:** {question['question_text']}") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown(f"**Your Answer:** {question['user_answer']}") | |
| with col2: | |
| st.markdown(f"**Correct Answer:** {question['correct_answer']}") | |
| if question.get('explanation'): | |
| st.markdown(f"**Explanation:** {question['explanation']}") | |
| if not is_correct and question.get('hint'): | |
| st.info(f"💡 **Hint for next time:** {question['hint']}") | |
| # Performance insights | |
| exam_system = get_exam_system() | |
| if exam_system.client: | |
| st.markdown("#### 🧠 AI Performance Analysis") | |
| with st.spinner("Generating personalized insights..."): | |
| summary = generate_enhanced_summary( | |
| st.session_state.grade_selected, | |
| questions, | |
| correct_count, | |
| total_questions, | |
| exam_system | |
| ) | |
| st.markdown(f""" | |
| <div class="custom-card"> | |
| {summary} | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Show completion message instead of action buttons | |
| st.markdown("#### 🎓 Exam Complete!") | |
| st.info("Great job completing the exam! Use the sidebar to generate a new exam or check out the Dashboard tab to view your progress.") | |
| def generate_enhanced_summary(grade, questions, score, total, exam_system): | |
| """Generate enhanced AI-powered performance summary""" | |
| try: | |
| # Analyze performance patterns | |
| correct_questions = [q for q in questions if q['user_answer'] == q['correct_answer']] | |
| incorrect_questions = [q for q in questions if q['user_answer'] != q['correct_answer']] | |
| difficulty_analysis = {} | |
| for q in questions: | |
| diff = q.get('difficulty', 'Medium') | |
| if diff not in difficulty_analysis: | |
| difficulty_analysis[diff] = {'correct': 0, 'total': 0} | |
| difficulty_analysis[diff]['total'] += 1 | |
| if q['user_answer'] == q['correct_answer']: | |
| difficulty_analysis[diff]['correct'] += 1 | |
| percentage = (score / total * 100) if total > 0 else 0 | |
| prompt = f"""Analyze this Math Olympiad performance for a Grade {grade} student: | |
| PERFORMANCE SUMMARY: | |
| - Score: {score}/{total} ({percentage:.1f}%) | |
| - Difficulty Breakdown: {difficulty_analysis} | |
| SAMPLE INCORRECT QUESTIONS: | |
| {chr(10).join([f"- {q['question_text'][:100]}..." for q in incorrect_questions[:2]])} | |
| Please provide a concise summary (max 4-5 sentences) with: | |
| - 1-2 key strengths | |
| - 1 main area to improve | |
| - 1 motivational message | |
| Use simple, encouraging language for a Grade {grade} student. Avoid long lists or detailed study plans.""" | |
| response = exam_system.client.chat.completions.create( | |
| model="llama-3.3-70b-versatile", | |
| messages=[ | |
| {"role": "system", "content": "You are an expert Math Olympiad mentor providing detailed, encouraging feedback to help students improve."}, | |
| {"role": "user", "content": prompt} | |
| ], | |
| temperature=0.3, | |
| max_tokens=1000 | |
| ) | |
| return response.choices[0].message.content | |
| except Exception as e: | |
| return f""" | |
| **Performance Summary:** | |
| You scored {score} out of {total} ({percentage:.1f}%). | |
| Great job! You showed strong skills in several areas. Focus on reviewing the questions you missed. Keep practicing and you'll get even better! 🌟 | |
| """ | |
| def reset_exam(): | |
| """Reset exam state for new attempt""" | |
| st.session_state.questions = [] | |
| st.session_state.exam_completed = False | |
| st.session_state.current_question = 0 | |
| st.session_state.start_time = None | |
| st.rerun() | |
| def render_sidebar(): | |
| """Enhanced sidebar with user profile and settings""" | |
| exam_system = get_exam_system() | |
| with st.sidebar: | |
| # User profile section | |
| st.markdown(f""" | |
| <div style="text-align: center; padding: 1rem; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| border-radius: 15px; color: white; margin-bottom: 1rem;"> | |
| <div style="font-size: 3rem; margin-bottom: 0.5rem;">👋</div> | |
| <div style="font-size: 1.2rem; font-weight: 600;">{st.session_state.user_profile['name']}</div> | |
| <div style="font-size: 0.9rem; opacity: 0.9;">Level {st.session_state.user_profile['favorite_grade']} Explorer</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown("### ⚙️ Exam Configuration") | |
| # Grade selection with enhanced UI | |
| grade_options = list(exam_system.grade_levels.keys()) | |
| grade_labels = [f"{exam_system.grade_levels[g]['emoji']} {exam_system.grade_levels[g]['name']}" for g in grade_options] | |
| grade = st.selectbox( | |
| "🎯 Select Grade Level:", | |
| options=grade_options, | |
| format_func=lambda x: f"{exam_system.grade_levels[x]['emoji']} {exam_system.grade_levels[x]['name']}", | |
| key="grade_selector", | |
| help="Choose your current grade level for appropriate difficulty" | |
| ) | |
| # Exam mode | |
| exam_mode = st.radio( | |
| "📝 Exam Mode:", | |
| ["practice", "timed", "challenge"], | |
| format_func=lambda x: { | |
| "practice": "🎯 Practice Mode", | |
| "timed": "⏰ Timed Mode", | |
| "challenge": "🔥 Challenge Mode" | |
| }[x], | |
| help="Practice: No time limit | Timed: 2 min/question | Challenge: Extra hard questions" | |
| ) | |
| st.session_state.exam_mode = exam_mode | |
| # Number of questions | |
| if exam_mode == "challenge": | |
| num_questions = st.slider("📊 Questions:", 5, 20, 10, help="Challenge mode: 5-20 questions") | |
| else: | |
| num_questions = st.slider("📊 Questions:", 3, 15, 5, help="Choose number of questions") | |
| # Difficulty level | |
| difficulty = st.select_slider( | |
| "⚡ Difficulty:", | |
| options=["easy", "medium", "hard"], | |
| value="medium", | |
| format_func=lambda x: { | |
| "easy": "🟢 Easy", | |
| "medium": "🟡 Medium", | |
| "hard": "🔴 Hard" | |
| }[x] | |
| ) | |
| # Generate exam button | |
| if st.button("🚀 Generate New Exam", type="primary", use_container_width=True): | |
| if not exam_system.client: | |
| st.error("🚫 API not available!") | |
| else: | |
| with st.spinner(f"🎭 Creating your {exam_mode} exam..."): | |
| # Add loading animation | |
| progress_bar = st.progress(0) | |
| for i in range(100): | |
| time.sleep(0.01) | |
| progress_bar.progress(i + 1) | |
| challenge_difficulty = "hard" if exam_mode == "challenge" else difficulty | |
| questions = exam_system.generate_questions(grade, num_questions, challenge_difficulty) | |
| if questions: | |
| # Filter out previously seen questions | |
| if 'seen_questions' in st.session_state: | |
| new_questions = [q for q in questions if q['question_text'] not in st.session_state.seen_questions] | |
| st.session_state.questions = new_questions | |
| # Update seen_questions with the new questions | |
| st.session_state.seen_questions.update(q['question_text'] for q in new_questions) | |
| else: | |
| st.session_state.questions = questions | |
| st.session_state.exam_completed = False | |
| st.session_state.grade_selected = grade | |
| st.session_state.current_question = 0 | |
| st.session_state.start_time = time.time() if exam_mode == "timed" else None | |
| st.success(f"✨ Generated {len(st.session_state.questions)} questions!") | |
| st.balloons() | |
| else: | |
| st.error("❌ Failed to generate exam. Try again!") | |
| st.markdown("---") | |
| # Quick stats | |
| profile = st.session_state.user_profile | |
| st.markdown("### 📈 Quick Stats") | |
| st.metric("🎯 Total Exams", profile['total_exams']) | |
| if profile['total_questions'] > 0: | |
| accuracy = (profile['correct_answers'] / profile['total_questions']) * 100 | |
| st.metric("🎪 Accuracy", f"{accuracy:.1f}%") | |
| st.metric("🔥 Streak", f"{profile['streak']} days") | |
| # Recent badges | |
| if profile['badges']: | |
| st.markdown("### 🏆 Recent Badges") | |
| for badge in profile['badges'][-3:]: | |
| st.markdown(f"- {badge}") | |
| st.markdown("---") | |
| # Settings | |
| with st.expander("⚙️ Settings"): | |
| new_name = st.text_input("Your Name:", value=profile['name']) | |
| if new_name != profile['name']: | |
| profile['name'] = new_name | |
| st.success("Name updated!") | |
| if st.button("🗑️ Reset Progress"): | |
| if st.checkbox("I'm sure"): | |
| initialize_session_state() | |
| st.success("Progress reset!") | |
| st.rerun() | |
| def render_welcome_screen(): | |
| """Render welcome screen for new users""" | |
| # Main welcome container | |
| st.markdown(""" | |
| <div class="custom-card slide-in-up" style="text-align: center; padding: 3rem;"> | |
| <div style="font-size: 4rem; margin-bottom: 1rem;">🌟</div> | |
| <h2 style="color: #667eea; margin-bottom: 1rem;">Welcome to MathGenius Academy!</h2> | |
| <p style="font-size: 1.2rem; color: #666; margin-bottom: 2rem;"> | |
| Ready to embark on an exciting mathematical journey? Let's discover your potential! | |
| </p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Feature cards using Streamlit columns for better compatibility | |
| st.markdown("### ✨ What Makes Us Special") | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.markdown(""" | |
| <div style="background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 1.5rem; border-radius: 15px; text-align: center; height: 200px; display: flex; flex-direction: column; justify-content: center;"> | |
| <div style="font-size: 3rem; margin-bottom: 1rem;">🎯</div> | |
| <h4 style="margin: 0.5rem 0; color: white;">Adaptive Learning</h4> | |
| <p style="margin: 0; color: rgba(255,255,255,0.9);">Questions adjust to your skill level</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with col2: | |
| st.markdown(""" | |
| <div style="background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 1.5rem; border-radius: 15px; text-align: center; height: 200px; display: flex; flex-direction: column; justify-content: center;"> | |
| <div style="font-size: 3rem; margin-bottom: 1rem;">📊</div> | |
| <h4 style="margin: 0.5rem 0; color: white;">Progress Tracking</h4> | |
| <p style="margin: 0; color: rgba(255,255,255,0.9);">See your improvement over time</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with col3: | |
| st.markdown(""" | |
| <div style="background: linear-gradient(135deg, #667eea, #764ba2); color: white; padding: 1.5rem; border-radius: 15px; text-align: center; height: 200px; display: flex; flex-direction: column; justify-content: center;"> | |
| <div style="font-size: 3rem; margin-bottom: 1rem;">🏆</div> | |
| <h4 style="margin: 0.5rem 0; color: white;">Achievement System</h4> | |
| <p style="margin: 0; color: rgba(255,255,255,0.9);">Earn badges and unlock new levels</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Getting started message | |
| st.markdown("---") | |
| st.info("👈 Choose your grade level from the sidebar and click 'Generate New Exam' to begin your mathematical adventure!") | |
| # Quick start tips | |
| with st.expander("🚀 Quick Start Guide"): | |
| st.markdown(""" | |
| **Ready to begin? Follow these simple steps:** | |
| 1. **🎯 Choose Your Grade**: Select your current grade level from the sidebar | |
| 2. **📝 Pick Your Mode**: | |
| - 🟢 **Practice Mode**: No time pressure, perfect for learning | |
| - ⏰ **Timed Mode**: Challenge yourself with time limits | |
| - 🔥 **Challenge Mode**: Extra difficult questions for advanced learners | |
| 3. **⚡ Set Difficulty**: Easy, Medium, or Hard - pick what feels right | |
| 4. **📊 Choose Questions**: 3-20 questions depending on your time | |
| 5. **🚀 Generate & Start**: Hit the generate button and begin! | |
| **💡 Pro Tips:** | |
| - Start with Practice mode to get comfortable | |
| - Use hints when you're stuck - learning is the goal! | |
| - Review all explanations to understand concepts better | |
| - Track your progress in the Dashboard tab | |
| """) | |
| # Motivational quote | |
| st.markdown(""" | |
| <div style="text-align: center; margin: 2rem 0; padding: 2rem; background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); border-radius: 20px; color: white;"> | |
| <h3 style="margin: 0; color: white;">"Mathematics is not about numbers, equations, or algorithms. It is about understanding." - William Paul Thurston</h3> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| def main(): | |
| # Load custom CSS | |
| load_custom_css() | |
| # Initialize session state | |
| initialize_session_state() | |
| # Get exam system | |
| exam_system = get_exam_system() | |
| # Render hero section | |
| render_hero_section() | |
| # Main navigation | |
| tab1, tab2, tab3 = st.tabs(["🎯 Exam", "📊 Dashboard", "ℹ️ About"]) | |
| with tab1: | |
| # Render sidebar | |
| render_sidebar() | |
| # Main exam interface | |
| if not st.session_state.questions: | |
| render_welcome_screen() | |
| elif st.session_state.exam_completed: | |
| render_results_section() | |
| else: | |
| st.markdown("### 🧮 Math Olympiad Challenge") | |
| if st.session_state.exam_mode == "timed" and st.session_state.start_time: | |
| # Show exam info | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.info(f"📚 Grade {st.session_state.grade_selected}") | |
| with col2: | |
| st.info(f"⏱️ {st.session_state.exam_mode.title()} Mode") | |
| with col3: | |
| st.info(f"📝 {len(st.session_state.questions)} Questions") | |
| render_exam_interface() | |
| with tab2: | |
| render_dashboard() | |
| # Additional dashboard features | |
| if st.session_state.exam_history: | |
| st.markdown("#### 🎯 Detailed Analytics") | |
| df = pd.DataFrame(st.session_state.exam_history) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown("##### 📊 Score Distribution") | |
| fig = px.histogram(df, x='percentage', nbins=10, | |
| title='Score Distribution', | |
| color_discrete_sequence=['#667eea']) | |
| fig.update_layout(plot_bgcolor='rgba(0,0,0,0)', paper_bgcolor='rgba(0,0,0,0)') | |
| st.plotly_chart(fig, use_container_width=True) | |
| with col2: | |
| st.markdown("##### 📈 Improvement Trend") | |
| df_trend = df.copy() | |
| df_trend['moving_avg'] = df_trend['percentage'].rolling(window=3, min_periods=1).mean() | |
| fig = go.Figure() | |
| fig.add_trace(go.Scatter(x=df_trend['date'], y=df_trend['percentage'], | |
| mode='markers+lines', name='Actual Score', | |
| line=dict(color='#667eea'))) | |
| fig.add_trace(go.Scatter(x=df_trend['date'], y=df_trend['moving_avg'], | |
| mode='lines', name='Trend', | |
| line=dict(color='#764ba2', dash='dash'))) | |
| fig.update_layout(title='Performance Trend', | |
| plot_bgcolor='rgba(0,0,0,0)', | |
| paper_bgcolor='rgba(0,0,0,0)') | |
| st.plotly_chart(fig, use_container_width=True) | |
| # Achievement showcase | |
| profile = st.session_state.user_profile | |
| if profile['badges']: | |
| st.markdown("#### 🏆 Your Achievements") | |
| badge_cols = st.columns(min(4, len(profile['badges']))) | |
| for i, badge in enumerate(profile['badges'][-8:]): # Show last 8 badges | |
| with badge_cols[i % 4]: | |
| st.markdown(f""" | |
| <div style="text-align: center; background: linear-gradient(135deg, #667eea, #764ba2); | |
| color: white; padding: 1rem; border-radius: 15px; margin-bottom: 1rem;"> | |
| <div style="font-size: 1.5rem; margin-bottom: 0.5rem;">{badge.split()[0]}</div> | |
| <div style="font-size: 0.8rem;">{' '.join(badge.split()[1:])}</div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with tab3: | |
| st.markdown("# 📖 About MathGenius Academy") | |
| # Mission section | |
| with st.container(): | |
| st.markdown("## 🎯 Our Mission") | |
| st.markdown(""" | |
| <div class="custom-card"> | |
| <p style="font-size: 1.1rem; line-height: 1.6; color: #444;"> | |
| To make mathematics accessible, engaging, and fun for students of all levels through | |
| interactive Olympiad-style training. We believe every student can excel in mathematics | |
| with the right guidance and practice. | |
| </p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Features section | |
| st.markdown("## ✨ Key Features") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown( | |
| """ | |
| <div class="custom-card"> | |
| <h4 style="color: #667eea;">🤖 AI-Powered Learning</h4> | |
| <ul style="color: #444;"> | |
| <li><strong>Adaptive Questions:</strong> Problems that match your skill level</li> | |
| <li><strong>Smart Difficulty:</strong> Automatic adjustment based on performance</li> | |
| <li><strong>Personalized Feedback:</strong> Detailed insights and recommendations</li> | |
| </ul> | |
| <h4 style="color: #667eea;">🎮 Multiple Game Modes</h4> | |
| <ul style="color: #444;"> | |
| <li><strong>Practice Mode:</strong> Learn at your own pace</li> | |
| <li><strong>Timed Mode:</strong> Build speed and confidence</li> | |
| <li><strong>Challenge Mode:</strong> Push your limits with hard problems</li> | |
| </ul> | |
| </div> | |
| """, | |
| unsafe_allow_html=True | |
| ) | |
| with col2: | |
| st.markdown( | |
| """ | |
| <div class="custom-card"> | |
| <h4 style="color: #667eea;">📊 Progress & Analytics</h4> | |
| <ul style="color: #444;"> | |
| <li><strong>Performance Tracking:</strong> Monitor improvement over time</li> | |
| <li><strong>Detailed Statistics:</strong> Accuracy, trends, and insights</li> | |
| <li><strong>Visual Charts:</strong> Interactive graphs and analysis</li> | |
| </ul> | |
| <h4 style="color: #667eea;">🏆 Achievement System</h4> | |
| <ul style="color: #444;"> | |
| <li><strong>Badges & Rewards:</strong> Celebrate your success</li> | |
| <li><strong>Streak Tracking:</strong> Build consistent study habits</li> | |
| <li><strong>Level Progression:</strong> Unlock new challenges</li> | |
| </ul> | |
| </div> | |
| """, | |
| unsafe_allow_html=True | |
| ) | |
| # Getting Started Guide | |
| st.markdown("## 🚀 Getting Started") | |
| steps_col1, steps_col2 = st.columns(2) | |
| with steps_col1: | |
| st.markdown(""" | |
| <div class="custom-card"> | |
| <h4 style="color: #667eea;">📋 Setup Steps</h4> | |
| <ol style="color: #444;"> | |
| <li><strong>Select Grade Level:</strong> Choose from Grade 1-10</li> | |
| <li><strong>Pick Exam Mode:</strong> Practice, Timed, or Challenge</li> | |
| <li><strong>Set Difficulty:</strong> Easy, Medium, or Hard</li> | |
| <li><strong>Choose Questions:</strong> 3-20 questions per exam</li> | |
| <li><strong>Generate Exam:</strong> Click the generate button</li> | |
| </ol> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with steps_col2: | |
| st.markdown(""" | |
| <div class="custom-card"> | |
| <h4 style="color: #667eea;">💡 Success Tips</h4> | |
| <ul style="color: #444;"> | |
| <li><strong>Start Easy:</strong> Begin with Practice mode</li> | |
| <li><strong>Use Hints:</strong> Don't hesitate to ask for help</li> | |
| <li><strong>Review Mistakes:</strong> Learn from wrong answers</li> | |
| <li><strong>Track Progress:</strong> Check your Dashboard regularly</li> | |
| <li><strong>Stay Consistent:</strong> Practice a little each day</li> | |
| </ul> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Grade Level Guide | |
| st.markdown("## 🎯 Grade Level Guide") | |
| grade_col1, grade_col2, grade_col3 = st.columns(3) | |
| with grade_col1: | |
| st.markdown(""" | |
| <div class="custom-card"> | |
| <h4 style="color: #667eea;">🌱 Elementary (Grades 1-4)</h4> | |
| <ul style="color: #444;"> | |
| <li>Basic arithmetic operations</li> | |
| <li>Simple word problems</li> | |
| <li>Pattern recognition</li> | |
| <li>Basic geometry shapes</li> | |
| <li>Counting and number sense</li> | |
| </ul> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with grade_col2: | |
| st.markdown(""" | |
| <div class="custom-card"> | |
| <h4 style="color: #667eea;">🚀 Middle School (Grades 5-8)</h4> | |
| <ul style="color: #444;"> | |
| <li>Pre-algebra concepts</li> | |
| <li>Fractions and decimals</li> | |
| <li>Basic statistics</li> | |
| <li>Coordinate geometry</li> | |
| <li>Problem-solving strategies</li> | |
| </ul> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with grade_col3: | |
| st.markdown(""" | |
| <div class="custom-card"> | |
| <h4 style="color: #667eea;">⭐ High School (Grades 9-10)</h4> | |
| <ul style="color: #444;"> | |
| <li>Advanced algebra</li> | |
| <li>Geometry proofs</li> | |
| <li>Trigonometry basics</li> | |
| <li>Complex problem solving</li> | |
| <li>Mathematical reasoning</li> | |
| </ul> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # FAQ Section | |
| with st.expander("❓ Frequently Asked Questions"): | |
| st.markdown(""" | |
| **Q: How are the questions generated?** | |
| A: We use advanced AI to create unique, grade-appropriate questions that follow Math Olympiad standards. | |
| **Q: Can I retake exams?** | |
| A: Yes! You can generate unlimited exams to practice and improve your skills. | |
| **Q: How is my progress tracked?** | |
| A: We track your accuracy, response times, difficulty preferences, and improvement trends over time. | |
| **Q: What if I get stuck on a question?** | |
| A: Use the hint feature! We provide helpful hints to guide your thinking without giving away the answer. | |
| **Q: Is there a time limit?** | |
| A: Only in Timed Mode. Practice and Challenge modes let you work at your own pace. | |
| **Q: How do I earn badges?** | |
| A: Badges are earned automatically based on your performance, consistency, and achievements. | |
| """) | |
| # Footer | |
| st.markdown("---") | |
| st.markdown(""" | |
| <div style="text-align: center; padding: 2rem; background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); border-radius: 20px; color: white;"> | |
| <h3 style="color: white; margin-bottom: 1rem;">Ready to become a Math Genius? 🧮</h3> | |
| <p style="color: rgba(255,255,255,0.9); margin: 0;"> | |
| Join thousands of students improving their mathematical skills every day! | |
| </p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown("<br>", unsafe_allow_html=True) | |
| st.markdown("**Made with ❤️ for young mathematicians everywhere!**") | |
| if __name__ == "__main__": | |
| main() |