bracket-feature
laurent 1 year ago
commit 03910e6d61
  1. 6
      api/serializers.py
  2. 1
      api/urls.py
  3. 15
      api/views.py
  4. 7
      tournaments/admin.py
  5. 26
      tournaments/migrations/0091_drawlog.py
  6. 18
      tournaments/migrations/0092_club_timezone.py
  7. 7
      tournaments/models/club.py
  8. 10
      tournaments/models/draw_log.py
  9. 41
      tournaments/models/match.py
  10. 83
      tournaments/models/tournament.py
  11. 2
      tournaments/static/misc/jap-test.csv
  12. 2
      tournaments/templates/tournaments/broadcast/broadcasted_match.html
  13. 4
      tournaments/templates/tournaments/match_cell.html
  14. 2
      tournaments/templates/tournaments/summon_row.html
  15. 3
      tournaments/templates/tournaments/tournament_info.html
  16. 13
      tournaments/views.py

@ -12,6 +12,7 @@ from django.contrib.sites.shortcuts import get_current_site
from api.tokens import account_activation_token from api.tokens import account_activation_token
from shared.cryptography import encryption_util from shared.cryptography import encryption_util
from tournaments.models.draw_log import DrawLog
class EncryptedUserField(serializers.Field): class EncryptedUserField(serializers.Field):
def to_representation(self, value): def to_representation(self, value):
@ -230,3 +231,8 @@ class DeviceTokenSerializer(serializers.ModelSerializer):
model = DeviceToken model = DeviceToken
fields = '__all__' fields = '__all__'
read_only_fields = ['user'] read_only_fields = ['user']
class DrawLogSerializer(serializers.ModelSerializer):
class Meta:
model = DrawLog
fields = '__all__'

@ -18,6 +18,7 @@ router.register(r'player-registrations', views.PlayerRegistrationViewSet)
router.register(r'purchases', views.PurchaseViewSet) router.register(r'purchases', views.PurchaseViewSet)
router.register(r'courts', views.CourtViewSet) router.register(r'courts', views.CourtViewSet)
router.register(r'date-intervals', views.DateIntervalViewSet) router.register(r'date-intervals', views.DateIntervalViewSet)
router.register(r'draw-logs', views.DrawLogViewSet)
router.register(r'failed-api-calls', views.FailedApiCallViewSet) router.register(r'failed-api-calls', views.FailedApiCallViewSet)
router.register(r'logs', views.LogViewSet) router.register(r'logs', views.LogViewSet)
router.register(r'device-token', views.DeviceTokenViewSet) router.register(r'device-token', views.DeviceTokenViewSet)

@ -1,5 +1,6 @@
from pandas.io.feather_format import pd from pandas.io.feather_format import pd
from .serializers import ClubSerializer, CourtSerializer, DateIntervalSerializer, TournamentSerializer, UserSerializer, ChangePasswordSerializer, EventSerializer, RoundSerializer, GroupStageSerializer, MatchSerializer, TeamScoreSerializer, TeamRegistrationSerializer, PlayerRegistrationSerializer, LiveMatchSerializer, PurchaseSerializer, UserUpdateSerializer, FailedApiCallSerializer, LogSerializer, DeviceTokenSerializer from tournaments.models.draw_log import DrawLog
from .serializers import ClubSerializer, CourtSerializer, DateIntervalSerializer, DrawLogSerializer, TournamentSerializer, UserSerializer, ChangePasswordSerializer, EventSerializer, RoundSerializer, GroupStageSerializer, MatchSerializer, TeamScoreSerializer, TeamRegistrationSerializer, PlayerRegistrationSerializer, LiveMatchSerializer, PurchaseSerializer, UserUpdateSerializer, FailedApiCallSerializer, LogSerializer, DeviceTokenSerializer
from tournaments.models import Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Court, DateInterval, Purchase, FailedApiCall, Log, DeviceToken from tournaments.models import Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Court, DateInterval, Purchase, FailedApiCall, Log, DeviceToken
from rest_framework import viewsets, permissions from rest_framework import viewsets, permissions
@ -288,3 +289,15 @@ class DeviceTokenViewSet(viewsets.ModelViewSet):
def perform_create(self, serializer): def perform_create(self, serializer):
serializer.save(user=self.request.user) serializer.save(user=self.request.user)
class DrawLogViewSet(viewsets.ModelViewSet):
queryset = DrawLog.objects.all()
serializer_class = DrawLogSerializer
def get_queryset(self):
tournament_id = self.request.query_params.get('tournament')
if tournament_id:
return self.queryset.filter(tournament=tournament_id)
if self.request.user:
return self.queryset.filter(tournament__event__creator=self.request.user)
return []

