File size: 11,940 Bytes
8f11219
29251f4
 
9c81979
1cb973f
 
 
984c361
 
7340672
984c361
5e4fdcb
984c361
 
 
8f11219
7e00835
29251f4
38a2fd0
5e4fdcb
1cb973f
 
984c361
38a2fd0
5e4fdcb
984c361
29251f4
984c361
9708d0e
5e4fdcb
c124d82
984c361
 
 
0bc91b7
ee84103
984c361
7340672
984c361
 
 
 
 
 
 
 
 
 
 
5e4fdcb
984c361
 
9708d0e
 
29251f4
5e4fdcb
29251f4
 
984c361
29251f4
984c361
29251f4
984c361
29251f4
984c361
29251f4
9708d0e
1cb973f
984c361
29251f4
 
1cb973f
984c361
1cb973f
29251f4
1cb973f
29251f4
 
7e00835
1cb973f
29251f4
 
9708d0e
 
 
 
 
1cb973f
5e4fdcb
29251f4
 
9708d0e
1cb973f
984c361
 
 
 
 
7340672
984c361
 
 
 
29251f4
984c361
 
29251f4
7340672
 
984c361
 
 
 
 
5e4fdcb
1cb973f
5e4fdcb
1cb973f
29251f4
984c361
 
 
9708d0e
1cb973f
5e4fdcb
9708d0e
29251f4
984c361
 
 
9708d0e
 
7340672
9708d0e
1cb973f
984c361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9708d0e
1cb973f
984c361
5e4fdcb
9708d0e
5e4fdcb
8f11219
38a2fd0
 
984c361
 
 
38a2fd0
9708d0e
7340672
9708d0e
984c361
9708d0e
5e4fdcb
29251f4
7340672
984c361
9708d0e
 
 
 
7340672
984c361
 
8f11219
10152dd
 
29251f4
9708d0e
 
 
 
 
38a2fd0
 
 
9708d0e
 
29251f4
 
9708d0e
8f11219
9708d0e
 
 
7340672
9708d0e
 
 
 
 
7340672
9708d0e
 
984c361
29251f4
38a2fd0
984c361
 
 
 
 
38a2fd0
5e4fdcb
984c361
 
 
 
 
29251f4
5e4fdcb
9708d0e
984c361
 
9708d0e
984c361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9708d0e
 
29251f4
5e4fdcb
984c361
 
 
 
 
 
29251f4
984c361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29251f4
984c361
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9708d0e
984c361
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
import gradio as gr
from tool2 import *  # Assuming this module contains your exam data and text-to-speech functionality
from backend1 import *

