from os import WEXITED, preadv from django.db import models from django.contrib.auth.models import AbstractUser from django.conf import settings import uuid import os from django.utils.encoding import Promise import tournaments class FederalCategory(models.IntegerChoices): MEN = 0, 'Men' WOMEN = 1, 'Women' MIXED = 2, 'Mixed' class FederalLevelCategory(models.IntegerChoices): P25 = 25, 'P25' P100 = 100, 'P100' P250 = 250, 'P250' P500 = 500, 'P500' P1000 = 1000, 'P1000' P1500 = 1500, 'P1500' P2000 = 2000, 'P2000' class FederalAgeCategory(models.IntegerChoices): A11_12 = 120, 'A11_12' A13_14 = 140, 'A13_14' A15_16 = 160, 'A15_16' A17_18 = 180, 'A17_18' SENIOR = 200, 'SENIOR' A45 = 450, 'A45' A55 = 550, 'A55' class FederalMatchCategory(models.IntegerChoices): TWO_SETS = 0, 'Two sets' TWO_SETS_SUPER_TIE = 1, 'Two sets super tie' TWO_SETS_FOUR_GAME = 2, 'Two sets of four games' NINE_GAMES = 3, 'Nine games' SUPER_TIE = 4, 'Super Tie-Break' MEGA_TIE = 5, 'Mega Tie-Break' TWO_SETS_DECISIVE_POINT = 6, 'Two Sets with decisive point' TWO_SETS_DECISIVE_POINT_SUPER_TIE = 7, 'Two Sets with decisive point and super tie-break' TWO_SETS_FOUR_GAME_DECISIVE_POINT = 8, 'Two sets of four games with decisive point' NINE_GAMES_DECISIVE_POINT = 9, 'Nine games with decisive point' class Club(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) name = models.CharField(max_length=50) acronym = models.CharField(max_length=10) phone = models.CharField(max_length=15, null=True, blank=True) code = models.CharField(max_length=10, null=True, blank=True) federal_club_data = models.JSONField(null=True, blank=True) address = models.CharField(max_length=200, null=True, blank=True) city = models.CharField(max_length=100, null=True, blank=True) zip_code = models.CharField(max_length=10, null=True, blank=True) latitude = models.FloatField(null=True, blank=True) longitude = models.FloatField(null=True, blank=True) def __str__(self): return self.name class CustomUser(AbstractUser): pass id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) umpire_code = models.CharField(max_length=50, blank=True, null=True) clubs = models.ManyToManyField(Club) phone = models.CharField(max_length=15, null=True, blank=True) first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) licence_id = models.CharField(max_length=10, null=True, blank=True) def __str__(self): return self.username class Event(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) club = models.ForeignKey(Club, on_delete=models.CASCADE) date = models.DateField() name = models.CharField(max_length=200, null=True, blank=True) federal_tournament_data = models.JSONField(null=True, blank=True) court_count = models.IntegerField(null=True, blank=True) tenup_id = models.IntegerField(null=True, blank=True) group_stage_format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) round_format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) loser_round_format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) def __str__(self): return self.name class Tournament(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) event = models.ForeignKey(Event, blank=True, null=True, on_delete=models.CASCADE) user = models.ForeignKey(CustomUser, blank=True, null=True, on_delete=models.CASCADE) name = models.CharField(max_length=200, null=True, blank=True) start_date = models.DateField() end_date = models.DateField(null=True, blank=True) creation_date = models.DateField() is_private = models.BooleanField() format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) group_stage_format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) round_format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) loser_round_format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) bracket_sort_mode = models.IntegerField(default=0) group_stage_count = models.IntegerField(default=0) rank_source_date = models.DateField(null=True, blank=True) custom_name = models.CharField(max_length=100, null=True, blank=True) day_duration = models.IntegerField(default=0) team_count = models.IntegerField(default=0) team_sorting = models.IntegerField(default=0) federal_category = models.IntegerField(default=FederalCategory.MEN, choices=FederalCategory.choices) # optional ? federal_level_category = models.IntegerField(default=FederalLevelCategory.P100, choices=FederalLevelCategory.choices) federal_age_category = models.IntegerField(default=FederalAgeCategory.SENIOR, choices=FederalAgeCategory.choices) group_stage_court_count = models.IntegerField(null=True, blank=True) seed_count = models.IntegerField(default=0) closed_registration_date = models.DateField(null=True, blank=True) additional_qualified = models.IntegerField(default=0) # ajouter group_stage dans le nom ? court_count = models.IntegerField(null=True, blank=True) prioritize_club_members = models.BooleanField() qualified_per_group_stage = models.IntegerField(default=0) teams_per_group_stage = models.IntegerField(default=0) #estimated_end_date = models.DateField(null=True, blank=True) def __str__(self): return self.name def level(self): return self.get_federal_level_category_display() def category(self): return self.get_federal_category_display() def formatted_start_date(self): return self.start_date.strftime("%d/%m/%y") def team_calls(self): team_calls = [] for team_registration in self.teamregistration_set.all(): names = team_registration.team_names() call_date = team_registration.call_date.strftime("%d/%m/%y %H:%M") stage = team_registration.next_stage() weight = team_registration.weight() team_call = TeamCall(names, call_date, weight, stage, team_registration.logo) team_calls.append(team_call) return team_calls # stage_call = StageCall(f"1/{self.index}") # for match in self.match_set.all(): # names = map(lambda ts: ts.player_names(), match.teamstate_set.all()) # if names: # team_call = TeamCall(names, match.formatted_start_date) # stage_call.add_team(team_call) # return stage_call class Round(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) tournament = models.ForeignKey(Club, on_delete=models.CASCADE) index = models.IntegerField(null=True, blank=True) loser = models.ForeignKey('self', blank=True, null=True, on_delete=models.CASCADE) format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) def __str__(self): return f"{self.tournament.name} - {self.name()}" # def stage_call(self): # stage_call = StageCall(f"1/{self.index}") # for match in self.match_set.all(): # names = map(lambda ts: ts.player_names(), match.teamstate_set.all()) # if names: # team_call = TeamCall(names, match.formatted_start_date) # stage_call.add_team(team_call) # return stage_call def name(self): if self.index == 0: return "Finale" elif self.index == 1: return "Demi-Finales" elif self.index == 2: return "Quarts de finale" elif self.index == 3: return "Huitième de finale" elif self.index == 4: return "Seizième de finale" else: return "" class GroupStage(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) tournament = models.ForeignKey(Club, on_delete=models.CASCADE) index = models.IntegerField(null=True, blank=True) format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) def __str__(self): return f"{self.tournament.name} - {self.name()}" def name(self): return f"Poule {self.index}" # def stage_call(self): # stage_call = StageCall(f"poule{self.index}") # for team_registration in self.teamregistration_set.all(): # names = map(lambda pr: pr.name(), team_registration.playerregistration_set.all()) # time = self.next_match(team_registration).start_date.strftime("%H:%M") # "17h45" # which match do we take, the first unfinished? # team_call = TeamCall(names, time) # return stage_call def next_match(self, player_registration): matches = self.matches_for_registration(player_registration).filter(end_date__isnull=False).order_by('start_date') return matches[0] def matches_for_registration(self, player_registration): team_states = TeamState.objects.filter(player_registrations=player_registration) return map(lambda ts: ts.match, team_states) class Match(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) round = models.ForeignKey(Round, null=True, blank=True, on_delete=models.CASCADE) group_stage = models.ForeignKey(GroupStage, null=True, blank=True, on_delete=models.CASCADE) start_date = models.DateField(null=True, blank=True) end_date = models.DateField(null=True, blank=True) index = models.IntegerField(null=True, blank=True) format = models.IntegerField(default=FederalMatchCategory.NINE_GAMES, choices=FederalMatchCategory.choices, null=True, blank=True) court = models.IntegerField(null=True, blank=True) serving_team_id = models.UUIDField(null=True, blank=True) winning_team_id = models.UUIDField(null=True, blank=True) losing_team_id = models.UUIDField(null=True, blank=True) broadcasted = models.BooleanField(default=False) def __str__(self): items = [f"Match {self.index}", self.formatted_start_date()] desc = " - ".join(items) player_names = " / ".join(self.player_names()) if self.round: return f"{str(self.round)} > {desc} > {player_names}" elif self.group_stage: return f"{str(self.group_stage)} > {desc} > {player_names}" def player_names(self): return map(lambda ts: ts.player_names(), self.teamstate_set.all()) def formatted_start_date(self): return self.start_date.strftime("%H:%M") class TeamRegistration(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) tournament = models.ForeignKey(Tournament, on_delete=models.CASCADE) group_stage = models.ForeignKey(GroupStage, null=True, blank=True, on_delete=models.SET_NULL) registration_date = models.DateField(null=True, blank=True) call_date = models.DateField(null=True, blank=True) initial_position = models.IntegerField(null=True, blank=True) group_stage_position = models.IntegerField(null=True, blank=True) comment = models.CharField(max_length=200, null=True, blank=True) source = models.CharField(max_length=20, null=True, blank=True) source_value = models.CharField(max_length=200, null=True, blank=True) logo = models.FilePathField(path=os.path.join(settings.STATIC_ROOT, "images"), null=True, blank=True) name = models.CharField(max_length=200, null=True, blank=True) def __str__(self): return self.player_names() def team_names(self): if self.name: return [self.name] else: return map(lambda pr: pr.name(), self.playerregistration_set.all()) def player_names(self): names = map(lambda pr: pr.name(), self.playerregistration_set.all()) str = " - ".join(names) if len(str) > 0: return str else: return "no players" def next_stage(self): matches = Match.objects.filter(group_stage__isnull=True, team_states__player_registrations__id=self.id).order_by('round__index') if matches: return matches[0].round.name() elif self.group_stage: return self.group_stage.name() else: return "--" def weight(self): top_two_players = self.playerregistration_set.all().order_by('rank')[:2] weight = 0 for player in top_two_players: rank = player.rank if player.rank is not None else 0 weight += rank return weight class PlayerRegistration(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) team_registration = models.ForeignKey(TeamRegistration, on_delete=models.CASCADE) first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) licence_id = models.CharField(max_length=20, null=True, blank=True) rank = models.IntegerField(null=True, blank=True) has_paid = models.BooleanField(default=False) unranked = models.BooleanField(default=False) def __str__(self): return self.name() def name(self): return f"{self.first_name} {self.last_name}" class TeamState(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) match = models.ForeignKey(Match, on_delete=models.CASCADE, related_name="team_states") player_registrations = models.ManyToManyField(PlayerRegistration, blank=True) score = models.CharField(max_length=50, null=True, blank=True) walk_out = models.IntegerField(null=True, blank=True) #id, int of the walked_out team lucky_loser = models.BooleanField() def __str__(self): return f"{str(self.match)}: {self.player_names()}" def player_names(self): names = map(lambda player: player.name(), self.player_registrations.all()) return " - ".join(names) # class StageCall: # def __init__(self, stage): # self.stage = stage # self.team_calls = [] # def add_team(self, team_call): # self.team_calls.append(team_call) class TeamCall: def __init__(self, names, date, weight, stage, image): self.names = [] self.names = names self.date = date self.weight = weight self.stage = stage self.image = image # class Set(models.Model): # class Game(models.Model): # set = models.ForeignKey(Set, on_delete=models.CASCADE) # format = models.IntegerField() # class Point(models.Model): # game = models.ForeignKey(Game, on_delete=models.CASCADE) # action = models.IntegerField() # date = models.DateField() # team_id = models.IntegerField()