def test_score_per_frame__success__open_frame(self):
     score_per_frame = game_models.ScorePerFrame(game=self.game_object,
                                                 first_attempt_score='2',
                                                 second_attempt_score='4',
                                                 third_attempt_score=0,
                                                 frame=1,
                                                 frame_version=1,
                                                 frame_score=10)
     score_per_frame.save()
     serializer_instance = serializers.ScorePerFrameSerializer(
         score_per_frame)
     assert serializer_instance.data == {
         'game': 'abcde12345',
         'frame': 1,
         'frame_score': 6,
         'total_score_for_frame': 6
     }
 def test_score_per_frame__failure(self):
     score_per_frame = game_models.ScorePerFrame(first_attempt_score=5,
                                                 second_attempt_score=5,
                                                 third_attempt_score=0,
                                                 frame=1,
                                                 frame_version=1,
                                                 frame_score=10)
     score_per_frame.add_error(
         game_models.Error(error_code=400,
                           error_message='Game has already been played.'))
     errors = {
         'errors': [{
             'error_code': 400,
             'error_message': 'Game has already been played.'
         }]
     }
     expected = collections.OrderedDict(errors)
     serializer_instance = serializers.ScorePerFrameSerializer(
         score_per_frame)
     assert serializer_instance.data == expected
示例#3
0
def set_frame_score(score_queryset, game_id, score):
    """Sets the frame score for a valid game.

    The implementation executes the following:

    1. load the game object associated with game id; if the game does not exist
    then raise a 404 error.

    2. fetch the number of frames that have been played so far. If the number of
    frames played equals "10", i.e. the game is over, then a 400 error is raised

    3. If the score format is valid, then and no frames have been played, then
       a frame is created and the score calculated.
    """
    try:
        with transaction.atomic(savepoint=False):
            # If the game has not been created, then return a 404.
            game_object, game_object_created = _get_game_object(
                game_id, game_models.ScorePerFrame)
            if not game_object_created:
                # Error object is returned
                return game_object

            if not _is_valid_score(score):
                frame_score = game_models.ScorePerFrame()
                frame_score.add_error(
                    game_models.Error(
                        error_code=400,
                        error_message='Score format: {} is invalid.'.format(
                            score)))
                return frame_score

            spf_qs = score_queryset.filter(game=game_object)
            if not spf_qs or len(spf_qs) == 0:
                # First frame.

                (first_score, second_score,
                 third_score) = _parse_score(score, 1)
                bowling_frame = game_object.game_score.create(
                    frame=1,
                    first_attempt_score=first_score,
                    second_attempt_score=second_score,
                    third_attempt_score=third_score,
                    frame_version=1)
                return bowling_frame

            # If the game has been completed, then return a 400.
            number_of_played_frames = spf_qs.aggregate(
                django_models.Max('frame')).get('frame__max', 0)

            if number_of_played_frames == 10:
                frame_score = game_models.ScorePerFrame()
                frame_score.add_error(
                    game_models.Error(
                        error_code=400,
                        error_message='Game:\'{}\' has already been played.'.
                        format(game_id)))
                return frame_score

            # Parse the score, and check if the version has been created.
            (first_score, second_score,
             third_score) = _parse_score(score, number_of_played_frames + 1)
            version_number_tuple = spf_qs.filter(game=game_object).filter(
                frame=number_of_played_frames +
                1).values_list('frame_version').first()
            (version_number, ) = (version_number_tuple if version_number_tuple
                                  is not None else (0, ))
            # Update the frame by to indicate a new frame is being played.
            score_per_frame = game_object.game_score.create(
                first_attempt_score=first_score,
                second_attempt_score=second_score,
                third_attempt_score=third_score,
                frame=number_of_played_frames + 1,
                frame_version=version_number + 1)
            return score_per_frame
    except:
        logging.exception(('Unable to save the frame for score {}'
                           ' and game:{}.'.format(score, game_id)))
        frame_score = game_models.ScorePerFrame()
        frame_score.add_error(
            game_models.Error(
                error_code=500,
                error_message=('Unable to save score: \'{score}\' for game: '
                               '\'{game}\'.'.format(game=game_id,
                                                    score=score))))
        return frame_score