Source code for brawlwiki.utils
import requests
from .errors import BrawlerNotFound
API_URL = "https://ariusx7.github.io/brawlwiki-api/api/{}"
def get_full_name(name: str, data: dict) -> str:
"""Returns full name of a Brawler from partial name.
Parameters
--------------
name: :class:`str`
The partial name of the Brawler.
data: :class:`dict`
The dictionary containing Brawler data
accessed from the BrawlWiki API.
Returns
---------
:class:`str`
The full name of the Brawler.
Raises
--------
BrawlerNotFound
If a Brawler can't be found from the given partial name.
"""
# special cases
if "bit" in name:
return "8-Bit"
if "primo" in name:
return "El Primo"
for brawler in data:
if name.lower() in brawler.lower():
return brawler
raise BrawlerNotFound(f"Brawler with name '{name}' not found.")
class BaseModel:
"""Base model class for Brawler stats."""
@classmethod
def _get(cls, name: str):
"""Get a stat instance of the given Brawler.
Parameters
--------------
name: :class:`str`
The full/partial name of the Brawler.
Returns
---------
:class:`dict`
The dictionary containing Brawler data
accessed from the BrawlWiki API.
Raises
--------
BrawlerNotFound
If a Brawler can't be found from the given ``name``.
"""
res = requests.get(API_URL.format("brawlers.json"))
data: dict = res.json()
name = get_full_name(name, data)
return data[name]
def __getattr__(self, attr: str):
# Instead of raising an exception, return
# None if attribute doesn't exist.
# This works because __getattr__ is only
# called when an attribute doesn't exist
return None
[docs]class Attack(BaseModel):
"""Class to represent a Brawler attack.
Parameters
--------------
data: :class:`dict`
The dictionary containing Brawler data
accessed from the BrawlWiki API.
Attributes
-------------
brawler: :class:`str`
The name of the Brawler.
name: :class:`str`
The name of the attack.
description: :class:`str`
The description of the attack.
value: :class:`int`
The damage (or any other) value of the attack.
action: :class:`str`
The action performed by the attack.
projectiles: :class:`int`
The number of projectiles of the attack.
range: :class:`float`
The range of the attack.
reload: :class:`float`
The reload speed of the attack.
special: Optional[:class:`str`]
The optional special effect of the attack.
"""
def __init__(self, data: dict):
self.brawler = data["name"]
data = data["attack"]
self.name: str = data["name"]
self.description: str = data["description"]
self.value: int = data["value"]
self.action: str = data["action"]
self.projectiles: int = data["projectiles"]
self.range: float = data["range"]
self.reload: float = data["reload"]
if "special" in data:
self.special: str = data["special"]
def __repr__(self):
return (
"<Attack object name='{0.name}' brawler='{0.brawler}'>"
).format(self)
[docs] @classmethod
def get(cls, name: str):
"""Get an ``Attack`` instance of the given Brawler.
Parameters
--------------
name: :class:`str`
The full/partial name of the Brawler.
Returns
----------
:class:`Attack`
``Attack`` instance from given name.
Raises
--------
BrawlerNotFound
If a Brawler can't be found from the given ``name``.
"""
data = cls._get(name)
return cls(data)
[docs]class Super(BaseModel):
"""Class to represent a Brawler super.
Parameters
--------------
data: :class:`dict`
The dictionary containing Brawler data
accessed from the BrawlWiki API.
Attributes
-------------
brawler: :class:`str`
The name of the Brawler.
name: :class:`str`
The name of the super.
description: :class:`str`
The description of the super.
value: Optional[:class:`int`]
The damage (or any other) value of the super.
Spawns have ``spawn_damage`` and ``spawn_health``.
action: :class:`str`
The action performed by the super.
projectiles: :class:`int`
The number of projectiles of the super.
range: :class:`float`
The range of the super.
hits_required: :class:`int`
The number of hits required to charge the super.
has_spawn: :class:`bool`
Whether super spawns a unit or not.
spawn_name: Optional[:class:`str`]
The name of the spawn.
spawn_health: Optional[:class:`int`]
The health of the spawn.
spawn_damage: Optional[:class:`int`]
The damage of the spawn.
spawn_range: Optional[:class:`float`]
The range of the spawn.
spawn_speed: Optional[:class:`int`]
The speed of the spawn.
"""
def __init__(self, data: dict):
self.brawler = data["name"]
data = data["super"]
self.name: str = data["name"]
self.description: str = data["description"]
self.value: int = data["value"]
self.action: str = data["action"]
self.projectiles: int = data["projectiles"]
self.range: float = data["range"]
self.hits_required: float = data["hits_required"]
if "spawn" in data:
spawn_data = data["spawn"]
self.has_spawn = True
self.spawn_name: str = spawn_data["name"]
self.spawn_health: int = spawn_data["health"]
self.spawn_range: float = spawn_data["range"]
if spawn_data["damage"]:
self.spawn_damage: int = spawn_data["damage"]
if spawn_data["speed"]:
self.spawn_speed: int = spawn_data["speed"]
else:
self.has_spawn = False
def __repr__(self):
return (
"<Super object name='{0.name}' brawler='{0.brawler}'>"
).format(self)
[docs] @classmethod
def get(cls, name: str):
"""Get a ``Super`` instance of the given Brawler.
Parameters
--------------
name: :class:`str`
The full/partial name of the Brawler.
Returns
----------
:class:`Super`
``Super`` instance from given name.
Raises
--------
BrawlerNotFound
If a Brawler can't be found from the given ``name``.
"""
data = cls._get(name)
return cls(data)
[docs]class StarPowers(BaseModel):
"""Class to represent the Brawler star powers.
Parameters
--------------
data: :class:`dict`
The dictionary containing Brawler data
accessed from the BrawlWiki API.
Attributes
-------------
brawler: :class:`str`
The name of the Brawler.
first_name: :class:`str`
The name of the first star power.
first_description: :class:`str`
The description of the first star power.
first_values: List[:class:`str`]
The list of numbers in first star power description.
second_name: :class:`str`
The name of the second star power.
second_description: :class:`str`
The description of the second star power.
second_values: List[:class:`str`]
The list of numbers in second star power description.
"""
def __init__(self, data: dict):
self.brawler = data["name"]
data = data["star_powers"]
self.first_name: str = data["first"]["name"]
self.first_values: list = data["first"]["values"]
first_desc_raw: str = data["first"]["description"]
self.first_description = first_desc_raw.format(*self.first_values)
self.second_name: str = data["second"]["name"]
self.second_values: list = data["second"]["values"]
second_desc_raw: str = data["second"]["description"]
self.second_description = second_desc_raw.format(*self.second_values)
def __repr__(self):
return "<StarPowers object brawler='{0.brawler}'>".format(self)
[docs] @classmethod
def get(cls, name: str):
"""Get a ``StarPowers`` instance of the given Brawler.
Parameters
--------------
name: :class:`str`
The full/partial name of the Brawler.
Returns
----------
:class:`StarPowers`
``StarPowers`` instance from given name.
Raises
--------
BrawlerNotFound
If a Brawler can't be found from the given ``name``.
"""
data = cls._get(name)
return cls(data)
[docs]class Skins(BaseModel):
"""A class to represent the Brawler skins.
Parameters
--------------
data: :class:`dict`
The dictionary containing Brawler data
accessed from the BrawlWiki API.
Attributes
-------------
brawler: :class:`str`
The name of the Brawler.
names: List[:class:`str`]
The names of the Brawler skins.
regular: Optional[Dict[:class:`str`, Dict]]
A dictionary containing regular skins data.
The skins data takes skin name as key
and has this structure:
::
{
"cost": 150,
"currency": "Gems",
}
special: Optional[Dict[:class:`str`, Dict]]
A dictionary containing special skins data.
The skins data takes skin name as key
and has this structure:
::
{
"cost": 150,
"currency": "Gems",
"event": "2019 Brawlidays"
}
"""
def __init__(self, data: dict):
self.brawler = data["name"]
data = data["skins"]
self.names = []
if "regular" in data:
self.regular: dict = data["regular"]
self.names += list(self.regular.keys())
if "special" in data:
self.special: dict = data["special"]
self.names += list(self.special.keys())
def __repr__(self):
return "<Skins object brawler='{0.brawler}'>".format(self)
[docs] @classmethod
def get(cls, name: str):
"""Get a ``Skins`` instance of the given Brawler.
Parameters
--------------
name: :class:`str`
The full/partial name of the Brawler.
Returns
----------
:class:`Skins`
``Skins`` instance from given name.
Raises
--------
BrawlerNotFound
If a Brawler can't be found from the given ``name``.
"""
data = cls._get(name)
return cls(data)
[docs]class Stats(BaseModel):
"""A class to represent the Brawler stats.
Parameters
--------------
data: :class:`dict`
The dictionary containing Brawler data
accessed from the BrawlWiki API.
Attributes
-------------
brawler: :class:`str`
The name of the Brawler.
offense: :class:`int`
The offense stat of the Brawler.
defense: :class:`int`
The defense stat of the Brawler.
utility: :class:`int`
The utility stat of the Brawler.
"""
def __init__(self, data: dict):
self.brawler = data["name"]
data = data["stats"]
self.offense = data["offense"]
self.defense = data["defense"]
self.utility = data["utility"]
def __repr__(self):
return "<Stats object brawler='{0.brawler}'>".format(self)
[docs] @classmethod
def get(cls, name: str):
"""Get a ``Stats`` instance of the given Brawler.
Parameters
--------------
name: :class:`str`
The full/partial name of the Brawler.
Returns
----------
:class:`Stats`
``Stats`` instance from given name.
Raises
--------
BrawlerNotFound
If a Brawler can't be found from the given ``name``.
"""
data = cls._get(name)
return cls(data)
[docs]class VoiceLines(BaseModel):
"""A class to represent the Brawler voice lines.
Parameters
--------------
data: :class:`dict`
The dictionary containing Brawler data
accessed from the BrawlWiki API.
Attributes
-------------
brawler: :class:`str`
The name of the Brawler.
start_of_battle: List[:class:`str`]
The start of battle voicelines of the Brawler.
when_in_lead: List[:class:`str`]
The when in lead voicelines of the Brawler.
once_hurt: List[:class:`str`]
The once hurt voicelines of the Brawler.
getting_kill: List[:class:`str`]
The getting kill voicelines of the Brawler.
when_dying: List[:class:`str`]
The when dying voicelines of the Brawler.
when_attacking: List[:class:`str`]
The when attacking voicelines of the Brawler.
using_super: List[:class:`str`]
The using super voicelines of the Brawler.
"""
def __init__(self, data: dict):
self.brawler = data["name"]
data = data["voice_lines"]
self.start_of_battle = data["start_of_battle"]
self.when_in_lead = data["when_in_lead"]
self.once_hurt = data["once_hurt"]
self.getting_kill = data["getting_kill"]
self.when_dying = data["when_dying"]
self.when_attacking = data["when_attacking"]
self.using_super = data["using_super"]
def __repr__(self):
return "<VoiceLines object brawler='{0.brawler}'>".format(self)
[docs] @classmethod
def get(cls, name: str):
"""Get a ``VoiceLines`` instance of the given Brawler.
Parameters
--------------
name: :class:`str`
The full/partial name of the Brawler.
Returns
----------
:class:`VoiceLines`
``VoiceLines`` instance from given name.
Raises
--------
BrawlerNotFound
If a Brawler can't be found from the given ``name``.
"""
data = cls._get(name)
return cls(data)