Esempio n. 1
0
def set_score(submission_uuid,
              points_earned,
              points_possible,
              annotation_creator=None,
              annotation_type=None,
              annotation_reason=None):
    """Set a score for a particular submission.

    Sets the score for a particular submission. This score is calculated
    externally to the API.

    Args:
        submission_uuid (str): UUID for the submission (must exist).
        points_earned (int): The earned points for this submission.
        points_possible (int): The total points possible for this particular student item.

        annotation_creator (str): An optional field for recording who gave this particular score
        annotation_type (str): An optional field for recording what type of annotation should be created,
                                e.g. "staff_override".
        annotation_reason (str): An optional field for recording why this score was set to its value.

    Returns:
        None

    Raises:
        SubmissionInternalError: Thrown if there was an internal error while
            attempting to save the score.
        SubmissionRequestError: Thrown if the given student item or submission
            are not found.

    Examples:
        >>> set_score("a778b933-9fb3-11e3-9c0f-040ccee02800", 11, 12)
        {
            'student_item': 2,
            'submission': 1,
            'points_earned': 11,
            'points_possible': 12,
            'created_at': datetime.datetime(2014, 2, 7, 20, 6, 42, 331156, tzinfo=<UTC>)
        }

    """
    try:
        submission_model = _get_submission_model(submission_uuid)
    except Submission.DoesNotExist as error:
        raise SubmissionNotFoundError(
            f"No submission matching uuid {submission_uuid}") from error
    except DatabaseError as error:
        error_msg = "Could not retrieve submission {}.".format(submission_uuid)
        logger.exception(error_msg)
        raise SubmissionRequestError(msg=error_msg) from error

    score = ScoreSerializer(
        data={
            "student_item": submission_model.student_item.pk,
            "submission": submission_model.pk,
            "points_earned": points_earned,
            "points_possible": points_possible,
        })
    if not score.is_valid():
        logger.exception(score.errors)
        raise SubmissionInternalError(score.errors)

    # When we save the score, a score summary will be created if
    # it does not already exist.
    # When the database's isolation level is set to repeatable-read,
    # it's possible for a score summary to exist for this student item,
    # even though we cannot retrieve it.
    # In this case, we assume that someone else has already created
    # a score summary and ignore the error.
    try:
        with transaction.atomic():
            score_model = score.save()
            _log_score(score_model)
            if annotation_creator is not None:
                score_annotation = ScoreAnnotation(
                    score=score_model,
                    creator=annotation_creator,
                    annotation_type=annotation_type,
                    reason=annotation_reason)
                score_annotation.save()
        # Send a signal out to any listeners who are waiting for scoring events.
        score_set.send(
            sender=None,
            points_possible=points_possible,
            points_earned=points_earned,
            anonymous_user_id=submission_model.student_item.student_id,
            course_id=submission_model.student_item.course_id,
            item_id=submission_model.student_item.item_id,
            created_at=score_model.created_at,
        )
    except IntegrityError:
        pass
Esempio n. 2
0
def set_score(submission_uuid, points_earned, points_possible):
    """Set a score for a particular submission.

    Sets the score for a particular submission. This score is calculated
    externally to the API.

    Args:
        submission_uuid (str): UUID for the submission (must exist).
        points_earned (int): The earned points for this submission.
        points_possible (int): The total points possible for this particular
            student item.

    Returns:
        None

    Raises:
        SubmissionInternalError: Thrown if there was an internal error while
            attempting to save the score.
        SubmissionRequestError: Thrown if the given student item or submission
            are not found.

    Examples:
        >>> set_score("a778b933-9fb3-11e3-9c0f-040ccee02800", 11, 12)
        {
            'student_item': 2,
            'submission': 1,
            'points_earned': 11,
            'points_possible': 12,
            'created_at': datetime.datetime(2014, 2, 7, 20, 6, 42, 331156, tzinfo=<UTC>)
        }

    """
    try:
        submission_model = Submission.objects.get(uuid=submission_uuid)
    except Submission.DoesNotExist:
        raise SubmissionNotFoundError(
            u"No submission matching uuid {}".format(submission_uuid))
    except DatabaseError:
        error_msg = u"Could not retrieve student item: {} or submission {}.".format(
            submission_uuid)
        logger.exception(error_msg)
        raise SubmissionRequestError(error_msg)

    score = ScoreSerializer(
        data={
            "student_item": submission_model.student_item.pk,
            "submission": submission_model.pk,
            "points_earned": points_earned,
            "points_possible": points_possible,
        })
    if not score.is_valid():
        logger.exception(score.errors)
        raise SubmissionInternalError(score.errors)

    # When we save the score, a score summary will be created if
    # it does not already exist.
    # When the database's isolation level is set to repeatable-read,
    # it's possible for a score summary to exist for this student item,
    # even though we cannot retrieve it.
    # In this case, we assume that someone else has already created
    # a score summary and ignore the error.
    try:
        score_model = score.save()
        _log_score(score_model)
    except IntegrityError:
        pass
