"""Karma logging models.""" from datetime import timedelta import logging import pytz from irc.client import NickMask from django.conf import settings from django.db import models from django.utils import timezone log = logging.getLogger('karma.models') def perdelta(start, end, delta): curr = start while curr < end: yield curr curr += delta yield end class KarmaKeyManager(models.Manager): """Manage handy queries for KarmaKey.""" def ranked_scored_order(self): keys = self.annotate(karma_score=models.Sum('karmalogentry__delta')).order_by('-karma_score') return keys def ranked_scored_reverse_order(self): keys = self.annotate(karma_score=models.Sum('karmalogentry__delta')).order_by('karma_score') return keys class KarmaKey(models.Model): """Track a thing being karmaed.""" key = models.CharField(max_length=200, unique=True) objects = KarmaKeyManager() def __str__(self): """String representation.""" return "{0:s} ({1:d})".format(self.key, self.score()) def score(self): """Determine the score for this karma entry.""" return KarmaLogEntry.objects.filter(key=self).aggregate(models.Sum('delta'))['delta__sum'] def rank(self): """Determine the rank of this karma entry relative to the others.""" sorted_keys = KarmaKey.objects.ranked_scored_order() for rank, key in enumerate(sorted_keys): if key == self: return rank+1 return None def history(self, mode='delta'): """Determine the score for this karma entry at every delta.""" history = [] if mode == 'delta': entries = KarmaLogEntry.objects.filter(key=self).order_by('created') for entry in entries: timestamp = entry.created delta = entry.delta score = KarmaLogEntry.objects.filter(key=self).filter(created__lte=entry.created).aggregate( models.Sum('delta'))['delta__sum'] history.append((timestamp, delta, score)) elif mode == 'date': first_entry = KarmaLogEntry.objects.filter(key=self).order_by('created')[0] slice_begin = first_entry.created.date() slice_end = timezone.now().date() for timeslice in perdelta(slice_begin, slice_end, timedelta(days=1)): score = KarmaLogEntry.objects.filter(key=self).filter( created__lte=timeslice+timedelta(days=1)).aggregate(models.Sum('delta'))['delta__sum'] if not score: score = 0 try: prev_score = history[-1][2] except IndexError: prev_score = 0 delta = score - prev_score history.append((timeslice, delta, score)) return history class KarmaLogEntryManager(models.Manager): """Manage handy queries for KarmaLogEntry.""" def optimists(self): karmaers = self.values('nickmask').annotate(karma_outlook=models.Sum('delta')).order_by('-karma_outlook') return karmaers def pessimists(self): karmaers = self.values('nickmask').annotate(karma_outlook=models.Sum('delta')).order_by('karma_outlook') return karmaers def most_opinionated(self): karmaers = self.values('nickmask').annotate(karma_count=models.Count('delta')).order_by('-karma_count') return karmaers class KarmaLogEntry(models.Model): """Track each karma increment/decrement.""" key = models.ForeignKey('KarmaKey') delta = models.SmallIntegerField() nickmask = models.CharField(max_length=200, default='', blank=True) created = models.DateTimeField(auto_now_add=True) objects = KarmaLogEntryManager() class Meta: verbose_name_plural = 'karma log entries' def __str__(self): """String representation.""" tz = pytz.timezone(settings.TIME_ZONE) return "{0:s}{1:s} @ {2:s} by {3:s}".format(self.key.key, '++' if self.delta > 0 else '--', self.created.astimezone(tz).strftime('%Y-%m-%d %H:%M:%S %Z'), NickMask(self.nickmask).nick)