Update app.py
Browse files
app.py
CHANGED
@@ -3,235 +3,267 @@ import google.generativeai as genai
|
|
3 |
import os
|
4 |
import re # For improved parsing
|
5 |
|
6 |
-
#
|
7 |
-
|
8 |
-
st.
|
9 |
|
10 |
-
|
11 |
-
|
|
|
12 |
|
13 |
-
if
|
14 |
-
|
15 |
-
|
16 |
-
else:
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
21 |
st.markdown("<font color='red'>**Warning:** Directly entering your API key is less secure than using Streamlit Secrets or environment variables. For production, use Secrets.</font>", unsafe_allow_html=True)
|
22 |
|
23 |
-
# Initialize session state for quiz data and progress
|
24 |
-
if 'quiz_data' not in st.session_state:
|
25 |
-
|
26 |
-
if 'current_question_index' not in st.session_state:
|
27 |
-
|
28 |
-
if 'user_answers' not in st.session_state:
|
29 |
-
|
30 |
-
if 'quiz_completed' not in st.session_state:
|
31 |
-
|
32 |
-
if 'score' not in st.session_state:
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
if
|
57 |
-
|
58 |
-
questions.append(current_question)
|
59 |
-
current_question = {'options': {}} # Start new question
|
60 |
-
current_question['question'] = re.sub(r'\*\*|\*', '', line).strip() # Question text, remove bold
|
61 |
-
elif re.match(r'^[A-D]\)\s', line) or re.match(r'^[A-D]\.\s', line): # Option line (handle both ')' and '.' after letter)
|
62 |
-
if current_question:
|
63 |
-
option_letter = line[0]
|
64 |
-
option_text = line[2:].strip() # Remove "A) " or "A. "
|
65 |
-
current_question['options'][option_letter] = option_text
|
66 |
-
elif re.match(r'^\*\*.*?\*\*$', line) or re.match(r'^\*.*?\*$', line) : # Check for title again, just in case after split. Remove bold title if found in lines.
|
67 |
-
pass # Ignore title lines within question section if any.
|
68 |
-
|
69 |
-
if current_question: # Append the last question
|
70 |
-
questions.append(current_question)
|
71 |
-
|
72 |
-
|
73 |
-
# --- Answer Key Parsing (No change needed) ---
|
74 |
-
answer_lines = answer_key_section.strip().split('\n')
|
75 |
-
for line in answer_lines:
|
76 |
-
line = line.strip()
|
77 |
-
match = re.match(r'(\d+)\.\s*([A-D])', line)
|
78 |
-
if match:
|
79 |
-
question_num = int(match.group(1)) - 1
|
80 |
-
correct_answer = match.group(2)
|
81 |
-
answer_key_dict[question_num] = correct_answer
|
82 |
-
|
83 |
-
# Basic validation
|
84 |
-
if not questions or not answer_key_dict:
|
85 |
-
st.error("Error parsing quiz content. Please try again or check the generated format.")
|
86 |
-
return None, None
|
87 |
-
if len(questions) != len(answer_key_dict):
|
88 |
-
st.warning(f"Number of questions parsed ({len(questions)}) does not match number of answers in answer key ({len(answer_key_dict)}). Parsing might be incomplete.")
|
89 |
-
|
90 |
-
|
91 |
-
# Combine parsed questions and answer key into quiz_data
|
92 |
-
quiz_data_list = []
|
93 |
-
for i, q_data in enumerate(questions):
|
94 |
-
correct_answer = answer_key_dict.get(i)
|
95 |
-
if correct_answer:
|
96 |
-
quiz_data_list.append({
|
97 |
-
'question': q_data['question'],
|
98 |
-
'options': q_data['options'],
|
99 |
-
'correct_answer': correct_answer
|
100 |
-
})
|
101 |
-
else:
|
102 |
-
st.warning(f"Could not find correct answer for question {i+1} in the answer key.")
|
103 |
return None, None
|
104 |
|
105 |
-
|
106 |
-
|
107 |
-
|
108 |
-
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
116 |
-
|
117 |
-
|
118 |
-
|
119 |
-
|
120 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
121 |
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
|
126 |
-
|
127 |
-
|
128 |
-
|
129 |
-
|
130 |
-
st.rerun()
|
131 |
-
|
132 |
-
|
133 |
-
def display_results():
|
134 |
-
"""Displays the quiz results after completion."""
|
135 |
-
if st.session_state.quiz_completed:
|
136 |
-
st.markdown("### Quiz Results")
|
137 |
-
correct_count = 0
|
138 |
-
for i in range(len(st.session_state.quiz_data)):
|
139 |
-
user_answer = st.session_state.user_answers[i] if i < len(st.session_state.user_answers) else None # Handle if user didn't answer all
|
140 |
-
correct_answer = st.session_state.quiz_data[i]['correct_answer']
|
141 |
-
if user_answer == correct_answer:
|
142 |
-
correct_count += 1
|
143 |
-
result_text = f"**Question {i+1}:** ✅ Correct! (Your answer: {user_answer}, Correct answer: {correct_answer})"
|
144 |
-
color = "green"
|
145 |
-
else:
|
146 |
-
result_text = f"**Question {i+1}:** ❌ Incorrect. (Your answer: {user_answer if user_answer else 'Not answered'}, Correct answer: {correct_answer})"
|
147 |
-
color = "red"
|
148 |
-
st.markdown(f"<font color='{color}'>{result_text}</font>", unsafe_allow_html=True)
|
149 |
-
|
150 |
-
percentage_correct = (correct_count / len(st.session_state.quiz_data)) * 100
|
151 |
-
st.markdown(f"### Final Score: {correct_count} out of {len(st.session_state.quiz_data)} correct ({percentage_correct:.2f}%)")
|
152 |
-
st.session_state.score = correct_count # Store score in session state
|
153 |
-
|
154 |
-
|
155 |
-
# User input for topic
|
156 |
-
topic = st.text_input("Enter the topic for your quiz:")
|
157 |
-
|
158 |
-
if topic:
|
159 |
-
if st.button("Generate Quiz"):
|
160 |
-
with st.spinner(f"Generating quiz on '{topic}'..."):
|
161 |
-
try:
|
162 |
-
prompt = f"""
|
163 |
-
Generate a multiple-choice quiz on the topic of "{topic}".
|
164 |
-
The quiz should have 5 questions.
|
165 |
-
|
166 |
-
**Formatting Instructions:**
|
167 |
-
|
168 |
-
1. **Question Numbering:** Start each question with a number followed by a period (e.g., "1.").
|
169 |
-
2. **Question Text:** Immediately after the question number, write the question text.
|
170 |
-
3. **Options:**
|
171 |
-
* List four options for each question, labeled A, B, C, and D.
|
172 |
-
* Use the format: "A) Option text", "B) Option text", etc. (letter followed by a parenthesis, then a space, then the option text).
|
173 |
-
* Place each option on a new line directly below the question.
|
174 |
-
4. **Answer Key:**
|
175 |
-
* After all questions, create a separate section titled "**Answer Key:**".
|
176 |
-
* In the Answer Key, list the correct answer for each question in the format: "1. Correct option letter", "2. Correct option letter", etc. (question number, period, space, correct option letter - A, B, C, or D).
|
177 |
-
|
178 |
-
**Example of Desired Format:**
|
179 |
-
|
180 |
-
**Quiz Title (Optional, but good to have)**
|
181 |
-
|
182 |
-
1. Question 1 text?
|
183 |
-
A) Option A
|
184 |
-
B) Option B
|
185 |
-
C) Option C
|
186 |
-
D) Option D
|
187 |
-
|
188 |
-
2. Question 2 text?
|
189 |
-
A) Option A
|
190 |
-
B) Option B
|
191 |
-
C) Option C
|
192 |
-
D) Option D
|
193 |
-
|
194 |
-
... (and so on for 5 questions) ...
|
195 |
-
|
196 |
-
**Answer Key:**
|
197 |
-
1. C
|
198 |
-
2. A
|
199 |
-
3. B
|
200 |
-
4. D
|
201 |
-
5. A
|
202 |
-
|
203 |
-
Please generate the quiz in this exact format.
|
204 |
-
"""
|
205 |
-
response = model.generate_content(prompt)
|
206 |
-
quiz_content = response.text
|
207 |
-
|
208 |
-
|
209 |
-
parsed_quiz_data, answer_key = parse_quiz_content(quiz_content)
|
210 |
-
|
211 |
-
|
212 |
-
if quiz_content: # Check if quiz_content was generated successfully (outer if)
|
213 |
-
if parsed_quiz_data: # Check if parsing was successful (inner if)
|
214 |
-
st.session_state.quiz_data = parsed_quiz_data
|
215 |
-
st.session_state.current_question_index = 0
|
216 |
-
st.session_state.user_answers = []
|
217 |
-
st.session_state.quiz_completed = False
|
218 |
-
st.session_state.score = 0
|
219 |
-
st.success(f"Quiz on '{topic}' generated successfully! Let's begin.")
|
220 |
-
else: # else associated with inner if parsed_quiz_data
|
221 |
-
st.error("Failed to parse quiz content. Please try generating again.")
|
222 |
-
st.session_state.quiz_data = None
|
223 |
-
else: # else associated with outer if quiz_content
|
224 |
-
st.error("Failed to generate quiz content. Please try again or check your API key.")
|
225 |
-
|
226 |
-
except Exception as e:
|
227 |
-
st.error(f"An error occurred: {e}")
|
228 |
-
st.error("Please check your API key and network connection. If the problem persists, try a different topic or try again later.")
|
229 |
-
|
230 |
-
# Quiz Display Logic
|
231 |
-
if st.session_state.quiz_data:
|
232 |
-
if not st.session_state.quiz_completed:
|
233 |
-
display_question()
|
234 |
-
else:
|
235 |
-
display_results()
|
236 |
-
elif topic and not st.session_state.quiz_data and not st.session_state.quiz_completed: # Message if topic entered but quiz not generated yet
|
237 |
-
st.info("Click 'Generate Quiz' to start the quiz.")
|
|
|
3 |
import os
|
4 |
import re # For improved parsing
|
5 |
|
6 |
+
# --- Login Page ---
|
7 |
+
def login_page():
|
8 |
+
st.title("Quiz Generator Login")
|
9 |
|
10 |
+
api_options = ["Gemini API"] # Extend this list for more APIs in the future
|
11 |
+
selected_api = st.selectbox("Select API:", api_options)
|
12 |
+
api_key = st.text_input(f"Enter your {selected_api} Key:", type="password")
|
13 |
|
14 |
+
if st.button("Login"):
|
15 |
+
if not api_key:
|
16 |
+
st.error("Please enter your API key.")
|
17 |
+
else:
|
18 |
+
st.session_state.api_key = api_key
|
19 |
+
st.session_state.selected_api = selected_api
|
20 |
+
st.session_state.logged_in = True
|
21 |
+
st.success(f"Logged in with {selected_api}!")
|
22 |
+
st.rerun() # Rerun to show the quiz app
|
23 |
+
|
24 |
+
# --- Quiz Application ---
|
25 |
+
def quiz_app():
|
26 |
+
st.title("Interactive Multiple Choice Quiz Generator")
|
27 |
+
st.markdown("Powered by Gemini API") # Keeping this as title, can be dynamically updated if more APIs are added
|
28 |
+
|
29 |
+
# Security Warning - Moved here as it is part of the quiz app
|
30 |
st.markdown("<font color='red'>**Warning:** Directly entering your API key is less secure than using Streamlit Secrets or environment variables. For production, use Secrets.</font>", unsafe_allow_html=True)
|
31 |
|
32 |
+
# Initialize session state for quiz data and progress (if not already initialized during login)
|
33 |
+
if 'quiz_data' not in st.session_state:
|
34 |
+
st.session_state.quiz_data = None
|
35 |
+
if 'current_question_index' not in st.session_state:
|
36 |
+
st.session_state.current_question_index = 0
|
37 |
+
if 'user_answers' not in st.session_state:
|
38 |
+
st.session_state.user_answers = []
|
39 |
+
if 'quiz_completed' not in st.session_state:
|
40 |
+
st.session_state.quiz_completed = False
|
41 |
+
if 'score' not in st.session_state:
|
42 |
+
st.session_state.score = 0
|
43 |
+
|
44 |
+
# API Configuration based on selection - Moved inside quiz_app after login
|
45 |
+
if st.session_state.selected_api == "Gemini API":
|
46 |
+
try:
|
47 |
+
genai.configure(api_key=st.session_state.api_key)
|
48 |
+
model = genai.GenerativeModel('gemini-pro')
|
49 |
+
except Exception as e:
|
50 |
+
st.error(f"Error configuring Gemini API: {e}")
|
51 |
+
st.error("Please check your API key and network connection.")
|
52 |
+
st.session_state.logged_in = False # Force logout if API config fails
|
53 |
+
del st.session_state.api_key
|
54 |
+
del st.session_state.selected_api
|
55 |
+
st.rerun() # Go back to login page
|
56 |
+
return # Exit quiz_app
|
57 |
+
|
58 |
+
|
59 |
+
def parse_quiz_content(quiz_content):
|
60 |
+
"""Parses the quiz content and answer key into a structured format, handling title."""
|
61 |
+
questions = []
|
62 |
+
answer_key_dict = {}
|
63 |
+
|
64 |
+
quiz_parts = quiz_content.split("Answer Key:")
|
65 |
+
if len(quiz_parts) != 2:
|
66 |
+
st.warning("Could not reliably separate quiz questions and answer key. Parsing might be imperfect.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
67 |
return None, None
|
68 |
|
69 |
+
question_section = quiz_parts[0].strip()
|
70 |
+
answer_key_section = quiz_parts[1].strip()
|
71 |
+
|
72 |
+
question_lines = question_section.strip().split('\n')
|
73 |
+
current_question = None
|
74 |
+
for line in question_lines:
|
75 |
+
line = line.strip()
|
76 |
+
if not line:
|
77 |
+
continue # Skip empty lines
|
78 |
+
|
79 |
+
if re.match(r'^\d+\.\s', line): # Start of a new question
|
80 |
+
if current_question: # Save previous question if exists
|
81 |
+
questions.append(current_question)
|
82 |
+
current_question = {'options': {}} # Start new question
|
83 |
+
current_question['question'] = re.sub(r'\*\*|\*', '', line).strip() # Question text, remove bold
|
84 |
+
elif re.match(r'^[A-D]\)\s', line) or re.match(r'^[A-D]\.\s', line): # Option line (handle both ')' and '.' after letter)
|
85 |
+
if current_question:
|
86 |
+
option_letter = line[0]
|
87 |
+
option_text = line[2:].strip() # Remove "A) " or "A. "
|
88 |
+
current_question['options'][option_letter] = option_text
|
89 |
+
elif re.match(r'^\*\*.*?\*\*$', line) or re.match(r'^\*.*?\*$', line) : # Check for title again, just in case after split. Remove bold title if found in lines.
|
90 |
+
pass # Ignore title lines within question section if any.
|
91 |
+
|
92 |
+
if current_question: # Append the last question
|
93 |
+
questions.append(current_question)
|
94 |
+
|
95 |
+
|
96 |
+
# --- Answer Key Parsing (No change needed) ---
|
97 |
+
answer_lines = answer_key_section.strip().split('\n')
|
98 |
+
for line in answer_lines:
|
99 |
+
line = line.strip()
|
100 |
+
match = re.match(r'(\d+)\.\s*([A-D])', line)
|
101 |
+
if match:
|
102 |
+
question_num = int(match.group(1)) - 1
|
103 |
+
correct_answer = match.group(2)
|
104 |
+
answer_key_dict[question_num] = correct_answer
|
105 |
+
|
106 |
+
# Basic validation
|
107 |
+
if not questions or not answer_key_dict:
|
108 |
+
st.error("Error parsing quiz content. Please try again or check the generated format.")
|
109 |
+
return None, None
|
110 |
+
if len(questions) != len(answer_key_dict):
|
111 |
+
st.warning(f"Number of questions parsed ({len(questions)}) does not match number of answers in answer key ({len(answer_key_dict)}). Parsing might be incomplete.")
|
112 |
+
|
113 |
+
|
114 |
+
# Combine parsed questions and answer key into quiz_data
|
115 |
+
quiz_data_list = []
|
116 |
+
for i, q_data in enumerate(questions):
|
117 |
+
correct_answer = answer_key_dict.get(i)
|
118 |
+
if correct_answer:
|
119 |
+
quiz_data_list.append({
|
120 |
+
'question': q_data['question'],
|
121 |
+
'options': q_data['options'],
|
122 |
+
'correct_answer': correct_answer
|
123 |
+
})
|
124 |
+
else:
|
125 |
+
st.warning(f"Could not find correct answer for question {i+1} in the answer key.")
|
126 |
+
return None, None
|
127 |
+
|
128 |
+
return quiz_data_list, answer_key_dict
|
129 |
+
|
130 |
+
|
131 |
+
def display_question():
|
132 |
+
"""Displays the current question and options for interactive quiz."""
|
133 |
+
if st.session_state.quiz_data is None:
|
134 |
+
st.error("Quiz data not loaded yet. Generate a quiz first.")
|
135 |
+
return
|
136 |
+
|
137 |
+
if st.session_state.current_question_index < len(st.session_state.quiz_data):
|
138 |
+
question_data = st.session_state.quiz_data[st.session_state.current_question_index]
|
139 |
+
question_number = st.session_state.current_question_index + 1
|
140 |
+
st.markdown(f"**Question {question_number}:** {question_data['question']}")
|
141 |
+
|
142 |
+
options_list = [f"{key}. {value}" for key, value in question_data['options'].items()]
|
143 |
+
user_choice = st.radio("Choose an answer:", options_list, key=f"q_{question_number}") # Unique key for radio buttons
|
144 |
+
|
145 |
+
if st.button("Submit Answer", key=f"submit_q_{question_number}"): # Unique key for submit button
|
146 |
+
selected_option_letter = user_choice.split('.')[0] # Extract A, B, C, or D
|
147 |
+
st.session_state.user_answers.append(selected_option_letter)
|
148 |
+
|
149 |
+
if st.session_state.current_question_index < len(st.session_state.quiz_data) - 1:
|
150 |
+
st.session_state.current_question_index += 1
|
151 |
+
else:
|
152 |
+
st.session_state.quiz_completed = True # Mark quiz as completed after last question
|
153 |
+
st.rerun()
|
154 |
+
|
155 |
+
|
156 |
+
def display_results():
|
157 |
+
"""Displays the quiz results after completion."""
|
158 |
+
if st.session_state.quiz_completed:
|
159 |
+
st.markdown("### Quiz Results")
|
160 |
+
correct_count = 0
|
161 |
+
for i in range(len(st.session_state.quiz_data)):
|
162 |
+
user_answer = st.session_state.user_answers[i] if i < len(st.session_state.user_answers) else None # Handle if user didn't answer all
|
163 |
+
correct_answer = st.session_state.quiz_data[i]['correct_answer']
|
164 |
+
if user_answer == correct_answer:
|
165 |
+
correct_count += 1
|
166 |
+
result_text = f"**Question {i+1}:** ✅ Correct! (Your answer: {user_answer}, Correct answer: {correct_answer})"
|
167 |
+
color = "green"
|
168 |
+
else:
|
169 |
+
result_text = f"**Question {i+1}:** ❌ Incorrect. (Your answer: {user_answer if user_answer else 'Not answered'}, Correct answer: {correct_answer})"
|
170 |
+
color = "red"
|
171 |
+
st.markdown(f"<font color='{color}'>{result_text}</font>", unsafe_allow_html=True)
|
172 |
+
|
173 |
+
percentage_correct = (correct_count / len(st.session_state.quiz_data)) * 100
|
174 |
+
st.markdown(f"### Final Score: {correct_count} out of {len(st.session_state.quiz_data)} correct ({percentage_correct:.2f}%)")
|
175 |
+
st.session_state.score = correct_count # Store score in session state
|
176 |
+
|
177 |
+
|
178 |
+
# User input for topic
|
179 |
+
topic = st.text_input("Enter the topic for your quiz:")
|
180 |
+
|
181 |
+
if topic:
|
182 |
+
if st.button("Generate Quiz"):
|
183 |
+
with st.spinner(f"Generating quiz on '{topic}'..."):
|
184 |
+
try:
|
185 |
+
prompt = f"""
|
186 |
+
Generate a multiple-choice quiz on the topic of "{topic}".
|
187 |
+
The quiz should have 5 questions.
|
188 |
+
|
189 |
+
**Formatting Instructions:**
|
190 |
+
|
191 |
+
1. **Question Numbering:** Start each question with a number followed by a period (e.g., "1.").
|
192 |
+
2. **Question Text:** Immediately after the question number, write the question text.
|
193 |
+
3. **Options:**
|
194 |
+
* List four options for each question, labeled A, B, C, and D.
|
195 |
+
* Use the format: "A) Option text", "B) Option text", etc. (letter followed by a parenthesis, then a space, then the option text).
|
196 |
+
* Place each option on a new line directly below the question.
|
197 |
+
4. **Answer Key:**
|
198 |
+
* After all questions, create a separate section titled "**Answer Key:**".
|
199 |
+
* In the Answer Key, list the correct answer for each question in the format: "1. Correct option letter", "2. Correct option letter", etc. (question number, period, space, correct option letter - A, B, C, or D).
|
200 |
+
|
201 |
+
**Example of Desired Format:**
|
202 |
+
|
203 |
+
**Quiz Title (Optional, but good to have)**
|
204 |
+
|
205 |
+
1. Question 1 text?
|
206 |
+
A) Option A
|
207 |
+
B) Option B
|
208 |
+
C) Option C
|
209 |
+
D) Option D
|
210 |
+
|
211 |
+
2. Question 2 text?
|
212 |
+
A) Option A
|
213 |
+
B) Option B
|
214 |
+
C) Option C
|
215 |
+
D) Option D
|
216 |
+
|
217 |
+
... (and so on for 5 questions) ...
|
218 |
+
|
219 |
+
**Answer Key:**
|
220 |
+
1. C
|
221 |
+
2. A
|
222 |
+
3. B
|
223 |
+
4. D
|
224 |
+
5. A
|
225 |
+
|
226 |
+
Please generate the quiz in this exact format.
|
227 |
+
"""
|
228 |
+
response = model.generate_content(prompt)
|
229 |
+
quiz_content = response.text
|
230 |
+
|
231 |
+
|
232 |
+
parsed_quiz_data, answer_key = parse_quiz_content(quiz_content)
|
233 |
+
|
234 |
+
|
235 |
+
if quiz_content: # Check if quiz_content was generated successfully (outer if)
|
236 |
+
if parsed_quiz_data: # Check if parsing was successful (inner if)
|
237 |
+
st.session_state.quiz_data = parsed_quiz_data
|
238 |
+
st.session_state.current_question_index = 0
|
239 |
+
st.session_state.user_answers = []
|
240 |
+
st.session_state.quiz_completed = False
|
241 |
+
st.session_state.score = 0
|
242 |
+
st.success(f"Quiz on '{topic}' generated successfully! Let's begin.")
|
243 |
+
else: # else associated with inner if parsed_quiz_data
|
244 |
+
st.error("Failed to parse quiz content. Please try generating again.")
|
245 |
+
st.session_state.quiz_data = None
|
246 |
+
else: # else associated with outer if quiz_content
|
247 |
+
st.error("Failed to generate quiz content. Please try again or check your API key.")
|
248 |
+
|
249 |
+
except Exception as e:
|
250 |
+
st.error(f"An error occurred: {e}")
|
251 |
+
st.error("Please check your API key and network connection. If the problem persists, try a different topic or try again later.")
|
252 |
+
|
253 |
+
# Quiz Display Logic
|
254 |
+
if st.session_state.quiz_data:
|
255 |
+
if not st.session_state.quiz_completed:
|
256 |
+
display_question()
|
257 |
+
else:
|
258 |
+
display_results()
|
259 |
+
elif topic and not st.session_state.quiz_data and not st.session_state.quiz_completed: # Message if topic entered but quiz not generated yet
|
260 |
+
st.info("Click 'Generate Quiz' to start the quiz.")
|
261 |
|
262 |
+
# --- Main App Flow Control ---
|
263 |
+
if 'logged_in' not in st.session_state:
|
264 |
+
st.session_state.logged_in = False
|
265 |
|
266 |
+
if not st.session_state.logged_in:
|
267 |
+
login_page()
|
268 |
+
else:
|
269 |
+
quiz_app()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|