Exemple #1
0
    def fix_failed(self):
        sheet = Sheet(gdstats_sheet)
        failed = sheet.to_df('Failed Players!A1:AN')
        fixed = pd.DataFrame(columns=failed.columns)
        if failed.empty:
            return print("No players found!")
        for row in failed.index:
            username = failed.loc[row, 'Username']
            known = input(f"Do you know who {username} is? (y/n) ")
            if known == "y":
                _id = input("Please type their discord id: ")
                # Add rl id to their account
                found = self.session.all_players.find_one_and_update(
                    {"_id": _id},
                    {"$push": {
                        "rl_id": failed.loc[row, "Discord ID"]
                    }})
                if found:
                    fixed = fixed.append(failed.loc[row])
                    fixed.loc[fixed['Username'] == username,
                              'Discord ID'] = _id
                    fixed.loc[fixed['Username'] == username,
                              'Username'] = found['username']
                    failed.drop(row)

        self.unknown = failed['Username'].values
        sheet.clear("Failed Players!A2:AN")
        self.log_data(fixed.set_index("Discord ID"),
                      f'{dates[get_latest_gameday()]}!A2:Z')
        self.upload_stats(fixed.set_index("Discord ID"))
Exemple #2
0
def get_players() -> list[dict]:
    """Gets all the players from the sheet and their associated ids for finding ballchasing replays

    Returns:
        list[dict]: List of {username: str, ids: list[str]} dicts each representing a unique player
    """
    sheet = Sheet(sheet_p4, refresh_cooldown=300)
    players = sheet.to_df('Players!A1:AH')
    players = players.loc[(players['Not Playing'] == "FALSE") & (
        players['Departed'] == "FALSE") & (~players['Team'].isin(
            ['Waitlist', 'Below MMR', 'Ineligible', 'Future Star', 'Banned']) &
                                           (players['Username'] != ''))]
    players.set_index('Username', inplace=True)

    processed_players: list[dict] = []

    for player in players.index:
        trackers = players.loc[player, 'Tracker']
        ids = get_ids_from_trackers(trackers)
        processed_players.append({
            "username": player,
            "ids": ids,
        })

    return processed_players
Exemple #3
0
    def __init__(self, refresh_cooldown: int = 30, session: Session = None):
        self.cooldown = refresh_cooldown

        if not session:
            self.session = Session()
        else:
            self.session = session
        
        self.sheet = Sheet(sheet_p4, refresh_cooldown=self.cooldown)
Exemple #4
0
 def __init__(self, p4sheet: Sheet = None, indysheet: Sheet = None):
     if not p4sheet:
         self.p4sheet = Sheet(sheet_p4)
     else:
         self.p4sheet = p4sheet
     if not indysheet:
         self.indysheet = Sheet(sheet_indy)
     else:
         self.indysheet = indysheet
Exemple #5
0
 def __init__(self, session: Session = None, p4sheet: Sheet = None):
     if not p4sheet:
         self.p4sheet = Sheet(sheet_p4)
     else:
         self.p4sheet = p4sheet
     if not session:
         self.session = Session()
     else:
         self.session = session
     self.ids = {}
     self.leagues = {}
     self.tracker_ids = {}
Exemple #6
0
 def __init__(self, session: Session = None, p4sheet: Sheet = None, identifier: Identifier = None):
     if not p4sheet:
         self.p4sheet = Sheet(sheet_p4)
     else:
         self.p4sheet = p4sheet
     if not session:
         self.session = Session()
     else:
         self.session = session
     if not identifier:
         self.identifier = Identifier()
     else:
         self.identifier = identifier
Exemple #7
0
    def __init__(self,
                 session: Session = None,
                 identifier: Identifier = None,
                 p4sheet: Sheet = None,
                 playersHandler: PlayersHandler = None) -> None:
        if not session:
            self.session = Session()
        else:
            self.session = session
        if not p4sheet:
            self.p4sheet = Sheet(sheet_p4)
        else:
            self.p4sheet = p4sheet
        if not identifier:
            self.identifier = Identifier(self.session, self.p4sheet)
        else:
            self.identifier = identifier
        if not playersHandler:
            self.playersHandler = PlayersHandler(self.session, self.p4sheet,
                                                 self.identifier)
        else:
            self.playersHandler = playersHandler

        self.failed = []
        self.unknown = []
Exemple #8
0
    def __init__(
        self,
        bot: Newsbot,
        session: Session = None,
        identifier: Identifier = None,
        p4sheet: Sheet = None,
        indysheet: Sheet = None,
        teams: TeamsHandler = None,
    ):
        self.bot = bot

        self.session = session if session else Session()
        self.identifier = identifier if identifier else Identifier()
        self.p4sheet = p4sheet if p4sheet else Sheet(sheet_p4)
        self.indysheet = indysheet if indysheet else Sheet(sheet_indy)
        self.teams = teams if teams else TeamsHandler(session=self.session,
                                                      p4sheet=self.p4sheet)
        self.streamsheet = Sheet(stream_sheet)

        super().__init__()
Exemple #9
0
    def __init__(
        self,
        bot: Newsbot,
        session: Session = None,
        p4sheet: Sheet = None,
        indysheet: Sheet = None,
        gdsheet: Sheet = None,
        identifier: Identifier = None,
        players: PlayersHandler = None,
        stats: StatsHandler = None,
        teams: TeamsHandler = None,
    ):
        self.bot = bot

        self.session = session if session else Session()
        self.p4sheet = p4sheet if p4sheet else Sheet(sheet_p4)
        self.indysheet = indysheet if indysheet else Sheet(sheet_indy)
        self.gdsheet = gdsheet if gdsheet else Sheet(gdstats_sheet)
        self.identifier = identifier if identifier else Identifier(session=self.session, p4sheet=self.p4sheet)
        self.players = players if players else PlayersHandler(session=self.session, p4sheet=self.p4sheet, identifier=self.identifier)
        self.teams = teams if teams else TeamsHandler(session=self.session)
        self.stats = stats if stats else StatsHandler(session=self.session, p4sheet=self.p4sheet, indysheet=self.indysheet, gdsheet=self.gdsheet, teams=self.teams, identifier=self.identifier)
Exemple #10
0
    def __init__(
        self,
        bot: commands.Bot,
        session: Session = None,
        identifier: Identifier = None,
        fc_sheet: Sheet = None,
        elo: EloHandler = None,
        poissonHandler: SheetsPoisson = None,
    ):
        self.bot = bot

        self.session = session if session else Session()
        self.identifier = identifier if identifier else Identifier(self.session)
        self.fc_sheet = fc_sheet if fc_sheet else Sheet(forecast_sheet)
        self.elo = elo if elo else EloHandler(session=self.session, identifier=self.identifier)
        self.poissonHandler = poissonHandler if poissonHandler else SheetsPoisson()
Exemple #11
0
 def __init__(
     self,
     bot,
     session: Session = None,
     fantasy: FantasyHandler = None,
     p4_sheet: Sheet = None,
 ):
     self.bot = bot
     if not p4_sheet:
         self.p4_sheet = Sheet(sheet_p4)
     else:
         self.p4_sheet = p4_sheet
     if not session:
         self.session = Session()
     else:
         self.session = session
     if not fantasy:
         self.fantasy = FantasyHandler(self.session)
     else:
         self.fantasy = fantasy
Exemple #12
0
 def __init__(self,
              session: Session = None,
              p4sheet: Sheet = None,
              indysheet: Sheet = None,
              powerrankings: Sheet = None,
              gdsheet: Sheet = None,
              teams: rlpc.players.TeamsHandler = None,
              identifier: rlpc.players.Identifier = None):
     if not session:
         self.session = Session()
     else:
         self.session = session
     if not p4sheet:
         self.p4sheet = Sheet(sheet_p4)
     else:
         self.p4sheet = p4sheet
     if not indysheet:
         self.indysheet = Sheet(sheet_indy)
     else:
         self.indysheet = indysheet
     if not powerrankings:
         self.powerrankings = Sheet(power_rankings_sheet)
     else:
         self.powerrankings = powerrankings
     if not gdsheet:
         self.gdsheet = Sheet(gdstats_sheet)
     else:
         self.gdsheet = gdsheet
     if not teams:
         self.teams = rlpc.players.TeamsHandler(session=self.session)
     else:
         self.teams = teams
     if not identifier:
         self.identifier = rlpc.players.Identifier(self.session,
                                                   self.p4sheet)
     else:
         self.identifier = identifier
Exemple #13
0
    def from_db_old(cls, id: ObjectId, session: Session, sheet: Sheet) -> Player:
        doc = session.players.find_one({"_id": id})
        team = session.teams.find_one({"_id": doc['info']['team']})
        if team:
            team_data = TeamData(
                    team['team'],
                    League.from_str(team['league']),
                    17,
                    JoinMethod.OTHER,
                    None,
                    LeaveMethod.OTHER
                )
        else:
            team_data = None
        players_df = sheet.to_df('Players!A1:Z').drop_duplicates(subset="Username").set_index("Username")
        links = players_df.loc[doc['username'], "Tracker"]

        return Player(
            players_df.loc[doc['username'], 'Discord ID'],  # Some of the ids in the database were wrong for some reason
            doc['username'],
            None,
            doc['info']['id'],
            links.split(', '),
            Region.from_str(doc['info']['region']),
            Platform.from_str(doc['info']['platform']),
            MMRData(doc['info']['mmr'], doc['info']['mmr'], {datetime.now().strftime("%m/%d/%y"): doc['info']['mmr']}),
            team['team'] if team else doc['info']['team'],
            [team_data],
            [PlayerSeason(
                17, 
                [team_data],
                Stats.from_db_old(doc),
                Stats(),
                [],
                False,
                False,
                False,
            )]
        )
