diff --git a/tito/commands/leaderboard.py b/tito/commands/leaderboard.py new file mode 100644 index 00000000..3cd0d8fd --- /dev/null +++ b/tito/commands/leaderboard.py @@ -0,0 +1,834 @@ +""" +TinyTorch Community Leaderboard Command + +Inclusive community showcase where everyone belongs, regardless of performance level. +Celebrates the journey, highlights improvements, and builds community through shared learning. +""" + +import json +import os +from argparse import ArgumentParser, Namespace +from datetime import datetime +from pathlib import Path +from typing import Dict, List, Optional, Any +import tempfile +import uuid + +from rich.panel import Panel +from rich.table import Table +from rich.progress import track +from rich.prompt import Prompt, Confirm +from rich.console import Group +from rich.align import Align + +from .base import BaseCommand +from ..core.exceptions import TinyTorchCLIError + + +class LeaderboardCommand(BaseCommand): + """Community leaderboard - Everyone welcome, celebrate the journey!""" + + @property + def name(self) -> str: + return "leaderboard" + + @property + def description(self) -> str: + return "Community showcase - Join, share progress, celebrate achievements together" + + def add_arguments(self, parser: ArgumentParser) -> None: + """Add leaderboard subcommands.""" + subparsers = parser.add_subparsers( + dest='leaderboard_command', + help='Leaderboard operations', + metavar='COMMAND' + ) + + # Register command + register_parser = subparsers.add_parser( + 'register', + help='Join the TinyTorch community (inclusive, welcoming)' + ) + register_parser.add_argument( + '--username', + help='Your display name (defaults to system username)' + ) + register_parser.add_argument( + '--institution', + help='Institution/organization (optional)' + ) + register_parser.add_argument( + '--country', + help='Country (optional, for global community view)' + ) + register_parser.add_argument( + '--update', + action='store_true', + help='Update existing registration' + ) + + # Submit command + submit_parser = subparsers.add_parser( + 'submit', + help='Submit your results (baseline or improvements welcome!)' + ) + submit_parser.add_argument( + '--task', + default='cifar10', + choices=['cifar10', 'mnist', 'tinygpt'], + help='Task to submit results for (default: cifar10)' + ) + submit_parser.add_argument( + '--accuracy', + type=float, + help='Accuracy achieved (any level welcome!)' + ) + submit_parser.add_argument( + '--model', + help='Model description (e.g., "CNN-3-layer", "Custom-Architecture")' + ) + submit_parser.add_argument( + '--notes', + help='Optional notes about your approach, learnings, challenges' + ) + submit_parser.add_argument( + '--checkpoint', + help='Which TinyTorch checkpoint you completed (e.g., "05", "10", "15")' + ) + + # View command + view_parser = subparsers.add_parser( + 'view', + help='See the community progress (everyone included!)' + ) + view_parser.add_argument( + '--task', + default='cifar10', + choices=['cifar10', 'mnist', 'tinygpt'], + help='Task leaderboard to view (default: cifar10)' + ) + view_parser.add_argument( + '--distribution', + action='store_true', + help='Show performance distribution graph' + ) + view_parser.add_argument( + '--recent', + action='store_true', + help='Focus on recent achievements and improvements' + ) + view_parser.add_argument( + '--all', + action='store_true', + help='Show complete community (not just top performers)' + ) + + # Profile command + profile_parser = subparsers.add_parser( + 'profile', + help='Your personal achievement journey' + ) + profile_parser.add_argument( + '--detailed', + action='store_true', + help='Show detailed progress across all tasks' + ) + + # Status command (quick personal stats) + status_parser = subparsers.add_parser( + 'status', + help='Quick personal stats and next steps' + ) + + def run(self, args: Namespace) -> int: + """Execute leaderboard command.""" + command = getattr(args, 'leaderboard_command', None) + + if not command: + self._show_leaderboard_overview() + return 0 + + if command == 'register': + return self._register_user(args) + elif command == 'submit': + return self._submit_results(args) + elif command == 'view': + return self._view_leaderboard(args) + elif command == 'profile': + return self._show_profile(args) + elif command == 'status': + return self._show_status(args) + else: + raise TinyTorchCLIError(f"Unknown leaderboard command: {command}") + + def _show_leaderboard_overview(self) -> None: + """Show leaderboard overview and welcome message.""" + self.console.print(Panel( + Group( + Align.center("[bold bright_green]🌟 TinyTorch Community Leaderboard 🌟[/bold bright_green]"), + "", + "[bold]Everyone Welcome![/bold] This is your inclusive community showcase where:", + "• [green]Every achievement matters[/green] - 10% accuracy gets the same celebration as 90%", + "• [blue]Progress is the goal[/blue] - We celebrate improvements and learning journeys", + "• [yellow]Community first[/yellow] - Help each other, share insights, grow together", + "• [magenta]No minimum required[/magenta] - Join with any level of progress", + "", + "[bold]Available Commands:[/bold]", + " [green]register[/green] - Join our welcoming community (free, inclusive)", + " [green]submit[/green] - Share your progress (any level welcome!)", + " [green]view[/green] - See everyone's journey together", + " [green]profile[/green] - Your personal achievement story", + " [green]status[/green] - Quick stats and encouragement", + "", + "[dim]💡 Tip: Start with 'tito leaderboard register' to join the community![/dim]", + ), + title="Community Leaderboard", + border_style="bright_green", + padding=(1, 2) + )) + + def _register_user(self, args: Namespace) -> int: + """Register user for the leaderboard with welcoming experience.""" + # Get user data directory + user_data_dir = self._get_user_data_dir() + profile_file = user_data_dir / "profile.json" + + # Check existing registration + existing_profile = None + if profile_file.exists() and not args.update: + with open(profile_file, 'r') as f: + existing_profile = json.load(f) + + self.console.print(Panel( + f"[green]✅ You're already registered![/green]\n\n" + f"[bold]Username:[/bold] {existing_profile.get('username', 'Unknown')}\n" + f"[bold]Institution:[/bold] {existing_profile.get('institution', 'Not specified')}\n" + f"[bold]Country:[/bold] {existing_profile.get('country', 'Not specified')}\n" + f"[bold]Joined:[/bold] {existing_profile.get('joined_date', 'Unknown')}\n\n" + f"[dim]Use --update to modify your registration[/dim]", + title="🎉 Welcome Back!", + border_style="green" + )) + return 0 + + # Welcome new user + if not existing_profile: + self.console.print(Panel( + Group( + Align.center("[bold bright_green]🎉 Welcome to the TinyTorch Community! 🎉[/bold bright_green]"), + "", + "You're joining a welcoming community of ML systems learners where:", + "• [green]Every skill level is celebrated[/green]", + "• [blue]Progress matters more than perfection[/blue]", + "• [yellow]Learning together makes us all stronger[/yellow]", + "", + "[bold]Let's get you registered![/bold]", + ), + border_style="bright_green", + padding=(1, 2) + )) + + # Gather registration information + username = args.username + if not username: + default_username = os.getenv('USER', 'tinytorch_learner') + username = Prompt.ask( + "[bold]Choose your display name[/bold]", + default=default_username + ) + + institution = args.institution + if not institution: + institution = Prompt.ask( + "[bold]Institution/Organization[/bold] (optional, or press Enter to skip)", + default="" + ) + + country = args.country + if not country: + country = Prompt.ask( + "[bold]Country[/bold] (optional, helps show global community)", + default="" + ) + + # Create profile + profile = { + "user_id": str(uuid.uuid4()), + "username": username, + "institution": institution or None, + "country": country or None, + "joined_date": datetime.now().isoformat(), + "updated_date": datetime.now().isoformat(), + "submissions": [], + "achievements": [], + "checkpoints_completed": [] + } + + # Save profile + user_data_dir.mkdir(parents=True, exist_ok=True) + with open(profile_file, 'w') as f: + json.dump(profile, f, indent=2) + + # Celebration message + self.console.print(Panel( + Group( + Align.center("[bold bright_green]🌟 Registration Complete! 🌟[/bold bright_green]"), + "", + f"[bold]Welcome, {username}![/bold]", + "", + "You're now part of our inclusive community! Here's what you can do:", + "• Submit any results with [green]tito leaderboard submit[/green]", + "• View the community with [blue]tito leaderboard view[/blue]", + "• Track your progress with [yellow]tito leaderboard profile[/yellow]", + "", + "[bold bright_blue]🚀 Next Steps:[/bold bright_blue]", + "1. Train any model on CIFAR-10 (even 10% accuracy counts!)", + "2. Submit with: [dim]tito leaderboard submit --accuracy 15.2[/dim]", + "3. Celebrate your achievement with the community!", + "", + "[dim]💝 Remember: Every step forward is worth celebrating![/dim]", + ), + title="🎊 You're In!", + border_style="bright_green", + padding=(1, 2) + )) + + return 0 + + def _submit_results(self, args: Namespace) -> int: + """Submit results with encouraging experience.""" + # Check registration + profile = self._load_user_profile() + if not profile: + self.console.print(Panel( + "[yellow]Please register first to join our community![/yellow]\n\n" + "Run: [bold]tito leaderboard register[/bold]", + title="📝 Registration Required", + border_style="yellow" + )) + return 1 + + # Get submission details + task = args.task + accuracy = args.accuracy + model = args.model + notes = args.notes + checkpoint = args.checkpoint + + # Interactive prompts if not provided + if accuracy is None: + accuracy = float(Prompt.ask( + f"[bold]Accuracy achieved on {task.upper()}[/bold] (any level welcome!)", + default="0.0" + )) + + if not model: + model = Prompt.ask( + "[bold]Model description[/bold] (e.g., 'CNN-3-layer', 'My-Custom-Net')", + default="Custom Model" + ) + + if not checkpoint: + checkpoint = Prompt.ask( + "[bold]TinyTorch checkpoint completed[/bold] (e.g., '05', '10', '15')", + default="" + ) + + if not notes: + notes = Prompt.ask( + "[bold]Notes about your approach/learnings[/bold] (optional)", + default="" + ) + + # Create submission + submission = { + "submission_id": str(uuid.uuid4()), + "task": task, + "accuracy": accuracy, + "model": model, + "notes": notes or None, + "checkpoint": checkpoint or None, + "submitted_date": datetime.now().isoformat(), + "version": "1.0" + } + + # Add to profile + profile["submissions"].append(submission) + profile["updated_date"] = datetime.now().isoformat() + + # Update achievements based on accuracy + achievement = self._calculate_achievement_level(accuracy, task) + if achievement: + profile["achievements"].append({ + "type": "accuracy_milestone", + "level": achievement, + "task": task, + "accuracy": accuracy, + "earned_date": datetime.now().isoformat() + }) + + # Save updated profile + self._save_user_profile(profile) + + # Celebration based on performance level + celebration_message = self._get_celebration_message(accuracy, task, model) + + self.console.print(Panel( + Group( + Align.center(celebration_message["title"]), + "", + celebration_message["message"], + "", + f"[bold]Your Submission:[/bold]", + f"• Task: {task.upper()}", + f"• Accuracy: {accuracy:.1f}%", + f"• Model: {model}", + f"• Checkpoint: {checkpoint or 'Not specified'}", + "", + celebration_message["encouragement"], + "", + "[bold bright_blue]🔍 Next:[/bold bright_blue]", + "• View community: [dim]tito leaderboard view[/dim]", + "• See your profile: [dim]tito leaderboard profile[/dim]", + "• Try improving: [dim]tito leaderboard submit[/dim]", + ), + title=celebration_message["panel_title"], + border_style=celebration_message["border_style"], + padding=(1, 2) + )) + + return 0 + + def _view_leaderboard(self, args: Namespace) -> int: + """View community leaderboard with inclusive display.""" + task = args.task + + # Load community data (mock for now - would connect to real backend) + community_data = self._load_community_data(task) + + if args.distribution: + self._show_performance_distribution(community_data, task) + elif args.recent: + self._show_recent_achievements(community_data, task) + else: + self._show_community_leaderboard(community_data, task, show_all=args.all) + + return 0 + + def _show_profile(self, args: Namespace) -> int: + """Show user's personal achievement journey.""" + profile = self._load_user_profile() + if not profile: + self.console.print(Panel( + "[yellow]Please register first to see your profile![/yellow]\n\n" + "Run: [bold]tito leaderboard register[/bold]", + title="📝 Registration Required", + border_style="yellow" + )) + return 1 + + # Create profile display + self._display_user_profile(profile, detailed=args.detailed) + return 0 + + def _show_status(self, args: Namespace) -> int: + """Show quick personal stats and encouragement.""" + profile = self._load_user_profile() + if not profile: + self.console.print(Panel( + "[yellow]Please register first![/yellow]\n\n" + "Run: [bold]tito leaderboard register[/bold]", + title="📝 Registration Required", + border_style="yellow" + )) + return 1 + + # Calculate quick stats + submissions = profile.get("submissions", []) + best_cifar10 = max([s["accuracy"] for s in submissions if s["task"] == "cifar10"], default=0) + total_submissions = len(submissions) + + # Encouraging status message + if total_submissions == 0: + status_message = "[bold bright_blue]🚀 Ready for your first submission![/bold bright_blue]" + next_step = "Train any model and submit with: [green]tito leaderboard submit[/green]" + else: + status_message = f"[bold bright_green]🌟 {total_submissions} submission{'s' if total_submissions != 1 else ''} made![/bold bright_green]" + if best_cifar10 > 0: + next_step = f"Best CIFAR-10: {best_cifar10:.1f}% - Keep improving! 🚀" + else: + next_step = "Try CIFAR-10 next: [green]tito leaderboard submit --task cifar10[/green]" + + self.console.print(Panel( + Group( + Align.center(status_message), + "", + f"[bold]{profile['username']}[/bold]'s Quick Status:", + f"• Total submissions: {total_submissions}", + f"• Best CIFAR-10 accuracy: {best_cifar10:.1f}%", + f"• Community member since: {profile.get('joined_date', 'Unknown')[:10]}", + "", + "[bold]Next Step:[/bold]", + next_step, + ), + title="⚡ Quick Status", + border_style="bright_blue", + padding=(1, 2) + )) + + return 0 + + def _get_user_data_dir(self) -> Path: + """Get user data directory for leaderboard.""" + data_dir = Path.home() / ".tinytorch" / "leaderboard" + data_dir.mkdir(parents=True, exist_ok=True) + return data_dir + + def _load_user_profile(self) -> Optional[Dict[str, Any]]: + """Load user profile if it exists.""" + profile_file = self._get_user_data_dir() / "profile.json" + if profile_file.exists(): + with open(profile_file, 'r') as f: + return json.load(f) + return None + + def _save_user_profile(self, profile: Dict[str, Any]) -> None: + """Save user profile.""" + profile_file = self._get_user_data_dir() / "profile.json" + with open(profile_file, 'w') as f: + json.dump(profile, f, indent=2) + + def _calculate_achievement_level(self, accuracy: float, task: str) -> Optional[str]: + """Calculate achievement level based on accuracy.""" + if task == "cifar10": + if accuracy >= 75: + return "expert" + elif accuracy >= 50: + return "advanced" + elif accuracy >= 25: + return "intermediate" + elif accuracy >= 10: + return "beginner" + return None + + def _get_celebration_message(self, accuracy: float, task: str, model: str) -> Dict[str, str]: + """Get appropriate celebration message based on performance.""" + if accuracy >= 75: + return { + "title": "[bold bright_green]🏆 OUTSTANDING ACHIEVEMENT! 🏆[/bold bright_green]", + "message": f"[green]WOW! {accuracy:.1f}% on {task.upper()} is exceptional![/green]", + "encouragement": "[bold]You've mastered this challenge! Consider helping others in the community. 🌟[/bold]", + "panel_title": "🚀 Elite Performance", + "border_style": "bright_green" + } + elif accuracy >= 50: + return { + "title": "[bold bright_blue]🎯 STRONG PERFORMANCE! 🎯[/bold bright_blue]", + "message": f"[blue]Great work! {accuracy:.1f}% on {task.upper()} shows solid progress![/blue]", + "encouragement": "[bold]You're doing really well! Can you push toward 75%? 💪[/bold]", + "panel_title": "📈 Solid Progress", + "border_style": "bright_blue" + } + elif accuracy >= 25: + return { + "title": "[bold bright_yellow]🌱 GOOD PROGRESS! 🌱[/bold bright_yellow]", + "message": f"[yellow]Nice! {accuracy:.1f}% on {task.upper()} shows you're learning![/yellow]", + "encouragement": "[bold]You're on the right track! Keep experimenting and improving! 🚀[/bold]", + "panel_title": "🌟 Learning Journey", + "border_style": "bright_yellow" + } + elif accuracy >= 10: + return { + "title": "[bold bright_magenta]🎉 FIRST STEPS! 🎉[/bold bright_magenta]", + "message": f"[magenta]Fantastic! {accuracy:.1f}% on {task.upper()} - you've started![/magenta]", + "encouragement": "[bold]Every expert was once a beginner! Keep going! 🌈[/bold]", + "panel_title": "🌸 Getting Started", + "border_style": "bright_magenta" + } + else: + return { + "title": "[bold bright_cyan]🌟 BRAVE ATTEMPT! 🌟[/bold bright_cyan]", + "message": f"[cyan]Thank you for sharing {accuracy:.1f}% on {task.upper()}![/cyan]", + "encouragement": "[bold]Every submission helps you learn! Try different approaches! 💡[/bold]", + "panel_title": "💝 Courage Counts", + "border_style": "bright_cyan" + } + + def _load_community_data(self, task: str) -> List[Dict[str, Any]]: + """Load community data (mock implementation).""" + # Mock community data for demonstration + return [ + {"username": "alex_chen", "accuracy": 78.2, "model": "ResNet-Custom", "country": "USA", "recent": True}, + {"username": "neural_ninja", "accuracy": 72.1, "model": "CNN-5-layer", "country": "Canada", "recent": False}, + {"username": "ml_student", "accuracy": 45.3, "model": "Basic-CNN", "country": "UK", "recent": True}, + {"username": "curious_coder", "accuracy": 28.7, "model": "First-Try", "country": "Germany", "recent": True}, + {"username": "tinytorch_fan", "accuracy": 15.2, "model": "Learning-Net", "country": "Australia", "recent": False}, + {"username": "beginner_ml", "accuracy": 8.9, "model": "Simple-Model", "country": "India", "recent": True}, + ] + + def _show_community_leaderboard(self, data: List[Dict[str, Any]], task: str, show_all: bool = False) -> None: + """Show inclusive community leaderboard.""" + # Sort by accuracy but show everyone + sorted_data = sorted(data, key=lambda x: x["accuracy"], reverse=True) + + if not show_all: + # Show top performers + some middle + recent submissions + display_data = sorted_data[:3] + sorted_data[-3:] if len(sorted_data) > 6 else sorted_data + else: + display_data = sorted_data + + # Create inclusive leaderboard table + table = Table(title=f"🌟 {task.upper()} Community Leaderboard 🌟") + table.add_column("Rank", style="dim", width=6) + table.add_column("Username", style="bold") + table.add_column("Accuracy", style="green", justify="right") + table.add_column("Model", style="blue") + table.add_column("Country", style="cyan") + table.add_column("Status", style="yellow") + + for i, entry in enumerate(display_data, 1): + rank = "🥇" if i == 1 else "🥈" if i == 2 else "🥉" if i == 3 else f"#{i}" + status = "🔥 Recent" if entry.get("recent") else "⭐" + + table.add_row( + rank, + entry["username"], + f"{entry['accuracy']:.1f}%", + entry["model"], + entry.get("country", "Global"), + status + ) + + self.console.print(table) + + # Encouraging footer + self.console.print(Panel( + Group( + "[bold bright_green]🎉 Everyone's journey matters![/bold bright_green]", + "", + "• [green]Top performers[/green]: Inspiring the community with excellence", + "• [blue]All achievers[/blue]: Every percentage point represents real learning", + "• [yellow]Recent submissions[/yellow]: Fresh progress and new insights", + "", + "[dim]💡 See your progress: tito leaderboard profile[/dim]", + "[dim]🚀 Submit improvements: tito leaderboard submit[/dim]", + ), + title="Community Insights", + border_style="bright_blue", + padding=(0, 1) + )) + + def _show_performance_distribution(self, data: List[Dict[str, Any]], task: str) -> None: + """Show performance distribution to normalize achievements.""" + accuracies = [entry["accuracy"] for entry in data] + + # Create distribution buckets + buckets = { + "🏆 Expert (75%+)": len([a for a in accuracies if a >= 75]), + "🎯 Advanced (50-75%)": len([a for a in accuracies if 50 <= a < 75]), + "🌱 Intermediate (25-50%)": len([a for a in accuracies if 25 <= a < 50]), + "🌸 Beginner (10-25%)": len([a for a in accuracies if 10 <= a < 25]), + "💝 Getting Started (<10%)": len([a for a in accuracies if a < 10]), + } + + table = Table(title=f"📊 {task.upper()} Performance Distribution") + table.add_column("Achievement Level", style="bold") + table.add_column("Community Members", style="green", justify="right") + table.add_column("Percentage", style="blue", justify="right") + table.add_column("Visual", style="cyan") + + total = len(accuracies) + for level, count in buckets.items(): + percentage = (count / total * 100) if total > 0 else 0 + visual = "█" * min(int(percentage / 5), 20) + + table.add_row( + level, + str(count), + f"{percentage:.1f}%", + visual + ) + + self.console.print(table) + + self.console.print(Panel( + "[bold bright_blue]🌈 Every level has value![/bold bright_blue]\n\n" + "This distribution shows our diverse, learning community where:\n" + "• [green]Every achievement level contributes to collective knowledge[/green]\n" + "• [blue]Different backgrounds bring different insights[/blue]\n" + "• [yellow]Progress at any level deserves celebration[/yellow]\n\n" + "[dim]Your journey is unique and valuable regardless of where you start! 💝[/dim]", + title="🎊 Community Insights", + border_style="bright_green" + )) + + def _show_recent_achievements(self, data: List[Dict[str, Any]], task: str) -> None: + """Show recent achievements to motivate continued participation.""" + recent_data = [entry for entry in data if entry.get("recent", False)] + + if not recent_data: + self.console.print(Panel( + "[yellow]No recent submissions![/yellow]\n\n" + "Be the first to share recent progress:\n" + "[bold]tito leaderboard submit[/bold]", + title="🔥 Recent Activity", + border_style="yellow" + )) + return + + # Sort recent by submission order (newest first) + recent_data = sorted(recent_data, key=lambda x: x["accuracy"], reverse=True) + + table = Table(title=f"🔥 Recent {task.upper()} Achievements") + table.add_column("Achievement", style="bold") + table.add_column("Username", style="green") + table.add_column("Accuracy", style="blue", justify="right") + table.add_column("Model", style="cyan") + table.add_column("Celebration", style="yellow") + + for entry in recent_data[:10]: # Show top 10 recent + # Determine achievement type + accuracy = entry["accuracy"] + if accuracy >= 75: + achievement = "🏆 Expert Level" + celebration = "Outstanding!" + elif accuracy >= 50: + achievement = "🎯 Strong Performance" + celebration = "Excellent work!" + elif accuracy >= 25: + achievement = "🌱 Good Progress" + celebration = "Keep going!" + elif accuracy >= 10: + achievement = "🌸 First Steps" + celebration = "Great start!" + else: + achievement = "💝 Brave Attempt" + celebration = "Learning!" + + table.add_row( + achievement, + entry["username"], + f"{accuracy:.1f}%", + entry["model"], + celebration + ) + + self.console.print(table) + + self.console.print(Panel( + "[bold bright_green]🎉 Celebrating recent community progress![/bold bright_green]\n\n" + "Join the momentum:\n" + "• [green]Share your latest results[/green]\n" + "• [blue]Try a new approach[/blue]\n" + "• [yellow]Learn from others' models[/yellow]\n\n" + "[dim]Every submission adds to our collective learning! 🚀[/dim]", + title="🌟 Community Energy", + border_style="bright_blue" + )) + + def _display_user_profile(self, profile: Dict[str, Any], detailed: bool = False) -> None: + """Display user's personal achievement profile.""" + username = profile.get("username", "Unknown") + submissions = profile.get("submissions", []) + achievements = profile.get("achievements", []) + + # Calculate stats + total_submissions = len(submissions) + best_cifar10 = max([s["accuracy"] for s in submissions if s["task"] == "cifar10"], default=0) + best_mnist = max([s["accuracy"] for s in submissions if s["task"] == "mnist"], default=0) + + # Create achievement summary + if detailed: + self._show_detailed_profile(profile) + else: + self._show_summary_profile(profile) + + def _show_summary_profile(self, profile: Dict[str, Any]) -> None: + """Show summary profile view.""" + username = profile.get("username", "Unknown") + submissions = profile.get("submissions", []) + + # Calculate stats + total_submissions = len(submissions) + best_cifar10 = max([s["accuracy"] for s in submissions if s["task"] == "cifar10"], default=0) + tasks_tried = len(set(s["task"] for s in submissions)) + + # Determine user level + if best_cifar10 >= 75: + level = "🏆 Expert" + level_color = "bright_green" + elif best_cifar10 >= 50: + level = "🎯 Advanced" + level_color = "bright_blue" + elif best_cifar10 >= 25: + level = "🌱 Intermediate" + level_color = "bright_yellow" + elif best_cifar10 >= 10: + level = "🌸 Beginner" + level_color = "bright_magenta" + else: + level = "💝 Getting Started" + level_color = "bright_cyan" + + self.console.print(Panel( + Group( + Align.center(f"[bold {level_color}]{level}[/bold {level_color}]"), + "", + f"[bold]{username}[/bold]'s Achievement Journey", + "", + f"🎯 Total submissions: {total_submissions}", + f"🏆 Best CIFAR-10: {best_cifar10:.1f}%", + f"🌐 Tasks explored: {tasks_tried}", + f"📅 Member since: {profile.get('joined_date', 'Unknown')[:10]}", + "", + "[bold bright_blue]🚀 What's Next?[/bold bright_blue]", + self._get_next_steps_suggestion(best_cifar10, total_submissions), + ), + title=f"🌟 {username}'s Profile", + border_style=level_color, + padding=(1, 2) + )) + + def _show_detailed_profile(self, profile: Dict[str, Any]) -> None: + """Show detailed profile with all submissions.""" + username = profile.get("username", "Unknown") + submissions = profile.get("submissions", []) + + # Summary first + self._show_summary_profile(profile) + + if submissions: + # Submissions table + table = Table(title="📈 Your Submission History") + table.add_column("Date", style="dim") + table.add_column("Task", style="bold") + table.add_column("Accuracy", style="green", justify="right") + table.add_column("Model", style="blue") + table.add_column("Checkpoint", style="yellow") + + for submission in sorted(submissions, key=lambda x: x["submitted_date"], reverse=True): + date = submission["submitted_date"][:10] + table.add_row( + date, + submission["task"].upper(), + f"{submission['accuracy']:.1f}%", + submission["model"], + submission.get("checkpoint", "—") + ) + + self.console.print(table) + + def _get_next_steps_suggestion(self, best_accuracy: float, total_submissions: int) -> str: + """Get personalized next steps suggestion.""" + if total_submissions == 0: + return "[green]Make your first submission![/green] Any accuracy level welcome." + elif best_accuracy >= 75: + return "[green]Help others in the community![/green] Share your insights and approaches." + elif best_accuracy >= 50: + return "[blue]Push toward expert level![/blue] Can you reach 75%?" + elif best_accuracy >= 25: + return "[yellow]Try advanced techniques![/yellow] Explore different architectures." + elif best_accuracy >= 10: + return "[magenta]Experiment and learn![/magenta] Each attempt teaches something new." + else: + return "[cyan]Keep experimenting![/cyan] Every expert started where you are now." \ No newline at end of file diff --git a/tito/commands/olympics.py b/tito/commands/olympics.py new file mode 100644 index 00000000..ec4d93af --- /dev/null +++ b/tito/commands/olympics.py @@ -0,0 +1,897 @@ +""" +TinyTorch Olympics Command + +Special competition events with focused challenges, time-limited competitions, +and unique recognition opportunities beyond the regular community leaderboard. +""" + +import json +import os +from argparse import ArgumentParser, Namespace +from datetime import datetime, timedelta +from pathlib import Path +from typing import Dict, List, Optional, Any +import uuid + +from rich.panel import Panel +from rich.table import Table +from rich.progress import track +from rich.prompt import Prompt, Confirm +from rich.console import Group +from rich.align import Align + +from .base import BaseCommand +from ..core.exceptions import TinyTorchCLIError + + +class OlympicsCommand(BaseCommand): + """Special competition events - Focused challenges and recognition""" + + @property + def name(self) -> str: + return "olympics" + + @property + def description(self) -> str: + return "Special competition events with unique challenges and recognition" + + def add_arguments(self, parser: ArgumentParser) -> None: + """Add olympics subcommands.""" + subparsers = parser.add_subparsers( + dest='olympics_command', + help='Olympics operations', + metavar='COMMAND' + ) + + # Events command + events_parser = subparsers.add_parser( + 'events', + help='View current and upcoming competition events' + ) + events_parser.add_argument( + '--upcoming', + action='store_true', + help='Show only upcoming events' + ) + events_parser.add_argument( + '--past', + action='store_true', + help='Show past competition results' + ) + + # Compete command + compete_parser = subparsers.add_parser( + 'compete', + help='Enter a specific competition event' + ) + compete_parser.add_argument( + '--event', + required=True, + help='Event ID to compete in' + ) + compete_parser.add_argument( + '--accuracy', + type=float, + help='Accuracy achieved for this competition' + ) + compete_parser.add_argument( + '--model', + help='Model description and approach used' + ) + compete_parser.add_argument( + '--code-url', + help='Optional: Link to your competition code/approach' + ) + compete_parser.add_argument( + '--notes', + help='Competition-specific notes, innovations, learnings' + ) + + # Awards command + awards_parser = subparsers.add_parser( + 'awards', + help='View special recognition and achievement badges' + ) + awards_parser.add_argument( + '--personal', + action='store_true', + help='Show only your personal awards' + ) + + # History command + history_parser = subparsers.add_parser( + 'history', + help='View past competition events and memorable moments' + ) + history_parser.add_argument( + '--year', + type=int, + help='Filter by specific year' + ) + history_parser.add_argument( + '--event-type', + choices=['speed', 'accuracy', 'innovation', 'efficiency', 'community'], + help='Filter by event type' + ) + + def run(self, args: Namespace) -> int: + """Execute olympics command.""" + command = getattr(args, 'olympics_command', None) + + if not command: + self._show_olympics_overview() + return 0 + + if command == 'events': + return self._show_events(args) + elif command == 'compete': + return self._compete_in_event(args) + elif command == 'awards': + return self._show_awards(args) + elif command == 'history': + return self._show_history(args) + else: + raise TinyTorchCLIError(f"Unknown olympics command: {command}") + + def _show_olympics_overview(self) -> None: + """Show olympics overview and current special events.""" + self.console.print(Panel( + Group( + Align.center("[bold bright_gold]🏅 TinyTorch Olympics 🏅[/bold bright_gold]"), + "", + "[bold]Special Competition Events![/bold] Beyond the regular community leaderboard:", + "", + "🎯 [bold bright_blue]Focused Challenges[/bold bright_blue]", + " • Time-limited competitions (24hr, 1week, 1month challenges)", + " • Specific constraints (memory-efficient, fastest training, novel architectures)", + " • Theme-based events (interpretability, fairness, efficiency)", + "", + "🏆 [bold bright_yellow]Special Recognition[/bold bright_yellow]", + " • Olympic medals and achievement badges", + " • Innovation awards for creative approaches", + " • Community impact recognition", + "", + "🌟 [bold bright_green]Current Active Events[/bold bright_green]", + " • Winter 2024 Speed Challenge (Training under 5 minutes)", + " • Memory Efficiency Olympics (Models under 1MB)", + " • Architecture Innovation Contest (Novel designs welcome)", + "", + "[bold]Available Commands:[/bold]", + " [green]events[/green] - See current and upcoming competitions", + " [green]compete[/green] - Enter a specific event", + " [green]awards[/green] - View special recognition and badges", + " [green]history[/green] - Past competitions and memorable moments", + "", + "[dim]💡 Note: Olympics are special events separate from daily community leaderboard[/dim]", + ), + title="🥇 Competition Central", + border_style="bright_yellow", + padding=(1, 2) + )) + + def _show_events(self, args: Namespace) -> int: + """Show current and upcoming competition events.""" + # Load events data (mock for now) + events = self._load_olympics_events() + + if args.upcoming: + events = [e for e in events if e["status"] == "upcoming"] + title = "📅 Upcoming Competition Events" + elif args.past: + events = [e for e in events if e["status"] == "completed"] + title = "🏛️ Past Competition Results" + else: + title = "🏅 All Competition Events" + + if not events: + status_text = "upcoming" if args.upcoming else "past" if args.past else "available" + self.console.print(Panel( + f"[yellow]No {status_text} events at this time![/yellow]\n\n" + "Check back soon for new competition opportunities!", + title="📅 No Events", + border_style="yellow" + )) + return 0 + + # Create events table + table = Table(title=title) + table.add_column("Event", style="bold") + table.add_column("Type", style="blue") + table.add_column("Duration", style="green") + table.add_column("Status", style="yellow") + table.add_column("Prize/Recognition", style="bright_magenta") + table.add_column("Participants", style="cyan", justify="right") + + for event in events: + status_display = self._get_status_display(event["status"], event.get("end_date")) + + table.add_row( + event["name"], + event["type"], + event["duration"], + status_display, + event["prize"], + str(event.get("participants", 0)) + ) + + self.console.print(table) + + # Show active event details + active_events = [e for e in events if e["status"] == "active"] + if active_events: + self.console.print(Panel( + Group( + "[bold bright_green]🔥 Active Competitions You Can Join Now![/bold bright_green]", + "", + *[f"• [bold]{event['name']}[/bold]: {event['description']}" for event in active_events[:3]], + "", + "[bold]Join a competition:[/bold]", + "[dim]tito olympics compete --event [/dim]", + ), + title="⚡ Join Now", + border_style="bright_green", + padding=(0, 1) + )) + + return 0 + + def _compete_in_event(self, args: Namespace) -> int: + """Enter a competition event.""" + # Check if user is registered for leaderboard + if not self._is_user_registered(): + self.console.print(Panel( + "[yellow]Please register for the community leaderboard first![/yellow]\n\n" + "Olympics competitions require community membership:\n" + "[bold]tito leaderboard register[/bold]", + title="📝 Registration Required", + border_style="yellow" + )) + return 1 + + # Load event details + event = self._get_event_details(args.event) + if not event: + self.console.print(Panel( + f"[red]Event '{args.event}' not found![/red]\n\n" + "See available events: [bold]tito olympics events[/bold]", + title="❌ Event Not Found", + border_style="red" + )) + return 1 + + # Check if event is active + if event["status"] != "active": + self.console.print(Panel( + f"[yellow]Event '{event['name']}' is not currently active![/yellow]\n\n" + f"Status: {event['status']}\n" + "See active events: [bold]tito olympics events[/bold]", + title="⏰ Event Not Active", + border_style="yellow" + )) + return 1 + + # Show event details and confirm participation + self._show_event_details(event) + + if not Confirm.ask("\n[bold]Compete in this event?[/bold]"): + self.console.print("[dim]Maybe next time! 👋[/dim]") + return 0 + + # Gather competition submission + submission = self._gather_competition_submission(event, args) + + # Validate submission meets event criteria + validation_result = self._validate_submission(event, submission) + if not validation_result["valid"]: + self.console.print(Panel( + f"[red]Submission doesn't meet event criteria![/red]\n\n" + f"Issue: {validation_result['reason']}\n\n" + "Please check event requirements and try again.", + title="❌ Validation Failed", + border_style="red" + )) + return 1 + + # Save competition entry + self._save_competition_entry(event, submission) + + # Show competition confirmation and standing + self._show_competition_confirmation(event, submission) + + return 0 + + def _show_awards(self, args: Namespace) -> int: + """Show special recognition and achievement badges.""" + if args.personal: + return self._show_personal_awards() + else: + return self._show_all_awards() + + def _show_personal_awards(self) -> int: + """Show user's personal awards and badges.""" + if not self._is_user_registered(): + self.console.print(Panel( + "[yellow]Please register first to see your awards![/yellow]\n\n" + "Run: [bold]tito leaderboard register[/bold]", + title="📝 Registration Required", + border_style="yellow" + )) + return 1 + + # Load user's Olympic achievements + olympic_profile = self._load_user_olympic_profile() + awards = olympic_profile.get("awards", []) + competitions = olympic_profile.get("competitions", []) + + if not awards and not competitions: + self.console.print(Panel( + Group( + "[bold bright_blue]🌟 Your Olympic Journey Awaits![/bold bright_blue]", + "", + "You haven't participated in Olympics competitions yet.", + "", + "[bold]Start your journey:[/bold]", + "• Check active events: [green]tito olympics events[/green]", + "• Join a competition: [green]tito olympics compete --event [/green]", + "• Earn your first Olympic badge! 🏅", + "", + "[dim]Every Olympic participant gets recognition for participation![/dim]", + ), + title="🏅 Your Olympic Profile", + border_style="bright_blue", + padding=(1, 2) + )) + return 0 + + # Show awards and achievements + self._display_personal_olympic_achievements(olympic_profile) + return 0 + + def _show_all_awards(self) -> int: + """Show community awards and notable achievements.""" + # Mock awards data + notable_awards = self._load_notable_awards() + + # Recent awards table + table = Table(title="🏆 Recent Olympic Achievements") + table.add_column("Award", style="bold") + table.add_column("Recipient", style="green") + table.add_column("Event", style="blue") + table.add_column("Achievement", style="yellow") + table.add_column("Date", style="dim") + + for award in notable_awards[:10]: + table.add_row( + award["award_type"], + award["recipient"], + award["event"], + award["description"], + award["date"] + ) + + self.console.print(table) + + # Award categories explanation + self.console.print(Panel( + Group( + "[bold bright_yellow]🏅 Olympic Award Categories[/bold bright_yellow]", + "", + "🥇 [bold]Performance Awards[/bold]", + " • Gold/Silver/Bronze medals for top competition results", + " • Speed records, accuracy achievements, efficiency milestones", + "", + "🌟 [bold]Innovation Awards[/bold]", + " • Novel Architecture Award for creative model designs", + " • Optimization Genius for breakthrough efficiency techniques", + " • Interpretability Champion for explainable AI contributions", + "", + "🤝 [bold]Community Awards[/bold]", + " • Mentor Badge for helping other competitors", + " • Knowledge Sharer for valuable insights and tutorials", + " • Sportsperson Award for exceptional community spirit", + "", + "🎯 [bold]Special Recognition[/bold]", + " • First Participation Badge (everyone gets this!)", + " • Consistency Award for regular competition participation", + " • Breakthrough Achievement for major personal improvements", + ), + title="🏆 Recognition System", + border_style="bright_yellow", + padding=(0, 1) + )) + + return 0 + + def _show_history(self, args: Namespace) -> int: + """Show past competition events and memorable moments.""" + # Load historical data + history = self._load_olympics_history() + + # Filter by year if specified + if args.year: + history = [h for h in history if h["year"] == args.year] + + # Filter by event type if specified + if args.event_type: + history = [h for h in history if h["type"] == args.event_type] + + if not history: + filter_text = f" for {args.year}" if args.year else "" + filter_text += f" ({args.event_type} events)" if args.event_type else "" + + self.console.print(Panel( + f"[yellow]No competition history found{filter_text}![/yellow]\n\n" + "The Olympics program is just getting started!", + title="📚 No History", + border_style="yellow" + )) + return 0 + + # Create history table + table = Table(title="📚 TinyTorch Olympics History") + table.add_column("Event", style="bold") + table.add_column("Date", style="dim") + table.add_column("Type", style="blue") + table.add_column("Winner", style="green") + table.add_column("Achievement", style="yellow") + table.add_column("Memorable Moment", style="cyan") + + for event in sorted(history, key=lambda x: x["date"], reverse=True): + table.add_row( + event["name"], + event["date"], + event["type"], + event["winner"], + event["winning_achievement"], + event["memorable_moment"] + ) + + self.console.print(table) + + # Show legendary moments + if not args.year and not args.event_type: + self.console.print(Panel( + Group( + "[bold bright_gold]🌟 Legendary Olympic Moments[/bold bright_gold]", + "", + "🏆 [bold]The Great Speed Challenge 2024[/bold]", + " Winner achieved 75% CIFAR-10 accuracy in just 47 seconds!", + "", + "🧠 [bold]Architecture Innovation Contest[/bold]", + " Revolutionary attention mechanism reduced parameters by 90%", + "", + "🤝 [bold]Community Spirit Award[/bold]", + " Competitor shared winning code to help others improve", + "", + "[dim]Each Olympics creates new legends in the TinyTorch community! 💫[/dim]", + ), + title="🏛️ Hall of Fame", + border_style="bright_gold", + padding=(0, 1) + )) + + return 0 + + def _load_olympics_events(self) -> List[Dict[str, Any]]: + """Load olympics events data (mock implementation).""" + return [ + { + "id": "winter2024_speed", + "name": "Winter 2024 Speed Challenge", + "type": "Speed", + "status": "active", + "duration": "24 hours", + "description": "Train CIFAR-10 model to 70%+ accuracy in under 5 minutes", + "prize": "🏆 Speed Medal + Recognition", + "participants": 23, + "start_date": "2024-01-15", + "end_date": "2024-01-16", + "criteria": {"min_accuracy": 70.0, "max_time_minutes": 5} + }, + { + "id": "memory2024_efficiency", + "name": "Memory Efficiency Olympics", + "type": "Efficiency", + "status": "active", + "duration": "1 week", + "description": "Best CIFAR-10 accuracy with model under 1MB", + "prize": "🥇 Efficiency Champion", + "participants": 15, + "start_date": "2024-01-10", + "end_date": "2024-01-17", + "criteria": {"max_model_size_mb": 1.0} + }, + { + "id": "innovation2024_arch", + "name": "Architecture Innovation Contest", + "type": "Innovation", + "status": "upcoming", + "duration": "2 weeks", + "description": "Novel architectures and creative approaches welcome", + "prize": "🌟 Innovation Award", + "participants": 0, + "start_date": "2024-02-01", + "end_date": "2024-02-14", + "criteria": {"novelty_required": True} + }, + { + "id": "autumn2023_classic", + "name": "Autumn 2023 Classic", + "type": "Accuracy", + "status": "completed", + "duration": "1 month", + "description": "Best overall CIFAR-10 accuracy challenge", + "prize": "🥇 Gold Medal", + "participants": 87, + "start_date": "2023-10-01", + "end_date": "2023-10-31", + "winner": "neural_champion", + "winning_score": 84.2 + } + ] + + def _get_status_display(self, status: str, end_date: Optional[str] = None) -> str: + """Get display-friendly status with timing information.""" + if status == "active": + if end_date: + # Calculate time remaining + end = datetime.fromisoformat(end_date) + now = datetime.now() + if end > now: + remaining = end - now + if remaining.days > 0: + return f"🔥 Active ({remaining.days}d left)" + else: + hours = remaining.seconds // 3600 + return f"🔥 Active ({hours}h left)" + return "🔥 Active" + elif status == "upcoming": + return "📅 Upcoming" + elif status == "completed": + return "✅ Completed" + else: + return status.title() + + def _is_user_registered(self) -> bool: + """Check if user is registered for community leaderboard.""" + from .leaderboard import LeaderboardCommand + leaderboard_cmd = LeaderboardCommand(self.config) + return leaderboard_cmd._load_user_profile() is not None + + def _get_event_details(self, event_id: str) -> Optional[Dict[str, Any]]: + """Get details for a specific event.""" + events = self._load_olympics_events() + return next((e for e in events if e["id"] == event_id), None) + + def _show_event_details(self, event: Dict[str, Any]) -> None: + """Show detailed information about an event.""" + self.console.print(Panel( + Group( + f"[bold bright_blue]{event['name']}[/bold bright_blue]", + "", + f"[bold]Type:[/bold] {event['type']}", + f"[bold]Duration:[/bold] {event['duration']}", + f"[bold]Current Participants:[/bold] {event.get('participants', 0)}", + "", + f"[bold]Challenge:[/bold]", + f" {event['description']}", + "", + f"[bold]Recognition:[/bold]", + f" {event['prize']}", + "", + f"[bold]Requirements:[/bold]", + *[f" • {k.replace('_', ' ').title()}: {v}" for k, v in event.get('criteria', {}).items()], + ), + title=f"🏅 {event['type']} Competition", + border_style="bright_blue", + padding=(1, 2) + )) + + def _gather_competition_submission(self, event: Dict[str, Any], args: Namespace) -> Dict[str, Any]: + """Gather submission details for competition.""" + submission = { + "event_id": event["id"], + "submitted_date": datetime.now().isoformat() + } + + # Get accuracy + if args.accuracy is not None: + submission["accuracy"] = args.accuracy + else: + submission["accuracy"] = float(Prompt.ask( + f"[bold]Accuracy achieved on {event.get('dataset', 'the task')}[/bold]", + default="0.0" + )) + + # Get model description + if args.model: + submission["model"] = args.model + else: + submission["model"] = Prompt.ask( + "[bold]Model description[/bold] (architecture, approach, innovations)", + default="Custom Model" + ) + + # Optional fields + submission["code_url"] = args.code_url or Prompt.ask( + "[bold]Code/approach URL[/bold] (optional)", + default="" + ) or None + + submission["notes"] = args.notes or Prompt.ask( + "[bold]Competition notes[/bold] (innovations, challenges, learnings)", + default="" + ) or None + + # Event-specific metrics + if "max_time_minutes" in event.get("criteria", {}): + training_time = float(Prompt.ask( + "[bold]Training time in minutes[/bold]", + default="0.0" + )) + submission["training_time_minutes"] = training_time + + if "max_model_size_mb" in event.get("criteria", {}): + model_size = float(Prompt.ask( + "[bold]Model size in MB[/bold]", + default="0.0" + )) + submission["model_size_mb"] = model_size + + return submission + + def _validate_submission(self, event: Dict[str, Any], submission: Dict[str, Any]) -> Dict[str, Any]: + """Validate submission meets event criteria.""" + criteria = event.get("criteria", {}) + + # Check minimum accuracy + if "min_accuracy" in criteria: + if submission["accuracy"] < criteria["min_accuracy"]: + return { + "valid": False, + "reason": f"Accuracy {submission['accuracy']:.1f}% below required {criteria['min_accuracy']:.1f}%" + } + + # Check maximum training time + if "max_time_minutes" in criteria: + if submission.get("training_time_minutes", 0) > criteria["max_time_minutes"]: + return { + "valid": False, + "reason": f"Training time {submission['training_time_minutes']:.1f}min exceeds limit {criteria['max_time_minutes']:.1f}min" + } + + # Check maximum model size + if "max_model_size_mb" in criteria: + if submission.get("model_size_mb", 0) > criteria["max_model_size_mb"]: + return { + "valid": False, + "reason": f"Model size {submission['model_size_mb']:.1f}MB exceeds limit {criteria['max_model_size_mb']:.1f}MB" + } + + return {"valid": True} + + def _save_competition_entry(self, event: Dict[str, Any], submission: Dict[str, Any]) -> None: + """Save competition entry to user's Olympic profile.""" + olympic_profile = self._load_user_olympic_profile() + + if "competitions" not in olympic_profile: + olympic_profile["competitions"] = [] + + olympic_profile["competitions"].append(submission) + + # Add participation award if first competition + if len(olympic_profile["competitions"]) == 1: + award = { + "type": "participation", + "name": "First Olympic Participation", + "description": "Welcomed to the Olympics community!", + "event": event["name"], + "earned_date": datetime.now().isoformat() + } + if "awards" not in olympic_profile: + olympic_profile["awards"] = [] + olympic_profile["awards"].append(award) + + self._save_user_olympic_profile(olympic_profile) + + def _show_competition_confirmation(self, event: Dict[str, Any], submission: Dict[str, Any]) -> None: + """Show confirmation and current standing.""" + # Determine performance level for this competition + ranking_message = self._get_competition_ranking_message(event, submission) + + self.console.print(Panel( + Group( + Align.center("[bold bright_green]🎉 Competition Entry Submitted! 🎉[/bold bright_green]"), + "", + f"[bold]Event:[/bold] {event['name']}", + f"[bold]Your Result:[/bold] {submission['accuracy']:.1f}% accuracy", + f"[bold]Model:[/bold] {submission['model']}", + "", + ranking_message, + "", + "[bold bright_blue]🏅 Recognition Earned:[/bold bright_blue]", + "• Olympic Participant Badge", + "• Competition Experience Points", + "• Community Recognition", + "", + "[bold]Next Steps:[/bold]", + "• View your awards: [green]tito olympics awards --personal[/green]", + "• See current standings: [green]tito olympics events[/green]", + "• Join another event: [green]tito olympics events[/green]", + ), + title="🥇 Olympic Achievement", + border_style="bright_green", + padding=(1, 2) + )) + + def _get_competition_ranking_message(self, event: Dict[str, Any], submission: Dict[str, Any]) -> str: + """Get appropriate ranking/performance message for competition.""" + accuracy = submission["accuracy"] + + # Mock competition standings for encouragement + if accuracy >= 80: + return "[bright_green]🏆 Outstanding performance! You're in contention for top prizes![/bright_green]" + elif accuracy >= 70: + return "[bright_blue]🎯 Strong showing! You're competing well in this event![/bright_blue]" + elif accuracy >= 60: + return "[bright_yellow]🌟 Good effort! Every competition teaches valuable lessons![/bright_yellow]" + else: + return "[bright_magenta]💝 Thank you for participating! Competition experience is valuable![/bright_magenta]" + + def _load_user_olympic_profile(self) -> Dict[str, Any]: + """Load user's Olympic competition profile.""" + data_dir = Path.home() / ".tinytorch" / "olympics" + data_dir.mkdir(parents=True, exist_ok=True) + profile_file = data_dir / "olympic_profile.json" + + if profile_file.exists(): + with open(profile_file, 'r') as f: + return json.load(f) + + return { + "competitions": [], + "awards": [], + "created_date": datetime.now().isoformat() + } + + def _save_user_olympic_profile(self, profile: Dict[str, Any]) -> None: + """Save user's Olympic competition profile.""" + data_dir = Path.home() / ".tinytorch" / "olympics" + profile_file = data_dir / "olympic_profile.json" + + with open(profile_file, 'w') as f: + json.dump(profile, f, indent=2) + + def _display_personal_olympic_achievements(self, olympic_profile: Dict[str, Any]) -> None: + """Display user's personal Olympic achievements.""" + competitions = olympic_profile.get("competitions", []) + awards = olympic_profile.get("awards", []) + + # Summary stats + total_competitions = len(competitions) + best_accuracy = max([c["accuracy"] for c in competitions], default=0) + events_participated = len(set(c["event_id"] for c in competitions)) + + self.console.print(Panel( + Group( + Align.center("[bold bright_gold]🏅 Your Olympic Journey 🏅[/bold bright_gold]"), + "", + f"🎯 Competitions Entered: {total_competitions}", + f"🏆 Best Performance: {best_accuracy:.1f}% accuracy", + f"🌟 Events Participated: {events_participated}", + f"🥇 Awards Earned: {len(awards)}", + ), + title="📊 Olympic Stats", + border_style="bright_gold", + padding=(1, 2) + )) + + # Awards table + if awards: + awards_table = Table(title="🏆 Your Olympic Awards") + awards_table.add_column("Award", style="bold") + awards_table.add_column("Event", style="blue") + awards_table.add_column("Description", style="green") + awards_table.add_column("Date", style="dim") + + for award in sorted(awards, key=lambda x: x["earned_date"], reverse=True): + awards_table.add_row( + award["name"], + award["event"], + award["description"], + award["earned_date"][:10] + ) + + self.console.print(awards_table) + + # Recent competitions + if competitions: + recent_comps = sorted(competitions, key=lambda x: x["submitted_date"], reverse=True)[:5] + + comps_table = Table(title="🎯 Recent Competition Entries") + comps_table.add_column("Event", style="bold") + comps_table.add_column("Accuracy", style="green", justify="right") + comps_table.add_column("Model", style="blue") + comps_table.add_column("Date", style="dim") + + for comp in recent_comps: + comps_table.add_row( + comp["event_id"], + f"{comp['accuracy']:.1f}%", + comp["model"], + comp["submitted_date"][:10] + ) + + self.console.print(comps_table) + + def _load_notable_awards(self) -> List[Dict[str, Any]]: + """Load notable community awards (mock implementation).""" + return [ + { + "award_type": "🥇 Gold Medal", + "recipient": "speed_demon", + "event": "Winter 2024 Speed Challenge", + "description": "2.3 min training, 78.4% accuracy", + "date": "2024-01-16" + }, + { + "award_type": "🌟 Innovation Award", + "recipient": "arch_wizard", + "event": "Memory Efficiency Olympics", + "description": "Novel attention mechanism", + "date": "2024-01-15" + }, + { + "award_type": "🤝 Community Spirit", + "recipient": "helpful_mentor", + "event": "Autumn 2023 Classic", + "description": "Shared winning approach publicly", + "date": "2023-11-01" + }, + { + "award_type": "🏆 Speed Record", + "recipient": "lightning_fast", + "event": "Winter 2024 Speed Challenge", + "description": "47 second training record", + "date": "2024-01-15" + }, + { + "award_type": "🎯 Accuracy Champion", + "recipient": "precision_master", + "event": "Architecture Innovation", + "description": "86.7% CIFAR-10 accuracy", + "date": "2024-01-10" + } + ] + + def _load_olympics_history(self) -> List[Dict[str, Any]]: + """Load historical Olympics data (mock implementation).""" + return [ + { + "name": "Autumn 2023 Classic", + "date": "2023-10-31", + "year": 2023, + "type": "accuracy", + "winner": "neural_champion", + "winning_achievement": "84.2% CIFAR-10 accuracy", + "memorable_moment": "First 80%+ achievement in community" + }, + { + "name": "Summer 2023 Speed Trial", + "date": "2023-07-15", + "year": 2023, + "type": "speed", + "winner": "velocity_victor", + "winning_achievement": "3.2 minute training", + "memorable_moment": "Breakthrough GPU optimization technique" + }, + { + "name": "Spring 2023 Innovation Fair", + "date": "2023-04-20", + "year": 2023, + "type": "innovation", + "winner": "creative_genius", + "winning_achievement": "Self-organizing architecture", + "memorable_moment": "Inspired 12 follow-up research papers" + } + ] \ No newline at end of file diff --git a/tito/main.py b/tito/main.py index b429335e..65499af9 100644 --- a/tito/main.py +++ b/tito/main.py @@ -40,6 +40,8 @@ from .commands.grade import GradeCommand from .commands.demo import DemoCommand from .commands.logo import LogoCommand from .commands.milestone import MilestoneCommand +from .commands.leaderboard import LeaderboardCommand +from .commands.olympics import OlympicsCommand # Configure logging logging.basicConfig( @@ -68,6 +70,8 @@ class TinyTorchCLI: 'nbgrader': NBGraderCommand, 'checkpoint': CheckpointCommand, 'milestone': MilestoneCommand, + 'leaderboard': LeaderboardCommand, + 'olympics': OlympicsCommand, # Convenience commands 'export': ExportCommand, 'test': TestCommand, @@ -85,12 +89,14 @@ class TinyTorchCLI: formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Command Groups: - system System environment and configuration commands - module Module development and management commands - package Package management and nbdev integration commands - nbgrader Assignment management and auto-grading commands - checkpoint Track ML systems engineering progress through checkpoints - milestone Epic capability achievements and ML systems mastery + system System environment and configuration commands + module Module development and management commands + package Package management and nbdev integration commands + nbgrader Assignment management and auto-grading commands + checkpoint Track ML systems engineering progress through checkpoints + milestone Epic capability achievements and ML systems mastery + leaderboard Join the inclusive community, share progress, celebrate achievements + olympics Special competition events with focused challenges and recognition Convenience Commands: export Export modules to package (quick shortcut) @@ -105,6 +111,8 @@ Examples: tito module view 01_setup Start coding in Jupyter Lab tito export 01_tensor Export specific module to package tito checkpoint timeline Visual progress timeline + tito leaderboard register Join the inclusive community + tito olympics events See special competitions tito book build Build the Jupyter Book locally """ ) @@ -198,12 +206,14 @@ Examples: # Show enhanced help with command groups self.console.print(Panel( "[bold]Command Groups:[/bold]\n" - " [bold green]system[/bold green] - System environment and configuration\n" - " [bold green]module[/bold green] - Module development and management\n" - " [bold green]package[/bold green] - Package management and nbdev integration\n" - " [bold green]nbgrader[/bold green] - Assignment management and auto-grading\n" - " [bold green]checkpoint[/bold green] - Track ML systems engineering progress\n" - " [bold magenta]milestone[/bold magenta] - Epic capability achievements and ML mastery\n\n" + " [bold green]system[/bold green] - System environment and configuration\n" + " [bold green]module[/bold green] - Module development and management\n" + " [bold green]package[/bold green] - Package management and nbdev integration\n" + " [bold green]nbgrader[/bold green] - Assignment management and auto-grading\n" + " [bold green]checkpoint[/bold green] - Track ML systems engineering progress\n" + " [bold magenta]milestone[/bold magenta] - Epic capability achievements and ML mastery\n" + " [bold bright_blue]leaderboard[/bold bright_blue] - Join the inclusive community, share progress\n" + " [bold bright_yellow]olympics[/bold bright_yellow] - Special competition events and recognition\n\n" "[bold]Convenience Commands:[/bold]\n" " [bold green]export[/bold green] - Export modules to package\n" " [bold green]test[/bold green] - Run tests\n" @@ -214,6 +224,8 @@ Examples: " [dim]tito module status --metadata[/dim] - Module status with metadata\n" " [dim]tito module view 01_setup[/dim] - Start coding in Jupyter Lab\n" " [dim]tito checkpoint timeline[/dim] - Visual progress timeline\n" + " [dim]tito leaderboard register[/dim] - Join the inclusive community\n" + " [dim]tito olympics events[/dim] - See special competitions\n" " [dim]tito milestone status[/dim] - See your epic achievement progress\n" "[bold]Get Help:[/bold]\n" " [dim]tito system[/dim] - Show system subcommands\n"