didier/functions/football.py

165 lines
5.2 KiB
Python

from enum import Enum
from attr import dataclass, field
from functions.timeFormatters import fromString
from functions.scraping import getJPLMatches, getJPLTable
from functions.stringFormatters import leadingZero
from datetime import datetime
import tabulate
class Status(Enum):
AfterToday = "--:--"
NotStarted = "--:--"
Over = "Einde"
HalfTime = "Rust"
@dataclass
class Match:
"""
Class representing a football match between two teams
"""
matchDict: dict
home: str = field(init=False)
homeScore: int = 0
away: str = field(init=False)
awayScore: int = 0
start: datetime = field(init=False)
date: str = field(init=False)
weekDay: str = field(init=False)
status: Status = field(init=False)
def __attrs_post_init__(self):
"""
Parse class attributes out of a dictionary returned from an API request
"""
# The API isn't public, so every single game state is differently formatted
self.status = self._getStatus(self.matchDict[Navigation.Status.value])
self.home = self.matchDict[Navigation.HomeTeam.value][Navigation.Name.value]
self.away = self.matchDict[Navigation.AwayTeam.value][Navigation.Name.value]
if self._hasStarted():
self.homeScore = self.matchDict[Navigation.HomeScore.value]
self.awayScore = self.matchDict[Navigation.AwayScore.value]
self.start = fromString(self.matchDict["startDateTime"], formatString="%Y-%m-%dT%H:%M:%S.%f%z")
self.date = self.start.strftime("%d/%m")
self.weekDay = self._getWeekday()
def _getStatus(self, status: str):
"""
Gets the string representation for the status of this match
"""
# LiveTime only exists if the status is live
# Avoids KeyErrors
if status.lower() == "live":
# Half time
if Navigation.LiveMatchPhase.value in self.matchDict and \
self.matchDict[Navigation.LiveMatchPhase.value] == Navigation.HalfTime.value:
return Status.HalfTime.value
# Current time
return self.matchDict[Navigation.LiveTime.value]
# If no special status, pull it out of this dict
statusses: dict = {
"after_today": Status.AfterToday.value,
"not_started": Status.NotStarted.value,
"end": Status.Over.value
}
return statusses[status.lower()]
def _getWeekday(self):
"""
Gets the day of the week this match is played on
"""
day = self.start.weekday()
days = ["Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"]
return days[day]
def getInfo(self):
"""
Returns a list of all the info of this class in order to create a table
"""
return [self.weekDay, self.date, self.home, self._getScore(), self.away, self.status]
def _getScore(self):
"""
Returns a string representing the scoreboard
"""
# No score to show yet, show time when the match starts
if not self._hasStarted():
return "{}:{}".format(leadingZero(str(self.start.hour)), leadingZero(str(self.start.minute)))
return "{} - {}".format(self.homeScore, self.awayScore)
def _hasStarted(self):
return self.status not in [Status.AfterToday.value, Status.NotStarted.value]
class Navigation(Enum):
"""
Enum to navigate through the matchdict,
seeing as the API is private the keys of the dict could change every now and then
so this makes sure a key only has to be changed once.
"""
AwayTeam = "awayTeam"
HomeTeam = "homeTeam"
AwayScore = "awayScore"
HomeScore = "homeScore"
LiveTime = "liveTime"
LiveMatchPhase = "liveMatchPhase"
HalfTime = "HALF_TIME"
Status = "status"
Name = "name"
def getMatches(matchweek: int):
"""
Function that constructs the list of matches for a given matchweek
"""
current_day = getJPLMatches(matchweek)
# API request failed
if current_day is None:
return "Er ging iets fout. Probeer het later opnieuw."
matches = list(map(Match, current_day))
matches = list(map(lambda x: x.getInfo(), matches))
header = "Jupiler Pro League - Speeldag {}".format(matchweek)
table = tabulate.tabulate(matches, headers=["Dag", "Datum", "Thuis", "Stand", "Uit", "Tijd"])
return "```{}\n\n{}```".format(header, table)
def getTable():
"""
Function that constructs the current table of the JPL
"""
rows = getJPLTable()
if rows is None:
return "Er ging iets fout. Probeer het later opnieuw."
# Format every row to work for Tabulate
formatted = [_formatRow(row) for row in rows]
header = "Jupiler Pro League Klassement"
table = tabulate.tabulate(formatted, headers=["#", "Ploeg", "Punten", "M", "M+", "M-", "M=", "D+", "D-", "D+/-"])
return "```{}\n\n{}```".format(header, table)
def _formatRow(row):
"""
Function that formats a row into a list for Tabulate to use
"""
scoresArray = list([td.renderContents().decode("utf-8") for td in row.find_all("td")])[:9]
# Insert the team name into the list
scoresArray.insert(1, row.find_all("a")[0].renderContents().decode("utf-8").split("<!--")[0])
return scoresArray