Coverage for bundesliga_tippspiel/db/match_data/Match.py: 97%
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""LICENSE
2Copyright 2017 Hermann Krumrey <hermann@krumreyh.com>
4This file is part of bundesliga-tippspiel.
6bundesliga-tippspiel is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
11bundesliga-tippspiel is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
16You should have received a copy of the GNU General Public License
17along with bundesliga-tippspiel. If not, see <http://www.gnu.org/licenses/>.
18LICENSE"""
20import pytz
21from datetime import datetime
22from typing import TYPE_CHECKING, List
24from flask import url_for
25from jerrycan.base import db
26from jerrycan.db.ModelMixin import ModelMixin
27if TYPE_CHECKING: # pragma: no cover
28 from bundesliga_tippspiel.db.match_data.Goal import Goal
29 from bundesliga_tippspiel.db.user_generated.Bet import Bet
30 from bundesliga_tippspiel.db.match_data.Team import Team
33class Match(ModelMixin, db.Model):
34 """
35 Model that describes the 'matches' SQL table
36 """
38 def __init__(self, *args, **kwargs):
39 """
40 Initializes the Model
41 :param args: The constructor arguments
42 :param kwargs: The constructor keyword arguments
43 """
44 super().__init__(*args, **kwargs)
46 __tablename__ = "matches"
48 league: str = db.Column(db.String(255), primary_key=True)
49 season: int = db.Column(db.Integer, primary_key=True)
50 matchday: int = db.Column(db.Integer, primary_key=True)
51 home_team_abbreviation: str = db.Column(
52 db.String(3),
53 db.ForeignKey("teams.abbreviation"),
54 primary_key=True,
55 )
56 away_team_abbreviation: str = db.Column(
57 db.String(3),
58 db.ForeignKey("teams.abbreviation"),
59 primary_key=True
60 )
62 home_current_score: int = db.Column(db.Integer, nullable=False)
63 away_current_score: int = db.Column(db.Integer, nullable=False)
64 home_ht_score: int = db.Column(db.Integer)
65 away_ht_score: int = db.Column(db.Integer)
66 home_ft_score: int = db.Column(db.Integer)
67 away_ft_score: int = db.Column(db.Integer)
68 kickoff: str = db.Column(db.String(255), nullable=False)
69 started: bool = db.Column(db.Boolean, nullable=False)
70 finished: bool = db.Column(db.Boolean, nullable=False)
72 home_team: "Team" = db.relationship(
73 "Team", foreign_keys=[home_team_abbreviation],
74 )
75 away_team: "Team" = db.relationship(
76 "Team", foreign_keys=[away_team_abbreviation]
77 )
78 goals: List["Goal"] = db.relationship("Goal", cascade="all, delete")
79 bets: List["Bet"] = db.relationship("Bet", cascade="all, delete")
81 @property
82 def minutes_since_kickoff(self) -> int:
83 """
84 :return: The amount of minutes elapsed since kickoff
85 """
86 delta = (datetime.utcnow() - self.kickoff_datetime).total_seconds()
87 delta = int(delta / 60)
88 return delta
90 @property
91 def minute_display(self) -> str:
92 """
93 This generates a string for displaying the current match minute.
94 Sadly, since OpenligaDB does not provide information on the current
95 minute, this can only offer an approximation.
96 :return: A formatted string displaying the current match minute
97 """
98 delta = self.minutes_since_kickoff
100 if self.finished:
101 return "Ende"
102 elif 0 <= delta <= 44:
103 return "{}.".format(delta + 1)
104 elif 45 <= delta < 47: # buffer for ET
105 return "45."
106 elif 47 <= delta <= 64:
107 return "HZ"
108 elif 65 <= delta <= 109:
109 return "{}.".format(delta - 65 + 1 + 45)
110 elif delta >= 110:
111 return "90."
112 else:
113 return "-"
115 @property
116 def current_score(self) -> str:
117 """
118 :return: The current score formatted as a string
119 """
120 return "{}:{}".format(self.home_current_score, self.away_current_score)
122 @property
123 def ht_score(self) -> str:
124 """
125 :return: The half time score formatted as a string
126 """
127 return "{}:{}".format(self.home_ht_score, self.away_ht_score)
129 @property
130 def ft_score(self) -> str:
131 """
132 :return: The full time score formatted as a string
133 """
134 return "{}:{}".format(self.home_ft_score, self.away_ft_score)
136 @property
137 def kickoff_datetime(self) -> datetime:
138 """
139 :return: A datetime object representing the kickoff time
140 """
141 return datetime.strptime(self.kickoff, "%Y-%m-%d:%H-%M-%S")
143 @kickoff_datetime.setter
144 def kickoff_datetime(self, kickoff: datetime):
145 """
146 Setter for the kickoff datetime
147 :param kickoff: The new kickoff datetime
148 :return: None
149 """
150 self.kickoff = kickoff.strftime("%Y-%m-%d:%H-%M-%S")
152 @property
153 def kickoff_local_datetime(self) -> datetime:
154 """
155 :return: A datetime object representing the kickoff time in local time
156 """
157 return self.kickoff_datetime.astimezone(pytz.timezone("europe/berlin"))
159 @property
160 def kickoff_time_string(self) -> str:
161 """
162 :return: A string representing the kickoff time
163 """
164 return self.kickoff_local_datetime.strftime("%H:%M")
166 @property
167 def kickoff_date_string(self) -> str:
168 """
169 :return: A string representing the kickoff date
170 """
171 return self.kickoff_local_datetime.strftime("%d. %m. %Y")
173 @property
174 def has_started(self) -> bool:
175 """
176 Checks if the match has started.
177 This is to be preferred over the 'started' attribute, just in case
178 the database update has failed for any reason.
179 :return: True if the match has started, False otherwise
180 """
181 return self.started or self.kickoff_datetime <= datetime.utcnow()
183 @property
184 def url(self) -> str:
185 """
186 :return: The URL for this match's info page
187 """
188 return url_for(
189 "info.match",
190 league=self.league,
191 season=self.season,
192 matchday=self.matchday,
193 matchup=f"{self.home_team_abbreviation}_"
194 f"{self.away_team_abbreviation}"
195 )