Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 7f4bee9

Browse files
committed
Merge pull request #9 from riknos314/master
Ported the assess components and the datafile component to be RSE 0001 complient
2 parents 0474325 + e8ede02 commit 7f4bee9

File tree

15 files changed

+2090
-1425
lines changed

15 files changed

+2090
-1425
lines changed

runestone/assess/README.md

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
<h2>Multiple Choice</h2>
2+
3+
<ul data-component="multiplechoice" data-multipleanswers="true" data-random id="question-1">
4+
The Question can go right here.
5+
6+
<li data-component="answer" id="123" >Answer One</li>
7+
<li data-component="feedback" for="123">Feedback for One</li>
8+
9+
<li data-component="answer" id="456">Answer Two</li>
10+
<li data-component="feedback" for="456">Feedback for Two</li>
11+
12+
<li data-component="answer" id="789" data-correct>Answer Three</li>
13+
<li data-component="feedback" for="789">Feedback for Three</li>
14+
15+
<li data-component="answer" id="1011" data-correct>Answer Four</li>
16+
<li data-component="feedback" for="1011">Feedback for Four</li>
17+
18+
<li data-component="answer" id="1112" data-correct>Answer Five</li>
19+
<li data-component="feedback" for="1112">Feedback for Five</li>
20+
</ul>
21+
22+
Here the <code>ul</code> tag represents the entire component to be rendered.
23+
Each 2 <code>li</code> answer/feedback pair represents a possible answer to the question and the feedback to be provided if that answer is selected.
24+
25+
<ul>
26+
<li><code>data-component</code> identifies this as a multiple choice component</li>
27+
<li><code>class</code> Standard CSS class options </li>
28+
<li><code>id</code> must be unique in the document</li>
29+
<li><code>data-multipleanswers</code> REQUIRED Attribute. Possible values are true and false. Determines whether the question can take one or more answers on submission (radio vs checkbox).</li>
30+
<li><code>data-random</code> Randomizes the order that the possible answers are displayed on the page</li>
31+
<li><code>data-timed</code> Required if this MC question is inside of a timed assessment, will break things if not.</li>
32+
<br />
33+
<p>Attributes of the question tags</p>
34+
<br />
35+
<li><code>id</code> must be unique per MC component</li>
36+
<li><code>for</code> must match the id of the option that the feedback is for</li>
37+
<li><code>data-correct</code> indicates that this option is a correct answer. If <code>data-multipleanswers</code> is true, all answers with the attribute will be considered correct, otherwise the first answer with the <code>data-correct></code> attribute will be considered correct.</li>
38+
</ul>
39+
40+
<h2>Fill In the Blank</h2>
41+
42+
<p data-component="fillintheblank" data-casei="false" id="fill1412" >
43+
<span data-blank>Without using the activecode infixToPostfix function, convert the following expression to postfix <code>10 + 3 * 5 / (16 - 4)</code>
44+
<span data-answer id="blank2_answer">\\b10\\s+3\\s+5\\s*\\*\\s*16\\s+4\\s*-\\s*/\\s*\\+</span>
45+
46+
<span data-feedback="regex" id="feedback1">10.*3.*5.*16.*4</span>
47+
<span data-feedback="text" for="feedback1">The numbers appear to be in the correct order check your operators</span>
48+
49+
<span data-feedback="regex" id="feedback2">.*</span>
50+
<span data-feedback="text" for="feedback2">Remember the numbers will be in the same order as the original equation</span>
51+
</span>
52+
</p>
53+
54+
Here the <code>p</code> tag represents the entire component.
55+
The <code>data-blank</code><code>span</code>Holds the question text.
56+
The <code>data-answer</code><code>span</code>Holds the correct regular expression.
57+
Each regex,text <code>span</code> pair represents a point of feedback for incorrect answers.
58+
59+
Multiple blanks can also be put into the same FITB question as shown here.
60+
61+
<p data-component="fillintheblank" data-casei="false" data-timed id="fill1412" >
62+
63+
<span data-blank>Give me a string that has an 'e' in it. Now.<span data-answer id="blank2_answer">e</span>
64+
<span data-feedback="regex" id="feedback1">f</span>
65+
<span data-feedback="text" for="feedback1">Oops</span>
66+
67+
<span data-feedback="regex" id="feedback2">.*</span>
68+
<span data-feedback="text" for="feedback2">There's no e there!</span>
69+
</span>
70+
71+
<span data-blank>Gimme an f. Please.<span data-answer id="blank12_answer">f</span>
72+
<span data-feedback="regex" id="feedback3">e</span>
73+
<span data-feedback="text" for="feedback3">Wrong.</span>
74+
75+
<span data-feedback="regex" id="feedback4">.*</span>
76+
<span data-feedback="text" for="feedback4">There's no f in that string!</span>
77+
</span>
78+
79+
<span data-blank>Show me 44!<span data-answer id="blank3_answer">44</span>
80+
<span data-feedback="regex" id="feedback5">1</span>
81+
<span data-feedback="text" for="feedback5">nope</span>
82+
83+
<span data-feedback="regex" id="feedback6">4</span>
84+
<span data-feedback="text" for="feedback6">close</span>
85+
86+
<span data-feedback="regex" id="feedback7">.*</span>
87+
<span data-feedback="text" for="feedback7">Sorry bro</span>
88+
</span>
89+
</p>
90+
91+
<ul>
92+
<li><code>data-casei</code> Determines if the answer is case insensitive</li>
93+
<li><code>id</code> Must be unique in the document</li>
94+
<li><code>timed</code> Required for a FITB component inside of a timed assessment</li>
95+
96+
</ul>
97+
98+
<h2>Timed</h2>
99+
100+
<ul data-component="timedAssessment" data-time id="timed_1">
101+
<ul data-component="multiplechoice" data-multipleanswers="true" data-timed data-random id="question_1">
102+
The Question can go right here.
103+
<li data-component="answer" id="123" >Answer One</li>
104+
<li data-component="feedback" for="123">Feedback for One</li>
105+
106+
<li data-component="answer" id="456">Answer Two</li>
107+
<li data-component="feedback" for="456">Feedback for Two</li>
108+
109+
<li data-component="answer" id="789" data-correct>Answer Three</li>
110+
<li data-component="feedback" for="789">Feedback for Three</li>
111+
</ul>
112+
113+
<ul data-component="multiplechoice" data-timed id="question_2">
114+
The Question can go right here.
115+
<li data-component="answer" id="123" >Answer One</li>
116+
<li data-component="feedback" for="123">Feedback for One</li>
117+
118+
<li data-component="answer" id="456">Answer Two</li>
119+
<li data-component="feedback" for="456">Feedback for Two</li>
120+
121+
<li data-component="answer" id="789" data-correct>Answer Three</li>
122+
<li data-component="feedback" for="789">Feedback for Three</li>
123+
</ul>
124+
125+
<p data-component="fillintheblank" data-casei="false" data-timed id="fill1412" >
126+
127+
<span data-blank>Give me a string that has an 'e' in it. Now.<span data-answer id="blank2_answer">e</span>
128+
129+
<span data-feedback="regex" id="feedback1">f</span>
130+
<span data-feedback="text" for="feedback1">Oops</span>
131+
132+
<span data-feedback="regex" id="feedback2">.*</span>
133+
<span data-feedback="text" for="feedback2">There's no e there!</span>
134+
135+
</span>
136+
</p>
137+
</ul>
138+
139+
Here the outermost <code>ul</code> tag marks the timed element, and the tags inside represent the questions in the timed assessment.
140+
141+
Currently only 1 timed assessment is allowed per page.
142+
143+
<ul>
144+
<li><code>data-time</code> Can either be set equal to the time limit for the assessment in minutes or left blank, in which case the assessment will keep track of how long it takes to complete the assessment.</li>
145+
<li><code>id</code> Must be unique in the document</li>
146+
<li><code>data-no-result</code> If present, it won't display the score to the user after the assessment is finished</li>
147+
<li><code>data-no-feedback</code> If present, feedback won't be displayed.</li>
148+
149+
</ul>

