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: identifier = f'{edition.year}-{request.user.id}-' queryset = Student.objects.filter(identifier__startswith=identifier) if edition.submissions is not True: identifier = f'{edition.year}-{request.user.id}' queryset = Student.objects.filter(identifier__startswith=identifier).order_by('identifier') return render(request, 'user/submission.html', {'account_page': 'is-active', 'submission_tab': 'is-active', 'ongoing': edition, 'students': queryset}) ArticleFormSet = formset_factory(StudentForm, extra=2, max_num=3, min_num=1) 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', {'account_page': 'is-active', 'submission_tab': 'is-active', 'ongoing': True, 'formset': formset}) else: return redirect(reverse_lazy('account')) class HomeView(TemplateView): template_name = 'home.html' class NewsView(TemplateView): template_name = 'news.html' extra_context = { 'news_page': 'is-active', 'announcements': Announcement.objects.all(), } class RulesView(TemplateView): template_name = 'rules.html' extra_context = { 'rules_page': 'is-active' } class TestsView(TemplateView): template_name = 'tests.html' extra_context = { 'tests_page': 'is-active', 'editions': Edition.objects.order_by('-year') } def ScoresRedirect(request): latest = Edition.objects.filter(scores_available=True).order_by('-year').first() if latest is not None: return redirect(reverse_lazy('scores', args=[latest.year])) else: return redirect(reverse_lazy('home')) def ScoresView(request, year): edition = get_object_or_404(Edition, year=year) if edition.scores_available is not True: return redirect('scores') 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 = { 'scores_page': 'is-active', 'year': year, 'editions': Edition.objects.filter(scores_available=True), 'individual': sorted(individual, key=lambda x: -x['score']), 'teams': sorted(teams, key=lambda x: -x['score']) } return render(request, 'scores.html', context) class ContactView(TemplateView): template_name = 'contact.html' extra_context = { 'contact_page': 'is-active' }