From d6b4be55afd4477ffd03e141fde693a216125896 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 24 Mar 2020 00:02:55 +0100 Subject: [PATCH] Add brawlhalla duos --- royalpack/commands/brawlhalla.py | 88 ++++++++++++++++++++++++++---- royalpack/tables/__init__.py | 2 + royalpack/tables/brawlhalla.py | 34 +++++++++++- royalpack/tables/brawlhalladuos.py | 58 ++++++++++++++++++++ 4 files changed, 169 insertions(+), 13 deletions(-) create mode 100644 royalpack/tables/brawlhalladuos.py diff --git a/royalpack/commands/brawlhalla.py b/royalpack/commands/brawlhalla.py index e1c7dcb4..7dd1461e 100644 --- a/royalpack/commands/brawlhalla.py +++ b/royalpack/commands/brawlhalla.py @@ -6,8 +6,9 @@ from typing import * from royalnet.commands import * from royalnet.utils import * from royalnet.serf.telegram.escape import escape as tg_escape -from ..tables import Steam, Brawlhalla +from ..tables import Steam, Brawlhalla, BrawlhallaDuo from ..types import BrawlhallaRank, BrawlhallaMetal, BrawlhallaTier +from sqlalchemy import or_, and_ log = logging.getLogger(__name__) @@ -36,15 +37,30 @@ class BrawlhallaCommand(Command): @staticmethod def _display(bh: Brawlhalla) -> str: - string = f"โ„น๏ธ [b]{bh.name}[/b]\n\n" + string = [f"โ„น๏ธ [b]{bh.name}[/b]", ""] if bh.rank_1v1: - string += f"1v1: [b]{bh.rank_1v1}[/b] ({bh.rating_1v1} MMR)\n" + string.append("๐Ÿ‘ค [b]1v1[/b]") + string.append(f"[b]{bh.rank_1v1}[/b] ({bh.rating_1v1} MMR)") + string.append("") - return string + duos = bh.duos + + if len(bh.duos) != 0: + string.append(f"๐Ÿ‘ฅ [b]2v2[/b]") + + for duo in bh.duos: + + other = duo.other(bh) + string.append(f"Con [b]{other.steam.user}[/b]: [b]{duo.rank_2v2}[/b] ({duo.rating_2v2} MMR)") + + if len(bh.duos) != 0: + string.append("") + + return "\n".join(string) async def _notify(self, - obj: Brawlhalla, + obj: Union[Brawlhalla, BrawlhallaDuo], attribute_name: str, old_value: Any, new_value: Any): @@ -53,17 +69,23 @@ class BrawlhallaCommand(Command): new_rank: Optional[BrawlhallaRank] = new_value if new_rank > old_rank: message = f"๐Ÿ“ˆ [b]{obj.steam.user}[/b] รจ salito a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla! Congratulazioni!" - elif new_rank < old_rank: - message = f"๐Ÿ“‰ [b]{obj.steam.user}[/b] รจ sceso a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla." else: - return + message = f"๐Ÿ“‰ [b]{obj.steam.user}[/b] รจ sceso a [b]{new_value}[/b] ({obj.rating_1v1} MMR) in 1v1 su Brawlhalla." + await self._send(message) + elif attribute_name == "rank_2v2": + old_rank: Optional[BrawlhallaRank] = old_value + new_rank: Optional[BrawlhallaRank] = new_value + if new_rank > old_rank: + message = f"๐Ÿ“ˆ [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] sono saliti a [b]{new_value}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla! Congratulazioni!" + else: + message = f"๐Ÿ“‰ [b]{obj.one.steam.user}[/b] e [b]{obj.two.steam.user}[/b] sono scesi a [b]{new_value}[/b] ({obj.rating_2v2} MMR) in 2v2 su Brawlhalla." await self._send(message) @staticmethod - async def _change(obj: Brawlhalla, + async def _change(obj: Union[Brawlhalla, BrawlhallaDuo], attribute_name: str, new_value: Any, - callback: Callable[[Brawlhalla, str, Any, Any], Awaitable[None]]): + callback: Callable[[Union[Brawlhalla, BrawlhallaDuo], str, Any, Any], Awaitable[None]]): old_value = obj.__getattribute__(attribute_name) if old_value != new_value: await callback(obj, attribute_name, old_value, new_value) @@ -71,6 +93,7 @@ class BrawlhallaCommand(Command): async def _update(self, steam: Steam, db_session): BrawlhallaT = self.alchemy.get(Brawlhalla) + DuoT = self.alchemy.get(BrawlhallaDuo) log.info(f"Updating: {steam}") async with aiohttp.ClientSession() as session: bh: Brawlhalla = steam.brawlhalla @@ -104,6 +127,48 @@ class BrawlhallaCommand(Command): tier = BrawlhallaTier(int(tier_name)) rank = BrawlhallaRank(metal=metal, tier=tier) await self._change(bh, "rank_1v1", rank, self._notify) + + for jduo in j.get("2v2", []): + bhduo: Optional[BrawlhallaDuo] = await asyncify( + db_session.query(DuoT) + .filter( + or_( + and_( + DuoT.id_one == jduo["brawlhalla_id_one"], + DuoT.id_two == jduo["brawlhalla_id_two"] + ), + and_( + DuoT.id_one == jduo["brawlhalla_id_two"], + DuoT.id_two == jduo["brawlhalla_id_one"] + ) + ) + ) + .one_or_none + ) + if bhduo is None: + if bh.brawlhalla_id == jduo["brawlhalla_id_one"]: + otherbh: Optional[Brawlhalla] = await asyncify( + db_session.query(BrawlhallaT).get, jduo["brawlhalla_id_two"] + ) + else: + otherbh: Optional[Brawlhalla] = await asyncify( + db_session.query(BrawlhallaT).get, jduo["brawlhalla_id_one"] + ) + if otherbh is None: + continue + bhduo = DuoT( + one=bh, + two=otherbh, + ) + + db_session.add(bhduo) + await self._change(bhduo, "rating_2v2", jduo["rating"], self._notify) + metal_name, tier_name = jduo["tier"].split(" ", 1) + metal = BrawlhallaMetal[metal_name.upper()] + tier = BrawlhallaTier(int(tier_name)) + rank = BrawlhallaRank(metal=metal, tier=tier) + await self._change(bhduo, "rank_2v2", rank, self._notify) + await asyncify(db_session.commit) async def _updater(self, period: int): @@ -117,8 +182,7 @@ class BrawlhallaCommand(Command): try: await self._update(steam, session) except Exception as e: - sentry_sdk.capture_exception(e) - log.error(f"Error while updating {steam.user.username}: {e}") + sentry_exc(e) await asyncio.sleep(1) await asyncify(session.commit) session.close() diff --git a/royalpack/tables/__init__.py b/royalpack/tables/__init__.py index 87099de9..71db86ca 100644 --- a/royalpack/tables/__init__.py +++ b/royalpack/tables/__init__.py @@ -13,6 +13,7 @@ from .brawlhalla import Brawlhalla from .polls import Poll from .pollcomments import PollComment from .pollvotes import PollVote +from .brawlhalladuos import BrawlhallaDuo # Enter the tables of your Pack here! available_tables = [ @@ -30,6 +31,7 @@ available_tables = [ Poll, PollComment, PollVote, + BrawlhallaDuo, ] # Don't change this, it should automatically generate __all__ diff --git a/royalpack/tables/brawlhalla.py b/royalpack/tables/brawlhalla.py index 99d71cce..27b60d66 100644 --- a/royalpack/tables/brawlhalla.py +++ b/royalpack/tables/brawlhalla.py @@ -15,7 +15,7 @@ class Brawlhalla: @declared_attr def _steamid(self): - return Column(BigInteger, ForeignKey("steam._steamid"), primary_key=True) + return Column(BigInteger, ForeignKey("steam._steamid"), unique=True) @declared_attr def steam(self): @@ -52,6 +52,38 @@ class Brawlhalla: self.metal_1v1 = value.metal self.tier_1v1 = value.tier + @property + def duos(self): + return [*self._duos_one, *self._duos_two] + + @property + def rating_2v2(self): + duos = sorted(self.duos, key=lambda d: -d.rating) + if len(duos) == 0: + return None + return duos[0].rating_2v2 + + @property + def tier_2v2(self): + duos = sorted(self.duos, key=lambda d: -d.rating) + if len(duos) == 0: + return None + return duos[0].tier_2v2 + + @property + def metal_2v2(self): + duos = sorted(self.duos, key=lambda d: -d.rating) + if len(duos) == 0: + return None + return duos[0].metal_2v2 + + @property + def rank_2v2(self): + duos = sorted(self.duos, key=lambda d: -d.rating) + if len(duos) == 0: + return None + return duos[0].rank_2v2 + def __repr__(self): return f"" diff --git a/royalpack/tables/brawlhalladuos.py b/royalpack/tables/brawlhalladuos.py new file mode 100644 index 00000000..1561cc2d --- /dev/null +++ b/royalpack/tables/brawlhalladuos.py @@ -0,0 +1,58 @@ +from sqlalchemy import * +from sqlalchemy.orm import * +from sqlalchemy.ext.declarative import declared_attr +from ..types import BrawlhallaRank, BrawlhallaTier, BrawlhallaMetal + + +class BrawlhallaDuo: + __tablename__ = "brawlhalladuos" + + @declared_attr + def id_one(self): + return Column(Integer, ForeignKey("brawlhalla.brawlhalla_id"), primary_key=True) + + @declared_attr + def id_two(self): + return Column(Integer, ForeignKey("brawlhalla.brawlhalla_id"), primary_key=True) + + @declared_attr + def one(self): + return relationship("Brawlhalla", foreign_keys=self.id_one, backref=backref("_duos_one")) + + @declared_attr + def two(self): + return relationship("Brawlhalla", foreign_keys=self.id_two, backref=backref("_duos_two")) + + @declared_attr + def rating_2v2(self): + return Column(Integer) + + @declared_attr + def tier_2v2(self): + return Column(Enum(BrawlhallaTier)) + + @declared_attr + def metal_2v2(self): + return Column(Enum(BrawlhallaMetal)) + + @property + def rank_2v2(self): + return BrawlhallaRank(metal=self.metal_2v2, tier=self.tier_2v2) + + @rank_2v2.setter + def rank_2v2(self, value): + if not isinstance(value, BrawlhallaRank): + raise TypeError("rank_1v1 can only be set to BrawlhallaRank values.") + self.metal_2v2 = value.metal + self.tier_2v2 = value.tier + + def other(self, bh): + if bh == self.one: + return self.two + elif bh == self.two: + return self.one + else: + raise ValueError("Argument is unrelated to this duo.") + + def __repr__(self): + return f""