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
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
156 additions
and
106 deletions
+156
-106
common/lib/xmodule/xmodule/graders.py
+57
-25
common/lib/xmodule/xmodule/tests/test_graders.py
+99
-81
No files found.
common/lib/xmodule/xmodule/graders.py
View file @
39d666cd
...
...
@@ -45,8 +45,9 @@ def invalid_args(func, argdict):
Given a function and a dictionary of arguments, returns a set of arguments
from argdict that aren't accepted by func
"""
args
,
varargs
,
keywords
,
defaults
=
inspect
.
getargspec
(
func
)
if
keywords
:
return
set
()
# All accepted
args
,
_
,
keywords
,
_
=
inspect
.
getargspec
(
func
)
if
keywords
:
return
set
()
# All accepted
return
set
(
argdict
)
-
set
(
args
)
...
...
@@ -119,7 +120,7 @@ class CourseGrader(object):
that has the matching section format.
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
that were graded. These are used for display in a graph or chart. The format for a
section_breakdown dictionary is explained below.
...
...
@@ -150,6 +151,7 @@ class CourseGrader(object):
@abc.abstractmethod
def
grade
(
self
,
grade_sheet
,
generate_random_scores
=
False
):
'''Given a grade sheet, return a dict containing grading information'''
raise
NotImplementedError
...
...
@@ -158,7 +160,10 @@ class WeightedSubsectionsGrader(CourseGrader):
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
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
composed using the score from each grader.
...
...
@@ -177,12 +182,12 @@ class WeightedSubsectionsGrader(CourseGrader):
for
subgrader
,
category
,
weight
in
self
.
sections
:
subgrade_result
=
subgrader
.
grade
(
grade_sheet
,
generate_random_scores
)
weighted
P
ercent
=
subgrade_result
[
'percent'
]
*
weight
section_detail
=
"{0} = {1:.1
%
} of a possible {2:.0
%
}"
.
format
(
category
,
weighted
P
ercent
,
weight
)
weighted
_p
ercent
=
subgrade_result
[
'percent'
]
*
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'
]
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
,
'section_breakdown'
:
section_breakdown
,
...
...
@@ -203,20 +208,20 @@ class SingleSectionGrader(CourseGrader):
self
.
category
=
category
or
name
def
grade
(
self
,
grade_sheet
,
generate_random_scores
=
False
):
found
S
core
=
None
found
_s
core
=
None
if
self
.
type
in
grade_sheet
:
for
score
in
grade_sheet
[
self
.
type
]:
if
score
.
section
==
self
.
name
:
found
S
core
=
score
found
_s
core
=
score
break
if
found
S
core
or
generate_random_scores
:
if
found
_s
core
or
generate_random_scores
:
if
generate_random_scores
:
# for debugging!
earned
=
random
.
randint
(
2
,
15
)
possible
=
random
.
randint
(
earned
,
15
)
else
:
# We found the score
earned
=
found
S
core
.
earned
possible
=
found
S
core
.
possible
earned
=
found
_s
core
.
earned
possible
=
found
_s
core
.
possible
percent
=
earned
/
float
(
possible
)
detail
=
"{name} - {percent:.0
%
} ({earned:.3n}/{possible:.3n})"
.
format
(
name
=
self
.
name
,
...
...
@@ -228,7 +233,8 @@ class SingleSectionGrader(CourseGrader):
percent
=
0.0
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
,
'section_breakdown'
:
breakdown
,
...
...
@@ -250,6 +256,13 @@ class AssignmentFormatGrader(CourseGrader):
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.
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
displayed, scores from the same category will be similar (for example, by color).
...
...
@@ -263,7 +276,8 @@ class AssignmentFormatGrader(CourseGrader):
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
.
min_count
=
min_count
self
.
drop_count
=
drop_count
...
...
@@ -275,7 +289,8 @@ class AssignmentFormatGrader(CourseGrader):
self
.
hide_average
=
hide_average
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
sorted_breakdown
=
sorted
(
enumerate
(
breakdown
),
key
=
lambda
x
:
-
x
[
1
][
'percent'
])
# A list of the indices of the dropped scores
...
...
@@ -308,7 +323,8 @@ class AssignmentFormatGrader(CourseGrader):
section_name
=
scores
[
i
]
.
section
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})"
summary
=
summary_format
.
format
(
index
=
i
+
self
.
starting_index
,
section_type
=
self
.
section_type
,
name
=
section_name
,
percent
=
percentage
,
...
...
@@ -316,25 +332,41 @@ class AssignmentFormatGrader(CourseGrader):
possible
=
float
(
possible
))
else
:
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
:
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
)
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
)}
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
:
breakdown
=
[]
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
,
'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
class
GradesheetTest
(
unittest
.
TestCase
):
'''Tests the aggregate_scores method'''
def
test_weighted_grading
(
self
):
scores
=
[]
Score
.
__sub__
=
lambda
me
,
other
:
(
me
.
earned
-
other
.
earned
)
+
(
me
.
possible
-
other
.
possible
)
all
,
graded
=
aggregate_scores
(
scores
)
self
.
assertEqual
(
all
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
False
,
section
=
"summary"
))
self
.
assertEqual
(
graded
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
True
,
section
=
"summary"
))
all
_total
,
graded_total
=
aggregate_scores
(
scores
)
self
.
assertEqual
(
all
_total
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
False
,
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"
))
all
,
graded
=
aggregate_scores
(
scores
)
self
.
assertEqual
(
all
,
Score
(
earned
=
0
,
possible
=
5
,
graded
=
False
,
section
=
"summary"
))
self
.
assertEqual
(
graded
,
Score
(
earned
=
0
,
possible
=
0
,
graded
=
True
,
section
=
"summary"
))
all
_total
,
graded_total
=
aggregate_scores
(
scores
)
self
.
assertEqual
(
all
_total
,
Score
(
earned
=
0
,
possible
=
5
,
graded
=
False
,
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"
))
all
,
graded
=
aggregate_scores
(
scores
)
self
.
assertAlmostEqual
(
all
,
Score
(
earned
=
3
,
possible
=
10
,
graded
=
False
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
graded
,
Score
(
earned
=
3
,
possible
=
5
,
graded
=
True
,
section
=
"summary"
))
all
_total
,
graded_total
=
aggregate_scores
(
scores
)
self
.
assertAlmostEqual
(
all
_total
,
Score
(
earned
=
3
,
possible
=
10
,
graded
=
False
,
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"
))
all
,
graded
=
aggregate_scores
(
scores
)
self
.
assertAlmostEqual
(
all
,
Score
(
earned
=
5
,
possible
=
15
,
graded
=
False
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
graded
,
Score
(
earned
=
5
,
possible
=
10
,
graded
=
True
,
section
=
"summary"
))
all
_total
,
graded_total
=
aggregate_scores
(
scores
)
self
.
assertAlmostEqual
(
all
_total
,
Score
(
earned
=
5
,
possible
=
15
,
graded
=
False
,
section
=
"summary"
))
self
.
assertAlmostEqual
(
graded
_total
,
Score
(
earned
=
5
,
possible
=
10
,
graded
=
True
,
section
=
"summary"
))
class
GraderTest
(
unittest
.
TestCase
):
'''Tests grader implementations'''
empty_gradesheet
=
{
}
...
...
@@ -45,7 +47,7 @@ class GraderTest(unittest.TestCase):
test_gradesheet
=
{
'Homework'
:
[
Score
(
earned
=
2
,
possible
=
20.0
,
graded
=
True
,
section
=
'hw1'
),
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
Score
(
earned
=
1
,
possible
=
1.0
,
graded
=
True
,
section
=
'lab2'
),
...
...
@@ -58,122 +60,138 @@ class GraderTest(unittest.TestCase):
'Midterm'
:
[
Score
(
earned
=
50.5
,
possible
=
100
,
graded
=
True
,
section
=
"Midterm Exam"
),
],
}
def
test_
SingleSectionG
rader
(
self
):
midterm
G
rader
=
graders
.
SingleSectionGrader
(
"Midterm"
,
"Midterm Exam"
)
lab4
G
rader
=
graders
.
SingleSectionGrader
(
"Lab"
,
"lab4"
)
bad
LabG
rader
=
graders
.
SingleSectionGrader
(
"Lab"
,
"lab42"
)
def
test_
single_section_g
rader
(
self
):
midterm
_g
rader
=
graders
.
SingleSectionGrader
(
"Midterm"
,
"Midterm Exam"
)
lab4
_g
rader
=
graders
.
SingleSectionGrader
(
"Lab"
,
"lab4"
)
bad
_lab_g
rader
=
graders
.
SingleSectionGrader
(
"Lab"
,
"lab42"
)
for
graded
in
[
midterm
G
rader
.
grade
(
self
.
empty_gradesheet
),
midtermG
rader
.
grade
(
self
.
incomplete_gradesheet
),
badLabG
rader
.
grade
(
self
.
test_gradesheet
)]:
for
graded
in
[
midterm
_g
rader
.
grade
(
self
.
empty_gradesheet
),
midterm_g
rader
.
grade
(
self
.
incomplete_gradesheet
),
bad_lab_g
rader
.
grade
(
self
.
test_gradesheet
)]:
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
1
)
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
.
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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
1
)
def
test_
AssignmentFormatG
rader
(
self
):
homework
G
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
no
DropG
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
0
)
#Even though the minimum number is 3, this should grade correctly when 7 assignments are found
overflow
G
rader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
3
,
2
)
lab
G
rader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
7
,
3
)
#Test the grading of an empty gradesheet
for
graded
in
[
homework
G
rader
.
grade
(
self
.
empty_gradesheet
),
noDropG
rader
.
grade
(
self
.
empty_gradesheet
),
homeworkG
rader
.
grade
(
self
.
incomplete_gradesheet
),
noDropG
rader
.
grade
(
self
.
incomplete_gradesheet
)]:
def
test_
assignment_format_g
rader
(
self
):
homework
_g
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
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
overflow
_g
rader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
3
,
2
)
lab
_g
rader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
7
,
3
)
#
Test the grading of an empty gradesheet
for
graded
in
[
homework
_g
rader
.
grade
(
self
.
empty_gradesheet
),
no_drop_g
rader
.
grade
(
self
.
empty_gradesheet
),
homework_g
rader
.
grade
(
self
.
incomplete_gradesheet
),
no_drop_g
rader
.
grade
(
self
.
incomplete_gradesheet
)]:
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
)
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
.
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
.
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
.
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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
7
+
1
)
def
test_WeightedSubsectionsGrader
(
self
):
#First, a few sub graders
homeworkGrader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
labGrader
=
graders
.
AssignmentFormatGrader
(
"Lab"
,
7
,
3
)
midtermGrader
=
graders
.
SingleSectionGrader
(
"Midterm"
,
"Midterm Exam"
)
def
test_assignment_format_grader_on_single_section_entry
(
self
):
midterm_grader
=
graders
.
AssignmentFormatGrader
(
"Midterm"
,
1
,
0
)
# Test the grading on a section with one item:
for
graded
in
[
midterm_grader
.
grade
(
self
.
empty_gradesheet
),
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
),
(
labGrader
,
labG
rader
.
category
,
0.25
),
(
midtermGrader
,
midtermG
rader
.
category
,
0.5
)])
weighted
_grader
=
graders
.
WeightedSubsectionsGrader
([(
homework_grader
,
homework_g
rader
.
category
,
0.25
),
(
lab_grader
,
lab_g
rader
.
category
,
0.25
),
(
midterm_grader
,
midterm_g
rader
.
category
,
0.5
)])
over
OneWeightsGrader
=
graders
.
WeightedSubsectionsGrader
([(
homeworkGrader
,
homeworkG
rader
.
category
,
0.5
),
(
labGrader
,
labG
rader
.
category
,
0.5
),
(
midtermGrader
,
midtermG
rader
.
category
,
0.5
)])
over
_one_weights_grader
=
graders
.
WeightedSubsectionsGrader
([(
homework_grader
,
homework_g
rader
.
category
,
0.5
),
(
lab_grader
,
lab_g
rader
.
category
,
0.5
),
(
midterm_grader
,
midterm_g
rader
.
category
,
0.5
)])
#The midterm should have all weight on this one
zero
WeightsGrader
=
graders
.
WeightedSubsectionsGrader
([(
homeworkGrader
,
homeworkG
rader
.
category
,
0.0
),
(
labGrader
,
labG
rader
.
category
,
0.0
),
(
midtermGrader
,
midtermG
rader
.
category
,
0.5
)])
#
The midterm should have all weight on this one
zero
_weights_grader
=
graders
.
WeightedSubsectionsGrader
([(
homework_grader
,
homework_g
rader
.
category
,
0.0
),
(
lab_grader
,
lab_g
rader
.
category
,
0.0
),
(
midterm_grader
,
midterm_g
rader
.
category
,
0.5
)])
#This should always have a final percent of zero
all
ZeroWeightsGrader
=
graders
.
WeightedSubsectionsGrader
([(
homeworkGrader
,
homeworkG
rader
.
category
,
0.0
),
(
labGrader
,
labG
rader
.
category
,
0.0
),
(
midtermGrader
,
midtermG
rader
.
category
,
0.0
)])
#
This should always have a final percent of zero
all
_zero_weights_grader
=
graders
.
WeightedSubsectionsGrader
([(
homework_grader
,
homework_g
rader
.
category
,
0.0
),
(
lab_grader
,
lab_g
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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
3
)
for
graded
in
[
weighted
G
rader
.
grade
(
self
.
empty_gradesheet
),
weightedG
rader
.
grade
(
self
.
incomplete_gradesheet
),
zeroWeightsG
rader
.
grade
(
self
.
empty_gradesheet
),
allZeroWeightsG
rader
.
grade
(
self
.
empty_gradesheet
)]:
for
graded
in
[
weighted
_g
rader
.
grade
(
self
.
empty_gradesheet
),
weighted_g
rader
.
grade
(
self
.
incomplete_gradesheet
),
zero_weights_g
rader
.
grade
(
self
.
empty_gradesheet
),
all_zero_weights_g
rader
.
grade
(
self
.
empty_gradesheet
)]:
self
.
assertAlmostEqual
(
graded
[
'percent'
],
0.0
)
self
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
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
.
assertEqual
(
len
(
graded
[
'section_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
#in test_graders.WeightedSubsectionsGrader, but generate the graders with confs.
#
Confs always produce a graders.WeightedSubsectionsGrader, so we test this by repeating the test
#
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"
,
'min_count'
:
12
,
...
...
@@ -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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
(
12
+
1
)
+
(
7
+
1
)
+
1
)
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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
0
)
self
.
assertEqual
(
len
(
graded
[
'grade_breakdown'
]),
0
)
#Test that graders can also be used instead of lists of dictionaries
homework
G
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
homework
Grader2
=
graders
.
grader_from_conf
(
homeworkG
rader
)
#
Test that graders can also be used instead of lists of dictionaries
homework
_g
rader
=
graders
.
AssignmentFormatGrader
(
"Homework"
,
12
,
2
)
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
.
assertEqual
(
len
(
graded
[
'section_breakdown'
]),
12
+
1
)
#TODO: How do we test failure cases? The parser only logs an error when
#it can't parse something. Maybe it should throw exceptions?
#
TODO: How do we test failure cases? The parser only logs an error when
#
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