parent
de3417b0d9
commit
affaded5be
@ -1,441 +0,0 @@ |
||||
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, json |
||||
from django.utils import timezone |
||||
|
||||
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.DateTimeField() |
||||
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) |
||||
creator = models.ForeignKey(CustomUser, blank=True, null=True, on_delete=models.CASCADE) |
||||
name = models.CharField(max_length=200, null=True, blank=True) |
||||
start_date = models.DateTimeField() |
||||
end_date = models.DateTimeField(null=True, blank=True) |
||||
creation_date = models.DateTimeField() |
||||
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.DateTimeField(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.DateTimeField(null=True, blank=True) |
||||
group_stage_additional_qualified = models.IntegerField(default=0) |
||||
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.DateTimeField(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(): |
||||
call_date = team_registration.call_date |
||||
if call_date: |
||||
names = team_registration.team_names() |
||||
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 |
||||
|
||||
def live_matches(self): |
||||
matches = [] |
||||
for group_stage in self.groupstage_set.all(): |
||||
for match in group_stage.match_set.all(): |
||||
matches.append(match) |
||||
for round in self.round_set.all(): |
||||
for match in round.match_set.all(): |
||||
matches.append(match) |
||||
|
||||
# matches = [m for m in matches if m.broadcasted==True] |
||||
|
||||
print(len(matches)) |
||||
|
||||
return map(lambda match: match.live_match(), matches) |
||||
|
||||
# # Convert object attributes to a dictionary |
||||
# dict = self.__dict__ |
||||
# # Convert dictionary to JSON |
||||
# return json.dumps(dict) |
||||
|
||||
class Round(models.Model): |
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) |
||||
tournament = models.ForeignKey(Tournament, 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(Tournament, 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 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_scores = TeamScore.objects.filter(player_registrations=player_registration) |
||||
return map(lambda ts: ts.match, team_scores) |
||||
|
||||
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.DateTimeField(null=True, blank=True) |
||||
end_date = models.DateTimeField(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.CharField(max_length=50, 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.team_scores.all()) |
||||
|
||||
def formatted_start_date(self): |
||||
if self.start_date: |
||||
return self.start_date.strftime("%H:%M") |
||||
else: |
||||
return "no date" |
||||
# return str(self.start_date) #.strftime("%H:%M") |
||||
|
||||
def current_duration(self): |
||||
if self.end_date: |
||||
return (self.end_date - self.start_date).total_seconds() |
||||
else: |
||||
return (timezone.now() - self.start_date).total_seconds() |
||||
|
||||
def durationPrefix(self): |
||||
if self.current_duration() > 0: |
||||
return "Temps de jeu" |
||||
else: |
||||
return "Démarrage prévu dans" |
||||
|
||||
def formatted_duration(self): |
||||
|
||||
_seconds = self.current_duration() |
||||
|
||||
if _seconds > 0: |
||||
_hours = int(_seconds / 3600) |
||||
_minutes = int((_seconds % 3600) / 60) |
||||
return f"{_hours:02d}h{_minutes:02d}min" |
||||
else : |
||||
_seconds = _seconds * -1 |
||||
_hours = int(_seconds / 3600) |
||||
_minutes = int((_seconds % 3600) / 60) |
||||
return f"{_hours:02d}h{_minutes:02d}min" |
||||
|
||||
# def seconds(self): |
||||
# return (timezone.now() - self.start_date).total_seconds() |
||||
|
||||
def live_match(self): |
||||
title = f"Match {self.index}" |
||||
date = self.formatted_start_date() |
||||
duration = self.formatted_duration() |
||||
court = "" |
||||
if self.court: |
||||
court = f"Terrain {self.court}" |
||||
livematch = LiveMatch(title, date, duration, court) |
||||
|
||||
for team_score in self.team_scores.all(): |
||||
image = team_score.team_registration.logo |
||||
names = team_score.team_names() |
||||
scores = team_score.scores_array() |
||||
weight = team_score.team_registration.weight() |
||||
is_winner = team_score.team_registration == self.winning_team_id |
||||
team = Team(image, names, scores, weight, is_winner) |
||||
livematch.add_team(team) |
||||
|
||||
return livematch |
||||
|
||||
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.DateTimeField(null=True, blank=True) |
||||
call_date = models.DateTimeField(null=True, blank=True) |
||||
bracket_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.CharField(max_length=200, null=True, blank=True) #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_scores__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 TeamScore(models.Model): |
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) |
||||
match = models.ForeignKey(Match, on_delete=models.CASCADE, related_name="team_scores") |
||||
team_registration = models.ForeignKey(TeamRegistration, on_delete=models.CASCADE, null=True, blank=True) |
||||
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) |
||||
|
||||
def team_names(self): |
||||
names = [] |
||||
if self.team_registration.name: |
||||
names.append(self.team_registration.name) |
||||
else: |
||||
names = list(map(lambda player: player.name(), self.player_registrations.all())) |
||||
return names |
||||
|
||||
def scores_array(self): |
||||
return [int(x) for x in self.score.split(',')] |
||||
|
||||
class Team: |
||||
def __init__(self, image, names, scores, weight, is_winner): |
||||
self.image = image |
||||
self.names = names |
||||
self.scores = scores |
||||
self.weight = weight |
||||
self.is_winner = is_winner |
||||
|
||||
class LiveMatch: |
||||
def __init__(self, title, date, duration, court): |
||||
self.title = title |
||||
self.date = date |
||||
self.teams = [] |
||||
self.duration = duration |
||||
self.court = court |
||||
|
||||
def add_team(self, team): |
||||
self.teams.append(team) |
||||
|
||||
def toJSON(self): |
||||
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) |
||||
|
||||
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.DateTimeField() |
||||
# team_id = models.IntegerField() |
||||
@ -0,0 +1,11 @@ |
||||
from .club import Club |
||||
from .custom_user import CustomUser |
||||
from .enums import FederalCategory, FederalLevelCategory, FederalAgeCategory, FederalMatchCategory |
||||
from .event import Event |
||||
from .tournament import Tournament, TeamCall |
||||
from .group_stage import GroupStage |
||||
from .round import Round |
||||
from .match import Match, LiveMatch |
||||
from .team_registration import TeamRegistration |
||||
from .player_registration import PlayerRegistration |
||||
from .team_score import TeamScore |
||||
@ -0,0 +1,19 @@ |
||||
from django.db import models |
||||
import uuid |
||||
|
||||
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 |
||||
@ -0,0 +1,17 @@ |
||||
from django.db import models |
||||
from django.contrib.auth.models import AbstractUser |
||||
from . import Club |
||||
import uuid |
||||
|
||||
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 |
||||
@ -0,0 +1,37 @@ |
||||
from django.db import models |
||||
import uuid |
||||
|
||||
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' |
||||
@ -0,0 +1,18 @@ |
||||
from django.db import models |
||||
from . import Club, FederalMatchCategory |
||||
import uuid |
||||
|
||||
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.DateTimeField() |
||||
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 |
||||
@ -0,0 +1,23 @@ |
||||
from django.db import models |
||||
from . import Tournament, FederalMatchCategory |
||||
import uuid |
||||
|
||||
class GroupStage(models.Model): |
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) |
||||
tournament = models.ForeignKey(Tournament, 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 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_scores = TeamScore.objects.filter(player_registrations=player_registration) |
||||
return map(lambda ts: ts.match, team_scores) |
||||
@ -0,0 +1,109 @@ |
||||
from django.db import models |
||||
from . import Round, GroupStage, FederalMatchCategory |
||||
from django.utils import timezone |
||||
import uuid |
||||
|
||||
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.DateTimeField(null=True, blank=True) |
||||
end_date = models.DateTimeField(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.CharField(max_length=50, 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.team_scores.all()) |
||||
|
||||
def formatted_start_date(self): |
||||
if self.start_date: |
||||
return self.start_date.strftime("%H:%M") |
||||
else: |
||||
return "no date" |
||||
# return str(self.start_date) #.strftime("%H:%M") |
||||
|
||||
def current_duration(self): |
||||
if self.end_date: |
||||
return (self.end_date - self.start_date).total_seconds() |
||||
else: |
||||
return (timezone.now() - self.start_date).total_seconds() |
||||
|
||||
def durationPrefix(self): |
||||
if self.current_duration() > 0: |
||||
return "Temps de jeu" |
||||
else: |
||||
return "Démarrage prévu dans" |
||||
|
||||
def formatted_duration(self): |
||||
|
||||
_seconds = self.current_duration() |
||||
|
||||
if _seconds > 0: |
||||
_hours = int(_seconds / 3600) |
||||
_minutes = int((_seconds % 3600) / 60) |
||||
return f"{_hours:02d}h{_minutes:02d}min" |
||||
else : |
||||
_seconds = _seconds * -1 |
||||
_hours = int(_seconds / 3600) |
||||
_minutes = int((_seconds % 3600) / 60) |
||||
return f"{_hours:02d}h{_minutes:02d}min" |
||||
|
||||
# def seconds(self): |
||||
# return (timezone.now() - self.start_date).total_seconds() |
||||
|
||||
def live_match(self): |
||||
title = f"Match {self.index}" |
||||
date = self.formatted_start_date() |
||||
duration = self.formatted_duration() |
||||
court = "" |
||||
if self.court: |
||||
court = f"Terrain {self.court}" |
||||
livematch = LiveMatch(title, date, duration, court) |
||||
|
||||
for team_score in self.team_scores.all(): |
||||
image = team_score.team_registration.logo |
||||
names = team_score.team_names() |
||||
scores = team_score.scores_array() |
||||
weight = team_score.team_registration.weight() |
||||
is_winner = team_score.team_registration == self.winning_team_id |
||||
team = Team(image, names, scores, weight, is_winner) |
||||
livematch.add_team(team) |
||||
|
||||
return livematch |
||||
|
||||
class Team: |
||||
def __init__(self, image, names, scores, weight, is_winner): |
||||
self.image = image |
||||
self.names = names |
||||
self.scores = scores |
||||
self.weight = weight |
||||
self.is_winner = is_winner |
||||
|
||||
class LiveMatch: |
||||
def __init__(self, title, date, duration, court): |
||||
self.title = title |
||||
self.date = date |
||||
self.teams = [] |
||||
self.duration = duration |
||||
self.court = court |
||||
|
||||
def add_team(self, team): |
||||
self.teams.append(team) |
||||
|
||||
def toJSON(self): |
||||
return json.dumps(self, default=lambda o: o.__dict__, sort_keys=True, indent=4) |
||||
@ -0,0 +1,19 @@ |
||||
from django.db import models |
||||
from . import TeamRegistration |
||||
import uuid |
||||
|
||||
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}" |
||||
@ -0,0 +1,34 @@ |
||||
from django.db import models |
||||
from . import Tournament, FederalMatchCategory |
||||
import uuid |
||||
|
||||
class Round(models.Model): |
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) |
||||
tournament = models.ForeignKey(Tournament, 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" |
||||
else: |
||||
squared = 2 ** self.index |
||||
return f"{squared}ème" |
||||
@ -0,0 +1,57 @@ |
||||
from django.db import models |
||||
from . import Tournament, GroupStage |
||||
import uuid |
||||
|
||||
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.DateTimeField(null=True, blank=True) |
||||
call_date = models.DateTimeField(null=True, blank=True) |
||||
bracket_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.CharField(max_length=200, null=True, blank=True) #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 = map(lambda ts: ts.match, self.teamscore_set.all()) |
||||
matches = [m for m in matches if m.group_stage is None] |
||||
matches = sorted(matches, key=lambda m: m.round.index) |
||||
|
||||
# matches = self.teamscore_set |
||||
# matches = Match.objects.filter(group_stage__isnull=True, team_scores__player_registrations__id=self.id).order_by('round__index') |
||||
print(f"matches = {len(matches)}") |
||||
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 |
||||
@ -0,0 +1,30 @@ |
||||
from django.db import models |
||||
from . import Match, TeamRegistration, PlayerRegistration |
||||
import uuid |
||||
|
||||
class TeamScore(models.Model): |
||||
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) |
||||
match = models.ForeignKey(Match, on_delete=models.CASCADE, related_name="team_scores") |
||||
team_registration = models.ForeignKey(TeamRegistration, on_delete=models.CASCADE, null=True, blank=True) |
||||
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) |
||||
|
||||
def team_names(self): |
||||
names = [] |
||||
if self.team_registration.name: |
||||
names.append(self.team_registration.name) |
||||
else: |
||||
names = list(map(lambda player: player.name(), self.player_registrations.all())) |
||||
return names |
||||
|
||||
def scores_array(self): |
||||
return [int(x) for x in self.score.split(',')] |
||||
@ -0,0 +1,91 @@ |
||||
from django.db import models |
||||
from . import Event, CustomUser, FederalMatchCategory, FederalCategory, FederalLevelCategory, FederalAgeCategory |
||||
import uuid |
||||
|
||||
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) |
||||
creator = models.ForeignKey(CustomUser, blank=True, null=True, on_delete=models.CASCADE) |
||||
name = models.CharField(max_length=200, null=True, blank=True) |
||||
start_date = models.DateTimeField() |
||||
end_date = models.DateTimeField(null=True, blank=True) |
||||
creation_date = models.DateTimeField() |
||||
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.DateTimeField(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.DateTimeField(null=True, blank=True) |
||||
group_stage_additional_qualified = models.IntegerField(default=0) |
||||
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.DateTimeField(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(): |
||||
call_date = team_registration.call_date |
||||
if call_date: |
||||
names = team_registration.team_names() |
||||
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 |
||||
|
||||
def live_matches(self): |
||||
matches = [] |
||||
for group_stage in self.groupstage_set.all(): |
||||
for match in group_stage.match_set.all(): |
||||
matches.append(match) |
||||
for round in self.round_set.all(): |
||||
for match in round.match_set.all(): |
||||
matches.append(match) |
||||
|
||||
# matches = [m for m in matches if m.broadcasted==True] |
||||
|
||||
print(len(matches)) |
||||
|
||||
return map(lambda match: match.live_match(), matches) |
||||
|
||||
# # Convert object attributes to a dictionary |
||||
# dict = self.__dict__ |
||||
# # Convert dictionary to JSON |
||||
# return json.dumps(dict) |
||||
|
||||
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 |
||||
@ -0,0 +1,17 @@ |
||||
{% load static %} |
||||
|
||||
<div class="table-row-5-colums bottom-border"> |
||||
<div class="table-cell"> |
||||
<img class="team_image horizontal-margin" src="{% static 'tournaments/images/pc_icon_round_200.png' %}" /> |
||||
</div> |
||||
<!-- <img src="{% static 'tournaments/images/{{ team_call.image }}' %}" class="team_image horizontal-margin"> --> |
||||
<div class="table-cell table-cell-large tight"> |
||||
{% for name in team_call.names %} |
||||
<div>{{ name }}</div> |
||||
{% endfor %} |
||||
</div> |
||||
|
||||
<div class="table-cell">{{ team_call.weight }}</div> |
||||
<div class="table-cell large">{{ team_call.date|date:'H:i' }}</div> |
||||
<div class="table-cell"><div class="mybox center">{{ team_call.stage }}</div></div> |
||||
</div> |
||||
@ -1,11 +1,11 @@ |
||||
|
||||
<a href="{% url 'tournament-planning' tournament.id %}"> |
||||
<div class="table-container bottom-border vertical-padding"> |
||||
<a href="{% url 'tournament' tournament.id %}"> |
||||
<div class="table-row-3-colums bottom-border vertical-padding"> |
||||
<div class="tight table-cell"> |
||||
<div class="large">{{ tournament.level }}</div> |
||||
<div class="small">{{ tournament.category }}</div> |
||||
</div> |
||||
<div class="w100 horizontal-padding table-cell">{{ tournament.event.club.name }}</div> |
||||
<div class="table-cell table-cell-large horizontal-padding">{{ tournament.event.club.name }}</div> |
||||
<div class="table-cell"><div class="mybox">{{ tournament.formatted_start_date }}</div></div> |
||||
</div> |
||||
</a> |
||||
|
||||
Loading…
Reference in new issue