Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
94b149f9
Commit
94b149f9
authored
Dec 15, 2011
by
Piotr Mitros
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
MathJAX and formula answers work
parent
b09ab3a7
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
94 additions
and
27 deletions
+94
-27
courseware/capa_problem.py
+94
-27
No files found.
courseware/capa_problem.py
View file @
94b149f9
# For calculator:
# http://pyparsing.wikispaces.com/file/view/fourFn.py
import
random
,
numpy
,
math
,
scipy
,
sys
,
StringIO
,
os
,
struct
,
json
import
random
,
numpy
,
math
,
scipy
,
sys
,
StringIO
,
os
,
struct
,
json
from
xml.dom.minidom
import
parse
,
parseString
from
xml.dom.minidom
import
parse
,
parseString
from
calc
import
evaluator
def
strip_dict
(
d
):
''' Takes a dict. Returns an identical dict, with all non-word keys stripped out. '''
d
=
dict
([(
k
,
float
(
d
[
k
]))
for
k
in
d
if
type
(
k
)
==
str
and
\
k
.
isalnum
()
and
\
(
type
(
d
[
k
])
==
float
or
type
(
d
[
k
])
==
int
)
])
return
d
class
LoncapaProblem
():
class
LoncapaProblem
():
def
get_state
(
self
):
def
get_state
(
self
):
''' Stored per-user session data neeeded to:
''' Stored per-user session data neeeded to:
...
@@ -71,15 +77,15 @@ class LoncapaProblem():
...
@@ -71,15 +77,15 @@ class LoncapaProblem():
# Loop through the nodes of the problem, and
# Loop through the nodes of the problem, and
for
e
in
dom
.
childNodes
:
for
e
in
dom
.
childNodes
:
print
e
,
ot
#
print e, ot
#
#
if
e
.
localName
==
'script'
:
if
e
.
localName
==
'script'
:
print
e
.
childNodes
[
0
]
.
data
#
print e.childNodes[0].data
exec
e
.
childNodes
[
0
]
.
data
in
g
,
self
.
context
exec
e
.
childNodes
[
0
]
.
data
in
g
,
self
.
context
elif
e
.
localName
==
'endouttext'
:
elif
e
.
localName
==
'endouttext'
:
ot
=
False
ot
=
False
elif
ot
:
elif
ot
:
print
e
,
"::"
,
e
.
toxml
()
#
print e, "::", e.toxml()
e
.
writexml
(
buf
)
e
.
writexml
(
buf
)
elif
e
.
localName
==
'startouttext'
:
elif
e
.
localName
==
'startouttext'
:
ot
=
True
ot
=
True
...
@@ -93,7 +99,7 @@ class LoncapaProblem():
...
@@ -93,7 +99,7 @@ class LoncapaProblem():
self
.
text
=
buf
.
getvalue
()
self
.
text
=
buf
.
getvalue
()
self
.
text
=
self
.
contextualize_text
(
self
.
text
)
self
.
text
=
self
.
contextualize_text
(
self
.
text
)
print
self
.
text
#
print self.text
self
.
filename
=
filename
self
.
filename
=
filename
done
=
False
done
=
False
...
@@ -129,29 +135,34 @@ class LoncapaProblem():
...
@@ -129,29 +135,34 @@ class LoncapaProblem():
if
id
not
in
answers
:
if
id
not
in
answers
:
correct_map
[
id
]
=
'incorrect'
# Should always be there
correct_map
[
id
]
=
'incorrect'
# Should always be there
else
:
else
:
correct_map
[
id
]
=
self
.
grade_nr
(
self
.
questions
[
key
],
#correct_map[id]=self.grade_nr(self.questions[key],
self
.
answers
[
id
])
# self.answers[id])
grader
=
self
.
graders
[
self
.
questions
[
key
][
'type'
]]
print
grader
correct_map
[
id
]
=
grader
(
self
,
self
.
questions
[
key
],
self
.
answers
[
id
])
self
.
correct_map
=
correct_map
self
.
correct_map
=
correct_map
return
correct_map
return
correct_map
## Internal methods
## Internal methods
def
number
(
self
,
text
):
#
def number(self,text):
''' Convert a number to a float, understanding suffixes '''
#
''' Convert a number to a float, understanding suffixes '''
try
:
#
try:
text
.
strip
()
#
text.strip()
suffixes
=
{
'
%
'
:
0.01
,
'k'
:
1e3
,
'M'
:
1e6
,
'G'
:
1e9
,
'T'
:
1e12
,
'P'
:
1e15
,
#
suffixes={'%':0.01,'k':1e3,'M':1e6,'G':1e9,'T':1e12,'P':1e15,
'E'
:
1e18
,
'Z'
:
1e21
,
'Y'
:
1e24
,
'c'
:
1e-2
,
'm'
:
1e-3
,
'u'
:
1e-6
,
#
'E':1e18,'Z':1e21,'Y':1e24,'c':1e-2,'m':1e-3,'u':1e-6,
'n'
:
1e-9
,
'p'
:
1e-12
,
'f'
:
1e-15
,
'a'
:
1e-18
,
'z'
:
1e-21
,
'y'
:
1e-24
}
#
'n':1e-9,'p':1e-12,'f':1e-15,'a':1e-18,'z':1e-21,'y':1e-24}
if
text
[
-
1
]
in
suffixes
:
#
if text[-1] in suffixes:
return
float
(
text
[:
-
1
])
*
suffixes
[
text
[
-
1
]]
#
return float(text[:-1])*suffixes[text[-1]]
else
:
#
else:
return
float
(
text
)
#
return float(text)
except
:
#
except:
return
0
# TODO: Better error handling?
#
return 0 # TODO: Better error handling?
def
grade_nr
(
self
,
question
,
answer
):
def
grade_nr
(
self
,
question
,
answer
):
error
=
abs
(
self
.
number
(
answer
)
-
question
[
'answer'
])
error
=
abs
(
evaluator
({},{},
answer
)
-
question
[
'answer'
])
allowed_error
=
abs
(
question
[
'answer'
]
*
question
[
'tolerance'
])
allowed_error
=
abs
(
question
[
'answer'
]
*
question
[
'tolerance'
])
if
error
<=
allowed_error
:
if
error
<=
allowed_error
:
return
'correct'
return
'correct'
...
@@ -165,13 +176,14 @@ class LoncapaProblem():
...
@@ -165,13 +176,14 @@ class LoncapaProblem():
tolerance
=
e
.
getAttribute
(
'default'
)
tolerance
=
e
.
getAttribute
(
'default'
)
self
.
lid
+=
1
self
.
lid
+=
1
id
=
str
(
self
.
gid
)
+
'_'
+
str
(
self
.
lid
)
id
=
str
(
self
.
gid
)
+
'_'
+
str
(
self
.
lid
)
problem
=
{
"answer"
:
self
.
number
(
self
.
contextualize_text
(
answer
)),
problem
=
{
"answer"
:
evaluator
({},{},
self
.
contextualize_text
(
answer
)),
"type"
:
"numericalresponse"
,
"type"
:
"numericalresponse"
,
"tolerance"
:
self
.
number
(
self
.
contextualize_text
(
tolerance
)),
"tolerance"
:
evaluator
({},{},
self
.
contextualize_text
(
tolerance
)),
"id"
:
id
,
"id"
:
id
,
"lid"
:
self
.
lid
,
"lid"
:
self
.
lid
,
}
}
self
.
questions
[
self
.
lid
]
=
problem
self
.
questions
[
self
.
lid
]
=
problem
if
id
in
self
.
answers
:
if
id
in
self
.
answers
:
value
=
self
.
answers
[
id
]
value
=
self
.
answers
[
id
]
else
:
else
:
...
@@ -185,9 +197,64 @@ class LoncapaProblem():
...
@@ -185,9 +197,64 @@ class LoncapaProblem():
html
=
'<input type="text" name="input_{id}" id="input_{id}" value="{value}"><span class="ui-icon ui-icon-{icon}" style="display:inline-block;" id="status_{id}"></span> '
.
format
(
id
=
id
,
value
=
value
,
icon
=
icon
)
html
=
'<input type="text" name="input_{id}" id="input_{id}" value="{value}"><span class="ui-icon ui-icon-{icon}" style="display:inline-block;" id="status_{id}"></span> '
.
format
(
id
=
id
,
value
=
value
,
icon
=
icon
)
return
html
return
html
def
grade_fr
(
self
,
question
,
answer
):
correct
=
True
for
i
in
range
(
question
[
'samples_count'
]):
instructor_variables
=
strip_dict
(
dict
(
self
.
context
))
student_variables
=
dict
()
for
var
in
question
[
'sample_range'
]:
value
=
random
.
uniform
(
*
question
[
'sample_range'
][
var
])
instructor_variables
[
str
(
var
)]
=
value
student_variables
[
str
(
var
)]
=
value
instructor_result
=
evaluator
(
instructor_variables
,{},
str
(
question
[
'answer'
]))
student_result
=
evaluator
(
student_variables
,{},
str
(
answer
))
if
abs
(
student_result
-
instructor_result
)
>
question
[
'tolerance'
]:
return
"incorrect"
return
"correct"
def
handle_fr
(
self
,
element
):
## Extract description from element
samples
=
element
.
getAttribute
(
'samples'
)
variables
=
samples
.
split
(
'@'
)[
0
]
.
split
(
','
)
numsamples
=
int
(
samples
.
split
(
'@'
)[
1
]
.
split
(
'#'
)[
1
])
sranges
=
zip
(
*
map
(
lambda
x
:
map
(
float
,
x
.
split
(
","
)),
samples
.
split
(
'@'
)[
1
]
.
split
(
'#'
)[
0
]
.
split
(
':'
)))
answer
=
element
.
getAttribute
(
'answer'
)
for
e
in
element
.
childNodes
:
if
e
.
nodeType
==
1
and
e
.
getAttribute
(
'type'
)
==
"tolerance"
:
tolerance
=
e
.
getAttribute
(
'default'
)
# Store element
self
.
lid
+=
1
id
=
str
(
self
.
gid
)
+
'_'
+
str
(
self
.
lid
)
problem
=
{
"answer"
:
self
.
contextualize_text
(
answer
),
"type"
:
"formularesponse"
,
"tolerance"
:
evaluator
({},{},
self
.
contextualize_text
(
tolerance
)),
"sample_range"
:
dict
(
zip
(
variables
,
sranges
)),
"samples_count"
:
numsamples
,
"id"
:
id
,
"lid"
:
self
.
lid
,
}
self
.
questions
[
self
.
lid
]
=
problem
# Generate HTML
if
id
in
self
.
answers
:
value
=
self
.
answers
[
id
]
else
:
value
=
""
icon
=
'bullet'
if
id
in
self
.
correct_map
and
self
.
correct_map
[
id
]
==
'correct'
:
icon
=
'check'
if
id
in
self
.
correct_map
and
self
.
correct_map
[
id
]
==
'incorrect'
:
icon
=
'close'
html
=
'<input type="text" name="input_{id}" id="input_{id}" value="{value}"><span class="ui-icon ui-icon-{icon}" style="display:inline-block;" id="status_{id}"></span> '
.
format
(
id
=
id
,
value
=
value
,
icon
=
icon
)
return
html
graders
=
{
'numericalresponse'
:
grade_nr
}
graders
=
{
'numericalresponse'
:
grade_nr
,
handlers
=
{
'numericalresponse'
:
handle_nr
}
'formularesponse'
:
grade_fr
}
handlers
=
{
'numericalresponse'
:
handle_nr
,
'formularesponse'
:
handle_fr
}
def
contextualize_text
(
self
,
text
):
def
contextualize_text
(
self
,
text
):
''' Takes a string with variables. E.g. $a+$b.
''' Takes a string with variables. E.g. $a+$b.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment