import streamlit as st import sys, os # ✅ FIX: Add project root first sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from config import APP_TITLE, APP_ICON, MAX_QUESTIONS # ✅ FIRST Streamlit call st.set_page_config( page_title=APP_TITLE, page_icon=APP_ICON, layout="centered", ) # Add project root to path sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) from src.evaluator import score_quiz from app.components import ( render_question_card, render_result_card, render_score_summary ) # ───────────────────────────────────────────── # CACHE MODEL (important for performance) # ───────────────────────────────────────────── @st.cache_resource def load_pipeline(): from src.mcq_builder import build_quiz return build_quiz build_quiz = load_pipeline() # ───────────────────────────────────────────── # SESSION STATE # ───────────────────────────────────────────── def init_state(): defaults = { "screen": "input", "mcqs": [], "current_q": 0, "user_answers": [], "quiz_result": None, } for k, v in defaults.items(): if k not in st.session_state: st.session_state[k] = v init_state() # ───────────────────────────────────────────── # RESET # ───────────────────────────────────────────── def reset(): st.session_state.screen = "input" st.session_state.mcqs = [] st.session_state.current_q = 0 st.session_state.user_answers = [] st.session_state.quiz_result = None # ───────────────────────────────────────────── # SCREEN 1: INPUT # ───────────────────────────────────────────── def screen_input(): st.title(f"{APP_ICON} {APP_TITLE}") st.write("Paste text to generate MCQs") passage = st.text_area( "Your passage", height=250, placeholder="Paste content here..." ) num_questions = st.slider( "Number of questions", 3, MAX_QUESTIONS, 5 ) if st.button("Generate Quiz", type="primary"): if not passage or len(passage.split()) < 30: st.warning("Enter at least 30 words") return with st.spinner("Generating questions..."): try: mcqs = build_quiz(passage, num_questions=num_questions) except Exception as e: st.error(f"Error: {e}") return if not mcqs: st.error("Failed to generate questions") return st.session_state.mcqs = mcqs st.session_state.user_answers = [-1] * len(mcqs) st.session_state.current_q = 0 st.session_state.screen = "quiz" st.rerun() # ───────────────────────────────────────────── # SCREEN 2: QUIZ # ───────────────────────────────────────────── def screen_quiz(): mcqs = st.session_state.mcqs current = st.session_state.current_q total = len(mcqs) mcq = mcqs[current] st.progress(current / total, text=f"Q {current+1}/{total}") selected_label = render_question_card(mcq, current) col1, col2, col3 = st.columns([1, 2, 1]) # Previous with col1: if current > 0: if st.button("← Prev"): st.session_state.current_q -= 1 st.rerun() # Next / Submit with col3: if selected_label: idx = ord(selected_label) - ord("A") st.session_state.user_answers[current] = idx if current < total - 1: if st.button("Next →", type="primary"): if selected_label is None: st.warning("Select an answer") else: st.session_state.current_q += 1 st.rerun() else: if st.button("Submit", type="primary"): result = score_quiz( st.session_state.mcqs, st.session_state.user_answers ) st.session_state.quiz_result = result st.session_state.screen = "results" st.rerun() # Quit with col2: if st.button("Quit"): reset() st.rerun() # ───────────────────────────────────────────── # SCREEN 3: RESULTS # ───────────────────────────────────────────── def screen_results(): result = st.session_state.quiz_result st.title("Quiz Complete") render_score_summary(result) for i, r in enumerate(result["results"]): render_result_card(r, i + 1) col1, col2 = st.columns(2) with col1: if st.button("New Quiz"): reset() st.rerun() with col2: if st.button("Retry"): st.session_state.user_answers = [-1] * len(st.session_state.mcqs) st.session_state.current_q = 0 st.session_state.screen = "quiz" st.rerun() # ───────────────────────────────────────────── # ROUTER # ───────────────────────────────────────────── if st.session_state.screen == "input": screen_input() elif st.session_state.screen == "quiz": screen_quiz() elif st.session_state.screen == "results": screen_results()