Commit 2fab97c1 by Victor Shnayder

Refactor imageinput and crystallography.

- also add a test for chemicalequationinput
parent 9135d7b2
......@@ -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 += "\nSee 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 = {'"': '&quot;'}
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", context)
register_input_class(ImageInput)
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 += "\nSee 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 = {'"': '&quot;'}
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 = {'"': '&quot;'}
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 = {'"': '&quot;'}
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)
#--------------------------------------------------------------------------------
......
<% 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>
<% 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>
......@@ -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)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment