Files
team-tryouts/app/models/evaluation.py
GGThed e15b3c1293
CI - Security, Lint & Tests / validate (push) Failing after 16m22s
fix(audit): centraliser l'horloge UTC
2026-08-17 15:21:08 -04:00

79 lines
3.2 KiB
Python

"""Player evaluation record."""
from app.extensions import db
from app.time_utils import utc_now_naive
class Evaluation(db.Model):
"""Player evaluation record."""
__tablename__ = 'evaluations'
id = db.Column(db.Integer, primary_key=True)
tryout_id = db.Column(db.Integer, db.ForeignKey('tryouts.id'), nullable=False)
player_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
evaluator_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
mecanics_score = db.Column(db.Integer, nullable=True)
cohesion_score = db.Column(db.Integer, nullable=True)
communication_score = db.Column(db.Integer, nullable=True)
gamesense_score = db.Column(db.Integer, nullable=True)
versatility_score = db.Column(db.Integer, nullable=True)
discipline_score = db.Column(db.Integer, nullable=True)
analysis_score = db.Column(db.Integer, nullable=True)
sport_ethics_score = db.Column(db.Integer, nullable=True)
mental_score = db.Column(db.Integer, nullable=True)
overall_score = db.Column(db.Float, nullable=True)
comments = db.Column(db.Text, nullable=True)
position_recommendation = db.Column(db.String(50), nullable=True)
created_at = db.Column(db.DateTime, default=utc_now_naive)
updated_at = db.Column(db.DateTime, default=utc_now_naive, onupdate=utc_now_naive)
__table_args__ = (
db.UniqueConstraint('tryout_id', 'player_id', 'evaluator_id', name='unique_evaluation'),
)
#: The nine criteria, in the order the form shows them. The overall score
#: is their mean; a criterion left blank is left out of the mean rather
#: than counted as a zero, which is why this list exists rather than the
#: route summing nine named variables (ARCH-005, QUA-003).
CRITERIA = (
'mecanics_score',
'cohesion_score',
'communication_score',
'gamesense_score',
'versatility_score',
'discipline_score',
'analysis_score',
'sport_ethics_score',
'mental_score',
)
@classmethod
def overall_from(cls, scores):
"""Mean of the criteria that were actually filled in.
Args:
scores: Mapping of criterion name to score or None.
Returns:
float | None: None when nothing was scored — which is not the
same as zero, and must not become one. A player nobody could
assess has no overall score; a player who scored zero on
everything cannot exist, the scale starts at one.
"""
given = [scores.get(name) for name in cls.CRITERIA]
given = [score for score in given if score is not None]
if not given:
return None
return sum(given) / len(given)
def apply_scores(self, scores):
"""Write these criteria onto the record and recompute the overall.
Every criterion is assigned, including the ones left blank: an edit
that clears a score has to clear it, and the mean has to be the mean
of what is on the record afterwards.
"""
for name in self.CRITERIA:
setattr(self, name, scores.get(name))
self.overall_score = self.overall_from(scores)