Exemple #14
0
    def log_data(self, stats: pd.DataFrame, range: str):
        def get_league(row):
            try:
                league = self.identifier.find_league(
                    self.identifier.find_team([row.name]))
                if not league:
                    return "Unknown"
                else:
                    return league
            except:
                return "Unknown"

        if 'League' not in stats.columns:
            stats['Fantasy Points'] = stats.apply(
                lambda row: fantasy_formula(row), axis=1)
            stats['League'] = stats.apply(lambda row: get_league(row), axis=1)

        known = stats.loc[~stats['Username'].isin(self.unknown)]
        unknown = stats.loc[stats['Username'].isin(self.unknown)]

        sheet = Sheet(gdstats_sheet)
        sheet.push_df(range, known.reset_index().fillna(value=0))
        sheet.push_df("Failed Players!A2:Z",
                      unknown.reset_index().fillna(value=0))
Exemple #15
0
def season2():
    s2_sheet = Sheet('1fjXBT93zTRSHSWnG01G7Q1EAxIeXOiftGHfNAqU09a4')
    games = []

    # Get Major players on each team
    major_players = s2_sheet.to_df('Major League Player Sheet !A4:K51')
    for row in major_players.index:
        if major_players.loc[row, "Team Name"] == "":
            major_players.loc[row,
                              "Team Name"] = major_players.loc[row - 1,
                                                               "Team Name"]
    major_players['Team Name'] = major_players['Team Name'].str.strip()
    major_players = major_players.loc[(major_players['Gamertag'] != '') & (
        major_players['ODC Confirmed'] != "Coach") &
                                      (major_players['Sub'] != "Yes")]
    major_players['MMR'] = major_players['MMR'].str.replace(',',
                                                            '').astype(int)
    major_players = major_players.loc[major_players['MMR'] > 805]

    # Get Major schedule
    major_schedule = s2_sheet.to_df('Major League Schedule!A3:D102')
    major_schedule = major_schedule.loc[major_schedule['Score'].str.len() == 3]
    major_schedule['Winner'] = major_schedule['Winner'].str.strip()
    major_schedule['Teams Playing'] = major_schedule[
        'Teams Playing'].str.strip()

    for i in major_schedule.index:
        row = major_schedule.loc[i]
        teams = row['Teams Playing'].split(' vs. ')
        if i == 2:
            teams = row['Teams Playing'].split(' vs ')  # Annoying misspelling
        game_3 = row['Score'][-1] == 1
        winner = row['Winner']
        loser = teams[1] if teams[0] == row['Winner'] else teams[0]

        series = {
            'league': 'major',
            'teams': teams,
            'score': {
                winner: 2,
                loser: 1 if game_3 else 0
            },
            'games': [],
        }

        # Games 1 and 2 are the winner's wins
        series['games'].append({
            'winner': winner,
            teams[0]: {
                'players':
                list(major_players.loc[major_players['Team Name'] == teams[0],
                                       'Gamertag'].values),
                'goals':
                1 if winner == teams[0] else 0
            },
            teams[1]: {
                'players':
                list(major_players.loc[major_players['Team Name'] == teams[1],
                                       'Gamertag'].values),
                'goals':
                1 if winner == teams[1] else 0
            }
        })

        # Do this again for game 2
        series['games'].append({
            'winner': winner,
            teams[0]: {
                'players':
                list(major_players.loc[major_players['Team Name'] == teams[0],
                                       'Gamertag'].values),
                'goals':
                1 if winner == teams[0] else 0
            },
            teams[1]: {
                'players':
                list(major_players.loc[major_players['Team Name'] == teams[1],
                                       'Gamertag'].values),
                'goals':
                1 if winner == teams[1] else 0
            }
        })

        # Add the loser's game if it went to game 3
        if game_3:
            series['games'].append({
                'winner':
                teams[1] if teams[0] == winner else teams[0],
                teams[0]: {
                    'players':
                    list(major_players.loc[major_players['Team Name'] ==
                                           teams[0], 'Gamertag'].values),
                    'goals':
                    1 if winner == teams[1] else 0
                },
                teams[1]: {
                    'players':
                    list(major_players.loc[major_players['Team Name'] ==
                                           teams[1], 'Gamertag'].values),
                    'goals':
                    1 if winner == teams[0] else 0
                }
            })

        games.append(series)

    # Get Minor players on each team
    minor_players = s2_sheet.to_df('Minor League Player Sheet!A4:K51')
    for row in minor_players.index:
        if minor_players.loc[row, "Team Name"] == "":
            minor_players.loc[row,
                              "Team Name"] = minor_players.loc[row - 1,
                                                               "Team Name"]
    minor_players['Team Name'] = minor_players['Team Name'].str.strip()
    minor_players = minor_players.loc[(minor_players['Gamertag'] != '') & (
        minor_players['ODC Confirmed'] != "Coach") &
                                      (minor_players['Sub'] != "Yes")]
    minor_players['MMR'] = minor_players['MMR'].str.replace(',',
                                                            '').astype(int)

    # Get Minor schedule
    minor_schedule = s2_sheet.to_df('Minor League Schedule!A3:D102')
    minor_schedule = minor_schedule.loc[minor_schedule['Score'].str.len() == 3]
    minor_schedule['Winner'] = minor_schedule['Winner'].str.strip()
    minor_schedule['Teams Playing'] = minor_schedule[
        'Teams Playing'].str.strip()

    for i in minor_schedule.index:
        row = minor_schedule.loc[i]
        teams = row['Teams Playing'].split(' vs. ')
        if '.' not in row['Teams Playing']:
            teams = row['Teams Playing'].split(' vs ')  # Annoying misspelling
        game_3 = row['Score'][-1] == 1
        winner = row['Winner']
        loser = teams[1] if teams[0] == row['Winner'] else teams[0]

        series = {
            'league': 'minor',
            'teams': teams,
            'score': {
                winner: 2,
                loser: 1 if game_3 else 0
            },
            'games': [],
        }

        # Games 1 and 2 are the winner's wins
        series['games'].append({
            'winner': winner,
            teams[0]: {
                'players':
                list(minor_players.loc[minor_players['Team Name'] == teams[0],
                                       'Gamertag'].values),
                'goals':
                1 if winner == teams[0] else 0
            },
            teams[1]: {
                'players':
                list(minor_players.loc[minor_players['Team Name'] == teams[1],
                                       'Gamertag'].values),
                'goals':
                1 if winner == teams[1] else 0
            }
        })

        # Do this again for game 2
        series['games'].append({
            'winner': winner,
            teams[0]: {
                'players':
                list(minor_players.loc[minor_players['Team Name'] == teams[0],
                                       'Gamertag'].values),
                'goals':
                1 if winner == teams[0] else 0
            },
            teams[1]: {
                'players':
                list(minor_players.loc[minor_players['Team Name'] == teams[1],
                                       'Gamertag'].values),
                'goals':
                1 if winner == teams[1] else 0
            }
        })

        # Add the loser's game if it went to game 3
        if game_3:
            series['games'].append({
                'winner':
                teams[1] if teams[0] == winner else teams[0],
                teams[0]: {
                    'players':
                    list(minor_players.loc[minor_players['Team Name'] ==
                                           teams[0], 'Gamertag'].values),
                    'goals':
                    1 if winner == teams[1] else 0
                },
                teams[1]: {
                    'players':
                    list(minor_players.loc[minor_players['Team Name'] ==
                                           teams[1], 'Gamertag'].values),
                    'goals':
                    1 if winner == teams[0] else 0
                }
            })

        games.append(series)

    return games
Exemple #16
0
from errors.sheets_errors import ClearValuesError, GetSheetError, NoPermissionError, PushDfError
import unittest

from googleapiclient.errors import HttpError
from tools.sheet import Sheet
import settings
import pandas as pd

p4 = Sheet(settings.sheet_p4)
indy = Sheet(settings.sheet_indy)
test = Sheet(settings.test_sheet)
invalid = Sheet('1h2GnudOmd8-86vvOfSPAX5TXFHN5PkflKgl94evhhDs')


class TestSheet(unittest.TestCase):
    def test_get(self):
        self.assertIsNotNone(p4.get("Players!A1:H"))
        self.assertIsNotNone(indy.get("Players!A1:H"))

    def test_no_perms(self):
        self.assertRaises(GetSheetError, invalid.get, "a1:b")

    def test_get_cache(self):
        p4.get("Players!A1:H")

    def test_to_df(self):
        df = p4.to_df("Players!A1:H")
        self.assertEqual(df.columns.to_list(), [
            'Username', 'Region', 'Platform', 'Sheet MMR', 'Team', 'League',
            'Conf', 'Div'
        ])
