Skip to content

PlayerProfile

Represents a particular Flesh and Blood player profile (Gem ID).

Warning

At this time PlayerProfile objects created via the from_gemid() or search() methods work by parsing the HTML tables embedded on the official website. Please be respectful by limiting query volumes to numbers comparable to what could be done manually via the browser.

Attributes:

Name Type Description
country str

The country code of the player.

id int

The Gem ID of the player.

name str

The name of the player.

elo_cc Optional[int]

The Constructed Elo Rating of the player.

elo_lim Optional[int]

The Limited Elo Rating of the player.

rank_elo_cc Optional[int]

The rank of the player's Constructed Elo Rating.

rank_elo_lim Optional[int]

The rank of the player's Limited Elo Rating.

rank_xp Optional[int]

The lifetime rank of the player in total XP.

rank_xp_90 Optional[int]

The 90-day XP rank of the player.

xp Optional[int]

The lifetime total XP of the player.

xp_90 Optional[int]

The XP of the player over the last 90 days.

Source code in fab/gemid.py
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
@dataclasses.dataclass
class PlayerProfile:
    '''
    Represents a particular Flesh and Blood player profile (Gem ID).

    Tip: Warning
      At this time `PlayerProfile` objects created via the `from_gemid()` or
      `search()` methods work by parsing the HTML tables embedded on [the
      official website](https://fabtcg.com/leaderboards/). Please be respectful
      by limiting query volumes to numbers comparable to what could be done
      manually via the browser.

    Attributes:
      country: The country code of the player.
      id: The Gem ID of the player.
      name: The name of the player.
      elo_cc: The Constructed Elo Rating of the player.
      elo_lim: The Limited Elo Rating of the player.
      rank_elo_cc: The rank of the player's Constructed Elo Rating.
      rank_elo_lim: The rank of the player's Limited Elo Rating.
      rank_xp: The lifetime rank of the player in total XP.
      rank_xp_90: The 90-day XP rank of the player.
      xp: The lifetime total XP of the player.
      xp_90: The XP of the player over the last 90 days.
    '''

    country: str
    id: int
    name: str
    elo_cc: Optional[int] = None
    elo_lim: Optional[int] = None
    rank_elo_cc: Optional[int] = None
    rank_elo_lim: Optional[int] = None
    rank_xp: Optional[int] = None
    rank_xp_90: Optional[int] = None
    xp: Optional[int] = None
    xp_90: Optional[int] = None

    @staticmethod
    def from_gemid(id: int) -> PlayerProfile:
        '''
        Creates a `PlayerProfile` object from the specified Gem ID.

        Args:
          id: The Gem ID of the player.

        Returns:
          A player profile record associated with the specified Gem ID.
        '''
        try:
            results = [p for p in PlayerProfile.search(id) if p.id == id]
        except Exception as e:
            raise Exception(f'unable to fetch player profile - {e}')
        if not results:
            raise Exception(f'unable to locate player profile associated with id "{id}"')
        return results[0]

    @staticmethod
    def search(query: int | str) -> list[PlayerProfile]:
        '''
        Searches the offical leaderboards for player profiles by player name or
        Gem ID.

        Args:
          query: The player name or Gem ID to search for.

        Returns:
          A list of player profiles matching the search query.
        '''
        agg_data: dict[int, PlayerProfile] = {}
        _query = quote(query) if isinstance(query, str) else str(query)
        for mode in ['xpall', 'xp90', 'elo_cons', 'elo_lim']:
            try:
                data = pandas.read_html(
                    f'{LEADERBOARDS_URL}/?mode={mode}&query={_query}'
                )[0].to_dict('records')
            except ValueError:
                pass
            except Exception as e:
                raise Exception(f'unable to fetch leaderboard data - {e}')
            for entry in data:
                name_parts = entry['Name'].rsplit(' ', 1)
                name = name_parts[0]
                gem_id = int(name_parts[1].replace('(', '').replace(')', ''))
                if not gem_id in agg_data:
                    agg_data[gem_id] = PlayerProfile(
                        country = entry['Country'],
                        id = gem_id,
                        name = name
                    )
                if mode == 'xpall':
                    agg_data[gem_id].rank_xp = entry.get('Rank (Lifetime)')
                    agg_data[gem_id].xp = entry.get('XP (Lifetime)')
                elif mode == 'xp90':
                    agg_data[gem_id].rank_xp = entry.get('Rank (90 Days)')
                    agg_data[gem_id].xp = entry.get('XP (90 Days)')
                elif mode == 'elo_cons':
                    agg_data[gem_id].elo_cc = entry.get('Rating')
                    agg_data[gem_id].rank_elo_cc = entry.get('Rank')
                elif mode == 'elo_lim':
                    agg_data[gem_id].elo_lim = entry.get('Rating')
                    agg_data[gem_id].rank_elo_lim = entry.get('Rank')
        return list(agg_data.values())

