Esempio n. 1
0
    def test_distance(self):
        # Test the distance function
        game = Game('default', 1000)

        # Exact match
        distance = game.sphere_distance(48.3515609, -1.204625999999962,
                                        48.3515609, -1.204625999999962)
        self.assertEquals(distance, 0)
Esempio n. 2
0
 def __init__(self, score_max_distance, leaderboard_answer_count,
              max_response_time, time_between_turns):
     """
     :param score_max_distance: The distance above which player scores will be null
     :param leaderboard_answer_count: How many answers are used to compute user scores in the leaderboard
     :param max_response_time: The time given to a player to answer a question
     :param between_turns_duration: The time between two turns
     """
     self.game = Game(score_max_distance, leaderboard_answer_count)
     self.max_response_time = max_response_time
     self.time_between_turns = time_between_turns
Esempio n. 3
0
    def test_distance(self):
        # Test the distance function
        game = Game('default', 1000)

        # Exact match
        distance = game.plane_distance(48.3515609, -1.204625999999962, 48.3515609, -1.204625999999962)
        self.assertEquals(distance, 0)

        # 6 km away
        distance = game.plane_distance(48.3515609, -1.204625999999962, 48.370431, -1.151591000000053)
        self.assertEquals(round(distance), 6)

        # More than a thousand km away
        distance = game.plane_distance(48.3515609, -1.204625999999962, 40.7127837, -74.00594130000002)
        self.assertEquals(round(distance), 8149)
Esempio n. 4
0
    def test_distance(self):
        # Test the distance function
        game = Game('default', 1000)

        # Exact match
        distance = game.plane_distance(48.3515609, -1.204625999999962,
                                       48.3515609, -1.204625999999962)
        self.assertEquals(distance, 0)

        # 6 km away
        distance = game.plane_distance(48.3515609, -1.204625999999962,
                                       48.370431, -1.151591000000053)
        self.assertEquals(round(distance), 6)

        # More than a thousand km away
        distance = game.plane_distance(48.3515609, -1.204625999999962,
                                       40.7127837, -74.00594130000002)
        self.assertEquals(round(distance), 8149)
Esempio n. 5
0
    def test_get_current_city(self):
        # Check that when a new turn is started the current city changes
        game = Game('default', 1000)

        game.start_new_turn()
        city1 = game.get_current_city()

        game.start_new_turn()
        city2 = game.get_current_city()

        self.assertNotEqual(city1, city2)
Esempio n. 6
0
    def test_score(self):
        # Test the scoring function
        game = Game('default', 1000, 1)

        # Exact match, really fast
        score = game.score(0)
        self.assertEquals(score, 1000)

        # Exact match but really slow
        score = game.score(0)
        self.assertEquals(score, 1000)

        # 6 km away but slow
        score = game.score(6)
        self.assertEquals(score, 994)

        # More than a thousand km away
        score = game.score(1000)
        self.assertEquals(score, 0)
Esempio n. 7
0
    def test_get_current_city(self):
        # Check that when a new turn is started the current city changes
        game = Game('default', 1000)

        game.start_new_turn()
        city1 = game.get_current_city()

        game.start_new_turn()
        city2 = game.get_current_city()

        self.assertNotEqual(city1, city2)
Esempio n. 8
0
    def create_game(self, game_id, score_max_distance, max_response_time, leaderboard_answer_count,
                    between_turns_duration):
        app.logger.debug('Starting a new game with the id {game_id}'.format(game_id=game_id))

        # Create the game
        game = Game(game_id, score_max_distance, max_response_time, leaderboard_answer_count, between_turns_duration)

        # Register it
        self.games.append(game)

        # Start the game
        socketio.start_background_task(target=self.run_game, game=game)

        return game
Esempio n. 9
0
    def test_score(self):
        # Test the scoring function
        game = Game('default', 1000, 1)

        # Exact match, really fast
        score = game.score(0)
        self.assertEquals(score, 1000)

        # Exact match but really slow
        score = game.score(0)
        self.assertEquals(score, 1000)

        # 6 km away but slow
        score = game.score(6)
        self.assertEquals(score, 994)

        # More than a thousand km away
        score = game.score(1000)
        self.assertEquals(score, 0)
