Spaces:
Sleeping
Sleeping
| # app.py | |
| """TriviaVerse Enhanced - Advanced Quiz Application""" | |
| import streamlit as st | |
| import time | |
| from datetime import datetime | |
| from config.settings import ( | |
| APP_NAME, | |
| APP_DESCRIPTION, | |
| DIFFICULTY_LEVELS, | |
| BADGES, | |
| RANDOM_TOPICS, | |
| ) | |
| from config.themes import THEMES | |
| from modules.mcq_generator import generate_mcq | |
| from modules.flashcard_generator import generate_flashcard | |
| from modules.fact_game import generate_random_fact | |
| from modules.adaptive_engine import AdaptiveEngine | |
| from utils.ui_components import ( | |
| apply_custom_theme, | |
| display_user_stats, | |
| display_badges, | |
| create_progress_chart, | |
| animated_success, | |
| create_quiz_card, | |
| render_flashcard, | |
| ) | |
| from utils.score_tracker import ScoreTracker | |
| from utils.mobile_responsive import responsive_columns, responsive_css | |
| from utils.user_auth import init_authentication, authenticate_user | |
| # Page configuration | |
| st.set_page_config( | |
| page_title=f"{APP_NAME} - Enhanced Edition", | |
| page_icon="๐ฏ", | |
| layout="wide", | |
| initial_sidebar_state="expanded", | |
| menu_items={ | |
| "Get Help": "https://github.com/yourusername/triviaverse", | |
| "Report a bug": "https://github.com/yourusername/triviaverse/issues", | |
| "About": f"{APP_NAME} - A gamified learning platform powered by Wikimedia", | |
| }, | |
| ) | |
| # Initialize authentication | |
| init_authentication() | |
| # Check authentication | |
| if not authenticate_user(): | |
| st.stop() | |
| # Initialize session state | |
| if "user_id" not in st.session_state: | |
| st.session_state.user_id = st.session_state.get( | |
| "username", f"user_{int(time.time())}" | |
| ) | |
| if "score_tracker" not in st.session_state: | |
| st.session_state.score_tracker = ScoreTracker(st.session_state.user_id) | |
| if "theme" not in st.session_state: | |
| st.session_state.theme = "default" | |
| if "current_streak" not in st.session_state: | |
| st.session_state.current_streak = 0 | |
| if "adaptive_engine" not in st.session_state: | |
| st.session_state.adaptive_engine = AdaptiveEngine(st.session_state.user_id) | |
| # Initialize topic in session state | |
| if "topic" not in st.session_state: | |
| st.session_state.topic = "Python programming" | |
| # Apply theme and responsive CSS | |
| apply_custom_theme(st.session_state.theme) | |
| st.markdown(responsive_css(), unsafe_allow_html=True) | |
| # Sidebar with enhanced features | |
| with st.sidebar: | |
| st.title(f"๐ฏ {APP_NAME}") | |
| st.markdown("### ๐ฎ Game Settings") | |
| # User info | |
| st.info(f"๐ค Welcome, {st.session_state.get('username', 'Guest')}!") | |
| # Theme selector | |
| theme_select = st.selectbox( | |
| "๐จ Choose Theme", | |
| list(THEMES.keys()), | |
| index=list(THEMES.keys()).index(st.session_state.theme), | |
| ) | |
| if theme_select != st.session_state.theme: | |
| st.session_state.theme = theme_select | |
| st.rerun() | |
| st.divider() | |
| # Game mode selection with icons | |
| mode = st.radio( | |
| "๐ฒ Select Game Mode", | |
| ["๐งฉ MCQ Quiz", "๐ Flashcards", "๐ก Fact Game"], | |
| help="Choose your preferred learning mode", | |
| ) | |
| # Adaptive difficulty | |
| use_adaptive = st.checkbox("๐ค Use Adaptive Difficulty", value=True) | |
| if use_adaptive: | |
| difficulty = st.session_state.adaptive_engine.get_recommended_difficulty() | |
| st.info(f"Recommended: {difficulty}") | |
| else: | |
| difficulty = st.selectbox( | |
| "โก Difficulty Level", | |
| list(DIFFICULTY_LEVELS.keys()), | |
| format_func=lambda x: f"{x} - {DIFFICULTY_LEVELS[x]['description']}", | |
| ) | |
| # Enhanced topic input | |
| st.markdown("### ๐ Choose Topic") | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| # Use st.session_state.topic for the text input | |
| st.session_state.topic = st.text_input( | |
| "Enter topic", value=st.session_state.topic, label_visibility="collapsed" | |
| ) | |
| with col2: | |
| if st.button("๐ฒ", help="Random topic"): | |
| import random # random is still needed here | |
| st.session_state.topic = random.choice(RANDOM_TOPICS) | |
| st.rerun() | |
| # Popular topics | |
| st.markdown("### ๐ฅ Trending Topics") | |
| trending = [ | |
| "Machine Learning", | |
| "Blockchain", | |
| "Sustainability", | |
| "Genetics", | |
| "Cybersecurity", | |
| ] | |
| selected_trending = st.selectbox( | |
| "Quick select", [""] + trending, label_visibility="collapsed" | |
| ) | |
| if selected_trending: | |
| st.session_state.topic = selected_trending | |
| st.rerun() | |
| st.divider() | |
| # User stats in sidebar | |
| st.markdown("### ๐ Your Stats") | |
| stats = st.session_state.score_tracker.get_stats() | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.metric("Total Score", f"{stats['total_score']:,}") | |
| st.metric("Current Streak", f"๐ฅ {stats['current_streak']}") | |
| with col2: | |
| st.metric("Quizzes", stats["quizzes_completed"]) | |
| st.metric("Best Streak", f"โญ {stats['best_streak']}") | |
| # Display badges in sidebar | |
| if stats["badges"]: | |
| st.markdown("### ๐ Your Badges") | |
| for badge_id in stats["badges"]: | |
| badge = BADGES.get(badge_id, {}) | |
| st.write(f"{badge.get('icon', '๐')} {badge.get('name', badge_id)}") | |
| # Logout button | |
| if st.button("๐ช Logout", type="secondary", use_container_width=True): | |
| st.session_state.clear() # A more efficient way to clear the session state | |
| st.rerun() # Rerun to go back to the login page | |
| # Main content area | |
| # Header with user dashboard | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| st.title(f"๐ฎ {APP_NAME} - Enhanced Edition") | |
| st.markdown(f"*{APP_DESCRIPTION}*") | |
| with col2: | |
| # Display current time and greeting | |
| current_hour = datetime.now().hour | |
| greeting = ( | |
| "Good morning" | |
| if current_hour < 12 | |
| else "Good afternoon" | |
| if current_hour < 18 | |
| else "Good evening" | |
| ) | |
| st.markdown(f"### {greeting}, {st.session_state.get('username', 'Learner')}! ๐") | |
| st.caption(f"{datetime.now().strftime('%B %d, %Y - %I:%M %p')}") | |
| # Display user statistics dashboard | |
| stats = st.session_state.score_tracker.get_stats() | |
| display_user_stats(stats) | |
| # Display badges | |
| if stats["badges"]: | |
| st.markdown("### ๐ Your Achievements") | |
| display_badges(stats["badges"]) | |
| # Progress chart | |
| with st.expander("๐ View Detailed Progress", expanded=False): | |
| if stats["quizzes_completed"] > 0: | |
| fig = create_progress_chart(stats) | |
| st.plotly_chart(fig, use_container_width=True) | |
| else: | |
| st.info("Complete some quizzes to see your progress chart!") | |
| st.divider() | |
| # Main game area | |
| if "MCQ" in mode: | |
| st.header("๐งฉ Multiple Choice Quiz") | |
| # Quiz controls | |
| col1, col2, col3 = responsive_columns([1, 1, 1], [1, 1, 1]) | |
| with col1: | |
| if st.button("๐ฏ Generate Question", type="primary", use_container_width=True): | |
| with st.spinner("๐ค Generating question..."): | |
| mcq = generate_mcq(st.session_state.topic, difficulty) | |
| if mcq.get("status"): | |
| st.session_state.current_question = mcq | |
| st.session_state.question_start_time = time.time() | |
| st.session_state.hints_used = 0 | |
| st.session_state.answered = False | |
| with col2: | |
| time_limit = DIFFICULTY_LEVELS[difficulty]["time_limit"] | |
| st.info(f"โฑ๏ธ Time Limit: {time_limit}s") | |
| with col3: | |
| hints_allowed = DIFFICULTY_LEVELS[difficulty]["hints_allowed"] | |
| st.info(f"๐ก Hints: {hints_allowed}") | |
| # Display question if available | |
| if hasattr(st.session_state, "current_question") and not st.session_state.get( | |
| "answered", True | |
| ): | |
| mcq = st.session_state.current_question | |
| # Timer | |
| elapsed_time = int(time.time() - st.session_state.question_start_time) | |
| remaining_time = max(0, time_limit - elapsed_time) | |
| if remaining_time > 0: | |
| progress = remaining_time / time_limit | |
| st.progress(progress) | |
| st.caption(f"โฑ๏ธ Time remaining: {remaining_time}s") | |
| # Quiz card | |
| answer = create_quiz_card(mcq["question"], mcq["options"]) | |
| # Hint system | |
| if hints_allowed > st.session_state.hints_used: | |
| if st.button( | |
| f"๐ก Get Hint ({hints_allowed - st.session_state.hints_used} left)" | |
| ): | |
| st.session_state.hints_used += 1 | |
| st.info(f"๐ก Hint: {mcq['explanation'][:100]}...") | |
| # Submit answer | |
| col1, col2, col3 = st.columns([1, 2, 1]) | |
| with col2: | |
| if st.button( | |
| "โ Submit Answer", type="primary", use_container_width=True | |
| ): | |
| is_correct = answer == mcq["correct_answer"] | |
| st.session_state.answered = True | |
| # Update adaptive engine | |
| st.session_state.adaptive_engine.update_performance( | |
| is_correct, difficulty, topic=mcq.get("topic") | |
| ) | |
| # Update streak | |
| if is_correct: | |
| st.session_state.current_streak += 1 | |
| points = st.session_state.score_tracker.add_quiz_result( | |
| "MCQ Quiz", 1, 1, difficulty | |
| ) | |
| animated_success(f"Correct! +{points} points") | |
| st.balloons() | |
| else: | |
| st.session_state.current_streak = 0 | |
| st.error( | |
| f"โ Incorrect. The answer was: {mcq['correct_answer']}" | |
| ) | |
| st.info(f"๐ {mcq['explanation']}") | |
| else: | |
| st.error("โฑ๏ธ Time's up!") | |
| st.session_state.answered = True | |
| st.session_state.score_tracker.add_quiz_result("MCQ Quiz", 0, 1, difficulty) | |
| elif "Flashcards" in mode: | |
| st.header("๐ Interactive Flashcards") | |
| # Flashcard controls | |
| if st.button("๐ Generate Flashcard", type="primary"): | |
| with st.spinner("Creating flashcard..."): | |
| flashcard = generate_flashcard(st.session_state.topic) | |
| if flashcard.get("status"): | |
| st.session_state.current_flashcard = flashcard | |
| st.session_state.card_flipped = False | |
| # Display flashcard | |
| if hasattr(st.session_state, "current_flashcard"): | |
| flashcard = st.session_state.current_flashcard | |
| # Create flashcard UI | |
| col1, col2, col3 = st.columns([1, 2, 1]) | |
| with col2: | |
| render_flashcard( | |
| front_content=flashcard["front"], | |
| back_content=flashcard["back"], | |
| is_flipped=st.session_state.get("card_flipped", False), | |
| ) | |
| if not st.session_state.get("card_flipped", False): | |
| if st.button("๐ Flip Card", use_container_width=True): | |
| st.session_state.card_flipped = True | |
| st.rerun() | |
| else: | |
| # Add a small spacer for the buttons | |
| st.write("") | |
| btn_col1, btn_col2 = st.columns(2) | |
| with btn_col1: | |
| if st.button("โ Got it!", use_container_width=True): | |
| points = st.session_state.score_tracker.add_quiz_result( | |
| "Flashcards", 1, 1, difficulty | |
| ) | |
| animated_success(f"Great! +{points} points") | |
| st.session_state.card_flipped = False | |
| with btn_col2: | |
| if st.button("โ Need Practice", use_container_width=True): | |
| st.session_state.score_tracker.add_quiz_result( | |
| "Flashcards", 0, 1, difficulty | |
| ) | |
| st.session_state.card_flipped = False | |
| elif "Fact" in mode: | |
| st.header("๐ก Random Fact Game") | |
| # Fact game with timer | |
| col1, col2 = st.columns([2, 1]) | |
| with col1: | |
| if st.button("๐ฒ Get Random Fact", type="primary", use_container_width=True): | |
| with st.spinner("Finding an interesting fact..."): | |
| fact = generate_random_fact() | |
| if fact.get("status"): | |
| st.session_state.current_fact = fact | |
| st.session_state.fact_start_time = time.time() | |
| with col2: | |
| st.info("โฑ๏ธ Quick Read Challenge: 15s") | |
| # Display fact | |
| if hasattr(st.session_state, "current_fact"): | |
| fact = st.session_state.current_fact | |
| # Timer for reading | |
| elapsed = int(time.time() - st.session_state.fact_start_time) | |
| remaining = max(0, 15 - elapsed) | |
| if remaining > 0: | |
| st.progress(remaining / 15) | |
| st.markdown( | |
| f""" | |
| <div class="quiz-container"> | |
| <h3>๐ Did you know?</h3> | |
| <p style="font-size: 18px; line-height: 1.8;">{fact["fact"]}</p> | |
| <p style="margin-top: 20px; color: #666;">Topic: <strong>{fact["topic"]}</strong></p> | |
| </div> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| if st.button("โ Interesting! Next fact"): | |
| points = st.session_state.score_tracker.add_quiz_result( | |
| "Fact Game", 1, 1, difficulty | |
| ) | |
| animated_success(f"Knowledge gained! +{points} points") | |
| del st.session_state["current_fact"] | |
| st.rerun() | |
| else: | |
| st.success("โฑ๏ธ Time's up! Ready for the next fact?") | |
| if st.button("Next Fact"): | |
| del st.session_state["current_fact"] | |
| st.rerun() | |
| # Footer | |
| st.divider() | |
| col1, col2, col3 = st.columns([1, 2, 1]) | |
| with col2: | |
| st.markdown( | |
| """ | |
| <div style='text-align: center'> | |
| <p>Made with โค๏ธ using Streamlit and Wikimedia APIs</p> | |
| <p style='opacity: 0.7; font-size: 0.9em;'>TriviaVerse v2.0 - Enhanced Edition</p> | |
| </div> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |