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
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