Пример #1
0
    async def fetch(channel: TextChannel):
        try:
            url = GameData.__get_url(channel)
        except BaseException as exception:
            await handle(None, exception)
            raise UsageException.directive_missing(channel, "games")

        try:
            sheets_fetcher = Sheets.from_files(
                "client_secrets.json",
                "oath_cache.json",
            )
            sheets = sheets_fetcher.get(url)
            games: List[Game] = []
            # Must be the first sheet
            # Skip headers
            for row in sheets._sheets[0]._values[1:]:
                try:
                    games.append(
                        Game(
                            datetime.strptime(row[4], "%m/%d/%Y"),
                            Team(json.loads(row[0]), row[1]),
                            Team(json.loads(row[2]), row[3]),
                        ))
                except BaseException as exception:
                    await handle(None, exception)

            return GameData(games)
        except BaseException as exception:
            await handle(None, exception)
            raise UsageException.game_sheet_not_loaded(channel, url)
Пример #2
0
    async def fetch(id: str, channel: TextChannel) -> List[Game]:
        url = f"https://docs.google.com/spreadsheets/d/{id}"
        try:
            sheets_fetcher = Sheets.from_files(
                "client_secrets.json",
                "oath_cache.json",
            )
            sheets = sheets_fetcher.get(url)
            games: List[Game] = []
            # Must be the first sheet
            # Skip headers
            for row in sheets._sheets[0]._values[1:]:
                try:
                    games.append(
                        Game(
                            datetime.strptime(row[4], "%m/%d/%Y"),
                            Team(json.loads(row[0]), row[1]),
                            Team(json.loads(row[2]), row[3]),
                        ))
                except BaseException as exception:
                    await handle(None, exception)

            return games
        except BaseException as exception:
            await handle(None, exception)
            raise UsageException.game_sheet_not_loaded(channel, url)
Пример #3
0
    async def show_next_match(self, order: Callable) -> None:
        if not self.is_ready():
            raise UsageException.not_enough_for_match(self.channel)

        next_match = await self.get_next_match(order)
        if next_match is None:
            raise UsageException.seen_all_matches(self.channel)

        (number, match) = next_match
        (team_one, team_two) = match
        composite = await draw_composite(
            number,
            team_one,
            team_two,
            self.channel.id,
        )
        await self.channel.send(file=File(composite))
Пример #4
0
    async def unready(self, user: Member) -> None:
        player = Player(user)
        if player not in self.players:
            raise UsageException.join_the_lobby_first(self.channel)

        ind = self.players.index(player)
        self.players[ind].set_unready()
        self.reset_orderings()

        await self.show(title=f"{player.get_name()} is not ready.")
Пример #5
0
    async def add(self, user: Member, author: Optional[Member] = None) -> None:
        if author is not None:
            if not self.has_joined(Player(author)):
                raise UsageException.adder_must_join(self.channel)

            # Other players cannot add you to the lobby
            # if you left on your own. (until lobby reset)
            if self.has_left_before(Player(user)):
                raise UsageException.leaver_not_added(self.channel)

        player = Player(user)
        if self.has_joined(player):
            raise UsageException.already_joined(self.channel, author
                                                is not None)

        if not self.has_open_spots():
            raise UsageException.no_overflow(self.channel)

        self.players.append(player)

        await self.show(desc=f"{player.get_name()} has Joined!")
Пример #6
0
    async def show_next_shuffle(self) -> None:
        if not self.is_ready():
            raise UsageException.not_enough_for_match(self.channel)

        if "shuffles" not in self._cache:
            matches = self.get_matches()
            shuffle(matches)
            self._cache["shuffles"] = iter(enumerate(matches))

        next_match = next(self._cache["shuffles"], None)
        if next_match is None:
            raise UsageException.seen_all_matches(self.channel)

        (number, match) = next_match
        embed = Embed(colour=Colour.teal())
        embed.title = f"Shuffle {number+1}"
        for i, team in enumerate(match):
            players = "".join([f"• {p.get_name()}\n" for p in team])
            players = players if players else "(empty)"
            embed.add_field(name=f"Team {i+1}", value=players, inline=False)
        await self.channel.send(embed=embed)
Пример #7
0
    async def unready(self, user: Member) -> None:
        player = Player(user)
        if player not in self.players:
            raise UsageException.join_the_lobby_first(self.channel)

        ind = self.players.index(player)
        player = self.players[ind]
        if player.is_ready():
            player.set_unready()
            self.clear_cache()

        await self.show(desc=f"{player.get_name()} is not Ready")