from_gemid(id) staticmethod

Creates a PlayerProfile object from the specified Gem ID.

Parameters:

Name Type Description Default
id int

The Gem ID of the player.

required

Returns:

Type Description
PlayerProfile

A player profile record associated with the specified Gem ID.

Source code in fab/gemid.py
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
@staticmethod
def from_gemid(id: int) -> PlayerProfile:
    '''
    Creates a `PlayerProfile` object from the specified Gem ID.

    Args:
      id: The Gem ID of the player.

    Returns:
      A player profile record associated with the specified Gem ID.
    '''
    try:
        results = [p for p in PlayerProfile.search(id) if p.id == id]
    except Exception as e:
        raise Exception(f'unable to fetch player profile - {e}')
    if not results:
        raise Exception(f'unable to locate player profile associated with id "{id}"')
    return results[0]

search(query) staticmethod

Searches the offical leaderboards for player profiles by player name or Gem ID.

Parameters:

Name Type Description Default
query int | str

The player name or Gem ID to search for.

required

Returns:

Type Description
list[PlayerProfile]

A list of player profiles matching the search query.

Source code in fab/gemid.py
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
@staticmethod
def search(query: int | str) -> list[PlayerProfile]:
    '''
    Searches the offical leaderboards for player profiles by player name or
    Gem ID.

    Args:
      query: The player name or Gem ID to search for.

    Returns:
      A list of player profiles matching the search query.
    '''
    agg_data: dict[int, PlayerProfile] = {}
    _query = quote(query) if isinstance(query, str) else str(query)
    for mode in ['xpall', 'xp90', 'elo_cons', 'elo_lim']:
        try:
            data = pandas.read_html(
                f'{LEADERBOARDS_URL}/?mode={mode}&query={_query}'
            )[0].to_dict('records')
        except ValueError:
            pass
        except Exception as e:
            raise Exception(f'unable to fetch leaderboard data - {e}')
        for entry in data:
            name_parts = entry['Name'].rsplit(' ', 1)
            name = name_parts[0]
            gem_id = int(name_parts[1].replace('(', '').replace(')', ''))
            if not gem_id in agg_data:
                agg_data[gem_id] = PlayerProfile(
                    country = entry['Country'],
                    id = gem_id,
                    name = name
                )
            if mode == 'xpall':
                agg_data[gem_id].rank_xp = entry.get('Rank (Lifetime)')
                agg_data[gem_id].xp = entry.get('XP (Lifetime)')
            elif mode == 'xp90':
                agg_data[gem_id].rank_xp = entry.get('Rank (90 Days)')
                agg_data[gem_id].xp = entry.get('XP (90 Days)')
            elif mode == 'elo_cons':
                agg_data[gem_id].elo_cc = entry.get('Rating')
                agg_data[gem_id].rank_elo_cc = entry.get('Rank')
            elif mode == 'elo_lim':
                agg_data[gem_id].elo_lim = entry.get('Rating')
                agg_data[gem_id].rank_elo_lim = entry.get('Rank')
    return list(agg_data.values())