graders for draganddrop
This commit is contained in:
0
common/lib/capa/capa/graders/__init__.py
Normal file
0
common/lib/capa/capa/graders/__init__.py
Normal file
98
common/lib/capa/capa/graders/draganddrop.py
Normal file
98
common/lib/capa/capa/graders/draganddrop.py
Normal file
@@ -0,0 +1,98 @@
|
||||
""" Grader of drag and drop input.
|
||||
|
||||
Client side behavior: user can drag and drop images from list on base image.
|
||||
Parameter 'use_targets' in xml can control two use cases.
|
||||
|
||||
if use_targets is true (defaut), then json returned from client is:
|
||||
{
|
||||
"use_targets": true,
|
||||
"draggable": [
|
||||
{ "image1": "t1" },
|
||||
{ "ant": "t2" },
|
||||
{ "molecule": "t3" },
|
||||
]
|
||||
}
|
||||
values are target names.
|
||||
|
||||
If use_targets is false:
|
||||
{
|
||||
"use_targets": false,
|
||||
"draggable": [
|
||||
{ "image1": "(10, 20)" },
|
||||
{ "ant": "(30, 40)" },
|
||||
{ "molecule": "(100, 200)" },
|
||||
]
|
||||
}
|
||||
values are (x,y) coordinates of centers of dragged images.
|
||||
|
||||
"""
|
||||
|
||||
import json
|
||||
import math
|
||||
|
||||
|
||||
def grade(user_input, correct_answer):
|
||||
'''
|
||||
Grade drag and drop problem.
|
||||
If use_targets is True - checks if image placed on proper target.
|
||||
If use_targets is False - checks if image placed on proper coordinates,
|
||||
with setted radius of forgiveness (default is 10)
|
||||
|
||||
Args:
|
||||
user_input, correct_answer: json. Format:
|
||||
|
||||
user_input: see module docstring
|
||||
|
||||
correct_answer:
|
||||
if use_targets is True:
|
||||
{'1': 't1', 'name_with_icon': 't2'}
|
||||
else:
|
||||
{'1': '(10, 10)', 'name_with_icon': '[(10, 10), 20]'}
|
||||
|
||||
Returns:
|
||||
True or False.
|
||||
'''
|
||||
|
||||
user_answer = json.loads(user_input)
|
||||
|
||||
if len(correct_answer.keys()) != len(user_answer['draggables']):
|
||||
return False
|
||||
|
||||
key = ['position']
|
||||
|
||||
def is_equal(user_answer, correct_answer):
|
||||
""" Checks if user_answer is equal to correct_answer inside radius
|
||||
of forgiveness (default 10 px).
|
||||
|
||||
Args:
|
||||
user_answer: (x, y) tuple of floats;
|
||||
correct_answer is one of variants:
|
||||
- (x, y) tuple of floats
|
||||
- [(x, y), r], r - radius of forgiveness;
|
||||
|
||||
Returns: bool.
|
||||
"""
|
||||
r = 10
|
||||
if type(correct_answer) is type(()): # (x, y) case
|
||||
corr_x = correct_answer[0]
|
||||
corr_y = correct_answer[1]
|
||||
else: # [(x, y), r] case
|
||||
r = correct_answer[1]
|
||||
corr_x = correct_answer[0][0]
|
||||
corr_y = correct_answer[0][1]
|
||||
|
||||
if ((user_answer[0] - corr_x) ** 2 +
|
||||
(user_answer[1] - corr_y) ** 2) > r * r:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
if user_answer["use_targets"]:
|
||||
key = ['target_id']
|
||||
is_equal = lambda x, y: x == y
|
||||
|
||||
for draggable in user_answer['draggables']:
|
||||
if not is_equal(draggable[key], correct_answer[key]):
|
||||
return False
|
||||
|
||||
return True
|
||||
23
common/lib/capa/capa/graders/tests.py
Normal file
23
common/lib/capa/capa/graders/tests.py
Normal file
@@ -0,0 +1,23 @@
|
||||
import unittest
|
||||
|
||||
import draganddrop
|
||||
|
||||
|
||||
class Test_DragAndDrop(unittest.TestCase):
|
||||
|
||||
def test_1(self):
|
||||
user_input = '{"laice": "bcc", "points": [["0.00", "1.00", "0.00"], ["1.00", "1.00", "0.00"], ["0.00", "0.00", "1.00"]]}'
|
||||
correct_answer = {}
|
||||
self.assertTrue(draganddrop.grade(user_input, correct_answer))
|
||||
|
||||
|
||||
def suite():
|
||||
|
||||
testcases = [Test_DragAndDrop]
|
||||
suites = []
|
||||
for testcase in testcases:
|
||||
suites.append(unittest.TestLoader().loadTestsFromTestCase(testcase))
|
||||
return unittest.TestSuite(suites)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.TextTestRunner(verbosity=2).run(suite())
|
||||
Reference in New Issue
Block a user