2019-06-03 14:59:18 +00:00
|
|
|
'''
|
|
|
|
Django Model Managers for the Radio application.
|
|
|
|
'''
|
|
|
|
|
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-28 18:43:03 +00:00
|
|
|
from random import randint
|
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
|
2018-03-29 16:14:24 +00:00
|
|
|
from .querysets import RadioQuerySet, SongQuerySet
|
2017-12-29 14:56:47 +00:00
|
|
|
|
|
|
|
|
2018-03-27 16:05:44 +00:00
|
|
|
# Set decimal precision
|
|
|
|
getcontext().prec = 16
|
|
|
|
|
|
|
|
|
2018-03-29 16:14:24 +00:00
|
|
|
class RadioManager(models.Manager):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
Custom object manager for filtering out common behaviors for radio
|
|
|
|
objects.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
def get_queryset(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
Return customized default QuerySet.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
return RadioQuerySet(self.model, using=self._db)
|
|
|
|
|
|
|
|
def disabled(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
Radio objects that are marked as disabled.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
return self.get_queryset().disabled()
|
|
|
|
|
|
|
|
def enabled(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
Radio objects that are marked as enabled.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
return self.get_queryset().enabled()
|
|
|
|
|
|
|
|
def published(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
Radio objects that are marked as published.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
return self.get_queryset().published()
|
|
|
|
|
|
|
|
def unpublished(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
Radio objects that are marked as unpublished.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
return self.get_queryset().unpublished()
|
|
|
|
|
2018-04-26 16:18:08 +00:00
|
|
|
def available(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-04-26 16:18:08 +00:00
|
|
|
Radio objects that are enabled and published.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-04-26 16:18:08 +00:00
|
|
|
return self.enabled().published()
|
|
|
|
|
2018-03-29 16:14:24 +00:00
|
|
|
|
|
|
|
class SongManager(RadioManager):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-29 16:14:24 +00:00
|
|
|
Custom object manager for filtering out common behaviors for Song objects.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2017-12-29 14:56:47 +00:00
|
|
|
def get_queryset(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 16:42:28 +00:00
|
|
|
Return customized default QuerySet for Songs.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2017-12-29 14:56:47 +00:00
|
|
|
return SongQuerySet(self.model, using=self._db)
|
|
|
|
|
2018-03-28 18:43:03 +00:00
|
|
|
def available_jingles(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 18:43:03 +00:00
|
|
|
Jingles that are currently published and are enabled.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-09-24 17:02:52 +00:00
|
|
|
return self.available().jingles()
|
2018-03-28 18:43:03 +00:00
|
|
|
|
|
|
|
def available_songs(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 16:42:28 +00:00
|
|
|
Songs that are currently published and are enabled.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-09-24 17:02:52 +00:00
|
|
|
return self.available().songs()
|
2018-03-27 19:58:26 +00:00
|
|
|
|
2018-03-27 16:05:44 +00:00
|
|
|
def playlist_length(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-27 16:05:44 +00:00
|
|
|
Total length of available songs in the playlist (in seconds).
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
|
|
|
a_songs = self.available_songs()
|
|
|
|
length = a_songs.aggregate(
|
|
|
|
total_time=models.Sum('current_store__length')
|
|
|
|
)
|
|
|
|
return length['total_time']
|
2018-03-27 16:05:44 +00:00
|
|
|
|
2019-01-15 20:29:14 +00:00
|
|
|
def wait_total(self, adjusted_ratio=0.0):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-27 16:05:44 +00:00
|
|
|
Default length in seconds before a song can be played again. This is
|
|
|
|
based on the replay ratio set in the application settings.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2019-01-15 20:29:14 +00:00
|
|
|
total_ratio = get_setting('replay_ratio') + adjusted_ratio
|
|
|
|
wait = self.playlist_length() * Decimal(total_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):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-27 16:05:44 +00:00
|
|
|
Datetime of now minus the default wait time for played songs.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
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):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
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).
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 18:43:03 +00:00
|
|
|
return self.available_songs().filter(
|
2019-06-03 14:59:18 +00:00
|
|
|
models.Q(next_play__lt=timezone.now()) |
|
|
|
|
models.Q(next_play__isnull=True)
|
|
|
|
)
|
2018-03-28 16:42:28 +00:00
|
|
|
|
|
|
|
def requestable(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 16:42:28 +00:00
|
|
|
Songs that can be placed in the request queue for playback.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 16:42:28 +00:00
|
|
|
# Import SongRequest here to get rid of circular dependencies
|
2019-06-03 14:59:18 +00:00
|
|
|
song_request = apps.get_model(app_label='profiles',
|
|
|
|
model_name='SongRequest')
|
|
|
|
requests = song_request.music.unplayed().values_list('song__id',
|
|
|
|
flat=True)
|
2018-03-28 16:42:28 +00:00
|
|
|
return self.playable().exclude(id__in=requests)
|
2018-03-28 18:43:03 +00:00
|
|
|
|
|
|
|
def get_random_requestable_song(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 18:43:03 +00:00
|
|
|
Pick a random requestable song and return it.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 18:43:03 +00:00
|
|
|
return self.requestable()[randint(0, self.requestable().count() - 1)]
|
|
|
|
|
|
|
|
def get_random_jingle(self):
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 18:43:03 +00:00
|
|
|
Pick a random jingle and return it.
|
2019-06-03 14:59:18 +00:00
|
|
|
'''
|
2018-03-28 18:43:03 +00:00
|
|
|
random_index = randint(0, self.available_jingles().count() - 1)
|
|
|
|
return self.available_jingles()[random_index]
|