Commit e3b39787 by Bridger Maxwell

Moved the weighting of problems to when problem scores are retrieved.

parent 3860f333
...@@ -12,7 +12,7 @@ from student.models import UserProfile ...@@ -12,7 +12,7 @@ from student.models import UserProfile
log = logging.getLogger("mitx.courseware") log = logging.getLogger("mitx.courseware")
Score = namedtuple("Score", "earned possible weight graded section") Score = namedtuple("Score", "earned possible graded section")
SectionPercentage = namedtuple("SectionPercentage", "percentage label summary") SectionPercentage = namedtuple("SectionPercentage", "percentage label summary")
...@@ -273,7 +273,7 @@ class AssignmentFormatGrader(CourseGrader): ...@@ -273,7 +273,7 @@ class AssignmentFormatGrader(CourseGrader):
def get_score(user, problem, cache): def get_score(user, problem, cache):
## HACK: assumes max score is fixed per problem ## HACK: assumes max score is fixed per problem
id = problem.get('id') id = problem.get('id')
correct = 0 correct = 0.0
# If the ID is not in the cache, add the item # If the ID is not in the cache, add the item
if id not in cache: if id not in cache:
...@@ -290,15 +290,22 @@ def get_score(user, problem, cache): ...@@ -290,15 +290,22 @@ def get_score(user, problem, cache):
if id in cache: if id in cache:
response = cache[id] response = cache[id]
if response.grade!=None: if response.grade!=None:
correct=response.grade correct=float(response.grade)
# Grab max grade from cache, or if it doesn't exist, compute and save to DB # Grab max grade from cache, or if it doesn't exist, compute and save to DB
if id in cache and response.max_grade != None: if id in cache and response.max_grade != None:
total = response.max_grade total = response.max_grade
else: else:
total=courseware.modules.capa_module.Module(etree.tostring(problem), "id").max_score() total=float(courseware.modules.capa_module.Module(etree.tostring(problem), "id").max_score())
response.max_grade = total response.max_grade = total
response.save() response.save()
#Now we re-weight the problem, if specified
weight = problem.get("weight", None)
if weight:
weight = float(weight)
correct = correct * weight / total
total = weight
return (correct, total) return (correct, total)
...@@ -348,12 +355,12 @@ def grade_sheet(student): ...@@ -348,12 +355,12 @@ def grade_sheet(student):
correct = random.randrange( max(total-2, 1) , total + 1 ) correct = random.randrange( max(total-2, 1) , total + 1 )
else: else:
correct = total correct = total
scores.append( Score(int(correct),total, float(p.get("weight", total)), graded, p.get("name")) ) scores.append( Score(correct,total, graded, p.get("name")) )
section_total, graded_total = aggregate_scores(scores, s.get("name"), s.get("weight", 1)) section_total, graded_total = aggregate_scores(scores, s.get("name"))
#Add the graded total to totaled_scores #Add the graded total to totaled_scores
format = s.get('format') if s.get('format') else "" format = s.get('format', "")
subtitle = s.get('subtitle') if s.get('subtitle') else format subtitle = s.get('subtitle', format)
if format and graded_total[1] > 0: if format and graded_total[1] > 0:
format_scores = totaled_scores.get(format, []) format_scores = totaled_scores.get(format, [])
format_scores.append( graded_total ) format_scores.append( graded_total )
...@@ -387,26 +394,21 @@ def grade_sheet(student): ...@@ -387,26 +394,21 @@ def grade_sheet(student):
return {'courseware_summary' : chapters, return {'courseware_summary' : chapters,
'grade_summary' : grade_summary} 'grade_summary' : grade_summary}
def aggregate_scores(scores, section_name = "summary", section_weight = 1): def aggregate_scores(scores, section_name = "summary"):
#TODO: What does a possible score of zero mean? We need to think what extra credit is total_correct_graded = sum(score.earned for score in scores if score.graded)
scores = filter( lambda score: score.possible > 0, scores ) total_possible_graded = sum(score.possible for score in scores if score.graded)
total_correct_graded = sum((score.earned*1.0/score.possible)*score.weight for score in scores if score.graded)
total_possible_graded = sum(score.weight for score in scores if score.graded)
total_correct = sum((score.earned*1.0/score.possible)*score.weight for score in scores) total_correct = sum(score.earned for score in scores)
total_possible = sum(score.weight for score in scores) total_possible = sum(score.possible for score in scores)
#regardless of whether or not it is graded #regardless of whether or not it is graded
all_total = Score(total_correct, all_total = Score(total_correct,
total_possible, total_possible,
section_weight,
False, False,
section_name) section_name)
#selecting only graded things #selecting only graded things
graded_total = Score(total_correct_graded, graded_total = Score(total_correct_graded,
total_possible_graded, total_possible_graded,
section_weight,
True, True,
section_name) section_name)
......
...@@ -61,38 +61,38 @@ class GradesheetTest(unittest.TestCase): ...@@ -61,38 +61,38 @@ class GradesheetTest(unittest.TestCase):
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, graded = aggregate_scores(scores)
self.assertEqual(all, Score(earned=0, possible=0, weight=1, graded=False, section="summary")) self.assertEqual(all, Score(earned=0, possible=0, graded=False, section="summary"))
self.assertEqual(graded, Score(earned=0, possible=0, weight=1, graded=True, section="summary")) self.assertEqual(graded, Score(earned=0, possible=0, graded=True, section="summary"))
scores.append(Score(earned=0, possible=5, weight=1, graded=False, section="summary")) scores.append(Score(earned=0, possible=5, graded=False, section="summary"))
all, graded = aggregate_scores(scores) all, graded = aggregate_scores(scores)
self.assertEqual(all, Score(earned=0, possible=1, weight=1, graded=False, section="summary")) self.assertEqual(all, Score(earned=0, possible=1, graded=False, section="summary"))
self.assertEqual(graded, Score(earned=0, possible=0, weight=1, graded=True, section="summary")) self.assertEqual(graded, Score(earned=0, possible=0, graded=True, section="summary"))
scores.append(Score(earned=3, possible=5, weight=1, graded=True, section="summary")) scores.append(Score(earned=3, possible=5, graded=True, section="summary"))
all, graded = aggregate_scores(scores) all, graded = aggregate_scores(scores)
self.assertAlmostEqual(all, Score(earned=3.0/5, possible=2, weight=1, graded=False, section="summary")) self.assertAlmostEqual(all, Score(earned=3.0/5, possible=2, graded=False, section="summary"))
self.assertAlmostEqual(graded, Score(earned=3.0/5, possible=1, weight=1, graded=True, section="summary")) self.assertAlmostEqual(graded, Score(earned=3.0/5, possible=1, graded=True, section="summary"))
scores.append(Score(earned=2, possible=5, weight=2, graded=True, section="summary")) scores.append(Score(earned=2, possible=5, weight=2, graded=True, section="summary"))
all, graded = aggregate_scores(scores) all, graded = aggregate_scores(scores)
self.assertAlmostEqual(all, Score(earned=7.0/5, possible=4, weight=1, graded=False, section="summary")) self.assertAlmostEqual(all, Score(earned=7.0/5, possible=4, graded=False, section="summary"))
self.assertAlmostEqual(graded, Score(earned=7.0/5, possible=3, weight=1, graded=True, section="summary")) self.assertAlmostEqual(graded, Score(earned=7.0/5, possible=3, graded=True, section="summary"))
scores.append(Score(earned=2, possible=5, weight=0, graded=True, section="summary")) scores.append(Score(earned=2, possible=5, weight=0, graded=True, section="summary"))
all, graded = aggregate_scores(scores) all, graded = aggregate_scores(scores)
self.assertAlmostEqual(all, Score(earned=7.0/5, possible=4, weight=1, graded=False, section="summary")) self.assertAlmostEqual(all, Score(earned=7.0/5, possible=4, graded=False, section="summary"))
self.assertAlmostEqual(graded, Score(earned=7.0/5, possible=3, weight=1, graded=True, section="summary")) self.assertAlmostEqual(graded, Score(earned=7.0/5, possible=3, graded=True, section="summary"))
scores.append(Score(earned=2, possible=5, weight=3, graded=False, section="summary")) scores.append(Score(earned=2, possible=5, weight=3, graded=False, section="summary"))
all, graded = aggregate_scores(scores) all, graded = aggregate_scores(scores)
self.assertAlmostEqual(all, Score(earned=13.0/5, possible=7, weight=1, graded=False, section="summary")) self.assertAlmostEqual(all, Score(earned=13.0/5, possible=7, graded=False, section="summary"))
self.assertAlmostEqual(graded, Score(earned=7.0/5, possible=3, weight=1, graded=True, section="summary")) self.assertAlmostEqual(graded, Score(earned=7.0/5, possible=3, graded=True, section="summary"))
scores.append(Score(earned=2, possible=5, weight=.5, graded=True, section="summary")) scores.append(Score(earned=2, possible=5, weight=.5, graded=True, section="summary"))
all, graded = aggregate_scores(scores) all, graded = aggregate_scores(scores)
self.assertAlmostEqual(all, Score(earned=14.0/5, possible=7.5, weight=1, graded=False, section="summary")) self.assertAlmostEqual(all, Score(earned=14.0/5, possible=7.5, graded=False, section="summary"))
self.assertAlmostEqual(graded, Score(earned=8.0/5, possible=3.5, weight=1, graded=True, section="summary")) self.assertAlmostEqual(graded, Score(earned=8.0/5, possible=3.5, graded=True, section="summary"))
class GraderTest(unittest.TestCase): class GraderTest(unittest.TestCase):
...@@ -106,19 +106,19 @@ class GraderTest(unittest.TestCase): ...@@ -106,19 +106,19 @@ class GraderTest(unittest.TestCase):
} }
test_gradesheet = { test_gradesheet = {
'Homework': [Score(earned=2, possible=20.0, weight=1, graded=True, section='hw1'), 'Homework': [Score(earned=2, possible=20.0, graded=True, section='hw1'),
Score(earned=16, possible=16.0, weight=1, 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, weight=1, graded=True, section='lab1'), #Dropped 'Lab': [Score(earned=1, possible=2.0, graded=True, section='lab1'), #Dropped
Score(earned=1, possible=1.0, weight=1, graded=True, section='lab2'), Score(earned=1, possible=1.0, graded=True, section='lab2'),
Score(earned=1, possible=1.0, weight=1, graded=True, section='lab3'), Score(earned=1, possible=1.0, graded=True, section='lab3'),
Score(earned=5, possible=25.0, weight=1, graded=True, section='lab4'), #Dropped Score(earned=5, possible=25.0, graded=True, section='lab4'), #Dropped
Score(earned=3, possible=4.0, weight=1, graded=True, section='lab5'), #Dropped Score(earned=3, possible=4.0, graded=True, section='lab5'), #Dropped
Score(earned=6, possible=7.0, weight=1, graded=True, section='lab6'), Score(earned=6, possible=7.0, graded=True, section='lab6'),
Score(earned=5, possible=6.0, weight=1, graded=True, section='lab7')], Score(earned=5, possible=6.0, graded=True, section='lab7')],
'Midterm' : [Score(earned=50.5, possible=100, weight=1, graded=True, section="Midterm Exam"),], 'Midterm' : [Score(earned=50.5, possible=100, graded=True, section="Midterm Exam"),],
} }
def test_SingleSectionGrader(self): def test_SingleSectionGrader(self):
......
...@@ -154,7 +154,7 @@ $(function() { ...@@ -154,7 +154,7 @@ $(function() {
%> %>
<h3><a href="${reverse('courseware_section', args=format_url_params([chapter['course'], chapter['chapter'], section['section']])) }"> <h3><a href="${reverse('courseware_section', args=format_url_params([chapter['course'], chapter['chapter'], section['section']])) }">
${ section['section'] }</a> ${"({0:g}/{1:g}) {2}".format( earned, total, percentageString )}</h3> ${ section['section'] }</a> ${"({0:.3n}/{1:.3n}) {2}".format( float(earned), float(total), percentageString )}</h3>
${section['subtitle']} ${section['subtitle']}
%if 'due' in section and section['due']!="": %if 'due' in section and section['due']!="":
due ${section['due']} due ${section['due']}
...@@ -164,7 +164,7 @@ $(function() { ...@@ -164,7 +164,7 @@ $(function() {
<ol class="scores"> <ol class="scores">
${ "Problem Scores: " if section['graded'] else "Practice Scores: "} ${ "Problem Scores: " if section['graded'] else "Practice Scores: "}
%for score in section['scores']: %for score in section['scores']:
<li class="score">${"{0:g}/{1:g}".format(score.earned,score.possible)}</li> <li class="score">${"{0:.3n}/{1:.3n}".format(float(score.earned),float(score.possible))}</li>
%endfor %endfor
</ol> </ol>
%endif %endif
......
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