import csv import http import logging from django.http import HttpResponse from django.shortcuts import render, get_object_or_404 from django.views import generic from django.shortcuts import HttpResponseRedirect from django.core.exceptions import ObjectDoesNotExist from django.db import transaction from various.views.pomocne import formularOKView from .forms import HlasovaniPrednaskaFormSet, HlasovaniZnalostiFormSet from various.models import Nastaveni from prednasky.models import Prednaska, Hlasovani, Znalost, HlasovaniOZnalostech, Seznam from soustredeni.models import Soustredeni from personalni.models import Osoba PREDNASKY_PREFIX = "prednasky" ZNALOSTI_PREFIX = "znalosti" logger = logging.getLogger(__name__) def newPrednaska(request): # hlasovani se vztahuje k nejnovejsimu soustredeni sous = Nastaveni.get_solo().aktualni_sous seznam = Seznam.objects.filter(soustredeni = sous, stav=Seznam.Stav.NAVRH).first() if sous is None or seznam is None: return render(request, 'universal.html', { 'title': "Nelze hlasovat", 'text': "Není žádný seznam přednášek, o kterém by se dalo hlasovat.", }, status=http.HTTPStatus.NOT_FOUND) osoba = Osoba.objects.filter(user=request.user).first() ucastnik = osoba.plne_jmeno() + ' ' + str(osoba.id) # id, kvůli kolizi jmen if request.method == 'POST': form_set_prednasky = HlasovaniPrednaskaFormSet(request.POST, prefix=PREDNASKY_PREFIX) form_set_znalosti = HlasovaniZnalostiFormSet(request.POST, prefix=ZNALOSTI_PREFIX) if form_set_prednasky.is_valid() and form_set_znalosti.is_valid(): with transaction.atomic(): seznam.hlasovani_set.filter(ucastnik=ucastnik).delete() seznam.hlasovanioznalostech_set.filter(ucastnik=osoba).delete() for form in form_set_prednasky: prednaska_id = form.cleaned_data['prednaska_id'] prednaska = Prednaska.objects.filter(id=prednaska_id).first() if prednaska is None: logger.error(f"Účastník {ucastnik} hodnotil neexistující přednášku {prednaska_id} číslem {form.cleaned_data['body']}") continue Hlasovani.objects.create( prednaska=prednaska, body=form.cleaned_data['body'], ucastnik=ucastnik, seznam=seznam, ) for form in form_set_znalosti: znalost_id = form.cleaned_data['znalost_id'] znalost = Znalost.objects.filter(id=znalost_id).first() if znalost is None: logger.error(f"Účastník {ucastnik} hodnotil neexistující znalost {znalost_id} číslem {form.cleaned_data['odpoved']}") continue HlasovaniOZnalostech.objects.create( odpoved=form.cleaned_data['odpoved'], znalost=znalost, ucastnik=osoba, seznam=seznam, ) return HttpResponseRedirect('./hotovo') else: prednasky = seznam.prednaska_set.all() znalosti = seznam.znalost_set.all() # Spadnout, pokud nesedí přednáška/znalost s formulářem. (Nějak se mi to nepovedlo.) else: def odpoved_prednasky(p): hlasovani = p.hlasovani_set.filter(ucastnik=ucastnik).first() return hlasovani.body if hlasovani else Hlasovani.Body.JEDNO def odpoved_znalosti(z): hlasovani = z.hlasovanioznalostech_set.filter(ucastnik=osoba).first() return hlasovani.odpoved if hlasovani else Hlasovani.Body.JEDNO prednasky = seznam.prednaska_set.all() znalosti = seznam.znalost_set.all() form_set_prednasky = HlasovaniPrednaskaFormSet(initial=[ {"prednaska_id": p.id, "body": odpoved_prednasky(p)} for p in prednasky ], prefix=PREDNASKY_PREFIX) form_set_znalosti = HlasovaniZnalostiFormSet(initial=[ {"znalost_id": z.id, "odpoved": odpoved_znalosti(z)} for z in znalosti ], prefix=ZNALOSTI_PREFIX) return render( request, 'prednasky/base.html', { 'form_set_prednasky': form_set_prednasky, 'form_set_znalosti': form_set_znalosti, 'formy_a_prednasky': zip(form_set_prednasky, prednasky), 'formy_a_znalosti': zip(form_set_znalosti, znalosti), } ) def Prednaska_hotovo(request): return formularOKView(request, "Děkujeme za vyplnění hlasování o přednáškách a těšíme se na soustředění.") class MetaSeznamListView(generic.ListView): model = Seznam template_name = 'prednasky/metaseznam_prednasek.html' class SeznamListView(generic.ListView): template_name = 'prednasky/seznam_prednasek.html' def get_queryset(self): self.seznam = get_object_or_404(Seznam, id=self.kwargs["seznam"]) prednasky = Prednaska.objects.filter(seznamy=self.seznam).order_by( 'org__osoba__user__first_name', 'org__osoba__user__last_name' ) return prednasky # FIXME nahradit anotaci s filtrem po prechodu na Django 2.2 def get_context_data(self,**kwargs): context = super(SeznamListView, self).get_context_data(**kwargs) # hlasovani se vztahuje k nejnovejsimu soustredeni sous = Soustredeni.objects.first() seznam = Seznam.objects.filter(soustredeni = sous, stav=Seznam.Stav.NAVRH).first() for obj in self.object_list: hlasovani_set = obj.hlasovani_set.filter(seznam=seznam).only('body') obj.body = sum(map(lambda x: x.body,hlasovani_set)) return context # def SeznamExportView(request, seznam): # """Vypíše výsledky hlasování ve formátu pro prologovský optimalizátor""" # # TODO zřejmě se nepoužívá, časem vyřadit? nahradit tabulkou vhodnější pro # # lidi? # hlasovani = Hlasovani.objects.filter(seznam=seznam) # prednasky = Prednaska.objects.filter(seznamy=seznam) # orgove = set(p.org for p in prednasky) # ucastnici = set(h.ucastnik for h in hlasovani) # # for p in prednasky: # p.body = [] # for u in ucastnici: # try: # p.body.append(hlasovani.get(ucastnik=u, prednaska=p).body) # except ObjectDoesNotExist: # # účastník nehlasoval # p.body.append("?") # # for h in hlasovani: # h.ucastnik = hash(h.ucastnik) # # return render( # request, # 'prednasky/seznam_prednasek_export.txt', # {"hlasovani": hlasovani, "prednasky": prednasky, "orgove": orgove}, # content_type="text/plain" # ) def PrednaskyExportView(request, seznam: int, **kwargs): hlasovani = Hlasovani.objects.filter(seznam=seznam).select_related("prednaska") hlasovani_o_znalostech = HlasovaniOZnalostech.objects.filter(seznam=seznam).select_related('ucastnik', 'znalost') prednasky = list(Prednaska.objects.filter(seznamy=seznam)) znalosti = list(Znalost.objects.filter(seznamy=seznam)) prednasky_map: dict[int, int] = {p.id: i for i, p in enumerate(prednasky, 1)} offset = len(prednasky_map) znalosti_map: dict[int, int] = {z.id: i for i, z in enumerate(znalosti, offset + 1)} width = offset + len(znalosti_map) table: [str, list[str|Prednaska|Znalost,]] = {} for h in hlasovani: if h.ucastnik not in table: table[h.ucastnik] = [h.ucastnik] + ([""] * width) if h.prednaska.id in prednasky_map: table[h.ucastnik][prednasky_map[h.prednaska.id]] = h.body else: pass # Padat hlasitě? for h in hlasovani_o_znalostech: ucastnik = str(h.ucastnik) + ' ' + str(h.ucastnik.id) # id, kvůli kolizi jmen if ucastnik not in table: table[ucastnik] = [ucastnik] + ([""] * width) if h.znalost.id in znalosti_map: table[ucastnik][znalosti_map[h.znalost.id]] = h.odpoved else: pass # Padat hlasitě? response = HttpResponse(content_type="text/csv", charset="utf-8") response["Content-Disposition"] = 'attachment; filename="hlasovani.csv"' writer = csv.writer(response) writer.writerow(["jména \\ přednáška|znalost"] + list(map(str, prednasky + znalosti))) for row in table.values(): writer.writerow(list(map(str, row))) return response