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 loguru import logger

from aoe2netwrapper.models import (  # LastMatchResponse, NumOnlineResponse,

    LeaderBoardResponse,

    MatchLobby,

    RatingTimePoint,

    StringsResponse,

)

try:

    import pandas as pd

except ImportError as error:

    logger.error("User tried to use the 'converters' submodule without the 'pandas' library.")

    msg = "The 'converters' submodule requires the 'pandas' library to function."

    raise NotImplementedError(msg) 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")

            msg = "Provided parameter should be an instance of 'StringsResponse'"

            raise TypeError(msg)

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

            msg = "Provided parameter should be an instance of 'LeaderBoardResponse'"

            raise TypeError(msg)

        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]")

    #         msg = "Provided parameter should be an instance of 'list[MatchLobby]'"

    #         raise TypeError(msg)

    #     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")

    #         msg = "Provided parameter should be an instance of 'LastMatchResponse'"

    #         raise TypeError(msg)

    #     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]")

            msg = "Provided parameter should be an instance of 'list[MatchLobby]'"

            raise TypeError(msg)

        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]")

            msg = "Provided parameter should be an instance of 'list[RatingTimePoint]'"

            raise TypeError(msg)

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

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

    # @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]")

    #         msg = "Provided parameter should be an instance of 'list[MatchLobby]'"

    #         raise TypeError(msg)

    #     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")

    #         msg = "Provided parameter should be an instance of 'NumOnlineResponse'"

    #         raise TypeError(msg)

    #     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")

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

# ----- 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")

        msg = "Provided parameter should be an instance of 'MatchLobby'"

        raise TypeError(msg)

    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
)

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.

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

            msg = "Provided parameter should be an instance of 'StringsResponse'"

            raise TypeError(msg)

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

            msg = "Provided parameter should be an instance of 'LeaderBoardResponse'"

            raise TypeError(msg)

        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]")

    #         msg = "Provided parameter should be an instance of 'list[MatchLobby]'"

    #         raise TypeError(msg)

    #     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")

    #         msg = "Provided parameter should be an instance of 'LastMatchResponse'"

    #         raise TypeError(msg)

    #     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]")

            msg = "Provided parameter should be an instance of 'list[MatchLobby]'"

            raise TypeError(msg)

        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]")

            msg = "Provided parameter should be an instance of 'list[RatingTimePoint]'"

            raise TypeError(msg)

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

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

    # @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]")

    #         msg = "Provided parameter should be an instance of 'list[MatchLobby]'"

    #         raise TypeError(msg)

    #     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")

    #         msg = "Provided parameter should be an instance of 'NumOnlineResponse'"

    #         raise TypeError(msg)

    #     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")

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

Static methods

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

            msg = "Provided parameter should be an instance of 'LeaderBoardResponse'"

            raise TypeError(msg)

        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

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]")

            msg = "Provided parameter should be an instance of 'list[MatchLobby]'"

            raise TypeError(msg)

        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)

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]")

            msg = "Provided parameter should be an instance of 'list[RatingTimePoint]'"

            raise TypeError(msg)

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

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

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

            msg = "Provided parameter should be an instance of 'StringsResponse'"

            raise TypeError(msg)

        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