Exemple #17
0
class PlayersHandler:
    def __init__(self, session: Session = None, p4sheet: Sheet = None, identifier: Identifier = None):
        if not p4sheet:
            self.p4sheet = Sheet(sheet_p4)
        else:
            self.p4sheet = p4sheet
        if not session:
            self.session = Session()
        else:
            self.session = session
        if not identifier:
            self.identifier = Identifier()
        else:
            self.identifier = identifier

    def move_teams(self, id: str, old: str, new: str, join_method: models.JoinMethod = models.JoinMethod.OTHER, leave_method: models.LeaveMethod = models.LeaveMethod.OTHER):
        player_doc = self.session.all_players.find_one({"_id": id})
        old_doc = self.session.teams.find_one({"_id": old})
        new_doc = self.session.teams.find_one({"_id": new})
        if old_doc and new_doc:
            leave_method = models.LeaveMethod.TRADE
            join_method = models.JoinMethod.TRADE

        new_team = {
                    "name": new,
                    "league": self.identifier.find_league(new),
                    "join_season": current_season,
                    "join_method": join_method.value,
                    "leave_season": None,
                    "leave_method": None
                }
        new_player = {
                    "playerid": id,
                    "join_date": datetime.now(),
                    "join_method": join_method.value,
                    "leave_date": None,
                    "leave_method": None
                }

        if not player_doc['team_history']:
            self.session.all_players.update_one({"_id": id}, {
                "$set": {"team_history": []}
            })

        # Update player
        self.session.all_players.find_one_and_update({"_id": id}, {
            "$set": {
                "current_team": new,
            }
        })
        if old_doc:
            if not player_doc['team_history']:
                team_history_basic = {
                        "name": old,
                        "league": old_doc['league'],
                        "join_season": current_season,
                        "join_method": None,
                        "leave_season": None,
                        "leave_method": None,
                    }
                self.session.all_players.update_one({"_id": id}, {
                    "$push": {"team_history": team_history_basic}
                })
                player_doc['team_history'] = [team_history_basic]
            self.session.all_players.find_one_and_update({"_id": id}, {
                "$set": {
                    f"team_history.{len(player_doc['team_history']) - 1}.leave_season": current_season,
                    f"team_history.{len(player_doc['team_history']) - 1}.leave_method": leave_method.value,
                    "seasons.$[season].teams.$[team].leave_season": current_season,
                    "seasons.$[season].teams.$[team].leave_method": leave_method.value,
                }}, array_filters = [{'season.season_num': current_season}, {"team.name": old, "team.leave_season": None}])
        if new_doc:
            self.session.all_players.find_one_and_update({"_id": id}, {
                "$push": {
                    "seasons.$[season].teams": new_team,
                    "team_history": new_team,
                }
            }, array_filters = [{'season.season_num': current_season}])
        
        # Update old team (assuming the old team isn't a non-playing team)
        if old_doc:
            self.session.teams.find_one_and_update({"_id": old}, {
                "$pull": {"current_players": id},
                "$push": {"previous_players": id},
                "$set": {
                    "seasons.$[season].players.$[player].leave_date": datetime.now(),
                    "seasons.$[season].players.$[player].leave_method": leave_method.value,
                }
            }, array_filters = [{'season.season_num': current_season}, {"player.playerid": id, "player.leave_date": None}])

        # Update new team (assuming the new team isn't a non_playing team)
        if new_doc:
            self.session.teams.find_one_and_update({"_id": new}, 
            {
                "$push": {
                    "current_players": id,
                    "seasons.$[season].players": new_player
                }
            }, array_filters = [{"season.season_num": current_season}])

    def check_players(self):
        """
        Compares the rlpc sheet to the database to ensure that all players are present and have accurate info

        Returns
        -------
        None.

        """

        logger.info("Checking players...")
        sheetdata = self.p4sheet.to_df("Players!A1:AG")
        sheetdata['Unique IDs'] = sheetdata['Unique IDs'].map(lambda x: x.split(","))
        sheetdata['Tracker'] = sheetdata['Tracker'].map(lambda x: x.split(', '))
        sheetdata['Sheet MMR'] = sheetdata['Sheet MMR'].map(lambda x: int(x))
        sheetdata['Tracker MMR'] = sheetdata['Tracker MMR'].map(lambda x: int(x))
        sheetdata = sheetdata.loc[sheetdata['Username'] != ""]
        sheetdata = sheetdata.loc[sheetdata['Team'] != "N/A"] # This should never happen unless sheets team puts it here, /shrug
        sheetdata = sheetdata.loc[sheetdata['Departed'] != "TRUE"]
        sheetdata = sheetdata.loc[sheetdata['Not Playing'] != "TRUE"]
        sheetdata = sheetdata.set_index('Discord ID')

        all_players = self.session.all_players
        teams = self.session.teams

        # NEW CHECKS
        for discord_id in sheetdata.index:
            player: str = sheetdata.loc[discord_id, 'Username']

            # First check if the player is already in the database
            doc = self.session.all_players.find_one({"_id": discord_id})

            # If the player is not in the database, add them as a player
            if doc == None:
                logger.debug(f"Adding {player} to database")
                data = models.Player(
                    _id = discord_id,
                    username = player,
                    league = sheetdata.loc[discord_id, 'League'],
                    date_joined = datetime.now(),
                    rl_id = sheetdata.loc[discord_id, 'Unique IDs'],
                    tracker_links = sheetdata.loc[discord_id, 'Tracker'],
                    region = models.Region.from_str(sheetdata.loc[discord_id, 'Region']),
                    platform = models.Platform.from_str(sheetdata.loc[discord_id, 'Platform']),
                    mmr = models.MMRData(sheetdata.loc[discord_id, 'Sheet MMR'], sheetdata.loc[discord_id, 'Tracker MMR'], {datetime.now().strftime("%m/%d/%y"): sheetdata.loc[discord_id, 'Tracker MMR']}), 
                    current_team = sheetdata.loc[discord_id, 'Team'],
                    team_history = None,
                    seasons = None              # Will be added later in this function if needed
                ).insert_new(self.session)
            
            # Otherwise, check fields to see if any of them changed
            else:
                data = models.Player.from_db(doc)

                if not data.league:
                    all_players.find_one_and_update({"_id": discord_id}, {"$set": {"league": sheetdata.loc[discord_id, 'League']}})

                # Season doesn't exist
                if not data.seasons:
                    season = models.PlayerSeason(
                        season_num = current_season, 
                        teams = [],
                        season_stats = models.Stats(),
                        playoff_stats = models.Stats(),
                        games = [], 
                        made_playoffs = False, 
                        finalists = False, 
                        champions = False
                    )
                    data.seasons = [season]
                    season_dict = season.to_dict()
                    all_players.find_one_and_update({"_id": discord_id}, {"$set": {"seasons": [season_dict]}})
                    logger.debug(f"{player} has joined this season.")

                elif filter(lambda x: x.season_num == current_season, data.seasons) == 0:
                    season = models.PlayerSeason(
                        season_num = current_season, 
                        teams = [],
                        season_stats = models.Stats(),
                        playoff_stats = models.Stats(),
                        games = [], 
                        made_playoffs = False, 
                        finalists = False, 
                        champions = False
                    )
                    data.seasons = [*data.seasons, season]
                    season_dict = season.to_dict()
                    all_players.find_one_and_update({"_id": discord_id}, {"$push": {"seasons": season_dict}})
                    logger.debug(f"{player} has joined this season.")

                # Username
                if data.username != player:
                    data.username = player
                    all_players.find_one_and_update({"_id": discord_id}, {"$set": {"username": player}})
                    logger.debug(f"{data.username} has changed their name to {player}")

                # League
                league = sheetdata.loc[discord_id, 'League']
                if data.league != league and league.lower() not in ("below mmr", "future star"):
                    data.league = models.League.from_str(league)
                    all_players.find_one_and_update({"_id": discord_id}, {"$set": {"league": league}})
                    logger.debug(f"{player} has changed league to {data.league}.")

                # rl ids
                for playerid in sheetdata.loc[discord_id, 'Unique IDs']:
                    if playerid == '':
                        continue # No ids are available, so just ignore
                    elif playerid not in data.rl_id:
                        data.rl_id.append(playerid)
                        all_players.find_one_and_update({"_id": discord_id}, {"$push": {"rl_id": playerid}})
                        logger.debug(f"Added id '{playerid}' for {player}")

                # tracker links
                for tracker in sheetdata.loc[discord_id, 'Tracker']:
                    if tracker == '':
                        continue # No trackers are available, so just ignore
                    elif tracker not in data.tracker_links:
                        data.tracker_links.append(tracker)
                        all_players.find_one_and_update({"_id": discord_id}, {"$push": {"tracker_links": tracker}})
                        logger.debug(f"Added tracker {tracker} for {player}")

                # Region
                if data.region != models.Region.from_str(sheetdata.loc[discord_id, 'Region']):
                    data.region = models.Region.from_str(sheetdata.loc[discord_id, 'Region'])
                    all_players.find_one_and_update({"_id": discord_id}, {"$set": {"region": sheetdata.loc[discord_id, 'Region']}})
                    logger.debug(f"Moved {player} to {data.region}")

                # Platform
                if data.platform != models.Platform.from_str(sheetdata.loc[discord_id, 'Platform']):
                    data.platform = models.Platform.from_str(sheetdata.loc[discord_id, 'Platform'])
                    all_players.find_one_and_update({"_id": discord_id}, {"$set": {"platform": sheetdata.loc[discord_id, 'Platform']}})
                    logger.debug(f"Switched {player} to {data.platform}")

                # MMR
                if data.mmr.current_official_mmr != sheetdata.loc[discord_id, 'Sheet MMR']:
                    data.mmr.current_official_mmr = sheetdata.loc[discord_id, 'Sheet MMR']
                    all_players.find_one_and_update({"_id": discord_id}, {"$set": {"mmr.current_official_mmr": sheetdata.loc[discord_id, 'Sheet MMR'].item()}})
                    logger.debug(f"Updated {player}'s Sheet MMR to {data.mmr.current_official_mmr}")

                # Team
                if data.current_team != sheetdata.loc[discord_id, 'Team']:
                    old = data.current_team
                    new = sheetdata.loc[discord_id, 'Team']
                    data.current_team = new
                    self.move_teams(discord_id, old, new)

        self.remove_not_playing()
        logger.info("Done checking players.")

    def remove_not_playing(self):
        """Changes team of anyone listed on the sheet as "Not Playing" or "Departed"

        Returns:
            None
        """
        sheetdata = self.p4sheet.to_df("Players!A1:AG")

        sheetdata = sheetdata.drop_duplicates(subset='Username')
        sheetdata = sheetdata.loc[sheetdata['Username'] != ""]
        sheetdata.set_index("Username", inplace=True)
        not_playing = sheetdata.loc[sheetdata['Not Playing'] == "TRUE"]
        departed = sheetdata.loc[sheetdata['Departed'] == "TRUE"]

        logger.info("NOT PLAYING")
        for player in not_playing.index:
            discord_id: str = not_playing.loc[player, 'Discord ID']
            doc = self.session.all_players.find_one({'_id': discord_id})
            if doc == None:
                continue
            if doc['current_team'] != "Not Playing":
                self.move_teams(discord_id, doc['current_team'], "Not Playing", models.JoinMethod.OTHER, models.LeaveMethod.NONPLAYING)
        
        logger.info("DEPARTED")
        for player in departed.index:
            discord_id: str = departed.loc[player, 'Discord ID']
            doc = self.session.all_players.find_one({'_id': discord_id})
            if doc == None:
                continue
            if doc['current_team'] != "Departed":
                self.move_teams(discord_id, doc['current_team'], "Departed", models.JoinMethod.OTHER, models.LeaveMethod.NONPLAYING)
