2018-03-27 16:05:44 +00:00
|
|
|
from datetime import timedelta
|
2018-03-28 16:42:28 +00:00
|
|
|
from decimal import getcontext, Decimal, ROUND_UP
|
2018-03-27 16:05:44 +00:00
|
|
|
|
2018-03-28 16:42:28 +00:00
|
|
|
from django.apps import apps
|
2017-12-29 14:56:47 +00:00
|
|
|
from django.db import models
|
2018-03-27 16:05:44 +00:00
|
|
|
from django.utils import timezone
|
2017-12-29 14:56:47 +00:00
|
|
|
|
2018-03-27 16:05:44 +00:00
|
|
|
from core.utils import get_setting
|
2017-12-29 14:56:47 +00:00
|
|
|
from .querysets import SongQuerySet
|
|
|
|
|
|
|
|
|
2018-03-27 16:05:44 +00:00
|
|
|
# Set decimal precision
|
|
|
|
getcontext().prec = 16
|
|
|
|
|
|
|
|
|
2017-12-29 14:56:47 +00:00
|
|
|
class SongManager(models.Manager):
|
|
|
|
"""
|
|
|
|
Custom object manager for filtering out common behaviors for a playlist.
|
|
|
|
"""
|
|
|
|
def get_queryset(self):
|
2018-03-28 16:42:28 +00:00
|
|
|
"""
|
|
|
|
Return customized default QuerySet for Songs.
|
|
|
|
"""
|
2017-12-29 14:56:47 +00:00
|
|
|
return SongQuerySet(self.model, using=self._db)
|
|
|
|
|
2018-03-27 19:58:26 +00:00
|
|
|
def available(self):
|
2018-03-28 16:42:28 +00:00
|
|
|
"""
|
|
|
|
Songs that are currently published and are enabled.
|
|
|
|
"""
|
2018-03-27 19:58:26 +00:00
|
|
|
return self.get_queryset().songs().enabled().published()
|
|
|
|
|
2018-03-27 16:05:44 +00:00
|
|
|
def playlist_length(self):
|
|
|
|
"""
|
|
|
|
Total length of available songs in the playlist (in seconds).
|
|
|
|
"""
|
|
|
|
return self.available().aggregate(models.Sum('length'))['length__sum']
|
|
|
|
|
|
|
|
def wait_total(self):
|
|
|
|
"""
|
|
|
|
Default length in seconds before a song can be played again. This is
|
|
|
|
based on the replay ratio set in the application settings.
|
|
|
|
"""
|
|
|
|
wait = self.playlist_length() * Decimal(get_setting('replay_ratio'))
|
2018-03-28 16:42:28 +00:00
|
|
|
wait = wait.quantize(Decimal('.01'), rounding=ROUND_UP)
|
|
|
|
return timedelta(seconds=float(wait))
|
2018-03-27 16:05:44 +00:00
|
|
|
|
|
|
|
def datetime_from_wait(self):
|
|
|
|
"""
|
|
|
|
Datetime of now minus the default wait time for played songs.
|
|
|
|
"""
|
2018-03-28 16:42:28 +00:00
|
|
|
return timezone.now() - self.wait_total()
|
2018-03-27 16:05:44 +00:00
|
|
|
|
|
|
|
def playable(self):
|
2018-03-28 16:42:28 +00:00
|
|
|
"""
|
|
|
|
Songs that are playable because they are available (enabled &
|
|
|
|
published) and they have not been played within the default wait time
|
|
|
|
(or at all).
|
|
|
|
"""
|
2018-03-27 16:05:44 +00:00
|
|
|
return self.available().filter(
|
2018-03-28 16:42:28 +00:00
|
|
|
models.Q(last_played__lt=self.datetime_from_wait()) |
|
|
|
|
models.Q(last_played__isnull=True)
|
2018-03-27 16:05:44 +00:00
|
|
|
)
|
2018-03-28 16:42:28 +00:00
|
|
|
|
|
|
|
def requestable(self):
|
|
|
|
"""
|
|
|
|
Songs that can be placed in the request queue for playback.
|
|
|
|
"""
|
|
|
|
# Import SongRequest here to get rid of circular dependencies
|
|
|
|
SongRequest = apps.get_model(app_label='profiles',
|
|
|
|
model_name='SongRequest')
|
|
|
|
requests = SongRequest.music.unplayed().values_list('song__id',
|
|
|
|
flat=True)
|
|
|
|
return self.playable().exclude(id__in=requests)
|