from django.conf import settings from django.db import models class Role(models.Model): name = models.CharField(max_length=100, unique=True) slug = models.SlugField(max_length=120, unique=True) description = models.TextField(blank=True) class Meta: ordering = ["name"] def __str__(self) -> str: return self.name class Specialty(models.Model): name = models.CharField(max_length=100, unique=True) slug = models.SlugField(max_length=120, unique=True) description = models.TextField(blank=True) class Meta: ordering = ["name"] def __str__(self) -> str: return self.name class Player(models.Model): class Position(models.TextChoices): PG = "PG", "PG" SG = "SG", "SG" SF = "SF", "SF" PF = "PF", "PF" C = "C", "C" full_name = models.CharField(max_length=255) first_name = models.CharField(max_length=100, blank=True) last_name = models.CharField(max_length=100, blank=True) birth_date = models.DateField(null=True, blank=True) nationality = models.CharField(max_length=100, blank=True) height_cm = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) weight_kg = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) wingspan_cm = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) position = models.CharField(max_length=2, choices=Position.choices) roles = models.ManyToManyField(Role, blank=True, related_name="players") specialties = models.ManyToManyField(Specialty, blank=True, related_name="players") created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["full_name"] def __str__(self) -> str: return self.full_name class Competition(models.Model): name = models.CharField(max_length=150, unique=True) country = models.CharField(max_length=100, blank=True) level = models.CharField(max_length=100, blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["name"] def __str__(self) -> str: return self.name class Team(models.Model): name = models.CharField(max_length=150) country = models.CharField(max_length=100, blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["name"] constraints = [ models.UniqueConstraint(fields=["name", "country"], name="uniq_team_name_country"), ] def __str__(self) -> str: return self.name class Season(models.Model): name = models.CharField(max_length=20, unique=True) start_year = models.PositiveSmallIntegerField() end_year = models.PositiveSmallIntegerField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["-start_year", "-end_year"] def __str__(self) -> str: return self.name class PlayerSeason(models.Model): player = models.ForeignKey(Player, on_delete=models.CASCADE, related_name="player_seasons") season = models.ForeignKey(Season, on_delete=models.CASCADE, related_name="player_seasons") team = models.ForeignKey( Team, on_delete=models.SET_NULL, null=True, blank=True, related_name="player_seasons", ) competition = models.ForeignKey( Competition, on_delete=models.SET_NULL, null=True, blank=True, related_name="player_seasons", ) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["player__full_name", "-season__start_year"] constraints = [ models.UniqueConstraint( fields=["player", "season", "team", "competition"], name="uniq_player_season_context", nulls_distinct=False, ), ] def __str__(self) -> str: team_name = self.team.name if self.team else "No team" competition_name = self.competition.name if self.competition else "No competition" return f"{self.player.full_name} - {self.season.name} - {team_name} - {competition_name}" class PlayerSeasonStats(models.Model): player_season = models.OneToOneField( PlayerSeason, on_delete=models.CASCADE, related_name="stats", ) points = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True) assists = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True) steals = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True) turnovers = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True) blocks = models.DecimalField(max_digits=6, decimal_places=2, null=True, blank=True) efg_pct = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) ts_pct = models.DecimalField(max_digits=5, decimal_places=2, null=True, blank=True) plus_minus = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True) offensive_rating = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True) defensive_rating = models.DecimalField(max_digits=7, decimal_places=2, null=True, blank=True) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: verbose_name_plural = "Player season stats" def __str__(self) -> str: return f"Stats for {self.player_season}" class FavoritePlayer(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="favorite_players", ) player = models.ForeignKey( Player, on_delete=models.CASCADE, related_name="favorite_entries", ) created_at = models.DateTimeField(auto_now_add=True) class Meta: ordering = ["-created_at", "player__full_name"] constraints = [ models.UniqueConstraint(fields=["user", "player"], name="uniq_favorite_player_per_user"), ] def __str__(self) -> str: return f"Favorite: {self.user} -> {self.player.full_name}" class PlayerNote(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="player_notes", ) player = models.ForeignKey( Player, on_delete=models.CASCADE, related_name="notes", ) body = models.TextField() created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["-created_at", "-id"] def __str__(self) -> str: return f"Note by {self.user} for {self.player.full_name}" class SavedSearch(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="saved_searches", ) name = models.CharField(max_length=120) params = models.JSONField(default=dict) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: ordering = ["name", "-updated_at", "-id"] constraints = [ models.UniqueConstraint(fields=["user", "name"], name="uniq_saved_search_name_per_user"), ] def __str__(self) -> str: return f"{self.user} - {self.name}"