@ -2,6 +2,7 @@ from django.contrib import admin
from tournaments.models import team_registration from tournaments.models import team_registration
from tournaments.models.device_token import DeviceToken from tournaments.models.device_token import DeviceToken
from tournaments.models.draw_log import DrawLog
from .models import Club, TeamScore, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamRegistration, PlayerRegistration, Purchase, Court, DateInterval, FailedApiCall, Log from .models import Club, TeamScore, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamRegistration, PlayerRegistration, Purchase, Court, DateInterval, FailedApiCall, Log
from django.contrib.auth.admin import UserAdmin from django.contrib.auth.admin import UserAdmin
@ -105,6 +106,11 @@ class LogAdmin(admin.ModelAdmin):
class DeviceTokenAdmin(admin.ModelAdmin): class DeviceTokenAdmin(admin.ModelAdmin):
list_display = ['user', 'value'] list_display = ['user', 'value']
class DrawLogAdmin(admin.ModelAdmin):
list_display = ['tournament', 'draw_date', 'draw_seed', 'draw_match_index', 'draw_team_position']
list_filter = [SimpleTournamentListFilter]
ordering = ['draw_date']
admin.site.register(CustomUser, CustomUserAdmin) admin.site.register(CustomUser, CustomUserAdmin)
admin.site.register(Club, ClubAdmin) admin.site.register(Club, ClubAdmin)
admin.site.register(Event, EventAdmin) admin.site.register(Event, EventAdmin)
@ -121,3 +127,4 @@ admin.site.register(DateInterval, DateIntervalAdmin)
admin.site.register(FailedApiCall, FailedApiCallAdmin) admin.site.register(FailedApiCall, FailedApiCallAdmin)
admin.site.register(Log, LogAdmin) admin.site.register(Log, LogAdmin)
admin.site.register(DeviceToken, DeviceTokenAdmin) admin.site.register(DeviceToken, DeviceTokenAdmin)
admin.site.register(DrawLog, DrawLogAdmin)

@ -0,0 +1,26 @@
# Generated by Django 4.2.11 on 2024-10-24 06:55
from django.db import migrations, models
import django.db.models.deletion
import uuid
class Migration(migrations.Migration):
dependencies = [
('tournaments', '0090_tournament_initial_seed_count_and_more'),
]
operations = [
migrations.CreateModel(
name='DrawLog',
fields=[
('id', models.UUIDField(default=uuid.uuid4, primary_key=True, serialize=False)),
('draw_date', models.DateTimeField()),
('draw_seed', models.IntegerField()),
('draw_match_index', models.IntegerField()),
('draw_team_position', models.IntegerField()),
('tournament', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='tournaments.tournament')),
],
),
]

File diff suppressed because one or more lines are too long

@ -1,4 +1,5 @@
from django.db import models from django.db import models
from zoneinfo import available_timezones
import uuid import uuid
class Club(models.Model): class Club(models.Model):
@ -15,7 +16,11 @@ class Club(models.Model):
zip_code = models.CharField(max_length=10, null=True, blank=True) zip_code = models.CharField(max_length=10, null=True, blank=True)
latitude = models.FloatField(null=True, blank=True) latitude = models.FloatField(null=True, blank=True)
longitude = models.FloatField(null=True, blank=True) longitude = models.FloatField(null=True, blank=True)
timezone = models.CharField(
max_length=50, null=True, blank=True,
choices=[(tz, tz) for tz in sorted(available_timezones())],
default='CET'
)
court_count = models.IntegerField(default=2) court_count = models.IntegerField(default=2)
broadcast_code = models.CharField(max_length=10, null=True, blank=True, unique=True) broadcast_code = models.CharField(max_length=10, null=True, blank=True, unique=True)

