]> git.0d.be Git - django-panik-nonstop.git/blobdiff - nonstop/views.py
nonstop: check add_track permission for zone settings
[django-panik-nonstop.git] / nonstop / views.py
index 20314407ec13dfed273629e3b86ae70baae24676..bd2081dccef6c836658fe418dd132fd16b1adc4a 100644 (file)
@@ -8,10 +8,10 @@ import mutagen
 
 from django.core.files.storage import default_storage
 from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
-from django.core.urlresolvers import reverse
+from django.core.urlresolvers import reverse, reverse_lazy
 from django.contrib import messages
-from django.db.models import Q
-from django.http import HttpResponse, HttpResponseRedirect, FileResponse
+from django.db.models import Q, Sum
+from django.http import HttpResponse, HttpResponseRedirect, FileResponse, Http404
 from django.utils.six import StringIO
 from django.utils.translation import ugettext_lazy as _
 from django.views.generic.base import RedirectView, TemplateView
@@ -20,8 +20,9 @@ from django.views.generic.detail import DetailView
 from django.views.generic.edit import CreateView, FormView, UpdateView
 from django.views.generic.list import ListView
 
-from .forms import UploadTracksForm, TrackMetaForm, TrackSearchForm, CleanupForm
-from .models import (SomaLogLine, Track, Artist, NonstopFile, ScheduledDiffusion, Jingle, Stream)
+from .forms import UploadTracksForm, TrackMetaForm, TrackSearchForm, CleanupForm, ZoneSettingsForm
+from .models import (SomaLogLine, Track, Artist, NonstopFile,
+        ScheduledDiffusion, Jingle, Stream, NonstopZoneSettings)
 from emissions.models import Nonstop, Diffusion
 from emissions.utils import period_program
 
@@ -95,6 +96,14 @@ class ArtistListView(ListView):
     model = Artist
 
 
+class ZonesView(ListView):
+    model = Nonstop
+    template_name = 'nonstop/zones.html'
+
+    def get_queryset(self):
+        return sorted(super().get_queryset(), key=lambda x: datetime.time(23, 59) if (x.start == x.end) else x.start)
+
+
 class ZoneStats(object):
     def __init__(self, zone, from_date=None, until_date=None, **kwargs):
         self.zone = zone
@@ -106,6 +115,23 @@ class ZoneStats(object):
             self.qs = self.qs.filter(nonstopfile__somalogline__play_timestamp__lte=until_date)
         self.qs = self.qs.distinct()
 
