ruslanmv commited on
Commit
984c361
·
verified ·
1 Parent(s): 31c14de

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -60
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 = """Developed by Ruslan Magana, this interactive quiz platform is designed to help you prepare and assess your knowledge in a variety of exams.
 
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. Simply toggle the "Enable Audio" checkbox to turn it on or off."""
 
 
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), # Hide description
29
- gr.update(visible=False), # Hide exam_selector
30
- gr.update(visible=False), # Hide start_button
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), # Show question_text
35
- question, # Question to display
36
- gr.update(choices=options, visible=True), # Update Radio choices and make visible
37
- gr.update(visible=True), # Show answer_button
38
- gr.update(visible=True),# Show next_button
39
- gr.update(visible=True), # Show prev_button
40
- gr.update(visible=True), # Show home_button
41
- start_question, "", # Update the question state
42
- audio_path, # Provide the audio_path
 
 
43
  gr.update(visible=True), # Show explain_button
44
- gr.update(visible=True),
45
- None # None for the audio stop signal
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 }:** {question_text_}"
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 and hides previous results."""
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
- """Handles answer submission, provides feedback, and generates audio."""
85
- # Handle the case when no answer is selected
 
 
 
86
  if answer is None:
87
- return "Please select an option before submitting.", None, None
88
-
89
- # Stop the current question audio before playing the answer audio
 
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
- return question, options, new_index, "", audio_path, gr.update(visible=False) # Hide explanation
 
 
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
- return question, options, new_index, "", audio_path, gr.update(visible=False) # Hide explanation
 
 
107
 
108
  def return_home():
109
  """Returns to the home screen."""
110
  return (
111
  # Show start screen elements
112
- gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True),
113
- gr.update(visible=True), # Show the audio_checkbox
114
- gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
115
- gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), "", "", gr.update(visible=False), gr.update(visible=False),
116
- gr.update(visible=False) # Hide explain button
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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(minimum=0, maximum=50, step=1, label="Select starting question", visible=False) # Slider for selecting the starting question
 
 
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 playing
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 gr.update(visible=True), gr.update(visible=True), gr.update(visible=True)
 
 
 
 
174
 
175
  # Connect exam selection to display settings section
176
- exam_selector.change(fn=show_settings, inputs=[exam_selector], outputs=[audio_checkbox, start_question_slider, start_button])
 
 
 
 
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, description, exam_selector, start_button,
184
- audio_checkbox, # Ensure the checkbox visibility is updated
185
- start_question_slider, # Ensure the slider is hidden
186
- question_text, question_text, choices, answer_button,
187
- next_button, prev_button, home_button, question_state, result_text, question_audio,
188
- explain_button, result_text, current_audio_state # Add current_audio_state to the outputs
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  ]
190
  )
191
 
192
  # Connect the quiz buttons to their functions
193
- answer_button.click(fn=handle_answer, inputs=[question_state, choices, audio_checkbox, current_audio_state], outputs=[result_text, answer_audio, current_audio_state])
194
- next_button.click(fn=handle_next, inputs=[question_state, audio_checkbox], outputs=[question_text, choices, question_state, result_text, question_audio, explanation_text])
195
- prev_button.click(fn=handle_previous, inputs=[question_state, audio_checkbox], outputs=[question_text, choices, question_state, result_text, question_audio, explanation_text])
 
 
 
196
 
197
- explain_button.click(fn=show_explanation, inputs=[question_state], outputs=[explanation_text, result_text, explanation_text])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
 
199
- home_button.click(fn=return_home, inputs=None, outputs=[
200
- title, description, exam_selector, start_button,
201
- audio_checkbox, # Ensure the checkbox visibility is updated
202
- #start_question_slider, # Ensure the slider is shown
203
- question_text, question_text, choices, answer_button,
204
- next_button, prev_button, home_button, question_state, result_text, explanation_text, explain_button
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()