Skip to content

Module aoe2netwrapper.converters

aoe2netwrapper.converters


This module implements a high-level class with static methods to convert result of AoENetAPI methods to pandas DataFrames.

View Source
"""

aoe2netwrapper.converters

-------------------------

This module implements a high-level class with static methods to convert result of AoENetAPI methods to

pandas DataFrames.

"""

from typing import List

from loguru import logger

from aoe2netwrapper.models import (

    LastMatchResponse,

    LeaderBoardResponse,

    MatchLobby,

    NumOnlineResponse,

    RatingTimePoint,

    StringsResponse,

)

try:

    import pandas as pd

except ImportError as error:

    logger.error(

        "User tried to use the 'converters' submodule without havinig installed the 'pandas' library."

    )

    raise NotImplementedError(

        "The 'aoe2netwrapper.converters' module exports results to 'pandas.DataFrame' objects and "

        "needs the 'pandas' library installed to function."

    ) from error

class Convert:

    """

    This is a convenience class providing methods to convert the outputs from the AoE2NetAPI query methods

    into pandas DataFrame objects. Every method below is a staticmethod, so no object has to be instantiated.

    """

    @staticmethod

    def strings(strings_response: StringsResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().strings to a pandas DataFrame.

        Args:

            strings_response (StringsResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the StringsResponse, each column being the values for a 'string' used

            by the API, and the index being the ID numbers. Since this is the result of a join for many

            'strings' that do not have the same amount of values, the resulting dataframe will contain NaNs

            wherever a given 'string' does not have a value for the given index ID.

        """

        if not isinstance(strings_response, StringsResponse):

            logger.error("Tried to use method with a parameter of type != StringsResponse")

            raise TypeError("Provided parameter should be an instance of 'StringsResponse'")

        logger.debug("Converting StringsResponse to DataFrame")

        dframe = pd.DataFrame(strings_response).transpose()

        dframe.columns = dframe.iloc[0]

        dframe = dframe.drop(index=[0]).reset_index(drop=True)

        dframe = dframe.drop(columns=["language"])

        logger.trace("Exporting each string attribute to its own dataframe and joining")

        result = pd.DataFrame()

        for col in dframe.columns:

            intermediate = pd.DataFrame()

            intermediate[col] = dframe[col][0]

            intermediate["id"] = intermediate[col].apply(lambda x: x.id)

            intermediate[col] = intermediate[col].apply(lambda x: x.string)

            result = result.join(intermediate.set_index("id"), how="outer")

        return result

    @staticmethod

    def leaderboard(leaderboard_response: LeaderBoardResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().leaderboard to a pandas DataFrame.

        Args:

            leaderboard_response (LeaderBoardResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the LeaderBoardResponse, each row being an entry in the leaderboard.

            Top level attributes such as 'start' or 'total' are broadcast to an entire array the size of

            the dataframe, and timestamps are converted to datetime objects.

        """

        if not isinstance(leaderboard_response, LeaderBoardResponse):

            logger.error("Tried to use method with a parameter of type != LeaderBoardResponse")

            raise TypeError("Provided parameter should be an instance of 'LeaderBoardResponse'")

        logger.debug("Converting LeaderBoardResponse leaderboard to DataFrame")

        dframe = pd.DataFrame(leaderboard_response.leaderboard)

        dframe = _export_tuple_elements_to_column_values_format(dframe)

        logger.trace("Inserting LeaderBoardResponse attributes as columns")

        dframe["leaderboard_id"] = leaderboard_response.leaderboard_id

        dframe["start"] = leaderboard_response.start

        dframe["count"] = leaderboard_response.count

        dframe["total"] = leaderboard_response.total

        logger.trace("Converting datetimes")

        dframe["last_match"] = pd.to_datetime(dframe["last_match"], unit="s")

        dframe["last_match_time"] = pd.to_datetime(dframe["last_match_time"], unit="s")

        return dframe

    @staticmethod

    def lobbies(lobbies_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().lobbies to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            lobbies_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements..

        """

        if not isinstance(lobbies_response, list):  # move list to List[MatchLobby] when supporting > 3.9

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Lobbies response to DataFrame")

        unfolded_lobbies = [_unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in lobbies_response]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

    @staticmethod

    def last_match(last_match_response: LastMatchResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().last_match to a pandas DataFrame. There is not

        much use to this as the DataFrame will only have one row, but the method is provided nonetheless in

        case users want to concatenate several of these results in a DataFrame.

        Args:

            last_match_response (LastMatchResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of LastMatchResponse attributes. Beware: the 'players'

            column is directly the content of the 'LastMatchResponse.last_match.players' attribute and as

            such holds a list of LobbyMember objects.

        """

        if not isinstance(last_match_response, LastMatchResponse):

            logger.error("Tried to use method with a parameter of type != LastMatchResponse")

            raise TypeError("Provided parameter should be an instance of 'LastMatchResponse'")

        logger.debug("Converting LastMatchResponse last_match to DataFrame")

        dframe = pd.DataFrame(last_match_response.last_match).transpose()

        dframe.columns = dframe.iloc[0]

        dframe = dframe.drop(0).reset_index()

        logger.trace("Inserting LastMatchResponse attributes as columns")

        dframe["profile_id"] = last_match_response.profile_id

        dframe["steam_id"] = last_match_response.steam_id

        dframe["name"] = last_match_response.name

        dframe["country"] = last_match_response.country

        return dframe

    @staticmethod

    def match_history(match_history_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().match_history to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            match_history_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements.

        """

        # move list to List[MatchLobby] when supporting > 3.9

        if not isinstance(match_history_response, list):

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Match History response to DataFrame")

        unfolded_lobbies = [

            _unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in match_history_response

        ]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

    @staticmethod

    def rating_history(rating_history_response: List[RatingTimePoint]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().leaderboard to a pandas DataFrame.

        Args:

            rating_history_response (List[RatingTimePoint]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of RatingTimePoint elements, each row being the information from

            one RatingTimePoint in the list. Timestamps are converted to datetime objects.

        """

        # move list to List[RatingTimePoint] when supporting > 3.9

        if not isinstance(rating_history_response, list):

            logger.error("Tried to use method with a parameter of type != List[RatingTimePoint]")

            raise TypeError("Provided parameter should be an instance of 'List[RatingTimePoint]'")

        logger.debug("Converting Rating History rsponse to DataFrame")

        dframe = pd.DataFrame(rating_history_response)

        dframe = _export_tuple_elements_to_column_values_format(dframe)

        logger.trace("Converting timestamps to datetime objects")

        dframe["time"] = pd.to_datetime(dframe["timestamp"], unit="s")

        dframe = dframe.drop(columns=["timestamp"])

        return dframe

    @staticmethod

    def matches(matches_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().match_history to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            matches_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements.

        """

        if not isinstance(matches_response, list):  # move list to List[MatchLobby] when supporting > 3.9

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Match History response to DataFrame")

        unfolded_lobbies = [_unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in matches_response]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

    @staticmethod

    def match(match_response: MatchLobby) -> pd.DataFrame:

        """

        Convert the content of a MatchLobby to a pandas DataFrame. The resulting DataFrame will have as many

        rows as there are players in the lobby, and all global attributes will be broadcasted to columns of

        the same length, making them duplicates.

        Args:

            match_response (MatchLobby): a MatchLobby object.

        Returns:

            A pandas DataFrame from the MatchLobby attributes, each row being global information from the

            MatchLobby as well as one of the players in the lobby.

        """

        return _unfold_match_lobby_to_dataframe(match_response)

    @staticmethod

    def num_online(num_online_response: NumOnlineResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().num_online to a pandas DataFrame.

        Args:

            num_online_response (NumOnlineResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the NumOnlineResponse, each row being an entry in the leaderboard.

            Top level attributes such as 'app_id' are broadcast to an entire array the size of the

            dataframe, and timestamps are converted to datetime objects.

        """

        if not isinstance(num_online_response, NumOnlineResponse):

            logger.error("Tried to use method with a parameter of type != NumOnlineResponse")

            raise TypeError("Provided parameter should be an instance of 'NumOnlineResponse'")

        logger.debug("Converting NumOnlineResponse to DataFrame")

        dframe = pd.DataFrame(num_online_response.dict())

        logger.trace("Exporting 'player_stats' attribute contents to columns")

        dframe["time"] = dframe.player_stats.apply(lambda x: x["time"]).apply(pd.to_datetime)

        dframe["steam"] = dframe.player_stats.apply(lambda x: x["num_players"]["steam"])

        dframe["looking"] = dframe.player_stats.apply(lambda x: x["num_players"]["looking"])

        dframe["in_game"] = dframe.player_stats.apply(lambda x: x["num_players"]["in_game"])

        dframe["multiplayer"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer"])

        dframe["multiplayer_1h"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer_1h"])

        dframe["multiplayer_24h"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer_24h"])

        logger.trace("Removing 'player_stats' column to avoid nested & duplicate data")

        dframe = dframe.drop(columns=["player_stats"])

        return dframe

# ----- Helpers ----- #

def _export_tuple_elements_to_column_values_format(dataframe: pd.DataFrame) -> pd.DataFrame:

    """

    Take in a pandas DataFrame with simple int values as columns, and elements being a tuple of

    (attribute_name, value) and cast it to have the attribute_name as column names, and the values as values.

    The original columns will be dropped in the process.

    Args:

        dataframe (pd.DataFrame): your pandas DataFrame.

    Returns:

        The refactored pandas DataFrame.

    """

    dframe = dataframe.copy(deep=True)

    logger.trace("Exporting attributes to columns and removing duplicate data")

    for _, col_index in enumerate(dframe.columns):

        attribute = dframe[col_index][0][0]

        dframe[attribute] = dframe[col_index].apply(lambda x: x[1])

        dframe = dframe.drop(columns=[col_index])

    return dframe

def _unfold_match_lobby_to_dataframe(match_lobby: MatchLobby) -> pd.DataFrame:

    """

    Convert the content of a MatchLobby to a pandas DataFrame. The resulting DataFrame will have as many

    rows as there are players in the lobby, and all global attributes will be broadcasted to columns of the

    same length, making them duplicates.

    Args:

        match_lobby (MatchLobby): a MatchLobby object.

    Returns:

        A pandas DataFrame from the MatchLobby attributes, each row being global information from the

        MatchLobby as well as one of the players in the lobby.

    """

    if not isinstance(match_lobby, MatchLobby):

        logger.error("Tried to use method with a parameter of type != MatchLobby")

        raise TypeError("Provided parameter should be an instance of 'MatchLobby'")

    logger.trace("Unfolding MatchLobby.players contents to DataFrame")

    dframe = pd.DataFrame(match_lobby.players)

    dframe = _export_tuple_elements_to_column_values_format(dframe)

    dframe = dframe.rename(columns={"name": "player"})

    logger.trace("Broadcasting global MatchLobby attributes")

    attributes_df = pd.DataFrame()

    for attribute, value in match_lobby.dict().items():

        if attribute != "players":

            attributes_df[attribute] = [value] * len(dframe)

    dframe = attributes_df.join(dframe, how="outer")

    logger.trace("Converting timestamps to datetime objects")

    dframe["opened"] = pd.to_datetime(dframe["opened"], unit="s")

    dframe["started"] = pd.to_datetime(dframe["started"], unit="s")

    dframe["finished"] = pd.to_datetime(dframe["finished"], unit="s")

    return dframe

Classes

Convert

class Convert(
    /,
    *args,
    **kwargs
)
View Source
class Convert:

    """

    This is a convenience class providing methods to convert the outputs from the AoE2NetAPI query methods

    into pandas DataFrame objects. Every method below is a staticmethod, so no object has to be instantiated.

    """

    @staticmethod

    def strings(strings_response: StringsResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().strings to a pandas DataFrame.

        Args:

            strings_response (StringsResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the StringsResponse, each column being the values for a 'string' used

            by the API, and the index being the ID numbers. Since this is the result of a join for many

            'strings' that do not have the same amount of values, the resulting dataframe will contain NaNs

            wherever a given 'string' does not have a value for the given index ID.

        """

        if not isinstance(strings_response, StringsResponse):

            logger.error("Tried to use method with a parameter of type != StringsResponse")

            raise TypeError("Provided parameter should be an instance of 'StringsResponse'")

        logger.debug("Converting StringsResponse to DataFrame")

        dframe = pd.DataFrame(strings_response).transpose()

        dframe.columns = dframe.iloc[0]

        dframe = dframe.drop(index=[0]).reset_index(drop=True)

        dframe = dframe.drop(columns=["language"])

        logger.trace("Exporting each string attribute to its own dataframe and joining")

        result = pd.DataFrame()

        for col in dframe.columns:

            intermediate = pd.DataFrame()

            intermediate[col] = dframe[col][0]

            intermediate["id"] = intermediate[col].apply(lambda x: x.id)

            intermediate[col] = intermediate[col].apply(lambda x: x.string)

            result = result.join(intermediate.set_index("id"), how="outer")

        return result

    @staticmethod

    def leaderboard(leaderboard_response: LeaderBoardResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().leaderboard to a pandas DataFrame.

        Args:

            leaderboard_response (LeaderBoardResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the LeaderBoardResponse, each row being an entry in the leaderboard.

            Top level attributes such as 'start' or 'total' are broadcast to an entire array the size of

            the dataframe, and timestamps are converted to datetime objects.

        """

        if not isinstance(leaderboard_response, LeaderBoardResponse):

            logger.error("Tried to use method with a parameter of type != LeaderBoardResponse")

            raise TypeError("Provided parameter should be an instance of 'LeaderBoardResponse'")

        logger.debug("Converting LeaderBoardResponse leaderboard to DataFrame")

        dframe = pd.DataFrame(leaderboard_response.leaderboard)

        dframe = _export_tuple_elements_to_column_values_format(dframe)

        logger.trace("Inserting LeaderBoardResponse attributes as columns")

        dframe["leaderboard_id"] = leaderboard_response.leaderboard_id

        dframe["start"] = leaderboard_response.start

        dframe["count"] = leaderboard_response.count

        dframe["total"] = leaderboard_response.total

        logger.trace("Converting datetimes")

        dframe["last_match"] = pd.to_datetime(dframe["last_match"], unit="s")

        dframe["last_match_time"] = pd.to_datetime(dframe["last_match_time"], unit="s")

        return dframe

    @staticmethod

    def lobbies(lobbies_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().lobbies to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            lobbies_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements..

        """

        if not isinstance(lobbies_response, list):  # move list to List[MatchLobby] when supporting > 3.9

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Lobbies response to DataFrame")

        unfolded_lobbies = [_unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in lobbies_response]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

    @staticmethod

    def last_match(last_match_response: LastMatchResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().last_match to a pandas DataFrame. There is not

        much use to this as the DataFrame will only have one row, but the method is provided nonetheless in

        case users want to concatenate several of these results in a DataFrame.

        Args:

            last_match_response (LastMatchResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of LastMatchResponse attributes. Beware: the 'players'

            column is directly the content of the 'LastMatchResponse.last_match.players' attribute and as

            such holds a list of LobbyMember objects.

        """

        if not isinstance(last_match_response, LastMatchResponse):

            logger.error("Tried to use method with a parameter of type != LastMatchResponse")

            raise TypeError("Provided parameter should be an instance of 'LastMatchResponse'")

        logger.debug("Converting LastMatchResponse last_match to DataFrame")

        dframe = pd.DataFrame(last_match_response.last_match).transpose()

        dframe.columns = dframe.iloc[0]

        dframe = dframe.drop(0).reset_index()

        logger.trace("Inserting LastMatchResponse attributes as columns")

        dframe["profile_id"] = last_match_response.profile_id

        dframe["steam_id"] = last_match_response.steam_id

        dframe["name"] = last_match_response.name

        dframe["country"] = last_match_response.country

        return dframe

    @staticmethod

    def match_history(match_history_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().match_history to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            match_history_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements.

        """

        # move list to List[MatchLobby] when supporting > 3.9

        if not isinstance(match_history_response, list):

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Match History response to DataFrame")

        unfolded_lobbies = [

            _unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in match_history_response

        ]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

    @staticmethod

    def rating_history(rating_history_response: List[RatingTimePoint]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().leaderboard to a pandas DataFrame.

        Args:

            rating_history_response (List[RatingTimePoint]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of RatingTimePoint elements, each row being the information from

            one RatingTimePoint in the list. Timestamps are converted to datetime objects.

        """

        # move list to List[RatingTimePoint] when supporting > 3.9

        if not isinstance(rating_history_response, list):

            logger.error("Tried to use method with a parameter of type != List[RatingTimePoint]")

            raise TypeError("Provided parameter should be an instance of 'List[RatingTimePoint]'")

        logger.debug("Converting Rating History rsponse to DataFrame")

        dframe = pd.DataFrame(rating_history_response)

        dframe = _export_tuple_elements_to_column_values_format(dframe)

        logger.trace("Converting timestamps to datetime objects")

        dframe["time"] = pd.to_datetime(dframe["timestamp"], unit="s")

        dframe = dframe.drop(columns=["timestamp"])

        return dframe

    @staticmethod

    def matches(matches_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().match_history to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            matches_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements.

        """

        if not isinstance(matches_response, list):  # move list to List[MatchLobby] when supporting > 3.9

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Match History response to DataFrame")

        unfolded_lobbies = [_unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in matches_response]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

    @staticmethod

    def match(match_response: MatchLobby) -> pd.DataFrame:

        """

        Convert the content of a MatchLobby to a pandas DataFrame. The resulting DataFrame will have as many

        rows as there are players in the lobby, and all global attributes will be broadcasted to columns of

        the same length, making them duplicates.

        Args:

            match_response (MatchLobby): a MatchLobby object.

        Returns:

            A pandas DataFrame from the MatchLobby attributes, each row being global information from the

            MatchLobby as well as one of the players in the lobby.

        """

        return _unfold_match_lobby_to_dataframe(match_response)

    @staticmethod

    def num_online(num_online_response: NumOnlineResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().num_online to a pandas DataFrame.

        Args:

            num_online_response (NumOnlineResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the NumOnlineResponse, each row being an entry in the leaderboard.

            Top level attributes such as 'app_id' are broadcast to an entire array the size of the

            dataframe, and timestamps are converted to datetime objects.

        """

        if not isinstance(num_online_response, NumOnlineResponse):

            logger.error("Tried to use method with a parameter of type != NumOnlineResponse")

            raise TypeError("Provided parameter should be an instance of 'NumOnlineResponse'")

        logger.debug("Converting NumOnlineResponse to DataFrame")

        dframe = pd.DataFrame(num_online_response.dict())

        logger.trace("Exporting 'player_stats' attribute contents to columns")

        dframe["time"] = dframe.player_stats.apply(lambda x: x["time"]).apply(pd.to_datetime)

        dframe["steam"] = dframe.player_stats.apply(lambda x: x["num_players"]["steam"])

        dframe["looking"] = dframe.player_stats.apply(lambda x: x["num_players"]["looking"])

        dframe["in_game"] = dframe.player_stats.apply(lambda x: x["num_players"]["in_game"])

        dframe["multiplayer"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer"])

        dframe["multiplayer_1h"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer_1h"])

        dframe["multiplayer_24h"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer_24h"])

        logger.trace("Removing 'player_stats' column to avoid nested & duplicate data")

        dframe = dframe.drop(columns=["player_stats"])

        return dframe

Static methods

last_match

def last_match(
    last_match_response: aoe2netwrapper.models.last_match.LastMatchResponse
) -> pandas.core.frame.DataFrame

Convert the result given by a call to AoE2NetAPI().last_match to a pandas DataFrame. There is not

much use to this as the DataFrame will only have one row, but the method is provided nonetheless in case users want to concatenate several of these results in a DataFrame.

Parameters:

Name Type Description Default
last_match_response LastMatchResponse the response directly returned by your AoE2NetAPI
client. None

Returns:

Type Description
None A pandas DataFrame from the list of LastMatchResponse attributes. Beware: the 'players'
column is directly the content of the 'LastMatchResponse.last_match.players' attribute and as
such holds a list of LobbyMember objects.
View Source
    @staticmethod

    def last_match(last_match_response: LastMatchResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().last_match to a pandas DataFrame. There is not

        much use to this as the DataFrame will only have one row, but the method is provided nonetheless in

        case users want to concatenate several of these results in a DataFrame.

        Args:

            last_match_response (LastMatchResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of LastMatchResponse attributes. Beware: the 'players'

            column is directly the content of the 'LastMatchResponse.last_match.players' attribute and as

            such holds a list of LobbyMember objects.

        """

        if not isinstance(last_match_response, LastMatchResponse):

            logger.error("Tried to use method with a parameter of type != LastMatchResponse")

            raise TypeError("Provided parameter should be an instance of 'LastMatchResponse'")

        logger.debug("Converting LastMatchResponse last_match to DataFrame")

        dframe = pd.DataFrame(last_match_response.last_match).transpose()

        dframe.columns = dframe.iloc[0]

        dframe = dframe.drop(0).reset_index()

        logger.trace("Inserting LastMatchResponse attributes as columns")

        dframe["profile_id"] = last_match_response.profile_id

        dframe["steam_id"] = last_match_response.steam_id

        dframe["name"] = last_match_response.name

        dframe["country"] = last_match_response.country

        return dframe

leaderboard

def leaderboard(
    leaderboard_response: aoe2netwrapper.models.leaderboard.LeaderBoardResponse
) -> pandas.core.frame.DataFrame

Convert the result given by a call to AoE2NetAPI().leaderboard to a pandas DataFrame.

Parameters:

Name Type Description Default
leaderboard_response LeaderBoardResponse the response directly returned by your AoE2NetAPI
client. None

Returns:

Type Description
None A pandas DataFrame from the LeaderBoardResponse, each row being an entry in the leaderboard.
Top level attributes such as 'start' or 'total' are broadcast to an entire array the size of
the dataframe, and timestamps are converted to datetime objects.
View Source
    @staticmethod

    def leaderboard(leaderboard_response: LeaderBoardResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().leaderboard to a pandas DataFrame.

        Args:

            leaderboard_response (LeaderBoardResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the LeaderBoardResponse, each row being an entry in the leaderboard.

            Top level attributes such as 'start' or 'total' are broadcast to an entire array the size of

            the dataframe, and timestamps are converted to datetime objects.

        """

        if not isinstance(leaderboard_response, LeaderBoardResponse):

            logger.error("Tried to use method with a parameter of type != LeaderBoardResponse")

            raise TypeError("Provided parameter should be an instance of 'LeaderBoardResponse'")

        logger.debug("Converting LeaderBoardResponse leaderboard to DataFrame")

        dframe = pd.DataFrame(leaderboard_response.leaderboard)

        dframe = _export_tuple_elements_to_column_values_format(dframe)

        logger.trace("Inserting LeaderBoardResponse attributes as columns")

        dframe["leaderboard_id"] = leaderboard_response.leaderboard_id

        dframe["start"] = leaderboard_response.start

        dframe["count"] = leaderboard_response.count

        dframe["total"] = leaderboard_response.total

        logger.trace("Converting datetimes")

        dframe["last_match"] = pd.to_datetime(dframe["last_match"], unit="s")

        dframe["last_match_time"] = pd.to_datetime(dframe["last_match_time"], unit="s")

        return dframe

lobbies

def lobbies(
    lobbies_response: List[aoe2netwrapper.models.lobbies.MatchLobby]
) -> pandas.core.frame.DataFrame

Convert the result given by a call to AoE2NetAPI().lobbies to a pandas DataFrame. The resulting

DataFrame will contain several rows for each lobby, namely as many as there are players in said lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or make use of the groupby functionality of pandas DataFrames.

Parameters:

Name Type Description Default
lobbies_response List[MatchLobby] the response directly returned by your AoE2NetAPI
client. None

Returns:

Type Description
None A pandas DataFrame from the list of MatchLobby elements..
View Source
    @staticmethod

    def lobbies(lobbies_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().lobbies to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            lobbies_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements..

        """

        if not isinstance(lobbies_response, list):  # move list to List[MatchLobby] when supporting > 3.9

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Lobbies response to DataFrame")

        unfolded_lobbies = [_unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in lobbies_response]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

match

def match(
    match_response: aoe2netwrapper.models.lobbies.MatchLobby
) -> pandas.core.frame.DataFrame

Convert the content of a MatchLobby to a pandas DataFrame. The resulting DataFrame will have as many

rows as there are players in the lobby, and all global attributes will be broadcasted to columns of the same length, making them duplicates.

Parameters:

Name Type Description Default
match_response MatchLobby a MatchLobby object. None

Returns:

Type Description
None A pandas DataFrame from the MatchLobby attributes, each row being global information from the
MatchLobby as well as one of the players in the lobby.
View Source
    @staticmethod

    def match(match_response: MatchLobby) -> pd.DataFrame:

        """

        Convert the content of a MatchLobby to a pandas DataFrame. The resulting DataFrame will have as many

        rows as there are players in the lobby, and all global attributes will be broadcasted to columns of

        the same length, making them duplicates.

        Args:

            match_response (MatchLobby): a MatchLobby object.

        Returns:

            A pandas DataFrame from the MatchLobby attributes, each row being global information from the

            MatchLobby as well as one of the players in the lobby.

        """

        return _unfold_match_lobby_to_dataframe(match_response)

match_history

def match_history(
    match_history_response: List[aoe2netwrapper.models.lobbies.MatchLobby]
) -> pandas.core.frame.DataFrame

Convert the result given by a call to AoE2NetAPI().match_history to a pandas DataFrame. The resulting

DataFrame will contain several rows for each lobby, namely as many as there are players in said lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or make use of the groupby functionality of pandas DataFrames.

Parameters:

Name Type Description Default
match_history_response List[MatchLobby] the response directly returned by your AoE2NetAPI
client. None

Returns:

Type Description
None A pandas DataFrame from the list of MatchLobby elements.
View Source
    @staticmethod

    def match_history(match_history_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().match_history to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            match_history_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements.

        """

        # move list to List[MatchLobby] when supporting > 3.9

        if not isinstance(match_history_response, list):

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Match History response to DataFrame")

        unfolded_lobbies = [

            _unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in match_history_response

        ]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

matches

def matches(
    matches_response: List[aoe2netwrapper.models.lobbies.MatchLobby]
) -> pandas.core.frame.DataFrame

Convert the result given by a call to AoE2NetAPI().match_history to a pandas DataFrame. The resulting

DataFrame will contain several rows for each lobby, namely as many as there are players in said lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or make use of the groupby functionality of pandas DataFrames.

Parameters:

Name Type Description Default
matches_response List[MatchLobby] the response directly returned by your AoE2NetAPI
client. None

Returns:

Type Description
None A pandas DataFrame from the list of MatchLobby elements.
View Source
    @staticmethod

    def matches(matches_response: List[MatchLobby]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().match_history to a pandas DataFrame. The resulting

        DataFrame will contain several rows for each lobby, namely as many as there are players in said

        lobby. All global attributes of each lobby are broadcasted to arrays, making them duplicates.

        To isolate a specific lobby, either call the AoE2NetAPI().match method with the lobby's UUID or

        make use of the groupby functionality of pandas DataFrames.

        Args:

            matches_response (List[MatchLobby]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of MatchLobby elements.

        """

        if not isinstance(matches_response, list):  # move list to List[MatchLobby] when supporting > 3.9

            logger.error("Tried to use method with a parameter of type != List[MatchLobby]")

            raise TypeError("Provided parameter should be an instance of 'List[MatchLobby]'")

        logger.debug("Converting Match History response to DataFrame")

        unfolded_lobbies = [_unfold_match_lobby_to_dataframe(match_lobby) for match_lobby in matches_response]

        return pd.concat(unfolded_lobbies).reset_index(drop=True)

num_online

def num_online(
    num_online_response: aoe2netwrapper.models.num_online.NumOnlineResponse
) -> pandas.core.frame.DataFrame

Convert the result given by a call to AoE2NetAPI().num_online to a pandas DataFrame.

Parameters:

Name Type Description Default
num_online_response NumOnlineResponse the response directly returned by your AoE2NetAPI
client. None

Returns:

Type Description
None A pandas DataFrame from the NumOnlineResponse, each row being an entry in the leaderboard.
Top level attributes such as 'app_id' are broadcast to an entire array the size of the
dataframe, and timestamps are converted to datetime objects.
View Source
    @staticmethod

    def num_online(num_online_response: NumOnlineResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().num_online to a pandas DataFrame.

        Args:

            num_online_response (NumOnlineResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the NumOnlineResponse, each row being an entry in the leaderboard.

            Top level attributes such as 'app_id' are broadcast to an entire array the size of the

            dataframe, and timestamps are converted to datetime objects.

        """

        if not isinstance(num_online_response, NumOnlineResponse):

            logger.error("Tried to use method with a parameter of type != NumOnlineResponse")

            raise TypeError("Provided parameter should be an instance of 'NumOnlineResponse'")

        logger.debug("Converting NumOnlineResponse to DataFrame")

        dframe = pd.DataFrame(num_online_response.dict())

        logger.trace("Exporting 'player_stats' attribute contents to columns")

        dframe["time"] = dframe.player_stats.apply(lambda x: x["time"]).apply(pd.to_datetime)

        dframe["steam"] = dframe.player_stats.apply(lambda x: x["num_players"]["steam"])

        dframe["looking"] = dframe.player_stats.apply(lambda x: x["num_players"]["looking"])

        dframe["in_game"] = dframe.player_stats.apply(lambda x: x["num_players"]["in_game"])

        dframe["multiplayer"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer"])

        dframe["multiplayer_1h"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer_1h"])

        dframe["multiplayer_24h"] = dframe.player_stats.apply(lambda x: x["num_players"]["multiplayer_24h"])

        logger.trace("Removing 'player_stats' column to avoid nested & duplicate data")

        dframe = dframe.drop(columns=["player_stats"])

        return dframe

rating_history

def rating_history(
    rating_history_response: List[aoe2netwrapper.models.rating_history.RatingTimePoint]
) -> pandas.core.frame.DataFrame

Convert the result given by a call to AoE2NetAPI().leaderboard to a pandas DataFrame.

Parameters:

Name Type Description Default
rating_history_response List[RatingTimePoint] the response directly returned by your AoE2NetAPI
client. None

Returns:

Type Description
None A pandas DataFrame from the list of RatingTimePoint elements, each row being the information from
one RatingTimePoint in the list. Timestamps are converted to datetime objects.
View Source
    @staticmethod

    def rating_history(rating_history_response: List[RatingTimePoint]) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().leaderboard to a pandas DataFrame.

        Args:

            rating_history_response (List[RatingTimePoint]): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the list of RatingTimePoint elements, each row being the information from

            one RatingTimePoint in the list. Timestamps are converted to datetime objects.

        """

        # move list to List[RatingTimePoint] when supporting > 3.9

        if not isinstance(rating_history_response, list):

            logger.error("Tried to use method with a parameter of type != List[RatingTimePoint]")

            raise TypeError("Provided parameter should be an instance of 'List[RatingTimePoint]'")

        logger.debug("Converting Rating History rsponse to DataFrame")

        dframe = pd.DataFrame(rating_history_response)

        dframe = _export_tuple_elements_to_column_values_format(dframe)

        logger.trace("Converting timestamps to datetime objects")

        dframe["time"] = pd.to_datetime(dframe["timestamp"], unit="s")

        dframe = dframe.drop(columns=["timestamp"])

        return dframe

strings

def strings(
    strings_response: aoe2netwrapper.models.strings.StringsResponse
) -> pandas.core.frame.DataFrame

Convert the result given by a call to AoE2NetAPI().strings to a pandas DataFrame.

Parameters:

Name Type Description Default
strings_response StringsResponse the response directly returned by your AoE2NetAPI
client. None

Returns:

Type Description
None A pandas DataFrame from the StringsResponse, each column being the values for a 'string' used
by the API, and the index being the ID numbers. Since this is the result of a join for many
'strings' that do not have the same amount of values, the resulting dataframe will contain NaNs
wherever a given 'string' does not have a value for the given index ID.
View Source
    @staticmethod

    def strings(strings_response: StringsResponse) -> pd.DataFrame:

        """

        Convert the result given by a call to AoE2NetAPI().strings to a pandas DataFrame.

        Args:

            strings_response (StringsResponse): the response directly returned by your AoE2NetAPI

                client.

        Returns:

            A pandas DataFrame from the StringsResponse, each column being the values for a 'string' used

            by the API, and the index being the ID numbers. Since this is the result of a join for many

            'strings' that do not have the same amount of values, the resulting dataframe will contain NaNs

            wherever a given 'string' does not have a value for the given index ID.

        """

        if not isinstance(strings_response, StringsResponse):

            logger.error("Tried to use method with a parameter of type != StringsResponse")

            raise TypeError("Provided parameter should be an instance of 'StringsResponse'")

        logger.debug("Converting StringsResponse to DataFrame")

        dframe = pd.DataFrame(strings_response).transpose()

        dframe.columns = dframe.iloc[0]

        dframe = dframe.drop(index=[0]).reset_index(drop=True)

        dframe = dframe.drop(columns=["language"])

        logger.trace("Exporting each string attribute to its own dataframe and joining")

        result = pd.DataFrame()

        for col in dframe.columns:

            intermediate = pd.DataFrame()

            intermediate[col] = dframe[col][0]

            intermediate["id"] = intermediate[col].apply(lambda x: x.id)

            intermediate[col] = intermediate[col].apply(lambda x: x.string)

            result = result.join(intermediate.set_index("id"), how="outer")

        return result