"""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)