From 24deb2198db2dfed50f0c215c1210c2f0940b1c2 Mon Sep 17 00:00:00 2001 From: Raz Date: Wed, 20 Nov 2024 07:42:06 +0100 Subject: [PATCH] improve registration --- tournaments/models/enums.py | 24 +++++ tournaments/models/team_registration.py | 2 +- tournaments/utils/player_search.py | 121 +++++++++++++++++++----- tournaments/views.py | 57 ++++++++--- 4 files changed, 166 insertions(+), 38 deletions(-) diff --git a/tournaments/models/enums.py b/tournaments/models/enums.py index f3228d1..c5099cd 100644 --- a/tournaments/models/enums.py +++ b/tournaments/models/enums.py @@ -13,6 +13,30 @@ class FederalCategory(models.IntegerChoices): MIXED = 2, 'Mixte' UNLISTED = 3, '' + @staticmethod + def female_in_male_assimilation_addition(rank: int) -> int: + if 1 <= rank <= 10: + return 400 + elif 11 <= rank <= 30: + return 1000 + elif 31 <= rank <= 60: + return 2000 + elif 61 <= rank <= 100: + return 3500 + elif 101 <= rank <= 200: + return 10000 + elif 201 <= rank <= 500: + return 15000 + elif 501 <= rank <= 1000: + return 25000 + elif 1001 <= rank <= 2000: + return 35000 + elif 2001 <= rank <= 3000: + return 45000 + else: + return 50000 + + class FederalLevelCategory(models.IntegerChoices): UNLISTED = 0, 'Animation' P25 = 25, 'P25' diff --git a/tournaments/models/team_registration.py b/tournaments/models/team_registration.py index 93fcaa8..6c09558 100644 --- a/tournaments/models/team_registration.py +++ b/tournaments/models/team_registration.py @@ -96,7 +96,7 @@ class TeamRegistration(models.Model): return "--" def set_weight(self): - self.weight = self.playerregistration_set.aggregate(total_weight=models.Sum('rank'))['total_weight'] or 0 + self.weight = self.playerregistration_set.aggregate(total_weight=models.Sum('computed_rank'))['total_weight'] or 0 self.save() # Save the updated weight if necessary def is_valid_for_summon(self): diff --git a/tournaments/utils/player_search.py b/tournaments/utils/player_search.py index 018c7ff..171b6bc 100644 --- a/tournaments/utils/player_search.py +++ b/tournaments/utils/player_search.py @@ -1,34 +1,107 @@ import csv import os import re +from datetime import datetime + +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 -def get_player_name_from_csv(licence_id): - # Define the file path - file_path = '/Users/razmig/Documents/XLR Sport/padelclub_backend/tournaments/static/rankings/CLASSEMENT-PADEL-MESSIEURS-11-2024.csv' +def get_player_name_from_csv(category, licence_id, base_folder="/Users/razmig/Documents/XLR Sport/padelclub_backend/tournaments/static"): + """ + Search for a player's first name, last name, and rank in the most recent rankings file. + + :param licence_id: The licence ID to search for. + :param base_folder: Base folder containing the rankings folder. + :return: A tuple (first_name, last_name, rank) or (None, None, None) if not found. + """ + folder_path = os.path.join(base_folder, "rankings") cleaned_licence_id = clean_licence_id(licence_id) - print(cleaned_licence_id) - # Open the file and read it - with open(file_path, newline='', encoding='utf-8') as file: - reader = csv.reader(file, delimiter=';') - - # Iterate through each row in the CSV - for row in reader: - # Ensure the row is not empty and has the expected number of columns - if len(row) >= 13: - current_licence_id = row[5] # The 5th column contains the licence_id - - # Check if the current row matches the given licence_id - if current_licence_id == str(cleaned_licence_id): - # Return first name and last name from the row (3rd and 4th columns) - first_name = row[3] # 4th column: first name - last_name = row[2] # 3rd column: last name - rank = row[1] # 3rd column: last name - return first_name, last_name, rank - - # Return None if no match is found - return None, None, None + + def extract_date(file_name): + """ + Extract the date (MM-YYYY) from the file name and return it as a datetime object. + """ + match = re.search(r"(\d{2}-\d{4})", file_name) + if match: + return datetime.strptime(match.group(1), "%m-%Y") + return None + + def find_most_recent_file(file_type): + """ + Find the most recent file for the given type (-MESSIEURS- or -DAMES-). + """ + files = [ + f for f in os.listdir(folder_path) + if file_type in f and re.search(r"\d{2}-\d{4}", f) + ] + files_with_dates = [(f, extract_date(f) or datetime.min) for f in files] + if not files_with_dates: + return None + # Sort by date in descending order + files_with_dates.sort(key=lambda x: x[1], reverse=True) + return os.path.join(folder_path, files_with_dates[0][0]) + + def search_file(file_path, is_woman): + if not file_path or not os.path.exists(file_path): + return None, False + + last_rank = None + last_rank_count = 0 + with open(file_path, newline='', encoding='utf-8') as file: + reader = csv.reader(file, delimiter=';') + rows = list(reader) # Read all rows at once to process later + + for row in rows: + if len(row) >= 15: # Ensure row has enough columns + current_licence_id = row[5] + if current_licence_id == str(cleaned_licence_id): + data = { + "first_name": row[3], # 4th column: first name + "last_name": row[2], # 3rd column: last name + "rank": row[1], + "points": row[6], + "assimilation": row[7], + "tournament_count": row[8], + "ligue_name": row[9], + "club_name": row[11], + "birth_year": row[14], + "is_woman": is_woman, + } + return data, True + + # Determine the rank for an unranked player + if rows: + # Find the last rank in the file + last_row = rows[-1] + if len(last_row) >= 2: + last_rank = last_row[1] + + # Count how many times the last rank appears + last_rank_count = sum(1 for row in rows if len(row) >= 2 and row[1] == last_rank) + + if last_rank is not None: + unranked_rank = int(last_rank) + last_rank_count + 1 + data = { + "rank": str(unranked_rank), + "is_woman": is_woman + } + return data, False + + return None, False + + + dames_file = find_most_recent_file("CLASSEMENT-PADEL-DAMES-") + result, found = search_file(dames_file, True) + if found or category is FederalCategory.WOMEN: + return result + + messieurs_file = find_most_recent_file("CLASSEMENT-PADEL-MESSIEURS-") + result, found = search_file(messieurs_file, False) + return result + + # Return None if not found in either file + return None diff --git a/tournaments/views.py b/tournaments/views.py index 490ed09..4079d20 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -9,10 +9,10 @@ from django.core.files.storage import default_storage from django.core.files.base import ContentFile from tournaments.models.device_token import DeviceToken -from tournaments.models.player_enums import PlayerDataSource +from tournaments.models.player_enums import PlayerDataSource, PlayerSexType from .models import Court, DateInterval, Club, Tournament, CustomUser, Event, Round, GroupStage, Match, TeamScore, TeamRegistration, PlayerRegistration, Purchase, FailedApiCall -from .models import TeamSummon +from .models import TeamSummon, FederalCategory from datetime import datetime, timedelta import time @@ -670,11 +670,12 @@ def register_tournament(request, tournament_id): else: if add_player_form.first_tournament is False: # Retrieve player names from the CSV file - first_name, last_name, rank = get_player_name_from_csv(licence_id) - if first_name and last_name and rank: - player_data['first_name'] = first_name - player_data['last_name'] = last_name - player_data['rank'] = rank + data = get_player_name_from_csv(tournament.federal_category, licence_id) + if data: + player_data['first_name'] = data['first_name'] + player_data['last_name'] = data['last_name'] + player_data['rank'] = data['rank'] + player_data['is_woman'] = data['is_woman'] # If validation passes, add the player to the session without clearing previous ones request.session['team_registration'].append(player_data) request.session.modified = True # Ensure session is updated @@ -703,13 +704,37 @@ def register_tournament(request, tournament_id): if player_licence_id.startswith(stripped_license): is_captain = True + + is_woman = player_data.get('is_woman', False) + rank = player_data['rank'] + computed_rank = None + sex = PlayerSexType.MALE + if is_woman is None: + computed_rank = rank + else: + computed_rank = rank + is_woman = player_data.get('is_woman', False) == True + if is_woman: + sex = PlayerSexType.FEMALE + if tournament.federal_category is FederalCategory.WOMEN and is_woman: + computed_rank += FederalCategory.female_in_male_assimilation_addition(rank) + + player_registration = PlayerRegistration.objects.create( team_registration=team_registration, captain=is_captain, source=PlayerDataSource.ONLINE_REGISTRATION, - first_name=player_data['first_name'], - last_name=player_data['last_name'], - rank = player_data.get('rank', 70000), + first_name=player_data.get('first_name', None), + last_name=player_data.get('last_name', None), + points=player_data.get('points', None), + assimilation=player_data.get('assimilation', None), + tournament_played=player_data.get('tournament_count', None), + ligue_name=player_data.get('ligue_name', None), + club_name=player_data.get('club_name', None), + birthdate=player_data.get('birth_year', None), + sex = sex, + rank = rank, + computed_rank = computed_rank, licence_id=player_data['licence_id'], email = player_data.get('email', None), phone_number = player_data.get('phone_number', None) @@ -747,9 +772,15 @@ def register_tournament(request, tournament_id): 'licence_id': validator.computed_licence_id } - first_name, last_name, rank = get_player_name_from_csv(user_licence_id) - if first_name and last_name and rank: - player_data['rank'] = rank + data = get_player_name_from_csv(tournament.federal_category, user_licence_id) + if data: + player_data['rank'] = data['rank'] + player_data['points'] = data.get('points', None) + player_data['assimilation'] = data.get('assimilation', None) + player_data['tournament_count'] = data.get('tournament_count', None) + player_data['ligue_name'] = data.get('ligue_name', None) + player_data['club_name'] = data.get('club_name', None) + player_data['birth_year'] = data.get('birth_year', None) request.session['team_registration'].insert(0, player_data) # Add them as the first player request.session.modified = True # Ensure session is updated