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() 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: queryset = Student.objects.filter(identifier__startswith=f'{edition.year}-{request.user.id}').order_by('identifier') return render(request, 'user/submission.html', {'students': queryset, **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) 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, '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 = 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)) individual = filter(lambda x: x['score'] >= edition.award_threshold, individual) 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) 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