Exemple #1
0
class Player(models.Model):
    user = fields.OneToOneField(models.User,
                                primary_key=True,
                                on_delete=fields.CASCADE)
    challonge_username = fields.CharField(null=True,
                                          blank=True,
                                          unique=True,
                                          max_length=64)
    challonge_user_id = fields.BigIntegerField(null=True,
                                               blank=True,
                                               unique=True)
    region = RegionField(null=True, blank=True, db_index=True)
    rating = fields.IntegerField(db_index=True, default=1500)
    deviation = fields.IntegerField(default=350)
    volatility = fields.FloatField(default=0.06)

    @async_using_db
    def get_last_ranked_match(self):
        from ..models import Match
        user = self.user
        qs = (Match.objects.filter(
            guild__guildsetup__verified=True, ranked=True, player_1=user)
              | Match.objects.filter(guild__guildsetup__verified=True,
                                     ranked=True,
                                     player_2=user))
        return qs.latest()
Exemple #2
0
class Participant(models.Model):
    member = fields.OneToOneField(models.Member, primary_key=True, on_delete=fields.CASCADE)
    challonge_id = fields.IntegerField(db_index=True)
    tournament = fields.ForeignKey(Tournament, db_index=True, on_delete=fields.CASCADE)
    current_match = fields.ForeignKey('Match', null=True, blank=True, on_delete=fields.SET_NULL)
    starting_elo = fields.IntegerField()
    starting_guild_elo = fields.IntegerField()
    match_count = fields.SmallIntegerField(default=0)
    forfeit_count = fields.SmallIntegerField(default=0)
Exemple #3
0
class ParticipantTeam(models.Model):
    challonge_id = fields.IntegerField(db_index=True)
    member_1 = fields.MemberField(on_delete=fields.CASCADE)
    member_2 = fields.MemberField(on_delete=fields.CASCADE)
    tournament = fields.ForeignKey(Tournament, on_delete=fields.CASCADE)
    current_match = fields.ForeignKey('DoublesMatch',
                                      null=True,
                                      on_delete=fields.SET_NULL)
    starting_elo = fields.IntegerField()
    starting_guild_elo = fields.IntegerField()
    match_count = fields.SmallIntegerField(default=0)
    forfeit_count = fields.SmallIntegerField(default=0)
Exemple #4
0
class GuildTeam(models.Model):
    class Meta:
        unique_together = (('team', 'guild'), )

    team = fields.ForeignKey(Team, on_delete=fields.CASCADE)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)
    guild_elo = fields.IntegerField(db_index=True, default=1000)
Exemple #5
0
class Ruleset(models.Model):
    class Meta:
        unique_together = (('name', 'guild', 'version'), )
        get_latest_by = 'version'

    name = fields.CharField(max_length=128)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)
    version = fields.IntegerField(default=1)
    starter_stages = fields.SeparatedValuesField(
        default=Stage.get_default_starters,
        max_length=64,
        converter=Stage.parse,
        serializer=Stage.serialize)
    counterpick_stages = fields.SeparatedValuesField(
        default=Stage.get_default_counterpicks,
        max_length=64,
        converter=Stage.parse,
        serializer=Stage.serialize)
    counterpick_bans = fields.SmallIntegerField(default=2)
    dsr = DSRField(default=DSR('on'))

    @classmethod
    async def convert(cls, ctx, argument):
        try:
            argument = int(argument)
        except ValueError:
            raise BadArgument(
                f"{argument} is not a valid identifier for a ruleset")
        return await cls.async_get(pk=argument)

    def __str__(self):
        return self.name
Exemple #6
0
class GuildPlayer(models.Model):
    member = fields.OneToOneField(models.Member,
                                  primary_key=True,
                                  on_delete=fields.CASCADE)
    rating = fields.IntegerField(db_index=True, default=1500)
    deviation = fields.IntegerField(default=350)
    volatility = fields.FloatField(default=0.06)

    @async_using_db
    def get_last_ranked_match(self):
        from ..models import Match

        guild = self.member.guild
        user = self.member.user
        qs = (Match.objects.filter(guild=guild, ranked=True, player_1=user)
              | Match.objects.filter(guild=guild, ranked=True, player_2=user))
        return qs.latest()