Esempio n. 10
0
    def test_get_ranked_scores(self):
        # Test the ranking function
        game = Game('default', 1000)

        # Mock the get_current_city function to always return the same city
        game.get_current_city = lambda: {
            'latitude': 48.3515609,
            'longitude': -1.204625999999962
        }

        game.add_player('a', 'a')
        game.add_player('b', 'b')
        game.add_player('c', 'c')

        # Always return the correct answer for player a, a close answer for c and an answer far away for b
        for i in range(0, 30):
            game.start_new_turn()
            game.store_answer('a', 48.3515609, -1.204625999999962)
            game.store_answer('b', 0, 0)
            game.store_answer('c', 48.370431, -1.151591000000053)
            game.end_current_turn()

        self.assertEquals(game.get_ranked_scores()[0]['player'].sid, 'a')
        self.assertEquals(game.get_ranked_scores()[1]['player'].sid, 'c')
        self.assertEquals(game.get_ranked_scores()[2]['player'].sid, 'b')
        # Max score shouldn't be higher than 20000 because we limit to 20 turns to compute score
        self.assertEquals(game.get_ranked_scores()[0]['score'], 20000)
Esempio n. 11
0
    def test_get_current_turn_ranks(self):
        # Test the ranking function
        game = Game('default', 1000)

        # Mock the get_current_city function to always return the same city
        game.get_current_city = lambda: {
            'latitude': 48.3515609,
            'longitude': -1.204625999999962
        }

        game.add_player('a', 'a')
        game.add_player('b', 'b')
        game.add_player('c', 'c')

        game.store_answer('a', 48.3515609, -1.204625999999962)
        game.store_answer('b', 48.370431, -1.151591000000053)
        game.store_answer('c', 40.7127837, -74.00594130000002)

        game.end_current_turn()

        ranked_players = game.get_current_turn_ranks()

        self.assertEquals(ranked_players[0].sid, 'a')
        self.assertEquals(ranked_players[1].sid, 'b')
        self.assertEquals(ranked_players[2].sid, 'c')
Esempio n. 12
0
 def test_get_cities(self):
     # Check that a list of cities is returned
     cities = Game.get_cities()
     self.assertTrue(len(cities) > 0)
Esempio n. 13
0
    def test_get_ranked_scores(self):
        # Test the ranking function
        game = Game('default', 1000)

        # Mock the get_current_city function to always return the same city
        game.get_current_city = lambda: {
            'latitude': 48.3515609,
            'longitude': -1.204625999999962
        }

        game.add_player('a', 'a')
        game.add_player('b', 'b')
        game.add_player('c', 'c')

        # Always return the correct answer for player a, a close answer for c and an answer far away for b
        for i in range(0, 30):
            game.start_new_turn()
            game.store_answer('a', 48.3515609, -1.204625999999962)
            game.store_answer('b', 0, 0)
            game.store_answer('c', 48.370431, -1.151591000000053)
            game.end_current_turn()

        self.assertEquals(game.get_ranked_scores()[0]['player'].sid, 'a')
        self.assertEquals(game.get_ranked_scores()[1]['player'].sid, 'c')
        self.assertEquals(game.get_ranked_scores()[2]['player'].sid, 'b')
        # Max score shouldn't be higher than 20000 because we limit to 20 turns to compute score
        self.assertEquals(game.get_ranked_scores()[0]['score'], 20000)
Esempio n. 14
0
    def test_get_current_turn_ranks(self):
        # Test the ranking function
        game = Game('default', 1000)

        # Mock the get_current_city function to always return the same city
        game.get_current_city = lambda: {
            'latitude': 48.3515609,
            'longitude': -1.204625999999962
        }

        game.add_player('a', 'a')
        game.add_player('b', 'b')
        game.add_player('c', 'c')

        game.store_answer('a', 48.3515609, -1.204625999999962)
        game.store_answer('b', 48.370431, -1.151591000000053)
        game.store_answer('c', 40.7127837, -74.00594130000002)

        game.end_current_turn()

        ranked_players = game.get_current_turn_ranks()

        self.assertEquals(ranked_players[0].sid, 'a')
        self.assertEquals(ranked_players[1].sid, 'b')
        self.assertEquals(ranked_players[2].sid, 'c')
Esempio n. 15
0
 def test_get_cities(self):
     # Check that a list of cities is returned
     cities = Game.get_cities()
     self.assertTrue(len(cities) > 0)
