puchar/app/views.py

197 lines
6.3 KiB
Python

from django.forms import formset_factory
from django.shortcuts import render, redirect, get_object_or_404
from django.urls import reverse_lazy
from django.views.generic.edit import CreateView
from django.views.generic import TemplateView
from django.contrib.auth.decorators import login_required
from django.db import transaction
from functools import reduce
from .forms import CustomUserCreationForm, CustomUserChangeForm, StudentForm
from .models import Announcement, Edition, Student
class SignUpView(CreateView):
form_class = CustomUserCreationForm
success_url = reverse_lazy('login')
template_name = 'registration/signup.html'
@login_required
def UpdateAccountView(request):
if request.method == 'POST':
form = CustomUserChangeForm(request.POST, instance=request.user)
if form.is_valid():
form.save()
request.user.updateTeam()
else:
form = CustomUserChangeForm(instance=request.user)
return render(request, 'user/account.html', {'account_page': 'is-active', 'account_tab': 'is-active', 'ongoing': Edition.current(), 'form': form})
@login_required
def SubmitStudentsView(request):
edition = Edition.current()
if edition is not None:
context = {
'account_page': 'is-active',
'submission_tab': 'is-active',
'ongoing': edition,
}
if edition.submissions is not True:
ranking = {}
for index, student in enumerate(sorted(Student.objects.filter(identifier__startswith=f'{edition.year}-'), key=lambda x: x.score_first*x.score_second, reverse=True)):
ranking[student.identifier] = index + 1
queryset = Student.objects.filter(
identifier__startswith=f'{edition.year}-{request.user.id}-').order_by('identifier')
students = [{**student.__dict__, 'ranking': ranking[student.identifier]}
for student in queryset]
return render(request, 'user/submission.html', {'students': students, **context})
queryset = Student.objects.filter(
identifier__startswith=f'{edition.year}-{request.user.id}-')
ArticleFormSet = formset_factory(
StudentForm, extra=3, max_num=3, min_num=0)
if request.method == 'POST':
with transaction.atomic():
formset = ArticleFormSet(request.POST)
if formset.is_valid():
queryset.delete()
students = filter(lambda x: x != {}, formset.cleaned_data)
for index, data in enumerate(students):
Student.objects.update_or_create(
identifier=f'{edition.year}-{request.user.id}-{index + 1}', defaults=data)
request.user.updateTeam()
else:
formset = ArticleFormSet(initial=list(
map(lambda x: x.__dict__, queryset)))
return render(request, 'user/submit.html', {'formset': formset, 'students': len(queryset), **context})
else:
return redirect(reverse_lazy('account'))
class AboutContestView(TemplateView):
template_name = 'home.html'
extra_context = {
'aboutcontest_page': 'is-active'
}
class NewsView(TemplateView):
template_name = 'news.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['news_page'] = 'is-active'
context['announcements'] = Announcement.objects.all()
return context
class RulesView(TemplateView):
template_name = 'rules.html'
extra_context = {
'rules_page': 'is-active'
}
class TestsView(TemplateView):
template_name = 'tests.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['tests_page'] = 'is-active'
context['editions'] = Edition.objects.order_by('-year')
return context
def ScoresView(request, year=None):
if year is not None:
edition = get_object_or_404(Edition, year=year)
else:
edition = Edition.objects.filter(
scores_available=True).order_by('-year').first()
if edition is None:
edition = Edition.objects.order_by('-year').first()
year = edition.year
context = {
'scores_page': 'is-active',
'year': year,
'scores_available': edition.scores_available or request.user.is_superuser,
'admin_preview': (not edition.scores_available) and request.user.is_superuser,
'editions': Edition.objects.order_by('year')
}
students = Student.objects.filter(identifier__startswith=year)
schools = map(lambda x: {
'id': x.identifier.split('-')[1],
'name': x.school_name,
'town': x.school_town
}, students)
schools = list({school['id']: school for school in schools}.values())
individual = filter(lambda x: x['score'] >= edition.award_threshold,
map(lambda x: {
**x.__dict__,
'score': x.score_first * x.score_second,
'title': 'Laureat' if x.score_first * x.score_second >= edition.laureate_threshold else 'Wyróżnienie'
}, students.filter(score_first__gte=edition.entry_threshold)))
teams = []
for school in schools:
team = students.filter(
identifier__startswith=f'{year}-' + school['id'] + '-')
score_first = reduce(lambda x, y: x + y.score_first, team, 0)
score_second = reduce(lambda x, y: x + y.score_second, team, 0)
if score_first*score_second > 0:
teams.append({**school, 'score': score_first * score_second})
context = {
'individual': sorted(individual, key=lambda x: -x['score']),
'teams': sorted(teams, key=lambda x: -x['score']),
**context
}
return render(request, 'scores.html', context)
class ContactView(TemplateView):
template_name = 'contact.html'
extra_context = {
'contact_page': 'is-active'
}
class RobotsView(TemplateView):
template_name = 'robots.txt'
content_type = 'text/plain'
class SitemapView(TemplateView):
template_name = 'sitemap.xml'
content_type = 'text/xml'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['latest'] = Announcement.objects.first()
return context