Exemple #18
0
class Identifier:
    def __init__(self, session: Session = None, p4sheet: Sheet = None):
        if not p4sheet:
            self.p4sheet = Sheet(sheet_p4)
        else:
            self.p4sheet = p4sheet
        if not session:
            self.session = Session()
        else:
            self.session = session
        self.ids = {}
        self.leagues = {}
        self.tracker_ids = {}

    @staticmethod
    def is_discord_id(string: str) -> bool:
        if len(string) in (17, 18) and string.isnumeric():
            return True
        else:
            return False

    def identify(self, id: str) -> str:
        """
        Determines which player matches a given ID

        Parameters
        ----------
        id : str
            The unique Rocket Leauge ID of any given player.

        Returns
        -------
        str
            The name of the player as spelled on the RLPC Spreadsheet.

        """
        if self.ids.get(id):
            return self.ids.get(id)

        player = self.session.all_players.find_one({'rl_id': id})
        if not player:
            return None
        else:
            self.ids[id] = player['username']
            return player['username']

    def find_team(self, names: list, id_players: bool = False, choices: list = None) -> str:
        """
        Determines which team most likely matches a given set of three players

        Parameters
        ----------
        names : list
            List of player names (should be verified as the same on the sheet before using find_team()).
        id_players : bool
            Whether or not this function should identify players first (if given a list of ids rather than names)
        choices : list
            A list of possible teams that this can be. This is used to find the correct team in case of subs or call downs

        Returns
        -------
        str
            Team name.

        """

        if id_players:
            new_names = []
            for id in names:
                name = self.identify(id)
                if not name:
                    continue
                new_names.append(name)
            names = new_names

        found_teams = []
        teams = self.p4sheet.to_df("Teams!F1:P129")

        for player in names:
            if self.is_discord_id(player):
                doc = self.session.all_players.find_one({"_id": player})
            else:
                doc = self.session.all_players.find_one({'username': player})
            team: str = doc['current_team']
            if team in ['Free Agent', 'Not Playing', 'Departed', 'Waitlist']:
                continue
            # Not sure why this was here, keeping it just in case
            # try:
            #     team = self.session.teams.find_one({'_id': team})
            # except TypeError:
            #     continue

            if choices:
                choice_league = self.find_league(choices[0])
                team_league = self.find_league(team)
                affiliate_columns = {
                    'Major': 'Major Affiliate',
                    'AAA': 'AAA Affiliate',
                    'AA': 'AA Affiliate',
                    'A': 'A Affiliate',
                    'Independent': 'Major Affiliate',
                    'Maverick': 'AAA Affiliate',
                    'Renegade': 'AA Affiliate',
                    'Paladin': 'A Affiliate'
                }
                if teams.loc[teams['Team'] == team, affiliate_columns[choice_league]].values[0] != '': # This player is from a different league, so is likely a sub
                    team = teams.loc[teams['Team'] == team, affiliate_columns[choice_league]].values[0]

            found_teams.append(team)

        for team in found_teams:
            if found_teams.count(team) > (len(found_teams)/2):
                return team  # This will return if more than half of the players are on the same team

        return "Undetermined"  # If every player belongs to a different team

    def find_league(self, team: str) -> str:
        """
        Finds out what league a team plays in

        Parameters
        ----------
        team : str
            Name of the team.

        Returns
        -------
        str
            Name of the league.

        """

        team = team.title()

        if self.leagues.get(team):
            return self.leagues.get(team)

        if team in ['Not Playing', 'Departed', 'Waitlist', 'Free Agent', 'Undetermined']:
            return None

        doc = self.session.teams.find_one({"_id": team})
        self.leagues[team] = doc['league']
        return doc['league']

    def tracker_identify(self, name: str) -> str:
        """
        Finds a player's username based on the name used in-game by seeing if it matches any rltracker links

        Parameters
        ----------
        name : str
            The in-game name of a player.

        Returns
        -------
        str
            The name of the player as spelled on the RLPC Spreadsheet.

        """
        sheetdata = self.p4sheet.to_df('Players!A1:AE')
        player = sheetdata.loc[sheetdata['Tracker'].str.contains(name.replace(' ', '%20').replace('(', '\('), case=False), 'Username']
        try:
            return player.values[0]
        except:
            return None
Exemple #19
0
class TeamsHandler: 
    def __init__(self, refresh_cooldown: int = 30, session: Session = None):
        self.cooldown = refresh_cooldown

        if not session:
            self.session = Session()
        else:
            self.session = session
        
        self.sheet = Sheet(sheet_p4, refresh_cooldown=self.cooldown)

    def get_data(self, team: str) -> pd.Series:
        data = self.sheet.to_df('Teams!A1:AD129') # ALL the team data, not really necessary but good to have
        data.set_index("Team", inplace=True)
        team = team.title()
        try:
            data = data.loc[team]
        except KeyError:
            raise TeamNotFoundError(team)

        return data

    def get_gm(self, data: pd.Series) -> str:
        return data.loc['GM']

    def get_agm(self, data: pd.Series) -> str:
        return data.loc['AGM']

    def get_captain(self, data: pd.Series) -> str:
        captain = data.loc['Captain']
        if captain == '':
            return None
        else:
            return captain

    def get_league(self, data: pd.Series) -> str:
        return data.loc['League']

    def get_org(self, data: pd.Series) -> dict:
        system = data['League System']

        org = {
            'System': system,
            'Teams': []
        }
        org['Teams'] = data.loc['Organization Name'].split('/')

        return org

    def get_logo_url(self, data: pd.Series) -> str:
        # path = '/'.join(os.getcwd().split('\\')) + f"/Image_templates/RLPC_Logos/{team.title()}.png"
        # return path

        return data.loc['Logo']

    def get_roster(self, team: str) -> list:
        players = self.sheet.to_df("Players!A1:AG")
        players = players[players['Departed'] == "FALSE"]
        players = players[players['Not Playing'] == "FALSE"]
        players = players[players['Team'] == team.title()]
        players.drop_duplicates(subset="Username", inplace=True)

        roster = list(players['Username'].values)
        return roster
Exemple #20
0
    @classmethod
    def get(cls, id: str, session: Session) -> Stock_Account:
        doc = session.stock_accounts.find_one({"_id": id})
        if doc:
            return Stock_Account(
                _id = doc['_id'],
                username = doc['username'],
                balance = doc['balance'],
                portfolio_value = doc['portfolio_value'],
                value_history = doc['value_history'],
                portfolio = doc['portfolio'],
                transaction_history = doc['transaction_history']
            )
        else:
            raise AccountNotFoundError(id)

# Just for testing
if __name__ == '__main__':
    session = Session()
    sheet = Sheet(sheet_p4)
    # from rlpc.players import PlayersHandler, Identifier
    # identifier = Identifier(session, sheet)
    # playersHandler = PlayersHandler(session, sheet, identifier)

    # replay = BallchasingReplay(r"C:\Users\Simcha\Desktop\Projects\RLPC_Newsbot\replay_processing\Replay_Files\Ascension - Whitecaps\match_1\2BE561564317ECAC8E2FB6997E799D7E.replay", session, playersHandler, identifier)
    # Game.from_replay(replay, session)

    # cursor = session.all_players.find({{"current_team": {"$nin": ["Departed", "Not Playing"]}, "seasons.$[season]": {"$exists": True}}}, array)
    # while cursor.alive:
    #     player = cursor.next()
    #     print(player)
    def __init__(self, token: Literal = BOT_TOKEN):
        intents = discord.Intents.default()
        intents.message_content = True
        super().__init__(command_prefix=prefix, intents=intents, help_command=None, case_insensitive=True)

        self.session = Session()
        self.p4sheet = Sheet(sheet_p4, refresh_cooldown=60)
        self.fc_sheet = Sheet(forecast_sheet)
        self.indysheet = Sheet(sheet_indy, refresh_cooldown=60)
        self.gdsheet = Sheet(gdstats_sheet)
        self.pr_sheet = Sheet(power_rankings_sheet)
        self.identifier = Identifier(self.session, self.p4sheet)
        self.elo = EloHandler(self.session, self.identifier)
        self.fantasy = FantasyHandler(self.session)
        self.players = PlayersHandler(self.session, self.p4sheet, self.identifier)
        self.teams = TeamsHandler(session=self.session)
        self.stats = StatsHandler(
            session=self.session,
            p4sheet=self.p4sheet,
            indysheet=self.indysheet,
            powerrankings=self.pr_sheet,
            teams=self.teams,
            identifier=self.identifier,
        )

        self.token = token

        self.COGS = [
            Elo(
                self,
                session=self.session,
                identifier=self.identifier,
                fc_sheet=self.fc_sheet,
                elo=self.elo,
            ),
            # Fantasy(
            #     self, session=self.session, fantasy=self.fantasy, p4_sheet=self.p4sheet
            # ),
            Help(self),
            Links(self),
            Reddit(self),
            Stats(
                self,
                session=self.session,
                p4sheet=self.p4sheet,
                indysheet=self.indysheet,
                gdsheet=self.gdsheet,
                identifier=self.identifier,
                players=self.players,
                stats=self.stats,
                teams=self.teams,
            ),
            Stocks(
                self,
                session=self.session,
            ),
            Misc(
                self,
                session=self.session,
                identifier=self.identifier,
                p4sheet=self.p4sheet,
                indysheet=self.indysheet,
                teams=self.teams,
            ),
        ]
