Commit fe044709 by Brian Wilson

add management command to regrade partial-credit problems affected by get_npoints bug.

parent dfd66c65
import json
import logging
from optparse import make_option
from django.core.management.base import BaseCommand # , CommandError
from courseware.models import StudentModule
from capa.correctmap import CorrectMap
#
# This is aimed at fixing a temporary problem encountered where partial credit was awarded for
# code problems, but the resulting score (or grade) was mistakenly set to zero
# because of a bug in CorrectMap.get_npoints().
#
# The fix here is to recalculate the score/grade based on the partial credit.
# To narrow down the set of problems that might need fixing, the StudentModule
# objects to be checked is filtered down to those:
#
# grade=0.0 (the grade must have been zeroed out)
# created < '2013-03-08 05:19:00' (the problem must have been answered before the fix was installed)
# modified > '2013-03-07 20:18:00' (the problem must have been visited after the bug was introduced)
# state like '%"npoints": 0.%' (the problem must have some form of partial credit).
#
log = logging.getLogger(__name__)
class Command(BaseCommand):
num_visited = 0
num_changed = 0
option_list = BaseCommand.option_list + (
make_option('--save',
action='store_true',
dest='save_changes',
default=False,
help='Persist the changes that were encountered. If not set, no changes are saved.'), )
def fix_studentmodules(self, save_changes):
modules = StudentModule.objects.filter(# module_type='problem',
modified__gt='2013-03-07 20:18:00',
created__lt='2013-03-08 05:19:00',
state__contains='"npoints": 0.',
grade=0.0)
for module in modules:
self.fix_studentmodule(module, save_changes)
def fix_studentmodule(self, module, save_changes):
module_state = module.state
if module_state is None:
log.info("No state found for {type} module {id} for student {student} in course {course_id}".format(
**{'type':module.module_type, 'id':module.module_state_key, 'student':module.student.username, 'course_id':module.course_id}))
return
state_dict = json.loads(module_state)
self.num_visited += 1
correct_map = CorrectMap()
if 'correct_map' in state_dict:
correct_map.set_dict(state_dict['correct_map'])
correct = 0
for key in correct_map:
correct += correct_map.get_npoints(key)
if module.grade == correct:
log.info("Grade matches for {type} module {id} for student {student} in course {course_id}".format(
**{'type':module.module_type, 'id':module.module_state_key, 'student':module.student.username, 'course_id':module.course_id}))
elif save_changes:
log.info("Grade changing from {0} to {1} for {type} module {id} for student {student} in course {course_id}".format(
module.grade, correct,
**{'type':module.module_type, 'id':module.module_state_key, 'student':module.student.username, 'course_id':module.course_id}))
module.grade = correct
module.save()
self.num_changed += 1
else:
log.info("Grade would change from {0} to {1} for {type} module {id} for student {student} in course {course_id}".format(
module.grade, correct,
**{'type':module.module_type, 'id':module.module_state_key, 'student':module.student.username, 'course_id':module.course_id}))
self.num_changed += 1
def handle(self, **options):
save_changes = 'save_changes' in options and options['save_changes']
log.info("Starting run: save_changes = {0}".format(save_changes))
self.fix_studentmodules(save_changes)
log.info("Finished run: updating {0} of {1} modules".format(self.num_changed, self.num_visited))
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