import streamlit as st from io import StringIO import json # Set the page configuration st.set_page_config(page_title="📚 Multiple Choice Test Creator", layout="wide") # Initialize session state for storing tests if 'tests' not in st.session_state: st.session_state['tests'] = [] # Initialize session state for current questions being added if 'current_questions' not in st.session_state: st.session_state['current_questions'] = [] # Function to add a new question def add_question(): if len(st.session_state['current_questions']) < 10: st.session_state['current_questions'].append({ 'question': '', 'options': {'A': '', 'B': '', 'C': '', 'D': ''}, 'correct': 'A' }) else: st.warning("You can only add up to 10 questions.") # Function to remove a question def remove_question(index): st.session_state['current_questions'].pop(index) # Function to generate HTML content for the test def generate_html(test_title, questions): html_content = f""" {test_title}
{test_title}
""" for idx, q in enumerate(questions, 1): html_content += f"""
Question {idx}: {q['question']}
""" html_content += """ """ return html_content # Tabs for navigation tabs = st.tabs(["📝 Create Test", "📖 Take Test"]) # -------------------- Create Test Tab -------------------- # with tabs[0]: st.header("Create a New Multiple-Choice Test") # Input for Test Title test_title = st.text_input("Enter Test Title", "") # Button to add a new question st.button("➕ Add a Question", on_click=add_question) # Display existing questions for idx, q in enumerate(st.session_state['current_questions']): with st.expander(f"Question {idx + 1}", expanded=True): # Question Text question_key = f"question_{idx}" question_text = st.text_input("Question Text", value=q['question'], key=question_key) st.session_state['current_questions'][idx]['question'] = question_text # Answer Options for option in ['A', 'B', 'C', 'D']: option_key = f"question_{idx}_option_{option}" option_text = st.text_input(f"Answer {option}", value=q['options'][option], key=option_key) st.session_state['current_questions'][idx]['options'][option] = option_text # Correct Answer Selector correct_option_key = f"question_{idx}_correct" correct_option = st.selectbox("Select Correct Answer", options=['A', 'B', 'C', 'D'], index=['A','B','C','D'].index(q['correct']), key=correct_option_key) st.session_state['current_questions'][idx]['correct'] = correct_option # Remove Question Button if st.button("🗑️ Remove", key=f"remove_{idx}"): remove_question(idx) st.experimental_rerun() # Button to create the test if st.button("✅ Create Test"): if not test_title: st.error("Please enter a test title.") elif len(st.session_state['current_questions']) == 0: st.error("Please add at least one question.") else: # Validate that all questions have all fields filled incomplete = False for idx, q in enumerate(st.session_state['current_questions'], 1): if not q['question'] or not all(q['options'][opt] for opt in ['A','B','C','D']): st.error(f"Question {idx} is incomplete. Please fill in all fields.") incomplete = True break if not incomplete: # Add the test to the session state test = { 'title': test_title, 'questions': st.session_state['current_questions'].copy() } st.session_state['tests'].append(test) st.success(f"Test '{test_title}' created successfully!") # Clear current questions after creation st.session_state['current_questions'] = [] # Provide download button html_content = generate_html(test_title, test['questions']) st.download_button( label="📄 Download Test as HTML", data=html_content, file_name=f"{test_title.replace(' ', '_')}.html", mime="text/html" ) # Optionally, display the test st.markdown("---") st.header("📝 Your Test") st.markdown(html_content, unsafe_allow_html=True) # -------------------- Take Test Tab -------------------- # with tabs[1]: st.header("Take a Multiple-Choice Test") if len(st.session_state['tests']) == 0: st.info("No tests available. Please create a test first.") else: # Select a test to take test_titles = [test['title'] for test in st.session_state['tests']] selected_test_title = st.selectbox("Select a Test to Take", options=test_titles) # Retrieve the selected test selected_test = next((test for test in st.session_state['tests'] if test['title'] == selected_test_title), None) if selected_test: # Initialize session state for user answers if not present if 'user_answers' not in st.session_state: st.session_state['user_answers'] = {} with st.form("take_test_form"): for idx, q in enumerate(selected_test['questions'], start=1): st.markdown(f"**{idx}. {q['question']}**") # Prepare options with letters and text option_list = [ f"A. {q['options']['A']}", f"B. {q['options']['B']}", f"C. {q['options']['C']}", f"D. {q['options']['D']}" ] # Create radio buttons with the full option text answer = st.radio( f"Select an answer for Question {idx}", options=option_list, key=f"test_{selected_test_title}_q{idx}" ) # Store the selected answer's letter st.session_state['user_answers'][idx] = answer.split(".")[0].strip() st.markdown("---") # Submit button submit = st.form_submit_button("Submit Test") if submit: # Grade the test score = 0 total = len(selected_test['questions']) feedback = [] for idx, q in enumerate(selected_test['questions'], start=1): user_ans = st.session_state['user_answers'].get(idx, None) correct_ans = q['correct'] is_correct = user_ans == correct_ans if is_correct: score += 1 feedback.append(f"**Question {idx}**: Correct ✅") else: feedback.append(f"**Question {idx}**: Incorrect ❌ (Correct Answer: {correct_ans})") # Display the result st.success(f"You scored {score} out of {total}.") # Display feedback with st.expander("View Feedback"): for fb in feedback: st.markdown(fb) # Optionally, clear answers for next test st.session_state['user_answers'] = {}