import streamlit as st import os from fpdf import FPDF import uuid import time # Initialize session state variables if 'session_id' not in st.session_state: st.session_state.session_id = str(uuid.uuid4()) if 'questions' not in st.session_state: st.session_state.questions = [] if 'current_index' not in st.session_state: st.session_state.current_index = 0 if 'current_module' not in st.session_state: st.session_state.current_module = None if 'correct_count' not in st.session_state: st.session_state.correct_count = 0 if 'module_correct_count' not in st.session_state: st.session_state.module_correct_count = {} if 'module_question_count' not in st.session_state: st.session_state.module_question_count = {} if 'pdf_data' not in st.session_state: st.session_state.pdf_data = None if 'selected_answer' not in st.session_state: st.session_state.selected_answer = None if 'button_label' not in st.session_state: st.session_state.button_label = "Submit/New" if 'start_time' not in st.session_state: st.session_state.start_time = time.time() def reset_pdf_cache(): st.session_state.pdf_data = None def generate_pdf_report(): pdf = FPDF() pdf.add_page() pdf.set_font("Arial", style='B', size=12) # Header for PDF report pdf.set_fill_color(211, 211, 211) # Light gray pdf.cell(0, 10, txt="Magic Math Quiz!", ln=True, align="C", fill=True) pdf.ln(5) pdf.set_font("Arial", size=8) pdf.cell(0, 10, txt="by Ghassem Tofighi", ln=True, align="C", link="https://ghassem.com") pdf.ln(10) for i, entry in enumerate(st.session_state.questions): # Zebra background if i % 2 == 0: pdf.set_fill_color(245, 245, 245) # Light gray else: pdf.set_fill_color(255, 255, 255) # White # Module Title pdf.set_font("Arial", style='B', size=10) pdf.multi_cell(0, 10, f"Module: {entry['module_title']}", border=1, fill=True) # Question pdf.set_font("Arial", style='B', size=10) pdf.multi_cell(0, 10, f"Q{i+1}: {entry['question']}", border=1, fill=True) # Time Taken pdf.set_font("Arial", size=10) pdf.multi_cell(0, 10, f"Time Taken: {entry['time_taken']} seconds", border=1, fill=True) # Options pdf.set_font("Arial", size=10) options = ['a', 'b', 'c', 'd'] for j, option in enumerate(entry['options']): if option == entry['correct_answer']: pdf.set_text_color(0, 128, 0) # Green for correct elif option == entry['selected']: pdf.set_text_color(255, 0, 0) # Red for incorrect else: pdf.set_text_color(0, 0, 0) # Default color for others pdf.multi_cell(0, 10, f"{options[j]}. {option}", border=1, fill=True) pdf.set_text_color(0, 0, 0) # Reset color pdf.multi_cell(0, 10, f"Explanation: {entry['explanation']}", border=1, fill=True) pdf.multi_cell(0, 10, f"Step-by-Step Solution: {', '.join(entry['step_by_step_solution'])}", border=1, fill=True) pdf.ln(10) return pdf.output(dest='S').encode('latin1', 'replace') def load_modules(): modules = {} base_dir = "modules" for category in os.listdir(base_dir): category_dir = os.path.join(base_dir, category) if os.path.isdir(category_dir): config_path = os.path.join(category_dir, "config.py") if os.path.exists(config_path): config = {} with open(config_path) as f: exec(f.read(), config) category_title = config.get("title", category.title().replace("_", " ")) else: category_title = category.title().replace("_", " ") modules[category_title] = {} for filename in os.listdir(category_dir): if filename.endswith(".py") and filename != "__init__.py" and filename != "config.py": module_name = filename[:-3] module = __import__(f"{category_dir.replace('/', '.')}.{module_name}", fromlist=['']) modules[category_title][module_name] = { "title": getattr(module, "title", module_name.replace("_", " ").title()), "description": getattr(module, "description", "No description available."), "generate_question": module.generate_question # Access the generate_question function } return modules def generate_new_question(category_name, module_name, module): question_data = module['generate_question']() # Ensure 'answered' is initialized to False and add the 'module' and 'selected' keys question_data['answered'] = False question_data['category'] = category_name # Add the category name to the question data question_data['module'] = module_name # Add the module name to the question data question_data['module_title'] = module['title'] # Add the module title to the question data question_data['selected'] = None # Initialize 'selected' to None question_data['time_taken'] = 0 # Initialize time taken to 0 # Ensure there are exactly 4 options if len(question_data['options']) != 4: st.warning(f"Question in module '{module_name}' does not have 4 options. Found {len(question_data['options'])}.") return question_data # Load all modules dynamically modules = load_modules() # Streamlit sidebar st.sidebar.title("Magic Math Quiz!") st.sidebar.markdown("