126 lines
7.6 KiB
Python
126 lines
7.6 KiB
Python
from django import forms
|
|
|
|
from apps.competitions.models import Competition, Season
|
|
from apps.players.models import Nationality, Position, Role
|
|
from apps.teams.models import Team
|
|
|
|
|
|
class PlayerSearchForm(forms.Form):
|
|
SORT_CHOICES = (
|
|
("name_asc", "Name (A-Z)"),
|
|
("name_desc", "Name (Z-A)"),
|
|
("age_youngest", "Age (Youngest first)"),
|
|
("age_oldest", "Age (Oldest first)"),
|
|
("height_desc", "Height (Tallest first)"),
|
|
("height_asc", "Height (Shortest first)"),
|
|
("ppg_desc", "Points per game (High to low)"),
|
|
("ppg_asc", "Points per game (Low to high)"),
|
|
("mpg_desc", "Minutes per game (High to low)"),
|
|
("mpg_asc", "Minutes per game (Low to high)"),
|
|
)
|
|
|
|
PAGE_SIZE_CHOICES = ((20, "20"), (50, "50"), (100, "100"))
|
|
|
|
q = forms.CharField(required=False, label="Name")
|
|
nominal_position = forms.ModelChoiceField(queryset=Position.objects.none(), required=False)
|
|
inferred_role = forms.ModelChoiceField(queryset=Role.objects.none(), required=False)
|
|
competition = forms.ModelChoiceField(queryset=Competition.objects.none(), required=False)
|
|
origin_competition = forms.ModelChoiceField(queryset=Competition.objects.none(), required=False)
|
|
nationality = forms.ModelChoiceField(queryset=Nationality.objects.none(), required=False)
|
|
team = forms.ModelChoiceField(queryset=Team.objects.none(), required=False)
|
|
origin_team = forms.ModelChoiceField(queryset=Team.objects.none(), required=False)
|
|
season = forms.ModelChoiceField(queryset=Season.objects.none(), required=False)
|
|
|
|
age_min = forms.IntegerField(required=False, min_value=0, max_value=60, label="Min age")
|
|
age_max = forms.IntegerField(required=False, min_value=0, max_value=60, label="Max age")
|
|
height_min = forms.IntegerField(required=False, min_value=120, max_value=250, label="Min height (cm)")
|
|
height_max = forms.IntegerField(required=False, min_value=120, max_value=250, label="Max height (cm)")
|
|
weight_min = forms.IntegerField(required=False, min_value=40, max_value=200, label="Min weight (kg)")
|
|
weight_max = forms.IntegerField(required=False, min_value=40, max_value=200, label="Max weight (kg)")
|
|
|
|
games_played_min = forms.IntegerField(required=False, min_value=0)
|
|
games_played_max = forms.IntegerField(required=False, min_value=0)
|
|
minutes_per_game_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
minutes_per_game_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
points_per_game_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
points_per_game_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
rebounds_per_game_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
rebounds_per_game_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
assists_per_game_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
assists_per_game_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
steals_per_game_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
steals_per_game_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
blocks_per_game_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
blocks_per_game_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
turnovers_per_game_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
turnovers_per_game_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=6)
|
|
fg_pct_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=5, label="FG% min")
|
|
fg_pct_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=5, label="FG% max")
|
|
three_pct_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=5, label="3P% min")
|
|
three_pct_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=5, label="3P% max")
|
|
ft_pct_min = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=5, label="FT% min")
|
|
ft_pct_max = forms.DecimalField(required=False, min_value=0, decimal_places=2, max_digits=5, label="FT% max")
|
|
efficiency_metric_min = forms.DecimalField(
|
|
required=False,
|
|
min_value=0,
|
|
decimal_places=2,
|
|
max_digits=6,
|
|
label="Impact metric min",
|
|
)
|
|
efficiency_metric_max = forms.DecimalField(
|
|
required=False,
|
|
min_value=0,
|
|
decimal_places=2,
|
|
max_digits=6,
|
|
label="Impact metric max",
|
|
)
|
|
|
|
sort = forms.ChoiceField(choices=SORT_CHOICES, required=False, initial="name_asc")
|
|
page_size = forms.TypedChoiceField(
|
|
choices=PAGE_SIZE_CHOICES,
|
|
required=False,
|
|
coerce=int,
|
|
initial=20,
|
|
)
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.fields["nominal_position"].queryset = Position.objects.order_by("code")
|
|
self.fields["inferred_role"].queryset = Role.objects.order_by("name")
|
|
self.fields["competition"].queryset = Competition.objects.order_by("name")
|
|
self.fields["origin_competition"].queryset = Competition.objects.order_by("name")
|
|
self.fields["nationality"].queryset = Nationality.objects.order_by("name")
|
|
self.fields["team"].queryset = Team.objects.order_by("name")
|
|
self.fields["origin_team"].queryset = Team.objects.order_by("name")
|
|
self.fields["season"].queryset = Season.objects.order_by("-start_date")
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
self._validate_min_max(cleaned_data, "age_min", "age_max")
|
|
self._validate_min_max(cleaned_data, "height_min", "height_max")
|
|
self._validate_min_max(cleaned_data, "weight_min", "weight_max")
|
|
self._validate_min_max(cleaned_data, "games_played_min", "games_played_max")
|
|
self._validate_min_max(cleaned_data, "minutes_per_game_min", "minutes_per_game_max")
|
|
self._validate_min_max(cleaned_data, "points_per_game_min", "points_per_game_max")
|
|
self._validate_min_max(cleaned_data, "rebounds_per_game_min", "rebounds_per_game_max")
|
|
self._validate_min_max(cleaned_data, "assists_per_game_min", "assists_per_game_max")
|
|
self._validate_min_max(cleaned_data, "steals_per_game_min", "steals_per_game_max")
|
|
self._validate_min_max(cleaned_data, "blocks_per_game_min", "blocks_per_game_max")
|
|
self._validate_min_max(cleaned_data, "turnovers_per_game_min", "turnovers_per_game_max")
|
|
self._validate_min_max(cleaned_data, "fg_pct_min", "fg_pct_max")
|
|
self._validate_min_max(cleaned_data, "three_pct_min", "three_pct_max")
|
|
self._validate_min_max(cleaned_data, "ft_pct_min", "ft_pct_max")
|
|
self._validate_min_max(cleaned_data, "efficiency_metric_min", "efficiency_metric_max")
|
|
|
|
if not cleaned_data.get("sort"):
|
|
cleaned_data["sort"] = "name_asc"
|
|
if not cleaned_data.get("page_size"):
|
|
cleaned_data["page_size"] = 20
|
|
return cleaned_data
|
|
|
|
def _validate_min_max(self, cleaned_data: dict, minimum_key: str, maximum_key: str) -> None:
|
|
minimum = cleaned_data.get(minimum_key)
|
|
maximum = cleaned_data.get(maximum_key)
|
|
if minimum is not None and maximum is not None and minimum > maximum:
|
|
self.add_error(maximum_key, f"{maximum_key.replace('_', ' ')} must be >= {minimum_key.replace('_', ' ')}")
|