from typing import Set, Union
from enum import Enum
from merakicommons.ghost import ghost_load_on
from merakicommons.container import SearchableDictionary, SearchableLazyList, searchable
from merakicommons.cache import lazy_property
from cassiopeia import configuration
from cassiopeia.data import Region, Tier
from cassiopeia.core.common import CoreData, CassiopeiaGhost, CoreDataList, CassiopeiaLazyList, CassiopeiaObject
from cassiopeia.core.patch import Patch
from .dto import ChampionGGStatsDto, ChampionGGStatsListDto, ChampionGGMatchupDto, ChampionGGMatchupListDto, MultipleChampionGGStatsDto
from .data import Role
class ChampionGGStatsListData(CoreDataList):
_dto_type = ChampionGGStatsListDto
_renamed = {}
@property
def region(self) -> str:
return self._dto["region"]
class ChampionGGMatchupListData(CoreDataList):
_dto_type = ChampionGGMatchupListDto
_renamed = {}
@property
def region(self) -> str:
return self._dto["region"]
class ChampionGGStatsData(CoreData):
_dto_type = ChampionGGStatsDto
_renamed = {"championId": "id", "overallPerformanceScore": "performanceScore", "percentRolePlayed": "playRateByRole", "totalHeal": "totalHealed", "neutralMinionsKilledTeamJungle": "neutralMinionsKilledInTeamJungle", "neutralMinionsKilledEnemyJungle": "neutralMinionsKilledInEnemyJungle"}
def __call__(self, **kwargs):
if "elo" in kwargs:
self.elo = kwargs.pop("elo").split(",")
super().__call__(**kwargs)
return self
class MultipleChampionGGStatsData(CoreDataList):
_dto_type = MultipleChampionGGStatsDto
_renamed = {}
class ChampionGGMatchupData(CoreData):
_dto_type = ChampionGGMatchupDto
_renamed = {}
def __call__(self, **kwargs):
if "elo" in kwargs:
self.elo = kwargs.pop("elo").split(",")
super().__call__(**kwargs)
class ChampionGGChampionData(CoreData):
_dto_type = ChampionGGMatchupDto
_renamed = {}
def __call__(self, **kwargs):
if "elo" in kwargs:
self.elo = kwargs.pop("elo").split(",")
super().__call__(**kwargs)
########
# Core #
########
[docs]class ChampionGGMatchupStats:
def __init__(self, data, id):
self._id = id
self._twenty_to_thirty = data.get('twentyToThirty', None)
self._wins = data.get('wins', None)
self._winrate = data.get('winrate', None)
self._kills = data.get('kills', None)
self._neutral_minions_killed_team_jungle = data.get('neutralMinionsKilledTeamJungle', None)
self._total_damage_dealt_to_champions = data.get('totalDamageDealtToChampions', None)
self._role = data.get('role', None)
self._assists = data.get('assists', None)
self._ten_to_twenty = data.get('tenToTwenty', None)
self._thirty_to_end = data.get('thirtyToEnd', None)
self._zero_to_ten = data.get('zeroToTen', None)
self._gold_earned = data.get('goldEarned', None)
self._killing_sprees = data.get('killingSprees', None)
self._minions_killed = data.get('minionsKilled', None)
self._deaths = data.get('deaths', None)
self._weighted_score = data.get('weighedScore', None)
self._delta_twenty_to_thirty = data.get('deltatwentyToThirty', None)
self._delta_wins = data.get('deltawins', None)
self._delta_winrate = data.get('deltawinrate', None)
self._delta_kills = data.get('deltakills', None)
self._delta_neutral_minions_killed_team_jungle = data.get('deltaneutralMinionsKilledTeamJungle', None)
self._delta_total_damage_dealt_to_champions = data.get('deltatotalDamageDealtToChampions', None)
self._delta_assists = data.get('deltaassists', None)
self._delta_ten_to_twenty = data.get('deltatenToTwenty', None)
self._delta_thirty_to_end = data.get('deltathirtyToEnd', None)
self._delta_zero_to_ten = data.get('deltazeroToTen', None)
self._delta_gold_earned = data.get('deltagoldEarned', None)
self._delta_killing_sprees = data.get('deltakillingSprees', None)
self._delta_minions_killed = data.get('deltaminionsKilled', None)
self._delta_deaths = data.get('deltadeaths', None)
self._delta_weighted_score = data.get('deltaweighedScore', None)
from cassiopeia import Champion
self._champion = Champion(id=self.id, region="NA") # TODO give correct version
@property
def id(self) -> int:
return self._id
@property
def twenty_to_thirty(self) -> int:
return self._twenty_to_thirty
@property
def wins(self) -> int:
return self._wins
@property
def winrate(self) -> float:
return self._winrate
@property
def kills(self) -> int:
return self._kills
@property
def neutral_minions_killed_team_jungle(self) -> int:
return self._neutral_minions_killed_team_jungle
@property
def total_damage_dealt_to_champions(self) -> int:
return self._total_damage_dealt_to_champions
@property
def role(self) -> Role:
return self._role
@property
def assists(self) -> int:
return self._assists
@property
def thirty_to_end(self) -> int:
return self._thirty_to_end
@property
def zero_to_ten(self) -> int:
return self._zero_to_ten
@property
def gold_earned(self) -> int:
return self._gold_earned
@property
def killing_sprees(self) -> int:
return self._killing_sprees
@property
def minions_killed(self) -> int:
return self._minions_killed
@property
def deaths(self) -> int:
return self._deaths
@property
def weighted_score(self) -> int:
return self._weighted_score
@property
def delta_twenty_to_thirty(self) -> int:
return self._delta_twenty_to_thirty
@property
def delta_wins(self) -> int:
return self._delta_wins
@property
def delta_kills(self) -> int:
return self._delta_kills
@property
def delta_neutral_minions_killed_team_jungle(self) -> int:
return self._delta_neutral_minions_killed_team_jungle
@property
def delta_total_damage_dealt_to_champions(self) -> int:
return self._delta_total_damage_dealt_to_champions
@property
def delta_assists(self) -> int:
return self._delta_assists
@property
def delta_ten_to_twenty(self) -> int:
return self._delta_ten_to_twenty
@property
def delta_thirty_to_end(self) -> int:
return self._delta_thirty_to_end
@property
def delta_zero_to_ten(self) -> int:
return self._delta_zero_to_ten
@property
def delta_gold_earned(self) -> int:
return self._delta_gold_earned
@property
def delta_killing_sprees(self) -> int:
return self._delta_killing_sprees
@property
def delta_minions_killed(self) -> int:
return self._delta_minions_killed
@property
def delta_deaths(self) -> int:
return self._delta_deaths
@property
def delta_weighted_score(self) -> int:
return self._delta_weighted_score
@property
def champion(self) -> "Champion":
return self._champion
[docs]@searchable({str: ["enemy.champion"]})
class ChampionGGMatchup(CassiopeiaGhost):
_data_types = {ChampionGGMatchupData}
def __init__(self, id: int = None, champion: int = None, patch: Patch = None, elo: Set[str] = None, region: Union[Region, str] = None):
if region is None:
region = configuration.settings.default_region
if region is not None and not isinstance(region, Region):
region = Region(region)
if elo is None:
elo = "PLATINUM_DIAMOND_MASTER_CHALLENGER"
kwargs = {}
if region is not None:
kwargs["region"] = region
if patch is not None:
kwargs["patch"] = patch.name
if id is not None:
kwargs["id"] = id
if elo is not None:
kwargs["elo"] = elo
super().__init__(**kwargs)
self._patch = patch
def __get_query__(self):
return {"id": self.id, "patch": self.patch.name, "elo": "_".join(self.elo)}
@lazy_property
def region(self) -> Region:
return Region(self._data[ChampionGGMatchupData].region)
@property
def elo(self) -> Set[str]:
return self._data[ChampionGGMatchupData].elo
@property
def patch(self) -> Patch:
return self._patch
@property
def me(self) -> ChampionGGMatchupStats:
data = self._data[ChampionGGMatchupData]
if data.champ1_id == self._hack:
return ChampionGGMatchupStats(data.champ1, id=data.champ1_id)
else:
return ChampionGGMatchupStats(data.champ2, id=data.champ2_id)
@property
def enemy(self) -> ChampionGGMatchupStats:
data = self._data[ChampionGGMatchupData]
if data.champ1_id == self._hack:
return ChampionGGMatchupStats(data.champ2, id=data.champ2_id)
else:
return ChampionGGMatchupStats(data.champ1, id=data.champ1_id)
@property
def winrate(self) -> float:
total = self.me.wins + self.enemy.wins
return self.me.wins / total
@property
def nmatches(self) -> int:
return self.me.wins + self.enemy.wins
[docs]class ChampionGGMatchups(CassiopeiaLazyList):
_data_types = {ChampionGGMatchupListData}
def __init__(self, *, id: int, role: Union[Role, str], patch: Union[Patch, str], elo: Set[str] = None):
if not isinstance(role, Role):
role = Role(role)
kwargs = {}
CassiopeiaObject.__init__(self, **kwargs)
SearchableLazyList.__init__(self, iter([]))
if elo is None:
elo = "PLATINUM_DIAMOND_MASTER_CHALLENGER"
elif isinstance(elo, str):
if "_" in elo:
elo = elo.split("_")
elif "," in elo:
elo = elo.split(",")
self._patch = patch
self._role = role
self._elo = elo
self._id = id
@classmethod
def __get_query_from_kwargs__(cls, *, id: int, role: Union[Role, str], patch: Union[Patch, str], elo: Set[str] = None) -> dict:
if isinstance(role, Role):
role = role.value
if isinstance(patch, Patch):
patch = patch.name
if isinstance(elo, list):
elo = "_".join(elo)
query = {"role": role, "id": id, "patch": patch, "elo": elo}
return query
[docs]class ChampionGGStats(CassiopeiaObject):
_data_types = {ChampionGGStatsData}
def __init__(self, **kwargs):
if kwargs:
role = kwargs["role"]
region = kwargs["region"]
elo = kwargs["elo"]
patch = kwargs["patch"]
if not isinstance(role, Role):
role = Role(role)
if region is None:
region = configuration.settings.default_region
if region is not None and not isinstance(region, Region):
region = Region(region)
if elo is None:
elo = "PLATINUM_DIAMOND_MASTER_CHALLENGER"
elif isinstance(elo, str):
if "_" in elo:
elo = elo.split("_")
elif "," in elo:
elo = elo.split(",")
kwargs = {"id": id}
super().__init__(**kwargs)
self._region = region
self._patch = patch
self._role = role
self._elo = elo
else:
super().__init__()
def __get_query__(self):
return {"id": self.id, "patch": self.patch.name, "elo": "_".join(self.elo), "role": self.role.value}
@property
def elo(self) -> Set[str]:
return self._data[ChampionGGStatsData].elo
@property
def patch(self) -> Patch:
return self._data[ChampionGGStatsData].patch
@property
def role(self) -> Role:
return Role(self._data[ChampionGGStatsData].role)
@property
def id(self) -> int:
return self._data[ChampionGGStatsData].id
@property
def win_rate(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].winRate
@property
def play_rate(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].playRate
@property
def play_rate_by_role(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].playRateByRole
@property
def ban_rate(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].banRate
@property
def games_played(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].gamesPlayed
@property
def damage_composition(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].damageComposition
@property
def kills(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].kills
@property
def total_damage_taken(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].totalDamageTaken
@property
def wards_killed(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].wardsKilled
@property
def neutral_minions_killed_in_team_jungle(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].neutralMinionsKilledInTeamJungle
@property
def assists(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].assists
@property
def performance_score(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].performanceScore
@property
def neutral_minions_killed_in_enemy_jungle(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].neutralMinionsKilledInEnemyJungle
@property
def gold_earned(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].goldEarned
@property
def deaths(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].deaths
@property
def minions_killed(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].minionsKilled
@property
def total_healed(self) -> SearchableDictionary:
return self._data[ChampionGGStatsData].totalHealed
@property
def championgg_metadata(self) -> dict:
return {
"elo": [Tier(tier) for tier in self._data[ChampionGGStatsData].elo],
"patch": self.patch
}
@lazy_property
def matchups(self) -> list:
return ChampionGGMatchups(id=self.id, role=self.role, patch=self.patch, elo=self.elo)
class MultipleChampionGGStats(CassiopeiaGhost, list):
"""Contains data for one champion for multiple roles."""
_data_types = {MultipleChampionGGStatsData}
def __init__(self, *, id: int, patch: Union[Patch, str], elo: Set[str] = None, region: Union[Region, str] = None):
if region is None:
region = configuration.settings.default_region
if region is not None and not isinstance(region, Region):
region = Region(region)
if elo is None:
elo = "PLATINUM_DIAMOND_MASTER_CHALLENGER"
elif isinstance(elo, str):
if "_" in elo:
elo = elo.split("_")
elif "," in elo:
elo = elo.split(",")
kwargs = {"id": id}
super().__init__(**kwargs)
self._region = region
self._patch = patch
self._elo = elo
list.__init__(self, [])
@classmethod
def from_data(cls, data, id: int, patch: Union[Patch, str], elo: Set[str] = None, region: Union[Region, str] = None):
self = cls.__new__(cls)
cls.__init__(self, id=id, patch=patch, elo=elo, region=region)
for d in data:
self.append(d)
return self
def __get_query__(self):
return {"id": self.id, "patch": self.patch.name, "elo": "_".join(self.elo)}
@property
def region(self) -> Region:
return self._region
@property
def elo(self) -> Set[str]:
return self._elo
@property
def patch(self) -> Patch:
return self._patch
@CassiopeiaGhost.property(MultipleChampionGGStatsData)
@ghost_load_on(AttributeError)
def id(self) -> int:
return self._data[MultipleChampionGGStatsData].id
class ChampionGGChampion(object):
_data_types = {ChampionGGChampionData}
def __init__(self, *, id: int, patch: Patch, elo: Set[str] = None, region: Union[Region, str] = None):
self._id = id
if region is None:
region = configuration.settings.default_region
if region is not None and not isinstance(region, Region):
region = Region(region)
if elo is None:
elo = "PLATINUM_DIAMOND_MASTER_CHALLENGER"
self._region = region
self._elo = elo
if isinstance(patch, str):
patch = Patch.from_str(patch, region=region)
self._patch = patch
self._roles = {}
def __get_query__(self):
return {"id": self.id, "patch": self.patch.name, "elo": "_".join(self.elo)}
@lazy_property
def region(self) -> Region:
return self._region
@property
def elo(self) -> Set[str]:
return self._elo
@property
def patch(self) -> Patch:
return self._patch
@property
def id(self) -> int:
return self._id
def __getitem__(self, role: Union[Role, str]):
if not isinstance(role, Enum):
role = Role(role)
return self.roles[role]
def load(self):
role_data = MultipleChampionGGStats(id=self.id, patch=self.patch, elo=self.elo, region=self.region).load(load_groups={MultipleChampionGGStatsData})
for data in role_data._data[MultipleChampionGGStatsData]:
stats = ChampionGGStats.from_data(data=data)
self._roles[stats.role] = stats
@property
def roles(self):
if not self._roles:
self.load()
return self._roles