From 28161b1fbb4dae0d4ac6e549f9c050d7d47ce3bd Mon Sep 17 00:00:00 2001 From: Raz Date: Sat, 8 Mar 2025 08:55:47 +0100 Subject: [PATCH 1/4] fix online register --- tournaments/models/enums.py | 2 + tournaments/repositories.py | 13 ++++-- .../services/tournament_registration.py | 40 +++++++++++++------ .../services/tournament_unregistration.py | 2 +- .../templates/register_tournament.html | 24 ++++++++++- tournaments/utils/player_search.py | 4 +- tournaments/views.py | 4 +- 7 files changed, 66 insertions(+), 23 deletions(-) diff --git a/tournaments/models/enums.py b/tournaments/models/enums.py index c3f3be6..fa2c263 100644 --- a/tournaments/models/enums.py +++ b/tournaments/models/enums.py @@ -15,6 +15,8 @@ class FederalCategory(models.IntegerChoices): @staticmethod def female_in_male_assimilation_addition(rank: int) -> int: + if rank is None: + return 0 if 1 <= rank <= 10: return 400 elif 11 <= rank <= 30: diff --git a/tournaments/repositories.py b/tournaments/repositories.py index d33690f..cd394bd 100644 --- a/tournaments/repositories.py +++ b/tournaments/repositories.py @@ -23,7 +23,7 @@ class TournamentRegistrationRepository: is_captain = False player_licence_id = player_data['licence_id'] if player_licence_id and stripped_license: - if player_licence_id.startswith(stripped_license): + if stripped_license.lower() in player_licence_id.lower(): is_captain = True sex, rank, computed_rank = TournamentRegistrationRepository._compute_rank_and_sex( @@ -31,6 +31,7 @@ class TournamentRegistrationRepository: player_data ) + print("create_player_registrations", player_data.get('last_name'), sex, rank, computed_rank) data_source = None if player_data.get('found_in_french_federation', False) == True: data_source = PlayerDataSource.FRENCH_FEDERATION @@ -66,14 +67,18 @@ class TournamentRegistrationRepository: @staticmethod def _compute_rank_and_sex(tournament, player_data): is_woman = player_data.get('is_woman', False) - rank = player_data.get('rank', 0) - computed_rank = rank - sex = PlayerSexType.MALE + rank = player_data.get('rank', None) + if rank is None: + computed_rank = 100000 + else: + computed_rank = rank + sex = PlayerSexType.MALE if is_woman: sex = PlayerSexType.FEMALE if tournament.federal_category == FederalCategory.MEN: computed_rank = str(int(computed_rank) + FederalCategory.female_in_male_assimilation_addition(int(rank))) + print("_compute_rank_and_sex", sex, rank, computed_rank) return sex, rank, computed_rank diff --git a/tournaments/services/tournament_registration.py b/tournaments/services/tournament_registration.py index 90492ba..8f033f0 100644 --- a/tournaments/services/tournament_registration.py +++ b/tournaments/services/tournament_registration.py @@ -31,9 +31,18 @@ class TournamentRegistrationService: if 'add_player' in self.request.POST: self.handle_add_player() + if 'remove_player' in self.request.POST: + self.handle_remove_player() elif 'register_team' in self.request.POST: self.handle_team_registration() + def handle_remove_player(self): + team_registration = self.request.session.get('team_registration', []) + if team_registration: # Check if list is not empty + team_registration.pop() # Remove last element + self.request.session['team_registration'] = team_registration + self.context['current_players'] = team_registration + def handle_add_player(self): if not self.context['add_player_form'].is_valid(): return @@ -106,6 +115,7 @@ class TournamentRegistrationService: self.initialize_session_data() def add_player_to_session(self, player_data): + print("add_player_to_session", player_data) if not self.request.session.get('team_registration'): self.request.session['team_registration'] = [] @@ -216,6 +226,7 @@ class TournamentRegistrationService: return False def _handle_valid_names(self, player_data): + print("_handle_valid_names", player_data) if player_data.get('rank') is None: self._set_default_rank(player_data) @@ -224,18 +235,19 @@ class TournamentRegistrationService: self.context['add_player_form'].first_tournament = False def _handle_invalid_names(self, licence_id, player_data): - if not self.context['add_player_form'].first_tournament: - data, found = get_player_name_from_csv(self.tournament.federal_category, licence_id) - if found and data: - self._update_player_data_from_csv(player_data, data) - player_check = self._player_check(player_data) - if player_check == True: - self.add_player_to_session(player_data) - self.context['add_player_form'] = AddPlayerForm() - else: - return + data, found = get_player_name_from_csv(self.tournament.federal_category, licence_id) + print("_handle_invalid_names get_player_name_from_csv", data, found) + if found and data: + self._update_player_data_from_csv(player_data, data) + player_check = self._player_check(player_data) + if player_check == True: + self.add_player_to_session(player_data) + self.context['add_player_form'] = AddPlayerForm() else: - self._handle_first_tournament_case(data) + return + else: + print("_handle_first_tournament_case") + self._handle_first_tournament_case(data) def _set_default_rank(self, player_data): if self.request.session.get('last_rank') is None: @@ -245,7 +257,7 @@ class TournamentRegistrationService: self.request.session['is_woman'] = data['is_woman'] self.request.session.modified = True - player_data['rank'] = self.request.session.get('last_rank', 0) + player_data['rank'] = self.request.session.get('last_rank', None) player_data['is_woman'] = self.request.session.get('is_woman', False) def _update_user_license(self, licence_id): @@ -261,6 +273,7 @@ class TournamentRegistrationService: self.context['add_player_form'].first_tournament = False def _update_player_data_from_csv(self, player_data, csv_data): + print("_update_player_data_from_csv", player_data, csv_data) player_data.update({ 'first_name': csv_data['first_name'], 'last_name': csv_data['last_name'], @@ -278,6 +291,7 @@ class TournamentRegistrationService: }) def _handle_first_tournament_case(self, data): + print("_handle_first_tournament_case", data) if data: self.request.session['last_rank'] = data['rank'] self.request.session['is_woman'] = data['is_woman'] @@ -307,6 +321,6 @@ class TournamentRegistrationService: def _license_already_registered(self, stripped_license): return PlayerRegistration.objects.filter( team_registration__tournament=self.tournament, - licence_id__startswith=stripped_license, + licence_id__icontains=stripped_license, team_registration__walk_out=False ).exists() diff --git a/tournaments/services/tournament_unregistration.py b/tournaments/services/tournament_unregistration.py index cfad4c4..aa932e0 100644 --- a/tournaments/services/tournament_unregistration.py +++ b/tournaments/services/tournament_unregistration.py @@ -53,7 +53,7 @@ class TournamentUnregistrationService: def _find_player_registration(self): self.player_registration = PlayerRegistration.objects.filter( - licence_id__startswith=self.request.user.licence_id, + licence_id__icontains=self.request.user.licence_id, team_registration__tournament_id=self.tournament.id, ).first() diff --git a/tournaments/templates/register_tournament.html b/tournaments/templates/register_tournament.html index 5d5a262..0210214 100644 --- a/tournaments/templates/register_tournament.html +++ b/tournaments/templates/register_tournament.html @@ -23,7 +23,7 @@ {% if registration_successful %}

