Spaces:
Build error
Build error
| import streamlit as st | |
| import sqlite3 | |
| import json | |
| import random | |
| from datetime import datetime | |
| import os | |
| # Import our custom modules | |
| from components.mcq_generator import MCQGenerator | |
| from utils.wiki_api import WikiAPI | |
| from utils.translator import Translator | |
| # Page configuration | |
| st.set_page_config( | |
| page_title="TriviaVerse - Multilingual Quiz Generator", | |
| page_icon="🧠", | |
| layout="wide", | |
| initial_sidebar_state="expanded" | |
| ) | |
| # Initialize session state | |
| if 'current_quiz' not in st.session_state: | |
| st.session_state.current_quiz = None | |
| if 'score' not in st.session_state: | |
| st.session_state.score = 0 | |
| if 'current_question' not in st.session_state: | |
| st.session_state.current_question = 0 | |
| if 'user_answers' not in st.session_state: | |
| st.session_state.user_answers = [] | |
| # Initialize components | |
| def initialize_components(): | |
| wiki_api = WikiAPI() | |
| translator = Translator() | |
| mcq_generator = MCQGenerator() | |
| return wiki_api, translator, mcq_generator | |
| def initialize_database(): | |
| """Initialize SQLite database for offline storage""" | |
| conn = sqlite3.connect('triviaverse.db') | |
| cursor = conn.cursor() | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS cached_content ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| topic TEXT NOT NULL, | |
| language TEXT NOT NULL, | |
| content TEXT NOT NULL, | |
| summary TEXT, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ) | |
| ''') | |
| cursor.execute(''' | |
| CREATE TABLE IF NOT EXISTS quiz_history ( | |
| id INTEGER PRIMARY KEY AUTOINCREMENT, | |
| topic TEXT NOT NULL, | |
| language TEXT NOT NULL, | |
| difficulty TEXT NOT NULL, | |
| mode TEXT NOT NULL, | |
| score INTEGER, | |
| total_questions INTEGER, | |
| created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP | |
| ) | |
| ''') | |
| conn.commit() | |
| conn.close() | |
| def main(): | |
| # Initialize database | |
| initialize_database() | |
| # Initialize components | |
| wiki_api, translator, mcq_generator = initialize_components() | |
| # Custom CSS | |
| st.markdown(""" | |
| <style> | |
| .main-header { | |
| text-align: center; | |
| background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| font-size: 3rem; | |
| font-weight: bold; | |
| margin-bottom: 2rem; | |
| } | |
| .quiz-card { | |
| background: white; | |
| padding: 2rem; | |
| border-radius: 15px; | |
| box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); | |
| margin: 1rem 0; | |
| } | |
| .score-display { | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| padding: 1rem; | |
| border-radius: 10px; | |
| text-align: center; | |
| font-size: 1.2rem; | |
| font-weight: bold; | |
| } | |
| .question-card { | |
| background: #f8f9fa; | |
| padding: 1.5rem; | |
| border-radius: 10px; | |
| border-left: 4px solid #667eea; | |
| margin: 1rem 0; | |
| } | |
| .sidebar-section { | |
| background: #f0f2f6; | |
| padding: 1rem; | |
| border-radius: 10px; | |
| margin: 1rem 0; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # Main header | |
| st.markdown('<h1 class="main-header">🧠 TriviaVerse</h1>', unsafe_allow_html=True) | |
| st.markdown('<p style="text-align: center; font-size: 1.2rem; color: #666;">Multilingual AI-Powered Quiz Generator</p>', unsafe_allow_html=True) | |
| # Sidebar configuration | |
| with st.sidebar: | |
| st.markdown('<div class="sidebar-section">', unsafe_allow_html=True) | |
| st.header("🎯 Quiz Configuration") | |
| # Language selection | |
| languages = { | |
| 'en': 'English', | |
| 'hi': 'हिंदी (Hindi)', | |
| 'te': 'తెలుగు (Telugu)', | |
| 'ta': 'தமிழ் (Tamil)', | |
| 'kn': 'ಕನ್ನಡ (Kannada)', | |
| 'bn': 'বাংলা (Bengali)' | |
| } | |
| selected_language = st.selectbox( | |
| "🌐 Select Language", | |
| options=list(languages.keys()), | |
| format_func=lambda x: languages[x], | |
| index=0 | |
| ) | |
| # Topic input | |
| topic = st.text_input("📚 Enter Topic", placeholder="e.g., Indian History, Science, Technology") | |
| # Mode selection | |
| mode = st.selectbox( | |
| "🎮 Select Mode", | |
| options=['mcq', 'flashcard', 'game'], | |
| format_func=lambda x: { | |
| 'mcq': '📝 Multiple Choice Questions', | |
| 'flashcard': '🃏 Flashcards', | |
| 'game': '🎲 Quiz Game' | |
| }[x] | |
| ) | |
| # Difficulty level | |
| difficulty = st.selectbox( | |
| "⚡ Difficulty Level", | |
| options=['easy', 'medium', 'hard'], | |
| format_func=lambda x: { | |
| 'easy': '🟢 Easy', | |
| 'medium': '🟡 Medium', | |
| 'hard': '🔴 Hard' | |
| }[x] | |
| ) | |
| # Online/Offline toggle | |
| is_online = st.toggle("🌐 Online Mode", value=True) | |
| # Number of questions | |
| num_questions = st.slider("📊 Number of Questions", min_value=5, max_value=20, value=10) | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Generate quiz button | |
| if st.button("🚀 Generate Quiz", type="primary", use_container_width=True): | |
| if topic: | |
| generate_quiz(wiki_api, translator, mcq_generator, topic, selected_language, | |
| difficulty, mode, is_online, num_questions) | |
| else: | |
| st.error("Please enter a topic!") | |
| # Quiz history | |
| st.markdown('<div class="sidebar-section">', unsafe_allow_html=True) | |
| st.subheader("📈 Recent Quizzes") | |
| display_quiz_history() | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Main content area | |
| if st.session_state.current_quiz: | |
| display_quiz() | |
| else: | |
| display_welcome_screen() | |
| def generate_quiz(wiki_api, translator, mcq_generator, topic, language, difficulty, mode, is_online, num_questions): | |
| """Generate a new quiz based on user parameters""" | |
| with st.spinner(f"🔍 Fetching content about '{topic}'..."): | |
| # Fetch content from Wikipedia | |
| if is_online: | |
| content = wiki_api.fetch_content(topic, language) | |
| if not content: | |
| st.error("❌ Could not fetch content. Try offline mode or a different topic.") | |
| return | |
| else: | |
| content = load_cached_content(topic, language) | |
| if not content: | |
| st.error("❌ No cached content found. Please try online mode first.") | |
| return | |
| with st.spinner("🧠 Generating quiz questions..."): | |
| # Generate questions | |
| questions = mcq_generator.generate_questions( | |
| content, difficulty, num_questions, language, translator | |
| ) | |
| if not questions: | |
| st.error("❌ Could not generate questions. Please try a different topic.") | |
| return | |
| # Store quiz in session state | |
| st.session_state.current_quiz = { | |
| 'topic': topic, | |
| 'language': language, | |
| 'difficulty': difficulty, | |
| 'mode': mode, | |
| 'questions': questions, | |
| 'created_at': datetime.now() | |
| } | |
| # Reset quiz state | |
| st.session_state.current_question = 0 | |
| st.session_state.score = 0 | |
| st.session_state.user_answers = [] | |
| # Cache content for offline use | |
| if is_online: | |
| cache_content(topic, language, content) | |
| st.success(f"✅ Generated {len(questions)} questions successfully!") | |
| st.rerun() | |
| def display_quiz(): | |
| """Display the current quiz""" | |
| quiz = st.session_state.current_quiz | |
| questions = quiz['questions'] | |
| current_q = st.session_state.current_question | |
| # Progress bar | |
| progress = (current_q + 1) / len(questions) | |
| st.progress(progress, text=f"Question {current_q + 1} of {len(questions)}") | |
| # Score display | |
| if current_q > 0: | |
| st.markdown(f'<div class="score-display">Score: {st.session_state.score}/{current_q}</div>', | |
| unsafe_allow_html=True) | |
| if current_q < len(questions): | |
| question = questions[current_q] | |
| # Display question | |
| st.markdown(f'<div class="question-card">', unsafe_allow_html=True) | |
| st.markdown(f"### Question {current_q + 1}") | |
| st.markdown(f"**{question['question']}**") | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Display options | |
| if quiz['mode'] == 'mcq': | |
| display_mcq_options(question, current_q) | |
| elif quiz['mode'] == 'flashcard': | |
| display_flashcard(question, current_q) | |
| else: # game mode | |
| display_game_mode(question, current_q) | |
| else: | |
| # Quiz completed | |
| display_quiz_results() | |
| def display_mcq_options(question, current_q): | |
| """Display multiple choice options""" | |
| options = question['options'] | |
| # Use unique key for each question | |
| selected_option = st.radio( | |
| "Select your answer:", | |
| options=options, | |
| key=f"q_{current_q}", | |
| index=None | |
| ) | |
| col1, col2 = st.columns([1, 1]) | |
| with col1: | |
| if st.button("Submit Answer", key=f"submit_{current_q}"): | |
| if selected_option is not None: | |
| answer_index = options.index(selected_option) | |
| is_correct = answer_index == question['correct_answer'] | |
| if is_correct: | |
| st.success("✅ Correct!") | |
| st.session_state.score += 1 | |
| else: | |
| st.error(f"❌ Incorrect! The correct answer is: {options[question['correct_answer']]}") | |
| # Show explanation | |
| if question.get('explanation'): | |
| st.info(f"💡 Explanation: {question['explanation']}") | |
| st.session_state.user_answers.append({ | |
| 'question': question['question'], | |
| 'user_answer': selected_option, | |
| 'correct_answer': options[question['correct_answer']], | |
| 'is_correct': is_correct | |
| }) | |
| st.session_state.current_question += 1 | |
| # Auto-advance after 3 seconds | |
| st.rerun() | |
| else: | |
| st.warning("Please select an answer!") | |
| with col2: | |
| if st.button("Skip Question", key=f"skip_{current_q}"): | |
| st.session_state.user_answers.append({ | |
| 'question': question['question'], | |
| 'user_answer': "Skipped", | |
| 'correct_answer': options[question['correct_answer']], | |
| 'is_correct': False | |
| }) | |
| st.session_state.current_question += 1 | |
| st.rerun() | |
| def display_flashcard(question, current_q): | |
| """Display flashcard mode""" | |
| if f"show_answer_{current_q}" not in st.session_state: | |
| st.session_state[f"show_answer_{current_q}"] = False | |
| if not st.session_state[f"show_answer_{current_q}"]: | |
| if st.button("🔍 Show Answer", key=f"show_{current_q}"): | |
| st.session_state[f"show_answer_{current_q}"] = True | |
| st.rerun() | |
| else: | |
| st.success(f"**Answer:** {question['options'][question['correct_answer']]}") | |
| if question.get('explanation'): | |
| st.info(f"💡 Explanation: {question['explanation']}") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.button("✅ I knew it!", key=f"correct_{current_q}"): | |
| st.session_state.score += 1 | |
| st.session_state.current_question += 1 | |
| st.rerun() | |
| with col2: | |
| if st.button("❌ I didn't know", key=f"incorrect_{current_q}"): | |
| st.session_state.current_question += 1 | |
| st.rerun() | |
| def display_game_mode(question, current_q): | |
| """Display game mode with timer""" | |
| # Simple game mode - similar to MCQ but with time pressure | |
| st.markdown("⏰ **Quick Answer Mode!**") | |
| display_mcq_options(question, current_q) | |
| def display_quiz_results(): | |
| """Display final quiz results""" | |
| quiz = st.session_state.current_quiz | |
| total_questions = len(quiz['questions']) | |
| score = st.session_state.score | |
| percentage = (score / total_questions) * 100 | |
| st.balloons() | |
| # Results header | |
| st.markdown('<div class="score-display">', unsafe_allow_html=True) | |
| st.markdown(f"## 🎉 Quiz Completed!") | |
| st.markdown(f"### Final Score: {score}/{total_questions} ({percentage:.1f}%)") | |
| st.markdown('</div>', unsafe_allow_html=True) | |
| # Performance message | |
| if percentage >= 80: | |
| st.success("🌟 Excellent! You're a trivia master!") | |
| elif percentage >= 60: | |
| st.info("👍 Good job! Keep learning!") | |
| else: | |
| st.warning("📚 Keep studying! You'll do better next time!") | |
| # Save to history | |
| save_quiz_history(quiz, score, total_questions) | |
| # Detailed results | |
| st.subheader("📊 Detailed Results") | |
| for i, answer in enumerate(st.session_state.user_answers): | |
| with st.expander(f"Question {i+1}: {answer['question'][:50]}..."): | |
| st.write(f"**Your Answer:** {answer['user_answer']}") | |
| st.write(f"**Correct Answer:** {answer['correct_answer']}") | |
| if answer['is_correct']: | |
| st.success("✅ Correct") | |
| else: | |
| st.error("❌ Incorrect") | |
| # Reset button | |
| if st.button("🔄 Take Another Quiz", type="primary"): | |
| st.session_state.current_quiz = None | |
| st.session_state.current_question = 0 | |
| st.session_state.score = 0 | |
| st.session_state.user_answers = [] | |
| st.rerun() | |
| def display_welcome_screen(): | |
| """Display welcome screen when no quiz is active""" | |
| col1, col2, col3 = st.columns([1, 2, 1]) | |
| with col2: | |
| st.markdown(""" | |
| <div style="text-align: center; padding: 2rem;"> | |
| <h2>🎯 Welcome to TriviaVerse!</h2> | |
| <p style="font-size: 1.1rem; color: #666;"> | |
| Generate intelligent quizzes on any topic in multiple Indian languages | |
| </p> | |
| <div style="margin: 2rem 0;"> | |
| <h3>✨ Features</h3> | |
| <ul style="text-align: left; display: inline-block;"> | |
| <li>🌐 Multi-language support (Hindi, Telugu, Tamil, Kannada, Bengali)</li> | |
| <li>📚 Wikipedia & Wikidata integration</li> | |
| <li>🧠 AI-powered question generation</li> | |
| <li>🎮 Multiple quiz modes (MCQ, Flashcards, Games)</li> | |
| <li>📊 Difficulty levels and progress tracking</li> | |
| <li>💾 Offline mode with caching</li> | |
| </ul> | |
| </div> | |
| <p style="color: #667eea; font-weight: bold;"> | |
| 👈 Configure your quiz in the sidebar and click "Generate Quiz" to start! | |
| </p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| def load_cached_content(topic, language): | |
| """Load content from local cache""" | |
| conn = sqlite3.connect('triviaverse.db') | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT content FROM cached_content | |
| WHERE topic = ? AND language = ? | |
| ORDER BY created_at DESC LIMIT 1 | |
| """, (topic, language)) | |
| result = cursor.fetchone() | |
| conn.close() | |
| return result[0] if result else None | |
| def cache_content(topic, language, content): | |
| """Cache content for offline use""" | |
| conn = sqlite3.connect('triviaverse.db') | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| INSERT INTO cached_content (topic, language, content) | |
| VALUES (?, ?, ?) | |
| """, (topic, language, content)) | |
| conn.commit() | |
| conn.close() | |
| def save_quiz_history(quiz, score, total_questions): | |
| """Save quiz results to history""" | |
| conn = sqlite3.connect('triviaverse.db') | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| INSERT INTO quiz_history (topic, language, difficulty, mode, score, total_questions) | |
| VALUES (?, ?, ?, ?, ?, ?) | |
| """, (quiz['topic'], quiz['language'], quiz['difficulty'], | |
| quiz['mode'], score, total_questions)) | |
| conn.commit() | |
| conn.close() | |
| def display_quiz_history(): | |
| """Display recent quiz history""" | |
| conn = sqlite3.connect('triviaverse.db') | |
| cursor = conn.cursor() | |
| cursor.execute(""" | |
| SELECT topic, score, total_questions, created_at | |
| FROM quiz_history | |
| ORDER BY created_at DESC | |
| LIMIT 5 | |
| """) | |
| results = cursor.fetchall() | |
| conn.close() | |
| if results: | |
| for result in results: | |
| topic, score, total, created_at = result | |
| percentage = (score / total) * 100 | |
| st.write(f"📚 {topic}: {score}/{total} ({percentage:.0f}%)") | |
| else: | |
| st.write("No quiz history yet!") | |
| if __name__ == "__main__": | |
| main() |