+    def total_duration(self, **kwargs):
+        try:
+            total = self.qs.filter(**kwargs).aggregate(Sum('duration'))['duration__sum'].total_seconds()
+        except AttributeError:
+            # 'NoneType' object has no attribute 'total_seconds', if there's no
+            # track in queryset
+            return '-'
+        if total > 3600 * 2:
+            duration = _('%d hours') % (total / 3600)
+        else:
+            duration = _('%d minutes') % (total / 60)
+        start = datetime.datetime(2000, 1, 1, self.zone.start.hour, self.zone.start.minute)
+        end = datetime.datetime(2000, 1, 1, self.zone.end.hour, self.zone.end.minute)
+        if end < start:
+            end = end + datetime.timedelta(days=1)
+        return duration + _(', → %d days') % (total // (end - start).total_seconds())
+
     def count(self, **kwargs):
         return self.qs.filter(**kwargs).count()
 
@@ -133,15 +159,43 @@ class ZoneStats(object):
     def cfwb_percentage(self):
         return self.percentage(cfwb=True)
 
+    def language_set(self):
+        return self.count() - self.language_unset()
+
+    def language_unset(self):
+        return self.count(language='')
+
+    def unset_language_percentage(self):
+        return self.percentage(language='')
+
     def french(self):
         return self.count(language='fr')
 
+    def unset_or_na_language(self):
+        return self.qs.filter(Q(language='') | Q(language='na')).count()
+
     def french_percentage(self):
-        considered_tracks = self.count() - self.instru()
+        considered_tracks = self.count() - self.unset_or_na_language()
         if considered_tracks == 0:
             return '-'
         return '%.2f%%' % (100. * self.french() / considered_tracks)
 
+    def quota_french(self):
+        # obligation de diffuser annuellement au moins 30% d'œuvres musicales de
+        # langue française
+        considered_tracks = self.count() - self.unset_or_na_language()
+        if considered_tracks == 0:
+            return True
+        return (100. * self.french() / considered_tracks) > 30.
+
+    def quota_cfwb(self):
+        # obligation de diffuser annuellement au moins 4,5% d'œuvres musicales
+        # émanant de la Communauté française
+        considered_tracks = self.count()
+        if considered_tracks == 0:
+            return True
+        return (100. * self.cfwb() / considered_tracks) > 4.5
+
     def new_files(self):
         return self.count(nonstopfile__creation_timestamp__gte=self.from_date)
 
@@ -154,6 +208,7 @@ def parse_date(date):
         return datetime.datetime.today() + datetime.timedelta(int(date.rstrip('d')))
     return datetime.datetime.strptime(date, '%Y-%m-%d').date()
 
+
 class StatisticsView(TemplateView):
     template_name = 'nonstop/statistics.html'
 
@@ -233,11 +288,16 @@ class UploadTracksView(FormView):
         return self.form_valid(form)
 
 
-class RecentTracksView(ListView):
-    template_name = 'nonstop/recent_tracks.html'
+class TracksMetadataView(ListView):
+    template_name = 'nonstop/tracks_metadata.html'
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context['view'] = self
+        return context
 
     def get_queryset(self):
-        return Track.objects.exclude(creation_timestamp__isnull=True).order_by('-creation_timestamp')[:50]
+        return Track.objects.exclude(nonstop_zones__isnull=True)
 
     def post(self, request, *args, **kwargs):
         assert self.request.user.has_perm('nonstop.add_track')
@@ -251,6 +311,30 @@ class RecentTracksView(ListView):
         return HttpResponseRedirect('.')
 
 
+class RandomTracksMetadataView(TracksMetadataView):
+    page_title = _('Metadata of random tracks')
+
+    def get_queryset(self):
+        return super().get_queryset().filter(Q(language='') | Q(language__isnull=True)).order_by('?')[:50]
+
+
+class RecentTracksMetadataView(TracksMetadataView):
+    page_title = _('Metadata of recent tracks')
+
+    def get_queryset(self):
+        return super().get_queryset().exclude(creation_timestamp__isnull=True).order_by('-creation_timestamp')[:50]
+
+
+class ArtistTracksMetadataView(TracksMetadataView):
+
+    @property
+    def page_title(self):
+        return _('Metadata of tracks from %s') % Artist.objects.get(id=self.kwargs['artist_pk']).name
+
+    def get_queryset(self):
+        return Track.objects.filter(artist_id=self.kwargs['artist_pk']).order_by('title')
+
+
 class QuickLinksView(TemplateView):
     template_name = 'nonstop/quick_links.html'
 
@@ -468,3 +552,66 @@ class AjaxProgram(TemplateView):
                 break
             previous_prog = x
         return context
+
+
+class ZoneSettings(FormView):
+    form_class = ZoneSettingsForm
+    template_name = 'nonstop/zone_settings.html'
+    success_url = reverse_lazy('nonstop-zones')
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context['zone'] = Nonstop.objects.get(slug=self.kwargs['slug'])
+        return context
+
+    def get_initial(self):
+        try:
+            zone = Nonstop.objects.get(slug=self.kwargs['slug'])
+        except Nonstop.DoesNotExist:
+            raise Http404()
+        zone_settings = zone.nonstopzonesettings_set.first()
+        if zone_settings is None:
+            zone_settings = NonstopZoneSettings(nonstop=zone)
+            zone_settings.save()
+        initial = super().get_initial()
+        initial['start'] = zone.start.strftime('%H:%M') if zone.start else None
+        initial['end'] = zone.end.strftime('%H:%M') if zone.end else None
+        initial['intro_jingle'] = zone_settings.intro_jingle_id
+        initial['jingles'] = [x.id for x in zone_settings.jingles.all()]
+        return initial
+
+    def form_valid(self, form):
+        assert self.request.user.has_perm('nonstop.add_track')
+        zone = Nonstop.objects.get(slug=self.kwargs['slug'])
+        zone_settings = zone.nonstopzonesettings_set.first()
+        zone.start = form.cleaned_data['start']
+        zone.end = form.cleaned_data['end']
+        zone_settings.jingles.set(form.cleaned_data['jingles'])
+        zone_settings.intro_jingle_id = form.cleaned_data['intro_jingle']
+        zone.save()
+        zone_settings.save()
+        return super().form_valid(form)
+
+
+class MuninTracks(StatisticsView):
+    template_name = 'nonstop/munin_tracks.txt'
+    content_type = 'text/plain; charset=utf-8'
+
+    def get_context_data(self, **kwargs):
+        context = super().get_context_data(**kwargs)
+        context['nonstop_general_total'] = Track.objects.count()
+        active_tracks_qs = Track.objects.filter(nonstop_zones__isnull=False).distinct()
+        context['nonstop_general_active'] = active_tracks_qs.count()
+        context['nonstop_percentages_instru'] = 100 * (
+                active_tracks_qs.filter(instru=True).count() /
+                context['nonstop_general_active'])
+        context['nonstop_percentages_cfwb'] = 100 * (
+                active_tracks_qs.filter(cfwb=True).count() /
+                context['nonstop_general_active'])
+        context['nonstop_percentages_langset'] = 100 * (
+                active_tracks_qs.exclude(language='').count() /
+                context['nonstop_general_active'])
+        context['nonstop_percentages_french'] = 100 * (
+                active_tracks_qs.filter(language='fr').count() /
+                active_tracks_qs.exclude(language__isnull=True).exclude(language__in=('', 'na')).count())
+        return context