maeliprof / app.py
gardarjuto's picture
Improved description and title
e568e74
import gradio as gr
import matplotlib as mpl
from quiz import BenchmarkQuiz, BENCHMARKS, QuestionData
mpl.rcParams["figure.dpi"] = 300
def update_quiz_screen(quiz: BenchmarkQuiz, question_data: QuestionData):
quiz_state = quiz.state
return {
quiz_screen: gr.update(visible=True),
question_number: gr.update(value=question_data.question_num),
question_text: gr.update(value=question_data.question),
answer_input: gr.update(
value=quiz_state.user_answers[quiz_state.current_question],
choices=question_data.options,
visible=BENCHMARKS[quiz_state.benchmark_name]["type"] == "multiple_choice",
label=question_data.instruction,
),
free_text_input: gr.update(
value=quiz_state.user_answers[quiz_state.current_question],
visible=BENCHMARKS[quiz_state.benchmark_name]["type"] == "free_text",
label=question_data.instruction,
),
next_button: gr.update(
value=question_data.next_button_text,
),
previous_button: gr.update(visible=question_data.previous_button_visibility),
}
def update_score_screen(plot, results_data):
updates = {
score_screen: gr.update(visible=True),
score_plot: gr.update(value=plot),
results_container: gr.update(visible=True),
}
for i, result in enumerate(results_data):
updates[result_cards[i]] = gr.update(
visible=True,
elem_classes=[
"correct-answer"
if result["points"] == 1.0
else "semi-correct-answer"
if result["points"] == 0.5
else "incorrect-answer"
],
)
emoji = (
"✅"
if result["points"] == 1.0
else "❌"
if result["points"] == 0.0
else "🔶"
)
markdown_string = f"### {emoji} Spurning {result['question_num']}"
markdown_string += f"\n{result['question']}"
markdown_string += (
f"\n\nValkostir:\n"
+ "\n".join([f"- {option}" for option in result["options"]])
if result["options"]
else ""
)
markdown_string += f"\n\n**Þitt svar:** {result['user_answer']}"
markdown_string += f"\n\n**Rétt svar:** {result['correct_answer']}"
markdown_string += f"\n\n**Stig:** {result['points']}"
updates[result_cards[i].children[0]] = gr.update(value=markdown_string)
return updates
def start_quiz_handler(benchmark_name):
quiz = BenchmarkQuiz()
quiz.start_quiz(benchmark_name)
question_data = quiz.update_question()
return {
start_screen: gr.update(visible=False),
score_screen: gr.update(visible=False),
**update_quiz_screen(quiz, question_data),
quiz_state: quiz,
}
def next_question_handler(quiz, answer_input, free_text_input):
answer = (
answer_input
if BENCHMARKS[quiz.state.benchmark_name]["type"] == "multiple_choice"
else free_text_input
)
result = quiz.next_question(answer)
if result["completed"]:
return {
quiz_screen: gr.update(visible=False),
**update_score_screen(result["plot"], result["results_data"]),
quiz_state: quiz,
}
else:
return {**update_quiz_screen(quiz, result["question_data"]), quiz_state: quiz}
def previous_question_handler(quiz):
question_data = quiz.previous_question()
return {**update_quiz_screen(quiz, question_data), quiz_state: quiz}
def reset_quiz_handler():
return {
start_screen: gr.update(visible=True),
quiz_screen: gr.update(visible=False),
score_screen: gr.update(visible=False),
next_button: gr.update(visible=True),
}
demo = gr.Blocks(
theme=gr.themes.Soft(),
title="Mælipróf",
css="""
.correct-answer, .correct-answer .block {
background-color: #d4edda !important;
border-color: #c3e6cb !important;
}
.incorrect-answer, .incorrect-answer .block {
background-color: #f8d7da !important;
border-color: #f5c6cb !important;
}
.semi-correct-answer, .semi-correct-answer .block {
background-color: #fff3cd !important;
border-color: #ffeeba !important;
}
.correct-answer, .incorrect-answer, .semi-correct-answer {
border-radius: 5px;
padding: 10px;
margin-bottom: 10px;
}
""",
)
with demo:
start_screen = gr.Column(visible=True)
with start_screen:
gr.Markdown("# Kepptu við risamállíkönin!")
gr.Markdown(
"Veldu þér einn af flokkunum að neðan og þreyttu stutta útgáfu af prófi sem við leggjum fyrir risamállíkönin. "
"Eftir að þú hefur lokið prófinu færðu að sjá hvar þú stendur miðað við líkönin."
)
benchmark_buttons = {
name: gr.Button(info["name"]) for name, info in BENCHMARKS.items()
}
quiz_screen = gr.Column(visible=False)
with quiz_screen:
question_number = gr.Markdown()
question_text = gr.Markdown()
answer_input = gr.Radio(choices=[], visible=False)
free_text_input = gr.Textbox(visible=False)
with gr.Row():
previous_button = gr.Button("Fyrri")
next_button = gr.Button("Næsta")
score_screen = gr.Column(visible=False)
with score_screen:
gr.Markdown(f"## Niðurstöður")
score_plot = gr.Plot()
reset_btn = gr.Button("Byrja upp á nýtt")
results_container = gr.Column(visible=False)
with results_container:
result_cards = [gr.Group(visible=False) for _ in range(5)]
for card in result_cards:
with card:
gr.Markdown("")
quiz_state = gr.State()
for benchmark_name, button in benchmark_buttons.items():
button.click(
fn=start_quiz_handler,
inputs=[gr.State(benchmark_name)],
outputs=[
start_screen,
quiz_screen,
score_screen,
question_number,
question_text,
answer_input,
free_text_input,
next_button,
previous_button,
quiz_state,
],
)
next_button.click(
fn=next_question_handler,
inputs=[quiz_state, answer_input, free_text_input],
outputs=[
quiz_screen,
score_screen,
question_number,
question_text,
answer_input,
free_text_input,
next_button,
previous_button,
score_plot,
results_container,
*result_cards,
*[child for card in result_cards for child in card.children],
quiz_state,
],
)
previous_button.click(
fn=previous_question_handler,
inputs=[quiz_state],
outputs=[
quiz_screen,
question_number,
question_text,
answer_input,
free_text_input,
next_button,
previous_button,
quiz_state,
],
)
reset_btn.click(
fn=reset_quiz_handler,
inputs=[],
outputs=[start_screen, quiz_screen, score_screen, next_button],
)
demo.launch()