Exemple #7
0
class ScheduledTask(models.Model):
    extension_name = fields.CharField(max_length=64)
    method_name = fields.CharField(max_length=128)
    kwargs = JSONField(null=True, blank=True)
    when = fields.DateTimeField(db_index=True)
    time_tolerance = fields.IntegerField(
        default=300, null=True)  # seconds | None means infinite time tolerance
    context = fields.ForeignKey(Context,
                                null=True,
                                blank=True,
                                on_delete=fields.SET_NULL)
Exemple #8
0
class Team(models.Model):
    class Meta:
        unique_together = (('member_1', 'member_2'), )

    # member_1 is always the user with the lower user ID
    # to avoid duplicate teams
    member_1 = fields.ForeignKey(Player,
                                 db_index=True,
                                 on_delete=fields.CASCADE)
    member_2 = fields.ForeignKey(Player,
                                 db_index=True,
                                 on_delete=fields.CASCADE)
    custom_name = fields.CharField(null=True, max_length=64)
    current_tournament = fields.ForeignKey(Tournament,
                                           null=True,
                                           blank=True,
                                           on_delete=fields.SET_NULL)
    current_participant_team = fields.ForeignKey(ParticipantTeam,
                                                 null=True,
                                                 blank=True,
                                                 on_delete=fields.SET_NULL)
    elo = fields.IntegerField(db_index=True, default=1000)
Exemple #9
0
class Match(models.Model):
    class Meta:
        get_latest_by = 'started_at'

    id = fields.BigAutoField(primary_key=True)
    channel = fields.TextChannelField(null=True,
                                      blank=True,
                                      db_index=True,
                                      unique=True,
                                      on_delete=fields.SET_NULL)
    guild = fields.GuildField(on_delete=fields.CASCADE)
    voice_channel = fields.VoiceChannelField(null=True,
                                             blank=True,
                                             on_delete=fields.SET_NULL)
    # if tournament is None, it's a matchmaking match
    tournament = fields.ForeignKey(Tournament,
                                   null=True,
                                   blank=True,
                                   on_delete=fields.CASCADE)
    setup = fields.ForeignKey(MatchmakingSetup,
                              null=True,
                              blank=True,
                              on_delete=fields.SET_NULL)
    management_message = fields.MessageField(null=True,
                                             blank=True,
                                             on_delete=fields.SET_NULL)
    ranked = fields.BooleanField()
    in_dms = fields.BooleanField()
    # if matchmaking match, looking is player_1, offering is player_2
    player_1 = fields.UserField(db_index=True, on_delete=fields.CASCADE)
    player_1_rating = fields.IntegerField(null=True, blank=True)
    player_1_deviation = fields.IntegerField(null=True, blank=True)
    player_1_volatility = fields.FloatField(null=True, blank=True)
    player_1_global_rating = fields.IntegerField(null=True, blank=True)
    player_1_global_deviation = fields.IntegerField(null=True, blank=True)
    player_1_global_volatility = fields.FloatField(null=True, blank=True)
    player_1_score = fields.SmallIntegerField(default=0)
    player_2 = fields.UserField(db_index=True, on_delete=fields.CASCADE)
    player_2_rating = fields.IntegerField(null=True, blank=True)
    player_2_deviation = fields.IntegerField(null=True, blank=True)
    player_2_volatility = fields.FloatField(null=True, blank=True)
    player_2_global_rating = fields.IntegerField(null=True, blank=True)
    player_2_global_deviation = fields.IntegerField(null=True, blank=True)
    player_2_global_volatility = fields.FloatField(null=True, blank=True)
    player_2_score = fields.SmallIntegerField(default=0)
    current_game = fields.SmallIntegerField(default=1)
    wins_required = fields.SmallIntegerField(default=3)
    ruleset = fields.ForeignKey(Ruleset,
                                null=True,
                                blank=True,
                                on_delete=fields.PROTECT)
    # if winner is None, match is active / ongoing
    # if winner is Purah, it was a friendly match
    winner = fields.UserField(null=True,
                              blank=True,
                              db_index=True,
                              on_delete=fields.CASCADE)
    started_at = fields.DateTimeField(auto_now_add=True, db_index=True)
    ended_at = fields.DateTimeField(null=True, blank=True)
    spectating_message = fields.MessageField(null=True,
                                             blank=True,
                                             on_delete=fields.SET_NULL)
    match_end_message = fields.MessageField(null=True,
                                            blank=True,
                                            on_delete=fields.SET_NULL)

    @classmethod
    def ranked_matches_today_qs(cls, player_1, player_2, guild=None):
        one_day_ago = datetime.now() - timedelta(hours=18)  # let's be generous
        if guild is None:
            qs = (cls.objects.filter(started_at__gt=one_day_ago,
                                     tournament=None,
                                     ranked=True,
                                     player_1=player_1,
                                     player_2=player_2)
                  | cls.objects.filter(started_at__gt=one_day_ago,
                                       tournament=None,
                                       ranked=True,
                                       player_1=player_2,
                                       player_2=player_1))
        else:
            qs = (cls.objects.filter(guild=guild,
                                     started_at__gt=one_day_ago,
                                     tournament=None,
                                     ranked=True,
                                     player_1=player_1,
                                     player_2=player_2)
                  | cls.objects.filter(guild=guild,
                                       started_at__gt=one_day_ago,
                                       tournament=None,
                                       ranked=True,
                                       player_1=player_2,
                                       player_2=player_1))
        return qs

    @async_using_db
    def get_match_participants(self):
        if self.tournament is None:
            return None, None
        member_1 = models.Member.objects.get(user=self.player_1,
                                             guild=self.guild)
        participant_1 = Participant.objects.get(pk=member_1)
        member_2 = models.Member.objects.get(user=self.player_2,
                                             guild=self.guild)
        participant_2 = Participant.objects.get(pk=member_2)
        return participant_1, participant_2
class TournamentSeries(models.Model):
    class Meta:
        unique_together = (('name', 'guild'), )

    key_prefix = fields.CharField(primary_key=True, max_length=128)
    guild = fields.GuildField(db_index=True, on_delete=fields.CASCADE)
    name = fields.CharField(max_length=128)
    next_iteration = fields.IntegerField(default=1)
    ranked = fields.BooleanField()
    admins = fields.ManyToManyField(Player, null=True, blank=True)
    participant_role = fields.RoleField(
        null=True, unique=True, on_delete=fields.SET_NULL
    )  # cancel tournament creation if not found on Discord
    organizer_role = fields.RoleField(
        null=True, on_delete=fields.SET_NULL
    )  # cancel tournament creation if not found on Discord
    streamer_role = fields.RoleField(
        null=True, blank=True,
        on_delete=fields.SET_NULL)  # delete if not found on Discord
    # signup_emoji = fields.EmojiField(default=get_default_emoji, on_delete=fields.SET_DEFAULT)
    # checkin_emoji = fields.EmojiField(default=get_default_emoji, on_delete=fields.SET_DEFAULT)
    announcements_channel = fields.TextChannelField(
        null=True,
        on_delete=fields.SET_NULL)  # if None, cancel tournament creation
    talk_channel = fields.TextChannelField(null=True,
                                           blank=True,
                                           on_delete=fields.SET_NULL)
    introduction = fields.TextField(max_length=2048)
    default_participants_limit = fields.IntegerField(default=512)
    last_start_time = fields.DateTimeField(null=True, blank=True)
    delay_start = fields.SmallIntegerField(null=True, blank=True)  # minutes
    interval = IntervalField(null=True, blank=True)
    doubles = fields.BooleanField(db_index=True)
    format = FormatField(default=Formats.double_elimination)
    affects_elo = fields.BooleanField(default=True)
    allow_matches_in_dms = fields.BooleanField()
    ruleset = fields.ForeignKey(Ruleset,
                                null=True,
                                blank=True,
                                on_delete=fields.SET_NULL)

    cancelled = fields.BooleanField(default=False)

    @property
    def next_start_time(self):
        self.last_start_time: datetime.datetime
        if self.last_start_time is None or self.interval is None:
            return None
        if self.interval == Intervals.MONTHLY:
            weekday = self.last_start_time.weekday()
            day_number = self.last_start_time.day

    @classmethod
    async def convert(cls, ctx, argument):
        try:
            tournament_series = await cls.async_get(pk=argument)
        except ObjectDoesNotExist:
            try:
                guild = await models.Guild.from_discord_obj(ctx.guild)
                tournament_series = await cls.async_get(guild=guild,
                                                        name=argument)
            except ObjectDoesNotExist:
                raise BadArgument(
                    f"{argument} does not seem to be a valid tournament series."
                )
        return tournament_series