dr.botzo/karma/models.py

137 lines
4.2 KiB
Python

"""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)