Version control Claude Code configuration including: - Global instructions (CLAUDE.md) - User settings (settings.json) - Custom agents (architect, designer, engineer, etc.) - Custom skills (create-skill templates and workflows) Excludes session data, secrets, cache, and temporary files per .gitignore. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
237 lines
7.7 KiB
Python
Executable File
237 lines
7.7 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Paper Dynasty Gauntlet Team Cleanup
|
|
|
|
Uses the shared Paper Dynasty API client to clean up gauntlet teams.
|
|
|
|
Usage:
|
|
# List active gauntlet runs in event 8
|
|
python gauntlet_cleanup.py list --event-id 8 --active-only
|
|
|
|
# Wipe a gauntlet team (cards + packs + end run)
|
|
python gauntlet_cleanup.py wipe --team-abbrev Gauntlet-SKB --event-id 8
|
|
"""
|
|
|
|
import argparse
|
|
import os
|
|
import sys
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
# Import shared API client from parent directory
|
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
|
from api_client import PaperDynastyAPI
|
|
|
|
|
|
def list_gauntlet_runs(api: PaperDynastyAPI, event_id: Optional[int] = None, active_only: bool = False):
|
|
"""List gauntlet teams and runs"""
|
|
print("\n🏆 GAUNTLET RUNS")
|
|
print("="*80)
|
|
|
|
try:
|
|
runs = api.list_gauntlet_runs(event_id=event_id, active_only=active_only)
|
|
|
|
if not runs:
|
|
filter_desc = f" in event {event_id}" if event_id else ""
|
|
status_desc = " active" if active_only else ""
|
|
print(f"No{status_desc} gauntlet runs found{filter_desc}")
|
|
else:
|
|
for run in runs:
|
|
team = run['team']
|
|
status = "ACTIVE" if run['ended'] == 0 else "ENDED"
|
|
created = datetime.fromtimestamp(run['created']/1000)
|
|
|
|
print(f"\n[{status}] Team: {team['abbrev']} - {team['lname']}")
|
|
print(f" Run ID: {run['id']}")
|
|
print(f" Team ID: {team['id']}")
|
|
print(f" Event: {run['gauntlet_id']}")
|
|
print(f" Record: {run['wins']}-{run['losses']}")
|
|
print(f" Created: {created}")
|
|
|
|
if run['ended'] != 0:
|
|
ended = datetime.fromtimestamp(run['ended']/1000)
|
|
print(f" Ended: {ended}")
|
|
|
|
except Exception as e:
|
|
print(f"❌ Error: {e}")
|
|
sys.exit(1)
|
|
|
|
print("="*80)
|
|
|
|
|
|
def wipe_gauntlet_team(
|
|
api: PaperDynastyAPI,
|
|
team_abbrev: Optional[str] = None,
|
|
team_id: Optional[int] = None,
|
|
event_id: Optional[int] = None,
|
|
skip_confirmation: bool = False
|
|
):
|
|
"""
|
|
Wipe gauntlet team data: cards, packs, and optionally end run
|
|
|
|
Args:
|
|
api: PaperDynastyAPI instance
|
|
team_abbrev: Team abbreviation (e.g., 'Gauntlet-SKB')
|
|
team_id: Team ID (use this OR team_abbrev)
|
|
event_id: If provided, end the active run in this event
|
|
skip_confirmation: Skip user confirmation prompt
|
|
"""
|
|
# Find the team
|
|
try:
|
|
if team_id:
|
|
team = api.get_team(team_id=team_id)
|
|
elif team_abbrev:
|
|
team = api.get_team(abbrev=team_abbrev)
|
|
else:
|
|
print("❌ Must provide either --team-abbrev or --team-id")
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"❌ Error finding team: {e}")
|
|
sys.exit(1)
|
|
|
|
team_id = team['id']
|
|
team_abbrev = team['abbrev']
|
|
|
|
print(f"\n✓ Found team: {team['lname']} (ID: {team_id}, Abbrev: {team_abbrev})")
|
|
|
|
# Show what will be done
|
|
print("\n⚠️ CLEANUP OPERATIONS:")
|
|
print(f" - Wipe all cards for team {team_abbrev}")
|
|
print(f" - Delete all packs for team {team_abbrev}")
|
|
if event_id:
|
|
print(f" - End active gauntlet run in event {event_id}")
|
|
|
|
# Confirmation
|
|
if not skip_confirmation:
|
|
response = input("\nType 'yes' to continue: ")
|
|
if response.lower() != 'yes':
|
|
print("Aborted.")
|
|
sys.exit(0)
|
|
|
|
stats = {
|
|
'cards_wiped': False,
|
|
'packs_deleted': 0,
|
|
'runs_ended': 0
|
|
}
|
|
|
|
# Step 1: Wipe cards
|
|
print("\n📦 Wiping cards...")
|
|
try:
|
|
result = api.wipe_team_cards(team_id)
|
|
print(f" ✓ Cards wiped: {result}")
|
|
stats['cards_wiped'] = True
|
|
except Exception as e:
|
|
print(f" ❌ Failed to wipe cards: {e}")
|
|
|
|
# Step 2: Delete packs
|
|
print("\n🎁 Deleting packs...")
|
|
try:
|
|
packs = api.list_packs(team_id=team_id)
|
|
print(f" Found {len(packs)} packs")
|
|
|
|
for pack in packs:
|
|
api.delete_pack(pack['id'])
|
|
stats['packs_deleted'] += 1
|
|
|
|
print(f" ✓ Deleted {stats['packs_deleted']} packs")
|
|
except Exception as e:
|
|
print(f" ❌ Failed to delete packs: {e}")
|
|
|
|
# Step 3: End gauntlet run (if event_id provided)
|
|
if event_id:
|
|
print(f"\n🏃 Ending gauntlet run in event {event_id}...")
|
|
try:
|
|
runs = api.list_gauntlet_runs(team_id=team_id, event_id=event_id, active_only=True)
|
|
|
|
if not runs:
|
|
print(f" ⚠️ No active run found for team {team_abbrev} in event {event_id}")
|
|
else:
|
|
for run in runs:
|
|
api.end_gauntlet_run(run['id'])
|
|
stats['runs_ended'] += 1
|
|
print(f" ✓ Ended run ID {run['id']} (Record: {run['wins']}-{run['losses']})")
|
|
except Exception as e:
|
|
print(f" ❌ Failed to end run: {e}")
|
|
|
|
# Summary
|
|
print("\n" + "="*60)
|
|
print("📊 CLEANUP SUMMARY:")
|
|
print(f" Cards wiped: {'✓' if stats['cards_wiped'] else '❌'}")
|
|
print(f" Packs deleted: {stats['packs_deleted']}")
|
|
print(f" Runs ended: {stats['runs_ended']}")
|
|
print("="*60)
|
|
|
|
return stats
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(
|
|
description='Paper Dynasty Gauntlet Team Cleanup',
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
Environment Variables:
|
|
API_TOKEN Bearer token for API authentication (required)
|
|
DATABASE 'prod' or 'dev' (default: dev)
|
|
|
|
Examples:
|
|
# Set up environment
|
|
export API_TOKEN='your-token-here'
|
|
export DATABASE='prod' # or 'dev'
|
|
|
|
# List all active runs in event 8
|
|
python gauntlet_cleanup.py list --event-id 8 --active-only
|
|
|
|
# Wipe team by abbreviation
|
|
python gauntlet_cleanup.py wipe --team-abbrev Gauntlet-SKB --event-id 8
|
|
|
|
# Wipe team by ID
|
|
python gauntlet_cleanup.py wipe --team-id 464 --event-id 8
|
|
|
|
# Skip confirmation (for automation)
|
|
python gauntlet_cleanup.py wipe --team-abbrev Gauntlet-SKB --event-id 8 --yes
|
|
"""
|
|
)
|
|
|
|
parser.add_argument('command', choices=['list', 'wipe'], help='Command to execute')
|
|
parser.add_argument('--team-abbrev', type=str, help='Team abbreviation (e.g., Gauntlet-SKB)')
|
|
parser.add_argument('--team-id', type=int, help='Team ID')
|
|
parser.add_argument('--event-id', type=int, help='Gauntlet event ID')
|
|
parser.add_argument('--active-only', action='store_true', help='Only show active runs (for list command)')
|
|
parser.add_argument('--yes', '-y', action='store_true', help='Skip confirmation prompt')
|
|
parser.add_argument('--env', choices=['prod', 'dev'], help='Override DATABASE environment variable')
|
|
parser.add_argument('--verbose', '-v', action='store_true', help='Verbose API output')
|
|
|
|
args = parser.parse_args()
|
|
|
|
# Determine environment
|
|
env = args.env or os.getenv('DATABASE', 'dev')
|
|
|
|
# Initialize API client
|
|
try:
|
|
api = PaperDynastyAPI(environment=env, verbose=args.verbose)
|
|
print(f"🌐 Using {env.upper()} database: {api.base_url}")
|
|
except ValueError as e:
|
|
print(f"❌ {e}")
|
|
sys.exit(1)
|
|
|
|
# Execute command
|
|
if args.command == 'list':
|
|
list_gauntlet_runs(api, event_id=args.event_id, active_only=args.active_only)
|
|
elif args.command == 'wipe':
|
|
if not args.team_abbrev and not args.team_id:
|
|
print("❌ Error: wipe command requires --team-abbrev or --team-id")
|
|
parser.print_help()
|
|
sys.exit(1)
|
|
|
|
wipe_gauntlet_team(
|
|
api,
|
|
team_abbrev=args.team_abbrev,
|
|
team_id=args.team_id,
|
|
event_id=args.event_id,
|
|
skip_confirmation=args.yes
|
|
)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|