From 940a337dd3f635788d0dada3611e789f0983dd89 Mon Sep 17 00:00:00 2001 From: Vik Paruchuri Date: Thu, 29 Aug 2013 12:14:30 -0400 Subject: [PATCH] Properly display student progress --- .../combined_open_ended_modulev1.py | 52 +++++++++++++------ .../xmodule/tests/test_combined_open_ended.py | 24 +++++++++ 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py b/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py index 6ab8db8334..becb0fd170 100644 --- a/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py +++ b/common/lib/xmodule/xmodule/open_ended_grading_classes/combined_open_ended_modulev1.py @@ -823,6 +823,16 @@ class CombinedOpenEndedV1Module(): """ return (self.state == self.DONE or self.ready_to_reset) and self.is_scored + def get_weight(self): + """ + Return the weight of the problem. The old default weight was None, so set to 1 in that case. + Output - int weight + """ + weight = self.weight + if weight is None: + weight = 1 + return weight + def get_score(self): """ Score the student received on the problem, or None if there is no @@ -837,9 +847,7 @@ class CombinedOpenEndedV1Module(): score = None #The old default was None, so set to 1 if it is the old default weight - weight = self.weight - if weight is None: - weight = 1 + weight = self.get_weight() if self.is_scored: # Finds the maximum score of all student attempts and keeps it. score_mat = [] @@ -879,27 +887,41 @@ class CombinedOpenEndedV1Module(): return score_dict def max_score(self): - ''' Maximum score. Two notes: - - * This is generic; in abstract, a problem could be 3/5 points on one - randomization, and 5/7 on another - ''' + """ + Maximum score possible in this module. Returns the max score if finished, None if not. + """ max_score = None if self.check_if_done_and_scored(): max_score = self._max_score return max_score def get_progress(self): - ''' Return a progress.Progress object that represents how far the + """ + Generate a progress object. Progress objects represent how far the student has gone in this module. Must be implemented to get correct - progress tracking behavior in nesting modules like sequence and - vertical. + progress tracking behavior in nested modules like sequence and + vertical. This behavior is consistent with capa. - If this module has no notion of progress, return None. - ''' - progress_object = Progress(self.current_task_number, len(self.task_xml)) + If the module is unscored, return None (consistent with capa). + """ - return progress_object + d = self.get_score() + score = d['score'] + total = d['total'] + + if total > 0 and self.is_scored: + if self.weight is not None: + # scale score and total by weight/total: + score = score * self.get_weight() / total + total = self.get_weight() + + try: + return Progress(score, total) + except (TypeError, ValueError): + log.exception("Got bad progress") + return None + + return None def out_of_sync_error(self, data, msg=''): """ diff --git a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py index 26c248f71d..d97d62d7d3 100644 --- a/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py +++ b/common/lib/xmodule/xmodule/tests/test_combined_open_ended.py @@ -22,6 +22,7 @@ from xmodule.open_ended_grading_classes.grading_service_module import GradingSer from xmodule.combined_open_ended_module import CombinedOpenEndedModule from xmodule.modulestore import Location from xmodule.tests import get_test_system, test_util_open_ended +from xmodule.progress import Progress from xmodule.tests.test_util_open_ended import (MockQueryDict, DummyModulestore, TEST_STATE_SA_IN, MOCK_INSTANCE_STATE, TEST_STATE_SA, TEST_STATE_AI, TEST_STATE_AI2, TEST_STATE_AI2_INVALID, TEST_STATE_SINGLE, TEST_STATE_PE_SINGLE) @@ -480,6 +481,29 @@ class CombinedOpenEndedModuleTest(unittest.TestCase): max_score = self.combinedoe_container.max_score() self.assertEqual(max_score, None) + def test_container_get_progress(self): + """ + See if we can get the progress from the actual xmodule + """ + progress = self.combinedoe_container.max_score() + self.assertEqual(progress, None) + + def test_get_progress(self): + """ + Test if we can get the correct progress from the combined open ended class + """ + self.combinedoe.update_task_states() + self.combinedoe.state = "done" + self.combinedoe.is_scored = True + progress = self.combinedoe.get_progress() + self.assertIsInstance(progress, Progress) + + #progress._a is the score of the xmodule, which is 0 right now + self.assertEqual(progress._a, 0) + + #progress._b is the max_score (which is 1), divided by the weight (which is 1) + self.assertEqual(progress._b, 1) + def test_container_weight(self): """ Check the problem weight in the container