Skip to content

Commit

Permalink
Added games_won and games_lost into stats summary endpoint (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
Valentin Porchet authored May 21, 2023
1 parent 99b555a commit 8f32930
Show file tree
Hide file tree
Showing 14 changed files with 39 additions and 70 deletions.
2 changes: 2 additions & 0 deletions app/models/players.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,8 @@ class AverageStatsSummary(BaseModel):

class StatsSummary(BaseModel):
games_played: int = Field(..., description="Number of games played", ge=0)
games_won: int = Field(..., description="Number of games won", ge=0)
games_lost: int = Field(..., description="Number of games lost", ge=0)
time_played: int = Field(..., description="Time played (in seconds)", ge=0)
winrate: float = Field(..., description="Winrate (in percent)", ge=0.0, le=100.0)
kda: float = Field(..., description="Kill / Death / Assist ratio", ge=0.0)
Expand Down
83 changes: 25 additions & 58 deletions app/parsers/player_stats_summary_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
class PlayerStatsSummaryParser(PlayerParser):
"""Overwatch player profile page Parser class"""

generic_stats_names = ["games_played", "games_lost", "time_played"]
generic_stats_names = ["games_played", "games_won", "games_lost", "time_played"]
total_stats_names = ["eliminations", "assists", "deaths", "damage", "healing"]

stats_placeholder = {
"games_played": 0,
"games_lost": 0, # We'll keep this one for calculation
"games_won": 0,
"games_lost": 0,
"time_played": 0,
"winrate": 0,
"kda": 0,
Expand All @@ -45,10 +46,17 @@ def filter_request_using_query(self, **kwargs) -> dict:
)

heroes_stats = self.__compute_heroes_data(gamemodes, platforms)
if not heroes_stats:
return {}

roles_stats = self.__get_roles_stats(heroes_stats)
general_stats = self.__get_general_stats(roles_stats)

return self.__compute_stats(general_stats, roles_stats, heroes_stats)
return {
"general": general_stats,
"roles": roles_stats,
"heroes": heroes_stats,
}

def parse_data(self) -> dict | None:
# We must check if we have the expected section for profile. If not,
Expand Down Expand Up @@ -125,50 +133,6 @@ def __init_heroes_data(

return computed_heroes_stats

def __compute_stats(
self,
general_stats: dict | None,
roles_stats: dict | None,
heroes_stats: dict | None,
) -> dict:
"""Last computing before sending the stats, here we will remove the
"games_lost" key.
"""
if not heroes_stats:
return {}

filtered_general_stats = {
stat_key: stat_value
for stat_key, stat_value in general_stats.items()
if stat_key != "games_lost"
}

filtered_roles_stats = {
role.value: {
stat_key: stat_value
for stat_key, stat_value in roles_stats[role.value].items()
if stat_key != "games_lost"
}
for role in Role
if role.value in roles_stats
}

filtered_heroes_stats = {
hero.value: {
stat_key: stat_value
for stat_key, stat_value in heroes_stats[hero.value].items()
if stat_key != "games_lost"
}
for hero in HeroKey
if hero.value in heroes_stats
}

return {
"general": filtered_general_stats,
"roles": filtered_roles_stats,
"heroes": filtered_heroes_stats,
}

@staticmethod
def _get_category_stats(category: str, hero_stats: dict) -> dict:
category_stats = filter(lambda x: x["category"] == category, hero_stats)
Expand Down Expand Up @@ -250,6 +214,14 @@ def __compute_hero_stats(self, hero_stats: dict) -> dict | None:
# in order for the player to have 50% winrate
games_lost = round(games_played / 2) if games_lost < 0 else games_lost

# We just calculate games won like this because sometimes Blizzard
# exposes "Games Won" stats several times for the same hero and
# not with the same value, but it doesn't happen for games lost
games_won = games_played - games_lost

# Make sure it's not negative
games_won = max(games_won, 0)

combat_stats = self._get_category_stats("combat", hero_stats)
eliminations = self._get_stat_value("eliminations", combat_stats)
deaths = self._get_stat_value("deaths", combat_stats)
Expand All @@ -261,6 +233,7 @@ def __compute_hero_stats(self, hero_stats: dict) -> dict | None:

return {
"games_played": games_played,
"games_won": games_won,
"games_lost": games_lost,
"time_played": time_played,
"total": {
Expand All @@ -272,10 +245,7 @@ def __compute_hero_stats(self, hero_stats: dict) -> dict | None:
},
}

def __get_roles_stats(self, heroes_stats: dict | None) -> dict | None:
if not heroes_stats:
return None

def __get_roles_stats(self, heroes_stats: dict) -> dict:
# Initialize stats
roles_stats = {role_key: deepcopy(self.stats_placeholder) for role_key in Role}

Expand All @@ -302,10 +272,7 @@ def __get_roles_stats(self, heroes_stats: dict | None) -> dict | None:
if role_stat["games_played"] > 0
}

def __get_general_stats(self, roles_stats: dict | None) -> dict | None:
if not roles_stats:
return None

def __get_general_stats(self, roles_stats: dict) -> dict:
general_stats = deepcopy(self.stats_placeholder)

# Retrieve raw data from roles
Expand All @@ -324,14 +291,14 @@ def __get_general_stats(self, roles_stats: dict | None) -> dict | None:

def __get_winrate_from_stat(self, stat: dict) -> float:
return self.__get_winrate(
stat.get("games_played") or 0, stat.get("games_lost") or 0
stat.get("games_won") or 0, stat.get("games_played") or 0
)

@staticmethod
def __get_winrate(games_played: int, games_lost: int) -> float:
def __get_winrate(games_won: int, games_played: int) -> float:
if games_played <= 0:
return 0
return round(((games_played - games_lost) / games_played) * 100, 2)
return round((games_won / games_played) * 100, 2)

def __get_kda_from_stat(self, stat: dict) -> float:
return self.__get_kda(
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "overfast-api"
version = "2.15.1"
version = "2.16.0"
description = "Overwatch API giving data about heroes, maps, and players statistics."
license = "MIT"
authors = ["TeKrop <[email protected]>"]
Expand Down
Loading

0 comments on commit 8f32930

Please sign in to comment.