merge feature/alex/drag_and_drop-mitx into feature/alex/poll-merged

This commit is contained in:
Vasyl Nakvasiuk
2013-03-05 18:20:38 +02:00
parent f87a5fbbbd
commit 0d83fefecf
16 changed files with 1422 additions and 874 deletions

View File

@@ -798,6 +798,10 @@ class DragAndDropInput(InputTypeBase):
if tag_type == 'draggable' and not self.no_labels:
dic['label'] = dic['label'] or dic['id']
if tag_type == 'draggable':
dic['target_fields'] = [parse(target, 'target') for target in
tag.iterchildren('target')]
return dic
# add labels to images?:
@@ -909,15 +913,15 @@ registry.register(DesignProtein2dInput)
class EditAGeneInput(InputTypeBase):
"""
An input type for editing a gene. Integrates with the genex java applet.
Example:
<editagene width="800" hight="500" dna_sequence="ETAAGGCTATAACCGA" />
"""
template = "editageneinput.html"
tags = ['editageneinput']
@classmethod
def get_attributes(cls):
"""
@@ -927,14 +931,14 @@ class EditAGeneInput(InputTypeBase):
Attribute('height'),
Attribute('dna_sequence')
]
def _extra_context(self):
"""
"""
context = {
'applet_loader': '/static/js/capa/edit-a-gene.js',
}
return context
registry.register(EditAGeneInput)

View File

@@ -539,14 +539,14 @@ class DragAndDropTest(unittest.TestCase):
"target_outline": "false",
"base_image": "/static/images/about_1.png",
"draggables": [
{"can_reuse": "", "label": "Label 1", "id": "1", "icon": ""},
{"can_reuse": "", "label": "cc", "id": "name_with_icon", "icon": "/static/images/cc.jpg", },
{"can_reuse": "", "label": "arrow-left", "id": "with_icon", "icon": "/static/images/arrow-left.png", "can_reuse": ""},
{"can_reuse": "", "label": "Label2", "id": "5", "icon": "", "can_reuse": ""},
{"can_reuse": "", "label": "Mute", "id": "2", "icon": "/static/images/mute.png", "can_reuse": ""},
{"can_reuse": "", "label": "spinner", "id": "name_label_icon3", "icon": "/static/images/spinner.gif", "can_reuse": ""},
{"can_reuse": "", "label": "Star", "id": "name4", "icon": "/static/images/volume.png", "can_reuse": ""},
{"can_reuse": "", "label": "Label3", "id": "7", "icon": "", "can_reuse": ""}],
{"can_reuse": "", "label": "Label 1", "id": "1", "icon": "", "target_fields": []},
{"can_reuse": "", "label": "cc", "id": "name_with_icon", "icon": "/static/images/cc.jpg", "target_fields": []},
{"can_reuse": "", "label": "arrow-left", "id": "with_icon", "icon": "/static/images/arrow-left.png", "can_reuse": "", "target_fields": []},
{"can_reuse": "", "label": "Label2", "id": "5", "icon": "", "can_reuse": "", "target_fields": []},
{"can_reuse": "", "label": "Mute", "id": "2", "icon": "/static/images/mute.png", "can_reuse": "", "target_fields": []},
{"can_reuse": "", "label": "spinner", "id": "name_label_icon3", "icon": "/static/images/spinner.gif", "can_reuse": "", "target_fields": []},
{"can_reuse": "", "label": "Star", "id": "name4", "icon": "/static/images/volume.png", "can_reuse": "", "target_fields": []},
{"can_reuse": "", "label": "Label3", "id": "7", "icon": "", "can_reuse": "", "target_fields": []}],
"one_per_target": "True",
"targets": [
{"y": "90", "x": "210", "id": "t1", "w": "90", "h": "90"},

View File

@@ -27,6 +27,49 @@ values are (x,y) coordinates of centers of dragged images.
import json
def flat_user_answer(user_answer):
"""
Convert nested `user_answer` to flat format.
{'up': {'first': {'p': 'p_l'}}}
to
{'up': 'p_l[p][first]'}
"""
def parse_user_answer(answer):
key = answer.keys()[0]
value = answer.values()[0]
if isinstance(value, dict):
# Make complex value:
# Example:
# Create like 'p_l[p][first]' from {'first': {'p': 'p_l'}
complex_value_list = []
v_value = value
while isinstance(v_value, dict):
v_key = v_value.keys()[0]
v_value = v_value.values()[0]
complex_value_list.append(v_key)
complex_value = '{0}'.format(v_value)
for i in reversed(complex_value_list):
complex_value = '{0}[{1}]'.format(complex_value, i)
res = {key: complex_value}
return res
else:
return answer
result = []
for answer in user_answer:
parse_answer = parse_user_answer(answer)
result.append(parse_answer)
return result
class PositionsCompare(list):
""" Class for comparing positions.
@@ -116,37 +159,36 @@ class DragAndDrop(object):
# Number of draggables in user_groups may be differ that in
# correct_groups, that is incorrect, except special case with 'number'
for groupname, draggable_ids in self.correct_groups.items():
for index, draggable_ids in enumerate(self.correct_groups):
# 'number' rule special case
# for reusable draggables we may get in self.user_groups
# {'1': [u'2', u'2', u'2'], '0': [u'1', u'1'], '2': [u'3']}
# if '+number' is in rule - do not remove duplicates and strip
# '+number' from rule
current_rule = self.correct_positions[groupname].keys()[0]
current_rule = self.correct_positions[index].keys()[0]
if 'number' in current_rule:
rule_values = self.correct_positions[groupname][current_rule]
rule_values = self.correct_positions[index][current_rule]
# clean rule, do not do clean duplicate items
self.correct_positions[groupname].pop(current_rule, None)
self.correct_positions[index].pop(current_rule, None)
parsed_rule = current_rule.replace('+', '').replace('number', '')
self.correct_positions[groupname][parsed_rule] = rule_values
self.correct_positions[index][parsed_rule] = rule_values
else: # remove dublicates
self.user_groups[groupname] = list(set(self.user_groups[groupname]))
self.user_groups[index] = list(set(self.user_groups[index]))
if sorted(draggable_ids) != sorted(self.user_groups[groupname]):
if sorted(draggable_ids) != sorted(self.user_groups[index]):
return False
# Check that in every group, for rule of that group, user positions of
# every element are equal with correct positions
for groupname in self.correct_groups:
for index, _ in enumerate(self.correct_groups):
rules_executed = 0
for rule in ('exact', 'anyof', 'unordered_equal'):
# every group has only one rule
if self.correct_positions[groupname].get(rule, None):
if self.correct_positions[index].get(rule, None):
rules_executed += 1
if not self.compare_positions(
self.correct_positions[groupname][rule],
self.user_positions[groupname]['user'], flag=rule):
self.correct_positions[index][rule],
self.user_positions[index]['user'], flag=rule):
return False
if not rules_executed: # no correct rules for current group
# probably xml content mistake - wrong rules names
@@ -248,7 +290,7 @@ class DragAndDrop(object):
correct_answer = {'name4': 't1',
'name_with_icon': 't1',
'5': 't2',
'7':'t2'}
'7': 't2'}
It is draggable_name: dragable_position mapping.
@@ -284,24 +326,25 @@ class DragAndDrop(object):
Args:
user_answer: json
correct_answer: dict or list
correct_answer: dict or list
"""
self.correct_groups = dict() # correct groups from xml
self.correct_positions = dict() # correct positions for comparing
self.user_groups = dict() # will be populated from user answer
self.user_positions = dict() # will be populated from user answer
self.correct_groups = [] # Correct groups from xml.
self.correct_positions = [] # Correct positions for comparing.
self.user_groups = [] # Will be populated from user answer.
self.user_positions = [] # Will be populated from user answer.
# convert from dict answer format to list format
# Convert from dict answer format to list format.
if isinstance(correct_answer, dict):
tmp = []
for key, value in correct_answer.items():
tmp_dict = {'draggables': [], 'targets': [], 'rule': 'exact'}
tmp_dict['draggables'].append(key)
tmp_dict['targets'].append(value)
tmp.append(tmp_dict)
tmp.append({
'draggables': [key],
'targets': [value],
'rule': 'exact'})
correct_answer = tmp
# Convert string `user_answer` to object.
user_answer = json.loads(user_answer)
# This dictionary will hold a key for each draggable the user placed on
@@ -312,24 +355,29 @@ class DragAndDrop(object):
self.excess_draggables = dict((users_draggable.keys()[0],True)
for users_draggable in user_answer['draggables'])
# create identical data structures from user answer and correct answer
for i in xrange(0, len(correct_answer)):
groupname = str(i)
self.correct_groups[groupname] = correct_answer[i]['draggables']
self.correct_positions[groupname] = {correct_answer[i]['rule']:
correct_answer[i]['targets']}
self.user_groups[groupname] = []
self.user_positions[groupname] = {'user': []}
for draggable_dict in user_answer['draggables']:
# draggable_dict is 1-to-1 {draggable_name: position}
# Convert nested `user_answer` to flat format.
user_answer = flat_user_answer(user_answer)
# Create identical data structures from user answer and correct answer.
for answer in correct_answer:
user_groups_data = []
user_positions_data = []
for draggable_dict in user_answer:
# Draggable_dict is 1-to-1 {draggable_name: position}.
draggable_name = draggable_dict.keys()[0]
if draggable_name in self.correct_groups[groupname]:
self.user_groups[groupname].append(draggable_name)
self.user_positions[groupname]['user'].append(
if draggable_name in answer['draggables']:
user_groups_data.append(draggable_name)
user_positions_data.append(
draggable_dict[draggable_name])
# proved that this is not excess
self.excess_draggables[draggable_name] = False
self.correct_groups.append(answer['draggables'])
self.correct_positions.append({answer['rule']: answer['targets']})
self.user_groups.append(user_groups_data)
self.user_positions.append({'user': user_positions_data})
def grade(user_input, correct_answer):
""" Creates DragAndDrop instance from user_input and correct_answer and
calls DragAndDrop.grade for grading.