class Newsbot(commands.Bot):
    def __init__(self, token: Literal = BOT_TOKEN):
        intents = discord.Intents.default()
        intents.message_content = True
        super().__init__(command_prefix=prefix, intents=intents, help_command=None, case_insensitive=True)

        self.session = Session()
        self.p4sheet = Sheet(sheet_p4, refresh_cooldown=60)
        self.fc_sheet = Sheet(forecast_sheet)
        self.indysheet = Sheet(sheet_indy, refresh_cooldown=60)
        self.gdsheet = Sheet(gdstats_sheet)
        self.pr_sheet = Sheet(power_rankings_sheet)
        self.identifier = Identifier(self.session, self.p4sheet)
        self.elo = EloHandler(self.session, self.identifier)
        self.fantasy = FantasyHandler(self.session)
        self.players = PlayersHandler(self.session, self.p4sheet, self.identifier)
        self.teams = TeamsHandler(session=self.session)
        self.stats = StatsHandler(
            session=self.session,
            p4sheet=self.p4sheet,
            indysheet=self.indysheet,
            powerrankings=self.pr_sheet,
            teams=self.teams,
            identifier=self.identifier,
        )

        self.token = token

        self.COGS = [
            Elo(
                self,
                session=self.session,
                identifier=self.identifier,
                fc_sheet=self.fc_sheet,
                elo=self.elo,
            ),
            # Fantasy(
            #     self, session=self.session, fantasy=self.fantasy, p4_sheet=self.p4sheet
            # ),
            Help(self),
            Links(self),
            Reddit(self),
            Stats(
                self,
                session=self.session,
                p4sheet=self.p4sheet,
                indysheet=self.indysheet,
                gdsheet=self.gdsheet,
                identifier=self.identifier,
                players=self.players,
                stats=self.stats,
                teams=self.teams,
            ),
            Stocks(
                self,
                session=self.session,
            ),
            Misc(
                self,
                session=self.session,
                identifier=self.identifier,
                p4sheet=self.p4sheet,
                indysheet=self.indysheet,
                teams=self.teams,
            ),
        ]

    async def setup_hook(self):
        await self.load_cogs()

    async def load_cogs(self) -> None:
        for cog in self.COGS:
            await self.add_cog(cog)

    async def on_command_error(
        self, ctx: Context, error: discord.errors.DiscordException
    ):
        if isinstance(error, commands.NoPrivateMessage):
            await ctx.send("This command cannot be used in private messages.")
        elif isinstance(error, commands.DisabledCommand):
            await ctx.send("Sorry. This command is disabled and cannot be used.")
        elif isinstance(error, commands.CommandInvokeError):
            if isinstance(error.original, discord.errors.Forbidden):
                return await ctx.send(
                    "This bot doesn't have adequate permissions in this channel or server. You may need to re-invite the bot to your server: https://discord.com/api/oauth2/authorize?client_id=635188576446840858&permissions=380104723520&scope=applications.commands%20bot"
                )
            else:
                await self.log_error(
                    error.original, ctx.channel, ctx.command, ctx.kwargs
                )

    async def log_error(
        self,
        error: commands.CommandInvokeError,
        channel: discord.ChannelType,
        command: commands.Command,
        args: dict,
    ):
        await channel.send("There was an unexpected error using this command.")
        error_channel: discord.TextChannel = self.get_channel(862730357371305995)
        if isinstance(channel, discord.TextChannel):
            await error_channel.send(
                "**" + str(type(error)) + " in " + f"<#{channel.id}>" + "**"
            )
        elif isinstance(channel, discord.DMChannel):
            await error_channel.send(
                "**" + str(type(error)) + " in DM with " + channel.recipient.name + "**"
            )
        await error_channel.send(f"*Command: {command.name}*")
        await error_channel.send(error)
        await error_channel.send(args)

    async def on_ready(self):
        print("Logged in as")
        print(f"Username:  {self.user.name}")
        print(f"User ID:  {self.user.id}")
        print("---------------------------------")
        await self.change_presence(activity=discord.Game(f"Commands are slash commands now!"))

    async def on_message(self, message: discord.Message):
        if message.type.value == 0:
            if message.content.split()[0] in (
                '$schedule', '$stats', '$top', '$ts', '$gdstats'
            ):
                await message.reply("This bot has converted all commands to slash commands! Type '/' to see all of the slash commands available in this server. If you don't see any slash commands, you may need to reinvite the bot to your server: https://discord.com/api/oauth2/authorize?client_id=635188576446840858&permissions=380104723520&scope=applications.commands%20bot")

        channels = {
            598237603254239238: "Major",
            598237794762227713: "AAA",
            598237830824591490: "AA",
            598237861837537304: "A",
            715549072936796180: "Indy",
            715551351236722708: "Mav",
            757714221759987792: "Ren",
            757719107041755286: "Pal",
        }
        if int(message.channel.id) in list(channels):

            # Criteria is either 'record' or 'rating', followed by the threshold for an upset
            criteria, threshold = ("record", 4)

            # Parse messages
            league = channels[message.channel.id]

            if "forfeit" in message.content:
                return

            game = message.content.split("\n")[2:4]
            team1 = game[0].split(": ")[0]
            team1_score = int(game[0][-1])
            team2 = game[1].split(": ")[0]
            team2_score = int(game[1][-1])

            # This is needed to put records in alert_message, even if using rating for the criteria
            records = self.pr_sheet.to_df("Team Wins!A1:AE17")
            records = {
                "Major": records.iloc[:, 0:3],
                "AAA": records.iloc[:, 4:7],
                "AA": records.iloc[:, 8:11],
                "A": records.iloc[:, 12:15],
                "Indy": records.iloc[:, 16:19],
                "Mav": records.iloc[:, 20:23],
                "Ren": records.iloc[:, 24:27],
                "Pal": records.iloc[:, 28:31]
            }[league]

            records = records.set_index(f"{league} Teams")
            team1_record = (
                f"({records.loc[team1, 'Wins']}-{records.loc[team1, 'Losses']})"
            )
            team2_record = (
                f"({records.loc[team2, 'Wins']}-{records.loc[team2, 'Losses']})"
            )
            team1_wins = int(records.loc[team1, "Wins"])
            team2_wins = int(records.loc[team2, "Wins"])

            if criteria == "rating":
                team1_rating = self.elo.get_elo(team1)
                team2_rating = self.elo.get_elo(team2)

            upset = False
            if criteria == "record" and team2_wins - team1_wins >= threshold:
                upset = True
            elif criteria == "rating" and team2_rating - team1_rating >= threshold:
                upset = True

            # Send to #game-scores channel
            gamescores_channel = self.get_channel(836784966221430805)
            await gamescores_channel.send(
                f"**{league} result**\n{team1} {team1_record}: {team1_score}\n{team2} {team2_record}: {team2_score}"
            )

            descriptors = [
                "have taken down",
                "have defeated",
                "beat",
                "were victorious over",
                "thwarted",
                "have upset",
                "have overpowered",
                "got the better of",
                "overcame",
                "triumphed over",
            ]

            if upset:
                UPSET_ALERT_MESSAGE = f"""**UPSET ALERT**\n{team1} {team1_record} {choice(descriptors)} {team2} {team2_record} with a score of {team1_score} - {team2_score}"""

                # Send the message out to subscribed channels
                await self.wait_until_ready()
                send_to = self.session.admin.find_one({"purpose": "channels"})[
                    "channels"
                ]["upset_alerts"]

                for channel in send_to:
                    channel: discord.TextChannel = self.get_channel(int(channel))

                    if channel == None:
                        continue

                    new_message = UPSET_ALERT_MESSAGE

                    for role in channel.guild.roles:
                        role: discord.Role
                        if role.name.lower() == "upset alerts":
                            new_message += (
                                f"\n{role.mention}"
                            )
                    #await channel.send(new_message) (TEMPORARILY DISABLED)
        await self.process_commands(message)

    async def close(self):
        await super().close()
        self.session.close()

    def run(self):
        # return await super().start(self.token, reconnect=True)
        super().run(self.token, reconnect=True)
