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
39d666cd
Commit
39d666cd
authored
Mar 29, 2013
by
Brian Wilson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
modify AssignmentFormatGrader to act like a SingleSectionGrader on single sections
parent
252f9364
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
175 additions
and
125 deletions
+175
-125
common/lib/xmodule/xmodule/graders.py
+69
-37
common/lib/xmodule/xmodule/tests/test_graders.py
+106
-88
No files found.
common/lib/xmodule/xmodule/graders.py
View file @
39d666cd
...
@@ -45,8 +45,9 @@ def invalid_args(func, argdict):
...
@@ -45,8 +45,9 @@ def invalid_args(func, argdict):
Given a function and a dictionary of arguments, returns a set of arguments
Given a function and a dictionary of arguments, returns a set of arguments
from argdict that aren't accepted by func
from argdict that aren't accepted by func
"""
"""
args
,
varargs
,
keywords
,
defaults
=
inspect
.
getargspec
(
func
)
args
,
_
,
keywords
,
_
=
inspect
.
getargspec
(
func
)
if
keywords
:
return
set
()
# All accepted
if
keywords
:
return
set
()
# All accepted
return
set
(
argdict
)
-
set
(
args
)
return
set
(
argdict
)
-
set
(
args
)
...
@@ -119,7 +120,7 @@ class CourseGrader(object):
...
@@ -119,7 +120,7 @@ class CourseGrader(object):
that has the matching section format.
that has the matching section format.
The grader outputs a dictionary with the following keys:
The grader outputs a dictionary with the following keys:
- percent: Contai
sn
a float value, which is the final percentage score for the student.
- percent: Contai
ns
a float value, which is the final percentage score for the student.
- section_breakdown: This is a list of dictionaries which provide details on sections
- section_breakdown: This is a list of dictionaries which provide details on sections
that were graded. These are used for display in a graph or chart. The format for a
that were graded. These are used for display in a graph or chart. The format for a
section_breakdown dictionary is explained below.
section_breakdown dictionary is explained below.
...
@@ -150,6 +151,7 @@ class CourseGrader(object):
...
@@ -150,6 +151,7 @@ class CourseGrader(object):
@abc.abstractmethod
@abc.abstractmethod
def
grade
(
self
,
grade_sheet
,
generate_random_scores
=
False
):
def
grade
(
self
,
grade_sheet
,
generate_random_scores
=
False
):
'''Given a grade sheet, return a dict containing grading information'''
raise
NotImplementedError
raise
NotImplementedError
...
@@ -158,7 +160,10 @@ class WeightedSubsectionsGrader(CourseGrader):
...
@@ -158,7 +160,10 @@ class WeightedSubsectionsGrader(CourseGrader):
This grader takes a list of tuples containing (grader, category_name, weight) and computes
This grader takes a list of tuples containing (grader, category_name, weight) and computes
a final grade by totalling the contribution of each sub grader and multiplying it by the
a final grade by totalling the contribution of each sub grader and multiplying it by the
given weight. For example, the sections may be
given weight. For example, the sections may be
[ (homeworkGrader, "Homework", 0.15), (labGrader, "Labs", 0.15), (midtermGrader, "Midterm", 0.30), (finalGrader, "Final", 0.40) ]
[ (homeworkGrader, "Homework", 0.15), (labGrader, "Labs", 0.15), (midtermGrader, "Midterm", 0.30),
(finalGrader, "Final", 0.40) ]
All items in section_breakdown for each subgrader will be combined. A grade_breakdown will be
All items in section_breakdown for each subgrader will be combined. A grade_breakdown will be
composed using the score from each grader.
composed using the score from each grader.
...
@@ -177,12 +182,12 @@ class WeightedSubsectionsGrader(CourseGrader):
...
@@ -177,12 +182,12 @@ class WeightedSubsectionsGrader(CourseGrader):
for
subgrader
,
category
,
weight
in
self
.
sections
:
for
subgrader
,
category
,
weight
in
self
.
sections
:
subgrade_result
=
subgrader
.
grade
(
grade_sheet
,
generate_random_scores
)
subgrade_result
=
subgrader
.
grade
(
grade_sheet
,
generate_random_scores
)
weighted
P
ercent
=
subgrade_result
[
'percent'
]
*
weight
weighted
_p
ercent
=
subgrade_result
[
'percent'
]
*
weight
section_detail
=
"{0} = {1:.1
%
} of a possible {2:.0
%
}"
.
format
(
category
,
weighted
P
ercent
,
weight
)
section_detail
=
"{0} = {1:.1
%
} of a possible {2:.0
%
}"
.
format
(
category
,
weighted
_p
ercent
,
weight
)
total_percent
+=
weighted
P
ercent
total_percent
+=
weighted
_p
ercent
section_breakdown
+=
subgrade_result
[
'section_breakdown'
]
section_breakdown
+=
subgrade_result
[
'section_breakdown'
]
grade_breakdown
.
append
({
'percent'
:
weighted
P
ercent
,
'detail'
:
section_detail
,
'category'
:
category
})
grade_breakdown
.
append
({
'percent'
:
weighted
_p
ercent
,
'detail'
:
section_detail
,
'category'
:
category
})
return
{
'percent'
:
total_percent
,
return
{
'percent'
:
total_percent
,
'section_breakdown'
:
section_breakdown
,
'section_breakdown'
:
section_breakdown
,
...
@@ -203,32 +208,33 @@ class SingleSectionGrader(CourseGrader):
...
@@ -203,32 +208,33 @@ class SingleSectionGrader(CourseGrader):
self
.
category
=
category
or
name
self
.
category
=
category
or
name
def
grade
(
self
,
grade_sheet
,
generate_random_scores
=
False
):
def
grade
(
self
,
grade_sheet
,
generate_random_scores
=
False
):
found
S
core
=
None
found
_s
core
=
None
if
self
.
type
in
grade_sheet
:
if
self
.
type
in
grade_sheet
:
for
score
in
grade_sheet
[
self
.
type
]:
for
score
in
grade_sheet
[
self
.
type
]:
if
score
.
section
==
self
.
name
:
if
score
.
section
==
self
.
name
:
found
S
core
=
score
found
_s
core
=
score
break
break
if
found
S
core
or
generate_random_scores
:
if
found
_s
core
or
generate_random_scores
:
if
generate_random_scores
:
# for debugging!
if
generate_random_scores
:
# for debugging!
earned
=
random
.
randint
(
2
,
15
)
earned
=
random
.
randint
(
2
,
15
)
possible
=
random
.
randint
(
earned
,
15
)
possible
=
random
.
randint
(
earned
,
15
)
else
:
# We found the score
else
:
# We found the score
earned
=
found
S
core
.
earned
earned
=
found
_s
core
.
earned
possible
=
found
S
core
.
possible
possible
=
found
_s
core
.
possible
percent
=
earned
/
float
(
possible
)
percent
=
earned
/
float
(
possible
)
detail
=
"{name} - {percent:.0
%
} ({earned:.3n}/{possible:.3n})"
.
format
(
name
=
self
.
name
,
detail
=
"{name} - {percent:.0
%
} ({earned:.3n}/{possible:.3n})"
.
format
(
name
=
self
.
name
,
percent
=
percent
,
percent
=
percent
,
earned
=
float
(
earned
),
earned
=
float
(
earned
),
possible
=
float
(
possible
))
possible
=
float
(
possible
))
else
:
else
:
percent
=
0.0
percent
=
0.0
detail
=
"{name} - 0
%
(?/?)"
.
format
(
name
=
self
.
name
)
detail
=
"{name} - 0
%
(?/?)"
.
format
(
name
=
self
.
name
)
breakdown
=
[{
'percent'
:
percent
,
'label'
:
self
.
short_label
,
'detail'
:
detail
,
'category'
:
self
.
category
,
'prominent'
:
True
}]
breakdown
=
[{
'percent'
:
percent
,
'label'
:
self
.
short_label
,
'detail'
:
detail
,
'category'
:
self
.
category
,
'prominent'
:
True
}]
return
{
'percent'
:
percent
,
return
{
'percent'
:
percent
,
'section_breakdown'
:
breakdown
,
'section_breakdown'
:
breakdown
,
...
@@ -250,6 +256,13 @@ class AssignmentFormatGrader(CourseGrader):
...
@@ -250,6 +256,13 @@ class AssignmentFormatGrader(CourseGrader):
show_only_average is to suppress the display of each assignment in this grader and instead
show_only_average is to suppress the display of each assignment in this grader and instead
only show the total score of this grader in the breakdown.
only show the total score of this grader in the breakdown.
hide_average is to suppress the display of the total score in this grader and instead
only show each assignment in this grader in the breakdown.
If there is only a single assignment in this grader, then it acts like a SingleSectionGrader
and returns only one entry for the grader. Since the assignment and the total are the same,
the total is returned but is not labeled as an average.
category should be presentable to the user, but may not appear. When the grade breakdown is
category should be presentable to the user, but may not appear. When the grade breakdown is
displayed, scores from the same category will be similar (for example, by color).
displayed, scores from the same category will be similar (for example, by color).
...
@@ -263,7 +276,8 @@ class AssignmentFormatGrader(CourseGrader):
...
@@ -263,7 +276,8 @@ class AssignmentFormatGrader(CourseGrader):
min_count = 2 would produce the labels "Assignment 3", "Assignment 4"
min_count = 2 would produce the labels "Assignment 3", "Assignment 4"
"""
"""
def
__init__
(
self
,
type
,
min_count
,
drop_count
,
category
=
None
,
section_type
=
None
,
short_label
=
None
,
show_only_average
=
False
,
hide_average
=
False
,
starting_index
=
1
):
def
__init__
(
self
,
type
,
min_count
,
drop_count
,
category
=
None
,
section_type
=
None
,
short_label
=
None
,
show_only_average
=
False
,
hide_average
=
False
,
starting_index
=
1
):
self
.
type
=
type
self
.
type
=
type
self
.
min_count
=
min_count
self
.
min_count
=
min_count
self
.
drop_count
=
drop_count
self
.
drop_count
=
drop_count
...
@@ -275,7 +289,8 @@ class AssignmentFormatGrader(CourseGrader):
...
@@ -275,7 +289,8 @@ class AssignmentFormatGrader(CourseGrader):
self
.
hide_average
=
hide_average
self
.
hide_average
=
hide_average
def
grade
(
self
,
grade_sheet
,
generate_random_scores
=
False
):
def
grade
(
self
,
grade_sheet
,
generate_random_scores
=
False
):
def
totalWithDrops
(
breakdown
,
drop_count
):
def
total_with_drops
(
breakdown
,
drop_count
):
'''calculates total score for a section while dropping lowest scores'''
#create an array of tuples with (index, mark), sorted by mark['percent'] descending
#create an array of tuples with (index, mark), sorted by mark['percent'] descending
sorted_breakdown
=
sorted
(
enumerate
(
breakdown
),
key
=
lambda
x
:
-
x
[
1
][
'percent'
])
sorted_breakdown
=
sorted
(
enumerate
(
breakdown
),
key
=
lambda
x
:
-
x
[
1
][
'percent'
])
# A list of the indices of the dropped scores
# A list of the indices of the dropped scores
...
@@ -308,33 +323,50 @@ class AssignmentFormatGrader(CourseGrader):
...
@@ -308,33 +323,50 @@ class AssignmentFormatGrader(CourseGrader):
section_name
=
scores
[
i
]
.
section
section_name
=
scores
[
i
]
.
section
percentage
=
earned
/
float
(
possible
)
percentage
=
earned
/
float
(
possible
)
summary
=
"{section_type} {index} - {name} - {percent:.0
%
} ({earned:.3n}/{possible:.3n})"
.
format
(
index
=
i
+
self
.
starting_index
,
summary_format
=
"{section_type} {index} - {name} - {percent:.0
%
} ({earned:.3n}/{possible:.3n})"
section_type
=
self
.
section_type
,
summary
=
summary_format
.
format
(
index
=
i
+
self
.
starting_index
,
name
=
section_name
,
section_type
=
self
.
section_type
,
percent
=
percentage
,
name
=
section_name
,
earned
=
float
(
earned
),
percent
=
percentage
,
possible
=
float
(
possible
))
earned
=
float
(
earned
),
possible
=
float
(
possible
))
else
:
else
:
percentage
=
0
percentage
=
0
summary
=
"{section_type} {index} Unreleased - 0
%
(?/?)"
.
format
(
index
=
i
+
self
.
starting_index
,
section_type
=
self
.
section_type
)
summary
=
"{section_type} {index} Unreleased - 0
%
(?/?)"
.
format
(
index
=
i
+
self
.
starting_index
,
section_type
=
self
.
section_type
)
short_label
=
"{short_label} {index:02d}"
.
format
(
index
=
i
+
self
.
starting_index
,
short_label
=
self
.
short_label
)
short_label
=
"{short_label} {index:02d}"
.
format
(
index
=
i
+
self
.
starting_index
,
short_label
=
self
.
short_label
)
breakdown
.
append
({
'percent'
:
percentage
,
'label'
:
short_label
,
'detail'
:
summary
,
'category'
:
self
.
category
})
breakdown
.
append
({
'percent'
:
percentage
,
'label'
:
short_label
,
'detail'
:
summary
,
'category'
:
self
.
category
})
total_percent
,
dropped_indices
=
total
WithD
rops
(
breakdown
,
self
.
drop_count
)
total_percent
,
dropped_indices
=
total
_with_d
rops
(
breakdown
,
self
.
drop_count
)
for
dropped_index
in
dropped_indices
:
for
dropped_index
in
dropped_indices
:
breakdown
[
dropped_index
][
'mark'
]
=
{
'detail'
:
"The lowest {drop_count} {section_type} scores are dropped."
.
format
(
drop_count
=
self
.
drop_count
,
section_type
=
self
.
section_type
)}
breakdown
[
dropped_index
][
'mark'
]
=
{
'detail'
:
"The lowest {drop_count} {section_type} scores are dropped."
.
format
(
drop_count
=
self
.
drop_count
,
section_type
=
self
.
section_type
)}
total_detail
=
"{section_type} Average = {percent:.0
%
}"
.
format
(
percent
=
total_percent
,
section_type
=
self
.
section_type
)
total_label
=
"{short_label} Avg"
.
format
(
short_label
=
self
.
short_label
)
if
len
(
breakdown
)
==
1
:
# if there is only one entry in a section, suppress the existing individual entry and the average,
# and just display a single entry for the section. That way it acts automatically like a
# SingleSectionGrader.
total_detail
=
"{section_type} = {percent:.0
%
}"
.
format
(
percent
=
total_percent
,
section_type
=
self
.
section_type
)
total_label
=
"{short_label}"
.
format
(
short_label
=
self
.
short_label
)
breakdown
=
[{
'percent'
:
total_percent
,
'label'
:
total_label
,
'detail'
:
total_detail
,
'category'
:
self
.
category
,
'prominent'
:
True
},
]
else
:
total_detail
=
"{section_type} Average = {percent:.0
%
}"
.
format
(
percent
=
total_percent
,
section_type
=
self
.
section_type
)
total_label
=
"{short_label} Avg"
.
format
(
short_label
=
self
.
short_label
)
if
self
.
show_only_average
:
if
self
.
show_only_average
:
breakdown
=
[]
breakdown
=
[]
if
not
self
.
hide_average
:
if
not
self
.
hide_average
:
breakdown
.
append
({
'percent'
:
total_percent
,
'label'
:
total_label
,
'detail'
:
total_detail
,
'category'
:
self
.
category
,
'prominent'
:
True
})
breakdown
.
append
({
'percent'
:
total_percent
,
'label'
:
total_label
,
'detail'
:
total_detail
,
'category'
:
self
.
category
,
'prominent'
:
True
})
return
{
'percent'
:
total_percent
,
return
{
'percent'
:
total_percent
,
'section_breakdown'
:
breakdown
,
'section_breakdown'
:
breakdown
,
...
...
common/lib/xmodule/xmodule/tests/test_graders.py
View file @
39d666cd
...
@@ -6,32 +6,34 @@ from xmodule.graders import Score, aggregate_scores
...
@@ -6,32 +6,34 @@ from xmodule.graders import Score, aggregate_scores
class
GradesheetTest
(
unittest
.
TestCase
):
class
GradesheetTest
(
unittest
.
TestCase
):
'''Tests the aggregate_scores method'''
def
test_weighted_grading
(
self
):
def
test_weighted_grading
(
self
):
scores
=
[]
scores
=
[]
Score
.
__sub__
=
lambda
me
,
other
:
(
me
.
earned
-
other
.
earned
)
+
(
me
.
possible
-
other
.
possible
)
Score
.
__sub__
=
lambda
me
,
other
:
(
me
.
earned
-
other
.
earned
)
+
(
me
.
possible
-
other
.
possible
)
all
,
graded
=
aggregate_scores
(
scores
)
all
_total
,
graded_total
=
aggregate_scores
(
scores
)
self
.
assertEqual
(
all
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
False
,
section
=
"summary"
))
self
.
assertEqual
(
all
_total
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
False
,
section
=
"summary"
))
self
.
assertEqual
(
graded
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
True
,
section
=
"summary"
))
self
.
assertEqual
(
graded
_total
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
True
,
section
=
"summary"
))
scores
.
append
(
Score
(
earned
=
0
,
possible
=
5
,
graded
=
False
,
section
=
"summary"
))
scores
.
append
(
Score
(
earned
=
0
,
possible
=
5
,
graded
=
False
,
section
=
"summary"
))
all
,
graded
=
aggregate_scores
(
scores
)
all
_total
,
graded_total
=
aggregate_scores
(
scores
)
self
.
assertEqual
(
all
,
Score
(
earned
=
0
,
possible
=
5
,
graded
=
False
,
section
=
"summary"
))
self
.
assertEqual
(
all
_total
,
Score
(
earned
=
0
,
possible
=
5
,
graded
=
False
,
section
=
"summary"
))
self
.
assertEqual
(
graded
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
True
,
section
=
"summary"
))
self
.
assertEqual
(
graded
_total
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
True
,
section
=
"summary"
))
scores
.
append
(
Score
(
earned
=
3
,
possible
=
5
,
graded
=
True
,
section
=
"summary"
))
scores
.
append
(
Score
(
earned
=
3
,
possible
=
5
,
graded
=
True
,
section
=
"summary"
))
all
,
graded
=
aggregate_scores
(
scores
)
all
_total
,
graded_total
=
aggregate_scores
(
scores
)
self
.
assertAlmostEqual
(
all
,
Score
(
earned
=
3
,
possible
=
10
,
graded
=
False
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
all
_total
,
Score
(
earned
=
3
,
possible
=
10
,
graded
=
False
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
graded
,
Score
(
earned
=
3
,
possible
=
5
,
graded
=
True
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
graded
_total
,
Score
(
earned
=
3
,
possible
=
5
,
graded
=
True
,
section
=
"summary"
))
scores
.
append
(
Score
(
earned
=
2
,
possible
=
5
,
graded
=
True
,
section
=
"summary"
))
scores
.
append
(
Score
(
earned
=
2
,
possible
=
5
,
graded
=
True
,
section
=
"summary"
))
all
,
graded
=
aggregate_scores
(
scores
)
all
_total
,
graded_total
=
aggregate_scores
(
scores
)
self
.
assertAlmostEqual
(
all
,
Score
(
earned
=
5
,
possible
=
15
,
graded
=
False
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
all
_total
,
Score
(
earned
=
5
,
possible
=
15
,
graded
=
False
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
graded
,
Score
(
earned
=
5
,
possible
=
10
,
graded
=
True
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
graded
_total
,
Score
(
earned
=
5
,
possible
=
10
,
graded
=
True
,
section
=
"summary"
))
class
GraderTest
(
unittest
.
TestCase
):
class
GraderTest
(
unittest
.
TestCase
):
'''Tests grader implementations'''
empty_gradesheet
=
{
empty_gradesheet
=
{
}
}
...
@@ -44,136 +46,152 @@ class GraderTest(unittest.TestCase):
...
@@ -44,136 +46,152 @@ class GraderTest(unittest.TestCase):
test_gradesheet
=
{
test_gradesheet
=
{
'Homework'
:
[
Score
(
earned
=
2
,
possible
=
20.0
,
graded
=
True
,
section
=
'hw1'
),
'Homework'
:
[
Score
(
earned
=
2
,
possible
=
20.0
,
graded
=
True
,
section
=
'hw1'
),
Score
(
earned
=
16
,
possible
=
16.0
,
graded
=
True
,
section
=
'hw2'
)],
Score
(
earned
=
16
,
possible
=
16.0
,
graded
=
True
,
section
=
'hw2'
)],
#
The dropped scores should be from the assignments that don't exist yet
#
The dropped scores should be from the assignments that don't exist yet
'Lab'
:
[
Score
(
earned
=
1
,
possible
=
2.0
,
graded
=
True
,
section
=
'lab1'
),
# Dropped
'Lab'
:
[
Score
(
earned
=
1
,
possible
=
2.0
,
graded
=
True
,
section
=
'lab1'
),
# Dropped
Score
(
earned
=
1
,
possible
=
1.0
,
graded
=
True
,
section
=
'lab2'
),
Score
(
earned
=
1
,
possible
=
1.0
,
graded
=
True
,
section
=
'lab2'
),
Score
(
earned
=
1
,
possible
=
1.0
,
graded
=
True
,
section
=
'lab3'
),
Score
(
earned
=
1
,
possible
=
1.0
,
graded
=
True
,
section
=
'lab3'
),
Score
(
earned
=
5
,
possible
=
25.0
,
graded
=
True
,
section
=
'lab4'
),
# Dropped
Score
(
earned
=
5
,
possible
=
25.0
,
graded
=
True
,
section
=
'lab4'
),
# Dropped
Score
(
earned
=
3
,
possible
=
4.0
,
graded
=
True
,
section
=
'lab5'
),
# Dropped
Score
(
earned
=
3
,
possible
=
4.0
,
graded
=
True
,
section
=
'lab5'
),
# Dropped
Score
(
earned
=
6
,
possible
=
7.0
,
graded
=
True
,
section
=
'lab6'
),
Score
(
earned
=
6
,
possible
=
7.0
,
graded
=
True
,
section
=
'lab6'
),
Score
(
earned
=
5
,
possible
=
6.0
,
graded
=
True
,
section
=
'lab7'
)],
Score
(
earned
=
5
,
possible
=
6.0
,
graded
=
True
,
section
=
'lab7'
)],
'Midterm'
:
[
Score
(
earned
=
50.5
,
possible
=
100
,
graded
=
True
,
section
=
"Midterm Exam"
),
],
'Midterm'
:
[
Score
(
earned
=
50.5
,
possible
=
100
,
graded
=
True
,
section
=
"Midterm Exam"
),
],
}
}
def
test_
SingleSectionG
rader
(
self
):
def
test_
single_section_g
rader
(
self
):
midterm
G
rader
=
graders
.
SingleSectionGrader
(
"Midterm"
,
"Midterm Exam"
)
midterm
_g
rader
=
graders
.
SingleSectionGrader
(
"Midterm"
,
"Midterm Exam"
)
lab4
G
rader
=
graders
.
SingleSectionGrader
(
"Lab"
,
"lab4"
)
lab4
_g
rader
=
graders
.
SingleSectionGrader
(
"Lab"
,
"lab4"
)
bad
LabG
rader
=
graders
.
SingleSectionGrader
(
"Lab"
,
"lab42"
)
bad
_lab_g
rader
=
graders
.
SingleSectionGrader
(
"Lab"
,
"lab42"
)
for
graded
in
[
midterm
G
rader
.
grade
(
self
.
empty_gradesheet
),
for
graded
in
[
midterm
_g
rader
.
grade
(
self
.
empty_gradesheet
),
midtermG
rader
.
grade
(
self
.
incomplete_gradesheet
),
midterm_g
rader
.
grade
(
self
.
incomplete_gradesheet
),
badLabG
rader
.
grade
(
self
.
test_gradesheet
)]:
bad_lab_g
rader
.
grade
(
self
.
test_gradesheet
)]:
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
1
)
self
.
assertEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertEqual
(
graded
[
'percent'
],
0.0
)
graded
=
midterm
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
midterm
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.505
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.505
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
1
)
graded
=
lab4
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
lab4
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.2
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.2
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
1
)
def
test_
AssignmentFormatG
rader
(
self
):
def
test_
assignment_format_g
rader
(
self
):
homework
G
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
homework
_g
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
no
DropG
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
0
)
no
_drop_g
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
0
)
#Even though the minimum number is 3, this should grade correctly when 7 assignments are found
#
Even though the minimum number is 3, this should grade correctly when 7 assignments are found
overflow
G
rader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
3
,
2
)
overflow
_g
rader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
3
,
2
)
lab
G
rader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
7
,
3
)
lab
_g
rader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
7
,
3
)
#Test the grading of an empty gradesheet
#
Test the grading of an empty gradesheet
for
graded
in
[
homework
G
rader
.
grade
(
self
.
empty_gradesheet
),
for
graded
in
[
homework
_g
rader
.
grade
(
self
.
empty_gradesheet
),
noDropG
rader
.
grade
(
self
.
empty_gradesheet
),
no_drop_g
rader
.
grade
(
self
.
empty_gradesheet
),
homeworkG
rader
.
grade
(
self
.
incomplete_gradesheet
),
homework_g
rader
.
grade
(
self
.
incomplete_gradesheet
),
noDropG
rader
.
grade
(
self
.
incomplete_gradesheet
)]:
no_drop_g
rader
.
grade
(
self
.
incomplete_gradesheet
)]:
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
#Make sure the breakdown includes 12 sections, plus one summary
#
Make sure the breakdown includes 12 sections, plus one summary
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
graded
=
homework
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
homework
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.11
)
# 100% + 10% / 10 assignments
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.11
)
# 100% + 10% / 10 assignments
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
graded
=
no
DropG
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
no
_drop_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0916666666666666
)
# 100% + 10% / 12 assignments
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0916666666666666
)
# 100% + 10% / 12 assignments
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
graded
=
overflow
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
overflow
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.8880952380952382
)
# 100% + 10% / 5 assignments
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.8880952380952382
)
# 100% + 10% / 5 assignments
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
7
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
7
+
1
)
graded
=
lab
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
lab
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.9226190476190477
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.9226190476190477
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
7
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
7
+
1
)
def
test_WeightedSubsectionsGrader
(
self
):
def
test_assignment_format_grader_on_single_section_entry
(
self
):
#First, a few sub graders
midterm_grader
=
graders
.
AssignmentFormatGrader
(
"Midterm"
,
1
,
0
)
homeworkGrader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
# Test the grading on a section with one item:
labGrader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
7
,
3
)
for
graded
in
[
midterm_grader
.
grade
(
self
.
empty_gradesheet
),
midtermGrader
=
graders
.
SingleSectionGrader
(
"Midterm"
,
"Midterm Exam"
)
midterm_grader
.
grade
(
self
.
incomplete_gradesheet
)]:
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
# Make sure the breakdown includes just the one summary
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
0
+
1
)
self
.
assertEqual
(
graded
[
'section_breakdown'
][
0
][
'label'
],
'Midterm'
)
graded
=
midterm_grader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.505
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
0
+
1
)
def
test_weighted_subsections_grader
(
self
):
# First, a few sub graders
homework_grader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
lab_grader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
7
,
3
)
# phasing out the use of SingleSectionGraders, and instead using AssignmentFormatGraders that
# will act like SingleSectionGraders on single sections.
midterm_grader
=
graders
.
AssignmentFormatGrader
(
"Midterm"
,
1
,
0
)
weighted
Grader
=
graders
.
WeightedSubsectionsGrader
([(
homeworkGrader
,
homeworkG
rader
.
category
,
0.25
),
weighted
_grader
=
graders
.
WeightedSubsectionsGrader
([(
homework_grader
,
homework_g
rader
.
category
,
0.25
),
(
labGrader
,
labG
rader
.
category
,
0.25
),
(
lab_grader
,
lab_g
rader
.
category
,
0.25
),
(
midtermGrader
,
midtermG
rader
.
category
,
0.5
)])
(
midterm_grader
,
midterm_g
rader
.
category
,
0.5
)])
over
OneWeightsGrader
=
graders
.
WeightedSubsectionsGrader
([(
homeworkGrader
,
homeworkG
rader
.
category
,
0.5
),
over
_one_weights_grader
=
graders
.
WeightedSubsectionsGrader
([(
homework_grader
,
homework_g
rader
.
category
,
0.5
),
(
labGrader
,
labG
rader
.
category
,
0.5
),
(
lab_grader
,
lab_g
rader
.
category
,
0.5
),
(
midtermGrader
,
midtermG
rader
.
category
,
0.5
)])
(
midterm_grader
,
midterm_g
rader
.
category
,
0.5
)])
#The midterm should have all weight on this one
#
The midterm should have all weight on this one
zero
WeightsGrader
=
graders
.
WeightedSubsectionsGrader
([(
homeworkGrader
,
homeworkG
rader
.
category
,
0.0
),
zero
_weights_grader
=
graders
.
WeightedSubsectionsGrader
([(
homework_grader
,
homework_g
rader
.
category
,
0.0
),
(
labGrader
,
labG
rader
.
category
,
0.0
),
(
lab_grader
,
lab_g
rader
.
category
,
0.0
),
(
midtermGrader
,
midtermG
rader
.
category
,
0.5
)])
(
midterm_grader
,
midterm_g
rader
.
category
,
0.5
)])
#This should always have a final percent of zero
#
This should always have a final percent of zero
all
ZeroWeightsGrader
=
graders
.
WeightedSubsectionsGrader
([(
homeworkGrader
,
homeworkG
rader
.
category
,
0.0
),
all
_zero_weights_grader
=
graders
.
WeightedSubsectionsGrader
([(
homework_grader
,
homework_g
rader
.
category
,
0.0
),
(
labGrader
,
labG
rader
.
category
,
0.0
),
(
lab_grader
,
lab_g
rader
.
category
,
0.0
),
(
midtermGrader
,
midtermG
rader
.
category
,
0.0
)])
(
midterm_grader
,
midterm_g
rader
.
category
,
0.0
)])
empty
G
rader
=
graders
.
WeightedSubsectionsGrader
([])
empty
_g
rader
=
graders
.
WeightedSubsectionsGrader
([])
graded
=
weighted
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
weighted
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.5106547619047619
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.5106547619047619
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
graded
=
over
OneWeightsG
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
over
_one_weights_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.7688095238095238
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.7688095238095238
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
graded
=
zero
WeightsG
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
zero
_weights_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.2525
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.2525
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
graded
=
all
ZeroWeightsG
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
all
_zero_weights_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
for
graded
in
[
weighted
G
rader
.
grade
(
self
.
empty_gradesheet
),
for
graded
in
[
weighted
_g
rader
.
grade
(
self
.
empty_gradesheet
),
weightedG
rader
.
grade
(
self
.
incomplete_gradesheet
),
weighted_g
rader
.
grade
(
self
.
incomplete_gradesheet
),
zeroWeightsG
rader
.
grade
(
self
.
empty_gradesheet
),
zero_weights_g
rader
.
grade
(
self
.
empty_gradesheet
),
allZeroWeightsG
rader
.
grade
(
self
.
empty_gradesheet
)]:
all_zero_weights_g
rader
.
grade
(
self
.
empty_gradesheet
)]:
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
graded
=
empty
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
empty
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
0
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
0
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
0
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
0
)
def
test_grader
FromC
onf
(
self
):
def
test_grader
_from_c
onf
(
self
):
#Confs always produce a graders.WeightedSubsectionsGrader, so we test this by repeating the test
#
Confs always produce a graders.WeightedSubsectionsGrader, so we test this by repeating the test
#in test_graders.WeightedSubsectionsGrader, but generate the graders with confs.
#
in test_graders.WeightedSubsectionsGrader, but generate the graders with confs.
weighted
G
rader
=
graders
.
grader_from_conf
([
weighted
_g
rader
=
graders
.
grader_from_conf
([
{
{
'type'
:
"Homework"
,
'type'
:
"Homework"
,
'min_count'
:
12
,
'min_count'
:
12
,
...
@@ -196,25 +214,25 @@ class GraderTest(unittest.TestCase):
...
@@ -196,25 +214,25 @@ class GraderTest(unittest.TestCase):
},
},
])
])
empty
G
rader
=
graders
.
grader_from_conf
([])
empty
_g
rader
=
graders
.
grader_from_conf
([])
graded
=
weighted
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
weighted
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.5106547619047619
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.5106547619047619
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
graded
=
empty
G
rader
.
grade
(
self
.
test_gradesheet
)
graded
=
empty
_g
rader
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
0
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
0
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
0
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
0
)
#Test that graders can also be used instead of lists of dictionaries
#
Test that graders can also be used instead of lists of dictionaries
homework
G
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
homework
_g
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
homework
Grader2
=
graders
.
grader_from_conf
(
homeworkG
rader
)
homework
_grader2
=
graders
.
grader_from_conf
(
homework_g
rader
)
graded
=
homework
G
rader2
.
grade
(
self
.
test_gradesheet
)
graded
=
homework
_g
rader2
.
grade
(
self
.
test_gradesheet
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.11
)
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.11
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
#TODO: How do we test failure cases? The parser only logs an error when
#
TODO: How do we test failure cases? The parser only logs an error when
#it can't parse something. Maybe it should throw exceptions?
#
it can't parse something. Maybe it should throw exceptions?
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