Skip to content

Commit

Permalink
feat: add skill and stat leaderboard support
Browse files Browse the repository at this point in the history
  • Loading branch information
Jackenmen committed Nov 2, 2024
1 parent a1448b9 commit 46d967e
Show file tree
Hide file tree
Showing 6 changed files with 270 additions and 7 deletions.
15 changes: 15 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ All enumerations are subclasses of `enum.Enum`.
.. autoclass:: rlapi.Platform
:members:

.. autoclass:: rlapi.Stat
:members:

Rocket League API Models
------------------------

Expand All @@ -106,6 +109,18 @@ and are not meant to be created by the user of the library.
.. autoclass:: rlapi.Playlist
:members:

.. autoclass:: rlapi.SkillLeaderboard
:members:

.. autoclass:: rlapi.SkillLeaderboardPlayer
:members:

.. autoclass:: rlapi.StatLeaderboard
:members:

.. autoclass:: rlapi.StatLeaderboardPlayer
:members:

.. autoclass:: rlapi.Population
:members:

Expand Down
18 changes: 17 additions & 1 deletion rlapi/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,24 @@

from . import errors as errors # noqa
from .client import Client as Client # noqa
from .enums import Platform as Platform, PlaylistKey as PlaylistKey # noqa
from .enums import ( # noqa
Platform as Platform,
PlaylistKey as PlaylistKey,
Stat as Stat,
)
from .errors import ( # noqa
HTTPException as HTTPException,
IllegalUsername as IllegalUsername,
PlayerNotFound as PlayerNotFound,
RLApiException as RLApiException,
Unauthorized as Unauthorized,
)
from .leaderboard import ( # noqa
SkillLeaderboard as SkillLeaderboard,
SkillLeaderboardPlayer as SkillLeaderboardPlayer,
StatLeaderboard as StatLeaderboard,
StatLeaderboardPlayer as StatLeaderboardPlayer,
)
from .player import ( # noqa
DIVISIONS as DIVISIONS,
PLAYLISTS_WITH_SEASON_REWARDS as PLAYLISTS_WITH_SEASON_REWARDS,
Expand Down Expand Up @@ -64,12 +74,18 @@
# enums
"Platform",
"PlaylistKey",
"Stat",
# errors
"HTTPException",
"IllegalUsername",
"PlayerNotFound",
"RLApiException",
"Unauthorized",
# leaderboard
"SkillLeaderboard",
"SkillLeaderboardPlayer",
"StatLeaderboard",
"StatLeaderboardPlayer",
# player
"DIVISIONS",
"PLAYLISTS_WITH_SEASON_REWARDS",
Expand Down
57 changes: 56 additions & 1 deletion rlapi/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@

from . import errors
from ._utils import TokenInfo, json_or_text
from .enums import Platform
from .enums import Platform, PlaylistKey, Stat
from .leaderboard import SkillLeaderboard, StatLeaderboard
from .player import Player
from .population import Population
from .typedefs import TierBreakdownType
Expand Down Expand Up @@ -616,3 +617,57 @@ async def get_population(self) -> Population:
"""
data = await self._rlapi_request("/population")
return Population(data)

async def get_skill_leaderboard(
self, platform: Platform, playlist_key: PlaylistKey
) -> SkillLeaderboard:
"""
Get skill leaderboard for the playlist on the given platform.
Parameters
----------
platform: Platform
Platform to get the leaderboard for.
playlist_key: PlaylistKey
Playlist to get the leaderboard for.
Returns
-------
SkillLeaderboard
Skill leaderboard for the playlist on the given platform.
Raises
------
HTTPException
HTTP request to Rocket League failed.
"""
endpoint = f"/leaderboard/skill/{platform.value}/{playlist_key.value}"
data = await self._rlapi_request(endpoint)
return SkillLeaderboard(platform, playlist_key, data)

async def get_stat_leaderboard(
self, platform: Platform, stat: Stat
) -> StatLeaderboard:
"""
Get leaderboard for the specified stat on the given platform.
Parameters
----------
platform: Platform
Platform to get the leaderboard for.
stat: Stat
Stat to get the leaderboard for.
Returns
-------
StatLeaderboard
Leaderboard for the specified stat on the given platform.
Raises
------
HTTPException
HTTP request to Rocket League failed.
"""
endpoint = f"/leaderboard/stat/{platform.value}/{stat.value}"
data = await self._rlapi_request(endpoint)
return StatLeaderboard(platform, stat, data)
17 changes: 17 additions & 0 deletions rlapi/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,23 @@ def __str__(self) -> str:
return _PLATFORM_FRIENDLY_NAMES[self]


class Stat(Enum):
"""Represents player stat."""

#: Assists.
assists = "Assists"
#: Goals.
goals = "Goals"
#: MVPs.
mvps = "MVPs"
#: Saves.
saves = "Saves"
#: Shots.
shots = "Shots"
#: Wins.
wins = "Wins"


_PLATFORM_FRIENDLY_NAMES = {
Platform.steam: "Steam",
Platform.ps4: "PlayStation",
Expand Down
157 changes: 157 additions & 0 deletions rlapi/leaderboard.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
from typing import Any, Dict, Optional

from .enums import Platform, PlaylistKey, Stat

__all__ = (
"SkillLeaderboardPlayer",
"SkillLeaderboard",
"StatLeaderboardPlayer",
"StatLeaderboard",
)


class SkillLeaderboardPlayer:
"""SkillLeaderboardPlayer()
Represents Rocket League Player on a platform's skill leaderboard.
Attributes
----------
platform: Platform
Platform that this leaderboard entry refers to.
playlist_key: PlaylistKey
Playlist that this leaderboard entry refers to.
user_id: str, optional
Player's user ID.
Only present for Steam and Epic Games players.
user_name: str
Player's username (display name).
tier: int
Player's tier on the specified playlist.
skill: int
Player's skill rating on the specified playlist.
"""

__slots__ = ("platform", "playlist_key", "user_name", "user_id", "tier", "skill")

def __init__(
self,
platform: Platform,
playlist_key: PlaylistKey,
data: Dict[str, Any],
) -> None:
self.platform = platform
self.playlist_key = playlist_key
self.user_name: str = data["user_name"]
self.user_id: Optional[str] = data.get("user_id")
if (
self.user_id is not None
and self.user_id.startswith(f"{platform.value}|")
and self.user_id.endswith("|0")
):
self.user_id = self.user_id[len(platform.value) + 1 : -2]
self.tier: int = data["tier"]
self.skill: int = data["skill"]


class SkillLeaderboard:
"""SkillLeaderboard()
Represents Rocket League playlist's skill leaderboard for a single platform.
Attributes
----------
platform: Platform
Platform that this leaderboard refers to.
playlist_key: PlaylistKey
Playlist that this leaderboard refers to.
players: list of `StatLeaderboardPlayer`
List of playlist's top 100 players on the platform.
"""

__slots__ = ("platform", "playlist_key", "players")

def __init__(
self,
platform: Platform,
playlist_key: PlaylistKey,
data: Dict[str, Any],
) -> None:
self.platform = platform
self.playlist_key = playlist_key
self.players = [
SkillLeaderboardPlayer(platform, playlist_key, player_data)
for player_data in data["leaderboard"]
]


class StatLeaderboardPlayer:
"""StatLeaderboardPlayer()
Represents Rocket League Player on a platform's stat leaderboard.
Attributes
----------
platform: Platform
Platform that this leaderboard entry refers to.
stat: Stat
Stat that this leaderboard entry refers to.
user_id: str, optional
Player's user ID.
Only present for Steam and Epic Games players.
user_name: str
Player's username (display name).
value: int
Value of the specified stat for the player.
"""

__slots__ = ("platform", "stat", "user_name", "user_id", "value")

def __init__(
self,
platform: Platform,
stat: Stat,
data: Dict[str, Any],
) -> None:
self.platform = platform
self.stat = stat
self.user_name: str = data["user_name"]
self.user_id: Optional[str] = data.get("user_id")
if (
self.user_id is not None
and self.user_id.startswith(f"{platform.value}|")
and self.user_id.endswith("|0")
):
self.user_id = self.user_id[len(platform.value) + 1 : -2]
self.value: int = data[stat.value]


class StatLeaderboard:
"""StatLeaderboard()
Represents Rocket League stat leaderboard for a single platform.
Attributes
----------
platform: Platform
Platform that this leaderboard refers to.
stat: Stat
Stat that this leaderboard refers to.
players: list of `StatLeaderboardPlayer`
List of stat's top 100 players on the platform.
"""

__slots__ = ("platform", "stat", "players")

def __init__(
self,
platform: Platform,
stat: Stat,
data: Dict[str, Any],
) -> None:
self.platform = platform
self.stat = stat
self.players = [
StatLeaderboardPlayer(platform, stat, player_data)
for player_data in data[stat.value]
]
13 changes: 8 additions & 5 deletions rlapi/player.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
import contextlib
from typing import Any, Dict, Final, List, Optional, Union

from .enums import Platform, PlaylistKey
from .enums import Platform, PlaylistKey, Stat
from .tier_estimates import TierEstimates
from .typedefs import PlaylistBreakdownType, TierBreakdownType

Expand Down Expand Up @@ -260,6 +260,11 @@ class PlayerStats:
"""PlayerStats()
Represents player stats (assists, goals, MVPs, etc.).
.. container:: operations
``x[key]``
Lookup player's stat value by `Stat` enum.
Attributes
----------
assists: int
Expand Down Expand Up @@ -294,10 +299,8 @@ def __init__(self, data: List[Dict[str, Any]]) -> None:
self.shots: int = stats.get("shots", 0)
self.wins: int = stats.get("wins", 0)

def __getitem__(self, key: str) -> int:
if key not in self.__slots__:
raise KeyError(key)
return int(getattr(self, key))
def __getitem__(self, stat: Stat) -> int:
return int(getattr(self, stat.name))

def __repr__(self) -> str:
attrs = " ".join(f"{key}={getattr(self, key)}" for key in self.__slots__)
Expand Down

0 comments on commit 46d967e

Please sign in to comment.