|
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() |
|
|