diff --git a/lms/djangoapps/courseware/grades.py b/lms/djangoapps/courseware/grades.py index 5a817e3d6c..ca8620c1f6 100644 --- a/lms/djangoapps/courseware/grades.py +++ b/lms/djangoapps/courseware/grades.py @@ -3,6 +3,7 @@ import logging from django.conf import settings +from module_render import get_module from xmodule import graders from xmodule.graders import Score from models import StudentModule @@ -10,6 +11,103 @@ from models import StudentModule _log = logging.getLogger("mitx.courseware") + + + +def get_graded_sections(course_descriptor): + """ + Arguments: + course_descriptor: a CourseDescriptor object for the course to be graded + + Returns: + A dictionary keyed by section-type. The values are arrays of dictionaries containing + "section_descriptor" : The section descriptor + "xmoduledescriptors" : An array of xmoduledescriptors that could possibly be in the section, for any student + """ + + graded_sections = {} + for c in course_descriptor.get_children(): + sections = [] + for s in c.get_children(): + if s.metadata.get('graded', False): + + xmoduledescriptors = [] + for module in yield_descriptor_descendents(s): + xmoduledescriptors.append(module) + + section_description = { 'section_descriptor' : s, 'xmoduledescriptors' : xmoduledescriptors} + + section_format = s.metadata.get('format', "") + graded_sections[ section_format ] = graded_sections.get( section_format, [] ) + [section_description] + + return graded_sections + +def yield_descriptor_descendents(module_descriptor): + for child in module_descriptor.get_children(): + yield child + for module_descriptor in yield_descriptor_descendents(child): + yield module_descriptor + +def yield_module_descendents(module): + for child in module.get_display_items(): + yield child + for module in yield_module_descendents(child): + yield module + +def fast_grade(student, request, course_graded_sections, grader, student_module_cache): + totaled_scores = {} + for section_format, sections in course_graded_sections.iteritems(): + format_scores = [] + for section in sections: + section_descriptor = section['section_descriptor'] + section_name = section_descriptor.metadata.get('display_name') + + should_grade_section = False + # If we haven't seen a single problem in the section, we don't have to grade it at all! We can assume 0% + for moduledescriptor in section['xmoduledescriptors']: + if student_module_cache.lookup(moduledescriptor.category, moduledescriptor.location.url() ): + should_grade_section = True + break + + if should_grade_section: + scores = [] + (section_module, _, _, _) = get_module(student, request, section_descriptor.location, student_module_cache) + + for module in yield_descriptor_descendents(section_module): + (correct, total) = get_score(student, module, student_module_cache) + graded = module.metadata.get("graded", False) + + if correct is None and total is None: + continue + + if settings.GENERATE_PROFILE_SCORES: + if total > 1: + correct = random.randrange(max(total - 2, 1), total + 1) + else: + correct = total + + if not total > 0: + #We simply cannot grade a problem that is 12/0, because we might need it as a percentage + graded = False + + scores.append(Score(correct, total, graded, module.metadata.get('display_name'))) + + section_total, graded_total = graders.aggregate_scores(scores, section_name) + else: + section_total = Score(0.0, 1.0, False, section_name) + graded_possible = 1.0 #if s.metadata.get("graded", False) else 0.0 + graded_total = Score(0.0, graded_possible, True, section_name) + + #Add the graded total to totaled_scores + if graded_total.possible > 0: + format_scores.append(graded_total) + + totaled_scores[section_format] = format_scores + + grade_summary = grade_summary = grader.grade(totaled_scores) + return grade_summary + + def grade_sheet(student, course, grader, student_module_cache): """ This pulls a summary of all problems in the course. It returns a dictionary with two datastructures: @@ -30,15 +128,9 @@ def grade_sheet(student, course, grader, student_module_cache): for c in course.get_children(): sections = [] for s in c.get_children(): - def yield_descendents(module): - yield module - for child in module.get_display_items(): - for module in yield_descendents(child): - yield module - graded = s.metadata.get('graded', False) scores = [] - for module in yield_descendents(s): + for module in yield_module_descendents(s): (correct, total) = get_score(student, module, student_module_cache) if correct is None and total is None: diff --git a/lms/djangoapps/courseware/views.py b/lms/djangoapps/courseware/views.py index 7281ab01ad..a89a4bf34f 100644 --- a/lms/djangoapps/courseware/views.py +++ b/lms/djangoapps/courseware/views.py @@ -35,6 +35,19 @@ log = logging.getLogger("mitx.courseware") template_imports = {'urllib': urllib} +def test_grading(request, course_id): + course = check_course(course_id) + + sections = grades.get_graded_sections(course) + + student_module_cache = StudentModuleCache(request.user, course) + + grade_result = grades.fast_grade(request.user, request, sections, course.grader, student_module_cache) + + return HttpResponse("
" + json.dumps(grade_result) + "") + + + def user_groups(user): if not user.is_authenticated(): return [] diff --git a/lms/urls.py b/lms/urls.py index 1c4a065e2b..8d7460ddc2 100644 --- a/lms/urls.py +++ b/lms/urls.py @@ -118,6 +118,10 @@ if settings.COURSEWARE_ENABLED: url(r'^courses/(?P