Esempio n. 16
0
class GameMaster:
    """
    Starts the game and manages the game lifecycle
    """
    def __init__(self, score_max_distance, leaderboard_answer_count,
                 max_response_time, time_between_turns):
        """
        :param score_max_distance: The distance above which player scores will be null
        :param leaderboard_answer_count: How many answers are used to compute user scores in the leaderboard
        :param max_response_time: The time given to a player to answer a question
        :param between_turns_duration: The time between two turns
        """
        self.game = Game(score_max_distance, leaderboard_answer_count)
        self.max_response_time = max_response_time
        self.time_between_turns = time_between_turns

    def start_game(self):
        # Start the game
        socketio.start_background_task(target=self.run_game)

    def run_game(self):
        while True:
            # Start a new turn
            self.start_turn()

            # Give the players some time to answer
            socketio.sleep(self.max_response_time)

            # End the turn
            self.end_turn()

            # Send the new leaderboard to players
            self.update_leaderboard()

            # Give the user some time between two turns
            socketio.sleep(self.time_between_turns)

    def start_turn(self):
        app.logger.debug('Starting new turn')

        # Start a new turn
        self.game.start_new_turn()

        # Get the city for this turn
        city = self.game.get_current_city()

        # Send the infos on the new city to locate to every players in the game
        socketio.emit(
            'new_turn',
            {
                'city': city['name'],
                'country': city['country'],
                'country_code': city['country'],
            },
        )

    def end_turn(self):
        app.logger.debug('Ending turn')

        # End current turn
        self.game.end_current_turn()

        # Rank answers
        ranked_players = self.game.get_current_turn_ranks()
        player_count = len(ranked_players)

        # Send end of turn signal and correct/best answers to players
        city = self.game.get_current_city()
        turn_results = {
            'correct_answer': {
                'name': city['name'],
                'country': city['country'],
                'lat': city['latitude'],
                'lng': city['longitude'],
            }
        }

        if player_count > 0:
            best_result = ranked_players[0].get_result(self.game.turn_number)
            best_answer = ranked_players[0].get_answer(self.game.turn_number)
            turn_results['best_answer'] = {
                'distance': best_result.distance,
                'lat': best_answer.latitude,
                'lng': best_answer.longitude
            }

        socketio.emit('end_of_turn', turn_results)

        # Then send individual player results
        for rank, player in enumerate(ranked_players):
            result = player.get_result(self.game.turn_number)
            answer = player.get_answer(self.game.turn_number)
            socketio.emit('player_results', {
                'rank': rank + 1,
                'total': player_count,
                'distance': result.distance,
                'score': result.score,
                'lat': answer.latitude,
                'lng': answer.longitude,
            },
                          room=player.sid)

    def update_leaderboard(self):
        app.logger.debug('Updating leaderboard')

        # Get a sorted list of all the scores
        scores = self.game.get_ranked_scores()
        top_ten = [{
            'player_name': score['player'].name,
            'score': score['score']
        } for score in scores[:10]]

        # Number of players
        total_player = len(scores)

        # Send top ten + player score and rank to each player
        for rank, score in enumerate(scores):
            socketio.emit('leaderboard_update', {
                'top_ten': top_ten,
                'total_player': total_player,
                'player_rank': rank,
                'player_score': score['score'],
            },
                          room=score['player'].sid)
