예제 #1
0
def register_player(player):
    """
        We keep a list of player in our redis in order to check things like ownership
        between player and user and to be able to enumerate all known players. This
        Redis key serves as an index

        :param player: Dictionary of player
        :return: True player was successfully registered
    """

    players_data = redis.get('players')
    players = []
    # If there are no players, then we create an empty list
    if players_data is not None:
        players = json.loads(players_data.decode('utf-8'))
    players.append(player)
    redis.set('players', json.dumps(players))
    # Now we create a board for the player once it has been registered on a game
    board = Board(player_id=player['player_id'],
                  game_id=player['game_id'],
                  board_id=player['board_id'],
                  persistence_provider=redis)
    board.expand()
    board.save()
    # Release the memory allocation to keep low overhead
    board = None
    players = None
    return True
예제 #2
0
def update_game_index(game_id, gameinfo):
    """
        Updates the persistence provider, removing a spot from it

        :param game_id: Game id
        :param gameinfo: full static metadata of a game
        :return: True if game was successfully updated
    """
    games_data = persistence_provider.get('games')
    games = []
    newgames = []
    # If there are no games, then we create an empty list
    if games_data is not None:
        games = json.loads(games_data.decode('utf-8'))
        key = None
        try:
            for game in games:
                if game_id == game["game_id"]:
                    newgames.append(gameinfo)
                else:
                    newgames.append(game)
        except:
            return False
    persistence_provider.set('games', json.dumps(newgames))
    games = None
    newgames = None
    return True
예제 #3
0
def get_board(board_id):
    """
        This endpoint allows a user to get it's current board. This method will only allow
        the player's own board. If another player's board is attempted to access, then a
        401 Not authorized error code should be returned.
        :return: A json representation of the player's board.
    """
    if board_id is not None:
        # Check current identity matches owner of the board.
        board_data = redis_store.get(board_id)
        board = json.loads(board_data)
        if verify_ownership(player_id=board['player_id'],
                            user_id=current_identity.id):
            # If the user is the actual owner of the board, then we can provide the complete
            # and updated representation of the board.
            board = Board(game_id=board['game_id'],
                          player_id=board['player_id'],
                          board_id=board_id,
                          persistence_provider=redis_store)
            board.load(board_data)
            result = board.export_state()
            board = None
            return jsonify(result), 200
        return jsonify({
            "Error":
            True,
            "Message":
            "You are not the owner of the requested board. Only owner can request he's board"
        }), 401
    return jsonify({
        "Error": True,
        "Message": "No board id provided"
    }), int(HTTPStatus.BAD_REQUEST)
예제 #4
0
def update_player_index(player_id, player_info):
    """
        Updates the persistence provider, removing a spot from it

        :param player_id: Player id
        :param player_info: full static metadata of a player
        :return: True if game was successfully updated
    """
    players_data = redis.get('players')
    players = []
    newplayers = []
    # If there are no games, then we create an empty list
    if players_data is not None:
        players = json.loads(players_data.decode('utf-8'))
        key = None
        try:
            for player in players:
                if player_id == player["player_id"]:
                    newplayers.append(player_info)
                else:
                    newplayers.append(player)
        except:
            return False
    redis.set('players', json.dumps(newplayers))
    players = None
    newplayers = None
    return True
예제 #5
0
def get_redis_status():
    """
        in order to check current REDIS status, we will submit some data and then 
        we will try to retrieve it just to verify we can successfully create a 
        connection with the REDIS Store.
        :return: JSON object with result 
    """
    # First we save some data to a given key
    redis_store.set("Battleship Version", "v1")
    redis_store.set("Battleship Stack", "Python + Flask + REDIS + MongoDB")

    # Now we retrieve the data

    result = {
        "Battleship Version": redis_store.get("Battleship Version"),
        "Stack": redis_store.get("Battleship Stack"),
        "Redis Status": "OK"
    }
    return jsonify(result), int(HTTPStatus.OK)
def get_player(player_id):
    """
        Searches the REDIS index and loads the instance of player associated to
        the given player id.
        :param player_id: The id of the player to load
    """
    player_data = redis.get(player_id)
    if player_data is not None:
        player = Player(None, None, redis)
        player.load(player_id)
        return player
    return None
예제 #7
0
def get_game_list():
    availible_games = []
    games_data = persistance_provider.get('games')
    if games_data is not None:
        games = json.loads(games_data)
        try:
            for game in games:
                if game["game_status"] == str(GameStatus.WAITING_FOR_PLAYERS):
                    availible_games.append(game)
            return jsonify(availible_games)
        except:
            return jsonify({"Error": "Unable to fetch games"
                            }), HTTPStatus.INTERNAL_SERVER_ERROR
    return jsonify({"Error":
                    "No games found, create a new one?"}), HTTPStatus.NOT_FOUND
예제 #8
0
def register_game(game):
    """
        We keep a list of games in our persistence_provider in order to check things open spots in game
        and to be able to enumerate all known games. This
        game
        persistence_provider key serves as an index
        :param game: Dictionary of game
        :return: True game was successfully registered
    """
    games_data = persistence_provider.get('games')
    games = []
    # If there are no games, then we create an empty list
    if games_data is not None:
        games = json.loads(games_data.decode('utf-8'))
    games.append(game)
    persistence_provider.set('games', json.dumps(games))
    games = None
    return True