Esempio n. 3
0
def set_score(submission_uuid, points_earned, points_possible):
    """Set a score for a particular submission.

    Sets the score for a particular submission. This score is calculated
    externally to the API.

    Args:
        submission_uuid (str): UUID for the submission (must exist).
        points_earned (int): The earned points for this submission.
        points_possible (int): The total points possible for this particular student item.

    Returns:
        None

    Raises:
        SubmissionInternalError: Thrown if there was an internal error while
            attempting to save the score.
        SubmissionRequestError: Thrown if the given student item or submission
            are not found.

    Examples:
        >>> set_score("a778b933-9fb3-11e3-9c0f-040ccee02800", 11, 12)
        {
            'student_item': 2,
            'submission': 1,
            'points_earned': 11,
            'points_possible': 12,
            'created_at': datetime.datetime(2014, 2, 7, 20, 6, 42, 331156, tzinfo=<UTC>)
        }

    """
    try:
        submission_model = Submission.objects.get(uuid=submission_uuid)
    except Submission.DoesNotExist:
        raise SubmissionNotFoundError(
            u"No submission matching uuid {}".format(submission_uuid)
        )
    except DatabaseError:
        error_msg = u"Could not retrieve student item: {} or submission {}.".format(
            submission_uuid
        )
        logger.exception(error_msg)
        raise SubmissionRequestError(msg=error_msg)

    score = ScoreSerializer(
        data={
            "student_item": submission_model.student_item.pk,
            "submission": submission_model.pk,
            "points_earned": points_earned,
            "points_possible": points_possible,
        }
    )
    if not score.is_valid():
        logger.exception(score.errors)
        raise SubmissionInternalError(score.errors)

    # When we save the score, a score summary will be created if
    # it does not already exist.
    # When the database's isolation level is set to repeatable-read,
    # it's possible for a score summary to exist for this student item,
    # even though we cannot retrieve it.
    # In this case, we assume that someone else has already created
    # a score summary and ignore the error.
    try:
        score_model = score.save()
        _log_score(score_model)
        # Send a signal out to any listeners who are waiting for scoring events.
        score_set.send(
            sender=None,
            points_possible=points_possible,
            points_earned=points_earned,
            anonymous_user_id=submission_model.student_item.student_id,
            course_id=submission_model.student_item.course_id,
            item_id=submission_model.student_item.item_id,
        )
    except IntegrityError:
        pass
Esempio n. 4
0
File: api.py Progetto: ctpad/edx-tim
def set_score(student_item, submission, score, points_possible):
    """Set a score for a particular student item, submission pair.

    Sets the score for a particular student item and submission pair. This score
    is calculated externally to the API.

    Args:
        student_item (dict): The student item associated with this score. This
            dictionary must contain a course_id, student_id, and item_id.
        submission (dict): The submission associated with this score. This
            dictionary must contain all submission fields to properly get a
            unique submission item.
        score (int): The score to associate with the given submission and
            student item.
        points_possible (int): The total points possible for this particular
            student item.

    Returns:
        (dict): The dictionary representation of the saved score.

    Raises:
        SubmissionInternalError: Thrown if there was an internal error while
            attempting to save the score.
        SubmissionRequestError: Thrown if the given student item or submission
            are not found.

    Examples:
        >>> student_item_dict = dict(
        >>>    student_id="Tim",
        >>>    item_id="item_1",
        >>>    course_id="course_1",
        >>>    item_type="type_one"
        >>> )
        >>>
        >>> submission_dict = dict(
        >>>    student_item=2,
        >>>    attempt_number=1,
        >>>    submitted_at=datetime.datetime(2014, 1, 29, 23, 14, 52, 649284, tzinfo=<UTC>),
        >>>    created_at=datetime.datetime(2014, 1, 29, 17, 14, 52, 668850, tzinfo=<UTC>),
        >>>    answer=u'The answer is 42.'
        >>> )
        >>> set_score(student_item_dict, submission_dict, 11, 12)
        {
            'student_item': 2,
            'submission': 1,
            'points_earned': 11,
            'points_possible': 12,
            'created_at': datetime.datetime(2014, 2, 7, 20, 6, 42, 331156, tzinfo=<UTC>)
        }

    """
    try:
        student_item_model = StudentItem.objects.get(**student_item)
        submission_model = Submission.objects.get(**submission)
    except DatabaseError:
        error_msg = u"Could not retrieve student item: {} or submission {}.".format(
            student_item, submission
        )
        logger.exception(error_msg)
        raise SubmissionRequestError(error_msg)

    score = ScoreSerializer(
        data={
            "student_item": student_item_model.pk,
            "submission": submission_model.pk,
            "points_earned": score,
            "points_possible": points_possible,
        }
    )
    if not score.is_valid():
        logger.exception(score.errors)
        raise SubmissionInternalError(score.errors)
    score.save()
    return score.data