@ -0,0 +1,10 @@
from django.db import models
import uuid
class DrawLog(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=True)
tournament = models.ForeignKey('Tournament', on_delete=models.CASCADE)
draw_date = models.DateTimeField()
draw_seed = models.IntegerField()
draw_match_index = models.IntegerField()
draw_team_position = models.IntegerField()

@ -2,7 +2,8 @@ from django.db import models
from tournaments.models import group_stage from tournaments.models import group_stage
from . import Round, GroupStage, FederalMatchCategory from . import Round, GroupStage, FederalMatchCategory
from django.utils import timezone, formats from django.utils import timezone, formats
from datetime import timedelta from datetime import datetime, timedelta
import uuid import uuid
from ..utils.extensions import format_seconds from ..utils.extensions import format_seconds
@ -41,6 +42,8 @@ class Match(models.Model):
if self.tournament().event: if self.tournament().event:
club = self.tournament().event.club club = self.tournament().event.club
if self.confirmed is False:
return ""
if club: if club:
return club.court_name(index) return club.court_name(index)
elif index is not None: elif index is not None:
@ -78,14 +81,16 @@ class Match(models.Model):
def player_names(self): def player_names(self):
return map(lambda ts: ts.player_names(), self.team_scores.all()) return map(lambda ts: ts.player_names(), self.team_scores.all())
def local_start_date(self):
timezone = self.tournament().timezone()
return self.start_date.astimezone(timezone)
def formatted_start_date(self): def formatted_start_date(self):
if self.start_date: if self.start_date:
timezoned_datetime = timezone.localtime(self.start_date) local_start = self.local_start_date()
return formats.date_format(timezoned_datetime, format='H:i') return formats.date_format(local_start, format='H:i')
# return formats.date_format(self.start_date, format='H:i')
else: else:
return '' return ''
# return str(self.start_date) #.strftime("%H:%M")
def time_indication(self): def time_indication(self):
if self.end_date: if self.end_date:
@ -95,10 +100,18 @@ class Match(models.Model):
return '' return ''
elif self.start_date: elif self.start_date:
if self.started(): if self.started():
return self.formatted_duration() if self.confirmed:
return self.formatted_duration()
else:
return 'À suivre'
else: else:
timezoned_datetime = timezone.localtime(self.start_date) # timezoned_datetime = timezone.localtime(self.start_date)
return formats.date_format(timezoned_datetime, format='l H:i') timezone = self.tournament().timezone()
local_start = self.start_date.astimezone(timezone)
if self.confirmed:
return formats.date_format(local_start, format='l H:i')
else:
return f"Estimée : {formats.date_format(local_start, format='l H:i')}"
else: else:
return 'À venir...' return 'À venir...'
@ -185,14 +198,14 @@ class Match(models.Model):
def live_match(self): def live_match(self):
title = self.name if self.name else self.backup_name() title = self.name if self.name else self.backup_name()
date = self.formatted_start_date() date = self.formatted_start_date()
duration = self.time_indication() time_indication = self.time_indication()
court = self.court_name(self.court_index) court = self.court_name(self.court_index)
group_stage_name = None group_stage_name = None
if self.group_stage: if self.group_stage:
group_stage_name = self.group_stage.display_name() group_stage_name = self.group_stage.display_name()
ended = self.end_date is not None ended = self.end_date is not None
livematch = LiveMatch(title, date, duration, court, self.started(), ended, group_stage_name) livematch = LiveMatch(title, date, time_indication, court, self.started(), ended, group_stage_name)
for team_score in self.sorted_team_scores(): for team_score in self.sorted_team_scores():
if team_score.team_registration: if team_score.team_registration:
@ -254,11 +267,11 @@ class Team:
} }
class LiveMatch: class LiveMatch:
def __init__(self, title, date, duration, court, started, ended, group_stage_name): def __init__(self, title, date, time_indication, court, started, ended, group_stage_name):
self.title = title self.title = title
self.date = date self.date = date
self.teams = [] self.teams = []
self.duration = duration self.time_indication = time_indication
self.court = court self.court = court
self.started = started self.started = started
self.ended = ended self.ended = ended
@ -275,7 +288,7 @@ class LiveMatch:
"title": self.title, "title": self.title,
"date": self.date, "date": self.date,
"teams": [team.to_dict() for team in self.teams], "teams": [team.to_dict() for team in self.teams],
"duration": self.duration, "time_indication": self.time_indication,
"court": self.court, "court": self.court,
"started": self.started, "started": self.started,
"ended": self.ended, "ended": self.ended,
@ -283,7 +296,7 @@ class LiveMatch:
"group_stage_name": self.group_stage_name, "group_stage_name": self.group_stage_name,
} }
def show_duration(self): def show_time_indication(self):
for team in self.teams: for team in self.teams:
if team.walk_out and len(team.scores) == 0: if team.walk_out and len(team.scores) == 0:
return False return False