Exemple #23
0
class StatsHandler:
    def __init__(self,
                 session: Session = None,
                 p4sheet: Sheet = None,
                 indysheet: Sheet = None,
                 powerrankings: Sheet = None,
                 gdsheet: Sheet = None,
                 teams: rlpc.players.TeamsHandler = None,
                 identifier: rlpc.players.Identifier = None):
        if not session:
            self.session = Session()
        else:
            self.session = session
        if not p4sheet:
            self.p4sheet = Sheet(sheet_p4)
        else:
            self.p4sheet = p4sheet
        if not indysheet:
            self.indysheet = Sheet(sheet_indy)
        else:
            self.indysheet = indysheet
        if not powerrankings:
            self.powerrankings = Sheet(power_rankings_sheet)
        else:
            self.powerrankings = powerrankings
        if not gdsheet:
            self.gdsheet = Sheet(gdstats_sheet)
        else:
            self.gdsheet = gdsheet
        if not teams:
            self.teams = rlpc.players.TeamsHandler(session=self.session)
        else:
            self.teams = teams
        if not identifier:
            self.identifier = rlpc.players.Identifier(self.session,
                                                      self.p4sheet)
        else:
            self.identifier = identifier

    def capitalize_username(self, username: str) -> List[str]:
        try:
            players = self.p4sheet.to_df('Players!A1:I')
        except SheetToDfError:
            raise StatSheetError("Players!A1:I")

        lower_players = players['Username'].str.lower()
        if username.lower() in lower_players.values:
            pindex = lower_players[lower_players == username.lower()].index[0]
            player = players.loc[pindex][0]
        players = players.set_index("Username")
        try:
            league = players.loc[player, "League"]
        except UnboundLocalError:
            raise FindPlayersError(None, None)
        if type(league) == pd.Series:
            league = league[0]

        return player, league

    def get_player_stats_db(self,
                            player: str,
                            category: str = "all",
                            pergame: bool = False) -> pd.DataFrame:

        player, league = self.capitalize_username(player)
        db_stats = self.session.all_players.find_one({'username': player})
        if db_stats == None:
            raise PlayerNotFoundError(player, 0)
        stats = pd.DataFrame()
        stats.loc[0, 'Player'] = player

        if category not in statsCategories.keys() and category != "all":
            raise InvalidStatError(category)

        games = 1
        if pergame:
            games = max(
                db_stats['seasons'][-1]['season_stats']['games_played'], 1)

        if category == "all":
            for stat in statsCategories['general']:
                stats.loc[0, stat] = round(
                    db_stats['seasons'][-1]['season_stats'][snakecase_stat(
                        stat)] / games, 1)
        else:
            keys = statsCategories[category]
            for key in keys:
                stats.loc[0, key] = round(
                    db_stats['seasons'][-1]['season_stats'][snakecase_stat(
                        key)] / games, 1)

        return stats

    def get_player_stats_sheet(self,
                               player: str,
                               stat: str = "all") -> pd.DataFrame:
        """
        Gets the stats from the RLPC Spreadsheet for a given player

        parameters
        ---------
        player: str
            The player's username, as spelled on the sheet (case insentive)
        stat: (optional) str
            What stat(s) to return. "all" returns all stats, but a single stat can be specified.

        returns
        ------
        stats: pd.DataFrame
            Series containing player's stats
        """
        # Make sure the program understands the specified stat if it's mis-capitalized or whatever
        # TODO: Replace with structural pattern matching in python 3.10
        if stat.lower() in [
                "sp", "series", "series_played", "series-played", "splayed",
                "seris", "sieries", "seiries"
        ]:
            stat = "Series Played"
        elif stat.lower() in [
                "gp", "games", "games_played", "games-played", "gplayed"
        ]:
            stat = "Games Played"
        elif stat.lower() in ["goals", "goal", "scores"]:
            stat = "Goals"
        elif stat.lower() in ['assists', 'assist', 'passes']:
            stat = "Assists"
        elif stat.lower() in ['saves', 'save']:
            stat = "Saves"
        elif stat.lower() in ['shots', 'shot']:
            stat = "Shots"
        elif stat.lower() in [
                'points', 'point', 'goals+assists', 'goals + assists',
                'goals and assists'
        ]:
            stat = "Points (Goals+Assists)"
        elif stat.lower() in [
                'gpg', 'goals per game', 'goals pg', 'goals per'
        ]:
            stat = "Goals per game"
        elif stat.lower() in [
                'apg', 'assists per game', 'assists pg', 'assists per'
        ]:
            stat = "Assists per game"
        elif stat.lower() in [
                'spg', 'sapg', 'saves per game', 'saves pg', 'saves per'
        ]:
            stat = "Saves per game"
        elif stat.lower() in [
                'shot rate', 'shooting percent', 'shooting percentage',
                'shot accuracy', 'shooting accuracy', 'shooting %', 'shot %'
        ]:
            stat = "Shooting %"
        elif stat.lower() in [
                'win rate', 'winning rate', 'winning percent',
                'winning percentage'
        ]:
            stat = "Winning %"
        elif stat.lower() in ['wins', 'win']:
            stat = "Wins"
        elif stat.lower() in [
                'ppg', 'points per game', 'points pg', 'points per'
        ]:
            stat = "Points per Game"
        elif stat.lower() in [
                'shpg', 'shots per game', ' shots pg', 'shots per'
        ]:
            stat = "Shots Per Game"

        try:
            players = self.p4sheet.to_df('Players!A1:I')
        except SheetToDfError:
            raise StatSheetError("Players!A1:I")

        player, league = self.capitalize_username(player)

        try:
            stats = self.p4sheet.to_df(f"{league} League Stat Database!C3:R")
        except:
            raise StatSheetError(f"{league} League Stat Database!C3:R")

        if stat not in list(stats) and stat.lower() != "all":
            raise InvalidStatError(stat)

        stats = stats.loc[stats['Player'] == player]

        if stats.empty:
            raise StatsError(player, stat)

        if stat != "all":
            stats = stats[['Player', stat]]
        return stats

    def power_rankings(self, league: str) -> pd.DataFrame:
        """
        Gets the most recent power rankings for a given league from the power rankings sheet

        parameters
        ---------
        league: str
            What league to get power rankings for

        returns
        ---------
        rankings: pd.DataFrame
            Dataframe containing each team's rank and how many points they had
        """

        try:
            league = leagues[league.lower()]
        except:
            return "Could not understand league"

        start_rows = {
            'Major': 2,
            'AAA': 21,
            'AA': 40,
            'A': 59,
            'Independent': 78,
            'Maverick': 97,
            'Renegade': 116,
            'Paladin': 135
        }
        data_range = f'Rankings History!A{start_rows[league]}:M{start_rows[league]+16}'
        try:
            data = self.powerrankings.to_df(data_range).set_index('')
        except GetSheetError or SheetToDfError:
            raise PRSheetError(league)
        if data.empty:
            raise NoPRError(league)

        column = 1
        for i in range(12):
            if data.iloc[:, i].values[0] == '':
                column = i - 1
                break
            else:
                continue
        try:
            data.iloc[:, column] = data.iloc[:, column].apply(lambda x: int(x))
        except ValueError:
            raise NoPRError(league)
        rankings = data.iloc[:, column]
        rankings = rankings.sort_values(ascending=False)
        return rankings

    @staticmethod
    def season_index(doc, season=current_season):
        if isinstance(doc['seasons'], dict):
            doc['seasons'] = [
                doc['seasons']
            ]  # Fix strange behavior from pymongo that turns arrays with 1 value into objects

        # Get the index needed for the current season
        season_index = 0
        for i, season in enumerate(doc['seasons']):
            if season['season_num'] == season:
                season_index = i

        return season_index

    def statlb(self,
               useSheet: bool = False,
               league: str = "all",
               stat: str = "Goals",
               limit: int = 10,
               pergame: bool = False,
               asc: bool = False) -> pd.Series:
        """Gets a series containing a leaderboard for a given stat

        Args:
            useSheet (bool, optional): Whether to use stats from the sheet instead of database (League can't be "all" if True). Defaults to False.
            league (str, optional): Which league to get stats from. Defaults to "all".
            stat (str, optional): Which stat to look at. Defaults to "Goals".
            limit (int, optional): How many players to include on the leaderboard. Defaults to 10.
            pergame (bool, optional): Whether to divide stats by # games played. Defaults to False.

        Returns:
            pd.Series: Sorted series containing players and their stats
        """
        if useSheet == True and league == "all":
            raise StatsError(player=None, stat=stat)
        if league != "all":
            try:
                league = leagues[league.lower()]
            except:
                return f"Could not understand league {league}."

        compound_stats = {
            'Winning %': ['Games Won', 'Games Played'],
            'Shooting %': ['Goals', 'Shots'],
            'Shooting % Against': ['Goals Against', 'Shots Against'],
            'Points': ['Goals', 'Assists'],
            'MVP Rate': ['MVPs', 'Games Won'],
            '% Time Slow': ['Time Slow', 'Time Boost', 'Time Supersonic'],
            '% Time Boost': ['Time Slow', 'Time Boost', 'Time Supersonic'],
            '% Time Supersonic':
            ['Time Slow', 'Time Boost', 'Time Supersonic'],
            '% Time Ground': ['Time Ground', 'Time Low Air', 'Time High Air'],
            '% Time Low Air': ['Time Ground', 'Time Low Air', 'Time High Air'],
            '% Time High Air':
            ['Time Ground', 'Time Low Air', 'Time High Air'],
            '% Most Back':
            ['Time Most Back', 'Time Defensive Half', 'Time Offensive Half'],
            '% Most Forward': [
                'Time Most Forward', 'Time Defensive Half',
                'Time Offensive Half'
            ],
            '% Goals Responsible': ['Conceded When Last', 'Goals Against'],
            'Position Ratio': ['Time Infront Ball', 'Time Behind Ball'],
        }

        stat = stat.title()

        # Make sure the program understands the specified stat if it's mis-capitalized or whatever
        # SHEETS STATS
        if useSheet:
            if stat.lower() in [
                    "sp", "series", "series_played", "series-played",
                    "splayed", "seris", "sieries", "seiries"
            ]:
                stat = "Series Played"
            elif stat.lower() in [
                    "gp", "games", "games_played", "games-played", "gplayed"
            ]:
                stat = "Games Played"
            elif stat.lower() in ["goals", "goal", "scores"]:
                stat = "Goals"
            elif stat.lower() in ['assists', 'assist', 'passes']:
                stat = "Assists"
            elif stat.lower() in ['saves', 'save']:
                stat = "Saves"
            elif stat.lower() in ['shots', 'shot']:
                stat = "Shots"
            elif stat.lower() in [
                    'points', 'point', 'goals+assists', 'goals + assists',
                    'goals and assists'
            ]:
                stat = "Points (Goals+Assists)"
            elif stat.lower() in [
                    'gpg', 'goals per game', 'goals pg', 'goals per'
            ]:
                stat = "Goals per game"
            elif stat.lower() in [
                    'apg', 'assists per game', 'assists pg', 'assists per'
            ]:
                stat = "Assists per game"
            elif stat.lower() in [
                    'spg', 'sapg', 'saves per game', 'saves pg', 'saves per'
            ]:
                stat = "Saves per game"
            elif stat.lower() in [
                    'shot rate', 'shooting percent', 'shooting percentage',
                    'shot accuracy', 'shooting accuracy', 'shooting %',
                    'shot %'
            ]:
                stat = "Shooting %"
            elif stat.lower() in [
                    'win rate', 'winning rate', 'winning percent',
                    'winning percentage'
            ]:
                stat = "Winning %"
            elif stat.lower() in ['wins', 'win']:
                stat = "Wins"
            elif stat.lower() in [
                    'ppg', 'points per game', 'points pg', 'points per'
            ]:
                stat = "Points per Game"
            elif stat.lower() in [
                    'shpg', 'shots per game', ' shots pg', 'shots per'
            ]:
                stat = "Shots Per Game"
            else:
                raise InvalidStatError(stat)

            try:
                if league.lower() in ['major', 'aaa', 'aa', 'a']:
                    data = self.p4sheet.to_df(
                        f'{league} League Stat Database!C3:R')
                elif league.lower() in [
                        'independent', 'maverick', 'renegade', 'paladin'
                ]:
                    data = self.indysheet.to_df(f'{league} Stat Database!C3:R')
            except SheetToDfError:
                raise StatSheetError('{league} League Stat Database!C3:R')

            data.set_index("Player", inplace=True)
            data.replace(to_replace='', value='0', inplace=True)
            # Turn number strings into ints and floats
            for col in data.columns:
                try:
                    data[col] = data[col].astype(int)
                except:
                    try:
                        data[col] = data[col].astype(float)
                    except:
                        data[col] = data[col].str.rstrip('%').astype(float)

            lb = data[stat.title()]
            lb: pd.Series = lb[lb > 0]
            games_played = data['Games Played']

            if pergame:
                if stat in [
                        'Goals Per Game', 'Assists per game', 'Saves per game',
                        'Points per Game', 'Shots per Game', 'Winning %',
                        'Shooting %'
                ]:
                    pass  # These stats are already per game
                else:
                    lb = round(lb / games_played, 2)

        # DATABASE STATS
        else:
            if stat not in valid_stats and stat not in compound_stats.keys(
            ) and stat != 'Mvp Rate':
                raise InvalidStatError(stat)
            else:
                stat = stat.title()
                if stat == 'Mvp Rate':
                    stat = 'MVP Rate'

            players = self.session.players
            data = pd.Series(name=stat, dtype=float)
            stat_snake = snakecase_stat(stat)

            if stat not in compound_stats.keys():
                # category = findCategory(stat)
                # if not category:
                #     raise InvalidStatError(stat)

                try:
                    if league != "all":
                        cursor = self.session.all_players.aggregate([{
                            "$unwind":
                            "$seasons"
                        }, {
                            "$match": {
                                "league": league,
                                f"seasons.season_stats.{stat_snake}": {
                                    '$gt': 0
                                },
                                f"seasons.season_stats.games_played": {
                                    '$gt': 0
                                }
                            }
                        }])
                    else:
                        cursor = self.session.all_players.aggregate([{
                            "$unwind":
                            "$seasons"
                        }, {
                            "$match": {
                                f"seasons.season_stats.{stat_snake}": {
                                    '$gt': 0
                                },
                                f"seasons.season_stats.games_played": {
                                    '$gt': 0
                                }
                            }
                        }])
                except:
                    raise FindPlayersError(league, stat)

                # Iterate through cursor and get all players' stats
                while cursor.alive:
                    doc = cursor.next()

                    if isinstance(doc['seasons'], dict):
                        doc['seasons'] = [
                            doc['seasons']
                        ]  # Fix strange behavior from pymongo that turns arrays with 1 value into objects

                    # Get the index needed for the current season
                    season_index = self.season_index(doc)

                    if pergame:
                        data[doc['username']] = round(
                            (doc['seasons'][season_index]['season_stats']
                             [stat_snake] / doc['seasons'][season_index]
                             ['season_stats']["games_played"]), 2)
                    else:
                        data[doc['username']] = round(
                            doc['seasons'][season_index]['season_stats']
                            [stat_snake], 2)

                return data.sort_values(ascending=asc).head(limit)
            else:
                filter = {"seasons.season_num": current_season}
                if league != "all":
                    filter['league'] = league
                necessary = compound_stats[stat]
                for stat_name in necessary:
                    filter[
                        f'seasons.season_stats.{snakecase_stat(stat_name)}'] = {
                            '$gt': 0
                        }

                try:
                    cursor = self.session.all_players.aggregate([{
                        "$unwind":
                        "$seasons"
                    }, {
                        "$match":
                        filter
                    }])
                except:
                    raise FindPlayersError(league, stat)

                # Iterate throuch cursor and get all players' stats
                while cursor.alive:
                    info = cursor.next()

                    if isinstance(info['seasons'], dict):
                        info['seasons'] = [
                            info['seasons']
                        ]  # Fix strange behavior from pymongo that turns arrays with 1 value into objects

                    # Get the index needed for the current season
                    player_stats = info['seasons'][self.season_index(
                        info)]['season_stats']

                    if stat == 'Winning %':
                        datapoint = round((player_stats['games_won'] /
                                           player_stats['games_played']), 2)
                    elif stat == 'Shooting %':
                        datapoint = round(
                            (player_stats['goals'] / player_stats['shots']), 2)
                    elif stat == 'Shooting % Against':
                        datapoint = round((player_stats['goals_against'] /
                                           player_stats['shots_against']), 2)
                    elif stat == 'Points':
                        datapoint = round(
                            (player_stats['goals'] + player_stats['assists']),
                            2)
                        if pergame:
                            datapoint = round(
                                (datapoint / player_stats['games_played']), 2)
                    elif stat == 'MVP Rate':
                        datapoint = round(
                            player_stats['mvps'] / player_stats['games_won'],
                            2)
                    elif stat == '% Time Slow':
                        datapoint = round(
                            player_stats['time_slow'] /
                            (player_stats['time_slow'] +
                             player_stats['time_boost'] +
                             player_stats['time_supersonic']), 2)
                    elif stat == '% Time Boost':
                        datapoint = round(
                            player_stats['time_boost'] /
                            (player_stats['time_slow'] +
                             player_stats['time_boost'] +
                             player_stats['time_supersonic']), 2)
                    elif stat == '% Time Supersonic':
                        datapoint = round(
                            player_stats['time_supersonic'] /
                            (player_stats['time_slow'] +
                             player_stats['time_boost'] +
                             player_stats['time_supersonic']), 2)
                    elif stat == '% Time Ground':
                        datapoint = round(
                            player_stats['time_ground'] /
                            (player_stats['time_ground'] +
                             player_stats['time_low_air'] +
                             player_stats['time_high_air']), 2)
                    elif stat == '% Time Low Air':
                        datapoint = round(
                            player_stats['time_low_air'] /
                            (player_stats['time_ground'] +
                             player_stats['time_low_air'] +
                             player_stats['time_high_air']), 2)
                    elif stat == '% Time High Air':
                        datapoint = round(
                            player_stats['time_high_air'] /
                            (player_stats['time_ground'] +
                             player_stats['time_low_air'] +
                             player_stats['time_high_air']), 2)
                    elif stat == '% Most Back':
                        datapoint = round(
                            player_stats['time_most_back'] /
                            (player_stats['time_defensive_half'] +
                             player_stats['time_offensive_half']), 2)
                    elif stat == '% Most Forward':
                        datapoint = round(
                            player_stats['time_most_forward'] /
                            (player_stats['time_defensive_half'] +
                             player_stats['time_offensive_half']), 2)
                    elif stat == '% Goals Responsible':
                        datapoint = round(
                            player_stats['conceded_when_last'] /
                            player_stats['goals_against'], 2)
                    elif stat == 'Position Ratio':
                        datapoint = round(
                            player_stats['time_infront_ball'] /
                            player_stats['time_behind_ball'], 2)

                    data[info['username']] = datapoint

                return data.sort_values(ascending=asc).head(limit)

        return lb.sort_values(ascending=asc).head(limit)

    def get_me(self, discord_id: str) -> str:
        ids = self.p4sheet.to_df('Trackers!A1:B').set_index('Discord ID')
        try:
            player = ids.loc[discord_id, 'Username']
            if type(player) == pd.core.series.Series:
                player = player[0]
        except:
            raise FindMeError(discord_id)

        return player

    def gdstats(self,
                player: str,
                day: int = None,
                stat: str = None,
                pergame: bool = False) -> pd.DataFrame:
        if day == None:
            day = get_latest_gameday()

        try:
            datarange = dates[day]
        except KeyError:
            raise InvalidDayError(day)

        try:
            data = self.gdsheet.to_df(datarange).set_index("Username")
            data.loc[:, 'Series Played':
                     'Fantasy Points'] = data.loc[:, 'Series Played':
                                                  'Fantasy Points'].astype(
                                                      float)
        except SheetToDfError:
            raise GDStatsSheetError(day)

        lower_players: pd.Index = data.index.str.lower()
        if player.lower() in lower_players.values:
            pindex = np.where(lower_players.to_numpy() == player.lower())
            player = data.index[pindex].values[0]
        else:
            raise PlayerNotFoundError(player, day)

        stats_series = data.loc[player]
        if isinstance(stats_series, pd.DataFrame):
            stats_series = stats_series.sum()

        if pergame:
            stats_series[3:-1] = stats_series[3:-1].apply(
                lambda x: float(x)) / int(stats_series['Games Played'])
            stats_series[3:-1] = stats_series[3:-1].apply(
                lambda x: round(x, 2))

        return stats_series

    def teamstats(self, team: str = None, league: str = None) -> pd.DataFrame:
        if team != None:
            team = team.title()
            roster = self.teams.get_roster(team)
            league = self.identifier.find_league(team)
        elif league != None:
            league = leagues[league.lower()]

        sheet: Sheet
        if league in ['Major', 'AAA', 'AA', 'A']:
            sheet = self.p4sheet
        elif league in ['Independent', 'Maverick', 'Renegade', 'Paladin']:
            sheet = self.indysheet
        else:
            raise LeagueNotFoundError(team)

        if not team:
            stats = sheet.to_df(f"{league} Stats!D5:Q9").set_index("")
            stats = stats.append(
                sheet.to_df(f"{league} Stats!D12:Q16").set_index(""))
            stats = stats.append(
                sheet.to_df(f"{league} Stats!D20:Q24").set_index(""))
            stats = stats.append(
                sheet.to_df(f"{league} Stats!D27:Q31").set_index(""))
            stats.rename(columns={
                'Record (Div Record)': 'Record',
                'Forfeits': "FFs",
                'W/L Streak': 'Streak',
                'Winning %': 'Win %',
                'Goals | PG': 'Goals',
                'Assists | PG': 'Assists',
                'Saves | PG': 'Saves',
                'Shots | PG': 'Shots',
                r'%Goals Assisted': 'Assist %',
                'Shooting %': 'Shot %',
                'GA | PG': 'GA',
                'Shots Agnst  | PG': 'SA',
                'Opp Shooting %': 'Opp Shot %'
            },
                         inplace=True)
            return stats

        else:
            stats = pd.DataFrame()
            for player in roster:
                stats = stats.append(self.get_player_stats_sheet(player))

            stats.rename(columns={
                'Series Played': 'Series',
                'Games Played': 'Games',
                'Points (Goals+Assists)': 'Points',
                'Goals per game': 'GPG',
                'Assists per game': 'APG',
                'Saves per game': 'SPG',
                'Shooting %': 'Shot %',
                'Winning %': 'Win %',
                'Points per Game': 'PPG',
                'Shots Per Game': 'ShPG'
            },
                         inplace=True)

            return stats.set_index('Player')

    def difference(self, player: str, stat: str) -> List[float]:
        stat = stat.title()
        if stat not in valid_stats:
            raise InvalidStatError(stat)
        day = get_latest_gameday()

        player_info = self.session.players.find_one(
            {'$text': {
                '$search': f"\"{player}\""
            }})
        if player_info == None:
            raise PlayerNotFoundError(player, 0)
        else:
            total_stat = player_info['stats'][findCategory(stat)][stat]
            games_played = player_info['stats']['general']['Games Played']
            total_stat /= games_played

        while day > 0:
            try:
                recent_stat = self.gdstats(player, day, stat,
                                           pergame=True).loc[stat.title()]
                break
            except PlayerNotFoundError:
                day -= 1
                continue

        if day == 0:
            # Raise error if player has no stats on gdstats sheet
            raise PlayerNotFoundError(player, 0)

        if recent_stat == 0:
            diff = -1
        elif total_stat == 0:
            raise ZeroError()
        else:
            diff = (recent_stat - total_stat) / total_stat

        return (diff, total_stat, recent_stat)
