Commit 75ff3aaa by Alexander Kryklia

docs and denied rule refactores

parent ab951932
...@@ -18,13 +18,12 @@ If use_targets is false: ...@@ -18,13 +18,12 @@ If use_targets is false:
{ {
"use_targets": false, "use_targets": false,
"draggable": [ "draggable": [
{ "image1": "(10, 20)" }, { "image1": "[10, 20]" },
{ "ant": "(30, 40)" }, { "ant": "[30, 40]" },
{ "molecule": "(100, 200)" }, { "molecule": "[100, 200]" },
] ]
} }
values are (x,y) coordinates of centers of dragged images. values are (x,y) coordinates of centers of dragged images.
""" """
import json import json
...@@ -32,55 +31,58 @@ from collections import OrderedDict ...@@ -32,55 +31,58 @@ from collections import OrderedDict
class PositionsCompare(list): class PositionsCompare(list):
"""Inputs are: "abc" - target """ Class for comparing positions.
Args:
list or string::
"abc" - target
[10, 20] - list of integers [10, 20] - list of integers
[[10,20], 200] list of list and integer [[10,20], 200] list of list and integer
""" """
def __eq__(self, other): def __eq__(self, other):
# Default lists behaviour is convers "abc" to ["a", "b", "c"]. """ Compares two arguments.
# We will use that.
# import ipdb; ipdb.set_trace()
#check if self or other is not empty list (empty lists = false) Default lists behavior is conversion of string "abc" to list
if not self or not other: ["a", "b", "c"]. We will use that.
return False
# check correct input types If self or other is empty - returns False.
if (not isinstance(self[0], (str, unicode, list, int, float)) or
not isinstance(other[0], (str, unicode, list, int, float))): Args:
print 'Incorrect input type' self, other: str, unicode, list, int, float
Returns: bool
"""
# checks if self or other is not empty list (empty lists = false)
if not self or not other:
return False return False
if (isinstance(self[0], (list, int, float)) and if (isinstance(self[0], (list, int, float)) and
isinstance(other[0], (list, int, float))): isinstance(other[0], (list, int, float))):
print 'Numerical position compare'
return self.coordinate_positions_compare(other) return self.coordinate_positions_compare(other)
elif (isinstance(self[0], (unicode, str)) and elif (isinstance(self[0], (unicode, str)) and
isinstance(other[0], (unicode, str))): isinstance(other[0], (unicode, str))):
print 'Targets compare'
return ''.join(self) == ''.join(other) return ''.join(self) == ''.join(other)
else: else: # improper argument types
# we do not have ints or lists of lists or two string/unicode lists # Now we have no (float / int or lists of list and float / int pair)
# on both sides # or two string / unicode lists pair
print type(self[0]), type(other[0]), "not correct"
return False return False
def __ne__(self, other): def __ne__(self, other):
return not self.__eq__(other) return not self.__eq__(other)
def coordinate_positions_compare(self, other, r=10): def coordinate_positions_compare(self, other, r=10):
""" Checks if pos1 is equal to pos2 inside radius """ Checks if self is equal to other inside radius of forgiveness
of forgiveness (default 10 px). (default 10 px).
Args: Args:
self, other: [x, y] or [[x, y], r], where self, other: [x, y] or [[x, y], r], where r is radius of
r is radius of forgiveness; forgiveness;
x, y, r: int x, y, r: int
Returns: bool. Returns: bool.
""" """
print 'I am called', self, other
# get max radius of forgiveness # get max radius of forgiveness
if isinstance(self[0], list): # [(x, y), r] case if isinstance(self[0], list): # [(x, y), r] case
r = max(self[1], r) r = max(self[1], r)
...@@ -101,62 +103,56 @@ class PositionsCompare(list): ...@@ -101,62 +103,56 @@ class PositionsCompare(list):
class DragAndDrop(object): class DragAndDrop(object):
""" Grader for drag and drop inputtype.
"""
def __init__(self): def __init__(self):
self.correct_groups = OrderedDict() # groups self.correct_groups = OrderedDict() # correct groups from xml
self.correct_positions = OrderedDict() # positions of comparing self.correct_positions = OrderedDict() # correct positions for comparing
self.user_groups = OrderedDict() self.user_groups = OrderedDict() # will be populated from user answer
self.user_positions = OrderedDict() self.user_positions = OrderedDict() # will be populated from user answer
# flag to check if user answer has more draggables than correct answer
self.incorrect = False self.incorrect = False
def grade(self): def grade(self):
''' ''' Grader user 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: If use_targets is True - checks if every draggable isplaced on proper
user_input, correct_answer: json. Format: target.
user_input: see module docstring If use_targets is False - checks if every draggable is placed on proper
coordinates within radius of forgiveness (default is 10).
correct_answer: Returns: bool.
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.
''' '''
if self.incorrect: if self.incorrect: # user answer has more draggables than correct answer
return False return False
# checks if we have same groups of draggables
if sorted(self.correct_groups.keys()) != sorted(self.user_groups.keys()): if sorted(self.correct_groups.keys()) != sorted(self.user_groups.keys()):
return False return False
# checks if for every groups draggables names are same
for groupname, draggable_ids in self.correct_groups.items(): for groupname, draggable_ids in self.correct_groups.items():
if sorted(draggable_ids) != sorted(self.user_groups[groupname]): if sorted(draggable_ids) != sorted(self.user_groups[groupname]):
return False return False
# from now self.correct_groups and self.user_groups are equal if # from now self.correct_groups and self.user_groups are equal if
# order is ignored # order is ignored
# Check fo every group that positions of every group element are equal # Checks in every group that user positions of every element are equal
# with positions # with correct positions for every rule
# 'denied' rule for group in self.correct_groups: # 'denied' rule
denied_positions = [item for g in self.correct_groups.keys() if not self.compare_positions(self.correct_positions[group].get(
for item in self.correct_positions[g].get('denied', [])] 'denied', []), self.user_positions[group]['user'], flag='denied'):
all_user_positions = [item for g in self.correct_groups.keys() return False
for item in self.user_positions[g]['user']]
if not self.compare_positions(denied_positions,
all_user_positions, flag='denied'):
return False
no_exact, no_allowed, no_anyof = False, False, False no_exact, no_allowed, no_anyof = False, False, False
# 'exact' rule
for groupname in self.correct_groups: for groupname in self.correct_groups: # 'exact' rule
if self.correct_positions[groupname].get('exact', []): if self.correct_positions[groupname].get('exact', []):
if not self.compare_positions( if not self.compare_positions(
self.correct_positions[groupname]['exact'], self.correct_positions[groupname]['exact'],
...@@ -165,8 +161,7 @@ class DragAndDrop(object): ...@@ -165,8 +161,7 @@ class DragAndDrop(object):
else: else:
no_exact = True no_exact = True
# 'allowed' rule for groupname in self.correct_groups: # 'allowed' rule
for groupname in self.correct_groups:
if self.correct_positions[groupname].get('allowed', []): if self.correct_positions[groupname].get('allowed', []):
if not self.compare_positions( if not self.compare_positions(
self.correct_positions[groupname]['allowed'], self.correct_positions[groupname]['allowed'],
...@@ -260,7 +255,17 @@ class DragAndDrop(object): ...@@ -260,7 +255,17 @@ class DragAndDrop(object):
def grade(user_input, correct_answer): def grade(user_input, correct_answer):
""" Support 2 interfaces""" """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]'}
Support 2 interfaces"""
if isinstance(correct_answer, dict): if isinstance(correct_answer, dict):
dnd = DragAndDrop() dnd = DragAndDrop()
else: else:
......
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