runestone/assess/README.rst

Lines changed: 0 additions & 13 deletions
This file was deleted.

runestone/assess/assess.py

Lines changed: 11 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -20,28 +20,30 @@
2020
from docutils.parsers.rst import Directive
2121
from .assessbase import Assessment
2222
from .multiplechoice import *
23-
from .textfield import *
24-
from .blankfill import *
23+
from .fitb import *
24+
from .timedassessment import *
2525

2626

2727
def setup(app):
28+
app.add_directive('mchoice', MChoice)
2829
app.add_directive('mchoicemf', MChoiceMF)
2930
app.add_directive('mchoicema', MChoiceMA)
30-
app.add_directive('timedmchoicemf', timedMChoiceMF)
31-
app.add_directive('starttimer', StartTimer)
32-
app.add_directive('finishtimer', FinishTimer)
31+
app.add_directive('mchoicerandommf', MChoiceRandomMF)
3332
app.add_directive('fillintheblank', FillInTheBlank)
34-
app.add_directive('mcmfrandom', MChoiceRandomMF)
33+
app.add_directive('blank', Blank)
3534
app.add_directive('addbutton', AddButton)
3635
app.add_directive('qnum', QuestionNumber)
37-
app.add_directive('revealquestions', RevealQuestions)
38-
app.add_role('textfield', textfield_role)
36+
app.add_directive('timed', TimedDirective)
3937

38+
app.add_stylesheet('fitb.css')
4039
app.add_javascript('assess.js')
4140

41+
app.add_node(TimedNode, html=(visit_timed_node, depart_timed_node))
4242
app.add_node(MChoiceNode, html=(visit_mc_node, depart_mc_node))
4343
app.add_node(FITBNode, html=(visit_fitb_node, depart_fitb_node))
44-
app.add_node(RevealQNode, html=(visit_reveal_qnode, depart_reveal_qnode))
44+
app.add_node(BlankNode, html=(visit_blank_node, depart_blank_node))
45+
46+
4547