# Global variable to store the currently selected set of exam questions
selected_questions = []

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. 
For more information about the developer, please visit [ruslanmv.com](https://ruslanmv.com/).

**Get Started with Your Quiz** 
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.
"""

# --- FUNCTION DEFINITIONS ---

def start_exam(exam_choice, start_question, audio_enabled):
    """Starts the exam by selecting questions, setting up UI."""
    global selected_questions
    selected_questions = select_exam_vce(exam_choice)

    if start_question >= len(selected_questions):
        start_question = 0  # Default to the first question if the input exceeds available questions

    question, options, audio_path = display_question(start_question, audio_enabled)

    return (
        # Hide start screen elements
        gr.update(visible=False),  # Hide title
        gr.update(visible=False),  # Hide description
        gr.update(visible=False),  # Hide exam_selector
        gr.update(visible=False),  # Hide start_button
        gr.update(visible=False),  # Hide the audio_checkbox
        gr.update(visible=False),  # Hide start_question_slider

        # Show quiz elements
        gr.update(visible=True),   # Show question_text
        question,                  # Question to display
        gr.update(choices=options, visible=True),  # Update Radio choices
        gr.update(visible=True),   # Show answer_button
        gr.update(visible=True),   # Show next_button
        gr.update(visible=True),   # Show prev_button
        gr.update(visible=True),   # Show home_button

        start_question,  # Update the question_state
        "",              # Clear result_text
        audio_path,      # Provide the question audio path
        gr.update(visible=True),  # Show explain_button
        gr.update(visible=True),  # Show result_text (for explanation)
        None             # current_audio_state = None
    )

def display_question(index, audio_enabled):
    """Displays a question with options and generates audio (if enabled)."""
    if index < 0 or index >= len(selected_questions):
        return "No more questions.", [], None

    question_text_ = selected_questions[index].get('question', 'No question text available.')
    question_text = f"**Question {index}:** {question_text_}"
    choices_options = selected_questions[index].get('options', [])

    audio_path = text_to_speech(question_text_ + " " + " ".join(choices_options)) if audio_enabled else None

    return question_text, choices_options, audio_path

def show_explanation(index):
    """Shows the explanation for the current question."""
    if 0 <= index < len(selected_questions):
        explanation = selected_questions[index].get('explanation', 'No explanation available for this question.')
        return (
            f"**Explanation:** {explanation}",
            gr.update(visible=True),  # Show explanation_text
            gr.update(visible=True)   # Show result_text
        )
    else:
        return "No explanation available for this question.", gr.update(visible=False), gr.update(visible=False)

def check_answer(index, answer):
    """Checks the given answer against the correct answer."""
    correct_answer = selected_questions[index].get('correct', 'No correct answer provided.')
    if answer == correct_answer:
        return f"Correct! The answer is: {correct_answer}"
    else:
        return f"Incorrect. The correct answer is: {correct_answer}"

def update_question(index, audio_enabled):
    """Updates the displayed question when the index changes."""
    question, options, audio_path = display_question(index, audio_enabled)
    return question, gr.update(choices=options), index, audio_path

def handle_answer(index, answer, audio_enabled, current_audio):
    """
    Handles answer submission:
      1) Stop the question audio.
      2) Provide and play the answer audio (if enabled).
    """
    if answer is None:
        # No answer was selected
        return "Please select an option before submitting.", None, None, gr.update(value=None)

    # Stop the current question audio
    stop_audio = True if current_audio else False

    # Check answer and generate answer audio
    result = check_answer(index, answer)
    answer_audio_path = text_to_speech(result) if audio_enabled else None

    # Return result (shown as text),
    # the new answer audio,
    # updated current_audio_state,
    # and question_audio set to None so it stops playing
    return result, answer_audio_path, stop_audio, gr.update(value=None)

def handle_next(index, audio_enabled):
    """Moves to the next question and updates the UI."""
    new_index = min(index + 1, len(selected_questions) - 1)
    question, options, new_index, audio_path = update_question(new_index, audio_enabled)

    # Hide explanation when moving to next question
    return question, options, new_index, "", audio_path, gr.update(visible=False)

def handle_previous(index, audio_enabled):
    """Moves to the previous question and updates the UI."""
    new_index = max(index - 1, 0)
    question, options, new_index, audio_path = update_question(new_index, audio_enabled)

    # Hide explanation when moving to previous question
    return question, options, new_index, "", audio_path, gr.update(visible=False)

def return_home():
    """Returns to the home screen."""
    return (
        # Show start screen elements
        gr.update(visible=True),  # title
        gr.update(visible=True),  # description
        gr.update(visible=True),  # exam_selector
        gr.update(visible=True),  # start_button
        gr.update(visible=True),  # audio_checkbox
        gr.update(visible=False), # start_question_slider

        # Hide quiz elements
        gr.update(visible=False), # question_text
        "",                       # question_text value
        gr.update(visible=False), # choices
        gr.update(visible=False), # answer_button
        gr.update(visible=False), # next_button
        gr.update(visible=False), # prev_button
        gr.update(visible=False), # home_button

        0,                        # question_state
        "",                       # result_text
        gr.update(value=None),    # question_audio
        gr.update(visible=False), # explain_button
        gr.update(visible=False), # result_text (for explanation)
        None                      # current_audio_state
    )


with gr.Blocks() as demo:
    # Home page elements
    title = gr.Markdown(value="**AWS Exam Simulator (Quiz)**")
    description = gr.Markdown(value=description_str)
    exam_selector = gr.Dropdown(label="Select an exam", choices=exams, value=None)
    audio_checkbox = gr.Checkbox(label="Enable Audio", value=True, visible=False)
    start_question_slider = gr.Slider(
        minimum=0, maximum=50, step=1, label="Select starting question", visible=False
    )
    start_button = gr.Button("Start Exam", visible=False)

    # Quiz elements (initially hidden)
    question_state = gr.State(0)
    current_audio_state = gr.State(None)  # State to track the current question audio
    question_text = gr.Markdown(visible=False, elem_id="question-text")
    choices = gr.Radio(visible=False, label="Options")
    result_text = gr.Markdown(visible=True)
    explanation_text = gr.Markdown(visible=False)

    answer_button = gr.Button("Submit Answer", visible=False)
    next_button = gr.Button("Next Question", visible=False)
    prev_button = gr.Button("Previous Question", visible=False)
    home_button = gr.Button("Return to Home", visible=False)
    explain_button = gr.Button("Explain", visible=False)

    # We use two different audio players for question and answer
    question_audio = gr.Audio(visible=False, label="Question Audio", autoplay=True)
    answer_audio = gr.Audio(visible=False, label="Answer Audio", autoplay=True)

    # Layout for the home page
    with gr.Row():
        gr.Column([title])
    with gr.Row():
        gr.Column([description])
    with gr.Row():
        gr.Column([exam_selector])
    with gr.Row():
        gr.Column([audio_checkbox, start_question_slider])
    with gr.Row():
        gr.Column([start_button])

    # Layout for the quiz
    with gr.Row():
        gr.Column([question_text, question_audio])
    with gr.Row():
        gr.Column([choices])
    with gr.Row():
        gr.Column([result_text, explanation_text, answer_audio])
    with gr.Row():
        gr.Column([prev_button], scale=1)
        gr.Column([], scale=8)
        gr.Column([next_button], scale=1)
    with gr.Row():
        gr.Column([answer_button, explain_button])
    with gr.Row():
        gr.Column([home_button])

    # Show settings after exam selection
    def show_settings(exam_choice):
        return (
            gr.update(visible=True),
            gr.update(visible=True),
            gr.update(visible=True)
        )

    # Connect exam selection to display settings section
    exam_selector.change(
        fn=show_settings,
        inputs=[exam_selector],
        outputs=[audio_checkbox, start_question_slider, start_button]
    )

    # Connect the start button to start the exam
    start_button.click(
        fn=start_exam,
        inputs=[exam_selector, start_question_slider, audio_checkbox],
        outputs=[
            title,
            description,
            exam_selector,
            start_button,
            audio_checkbox,        # Hide the checkbox
            start_question_slider, # Hide the slider

            question_text,         # Show question_text
            question_text,         # question content
            choices,               # show choices
            answer_button,
            next_button,
            prev_button,
            home_button,

            question_state,
            result_text,
            question_audio,
            explain_button,
            result_text,
            current_audio_state
        ]
    )

    # Connect the quiz buttons to their functions
    answer_button.click(
        fn=handle_answer,
        inputs=[question_state, choices, audio_checkbox, current_audio_state],
        # We now also update question_audio -> set it to None to stop playback.
        outputs=[result_text, answer_audio, current_audio_state, question_audio]
    )

    next_button.click(
        fn=handle_next,
        inputs=[question_state, audio_checkbox],
        outputs=[question_text, choices, question_state, result_text, question_audio, explanation_text]
    )

    prev_button.click(
        fn=handle_previous,
        inputs=[question_state, audio_checkbox],
        outputs=[question_text, choices, question_state, result_text, question_audio, explanation_text]
    )

    explain_button.click(
        fn=show_explanation,
        inputs=[question_state],
        outputs=[explanation_text, result_text, explanation_text]
    )

    home_button.click(
        fn=return_home,
        inputs=None,
        outputs=[
            title,
            description,
            exam_selector,
            start_button,
            audio_checkbox,
            start_question_slider,
            question_text,
            question_text,
            choices,
            answer_button,
            next_button,
            prev_button,
            home_button,
            question_state,
            result_text,
            question_audio,
            explain_button,
            result_text,
            current_audio_state
        ]
    )

demo.launch()