bgneal@540: """
bgneal@540: Models for the contest application.
bgneal@540: 
bgneal@540: """
bgneal@540: import random
bgneal@540: import datetime
bgneal@540: 
bgneal@540: from django.db import models
bgneal@540: from django.contrib.auth.models import User
bgneal@540: 
bgneal@540: 
bgneal@540: class PublicContestManager(models.Manager):
bgneal@540:     """
bgneal@540:     The manager for all public contests.
bgneal@540: 
bgneal@540:     """
bgneal@740:     def get_queryset(self):
bgneal@740:         return super(PublicContestManager, self).get_queryset().filter(is_public=True)
bgneal@540: 
bgneal@788:     def get_current_contests(self):
bgneal@788:         now = datetime.datetime.now()
bgneal@788:         return self.filter(creation_date__lte=now, win_date__isnull=True)
bgneal@788: 
bgneal@540: 
bgneal@540: class Contest(models.Model):
bgneal@540:     """
bgneal@540:     A model to represent contests where users sign up to win something.
bgneal@540: 
bgneal@540:     """
bgneal@540:     title = models.CharField(max_length=64)
bgneal@540:     slug = models.SlugField(max_length=64)
bgneal@540:     description = models.TextField()
bgneal@540:     is_public = models.BooleanField(db_index=True)
bgneal@540:     creation_date = models.DateTimeField(blank=True)
bgneal@540:     end_date = models.DateTimeField()
bgneal@540:     contestants = models.ManyToManyField(User, related_name='contests',
bgneal@540:             null=True, blank=True)
bgneal@796:     winners = models.ManyToManyField(User, null=True, blank=True,
bgneal@540:             related_name='winning_contests')
bgneal@540:     win_date = models.DateTimeField(null=True, blank=True)
bgneal@540:     meta_description = models.TextField()
bgneal@796:     num_winners = models.IntegerField(default=1,
bgneal@796:             verbose_name='Number of winners')
bgneal@540: 
bgneal@540:     objects = models.Manager()
bgneal@540:     public_objects = PublicContestManager()
bgneal@540: 
bgneal@540:     class Meta:
bgneal@540:         ordering = ['-creation_date']
bgneal@540: 
bgneal@540:     def __unicode__(self):
bgneal@540:         return self.title
bgneal@540: 
bgneal@540:     @models.permalink
bgneal@540:     def get_absolute_url(self):
bgneal@540:         return ('contests-contest', [], {'slug': self.slug})
bgneal@540: 
bgneal@540:     def save(self, *args, **kwargs):
bgneal@540:         if not self.pk and not self.creation_date:
bgneal@540:             self.creation_date = datetime.datetime.now()
bgneal@540: 
bgneal@540:         super(Contest, self).save(*args, **kwargs)
bgneal@540: 
bgneal@540:     def is_active(self):
bgneal@540:         """
bgneal@540:         Returns True if the contest is still active.
bgneal@540: 
bgneal@540:         """
bgneal@540:         now = datetime.datetime.now()
bgneal@540:         return self.creation_date <= now < self.end_date
bgneal@540: 
bgneal@540:     def can_enter(self):
bgneal@540:         """
bgneal@796:         Returns True if the contest is still active and does not have any
bgneal@796:         winners.
bgneal@540: 
bgneal@540:         """
bgneal@796:         return not self.win_date and self.is_active()
bgneal@540: 
bgneal@796:     def pick_winners(self):
bgneal@540:         """
bgneal@796:         This function randomly picks winners from all the contestants.
bgneal@540: 
bgneal@540:         """
bgneal@796:         user_ids = list(self.contestants.values_list('id', flat=True))
bgneal@796: 
bgneal@796:         winner_count = min(len(user_ids), self.num_winners)
bgneal@796:         if winner_count == 0:
bgneal@796:             return
bgneal@796: 
bgneal@796:         winner_ids = []
bgneal@796:         for n in xrange(winner_count):
bgneal@796:             winner = random.choice(user_ids)
bgneal@796:             winner_ids.append(winner)
bgneal@796:             user_ids.remove(winner)
bgneal@796: 
bgneal@796:         winners = list(User.objects.filter(pk__in=winner_ids))
bgneal@796:         self.winners.add(*winners)
bgneal@540:         self.win_date = datetime.datetime.now()
bgneal@540: 
bgneal@540:     def ogp_tags(self):
bgneal@540:         """
bgneal@540:         Returns a dict of Open Graph Protocol meta tags.
bgneal@540: 
bgneal@540:         """
bgneal@540:         return {
bgneal@540:             'og:title': self.title,
bgneal@567:             'og:type': 'article',
bgneal@540:             'og:url': self.get_absolute_url(),
bgneal@540:             'og:description': self.meta_description,
bgneal@540:         }