forked from rc/aircox
cfr #121 Co-authored-by: Christophe Siraut <d@tobald.eu.org> Co-authored-by: bkfox <thomas bkfox net> Co-authored-by: Thomas Kairos <thomas@bkfox.net> Reviewed-on: rc/aircox#131 Co-authored-by: Chris Tactic <ctactic@noreply.git.radiocampus.be> Co-committed-by: Chris Tactic <ctactic@noreply.git.radiocampus.be>
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
import datetime
|
||||
import logging
|
||||
import operator
|
||||
from collections import deque
|
||||
|
||||
from django.db import models
|
||||
@ -7,8 +8,10 @@ from django.utils import timezone as tz
|
||||
from django.utils.translation import gettext_lazy as _
|
||||
|
||||
from .diffusion import Diffusion
|
||||
from .sound import Sound, Track
|
||||
from .sound import Sound
|
||||
from .station import Station
|
||||
from .track import Track
|
||||
from .page import Renderable
|
||||
|
||||
logger = logging.getLogger("aircox")
|
||||
|
||||
@ -30,6 +33,9 @@ class LogQuerySet(models.QuerySet):
|
||||
def after(self, date):
|
||||
return self.filter(date__gte=date) if isinstance(date, tz.datetime) else self.filter(date__date__gte=date)
|
||||
|
||||
def before(self, date):
|
||||
return self.filter(date__lte=date) if isinstance(date, tz.datetime) else self.filter(date__date__lte=date)
|
||||
|
||||
def on_air(self):
|
||||
return self.filter(type=Log.TYPE_ON_AIR)
|
||||
|
||||
@ -46,13 +52,15 @@ class LogQuerySet(models.QuerySet):
|
||||
return self.filter(track__isnull=not with_it)
|
||||
|
||||
|
||||
class Log(models.Model):
|
||||
class Log(Renderable, models.Model):
|
||||
"""Log sounds and diffusions that are played on the station.
|
||||
|
||||
This only remember what has been played on the outputs, not on each
|
||||
source; Source designate here which source is responsible of that.
|
||||
"""
|
||||
|
||||
template_prefix = "log"
|
||||
|
||||
TYPE_STOP = 0x00
|
||||
"""Source has been stopped, e.g. manually."""
|
||||
# Rule: \/ diffusion != null \/ sound != null
|
||||
@ -90,7 +98,7 @@ class Log(models.Model):
|
||||
blank=True,
|
||||
null=True,
|
||||
verbose_name=_("source"),
|
||||
help_text=_("identifier of the source related to this log"),
|
||||
help_text=_("Identifier of the log's source."),
|
||||
)
|
||||
comment = models.CharField(
|
||||
max_length=512,
|
||||
@ -160,21 +168,22 @@ class Log(models.Model):
|
||||
object_list += [cls(obj) for obj in items]
|
||||
|
||||
@classmethod
|
||||
def merge_diffusions(cls, logs, diffs, count=None):
|
||||
def merge_diffusions(cls, logs, diffs, count=None, diff_count=None, group_logs=False):
|
||||
"""Merge logs and diffusions together.
|
||||
|
||||
`logs` can either be a queryset or a list ordered by `Log.date`.
|
||||
"""
|
||||
# TODO: limit count
|
||||
# FIXME: log may be iterable (in stats view)
|
||||
if isinstance(logs, models.QuerySet):
|
||||
logs = list(logs.order_by("-date"))
|
||||
diffs = deque(diffs.on_air().before().order_by("-start"))
|
||||
diffs = diffs.on_air().order_by("-start")
|
||||
if diff_count:
|
||||
diffs = diffs[:diff_count]
|
||||
diffs = deque(diffs)
|
||||
object_list = []
|
||||
|
||||
while True:
|
||||
if not len(diffs):
|
||||
object_list += logs
|
||||
cls._append_logs(object_list, logs, len(logs), group=group_logs)
|
||||
break
|
||||
|
||||
if not len(logs):
|
||||
@ -184,13 +193,8 @@ class Log(models.Model):
|
||||
diff = diffs.popleft()
|
||||
|
||||
# - takes all logs after diff start
|
||||
index = next(
|
||||
(i for i, v in enumerate(logs) if v.date <= diff.end),
|
||||
len(logs),
|
||||
)
|
||||
if index is not None and index > 0:
|
||||
object_list += logs[:index]
|
||||
logs = logs[index:]
|
||||
index = cls._next_index(logs, diff.end, len(logs), pred=operator.le)
|
||||
cls._append_logs(object_list, logs, index, group=group_logs)
|
||||
|
||||
if len(logs):
|
||||
# FIXME
|
||||
@ -199,10 +203,7 @@ class Log(models.Model):
|
||||
# object_list.append(logs[0])
|
||||
|
||||
# - skips logs while diff is running
|
||||
index = next(
|
||||
(i for i, v in enumerate(logs) if v.date < diff.start),
|
||||
len(logs),
|
||||
)
|
||||
index = cls._next_index(logs, diff.start, len(logs))
|
||||
if index is not None and index > 0:
|
||||
logs = logs[index:]
|
||||
|
||||
@ -211,6 +212,40 @@ class Log(models.Model):
|
||||
|
||||
return object_list if count is None else object_list[:count]
|
||||
|
||||
@classmethod
|
||||
def _next_index(cls, items, date, default, pred=operator.lt):
|
||||
iter = (i for i, v in enumerate(items) if pred(v.date, date))
|
||||
return next(iter, default)
|
||||
|
||||
@classmethod
|
||||
def _append_logs(cls, object_list, logs, count, group=False):
|
||||
logs = logs[:count]
|
||||
if not logs:
|
||||
return object_list
|
||||
|
||||
if group:
|
||||
grouped = cls._group_logs_by_time(logs)
|
||||
object_list.extend(grouped)
|
||||
else:
|
||||
object_list += logs
|
||||
return object_list
|
||||
|
||||
@classmethod
|
||||
def _group_logs_by_time(cls, logs):
|
||||
last_time = -1
|
||||
cum = []
|
||||
for log in logs:
|
||||
hour = log.date.time().hour
|
||||
if hour != last_time:
|
||||
if cum:
|
||||
yield cum
|
||||
cum = []
|
||||
last_time = hour
|
||||
# reverse from lowest to highest date
|
||||
cum.insert(0, log)
|
||||
if cum:
|
||||
yield cum
|
||||
|
||||
def print(self):
|
||||
r = []
|
||||
if self.diffusion:
|
||||
|
Reference in New Issue
Block a user