Spaces:
Running
Running
updates
Browse files- app.py +73 -114
- questions/GCP-ML-vA.json +0 -0
- questions/MLS-C01-v0624.json +0 -0
- questions/SAA-C03-v2.json +0 -0
app.py
CHANGED
@@ -1,156 +1,110 @@
|
|
1 |
'''
|
2 |
-
AWS Exam Simulator v.
|
3 |
Program Developed by Ruslan Magana Vsevolovna
|
4 |
The purpose of this program is help to practice the questions of AWS Exams.
|
5 |
'''
|
6 |
import gradio as gr
|
7 |
-
from
|
8 |
-
import
|
9 |
-
import json
|
10 |
-
|
11 |
-
# Function to load question sets from a directory
|
12 |
-
def load_question_sets_vce(directory='questions'):
|
13 |
-
question_sets = []
|
14 |
-
for root, dirs, files in os.walk(directory):
|
15 |
-
for file in files:
|
16 |
-
if file.endswith(".json"):
|
17 |
-
question_sets.append(os.path.join( file)[:-5]) # remove the .json extension
|
18 |
-
return question_sets
|
19 |
-
|
20 |
-
exams = load_question_sets_vce('questions/')
|
21 |
-
print("question_sets:", exams)
|
22 |
-
|
23 |
-
def select_exam_vce(exam_name):
|
24 |
-
file_path = os.path.join(os.getcwd(), 'questions', f'{exam_name}.json')
|
25 |
-
try:
|
26 |
-
with open(file_path, 'r') as f:
|
27 |
-
questions = json.load(f)
|
28 |
-
print(f"Loaded {len(questions)} questions")
|
29 |
-
return questions # Ensure the questions are returned here
|
30 |
-
except FileNotFoundError:
|
31 |
-
print(f"File {file_path} not found.")
|
32 |
-
return [] # Return an empty list to indicate no questions were found
|
33 |
-
|
34 |
-
import time
|
35 |
-
import httpx
|
36 |
-
# Text-to-speech clients
|
37 |
-
client_1 = Client("ruslanmv/text-to-speech-fast")
|
38 |
-
client_2 = Client("ruslanmv/Text-To-Speech")
|
39 |
-
client_3 = Client("ruslanmv/Text-to-Voice-Transformers")
|
40 |
-
clients = [client_1, client_2, client_3]
|
41 |
-
# Text-to-speech function with rate limiting, retry mechanism, and client rotation
|
42 |
-
def text_to_speech(text, retries=3, delay=5):
|
43 |
-
client_index = 0 # Start with the first client
|
44 |
-
|
45 |
-
for attempt in range(retries):
|
46 |
-
try:
|
47 |
-
client = clients[client_index]
|
48 |
-
print(f"Attempt {attempt + 1}")
|
49 |
-
|
50 |
-
if client_index == 0:
|
51 |
-
result = client.predict(
|
52 |
-
language="English",
|
53 |
-
repo_id="csukuangfj/vits-piper-en_US-hfc_female-medium|1 speaker",
|
54 |
-
text=text,
|
55 |
-
sid="0",
|
56 |
-
speed=0.8,
|
57 |
-
api_name="/process"
|
58 |
-
)
|
59 |
-
else:
|
60 |
-
result = client.predict(
|
61 |
-
text=text,
|
62 |
-
api_name="/predict"
|
63 |
-
)
|
64 |
-
|
65 |
-
return result
|
66 |
-
|
67 |
-
except httpx.HTTPStatusError as e:
|
68 |
-
if e.response.status_code == 429:
|
69 |
-
print(f"Rate limit exceeded. Retrying in {delay} seconds...")
|
70 |
-
client_index = (client_index + 1) % len(clients) # Rotate to the next client
|
71 |
-
time.sleep(delay)
|
72 |
-
else:
|
73 |
-
raise e
|
74 |
-
|
75 |
-
print("Max retries exceeded. Could not process the request.")
|
76 |
-
return None
|
77 |
-
|
78 |
|
79 |
|
|
|
|
|
80 |
|
|
|
|
|
|
|
|
|
81 |
|
82 |
-
#
|
83 |
-
selected_questions = []
|
84 |
|
85 |
-
# Function to start exam
|
86 |
def start_exam(exam_choice, audio_enabled):
|
|
|
87 |
global selected_questions
|
88 |
selected_questions = select_exam_vce(exam_choice)
|
89 |
question, options, audio_path = display_question(0, audio_enabled)
|
90 |
return (
|
|
|
91 |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
92 |
-
gr.update(visible=False),
|
|
|
93 |
gr.update(visible=True), question, gr.update(choices=options, visible=True), gr.update(visible=True),
|
94 |
-
gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), 0, "", audio_path
|
|
|
95 |
)
|
96 |
|
97 |
-
# Function to display a question
|
98 |
def display_question(index, audio_enabled):
|
|
|
99 |
if index < 0 or index >= len(selected_questions):
|
100 |
return "No more questions.", [], None
|
101 |
-
question_text_ = selected_questions[index]
|
102 |
-
question_text = f"**Question {index + 1}:** {question_text_}"
|
103 |
-
choices_options = selected_questions[index]
|
104 |
audio_path = text_to_speech(question_text_ + " " + " ".join(choices_options)) if audio_enabled else None
|
105 |
return question_text, choices_options, audio_path
|
106 |
|
107 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
def check_answer(index, answer):
|
109 |
-
|
|
|
110 |
if answer == correct_answer:
|
111 |
return f"Correct! The answer is: {correct_answer}"
|
112 |
else:
|
113 |
return f"Incorrect. The correct answer is: {correct_answer}"
|
114 |
|
115 |
-
# Function to update the question
|
116 |
def update_question(index, audio_enabled):
|
|
|
117 |
question, options, audio_path = display_question(index, audio_enabled)
|
118 |
return question, gr.update(choices=options), index, audio_path
|
119 |
|
120 |
-
|
121 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
122 |
result = check_answer(index, answer)
|
123 |
-
|
124 |
-
return result,
|
|
|
125 |
|
126 |
-
# Function to handle the next question
|
127 |
def handle_next(index, audio_enabled):
|
|
|
128 |
new_index = min(index + 1, len(selected_questions) - 1)
|
129 |
question, options, new_index, audio_path = update_question(new_index, audio_enabled)
|
130 |
-
return question, options, new_index, "", audio_path
|
131 |
|
132 |
-
# Function to handle the previous question
|
133 |
def handle_previous(index, audio_enabled):
|
|
|
134 |
new_index = max(index - 1, 0)
|
135 |
question, options, new_index, audio_path = update_question(new_index, audio_enabled)
|
136 |
-
return question, options, new_index, "", audio_path
|
137 |
|
138 |
-
# Function to return to the home page
|
139 |
def return_home():
|
|
|
140 |
return (
|
|
|
141 |
gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True),
|
142 |
-
gr.update(visible=True),
|
|
|
143 |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
144 |
-
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), "", ""
|
|
|
145 |
)
|
146 |
|
147 |
-
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.
|
148 |
-
For more information about the developer, please visit [ruslanmv.com](https://ruslanmv.com/).
|
149 |
-
|
150 |
-
**Get Started with Your Quiz**
|
151 |
-
|
152 |
-
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."""
|
153 |
-
|
154 |
with gr.Blocks() as demo:
|
155 |
# Home page elements
|
156 |
title = gr.Markdown(value="**AWS Exam Simulator (Quiz)**")
|
@@ -159,15 +113,18 @@ with gr.Blocks() as demo:
|
|
159 |
audio_checkbox = gr.Checkbox(label="Enable Audio", value=True)
|
160 |
start_button = gr.Button("Start Exam")
|
161 |
|
162 |
-
#Quiz elements (initially hidden)
|
163 |
question_state = gr.State(0)
|
|
|
164 |
question_text = gr.Markdown(visible=False, elem_id="question-text")
|
165 |
choices = gr.Radio(visible=False, label="Options")
|
166 |
result_text = gr.Markdown(visible=True)
|
|
|
167 |
answer_button = gr.Button("Submit Answer", visible=False)
|
168 |
next_button = gr.Button("Next Question", visible=False)
|
169 |
prev_button = gr.Button("Previous Question", visible=False)
|
170 |
home_button = gr.Button("Return to Home", visible=False)
|
|
|
171 |
question_audio = gr.Audio(visible=False, label="Question Audio", autoplay=True)
|
172 |
answer_audio = gr.Audio(visible=False, label="Answer Audio", autoplay=True)
|
173 |
|
@@ -187,16 +144,16 @@ with gr.Blocks() as demo:
|
|
187 |
with gr.Row():
|
188 |
gr.Column([choices])
|
189 |
with gr.Row():
|
190 |
-
gr.Column([result_text, answer_audio])
|
191 |
with gr.Row():
|
192 |
gr.Column([prev_button], scale=1)
|
193 |
gr.Column([], scale=8)
|
194 |
gr.Column([next_button], scale=1)
|
195 |
with gr.Row():
|
196 |
-
gr.Column([answer_button])
|
197 |
with gr.Row():
|
198 |
gr.Column([home_button])
|
199 |
-
|
200 |
# Connect the start button to start the exam
|
201 |
start_button.click(
|
202 |
fn=start_exam,
|
@@ -205,21 +162,23 @@ with gr.Blocks() as demo:
|
|
205 |
title, description, exam_selector, start_button,
|
206 |
audio_checkbox, # Ensure the checkbox visibility is updated
|
207 |
question_text, question_text, choices, answer_button,
|
208 |
-
next_button, prev_button, home_button, question_state, result_text, question_audio
|
|
|
209 |
]
|
210 |
)
|
|
|
211 |
# Connect the quiz buttons to their functions
|
212 |
-
answer_button.click(fn=handle_answer, inputs=[question_state, choices, audio_checkbox], outputs=[result_text, answer_audio])
|
213 |
-
next_button.click(fn=handle_next, inputs=[question_state, audio_checkbox], outputs=[question_text, choices, question_state, result_text, question_audio])
|
214 |
-
prev_button.click(fn=handle_previous, inputs=[question_state, audio_checkbox], outputs=[question_text, choices, question_state, result_text, question_audio])
|
|
|
|
|
|
|
215 |
home_button.click(fn=return_home, inputs=None, outputs=[
|
216 |
title, description, exam_selector, start_button,
|
217 |
audio_checkbox, # Ensure the checkbox visibility is updated
|
218 |
question_text, question_text, choices, answer_button,
|
219 |
-
next_button, prev_button, home_button, question_state, result_text
|
220 |
])
|
221 |
|
222 |
demo.launch()
|
223 |
-
|
224 |
-
### Notes revision v0.3.1
|
225 |
-
#In this revised code, JavaScript is used to stop any currently playing audio when a new audio is about to be played. The _js parameter is added to the click function of the buttons that play audio (answer_button, next_button, and prev_button) to ensure that no multiple audios are played simultaneously
|
|
|
1 |
'''
|
2 |
+
AWS Exam Simulator v.05
|
3 |
Program Developed by Ruslan Magana Vsevolovna
|
4 |
The purpose of this program is help to practice the questions of AWS Exams.
|
5 |
'''
|
6 |
import gradio as gr
|
7 |
+
from tool import * # Assuming this module contains your exam data and text-to-speech functionality
|
8 |
+
from backend1 import *
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
|
10 |
|
11 |
+
# Global variable to store the currently selected set of exam questions
|
12 |
+
selected_questions = []
|
13 |
|
14 |
+
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.
|
15 |
+
For more information about the developer, please visit [ruslanmv.com](https://ruslanmv.com/).
|
16 |
+
**Get Started with Your Quiz**
|
17 |
+
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."""
|
18 |
|
19 |
+
# --- FUNCTION DEFINITIONS ---
|
|
|
20 |
|
|
|
21 |
def start_exam(exam_choice, audio_enabled):
|
22 |
+
"""Starts the exam by selecting questions, setting up UI."""
|
23 |
global selected_questions
|
24 |
selected_questions = select_exam_vce(exam_choice)
|
25 |
question, options, audio_path = display_question(0, audio_enabled)
|
26 |
return (
|
27 |
+
# Hide start screen elements
|
28 |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
29 |
+
gr.update(visible=False), # Hide the audio_checkbox
|
30 |
+
# Show quiz elements
|
31 |
gr.update(visible=True), question, gr.update(choices=options, visible=True), gr.update(visible=True),
|
32 |
+
gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), 0, "", audio_path, gr.update(visible=True),
|
33 |
+
gr.update(visible=True), None # None for the audio stop signal
|
34 |
)
|
35 |
|
|
|
36 |
def display_question(index, audio_enabled):
|
37 |
+
"""Displays a question with options and generates audio (if enabled)."""
|
38 |
if index < 0 or index >= len(selected_questions):
|
39 |
return "No more questions.", [], None
|
40 |
+
question_text_ = selected_questions[index].get('question', 'No question text available.')
|
41 |
+
question_text = f"**Question {index + 1}:** {question_text_}"
|
42 |
+
choices_options = selected_questions[index].get('options', [])
|
43 |
audio_path = text_to_speech(question_text_ + " " + " ".join(choices_options)) if audio_enabled else None
|
44 |
return question_text, choices_options, audio_path
|
45 |
|
46 |
+
def show_explanation(index):
|
47 |
+
"""Shows the explanation for the current question and hides previous results."""
|
48 |
+
if 0 <= index < len(selected_questions):
|
49 |
+
explanation = selected_questions[index].get('explanation', 'No explanation available for this question.')
|
50 |
+
return (
|
51 |
+
f"**Explanation:** {explanation}",
|
52 |
+
gr.update(visible=True), # Show explanation_text
|
53 |
+
gr.update(visible=True) # Show result_text
|
54 |
+
)
|
55 |
+
else:
|
56 |
+
return "No explanation available for this question.", gr.update(visible=False), gr.update(visible=False)
|
57 |
+
|
58 |
def check_answer(index, answer):
|
59 |
+
"""Checks the given answer against the correct answer."""
|
60 |
+
correct_answer = selected_questions[index].get('correct', 'No correct answer provided.')
|
61 |
if answer == correct_answer:
|
62 |
return f"Correct! The answer is: {correct_answer}"
|
63 |
else:
|
64 |
return f"Incorrect. The correct answer is: {correct_answer}"
|
65 |
|
|
|
66 |
def update_question(index, audio_enabled):
|
67 |
+
"""Updates the displayed question when the index changes."""
|
68 |
question, options, audio_path = display_question(index, audio_enabled)
|
69 |
return question, gr.update(choices=options), index, audio_path
|
70 |
|
71 |
+
def handle_answer(index, answer, audio_enabled, current_audio):
|
72 |
+
"""Handles answer submission, provides feedback, and generates audio."""
|
73 |
+
# Handle the case when no answer is selected
|
74 |
+
if answer is None:
|
75 |
+
return "Please select an option before submitting.", None, None
|
76 |
+
|
77 |
+
# Stop the current question audio before playing the answer audio
|
78 |
+
stop_audio = True if current_audio else False
|
79 |
result = check_answer(index, answer)
|
80 |
+
answer_audio_path = text_to_speech(result) if audio_enabled else None
|
81 |
+
return result, answer_audio_path, stop_audio
|
82 |
+
|
83 |
|
|
|
84 |
def handle_next(index, audio_enabled):
|
85 |
+
"""Moves to the next question and updates the UI."""
|
86 |
new_index = min(index + 1, len(selected_questions) - 1)
|
87 |
question, options, new_index, audio_path = update_question(new_index, audio_enabled)
|
88 |
+
return question, options, new_index, "", audio_path, gr.update(visible=False) # Hide explanation
|
89 |
|
|
|
90 |
def handle_previous(index, audio_enabled):
|
91 |
+
"""Moves to the previous question and updates the UI."""
|
92 |
new_index = max(index - 1, 0)
|
93 |
question, options, new_index, audio_path = update_question(new_index, audio_enabled)
|
94 |
+
return question, options, new_index, "", audio_path, gr.update(visible=False) # Hide explanation
|
95 |
|
|
|
96 |
def return_home():
|
97 |
+
"""Returns to the home screen."""
|
98 |
return (
|
99 |
+
# Show start screen elements
|
100 |
gr.update(visible=True), gr.update(visible=True), gr.update(visible=True), gr.update(visible=True),
|
101 |
+
gr.update(visible=True), # Show the audio_checkbox
|
102 |
+
# Hide quiz elements
|
103 |
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False),
|
104 |
+
gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), "", "", gr.update(visible=False), gr.update(visible=False),
|
105 |
+
gr.update(visible=False) # Hide explain button
|
106 |
)
|
107 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
108 |
with gr.Blocks() as demo:
|
109 |
# Home page elements
|
110 |
title = gr.Markdown(value="**AWS Exam Simulator (Quiz)**")
|
|
|
113 |
audio_checkbox = gr.Checkbox(label="Enable Audio", value=True)
|
114 |
start_button = gr.Button("Start Exam")
|
115 |
|
116 |
+
# Quiz elements (initially hidden)
|
117 |
question_state = gr.State(0)
|
118 |
+
current_audio_state = gr.State(None) # State to track the current audio playing
|
119 |
question_text = gr.Markdown(visible=False, elem_id="question-text")
|
120 |
choices = gr.Radio(visible=False, label="Options")
|
121 |
result_text = gr.Markdown(visible=True)
|
122 |
+
explanation_text = gr.Markdown(visible=False)
|
123 |
answer_button = gr.Button("Submit Answer", visible=False)
|
124 |
next_button = gr.Button("Next Question", visible=False)
|
125 |
prev_button = gr.Button("Previous Question", visible=False)
|
126 |
home_button = gr.Button("Return to Home", visible=False)
|
127 |
+
explain_button = gr.Button("Explain", visible=False)
|
128 |
question_audio = gr.Audio(visible=False, label="Question Audio", autoplay=True)
|
129 |
answer_audio = gr.Audio(visible=False, label="Answer Audio", autoplay=True)
|
130 |
|
|
|
144 |
with gr.Row():
|
145 |
gr.Column([choices])
|
146 |
with gr.Row():
|
147 |
+
gr.Column([result_text, explanation_text, answer_audio])
|
148 |
with gr.Row():
|
149 |
gr.Column([prev_button], scale=1)
|
150 |
gr.Column([], scale=8)
|
151 |
gr.Column([next_button], scale=1)
|
152 |
with gr.Row():
|
153 |
+
gr.Column([answer_button, explain_button])
|
154 |
with gr.Row():
|
155 |
gr.Column([home_button])
|
156 |
+
|
157 |
# Connect the start button to start the exam
|
158 |
start_button.click(
|
159 |
fn=start_exam,
|
|
|
162 |
title, description, exam_selector, start_button,
|
163 |
audio_checkbox, # Ensure the checkbox visibility is updated
|
164 |
question_text, question_text, choices, answer_button,
|
165 |
+
next_button, prev_button, home_button, question_state, result_text, question_audio,
|
166 |
+
explain_button, current_audio_state # Add current_audio_state to the outputs
|
167 |
]
|
168 |
)
|
169 |
+
|
170 |
# Connect the quiz buttons to their functions
|
171 |
+
answer_button.click(fn=handle_answer, inputs=[question_state, choices, audio_checkbox, current_audio_state], outputs=[result_text, answer_audio, current_audio_state])
|
172 |
+
next_button.click(fn=handle_next, inputs=[question_state, audio_checkbox], outputs=[question_text, choices, question_state, result_text, question_audio, explanation_text])
|
173 |
+
prev_button.click(fn=handle_previous, inputs=[question_state, audio_checkbox], outputs=[question_text, choices, question_state, result_text, question_audio, explanation_text])
|
174 |
+
|
175 |
+
explain_button.click(fn=show_explanation, inputs=[question_state], outputs=[explanation_text, result_text, explanation_text]) # Output to both to toggle visibility
|
176 |
+
|
177 |
home_button.click(fn=return_home, inputs=None, outputs=[
|
178 |
title, description, exam_selector, start_button,
|
179 |
audio_checkbox, # Ensure the checkbox visibility is updated
|
180 |
question_text, question_text, choices, answer_button,
|
181 |
+
next_button, prev_button, home_button, question_state, result_text, explanation_text, explain_button
|
182 |
])
|
183 |
|
184 |
demo.launch()
|
|
|
|
|
|
questions/GCP-ML-vA.json
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
questions/MLS-C01-v0624.json
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
questions/SAA-C03-v2.json
CHANGED
The diff for this file is too large to render.
See raw diff
|
|