Esempio n. 1
0
 def basic(self, commit=False, n=None, **kwargs):
     if n:
         return [self.basic(commit=commit, **kwargs) for _ in range(n)]
     game = Game(width=20,
                 height=20,
                 max_turns_to_next_food_spawn=12,
                 **kwargs)
     if commit:
         game.save()
     return game
Esempio n. 2
0
    def start_game(self, snake_ids):
        """ Start a game given a tuple of snake id's. Returning a game id. """
        if len(snake_ids) == 1:
            return

        game = Game(width=11, height=11, max_turns_to_next_food_spawn=12)
        game.save()

        logger.info(f"starting game id={game.id}")

        for s in Snake.objects.filter(id__in=snake_ids):
            game.snakes.add(s)
            GameSnake.objects.create(snake=s, game=game)

        game.save()
        game.create()
        game.run()
        GameLeaderboard(game=game).save()
Esempio n. 3
0
    def create(self, *args, **kwargs):
        heat = kwargs.get("heat")
        previous_game = heat.latest_game
        skip = [w.snake.id for w in heat.winners]
        if previous_game is not None:
            if previous_game.winner is None:
                raise PreviousGameTiedException()
            skip.append(previous_game.winner.snake.id)
            next_snakes = [
                sh.snake for sh in previous_game.snakes
                if sh.snake.id not in skip
            ]
        else:
            next_snakes = [sh.snake for sh in heat.snakes]

        max_turns = 15
        if heat.round.tournament_bracket.board_max_turns_to_next_food_spawn is not None:
            max_turns = heat.round.tournament_bracket.board_max_turns_to_next_food_spawn

        game = Game(
            width=heat.round.tournament_bracket.board_width,
            height=heat.round.tournament_bracket.board_height,
            max_turns_to_next_food_spawn=max_turns,
            engine_url=heat.round.tournament_bracket.tournament.engine_url,
        )
        game.save()

        snake_ids = [snake.id for snake in next_snakes]
        snakes = (TournamentSnake.objects.filter(
            snake__id__in=snake_ids,
            bracket=heat.round.tournament_bracket).prefetch_related(
                "snake").prefetch_related("team"))
        for ts in snakes:
            game.snakes.add(ts.snake)
            GameSnake.objects.create(snake=ts.snake,
                                     game=game,
                                     name=ts.team.name)
        game.save()
        game.create()

        return super(HeatGameManager, self).create(*args, **kwargs, game=game)
Esempio n. 4
0
 def setUp(self):
     self.game_ip = Game.objects.get(name='Game One')
     self.game_r = Game.objects.get(name='Game Two')
     self.game_s = Game.objects.get(name='Game Three')
     self.game_r2 = Game.objects.get(name='Game Four')
     self.girl1 = Person.objects.get(username='******')
     self.girl2 = Person.objects.get(username='******')
     self.girl3 = Person.objects.get(username='******')
     self.girl4 = Person.objects.get(username='******')
     self.man1 = Person.objects.get(username='******')
     self.man2 = Person.objects.get(username='******')
     self.man3 = Person.objects.get(username='******')
     self.man4 = Person.objects.get(username='******')
     
     # Create game that is being initialised
     self.game_init = Game(
         name = "Game Initialising A",
         owner = self.girl1,
         status = GameStatus.objects.initialising,
         max_rounds = 4,
         max_players = 10,
     )
     self.game_init.save()
