mcq_generator / app /main.py
tanmmayyy's picture
for deployment
a50befe
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()