-
Notifications
You must be signed in to change notification settings - Fork 0
/
widgets_problem_basic.py
143 lines (110 loc) · 4.46 KB
/
widgets_problem_basic.py
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
from IPython.display import display, Markdown, clear_output
import ipywidgets as widgets
import random
import markdown
from ..MathProblems.problem_basic import Problem, MultipleChoice
from .widgets_aux import update_output_widget
"""
Defines a class for basic problem handling: statement, type, answer
and checking
"""
COLORS = ['primary', 'success', 'info', 'warning', 'danger']
class ProblemWidget:
"""
Show a basic widget displaying title, statement, and solution
"""
def __init__(self, problem: Problem):
self.problem = problem
self.status = 'undecided'
self.check = []
self.title = widgets.Output()
self.statement = widgets.Output()
self.has_solution = bool(self.problem.solution)
self.solution_text = widgets.Output()
with self.solution_text:
display(widgets.HTMLMath(markdown.markdown(self.problem.solution)))
self.solution = widgets.Accordion(
children=[self.solution_text])
self.solution.selected_index = None
self.solution.set_title(0, 'Show Solution')
def show(self):
# Show just title and statement
update_output_widget(self.title, '### ' + self.problem.title)
update_output_widget(
self.statement, self.problem.statement)
display(widgets.VBox([self.title, self.statement]))
if self.has_solution:
display(self.solution)
class MultipleChoiceWidget(ProblemWidget):
def __init__(self, problem: MultipleChoice):
super().__init__(problem)
self.choices = widgets.Output()
self.feedback = widgets.Output(layout=widgets.Layout(height='50px'))
self.shuffle_answers()
# create buttons
self.choice_buttons = [
widgets.Button(
description='( '+str(i+1)+' )',
disabled=False,
button_style=COLORS[i],
tooltip='Answer choice '+str(i+1),
layout=widgets.Layout(flex='1 1 auto', width='auto'))
for i in range(self.problem.num_choices)]
# Activate handler for every button
for button in self.choice_buttons:
# link to a click event function
button.on_click(self.on_button_clicked)
def shuffle_answers(self):
self.indices = [i for i in range(self.problem.num_choices)]
random.shuffle(self.indices)
self.correct = self.indices.index(0)
def show(self):
# show title and statement
update_output_widget(self.title, '### ' + self.problem.title)
update_output_widget(self.statement, self.problem.statement)
display(widgets.VBox([self.title, self.statement]))
# display choices
with self.choices:
clear_output()
for i in range(self.problem.num_choices):
display(widgets.HTMLMathL(markdown.markdown(
'**(' + str(i+1) + ')** ' + self.problem.choices[self.indices[i]])))
display(widgets.VBox([self.choices, widgets.HBox(
self.choice_buttons), self.feedback]))
with self.feedback:
clear_output()
display(Markdown('Please select your answer.'))
display(self.solution)
def on_button_clicked(self, bt):
self.check_answer(bt.description[2:-2])
def check_answer(self, answer):
# reset current answer check
self.check = []
# Pre-process answer string to remove parentheses (if present)
answer = answer[0]
if len(answer) > 0 and answer[0] == '(':
answer = answer[1:]
if len(answer) > 0 and answer[-1] == ')':
answer = answer[:-1]
try:
if self.correct == int(answer)-1:
self.check.append(True)
else:
self.check.append(False)
except ValueError:
self.check.append('Error')
if self.check[0] == True:
result_string = 'You selected: ('+answer+') -- ' + \
'✅ **Correct!**'
self.status = 'correct'
elif self.check[0] == False:
result_string = 'You selected: ('+answer+') -- ' + \
'❌ **Incorrect**'
self.status = 'incorrect'
else:
result_string = 'Please enter an integer value.'
self.status = 'undecided'
# show feedback
with self.feedback:
clear_output()
display(Markdown(result_string))