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)
#-----------------------------------------------------------------------------
def
imageinput
(
element
,
value
,
status
,
render_template
,
msg
=
''
):
'''
class
ImageInput
(
InputTypeBase
):
"""
Clickable image as an input field. Element should specify the image source, height,
and width, e.g.
...
...
@@ -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
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
=
''
):
eid
=
element
.
get
(
'id'
)
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
)
# 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]+)]'
,
self
.
value
.
strip
()
.
replace
(
' '
,
''
))
if
m
:
# TODO (vshnayder): why is there a "-15" here??
(
self
.
gx
,
self
.
gy
)
=
[
int
(
x
)
-
15
for
x
in
m
.
groups
()]
else
:
(
self
.
gx
,
self
.
gy
)
=
(
0
,
0
)
context
=
{
'id'
:
eid
,
'value'
:
value
,
'state'
:
status
,
'count'
:
count
,
'size'
:
size
,
'msg'
:
msg
,
'hidden'
:
hidden
,
'inline'
:
element
.
get
(
'inline'
,
''
),
'width'
:
width
,
'height'
:
height
,
'display_file'
:
display_file
,
def
_get_render_context
(
self
):
context
=
{
'id'
:
self
.
id
,
'value'
:
self
.
value
,
'height'
:
self
.
height
,
'width'
:
self
.
width
,
'src'
:
self
.
src
,
'gx'
:
self
.
gx
,
'gy'
:
self
.
gy
,
'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
=
''
):
eid
=
element
.
get
(
'id'
)
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
)
template
=
"crystallography.html"
tags
=
[
'crystallography'
]
molecules
=
element
.
get
(
'molecules'
)
geometries
=
element
.
get
(
'geometries'
)
def
__init__
(
self
,
system
,
xml
,
state
):
super
(
Crystallography
,
self
)
.
__init__
(
system
,
xml
,
state
)
context
=
{
'id'
:
eid
,
'value'
:
value
,
'state'
:
status
,
'count'
:
count
,
'size'
:
size
,
'msg'
:
msg
,
'hidden'
:
hidden
,
'inline'
:
element
.
get
(
'inline'
,
''
),
'width'
:
width
,
'height'
:
height
,
'display_file'
:
display_file
,
'molecules'
:
molecules
,
'geometries'
:
geometries
,
self
.
height
=
xml
.
get
(
'height'
)
self
.
width
=
xml
.
get
(
'width'
)
self
.
size
=
xml
.
get
(
'size'
)
# if specified, then textline is hidden and id is stored in div of name given by hidden
self
.
hidden
=
xml
.
get
(
'hidden'
,
''
)
# Escape answers with quotes, so they don't crash the system!
escapedict
=
{
'"'
:
'"'
}
self
.
value
=
saxutils
.
escape
(
self
.
value
,
escapedict
)
def
_get_render_context
(
self
):
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 ${doinline}"
>
<section
id=
"textinput_${id}"
class=
"textinput"
>
<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>
% if state == 'unsubmitted':
<div
class=
"unanswered
${doinline}
"
id=
"status_${id}"
>
<div
class=
"unanswered"
id=
"status_${id}"
>
% elif state == 'correct':
<div
class=
"correct
${doinline}
"
id=
"status_${id}"
>
<div
class=
"correct"
id=
"status_${id}"
>
% elif state == 'incorrect':
<div
class=
"incorrect
${doinline}
"
id=
"status_${id}"
>
<div
class=
"incorrect"
id=
"status_${id}"
>
% 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}"
/>
...
...
@@ -45,7 +45,7 @@
% if msg:
<span
class=
"message"
>
${msg|n}
</span>
% endif
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete']
or hidden
:
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
</div>
% endif
</section>
common/lib/capa/capa/templates/vsepr_input.html
View file @
2fab97c1
<
%
doinline =
"inline"
if
inline
else
""
%
>
<section
id=
"textinput_${id}"
class=
"textinput ${doinline}"
>
<section
id=
"vsepr_input_${id}"
class=
"textinput"
>
<table><tr><td
height=
'600'
>
<div
id=
"vsepr_div_${id}"
style=
"position:relative;"
data-molecules=
"${molecules}"
data-geometries=
"${geometries}"
>
<canvas
id=
"vsepr_canvas_${id}"
width=
"${width}"
height=
"${height}"
>
...
...
@@ -14,25 +12,17 @@
<div
class=
"script_placeholder"
data-src=
"/static/js/vsepr/vsepr.js"
></div>
% if state == 'unsubmitted':
<div
class=
"unanswered
${doinline}
"
id=
"status_${id}"
>
<div
class=
"unanswered"
id=
"status_${id}"
>
% elif state == 'correct':
<div
class=
"correct
${doinline}
"
id=
"status_${id}"
>
<div
class=
"correct"
id=
"status_${id}"
>
% elif state == 'incorrect':
<div
class=
"incorrect
${doinline}
"
id=
"status_${id}"
>
<div
class=
"incorrect"
id=
"status_${id}"
>
% elif state == 'incomplete':
<div
class=
"incorrect ${doinline}"
id=
"status_${id}"
>
% endif
% if hidden:
<div
style=
"display:none;"
name=
"${hidden}"
inputid=
"input_${id}"
/>
<div
class=
"incorrect"
id=
"status_${id}"
>
% endif
<input
type=
"text"
name=
"input_${id}"
id=
"input_${id}"
value=
"${value}"
%
if
size:
size=
"${size}"
%
endif
%
if
hidden:
style=
"display:none;"
%
endif
style=
"display:none;"
/>
<p
class=
"status"
>
...
...
@@ -52,7 +42,7 @@
% if msg:
<span
class=
"message"
>
${msg|n}
</span>
% endif
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete']
or hidden
:
% if state in ['unsubmitted', 'correct', 'incorrect', 'incomplete']:
</div>
% endif
</section>
common/lib/capa/capa/tests/test_inputtypes.py
View file @
2fab97c1
...
...
@@ -4,6 +4,7 @@ Tests of input types (and actually responsetypes too).
TODO:
- test unicode in values, parameters, etc.
- test various html escapes
- test funny xml chars -- should never get xml parse error if things are escaped properly.
"""
from
datetime
import
datetime
...
...
@@ -351,8 +352,7 @@ class SchematicTest(unittest.TestCase):
value
=
'three resistors and an oscilating pendulum'
state
=
{
'value'
:
value
,
'status'
:
'unsubmitted'
,
'feedback'
:
{
'message'
:
'3'
},
}
'status'
:
'unsubmitted'
}
the_input
=
inputtypes
.
get_class_for_tag
(
'schematic'
)(
system
,
element
,
state
)
...
...
@@ -371,3 +371,120 @@ class SchematicTest(unittest.TestCase):
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