Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -5,10 +5,14 @@ from backend1 import *
|
|
5 |
# Global variable to store the currently selected set of exam questions
|
6 |
selected_questions = []
|
7 |
|
8 |
-
description_str = """
|
|
|
9 |
For more information about the developer, please visit [ruslanmv.com](https://ruslanmv.com/).
|
|
|
10 |
**Get Started with Your Quiz**
|
11 |
-
Select an exam from the dropdown menu below and start testing your skills. You can also choose to enable audio feedback to enhance your learning experience.
|
|
|
|
|
12 |
|
13 |
# --- FUNCTION DEFINITIONS ---
|
14 |
|
@@ -16,51 +20,57 @@ def start_exam(exam_choice, start_question, audio_enabled):
|
|
16 |
"""Starts the exam by selecting questions, setting up UI."""
|
17 |
global selected_questions
|
18 |
selected_questions = select_exam_vce(exam_choice)
|
19 |
-
|
20 |
if start_question >= len(selected_questions):
|
21 |
start_question = 0 # Default to the first question if the input exceeds available questions
|
22 |
-
|
23 |
question, options, audio_path = display_question(start_question, audio_enabled)
|
24 |
-
|
25 |
return (
|
26 |
# Hide start screen elements
|
27 |
gr.update(visible=False), # Hide title
|
28 |
-
gr.update(visible=False),
|
29 |
-
gr.update(visible=False),
|
30 |
-
gr.update(visible=False),
|
31 |
gr.update(visible=False), # Hide the audio_checkbox
|
32 |
gr.update(visible=False), # Hide start_question_slider
|
|
|
33 |
# Show quiz elements
|
34 |
-
gr.update(visible=True),
|
35 |
-
question,
|
36 |
-
gr.update(choices=options, visible=True), # Update Radio choices
|
37 |
-
gr.update(visible=True),
|
38 |
-
gr.update(visible=True)
|
39 |
-
gr.update(visible=True),
|
40 |
-
gr.update(visible=True),
|
41 |
-
|
42 |
-
|
|
|
|
|
43 |
gr.update(visible=True), # Show explain_button
|
44 |
-
gr.update(visible=True),
|
45 |
-
None
|
46 |
)
|
47 |
|
48 |
def display_question(index, audio_enabled):
|
49 |
"""Displays a question with options and generates audio (if enabled)."""
|
50 |
if index < 0 or index >= len(selected_questions):
|
51 |
return "No more questions.", [], None
|
|
|
52 |
question_text_ = selected_questions[index].get('question', 'No question text available.')
|
53 |
-
question_text = f"**Question {index
|
54 |
choices_options = selected_questions[index].get('options', [])
|
|
|
55 |
audio_path = text_to_speech(question_text_ + " " + " ".join(choices_options)) if audio_enabled else None
|
|
|
56 |
return question_text, choices_options, audio_path
|
57 |
|
58 |
def show_explanation(index):
|
59 |
-
"""Shows the explanation for the current question
|
60 |
if 0 <= index < len(selected_questions):
|
61 |
explanation = selected_questions[index].get('explanation', 'No explanation available for this question.')
|
62 |
return (
|
63 |
-
f"**Explanation:** {explanation}",
|
64 |
gr.update(visible=True), # Show explanation_text
|
65 |
gr.update(visible=True) # Show result_text
|
66 |
)
|
@@ -81,62 +91,99 @@ def update_question(index, audio_enabled):
|
|
81 |
return question, gr.update(choices=options), index, audio_path
|
82 |
|
83 |
def handle_answer(index, answer, audio_enabled, current_audio):
|
84 |
-
"""
|
85 |
-
|
|
|
|
|
|
|
86 |
if answer is None:
|
87 |
-
|
88 |
-
|
89 |
-
|
|
|
90 |
stop_audio = True if current_audio else False
|
|
|
|
|
91 |
result = check_answer(index, answer)
|
92 |
answer_audio_path = text_to_speech(result) if audio_enabled else None
|
93 |
-
return result, answer_audio_path, stop_audio
|
94 |
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
def handle_next(index, audio_enabled):
|
97 |
"""Moves to the next question and updates the UI."""
|
98 |
new_index = min(index + 1, len(selected_questions) - 1)
|
99 |
question, options, new_index, audio_path = update_question(new_index, audio_enabled)
|
100 |
-
|
|
|
|
|
101 |
|
102 |
def handle_previous(index, audio_enabled):
|
103 |
"""Moves to the previous question and updates the UI."""
|
104 |
new_index = max(index - 1, 0)
|
105 |
question, options, new_index, audio_path = update_question(new_index, audio_enabled)
|
106 |
-
|
|
|
|
|
107 |
|
108 |
def return_home():
|
109 |
"""Returns to the home screen."""
|
110 |
return (
|
111 |
# Show start screen elements
|
112 |
-
gr.update(visible=True),
|
113 |
-
gr.update(visible=True), #
|
114 |
-
gr.update(visible=
|
115 |
-
gr.update(visible=
|
116 |
-
gr.update(visible=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
)
|
118 |
|
|
|
119 |
with gr.Blocks() as demo:
|
120 |
# Home page elements
|
121 |
title = gr.Markdown(value="**AWS Exam Simulator (Quiz)**")
|
122 |
description = gr.Markdown(value=description_str)
|
123 |
exam_selector = gr.Dropdown(label="Select an exam", choices=exams, value=None)
|
124 |
audio_checkbox = gr.Checkbox(label="Enable Audio", value=True, visible=False)
|
125 |
-
start_question_slider = gr.Slider(
|
|
|
|
|
126 |
start_button = gr.Button("Start Exam", visible=False)
|
127 |
|
128 |
# Quiz elements (initially hidden)
|
129 |
question_state = gr.State(0)
|
130 |
-
current_audio_state = gr.State(None) # State to track the current audio
|
131 |
question_text = gr.Markdown(visible=False, elem_id="question-text")
|
132 |
choices = gr.Radio(visible=False, label="Options")
|
133 |
result_text = gr.Markdown(visible=True)
|
134 |
explanation_text = gr.Markdown(visible=False)
|
|
|
135 |
answer_button = gr.Button("Submit Answer", visible=False)
|
136 |
next_button = gr.Button("Next Question", visible=False)
|
137 |
prev_button = gr.Button("Previous Question", visible=False)
|
138 |
home_button = gr.Button("Return to Home", visible=False)
|
139 |
explain_button = gr.Button("Explain", visible=False)
|
|
|
|
|
140 |
question_audio = gr.Audio(visible=False, label="Question Audio", autoplay=True)
|
141 |
answer_audio = gr.Audio(visible=False, label="Answer Audio", autoplay=True)
|
142 |
|
@@ -167,41 +214,101 @@ with gr.Blocks() as demo:
|
|
167 |
gr.Column([answer_button, explain_button])
|
168 |
with gr.Row():
|
169 |
gr.Column([home_button])
|
170 |
-
|
171 |
# Show settings after exam selection
|
172 |
def show_settings(exam_choice):
|
173 |
-
return
|
|
|
|
|
|
|
|
|
174 |
|
175 |
# Connect exam selection to display settings section
|
176 |
-
exam_selector.change(
|
|
|
|
|
|
|
|
|
177 |
|
178 |
# Connect the start button to start the exam
|
179 |
start_button.click(
|
180 |
-
fn=start_exam,
|
181 |
-
inputs=[exam_selector, start_question_slider, audio_checkbox],
|
182 |
outputs=[
|
183 |
-
title,
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
189 |
]
|
190 |
)
|
191 |
|
192 |
# Connect the quiz buttons to their functions
|
193 |
-
answer_button.click(
|
194 |
-
|
195 |
-
|
|
|
|
|
|
|
196 |
|
197 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
198 |
|
199 |
-
home_button.click(
|
200 |
-
|
201 |
-
|
202 |
-
|
203 |
-
|
204 |
-
|
205 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
206 |
|
207 |
-
demo.launch()
|
|
|
5 |
# Global variable to store the currently selected set of exam questions
|
6 |
selected_questions = []
|
7 |
|
8 |
+
description_str = """
|
9 |
+
Developed by Ruslan Magana, this interactive quiz platform is designed to help you prepare and assess your knowledge in a variety of exams.
|
10 |
For more information about the developer, please visit [ruslanmv.com](https://ruslanmv.com/).
|
11 |
+
|
12 |
**Get Started with Your Quiz**
|
13 |
+
Select an exam from the dropdown menu below and start testing your skills. You can also choose to enable audio feedback to enhance your learning experience.
|
14 |
+
Simply toggle the "Enable Audio" checkbox to turn it on or off.
|
15 |
+
"""
|
16 |
|
17 |
# --- FUNCTION DEFINITIONS ---
|
18 |
|
|
|
20 |
"""Starts the exam by selecting questions, setting up UI."""
|
21 |
global selected_questions
|
22 |
selected_questions = select_exam_vce(exam_choice)
|
23 |
+
|
24 |
if start_question >= len(selected_questions):
|
25 |
start_question = 0 # Default to the first question if the input exceeds available questions
|
26 |
+
|
27 |
question, options, audio_path = display_question(start_question, audio_enabled)
|
28 |
+
|
29 |
return (
|
30 |
# Hide start screen elements
|
31 |
gr.update(visible=False), # Hide title
|
32 |
+
gr.update(visible=False), # Hide description
|
33 |
+
gr.update(visible=False), # Hide exam_selector
|
34 |
+
gr.update(visible=False), # Hide start_button
|
35 |
gr.update(visible=False), # Hide the audio_checkbox
|
36 |
gr.update(visible=False), # Hide start_question_slider
|
37 |
+
|
38 |
# Show quiz elements
|
39 |
+
gr.update(visible=True), # Show question_text
|
40 |
+
question, # Question to display
|
41 |
+
gr.update(choices=options, visible=True), # Update Radio choices
|
42 |
+
gr.update(visible=True), # Show answer_button
|
43 |
+
gr.update(visible=True), # Show next_button
|
44 |
+
gr.update(visible=True), # Show prev_button
|
45 |
+
gr.update(visible=True), # Show home_button
|
46 |
+
|
47 |
+
start_question, # Update the question_state
|
48 |
+
"", # Clear result_text
|
49 |
+
audio_path, # Provide the question audio path
|
50 |
gr.update(visible=True), # Show explain_button
|
51 |
+
gr.update(visible=True), # Show result_text (for explanation)
|
52 |
+
None # current_audio_state = None
|
53 |
)
|
54 |
|
55 |
def display_question(index, audio_enabled):
|
56 |
"""Displays a question with options and generates audio (if enabled)."""
|
57 |
if index < 0 or index >= len(selected_questions):
|
58 |
return "No more questions.", [], None
|
59 |
+
|
60 |
question_text_ = selected_questions[index].get('question', 'No question text available.')
|
61 |
+
question_text = f"**Question {index}:** {question_text_}"
|
62 |
choices_options = selected_questions[index].get('options', [])
|
63 |
+
|
64 |
audio_path = text_to_speech(question_text_ + " " + " ".join(choices_options)) if audio_enabled else None
|
65 |
+
|
66 |
return question_text, choices_options, audio_path
|
67 |
|
68 |
def show_explanation(index):
|
69 |
+
"""Shows the explanation for the current question."""
|
70 |
if 0 <= index < len(selected_questions):
|
71 |
explanation = selected_questions[index].get('explanation', 'No explanation available for this question.')
|
72 |
return (
|
73 |
+
f"**Explanation:** {explanation}",
|
74 |
gr.update(visible=True), # Show explanation_text
|
75 |
gr.update(visible=True) # Show result_text
|
76 |
)
|
|
|
91 |
return question, gr.update(choices=options), index, audio_path
|
92 |
|
93 |
def handle_answer(index, answer, audio_enabled, current_audio):
|
94 |
+
"""
|
95 |
+
Handles answer submission:
|
96 |
+
1) Stop the question audio.
|
97 |
+
2) Provide and play the answer audio (if enabled).
|
98 |
+
"""
|
99 |
if answer is None:
|
100 |
+
# No answer was selected
|
101 |
+
return "Please select an option before submitting.", None, None, gr.update(value=None)
|
102 |
+
|
103 |
+
# Stop the current question audio
|
104 |
stop_audio = True if current_audio else False
|
105 |
+
|
106 |
+
# Check answer and generate answer audio
|
107 |
result = check_answer(index, answer)
|
108 |
answer_audio_path = text_to_speech(result) if audio_enabled else None
|
|
|
109 |
|
110 |
+
# Return result (shown as text),
|
111 |
+
# the new answer audio,
|
112 |
+
# updated current_audio_state,
|
113 |
+
# and question_audio set to None so it stops playing
|
114 |
+
return result, answer_audio_path, stop_audio, gr.update(value=None)
|
115 |
|
116 |
def handle_next(index, audio_enabled):
|
117 |
"""Moves to the next question and updates the UI."""
|
118 |
new_index = min(index + 1, len(selected_questions) - 1)
|
119 |
question, options, new_index, audio_path = update_question(new_index, audio_enabled)
|
120 |
+
|
121 |
+
# Hide explanation when moving to next question
|
122 |
+
return question, options, new_index, "", audio_path, gr.update(visible=False)
|
123 |
|
124 |
def handle_previous(index, audio_enabled):
|
125 |
"""Moves to the previous question and updates the UI."""
|
126 |
new_index = max(index - 1, 0)
|
127 |
question, options, new_index, audio_path = update_question(new_index, audio_enabled)
|
128 |
+
|
129 |
+
# Hide explanation when moving to previous question
|
130 |
+
return question, options, new_index, "", audio_path, gr.update(visible=False)
|
131 |
|
132 |
def return_home():
|
133 |
"""Returns to the home screen."""
|
134 |
return (
|
135 |
# Show start screen elements
|
136 |
+
gr.update(visible=True), # title
|
137 |
+
gr.update(visible=True), # description
|
138 |
+
gr.update(visible=True), # exam_selector
|
139 |
+
gr.update(visible=True), # start_button
|
140 |
+
gr.update(visible=True), # audio_checkbox
|
141 |
+
gr.update(visible=False), # start_question_slider
|
142 |
+
|
143 |
+
# Hide quiz elements
|
144 |
+
gr.update(visible=False), # question_text
|
145 |
+
"", # question_text value
|
146 |
+
gr.update(visible=False), # choices
|
147 |
+
gr.update(visible=False), # answer_button
|
148 |
+
gr.update(visible=False), # next_button
|
149 |
+
gr.update(visible=False), # prev_button
|
150 |
+
gr.update(visible=False), # home_button
|
151 |
+
|
152 |
+
0, # question_state
|
153 |
+
"", # result_text
|
154 |
+
gr.update(value=None), # question_audio
|
155 |
+
gr.update(visible=False), # explain_button
|
156 |
+
gr.update(visible=False), # result_text (for explanation)
|
157 |
+
None # current_audio_state
|
158 |
)
|
159 |
|
160 |
+
|
161 |
with gr.Blocks() as demo:
|
162 |
# Home page elements
|
163 |
title = gr.Markdown(value="**AWS Exam Simulator (Quiz)**")
|
164 |
description = gr.Markdown(value=description_str)
|
165 |
exam_selector = gr.Dropdown(label="Select an exam", choices=exams, value=None)
|
166 |
audio_checkbox = gr.Checkbox(label="Enable Audio", value=True, visible=False)
|
167 |
+
start_question_slider = gr.Slider(
|
168 |
+
minimum=0, maximum=50, step=1, label="Select starting question", visible=False
|
169 |
+
)
|
170 |
start_button = gr.Button("Start Exam", visible=False)
|
171 |
|
172 |
# Quiz elements (initially hidden)
|
173 |
question_state = gr.State(0)
|
174 |
+
current_audio_state = gr.State(None) # State to track the current question audio
|
175 |
question_text = gr.Markdown(visible=False, elem_id="question-text")
|
176 |
choices = gr.Radio(visible=False, label="Options")
|
177 |
result_text = gr.Markdown(visible=True)
|
178 |
explanation_text = gr.Markdown(visible=False)
|
179 |
+
|
180 |
answer_button = gr.Button("Submit Answer", visible=False)
|
181 |
next_button = gr.Button("Next Question", visible=False)
|
182 |
prev_button = gr.Button("Previous Question", visible=False)
|
183 |
home_button = gr.Button("Return to Home", visible=False)
|
184 |
explain_button = gr.Button("Explain", visible=False)
|
185 |
+
|
186 |
+
# We use two different audio players for question and answer
|
187 |
question_audio = gr.Audio(visible=False, label="Question Audio", autoplay=True)
|
188 |
answer_audio = gr.Audio(visible=False, label="Answer Audio", autoplay=True)
|
189 |
|
|
|
214 |
gr.Column([answer_button, explain_button])
|
215 |
with gr.Row():
|
216 |
gr.Column([home_button])
|
217 |
+
|
218 |
# Show settings after exam selection
|
219 |
def show_settings(exam_choice):
|
220 |
+
return (
|
221 |
+
gr.update(visible=True),
|
222 |
+
gr.update(visible=True),
|
223 |
+
gr.update(visible=True)
|
224 |
+
)
|
225 |
|
226 |
# Connect exam selection to display settings section
|
227 |
+
exam_selector.change(
|
228 |
+
fn=show_settings,
|
229 |
+
inputs=[exam_selector],
|
230 |
+
outputs=[audio_checkbox, start_question_slider, start_button]
|
231 |
+
)
|
232 |
|
233 |
# Connect the start button to start the exam
|
234 |
start_button.click(
|
235 |
+
fn=start_exam,
|
236 |
+
inputs=[exam_selector, start_question_slider, audio_checkbox],
|
237 |
outputs=[
|
238 |
+
title,
|
239 |
+
description,
|
240 |
+
exam_selector,
|
241 |
+
start_button,
|
242 |
+
audio_checkbox, # Hide the checkbox
|
243 |
+
start_question_slider, # Hide the slider
|
244 |
+
|
245 |
+
question_text, # Show question_text
|
246 |
+
question_text, # question content
|
247 |
+
choices, # show choices
|
248 |
+
answer_button,
|
249 |
+
next_button,
|
250 |
+
prev_button,
|
251 |
+
home_button,
|
252 |
+
|
253 |
+
question_state,
|
254 |
+
result_text,
|
255 |
+
question_audio,
|
256 |
+
explain_button,
|
257 |
+
result_text,
|
258 |
+
current_audio_state
|
259 |
]
|
260 |
)
|
261 |
|
262 |
# Connect the quiz buttons to their functions
|
263 |
+
answer_button.click(
|
264 |
+
fn=handle_answer,
|
265 |
+
inputs=[question_state, choices, audio_checkbox, current_audio_state],
|
266 |
+
# We now also update question_audio -> set it to None to stop playback.
|
267 |
+
outputs=[result_text, answer_audio, current_audio_state, question_audio]
|
268 |
+
)
|
269 |
|
270 |
+
next_button.click(
|
271 |
+
fn=handle_next,
|
272 |
+
inputs=[question_state, audio_checkbox],
|
273 |
+
outputs=[question_text, choices, question_state, result_text, question_audio, explanation_text]
|
274 |
+
)
|
275 |
+
|
276 |
+
prev_button.click(
|
277 |
+
fn=handle_previous,
|
278 |
+
inputs=[question_state, audio_checkbox],
|
279 |
+
outputs=[question_text, choices, question_state, result_text, question_audio, explanation_text]
|
280 |
+
)
|
281 |
+
|
282 |
+
explain_button.click(
|
283 |
+
fn=show_explanation,
|
284 |
+
inputs=[question_state],
|
285 |
+
outputs=[explanation_text, result_text, explanation_text]
|
286 |
+
)
|
287 |
|
288 |
+
home_button.click(
|
289 |
+
fn=return_home,
|
290 |
+
inputs=None,
|
291 |
+
outputs=[
|
292 |
+
title,
|
293 |
+
description,
|
294 |
+
exam_selector,
|
295 |
+
start_button,
|
296 |
+
audio_checkbox,
|
297 |
+
start_question_slider,
|
298 |
+
question_text,
|
299 |
+
question_text,
|
300 |
+
choices,
|
301 |
+
answer_button,
|
302 |
+
next_button,
|
303 |
+
prev_button,
|
304 |
+
home_button,
|
305 |
+
question_state,
|
306 |
+
result_text,
|
307 |
+
question_audio,
|
308 |
+
explain_button,
|
309 |
+
result_text,
|
310 |
+
current_audio_state
|
311 |
+
]
|
312 |
+
)
|
313 |
|
314 |
+
demo.launch()
|