Exemple #24
0
class Misc(commands.Cog, name="Misc"):
    def __init__(
        self,
        bot: Newsbot,
        session: Session = None,
        identifier: Identifier = None,
        p4sheet: Sheet = None,
        indysheet: Sheet = None,
        teams: TeamsHandler = None,
    ):
        self.bot = bot

        self.session = session if session else Session()
        self.identifier = identifier if identifier else Identifier()
        self.p4sheet = p4sheet if p4sheet else Sheet(sheet_p4)
        self.indysheet = indysheet if indysheet else Sheet(sheet_indy)
        self.teams = teams if teams else TeamsHandler(session=self.session,
                                                      p4sheet=self.p4sheet)
        self.streamsheet = Sheet(stream_sheet)

        super().__init__()

    @commands.command()
    @commands.is_owner()
    async def sync(self, ctx: Context) -> None:
        await self.bot.tree.sync()
        # await self.bot.tree.sync(guild=self.bot.get_guild(224552524173148171))
        await ctx.send("Synced!")

    @app_commands.command(name="ping")
    async def ping(self, interaction: discord.Interaction):
        """Shows the bot's latency"""
        await interaction.response.send_message(
            f"Pong! {round(self.bot.latency * 1000)}ms", ephemeral=True)

    @app_commands.command(name="upset_alerts")
    @has_permissions(manage_channels=True)
    async def upset_alerts(self, interaction: discord.Interaction) -> str:
        """Subscribes the given channel to upset alerts

        Args:
            ctx (Context): discord context object

        Returns:
            str: response sent in discord
        """
        async with interaction.channel.typing():
            channels = self.bot.session.admin.find_one(
                {"purpose": "channels"})["channels"]["upset_alerts"]

            if interaction.channel_id in channels:
                self.bot.session.admin.find_one_and_update(
                    {"purpose": "channels"},
                    {
                        "$pull": {
                            "channels.upset_alerts": interaction.channel_id
                        }
                    },
                )
                return await interaction.response.send_message(
                    "This channel will no longer receive alerts.")
            else:
                self.bot.session.admin.find_one_and_update(
                    {"purpose": "channels"},
                    {
                        "$push": {
                            "channels.upset_alerts": interaction.channel_id
                        }
                    },
                )
                return await interaction.response.send_message(
                    "This channel will now receive alerts!")
        return

    @upset_alerts.error
    async def upset_alerts_error(self, ctx: Context,
                                 error: commands.CommandError):
        if isinstance(error, commands.CheckFailure):
            return await ctx.send(
                "You don't have manage_channel perms for this server.")

    @app_commands.command(name="schedule")
    async def schedule(self, interaction: discord.Interaction, *, team: str):
        """Shows the schedule for any team.

        Args:
            team (str): Team name
        """
        async with interaction.channel.typing():
            team: str = team.title()

            if team not in divisions.keys():
                return await interaction.response.send_message(
                    f"Couldn't find team `{team}`", ephemeral=True)

            league: str = self.identifier.find_league(team)

            sheet: Sheet = (self.p4sheet if league.lower()
                            in ["major", "aaa", "aa", "a"] else self.indysheet)

            all_games: pd.DataFrame = sheet.to_df(f"{league} Schedule!O4:X188")
            if all_games.empty:
                return await interaction.response.send_message(
                    "Schedules couldn't be found, possibly because they aren't on the sheet. Contact arco if you believe this is an error."
                )

            # If any non-preseason results are in, get rid of the preseason games
            if 'N' in all_games[all_games['Score'] != ""]['Preseason'].values:
                all_games = all_games[all_games['Preseason'] == "N"]

            all_games.columns.values[3] = "Team 1"
            all_games.columns.values[5] = "Team 2"
            all_games.columns.values[8] = "Logs"
            all_games.drop(
                columns=["Preseason", "Playoff", "Game Logs Processed"],
                inplace=True)

            schedule: pd.DataFrame = all_games.loc[(
                all_games["Team 1"] == team) | (all_games["Team 2"] == team)]
            schedule.set_index("Day", drop=True, inplace=True)

            dfi.export(schedule, "schedule.png", table_conversion="matplotlib")
            path = os.path.abspath("schedule.png")
            file = discord.File(path)
            await interaction.response.send_message(file=file)
            file.close()
            return os.remove(path)

    @app_commands.command(name="roster")
    async def roster(self, interaction: discord.Interaction, *, team: str):
        """Shows a team's roster as well as other useful information about the team

        Args:
            team (str): Team name
        """
        async with interaction.channel.typing():
            try:
                data = self.teams.get_data(team)
            except TeamNotFoundError:
                return await interaction.response.send_message(
                    f"Couldn't find team: {team}", ephemeral=True)

            embed = discord.Embed(title=team.title(), color=0x00008B)
            embed.set_thumbnail(url=self.teams.get_logo_url(data))
            embed.add_field(name="**GM**",
                            value=self.teams.get_gm(data),
                            inline=True)
            embed.add_field(name="**AGM**",
                            value=self.teams.get_agm(data),
                            inline=True)
            embed.add_field(name="**Captain**",
                            value=self.teams.get_captain(data),
                            inline=True)
            embed.add_field(name="**Org**",
                            value="\n".join(self.teams.get_org(data)["Teams"]))
            embed.add_field(name="**Roster**",
                            value="\n".join(self.teams.get_roster(team)))
            embed.add_field(name="**League**",
                            value=self.teams.get_league(data),
                            inline=True)

        for i, field in enumerate(embed.fields):
            if field.value == "":
                embed.set_field_at(i, name=field.name, value="-")

        return await interaction.response.send_message(embed=embed)

    @app_commands.command()
    async def stream(self, interaction: discord.Interaction):
        """Shows the upcoming stream schedule"""
        async with interaction.channel.typing():
            try:
                data = self.streamsheet.to_df("S17 Stream Schedule!D3:K")
            except:
                return await interaction.response.send_message(
                    "Couldn't find the stream schedule :(")

            data = data.rename(
                columns={
                    "Date:": "Date",
                    "League:": "League",
                    "Series:": "Series",
                    "Time:": "Time",
                    "Streamer:": "Streamer",
                    "Play by Play:": "PBP",
                    "Color:": "Color",
                })
            data = data[(data["League"].str.lower().isin(leagues.keys())) &
                        (data['Series'].str.strip() != "-") &
                        (data['Date'].str.strip() !=
                         "")]  # Get rid of empty rows and TBD rows
            data["Date"] = pd.to_datetime(data["Date"],
                                          format="%m/%d/%y",
                                          errors="coerce")
            monday = datetime.today() - timedelta(
                days=datetime.today().weekday())
            week = timedelta(days=7)

            sched = data[data["Date"] > datetime.today()].set_index("Date")
            filename = "stream_schedule.png"
            dfi.export(sched, filename, table_conversion="matplotlib")
            path = os.path.abspath(filename)
            file = discord.File(path)

            await interaction.response.send_message(file=file)
        return os.remove(path)