Merci, l'inscription a bien été envoyée au juge-arbitre.

- Un email de confirmation a été envoyé à {{ user.email }} pour confirmer votre inscription. Pensez à vérifier vos spams si vous ne recevez pas l'email. En cas de problème, contactez le juge-arbitre. + Un email de confirmation a été envoyé à l'adresse associée à votre compte Padel Club ({{ user.email }}). Pensez à vérifier vos spams si vous ne recevez pas l'email. En cas de problème, contactez le juge-arbitre.

{% else %}
@@ -48,7 +48,24 @@

{% endif %} @@ -73,6 +90,9 @@ {% endif %} {% if add_player_form.first_tournament or add_player_form.user_without_licence or tournament.license_is_required is False %} {% if not add_player_form.user_without_licence and tournament.license_is_required is True %} +
+ Padel Club n'a pas trouvé votre partenaire, il se peut qu'il s'agisse de son premier tournoi. Contacter le juge-arbitre après l'inscription si ce n'est pas le cas. +
Précisez les informations du joueur :
diff --git a/tournaments/utils/player_search.py b/tournaments/utils/player_search.py index 0f766ef..f8aeedd 100644 --- a/tournaments/utils/player_search.py +++ b/tournaments/utils/player_search.py @@ -9,7 +9,7 @@ from tournaments.models.enums import FederalCategory def clean_licence_id(licence_id): # This regex matches the trailing letters (non-digits) and removes them cleaned_licence_id = re.sub(r'\D+$', '', str(licence_id)) # \D+ matches non-digits at the end - return cleaned_licence_id + return cleaned_licence_id.lstrip("0") def get_player_name_from_csv(category, licence_id, base_folder=None): """ @@ -29,6 +29,8 @@ def get_player_name_from_csv(category, licence_id, base_folder=None): else: cleaned_licence_id = None + print("get_player_name_from_csv", cleaned_licence_id) + def extract_date(file_name): """ Extract the date (MM-YYYY) from the file name and return it as a datetime object. diff --git a/tournaments/views.py b/tournaments/views.py index 5eefc8c..1f4e67a 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -170,7 +170,7 @@ def tournament_info(request, tournament_id): stripped_license = validator.stripped_license # Check if there is a PlayerRegistration for this user in this tournament registered_user = PlayerRegistration.objects.filter( - licence_id__startswith=stripped_license, + licence_id__icontains=stripped_license, team_registration__tournament=tournament, team_registration__walk_out=False, ).first() @@ -747,7 +747,7 @@ def my_tournaments(request): def filter_user_tournaments(tournaments): return [t for t in tournaments if t.teamregistration_set.filter( - playerregistration__licence_id__startswith=stripped_license, + playerregistration__licence_id__icontains=stripped_license, walk_out=False ).exists()] From 530a60b0e1bd319aec92c96258460fdb03a7fa74 Mon Sep 17 00:00:00 2001 From: Raz Date: Sat, 8 Mar 2025 09:16:24 +0100 Subject: [PATCH 2/4] fix hide weight broadcast --- .../templates/tournaments/broadcast/broadcasted_auto.html | 1 + .../tournaments/broadcast/broadcasted_auto_event.html | 1 + .../tournaments/broadcast/broadcasted_group_stage.html | 6 +++--- .../tournaments/broadcast/broadcasted_group_stages.html | 1 + 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/tournaments/templates/tournaments/broadcast/broadcasted_auto.html b/tournaments/templates/tournaments/broadcast/broadcasted_auto.html index a20e5fb..39545ef 100644 --- a/tournaments/templates/tournaments/broadcast/broadcasted_auto.html +++ b/tournaments/templates/tournaments/broadcast/broadcasted_auto.html @@ -38,6 +38,7 @@ paginatedSummons: null, paginatedRankings: null, active: 1, + hide_weight: {{ tournament.hide_weight|lower }}, prefixTitle: '', retrieveData() { fetch('/tournament/{{ tournament.id }}/broadcast/json/') diff --git a/tournaments/templates/tournaments/broadcast/broadcasted_auto_event.html b/tournaments/templates/tournaments/broadcast/broadcasted_auto_event.html index 2d63558..61153e4 100644 --- a/tournaments/templates/tournaments/broadcast/broadcasted_auto_event.html +++ b/tournaments/templates/tournaments/broadcast/broadcasted_auto_event.html @@ -39,6 +39,7 @@ paginatedSummons: null, paginatedRankings: null, active: 1, + hide_weight: {{ tournament.hide_weight|lower }}, prefixTitle: '', eventTitle: '', title: '', diff --git a/tournaments/templates/tournaments/broadcast/broadcasted_group_stage.html b/tournaments/templates/tournaments/broadcast/broadcasted_group_stage.html index 8c21269..48d7c68 100644 --- a/tournaments/templates/tournaments/broadcast/broadcasted_group_stage.html +++ b/tournaments/templates/tournaments/broadcast/broadcasted_group_stage.html @@ -31,9 +31,9 @@
- {% if not tournament.hide_weight %} -
- {% endif %} +
+ +
diff --git a/tournaments/templates/tournaments/broadcast/broadcasted_group_stages.html b/tournaments/templates/tournaments/broadcast/broadcasted_group_stages.html index 69b7028..1d4171f 100644 --- a/tournaments/templates/tournaments/broadcast/broadcasted_group_stages.html +++ b/tournaments/templates/tournaments/broadcast/broadcasted_group_stages.html @@ -38,6 +38,7 @@ 16: + # if more than 16 groupstage matches + now = timezone.now() + future_threshold = now + timedelta(hours=1) + past_threshold = now - timedelta(hours=1) + matches = [m for m in matches if m.should_appear() and + (m.start_date is None or m.start_date <= future_threshold) and # Not starting in more than 1h + (m.end_date is None or m.end_date >= past_threshold)] # Not finished for more than 1h + matches = matches[:16] matches.sort(key=lambda m: (m.start_date is None, m.end_date is not None, m.start_date, m.index)) group_stage_loser_bracket = list(self.round_set.filter(parent=None, group_stage_loser_bracket=True).all()) diff --git a/tournaments/static/tournaments/css/broadcast.css b/tournaments/static/tournaments/css/broadcast.css index ffd1f78..5171712 100644 --- a/tournaments/static/tournaments/css/broadcast.css +++ b/tournaments/static/tournaments/css/broadcast.css @@ -25,3 +25,57 @@ body { .bold { font-family: "Montserrat-Bold"; } + +.player { + position: relative; + flex: 1; + display: flex; + flex-direction: column; + min-height: 2.8em; /* This ensures minimum height for 2 lines */ + justify-content: center; + overflow: hidden; +} + +/* Add this if you want empty lines to take up space */ +.player div { + min-height: 1.4em; /* Height for single line */ +} + +/* For single player teams */ +.player.single-player .bold { + max-height: 2.8em; /* Adjust based on your needs */ + line-height: 1.4em; + overflow: hidden; + position: relative; + text-overflow: ellipsis; +} + +/* For two player teams */ +.player.two-players .bold { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.flex { + display: flex; + align-items: center; +} + +.flex-left { + flex: 1; + text-align: left; + justify-content: center; + min-height: 4em; + padding-right: 5px; +} + +.flex-right { + flex: initial; + text-align: right; + justify-content: center; +} + +.center { + align-items: center; +} diff --git a/tournaments/static/tournaments/css/style.css b/tournaments/static/tournaments/css/style.css index 035357a..80bcd9c 100644 --- a/tournaments/static/tournaments/css/style.css +++ b/tournaments/static/tournaments/css/style.css @@ -323,9 +323,34 @@ tr { } .player { + position: relative; flex: 1; display: flex; flex-direction: column; + min-height: 2.8em; /* This ensures minimum height for 2 lines */ + justify-content: center; + overflow: hidden; +} + +/* Add this if you want empty lines to take up space */ +.player div { + min-height: 1.4em; /* Height for single line */ +} + +/* For single player teams */ +.player.single-player .semibold { + max-height: 2.8em; /* Adjust based on your needs */ + line-height: 1.4em; + overflow: hidden; + position: relative; + text-overflow: ellipsis; +} + +/* For two player teams */ +.player.two-players .semibold { + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .scores { @@ -344,7 +369,6 @@ tr { font-size: 1.3em; vertical-align: middle; text-align: center; - padding: 0px 5px; /* width: 30px; */ } @@ -718,14 +742,15 @@ h-margin { .flex-left { flex: 1; text-align: left; - padding: 5px 0px; + justify-content: center; + min-height: 4em; + padding-right: 5px; } .flex-right { flex: initial; text-align: right; - vertical-align: middle; - padding: 5px 0px; + justify-content: center; } #header { @@ -838,10 +863,6 @@ h-margin { background-color: #90ee90; /* Light green color */ } -.player { - position: relative; /* Ensures the overlay is positioned within this block */ -} - .overlay-text { position: absolute; top: 50%; diff --git a/tournaments/templates/tournaments/broadcast/broadcasted_group_stage.html b/tournaments/templates/tournaments/broadcast/broadcasted_group_stage.html index 48d7c68..0d35253 100644 --- a/tournaments/templates/tournaments/broadcast/broadcasted_group_stage.html +++ b/tournaments/templates/tournaments/broadcast/broadcasted_group_stage.html @@ -8,7 +8,10 @@
-
+