Esempio n. 5
0
class GameTestCase(TestCase):
    fixtures = ['players.json', 'basic_games.json']
    
    def setUp(self):
        self.game_ip = Game.objects.get(name='Game One')
        self.game_r = Game.objects.get(name='Game Two')
        self.game_s = Game.objects.get(name='Game Three')
        self.game_r2 = Game.objects.get(name='Game Four')
        self.girl1 = Person.objects.get(username='******')
        self.girl2 = Person.objects.get(username='******')
        self.girl3 = Person.objects.get(username='******')
        self.girl4 = Person.objects.get(username='******')
        self.man1 = Person.objects.get(username='******')
        self.man2 = Person.objects.get(username='******')
        self.man3 = Person.objects.get(username='******')
        self.man4 = Person.objects.get(username='******')
        
        # Create game that is being initialised
        self.game_init = Game(
            name = "Game Initialising A",
            owner = self.girl1,
            status = GameStatus.objects.initialising,
            max_rounds = 4,
            max_players = 10,
        )
        self.game_init.save()
    
    def testCanRegister(self):
        """
        Tests if someone can register for a game.
        If the same is in progress, it can't register new people.
        If the person is a girl, she can register.
        If the man is already in the game, he can't register.
        """
        
        self.assertEquals(self.game_ip.can_register(self.girl1), False)
        self.assertEquals(self.game_ip.can_register(self.man1), False)
        self.assertEquals(self.game_ip.can_register(self.girl2), False)
        self.assertEquals(self.game_ip.can_register(self.man4), False)
        
        self.assertEquals(self.game_r.can_register(self.girl1), False)
        self.assertEquals(self.game_r.can_register(self.man1), True)
        self.assertEquals(self.game_r.can_register(self.girl2), False)
        self.assertEquals(self.game_r.can_register(self.man4), False)
    
    def testRoundIsActive(self):
        """
        Test that the is_active function of a round
        is working.
        """
        
        r = self.game_s.active_round()
        self.assertTrue(r.is_active(self.man1))
        self.assertRaises(GameError, r.is_active, self.man4)
        
    def testRoundIsEliminated(self):
        """
        Test that the is_eliminated function of a round
        is working.
        """
        
        r = self.game_s.active_round()
        self.assertFalse(r.is_eliminated(self.man1))
        self.assertRaises(GameError, r.is_active, self.man4)
    
    def testActiveQuestion(self):
        """
        Test that an active question can be found
        """
        
        self.assertEquals(self.game_ip.get_active_question().question, "What is your best dance move?")
        
        # Registering games should not have an active round
        self.assertIsNone(self.game_r.get_active_question())
        
    def testActiveRound(self):
        """
        Test that an active round can be found
        """
        
        self.assertEquals(self.game_ip.active_round().__class__, Round)
        self.assertEquals(self.game_ip.active_round().number, 1)
        self.assertIsNone(self.game_r.active_round(), None)
        
    def testStart(self):
        """
        Test starting a game. When a game starts
        it should:
        
        - have it's status set to active
        - have the first round set to state answering
        - have all players registered in the game set
        to state active
        - enroll all registered players into the first
        round and set them to active
        - update the current round from 0 to 1
        
        If the game is not full it cannot be started. A
        GameError should be thrown.
        
        """
        
        # Attempt to start a non-full game.
        self.assertRaises(GameError, self.game_r.start)
        
        # Attempt to start a game already in progress
        self.assertRaises(GameError, self.game_ip.start)
        
        game = self.game_r2
        game.start()
        
        # Ensure the current round has been set
        self.assertEquals(game.current_round, 1)
        
        # Ensure the active round has been set up
        active_round = game.active_round()
        self.assertIsNotNone(active_round)
        self.assertEquals(active_round.number, 1)
        self.assertIsNotNone(active_round.question)
    
        # Ensure the active round has the players
        # enrolled in it
        players = game.registered_players()
        round_players = active_round.registered_players()
        self.assertEquals(len(players), len(round_players))
        for p in players:
            self.assertTrue(p in round_players)

        # Ensure player have active status
        # TODO
        pass
    
    def testHasAnswered(self):
        """
        Test is a user has answered a question in a game round
        """
        
        round = self.game_ip.active_round()
        
        # Man 1 is in the game but hasn't answered any questions,
        # so should be allowed to
        self.assertEquals(round.has_answered(self.man1), False)
    
        # Man 4 is not in this game, so an error should be raised
        self.assertRaises(GameError, round.has_answered, self.man4)
    
    def testCanAnswer(self):
        """
        Test is a user can answer a question in a game.
        """
        
        # If the method is called on a game not in
        # progress, an error should be thrown
        self.assertEquals(self.game_r.can_answer(self.man1), False)
        
        # If a game is in progress, but the active round
        # is in the scoring state, the user cannot answer
        self.assertEquals(self.game_s.can_answer(self.man1), False)
        
        # A girl cannot answer questions
        self.assertEquals(self.game_ip.can_answer(self.girl1), False)
        
        # A person not involved in the game should
        # not be able to answer
        self.assertEquals(self.game_ip.can_answer(self.man4), False)
        
        # A person in this game who has not given an
        # answer should be able to
        self.assertEquals(self.game_ip.can_answer(self.man1), True)
        
        # A person who has already given an answer in this
        # round should not be able to answer
        
        # A person involved in the game but who has
        # been eliminated should not be allowed to answer
        membership = self.man1.roundmembership_set.get(round=self.game_ip.active_round())
        membership.status = PlayerStatus.objects.eliminated
        membership.save()
        self.assertEquals(self.game_ip.can_answer(self.man1), False)

    def testInitialiseRounds(self):
        """
        Test the initialisation of a game rounds.
        After a game has been initialised it should
        have the following properties.
        
        - n pending rounds associated with it, where n is equal
        to game.max_rounds
        - game.current_round equal to 0
        - game should be in a pending state
        - a question associated with each of the rounds
        - if too many questions are passed in, the game should throw
        an initialisation error
        """
        
        # Test standard game initialisation
        game = self.game_init
        questions = [(1, 'q1'), (2, 'q2'), (3, 'q3'), (4, 'q4')]
        game.initialise(questions)
        
        self.assertEquals(game.current_round, 0)
        self.assertEquals(game.status, GameStatus.objects.registering)
        self.assertEquals(game.round_set.count(), 4)
        
        # Ensure all rounds have been correctly initialised
        for i, r in enumerate(game.round_set.all()):
            self.assertEquals(r.number, i+1)
            self.assertIsNotNone(r.question)
            self.assertEquals(r.question.question, questions[i][1])
            
        # Ensure game is now in registering state
        self.assertEquals(game.status, GameStatus.objects.registering)
        
    def testInitialiseWrongQuestions(self):
        """
        Test that an error is thrown if an invalid number of
        questions is passed to the initialise function.
        """

        game = self.game_init
        too_many_questions = [(1, 'q1'), (2, 'q2'), (3, 'q3'), (4, 'q4'), (5, 'q5')]
        too_few_questions = [(1, 'q1'), (2, 'q2')]
        self.assertRaises(GameError, game.initialise, too_many_questions)
        self.assertRaises(GameError, game.initialise, too_few_questions)
        self.assertRaises(GameError, game.initialise, None)
    
    def testDeleteGame(self):
        """
        Ensure that when registering games are deleted, the
        rounds and questions are deleted to. Any preset questions
        should not be deleted.
        """
    
    def testAdvanceToScoring(self):
        """
        Test game state change from
        in progress round to scoring round.
        
        When this happens, the currently
        active round should change to 'scoring'
        state.
        
        Players who have not responded should
        be given a score of zero and a no_show
        status.
        """
        
        game = self.game_ip
        game.advance_to_scoring()
        
        # After advancing, the game should be in scoring state
        self.assertEquals(game.is_scoring, True)
        
        # After advancing, man1 and man2 should have
        # been set to no_show and given a score of zero
        self.assertEquals(game.active_round().score(self.man1), 0)
        self.assertEquals(game.active_round().score(self.man2), 0)
        
        # Man3 should not have been given a score yet
        self.assertIsNone(game.active_round().score(self.man3))
        
        # The active round should be in state scoring
        self.assertEquals(game.active_round().status, RoundStatus.objects.scoring)

        # A game already in the scoring phase, cannot advance to scoring, so
        # raise an error
        self.assertRaises(GameError, game.advance_to_scoring)
        
    def testAdvanceRound(self):
        """
        Test advancing a game round. Rounds
        should only be advanced when they are in the
        active round is in the scoring phase.
        
        Before advancing, any players who have not
        have their answers scored should be given
        a score of full marks.
        """
        
        # Advance a game from the scoring phase.
        # The current_round variable should increase
        # by one, the round should be set to completed,
        # and the new round should be set to answering
        game = self.game_s
        r = game.active_round()
        n = game.current_round
        game.advance_round()
        self.assertEquals(game.current_round, n+1)
        self.assertEquals(game.round_set.get(number=n).status, RoundStatus.objects.completed)
        self.assertEquals(game.active_round().status, RoundStatus.objects.answering)
        
        # Ensure that players whose answers were not rated in time
        # are given top marks.
        self.assertEquals(r.score(self.man1), 100)
        
        # Ensure that the new round memberships have been created
        self.assertTrue(game.active_round().is_active(self.man1))
        
        # Games that are not active with the round in the
        # scoring phase should thow an error
        # if you attempt to advance them
        self.assertRaises(GameError, self.game_r.advance_round)
        self.assertRaises(GameError, self.game_ip.advance_round)

    def testTick(self):
        
        # Attempt to advance a game from scoring phase
        r = self.game_s.active_round()
        n = self.game_s.current_round
        self.assertTrue(self.game_s.tick())
        self.assertEquals(self.game_s.current_round, n+1)
        old_r = self.game_s.round_set.get(number=r.number)
        self.assertEquals(old_r.status, RoundStatus.objects.completed)
        new_r = self.game_s.round_set.get(number=r.number+1)
        self.assertEquals(new_r.status, RoundStatus.objects.answering)
        
        # Test advancing a game from answering phase
        n = self.game_ip.current_round
        self.assertTrue(self.game_ip.tick())
        self.assertEquals(self.game_ip.current_round, n)
        
        # Test advancing a game that is not in progress
        self.assertFalse(self.game_init.tick())
        self.assertFalse(self.game_r.tick())
        
    def testEnroll(self):
        """
        Test the enroll process.
        """
        
        # Attempt to register someone in a game
        # that is already full
        self.assertRaises(EnrollFailed, self.game_r2.enroll, self.man1)
        
        # Attempt to register someone in a game
        # they are already registered for
        self.assertRaises(EnrollFailed, self.game_r.enroll, self.man4)
        
        # Attempt to register a girl in a game
        self.assertRaises(EnrollFailed, self.game_r.enroll, self.girl1)
        
        # Attempt to register someone in a game
        # that has already started
        self.assertRaises(EnrollFailed, self.game_ip.enroll, self.man1)
        self.assertRaises(EnrollFailed, self.game_s.enroll, self.man1)

        # Register someone in a valid game
        self.game_r.enroll(self.man1)
        players = self.game_r.registered_players()
        self.assertTrue(self.man1 in players)
        
    def testEliminate(self):
        """
        When someone is eliminated, their status
        in the game and the round should be set
        to eliminated.
        
        People can only be eliminated in the
        scoring phase of a round.
        """
        
        game = self.game_s
        game.eliminate(self.man1)
        self.assertTrue(game.is_eliminated(self.man1))
        self.assertTrue(game.active_round().is_eliminated(self.man1))
        
        # Attempt to elimiante someone who is not in the
        # game.
        game.eliminate(self.man4)