136 lines
4.6 KiB
Python
136 lines
4.6 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):
|
|
"""Return karma between two dates."""
|
|
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):
|
|
"""Provide karma keys in rank order, with numbered position."""
|
|
keys = self.annotate(karma_score=models.Sum('karmalogentry__delta')).order_by('-karma_score')
|
|
return keys
|
|
|
|
def ranked_scored_reverse_order(self):
|
|
"""Provide karma keys in reverse rank order, with numbered position."""
|
|
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):
|
|
"""Return karma users who gave the most positive karma."""
|
|
karmaers = self.values('nickmask').annotate(karma_outlook=models.Sum('delta')).order_by('-karma_outlook')
|
|
return karmaers
|
|
|
|
def pessimists(self):
|
|
"""Return karma users who gave the most negative karma."""
|
|
karmaers = self.values('nickmask').annotate(karma_outlook=models.Sum('delta')).order_by('karma_outlook')
|
|
return karmaers
|
|
|
|
def most_opinionated(self):
|
|
"""Return karma users who gave the most karma."""
|
|
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:
|
|
"""Meta options."""
|
|
|
|
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)
|