|
import streamlit as st |
|
import importlib |
|
import logging |
|
from fpdf import FPDF |
|
|
|
|
|
logging.basicConfig(level=logging.INFO) |
|
|
|
|
|
module_names = { |
|
"Bases": "presentation_bases", |
|
"Validity": "valid_invalid_numbers", |
|
"Conversion": "conversion_bases", |
|
"Grouping": "grouping_techniques", |
|
"Addition": "addition_bases", |
|
"2's Complement": "twos_complement", |
|
"Negative Numbers": "negative_binary", |
|
"Subtraction": "subtraction_bases", |
|
} |
|
|
|
|
|
if 'correct_count' not in st.session_state: |
|
st.session_state.correct_count = 0 |
|
if 'question_count' not in st.session_state: |
|
st.session_state.question_count = 0 |
|
if 'current_module' not in st.session_state: |
|
st.session_state.current_module = None |
|
if 'question_queue' not in st.session_state: |
|
st.session_state.question_queue = [] |
|
if 'submitted' not in st.session_state: |
|
st.session_state.submitted = False |
|
if 'current_question' not in st.session_state: |
|
st.session_state.current_question = None |
|
if 'options' not in st.session_state: |
|
st.session_state.options = [] |
|
if 'correct_answer' not in st.session_state: |
|
st.session_state.correct_answer = None |
|
if 'explanation' not in st.session_state: |
|
st.session_state.explanation = None |
|
if 'selected_answer' not in st.session_state: |
|
st.session_state.selected_answer = None |
|
|
|
def generate_pdf_report(): |
|
pdf = FPDF() |
|
pdf.add_page() |
|
pdf.set_font("Arial", size=12) |
|
|
|
pdf.cell(200, 10, txt="Quiz Report", ln=True, align="C") |
|
pdf.ln(10) |
|
|
|
for idx, entry in enumerate(st.session_state.question_queue): |
|
question, options, selected, correct, explanation = entry |
|
pdf.multi_cell(0, 10, f"Q{idx+1}: {question}") |
|
for option in options: |
|
if option == correct: |
|
pdf.multi_cell(0, 10, f"Correct: {option}") |
|
elif option == selected: |
|
pdf.multi_cell(0, 10, f"Your Choice: {option}") |
|
else: |
|
pdf.multi_cell(0, 10, f" {option}") |
|
pdf.multi_cell(0, 10, f"Explanation: {explanation}") |
|
pdf.ln(10) |
|
|
|
return pdf.output(dest='S').encode('latin1', 'replace') |
|
|
|
|
|
logging.info(f"Current Module: {st.session_state.current_module}") |
|
logging.info(f"Question Count: {st.session_state.question_count}") |
|
logging.info(f"Correct Count: {st.session_state.correct_count}") |
|
logging.info(f"Submitted: {st.session_state.submitted}") |
|
logging.info(f"Current Question: {st.session_state.current_question}") |
|
logging.info(f"Options: {st.session_state.options}") |
|
logging.info(f"Selected Answer: {st.session_state.selected_answer}") |
|
logging.info(f"Correct Answer: {st.session_state.correct_answer}") |
|
logging.info(f"Explanation: {st.session_state.explanation}") |
|
|
|
|
|
st.sidebar.title("Quiz Modules") |
|
module_name = st.sidebar.radio("Choose a module:", list(module_names.keys()), index=0) |
|
|
|
if module_name: |
|
if st.session_state.current_module != module_name: |
|
st.session_state.current_module = module_name |
|
st.session_state.question_count = 0 |
|
st.session_state.correct_count = 0 |
|
st.session_state.question_queue = [] |
|
st.session_state.current_question = None |
|
st.session_state.submitted = False |
|
logging.info("Module changed. Resetting session state.") |
|
|
|
module_file = module_names[module_name] |
|
try: |
|
module = importlib.import_module(f'modules.{module_file}') |
|
generate_question = module.generate_question |
|
title = getattr(module, 'title', f"{module_name} Module") |
|
description = getattr(module, 'description', "Description is not available") |
|
|
|
|
|
st.title(title) |
|
st.write(description) |
|
|
|
|
|
if st.session_state.current_question is None or st.session_state.submitted: |
|
st.session_state.current_question, st.session_state.options, st.session_state.correct_answer, st.session_state.explanation = generate_question() |
|
st.session_state.submitted = False |
|
st.session_state.selected_answer = None |
|
logging.info("Generated new question.") |
|
|
|
if st.session_state.question_count > 0: |
|
correct_percentage = (st.session_state.correct_count / st.session_state.question_count) * 100 |
|
st.write(f"**Correct Answers:** {st.session_state.correct_count}/{st.session_state.question_count} ({correct_percentage:.2f}%)") |
|
|
|
st.write(f"**Question {st.session_state.question_count + 1}:** {st.session_state.current_question}") |
|
st.session_state.selected_answer = st.radio("Choose an answer:", st.session_state.options, key=st.session_state.question_count) |
|
|
|
if st.button("Submit"): |
|
st.session_state.submitted = True |
|
st.session_state.question_count += 1 |
|
st.session_state.question_queue.append(( |
|
st.session_state.current_question, |
|
st.session_state.options, |
|
st.session_state.selected_answer, |
|
st.session_state.correct_answer, |
|
st.session_state.explanation |
|
)) |
|
|
|
if st.session_state.selected_answer == st.session_state.correct_answer: |
|
st.session_state.correct_count += 1 |
|
st.success("Correct!") |
|
else: |
|
st.error("Incorrect.") |
|
|
|
logging.info("Answer submitted.") |
|
logging.info(f"Selected Answer: {st.session_state.selected_answer}") |
|
logging.info(f"Correct Answer: {st.session_state.correct_answer}") |
|
|
|
|
|
st.markdown( |
|
f""" |
|
<div style='border: 2px solid #ccc; padding: 15px;'> |
|
<strong>Explanation:</strong> {st.session_state.explanation} |
|
</div> |
|
""", |
|
unsafe_allow_html=True |
|
) |
|
|
|
|
|
col1, col2, col3 = st.columns([1, 1, 2]) |
|
with col1: |
|
if st.session_state.submitted: |
|
if st.button("➡️ Next"): |
|
st.session_state.current_question = None |
|
logging.info("Navigated to next question.") |
|
with col2: |
|
if st.session_state.question_count > 1: |
|
if st.button("⬅️ Prev"): |
|
st.session_state.question_count -= 1 |
|
st.session_state.submitted = False |
|
question_data = st.session_state.question_queue[st.session_state.question_count - 1] |
|
st.session_state.current_question = question_data[0] |
|
st.session_state.options = question_data[1] |
|
st.session_state.selected_answer = question_data[2] |
|
st.session_state.correct_answer = question_data[3] |
|
st.session_state.explanation = question_data[4] |
|
logging.info("Navigated to previous question.") |
|
with col3: |
|
if st.session_state.question_count > 0: |
|
pdf = generate_pdf_report() |
|
st.download_button( |
|
label="Download PDF Report 📄", |
|
data=pdf, |
|
file_name="quiz_report.pdf", |
|
mime="application/pdf" |
|
) |
|
logging.info("PDF report generated.") |
|
|
|
except ModuleNotFoundError as e: |
|
st.error(f"The module '{module_name}' was not found. Please select another module.") |
|
logging.error(f"Error: {e}") |
|
except Exception as e: |
|
st.error(f"An unexpected error occurred: {str(e)}") |
|
logging.error(f"Error: {str(e)}") |
|
|