Skip to content

Commit d437db3

Browse files
committed
feat: session ELO leaderboard embed and green/red ELO diff coloring
- Add in-memory session ELO tracker (resets on reboot) with a live embed in the queue status channel showing cumulative gains/losses per player, sorted descending, colored via diff code block - Color ELO changes green/red in per-series summary using diff blocks - Fix ranked display history search to filter by embed title so it can't accidentally latch onto the session ELO message
1 parent f2cf7a2 commit d437db3

1 file changed

Lines changed: 59 additions & 2 deletions

File tree

cogs/ranked.py

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,8 @@ def __init__(self, bot):
428428
self.bots = None # type: discord.Role | None
429429
self.bot = bot
430430
self.ranked_display = None
431+
self.elo_display = None # type: discord.Message | None
432+
self.session_elo: dict[int, tuple[str, float]] = {}
431433
self.session = None # type: aiohttp.ClientSession | None
432434
self.check_queue_joins.start()
433435
self.lobby = self.bot.get_channel(LOBBY_VC_ID)
@@ -561,7 +563,8 @@ async def update_ranked_display(self):
561563

562564
qstatus_channel = get(self.bot.get_all_channels(), id=QUEUE_STATUS_CHANNEL_ID)
563565
async for msg in qstatus_channel.history(limit=None):
564-
if msg.author.id == self.bot.user.id:
566+
if (msg.author.id == self.bot.user.id and msg.embeds
567+
and msg.embeds[0].title == "xRC Sim Ranked Queues"):
565568
self.ranked_display = msg
566569
logger.info("Found Ranked Queue Display")
567570
break
@@ -621,6 +624,55 @@ async def update_ranked_display(self):
621624
logger.error(e)
622625
self.ranked_display = None
623626

627+
def _accumulate_session_elo(self, response):
628+
for side in ('red', 'blue'):
629+
names = response.get(f'{side}_display_names', [])
630+
players = response.get(f'{side}_player_elos', [])
631+
changes = response.get(f'{side}_elo_changes', [])
632+
for name, player, change in zip(names, players, changes):
633+
uid = player['player']
634+
_, prev_total = self.session_elo.get(uid, (name, 0.0))
635+
self.session_elo[uid] = (name, prev_total + change)
636+
637+
async def update_elo_display(self):
638+
qstatus_channel = get(self.bot.get_all_channels(), id=QUEUE_STATUS_CHANNEL_ID)
639+
if qstatus_channel is None:
640+
return
641+
642+
if self.elo_display is None:
643+
async for msg in qstatus_channel.history(limit=20):
644+
if (msg.author.id == self.bot.user.id and msg.embeds
645+
and msg.embeds[0].title == "Session ELO"):
646+
self.elo_display = msg
647+
break
648+
649+
embed = discord.Embed(
650+
title="Session ELO",
651+
description="ELO gains/losses since last bot restart — resets on reboot",
652+
color=0x2ECC71,
653+
timestamp=datetime.now(timezone.utc),
654+
)
655+
embed.set_footer(text="xRC Sim Ranked", icon_url=XRC_SIM_LOGO_URL)
656+
657+
if not self.session_elo:
658+
embed.add_field(name="No games yet", value="Play a match to see ELO changes!", inline=False)
659+
else:
660+
sorted_players = sorted(self.session_elo.values(), key=lambda x: x[1], reverse=True)
661+
lines = [
662+
f"{'+' if total >= 0 else '-'} {name:<20} {total:+.1f}"
663+
for name, total in sorted_players
664+
]
665+
embed.add_field(name="Players", value="```diff\n" + "\n".join(lines) + "\n```", inline=False)
666+
667+
if self.elo_display is None:
668+
self.elo_display = await qstatus_channel.send(embed=embed)
669+
else:
670+
try:
671+
await self.elo_display.edit(embed=embed)
672+
except Exception as e:
673+
logger.error(e)
674+
self.elo_display = None
675+
624676
async def queue_player(self, interaction: discord.Interaction, game: str, from_button: bool = False):
625677
logger.info(f"{interaction.user.name} called /q")
626678
try:
@@ -1772,12 +1824,14 @@ async def submit(self, interaction: discord.Interaction, red_score: int, blue_sc
17721824

17731825
current_match.elo_history.append(response)
17741826
current_match.game_scores.append((red_score, blue_score))
1827+
self._accumulate_session_elo(response)
17751828
embed = self.create_score_embed(current_match, red_score, blue_score, response)
17761829

17771830
password_channel = (interaction.guild.get_channel(current_match.password_channel_id)
17781831
if current_match.password_channel_id else None)
17791832
await (password_channel or interaction.channel).send(embed=embed)
17801833
await interaction.followup.send(result_message, ephemeral=True)
1834+
await self.update_elo_display()
17811835

17821836
if gg:
17831837
summary_embed = self.create_series_summary_embed(current_match)
@@ -1903,7 +1957,10 @@ def create_series_summary_embed(self, match: XrcGame) -> discord.Embed:
19031957
blue_totals = [sum(r['blue_elo_changes'][i] for r in history) for i in range(len(blue_names))]
19041958

19051959
def fmt(names, totals):
1906-
return "\n".join(f"{name} `{'%+.1f' % t}`" for name, t in zip(names, totals)) or "—"
1960+
return "\n".join(
1961+
f"{name} ```diff\n{'%+.1f' % t}\n```"
1962+
for name, t in zip(names, totals)
1963+
) or "—"
19071964

19081965
embed.add_field(name="🟥 Red", value=fmt(red_names, red_totals), inline=True)
19091966
embed.add_field(name="🟦 Blue", value=fmt(blue_names, blue_totals), inline=True)

0 commit comments

Comments
 (0)