Пример #8
0
    async def add(self, user: Member, author: Optional[Member] = None) -> None:
        if author is not None:
            if not self.has_joined(Player(author)):
                raise UsageException.adder_must_join(self.channel)

            # Other players cannot add you to the lobby
            # if you left on your own. (until lobby reset)
            if self.has_left_before(Player(user)):
                raise UsageException.leaver_not_added(self.channel)

        player = Player(user)
        if self.has_joined(player):
            raise UsageException.already_joined(self.channel, author
                                                is not None)

        self.players.append(player)

        if self.ready_count() == 7:
            await self.broadcast_game_almost_full()

        await self.show(title=f"{player.get_name()} has joined the game!")
Пример #9
0
    async def ready(self, user: Member) -> None:
        player = Player(user)
        if player not in self.players:
            await self.add(user)

        if player.is_ready():
            raise UsageException.already_ready(self.channel)

        if self.is_ready():
            raise UsageException.game_is_full(self.channel)

        ind = self.players.index(player)
        self.players[ind].set_ready()
        self.reset_orderings()

        if self.is_ready():
            title = f"Game starting in ({self.channel.mention}))"
            embed = self.get_lobby_message(mention=True, title=title)
            await self.channel.send(embed=embed)
        else:
            await self.show(title=f"{player.get_name()} is ready!")
Пример #10
0
    async def remove(self, user: Member, author: Optional[Member] = None):
        player = Player(user)
        if player not in self.players:
            raise UsageException.not_in_lobby(self.channel, player)

        if author is None:
            # If a user removes themself, then _others_
            # can't add them back until the lobby resets.
            self.leavers.append(player)

        self.players.remove(player)

        await self.show(title=f"{player.get_name()} has left the lobby.")
Пример #11
0
    async def ready(self, user: Member) -> None:
        player = Player(user)
        if player not in self.players:
            await self.add(user)

        if player.is_ready():
            raise UsageException.already_ready(self.channel)

        if self.is_full():
            raise UsageException.game_is_full(self.channel)

        was_ready = self.is_ready()

        ind = self.players.index(player)
        self.players[ind].set_ready()
        self.clear_cache()

        if self.c.vMax is not None and self.ready_count() == self.c.vMax - 1:
            await self.broadcast_game_almost_full()

        if not was_ready and self.is_ready():
            await self.show(mention=True, desc="The lobby is now ready!")
        else:
            await self.show(desc=f"{player.get_name()} is Ready!")
Пример #12
0
async def ranked(lobby: "Lobby", ctx: Context):
    """Create fair teams based on player history"""
    if not lobby.is_ready():
        raise UsageException.not_enough_for_match(lobby.channel)

    if __name__ not in lobby._cache:
        id = lobby.c.pLeft4Dead["history"]
        matches = lobby.get_matches()
        data = await GameData.fetch(id, lobby.channel)
        inactive_rank = get_ranks(data, Season.all_time())
        if rc.USE_ROLLING_SEASON:
            season = Season(rc.LENGTH_DAYS, rc.PLACEMENT_GAMES)
            active_rank = get_ranks(data, season)

        def get_player_rank(p: int) -> int:
            if active_rank and p in active_rank:
                return active_rank[p]
            if p in inactive_rank:
                return inactive_rank[p]
            return rc.AVERAGE_RANK

        await rank(matches, get_player_rank)
        lobby._cache[__name__] = iter(enumerate(matches))
        lobby._cache[f"{__name__}-get_rank"] = get_player_rank

    next_match = next(lobby._cache[__name__], None)
    if next_match is None:
        raise UsageException.seen_all_matches(lobby.channel)

    i, teams = next_match
    teams = list(teams)
    team1, team2 = list(teams)[0], list(teams[1])
    channel = lobby.channel.id
    get_rank = lobby._cache[f"{__name__}-get_rank"]
    composite = await draw_composite(i, team1, team2, channel, get_rank)
    await ctx.send(file=File(composite))
Пример #13
0
    async def remove(self,
                     user: Member,
                     author: Optional[Member] = None,
                     rage=False):
        player = Player(user)
        if player not in self.players:
            raise UsageException.not_in_lobby(self.channel, player)

        if author is None:
            # If a user removes themself, then _others_
            # can't add them back until the lobby resets.
            self.leavers.append(player)

        await self.unready(user)
        self.players.remove(player)

        if not rage:
            await self.show(desc=f"{player.get_name()} has Left")
        else:
            await self.show(desc=f"{player.get_name()} says see ya jerks")
Пример #14
0
    def __get_url(channel: TextChannel) -> str:
        if channel.topic is None:
            raise UsageException.directive_missing(channel, "games")

        id = re.findall(r"^@games\(([^\s]+)\)", channel.topic, re.M)
        return f"https://docs.google.com/spreadsheets/d/{id[0]}"