tennis-api / src /entity /match.py
sghorbal
expose the odds in the base match model
02c056c
from sqlalchemy import Integer, String, Date, ForeignKey, UniqueConstraint
from sqlalchemy.orm import relationship, mapped_column, Mapped
from src.entity.odds import Odds, OddsApi
from src.entity.player import Player, PlayerApiDetail
from typing import Literal, Optional, ClassVar, List
from pydantic import BaseModel, Field, ConfigDict
from datetime import date as ddate
from . import Base
class Match(Base):
"""
Match table
"""
__tablename__ = "match"
__table_args__ = (
UniqueConstraint('date', 'fk_winner_id', 'fk_loser_id', name='uq_date_fk_winner_id_fk_loser_id'),
{'schema': 'data'},
)
# Match table columns
id: Mapped[int] = mapped_column(primary_key=True)
date: Mapped[ddate] = mapped_column(Date, nullable=True)
comment: Mapped[str] = mapped_column(String, nullable=True)
winner_rank: Mapped[int] = mapped_column(Integer, nullable=True)
winner_points: Mapped[int] = mapped_column(Integer, nullable=True)
loser_rank: Mapped[int] = mapped_column(Integer, nullable=True)
loser_points: Mapped[int] = mapped_column(Integer, nullable=True)
tournament_name: Mapped[str] = mapped_column(String, nullable=True)
tournament_series: Mapped[str] = mapped_column(String, nullable=True)
tournament_surface: Mapped[str] = mapped_column(String, nullable=True)
tournament_court: Mapped[str] = mapped_column(String, nullable=True)
tournament_round: Mapped[str] = mapped_column(String, nullable=True)
tournament_location: Mapped[str] = mapped_column(String, nullable=True)
# Dependent table
odds: Mapped[list["Odds"]] = relationship("Odds", back_populates="match", cascade="all, delete-orphan", passive_deletes=True)
fk_winner_id: Mapped[int] = mapped_column(ForeignKey("data.player.id", ondelete="CASCADE", name='match_fk_winner_id_fkey'), nullable=False)
fk_loser_id: Mapped[int] = mapped_column(ForeignKey("data.player.id", ondelete="CASCADE", name='match_fk_loser_id_fkey'), nullable=False)
winner: Mapped["Player"] = relationship("Player", foreign_keys=[fk_winner_id])
loser: Mapped["Player"] = relationship("Player", foreign_keys=[fk_loser_id])
# -----------------------------------------------------------
# Pydantic Model for Match
# -----------------------------------------------------------
class MatchApiBase(BaseModel):
id: int
date: Optional[ddate]
comment: Optional[str]
winner_rank: Optional[int]
winner_points: Optional[int]
loser_rank: Optional[int]
loser_points: Optional[int]
tournament_name: Optional[str]
tournament_series: Optional[str]
tournament_surface: Optional[str]
tournament_court: Optional[str]
tournament_round: Optional[str]
tournament_location: Optional[str]
fk_winner_id: int
fk_loser_id: int
odds: Optional[List[OddsApi]]
model_config: ClassVar[ConfigDict] = ConfigDict(from_attributes=True)
class MatchApiDetail(MatchApiBase):
winner: Optional[PlayerApiDetail]
loser: Optional[PlayerApiDetail]
# -------------------------------------------------------
class RawMatch(BaseModel):
Comment: Literal['Completed', 'Retired', 'Walkover'] = 'Completed'
Loser: str = Field(description="The name of the loser.", json_schema_extra={"example": "'Djokovic N.'"})
Winner: str = Field(description="The name of the winner.", json_schema_extra={"example": "'Federer R.'"})
Round: Literal['1st Round', '2nd Round', '3rd Round', '4th Round', 'Quarterfinals', 'Semifinals', 'The Final', 'Round Robin'] = '1st Round'
Court: Literal['Outdoor', 'Indoor'] = 'Outdoor'
Surface: Literal['Grass', 'Carpet', 'Clay', 'Hard'] = 'Grass'
Wsets: int = Field(description="The number of sets won by the winner.", json_schema_extra={"example": "3"})
Lsets: int = Field(description="The number of sets won by the loser.", json_schema_extra={"example": "0"})
Date: str = Field(description="The date of the match.", json_schema_extra={"example": "'2019-06-15'"})
WRank: int = Field(description="The rank of the winner.", json_schema_extra={"example": "1"})
WPts: int = Field(description="The number of points of the winner.", json_schema_extra={"example": "4000"})
LPts: int = Field(description="The number of points of the loser.", json_schema_extra={"example": "3000"})
LRank: int = Field(description="The rank of the loser.", json_schema_extra={"example": "2"})
Location: str = Field(description="The location of the tournament.", json_schema_extra={"example": "'London'"})
Series: Literal['ATP250', 'ATP500', 'Grand Slam', 'Masters 1000', 'Masters', 'Masters Cup', 'International Gold', 'International'] = 'Grand Slam'
W1: Optional[int] = Field(description="The score of the winner in the first set.", json_schema_extra={"example": "6"})
W2: Optional[int] = Field(description="The score of the winner in the second set.", json_schema_extra={"example": "6"})
W3: Optional[int] = Field(description="The score of the winner in the third set.", json_schema_extra={"example": "6"})
W4: Optional[int] = Field(description="The score of the winner in the fourth set.", json_schema_extra={"example": "None"})
W5: Optional[int] = Field(description="The score of the winner in the fifth set.", json_schema_extra={"example": "None"})
L1: Optional[int] = Field(description="The score of the loser in the first set.", json_schema_extra={"example": "3"})
L2: Optional[int] = Field(description="The score of the loser in the second set.", json_schema_extra={"example": "2"})
L3: Optional[int] = Field(description="The score of the loser in the third set.", json_schema_extra={"example": "0"})
L4: Optional[int] = Field(description="The score of the loser in the fourth set.", json_schema_extra={"example": "None"})
L5: Optional[int] = Field(description="The score of the loser in the fifth set.", json_schema_extra={"example": "None"})
Tournament: str = Field(description="The name of the tournament.", json_schema_extra={"example": "Wimbledon"})
model_config: ClassVar[ConfigDict] = ConfigDict(extra="allow")