CLAUDE: Add draft system view components

Add comprehensive embed and UI components for draft system:

- On the clock embed: Shows current pick with team info, deadline, recent/upcoming picks
- Draft status embed: Current state, timer status, lock status
- Player draft card: Player info when drafted
- Draft list embed: Team's auto-draft queue display
- Draft board embed: Round-by-round pick display
- Admin info embed: Detailed configuration for admins
- Error/success embeds: Pick validation feedback

All components follow EmbedTemplate patterns with consistent
styling and proper color usage. Ready for command integration.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Cal Corum 2025-10-24 14:56:11 -05:00
parent 1adf9f6caa
commit 39934fb522

460
views/draft_views.py Normal file
View File

@ -0,0 +1,460 @@
"""
Draft Views for Discord Bot v2.0
Provides embeds and UI components for draft system.
"""
from typing import Optional, List
from datetime import datetime
import discord
from models.draft_pick import DraftPick
from models.draft_data import DraftData
from models.team import Team
from models.player import Player
from models.draft_list import DraftList
from views.embeds import EmbedTemplate, EmbedColors
from utils.draft_helpers import format_pick_display, get_round_name
async def create_on_the_clock_embed(
current_pick: DraftPick,
draft_data: DraftData,
recent_picks: List[DraftPick],
upcoming_picks: List[DraftPick],
team_roster_swar: Optional[float] = None
) -> discord.Embed:
"""
Create "on the clock" embed showing current pick info.
Args:
current_pick: Current DraftPick being made
draft_data: Current draft configuration
recent_picks: List of recent draft picks
upcoming_picks: List of upcoming draft picks
team_roster_swar: Current team sWAR (optional)
Returns:
Discord embed with pick information
"""
if not current_pick.owner:
raise ValueError("Pick must have owner")
# Create base embed with team colors
embed = EmbedTemplate.create_base_embed(
title=f"{current_pick.owner.lname} On The Clock",
description=format_pick_display(current_pick.overall),
color=EmbedColors.PRIMARY
)
# Add team info
if current_pick.owner.sname:
embed.add_field(
name="Team",
value=f"{current_pick.owner.abbrev} {current_pick.owner.sname}",
inline=True
)
# Add timer info
if draft_data.pick_deadline:
deadline_timestamp = int(draft_data.pick_deadline.timestamp())
embed.add_field(
name="Deadline",
value=f"<t:{deadline_timestamp}:R>",
inline=True
)
# Add team sWAR if provided
if team_roster_swar is not None:
embed.add_field(
name="Current sWAR",
value=f"{team_roster_swar:.2f} / 32.00",
inline=True
)
# Add recent picks
if recent_picks:
recent_str = ""
for pick in recent_picks[:5]:
if pick.player:
recent_str += f"**#{pick.overall}** - {pick.player.name}\n"
if recent_str:
embed.add_field(
name="📋 Last 5 Picks",
value=recent_str or "None",
inline=False
)
# Add upcoming picks
if upcoming_picks:
upcoming_str = ""
for pick in upcoming_picks[:5]:
upcoming_str += f"**#{pick.overall}** - {pick.owner.sname if pick.owner else 'Unknown'}\n"
if upcoming_str:
embed.add_field(
name="🔜 Next 5 Picks",
value=upcoming_str,
inline=False
)
# Add footer
if current_pick.is_traded:
embed.set_footer(text="📝 This pick was traded")
return embed
async def create_draft_status_embed(
draft_data: DraftData,
current_pick: DraftPick,
lock_status: str = "🔓 No pick in progress"
) -> discord.Embed:
"""
Create draft status embed showing current state.
Args:
draft_data: Current draft configuration
current_pick: Current DraftPick
lock_status: Lock status message
Returns:
Discord embed with draft status
"""
embed = EmbedTemplate.info(
title="Draft Status",
description=f"Currently on {format_pick_display(draft_data.currentpick)}"
)
# On the clock
if current_pick.owner:
embed.add_field(
name="On the Clock",
value=f"{current_pick.owner.abbrev} {current_pick.owner.sname}",
inline=True
)
# Timer status
timer_status = "✅ Active" if draft_data.timer else "⏹️ Inactive"
embed.add_field(
name="Timer",
value=f"{timer_status} ({draft_data.pick_minutes} min)",
inline=True
)
# Deadline
if draft_data.pick_deadline:
deadline_timestamp = int(draft_data.pick_deadline.timestamp())
embed.add_field(
name="Deadline",
value=f"<t:{deadline_timestamp}:R>",
inline=True
)
else:
embed.add_field(
name="Deadline",
value="None",
inline=True
)
# Lock status
embed.add_field(
name="Lock Status",
value=lock_status,
inline=False
)
return embed
async def create_player_draft_card(
player: Player,
draft_pick: DraftPick
) -> discord.Embed:
"""
Create player draft card embed.
Args:
player: Player being drafted
draft_pick: DraftPick information
Returns:
Discord embed with player info
"""
if not draft_pick.owner:
raise ValueError("Pick must have owner")
embed = EmbedTemplate.success(
title=f"{player.name} Drafted!",
description=format_pick_display(draft_pick.overall)
)
# Team info
embed.add_field(
name="Selected By",
value=f"{draft_pick.owner.abbrev} {draft_pick.owner.sname}",
inline=True
)
# Player info
if hasattr(player, 'pos_1') and player.pos_1:
embed.add_field(
name="Position",
value=player.pos_1,
inline=True
)
if hasattr(player, 'wara') and player.wara is not None:
embed.add_field(
name="sWAR",
value=f"{player.wara:.2f}",
inline=True
)
# Add player image if available
if hasattr(player, 'image') and player.image:
embed.set_thumbnail(url=player.image)
return embed
async def create_draft_list_embed(
team: Team,
draft_list: List[DraftList]
) -> discord.Embed:
"""
Create draft list embed showing team's auto-draft queue.
Args:
team: Team owning the list
draft_list: List of DraftList entries
Returns:
Discord embed with draft list
"""
embed = EmbedTemplate.info(
title=f"{team.sname} Draft List",
description=f"Auto-draft queue for {team.abbrev}"
)
if not draft_list:
embed.add_field(
name="Queue Empty",
value="No players in auto-draft queue",
inline=False
)
else:
# Group players by rank
list_str = ""
for entry in draft_list[:25]: # Limit to 25 for embed size
player_name = entry.player.name if entry.player else f"Player {entry.player_id}"
player_swar = f" ({entry.player.wara:.2f})" if entry.player and hasattr(entry.player, 'wara') else ""
list_str += f"**{entry.rank}.** {player_name}{player_swar}\n"
embed.add_field(
name=f"Queue ({len(draft_list)} players)",
value=list_str,
inline=False
)
embed.set_footer(text="Use /draft-list to manage your auto-draft queue")
return embed
async def create_draft_board_embed(
round_num: int,
picks: List[DraftPick]
) -> discord.Embed:
"""
Create draft board embed showing all picks in a round.
Args:
round_num: Round number
picks: List of DraftPick for this round
Returns:
Discord embed with draft board
"""
embed = EmbedTemplate.create_base_embed(
title=f"📋 {get_round_name(round_num)}",
description=f"Draft board for round {round_num}",
color=EmbedColors.PRIMARY
)
if not picks:
embed.add_field(
name="No Picks",
value="No picks found for this round",
inline=False
)
else:
# Create picks display
picks_str = ""
for pick in picks:
if pick.player:
player_display = pick.player.name
else:
player_display = "TBD"
team_display = pick.owner.abbrev if pick.owner else "???"
picks_str += f"**Pick {pick.overall % 16 or 16}:** {team_display} - {player_display}\n"
embed.add_field(
name="Picks",
value=picks_str,
inline=False
)
embed.set_footer(text="Use /draft-board [round] to view different rounds")
return embed
async def create_pick_illegal_embed(
reason: str,
details: Optional[str] = None
) -> discord.Embed:
"""
Create embed for illegal pick attempt.
Args:
reason: Main reason pick is illegal
details: Additional details (optional)
Returns:
Discord error embed
"""
embed = EmbedTemplate.error(
title="Invalid Pick",
description=reason
)
if details:
embed.add_field(
name="Details",
value=details,
inline=False
)
return embed
async def create_pick_success_embed(
player: Player,
team: Team,
pick_overall: int,
projected_swar: float
) -> discord.Embed:
"""
Create embed for successful pick.
Args:
player: Player drafted
team: Team that drafted player
pick_overall: Overall pick number
projected_swar: Projected team sWAR after pick
Returns:
Discord success embed
"""
embed = EmbedTemplate.success(
title="Pick Confirmed",
description=f"{team.abbrev} selects **{player.name}**"
)
embed.add_field(
name="Pick",
value=format_pick_display(pick_overall),
inline=True
)
if hasattr(player, 'wara') and player.wara is not None:
embed.add_field(
name="Player sWAR",
value=f"{player.wara:.2f}",
inline=True
)
embed.add_field(
name="Projected Team sWAR",
value=f"{projected_swar:.2f} / 32.00",
inline=True
)
return embed
async def create_admin_draft_info_embed(
draft_data: DraftData,
current_pick: Optional[DraftPick] = None
) -> discord.Embed:
"""
Create detailed admin view of draft status.
Args:
draft_data: Current draft configuration
current_pick: Current DraftPick (optional)
Returns:
Discord embed with admin information
"""
embed = EmbedTemplate.info(
title="⚙️ Draft Administration",
description="Current draft configuration and state"
)
# Current pick
embed.add_field(
name="Current Pick",
value=str(draft_data.currentpick),
inline=True
)
# Timer status
timer_emoji = "" if draft_data.timer else "⏹️"
embed.add_field(
name="Timer Status",
value=f"{timer_emoji} {'Active' if draft_data.timer else 'Inactive'}",
inline=True
)
# Timer duration
embed.add_field(
name="Pick Duration",
value=f"{draft_data.pick_minutes} minutes",
inline=True
)
# Channels
embed.add_field(
name="Ping Channel",
value=f"<#{draft_data.ping_channel_id}>",
inline=True
)
embed.add_field(
name="Result Channel",
value=f"<#{draft_data.result_channel_id}>",
inline=True
)
# Deadline
if draft_data.pick_deadline:
deadline_timestamp = int(draft_data.pick_deadline.timestamp())
embed.add_field(
name="Current Deadline",
value=f"<t:{deadline_timestamp}:F>",
inline=True
)
# Current pick owner
if current_pick and current_pick.owner:
embed.add_field(
name="On The Clock",
value=f"{current_pick.owner.abbrev} {current_pick.owner.sname}",
inline=False
)
embed.set_footer(text="Use /draft-admin to modify draft settings")
return embed