diff --git a/common/lib/capa/capa/responsetypes.py b/common/lib/capa/capa/responsetypes.py
index 427067d523..648fc9e861 100644
--- a/common/lib/capa/capa/responsetypes.py
+++ b/common/lib/capa/capa/responsetypes.py
@@ -1717,7 +1717,7 @@ class ImageResponse(LoncapaResponse):
"""
Handle student response for image input: the input is a click on an image,
which produces an [x,y] coordinate pair. The click is correct if it falls
- within a region specified. This region is nominally a rectangle.
+ within a region specified. This region is a union of rectangles.
Lon-CAPA requires that each has a inside it. That
doesn't make sense to me (Ike). Instead, let's have it such that
@@ -1727,6 +1727,7 @@ class ImageResponse(LoncapaResponse):
snippets = [{'snippet': '''
+
'''}]
response_tag = 'imageresponse'
@@ -1743,20 +1744,10 @@ class ImageResponse(LoncapaResponse):
for aid in self.answer_ids: # loop through IDs of fields in our stanza
given = student_answers[aid] # this should be a string of the form '[x,y]'
+ correct_map.set(aid, 'incorrect')
if not given: # No answer to parse. Mark as incorrect and move on
- correct_map.set(aid, 'incorrect')
continue
- # parse expected answer
- # TODO: Compile regexp on file load
- m = re.match('[\(\[]([0-9]+),([0-9]+)[\)\]]-[\(\[]([0-9]+),([0-9]+)[\)\]]',
- expectedset[aid].strip().replace(' ', ''))
- if not m:
- msg = 'Error in problem specification! cannot parse rectangle in %s' % (
- etree.tostring(self.ielements[aid], pretty_print=True))
- raise Exception('[capamodule.capa.responsetypes.imageinput] ' + msg)
- (llx, lly, urx, ury) = [int(x) for x in m.groups()]
-
# parse given answer
m = re.match('\[([0-9]+),([0-9]+)]', given.strip().replace(' ', ''))
if not m:
@@ -1764,11 +1755,24 @@ class ImageResponse(LoncapaResponse):
'error grading %s (input=%s)' % (aid, given))
(gx, gy) = [int(x) for x in m.groups()]
- # answer is correct if (x,y) is within the specified rectangle
- if (llx <= gx <= urx) and (lly <= gy <= ury):
- correct_map.set(aid, 'correct')
- else:
- correct_map.set(aid, 'incorrect')
+ # Check whether given point lies in any of the solution rectangles
+ solution_rectangles = expectedset[aid].split(';')
+ for solution_rectangle in solution_rectangles:
+ # parse expected answer
+ # TODO: Compile regexp on file load
+ m = re.match('[\(\[]([0-9]+),([0-9]+)[\)\]]-[\(\[]([0-9]+),([0-9]+)[\)\]]',
+ solution_rectangle.strip().replace(' ', ''))
+ if not m:
+ msg = 'Error in problem specification! cannot parse rectangle in %s' % (
+ etree.tostring(self.ielements[aid], pretty_print=True))
+ raise Exception('[capamodule.capa.responsetypes.imageinput] ' + msg)
+ (llx, lly, urx, ury) = [int(x) for x in m.groups()]
+
+ # answer is correct if (x,y) is within the specified rectangle
+ if (llx <= gx <= urx) and (lly <= gy <= ury):
+ correct_map.set(aid, 'correct')
+ break
+
return correct_map
def get_answers(self):
diff --git a/common/lib/capa/capa/tests/test_files/imageresponse.xml b/common/lib/capa/capa/tests/test_files/imageresponse.xml
index 72bf06401a..34dba37e3b 100644
--- a/common/lib/capa/capa/tests/test_files/imageresponse.xml
+++ b/common/lib/capa/capa/tests/test_files/imageresponse.xml
@@ -8,8 +8,14 @@ Hello
Click on the image where the top skier will stop momentarily if the top skier starts from rest.
Click on the image where the lower skier will stop momentarily if the lower skier starts from rest.
+
+Click on either of the two positions as discussed previously.
+
+Click on either of the two positions as discussed previously.
+
+Click on either of the two positions as discussed previously.
Use conservation of energy.
-
\ No newline at end of file
+
diff --git a/common/lib/capa/capa/tests/test_responsetypes.py b/common/lib/capa/capa/tests/test_responsetypes.py
index f2fa873080..bcac555b5e 100644
--- a/common/lib/capa/capa/tests/test_responsetypes.py
+++ b/common/lib/capa/capa/tests/test_responsetypes.py
@@ -53,12 +53,22 @@ class ImageResponseTest(unittest.TestCase):
imageresponse_file = os.path.dirname(__file__) + "/test_files/imageresponse.xml"
test_lcp = lcp.LoncapaProblem(open(imageresponse_file).read(), '1', system=test_system)
correct_answers = {'1_2_1': '(490,11)-(556,98)',
- '1_2_2': '(242,202)-(296,276)'}
+ '1_2_2': '(242,202)-(296,276)',
+ '1_2_3': '(490,11)-(556,98);(242,202)-(296,276)',
+ '1_2_4': '(490,11)-(556,98);(242,202)-(296,276)',
+ '1_2_5': '(490,11)-(556,98);(242,202)-(296,276)',
+ }
test_answers = {'1_2_1': '[500,20]',
'1_2_2': '[250,300]',
+ '1_2_3': '[500,20]',
+ '1_2_4': '[250,250]',
+ '1_2_5': '[10,10]',
}
self.assertEquals(test_lcp.grade_answers(test_answers).get_correctness('1_2_1'), 'correct')
self.assertEquals(test_lcp.grade_answers(test_answers).get_correctness('1_2_2'), 'incorrect')
+ self.assertEquals(test_lcp.grade_answers(test_answers).get_correctness('1_2_3'), 'correct')
+ self.assertEquals(test_lcp.grade_answers(test_answers).get_correctness('1_2_4'), 'correct')
+ self.assertEquals(test_lcp.grade_answers(test_answers).get_correctness('1_2_5'), 'incorrect')
class SymbolicResponseTest(unittest.TestCase):