218 lines
7.4 KiB
Python
218 lines
7.4 KiB
Python
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
|
|
|
|
|