4648

4749
class AddButton(Directive):
@@ -102,158 +104,3 @@ def run(self):
102104
env.assesssuffix = self.options['suffix']
103105

104106
return []
105-
106-
107-
#####################
108-
109-
class StartTimer(Directive):
110-
required_arguments = 1
111-
optional_arguments = 1
112-
final_argument_whitespace = True
113-
has_content = True
114-
option_spec = {"duration": directives.unchanged}
115-
116-
def run(self):
117-
"""
118-
:param self:
119-
:return:
120-
.. addbutton:: bname
121-
122-
...
123-
"""
124-
125-
if 'duration' in self.options:
126-
TEMPLATE_START = '''
127-
<div id="startWrapper">
128-
<p id="output"></p>
129-
</div>
130-
<div id="controls" style="text-align: center;">
131-
<button class='btn btn-inverse' id ="start" onclick="start()">Start</button>
132-
<button class='btn btn-inverse' id ="pause" onclick="pause()">Pause</button>
133-
'''
134-
else:
135-
TEMPLATE_START = '''
136-
<p id="output"></p>
137-
<div id="controls">
138-
<button class='btn btn-inverse' id ="start" onclick="start(30)">Start</button>
139-
<button class='btn btn-inverse' id ="pause" onclick="pause()">Pause</button>
140-
'''
141-
142-
TEMPLATE_END = '''
143-
<script>
144-
var time = %(duration)s * 60;
145-
showTime(%(duration)s * 60);
146-
</script>
147-
148-
</div>
149-
'''
150-
151-
self.options['divid'] = self.arguments[0]
152-
153-
res = ""
154-
res = TEMPLATE_START % self.options
155-
156-
res += TEMPLATE_END % self.options
157-
return [nodes.raw('', res, format='html')]
158-
159-
160-
################################################################################################
161-
162-
class FinishTimer(Directive):
163-
required_arguments = 1
164-
optional_arguments = 1
165-
final_argument_whitespace = True
166-
has_content = True
167-
168-
def run(self):
169-
"""
170-
:param self:
171-
:return:
172-
.. addbutton:: bname
173-
174-
...
175-
"""
176-
177-
TEMPLATE_START = '''
178-
179-
'''
180-
181-
TEMPLATE_END = '''
182-
183-
<div style="text-align: center;">
184-
<button class='btn btn-inverse' id ="finish" onclick="checkTimedMCMFStorage()">Submit Answers</button>
185-
</div>
186-
<p id="results"></p>
187-
<script>
188-
$(document).ready(function() {checkIfFinished()});
189-
</script>
190-
191-
192-
'''
193-
194-
self.options['divid'] = self.arguments[0]
195-
196-
res = ""
197-
res = TEMPLATE_START % self.options
198-
199-
res += TEMPLATE_END % self.options
200-
return [nodes.raw('', res, format='html')]
201-
202-
#########################################################################
203-
204-
BEGIN = """
205-
206-
<div id='%(divid)s' style='display:none'>
207-
"""
208-
# <button type='button' id='button_show' class='btn btn-default reveal_button' style='margin-bottom:10px;' onclick="">
209-
# %(showtitle)s
210-
# </button>
211-
# <button type='button' id='button_hide' class='btn btn-default reveal_button' onclick="" style='display:none'>
212-
# %(hidetitle)s
213-
# </button>
214-
END = """
215-
</div> <!-- end reveal -->
216-
"""
217-
218-
219-
class RevealQNode(nodes.General, nodes.Element):
220-
def __init__(self, content):
221-
super(RevealQNode, self).__init__()
222-
self.reveal_components = content
223-
224-
225-
def visit_reveal_qnode(self, node):
226-
res = BEGIN % node.reveal_components
227-
228-
self.body.append(res)
229-
230-
231-
def depart_reveal_qnode(self, node):
232-
res = END % node.reveal_components
233-
234-
self.body.append(res)
235-
236-
237-
class RevealQuestions(Directive):
238-
required_arguments = 1
239-
optional_arguments = 0
240-
final_argument_whitespace = True
241-
has_content = True
242-
option_spec = {"showtitle": directives.unchanged,
243-
"hidetitle": directives.unchanged}
244-
245-
def run(self):
246-
self.assert_has_content() # an empty reveal block isn't very useful...
247-
248-
if not 'showtitle' in self.options:
249-
self.options['showtitle'] = "Timed Quiz Paused/Not Started"
250-
if not 'hidetitle' in self.options:
251-
self.options['hidetitle'] = "Currently Taking Timed Quiz"
252-
253-
self.options['divid'] = self.arguments[0]
254-
255-
reveal_node = RevealQNode(self.options)
256-
257-
self.state.nested_parse(self.content, self.content_offset, reveal_node)
258-
259-
return [reveal_node]

0 commit comments

Comments
 (0)