Example #1
0
    def test_weighted_grading(self):
        scores = []
        agg_fields = dict(first_attempted=None)
        prob_fields = dict(raw_earned=0, raw_possible=0, weight=0, first_attempted=None)

        # No scores
        all_total, graded_total = aggregate_scores(scores)
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0, tw_possible=0, graded=False, **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0, tw_possible=0, graded=True, **agg_fields),
        )

        # (0/5 non-graded)
        scores.append(ProblemScore(weighted_earned=0, weighted_possible=5, graded=False, **prob_fields))
        all_total, graded_total = aggregate_scores(scores)
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0, tw_possible=5, graded=False, **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0, tw_possible=0, graded=True, **agg_fields),
        )

        # (0/5 non-graded) + (3/5 graded) = 3/10 total, 3/5 graded
        now = datetime.now()
        prob_fields['first_attempted'] = now
        agg_fields['first_attempted'] = now
        scores.append(ProblemScore(weighted_earned=3, weighted_possible=5, graded=True, **prob_fields))
        all_total, graded_total = aggregate_scores(scores)
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=3, tw_possible=10, graded=False, **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=3, tw_possible=5, graded=True, **agg_fields),
        )

        # (0/5 non-graded) + (3/5 graded) + (2/5 graded) = 5/15 total, 5/10 graded
        scores.append(ProblemScore(weighted_earned=2, weighted_possible=5, graded=True, **prob_fields))
        all_total, graded_total = aggregate_scores(scores)
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=5, tw_possible=15, graded=False, **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=5, tw_possible=10, graded=True, **agg_fields),
        )
Example #2
0
def mock_get_score(earned=0, possible=1):
    """
    Mocks the get_score function to return a valid grade.
    """
    with patch('lms.djangoapps.grades.new.subsection_grade.get_score') as mock_score:
        mock_score.return_value = ProblemScore(earned, possible, earned, possible, 1, True, None, None)
        yield mock_score
Example #3
0
 def test_get_score(self, submission_value, csm_value, persisted_block_value, block_value, expected_result):
     score = scores.get_score(
         self._create_submissions_scores(submission_value),
         self._create_csm_scores(csm_value),
         self._create_persisted_block(persisted_block_value),
         self._create_block(block_value),
     )
     expected_score = ProblemScore(**expected_result._asdict())
     self.assertEquals(score, expected_score)
Example #4
0
def mock_get_score(earned=0, possible=1, first_attempted=datetime(2000, 1, 1, 0, 0, 0, tzinfo=pytz.UTC)):
    """
    Mocks the get_score function to return a valid grade.
    """
    with patch('lms.djangoapps.grades.subsection_grade.get_score') as mock_score:
        mock_score.return_value = ProblemScore(
            raw_earned=earned,
            raw_possible=possible,
            weighted_earned=earned,
            weighted_possible=possible,
            weight=1,
            graded=True,
            first_attempted=first_attempted
        )
        yield mock_score
Example #5
0
def mock_get_score(earned=0, possible=1):
    """
    Mocks the get_score function to return a valid grade.
    """
    with patch('lms.djangoapps.grades.new.subsection_grade.get_score'
               ) as mock_score:
        mock_score.return_value = ProblemScore(
            raw_earned=earned,
            raw_possible=possible,
            weighted_earned=earned,
            weighted_possible=possible,
            weight=1,
            graded=True,
            attempted=True,
        )
        yield mock_score
Example #6
0
    def test_problem_weight(self, raw_earned, raw_possible, weight):

        use_weight = weight is not None and raw_possible != 0
        if use_weight:
            expected_w_earned = raw_earned / raw_possible * weight
            expected_w_possible = weight
        else:
            expected_w_earned = raw_earned
            expected_w_possible = raw_possible

        expected_graded = expected_w_possible > 0

        expected_score = ProblemScore(
            raw_earned=raw_earned,
            raw_possible=raw_possible,
            weighted_earned=expected_w_earned,
            weighted_possible=expected_w_possible,
            weight=weight,
            graded=expected_graded,
            first_attempted=datetime.datetime(2010, 1, 1),
        )
        self._verify_grades(raw_earned, raw_possible, weight, expected_score)
