Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
E
edx-platform
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
edx
edx-platform
Commits
7ab13256
Commit
7ab13256
authored
Jan 02, 2013
by
Alexander Kryklia
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
extended grader
parent
744b7947
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
169 additions
and
33 deletions
+169
-33
common/lib/capa/capa/graders/draganddrop.py
+169
-33
No files found.
common/lib/capa/capa/graders/draganddrop.py
View file @
7ab13256
...
...
@@ -28,9 +28,88 @@ values are (x,y) coordinates of centers of dragged images.
"""
import
json
from
collections
import
OrderedDict
def
grade
(
user_input
,
correct_answer
):
class
PositionsCompare
(
list
):
"""Inputs are: "abc" - target
[10, 20] - list of integers
[[10,20], 200] list of list and integer
"""
def
__eq__
(
self
,
other
):
# Default lists behaviour is convers "abc" to ["a", "b", "c"].
# We will use that.
# import ipdb; ipdb.set_trace()
#check if self or other is not empty list (empty lists = false)
if
not
self
or
not
other
:
return
False
# check correct input types
if
(
not
isinstance
(
self
[
0
],
(
str
,
unicode
,
list
,
int
))
or
not
isinstance
(
other
[
0
],
(
str
,
unicode
,
list
,
int
))):
print
'Incorrect input type'
return
False
if
(
isinstance
(
self
[
0
],
(
list
,
int
))
and
isinstance
(
other
[
0
],
(
list
,
int
))):
print
'Numerical position compare'
return
self
.
coordinate_positions_compare
(
other
)
elif
(
isinstance
(
self
[
0
],
(
unicode
,
str
))
and
isinstance
(
other
[
0
],
(
unicode
,
str
))):
print
'Targets compare'
return
''
.
join
(
self
)
==
''
.
join
(
other
)
else
:
# we do not have ints or lists of lists or two string/unicode lists
# on both sides
print
type
(
self
[
0
]),
type
(
other
[
0
]),
"not correct"
return
False
def
__ne__
(
self
,
other
):
return
not
self
.
__eq__
(
other
)
def
coordinate_positions_compare
(
self
,
other
,
r
=
10
):
""" Checks if pos1 is equal to pos2 inside radius
of forgiveness (default 10 px).
Args:
self, other: [x, y] or [[x, y], r], where
r is radius of forgiveness;
x, y, r: int
Returns: bool.
"""
print
'I am called'
,
self
,
other
# get max radius of forgiveness
if
isinstance
(
self
[
0
],
list
):
# [(x, y), r] case
r
=
max
(
self
[
1
],
r
)
x1
,
y1
=
self
[
0
]
else
:
x1
,
y1
=
self
if
isinstance
(
other
[
0
],
list
):
# [(x, y), r] case
r
=
max
(
other
[
1
],
r
)
x2
,
y2
=
other
[
0
]
else
:
x2
,
y2
=
other
if
(
x2
-
x1
)
**
2
+
(
y2
-
y1
)
**
2
>
r
*
r
:
return
False
return
True
class
DragAndDrop
(
object
):
def
__init__
(
self
):
self
.
correct_groups
=
OrderedDict
()
# groups
self
.
correct_positions
=
OrderedDict
()
# positions of comparing
self
.
user_groups
=
OrderedDict
()
self
.
user_positions
=
OrderedDict
()
def
grade
(
self
):
'''
Grade drag and drop problem.
If use_targets is True - checks if image placed on proper target.
...
...
@@ -51,51 +130,108 @@ def grade(user_input, correct_answer):
Returns:
True or False.
'''
if
sorted
(
self
.
correct_groups
.
keys
())
!=
sorted
(
self
.
user_groups
.
keys
()):
return
False
user_answer
=
json
.
loads
(
user_input
)
if
len
(
correct_answer
.
keys
())
!=
len
(
user_answer
[
'draggables'
]):
for
groupname
,
draggable_ids
in
self
.
correct_groups
.
items
():
if
sorted
(
draggable_ids
)
!=
sorted
(
self
.
user_groups
[
groupname
]):
return
False
def
is_equal
(
user_answer
,
correct_answer
):
""" Checks if user_answer is equal to correct_answer inside radius
of forgiveness (default 10 px).
# from now self.groups and self.user_groups are equal
assert
self
.
correct_groups
==
self
.
user_groups
Args:
user_answer: [x, y] - list of floats;
correct_answer: [x, y] or [[x, y], r], where
r is radius of forgiveness;
# Check fo every group that positions of every group element are equal
# with positions
Returns: bool.
"""
if
not
isinstance
(
correct_answer
,
list
)
or
isinstance
(
user_answer
,
list
):
# 'denied' rule
# import ipdb; ipdb.set_trace()
denied_positions
=
[
self
.
correct_positions
[
g
]
.
get
(
'denied'
,
[])
for
g
in
self
.
correct_groups
.
keys
()]
all_user_positions
=
[
self
.
user_positions
[
g
][
'user'
]
for
g
in
self
.
correct_groups
.
keys
()]
if
not
self
.
compare_positions
(
denied_positions
,
all_user_positions
,
flag
=
'denied'
):
return
False
r
=
10
if
isinstance
(
correct_answer
[
0
],
list
):
# [(x, y), r] case
r
=
correct_answer
[
1
]
corr_x
=
correct_answer
[
0
][
0
]
corr_y
=
correct_answer
[
0
][
1
]
else
:
# (x, y) case
corr_x
=
correct_answer
[
0
]
corr_y
=
correct_answer
[
1
]
if
((
user_answer
[
0
]
-
corr_x
)
**
2
+
(
user_answer
[
1
]
-
corr_y
)
**
2
)
>
r
*
r
:
no_exact
,
no_allowed
=
False
,
False
# 'exact' rule
for
groupname
in
self
.
correct_groups
:
if
self
.
correct_positions
[
groupname
]
.
get
(
'exact'
,
[]):
if
not
self
.
compare_positions
(
self
.
correct_positions
[
groupname
][
'exact'
],
self
.
user_positions
[
groupname
][
'user'
],
flag
=
'exact'
):
return
False
else
:
no_exact
=
True
# 'allowed' rule
for
groupname
in
self
.
correct_groups
:
if
self
.
correct_positions
[
groupname
]
.
get
(
'allowed'
,
[]):
if
not
self
.
compare_positions
(
self
.
correct_positions
[
groupname
][
'allowed'
],
self
.
user_positions
[
groupname
][
'user'
],
flag
=
'allowed'
):
return
False
else
:
no_allowed
=
True
if
no_allowed
and
no_exact
:
return
False
return
True
if
user_answer
[
"use_targets"
]:
is_equal
=
lambda
user
,
correct
:
user
==
correct
if
(
isinstance
(
user
,
unicode
)
and
isinstance
(
correct
,
str
))
else
False
def
compare_positions
(
self
,
list1
,
list2
,
flag
):
# import ipdb; ipdb.set_trace()
if
flag
==
'denied'
:
for
el1
in
list1
:
for
el2
in
list2
:
if
PositionsCompare
(
el1
)
==
PositionsCompare
(
el2
):
return
False
for
draggable
in
user_answer
[
'draggables'
]:
user_img_location
=
draggable
.
values
()[
0
]
corr_img_location
=
correct_answer
.
get
(
draggable
.
keys
()[
0
],
None
)
if
not
corr_img_location
:
if
flag
==
'allowed'
:
for
el1
,
el2
in
zip
(
sorted
(
list1
),
sorted
(
list2
)):
if
PositionsCompare
(
el1
)
!=
PositionsCompare
(
el2
):
return
False
if
not
is_equal
(
user_img_location
,
corr_img_location
):
if
flag
==
'exact'
:
for
el1
,
el2
in
zip
(
list1
,
list2
):
if
PositionsCompare
(
el1
)
!=
PositionsCompare
(
el2
):
return
False
return
True
def
populate
(
self
,
correct_answer
,
user_answer
):
""" """
if
isinstance
(
correct_answer
,
dict
):
for
key
,
value
in
correct_answer
.
items
():
self
.
correct_groups
[
key
]
=
[
key
]
self
.
correct_positions
[
key
]
=
{
'exact'
:
[
value
]}
user_answer
=
json
.
loads
(
user_answer
)
self
.
use_targets
=
user_answer
.
get
(
'use_targets'
)
# create identical data structures
# user groups must mirror correct_groups
# and positions must reflect order in groups
for
groupname
in
self
.
correct_groups
:
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}
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
(
draggable_dict
[
draggable_name
])
# import ipdb; ipdb.set_trace()
def
grade
(
user_input
,
correct_answer
):
""" Support 2 interfaces"""
if
isinstance
(
correct_answer
,
dict
):
dnd
=
DragAndDrop
()
dnd
.
populate
(
correct_answer
=
correct_answer
,
user_answer
=
user_input
)
return
dnd
.
grade
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment