<commit_before>import bleach
from django.contrib.contenttypes.models import ContentType
from django.core import urlresolvers
from django.db import models
from django.utils.translation import ugettext as _
from django.utils import timezone
from django_countries.fields import CountryField


class ClanMember(models.Model):
    """Model for clan member"""

    # If player's score is of this value - we know they are a clan member, but unranked.
    SCORE_UNRANKED = -1

    RACE_TERRAN = 'TERRAN'
    RACE_ZERG = 'ZERG'
    RACE_PROTOSS = 'PROTOSS'
    RACE_RANDOM = 'RANDOM'

    # For how many days after a member is added is it's status protected from being changed by management jobs.
    STATUS_PROTECTION_DAYS = 3

    name = models.CharField('player name', max_length=50, help_text=_(
        'In the Battle.net URL http://eu.battle.net/sc2/en/profile/3568824/1/pundurs/, '
        '<i>pundurs</i> is the player name.'
    ))
    bnet_id = models.IntegerField('battle.net ID', help_text=_(
        'In the Battle.net URL http://eu.battle.net/sc2/en/profile/3568824/1/pundurs/, '
        '<i>3568824</i> is the Battle.net ID.'
    ))
    region = models.IntegerField('region', default=1, help_text=_(
        'In the Battle.net URL http://eu.battle.net/sc2/en/profile/3568824/1/pundurs/, '
        '<i>1</i> is the region. It\'s <i>1</i> for most accounts.'
    ))
    ladder_name = models.CharField('division', max_length=50, editable=False, blank=True)
    ladder_id = models.IntegerField('division id', editable=False, default=0)
    country = CountryField(blank_label=_('(select country)'), blank=True)
    league = models.CharField('league', editable=False, max_length=12, choices=(
        ('BRONZE', _('Bronze')),
        ('SILVER', _('Silver')),
        ('GOLD', _('Gold')),
        ('PLATINUM', _('Platinum')),
        ('DIAMOND', _('Diamond')),
        ('MASTER', _('Masters')),
        ('GRANDMASTER', _('Grandmasters')),
    ))
    race = models.CharField('race', editable=False, max_length=10, choices=(
        (RACE_TERRAN, _('Terran')),
        (RACE_ZERG, _('Zerg')),
        (RACE_PROTOSS, _('Protoss')),
        (RACE_RANDOM, _('Random')),
    ))
    skype_id = models.CharField('skype', max_length=100, blank=True)
    last_game = models.DateField('last game', auto_now_add=True, editable=False)
    wins = models.IntegerField('wins', editable=False, default=0)
    losses = models.IntegerField('losses', editable=False, default=0)
    score = models.IntegerField('ladder points', editable=False, default=SCORE_UNRANKED)
    rank = models.IntegerField('rank in division', editable=False, default=100)
    join_date = models.DateField('date joined', auto_now_add=True)
    practice_register = models.CharField('practice register', max_length=1, choices=(
        ('Y', _('Yes')),
        ('N', _('No (No excuse)')),
        ('E', _('Explained')),
    ), default='Y')
    strikes = models.IntegerField('amount of strikes', default=0)
    notes = models.TextField('notes', blank=True, help_text=_(
        'You can use HTML. Allowed tags - %s.<br> Links will be made clickable automatically.' % ', '.join(['&lt;' + tag + '&gt;' for tag in bleach.ALLOWED_TAGS])
    ))
    twitch_username = models.CharField('Twitch username', max_length=100, blank=True)

    is_member = models.BooleanField('is clan member', default=True, help_text=_(
        'Uncheck this instead of deleting the member from the database, so you don\'t lose the extra data you added '
        'which you might need again in case the member re-joins the clan.'
    ))

    # Member won't be affected by sync with Nios.kr.
    name_locked = models.BooleanField('is name locked', default=False, help_text=_(
        'If this is enabled, the player\'s name won\'t be changed by sync jobs.<br><br>Example use case: Nios.kr lists '
        'a member with an old name, but you want to specify the new one, so the stats sync works.'
    ))
    membership_status_locked = models.BooleanField('is membership status locked', default=False, help_text=_(
        'If this is enabled, the player\'s status won\'t be changed by sync jobs.<br><br>Example use case: Nios.kr '
        'lists a member who actually isn\'t in the clan anymore, but keeps getting listed as one.<br> '
        '<strong>NOTE:</strong> You most likely won\'t need to use this if you add a member manually, since '
        'their status is locked for ' + str(STATUS_PROTECTION_DAYS) + ' days allowing Nios.kr to catch up!'
    ))

    is_staff = models.BooleanField('is staff', default=False, help_text=_(
      'Used for informative purposes only.'
    ))

    @property
    def is_unranked(self):
        return self.score == self.SCORE_UNRANKED

    @property
    def winrate(self):
        return round(100 / (self.wins + self.losses) * self.wins, 2)

    @property
    def is_winrate_positive(self):
        return self.winrate > 50

    @property
    def total_games(self):
        return self.wins + self.losses

    @property
    def days_since_last_game(self):
        return (timezone.now().date() - self.last_game).days

    @property
    def bnet_profile_url(self):
        return 'http://eu.battle.net/sc2/en/profile/{}/{}/{}/'.format(self.bnet_id, self.region, self.name)

    @property
    def bnet_ladder_url(self):
        return 'http://eu.battle.net/sc2/en/profile/{}/{}/{}/ladder/{}#current-rank'.format(
            self.bnet_id, self.region, self.name, self.ladder_id
        )

    @property
    def twitch_url(self):
        return 'http://twitch.tv/{}/'.format(self.twitch_username)

    @property
    def get_admin_url(self):
        # Get admin URL for specific object, AdminSite independent.
        content_type = ContentType.objects.get_for_model(self.__class__)
        return urlresolvers.reverse(
            "admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,)
        )

    @property
    def bleached_notes(self):
        linkified = bleach.linkify(self.notes)
        return bleach.clean(linkified)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'player'
        verbose_name_plural = 'players'


class SyncLog(models.Model):
    """ A log entry for sync events triggered by management jobs"""
    # Identifiers for actions
    CLAN_MEMBER_SYNC = 'CM'
    CLAN_MEMBER_DETAIL_SYNC = 'CMD'

    action = models.CharField('identifier', max_length=3, choices=(
        (CLAN_MEMBER_SYNC, _('Clan member sync')),
        (CLAN_MEMBER_DETAIL_SYNC, _('Clan member detail sync')),
    ))
    time = models.DateTimeField('time', auto_now_add=True)
    notes = models.TextField('notes', blank=True)
    success = models.BooleanField('was operation successful?', default=False)

    class Meta:
        verbose_name = 'sync event'
        verbose_name_plural = 'sync events'

    def __str__(self):
        return self.get_action_display()


class PracticeEvent(models.Model):
    date = models.DateTimeField(_('event date'))
    notes = models.TextField(_('notes'), blank=True)

    @property
    def bleached_notes(self):
        linkified = bleach.linkify(self.notes)
        return bleach.clean(linkified)

    class Meta:
        verbose_name = 'practice event'
        verbose_name_plural = 'practice events'


class PracticeAttendant(models.Model):
    MU_TVT = 'TT'
    MU_TVZ = 'TZ'
    MU_TVP = 'TP'
    MU_ZVZ = 'ZZ'
    MU_ZVT = 'ZT'
    MU_ZVP = 'ZP'
    MU_PVP = 'PP'
    MU_PVZ = 'PZ'
    MU_PVT = 'PT'

    player = models.ForeignKey(ClanMember, verbose_name='player')
    event = models.ForeignKey(PracticeEvent, verbose_name='event')
    matchup = models.CharField(_('matchup'), max_length=2, choices=(
        (MU_TVT, _('Terran vs. Terran')),
        (MU_TVZ, _('Terran vs. Zerg')),
        (MU_TVP, _('Terran vs. Protoss')),
        (MU_ZVZ, _('Zerg vs. Zerg')),
        (MU_ZVT, _('Zerg vs. Terran')),
        (MU_ZVP, _('Zerg vs. Protoss')),
        (MU_PVP, _('Protoss vs. Protoss')),
        (MU_PVZ, _('Protoss vs. Zerg')),
        (MU_PVT, _('Protoss vs. Terran')),
    ))
    win = models.BooleanField(_('Did the player win'), default=False)
    notes = models.TextField(_('notes'), blank=True)

    @property
    def bleached_notes(self):<commit_msg>Added string representation of PracticeEvent objects.<commit_after>import bleach
from django.contrib.contenttypes.models import ContentType
from django.core import urlresolvers
from django.db import models
from django.utils.translation import ugettext as _
from django.utils import timezone
from django_countries.fields import CountryField


class ClanMember(models.Model):
    """Model for clan member"""

    # If player's score is of this value - we know they are a clan member, but unranked.
    SCORE_UNRANKED = -1

    RACE_TERRAN = 'TERRAN'
    RACE_ZERG = 'ZERG'
    RACE_PROTOSS = 'PROTOSS'
    RACE_RANDOM = 'RANDOM'

    # For how many days after a member is added is it's status protected from being changed by management jobs.
    STATUS_PROTECTION_DAYS = 3

    name = models.CharField('player name', max_length=50, help_text=_(
        'In the Battle.net URL http://eu.battle.net/sc2/en/profile/3568824/1/pundurs/, '
        '<i>pundurs</i> is the player name.'
    ))
    bnet_id = models.IntegerField('battle.net ID', help_text=_(
        'In the Battle.net URL http://eu.battle.net/sc2/en/profile/3568824/1/pundurs/, '
        '<i>3568824</i> is the Battle.net ID.'
    ))
    region = models.IntegerField('region', default=1, help_text=_(
        'In the Battle.net URL http://eu.battle.net/sc2/en/profile/3568824/1/pundurs/, '
        '<i>1</i> is the region. It\'s <i>1</i> for most accounts.'
    ))
    ladder_name = models.CharField('division', max_length=50, editable=False, blank=True)
    ladder_id = models.IntegerField('division id', editable=False, default=0)
    country = CountryField(blank_label=_('(select country)'), blank=True)
    league = models.CharField('league', editable=False, max_length=12, choices=(
        ('BRONZE', _('Bronze')),
        ('SILVER', _('Silver')),
        ('GOLD', _('Gold')),
        ('PLATINUM', _('Platinum')),
        ('DIAMOND', _('Diamond')),
        ('MASTER', _('Masters')),
        ('GRANDMASTER', _('Grandmasters')),
    ))
    race = models.CharField('race', editable=False, max_length=10, choices=(
        (RACE_TERRAN, _('Terran')),
        (RACE_ZERG, _('Zerg')),
        (RACE_PROTOSS, _('Protoss')),
        (RACE_RANDOM, _('Random')),
    ))
    skype_id = models.CharField('skype', max_length=100, blank=True)
    last_game = models.DateField('last game', auto_now_add=True, editable=False)
    wins = models.IntegerField('wins', editable=False, default=0)
    losses = models.IntegerField('losses', editable=False, default=0)
    score = models.IntegerField('ladder points', editable=False, default=SCORE_UNRANKED)
    rank = models.IntegerField('rank in division', editable=False, default=100)
    join_date = models.DateField('date joined', auto_now_add=True)
    practice_register = models.CharField('practice register', max_length=1, choices=(
        ('Y', _('Yes')),
        ('N', _('No (No excuse)')),
        ('E', _('Explained')),
    ), default='Y')
    strikes = models.IntegerField('amount of strikes', default=0)
    notes = models.TextField('notes', blank=True, help_text=_(
        'You can use HTML. Allowed tags - %s.<br> Links will be made clickable automatically.' % ', '.join(['&lt;' + tag + '&gt;' for tag in bleach.ALLOWED_TAGS])
    ))
    twitch_username = models.CharField('Twitch username', max_length=100, blank=True)

    is_member = models.BooleanField('is clan member', default=True, help_text=_(
        'Uncheck this instead of deleting the member from the database, so you don\'t lose the extra data you added '
        'which you might need again in case the member re-joins the clan.'
    ))

    # Member won't be affected by sync with Nios.kr.
    name_locked = models.BooleanField('is name locked', default=False, help_text=_(
        'If this is enabled, the player\'s name won\'t be changed by sync jobs.<br><br>Example use case: Nios.kr lists '
        'a member with an old name, but you want to specify the new one, so the stats sync works.'
    ))
    membership_status_locked = models.BooleanField('is membership status locked', default=False, help_text=_(
        'If this is enabled, the player\'s status won\'t be changed by sync jobs.<br><br>Example use case: Nios.kr '
        'lists a member who actually isn\'t in the clan anymore, but keeps getting listed as one.<br> '
        '<strong>NOTE:</strong> You most likely won\'t need to use this if you add a member manually, since '
        'their status is locked for ' + str(STATUS_PROTECTION_DAYS) + ' days allowing Nios.kr to catch up!'
    ))

    is_staff = models.BooleanField('is staff', default=False, help_text=_(
      'Used for informative purposes only.'
    ))

    @property
    def is_unranked(self):
        return self.score == self.SCORE_UNRANKED

    @property
    def winrate(self):
        return round(100 / (self.wins + self.losses) * self.wins, 2)

    @property
    def is_winrate_positive(self):
        return self.winrate > 50

    @property
    def total_games(self):
        return self.wins + self.losses

    @property
    def days_since_last_game(self):
        return (timezone.now().date() - self.last_game).days

    @property
    def bnet_profile_url(self):
        return 'http://eu.battle.net/sc2/en/profile/{}/{}/{}/'.format(self.bnet_id, self.region, self.name)

    @property
    def bnet_ladder_url(self):
        return 'http://eu.battle.net/sc2/en/profile/{}/{}/{}/ladder/{}#current-rank'.format(
            self.bnet_id, self.region, self.name, self.ladder_id
        )

    @property
    def twitch_url(self):
        return 'http://twitch.tv/{}/'.format(self.twitch_username)

    @property
    def get_admin_url(self):
        # Get admin URL for specific object, AdminSite independent.
        content_type = ContentType.objects.get_for_model(self.__class__)
        return urlresolvers.reverse(
            "admin:%s_%s_change" % (content_type.app_label, content_type.model), args=(self.id,)
        )

    @property
    def bleached_notes(self):
        linkified = bleach.linkify(self.notes)
        return bleach.clean(linkified)

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = 'player'
        verbose_name_plural = 'players'


class SyncLog(models.Model):
    """ A log entry for sync events triggered by management jobs"""
    # Identifiers for actions
    CLAN_MEMBER_SYNC = 'CM'
    CLAN_MEMBER_DETAIL_SYNC = 'CMD'

    action = models.CharField('identifier', max_length=3, choices=(
        (CLAN_MEMBER_SYNC, _('Clan member sync')),
        (CLAN_MEMBER_DETAIL_SYNC, _('Clan member detail sync')),
    ))
    time = models.DateTimeField('time', auto_now_add=True)
    notes = models.TextField('notes', blank=True)
    success = models.BooleanField('was operation successful?', default=False)

    class Meta:
        verbose_name = 'sync event'
        verbose_name_plural = 'sync events'

    def __str__(self):
        return self.get_action_display()


class PracticeEvent(models.Model):
    date = models.DateTimeField(_('event date'))
    notes = models.TextField(_('notes'), blank=True)

    @property
    def bleached_notes(self):
        linkified = bleach.linkify(self.notes)
        return bleach.clean(linkified)

    class Meta:
        verbose_name = 'practice event'
        verbose_name_plural = 'practice events'

    def __str__(self):
        return self.date.strftime('%d.%M.%Y %H:%m')


class PracticeAttendant(models.Model):
    MU_TVT = 'TT'
    MU_TVZ = 'TZ'
    MU_TVP = 'TP'
    MU_ZVZ = 'ZZ'
    MU_ZVT = 'ZT'
    MU_ZVP = 'ZP'
    MU_PVP = 'PP'
    MU_PVZ = 'PZ'
    MU_PVT = 'PT'

    player = models.ForeignKey(ClanMember, verbose_name='player')
    event = models.ForeignKey(PracticeEvent, verbose_name='event')
    matchup = models.CharField(_('matchup'), max_length=2, choices=(
        (MU_TVT, _('Terran vs. Terran')),
        (MU_TVZ, _('Terran vs. Zerg')),
        (MU_TVP, _('Terran vs. Protoss')),
        (MU_ZVZ, _('Zerg vs. Zerg')),
        (MU_ZVT, _('Zerg vs. Terran')),
        (MU_ZVP, _('Zerg vs. Protoss')),
        (MU_PVP, _('Protoss vs. Protoss')),
        (MU_PVZ, _('Protoss vs. Zerg')),
        (MU_PVT, _('Protoss vs. Terran')),
    ))
    win = models.BooleanField(_('Did the player win'), default=False)
    notes = models.TextField(_('notes'), blank=True)

    @property
    def bleached_notes(self):
{'fraction_non_alphanumeric': 0.13528843832971277, 'fraction_numerical': 0.008568670045860488, 'mean_word_length': 3.2138316806509026, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 37, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4374579', 'n_tokens_mistral': 5640, 'n_tokens_neox': 5415, 'n_words': 1335}