View File

@@ -2,6 +2,7 @@ import unittest
import draganddrop
from draganddrop import PositionsCompare
import json
class Test_PositionsCompare(unittest.TestCase):
@@ -40,10 +41,242 @@ class Test_PositionsCompare(unittest.TestCase):
class Test_DragAndDrop_Grade(unittest.TestCase):
def test_targets_are_draggable_1(self):
user_input = json.dumps([
{'p': 'p_l'},
{'up': {'first': {'p': 'p_l'}}}
])
correct_answer = [
{
'draggables': ['p'],
'targets': [
'p_l', 'p_r'
],
'rule': 'anyof'
},
{
'draggables': ['up'],
'targets': [
'p_l[p][first]'
],
'rule': 'anyof'
}
]
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_targets_are_draggable_2(self):
user_input = json.dumps([
{'p': 'p_l'},
{'p': 'p_r'},
{'s': 's_l'},
{'s': 's_r'},
{'up': {'1': {'p': 'p_l'}}},
{'up': {'3': {'p': 'p_l'}}},
{'up': {'1': {'p': 'p_r'}}},
{'up': {'3': {'p': 'p_r'}}},
{'up_and_down': {'1': {'s': 's_l'}}},
{'up_and_down': {'1': {'s': 's_r'}}}
])
correct_answer = [
{
'draggables': ['p'],
'targets': ['p_l', 'p_r'],
'rule': 'unordered_equal'
},
{
'draggables': ['s'],
'targets': ['s_l', 's_r'],
'rule': 'unordered_equal'
},
{
'draggables': ['up_and_down'],
'targets': [
's_l[s][1]', 's_r[s][1]'
],
'rule': 'unordered_equal'
},
{
'draggables': ['up'],
'targets': [
'p_l[p][1]', 'p_l[p][3]', 'p_r[p][1]', 'p_r[p][3]'
],
'rule': 'unordered_equal'
}
]
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_targets_are_draggable_2_manual_parsing(self):
user_input = json.dumps([
{'up': 'p_l[p][1]'},
{'p': 'p_l'},
{'up': 'p_l[p][3]'},
{'up': 'p_r[p][1]'},
{'p': 'p_r'},
{'up': 'p_r[p][3]'},
{'up_and_down': 's_l[s][1]'},
{'s': 's_l'},
{'up_and_down': 's_r[s][1]'},
{'s': 's_r'}
])
correct_answer = [
{
'draggables': ['p'],
'targets': ['p_l', 'p_r'],
'rule': 'unordered_equal'
},
{
'draggables': ['s'],
'targets': ['s_l', 's_r'],
'rule': 'unordered_equal'
},
{
'draggables': ['up_and_down'],
'targets': [
's_l[s][1]', 's_r[s][1]'
],
'rule': 'unordered_equal'
},
{
'draggables': ['up'],
'targets': [
'p_l[p][1]', 'p_l[p][3]', 'p_r[p][1]', 'p_r[p][3]'
],
'rule': 'unordered_equal'
}
]
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_targets_are_draggable_3_nested(self):
user_input = json.dumps([
{'molecule': 'left_side_tagret'},
{'molecule': 'right_side_tagret'},
{'p': {'p_target': {'molecule': 'left_side_tagret'}}},
{'p': {'p_target': {'molecule': 'right_side_tagret'}}},
{'s': {'s_target': {'molecule': 'left_side_tagret'}}},
{'s': {'s_target': {'molecule': 'right_side_tagret'}}},
{'up': {'1': {'p': {'p_target': {'molecule': 'left_side_tagret'}}}}},
{'up': {'3': {'p': {'p_target': {'molecule': 'left_side_tagret'}}}}},
{'up': {'1': {'p': {'p_target': {'molecule': 'right_side_tagret'}}}}},
{'up': {'3': {'p': {'p_target': {'molecule': 'right_side_tagret'}}}}},
{'up_and_down': {'1': {'s': {'s_target': {'molecule': 'left_side_tagret'}}}}},
{'up_and_down': {'1': {'s': {'s_target': {'molecule': 'right_side_tagret'}}}}}
])
correct_answer = [
{
'draggables': ['molecule'],
'targets': ['left_side_tagret', 'right_side_tagret'],
'rule': 'unordered_equal'
},
{
'draggables': ['p'],
'targets': [
'left_side_tagret[molecule][p_target]',
'right_side_tagret[molecule][p_target]'
],
'rule': 'unordered_equal'
},
{
'draggables': ['s'],
'targets': [
'left_side_tagret[molecule][s_target]',
'right_side_tagret[molecule][s_target]'
],
'rule': 'unordered_equal'
},
{
'draggables': ['up_and_down'],
'targets': [
'left_side_tagret[molecule][s_target][s][1]',
'right_side_tagret[molecule][s_target][s][1]'
],
'rule': 'unordered_equal'
},
{
'draggables': ['up'],
'targets': [
'left_side_tagret[molecule][p_target][p][1]',
'left_side_tagret[molecule][p_target][p][3]',
'right_side_tagret[molecule][p_target][p][1]',
'right_side_tagret[molecule][p_target][p][3]'
],
'rule': 'unordered_equal'
}
]
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_targets_are_draggable_4_real_example(self):
user_input = json.dumps([
{'single_draggable': 's_l'},
{'single_draggable': 's_r'},
{'single_draggable': 'p_sigma'},
{'single_draggable': 'p_sigma*'},
{'single_draggable': 's_sigma'},
{'single_draggable': 's_sigma*'},
{'double_draggable': 'p_pi*'},
{'double_draggable': 'p_pi'},
{'triple_draggable': 'p_l'},
{'triple_draggable': 'p_r'},
{'up': {'1': {'triple_draggable': 'p_l'}}},
{'up': {'2': {'triple_draggable': 'p_l'}}},
{'up': {'2': {'triple_draggable': 'p_r'}}},
{'up': {'3': {'triple_draggable': 'p_r'}}},
{'up_and_down': {'1': {'single_draggable': 's_l'}}},
{'up_and_down': {'1': {'single_draggable': 's_r'}}},
{'up_and_down': {'1': {'single_draggable': 's_sigma'}}},
{'up_and_down': {'1': {'single_draggable': 's_sigma*'}}},
{'up_and_down': {'1': {'double_draggable': 'p_pi'}}},
{'up_and_down': {'2': {'double_draggable': 'p_pi'}}}
])
# 10 targets:
# s_l, s_r, p_l, p_r, s_sigma, s_sigma*, p_pi, p_sigma, p_pi*, p_sigma*
#
# 3 draggable objects, which have targets (internal target ids - 1, 2, 3):
# single_draggable, double_draggable, triple_draggable
#
# 2 draggable objects:
# up, up_and_down
correct_answer = [
{
'draggables': ['triple_draggable'],
'targets': ['p_l', 'p_r'],
'rule': 'unordered_equal'
},
{
'draggables': ['double_draggable'],
'targets': ['p_pi', 'p_pi*'],
'rule': 'unordered_equal'
},
{
'draggables': ['single_draggable'],
'targets': ['s_l', 's_r', 's_sigma', 's_sigma*', 'p_sigma', 'p_sigma*'],
'rule': 'unordered_equal'
},
{
'draggables': ['up'],
'targets': ['p_l[triple_draggable][1]', 'p_l[triple_draggable][2]',
'p_r[triple_draggable][2]', 'p_r[triple_draggable][3]'],
'rule': 'unordered_equal'
},
{
'draggables': ['up_and_down'],
'targets': ['s_l[single_draggable][1]', 's_r[single_draggable][1]',
's_sigma[single_draggable][1]', 's_sigma*[single_draggable][1]',
'p_pi[double_draggable][1]', 'p_pi[double_draggable][2]'],
'rule': 'unordered_equal'
},
]
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_targets_true(self):
user_input = '{"draggables": [{"1": "t1"}, \
{"name_with_icon": "t2"}]}'
correct_answer = {'1': 't1', 'name_with_icon': 't2'}
user_input = '[{"1": "t1"}, \
{"name_with_icon": "t2"}]'
correct_answer = {'1': 't1', 'name_with_icon': 't2'}
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_expect_no_actions_wrong(self):
@@ -59,71 +292,63 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_targets_false(self):
user_input = '{"draggables": [{"1": "t1"}, \
{"name_with_icon": "t2"}]}'
correct_answer = {'1': 't3', 'name_with_icon': 't2'}
user_input = '[{"1": "t1"}, \
{"name_with_icon": "t2"}]'
correct_answer = {'1': 't3', 'name_with_icon': 't2'}
self.assertFalse(draganddrop.grade(user_input, correct_answer))
def test_multiple_images_per_target_true(self):
user_input = '{\
"draggables": [{"1": "t1"}, {"name_with_icon": "t2"}, \
{"2": "t1"}]}'
correct_answer = {'1': 't1', 'name_with_icon': 't2',
user_input = '[{"1": "t1"}, {"name_with_icon": "t2"}, \
{"2": "t1"}]'
correct_answer = {'1': 't1', 'name_with_icon': 't2',
'2': 't1'}
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_multiple_images_per_target_false(self):
user_input = '{\
"draggables": [{"1": "t1"}, {"name_with_icon": "t2"}, \
{"2": "t1"}]}'
correct_answer = {'1': 't2', 'name_with_icon': 't2',
user_input = '[{"1": "t1"}, {"name_with_icon": "t2"}, \
{"2": "t1"}]'
correct_answer = {'1': 't2', 'name_with_icon': 't2',
'2': 't1'}
self.assertFalse(draganddrop.grade(user_input, correct_answer))
def test_targets_and_positions(self):
user_input = '{"draggables": [{"1": [10,10]}, \
{"name_with_icon": [[10,10],4]}]}'
user_input = '[{"1": [10,10]}, \
{"name_with_icon": [[10,10],4]}]'
correct_answer = {'1': [10, 10], 'name_with_icon': [[10, 10], 4]}
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_position_and_targets(self):
user_input = '{"draggables": [{"1": "t1"}, {"name_with_icon": "t2"}]}'
user_input = '[{"1": "t1"}, {"name_with_icon": "t2"}]'
correct_answer = {'1': 't1', 'name_with_icon': 't2'}
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_positions_exact(self):
user_input = '{"draggables": \
[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]}'
user_input = '[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]'
correct_answer = {'1': [10, 10], 'name_with_icon': [20, 20]}
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_positions_false(self):
user_input = '{"draggables": \
[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]}'
user_input = '[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]'
correct_answer = {'1': [25, 25], 'name_with_icon': [20, 20]}
self.assertFalse(draganddrop.grade(user_input, correct_answer))
def test_positions_true_in_radius(self):
user_input = '{"draggables": \
[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]}'
user_input = '[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]'
correct_answer = {'1': [14, 14], 'name_with_icon': [20, 20]}
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_positions_true_in_manual_radius(self):
user_input = '{"draggables": \
[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]}'
user_input = '[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]'
correct_answer = {'1': [[40, 10], 30], 'name_with_icon': [20, 20]}
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_positions_false_in_manual_radius(self):
user_input = '{"draggables": \
[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]}'
user_input = '[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]'
correct_answer = {'1': [[40, 10], 29], 'name_with_icon': [20, 20]}
self.assertFalse(draganddrop.grade(user_input, correct_answer))
def test_correct_answer_not_has_key_from_user_answer(self):
user_input = '{"draggables": [{"1": "t1"}, \
{"name_with_icon": "t2"}]}'
user_input = '[{"1": "t1"}, {"name_with_icon": "t2"}]'
correct_answer = {'3': 't3', 'name_with_icon': 't2'}
self.assertFalse(draganddrop.grade(user_input, correct_answer))
@@ -131,20 +356,20 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
"""Draggables can be places anywhere on base image.
Place grass in the middle of the image and ant in the
right upper corner."""
user_input = '{"draggables": \
[{"ant":[610.5,57.449951171875]},{"grass":[322.5,199.449951171875]}]}'
user_input = '[{"ant":[610.5,57.449951171875]},\
{"grass":[322.5,199.449951171875]}]'
correct_answer = {'grass': [[300, 200], 200], 'ant': [[500, 0], 200]}
self.assertTrue(draganddrop.grade(user_input, correct_answer))
def test_lcao_correct(self):
"""Describe carbon molecule in LCAO-MO"""
user_input = '{"draggables":[{"1":"s_left"}, \
user_input = '[{"1":"s_left"}, \
{"5":"s_right"},{"4":"s_sigma"},{"6":"s_sigma_star"},{"7":"p_left_1"}, \
{"8":"p_left_2"},{"10":"p_right_1"},{"9":"p_right_2"}, \
{"2":"p_pi_1"},{"3":"p_pi_2"},{"11":"s_sigma_name"}, \
{"13":"s_sigma_star_name"},{"15":"p_pi_name"},{"16":"p_pi_star_name"}, \
{"12":"p_sigma_name"},{"14":"p_sigma_star_name"}]}'
{"12":"p_sigma_name"},{"14":"p_sigma_star_name"}]'
correct_answer = [{
'draggables': ['1', '2', '3', '4', '5', '6'],
@@ -178,12 +403,12 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_lcao_extra_element_incorrect(self):
"""Describe carbon molecule in LCAO-MO"""
user_input = '{"draggables":[{"1":"s_left"}, \
user_input = '[{"1":"s_left"}, \
{"5":"s_right"},{"4":"s_sigma"},{"6":"s_sigma_star"},{"7":"p_left_1"}, \
{"8":"p_left_2"},{"17":"p_left_3"},{"10":"p_right_1"},{"9":"p_right_2"}, \
{"2":"p_pi_1"},{"3":"p_pi_2"},{"11":"s_sigma_name"}, \
{"13":"s_sigma_star_name"},{"15":"p_pi_name"},{"16":"p_pi_star_name"}, \
{"12":"p_sigma_name"},{"14":"p_sigma_star_name"}]}'
{"12":"p_sigma_name"},{"14":"p_sigma_star_name"}]'
correct_answer = [{
'draggables': ['1', '2', '3', '4', '5', '6'],
@@ -217,9 +442,9 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_reuse_draggable_no_mupliples(self):
"""Test reusable draggables (no mupltiple draggables per target)"""
user_input = '{"draggables":[{"1":"target1"}, \
user_input = '[{"1":"target1"}, \
{"2":"target2"},{"1":"target3"},{"2":"target4"},{"2":"target5"}, \
{"3":"target6"}]}'
{"3":"target6"}]'
correct_answer = [
{
'draggables': ['1'],
@@ -240,9 +465,9 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_reuse_draggable_with_mupliples(self):
"""Test reusable draggables with mupltiple draggables per target"""
user_input = '{"draggables":[{"1":"target1"}, \
user_input = '[{"1":"target1"}, \
{"2":"target2"},{"1":"target1"},{"2":"target4"},{"2":"target4"}, \
{"3":"target6"}]}'
{"3":"target6"}]'
correct_answer = [
{
'draggables': ['1'],
@@ -263,10 +488,10 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_reuse_many_draggable_with_mupliples(self):
"""Test reusable draggables with mupltiple draggables per target"""
user_input = '{"draggables":[{"1":"target1"}, \
user_input = '[{"1":"target1"}, \
{"2":"target2"},{"1":"target1"},{"2":"target4"},{"2":"target4"}, \
{"3":"target6"}, {"4": "target3"}, {"5": "target4"}, \
{"5": "target5"}, {"6": "target2"}]}'
{"5": "target5"}, {"6": "target2"}]'
correct_answer = [
{
'draggables': ['1', '4'],
@@ -292,12 +517,12 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_reuse_many_draggable_with_mupliples_wrong(self):
"""Test reusable draggables with mupltiple draggables per target"""
user_input = '{"draggables":[{"1":"target1"}, \
user_input = '[{"1":"target1"}, \
{"2":"target2"},{"1":"target1"}, \
{"2":"target3"}, \
{"2":"target4"}, \
{"3":"target6"}, {"4": "target3"}, {"5": "target4"}, \
{"5": "target5"}, {"6": "target2"}]}'
{"5": "target5"}, {"6": "target2"}]'
correct_answer = [
{
'draggables': ['1', '4'],
@@ -323,10 +548,10 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_label_10_targets_with_a_b_c_false(self):
"""Test reusable draggables (no mupltiple draggables per target)"""
user_input = '{"draggables":[{"a":"target1"}, \
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"},{"a":"target4"},{"b":"target5"}, \
{"c":"target6"}, {"a":"target7"},{"b":"target8"},{"c":"target9"}, \
{"a":"target1"}]}'
{"a":"target1"}]'
correct_answer = [
{
'draggables': ['a'],
@@ -347,10 +572,10 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_label_10_targets_with_a_b_c_(self):
"""Test reusable draggables (no mupltiple draggables per target)"""
user_input = '{"draggables":[{"a":"target1"}, \
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"},{"a":"target4"},{"b":"target5"}, \
{"c":"target6"}, {"a":"target7"},{"b":"target8"},{"c":"target9"}, \
{"a":"target10"}]}'
{"a":"target10"}]'
correct_answer = [
{
'draggables': ['a'],
@@ -371,10 +596,10 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_label_10_targets_with_a_b_c_multiple(self):
"""Test reusable draggables (mupltiple draggables per target)"""
user_input = '{"draggables":[{"a":"target1"}, \
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"},{"b":"target5"}, \
{"c":"target6"}, {"a":"target7"},{"b":"target8"},{"c":"target9"}, \
{"a":"target1"}]}'
{"a":"target1"}]'
correct_answer = [
{
'draggables': ['a', 'a', 'a'],
@@ -395,10 +620,10 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_label_10_targets_with_a_b_c_multiple_false(self):
"""Test reusable draggables (mupltiple draggables per target)"""
user_input = '{"draggables":[{"a":"target1"}, \
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"},{"a":"target4"},{"b":"target5"}, \
{"c":"target6"}, {"a":"target7"},{"b":"target8"},{"c":"target9"}, \
{"a":"target1"}]}'
{"a":"target1"}]'
correct_answer = [
{
'draggables': ['a', 'a', 'a'],
@@ -419,10 +644,10 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_label_10_targets_with_a_b_c_reused(self):
"""Test a b c in 10 labels reused"""
user_input = '{"draggables":[{"a":"target1"}, \
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"},{"b":"target5"}, \
{"c":"target6"}, {"b":"target8"},{"c":"target9"}, \
{"a":"target10"}]}'
{"a":"target10"}]'
correct_answer = [
{
'draggables': ['a', 'a'],
@@ -443,10 +668,10 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_label_10_targets_with_a_b_c_reused_false(self):
"""Test a b c in 10 labels reused false"""
user_input = '{"draggables":[{"a":"target1"}, \
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"},{"b":"target5"}, {"a":"target8"},\
{"c":"target6"}, {"b":"target8"},{"c":"target9"}, \
{"a":"target10"}]}'
{"a":"target10"}]'
correct_answer = [
{
'draggables': ['a', 'a'],
@@ -467,9 +692,9 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_mixed_reuse_and_not_reuse(self):
"""Test reusable draggables """
user_input = '{"draggables":[{"a":"target1"}, \
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"}, {"a":"target4"},\
{"a":"target5"}]}'
{"a":"target5"}]'
correct_answer = [
{
'draggables': ['a', 'b'],
@@ -485,8 +710,8 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_mixed_reuse_and_not_reuse_number(self):
"""Test reusable draggables with number """
user_input = '{"draggables":[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"}, {"a":"target4"}]}'
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"}, {"a":"target4"}]'
correct_answer = [
{
'draggables': ['a', 'a', 'b'],
@@ -502,8 +727,8 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
def test_mixed_reuse_and_not_reuse_number_false(self):
"""Test reusable draggables with numbers, but wrong"""
user_input = '{"draggables":[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"}, {"a":"target4"}, {"a":"target10"}]}'
user_input = '[{"a":"target1"}, \
{"b":"target2"},{"c":"target3"}, {"a":"target4"}, {"a":"target10"}]'
correct_answer = [
{
'draggables': ['a', 'a', 'b'],
@@ -518,9 +743,9 @@ class Test_DragAndDrop_Grade(unittest.TestCase):
self.assertFalse(draganddrop.grade(user_input, correct_answer))
def test_alternative_correct_answer(self):
user_input = '{"draggables":[{"name_with_icon":"t1"},\
user_input = '[{"name_with_icon":"t1"},\
{"name_with_icon":"t1"},{"name_with_icon":"t1"},{"name4":"t1"}, \
{"name4":"t1"}]}'
{"name4":"t1"}]'
correct_answer = [
{'draggables': ['name4'], 'targets': ['t1', 't1'], 'rule': 'exact'},
{'draggables': ['name_with_icon'], 'targets': ['t1', 't1', 't1'],
@@ -533,14 +758,13 @@ class Test_DragAndDrop_Populate(unittest.TestCase):
def test_1(self):
correct_answer = {'1': [[40, 10], 29], 'name_with_icon': [20, 20]}
user_input = '{"draggables": \
[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]}'
user_input = '[{"1": [10, 10]}, {"name_with_icon": [20, 20]}]'
dnd = draganddrop.DragAndDrop(correct_answer, user_input)
correct_groups = {'1': ['name_with_icon'], '0': ['1']}
correct_positions = {'1': {'exact': [[20, 20]]}, '0': {'exact': [[[40, 10], 29]]}}
user_groups = {'1': [u'name_with_icon'], '0': [u'1']}
user_positions = {'1': {'user': [[20, 20]]}, '0': {'user': [[10, 10]]}}
correct_groups = [['1'], ['name_with_icon']]
correct_positions = [{'exact': [[[40, 10], 29]]}, {'exact': [[20, 20]]}]
user_groups = [['1'], ['name_with_icon']]
user_positions = [{'user': [[10, 10]]}, {'user': [[20, 20]]}]
self.assertEqual(correct_groups, dnd.correct_groups)
self.assertEqual(correct_positions, dnd.correct_positions)
@@ -551,49 +775,49 @@ class Test_DragAndDrop_Populate(unittest.TestCase):
class Test_DraAndDrop_Compare_Positions(unittest.TestCase):
def test_1(self):
dnd = draganddrop.DragAndDrop({'1': 't1'}, '{"draggables": [{"1": "t1"}]}')
dnd = draganddrop.DragAndDrop({'1': 't1'}, '[{"1": "t1"}]')
self.assertTrue(dnd.compare_positions(correct=[[1, 1], [2, 3]],
user=[[2, 3], [1, 1]],
flag='anyof'))
def test_2a(self):
dnd = draganddrop.DragAndDrop({'1': 't1'}, '{"draggables": [{"1": "t1"}]}')
dnd = draganddrop.DragAndDrop({'1': 't1'}, '[{"1": "t1"}]')
self.assertTrue(dnd.compare_positions(correct=[[1, 1], [2, 3]],
user=[[2, 3], [1, 1]],
flag='exact'))
def test_2b(self):
dnd = draganddrop.DragAndDrop({'1': 't1'}, '{"draggables": [{"1": "t1"}]}')
dnd = draganddrop.DragAndDrop({'1': 't1'}, '[{"1": "t1"}]')
self.assertFalse(dnd.compare_positions(correct=[[1, 1], [2, 3]],
user=[[2, 13], [1, 1]],
flag='exact'))
def test_3(self):
dnd = draganddrop.DragAndDrop({'1': 't1'}, '{"draggables": [{"1": "t1"}]}')
dnd = draganddrop.DragAndDrop({'1': 't1'}, '[{"1": "t1"}]')
self.assertFalse(dnd.compare_positions(correct=["a", "b"],
user=["a", "b", "c"],
flag='anyof'))
def test_4(self):
dnd = draganddrop.DragAndDrop({'1': 't1'}, '{"draggables": [{"1": "t1"}]}')
dnd = draganddrop.DragAndDrop({'1': 't1'}, '[{"1": "t1"}]')
self.assertTrue(dnd.compare_positions(correct=["a", "b", "c"],
user=["a", "b"],
flag='anyof'))
def test_5(self):
dnd = draganddrop.DragAndDrop({'1': 't1'}, '{"draggables": [{"1": "t1"}]}')
dnd = draganddrop.DragAndDrop({'1': 't1'}, '[{"1": "t1"}]')
self.assertFalse(dnd.compare_positions(correct=["a", "b", "c"],
user=["a", "c", "b"],
flag='exact'))
def test_6(self):
dnd = draganddrop.DragAndDrop({'1': 't1'}, '{"draggables": [{"1": "t1"}]}')
dnd = draganddrop.DragAndDrop({'1': 't1'}, '[{"1": "t1"}]')
self.assertTrue(dnd.compare_positions(correct=["a", "b", "c"],
user=["a", "c", "b"],
flag='anyof'))
def test_7(self):
dnd = draganddrop.DragAndDrop({'1': 't1'}, '{"draggables": [{"1": "t1"}]}')
dnd = draganddrop.DragAndDrop({'1': 't1'}, '[{"1": "t1"}]')
self.assertFalse(dnd.compare_positions(correct=["a", "b", "b"],
user=["a", "c", "b"],
flag='anyof'))