Example #7
0
    def test_problem_weight(self, raw_earned, raw_possible, weight):

        use_weight = weight is not None and raw_possible != 0
        if use_weight:
            expected_w_earned = raw_earned / raw_possible * weight
            expected_w_possible = weight
        else:
            expected_w_earned = raw_earned
            expected_w_possible = raw_possible

        expected_graded = expected_w_possible > 0

        expected_score = ProblemScore(
            raw_earned=raw_earned,
            raw_possible=raw_possible,
            weighted_earned=expected_w_earned,
            weighted_possible=expected_w_possible,
            weight=weight,
            graded=expected_graded,
            display_name=None,  # problem-specific, filled in by _verify_grades
            module_id=None,  # problem-specific, filled in by _verify_grades
        )
        self._verify_grades(raw_earned, raw_possible, weight, expected_score)
Example #8
0
def get_score(submissions_scores, csm_scores, persisted_block, block):
    """
    Returns the score for a problem, as a ProblemScore object.  It is
    assumed that the provided storages have already been filtered for
    a single user in question and have user-specific values.

    The score is retrieved from the provided storages in the following
    order of precedence.  If no value for the block is found in a
    given storage, the next storage is checked.

    submissions_scores (dict of {unicode(usage_key): (earned, possible)}):

        A python dictionary of serialized UsageKeys to (earned, possible)
        tuples. These values, retrieved using the Submissions API by the
        caller (already filtered for the user and course), take precedence
        above all other score storages.

        When the score is found in this storage, it implies the user's score
        for the block was persisted via the submissions API. Typically, this API
        is used by ORA.

        The returned score includes valid values for:
            weighted_earned
            weighted_possible
            graded - retrieved from the persisted block, if found, else from
                the latest block content.

        Note: raw_earned and raw_possible are not required when submitting scores
        via the submissions API, so those values (along with the unused weight)
        are invalid and irrelevant.

    csm_scores (ScoresClient):

        The ScoresClient object (already filtered for the user and course),
        from which a courseware.models.StudentModule object can be retrieved for
        the block.

        When the score is found from this storage, it implies the user's score
        for the block was persisted in the Courseware Student Module. Typically,
        this storage is used for all CAPA problems, including scores calculated
        by external graders.

        The returned score includes valid values for:
            raw_earned, raw_possible - retrieved from CSM
            weighted_earned, weighted_possible - calculated from the raw scores and weight
            weight, graded - retrieved from the persisted block, if found,
                else from the latest block content

    persisted_block (.models.BlockRecord):
        The block values as found in the grades persistence layer. These values
        are used only if not found from an earlier storage, and take precedence
        over values stored within the latest content-version of the block.

        When the score is found from this storage, it implies the user has not
        yet attempted this problem, but the user's grade _was_ persisted.

        The returned score includes valid values for:
            raw_earned - will equal 0.0 since the user's score was not found from
                earlier storages
            raw_possible - retrieved from the persisted block
            weighted_earned, weighted_possible - calculated from the raw scores and weight
            weight, graded - retrieved from the persisted block

    block (block_structure.BlockData):
        Values from the latest content-version of the block are used only if
        they were not available from a prior storage.

        When the score is found from this storage, it implies the user has not
        yet attempted this problem and the user's grade was _not_ yet persisted.

        The returned score includes valid values for:
            raw_earned - will equal 0.0 since the user's score was not found from
                earlier storages
            raw_possible - retrieved from the latest block content
            weighted_earned, weighted_possible - calculated from the raw scores and weight
            weight, graded - retrieved from the latest block content
    """
    weight = _get_weight_from_block(persisted_block, block)

    # Priority order for retrieving the scores:
    # submissions API -> CSM -> grades persisted block -> latest block content
    raw_earned, raw_possible, weighted_earned, weighted_possible, first_attempted = (
        _get_score_from_submissions(submissions_scores, block)
        or _get_score_from_csm(csm_scores, block, weight)
        or _get_score_from_persisted_or_latest_block(persisted_block, block,
                                                     weight))

    if weighted_possible is None or weighted_earned is None:
        return None

    else:
        has_valid_denominator = weighted_possible > 0.0
        graded = _get_graded_from_block(
            persisted_block, block) if has_valid_denominator else False

        return ProblemScore(
            raw_earned,
            raw_possible,
            weighted_earned,
            weighted_possible,
            weight,
            graded,
            first_attempted=first_attempted,
        )
