From 9746a9f3bfa65500dc3b69e176fad45b29b7cf8d Mon Sep 17 00:00:00 2001 From: SimolZimol <70102430+SimolZimol@users.noreply.github.com> Date: Sun, 26 Oct 2025 02:19:25 +0200 Subject: [PATCH] modified: app.py --- app.py | 163 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/app.py b/app.py index e85420a..88aa09f 100644 --- a/app.py +++ b/app.py @@ -612,6 +612,169 @@ async def hoi4games(ctx): except Exception as e: await ctx.send(f"❌ Error getting games: {str(e)}") +@bot.hybrid_command(name='hoi4history', description='Show past games with optional filters') +async def hoi4history(ctx, limit: Optional[int] = 10, player: Optional[discord.Member] = None, game_name: Optional[str] = None, game_type: Optional[str] = None): + """Show past games with optional filters""" + if limit > 50: + limit = 50 # Prevent too many results + + try: + async with db_pool.acquire() as conn: + async with conn.cursor(aiomysql.DictCursor) as cursor: + # Build dynamic query based on filters + query = "SELECT * FROM games WHERE status = 'finished'" + params = [] + + if game_name: + query += " AND game_name LIKE %s" + params.append(f"%{game_name}%") + + if game_type and game_type.lower() in ['standard', 'competitive']: + query += " AND game_type = %s" + params.append(game_type.lower()) + + if player: + query += " AND JSON_CONTAINS(players, JSON_OBJECT('discord_id', %s))" + params.append(player.id) + + query += " ORDER BY finished_at DESC LIMIT %s" + params.append(limit) + + await cursor.execute(query, params) + games = await cursor.fetchall() + + if not games: + await ctx.send("📝 No finished games found with the specified filters!") + return + + embed = discord.Embed( + title="📚 HOI4 Game History", + color=discord.Color.blue() + ) + + if player: + embed.description = f"Filtered by player: {player.display_name}" + if game_name: + embed.description = f"Filtered by game name: {game_name}" + if game_type: + embed.description = f"Filtered by type: {game_type.title()}" + + for game in games: + players = json.loads(game['players']) if game['players'] else [] + + # Count teams and players + teams = {} + for p in players: + team = p['team_name'] + if team not in teams: + teams[team] = 0 + teams[team] += 1 + + # Format date + finished_date = game['finished_at'].strftime("%m/%d/%Y %H:%M") if game['finished_at'] else "Unknown" + + # Winner indicator + winner = game['winner_team'] if game['winner_team'] else "Unknown" + + game_info = f"**Winner:** {winner}\n" + game_info += f"**Type:** {game['game_type'].title()}\n" + game_info += f"**Players:** {len(players)} | **Teams:** {len(teams)}\n" + game_info += f"**Finished:** {finished_date}" + + embed.add_field( + name=f"🏆 {game['game_name']}", + value=game_info, + inline=False + ) + + embed.set_footer(text=f"Showing {len(games)} of last {limit} games") + await ctx.send(embed=embed) + + except Exception as e: + await ctx.send(f"❌ Error getting game history: {str(e)}") + +@bot.hybrid_command(name='hoi4leaderboard', description='Show ELO leaderboard') +async def hoi4leaderboard(ctx, game_type: Optional[str] = "standard", limit: Optional[int] = 10): + """Show ELO leaderboard for standard or competitive""" + if game_type.lower() not in ['standard', 'competitive']: + await ctx.send("❌ Game type must be either 'standard' or 'competitive'") + return + + if limit > 25: + limit = 25 # Prevent too many results + + try: + async with db_pool.acquire() as conn: + async with conn.cursor(aiomysql.DictCursor) as cursor: + # Get top players by ELO + elo_field = f"{game_type.lower()}_elo" + await cursor.execute( + f"SELECT discord_id, username, {elo_field}, created_at FROM players ORDER BY {elo_field} DESC LIMIT %s", + (limit,) + ) + players = await cursor.fetchall() + + # Also get some statistics + await cursor.execute( + f"SELECT COUNT(*) as total_players, AVG({elo_field}) as avg_elo, MAX({elo_field}) as max_elo, MIN({elo_field}) as min_elo FROM players" + ) + stats = await cursor.fetchone() + + if not players: + await ctx.send("📝 No players found in the database!") + return + + # Create leaderboard embed + embed = discord.Embed( + title=f"🏆 HOI4 {game_type.title()} Leaderboard", + color=discord.Color.gold() + ) + + # Add statistics + embed.description = f"**Total Players:** {stats['total_players']} | **Average ELO:** {stats['avg_elo']:.0f}" + + leaderboard_text = "" + medals = ["🥇", "🥈", "🥉"] + + for i, player in enumerate(players, 1): + # Get medal or rank number + if i <= 3: + rank_indicator = medals[i-1] + else: + rank_indicator = f"**{i}.**" + + elo_value = player[elo_field] + username = player['username'] + + # Get additional player stats + async with db_pool.acquire() as conn: + async with conn.cursor(aiomysql.DictCursor) as cursor: + # Count games played + await cursor.execute( + "SELECT COUNT(*) as games_played, SUM(won) as games_won FROM game_results WHERE discord_id = %s", + (player['discord_id'],) + ) + player_stats = await cursor.fetchone() + + games_played = player_stats['games_played'] or 0 + games_won = player_stats['games_won'] or 0 + win_rate = (games_won / games_played * 100) if games_played > 0 else 0 + + leaderboard_text += f"{rank_indicator} **{username}** - {elo_value} ELO\n" + leaderboard_text += f" 📊 {games_played} games | {win_rate:.1f}% win rate\n\n" + + embed.add_field( + name="Rankings", + value=leaderboard_text, + inline=False + ) + + embed.set_footer(text=f"ELO Range: {stats['min_elo']:.0f} - {stats['max_elo']:.0f}") + await ctx.send(embed=embed) + + except Exception as e: + await ctx.send(f"❌ Error getting leaderboard: {str(e)}") + @bot.event async def on_command_error(ctx, error): """Handles command errors"""