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
2fab97c1
Commit
2fab97c1
authored
Oct 26, 2012
by
Victor Shnayder
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Refactor imageinput and crystallography.
- also add a test for chemicalequationinput
parent
9135d7b2
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
234 additions
and
138 deletions
+234
-138
common/lib/capa/capa/inputtypes.py
+99
-110
common/lib/capa/capa/templates/crystallography.html
+9
-9
common/lib/capa/capa/templates/vsepr_input.html
+7
-17
common/lib/capa/capa/tests/test_inputtypes.py
+119
-2
No files found.
common/lib/capa/capa/inputtypes.py
View file @
2fab97c1
...
@@ -647,9 +647,8 @@ _reg(solution)
...
@@ -647,9 +647,8 @@ _reg(solution)
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
class
ImageInput
(
InputTypeBase
):
def
imageinput
(
element
,
value
,
status
,
render_template
,
msg
=
''
):
"""
'''
Clickable image as an input field. Element should specify the image source, height,
Clickable image as an input field. Element should specify the image source, height,
and width, e.g.
and width, e.g.
...
@@ -657,130 +656,120 @@ def imageinput(element, value, status, render_template, msg=''):
...
@@ -657,130 +656,120 @@ def imageinput(element, value, status, render_template, msg=''):
TODO: showanswer for imageimput does not work yet - need javascript to put rectangle
TODO: showanswer for imageimput does not work yet - need javascript to put rectangle
over acceptable area of image.
over acceptable area of image.
'''
"""
eid
=
element
.
get
(
'id'
)
src
=
element
.
get
(
'src'
)
height
=
element
.
get
(
'height'
)
width
=
element
.
get
(
'width'
)
# if value is of the form [x,y] then parse it and send along coordinates of previous answer
m
=
re
.
match
(
'
\
[([0-9]+),([0-9]+)]'
,
value
.
strip
()
.
replace
(
' '
,
''
))
if
m
:
(
gx
,
gy
)
=
[
int
(
x
)
-
15
for
x
in
m
.
groups
()]
else
:
(
gx
,
gy
)
=
(
0
,
0
)
context
=
{
'id'
:
eid
,
'value'
:
value
,
'height'
:
height
,
'width'
:
width
,
'src'
:
src
,
'gx'
:
gx
,
'gy'
:
gy
,
'state'
:
status
,
# to change
'msg'
:
msg
,
# to change
}
html
=
render_template
(
"imageinput.html"
,
context
)
return
etree
.
XML
(
html
)
_reg
(
imageinput
)
template
=
"imageinput.html"
tags
=
[
'imageinput'
]
def
__init__
(
self
,
system
,
xml
,
state
):
super
(
ImageInput
,
self
)
.
__init__
(
system
,
xml
,
state
)
self
.
src
=
xml
.
get
(
'src'
)
self
.
height
=
xml
.
get
(
'height'
)
self
.
width
=
xml
.
get
(
'width'
)
def
crystallography
(
element
,
value
,
status
,
render_template
,
msg
=
''
):
# if value is of the form [x,y] then parse it and send along coordinates of previous answer
eid
=
element
.
get
(
'id'
)
m
=
re
.
match
(
'
\
[([0-9]+),([0-9]+)]'
,
self
.
value
.
strip
()
.
replace
(
' '
,
''
))
if
eid
is
None
:
if
m
:
msg
=
'cryst has no id: it probably appears outside of a known response type'
# TODO (vshnayder): why is there a "-15" here??
msg
+=
"
\n
See problem XML source line
%
s"
%
getattr
(
element
,
'sourceline'
,
'<unavailable>'
)
(
self
.
gx
,
self
.
gy
)
=
[
int
(
x
)
-
15
for
x
in
m
.
groups
()]
raise
Exception
(
msg
)
else
:
height
=
element
.
get
(
'height'
)
(
self
.
gx
,
self
.
gy
)
=
(
0
,
0
)
width
=
element
.
get
(
'width'
)
display_file
=
element
.
get
(
'display_file'
)
count
=
int
(
eid
.
split
(
'_'
)[
-
2
])
-
1
# HACK
size
=
element
.
get
(
'size'
)
# if specified, then textline is hidden and id is stored in div of name given by hidden
hidden
=
element
.
get
(
'hidden'
,
''
)
# Escape answers with quotes, so they don't crash the system!
escapedict
=
{
'"'
:
'"'
}
value
=
saxutils
.
escape
(
value
,
escapedict
)
context
=
{
'id'
:
eid
,
'value'
:
value
,
def
_get_render_context
(
self
):
'state'
:
status
,
'count'
:
count
,
context
=
{
'id'
:
self
.
id
,
'size'
:
size
,
'value'
:
self
.
value
,
'msg'
:
msg
,
'height'
:
self
.
height
,
'hidden'
:
hidden
,
'width'
:
self
.
width
,
'inline'
:
element
.
get
(
'inline'
,
''
),
'src'
:
self
.
src
,
'width'
:
width
,
'gx'
:
self
.
gx
,
'height'
:
height
,
'gy'
:
self
.
gy
,
'display_file'
:
display_file
,
'state'
:
self
.
status
,
# to change (VS: to what??)
'msg'
:
self
.
msg
,
# to change
}
}
return
context
html
=
render_template
(
"crystallography.html"
,
contex
t
)
register_input_class
(
ImageInpu
t
)
try
:
#-----------------------------------------------------------------------------
xhtml
=
etree
.
XML
(
html
)
except
Exception
as
err
:
# TODO: needs to be self.system.DEBUG - but can't access system
if
True
:
log
.
debug
(
'[inputtypes.crystallography] failed to parse XML for:
\n
%
s'
%
html
)
raise
return
xhtml
_reg
(
crystallography
)
class
Crystallography
(
InputTypeBase
):
"""
An input for crystallography -- user selects 3 points on the axes, and we get a plane.
TODO: what's the actual value format?
"""
def
vsepr_input
(
element
,
value
,
status
,
render_template
,
msg
=
''
):
template
=
"crystallography.html"
eid
=
element
.
get
(
'id'
)
tags
=
[
'crystallography'
]
if
eid
is
None
:
msg
=
'cryst has no id: it probably appears outside of a known response type'
msg
+=
"
\n
See problem XML source line
%
s"
%
getattr
(
element
,
'sourceline'
,
'<unavailable>'
)
raise
Exception
(
msg
)
height
=
element
.
get
(
'height'
)
width
=
element
.
get
(
'width'
)
display_file
=
element
.
get
(
'display_file'
)
count
=
int
(
eid
.
split
(
'_'
)[
-
2
])
-
1
# HACK
size
=
element
.
get
(
'size'
)
# if specified, then textline is hidden and id is stored in div of name given by hidden
hidden
=
element
.
get
(
'hidden'
,
''
)
# Escape answers with quotes, so they don't crash the system!
escapedict
=
{
'"'
:
'"'
}
value
=
saxutils
.
escape
(
value
,
escapedict
)
molecules
=
element
.
get
(
'molecules'
)
def
__init__
(
self
,
system
,
xml
,
state
):
geometries
=
element
.
get
(
'geometries'
)
super
(
Crystallography
,
self
)
.
__init__
(
system
,
xml
,
state
)
context
=
{
'id'
:
eid
,
self
.
height
=
xml
.
get
(
'height'
)
'value'
:
value
,
self
.
width
=
xml
.
get
(
'width'
)
'state'
:
status
,
self
.
size
=
xml
.
get
(
'size'
)
'count'
:
count
,
'size'
:
size
,
# if specified, then textline is hidden and id is stored in div of name given by hidden
'msg'
:
msg
,
self
.
hidden
=
xml
.
get
(
'hidden'
,
''
)
'hidden'
:
hidden
,
'inline'
:
element
.
get
(
'inline'
,
''
),
# Escape answers with quotes, so they don't crash the system!
'width'
:
width
,
escapedict
=
{
'"'
:
'"'
}
'height'
:
height
,
self
.
value
=
saxutils
.
escape
(
self
.
value
,
escapedict
)
'display_file'
:
display_file
,
'molecules'
:
molecules
,
def
_get_render_context
(
self
):
'geometries'
:
geometries
,
context
=
{
'id'
:
self
.
id
,
'value'
:
self
.
value
,
'state'
:
self
.
status
,
'size'
:
self
.
size
,
'msg'
:
self
.
msg
,
'hidden'
:
self
.
hidden
,
'width'
:
self
.
width
,
'height'
:
self
.
height
,
}
}
return
context
html
=
render_template
(
"vsepr_input.html"
,
context
)
register_input_class
(
Crystallography
)
try
:
# -------------------------------------------------------------------------
xhtml
=
etree
.
XML
(
html
)
except
Exception
as
err
:
# TODO: needs to be self.system.DEBUG - but can't access system
if
True
:
log
.
debug
(
'[inputtypes.vsepr_input] failed to parse XML for:
\n
%
s'
%
html
)
raise
return
xhtml
_reg
(
vsepr_input
)
class
VseprInput
(
InputTypeBase
):
"""
Input for molecular geometry--show possible structures, let student
pick structure and label positions with atoms or electron pairs.
"""
template
=
'vsepr_input.html'
tags
=
[
'vsepr_input'
]
def
__init__
(
self
,
system
,
xml
,
state
):
super
(
ImageInput
,
self
)
.
__init__
(
system
,
xml
,
state
)
self
.
height
=
xml
.
get
(
'height'
)
self
.
width
=
xml
.
get
(
'width'
)
# Escape answers with quotes, so they don't crash the system!
escapedict
=
{
'"'
:
'"'
}
self
.
value
=
saxutils
.
escape
(
self
.
value
,
escapedict
)
self
.
molecules
=
xml
.
get
(
'molecules'
)
self
.
geometries
=
xml
.
get
(
'geometries'
)
def
_get_render_context
(
self
):
context
=
{
'id'
:
self
.
id
,
'value'
:
self
.
value
,
'state'
:
self
.
status
,
'msg'
:
self
.
msg
,
'width'
:
self
.
width
,
'height'
:
self
.
height
,
'molecules'
:
self
.
molecules
,
'geometries'
:
self
.
geometries
,
}
return
context
register_input_class
(
VseprInput
)
#--------------------------------------------------------------------------------
#--------------------------------------------------------------------------------
...
...
common/lib/capa/capa/templates/crystallography.html
View file @
2fab97c1
<
%
doinline =
"inline"
if
inline
else
""
%
>
<section
id=
"textinput_${id}"
class=
"textinput"
>
<section
id=
"textinput_${id}"
class=
"textinput ${doinline}"
>
<div
id=
"holder"
style=
"width:${width};height:${height}"
></div>
<div
id=
"holder"
style=
"width:${width};height:${height}"
></div>
<div
class=
"script_placeholder"
data-src=
"/static/js/raphael.js"
></div><div
class=
"script_placeholder"
data-src=
"/static/js/sylvester.js"
></div><div
class=
"script_placeholder"
data-src=
"/static/js/underscore-min.js"
></div>
<div
class=
"script_placeholder"
data-src=
"/static/js/raphael.js"
></div>
<div
class=
"script_placeholder"
data-src=
"/static/js/sylvester.js"
></div>
<div
class=
"script_placeholder"
data-src=
"/static/js/underscore-min.js"
></div>
<div
class=
"script_placeholder"
data-src=
"/static/js/crystallography.js"
></div>
<div
class=
"script_placeholder"
data-src=
"/static/js/crystallography.js"
></div>
% if state == 'unsubmitted':
% if state == 'unsubmitted':
<div
class=
"unanswered
${doinline}
"
id=
"status_${id}"
>
<div
class=
"unanswered"
id=
"status_${id}"
>
% elif state == 'correct':
% elif state == 'correct':
<div
class=
"correct
${doinline}
"
id=
"status_${id}"
>
<div
class=
"correct"
id=
"status_${id}"
>
% elif state == 'incorrect':
% elif state == 'incorrect':
<div
class=
"incorrect
${doinline}
"
id=
"status_${id}"
>
<div
class=
"incorrect"
id=
"status_${id}"
>
% elif state == 'incomplete':
% elif state == 'incomplete':
<div
class=
"incorrect
${doinline}
"
id=
"status_${id}"
>
<div
class=
"incorrect"
id=
"status_${id}"
>
% endif
% endif
% if hidden:
% if hidden:
<div
style=
"display:none;"
name=
"${hidden}"
inputid=
"input_${id}"
/>
<div
style=
"display:none;"
name=
"${hidden}"
inputid=
"input_${id}"
/>
...
@@ -45,7 +45,7 @@
...
@@ -45,7 +45,7 @@
% if msg:
% if msg:
<span
class=
"message"
>
${msg|n}
</span>
<span
class=
"message"
>
${msg|n}
</span>
% endif
% endif
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete']
or hidden
:
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
</div>
</div>
% endif
% endif
</section>
</section>
common/lib/capa/capa/templates/vsepr_input.html
View file @
2fab97c1
<
%
doinline =
"inline"
if
inline
else
""
%
>
<section
id=
"vsepr_input_${id}"
class=
"textinput"
>
<section
id=
"textinput_${id}"
class=
"textinput ${doinline}"
>
<table><tr><td
height=
'600'
>
<table><tr><td
height=
'600'
>
<div
id=
"vsepr_div_${id}"
style=
"position:relative;"
data-molecules=
"${molecules}"
data-geometries=
"${geometries}"
>
<div
id=
"vsepr_div_${id}"
style=
"position:relative;"
data-molecules=
"${molecules}"
data-geometries=
"${geometries}"
>
<canvas
id=
"vsepr_canvas_${id}"
width=
"${width}"
height=
"${height}"
>
<canvas
id=
"vsepr_canvas_${id}"
width=
"${width}"
height=
"${height}"
>
...
@@ -14,25 +12,17 @@
...
@@ -14,25 +12,17 @@
<div
class=
"script_placeholder"
data-src=
"/static/js/vsepr/vsepr.js"
></div>
<div
class=
"script_placeholder"
data-src=
"/static/js/vsepr/vsepr.js"
></div>
% if state == 'unsubmitted':
% if state == 'unsubmitted':
<div
class=
"unanswered
${doinline}
"
id=
"status_${id}"
>
<div
class=
"unanswered"
id=
"status_${id}"
>
% elif state == 'correct':
% elif state == 'correct':
<div
class=
"correct
${doinline}
"
id=
"status_${id}"
>
<div
class=
"correct"
id=
"status_${id}"
>
% elif state == 'incorrect':
% elif state == 'incorrect':
<div
class=
"incorrect
${doinline}
"
id=
"status_${id}"
>
<div
class=
"incorrect"
id=
"status_${id}"
>
% elif state == 'incomplete':
% elif state == 'incomplete':
<div
class=
"incorrect ${doinline}"
id=
"status_${id}"
>
<div
class=
"incorrect"
id=
"status_${id}"
>
% endif
% if hidden:
<div
style=
"display:none;"
name=
"${hidden}"
inputid=
"input_${id}"
/>
% endif
% endif
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
value=
"${value}"
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
value=
"${value}"
%
if
size:
style=
"display:none;"
size=
"${size}"
%
endif
%
if
hidden:
style=
"display:none;"
%
endif
/>
/>
<p
class=
"status"
>
<p
class=
"status"
>
...
@@ -52,7 +42,7 @@
...
@@ -52,7 +42,7 @@
% if msg:
% if msg:
<span
class=
"message"
>
${msg|n}
</span>
<span
class=
"message"
>
${msg|n}
</span>
% endif
% endif
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete']
or hidden
:
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
</div>
</div>
% endif
% endif
</section>
</section>
common/lib/capa/capa/tests/test_inputtypes.py
View file @
2fab97c1
...
@@ -4,6 +4,7 @@ Tests of input types (and actually responsetypes too).
...
@@ -4,6 +4,7 @@ Tests of input types (and actually responsetypes too).
TODO:
TODO:
- test unicode in values, parameters, etc.
- test unicode in values, parameters, etc.
- test various html escapes
- test various html escapes
- test funny xml chars -- should never get xml parse error if things are escaped properly.
"""
"""
from
datetime
import
datetime
from
datetime
import
datetime
...
@@ -351,8 +352,7 @@ class SchematicTest(unittest.TestCase):
...
@@ -351,8 +352,7 @@ class SchematicTest(unittest.TestCase):
value
=
'three resistors and an oscilating pendulum'
value
=
'three resistors and an oscilating pendulum'
state
=
{
'value'
:
value
,
state
=
{
'value'
:
value
,
'status'
:
'unsubmitted'
,
'status'
:
'unsubmitted'
}
'feedback'
:
{
'message'
:
'3'
},
}
the_input
=
inputtypes
.
get_class_for_tag
(
'schematic'
)(
system
,
element
,
state
)
the_input
=
inputtypes
.
get_class_for_tag
(
'schematic'
)(
system
,
element
,
state
)
...
@@ -371,3 +371,120 @@ class SchematicTest(unittest.TestCase):
...
@@ -371,3 +371,120 @@ class SchematicTest(unittest.TestCase):
self
.
assertEqual
(
context
,
expected
)
self
.
assertEqual
(
context
,
expected
)
class
ImageInputTest
(
unittest
.
TestCase
):
'''
Check that image inputs work
'''
def
check
(
self
,
value
,
egx
,
egy
):
height
=
'78'
width
=
'427'
src
=
'http://www.edx.org/cowclicker.jpg'
xml_str
=
"""<imageinput id="prob_1_2"
src="{s}"
height="{h}"
width="{w}"
/>"""
.
format
(
s
=
src
,
h
=
height
,
w
=
width
)
element
=
etree
.
fromstring
(
xml_str
)
state
=
{
'value'
:
value
,
'status'
:
'unsubmitted'
}
the_input
=
inputtypes
.
get_class_for_tag
(
'imageinput'
)(
system
,
element
,
state
)
context
=
the_input
.
_get_render_context
()
expected
=
{
'id'
:
'prob_1_2'
,
'value'
:
value
,
'state'
:
'unsubmitted'
,
'width'
:
width
,
'height'
:
height
,
'src'
:
src
,
'gx'
:
egx
,
'gy'
:
egy
,
'state'
:
'unsubmitted'
,
'msg'
:
''
}
self
.
assertEqual
(
context
,
expected
)
def
test_with_value
(
self
):
self
.
check
(
'[50,40]'
,
35
,
25
)
def
test_without_value
(
self
):
self
.
check
(
''
,
0
,
0
)
def
test_corrupt_values
(
self
):
self
.
check
(
'[12'
,
0
,
0
)
self
.
check
(
'[12, a]'
,
0
,
0
)
self
.
check
(
'[12 10]'
,
0
,
0
)
self
.
check
(
'[12]'
,
0
,
0
)
self
.
check
(
'[12 13 14]'
,
0
,
0
)
class
CrystallographyTest
(
unittest
.
TestCase
):
'''
Check that crystallography inputs work
'''
def
test_rendering
(
self
):
height
=
'12'
width
=
'33'
size
=
'10'
xml_str
=
"""<crystallography id="prob_1_2"
height="{h}"
width="{w}"
size="{s}"
/>"""
.
format
(
h
=
height
,
w
=
width
,
s
=
size
)
element
=
etree
.
fromstring
(
xml_str
)
value
=
'abc'
state
=
{
'value'
:
value
,
'status'
:
'unsubmitted'
}
the_input
=
inputtypes
.
get_class_for_tag
(
'crystallography'
)(
system
,
element
,
state
)
context
=
the_input
.
_get_render_context
()
expected
=
{
'id'
:
'prob_1_2'
,
'value'
:
value
,
'state'
:
'unsubmitted'
,
'size'
:
size
,
'msg'
:
''
,
'hidden'
:
''
,
'width'
:
width
,
'height'
:
height
,
}
self
.
assertEqual
(
context
,
expected
)
class
ChemicalEquationTest
(
unittest
.
TestCase
):
'''
Check that chemical equation inputs work.
'''
def
test_rendering
(
self
):
size
=
"42"
xml_str
=
"""<chemicalequationinput id="prob_1_2" size="{size}"/>"""
.
format
(
size
=
size
)
element
=
etree
.
fromstring
(
xml_str
)
state
=
{
'value'
:
'H2OYeah'
,}
the_input
=
inputtypes
.
get_class_for_tag
(
'chemicalequationinput'
)(
system
,
element
,
state
)
context
=
the_input
.
_get_render_context
()
expected
=
{
'id'
:
'prob_1_2'
,
'value'
:
'H2OYeah'
,
'status'
:
'unanswered'
,
'size'
:
size
,
'previewer'
:
'/static/js/capa/chemical_equation_preview.js'
,
}
self
.
assertEqual
(
context
,
expected
)
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