Example #9
0
    def test_weighted_grading(self):
        scores = []
        agg_fields = dict(display_name="aggregated_score", module_id=None)
        prob_fields = dict(display_name="problem_score",
                           module_id=None,
                           raw_earned=0,
                           raw_possible=0,
                           weight=0)

        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=False,
                            **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=True,
                            **agg_fields),
        )

        scores.append(
            ProblemScore(weighted_earned=0,
                         weighted_possible=5,
                         graded=False,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=5,
                            graded=False,
                            **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=True,
                            **agg_fields),
        )

        scores.append(
            ProblemScore(weighted_earned=3,
                         weighted_possible=5,
                         graded=True,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=3,
                            tw_possible=10,
                            graded=False,
                            **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=3,
                            tw_possible=5,
                            graded=True,
                            **agg_fields),
        )

        scores.append(
            ProblemScore(weighted_earned=2,
                         weighted_possible=5,
                         graded=True,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=5,
                            tw_possible=15,
                            graded=False,
                            **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=5,
                            tw_possible=10,
                            graded=True,
                            **agg_fields),
        )
Example #10
0
    def test_weighted_grading(self):
        scores = []
        agg_fields = dict(display_name="aggregated_score",
                          module_id=None,
                          attempted=False)
        prob_fields = dict(
            display_name="problem_score",
            module_id=None,
            raw_earned=0,
            raw_possible=0,
            weight=0,
            attempted=False,
        )

        # No scores
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=False,
                            **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=True,
                            **agg_fields),
        )

        # (0/5 non-graded)
        scores.append(
            ProblemScore(weighted_earned=0,
                         weighted_possible=5,
                         graded=False,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertEqual(
            all_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=5,
                            graded=False,
                            **agg_fields),
        )
        self.assertEqual(
            graded_total,
            AggregatedScore(tw_earned=0,
                            tw_possible=0,
                            graded=True,
                            **agg_fields),
        )

        # (0/5 non-graded) + (3/5 graded) = 3/10 total, 3/5 graded
        prob_fields['attempted'] = True
        agg_fields['attempted'] = True
        scores.append(
            ProblemScore(weighted_earned=3,
                         weighted_possible=5,
                         graded=True,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=3,
                            tw_possible=10,
                            graded=False,
                            **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=3,
                            tw_possible=5,
                            graded=True,
                            **agg_fields),
        )

        # (0/5 non-graded) + (3/5 graded) + (2/5 graded) = 5/15 total, 5/10 graded
        scores.append(
            ProblemScore(weighted_earned=2,
                         weighted_possible=5,
                         graded=True,
                         **prob_fields))
        all_total, graded_total = aggregate_scores(
            scores, display_name=agg_fields['display_name'])
        self.assertAlmostEqual(
            all_total,
            AggregatedScore(tw_earned=5,
                            tw_possible=15,
                            graded=False,
                            **agg_fields),
        )
        self.assertAlmostEqual(
            graded_total,
            AggregatedScore(tw_earned=5,
                            tw_possible=10,
                            graded=True,
                            **agg_fields),
        )