Esempio n. 17
0
class GameMaster:
    """
    Starts the game and manages the game lifecycle
    """
    def __init__(self, score_max_distance, leaderboard_answer_count,
                 max_response_time, time_between_turns):
        """
        :param score_max_distance: The distance above which player scores will be null
        :param leaderboard_answer_count: How many answers are used to compute user scores in the leaderboard
        :param max_response_time: The time given to a player to answer a question
        :param between_turns_duration: The time between two turns
        """
        self.game = Game(score_max_distance, leaderboard_answer_count)
        self.max_response_time = max_response_time
        self.time_between_turns = time_between_turns

    def start_game(self):
        # Start the game
        socketio.start_background_task(target=self.run_game)

    def run_game(self):
        while True:
            # Start a new turn
            self.start_turn()

            # Give the players some time to answer
            socketio.sleep(self.max_response_time)

            # End the turn
            self.end_turn()

            # Send the new leaderboard to players
            self.update_leaderboard()

            # send the new legend to players (only joining and leaving changes it)
            self.update_legend()

            # Give the user some time between two turns
            socketio.sleep(self.time_between_turns)

    def start_turn(self):
        app.logger.debug('Starting new turn')

        # Start a new turn
        self.game.start_new_turn()

        # Get the city for this turn
        city = self.game.get_current_city()

        # Send the infos on the new city to locate to every players in the game
        socketio.emit(
            'new_turn',
            {
                'city': city['name'],
                'country': city['country'],
                'country_code': city['country'],
            },
        )

    def end_turn(self):
        app.logger.debug('Ending turn')

        # End current turn
        self.game.end_current_turn()

        # Rank answers
        ranked_players = self.game.get_current_turn_ranks()
        player_count = len(ranked_players)

        # Send end of turn signal and correct/best answers to players
        city = self.game.get_current_city()
        turn_results = {
            'correct_answer': {
                'name': city['name'],
                'lat': city['latitude'],
                'lng': city['longitude'],
            }
        }

        if player_count > 0:
            answers = []
            for i, p in enumerate(ranked_players):
                p_result = p.get_result(self.game.turn_number)
                p_answer = p.get_answer(self.game.turn_number)
                p_emit = {
                    'sid': p.sid,
                    'name': p.name,
                    'distance': p_result.distance,
                    'lat': p_answer.latitude,
                    'lng': p_answer.longitude,
                }
                try:
                    p_emit['color'] = self.game.colors_mapped[p.sid][1]
                except KeyError:
                    p_emit['color'] = 'grey'
                answers.append(p_emit)
            turn_results['answers'] = answers
        # if player_count > 0:
        #     best_player = ranked_players[0]
        #     best_result = best_player.get_result(self.game.turn_number)
        #     best_answer = best_player.get_answer(self.game.turn_number)
        #     turn_results['best_answer'] = {
        #         'sid': best_player.sid,
        #         'name': best_player.name,
        #         'distance': best_result.distance,
        #         'lat': best_answer.latitude,
        #         'lng': best_answer.longitude
        #     }
        #     if player_count > 1:
        #         other_answers = []
        #         for i, p in enumerate(ranked_players[1:]):
        #             p_result = p.get_result(self.game.turn_number)
        #             p_answer = p.get_answer(self.game.turn_number)
        #             p_emit = {
        #                 'sid': p.sid,
        #                 'name': p.name,
        #                 'distance': p_result.distance,
        #                 'lat': p_answer.latitude,
        #                 'lng': p_answer.longitude,
        #             }
        #             if len(ranked_players) <= 6:
        #                 p_emit['color'] = self.game.colors_mapped[p.sid][1]
        #             other_answers.append(p_emit)
        #
        #         turn_results['other_answers'] = other_answers

        socketio.emit('end_of_turn', turn_results)

        # Then send individual player results
        # for rank, player in enumerate(ranked_players):
        #     result = player.get_result(self.game.turn_number)
        #     answer = player.get_answer(self.game.turn_number)
        #     socketio.emit('player_results',
        #                   {
        #                       'rank': rank + 1,
        #                       'total': player_count,
        #                       'distance': result.distance,
        #                       'score': result.score,
        #                       'lat': answer.latitude,
        #                       'lng': answer.longitude,
        #                   },
        #                   room=player.sid)

    def update_leaderboard(self):
        app.logger.debug('Updating leaderboard')

        # Get a sorted list of all the scores
        scores = self.game.get_ranked_scores()
        top_ten = [{
            'player_name': score['player'].name,
            'score': score['score']
        } for score in scores[:10]]

        # Number of players
        total_player = len(scores)

        # Send top ten + player score and rank to each player
        for rank, score in enumerate(scores):
            socketio.emit('leaderboard_update', {
                'top_ten': top_ten,
                'total_player': total_player,
                'player_rank': rank,
                'player_score': score['score'],
            },
                          room=score['player'].sid)

    def update_legend(self):
        app.logger.debug('Updating legend')

        legend_changes = []

        ranks = self.game.get_current_turn_ranks()
        for p in ranks:
            p_name, p_color = self.game.colors_mapped[p.sid]
            legend_changes.append(
                (p_name, p_color,
                 p.get_result(self.game.turn_number).distance))

        # for player_sid, player_name_and_color in self.game.colors_mapped.items():
        #     legend_item = [player_name_and_color[1], player_name_and_color[0]]
        #     if len(current_turn_players_results) > 0:
        #         legend_item.append(current_turn_players_results[player_sid])
        #     else:
        #         legend_item.append(0)
        #     legend_changes.append(legend_item)
        socketio.emit('legend_changes', legend_changes)