예제 #9
0
def verify_ownership(player_id, user_id):
    """
        Checks on the players index if a given player id is owned by the given user id.
        :param player_id: The id of the player
        :param user_id:  The user who supposedly owns the given player id
        :return:
    """
    players_data = redis.get('players')
    players = []
    # If there are no players, then we create an empty list
    if players_data is not None:
        app.logger.info('Reading players data... for player: [' + player_id +
                        '] with user: [' + user_id + ']')
        players = json.loads(players_data)
        app.logger.info('Players loaded... List: ' + json.dumps(players))
    try:
        for player in players:
            if player['player_id'] == player_id and player[
                    'user_id'] == user_id:
                return True
        return False
    except:
        return False
예제 #10
0
def post_torpedo(board_id):
    """
        ---------------------------------------------------------------------------------
        This method allows to drop a torpedo in a given pair of coordinates on a board belonging
        to an opponent that is currently playing within the same game instance. The boards are
        uniquely identified by a key.

        In order to specify the coordinates that are going to indicate the location where
        the torpedo is going to be sent, the following payload must be provided (example
        values):

            {
                "x_coordinate": 3,
                "y_coordinate": 4,
                "shooter": "56c142a9-8946-4b50-9e12-e12867573d3f"
            }

        :param board_id: The id of the board to where the
        :return: A json payload containing the result of the bombing operation in the
                 given board.
        ---------------------------------------------------------------------------------
    """

    torpedo_coordinates = request.get_json()
    board_data = redis_store.get(board_id)

    # First we check if the board instance actually exists within redis store.
    app.logger.info('Checking board...')
    if board_data is not None:
        brt = json.loads(board_data.decode('utf-8'))
        # Next we verify the user is not trying to send torpedo to his own board.

        board = Board(game_id=brt['game_id'],
                      player_id=brt['player_id'],
                      board_id=brt['board_id'],
                      persistence_provider=redis_store)

        app.logger.info('Instantiating board...')
        board.load(board_data)

        app.logger.info('board loaded with data: ' + str(board_data))

        app.logger.info('Getting shooter...')
        shooter = get_player(torpedo_coordinates['shooter'])

        app.logger.info('Getting receiver...')
        receiver = get_player(board.get_player_id())

        if board.get_owner_id(
        ) != current_identity.id and current_identity.id == shooter.get_owner(
        ):
            app.logger.info('Valid shooter shooting valid board')

            game = Game(None, None, persistence_provider=redis_store
                        )  #instace as null to later load from id
            game.load(game_id=brt['game_id'])

            if game.static_metadata(
            )["moves_next"] != torpedo_coordinates['shooter']:
                return jsonify(
                    ErrorResponse(
                        'Trying to shoot when its not your turn',
                        'You are trying to shoot but its not your turn').get()
                ), int(HTTPStatus.BAD_REQUEST)

            if torpedo_coordinates is not None:
                result = board.shoot(torpedo_coordinates['x_coordinate'],
                                     torpedo_coordinates['y_coordinate'])

                if result >= 0:
                    # We update the state on the redis store
                    board.save()
                    app.logger.info('Torpedo was sent: shooter: [' +
                                    current_identity.id +
                                    '] destination ->> [' +
                                    board.get_player_id() + ']')
                    if not shooter.is_alive() or not receiver.is_alive():
                        app.logger.error(
                            'Somebody is wasting bullets on a dead player')
                        return jsonify(
                            ErrorResponse(
                                'Trying to torpedo dead player',
                                'Either you are dead, or you\'re tryiing to shoot a dead player;'
                            ).get()), int(HTTPStatus.BAD_REQUEST)

                    if shooter is not None and receiver is not None and receiver:
                        app.logger.info('Shoot result was: [' + str(result) +
                                        ']')
                        if result > 0:
                            shooter.add_points(result)
                            receiver.update_fleet_value(result)
                            app.logger.info('Boat was damaged by torpedo...')
                        app.logger.info('moving to next player...')
                        move_to_next_player(board.get_game_id())
                        app.logger.info('building result...')
                        s = shooter.export_state()
                        r = receiver.export_state()
                        shooter = None
                        receiver = None
                        return jsonify({
                            "result_code": result,
                            "shooter": s,
                            "receiver": r
                        }), HTTPStatus.CREATED
                    else:
                        app.logger.error(
                            'If you get here...This shit is nasty... players not found for transaction'
                        )
                        return jsonify({
                            'Error':
                            'Internal player reference error',
                            'Message':
                            'Players in transaction could not be found'
                        })
                else:
                    app.logger.error(
                        'Some stupid player tried to shoot an already shot location'
                    )
                    return jsonify({"result_code": -1}), HTTPStatus.BAD_REQUEST
            else:
                app.logger.error(
                    'Some stupid player tried to shoot a torpedo into a non-valid location'
                )
                return jsonify(
                    ErrorResponse(
                        'Invalid coordinates for torpedo',
                        'You cannot shoot to nowhere. Provide a valid json payload to shoot'
                    ).get()), int(HTTPStatus.BAD_REQUEST)
        else:
            return jsonify({
                'Error':
                'Invalid torpedo operation',
                'Message':
                'Dude, you cannot shoot your own crappy boats nor steal identities...!'
            }), int(HTTPStatus.BAD_REQUEST)
    else:
        return jsonify(
            ErrorResponse(
                'Unable to find board',
                'The provided board is does not correspond to a valid board').
            get()), int(HTTPStatus.NOT_FOUND)