@ -1,3 +1,4 @@
from zoneinfo import ZoneInfo
from django.db import models from django.db import models
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
if TYPE_CHECKING: if TYPE_CHECKING:
@ -7,6 +8,8 @@ from . import Event, TournamentPayment, FederalMatchCategory, FederalCategory, F
import uuid import uuid
from django.utils import timezone, formats from django.utils import timezone, formats
from datetime import datetime, timedelta from datetime import datetime, timedelta
from zoneinfo import ZoneInfo
from shared.cryptography import encryption_util from shared.cryptography import encryption_util
from ..utils.extensions import plural_format from ..utils.extensions import plural_format
@ -129,6 +132,19 @@ class Tournament(models.Model):
components.append(self.name) components.append(self.name)
return (' ').join(components) return (' ').join(components)
def timezone(self):
tz = 'CET'
if self.event and self.event.club:
tz = self.event.club.timezone
return ZoneInfo(tz)
def local_start_date(self):
timezone = self.timezone()
return self.start_date.astimezone(timezone)
def local_start_date_formatted(self):
return formats.date_format(self.local_start_date(), format='j F Y H:i')
def level(self): def level(self):
if self.federal_level_category == 0: if self.federal_level_category == 0:
return "Anim." return "Anim."
@ -216,6 +232,7 @@ class Tournament(models.Model):
def team_summons(self): def team_summons(self):
summons = [] summons = []
print('>>> team_summons')
if self.supposedly_in_progress() and self.end_date is None: if self.supposedly_in_progress() and self.end_date is None:
for team in self.teams(False): for team in self.teams(False):
names = team.names names = team.names
@ -231,7 +248,7 @@ class Tournament(models.Model):
names = team_registration.team_names() names = team_registration.team_names()
stage = next_match.summon_stage_name() stage = next_match.summon_stage_name()
weight = team_registration.weight weight = team_registration.weight
summon = TeamSummon(names, next_match.start_date, weight, stage, next_match.court_name(next_match.court_index), team_registration.logo) summon = TeamSummon(names, next_match.local_start_date(), weight, stage, next_match.court_name(next_match.court_index), team_registration.logo)
summons.append(summon) summons.append(summon)
summons.sort(key=lambda s: (s.date is None, s.date or datetime.min)) summons.sort(key=lambda s: (s.date is None, s.date or datetime.min))
@ -259,7 +276,7 @@ class Tournament(models.Model):
return rankings return rankings
def teams(self, includeWaitingList): def teams(self, includeWaitingList):
print("Starting teams method") # print("Starting teams method")
bracket_teams = [] bracket_teams = []
group_stage_teams = [] group_stage_teams = []
waiting_teams = [] waiting_teams = []
@ -268,10 +285,10 @@ class Tournament(models.Model):
wildcard_group_stage = [] wildcard_group_stage = []
complete_teams = [] complete_teams = []
closed_registration_date = self.closed_registration_date closed_registration_date = self.closed_registration_date
print(f"Closed registration date: {closed_registration_date}") # print(f"Closed registration date: {closed_registration_date}")
for team_registration in self.teamregistration_set.all(): for team_registration in self.teamregistration_set.all():
print(f"Processing team registration: {team_registration}") # print(f"Processing team registration: {team_registration}")
is_valid = False is_valid = False
if closed_registration_date is not None and team_registration.registration_date is not None and team_registration.registration_date <= closed_registration_date: if closed_registration_date is not None and team_registration.registration_date is not None and team_registration.registration_date <= closed_registration_date:
is_valid = True is_valid = True
@ -279,7 +296,7 @@ class Tournament(models.Model):
is_valid = True is_valid = True
if team_registration.registration_date is None: if team_registration.registration_date is None:
is_valid = True is_valid = True
print(f"Is valid: {is_valid}") # print(f"Is valid: {is_valid}")
if team_registration.walk_out is False: if team_registration.walk_out is False:
names = team_registration.team_names() names = team_registration.team_names()
@ -287,14 +304,14 @@ class Tournament(models.Model):
initial_weight = team_registration.initial_weight() initial_weight = team_registration.initial_weight()
date = team_registration.call_date date = team_registration.call_date
team = TeamList(names, weight, date, initial_weight, team_registration.wild_card_bracket, team_registration.wild_card_group_stage, team_registration.logo) team = TeamList(names, weight, date, initial_weight, team_registration.wild_card_bracket, team_registration.wild_card_group_stage, team_registration.logo)
print(f"Created team: {team}") # print(f"Created team: {team}")
if team_registration.group_stage_position is not None: if team_registration.group_stage_position is not None:
team.set_stage("Poule") team.set_stage("Poule")
elif team_registration.bracket_position is not None: elif team_registration.bracket_position is not None:
team.set_stage("Tableau") team.set_stage("Tableau")
else: else:
team.set_stage("Attente") team.set_stage("Attente")
print(f"Team stage: {team.stage}") # print(f"Team stage: {team.stage}")
teams.append(team) teams.append(team)
if team_registration.wild_card_bracket: if team_registration.wild_card_bracket:
@ -306,11 +323,11 @@ class Tournament(models.Model):
else: else:
waiting_teams.append(team) waiting_teams.append(team)
print(f"Total teams: {len(teams)}") # print(f"Total teams: {len(teams)}")
print(f"Wildcard bracket: {len(wildcard_bracket)}") # print(f"Wildcard bracket: {len(wildcard_bracket)}")
print(f"Wildcard group stage: {len(wildcard_group_stage)}") # print(f"Wildcard group stage: {len(wildcard_group_stage)}")
print(f"Complete teams: {len(complete_teams)}") # print(f"Complete teams: {len(complete_teams)}")
print(f"Waiting teams: {len(waiting_teams)}") # print(f"Waiting teams: {len(waiting_teams)}")
if len(teams) < self.team_count: if len(teams) < self.team_count:
teams.sort(key=lambda s: (s.initial_weight, s.date)) teams.sort(key=lambda s: (s.initial_weight, s.date))
@ -323,8 +340,8 @@ class Tournament(models.Model):
group_stage_members_count = 0 group_stage_members_count = 0
if seeds_count < 0: if seeds_count < 0:
seeds_count = 0 seeds_count = 0
print(f"Seeds count: {seeds_count}") # print(f"Seeds count: {seeds_count}")
print(f"Group stage members count: {group_stage_members_count}") # print(f"Group stage members count: {group_stage_members_count}")
if self.team_sorting == TeamSortingType.INSCRIPTION_DATE: if self.team_sorting == TeamSortingType.INSCRIPTION_DATE:
complete_teams.sort(key=lambda s: (s.date is None, s.date or datetime.min, s.initial_weight)) complete_teams.sort(key=lambda s: (s.date is None, s.date or datetime.min, s.initial_weight))
@ -333,25 +350,25 @@ class Tournament(models.Model):
selected_teams = complete_teams[:self.team_count] selected_teams = complete_teams[:self.team_count]
selected_teams.sort(key=lambda s: s.initial_weight) selected_teams.sort(key=lambda s: s.initial_weight)
print(f"Selected teams: {len(selected_teams)}") # print(f"Selected teams: {len(selected_teams)}")
if seeds_count > 0: if seeds_count > 0:
bracket_teams = selected_teams[:seeds_count] + wildcard_bracket bracket_teams = selected_teams[:seeds_count] + wildcard_bracket
else: else:
bracket_teams = [] bracket_teams = []
print(f"Bracket teams: {len(bracket_teams)}") # print(f"Bracket teams: {len(bracket_teams)}")
if group_stage_members_count: if group_stage_members_count:
group_stage_end = seeds_count + group_stage_members_count group_stage_end = seeds_count + group_stage_members_count
group_stage_teams = selected_teams[seeds_count:group_stage_end] + wildcard_group_stage group_stage_teams = selected_teams[seeds_count:group_stage_end] + wildcard_group_stage
else: else:
group_stage_teams = [] group_stage_teams = []
print(f"Group stage teams: {len(group_stage_teams)}") # print(f"Group stage teams: {len(group_stage_teams)}")
waiting_list_count = len(teams) - self.team_count waiting_list_count = len(teams) - self.team_count
if waiting_list_count < 0: if waiting_list_count < 0:
waiting_list_count = 0 waiting_list_count = 0
print(f"Waiting list count: {waiting_list_count}") # print(f"Waiting list count: {waiting_list_count}")
if waiting_list_count > 0 or len(waiting_teams) > 0: if waiting_list_count > 0 or len(waiting_teams) > 0:
if waiting_list_count > 0: if waiting_list_count > 0:
@ -362,7 +379,7 @@ class Tournament(models.Model):
waiting_teams.sort(key=lambda s: (s.initial_weight, s.date)) waiting_teams.sort(key=lambda s: (s.initial_weight, s.date))
else: else:
waiting_teams = [] waiting_teams = []
print(f"Final waiting teams: {len(waiting_teams)}") # print(f"Final waiting teams: {len(waiting_teams)}")
bracket_teams.sort(key=lambda s: s.weight) bracket_teams.sort(key=lambda s: s.weight)
group_stage_teams.sort(key=lambda s: s.weight) group_stage_teams.sort(key=lambda s: s.weight)
@ -380,10 +397,10 @@ class Tournament(models.Model):
if includeWaitingList is True: if includeWaitingList is True:
final_teams = bracket_teams + group_stage_teams + waiting_teams final_teams = bracket_teams + group_stage_teams + waiting_teams
print(f"Final teams with waiting list: {len(final_teams)}") # print(f"Final teams with waiting list: {len(final_teams)}")
else: else:
final_teams = bracket_teams + group_stage_teams final_teams = bracket_teams + group_stage_teams
print(f"Final teams without waiting list: {len(final_teams)}") # print(f"Final teams without waiting list: {len(final_teams)}")
return final_teams return final_teams
@ -791,8 +808,23 @@ class Tournament(models.Model):
return date.replace(hour=8, minute=0, second=0, microsecond=0, tzinfo=date.tzinfo) return date.replace(hour=8, minute=0, second=0, microsecond=0, tzinfo=date.tzinfo)
def supposedly_in_progress(self): def supposedly_in_progress(self):
end = self.start_date + timedelta(days=self.day_duration + 1) # end = self.start_date + timedelta(days=self.day_duration + 1)
return self.start_date.replace(hour=0, minute=0) <= timezone.now() <= end # return self.start_date.replace(hour=0, minute=0) <= timezone.now() <= end
timezoned_datetime = timezone.localtime(self.start_date)
end = timezoned_datetime + timedelta(days=self.day_duration + 1)
now = timezone.now()
start = timezoned_datetime.replace(hour=0, minute=0)
print(f"timezoned_datetime: {timezoned_datetime}")
print(f"tournament end date: {end}")
print(f"current time: {now}")
print(f"tournament start: {start}")
print(f"start <= now <= end: {start <= now <= end}")
return start <= now <= end
def display_points_earned(self): def display_points_earned(self):
return self.federal_level_category != FederalLevelCategory.UNLISTED and self.hide_points_earned is False return self.federal_level_category != FederalLevelCategory.UNLISTED and self.hide_points_earned is False
@ -840,10 +872,9 @@ class TeamSummon:
def formatted_date(self): def formatted_date(self):
if self.date: if self.date:
timezoned_datetime = timezone.localtime(self.date) return formats.date_format(self.date, format='l H:i')
return formats.date_format(timezoned_datetime, format='l H:i')
else: else:
return None return ''
def to_dict(self): def to_dict(self):
return { return {

@ -1,3 +1 @@
CAN PADEL,POPOVITCH,Laurent,laurent@padelclub.app,0629445485 CAN PADEL,POPOVITCH,Laurent,laurent@padelclub.app,0629445485
CAN PADEL,POPOVITCH,Razmig,razmig@padelclub.app,0629445485
CAN PADEL,POPOVITCH,Xavier,xavier@padelclub.app,0629445485

1 CAN PADEL POPOVITCH Laurent laurent@padelclub.app 0629445485
CAN PADEL POPOVITCH Razmig razmig@padelclub.app 0629445485
CAN PADEL POPOVITCH Xavier xavier@padelclub.app 0629445485

@ -51,7 +51,7 @@
</template> </template>
<div class="top-margin flex-row"> <div class="top-margin flex-row">
<label class="left-label minor-info bold"><span x-text="match.duration"></span></label> <label class="left-label minor-info bold"><span x-text="match.time_indication"></span></label>
<label class="right-label minor-info semibold"><span x-text="match.court"></span></label> <label class="right-label minor-info semibold"><span x-text="match.court"></span></label>
</div> </div>

@ -42,8 +42,8 @@
<div class="flex-row top-margin"> <div class="flex-row top-margin">
<label class="left-label minor-info bold"> <label class="left-label minor-info bold">
{% if match.show_duration %} {% if match.show_time_indication %}
{{ match.duration }} {{ match.time_indication }}
{% endif %} {% endif %}
</label> </label>
<label class="right-label minor-info"> <label class="right-label minor-info">

@ -9,7 +9,7 @@
</div> </div>
<div class="table-cell left"> <div class="table-cell left">
<div class="table-cell large">{{ summon.date|date:'l H:i' }}</div> <div class="table-cell large">{{ summon.formatted_date }}</div>
<div class="table-cell">{{ summon.court }}</div> <div class="table-cell">{{ summon.court }}</div>
</div> </div>
<div class="table-cell right"><div class="mybox center">{{ summon.stage }}</div></div> <div class="table-cell right"><div class="mybox center">{{ summon.stage }}</div></div>

@ -7,6 +7,7 @@
{% block content %} {% block content %}
{% load static %} {% load static %}
{% load tz %}
{% include 'tournaments/navigation_tournament.html' %} {% include 'tournaments/navigation_tournament.html' %}
@ -17,7 +18,7 @@
<div class="bubble"> <div class="bubble">
<p> <p>
<div class="semibold">{{ tournament.start_date }}</div> <div class="semibold">{{ tournament.local_start_date_formatted }}</div>
<div>{{ tournament.day_duration_formatted }}</div> <div>{{ tournament.day_duration_formatted }}</div>
<div>{{ tournament.court_count }} terrains</div> <div>{{ tournament.court_count }} terrains</div>
</p> </p>

@ -79,8 +79,8 @@ def live_tournaments(club_id):
return [t for t in tournaments if t.display_tournament() and t.supposedly_in_progress()] return [t for t in tournaments if t.display_tournament() and t.supposedly_in_progress()]
def future_tournaments(club_id): def future_tournaments(club_id):
tomorrow = date.today() + timedelta(days=1) tomorrow = datetime.now().date() + timedelta(days=1)
tournaments = tournaments_query(Q(end_date__isnull=True, start_date__gt=tomorrow), club_id, True) tournaments = tournaments_query(Q(end_date__isnull=True, start_date__gte=tomorrow), club_id, True)
return [t for t in tournaments if t.display_tournament()] return [t for t in tournaments if t.display_tournament()]
def tournament_info(request, tournament_id): def tournament_info(request, tournament_id):
@ -147,13 +147,8 @@ def tournament(request, tournament_id):
rounds = list(tournament.round_set.filter(group_stage_loser_bracket=True)) rounds = list(tournament.round_set.filter(group_stage_loser_bracket=True))
rounds.extend(bracket_rounds) rounds.extend(bracket_rounds)
#group_stages = tournament.groupstage_set.order_by('index')
group_stages = sorted(tournament.get_computed_group_stage(), key=lambda s: (s.step, s.index)) group_stages = sorted(tournament.get_computed_group_stage(), key=lambda s: (s.step, s.index))
#print(len(match_groups))
#print(len(rounds))
#print(len(group_stages))
if tournament.display_matches() or tournament.display_group_stages(): if tournament.display_matches() or tournament.display_group_stages():
return render(request, 'tournaments/matches.html', { return render(request, 'tournaments/matches.html', {
'tournament': tournament, 'tournament': tournament,
@ -430,7 +425,7 @@ def simple_form_view(request):
return HttpResponse(f"Hello, {name}!") # Simple response with name return HttpResponse(f"Hello, {name}!") # Simple response with name
else: else:
form = SimpleForm() form = SimpleForm()
print(request.method) # print(request.method)
# If this is a GET request, we display an empty form # If this is a GET request, we display an empty form
return render(request, 'tournaments/admin/mail_test.html', {'form': form}) return render(request, 'tournaments/admin/mail_test.html', {'form': form})
@ -484,7 +479,7 @@ def send_email(mail, name):
name = "" name = ""
subject = "Tes tournois en toute simplicité avec Padel Club" subject = "Tes tournois en toute simplicité avec Padel Club"
body = f"Salut {name} !\n\nJe me permets de t'écrire car je suis JAP2 en région PACA et développeur, et je viens de lancer Padel Club, une app iOS qui facilite enfin l'organisation des tournois. Avec elle, tu peux convoquer rapidement, simuler et programmer tes structures, diffuser tous les résultats à tous les joueurs, et ce depuis un iPhone.\n\nTu peux l'essayer gratuitement pour découvrir tout son potentiel ! Télécharge l'app ici et teste la dès ton prochain tournoi: https://padelclub.app/download/\n\nJe suis disponible pour échanger avec toi par mail ou téléphone au 06 81 59 81 93 et voir ce que tu en penses.\nÀ bientôt j'espère !\n\nRazmig" body = f"Salut {name} !\n\nJe me permets de t'écrire car je suis JAP2 en région PACA et développeur, et je viens de lancer Padel Club, une app iOS qui facilite enfin l'organisation des tournois.\n\nAvec elle, tu peux convoquer rapidement, simuler et programmer tes structures, diffuser tous les résultats à tous les joueurs, et ce depuis un iPhone.\n\nTu peux l'essayer gratuitement pour découvrir tout son potentiel ! Télécharge l'app ici et teste la dès ton prochain tournoi: https://padelclub.app/download/\n\nJe suis disponible pour échanger avec toi par mail ou téléphone au 06 81 59 81 93 et voir ce que tu en penses.\nÀ bientôt j'espère !\n\nRazmig"
email = EmailMessage(subject, body, to=[mail]) email = EmailMessage(subject, body, to=[mail])
email.send() email.send()

Loading…
Cancel
Save