# 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"""

🌟 Did you know?

{fact["fact"]}

Topic: {fact["topic"]}

""", 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( """

Made with ❤️ using Streamlit and Wikimedia APIs

TriviaVerse v2.0 - Enhanced Edition

""", unsafe_allow_html=True, )