From 8cde47bab7ba772d8c9560f3674bba3345771c2c Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 02:24:12 +0200 Subject: [PATCH 001/132] C'est parti ... --- .gitignore | 47 ++++++++++++++ Dockerfile | 18 ++++++ apps/member/__init__.py | 0 apps/tournament/__init__.py | 0 entrypoint.sh | 9 +++ manage.py | 21 +++++++ requirements.txt | 24 +++++++ tfjm/__init__.py | 0 tfjm/asgi.py | 16 +++++ tfjm/settings.py | 121 ++++++++++++++++++++++++++++++++++++ tfjm/urls.py | 21 +++++++ tfjm/wsgi.py | 16 +++++ 12 files changed, 293 insertions(+) create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 apps/member/__init__.py create mode 100644 apps/tournament/__init__.py create mode 100755 entrypoint.sh create mode 100755 manage.py create mode 100644 requirements.txt create mode 100644 tfjm/__init__.py create mode 100644 tfjm/asgi.py create mode 100644 tfjm/settings.py create mode 100644 tfjm/urls.py create mode 100644 tfjm/wsgi.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f908240 --- /dev/null +++ b/.gitignore @@ -0,0 +1,47 @@ +# Server config files +nginx_note.conf + +# Byte-compiled / optimized / DLL files +dist +build +__pycache__ +*.py[cod] +*$py.class +*.swp +*.egg-info +_build +.tox +.coverage +coverage + +# Translations +*.mo +*.pot + +# Jupyter Notebook +.ipynb_checkpoints + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# PyCharm project settings +.idea + +# VSCode project settings +.vscode + +# Local data +secrets.py +*.log +media/ +# Virtualenv +env/ +venv/ +db.sqlite3 + +# Ignore migrations during first phase dev +migrations/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..39e3aa5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM python:3-buster + +ENV PYTHONUNBUFFERED 1 + +RUN mkdir /code +WORKDIR /code + +# Install LaTeX requirements +RUN apt update && \ + apt install -y texlive-latex-extra texlive-fonts-extra texlive-lang-french && \ + rm -rf /var/lib/apt/lists/* + +COPY . /code/ + +RUN pip install -r requirements.txt + +ENTRYPOINT ["/code/entrypoint.sh"] +EXPOSE 8000 diff --git a/apps/member/__init__.py b/apps/member/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/tournament/__init__.py b/apps/tournament/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100755 index 0000000..5fb94c4 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Copyright (C) 2018-2020 by BDE ENS Paris-Saclay +# SPDX-License-Identifier: GPL-3.0-or-later + +python manage.py compilemessages +python manage.py makemigrations +python manage.py migrate + +python manage.py runserver 0.0.0.0:8000 diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..2bf0cbf --- /dev/null +++ b/manage.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python +"""Django's command-line utility for administrative tasks.""" +import os +import sys + + +def main(): + os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tfjm.settings') + try: + from django.core.management import execute_from_command_line + except ImportError as exc: + raise ImportError( + "Couldn't import Django. Are you sure it's installed and " + "available on your PYTHONPATH environment variable? Did you " + "forget to activate a virtual environment?" + ) from exc + execute_from_command_line(sys.argv) + + +if __name__ == '__main__': + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..c1ebf46 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,24 @@ +certifi==2019.6.16 +chardet==3.0.4 +defusedxml==0.6.0 +Django~=3.0 +django-allauth==0.39.1 +django-crispy-forms==1.7.2 +django-extensions==2.1.9 +django-filter==2.2.0 +django-polymorphic==2.0.3 +django-tables2==2.1.0 +docutils==0.14 +idna==2.8 +oauthlib==3.1.0 +Pillow==6.1.0 +python3-openid==3.1.0 +pytz==2019.1 +requests==2.22.0 +requests-oauthlib==1.2.0 +six==1.12.0 +sqlparse==0.3.0 +djangorestframework==3.9.0 +django-rest-polymorphic==0.1.8 +urllib3==1.25.3 +psycopg2-binary==2.8.4 diff --git a/tfjm/__init__.py b/tfjm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tfjm/asgi.py b/tfjm/asgi.py new file mode 100644 index 0000000..a75729d --- /dev/null +++ b/tfjm/asgi.py @@ -0,0 +1,16 @@ +""" +ASGI config for tfjm project. + +It exposes the ASGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ +""" + +import os + +from django.core.asgi import get_asgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tfjm.settings') + +application = get_asgi_application() diff --git a/tfjm/settings.py b/tfjm/settings.py new file mode 100644 index 0000000..507fe74 --- /dev/null +++ b/tfjm/settings.py @@ -0,0 +1,121 @@ +""" +Django settings for tfjm project. + +Generated by 'django-admin startproject' using Django 3.0.5. + +For more information on this file, see +https://docs.djangoproject.com/en/3.0/topics/settings/ + +For the full list of settings and their values, see +https://docs.djangoproject.com/en/3.0/ref/settings/ +""" + +import os + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + + +# Quick-start development settings - unsuitable for production +# See https://docs.djangoproject.com/en/3.0/howto/deployment/checklist/ + +# SECURITY WARNING: keep the secret key used in production secret! +SECRET_KEY = '6$wl1=ehfoiymin3m3i-wyx5d3t=1h7g4(j2izn*my)*yiq#he' + +# SECURITY WARNING: don't run with debug turned on in production! +DEBUG = True + +ALLOWED_HOSTS = ['*'] + + +# Application definition + +INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +] + +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] + +ROOT_URLCONF = 'tfjm.urls' + +TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [os.path.join(BASE_DIR, 'templates')] + , + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +] + +WSGI_APPLICATION = 'tfjm.wsgi.application' + + +# Database +# https://docs.djangoproject.com/en/3.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + + +# Password validation +# https://docs.djangoproject.com/en/3.0/ref/settings/#auth-password-validators + +AUTH_PASSWORD_VALIDATORS = [ + { + 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', + }, + { + 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', + }, +] + + +# Internationalization +# https://docs.djangoproject.com/en/3.0/topics/i18n/ + +LANGUAGE_CODE = 'fr-fr' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + + +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/3.0/howto/static-files/ + +STATIC_URL = '/static/' diff --git a/tfjm/urls.py b/tfjm/urls.py new file mode 100644 index 0000000..1a5069e --- /dev/null +++ b/tfjm/urls.py @@ -0,0 +1,21 @@ +"""tfjm URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/3.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] diff --git a/tfjm/wsgi.py b/tfjm/wsgi.py new file mode 100644 index 0000000..7fd654c --- /dev/null +++ b/tfjm/wsgi.py @@ -0,0 +1,16 @@ +""" +WSGI config for tfjm project. + +It exposes the WSGI callable as a module-level variable named ``application``. + +For more information on this file, see +https://docs.djangoproject.com/en/3.0/howto/deployment/wsgi/ +""" + +import os + +from django.core.wsgi import get_wsgi_application + +os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'tfjm.settings') + +application = get_wsgi_application() From 6a3390bb8d6e39140aeaf30384d8895936361bce Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 04:06:02 +0200 Subject: [PATCH 002/132] Create models --- apps/member/admin.py | 3 + apps/member/apps.py | 5 + apps/member/migrations/__init__.py | 0 apps/member/models.py | 219 +++++++++++++++++++++++++ apps/member/tests.py | 3 + apps/member/views.py | 3 + apps/tournament/admin.py | 3 + apps/tournament/apps.py | 5 + apps/tournament/migrations/__init__.py | 0 apps/tournament/models.py | 171 +++++++++++++++++++ apps/tournament/tests.py | 3 + apps/tournament/views.py | 3 + requirements.txt | 2 +- tfjm/settings.py | 9 + 14 files changed, 428 insertions(+), 1 deletion(-) create mode 100644 apps/member/admin.py create mode 100644 apps/member/apps.py create mode 100644 apps/member/migrations/__init__.py create mode 100644 apps/member/models.py create mode 100644 apps/member/tests.py create mode 100644 apps/member/views.py create mode 100644 apps/tournament/admin.py create mode 100644 apps/tournament/apps.py create mode 100644 apps/tournament/migrations/__init__.py create mode 100644 apps/tournament/models.py create mode 100644 apps/tournament/tests.py create mode 100644 apps/tournament/views.py diff --git a/apps/member/admin.py b/apps/member/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/apps/member/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/member/apps.py b/apps/member/apps.py new file mode 100644 index 0000000..b704170 --- /dev/null +++ b/apps/member/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class MemberConfig(AppConfig): + name = 'apps.member' diff --git a/apps/member/migrations/__init__.py b/apps/member/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/member/models.py b/apps/member/models.py new file mode 100644 index 0000000..6f562c5 --- /dev/null +++ b/apps/member/models.py @@ -0,0 +1,219 @@ +from django.contrib.auth.models import AbstractUser +from django.db import models +from django.utils.translation import gettext_lazy as _ +from polymorphic.models import PolymorphicModel + +from tournament.models import Team, Tournament + + +class TFJMUser(AbstractUser): + USERNAME_FIELD = 'email' + REQUIRED_FIELDS = [] + + email = models.EmailField( + unique=True, + verbose_name=_("email"), + ) + + team = models.ForeignKey( + Team, + null=True, + on_delete=models.SET_NULL, + related_name="users", + verbose_name=_("team"), + ) + + birth_date = models.DateField( + null=True, + default=None, + verbose_name=_("birth date"), + ) + + gender = models.CharField( + max_length=16, + null=True, + default=None, + choices=[ + ("male", _("Male")), + ("female", _("Female")), + ("non-binary", _("Non binary")), + ], + verbose_name=_("addresss"), + ) + + address = models.CharField( + max_length=255, + null=True, + default=None, + verbose_name=_("address"), + ) + + postal_code = models.PositiveSmallIntegerField( + null=True, + default=None, + verbose_name=_("postal code"), + ) + + city = models.CharField( + max_length=255, + null=True, + default=None, + verbose_name=_("city"), + ) + + country = models.CharField( + max_length=255, + default="France", + null=True, + verbose_name=_("country"), + ) + + phone_number = models.CharField( + max_length=20, + null=True, + blank=True, + default=None, + verbose_name=_("phone number"), + ) + + school = models.CharField( + max_length=255, + null=True, + default=None, + verbose_name=_("school"), + ) + + student_class = models.CharField( + max_length=16, + choices=[ + ('seconde', _("Seconde or less")), + ('première', _("Première")), + ('terminale', _("Terminale")), + ], + null=True, + default=None, + verbose_name="class", + ) + + responsible_name = models.CharField( + max_length=255, + null=True, + default=None, + verbose_name=_("responsible name"), + ) + + responsible_phone = models.CharField( + max_length=20, + null=True, + default=None, + verbose_name=_("responsible phone"), + ) + + responsible_email = models.EmailField( + null=True, + default=None, + verbose_name=_("responsible email"), + ) + + description = models.TextField( + null=True, + default=None, + verbose_name=_("description"), + ) + + role = models.CharField( + max_length=16, + choices=[ + ("admin", _("admin")), + ("organizer", _("organizer")), + ("encadrant", _("encadrant")), + ("participant", _("participant")), + ] + ) + + year = models.PositiveIntegerField( + verbose_name=_("year"), + ) + + class Meta: + verbose_name = _("user") + verbose_name_plural = _("users") + + +class AbstractDocument(PolymorphicModel): + file = models.FileField( + unique=True, + upload_to="files/", + verbose_name=_("file"), + ) + + team = models.ForeignKey( + Team, + on_delete=models.CASCADE, + related_name="documents", + verbose_name=_("team"), + ) + + tournament = models.ForeignKey( + Tournament, + on_delete=models.CASCADE, + related_name="documents", + verbose_name=_("tournament"), + ) + + type = models.CharField( + max_length=32, + choices=[ + ("parental_consent", _("Parental consent")), + ("photo_consent", _("Photo consent")), + ("sanitary_plug", _("Sanitary plug")), + ("motivation_letter", _("Motivation letter")), + ("scholarship", _("Scholarship")), + ("solution", _("Solution")), + ("synthesis", _("Synthesis")), + ], + verbose_name=_("type"), + ) + + uploaded_at = models.DateTimeField( + auto_now_add=True, + verbose_name=_("uploaded at"), + ) + + class Meta: + verbose_name = _("abstract document") + verbose_name_plural = _("abstract documents") + + +class Document(AbstractDocument): + class Meta: + verbose_name = _("document") + verbose_name_plural = _("documents") + + +class Solution(Document): + problem = models.PositiveSmallIntegerField( + verbose_name=_("problem"), + ) + + def save(self, **kwargs): + self.type = "solution" + super().save(**kwargs) + + class Meta: + verbose_name = _("solution") + verbose_name_plural = _("solutions") + + +class Synthesis(Document): + problem = models.PositiveSmallIntegerField( + verbose_name=_("problem"), + ) + + def save(self, **kwargs): + self.type = "synthesis" + super().save(**kwargs) + + class Meta: + verbose_name = _("synthesis") + verbose_name_plural = _("syntheses") diff --git a/apps/member/tests.py b/apps/member/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/apps/member/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/member/views.py b/apps/member/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/apps/member/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/apps/tournament/admin.py b/apps/tournament/admin.py new file mode 100644 index 0000000..8c38f3f --- /dev/null +++ b/apps/tournament/admin.py @@ -0,0 +1,3 @@ +from django.contrib import admin + +# Register your models here. diff --git a/apps/tournament/apps.py b/apps/tournament/apps.py new file mode 100644 index 0000000..eec1530 --- /dev/null +++ b/apps/tournament/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class TournamentConfig(AppConfig): + name = 'apps.tournament' diff --git a/apps/tournament/migrations/__init__.py b/apps/tournament/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/tournament/models.py b/apps/tournament/models.py new file mode 100644 index 0000000..0628115 --- /dev/null +++ b/apps/tournament/models.py @@ -0,0 +1,171 @@ +import os + +from django.db import models +from django.utils.translation import gettext_lazy as _ + + +class Tournament(models.Model): + name = models.CharField( + max_length=255, + verbose_name=_("name"), + ) + + organizers = models.ManyToManyField( + 'member.TFJMUser', + related_name="organized_tournaments", + verbose_name=_("organizers"), + ) + + size = models.PositiveSmallIntegerField( + verbose_name=_("size"), + ) + + place = models.CharField( + max_length=255, + verbose_name=_("place"), + ) + + price = models.PositiveSmallIntegerField( + verbose_name=_("price"), + ) + + description = models.TextField( + verbose_name=_("description"), + ) + + date_start = models.DateField( + verbose_name=_("date start"), + ) + + date_end = models.DateField( + verbose_name=_("date start"), + ) + + date_inscription = models.DateTimeField( + verbose_name=_("date of registration closing"), + ) + + date_solutions = models.DateTimeField( + verbose_name=_("date of maximal solution submission"), + ) + + date_syntheses = models.DateTimeField( + verbose_name=_("date of maximal syntheses submission"), + ) + + final = models.BooleanField( + verbose_name=_("final tournament"), + ) + + year = models.PositiveIntegerField( + verbose_name=_("year") + ) + + @classmethod + def get_final(cls): + return cls.objects.get(year=os.getenv("TFJM_YEAR"), final=True) + + class Meta: + verbose_name = _("tournament") + verbose_name_plural = _("tournaments") + + +class Team(models.Model): + name = models.CharField( + max_length=255, + verbose_name=_("name"), + ) + + trigram = models.CharField( + max_length=3, + verbose_name=_("trigram"), + ) + + tournament = models.ForeignKey( + Tournament, + on_delete=models.PROTECT, + verbose_name=_("tournament"), + ) + + inscription_date = models.DateTimeField( + auto_now_add=True, + verbose_name=_("inscription date"), + ) + + validation_status = models.CharField( + max_length=8, + choices=[ + ("invalid", _("Registration not validated")), + ("waiting", _("Waiting for validation")), + ("valid", _("Registration validated")), + ], + verbose_name=_("validation status"), + ) + + selected_for_final = models.BooleanField( + default=False, + verbose_name=_("selected for final"), + ) + + access_code = models.CharField( + max_length=6, + unique=True, + verbose_name=_("access code"), + ) + + year = models.PositiveIntegerField( + verbose_name=_("year"), + ) + + @property + def encadrants(self): + return self.users.filter(role="encadrant") + + @property + def participants(self): + return self.users.filter(role="participant") + + class Meta: + verbose_name = _("team") + verbose_name_plural = _("teams") + unique_together = (('name', 'year',), ('trigram', 'year',),) + + +class Payment(models.Model): + user = models.OneToOneField( + 'member.TFJMUser', + on_delete=models.CASCADE, + related_name="payment", + verbose_name=_("user"), + ) + + team = models.ForeignKey( + Team, + on_delete=models.CASCADE, + related_name="payments", + verbose_name=_("team"), + ) + + method = models.CharField( + max_length=16, + choices=[ + ("not_paid", _("Not paid")), + ("credit_card", _("Credit card")), + ("check", _("Bank check")), + ("transfer", _("Bank transfer")), + ("cash", _("Cash")), + ("scholarship", _("Scholarship")), + ], + default="not_paid", + verbose_name=_("payment method"), + ) + + validation_status = models.CharField( + max_length=8, + choices=[ + ("invalid", _("Registration not validated")), + ("waiting", _("Waiting for validation")), + ("valid", _("Registration validated")), + ], + verbose_name=_("validation status"), + ) diff --git a/apps/tournament/tests.py b/apps/tournament/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/apps/tournament/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/tournament/views.py b/apps/tournament/views.py new file mode 100644 index 0000000..91ea44a --- /dev/null +++ b/apps/tournament/views.py @@ -0,0 +1,3 @@ +from django.shortcuts import render + +# Create your views here. diff --git a/requirements.txt b/requirements.txt index c1ebf46..9dc350c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,7 +6,7 @@ django-allauth==0.39.1 django-crispy-forms==1.7.2 django-extensions==2.1.9 django-filter==2.2.0 -django-polymorphic==2.0.3 +django-polymorphic==2.1.2 django-tables2==2.1.0 docutils==0.14 idna==2.8 diff --git a/tfjm/settings.py b/tfjm/settings.py index 507fe74..fd4844e 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -11,9 +11,13 @@ https://docs.djangoproject.com/en/3.0/ref/settings/ """ import os +import sys # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +APPS_DIR = os.path.realpath(os.path.join(BASE_DIR, "apps")) +sys.path.append(APPS_DIR) # Quick-start development settings - unsuitable for production @@ -37,6 +41,9 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + + 'member', + 'tournament', ] MIDDLEWARE = [ @@ -100,6 +107,8 @@ AUTH_PASSWORD_VALIDATORS = [ }, ] +AUTH_USER_MODEL = 'member.TFJMUser' + # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ From 706de5bd41fb4ca14310087b70e248d124671ad7 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 04:26:26 +0200 Subject: [PATCH 003/132] Update translations --- Dockerfile | 2 +- apps/member/management/__init__.py | 0 apps/member/management/commands/__init__.py | 0 apps/member/management/commands/create_su.py | 30 ++ apps/member/models.py | 2 +- locale/fr/LC_MESSAGES/django.po | 319 +++++++++++++++++++ tfjm/settings.py | 13 +- 7 files changed, 363 insertions(+), 3 deletions(-) create mode 100644 apps/member/management/__init__.py create mode 100644 apps/member/management/commands/__init__.py create mode 100644 apps/member/management/commands/create_su.py create mode 100644 locale/fr/LC_MESSAGES/django.po diff --git a/Dockerfile b/Dockerfile index 39e3aa5..fc59134 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,7 +7,7 @@ WORKDIR /code # Install LaTeX requirements RUN apt update && \ - apt install -y texlive-latex-extra texlive-fonts-extra texlive-lang-french && \ + apt install -y gettext texlive-latex-extra texlive-fonts-extra texlive-lang-french && \ rm -rf /var/lib/apt/lists/* COPY . /code/ diff --git a/apps/member/management/__init__.py b/apps/member/management/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/member/management/commands/__init__.py b/apps/member/management/commands/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/member/management/commands/create_su.py b/apps/member/management/commands/create_su.py new file mode 100644 index 0000000..9d7df58 --- /dev/null +++ b/apps/member/management/commands/create_su.py @@ -0,0 +1,30 @@ +import os +from datetime import date +from getpass import getpass + +from django.core.management import BaseCommand +from member.models import TFJMUser + + +class Command(BaseCommand): + def handle(self, *args, **options): + email = input("Email: ") + password = "1" + confirm_password = "2" + while password != confirm_password: + password = getpass("Password: ") + confirm_password = getpass("Confirm password: ") + if password != confirm_password: + self.stderr.write(self.style.ERROR("Passwords don't match.")) + + user = TFJMUser.objects.create( + email=email, + password="", + role="admin", + year=os.getenv("TFJM_YEAR", date.today().year), + is_active=True, + is_staff=True, + is_superuser=True, + ) + user.set_password(password) + user.save() diff --git a/apps/member/models.py b/apps/member/models.py index 6f562c5..62ed9cf 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -38,7 +38,7 @@ class TFJMUser(AbstractUser): ("female", _("Female")), ("non-binary", _("Non binary")), ], - verbose_name=_("addresss"), + verbose_name=_("address"), ) address = models.CharField( diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po new file mode 100644 index 0000000..22a99ba --- /dev/null +++ b/locale/fr/LC_MESSAGES/django.po @@ -0,0 +1,319 @@ +# SOME DESCRIPTIVE TITLE. +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the PACKAGE package. +# FIRST AUTHOR , YEAR. +# +#, fuzzy +msgid "" +msgstr "" +"Project-Id-Version: TFJM2\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2020-04-29 02:09+0000\n" +"PO-Revision-Date: 2020-04-29 02:09+0000\n" +"Last-Translator: Yohann D'ANELLO \n" +"Language-Team: fr \n" +"Language: fr\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n > 1);\n" + +#: apps/member/models.py:15 +msgid "email" +msgstr "Adresse électronique" + +#: apps/member/models.py:23 apps/member/models.py:154 +#: apps/tournament/models.py:129 apps/tournament/models.py:146 +msgid "team" +msgstr "équipe" + +#: apps/member/models.py:29 +msgid "birth date" +msgstr "date de naissance" + +#: apps/member/models.py:37 +msgid "Male" +msgstr "Homme" + +#: apps/member/models.py:38 +msgid "Female" +msgstr "Femme" + +#: apps/member/models.py:39 +msgid "Non binary" +msgstr "Non binaire" + +#: apps/member/models.py:41 +#: apps/member/models.py:48 +msgid "address" +msgstr "adresse" + +#: apps/member/models.py:54 +msgid "postal code" +msgstr "code postal" + +#: apps/member/models.py:61 +msgid "city" +msgstr "ville" + +#: apps/member/models.py:68 +msgid "country" +msgstr "pays" + +#: apps/member/models.py:76 +msgid "phone number" +msgstr "numéro de téléphone" + +#: apps/member/models.py:83 +msgid "school" +msgstr "école" + +#: apps/member/models.py:89 +msgid "Seconde or less" +msgstr "Seconde ou inférieur" + +#: apps/member/models.py:90 +msgid "Première" +msgstr "Première" + +#: apps/member/models.py:91 +msgid "Terminale" +msgstr "Terminale" + +#: apps/member/models.py:102 +msgid "responsible name" +msgstr "nom du responsable" + +#: apps/member/models.py:109 +msgid "responsible phone" +msgstr "téléphone du responsable" + +#: apps/member/models.py:115 +msgid "responsible email" +msgstr "email du responsable" + +#: apps/member/models.py:121 apps/tournament/models.py:33 +msgid "description" +msgstr "description" + +#: apps/member/models.py:127 +msgid "admin" +msgstr "administrateur" + +#: apps/member/models.py:128 +msgid "organizer" +msgstr "oragnisateur" + +#: apps/member/models.py:129 +msgid "encadrant" +msgstr "encadrant" + +#: apps/member/models.py:130 +msgid "participant" +msgstr "participant" + +#: apps/member/models.py:135 apps/tournament/models.py:61 +#: apps/tournament/models.py:117 +msgid "year" +msgstr "année" + +#: apps/member/models.py:139 apps/tournament/models.py:139 +msgid "user" +msgstr "utilisateur" + +#: apps/member/models.py:140 +msgid "users" +msgstr "utilisateurs" + +#: apps/member/models.py:147 +msgid "file" +msgstr "fichier" + +#: apps/member/models.py:161 apps/tournament/models.py:69 +#: apps/tournament/models.py:87 +msgid "tournament" +msgstr "tournoi" + +#: apps/member/models.py:167 +msgid "Parental consent" +msgstr "Autorisation parentale" + +#: apps/member/models.py:168 +msgid "Photo consent" +msgstr "Autorisation de droit à l'image" + +#: apps/member/models.py:169 +msgid "Sanitary plug" +msgstr "Fiche sanitaire" + +#: apps/member/models.py:170 +msgid "Motivation letter" +msgstr "Lettre de motivation" + +#: apps/member/models.py:171 apps/tournament/models.py:157 +msgid "Scholarship" +msgstr "Bourse" + +#: apps/member/models.py:172 +msgid "Solution" +msgstr "Solution" + +#: apps/member/models.py:173 +msgid "Synthesis" +msgstr "Synthèse" + +#: apps/member/models.py:175 +msgid "type" +msgstr "type" + +#: apps/member/models.py:180 +msgid "uploaded at" +msgstr "téléversé le" + +#: apps/member/models.py:184 +msgid "abstract document" +msgstr "document abstrait" + +#: apps/member/models.py:185 +msgid "abstract documents" +msgstr "documents abstraits" + +#: apps/member/models.py:190 +msgid "document" +msgstr "document" + +#: apps/member/models.py:191 +msgid "documents" +msgstr "documents" + +#: apps/member/models.py:196 apps/member/models.py:210 +msgid "problem" +msgstr "problème" + +#: apps/member/models.py:204 +msgid "solution" +msgstr "solution" + +#: apps/member/models.py:205 +msgid "solutions" +msgstr "solutions" + +#: apps/member/models.py:218 +msgid "synthesis" +msgstr "synthèse" + +#: apps/member/models.py:219 +msgid "syntheses" +msgstr "synthèses" + +#: apps/tournament/models.py:10 apps/tournament/models.py:76 +msgid "name" +msgstr "nom" + +#: apps/tournament/models.py:16 +msgid "organizers" +msgstr "organisateurs" + +#: apps/tournament/models.py:20 +msgid "size" +msgstr "taille" + +#: apps/tournament/models.py:25 +msgid "place" +msgstr "lieu" + +#: apps/tournament/models.py:29 +msgid "price" +msgstr "prix" + +#: apps/tournament/models.py:37 apps/tournament/models.py:41 +msgid "date start" +msgstr "date de début" + +#: apps/tournament/models.py:45 +msgid "date of registration closing" +msgstr "date de clôture des inscriptions" + +#: apps/tournament/models.py:49 +msgid "date of maximal solution submission" +msgstr "date d'envoi maximal des solutions" + +#: apps/tournament/models.py:53 +msgid "date of maximal syntheses submission" +msgstr "date d'envoi maximal des notes de synthèses" + +#: apps/tournament/models.py:57 +msgid "final tournament" +msgstr "finale" + +#: apps/tournament/models.py:70 +msgid "tournaments" +msgstr "tournois" + +#: apps/tournament/models.py:81 +msgid "trigram" +msgstr "trigramme" + +#: apps/tournament/models.py:92 +msgid "inscription date" +msgstr "date d'inscription" + +#: apps/tournament/models.py:98 apps/tournament/models.py:166 +msgid "Registration not validated" +msgstr "Inscription non validée" + +#: apps/tournament/models.py:99 apps/tournament/models.py:167 +msgid "Waiting for validation" +msgstr "En attente de validation" + +#: apps/tournament/models.py:100 apps/tournament/models.py:168 +msgid "Registration validated" +msgstr "Inscription validée" + +#: apps/tournament/models.py:102 apps/tournament/models.py:170 +msgid "validation status" +msgstr "statut de validation" + +#: apps/tournament/models.py:107 +msgid "selected for final" +msgstr "sélectionnée pour la finale" + +#: apps/tournament/models.py:113 +msgid "access code" +msgstr "code d'accès" + +#: apps/tournament/models.py:130 +msgid "teams" +msgstr "équipes" + +#: apps/tournament/models.py:152 +msgid "Not paid" +msgstr "Non payé" + +#: apps/tournament/models.py:153 +msgid "Credit card" +msgstr "Carte bancaire" + +#: apps/tournament/models.py:154 +msgid "Bank check" +msgstr "Chèque bancaire" + +#: apps/tournament/models.py:155 +msgid "Bank transfer" +msgstr "Virement bancaire" + +#: apps/tournament/models.py:156 +msgid "Cash" +msgstr "Espèces" + +#: apps/tournament/models.py:160 +msgid "payment method" +msgstr "moyen de paiement" + +#: tfjm/settings.py:123 +msgid "English" +msgstr "Anglais" + +#: tfjm/settings.py:124 +msgid "French" +msgstr "Français" diff --git a/tfjm/settings.py b/tfjm/settings.py index fd4844e..a4b4e74 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -13,6 +13,8 @@ https://docs.djangoproject.com/en/3.0/ref/settings/ import os import sys +from django.utils.translation import gettext_lazy as _ + # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) @@ -54,6 +56,8 @@ MIDDLEWARE = [ 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', + 'django.middleware.locale.LocaleMiddleware', + 'django.contrib.sites.middleware.CurrentSiteMiddleware', ] ROOT_URLCONF = 'tfjm.urls' @@ -113,7 +117,12 @@ AUTH_USER_MODEL = 'member.TFJMUser' # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ -LANGUAGE_CODE = 'fr-fr' +LANGUAGE_CODE = 'en' + +LANGUAGES = [ + ('en', _('English')), + ('fr', _('French')), +] TIME_ZONE = 'UTC' @@ -123,6 +132,8 @@ USE_L10N = True USE_TZ = True +LOCALE_PATHS = [os.path.join(BASE_DIR, "locale")] + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.0/howto/static-files/ From bc869241b6f725f6b5064233298112df48f47e0f Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 04:51:25 +0200 Subject: [PATCH 004/132] Django admin management --- apps/member/__init__.py | 1 + apps/member/admin.py | 30 +++++++++++++- apps/member/apps.py | 4 +- apps/member/models.py | 7 ++++ apps/tournament/__init__.py | 1 + apps/tournament/admin.py | 19 ++++++++- apps/tournament/apps.py | 4 +- apps/tournament/models.py | 4 ++ locale/fr/LC_MESSAGES/django.po | 69 +++++++++++++++++++-------------- 9 files changed, 104 insertions(+), 35 deletions(-) diff --git a/apps/member/__init__.py b/apps/member/__init__.py index e69de29..6bb559b 100644 --- a/apps/member/__init__.py +++ b/apps/member/__init__.py @@ -0,0 +1 @@ +default_app_config = 'member.apps.MemberConfig' diff --git a/apps/member/admin.py b/apps/member/admin.py index 8c38f3f..5f3e6e7 100644 --- a/apps/member/admin.py +++ b/apps/member/admin.py @@ -1,3 +1,29 @@ -from django.contrib import admin +from django.contrib.auth.admin import admin, UserAdmin +from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin +from member.models import TFJMUser, AbstractDocument, Document, Solution, Synthesis -# Register your models here. + +@admin.register(TFJMUser) +class TFJMUserAdmin(UserAdmin): + list_display = ('email', 'first_name', 'last_name', 'role', ) + + +@admin.register(AbstractDocument) +class AbstractDocumentAdmin(PolymorphicParentModelAdmin): + child_models = (Document, Solution, Synthesis,) + polymorphic_list = True + + +@admin.register(Document) +class DocumentAdmin(PolymorphicChildModelAdmin): + pass + + +@admin.register(Solution) +class SolutionAdmin(PolymorphicChildModelAdmin): + pass + + +@admin.register(Synthesis) +class SynthesisAdmin(PolymorphicChildModelAdmin): + pass diff --git a/apps/member/apps.py b/apps/member/apps.py index b704170..6635e7e 100644 --- a/apps/member/apps.py +++ b/apps/member/apps.py @@ -1,5 +1,7 @@ from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ class MemberConfig(AppConfig): - name = 'apps.member' + name = 'member' + verbose_name = _('member') diff --git a/apps/member/models.py b/apps/member/models.py index 62ed9cf..c6fa1a3 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -139,6 +139,13 @@ class TFJMUser(AbstractUser): verbose_name = _("user") verbose_name_plural = _("users") + def save(self, *args, **kwargs): + self.username = self.email + super().save(*args, **kwargs) + + def __str__(self): + return self.first_name + " " + self.last_name + class AbstractDocument(PolymorphicModel): file = models.FileField( diff --git a/apps/tournament/__init__.py b/apps/tournament/__init__.py index e69de29..9868b56 100644 --- a/apps/tournament/__init__.py +++ b/apps/tournament/__init__.py @@ -0,0 +1 @@ +default_app_config = 'tournament.apps.TournamentConfig' diff --git a/apps/tournament/admin.py b/apps/tournament/admin.py index 8c38f3f..de69249 100644 --- a/apps/tournament/admin.py +++ b/apps/tournament/admin.py @@ -1,3 +1,18 @@ -from django.contrib import admin +from django.contrib.auth.admin import admin -# Register your models here. +from tournament.models import Team, Tournament, Payment + + +@admin.register(Team) +class TeamAdmin(admin.ModelAdmin): + pass + + +@admin.register(Tournament) +class TournamentAdmin(admin.ModelAdmin): + pass + + +@admin.register(Payment) +class PaymentAdmin(admin.ModelAdmin): + pass diff --git a/apps/tournament/apps.py b/apps/tournament/apps.py index eec1530..2df95c1 100644 --- a/apps/tournament/apps.py +++ b/apps/tournament/apps.py @@ -1,5 +1,7 @@ from django.apps import AppConfig +from django.utils.translation import gettext_lazy as _ class TournamentConfig(AppConfig): - name = 'apps.tournament' + name = 'tournament' + verbose_name = _('tournament') diff --git a/apps/tournament/models.py b/apps/tournament/models.py index 0628115..f4cf6da 100644 --- a/apps/tournament/models.py +++ b/apps/tournament/models.py @@ -169,3 +169,7 @@ class Payment(models.Model): ], verbose_name=_("validation status"), ) + + class Meta: + verbose_name = _("payment") + verbose_name_plural = _("payments") diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 22a99ba..edcc0a6 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -1,15 +1,15 @@ # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. +# FIRST AUTHOR yohann.danello@animath.fr, 2020. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: TFJM2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-29 02:09+0000\n" -"PO-Revision-Date: 2020-04-29 02:09+0000\n" +"POT-Creation-Date: 2020-04-29 02:45+0000\n" +"PO-Revision-Date: 2020-04-29 02:30+0000\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: fr \n" "Language: fr\n" @@ -18,11 +18,15 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" +#: apps/member/apps.py:7 +msgid "member" +msgstr "membre" + #: apps/member/models.py:15 msgid "email" msgstr "Adresse électronique" -#: apps/member/models.py:23 apps/member/models.py:154 +#: apps/member/models.py:23 apps/member/models.py:161 #: apps/tournament/models.py:129 apps/tournament/models.py:146 msgid "team" msgstr "équipe" @@ -43,8 +47,7 @@ msgstr "Femme" msgid "Non binary" msgstr "Non binaire" -#: apps/member/models.py:41 -#: apps/member/models.py:48 +#: apps/member/models.py:41 apps/member/models.py:48 msgid "address" msgstr "adresse" @@ -125,84 +128,84 @@ msgstr "utilisateur" msgid "users" msgstr "utilisateurs" -#: apps/member/models.py:147 +#: apps/member/models.py:154 msgid "file" msgstr "fichier" -#: apps/member/models.py:161 apps/tournament/models.py:69 -#: apps/tournament/models.py:87 +#: apps/member/models.py:168 apps/tournament/apps.py:7 +#: apps/tournament/models.py:69 apps/tournament/models.py:87 msgid "tournament" msgstr "tournoi" -#: apps/member/models.py:167 +#: apps/member/models.py:174 msgid "Parental consent" msgstr "Autorisation parentale" -#: apps/member/models.py:168 +#: apps/member/models.py:175 msgid "Photo consent" msgstr "Autorisation de droit à l'image" -#: apps/member/models.py:169 +#: apps/member/models.py:176 msgid "Sanitary plug" msgstr "Fiche sanitaire" -#: apps/member/models.py:170 +#: apps/member/models.py:177 msgid "Motivation letter" msgstr "Lettre de motivation" -#: apps/member/models.py:171 apps/tournament/models.py:157 +#: apps/member/models.py:178 apps/tournament/models.py:157 msgid "Scholarship" msgstr "Bourse" -#: apps/member/models.py:172 +#: apps/member/models.py:179 msgid "Solution" msgstr "Solution" -#: apps/member/models.py:173 +#: apps/member/models.py:180 msgid "Synthesis" msgstr "Synthèse" -#: apps/member/models.py:175 +#: apps/member/models.py:182 msgid "type" msgstr "type" -#: apps/member/models.py:180 +#: apps/member/models.py:187 msgid "uploaded at" msgstr "téléversé le" -#: apps/member/models.py:184 +#: apps/member/models.py:191 msgid "abstract document" -msgstr "document abstrait" +msgstr "document générique" -#: apps/member/models.py:185 +#: apps/member/models.py:192 msgid "abstract documents" -msgstr "documents abstraits" +msgstr "documents génériques" -#: apps/member/models.py:190 +#: apps/member/models.py:197 msgid "document" msgstr "document" -#: apps/member/models.py:191 +#: apps/member/models.py:198 msgid "documents" msgstr "documents" -#: apps/member/models.py:196 apps/member/models.py:210 +#: apps/member/models.py:203 apps/member/models.py:217 msgid "problem" msgstr "problème" -#: apps/member/models.py:204 +#: apps/member/models.py:211 msgid "solution" msgstr "solution" -#: apps/member/models.py:205 +#: apps/member/models.py:212 msgid "solutions" msgstr "solutions" -#: apps/member/models.py:218 +#: apps/member/models.py:225 msgid "synthesis" msgstr "synthèse" -#: apps/member/models.py:219 +#: apps/member/models.py:226 msgid "syntheses" msgstr "synthèses" @@ -310,6 +313,14 @@ msgstr "Espèces" msgid "payment method" msgstr "moyen de paiement" +#: apps/tournament/models.py:174 +msgid "payment" +msgstr "paiement" + +#: apps/tournament/models.py:175 +msgid "payments" +msgstr "paiements" + #: tfjm/settings.py:123 msgid "English" msgstr "Anglais" From 1ba789411db19afd836b50444811e67c0c10e9cf Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 06:52:39 +0200 Subject: [PATCH 005/132] Import data of old database --- .gitignore | 3 + apps/member/admin.py | 17 +- .../management/commands/import_olddb.py | 225 ++++++++++++++++++ apps/member/models.py | 111 ++++++--- apps/tournament/models.py | 9 + locale/fr/LC_MESSAGES/django.po | 151 +++++++----- tfjm/settings.py | 5 + 7 files changed, 412 insertions(+), 109 deletions(-) create mode 100644 apps/member/management/commands/import_olddb.py diff --git a/.gitignore b/.gitignore index f908240..aa0a2fc 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,6 @@ db.sqlite3 # Ignore migrations during first phase dev migrations/ + +# Don't git personal data +import_olddb/ diff --git a/apps/member/admin.py b/apps/member/admin.py index 5f3e6e7..0ba73a3 100644 --- a/apps/member/admin.py +++ b/apps/member/admin.py @@ -1,6 +1,6 @@ from django.contrib.auth.admin import admin, UserAdmin from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin -from member.models import TFJMUser, AbstractDocument, Document, Solution, Synthesis +from member.models import TFJMUser, Document, Solution, Synthesis, MotivationLetter, Authorization @admin.register(TFJMUser) @@ -8,14 +8,19 @@ class TFJMUserAdmin(UserAdmin): list_display = ('email', 'first_name', 'last_name', 'role', ) -@admin.register(AbstractDocument) -class AbstractDocumentAdmin(PolymorphicParentModelAdmin): - child_models = (Document, Solution, Synthesis,) +@admin.register(Document) +class DocumentAdmin(PolymorphicParentModelAdmin): + child_models = (Authorization, MotivationLetter, Solution, Synthesis,) polymorphic_list = True -@admin.register(Document) -class DocumentAdmin(PolymorphicChildModelAdmin): +@admin.register(Authorization) +class AuthorizationAdmin(PolymorphicChildModelAdmin): + pass + + +@admin.register(MotivationLetter) +class MotivationLetterAdmin(PolymorphicChildModelAdmin): pass diff --git a/apps/member/management/commands/import_olddb.py b/apps/member/management/commands/import_olddb.py new file mode 100644 index 0000000..f007215 --- /dev/null +++ b/apps/member/management/commands/import_olddb.py @@ -0,0 +1,225 @@ +from django.core.management import BaseCommand +from django.db import transaction + +from member.models import TFJMUser, Document, Solution, Synthesis, Authorization, MotivationLetter +from tournament.models import Team, Tournament + + +class Command(BaseCommand): + def add_arguments(self, parser): + parser.add_argument('--tournaments', '-t', action="store_true", help="Import tournaments") + parser.add_argument('--teams', '-T', action="store_true", help="Import teams") + parser.add_argument('--users', '-u', action="store_true", help="Import users") + parser.add_argument('--documents', '-d', action="store_true", help="Import all documents") + + def handle(self, *args, **options): + if "tournaments" in options: + self.import_tournaments() + + if "teams" in options: + self.import_teams() + + if "users" in options: + self.import_users() + + if "documents" in options: + self.import_documents() + + @transaction.atomic + def import_tournaments(self): + print("Importing tournaments...") + with open("import_olddb/tournaments.csv") as f: + first_line = True + for line in f: + if first_line: + first_line = False + continue + + line = line[:-1].replace("\"", "") + args = line.split(";") + args = [arg if arg and arg != "NULL" else None for arg in args] + + if Tournament.objects.filter(pk=args[0]).exists(): + continue + + obj_dict = { + "id": args[0], + "name": args[1], + "size": args[2], + "place": args[3], + "price": args[4], + "description": args[5], + "date_start": args[6], + "date_end": args[7], + "date_inscription": args[8], + "date_solutions": args[9], + "date_syntheses": args[10], + "final": args[11], + "year": args[12], + } + with transaction.atomic(): + Tournament.objects.create(**obj_dict) + print(self.style.SUCCESS("Tournaments imported")) + + @transaction.atomic + def import_teams(self): + self.stdout.write("Importing teams...") + with open("import_olddb/teams.csv") as f: + first_line = True + for line in f: + if first_line: + first_line = False + continue + + line = line[:-1].replace("\"", "") + args = line.split(";") + args = [arg if arg and arg != "NULL" else None for arg in args] + + if Team.objects.filter(pk=args[0]).exists(): + continue + + obj_dict = { + "id": args[0], + "name": args[1], + "trigram": args[2], + "tournament": Tournament.objects.get(pk=args[3]), + "inscription_date": args[13], + "validation_status": args[14].lower(), + "selected_for_final": args[15], + "access_code": args[16], + "year": args[17], + } + with transaction.atomic(): + Team.objects.create(**obj_dict) + print(self.style.SUCCESS("Teams imported")) + + @transaction.atomic + def import_users(self): + self.stdout.write("Importing users...") + with open("import_olddb/users.csv") as f: + first_line = True + for line in f: + if first_line: + first_line = False + continue + + line = line[:-1].replace("\"", "") + args = line.split(";") + args = [arg if arg and arg != "NULL" else None for arg in args] + + if TFJMUser.objects.filter(pk=args[0]).exists(): + continue + + obj_dict = { + "id": args[0], + "email": args[1], + "username": args[1], + "password": "bcrypt$" + args[2], + "last_name": args[3], + "first_name": args[4], + "birth_date": args[5], + "gender": "male" if args[6] == "M" else "female", + "address": args[7], + "postal_code": args[8], + "city": args[9], + "country": args[10], + "phone_number": args[11], + "school": args[12], + "student_class": args[13], + "responsible_name": args[14], + "responsible_phone": args[15], + "responsible_email": args[16], + "description": args[17].replace("\\n", "\n") if args[17] else None, + "role": args[18].lower(), + "team": Team.objects.get(pk=args[19]) if args[19] else None, + "year": args[20], + "date_joined": args[23], + "is_active": args[18] == "ADMIN", # TODO Replace it with "True" + "is_staff": args[18] == "ADMIN", + "is_superuser": args[18] == "ADMIN", + } + with transaction.atomic(): + TFJMUser.objects.create(**obj_dict) + self.stdout.write(self.style.SUCCESS("Users imported")) + + @transaction.atomic + def import_documents(self): + self.stdout.write("Importing documents...") + with open("import_olddb/documents.csv") as f: + first_line = True + for line in f: + if first_line: + first_line = False + continue + + line = line[:-1].replace("\"", "") + args = line.split(";") + args = [arg if arg and arg != "NULL" else None for arg in args] + + if Document.objects.filter(file=args[0]).exists(): + continue + + obj_dict = { + "file": args[0], + "uploaded_at": args[5], + } + if args[4] != "MOTIVATION_LETTER": + obj_dict["user"] = TFJMUser.objects.get(args[1]), + obj_dict["type"] = args[4].lower() + else: + obj_dict["team"] = Team.objects.get(pk=args[2]) + with transaction.atomic(): + if args[4] != "MOTIVATION_LETTER": + Authorization.objects.create(**obj_dict) + else: + MotivationLetter.objects.create(**obj_dict) + self.stdout.write(self.style.SUCCESS("Authorizations imported")) + + with open("import_olddb/solutions.csv") as f: + first_line = True + for line in f: + if first_line: + first_line = False + continue + + line = line[:-1].replace("\"", "") + args = line.split(";") + args = [arg if arg and arg != "NULL" else None for arg in args] + + if Document.objects.filter(file=args[0]).exists(): + continue + + obj_dict = { + "file": args[0], + "team": Team.objects.get(pk=args[1]), + "problem": args[3], + "uploaded_at": args[4], + } + with transaction.atomic(): + Solution.objects.create(**obj_dict) + self.stdout.write(self.style.SUCCESS("Solutions imported")) + + with open("import_olddb/syntheses.csv") as f: + first_line = True + for line in f: + if first_line: + first_line = False + continue + + line = line[:-1].replace("\"", "") + args = line.split(";") + args = [arg if arg and arg != "NULL" else None for arg in args] + + if Document.objects.filter(file=args[0]).exists(): + continue + + obj_dict = { + "file": args[0], + "team": Team.objects.get(pk=args[1]), + "dest": "defender" if args[3] == "DEFENDER" else "opponent" + if args[4] == "OPPOSANT" else "rapporteur", + "uploaded_at": args[4], + } + with transaction.atomic(): + Synthesis.objects.create(**obj_dict) + self.stdout.write(self.style.SUCCESS("Syntheses imported")) diff --git a/apps/member/models.py b/apps/member/models.py index c6fa1a3..72ac9c8 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -147,58 +147,74 @@ class TFJMUser(AbstractUser): return self.first_name + " " + self.last_name -class AbstractDocument(PolymorphicModel): +class Document(PolymorphicModel): file = models.FileField( unique=True, upload_to="files/", verbose_name=_("file"), ) - team = models.ForeignKey( - Team, - on_delete=models.CASCADE, - related_name="documents", - verbose_name=_("team"), - ) - - tournament = models.ForeignKey( - Tournament, - on_delete=models.CASCADE, - related_name="documents", - verbose_name=_("tournament"), - ) - - type = models.CharField( - max_length=32, - choices=[ - ("parental_consent", _("Parental consent")), - ("photo_consent", _("Photo consent")), - ("sanitary_plug", _("Sanitary plug")), - ("motivation_letter", _("Motivation letter")), - ("scholarship", _("Scholarship")), - ("solution", _("Solution")), - ("synthesis", _("Synthesis")), - ], - verbose_name=_("type"), - ) - uploaded_at = models.DateTimeField( auto_now_add=True, verbose_name=_("uploaded at"), ) - class Meta: - verbose_name = _("abstract document") - verbose_name_plural = _("abstract documents") - - -class Document(AbstractDocument): class Meta: verbose_name = _("document") verbose_name_plural = _("documents") +class Authorization(Document): + user = models.ForeignKey( + TFJMUser, + on_delete=models.CASCADE, + related_name="authorizations", + verbose_name=_("user"), + ) + + type = models.CharField( + max_length=32, + choices=[ + ("parental_consent", _("Parental consent")), + ("photo_consent", _("Photo consent")), + ("sanitary_plug", _("Sanitary plug")), + ("scholarship", _("Scholarship")), + ], + verbose_name=_("type"), + ) + + class Meta: + verbose_name = _("authorization") + verbose_name_plural = _("authorizations") + + def __str__(self): + return _("{authorization} for user {user}").format(authorization=self.type, user=str(self.user)) + + +class MotivationLetter(Document): + team = models.ForeignKey( + Team, + on_delete=models.CASCADE, + related_name="motivation_letters", + verbose_name=_("team"), + ) + + class Meta: + verbose_name = _("motivation letter") + verbose_name_plural = _("motivation letters") + + def __str__(self): + return _("Motivation letter of team {team} ({trigram})").format(team=self.team.name, trigram=self.team.trigram) + + class Solution(Document): + team = models.ForeignKey( + Team, + on_delete=models.CASCADE, + related_name="solutions", + verbose_name=_("team"), + ) + problem = models.PositiveSmallIntegerField( verbose_name=_("problem"), ) @@ -211,10 +227,27 @@ class Solution(Document): verbose_name = _("solution") verbose_name_plural = _("solutions") + def __str__(self): + return _("Solution of team {trigram} for problem {problem}")\ + .format(trigram=self.team.trigram, problem=self.problem) + class Synthesis(Document): - problem = models.PositiveSmallIntegerField( - verbose_name=_("problem"), + team = models.ForeignKey( + Team, + on_delete=models.CASCADE, + related_name="syntheses", + verbose_name=_("team"), + ) + + dest = models.CharField( + max_length=16, + choices=[ + ("defender", _("Defender")), + ("opponent", _("Opponent")), + ("rapporteur", _("Rapporteur")), + ], + verbose_name=_("dest"), ) def save(self, **kwargs): @@ -224,3 +257,7 @@ class Synthesis(Document): class Meta: verbose_name = _("synthesis") verbose_name_plural = _("syntheses") + + def __str__(self): + return _("Synthesis of team {trigram} that is {dest} for problem {problem}")\ + .format(trigram=self.team.trigram, dest=self.dest, problem=self.problem) diff --git a/apps/tournament/models.py b/apps/tournament/models.py index f4cf6da..4e13909 100644 --- a/apps/tournament/models.py +++ b/apps/tournament/models.py @@ -69,6 +69,9 @@ class Tournament(models.Model): verbose_name = _("tournament") verbose_name_plural = _("tournaments") + def __str__(self): + return self.name + class Team(models.Model): name = models.CharField( @@ -130,6 +133,9 @@ class Team(models.Model): verbose_name_plural = _("teams") unique_together = (('name', 'year',), ('trigram', 'year',),) + def __str__(self): + return self.name + class Payment(models.Model): user = models.OneToOneField( @@ -173,3 +179,6 @@ class Payment(models.Model): class Meta: verbose_name = _("payment") verbose_name_plural = _("payments") + + def __str__(self): + return _("Payment of {user}").format(str(self.user)) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index edcc0a6..456aeff 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: TFJM2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-29 02:45+0000\n" +"POT-Creation-Date: 2020-04-29 04:43+0000\n" "PO-Revision-Date: 2020-04-29 02:30+0000\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: fr \n" @@ -26,8 +26,9 @@ msgstr "membre" msgid "email" msgstr "Adresse électronique" -#: apps/member/models.py:23 apps/member/models.py:161 -#: apps/tournament/models.py:129 apps/tournament/models.py:146 +#: apps/member/models.py:23 apps/member/models.py:196 apps/member/models.py:209 +#: apps/member/models.py:230 apps/tournament/models.py:132 +#: apps/tournament/models.py:152 msgid "team" msgstr "équipe" @@ -116,11 +117,12 @@ msgid "participant" msgstr "participant" #: apps/member/models.py:135 apps/tournament/models.py:61 -#: apps/tournament/models.py:117 +#: apps/tournament/models.py:120 msgid "year" msgstr "année" -#: apps/member/models.py:139 apps/tournament/models.py:139 +#: apps/member/models.py:139 apps/member/models.py:172 +#: apps/tournament/models.py:145 msgid "user" msgstr "utilisateur" @@ -132,84 +134,96 @@ msgstr "utilisateurs" msgid "file" msgstr "fichier" -#: apps/member/models.py:168 apps/tournament/apps.py:7 -#: apps/tournament/models.py:69 apps/tournament/models.py:87 -msgid "tournament" -msgstr "tournoi" +#: apps/member/models.py:159 +msgid "uploaded at" +msgstr "téléversé le" -#: apps/member/models.py:174 +#: apps/member/models.py:163 +msgid "document" +msgstr "document" + +#: apps/member/models.py:164 +msgid "documents" +msgstr "documents" + +#: apps/member/models.py:178 msgid "Parental consent" msgstr "Autorisation parentale" -#: apps/member/models.py:175 +#: apps/member/models.py:179 msgid "Photo consent" msgstr "Autorisation de droit à l'image" -#: apps/member/models.py:176 +#: apps/member/models.py:180 msgid "Sanitary plug" msgstr "Fiche sanitaire" -#: apps/member/models.py:177 -msgid "Motivation letter" -msgstr "Lettre de motivation" - -#: apps/member/models.py:178 apps/tournament/models.py:157 +#: apps/member/models.py:181 apps/tournament/models.py:163 msgid "Scholarship" msgstr "Bourse" -#: apps/member/models.py:179 -msgid "Solution" -msgstr "Solution" - -#: apps/member/models.py:180 -msgid "Synthesis" -msgstr "Synthèse" - -#: apps/member/models.py:182 +#: apps/member/models.py:183 msgid "type" msgstr "type" #: apps/member/models.py:187 -msgid "uploaded at" -msgstr "téléversé le" +msgid "authorization" +msgstr "autorisation" -#: apps/member/models.py:191 -msgid "abstract document" -msgstr "document générique" +#: apps/member/models.py:188 +msgid "authorizations" +msgstr "autorisations" -#: apps/member/models.py:192 -msgid "abstract documents" -msgstr "documents génériques" +#: apps/member/models.py:200 +msgid "motivation letter" +msgstr "lettre de motivation" -#: apps/member/models.py:197 -msgid "document" -msgstr "document" +#: apps/member/models.py:201 +msgid "motivation letters" +msgstr "lettres de motivation" -#: apps/member/models.py:198 -msgid "documents" -msgstr "documents" - -#: apps/member/models.py:203 apps/member/models.py:217 +#: apps/member/models.py:213 msgid "problem" msgstr "problème" -#: apps/member/models.py:211 +#: apps/member/models.py:221 msgid "solution" msgstr "solution" -#: apps/member/models.py:212 +#: apps/member/models.py:222 msgid "solutions" msgstr "solutions" -#: apps/member/models.py:225 +#: apps/member/models.py:236 +msgid "Defender" +msgstr "Défenseur" + +#: apps/member/models.py:237 +msgid "Opponent" +msgstr "Opposant" + +#: apps/member/models.py:238 +msgid "Rapporteur" +msgstr "Rapporteur" + +#: apps/member/models.py:240 +msgid "dest" +msgstr "destinataire" + +#: apps/member/models.py:248 msgid "synthesis" msgstr "synthèse" -#: apps/member/models.py:226 +#: apps/member/models.py:249 msgid "syntheses" msgstr "synthèses" -#: apps/tournament/models.py:10 apps/tournament/models.py:76 +#: apps/tournament/apps.py:7 apps/tournament/models.py:69 +#: apps/tournament/models.py:90 +msgid "tournament" +msgstr "tournoi" + +#: apps/tournament/models.py:10 apps/tournament/models.py:79 msgid "name" msgstr "nom" @@ -253,78 +267,83 @@ msgstr "finale" msgid "tournaments" msgstr "tournois" -#: apps/tournament/models.py:81 +#: apps/tournament/models.py:84 msgid "trigram" msgstr "trigramme" -#: apps/tournament/models.py:92 +#: apps/tournament/models.py:95 msgid "inscription date" msgstr "date d'inscription" -#: apps/tournament/models.py:98 apps/tournament/models.py:166 +#: apps/tournament/models.py:101 apps/tournament/models.py:172 msgid "Registration not validated" msgstr "Inscription non validée" -#: apps/tournament/models.py:99 apps/tournament/models.py:167 +#: apps/tournament/models.py:102 apps/tournament/models.py:173 msgid "Waiting for validation" msgstr "En attente de validation" -#: apps/tournament/models.py:100 apps/tournament/models.py:168 +#: apps/tournament/models.py:103 apps/tournament/models.py:174 msgid "Registration validated" msgstr "Inscription validée" -#: apps/tournament/models.py:102 apps/tournament/models.py:170 +#: apps/tournament/models.py:105 apps/tournament/models.py:176 msgid "validation status" msgstr "statut de validation" -#: apps/tournament/models.py:107 +#: apps/tournament/models.py:110 msgid "selected for final" msgstr "sélectionnée pour la finale" -#: apps/tournament/models.py:113 +#: apps/tournament/models.py:116 msgid "access code" msgstr "code d'accès" -#: apps/tournament/models.py:130 +#: apps/tournament/models.py:133 msgid "teams" msgstr "équipes" -#: apps/tournament/models.py:152 +#: apps/tournament/models.py:158 msgid "Not paid" msgstr "Non payé" -#: apps/tournament/models.py:153 +#: apps/tournament/models.py:159 msgid "Credit card" msgstr "Carte bancaire" -#: apps/tournament/models.py:154 +#: apps/tournament/models.py:160 msgid "Bank check" msgstr "Chèque bancaire" -#: apps/tournament/models.py:155 +#: apps/tournament/models.py:161 msgid "Bank transfer" msgstr "Virement bancaire" -#: apps/tournament/models.py:156 +#: apps/tournament/models.py:162 msgid "Cash" msgstr "Espèces" -#: apps/tournament/models.py:160 +#: apps/tournament/models.py:166 msgid "payment method" msgstr "moyen de paiement" -#: apps/tournament/models.py:174 +#: apps/tournament/models.py:180 msgid "payment" msgstr "paiement" -#: apps/tournament/models.py:175 +#: apps/tournament/models.py:181 msgid "payments" msgstr "paiements" -#: tfjm/settings.py:123 +#: apps/tournament/models.py:184 +#, python-brace-format +msgid "Payment of {user}" +msgstr "Paiement de {user}" + +#: tfjm/settings.py:128 msgid "English" msgstr "Anglais" -#: tfjm/settings.py:124 +#: tfjm/settings.py:129 msgid "French" msgstr "Français" diff --git a/tfjm/settings.py b/tfjm/settings.py index a4b4e74..2f7d9a8 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -113,6 +113,11 @@ AUTH_PASSWORD_VALIDATORS = [ AUTH_USER_MODEL = 'member.TFJMUser' +PASSWORD_HASHERS = [ + 'django.contrib.auth.hashers.PBKDF2PasswordHasher', + 'django.contrib.auth.hashers.BCryptPasswordHasher', +] + # Internationalization # https://docs.djangoproject.com/en/3.0/topics/i18n/ From 0ba38311c7967ed9bcd3dee94e6cd39fbb325e8c Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 06:55:02 +0200 Subject: [PATCH 006/132] Add Bcrypt lib --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 9dc350c..d475dc3 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ +bcrypt==3.1.7 certifi==2019.6.16 chardet==3.0.4 defusedxml==0.6.0 From 264f2b7e6bd20f0444b73daa9823ae3eed5c9b4c Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 07:39:52 +0200 Subject: [PATCH 007/132] Index page --- apps/member/admin.py | 7 +- apps/member/models.py | 30 ++- apps/member/templatetags/__init__.py | 0 apps/member/templatetags/getconfig.py | 19 ++ apps/tournament/models.py | 12 ++ static/Autorisation_droit_image_majeur.tex | 113 ++++++++++ static/Autorisation_droit_image_mineur.tex | 122 +++++++++++ static/Autorisation_parentale.tex | 66 ++++++ static/Fiche_sanitaire.pdf | Bin 0 -> 54296 bytes static/Instructions.tex | 88 ++++++++ static/favicon.ico | Bin 0 -> 1514 bytes static/logo.svg | 114 ++++++++++ static/logo_animath.png | Bin 0 -> 106600 bytes static/style.css | 47 +++++ templates/base.html | 234 +++++++++++++++++++++ templates/index.html | 9 + tfjm/settings.py | 8 + tfjm/urls.py | 14 +- 18 files changed, 879 insertions(+), 4 deletions(-) create mode 100644 apps/member/templatetags/__init__.py create mode 100644 apps/member/templatetags/getconfig.py create mode 100644 static/Autorisation_droit_image_majeur.tex create mode 100644 static/Autorisation_droit_image_mineur.tex create mode 100644 static/Autorisation_parentale.tex create mode 100644 static/Fiche_sanitaire.pdf create mode 100644 static/Instructions.tex create mode 100644 static/favicon.ico create mode 100644 static/logo.svg create mode 100644 static/logo_animath.png create mode 100644 static/style.css create mode 100644 templates/base.html create mode 100644 templates/index.html diff --git a/apps/member/admin.py b/apps/member/admin.py index 0ba73a3..f275084 100644 --- a/apps/member/admin.py +++ b/apps/member/admin.py @@ -1,6 +1,6 @@ from django.contrib.auth.admin import admin, UserAdmin from polymorphic.admin import PolymorphicParentModelAdmin, PolymorphicChildModelAdmin -from member.models import TFJMUser, Document, Solution, Synthesis, MotivationLetter, Authorization +from member.models import TFJMUser, Document, Solution, Synthesis, MotivationLetter, Authorization, Config @admin.register(TFJMUser) @@ -32,3 +32,8 @@ class SolutionAdmin(PolymorphicChildModelAdmin): @admin.register(Synthesis) class SynthesisAdmin(PolymorphicChildModelAdmin): pass + + +@admin.register(Config) +class ConfigAdmin(admin.ModelAdmin): + pass diff --git a/apps/member/models.py b/apps/member/models.py index 72ac9c8..197d9c1 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -135,6 +135,18 @@ class TFJMUser(AbstractUser): verbose_name=_("year"), ) + @property + def participates(self): + return self.role == "participant" or self.role == "encadrant" + + @property + def organizes(self): + return self.role == "organizer" or self.role == "admin" + + @property + def admin(self): + return self.role == "admin" + class Meta: verbose_name = _("user") verbose_name_plural = _("users") @@ -150,7 +162,6 @@ class TFJMUser(AbstractUser): class Document(PolymorphicModel): file = models.FileField( unique=True, - upload_to="files/", verbose_name=_("file"), ) @@ -261,3 +272,20 @@ class Synthesis(Document): def __str__(self): return _("Synthesis of team {trigram} that is {dest} for problem {problem}")\ .format(trigram=self.team.trigram, dest=self.dest, problem=self.problem) + + +class Config(models.Model): + key = models.CharField( + max_length=255, + primary_key=True, + verbose_name=_("key"), + ) + + value = models.TextField( + default="", + verbose_name=_("value"), + ) + + class Meta: + verbose_name = _("configuration") + verbose_name_plural = _("configurations") diff --git a/apps/member/templatetags/__init__.py b/apps/member/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/apps/member/templatetags/getconfig.py b/apps/member/templatetags/getconfig.py new file mode 100644 index 0000000..46b3cfa --- /dev/null +++ b/apps/member/templatetags/getconfig.py @@ -0,0 +1,19 @@ +from django import template + +import os + +from member.models import Config + + +def get_config(value): + config = Config.objects.get_or_create(key=value)[0] + return config.value + + +def get_env(value): + return os.getenv(value) + + +register = template.Library() +register.filter('get_config', get_config) +register.filter('get_env', get_env) diff --git a/apps/tournament/models.py b/apps/tournament/models.py index 4e13909..1e7500b 100644 --- a/apps/tournament/models.py +++ b/apps/tournament/models.py @@ -120,6 +120,18 @@ class Team(models.Model): verbose_name=_("year"), ) + @property + def valid(self): + return self.validation_status == "valid" + + @property + def waiting(self): + return self.validation_status == "waiting" + + @property + def invalid(self): + return self.validation_status == "invalid" + @property def encadrants(self): return self.users.filter(role="encadrant") diff --git a/static/Autorisation_droit_image_majeur.tex b/static/Autorisation_droit_image_majeur.tex new file mode 100644 index 0000000..7cb1727 --- /dev/null +++ b/static/Autorisation_droit_image_majeur.tex @@ -0,0 +1,113 @@ +\documentclass[a4paper,french,11pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{lmodern} +\usepackage[frenchb]{babel} + +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amssymb} +%\usepackage{anyfontsize} +\usepackage{fancybox} +\usepackage{eso-pic,graphicx} +\usepackage{xcolor} + + +% Specials +\newcommand{\writingsep}{\vrule height 4ex width 0pt} + +% Page formating +\hoffset -1in +\voffset -1in +\textwidth 180 mm +\textheight 250 mm +\oddsidemargin 15mm +\evensidemargin 15mm +\pagestyle{fancy} + +% Headers and footers +\fancyfoot{} +\lhead{} +\rhead{} +\renewcommand{\headrulewidth}{0pt} +\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018} +\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.} + +\begin{document} + +\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}} + +\vfill + +\begin{center} + + +\LARGE +Autorisation d'enregistrement et de diffusion de l'image ({TOURNAMENT_NAME}) +\end{center} +\normalsize + + +\thispagestyle{empty} + +\bigskip + + + +Je soussign\'e {PARTICIPANT_NAME}\\ +demeurant au {ADDRESS} + +\medskip +Cochez la/les cases correspondantes.\\ +\medskip + + \fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$ du {START_DATE} au {END_DATE} {YEAR} à : {PLACE}, \`a me photographier ou \`a me filmer et \`a diffuser les photos et/ou les vid\'eos r\'ealis\'ees \`a cette occasion sur son site et sur les sites partenaires. D\'eclare c\'eder \`a titre gracieux \`a Animath le droit d’utiliser mon image sur tous ses supports d'information : brochures, sites web, r\'eseaux sociaux. Animath devient, par la pr\'esente, cessionnaire des droits pendant toute la dur\'ee pour laquelle ont \'et\'e acquis les droits d'auteur de ces photographies.\\ + +\medskip +Animath s'engage, conform\'ement aux dispositions l\'egales en vigueur relatives au droit \`a l'image, \`a ce que la publication et la diffusion de l'image ainsi que des commentaires l'accompagnant ne portent pas atteinte \`a la vie priv\'ee, \`a la dignit\'e et \`a la r\'eputation de la personne photographiée.\\ + +\medskip + \fbox{\textcolor{white}{A}} Autorise la diffusion dans les medias (Presse, T\'el\'evision, Internet) de photographies prises \`a l'occasion d’une \'eventuelle m\'ediatisation de cet événement.\\ + + \medskip + +Conform\'ement \`a la loi informatique et libert\'es du 6 janvier 1978, vous disposez d'un droit de libre acc\`es, de rectification, de modification et de suppression des donn\'ees qui vous concernent. +Cette autorisation est donc r\'evocable \`a tout moment sur volont\'e express\'ement manifest\'ee par lettre recommand\'ee avec accus\'e de r\'eception adress\'ee \`a Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\ + +\medskip + \fbox{\textcolor{white}{A}} Autorise Animath à conserver mes données personnelles, dans le cadre défini par la loi n 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés et les textes la modifiant, pendant une durée de quatre ans à compter de ma dernière participation à un événement organisé par Animath.\\ + + \medskip + \fbox{\textcolor{white}{A}} J'accepte d'être tenu informé d'autres activités organisées par l'association et ses partenaires. + +\bigskip + +Signature pr\'ec\'ed\'ee de la mention \og lu et approuv\'e \fg{} + +\medskip + + + +\begin{minipage}[c]{0.5\textwidth} + +\underline{L'\'el\`eve :}\\ + +Fait \`a :\\ +le +\end{minipage} + + +\vfill +\vfill +\begin{minipage}[c]{0.5\textwidth} +\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018 +\end{minipage} +\begin{minipage}[c]{0.5\textwidth} +\footnotesize +\begin{flushright} +Association agréée par\\le Ministère de l'éducation nationale. +\end{flushright} +\end{minipage} +\end{document} diff --git a/static/Autorisation_droit_image_mineur.tex b/static/Autorisation_droit_image_mineur.tex new file mode 100644 index 0000000..4f14a43 --- /dev/null +++ b/static/Autorisation_droit_image_mineur.tex @@ -0,0 +1,122 @@ +\documentclass[a4paper,french,11pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{lmodern} +\usepackage[frenchb]{babel} + +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amssymb} +%\usepackage{anyfontsize} +\usepackage{fancybox} +\usepackage{eso-pic,graphicx} +\usepackage{xcolor} + + +% Specials +\newcommand{\writingsep}{\vrule height 4ex width 0pt} + +% Page formating +\hoffset -1in +\voffset -1in +\textwidth 180 mm +\textheight 250 mm +\oddsidemargin 15mm +\evensidemargin 15mm +\pagestyle{fancy} + +% Headers and footers +\fancyfoot{} +\lhead{} +\rhead{} +\renewcommand{\headrulewidth}{0pt} +\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018} +\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.} + +\begin{document} + +\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}} + +\vfill + +\begin{center} + + +\LARGE +Autorisation d'enregistrement et de diffusion de l'image +({TOURNAMENT_NAME}) +\end{center} +\normalsize + + +\thispagestyle{empty} + +\bigskip + + + +Je soussign\'e \dotfill (p\`ere, m\`ere, responsable l\'egal) \\ +agissant en qualit\'e de repr\'esentant de {PARTICIPANT_NAME}\\ +demeurant au {ADDRESS} + +\medskip +Cochez la/les cases correspondantes.\\ +\medskip + + \fbox{\textcolor{white}{A}} Autorise l'association Animath, \`a l'occasion du $\mathbb{TFJM}^2$ du {START_DATE} au {END_DATE} {YEAR} à : {PLACE}, \`a photographier ou \`a filmer l'enfant et \`a diffuser les photos et/ou les vid\'eos r\'ealis\'ees \`a cette occasion sur son site et sur les sites partenaires. D\'eclare c\'eder \`a titre gracieux \`a Animath le droit d’utiliser l'image de l'enfant sur tous ses supports d'information : brochures, sites web, r\'eseaux sociaux. Animath devient, par la pr\'esente, cessionnaire des droits pendant toute la dur\'ee pour laquelle ont \'et\'e acquis les droits d'auteur de ces photographies.\\ + +\medskip +Animath s'engage, conform\'ement aux dispositions l\'egales en vigueur relatives au droit \`a l'image, \`a ce que la publication et la diffusion de l'image de l'enfant ainsi que des commentaires l'accompagnant ne portent pas atteinte \`a la vie priv\'ee, \`a la dignit\'e et \`a la r\'eputation de l’enfant.\\ + +\medskip + \fbox{\textcolor{white}{A}} Autorise la diffusion dans les medias (Presse, T\'el\'evision, Internet) de photographies de mon enfant prises \`a l'occasion d’une \'eventuelle m\'ediatisation de cet événement.\\ + + \medskip + +Conform\'ement \`a la loi informatique et libert\'es du 6 janvier 1978, vous disposez d'un droit de libre acc\`es, de rectification, de modification et de suppression des donn\'ees qui vous concernent. +Cette autorisation est donc r\'evocable \`a tout moment sur volont\'e express\'ement manifest\'ee par lettre recommand\'ee avec accus\'e de r\'eception adress\'ee \`a Animath, IHP, 11 rue Pierre et Marie Curie, 75231 Paris cedex 05.\\ + +\medskip + \fbox{\textcolor{white}{A}} Autorise Animath à conserver mes données personnelles, dans le cadre défini par la loi n 78-17 du 6 janvier 1978 relative à l'informatique, aux fichiers et aux libertés et les textes la modifiant, pendant une durée de quatre ans à compter de ma dernière participation à un événement organisé par Animath.\\ + + \medskip + \fbox{\textcolor{white}{A}} J'accepte d'être tenu informé d'autres activités organisées par l'association et ses partenaires. + + \bigskip + +Signatures pr\'ec\'ed\'ees de la mention \og lu et approuv\'e \fg{} + +\medskip + + +\begin{minipage}[c]{0.5\textwidth} + +\underline{Le responsable l\'egal :}\\ + +Fait \`a :\\ +le : + +\end{minipage} +\begin{minipage}[c]{0.5\textwidth} + +\underline{L'\'el\`eve :}\\ + +Fait \`a :\\ +le +\end{minipage} + + +\vfill +\vfill +\begin{minipage}[c]{0.5\textwidth} +\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018 +\end{minipage} +\begin{minipage}[c]{0.5\textwidth} +\footnotesize +\begin{flushright} +Association agréée par\\le Ministère de l'éducation nationale. +\end{flushright} +\end{minipage} +\end{document} diff --git a/static/Autorisation_parentale.tex b/static/Autorisation_parentale.tex new file mode 100644 index 0000000..6c56ac4 --- /dev/null +++ b/static/Autorisation_parentale.tex @@ -0,0 +1,66 @@ +\documentclass[a4paper,french,11pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{lmodern} +\usepackage[french]{babel} + +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amssymb} +%\usepackage{anyfontsize} +\usepackage{fancybox} +\usepackage{eso-pic,graphicx} +\usepackage{xcolor} + + +% Specials +\newcommand{\writingsep}{\vrule height 4ex width 0pt} + +% Page formating +\hoffset -1in +\voffset -1in +\textwidth 180 mm +\textheight 250 mm +\oddsidemargin 15mm +\evensidemargin 15mm +\pagestyle{fancy} + +% Headers and footers +\fancyfoot{} +\lhead{} +\rhead{} +\renewcommand{\headrulewidth}{0pt} +\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018} +\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.} + +\begin{document} + +\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{55pt}{55pt}{$\mathbb{TFJM}^2$}} + +\vfill + +\begin{center} +\Large \bf Autorisation parentale pour les mineurs ({TOURNAMENT_NAME}) +\end{center} + +Je soussigné(e) \hrulefill,\\ +responsable légal, demeurant \writingsep\hrulefill\\ +\writingsep\hrulefill,\\ +\writingsep autorise {PARTICIPANT_NAME},\\ +né(e) le {BIRTHDAY}, +à participer au Tournoi Français des Jeunes Mathématiciennes et Mathématiciens ($\mathbb{TFJM}^2$) organisé \`a : {PLACE}, du {START_DATE} au {END_DATE} {YEAR}. + +{PRONOUN} se rendra au lieu indiqu\'e ci-dessus le vendredi matin et quittera les lieux l'après-midi du dimanche par ses propres moyens et sous la responsabilité du représentant légal. + + + +\vspace{8ex} + +Fait à \vrule width 10cm height 0pt depth 0.4pt, le \phantom{232323}/\phantom{XXX}/{YEAR}, + +\vfill +\vfill + +\end{document} diff --git a/static/Fiche_sanitaire.pdf b/static/Fiche_sanitaire.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b828b9d7e45882ad06a54278929b12aa576ae360 GIT binary patch literal 54296 zcmeEuWmr|)*06|lcZr0g#AZ{Q?iP>|k&xVUZaP$2Bt%*e1eKCTS`cXj1Vp+!1eF%) zZ!M5>JnFsY-21-I_v?jcG1sgy$BdD4EEv^f=Dpa@aH{(@&JqVGdx}x@6WhEd10_$+VR17ex4hYpP%cO zzWjm$zu*kx;`#+=0pMW$jEeyD*EJ9jfd0HL+}u2{pXbKS%l*q*aSQNp|BN%Y052Cn zl;F=FXB;RK_!$>q`F`0W9vF|nFX!NdbpHyE3(5!m;hef4jIC_p2!IFRKr{jBr{&|r zfhgLWJJ3RbQE4>*!q#wbaG`|)uupPo2)G+a>D&ONLlkB7M9fXi%*^>ie|S089U4O#p^{vXtNgo~$DRZVznp_l1OLz?~gj5vJhU0;lw3=cOI&U4S;ufJgv2 z9Z<#%5Ezi~oOa?lJt8320t*2m01{qM$NEsng3q8ddA}2r#(#T1vAT9Ul6d-Z{Mev-?0|&@JX?ae2 zf@cPzbIrsWZh8t|(GE(>ciQQsPS(RkUh@QhaCCW1C@sjVOa#;^ zbiU)k3j+t1wlqe7+r|PxK%BvuL$o1qV^dcbI7HF{VeAHnI76%;$`D6m;DFk~&0Qca z5FLohX&wPi2x1Fyg{VPPA=e;M5G{y4jvYi7q7IRUm;$S54{>sJaDh8pfv7+nAg3TT zAaW2Hh#ABbaypVML=z$pF^0e)77$BMM@zUpMAibKj{^>W9U^<$ND(3lv1dJ98-SI- zd1!f056NFP1}ysHOrDb1$-x8ItE-923CV$_ppGSHg>ZHO=TFN6Dp1PC-*bQ#0%UJk znYmb=5}N=m4?tYt1L_IjbFvpO;AC`=ZDeq1E(HLVL&53;52{__zpg2Sb%N7asgmuuv`E@`ve2<<*X9K1gr#s zoy_F~G6)@{D{!KK00vVK4GUMJ64 zCD0f|tC?jzyJLX;QJJSY5dt7T;J1CPZ0-mXB%-g zDPRr2xtwKxOwXGC2@tG31#$Xz)&d7y@IRaV`1WVRA4`9J$N71lU^kF=%i06-6reI% zh>EePhJ&54{U0Sb5GiA4_z4yKo?C!bKX9%S=Jr=II}19V1FUdw8CCsow$IM_ z$&Q}j4OE_`ClmahKSKfR0KWf7RVOHbe?UqBCw0;h$b*f4M^z{7zSA|>7Cc`ki*RDdEP0yi*E zFam4D_MXZf!~qE4}$AotK5R1;``54Zoqi~>fAiEf`Fey5HME2>4B8{ zr^@~76#j+I4OoId=-h&!runDNeX4OQLljQbXDvW!K2?oDg&5Fx|Elet8g@UjiWBbf z8&>g;*5qHCAt&lEINdW71UTG3m>__~_Un55$m4#$60pB41hBY2E`*D_1H=xn8h*4E zPHlxh4G#^#esHlwz~MkExU-8DU|cwUHy|{>+avloCl-k@#2m1mAx;o;s}l=C6=G_I zFm<&vw}pEEMhc+l!x2`_Hb0m=-)$Xm2TTBq#}qJQzMCixc6P>q&2wVA0hW&}V5G>O z87ZLMV-B$gw(7c>6&wMWInEGA0JMV{#O=(Aved`~BRHZhU^O||!vXv2 zyQTEka|2N5FSG<&$GPC-84egg2saB=~AV*vP%i~;5V`r|kO zSr0JdpHmQJ6=N5K)rq%_lNZVj_^&v*0k<%a0Jk@QZ;6wK54;25gaLkGK=I>*LIDv0 zBm&?~2qzb)D}5i=fEIK>;TW9xpg>r^BjSI?{9yoUzZHnTFn=gNFUbABJ3Rz|Tbp0G zzogQcKnLB6u66+M-wS~g`S*th3hoExRQ(kX$kV>>!8ep*z4o`Rc?NFp#I>#J8?h$FY`a(NQ1oXOtS*hKlmR|_XlqT z%K3ne2Nfr<>_n^jt~~xD75hvL1A&}9rz-Y$OAb`W{#M2QuC@vS_i|?{Hb`TqDmGXN zWWeVisn{oIfLbHSeZYx>DEyHEP{4_T(7^ID8VB>>`~N`2hJ9DD0gK@Kih_&tzoQ|a zE%Seqo?vix5Pk;$T-D!|pOxYKI3KX^KUcATLyj>-!xlzY5E%mD$RW!X+s6ar1#C`fp42s=1zZ7-yJ)ZE)TDIeh2iWe)5Tdfr@S zw!J`op!e;D|88SIf;ht)rqo-(0jZDYmWF7(oDfAK=v^`ul*IPIZ6bU5cLN|Xkq9p&TPw%gCD=c308d8aqA!GzPHS93n$eL8!948!o6W7op5;>Ei%!%l*G8EKR* zl`iCpFWQ+p8jWvV@?R#UGo#&7dtVQU?Z?_B91*%TZe;~vw& zcst%(cQx~QXogz2^!s={^At~<`r(u*uNg-Yd36G9q$H%E^Y@<639g*?VsG7l*iO)PtB;*7sQJ<}VlIehj>WZM&H! zYiiJE;>BNm*K%EHx$t_@)4B^0dL-Q9@gY~FKX%Y zmM$R&hu;GZ$CdFZaWt=decn(<{qcH6%SQw|c+b;Vz^n%*i5& z;HJLal|#xFV)vyn<&BUISqWW%M#Lh@AyLk@)6LI{#&+|b$;HvEh3kreJRQ!|GO_K) zFciL=#0Shf4~G>QI83g(YV_XSmpX6Ad3meEeyb9@_G$&& zE1d44!gKGOo;y}{K6~K1wd$sMFNo*!YX?|H0$!IhQ~qa_N%3tvk&0YBU7yVPnXf{3 z(yXd0YrUr?po<4Q?{D*T$tuB836`$u7TB*2B&^KO*i$teMzuYR2%AUTevN+EP;Pfg zdobbL2B+yEmiTK{Es;`1ZM4SgCVA#9F1;%Lp=2YXR9=n9HpvakYCe4PmojdA?i}~& z-S$IG3~Q+3aoo=<7Law!StroOJ&@;8~Yp*a>gwd(*bvPHnNf9MmLlWAXge%sHJ>=oEIVAC2tMvLSG*8zILx}v&ZoGVtai$eAzcshsYV!ZI{VW$ww48KMcw88yYdn z62layC%fyA-EMArSW>NEc8|{rJLdD}e^{Ix{hBUmW7j{gQrgk_b!~5UbasB{tIsem zzV7x@{;j(7_fR!8;<_j=Zd`q}yLau0CFQkPguJy@M|V0s-`6h~t__4~p-4?F_0tHN zYVExxLnkoNzjUCrnV%z*ms8*CA;339 zDt^Yt7&G*wNhf$}07s5p4pon42I(DNG7*mhgZ8qOkMG-p_m0nAC}mCyCs|H?E8Mm^ z!e?st6htJw>%&sfJwI4XOUY%18Ag=Pn%KO}zQpVC#-7VxQr_1mspI~2iIA2Z_Lm74 z8@r@1GBEuKz43E7xC*Y(`03n~d3l6BpVU6~Zlv`5Q|aOXf4A)gw4S7BQw(?BOT9(# z0J?}BBl@IXBh`100^__Xhm{7l_n7lpSt%k!aoUPDmN_WGEfutT2x$zCZTOvelqS2I z9t4Nb#&>S=`W)k0i6AuWlGJg$;LT3o?W3%#y|LKRqT!7X z3kH@C2*P6QWbT%l4;n3Kt6m}~cei8x{MN7I5OzP~if8A$alP^cDE-^v&D~kDb8iI` z9X<&4PHXZz=XC1Jm5y{T8cdDsVU~p#i?AOy_w;_Cf%+^T6szaXQH8voW(&4SF_avu z+`NIakRska+mx%l!J*9QF=kv45h;v?gLT(+uV!uWg>t?w^`!5dTSaj?q4gv)V-{h{ z?Kjq3EBi6R-0nF+K4HD1ndv42YAkQnTA{_V|F2R=Yp@qn*DnAdCvTAP%v=j%m_J&J@_ZO!AbXD4!?HC14cgVL;t;d zx(y1{gspC$I0#K(=qguzB*G{pdKI{^?xdOuSA4Mx#9x-3oP9YvSRAwY?aS^XC6xh1 znTXc5T#VFf(o$a+yIXnf<=j4ycM7Ezw%#-KIvC)MB6)fBLm9>9E`{!F_!|fWZMKN- z_)S3M>H~*VJcshG2X7AQ8%NDHuYTU$UfQL=t@S!?+%HVM8)kMiO2)%SbHqepZeIYW z=clb^NPPF!%qwQIaFaY{#Fx&qJK)x8^d)(rSd4`f%M}(EPQ@kVpe|x7F^5GRtu-b^ z>Hyr8cHK8_Xi(F1O| z=oy4qGagI)h16M_6&_kb^ptNqrF6WSvj;9dn}=vZ;c&MthA)80r$Jm%-L!r{J5t0gW=dR)5iW5 zJWgw$9z?lz?->$SHc0eg5Crlg#>H5$LZimS*c;1RD0op0)hyccpwZ9nN3dZe^FD9P zu0fbnUxeb9Sde1%=$U++M@lwQx?gPpw`k&3gB2)2cCg4eUJk$_(l8j`H6U>gh&bk# z;rPU14RF=5%f28;4`a@(B8(a8Y|wZ=n0;A({xf;fTz_6o!k7u=3~Nsi7%Ik-M_@)_>tF&z#Dj)$#@%^goccSnvEiJ}Y4dFg zPmX*|n>_W#82mY+17ZT+-dtaU4k!(H4^opjN8~6q+g0>1cGkQd2x4=-?)|=qKf6fV zj;|UPQ`3*L%x7JzIO6`Wgba;_ROu51T~i^S-g7-p3YNmC=qGtna!@Mue1g2jX?~*7 zyr2-*Skj^FPgd$wq+bFCb#ikl&1HEM`s{h7dNG=#?>Su{-Nd>lI~Kl|R%|Vg7WPcC zPCC@R;|fcxbN=T>4bv}HN>{|EIBPjHUbZq{TZ%)~M4gAePb67Q>w|T_(=bI$x5a&{ zwa7`W8?GfO4CuZI+j%|c0w0ej&Qy=P`>C^I{VK^bH&)(TM0oKtA(2}zo^$C*QNpzH zH3s)Bw)R@Gmt6`YTLj6LTsu)Fi1CY%Mex5W>`FYG}9=#|am&w0;Zk zXeM3r*)-V3;T^%)N@i0Gz1vl;s7)Ov)6kT=z7&&(b`dL+EYUtXib~jVfUEpCyw>=B zKU|HkIsUriqX1bRl9?#Y?qkZ7MHOiR0ghJ z?=9P@oM@M8gz#ftiixkLskdW)Z2Q=!GCuoD-<&RkrfYJs9%p!$>L@Cs-)cDPmok&q zkbKO%eLI4}q?c=RY!j$4Jj+IkQ&8BOucLI18Po=EY^8Yw>7Q0%jT+)33D|7?_00OLMn;xJ3I-(@1yK zMzKn&v#Rl3UTU3dcOm;_k=+{)nY)AGt@4c}m34*Z*&f<8Z)}ed>-6pUZue0d4L22R z;qQK3I{e%tR1DK^_f1x_yF8U4gjBVOSsX}^NG2AUisiGv$${o4P2E2^TO1Nu=pGOj zUhk+NW`f3ENwF4nh$Tg9YNcG&x$gI&TD~g#i2lXM+`>T&oaaSEk z^+zlHY>}hf4%CpL^Yv**7c}q# zv&4X>_C~l2U&@D0Ccb(VynX{xMfSH2oE78pUAxVn^NkJ$F;h{Jd@WwPg*jEGX%}Cg z)!)Lmy4d|nc`_$uZuTk*f3ss zIQEPZi%mZDkyK%swE}FV_WIT11JC}3PWJhIbd#I!xjU@}k@oDY^a)-|7ZQ3*R~>wM zc+c#*5appz_Tw!7r6QK9(7Vh1dLD)XIn|NGYHE)#B*OKU~3bCklm620toPY*7Aah6H5 zi~UfiH~j=BqF#>-A5s-(;Z}(HRap2fp^jJZRtD!wXBsYp`DYvc48|EpK9G3)nUr@m zUKWG=)~`Irv7ch)SzgO(%+ZILH-*RE7hEpdvb7&Gv0-0Um><4x51-L0$0h?Mo3CZnqwFJex?uS`F(rtkHfq(KJy`Pd zg@g=vZIuNq=oQ~Yy1|B=hD&pD@wz>ySTfsrHhUQf>6~>b;SJGb^ALAw~W|r4+$MPDZDD}%x#@4Sn zs&kbUcP^Xs_^htUcxds7B!23##_I03!ZfktgNVme+&br#L-YDBKysaN3sGy?vKnw( zy*|n(VN*=U%95!`9(82Tya`bE@8^AW|A?*bTqEMn!{4yff8kOGywv}j_hSDSJ$T|? z1{}rz|Dp%a+|K`P`oD8229AC*_wUZ{pRxIO7h@+F{Le4Oeu)+S$u0bw=s)n|j#IZV za7p#2rg7#hK8fl6H?jRE-G4Uy-reZXnAOHVJbxJA7DY<9bExD08D9e%|9Lz6BleIE zp4r%Xqgf@m=)RA$s(S}2G7s_#wKx;H)Z9BeA8Vhn*M!;ezEW;4FEC4IznpT2tKAY8 zGjr5b%9?(Qp8Ekm*1!{|BCF@dGL54wgac5wE=*FCl?u$8%9PAZG2P*=#6h<6ugmiu z>h|wz-4{vMe#{_np@k`!gEV5yMnHwIYFqKDcE%3o#)A@mp=c3RM2HU|yVM#bG$t^B z8CiMQtA)-c@ykGd98t9__WCjM{?JAVP$B4U>= z`!Lr0u}pGz1`|RuIjVYXtOo^y=<5D2wJ`~j<5+A*>cui6Rc>HK~L>6QLP&)##WJv)DvOCd_lf zL0r7*CVEtbyE5`lHu^@k;pWlb@+x#ZmZAvu>-K$p7*RW9@D#Y5V%soZ_}ILN7buPw zNu$@on0rjI`-y^*aifosP=S_CQ74?($TlUd&IkPwg3qH9IEUOWm9kP0`ntY7A?7-(RIXyNyGKFCwcKZZWEn=r zQb*a^tjy|00;Lli5Y5 zj4CCek)ZV1w&jvDX~(*y4-cnUaUmidS=x^VLm-MHjeDL%w@i4$8_HLI#?Zsk2x#-_k3 zq%6EUsnYtvAVB4K#3!fOXC#?3t7O;5>9uuB*mf4{0|sVxyo3*p$uhkP$`*VaB07&a z3aoA0bPl&!ST?MVWM>yx*rT@->=y6=7oX|H=C9OaV zPtl`2rR1QjHZ`Qi#%<%QO_GYA+9mt48xFy|x56RsLr&{MvFjY&a%idZ=&lDlX(YVt za(H(I%a(x9oi52VJUsoCYoZ5hebRN}=#rm3zRCL{o%3C+F!_z-Kl^S#KmfQIKeMII z+`WIx;lSQMbGRDqPQ(Zo{+;u00_>yk&<}MrAk7_wTMy|}?jM6vmAKCDUu1IG6LrpT5c}UtT<4@FBtCfqdS$#ep zP>oUT<5A+7Ji^QjX->^~{ZMacX(y(%obnQ0bjhu3ly@cgHRK}7a!#-BiYb4HQLnjm z>t3wF+dO@_N}5Qig&K=Cs}Fb?fe!O<)Eit1KI#qcMf*dZeiHM=r?*C7c$A{$d5rLM zzm^X>hc;mSW>R50{VSKwJ!cKH0h&yTz~SIZ-gpJO=cG---2@4wX=(c961SXie7`9W z-$G8n9&IZRcI24S=n9F|cM#dpt;{5NDwQ3)O?qCSW2V#vMLxAn3908@dyDY_Qd#Bw z3k3Qh!Sgt8=iy~_4>G?HRXTLWV4(yUaojJLco!6;6KB_wrs(p~dFm4}H>-20K zY4Tnr%L}x(etQt~%3$qBuWn@<#HH0oc@v}s#CAmAKgLbBYb`d{xk`^ciQH1Jers%! zl&#b!sX(Y#eoHGYK*_IOBEooo(J|l#){RF5wJ8M~H*wqEERJPm{7$1 zW-nBA+lNf~mPvmZSN7cD&BG^T?hpD}FLF@jYu8itdpx947#du8CUszZR4PH!_`r`W zc6zs$_Y;>iMGZ@HjYle>hoXcl4hv43)mNs$Jn!zrgY464H8W#I7#XIjGw3X6xYnWF|RVbOQ4;qrvd0eM=$iF1w zM;iBhEN*e5sL#p61Ku=L^640z>s+`+{rTTe_7B%HINv|I167{?M5pKG{o79${!gd> z|F6@7HxmEq7Yx7n^B2^!|ID4e{Sotjrjnmk0P);F(8Xzh&S_W+m;-_QsDFbo@&7`P zKWqLcz*7v)^!?LvF!u)ze>VNI^5?SO<^KZUbd)~d<$xz@!Z6GKOh{Xdx z760v5k^gcgKSri;01-)masMBD9{K&_NFdPnk1ryvfcW5(+}Zb#W)3d4aA#*L;KN8a zAac#*hsZU39Pl$p@Y6@DAA)>Ozi@;Dk!%(~)bbA%Ky>k6g4w|TKk)OigGDDnJ6yoG zzh}D3$%nuH1}5ST~#W#Wqtu?;6zbKcN5^5giXHVtgAtObL`^0_|3Lu>Xoz4 z+r_Udc=z(g4q%Jl`pyL$yq?v(>=DwkdtcfM5}P$YG)wmXjsQT8YyH|Li7 zfJj$LMVI`&`tw}AQP^79btN#nvO|mc18lxmn?bkJ#VYu}wvLKD%P8}RGu?7T?;@Yi zyaye_Xn9e1^PH4bdzswxIA@XNK8y7)8Nz8#V0L=0G)a3oO-<9)W?e&M8Zf%Jk&90R zQR@b6_Y&p|Hg{evPv!XcciJJH>v1W{;w1G}swD*beJY zVU?C<6i8FH!VlbY{K~1oTQ~F$#+SFZ6?ttN|5}W=$YYBUcjb zqq>NoYn;rbXNtH5=#~=nkX8}srS)iH)tNzLb%G|8^mXhOb;=Y54<5GYRC~jgMH+7% zuY6!>GYN?vP|1f-7 zrS6gwcTz3KOeuMao^@b3O3JGS)Gm(8^mFL6k4Y`o>z?3;VsdxRFsNk34DWoL9sjak z6eXC|pp0%)tE>z z3@>`|@u!Iwq3Wa;7I@HzuR|WnaUrUfvJ4D0*qOSl6e8WIk(?&1Y88-JXy4G4_h5r?*23{$--6dk1@qN z-XFbs`aE9x**h5|bmTOfwqm)7TLaJ zRb8>K1!R+5e)3yG%@K*wxl76eZoev2;J-UL;WvC>Fzj@q-!TLp8ISGE!$+pZsNYa233?s^&s=@qOU zyM49ga(H(`dJO{`CH=z9P%pf>InuN+T54XB6*y$J8zd@?mFd9f*wv57ukXPTaf+0WRWoRt)}I>wpeQ1#81&gC*( z7w41*^X!?i8^oPEm$g(M!o{Rg9+k$IwujEK7UnlzjuyWnF(Q%Q%?(K!1mN6GydizCZk=&)=yG*V zsj%iPf42ELg!v1)2~_Jt4VRKm*V+q%dx%?7HXC+nQ9js9?LHeEl~F!s%6&>l7cCjY zv)-ILPChVQZ_RyufP9E=bZ)B3Ddjgu_RN9#w}w0~4ERSSfA#fC{}j-wrG=qJY(e?i zTtIhes-+nEwNmss_LZ0T-L^IS6D*bk+}R!lECCOK8!6^^S+KEr#zjSuvF~9ggeY(o z*?YKxrW4q{T7r$a@lXuX2sQeLo?wl42gBZ?9&F_1qPM^?qSyl8aoB-9*K>tuimuqj1#CLV_pE+XwT< zn+yu`_(bSZh4h&ZWzr!~X<2sq5JoW>Y{@(g0w;#zFj|2Otw6k|^x;kS=B{k`U3+;g zODSVyX=T>C>Dv6_TI%#92|lS~V3N{JIj+lJA5@Z(6M6`b~>iexgpKSQ*5TUF>5)02U*10@}ImHpH>J|eQB`t^a5_fC|7C3AwryltB>#Np;-q8T=n_wkhx z+o#?Q68;Lc_4C4SjGhQwOZT6RV-i;@-4-82t)M7=p=jIVa>oSnZS96={~I+E4uS*Q zs6CZ^MO9l{{AIq10=>{z!NvAZ_fYs>cqC8{qqH^Xl}?b*O^36x2NSPgHVQ;)vGUR6 zmU~*h-j;I8`t}I3h4@;qyC)NdU!)d3`ZbF1ie@tU7e=`mjrXW*T}vmv%C4*EbV)r# z_E(|}>0s?D$;za5ocpk+5l(`s)_ui^>!7ki4}*9^=lZ>A<%CVCk7&2Gjs;r<*H&k| zt93$RX-l!sSK8`5=uCdXIM1@jbag2}?34bb7>=H?`XX1)(L5!1-r+<7Pa93`jrw>o zR8GtrV^i85H_KmViYQhM7U#=QY&fw$m~Pc`Bx>ggM-bs2#3$BK_KY6te#EZaZVn!wQy%^gT)|y-?SW-C-Lr&G`qq z7PsR@3$z{`XOdb!sEfTy?nrdG@M)&oji489!t;bF&w4-37?jq&>>uyjYhxt$CTTe! zl1eX)5sxHxZS2r|(j$`R(x;Z1JdoAp?>O99=XG#Z zVM={k#(mCh9mh z=)ZO3PZdTFdfwo+Y+V)4 zJlBh#S6{c%Cw3b#yc|#@Y!xSZ5@M*SVeovZ$A`<&=-T7*woemrZ&3}^V#llkW~oD? zpWb_TtVOV4$LgGhildgoD{)&3DTxUker?f}T(@drT(O@#R`_wZb{{+)Q#C+a%8->e zwE4ap_Dd7m8ywdaI?E#5WK&SgL$8UOM(*LMzP_|et@`wVVuVJcab&)vQ!QQcwm(Yn<=ueH{_GOI5WJIB1k57PIVKv6w zVYz^GKZIlR=*vZns?f-}b~$9OnLK6ts^;nqOABEa(~K!b&n3?#6NxrQ;0j%SPB1te9@ z2;4GDE6z|hj+iMZ37bWtA0QRJMZ%F`jgs?-o4#C#g!nyz1qp$F9s!RT|3v6_fzY0i zunQrJyUt$zj)mIJVvXEduUH`~1u@hGc}HdOYCUzQ`|(c7r1$F1zR#O}9y6rd_q*CS z=laA}a-Vs`I+AvOpew8iV89fK9Ede1gsKl5Ib^4+cOtK~Qc*nAYPh1os>Uo&H;cGE zaD!G{E;#AJ4fO}jcvbupYpeVF*(5LTPC_Gaj6R30DUIn2yKJ&LIWVjnnMVng1n#MQ z3BviLZJSWoJo~DVj7Hd7ctnx?b8NBnfa1{O@D?T|i=7YgB)upy+_R4|ZAHEbt~mu= zuD<_CF*H{|`jb#pbex>kvkP=n>IDLvoF6@`r4C=~Z6mK0M{J1}kh|Hrdttu`l#Iz* z*@DdQuomaY%&_QAphBnI7co5U2x}8hrzub9i#ot|LN8(%lAB_bvUxn`Iyc0yf!x*< zu@}rAns02wrYBn~{_0$GNrs?`&R!r8!Co$1P^55dw-mnp4^@ zwsMtD`G#^yn-Jg^U!-sTe3RoN#mx_;F1dX@=5|(> z4ObxZ?IPwDA{GX#q3Vn=H(#ma^CJediR|34(5#uKkT242na&qYmq}ik^Ry4(y#T$* z9$g*9M!frRr{SKmINC>Eh15cw0G0X>o7ABm!{i}}#O@VXO7o75_>~Bz+}$g;b6>aH zNhdKUiPOxucc2u7+Kw~6h)AD5Unqm*K}=*wEH$t}dfOoXCL8U&OV3-s3~k}71&w~3 zz)G1@L%f^EmO@B)En&Ovm?VFujl$0j5s@{1e&~}>o1|qGM_I+5dIJOg%ph-u=zu5X zB{oV-gil1RHohG``HtGoCf~)!y6^FBdbd4^chiJT2j{HBI89&S={5536HW3nhhnmZ zaSF3f^}OSQ>5YAs*@-o{8y?9ub$w6;w@g6Ko^a~sCCYT8_b;DGw7+}2#hcicU_~Jf`=&W{rSRTOOxU|`jZ<{Shn}8Uf;V=)Uj{iy)Rn8 zS@#;{TIJ_!_#-`N4?Nv9KEAd9evGs^Z3ci zmDs6hqMPf2WS-8XiDND=%F@eyao^{Jz0tlZ+uX9+r9vPve(-r(-|V&yPn<5rs0Z4c z4?R#-lM>Qu?S2J8vtagH^QsQJ$OW#*_ZyF}?%FeF^6eef$r(zZ*azv)Q*3t1tdc2BWVH5i7wY3uIZDp3+d_fEEF5bSA zDR|9PC{OXNsQDFkj`#PPKFXFnqE32eD)^MCgy}|UIWhbu!WqHSS>@GnEOPLuH*EhH z&RXBZc#|#4G9%hZnUFpz&?GwHH3M5ygF+1>w_=bP>eZ&q*E2Pj6bF^AriV>bzkag? z-SY`1C7G!mzlm*CBBhMc!dVda5@~U{`cWos!fWcma!)T2yTLiKs<2N%J;v7LgHJkF zm6r6Ff&b-c8jOni5lO!qYv3{kc92AB&6u`aTtXZIUg;*RB>lLyl_*Ms)9C$k-X5lQ zEwwt*sS!`ET^0#9gznl{Yl|eafj&fEZ6gJT=<{lud_|CO7wW@~m9tls0;k2Si{$#cruFhxXwyz)l!2#*_pbZsGk{QP4>`x-T6%2vng(d zJSJ}|?zv6iJX1CDg}9z0$liHYvTz`H)IFV{Sg~>->fNde-Owts&(|I+zK?VG;thDX zcxow?U$;p1x=5txT70y~$MlFQ|Ek_1+9M&84k7Eg4JQtV?5he)#Mu=k9_lyzMS~Ss z9k~iG7+wlNU1MZp4dCc7nrl+E9jklh>nbA@5UToG8CL+c%J1m}BX<8?IPJGx!mLOX z7J|`_e8q7t?K=Cy1H>CxN9yCuM4IK1jvW2g4i?GEJfmYlXh1X-`E$*l+b(x$kepv$ zeZY*vV^+(N3b?3EHy!N^+{T}zT%FfF|Min5-I3;tH5{!gjZdD66rna=*>&>1|2jQ8 z1VStfjaQU*x)5rFtDSb?WeQoMbMmze_JVjMCru`1lA4Cg~z)08X}1>$pzOX9^Lj;@l_pq$smDukQRt2 z#hGKl>!%|O3LVMyzk!cSDsax*h=MmtL7r6|LB1h%wBmn!{$tTRXw-y`v-3&nm~m|XPU zLw&JnVt!j$d>oP`vK8@$NTjjk;?-Vu44a43QV6~B=R#|u@?`FwW`U&41crt)-1=;* zxH3;AcE@bLEmN{Hzi+5eD#%E*QXfw)rZ*(chU4ByF&UyPqc2+~GTy75R6&>Mc=eR3 zuV?Xq>_D7MBS?~Qa9m_qjD7W;;^*;nDJp40va3_B7OP~#*2m%j^zd|%Lo4;?@+;6*e=aKl`JK@WXWo58zs*2U(B1H5f_!noI zheYl#dSk4Y^H}uBX6KThak>sDU>*{`E`4&9giWpOIv0sDg@JZ38lTsfmozy#fjl7+ zcLEzelw~{9g<(zD9@&LKmYv#_#>4c+v)^Gr3+_cAEDO*uHXD~);Dd(#ogIZcV+~HE zH`vPy36Js*3eO>*DV(($pmc<)oN0-E7$JFwW2aeAiL>?W3)vC=SY0`pmXy)=C>Kfd@UR8 zQq|n&A=;(mFSMP;v`6js4MeI-ypi3qTwWcOIe$4^=n`Dq?^<=QUEMJ_zb=X|iT|vh ztyeoUD>#oMSB-2jkTJo&)BPI6G$SNMzGzcaC#kh-x`cb#{py-u>#J7dC#3=3D%yDM zSRqT>K{N;V7Vd|fn^VL$+wbvSH~JYpGm>6vsHn z^Q`su{`rlIomZ_Vy%}_TdDpzoI!>($6 z*~j&PoPpYr^99)K$8N)0Nc5F{<^&2M4~d_moG-obl*@rQ@;whavJdPvo|S4f~!5OR7s zZQ%{=2DaEP!X@Pxp#sdxZ#_Jv!<~-0yTevN0 z^|*PFX6V4xeMq?>L#OEY!X>M_hSJh+@;E*pYROZ6G!tT1&FXaw(O{5be}Ym#o=xx6 zAg|X2JE%DqP{7S~x zp%{-Ke$JC&rrZebC0j}N#;1+Z_6yjXbe;c?w08im?CaLOgO1fPJ4wg3*|BZgwv&$S zj&0kvZQHi7Z~Fh9_nvdVd#diK`c~~#wQH|A$HK0)YOFb*@q3t9Q#tcl(`kzwcCc=k z?e2rdoz@(U9hf%^+CRmrR!;sfF{f=ML_L`Vjs*}d9IbF3h2n-7pi*-^>TDBEZvIhB zry0;zbw#$%fi#wRcXVq$4~(xx^DStrDQXFKG%msMiP`0EXZh~3jjqR|?030H+;;b8 zeAlzhAS)h)KX-E=suhy;tqMPk)!((P;4ClvH5li{>H9!}IOh3aY+kc?A%oGWPKFr6 zG53ubGUP->{edp_oiEC9n>bGJoj`)Cm^G%s;wYAS%flQ}jwUboqJ%7ia73T}=JPn{ z&&SQ_$-Y0m%ZBR~_Q^Qon`q)M#{9jLNBM($a35YDho3wn4fK6c77YG<%|rE5^Ol=; zJOz^LDb^7zae0N5Z6YVq*{2UnhQioQJ$mj*X6CtnjDl1Ru3H=07C+EyWhYTLCP;tz zdBf$Gm2FgK$)7h{wZnUkR4)NeBt_H34ZFV=p#r%nhabn9>N5mgAZfHc+4*y&#x?rH zqSy?XsRm%*kc135iK$II+ty!P1)AheSYHN$NLX+lPklh!7AhYnicZ zU|~@uA3#-gN9`TbB_Dx2cRk@`%Rw9yEgBf9Z)(C`BM$@z3Ev*g$_XlGp2xDVaFV1h z5bY^-O~0msmk#R25S0Q)RU4{UTv%*Tk+7RU(~S4G5N#V6T()v1T+(~wAI61r`W2!< zIyc<;60vcOd4=659Km{W&Eo|%@jy7p(y?XRZwsDFY*0v>Opn!T2TQfP`N9@tSunPZtZp)m>BR9PFApVhg=9TQ38@`J(eSj9bicX{P zYHvQal+Ucm#5s7M53+%s<^zR$ujiI$7Ryy#%DMbfu*RQSa-^1o_;4*?8PgE(71gKc zGbmllAi;Css$t#AQ`M1;eTB)*r=aruVsojYUH)rGsM2V>Zk&*~5OAME@ji>^$vM%> zT~Y1Jz{e9FbTBacDt~KAiuF3t zRO8kBEiQlD%%cZhr@6MF@V4Be0X=L+rH2ROJB@p-yQOh0tPo_UWet))GG|=~#(_<} zYul8my6Ck6yNAAmpi&SclYU9+3i->Vbck~d<$*hUY=X5sycS^8t({zF`#M`ON>HbD zTkD!hLe^&(CG7-Y3(-%%dP}hDmz5y-;t*cnzTR4u<93q8sl$gLhxZIeQ;I@2cAe%O zlg)CXeOmH9>&JB&8uoHtzsMpnTD4Q)0i;#(_;HW@1? zt14)tYS=t$xpJ7AES2~{4u1ac0Wu;#sAzongB8s<>_6SNXppzU-w;C*!4N6u`AQk8 zmvi7zo60K7*e1_gCc8FPcpW*`HZY4AGdNvHo({*kw_c{6GDHe5i84}BMhv0zi#j6C z+C@>`*>44~W8%xv9lKfE%YjHK)Lhb~rFkZaVDiW5No*5%e*~RjtwPXnZub?i_muX& zs=(tc0{eyNUOxnHW4I<&&61lXh>s9KYZT-%g zy0KLPv;G7+;rX_M$Zq4s(r$?(oi(K`%favWQ4{DssMnuvi@5F=4-$$rR0`vFF!0`g z48I>pePF+_+-ThVnOR-UwLll$Gugl=0}^b?;s#?KgX>HjoH5R1G6$O#;EB~hcD>}XSeKSbsNMH;fxu}B(fT^s<6 z^C3~=E8Iv1-9q^K<31CnaNBCpd9V;svjzSFBWj-XZu z+eGIc;AeI?-jq2Y1s#Uf+QaxewkQVHq?lP-71#~J_?CG9Pd?9?BCQ~9voCM4uKx%E z`xyx!q9VD3e$T88g2+F;%wZi1b_h85{=nd)6PN$8Qr(K=OWX@8lxVTbqgCq<9V97#l zjVO0z4$yB@IIL(myEmrG0JR=Pgz^Kq$P5mgOIxxHYo1)V0RxKl(&4RMb0&rWafd12 z(bU7?nTeL^tWLn5p~rLA6HVx@IxA-WxzA(RiZSP!vt7Me$Nzyh;E6y3v{FIk19sik zzqQhzOG8dUYC#cADa`ljV!w{J$O+Hl4+dtXsXK)Gl%S?5&*4QzBEF1#J+G=MMl)59 z#y1)@%oEijJjfwiY{wyXFD5YY-r!9&{5KZT&$}<@`(E@aUp*Ej4LuMxV*vd%cO(Uf%7BLoh_d<_4Sp2$} zb+FsikuM~`x+aaoo{SFm`)${DsE0GP)6M`A<@Yhx%{I-?V>WaGdIz5~%x{l)a8X5r z3%7S310L`=a1t@o&Jr2AP^WA`EpUD5f&N{7{do9Tmf=RQ>0Zq&xzVU#=isdf`Be4>t%|IFpzxS* z*iu6TS4LULpk^4!<4sx|r=}`Fpqf+b8Az0<7phkS*sxlxU-jnx#G9gsh=iGgnxk*P zwL3e4*hrWr-e7p{==3hk{_dN#3#{hM?xAPBKIaL~cjvAldF2g3t=$8Yqf_aSJcn_7 zOnN`58;r-!Uk+vpa^#i31>g!P-Ec>ydPA^hDV_cLl*|l3s7O)~E6dBKi_D*0Uo$Mw z%IdZBcU?ml2{^5+{BAcq%Zxs>8LtJ($)JNF%OSM6Aasn=qca~N7sgt8GB{tj%mDn@DQ-)WWa4PBGRGq>B$9RQZy6bT?=u< z{%&QyWeeR`MrLk|D=|jWiii7zmQh9DuEDaPARQdRu&-O-c6b5ZHkl{rH+7AV3wY+S zg=me6Q_1Jq?dK(*L#TyC?wLmHF^_1zK*Qp`{(RezTUCZSNB~4#ASr($)c@v%|G$(x z{kvM?KmBvQl+t|oj`siP!4;(b@=3oGfV7HVPC8_ApE~6z4-qGGuE?o z_^U4eA4K~{k^etYG_x>%8N>WP#v(lbjzyTD0cd_A&9J60zvcS=W8nKpNUaI~|M zIbO=x2zN38*f~#*vomguUvYUmcpnkQG@%nf^4Hs++!j!x%Y=^&i*Homesw3?ha%uY z?%-k?B7At9?*09AU7`d3&JZcFgbbjec%6WGk>y77zIK6_k<;Io`tG+XtRg75e;*Q} zCQ*;M(mMZxTrG?oFPMTL@36F2_#=IZ$9!Hyh(bTEevLWoVI@T^bt5G#;RMgZ2~$0T zLn5Aun}k}b#u_E7M73yS{`j%Rrpu{VbV9KhRgJ?b&bUdvNg_u|*)t}!a$Xsv&LK6jfvCZt2oj37aHW%GM}NzUTvW*S~eT@euc)L%bGWm%YF}U0!+c z>I@?ko};D@Nbkm;uu%rWIx#stEbp4x_s%~JJ`lo(;x`RxUUc7cZ(ia8<0ygse(yr< zkzkO(LKH%LQc1-$j`16Y8#UCjtl%?8sS99|Ys3(kipvU4w`V73qY}&vgM7GkGZ)qOFAa6Y&C9 zp%Uz9VFpwMm&E@TiGO&tyoBNEgn!$$Wy!*Q3(`dkIqLT67IME~b``faP#|%`BH|Ai zm}-7a|3XBV%2xJq z;Yw9n__FguxG_&g&w+FYJZLXy0!f#Hz7P2TB>ET>x2P)6il#zO#=t;8z+f*ksJ@=t zW7bqoKgywhO^oTOht&(`dmkuNIX8lVFGTxYa_`tR101$%auG0e;*12rSudrro8Tg zeXFVZ-t|w9*8ZX=77W=<4U_g|V&?^>MzQKNOUGtf zEX6BP@}{6>I{emy9}R~a2qIXd0{6GAU63=V$RAcgup!Z_nqH_;*xd5mkt}TQHk?7v z$G*#do6;J;EX4PGCV%cp{(c0V)*c}9xvcDV^_qQNaH?-RzL0o9>~jl`R;7orG|ACK*Nm=2Pm z*R>7F`%#wWW`z;}i{Sr^Hv_s%DxKs(C-B*tK`PC5in8VUu7`JissTv$bn_<$i^kR* zwLV%#|M(7>I}M{TdMwYw{+tw#&cSK)wCiDue>fmG%vdN13V= zRKh~jBtn}GbXZy^m33}v8g*jT{*kfvpmsxzAC?8Pf`WooB_ajyJEqJ-wk#WdGoVaS zUu;n|PJu}h8tmI2dm)xQ7!EDlSz_E%(7U~ZsbLiXSrWMv;}qi==`*##6D|u!=mh-V zp-Z~Z*JwI}2IBj$S@-R1GfoDg;Oixk=Ral0SM?;tR(kRw6B<_<)hN`qu86npY*wrp zn@lY(#15n9JA5r8=uA#0ZQb~5^8-aXK~8>wd-TgXrkjf}7%YrTY^An#CWNlmX%Pa` z^m6xO-r&Y1Tdq4!)CSOneXs{i@eN^N695()SS}*k18NqMwAqvixihM(wS{)LT{$v; zKd2&D2K=DKZ9SD96RI9QzWtqsaeCK}V5b{sl9QiwQnOKbA+>aIJ~#!o!{G^}vZrQY zC%P-F5vpu`%JTF$oC_ixDmz2HXk1uOu(I5XM33Ca>(8;w1NVOO^QG|XVNxg+I!@wj zy>Prv5O{;6>FmFUq!D$;OT$@yAt@r#)^fr7C&@z*kk zM{Z`DFdIyefZx&!F$|$!G@pXU84T@vfRTx_aqJMyHt3(=MgM8$RzXDO&VlUmFswKv zA<6xaLczJsgZ0PyE-*36sh-Tt4}+I9gR}3rU&HiB08{ z*_=~Vt#z1+5aN?}Zv&vHSkHm$_;~yB zwXnHA&C1eqXGbZi@Py2j!)ElEio)Sm8-EYjok;m7mu$<`3+88BHjSI-nCt|N*b-!16v=iK-C^(Zo z;qcfX4_kV1dBXz#^rF5Hs@%c<0EqT~af}~-CFOa1qRlhVRUaV2ZgWb~!78S9&g01L z_FDzWR@q+mp1YrQHC8ogCZ5qQ!6c1vf9M}72*0Eb)$StuvejXFQD1^Bv^k=-R=&7D zgjQ0xgSsNi&pc8$lVC|K>2fLQ)*vdc1b`$c`+Y*-cVKvqd3?HY|TF zx6D54;-|hH3cO0Ye^fq#la!QhzX3=;Als~wUvN^$I*q*I31qU*&R8?Tfyt4`z2{d% zu%!ME&=MjUi9at^iWauE(1$kB`|fTQglH$CXrAk(FKM1)wGQ{z*L~k1d$#&8kSfrR z-AfKQ#JZW$S25Q^N@oJpk+ruMzv&x{L}R!3+}iLI&4Y&o+g+m_^F{Bc(OC+}nA|_d z(4O1&NY{cl2Gf?M)rsfiYH|%bcb8K@{yt$7gWp?9 zc7rCt^A>JbPA*iz5y3lK81gVe_If(ky_#8i#FqZYR7e(U%C-)RZUqQ(TY7vhApfZI{w&0CvbkhlN3RsBk_t zkZce^Pfu?@KDB+BqwH0u1DtMFxOPI@^_w-h93!6RD_PXhYP-Zn8}xcYX@@ky$Hg{5 zQj#)}-stqQ?Kvf=>}I^OwKn4;SHk?!;D8%0P&g?F7F{y^j5;|dse{1~o7Z)(=HBTH zvvo1FP{fTNnfz9tl-o_tZbW+I8Ixf5HScdu2xlH&(XalR?D-834{t@JpusYJZrsdx zmwHZdv*ifakW-Ca6dL*z+|DXV`Rb;4fVoR~=N0|kpRWN^W!rt-Fz6Qsbe@AQnOOwN z?COY^JA0_?W8XQ{vQ5biLJpSZJPR%X{xdllzU-kPMhXP5+l3;>O^w;eh&9PkIYXB} z43qWP*K@QA~(MMOmLY>{HVn`~8 zMX%TqaVkJthE%%qT5Q-ovF)=at zq{a18#qCjlkP|+OJ@HB~m$RyiV(zVS(zs1HXq{P{wXxmo_m2q0%+6!O!=E4rC@x@K zy-12be68Q#F1j{9Zw7#TiXxM7IegEp%bgmQ-2b$mq811r=7WLko48a${`i)};wRBG z(-dbS<&Gbe?@@PyP3%VP^GToX=;&eSpDx1a>`wnhkM}tV$1DM6;kQt8ymCxxRlH{{T&E?$kZ7#%=LWCKVw4<5k!7 znqtrSesg@TAwC|RCadzM4a=?K#`Gl=8K)wAVza3;sDf;4jC}WrypEwUjd4ZkFfaJI zZKcWD0(ZRQc``RzKDU>x6|FX8MZ3dog;ZkMXpFMzJ0}}epPG2soNP*kLm-E4miC4% zOjP}h6AiW~EG#rIm_0Cz0cajuk3tY1nrga7(5g8DB)C5xON=>WVk~A=PmA~}o%Syh z#y@L&VoMj)D=PAh!C@tAO^47hT>dT^tww06ICX%ACpa;gc_8W`IE@C>iagR69jl#JEX{Tad< zJCy$1uuX&@&kJ)t-Ze%HJyN)D=ubQ{0m=9?N1f1>rCdjoJN$<)w2o(1(b+U0SS>?F zTFdE=Z7r!cv_Gcn#d2PhND+u^B(B`DkKph*R`PlU%r3>x?Ag3lxG)Wrg=*iPpIaXO zjUp=288fp0QYjy|LzWO_?bmYQ&xj5?f$uiA@;QpC#lS+gobY{eorHGK5MnX?T$GRS z+XJYvy$sGm`BWAAHkZ{dJbIxUwqR>NFN4H%N>zB9g;=MhWY?HeN~+J39vvM0(_6Gg z4GnUeELZz!)ltI3Qc@?d3#7{b{4`2toWRrPbC3JyEO+kKOOI#jTurMozNQF(78~WxlSZFT#sKV#sL9ds%Xf#nsr7V^$(JdgNtez${3^<-CCLYt2h}r# zgQNLve0&Ga{k6>0oIg@#Q>IHL`65C3q%82glc5{VyB-L;d?Ricg#OFPzD(-0B)FcL zf0_u*C>uKH3oLj6yB^WSR0E3%^Q29z-BhYP(0;*7tU7|1LQFSgJUz*#l62yY7z+zS z#fgXRjFFTb(%`-HYjbxc=uOO{n8KoLhmL5qU_(ww`m=e}^CwOva~8cjIdl2PO=I&X zuy+YKYx+n^<20TzaV?!Q7?Yt8aJDr8nm0zrSD;9=n=Mu?*Av$#%Q9wEZZ|qP`Au7m zMqMzxkA2)0L-AQ{@$VUM=`a@qm`Ar2KOCKVnx@4#C<*5=M@~=8xhGrO%iQsYN=(q! z@+gZ?wC}O(etF06gjDuoC@U$AgdfXbQWc4WS$&{POK_@`uP4{j_%23=Uo!qmt(;u} zC!n20PB~7?9$!<3~iyLmX9j^x1ZOrbfDxG}13ge%O$y4Sf@l?;kRE^%a?) zFXXnel9IBr@<^3ecsds=*ob|(Ry;pjWsU1h1p|hFju`Z8y&wBo_+;B=FsQlD2X>Np1olaKQj>2j>$6LXQcg)>@yxiP=~7=K!ZL$|8peN% zhDJ18mQGRjd^)WL`y+#HZr&#dWT(`6YrBE7FP`4|v5b)FXYKU_xdqaJJ8V?NAX?$V ziRa{5j!y#nvXjZ~ch(j#+vN8wWC1}(nLO7@*VQ>>))(0P7Zk@v;7dkQWvwred>|hi zY=~^kwvZ-R<};E?>^E8hl)#zz%`NFQNu?V)@JeMM^N1Sgi_&^{> zYe%#pY7Y>oc;joq;T+;o9kEb7w2V7&cy!NM^#*u}eo=x~f`m(8S(Ysb1gh+I=FeGL z;YV|i3q*EnDauRQD$2EWqA3xaKsS5cnNlVlM%u&7Kox>J_#w|`%g*P6cI?Pxsf!LS z^I=u@dz9b_Y74n>o3(wp^0^^o!Fty4E9Pw4>H^3@#HpZzAGOWN{Ry1=?s+k$RxHU9 z?sU8gXUyhsSKq7!vxF2z^!LrLX_q4|wk3_)zpR*m&p^x02H|!p@k8 z(+(2rW-k$iz=$FQ6|d_TUqMS|Ne+!?)vQPvAq?>`Iv6J%)P3?FKxIbV3tzrTaUJvA zD%q#B^Y<$z)g1&A8HpQh7_Zn6^m)~g-9lVo&_queB&5+*XyMtIDUEH|4Z7Ae&-;;t zdh{Rbw8+JUvVK)d68CdIED6IFH`i=8>JL+M#hkHZnVB)ok3q+(WV(Dm@L_ngcJMgq zAz7uOnKnGGuRVCZ!G4nHP9u*;&O59F|Db=7$Uj6MH22cf%uydqH<(1tO4<*%?R+%8 z4k7)~1ZqIqI@A-M?!kV$Vstjslh@3Q?4bZh{))mirNoeskl@+v=oP3;`A~OLbAlOF z4X#rcBxeAQW1w1*eVx3km0T89gv{uYUzubjQ(?ADImMOF!ywL0?wm|w%Irg$YWWGX z=f3x4sStZhiOKV*=}0>0d<@j3?wk=irhi zQe895h(#@rpVV;OLxSJrTSSCyF*P~9yFwSs669$$Yy$M6>wX;Ilw?dJ4uop!7l9pt zw{C~&up>Dh$mmAHb$`;$a8@e{VE)|sjI-zJ=p@+PAmk=I5_adG3`&QOokv?>XlQ77 zFGsZJwPd*Md`R;>6EH{y*`wF*N-XNuAly|RDj!6%JCVFlXkoIi0a;EEA$hib2)*?x zXz^RJ?C}qXvbe&DH+`9EP!~R9xq=~5%5K4qaRnWZ@_TCXMad$E8Da~c+HHi4$#pP^ zN$bzh0MPtSQtq@NL z5W0j)^w>r54~!0EHhM@fF6C3I9GUEm|6XNfeuJ;7%hmNRus-x6V=FItsG214UbT&6Lh=#RXT5=i+v!AU zxjaQnH6CruZN<&aq9G$`Xb20qUp95Ye&*YzBU`s3i|^=rtWn4;4?lpa_6NZb0ja(J zUA?TRHBV+?F4zF_l#JQ-@vZH;H|=RJwqcZ|C6wHnj9X5bwM`9ix>_-4b_R*-zC;$p zGsL(DD`DMhQUMYtuvn!HM5e478{~?Q%G=;M_zt06sO_pOOm59>K^ZAqp1Y`W0VYPWXr94 z@JB=NJG)^IWA=bMqS|<=k(eY=A(B*qr`6}`#AAd7vGqW{d089a^z;+()cMr$)XnI|r_jFnV6J}zGWp*0{*zZg06Iq6&QW2HnIFC0fT z#Z;ZB^rZ&?A(LLY|6!U>S(9QBeo-YH3uN8W`(*Rb+Ttokmp+8N_yD_pe{=J2dvl{v zHacCFz=@)6to_azadm4HzSU46adF1**1FzE^JMgntY{Z1S*)EWB{@fjJ-erL3Y(x_ zDJ6NWj{%rhBFs5v3cK%bGPoh(#W zsL_DA0OK9Po#;s$P6)OuCl-#RkO3H-=M#6wI3EyU&u=E$mOo?5g14yt2W%6G+N5xmCvlrtT0D8uhpd1fK*Cgisw7Qi}S zbHZ&D<{HPP;U3~Q^*`*`XXI^OxVsJY3#rnyHW0cXf6=RU{Sg~qTR~Cipja_aWZpbrnLQ4rtFd6})t*2XzvL0gIh2P!^ z;j&6S+xLt$?m4y;^sHaIS3H3sgSQWxlQFAD78sxL#Rfmam$Ji!g?3v)vO#&Yp%xKG z>QDh2qv_J2CIfw+#3LP~SQ#0Pg$;xD$Rgn}ShTVNh}bweq$nxd*N@Ip9DMS&#?*-m zM_l+!KE??x5>TRVnb)cd;c~`>#TBf$$D1WZG*2WmrJzNkh@tsx-^~0JQYwttCLyR( z+lr-Rg6y?N0(_SsRw|R(p9Tj`B4wlG(L-)9XM!!XCCG39M)Rtv0A)`$)jv<~g4!~k zRb)~af=^1CIS>hp66L#IX|VZB+(^_UtV_1reKfzXOyE*WIzLOxKuIe#b!XFFSRh1p z7{8kDVNxZ-3l1 zN5{-Omy6zl2T51u5l!IvSiPAK8E&QI=+w~Y>_o0^V1OE?nksSKo4prlTgT8lvZK;U zPxXvC6RKtdUvhMOYBypez1X>4m)z%$-dKahFqcg|Z(5HwLCJLE$GQusz3km?xjja` zPh`EoL`>(lw{p#<*Tb}@ryACHb0`n`?Dd`W-K|?<&*+|?4tL;%RI&~&3TCPyZ4_s< zQVAlp+w2j0L{&}$tJt-T>InuwOm6j0TMg+>Nvz$SwyhY^4z$1>vN!%h3kCUA3#{4w zal)tyedpE5uPy4QiI(%g>Q@tF#-{S8Js6859xClJ(^`x%3={{i^fD!SW% zH3uI{?FvY;7?MucVqpaAU6$Zwzm~-2XExWUZZ~b&-l~dttOi+XfN{(BR{1-%F zY}|9dmwD@>VbjONhWjWeT#SjBoQsNO);QC;$isuyDFEL^JzX;q4gjK(S1Cu@GFihu zCH@DQ`uoUC$-(iwc>~&o&8!%#3*=@m?tyo z#-Q>X8~`$8+Wk1Gi{MC(5rHTtzq}W6bVt%7FaLq2r>q6m5xcnCk|`P zL6zv*OpdmEOM_NqSzxzyO{1n@8H*{QA*)X`5QRq za*|PE>lPAeTdG@y+w;xy1Ydm&}E{jg{3k#16x5fFNhmtQ7 zvDazw{#OulPbytiiBQ~b2>1JrVXOk3TnGxYMibFJ;nNx+D(0o07e(7}lOn6t)}zsOj&8Xn_~Rb}+ejSL+B zOEM;ArDyWBLB-6_(G;JB4WCx@AOG<${3JdtznP=M7dl(O#>)1~_4^BC`UR1s6|k|i zu~)FwGx+KyXyj~WU?gI%=Y~%!X=H8k6@r0@jRpUI+rbD5C<+=G*ccl9A7mrIGT;&j zp3l%m-w4R?H_+DtSOXFO0{;KG0J?!-Ac44m1c8AGfB+jn-+;gX{Xnx{;lV*bf&cF2 zUkd~zIM_ERP-qZfAeiq!Ai$vCfI&e)K)+USC?{YL&~J!fNZ>yqkO_bw=~4I?2vMQr z_|f!;7}4eJd@=N6i3M_Mu1T2ep)q@Am`T5E*8Fbbas?F~goIf|49Jv}Rj_J%XLoN6 z{T<^2jPmOG=Jv?hjPIN%*f~VS#8uVQO-#+qon2hr+yjGxLqfy;BqSy!r=;c=6c!bi zl-4&iHZ`}j_74mW4Ude@FDx!CudMDL93CB?oZde?K0Uv@0#<<_fxk|N7iep56S}n2 zoWeY8bv1;X>;yltw6d~P_2i_)tYpv3q_{X!Sv1EFBX&Pg?T0}Wvx&2kJRkLy_2pW} z#Ld;diuOCt3;NtjbUgcK*u^=kXy@dGR%q(@PMdvK)e{(=wvjxnvwf|&%E0AI^+T2u z7YVcgWTq3naQB%800>Ip1n)3uQLQRf?JCQ)Dv?u0*9ZVK(}`Z$cs1(TWI%1LQ(g07 zb)(Sv#4@_36|cb~&%r!26<9c7gQG>vgY7h;5gL_5nqkQmjNYQt1(@F2+v<4x`vJ^s z=CyHHRCWqFp&Q<-SnC$7f9R}vu<};3K5hilr>)%{HWnTZO@vPvD6lr(vZY_rmmZfA z2Vc>vQBW*9nFr+{@I26cn&1u7zOcPBe~puH`_FYDGgRHGcpb6e@x3cB`w;R-DlU!P zs&ueAQ&zNQwqZy7XiZ+Pe^X%3;CyXD*Wgo=PzzaAV>>9wq_!3F@q)O;l8&p$ejeI7 zQEN!5tVzBIU((8GDH{1myj#O&L>2Ju-*3|1om^BN(aIP%C^oZy(5O^@${$lUB#9<| z=fy|ADv$X73*Qg&+jnb7EZ^MgP9S0JyxbxmGqa%G1aj_Il({bH*Y&)^qr0)^ zo*NlN{L%ZZ+pe>SqKT^*#5}j_2VRmkUPPAe=dRk?VrH+(qvbRWTjRFqZ>w^oxucU< z2E^pQx4czA{U<9pjIWo|d*#L{%+M*L@`kCYe>D^psW%&cm!zVm;?q=hZ+<+x+Wfcz z%>O;`)A;v~PG%oQuM56g*BsVC}gr?yB@l?zc`B7oF{DW~bVt+P5q(Jyzk_%A#Rrl>2(N z^#bMH@p%Q^>lMpD@~}@~01)DvOT#Ckv&$XO<;Gci>(N2e9okjo#vLeeOXG*M06Gn8 z)t+V{X#S&@GTHoGhxS0x+MUUh^*~-!E839NkEh`Lf(+B$#4sDc!Uh0n4_)_&Qzn<= z%=1!3%wfe-%ZW$1kZl&VqP*wuHqBeoUkE9mULy7rjj}Kba?h8fI94}`&5t0O=i{Gi zx45;p%y$c#=YF@pB=R^lRJl4Zm2#$ieD*Q7xVDBTCU07{zxLLIs1#C_g|1DQP_q(7 zcIy3x5EsQ7|0BLIzams!6vbm+V)yBt;Al5X(WRU_@)mu6@%4pp0o%cW$He?TK+7%a zjDqU|j9Okv?}odg{g^fCaM(J+e8^q%lGk*X1>vUA*F^ml8hSLH;KJcnz-zY^eQ)xx zYVD8e`u8ELSE<*Y~#b697F%FYZrS8*FHf5E;%am znl}Yc>y_Danvm0p3OUT6+Hg|?3kEv6pV^}(sCO&k&JY>0h73;h^wll=mb6!ZrT@Iw z|GDj#c*jQ7-V8cA+21{arou``=AC(Ne3z-@b?t5!`1Xm*!wK}R+d5N!sJF*2^&$0H3ZL{TxE3uX8t4iKvh-F!1SWwt<#_8b8C*c+^(N7 zmBnFkVL?H0=*4B_<)s;WeyNG6ko&2*xhA4Hp}1l{8qgoVo(s zs8+@twHZ&|5SQfk7{{cg!*Vjxl;bl>vI_DGii_RH#07qdg=ULvCx?b4I)trxxt-#d zmbfPXAn7#;vjxkEw)nxz&=LkV&p^%RZ{zv^pui4EC3bhP0aV72ZtdsR9IWGqJ}dkoEzku+{uf^6sT6lFivzSUBw1ps1W?4ab>2|C|o?fH^Ab9$-B7_%JNPEt%E8N zx;4?p(yr4`?8b_QNLxlONCKGKY{fk|6%W&lbo`N0Lz3GU0TPnzE^+^lfvU@Uk*HRoxZ;0?wan!7riYr@ylvNn(jbwtFgiQ540J z+iYV7mN{z(!-6pLFGI9Pk~f<%ALviixKGY^-e=NfB>)h{C-vi2Zj(Hj70SI6yB z>=Do6;H|3_07QE2#wmx zMfmglqciIXu4s$m>QUqKk@l;D#B=16jQ>?vbC#Ev&Bx>Q$Iy$=d#22lNc5XK04VIv z$2xiH9(lLm6YewA6W43!QKyf$<&(DMlM?;u?ZSI$?&yeb1R$yyqWTTN;l%d&@IdfR+C{zx+21 z`YXNsw}4yrZ!!r-EBhB%?f6B^{s;IBM=NjSVB=(OVB~=RFDt;mS){e&R}%;Pzlhf_ zxHqkok)fF$zl|%t#@7#Y_{{9g_-tRm=)XvD0ec(U|9*?Sjia8U(O2{T3J3o$S?|}8 z*xMK=7&(4LrIi&F{z`+5Tpj-j`VW}@pIUQPeEPpq^e<_-FdIJozx*|5h1u~L{&lRh z!t`Hw_P@~Czb(GZ>i_pwM*P39&wmkSY5!Ag{x_(I0zE#{UrqW~9}$JGKL6UoU%&eQ znn3?;D&WA3&+xCS@OSgy^*>0r|EAymZS^17H8TtAm*8CZzp+62+t0z#-bl|14q7zy zTt&JY`p|92wiFRCEW=aRsazh+c41bX$MQkZU@IJQKt|f zOAUkE&mXL|kBGuyNjMSr)W3 z&$zkM_rc$G?EE#o?(*IxKSgDq-d|3oo5v4xTcb_*OF}j9`51pR8h?4b zIOsN`cqOB5Blg7)^0Tc*0yY%G;BU%M)&!8Lb126Bn?W6%7o|GG??f(xo|qEe4%E zKLRrps9SSmHAR1ED`&&!bqUwj&K=X5H9Zo_yY=3@z=^T0g7%Aamykv!d$BU1u7HWP zJ&T1ja!VUHeQR>g`vGGU^+JBtNb`n(m|e zcKpCv3Rb&d$u#AW__LV^_2-a25jckbD1^jes(3@sTi059Bz+TGCk0rD>7v;~-3Qx~ z@QXN1d^o!k?N%i*icp{RIIj@qQljcb4Jw&oqcSg)*Cwx`n)$Tk3Wi@WMF8w647}{s zD#s@V&(_=3K(!XEHmpZ)7kZyF{qq>sAgW}ejU_)gZbZB%GgKpe1;N9I-&+M{0Z>2L zw7yoIN8bW8&O@E?({b^PS;1&u=Hjp4D13T+K_{o=;NQ7#!lO0y%(ia`tKtsx zky4I$PFDV>|}<&<0)T+hQ}xuXgXtzB-%cXF*|A zSUlRAD&7NuGjG;2CI{qyfa*hFw1U_4Y12+1H zR$!k2r*_kA^$UkV_q_kuTd#<|(;c6M2NYdELND+kQmT^45azG)Bb<>>oAM!jk(0&T zF@Nn7+Xh6CHQJ&>tQ#%B5jmpkh7RvqxlHqlbw$779iX4X$E+xqWo-O(WIZTW?9F}) zhHLa~IqI)jY9?)7>BBdP;s#CLOv*)RwQN&**?VmX<6zTh6)}#rH;fH@W6RRrY;{&}ySHx^f8$v7f6o^?!5zZFOW2VE zC@+q4=AX0P3PI+GfHUq&ItO@&G%%%#_LV#-E2g1)d&S`>XE0m0e%TjQvj>Xf5A-*>~6IOn?#ctDl0vlaYDcKdqoGJsG5TxMhaVZ_Qc0 zjCz}Sew$G;;ase!%-x*d9Sm4LN7vD_w|&xa5f;^KVkCIdhb_j@_*(Er&~75o9`656 z*N&bHnzJi!I1O(|`9@-=^^kVc6_oc9ksfKXy%@fN5rLBxO}l-3ci`yFO;}gEACJ}~i}Y@1#gHXk zhK3e?cwe6<^OI3KIL%hr?^l{vTc z$cbx-D%o40$y0ofw+jdiq3`}FA6v(1X2s8d3+BS|g}BrF-^cJr+bV49FycBiKm4%p zBB5l`J&vEzB0z+nK+af!Nl#2fI-EC2JLUs2mqn^qM&H!x#=*Vhoy3=gv2JRp>ZDU# zIID9}h|WouMb+&8G_9%CkU|V!a0fC19pQkCbmRxsKu~M8nu|!C187d1-zuz&?oiL6 zEYQ0_abS3vIoxJM;dmfay16Jj3G7KWfRUtZ1$oQO$%iljG)}lCauj`vVqQR36JG2G ziLghoG2uw5wq+$k{f{v}F5O~DoI!%Pl{AL3@SbxyrYkdbLO-1TXsi+*g^3>x_}d?` zoph4dLThyOS?k3KzxM>m#gJBj{@ih(3}sd1bn$7veOIdPv{@Ot(69*4hkGEZ_xyBs zr?+JFNAJtL{^yyPEfH+JLRD(5#+1X{85k_{zgqhWu&S1>f9aBvlI|2ZvoN=^aNIP zl*?or8-nF$+P{p0%u;CoFp41)ah97wm;wPVx{Le=r9zw_kICZ;KNpeZ%uhwNH1Vo1 z6r(V^a@+@ovd@|L;sTJhm|m&PlF_e>1E>9v5uha|tngE4QXMwrzD9Y|bi4u>gzob3%dkilUa}Xs-`(Dx1ijdV+ zx2mqWf8r3FigqB?8DAKTV=3IbX(+9{NdU?pHO+$|k<*IZ7E&bk&tQ~bwR7hymtq_)m;X{4G|sTusMdc{~AWZdkPnECJ*)Adc>)$@RA-8F<7+@5B~`|?H>2u z((mwW@MvW$V=7pSI>hQGhc@}gfNh++m(?iNgjsfbii95EISy(w9JWd(}Ep#+rGA%AFK6v&>{_;9T6{OqY6vkdaW!fT*3Ig ziP2BNJN3zNrHX*{?YVGSr{Oc>?gg!Izi*)S-zxUwwX;Vs-NtM-u64s}O5%EnVk=NHJYCHB*%Hh$SN6 zw8}NLwl1|yDw-xR@SnC7ZzzpwGlkK?oDQmGP54W&dw!2?An-(1>^Er`5Toba-jTBj ztwt3Qchu~Ug4=MibZTN>28T=fA5~HGJlGQ;nx)Y72}Z>y#+cZ}U6fqpT|Y(lD67^d zX{qm3_1M#fiWDr!npe=yfY#;X*Iw!YnQZS+V^_z_8>nGm3sw;uX1w+xM1iWYls z{UP##JDLI!Qd2Bp^-m*>_~2beB(k&2#&_Ddk%MsG*q)3Y>?3>)b=!zKUnyL=Th@9FZ zb)K#b7G53JKh{;pY2e;LL80#B$6C_FZB{{ruI()rpioL9jdI%1j?m=Qiej~x6kF=c z$Js*NZm{~}NiS>6I>H(zvzRM))z~9m$ZD$1shlDhsi+_Y=jamlIAN3>eix?wzL9Lb z9-iI1x?%ak+LiwKBSWSU(Mxp8zIBy4&#>fA0b*x1({NA?H#m(F!qE@iFb@38Vii%Z zbP1&8Z{DQ$@AALy>Kv$P#Usr?eq-TUp5Zh3^s9+hrF7i*XZ#k+iVHj1A#e#Qeoi@^ zde5-Q6O|xc&(mQ#*%9q^M(YFe;np*R#!Zqry{i7&kz+@F?h(&M$~JtcLf*;;X_b$R zTj@(*1oW4QHuaVEAf7Kr*beS0P#xLQiL!QB3pu^0AF9{D&WfHGT*XkLbfe5`U3Emi zuD|9Wff?)&S>dSTZO2nVP_AEKKYUd6Xl6LDTI};kP{k*^g#;#2#A(gm(L{z_nva|X zR(2cUN^Tzug9W`L-mk~{u0IdjSmCs?3Lax=Xr{+72FM`@TP?a#61*bDS7kGra;&yS z$yfUgc)E z4>Ha!1SH9S_Fu>i%i;y0P!R9mXc8J6K@Cg9=$faCYqeZd42NK}CHQiWAtob|RjpeV zu?16d!&yTqY^vdQ`$LM zWD0n>DtYu*Ozn)9qN&0dMn`kG(yUL$Y`ebu(Q0GLBm33U;CFv`H>&tMtPOj~`gfId*kNhPA@WBOg?4e-7^m35U{gDg88-lvP<^|J>Q6YXZwh-MDj@VL{E!7v@EqE&hyMLsXp(0>Or5>Ck-n z0WC{(UpS0X;Ho}==l9mIJ1a?%Xf}!)Hp$QtwZIQ?cDs++ zoswp`qdJCkc!8D%^_WLWeO|yNhE*HZ$A7`IMCF25^b;8o6Kx3^Nc0mY8e;*DP^q4y z9~)G&534%gN5(WaZ>Nv-V;(!Z2S|FA)(x47vcs*+BpmO!O3BGA;}`QxaJRIhDq-Bq zQ9r3Jfv4w6$Q!4NKqUqBYFGYU$Ol&s>gptO0_!IyWG zo`&eFubO7Vr=a zjwG?GSdVA~_gd;NmnKVsV>`S@cj7Kpx~uVNVm-t{)dwG{Mq(CJzDN5!&p1fM@%2ZU zPf1SFjyF0fw12tOe3Z1g>{4e7u(xGvbS2V#X_tiEp+;Kh?b=FRrhK?ZBhgMwvOEcN z_zZuQyrYMUF$~dD=^;!k=;X_#+Y3;_Ql;{j{_BJsF&{42YdU?7o*Ss1v}>J3nP+FK zD4vc(EZ7_lUSCbthmNv#S$2k7O|rE6LbDruuQwb<`M|FcUO=B-=cQtLmV|o~Nt8Zx z`NqrcU3s>O-cPCWX`b`KEpq0lBY=gM>}RrQ?fH4(y6=0eDr$5g?FYfPo^WvH=jB+3 z`{>YWDLDiQ&etgqqWqR&eW$-11l^n?U0+RCX6uG7-D=20jkO-Ij9%WJ6ZgTD`zngo zWgT@pX(Xc{CvOLFH^V9(Jr^p1i=cn>PEzom53TiN3hu*O8Re#j zTh3Wg--Lt_TcL-^=->l+2E8dx1$DRtdeqUY&V@bx&=;N4w{`{;v zAA{_iJe7Jv^b6sRTBaebvKW~Ue(4I&B+}1ii?An#4HUF?fC?5hP7l* zSH->!`Rcy|D>k=p4L)k$CFdlT*!Lc3)wlBAtlmHwkm?Nea|uR|9eH#+ErXH>$8ngi zg}*V?i9M=>rPtQ*G8Z=>^z6B~qVRS81O1|nw-I*BAF6Z)YZW7L(LQRlB#kzZZy9gRgP(gMuN&b?&IxX;HXu=ZR#>ay-yfv?r4rMg%d?v$0gsZ%(XO;HXhyHKh{OIF`Wi#w;V&t-a z1J72){IySTMlcc+phxq zo~K4(3WW7w=rbdXMtX+LIW>Ehn;o8?PlV)3V>z2VKowF;&r@Mi#lBcpUeU9ql|D+0 z3PG4Y6p6?!BLYk8!C@Ewsiro$?(uLu*NcSBla)OEpsS!(v^$rf zti~BnUE|7y4b`0PCEIPwBlV4dC%HL{47o|IF;`i736J9X6}+9gY8_QXvJE3;h+r}j zSyB^)ZmLAcX9N<%;2$?tGK2F=retLv%gK=KKaDmP;aKrEKbtH)A?DE7%Zn`wDtz~_ zPjNjrsO=*fwJXN{n;^8=_gDt_cO*RG{b-@mO_p@vso`TA&hgrujB; zX#c-X>qF+Z|5(*~KdpZ^Sq>bX;%4l6w~Pd`m;{1mDPiU8;woxs5x2k0I2tw|5JRQ z0V3o+umc5g0}!pKU@#XM7;s5IVlJRm2yQDRK+=%#XJ&v0Lch}xpmYDBH7X9thtb8bEjTtRrpJTzi0o8{;#Ru1VA$V-#}|+#U<`RYyTr)Ed&z)aB2PK z$@vWw?*CVp0@i0iw1;#VPF9|~z|94`2#_wt$wS7@%6S(!Sb&!vct;^LNc!#`@bWay zM#c#MBA`MNV0NG%vUA;iGeFdbT>sgnAky!;6r?_Y-jI4hRDei>)a6%~0+=|sfsP5p z5J?cGyE*|yK$su_LWjhVMuHT5#|!YILK2V)L0SjWUG8oI(z$qkbuCCq5aAq<5&`uf z@m-4oPXO`(UZ?-A>-_7R_?Lh`p5R|B+yK__uMgWFF@pN zH`I;a`_pfEP(i{jCJ-Mq7bozHL83;E_v;$D|0Db}@W6kSeGmQ2&Hg*`Gw_Tcm4hg! zU}OiZev}rI{I_2R{|WUO^1_3({?LPi>rOA=w-e%?rUN;eIa@iHf}BAvkfoKNKd_%I zK{6m0kkxMp(5@iszav2313y2%gMJ1;pIxl%Eo>ps&lb)`?q+uY&?XLcc19pa(C^^S zM!#i#iC_$Q)el=|KAsvRk>V4>oi+hZ1|Gqm*QD3Bv; zo@KXv%eBPQbbV5q2OAa*D~ zkK(00UK-hxughv_9oo5KznvfO?Qj8h7T*#PxwyS^BqGHkC4MSsuKy{|Hpy1c`XKL% z^Rp4J;?+^cR>a!afnCy;X{*;hncry?@mi-{hImac=)V?{2`u>CeiY&|T+REC84IsS zo=F53D_9jny0sd3=rmt$zm&^PPM(_}BGR3QJ>v=BL%x;y(aK3GE7BvF1s7=5>Vykht;twFI2-o+}&yq!wQkYO<5}eI3tK%oi>fR$4i1k0)s4&QSBAZaaU^YH) zfU!t@eYz_c*5zn#MCoWt6%yTDMfNa~$e+5!I8v`#&_s(S#L8)hEkv)U3W+E?6{Ww& z-1vL7_0D7SfujTR6si=$Ho8TR3cPd7D_$t(FkItq`EFTzlm!5pVmu6dR=j79u8CeP zSvJ6no+R0kGWAJrSU6hoOxzfUE)+K&>y;rZvN#krvOuVSXCSPr50fB{i55+}C)0|Hdt^zf&WFCmT847#6lr4>CwM}(j znFbB0X<|Zg7@u(lrn^wDZP)j-DrDv$)t8kikI`E<*p?SP;zE{AUUg3=9aKngE%XR?;>$Ua<+x1ZzrJUCM*9>2y!ZPJ@pOfci4Uws& zNKGM!RfJsjd&!n()LrPVQ)9jYb-@MnsmfEOzv8BU@wMhV3vRc=i=PLVNzcFSQgw}} zo;9pYzT~b?vIrJ=)CY|TV~^*3TIVBL%h_Kk&)N63+J+5l?L9@WY#S13cTq(l%a8Hu zq#E8s4dG@po7D!dMw+#N5GhQ8=rA6-?l`Sb1v^D&ntmhFDonkgNfK>24SbJu_r3Yz z%G2W~?E|{E{sBBRMT@6?i(S~8D9CkhUr6RY%shQTC-Es?YnFukhj^PKhmM?UZgU`} zU%7_YMtlO!~z0O(l>3(~>T1nn$Nii-5wt~i9TWXzW(omp1`uLo#g9pdn1V6~L zU#M@8GBL}`8)-zSs7CErAC~`!AvFkVvz|C@LVL9|VUx}w00YhoZ9*Lg?H)8&MVS-9 z;+I&!)u4^9c$S^kA#XpXp_zS_D`wP~0X3;Nzn9J!n35PVSt4!~I7m zx8K-ks#rxo3+3V!;5$_qF{ojSNO!(fWFauuM_5eA$j%nmr%8X_!jLs=`1x5Qj;*lU z(=TnMiy~9N9$?_CroES*Do*Zh`O}u)uma;@3W%u@PVB`xJ&I@W>u2yeSvSi;L&oD` za6A&LysR4^Q*&7vn#Df&^dwWfPJL|YSG#5!#ArXV6IJVTR&HT`LL`k;*qmT-i!T{6 zqIDgrxY2lfa3JzMl1p-GB(J@Nn3H>$9?jPfrak)X0otpP49pGFnwFOI6}7_F4-Y&; zz07uBdKI|5A2=3S+4(9(6JNom?rf^b8^e+X|2@veY+-{wr;s=-OuGS0pJl#>*ue$; z%qeN|W{TQX&7c@+NjUrFT`~CU78%v6$kfMr|8Cyn%(xR(Gf@c{#5uTxXNNu zP*+2oJmLw~XM1noF0`u4BL~YAET?A{*wL*uZhjoB>h_xvr)JcV%P>ocE}T2n8mK2R zi_L1)ao*TtVHUCA)}6k-EsP{M!N`AyVAu9;g~wY&xb5J56?T^i?R5sHKs$J__FW42 z>&yKEK0a(`oac4>e%jB(eVHs8$s8C|1Xa1tG{;)2msDPv&MsD^EULG59tIUP z^6;SbZ9~hB_o*ukG7Ri~0^o!Zy4t^9u_B)zO7Ulq?i@R-Pf$beL^79GqF;|>-qkH8p^@#_5=P0v% zTSaiHw23D3ff!MfQ)Ck|(ks8P(!ppQF(R3qp96k212*;;tsXCebmMF;CFf1u6n#-E z=81*iIn`XJ3w5||*_3bWvr!G=EWbsB3uC45%r+hzxO92hSBe;MT;iLd8tltTtOQJc zP6LnGET6oyP5th0gsw%BUE=i0vvYVtd-3M=BjZH|DEW=eht0;Hv^a(dvc18GY*;kL z2*=aZrjaW-%^@^$Yr*0>5@QC*7GlzU4?ogsyW=yi(Qb=s!6L!=^ zPrn5eW}K4YDzG~kGDAUUfC4|lh=O$rMZ7-jVAc3Y-@F<@-4FV)V2Ec6+wp;*2suM~ z?AWy%JF(~dV8D%fI@mg{ zj9RRoIAmj{-iKV3%PGfCo}^-`QG#B;=Ye4Be}F*FXo9K`ctir9wL-<)_M&|7Rw^Gw;4sR!h-8IT6ck9)z^U@jYk7T2)LrUw>uO@Dnn8 z^vm~SEY*CW26e@syY&h(_^ zxaMWuQ8=mL&vrEcXqz$|O(=u3R9&jqpTnJ|R>F3sblte(GplTz3Lw~0-yOaMqid(Mi8vdEijHAam1Eh z<<5N4wFEoR?5mTk+nv?uSEihPEos~R_%waD>*w-^9}JVWg_b30#u-juhF|yyTS3v_ zj4x9KqRj+(8Va4+1-uH8;z6g4q@w%O4LuaTYN*FIfrL^+AD#-Wiq-O-W`wbkL+RuU zfw5g<&38dye0RW<#SE02LU`~HD-gA>!be`g^< z>>vmy#C~F80|QnzNW#|00$9BZW@F|0r3=N6hR6gHIV3?-E(jCsDQ*k;viL!BuE`3 z{>$8v1_{&uGTVT4vu5mMzn10xZsGiPc=W$rTYJCymW_quf3OK2b?^gva94I3e zX2}>3O(8>E57r)dn;stVWp+CKMJtc{j#*Te)la}x&2F*I*Rhnjw13rsJ`fPdLNp*r z&3I1cG?phVTQg*Zf4K=45>@xy#A|zb?4d90`qc6btME-VvLNx!R6J!I+LtS>^HnNp zz1U9dAWe3BWF}0X@et))})KgtcY1v&rS=3v(GXn~TxmX%!hM*7KI1 zd`vmhQ1NN>MAm62Gt5j+%tg0Nv+VV~TI?^DeG=@O-LU8h zVhZI$GH&Mc3N~?1YEx+`k3mvVkIq4j_a@dpXr{*(g&SW_g%Z2>iJm3J8F$%MsebI*htV&v*2tifVk_cH<~hG05G7HmUYmWK zVrmS-iYLnUaLi7S8{l4p4pT35!PmW<@#kRoqN$2kxysShLL={VG?4hT2f>69;uC%#@D8)siryuT{$1U$^A%KOb5EHPfnXi=9zrFy)= ztuZ7CG1g=!6cHlUY9U|av8Idd$MV(`coehq)I>-*u5fLA&PBtNx=w|vE{)Q~inIG@@ zOLKf5T+;$8no3IyB`o5&AWo?nox#hjm5x{ueB-@(neA(5V7lmYP#k@w%N)rpqHPvj zI=)t3Qk#+>cPQEsC8+4Qbi`%&5NGD%T5K5;Auf!DFOP_tWKonY`s&%zGm_LJ>^6G6 zCG?fLVJjEy@?hqSoy1h1&lXBysPz+jhu^;Bv5-l8?8FDVEoW_rVHynK;oyXe|3IOQ z92-kS7C~vb^4;%lHG_Hcks9iwkr1j0sK+)HC+yv*ZI-kr%S6qqNv)o74@bYz)YFMpl0{v9MN?6zY&$}QGdNR{%kh!rKQ%A#__ zJN<0Xt)_Cg13&9bSTxgAcd&;=Y7 z9h>~xG}Cx{3*tyP@t5suQZM;)MQl(;&V9Mruda?Z87u><2K@(hG>!6RJ3>J7)e%(< zrw*-!{=MH>zCCj}g!3r`*HY*6?Xh6;uy7BSs)tx z2!S~yNUTDJQ_OI)JW0T|tKF@upOGM^3+mK523InvX3X^0cXMpNKA3h( zAmQjWEart4)a+tUEe3nkTDW)_8-fBsacFj}RpOVJ#8I)hV$fT(} zBw#~JAgtCbqla2gVgdI)Gswt5NDMEik$(qn_q_vRWWHbRE<@tCio^&CGo6MVR;&`d zGC}0a1D#QvM(Fq3G!un84|$M%KHL_bqI|!O{PNmI-AtflOl4Tx0~;56+>*#kat0^w zLos@93V8#Xx#n3)P)>Thl8qf%1McoYciVQQ3{nvtl-&8o<~aFA&jV7gjsz;Gv-lN? z;vY{XVHvl5kysv}9m*d6>nIG^IrQ5wOcdCi<7(w#F9zAOL?^}z?2u#y#!Nh{tn6SG z7GR75Y*sRLGcj`}qZ2l9b}%+_B@?r9aka9w1xOssEM(>m&SdgNCRX;Y4lb4ezp$ID zB|xH+mr(_-)T~@>0l6|}ZuVv_0MrFAt?c6H;Oq+Ax+@vNsqALtY@?;*3^3@@x!UQ{ z19Dke0S2|V4(4Qe!oo_+!a_^``*;a(asF1VUndJdc7C}4Lp50|Q;5r# z_17+`UmL*gHgP$)0i#L4OZ=N#?76dqf)01lsj(6}I5&Hh0HJTQQp;ct04S=m_r znU|B56L5b0gO45jFY-9qxdHFzpM0*)M!;ay8I_L@824IvnE{P}3OE#W_{>dAO-(sj zjm=F=jE#)UxxipfW5Ce^RL+czhZAfh@V|5D0c{NI1v7GXy=!1rE_PIEYH>vg)c*(g C<@G%P literal 0 HcmV?d00001 diff --git a/static/Instructions.tex b/static/Instructions.tex new file mode 100644 index 0000000..da293ef --- /dev/null +++ b/static/Instructions.tex @@ -0,0 +1,88 @@ +\documentclass[a4paper,french,11pt]{article} + +\usepackage[T1]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage{lmodern} +\usepackage[frenchb]{babel} + +\usepackage{fancyhdr} +\usepackage{graphicx} +\usepackage{amsmath} +\usepackage{amssymb} +%\usepackage{anyfontsize} +\usepackage{fancybox} +\usepackage{eso-pic,graphicx} +\usepackage{xcolor} +\usepackage{hyperref} + + +% Specials +\newcommand{\writingsep}{\vrule height 4ex width 0pt} + +% Page formating +\hoffset -1in +\voffset -1in +\textwidth 180 mm +\textheight 250 mm +\oddsidemargin 15mm +\evensidemargin 15mm +\pagestyle{fancy} + +% Headers and footers +\fancyfoot{} +\lhead{} +\rhead{} +\renewcommand{\headrulewidth}{0pt} +\lfoot{\footnotesize 11 rue Pierre et Marie Curie, 75231 Paris Cedex 05\\ Numéro siret 431 598 366 00018} +\rfoot{\footnotesize Association agréée par\\le Ministère de l'éducation nationale.} + +\begin{document} + +\includegraphics[height=2cm]{assets/logo_animath.png}\hfill{\fontsize{50pt}{50pt}{$\mathbb{TFJM}^2$}} + + + +\begin{center} +\Large \bf Instructions ({TOURNAMENT_NAME}) +\end{center} + +\section{Documents} +\subsection{Autorisation parentale} +Elle est nécessaire si l'élève est mineur au moment du tournoi (y compris si son anniversaire est pendant le tournoi). + +\subsection{Autorisation de prise de vue} +Si l'élève est mineur \textbf{au moment de la signature}, il convient de remplir l'autorisation pour les mineurs. En revanche, s'il est majeur \textbf{au moment de la signature}, il convient de remplir la fiche pour majeur. + +\subsection{Fiche sanitaire} +Elle est nécessaire si l'élève est mineur au moment du tournoi (y compris si son anniversaire est pendant le tournoi). + + +\section{Paiement} + +\subsection{Montant} +Les frais d'inscription sont fixés à {PRICE} euros. Vous devez vous en acquitter \textbf{avant le {END_PAYMENT_DATE} {YEAR}}. Si l'élève est boursier, il en est dispensé, vous devez alors fournir une copie de sa notification de bourse directement sur la plateforme \textbf{avant le {END_PAYMENT_DATE} {YEAR}}. + +\subsection{Procédure} + +Si le paiement de plusieurs élèves est fait en une seule opération, merci de contacter \href{mailto: contact@tfjm.org}{contact@tfjm.org} \textbf{avant le paiement} pour garantir l'identification de ce dernier + +\subsubsection*{Carte bancaire (uniquement les cartes françaises)} +Le paiement s'effectue en ligne via la plateforme à l'adresse : \url{https://www.helloasso.com/associations/animath/evenements/tfjm-2020} + +Vous devez impérativement indiquer dans le champ "Référence" la mention "TFJMpu" suivie des noms et prénoms \textbf{de l'élève}. + +\subsubsection*{Virement} +\textbf{Si vous ne pouvez pas utiliser le paiement par carte}, vous pouvez faire un virement sur le compte ci-dessous en indiquant bien dans le champ "motif" (ou autre champ propre à votre banque dont le contenu est communiqué au destinataire) la mention "TFJMpu" suivie des noms et prénoms \textbf{de l'élève}. + +IBAN FR76 1027 8065 0000 0206 4290 127 + +BIC CMCIFR2A + +\subsubsection*{Autre} + +Si aucune de ces procédures n'est possible pour vous, envoyez un mail à \href{mailto: contact@tfjm.org}{contact@tfjm.org} pour que nous trouvions une solution à vos difficultés. + + + + +\end{document} diff --git a/static/favicon.ico b/static/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..97757d37b247a0f247f1288a6f1a43c15614b612 GIT binary patch literal 1514 zcmcgsO-o{76uz^V)$C^-%w|^elllR+Y!L+NV1Ypz^nr>Lq*i7YrIls*QEDbGl+vhF zGzcTgJ~l}o)-yh5xFX@i%w~?f-uIsOyyrRRIp7_s3MiFIczSxm%gYPO<+A8bPEK%faY0j&bUKax z{(kiJ^lR4NtG6XWXYN_EqEW-=KVjYje1a=GyE z@PNn1M{qwnIx1(hd3$@4I|~a7Fq_Tr`~8@moyG3%E{H`Rdc7X^_xGZs9rJKF9OB1d zFo1sE3-euBS;6-9Hja;vTgQiohX@1$SY2Jk>+7p59^TyC;Qag?$z&3dNJMO?XB>Pd z=G@#I#>U3Pmb|R5uL}mx-pilxbGe-O=3Vke-zo?6LHuYm+QLsH5{SiOQp2UCCFpcI zxx+fHt*yc5^GR&~g1@n`A$1uX9F%AK-A?#BJ39ylgIHW#l(?p+r@=g!LnnOZ^HKi9 zpPHJ2#bOaYKf>SJ+k@BZ1#|a!Jkkf;FE1~HepGzcV}E~N_>0Hm(yMCy+3U4hP5LCC z&$sx$zP<)?V=mlN=%bx~^1&V?-qzNZ*l?x>1_oOEa~{}FJv}`b9v((_cQ;b06r4_{ z+zW@pn3$M=-ENoo$Rm54F=ew^^!E13ERi?%ChIysKQA0|9yA(_^xoOonc%bEv|24} zHXB%rySqD?N%l!76q0yHMn;5RVsf5`hK8hX$RTxBs}*jyTli;B(?_*h#pL9qEc!k; zIFKAnCX?jOJXK-b^g-XW<1BH$Syxqz>*lK0KcP5FkY-{HS`{sP(p$%_C0 literal 0 HcmV?d00001 diff --git a/static/logo.svg b/static/logo.svg new file mode 100644 index 0000000..699316b --- /dev/null +++ b/static/logo.svg @@ -0,0 +1,114 @@ + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + diff --git a/static/logo_animath.png b/static/logo_animath.png new file mode 100644 index 0000000000000000000000000000000000000000..da4533ee3695392417e3db8afc4b9852fddc1cd2 GIT binary patch literal 106600 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

~{D|}{2p(v{ zLcR0fzg%ATfKx|gQ;#p*y{KkfNyUg1)aw5ocfmcax`+MeiF0GTdRG!1cgpnI)ESmB zza>HYmn$g1=61RR#azdY6j}0qvD#e0fNFtJU!B3FJ^roPaL7S{zOVmsh)_SWz|=c zpQ=l*`8a^CvALQf9&eqh<+Z!Hd#I?Ih+k2}MhT4LC#EJ*anoF|YD2W4u21;!gPqKU z(`HSq3c~z0P^HQ#Mo0^8j4xBbbs0(C6fJqyAdh~zV zz7w!j?=&FJd6nN&ZWorW>@uFVWce>)DQsTTO_~5gq&yf`tD*5to|;^@D-PS>;ZOD%gE?;V zSK4eWZD^}qt<{mlqXiw~Pc#BfI#~!OCmYrJRaHeJ`HTdlO_B#VAqsWurj8==X~(Yl z@c_3E8PA?qZ@Ngw6Z_xXm&>+%7=Rwjbi7KfzNMBPVx&RAYHSb|$FLeR@*{WKh}fD; z5;x!)(J>OeUPt_w*$5rOqCIZRQ7>055=p>g!;b-Az_G)-ShSxprcq;^y`+{Wv8iiP zc!~c-lw^5;C-BVZ3l5n9aM#5{XusO8AG?N~uqT~5Iy8sxnTM>^?^U&9iapLqrNzSU zB1r)xI{6JyKv^>Hds_fJb;D3jy>!8H14f;DpbJt6b0X9Vgi6-&Og#}2<%tI(vb<`z zN)YN=BGMR1d6ulT-Hh;hZFS{q0Ehf@)O_EUC-QaVS&&L9I>=E8VcE~Vo?Hp3VcD;_ zj=j(kj6eGLTOZUXVR~y?EOdugge%th%L67)0HC1itF>Ncq9|od)oAB7&YMB&oxebM z&YGJNH1A6o#P{T6XWh{nr~tXDap4X_Ujhi9yX4m&{uMQIRJAEBKxPVpkwXTBIg3fD zaRUJF+;80L&RXR_nr5xx)Qe&uLq?fIl5!exBC&ef7Sihe&&D= zLq1*4c%KwiAW4TON&rNZZoc0C*#_Pv00%8A_JpO-f{R`s_S_oqF%DZ9141Uj-YfrAb=CPxc>D`{*RIH4fI2y5f}| zEoDBfxyU$4RRJ@eklk`l@+<`+r!)T>z7`A*IqsZcx3o7FNRj%Rj4N8GOJlZsVtj2+iK{q9vkVnWD`gswWleIl-yYq7NKtPf$?j?k%N|y zx^K@D4M43`$)G}#(9GJ+W2sK$86}qfU>Cmi>z;3T(F0{{9cpq_JT-O!c;TVmLG@?B(6mWO~K3^{xx>B0|74UUqt7j2Jq;| zr*rPu)x2Xi8Rv>FZ|}e4=}-URx@iqxJXQ)Dda8zm8cGDGjHD$pYb*udML=;uv6A;X zOzqvJ?_d!L&Uj`S*>9bj+jcw+dB8+cvI&ezG=f!=Nv%@uf(l}t!i2=0V4C{%m3gyO zp-k$sWc3pOm9?JoJGwgbs^W$LPs`rJH=9${$^RG1N2vA?k$@@TQt< z^r~tE(}b{&rL;c4M-QI;+dNRHMwLpX%nV8u^#z$#UOB(3It+DtV@y-Dx-6=-0+aH- z_Z+}p$6xzv!=`VXRzC@rBswpwwOU(Ik!yA5;8_g~RX_!il87WF|KupPF#m8MW8Aiz z>$+Uh8c(aJluO534UiNU9-g!MCN$OU9w|VWq@tdNUOpx_LAO4141jFdw{-?(i8be7 zyh6tILSy_=1g*4cfX2FA?A^yM2Ed1pjigxL18gE?kSmWwN4Ts8e|IrNx1nV z`Q&U%=lJ*CKKkXuv&nlQtG#KteI*~rvCdn;E?+itL*fW5*$Q)6dJDZGpEAHd#Z_@o+L9mnbTSpRF^C?THSHik4nq4t%MuC6E3jr zttQv&mAqG@8L5@BysU-snY(R8MT`w>6SJDWzVxCOHryypgyHmO{=m&|?^pIYPkwqX zSH8Se^5>maKATheP6$<%vz}Y=pbx))_=Sezw1cgdP(o`puq{;|HLDt{sjabNM0@xOiO z>UM8{_Uq@b!KdCt=NJ;?%e|qs^@8ML#6euvO%j4cFFCFDxv8o)=a~ZNUw@0|xb;zo zBMsF05w{@&mBSbjt5Bv?^3~*NTZ490G|bp=bhN4y?!EkomjUh=cIdCVucl%!%?OQ} ztt-Zr4-wncTwJNO$D&vabD+88Ym@T5RN}70d^Q4f&J6eS`HL&D*2MO;nO$A8A&96= ztI-Y9&md@OxvguIU>Y$VQq%S6T;JnoghzVD``g&oIsA7x?OTkga}e^ZccrFsbqWLx zdEUJ3j_|~uk4n?@KdP(8*hq~b5;BT`IY3R=tCKXiAw%xZ6; ze65l3Try^4%8~K$=n-hKA_)HvyRn;4RFIBqTm=#P8idlQwB3jSB8rI#7GVblpdfHKIs09|Kla`;drfh22xdEcwW{{BYrbW zRuKGB%U17~nl=D$?&;Cuy$x#w`|wA-gQ8)x$G%T_1#c-9gIUYRAQnqy7iq(20Src~ zZCS~ZH4C4*arW*RC%NkmTTJ`Caz)UN+~G>P@Bc#1_XfYZ|4COq*I?$Vitp~K@>g#S zzOR}No9811!&sY4&P6Btz^ZRN$){Fci<^Z7T+0*BzV zJqBnXB4weeWmHxZ3Ee7G;sy+vsKQs(Vw44GKm97eE^P+5=+^POm~cZ!Cf{@s0FU3% zqtqCA)c0+TP_sQ_LoczWZw;$Ru?B#kkt0x^X@1V-W9tL7yW*~m_C7vZ^leyQSEG;& z27EJNo)}}wBcrh9XWbwG6_x1|MI;ZEs&J+;52Z5cC0+zLw#)5*`ubv_Qbd+!KBm}G zfC$!FyW4uN9{ZXPl!W^v6Q60ez~YhlhjqM_0+cQ*Mtv^|KR5)K^GncT8R0OC=mg*L}Oa_oV}Z2;GX*e$Qpb~NpEr~K0GrS8<()kfJiqI&pUy_~ z5romIkb*#Yl=8d7BUEf5^gHg9Knd>3h&?^js_H z*f2{0)Dp!DJhn5}!|<~W6!78>R+??Nmgv8XW>DCz5gqvog~pR7&mMVj#*KZ>_)q@d z#T4g`YstBHA4InqM=|d7S#tWY1FFxvxAh3|WT+^sf!c}|#>7Fx{xQw1ct;&VVGlya zZ#b00SJgVk$cKOHB;be(hp=$k_4e3{Z{H)~nZre7Mdl7024Nca1JC-?WZE-CNc+~- zQ+Rax*uGx^G~Z(z7u`D6?ItfW!D{9(i#0n+u02iGS|!X?RYYWs5z}D#&uiKNeEY-C z8_hxZ#y&w|D`~uh1WG_Qyaz?HkSj$g2YBQDe%kTMyBh<0DflAz;XS_4s{UN3X5oVX zo7JuHr-RU>ky24U1Cl`-PUZvEutK-ql7P+wGYf(F0{LOZ-;kB%h@u)V+NbMwAB~2^ z#m}tqucZo_U1$)aV#)w?>1Q{g)nL_T;<$_fA_fI1uJ?-9<>_|-Oo#R4pU}5Pkc4=7 zYr<75QOQ*cjNN*`R)bCdq6r{-I*7#wifYgFFMnb#fPdpIc<0}{VTwi9?igrom(+Wa zz&ggT_U$rTk`Epkl)S;5O2Q0gY+^*gth zvqg+HoMX)?b$`94e^j_KP(NuF$`S?U+a>I;wMsxB2=v>VuI7ruC*W#_j1eXEQ+d{pcAp0(yFDWE?zbF?fx?xy+3f) z)?==lwZje9zp&#K*S*+uz}3%hHDti^jh~;tblP{{mChetUj1`()hf@bk77}*7aWEe z``ql+AyXKSgh8Xj#Trjil%yJtzUHtm`T|@#tEpVL&(w|9GNVcfIo_(_5P7B#J?k-% zqjwxRSOv!+Sv8@sl~5@X;R{KcrvdIhV(03BY+%TF)x1 zo7ck_nF^GvYR$mQhBRO`s*`2Zfg}onHT<+Cyr-pAwGKu;P3C(;{T-|1V@Z7x`32XLG_%|%BuF>cXf5Nv_Twkf+M{>Wq zR;roXxer#T>9M?JP0nvqS4w%w@7yh_f0w@7^3pab2@%9h6+6@ zDpq|fD88+vv});YE6Ts>^i%ogSN>G~`HjoVKELMYif?+as{H=YD!()t{JM{-ZxyS- zywpKS+C=@V~nLw0`BVn*g8z|&htF_c>1B93J3(SCX z?ml?g-!=(Y_~rKi9N%qNEk#c-!74!N*D7l9OHWV*(u@?FRjp@L-=03U@5=zwM)qX{#L}*s`*zMiQ(rKL<7>D7jX3j+umP<@_#48)mh0&5{M1C?xc01+j+m8cSxw>rQ zu4EX=1H4${rYfXFvi`4aN6j1oz1I}rldqSpuWDC5P=JWd9dZnIlZH#-s_V8A5OrY&(l{Br)<`WQ zTRRPkfy(Ev|5Gbh^cBC7Y|Sz*uNO22Nq&vbXmREX0Jd-O`a34Ppt7u~)RM?NIot1{ zVfd=?!g^HokKBWDK3?%jXsY-tZL-S@fb{UAFzqL7uw%Ni+YA7_E>FEje(~b?LO^cF zCn~x34vQ$V`iHChtG7Q7Akld$%zFWU&>x#!xO%JLH4m<7%RTrcYXT9uKuK1tCL1nW z72)SJr|dV+KN4X0HVOK_B($0Dv&*|dGB9=L?EBe&o`2Y&#paD4eL7SEK4PPYAP6!u zWCNowOT_}ljI0&sizHDiL&^L z)<9%I%|?aK15CN#W!jE!>4J(F9VWE~;NA;g=HJbx(QbUp1?Sy+$RP3L8u4VJ82Lic zeBavI8U*?^tZIp(C2F;XTCIs{Z4nk4BmX}C-a~FY`|g&@$DjGa-*YBlby*qH$3(Js zy1TX7LPS=psuw$(Byvy)MT(88nrzusKs8^{GDW8Y9C6WL&mC@#b>-}^YVR2{3*>#P zS~rkIQ8Hlq#UEmynhK&yMNMi2G)3wD;hNsi*cAH9`+qk)O<4 z18`E0Vf%>CLWCcKK}%6pO&MdpGse6aJ=gI2X0G#gjJ)dHY$Rq`ETIZ@c#Dpyq>)hgdv65`m;FHmI6N8GTi)Hb9 z9jIQj72wAQ!ZcP{S7Xq;k_p}+msJ3m!KLf(#_uJ=gCn^R-}*UK5Oc@&y)W=rB z&)<&ouiCaFfEf?oKVK(3`H!!3-L_S-%oBP4SL)62EHO5qpteFuE+~`n&F1+B0npZC z>dqb??VXj_Kl}r`!$02gC%jjtPp!1tPuRnZo2NAK|r-?k*0mi&_ z0vGJ_&_=$?NkWjc#O9$ioUV{SyHa9BE^WC6TiVZcOA^X-a4L%?Orqh9VWM4blyF!r+7(owMm#>iF|XjmogJf(mZTDGtGEr znn{?)P120^lBRbu-y6{3-qtSyOm08hod3Wfe^1BY6T6ShJobIjiT%#H(R*f0ug|R7>1wq` zP`MSG6-^Tx-FgLVI8_^p6+KK{-?IXTh& zM3$=t2411Nq)MPFQ)I2(8(`^*RqG`Q2$Qj}%o*&XaPl_LR}Q=&ei^*|?iYw27|XAF zmt;G)RfTkQ;J_JK!;8dI2gTx%Us9np8$1o*_sL(s2S~CY_&ZhjqpDVhF;Ogd-TX9T%5ME8iW=ygPmF8xaS<@|BYH75voR_wG z%OAS?yZ(N=y_?>>>DzXn9pCoP*z!&Pi8o4h!M9a(s8GrCRjfu0=b2JN?#Mw{_Ex|Y z7}zpTFPguPHwB>f94mKk>+{}T|Gg$wBbkKfd^2??Z+?-{=aZ4CUc3`5<{cJ`4Wo4; zRe_(<~94Dgn>UMJMg`>25H=yAtON+4gn*+RW+U|pk{vK%dR{8>mC3X zK8EbRSsD~?Rfy&O=!8Q!=zSUwV%*xcKb=K9_%o=)r1aHT8#<++|^-ntEufL zwOV-Y_?Be=liJNDza(iPcR=cI!>n)?;PgJD8>4!t5h=^wgtA43$af>StV_%dT@=Bn zsu5w<*nu5N0q(i^B6oB-{uB-B1Z^0Jgf~NBiK-UGul3PYP;!UVv;LimL1c}hI|yxb)4y zVQ!aW*Kh5wM#CV4so8ji7?UPP;8uQ988Ua$Hn6Qh1oDetO>}+sT>#zp9N)B`wBaL{ z!9fw-^m+bMDX8%h)*>d;wV;_sTC!crq2f`-`W9P(mM-b7GX~A}2W->BK6Pb1?}qQJ zcj7Jhm)9q8RKNeY4fWs1OrO48Xu<*Wj37*W5;ar@(oBaKDrl*Xd|fHMzN+MnZ>!{u zrD@*&vQi%Swo2NpQH&4Rp!&~RayQ`sr^K4HL{Tw$0$U{MyJ%nUE`S5)S=!fEZCNY% zyFc6g8U(MkO@WzWR4Pq;TqRg(_+ZRnmztk-r~Hq)1*LeT{UBX zlWA(p#QYK&9!u`UD+#1c%1i;6)P6Q+3_HLD5xO_>xh?E2_-r==VA}#80fjQ|JvkcX? zJ00KO0Q|ga!_5Ztx+&Ynua+W-OtP{wUkOny2T105t*qKzB}lvtQ0@D+t`T`BKQHkf zK(`y#ugXiq`ZbnV)n!2uRjfuH=wL)xDMq%tfBHKI0WA4xbxve{*`VCz@*^%9%mw`? z{Oar6ddV44P1plX#3SuYeO}d5G!LLUy>5Yt<^>B0+Gv;R$j&_5Z>+zV-^`BGhW!Mw zVFa}#N#sLOoo4{-1>jxy==!am*AEmrbo)a-QZKm%G1>ZGyqjUI$60NY$Uq2DNkaW? zCIk4xj*!F=mv5Bw()4{L3|K@lsR@!OKvk{A3YZ!TSYtB|q0|Y8RYj|P%9roXs_*Y$ z*2tIqYj)@i;N83oJMcdbGA`XOI9}S+x1S}1H^Y?9&r#`#>%&LgRgqmEViC0~Ei6xy zzap(vq83qWRcv4*s*(|yRdVyQxZ{+n$rGhfk}E%L<_!Vp^oixwJq@>S`^UOsyKf%M zsl2wk%q;PEJLr`QX9BXVH977QYaLlPmul!BWHY^xvC({TBzj`PJ;Vf{a}r;E>H3iM%8r-L*UpSAzEL%% zAW?hn7B%)dqJQi8cL7}g;!aF$3lD$PXH&S%g%_iE+gzB*#Z`AT(gV$m3}@71gH<-I zAx2*9FtOE#0P~()%>7+obwR{BaLV8ozw77PjX!|n2Ii{T{_T>0D+WKz>`9l0RZBfu zf+@Rn*uR+_h|VcDNJd9Ba^qIjLg1ChhjpJ1u=`0@^T42s-O=RuQ`|r3VovHYJeUMF z@{n&;2?lG)tdeK0o)Q-cl~^?r5vfGjd&g}y-woiIF}*j~Hdj?w$C3ao$&ANkZ8bba zmIK&ozpIFpq9npWIA4SsYIXL5w_UshU_`%j*2{Kvx@HnZdv%kM{oAfY`5wrR7Em%n zXCf79bu-`E69AqX)k{zAIf8%Q@*pR48^$gF%pIJ2?#{k^@!c|c`sELPJLnCfrL@Gw zdLosM;M$T0@YAX_>-NUB*dutIy-%*hOK3dSSgT({GHXVW8IQ&!9U}=elbY|hJpX9` zbNBi`KFUtJJtzSl+UrLW1wj%JichFyTBpg;PKw&T!&-WjAV^`Y`Q9b3KMLUWcuv!k z&)aC{rVa{jl-hWw=SUQMj!FU(O5u_-ni;G1Y9JXD%DISQL`aKYp4O_>JF$H6Xxo3Q zYXQu_kMSS=ZD9$Kpt?SItHiPb(WeVcY#ss4b)U=Wtjd&8L;X#$NbpBB=pN5huS0W* zOdC*EgCJIiRVg&kIFDXm?C0GC&}^<{?DmEe=l^ku&h`zmVML>p-r)s-MUM7p=FG{; zUuL}tBE4G`gP<0w)+pwOYA*f9TXs0WlIH6#RJr@@Qb64y}ma~VWwUBV-pb%lX zc-#{`@!%Eba@NQLT@bO6`P(G{?=1M*130Gh&@+vZ9T8UNr0rzIs3W7aaHJ=5HxjUE z-xeE@%qqbCdu{8E2FH3~hbHwEpvh)6Cs=ELRMq_4ichv)7kDj&TGX1;A#OcmsHm*o z;5}-it{xh%No{EYH^^v%lg7x8#>hUW_Z@Ym3VR7s5jt?7szoC5RbDDF69S3d^~Kn$ z+tYHt?GxcS{e=;!illX7VOml|mVut#rrWUN03N%e8-wneCQptCT)$85HKOT>J%;x? zvB&Us0JFwjsw3~6^&gS|*6ss}*JdqBO@KG=>$gs#=H}oo03<|IOtLByFK6py#Abh^ z1%OC4FcT1>7$kuf*PW3(^k2*Te>L17*YlEiaGJ{hDjW1fvOt;SmbF{l$gcj2NCHY4 z+!BB8M7s$a?Y#7xcMOu5F3&91RPo)C$U`hP-j|KUC37-O>|vfGVH=HlYVkyUi(iJW zUV4=su-%0K^6L1+f7*uq-wRd)4zH_srG(EsAsLI1`SmfASoK^b-eeM+DPQZXSW9S@ zY-5m=7=GR%Ur+vQUoVi8o$a$(&>qYaJFnXzlzb)l{rC3v9;}s+SppbQi^kiM)^L3Y?u9>0if?eFaGsQ07kwJ=hu9Kq$w+*9G79w$^=KP*->5^9qjqW z$UPkJ;2_`R)Ruv9A&dK`FyS!J!=zpSF_Qe&hNG#!W=1+IhE>Zgz1 z(QP)swoMwW*G)?%6Jha_&k&ZWl8VPPK{_SXh{3|YPwF{5m`471lAd+xm?mwy59{Uo zI$2dOtFBIuJhk`8JpiVS`j1k;ky=x{<{s`s^(|U__aiSAtn-aDuA1m2)@W>&iC9B1 zvHEb1%XyBFWO5Z->^e56aPPX|otC`ByZAQK@1M0e)|~m)=xC0z0I@((?N4>*!yX0j zd**HQ^D=QzC+xq&rSN7a-l<;xCn{blqXI+BBp}wgoS7(#t$M_;RF^^d%G0YfPfUFtoo9yABId$lG+#kELplS?w zwLKQ@UL?oN+dJ`i5WFiVHGpZmCjQiC+p1RfQ)!UYoAX4lh!+miM*;P(?wz>=>~S>oqf|idEkzlFajJ{#Y|_ise79knPaUMiILEtO5?+pVdq@vx1kxER>|4fN-Ysy>M*7CG=PciX47thlLU21 z!0+I*ZEYE(~m zBskU^9s7;XRv#_*T3-vZ0bn#pl~JC{t}|y;JS30{6)E?Osad+ZydA*m(uxg!zN%^+ ze&Lyk5iw;(%#SFMVV8!3!Ihq8o(DL((-3p}zt-G*9du&%;p5tLAAVO^dG$nrf1z3*<$FYY-|Fvhr4kg3hWhH!wI#ftr3Di6 z7A-DZPdC-C!Y+xphD-Ld*Jz$3d@Nx?5;+7H)p|8?@skSx65VHR@MBx@YrP`I3zbh| zUdnNU*l^u7Q33e7Y}#ON_i`GB!)G)^f@5 z6qX$4RgHyHntQygrNJ0=8%a{2ev&6nsKa5e?qTLICCY=;&)n7Hg!#d9 zez3PUqn5{rWad+n*!3hnJ|6p4CYy{24Fu;oRhFP+zfvjk*57QvDZ32iy2BS|GW;uB z&V9CV$)2r>Qw?7gNnzCn+HH|)ti%M!HP)&1E0@u*>L1Pahr7xe4P`?uLVluFRgL^D zMsHKQd8=y<`|@80{GFrgFkdZo#7KD{ zpPapKWe?Vj%2D|70fMh+E#T`!VPX`(qzc5Wl-(`C&&|(q36k!IyjztltrPUn z2hn~Qyygt=Np7{+hDIuztLmw$%Ji{)Hb|v+^!+aY@aR*o8kEBL)LW+8Ah_6@(CsqX z)IzJeqGA1#djPiIy1{zizB;vv6=2HE7k&!-BqAPUMJhEO`Y2_p6sqbms(QRtyNy*{ zp{mvfGeFi_`(G>gaRtuUgQ#OX4N|add1;+>eNT2sPSxv+sAQ3CD%SXvU8Eh7@jMA? z8GuPZ%|>@+63!Dg{IRXIo4ls^HCAO>9yI4L$<#l|PB1IrkyrAL9@ODM0ROf<(L6Bc z-1*ns^ln{l0lWe8@1(HKV~~hRJ!PlMvb!SF1}-sAx2PXF6q7X{n-gyOUF!COwu(%) zjP6pXJqt{x-NettQSsR}i7jwTPA~e}U&mZo1O0y#DfFbWNs4|;nwyg*HTAxemwlss zfmeKnE?$49?2|itG<_$S;5~0M?N`I-Jb?rm1)!KBj;tLz=d=lBJhcr_Gbu9wYBz-Y zm#zQfK}2}<^WmKSAg1?$vp+g>m)no1U%1`HMagWh>oUjA6TFYAd`ZJ?@ zzXovVLEF2dz_H#La(SRM^UT=ZYeeK;tF{=_hNe?SQ4^WjsS-C1s|Lhc-P~GRWL4j? zs;{(ce{0PRwXKW3Tmrz0^S-KQRf_?e^{WipVkF!19jsEIMpaXuk=b_+JnuVzVON~H z{u7h|ZE4eecr+~it{@eFry32R1?FpE9OS8L!m5_3>KYVZmHe>AYEcrYg!jYm2zAo} z)tNXpbQuXu->5Q1>Qq%%Z?n#Cs%E3?V=uL0Eu~G3^bKMPBY{nUtW|w3to@DM?WAV` zv}Y1;1ImU+ReP_?6F-tH8m{7@L82P1WJzXDFi=1-DxemRWC7G_bbaEe0YCef)=x^a z&Pe57dw!!1o@dczxz7BUl8jU&1Yw#YjlC&9(ugE18Q9KfbXw61b0PMh~zpJmN z{+uB8d1(*toy}96RS?|75!N-aLmO+y^&X)>&z(}>z(bIG~mSU!+BzO zcZ`ua*0NBQx`>pcp-ErVWE_;Wt*REJt=&R|<<{3}R&{3MhIJkqcU^~-0H^mI%|nCN zzk*e1c?AGv6_s^^Yl7Of7P)mTO*}x1qKRbEyJtgxmc<3Z&7v?b^-O6+WqW~yM8Q(F zy&#eXjyoe|HP}Urh*lUQZ~fNmTsr7MZvE#OfcQXlq;3&hL^K-Ut^}>0PWzh!bi4i@ zM)dz<$&cxnHD}XQ$#RI-abs;EIl};P!BBiPCPA|B&cyLol>z83#{g3|T(#(&JMjnZ zfH&}CWb++{Y31s+RIF&CLbZSwN`S6i+BJxvg>~=o`hV~^fbMo=wS4o|Utj%dx)ZPf zIqvEe{tf$_&C*5Bk}fS#AuWm*69|fy2C~f!+2toe3>4NK<@KBQ1c2TB*fcEqudjc6 zUFGRHK1*77e6p|i;P!7>^L@46Q))GlO~0dfIj2}28xW6w)?spB5hIeQ>G55i1VcXE zw{oaRVKApKs~QgVcyR-Mt~dU}7r0BIGPVm8}X_&)1cg?>_UdZ^ zPzCA-!M`Y$S_%n-x4o1Z*?wZHZvZBo`y%NIw+P^pfZxg2-~W`YNGa`%k(FVH?}r_z zVGF8chLEzF>w*L;9tv9ETm5Q}rdvKV9jH^Y$Rz-d4aO70yVLC4>&>*0Jr^C-X~?UH zIX@xtrHUlT*hEsGs>!r(YXOUlF(cBxeR=xW-Y-Ybv(pJzall^NardQq~wb%%sl;r0J5nas_VdWDWWcwP|uMNQVTW2OZjtcJ_y-4f`SQ1d_aFfP1Ro_GEir~7kg zZ>`Nwc%~8XhZ6t*e^Lj$_MtGDmzpPuB-rX44H&W&jc5`$98JLDlOVsiN{i||4PT)h zK{`*};K#E!@Z%tW?lJQR|N31!v$S$5>9Qmy8~?|;Jc5zX{92#+dmYyY#*iL)lqA~U zvq@C{%+(99gATy_^EJGF@4V*!d*3$t{lckKmzHGp8zs`5jz0TL76us9pv4WIt+?^) z-rOXl$DT;yl;0=eIDY$}C1}riKJ)hU_@tS+zuCO>_n(!^-OGKp4N^}btgf!*$)?#1 zASftg7G!EBSX0Z>p?j3ryPw!8`Go+D-bl+)wbAiAB!_f!X?i$`|I23+-xfC_nPtnkkJ)>;nN|Te_Q%qL0R?kl&EhkXhKqc zjr>McTh~5t&AyG#i8U^LNLPd#UfhX(trujz`}$XRg$cmlhYnL(!<0bHCp;mZeC(1p zUs%1gd}lT6h|)ln8o*`*O0n;wyjrqFYWAtO9#B2%*cnoLt0Hw$pqmczciPyqFB!Y# zidAdg2o*!hqgzj8^B0Bz*&fxb?K>i3Y@lRv$1|gQ4RE{Ou`xKN^U%aIV|u5L?mXmJ z5i>U786T)t)jFzp*4lD}1p=de)!Ea>^vSfV9CpE=M7`Q2{sXsl3hi+%M%HgNtp6QP zu;`0#d1y#iPVYVPur-y{Q;bMjL@FVYFVZNViG+9U)Zsm@+o0$C<#%!4 z%@=0AKC%0Ve!lfDl|U)Tgw4+)A~xJs$@ZrJBEG8DwyGUNyebNJqB8E>r?YuL{k)454owOe?ex$lW#-7glAKNZy4fjc+VRf`u=wTehrJnTo0 z^y$eO0;s4^jgq3U{v-C5rDr5XHflM|zCH-q|DOopU%T^J{Pe{H(&c$%UAI&twVS+} zOWAzKc)M!&fuy>>ia+8gyl&Gsne#LK$i;Z4jurv+|J`hVmVWX8m8-TCwZRTI zIU^6jdYxb}DJZOaABT46;vMzxmDM-wL$cpHq(>e@qU#^4>JD6N8Q8WOUd-d{1%AEP zOBuARTH2Lc#O8?8YtC)kBhv7N8b%k@O){xoLLYu*k3^8Iz36)#8mXPQLqY-C%=ekP zv$xSc+a2HbS-5ZTdi%YXZv9!gj9BTjbNW}`Pw+S?LY;)Zv}X}Lrtj*#4{+p1zRcLg z`^%EYhv)a^`<3sR(yFEA=gRNo<|9{B|DNBwYQuU{st{EvY>>b5lv`U= z0gO9ymg)Gwp|1Q@U1dO&P1n9zmRJx(R62Bt1q1=L^>CPkP;B-kakIx zZb3?7K}m@vL^@pFApxo6Iq*-k)uS@K%kRq~?q$2~ru)s>PB zDl?AxT-8Cu^|n=;wJwyfK$Zm>xmK0^1^uwb_cYekyuoyPf@ZIIDVWgQn+j0!VG^H- zVBl<5#jGW_t^fAxeUD2!c5yxRiCq&+`Oc;=EmMpo#I%@+%%G{GlKH*luWD=ypwx{N zM(wZt!tGzEQD&xUkP$ZNpnS7_#iokqP7z%u4KH__Hdu;ymXPl($>SXMgP9+E9}Csd zOcIiPkh=z*d?i*qtxCtXia_*X)w*Fyd%joZHXe3+V9GLsu>~5NLLO69+i}&XsduX4 zg49>Qf#7Nso1#syr5UON|Ct1@S&_wYxd0!vbc9)}owe!yW_PKPKGFg%z;2>_sB&~` zNL`Ov`Q}UEiSttV)P-6J`vZsK&3mBQg%dfM2r&;f(=Dqql5zRI3vL$i3$~t zi9vTY_WZZxfPhKc6vP|ngyrIpWffm)DRS9;f$=c`-Z)0p$=z?2a6i4GCmnidxr7%o z4l!XO0po!lPAPO&ZnN~;yFTN7^l50UpEcSU8T?i0JQjOrrKL3O>`s|rjs5*PTK!k3 z=R3Ob!;jdQ+?=z~ESfkEVhU-Qnce?w;kM0tW&-D#YPMeb7=dp}ZL6L)3CIke%vr{_w`w zm&Mn&2WE(BBH#CBo7(L$c0PO7IP`lB^4t7u2m9D^iHA{4w2OBLN(;A<(;wz3erv=- zk#ds_z#Ri9+OYp{cjmZsk#4VMxh%R#UAPzO#f>+1q@=pnnHawd!MGeBAM6WGc_G5~ zr+mK;-Gswa{WIKLv`hIYj%dLj_j5y^0J7C^7c2R#KVAWlb$Dlz^{T)&x)(dxcZY_` zWolNXPj@}PXFEqnM3h4G!B#U^$|aETxUmq_!{{}TF=Blbq6PpYq*(oO6Vnz|cp_BK zN&gpR8_iq290xyzrJrpJgZMCh+c{<|EkCt14J-cC=KGiRm{y)IpB!0#deZ!UT>j|D z=JTtbfWAhLS(d%)&fmtIH-Z=B(UV8`HJ=&}o={!{dXW!7gAh@PN58}I1x-!4JFAz| zf|=EB#B*&D*5qGn*iLPGrM}Csf7hSk;(O)}A@?o6ek5~f&FU0F<5fX+wwl+{Y(lwX zgd?T3zN*k=t7v(vx-_ojD)zF;0NJJcCiIO97wI<@`58{)D-dW+fhWsg=sT{t znz)BvHp#pjpJent${D|dRpwg0j5C|4-tdc0P%Ah}i8BH1_~iU***{-LS21n}0w$D| zv886ZslZqBiyiE0mom$3cjDOmkJfKS8)|}7N61;9X6qw#S)H^uDS_^;Ib1@BpWA#b zNo8TFqsOy`&g;z0%?Qr6H{s@k{6t&*6HZUfF2oM^?FJQRr7?u;b%4GQZEfcj%^c-a z7(?PnzU(^~C9#s*WNd)dra1k}vYO%!+MuqTxmSZ~jI(Ex!ZYDM>L=%$xq`xq`Y050 z))^t+7%n5sXoao+ktX@}uPd_S>o9>2A&r>8n5c@({uR8<6i@4JX3Y)$1-o0!90dCw zMe?18Wn&s_&0TGX5J9{i6~e&`Efn+VqVu@iI_CnM?7rMRIE7Y&)w z<4dWnHhwcW&NqlOt+JbRC=G&hA|L*gBnK~fw!Aoh${0xT^)RXOfv8QQv}QBj{R(gY ziFsE4e%9gjg48y(i)xAW^`>xwWOr#>iL4su85;2S?KF( z&3|AO3ZMyEa|6{O!pbLKJx{2;78O^s=sKnf~)5Hpx zByK#U<&!$aZ)@NAF|*w)NIe=JMaQ;chB+ncdc+vpDw6IgF*Ffw`)zfv4=EzrfE|K# z^*ChlW9))u^J23(G$1;7Nep@7=EKHgYj(N*Uv#bgFWlSeMSgvkGN^0bp0H;K{$yc0 zJ421sXLMB=d1v%P##^bjHBfnX!3l;t?8wH=QCQId-DBHFUjABq6tva&j|3b+G2g_C z2c?!Gq~eNhCBNjzzfgM9GUjF^J z_f1=fMAyIaPlv3BxK-dHMa*o*N%`KCC%yNx2R;^&TwN9!fzm~&fwSirOI5j{myw` zoXf?Qz%UzDiqq6`M3aS}Q-956Gkptf>E;q!zZcUwTEC{rhzypT5vXVm^?S|mi}*tM ziqb~7&uTi=t+NqX%5Ji0i>a??y4hFz_#dM1Ir;I8aq~(Cb#;S-YvF9O`~?hM8>m}g zTM+lFs_mk6mY}saID9pEC)G znh}5KLwofS$>WWbSs5V1%TvItv3oPH8~0Qf0N83aaW}tn9v6-wF??@D24wNeAQaT< zK2X&F3Rc0zj!Y=w)Sa!yOVGQ0nrGDLC!O;2b745(HMa%Q!oy7ZS>zh;0^<91!K!9{ z)#m0DJYO_f@zxRXEb%z@g+yD4L!1CK9aicj`jQ7up;h_V7-Rb7iy#lfy> zk*Ev+O{7dn*$+Zgd?9pA=vE^TFjrmwX8Mrwq?Xpu)`k>Ie-96!X~`tQ-3k#cf+V^q z9B=RT79I}x;%C0S;4UgGoL*{V*m!4ap)CBED83~nPd*=4qYjnxifKQ$_`u<8Ob(-c zF~p-*iBf1wMtKXjK}@%E>>4{}vV265eRm}@b8`a$l3iW%YfHmvt7TVX613nv`b$xA z2*FHH<)aSq5S2S$W$2 z8U>V8Id!5JWF-x1a8iYPX4-T#iSs2oU>)(*F6{W^fvP`2N40-v;}eA?KgsL$94~6p zE%Wl??o--pH!ts}pfO?ZuOGJr`5aG3ySaGT$oP5KXx5H1#?qW@e5FC&g>BXM(7fTuZ|Cx? zsbJsmWa`iKKv&;`EDG#?K#+xqQ32Ov35I%4i4$VLxN1U4q2C^JxXx)T zcazsp?HdSF8zW^MCdFTRA~(G4RkyIEZgp}ox+;o0^9{E&$Qnq>j62aqdp*h46{|2e z0Cuqna)Bi`Q4OiN5H0Njc{sgq*7WY@oh>w;=Y~jdrdi+m5%7IsS`g_o09)*>@TyfM z`6QRvIcod_EA~Cdfx2e;iRN};XRWW2nW=5SxL}E%N=87Dg!?6HzltVUiJl#bFFF2{ z_9y$Z93Bv`4Y9VVNBM(iE#evN)l^vO0c zSwP7|G-7${7zW^G>LPo|_c4J&WjMABj){m4@UV$9gSLmdTny+VMwYVDFAhtFVcyKa zu3q0;$9#2^^dvFgA9eNgIIskelT>K#;$lSzN}`*&F2)yM#sIlD_onFKz1A;d-+%7g zG!8#plu2gt=Zh?juezj$;UYjq_A_K=YvNtQ_v}P9c742?C`S-=r6J|5+=Rp{HqOE^ z)iq%#azB61?e&>*Z_(iNZx>==@RGh%=^CFMFO2rUoszFaC8LDU-NBJ-QcQs8>FHE4 zqBe!dwecuK;%J*c0~Y2*bh$L&Ff`K+%IEUyeJ-+&OCg=b6Fq%8HBshpJ{nxC^0 zETo=TkC5k@jn{c~ja57IfRy0C-&SqgZ5n6mxd85aq>wn^c<;xTC&Bv|biApjt0uw~Az@$5$d<>rpGK>)suw>*{JB+88tb zOizp^NZf=!Hd4eZA02a*iuY)(ky;Y%>?Z$)a5vBqV1Wj6Lx{Up0Ej*z0C%b`=hBpt zYA`?`69Z!B-b*ypOKrKIQkU25-}z|F zHy}ZG5`Fo2XL_xlJd;&!A|emcixl_$KW*CLf(wpp@^F?u_JTK0{4v8gFjeSehw}(X zLb=HDL)38VJqkJv{1n+cHz4;yZ{cZ;rYZg)yFW`L`gWbKw&+iI!fA+A=Z6@Y8soLa zQpeUrfC2%kH(_4KGY zlJs1OzF9uR%BDFwLK`QLfv685plu7XDI^r%5{@9Wrnn7Df0{c7FVmmaHhG6biKn#EgAJ zjY~=t9=f=WUpoJvu3HD$3&{11l3IqaYLvw!)kwiT@GC76!K_*^^!}tE`zpc|uJ=l0 za8v&uo~^HIfHYQxbb!GI8)s9vG072<+3Oe?wjiV37x$CvITzF-$SF!nvry_@Ri6j) zdc(~8!Jk-t+2wmqcDzSRaHh81qyoDDMY_lyRk)ho(N#4-(1g6llq7;ewv5WyoH?>( zyi!BG*5_a6z>({|G$Scd<6{i(6!=MTO$8Vww&#G{*gFef1e9a70c3>UiN4dFCaa`c zVDNaEW~-_E*;M0Sek$h9l6cMFPp$@^9Gi19`Z z=uxX;bi_7dN(=6mjyrBO0Hgzh(xyKCRpYjkTn5gVb^?C@-{=pV8e(rs{WbEFdD%2$bm@HF_lPIFM4 zkbI<|6F|jH7Lmgxk1>E`K7(`qDhpcfjh~U3JsDY7OH}llHuL&Nhj2CPT&u^2^J00MK$YF)&&aH5QDM#~@gf^&v#g=i;R%ce^H4gu$>O#&AW zfmrEnZ|%|8uEbH4V>`f{J8w>=4`^w_wTGkmv;-MUULR~eU9~=z#2;E-=qQ^i_^W_D z1su4$rw-)5R133Kw`lYfZWo{m2nc#%)2^O>M?KFv z_am!gsrR<2Siy3HBJs&nWBCs*l9bT|#n55BO7L&wbLme{BaX+$Zp=q2g?XA1x(|;g zPS5_Up_A1@U7?ytOW$Z_469~+&FCiisj(h@Gcy^JtRP#?OUIGxHh85Ks4ve~{I;74 zo2SzMHTw0<9ypW#I)Z`q74WtAR_;8PtmxI8TqvdBd9gAdGm?<}Q%zPx ze=$Pm2v5`v_&aM7)j?E&=Td+3;SQk7d_l<^!57E`jq;n7>EP>^(~a*We)9<=Doo-N;HYQ9^46^lp+%{gzXBT zomc|@k1!_Ed4pOKg&ks)ino(O8^WtU)m6w&95L^mJvX|)&>5PZh{=6pZg&fu?c z!%!_x{}`x0B*APd{$u#!;YV$KP=lEW8&-5RRlm(PM><}vl54Ungn0VtwR?-7=)}Ou z#iIr9pglarN48d7gN= z6eL(0WK~9I{Udb6uVTZqbn4l^bfthjMIW03sFKajEW7Aj2L*yrcN$p*xO&w+*&!DB z9XE;^{DMHIC%EL$-lc35C>idejrs5WHB=PgL+x~n! z+BcRLQkySI!kf{e6Ntgjkl^f&unw{GvkzwH>lt446HiU?u*zKmqv!qT_Kp?qXcTfJZq4*)9-nlFoifMSu9h$uU4Vy=Jvhf6ZUqaot z89{pWdCKI(3AnFi+No{046zsk06hU zMWDZo=EAM>NV5;|d>|kIygU6ln!7fi!q*F&ieWdp)1U(6Ddm6_ zN~jV3s|Wn#g3P~H!~9yVb8nNas9)h&do~>|9$Zy(LmE`)=`82$lA2rmA9J4tZ$o_N zCVhOdtMx#?$%pdt>BL|IL}IjOtpREOKMRSUu| zR4@C^57|4B!Ak-IxBN30xCIy9q%IZ6*!hE|v6#~{HEAoR-BlwA>~(vBcWyaY)3 zCJZmAz#$`>)wXSQfo1zid@?@mZ&DxFL4C!Kt?;{aVu5k(tbYLMRB787+sCueUvK#J zX~XdrkH*nYjUHYRfexOFkzR8pC7$vtYp8yNPwY>;$Mws@?q3o+F-TzfajI#*K5JYdU< z2vOmDU6^Jhl2q2Fw}#xsoc3y-{VvXd^1C0}|CHkIx@OVn+GKgE3HaO%QH!ViBR$3n z|l%=T-F@SroyvTZ`S#b%qpxP)YrZ~ zBN&0=6r!Itxm$E-Tv@0?xfTk}`&OwTu#5M$^VQcT79_W#TicQ4#L)c{AXsLPIwntv zL+5gw(9txo8sZ4G>0&-g#sDUdO{;S5+rOSxE^exUU~olovc<&vS`vG6r+CR1fpJ{m zfwW!@A8s3dTye)vCqKj~%KtAb7psRJInA3TfxSe13}Dg_Ce-vFG0UXOA~@m;V5l!KD*HX P;F^kphJ5)0i>LnwUcrUQ literal 0 HcmV?d00001 diff --git a/static/style.css b/static/style.css new file mode 100644 index 0000000..5c8d3ff --- /dev/null +++ b/static/style.css @@ -0,0 +1,47 @@ +html, body { + height: 100%; + margin: 0; +} + +:root { + --navbar-height: 32px; +} + +.container { + min-height: 78%; +} + +.inner { + margin: 20px; +} + +.alert { + text-align: justify; +} + + +footer .alert { + text-align: center; +} + +#navbar-logo { + height: var(--navbar-height); + display: block; +} + +ul .deroule { + display: none; + position: absolute; + background: #f8f9fa !important; + list-style-type: none; + padding: 20px; + z-index: 42; +} + +li:hover ul.deroule { + display:block; +} + +a.nav-link:hover { + background-color: #d8d9da; +} diff --git a/templates/base.html b/templates/base.html new file mode 100644 index 0000000..cb92dd2 --- /dev/null +++ b/templates/base.html @@ -0,0 +1,234 @@ +{% load static i18n static getconfig %} + + + + + + + + {% block title %}{{ title }}{% endblock title %} - Inscription au TFJM² + + + + {# Favicon #} + + + {% if no_cache %} + + {% endif %} + + {# Bootstrap CSS #} + + + + + {# Custom CSS #} + + + {# JQuery, Bootstrap and Turbolinks JavaScript #} + + + + + + {# Si un formulaire requiert des données supplémentaires (notamment JS), les données sont chargées #} + {% if form.media %} + {{ form.media }} + {% endif %} + + + + {% block extracss %}{% endblock %} + + +

+ +
+
+
+
+
+ + 𝕋𝔽𝕁𝕄² — + Nous contacter — + + {% csrf_token %} + + +
+
+
+ Ce site a été conçu pour Animath, avec amour et passion. Il est récent et il est possible que + certaines pages ne fonctionnent pas correctement. Si vous remarquez des bugs, merci de les signaler + à + l'adresse contact@tfjm.org.
+ © {{ "TFJM_YEAR"|get_env }} Tournoi Français des Jeunes Mathématiciennes et Mathématiciens +
+ +
+
+
+ + + +{% block extrajavascript %} +{% endblock extrajavascript %} + + diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..9455dc1 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} + +{% load getconfig %} + +{% block content %} + {% autoescape off %} + {{ "index_page"|get_config|safe }} + {% endautoescape %} +{% endblock %} diff --git a/tfjm/settings.py b/tfjm/settings.py index 2f7d9a8..6031984 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -144,3 +144,11 @@ LOCALE_PATHS = [os.path.join(BASE_DIR, "locale")] # https://docs.djangoproject.com/en/3.0/howto/static-files/ STATIC_URL = '/static/' + +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, "static"), +] + +MEDIA_URL = '/media/' + +MEDIA_ROOT = os.path.join(BASE_DIR, "media") diff --git a/tfjm/urls.py b/tfjm/urls.py index 1a5069e..40e28d8 100644 --- a/tfjm/urls.py +++ b/tfjm/urls.py @@ -13,9 +13,19 @@ Including another URLconf 1. Import the include() function: from django.urls import include, path 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ +from django.conf import settings +from django.conf.urls.static import static from django.contrib import admin -from django.urls import path +from django.urls import path, include +from django.views.generic import TemplateView urlpatterns = [ - path('admin/', admin.site.urls), + path('', TemplateView.as_view(template_name="index.html"), name="index"), + path('i18n/', include('django.conf.urls.i18n')), + path('admin/doc/', include('django.contrib.admindocs.urls')), + path('admin/', admin.site.urls, name="admin"), + path('accounts/', include('django.contrib.auth.urls')), ] + +urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) +urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) From 93735da1a40dc63b6674be135dd4533510ff1c73 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 07:55:06 +0200 Subject: [PATCH 008/132] Login is possible --- requirements.txt | 4 +-- templates/base.html | 9 ++----- .../email_validation_complete.html | 15 +++++++++++ .../email_validation_email_sent.html | 7 ++++++ templates/registration/logged_out.html | 10 ++++++++ templates/registration/login.html | 25 +++++++++++++++++++ .../registration/password_change_done.html | 9 +++++++ .../registration/password_change_form.html | 13 ++++++++++ .../registration/password_reset_complete.html | 12 +++++++++ .../registration/password_reset_confirm.html | 17 +++++++++++++ .../registration/password_reset_done.html | 10 ++++++++ .../registration/password_reset_form.html | 13 ++++++++++ templates/registration/signup.html | 22 ++++++++++++++++ tfjm/settings.py | 11 ++++++++ 14 files changed, 168 insertions(+), 9 deletions(-) create mode 100644 templates/registration/email_validation_complete.html create mode 100644 templates/registration/email_validation_email_sent.html create mode 100644 templates/registration/logged_out.html create mode 100644 templates/registration/login.html create mode 100644 templates/registration/password_change_done.html create mode 100644 templates/registration/password_change_form.html create mode 100644 templates/registration/password_reset_complete.html create mode 100644 templates/registration/password_reset_confirm.html create mode 100644 templates/registration/password_reset_done.html create mode 100644 templates/registration/password_reset_form.html create mode 100644 templates/registration/signup.html diff --git a/requirements.txt b/requirements.txt index d475dc3..8cc9947 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ chardet==3.0.4 defusedxml==0.6.0 Django~=3.0 django-allauth==0.39.1 -django-crispy-forms==1.7.2 +django-crispy-forms==1.9.0 django-extensions==2.1.9 django-filter==2.2.0 django-polymorphic==2.1.2 @@ -19,7 +19,7 @@ requests==2.22.0 requests-oauthlib==1.2.0 six==1.12.0 sqlparse==0.3.0 -djangorestframework==3.9.0 +djangorestframework==3.11.0 django-rest-polymorphic==0.1.8 urllib3==1.25.3 psycopg2-binary==2.8.4 diff --git a/templates/base.html b/templates/base.html index cb92dd2..d17aac9 100644 --- a/templates/base.html +++ b/templates/base.html @@ -152,25 +152,20 @@
- {% if user.is_authenticated and not user.profile.email_confirmed %} -
- {% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %} -
- {% endif %} {% block contenttitle %}

{{ title }}

{% endblock %}
{% block content %} diff --git a/templates/registration/email_validation_complete.html b/templates/registration/email_validation_complete.html new file mode 100644 index 0000000..b54432f --- /dev/null +++ b/templates/registration/email_validation_complete.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} +{% load i18n %} + +{% block content %} + {% if validlink %} + {% trans "Your email have successfully been validated." %} + {% if user_object.profile.registration_valid %} + {% blocktrans %}You can now log in.{% endblocktrans %} + {% else %} + {% trans "You must pay now your membership in the Kfet to complete your registration." %} + {% endif %} + {% else %} + {% trans "The link was invalid. The token may have expired. Please send us an email to activate your account." %} + {% endif %} +{% endblock %} diff --git a/templates/registration/email_validation_email_sent.html b/templates/registration/email_validation_email_sent.html new file mode 100644 index 0000000..bd4cf8d --- /dev/null +++ b/templates/registration/email_validation_email_sent.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} + +{% block content %} +

Account Activation

+ +An email has been sent. Please click on the link to activate your account. +{% endblock %} \ No newline at end of file diff --git a/templates/registration/logged_out.html b/templates/registration/logged_out.html new file mode 100644 index 0000000..3b044b7 --- /dev/null +++ b/templates/registration/logged_out.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +

{% trans "Thanks for spending some quality time with the Web site today." %}

+

{% trans 'Log in again' %}

+{% endblock %} diff --git a/templates/registration/login.html b/templates/registration/login.html new file mode 100644 index 0000000..64c5c26 --- /dev/null +++ b/templates/registration/login.html @@ -0,0 +1,25 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-2.0-or-later +{% endcomment %} +{% load i18n crispy_forms_filters %} + +{% block title %}{% trans "Log in" %}{% endblock %} +{% block contenttitle %}

{% trans "Log in" %}

{% endblock %} + +{% block content %} + {% if user.is_authenticated %} +

+ {% blocktrans trimmed %} + You are authenticated as {{ user }}, but are not authorized to + access this page. Would you like to login to a different account? + {% endblocktrans %} +

+ {% endif %} +
+ {% csrf_token %} + {{ form | crispy }} + + {% trans 'Forgotten your password or username?' %} +
+{% endblock %} diff --git a/templates/registration/password_change_done.html b/templates/registration/password_change_done.html new file mode 100644 index 0000000..150a00e --- /dev/null +++ b/templates/registration/password_change_done.html @@ -0,0 +1,9 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +

{% trans 'Your password was changed.' %}

+{% endblock %} diff --git a/templates/registration/password_change_form.html b/templates/registration/password_change_form.html new file mode 100644 index 0000000..01133e4 --- /dev/null +++ b/templates/registration/password_change_form.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n crispy_forms_tags %} + +{% block content %} +
{% csrf_token %} +

{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}

+ {{ form | crispy }} + +
+{% endblock %} \ No newline at end of file diff --git a/templates/registration/password_reset_complete.html b/templates/registration/password_reset_complete.html new file mode 100644 index 0000000..bb91a3c --- /dev/null +++ b/templates/registration/password_reset_complete.html @@ -0,0 +1,12 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +

{% trans "Your password has been set. You may go ahead and log in now." %}

+

+ {% trans 'Log in' %} +

+{% endblock %} diff --git a/templates/registration/password_reset_confirm.html b/templates/registration/password_reset_confirm.html new file mode 100644 index 0000000..5db0e81 --- /dev/null +++ b/templates/registration/password_reset_confirm.html @@ -0,0 +1,17 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n crispy_forms_tags %} + +{% block content %} + {% if validlink %} +

{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}

+
{% csrf_token %} + {{ form | crispy }} + +
+ {% else %} +

{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}

+ {% endif %} +{% endblock %} diff --git a/templates/registration/password_reset_done.html b/templates/registration/password_reset_done.html new file mode 100644 index 0000000..a215ab9 --- /dev/null +++ b/templates/registration/password_reset_done.html @@ -0,0 +1,10 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n %} + +{% block content %} +

{% trans "We've emailed you instructions for setting your password, if an account exists with the email you entered. You should receive them shortly." %}

+

{% trans "If you don't receive an email, please make sure you've entered the address you registered with, and check your spam folder." %}

+{% endblock %} diff --git a/templates/registration/password_reset_form.html b/templates/registration/password_reset_form.html new file mode 100644 index 0000000..61adaa9 --- /dev/null +++ b/templates/registration/password_reset_form.html @@ -0,0 +1,13 @@ +{% extends "base.html" %} +{% comment %} +SPDX-License-Identifier: GPL-3.0-or-later +{% endcomment %} +{% load i18n crispy_forms_tags %} + +{% block content %} +

{% trans "Forgotten your password? Enter your email address below, and we'll email instructions for setting a new one." %}

+
{% csrf_token %} + {{ form | crispy }} + +
+{% endblock %} diff --git a/templates/registration/signup.html b/templates/registration/signup.html new file mode 100644 index 0000000..76f88a4 --- /dev/null +++ b/templates/registration/signup.html @@ -0,0 +1,22 @@ + +{% extends 'base.html' %} +{% load crispy_forms_tags %} +{% load i18n %} +{% block title %}{% trans "Sign up" %}{% endblock %} + +{% block content %} +

{% trans "Sign up" %}

+ +
+ {% blocktrans %}If you already signed up, your registration is taken into account. The BDE must validate your account before your can log in. You have to go to the Kfet and pay the registration fee. You must also validate your email address by following the link you received.{% endblocktrans %} +
+ +
+ {% csrf_token %} + {{ form|crispy }} + {{ profile_form|crispy }} + +
+{% endblock %} diff --git a/tfjm/settings.py b/tfjm/settings.py index 6031984..10de9de 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -43,6 +43,13 @@ INSTALLED_APPS = [ 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'django.forms', + + 'polymorphic', + 'crispy_forms', + 'django_tables2', + 'rest_framework', + 'rest_framework.authtoken', 'member', 'tournament', @@ -152,3 +159,7 @@ STATICFILES_DIRS = [ MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, "media") + +CRISPY_TEMPLATE_PACK = 'bootstrap4' + +DJANGO_TABLES2_TEMPLATE = 'django_tables2/bootstrap4.html' From eead3852188dd2782cb99f309e80ee6769babc53 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Wed, 29 Apr 2020 15:29:01 +0200 Subject: [PATCH 009/132] Login is possible --- apps/member/forms.py | 39 ++ apps/member/models.py | 6 +- apps/member/urls.py | 10 + apps/member/views.py | 11 +- apps/tournament/models.py | 5 +- locale/fr/LC_MESSAGES/django.po | 358 +++++++++++++----- .../css/datepicker-widget.css | 121 ++++++ .../js/datepicker-widget.js | 55 +++ templates/amount_input.html | 11 + templates/autocomplete_model.html | 9 + templates/base.html | 2 +- .../date_picker.html | 6 + .../bootstrap_datepicker_plus/input.html | 4 + .../time_picker.html | 6 + templates/colorfield/color.html | 8 + .../mails/email_validation_email.html | 15 + templates/registration/signup.html | 7 +- tfjm/inputs.py | 325 ++++++++++++++++ tfjm/urls.py | 3 + 19 files changed, 904 insertions(+), 97 deletions(-) create mode 100644 apps/member/forms.py create mode 100644 apps/member/urls.py create mode 100644 static/bootstrap_datepicker_plus/css/datepicker-widget.css create mode 100644 static/bootstrap_datepicker_plus/js/datepicker-widget.js create mode 100644 templates/amount_input.html create mode 100644 templates/autocomplete_model.html create mode 100644 templates/bootstrap_datepicker_plus/date_picker.html create mode 100644 templates/bootstrap_datepicker_plus/input.html create mode 100644 templates/bootstrap_datepicker_plus/time_picker.html create mode 100755 templates/colorfield/color.html create mode 100644 templates/registration/mails/email_validation_email.html create mode 100644 tfjm/inputs.py diff --git a/apps/member/forms.py b/apps/member/forms.py new file mode 100644 index 0000000..6a9449f --- /dev/null +++ b/apps/member/forms.py @@ -0,0 +1,39 @@ +from django.contrib.auth.forms import UserCreationForm +from django.utils.translation import gettext_lazy as _ + +from member.models import TFJMUser + + +class SignUpForm(UserCreationForm): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self.fields["first_name"].required = True + self.fields["last_name"].required = True + print(self.fields["role"].choices) + self.fields["role"].choices = [ + ('', _("Choose a role...")), + ('participant', _("Participant")), + ('encadrant', _("Encadrant")), + ] + + class Meta: + model = TFJMUser + fields = ( + 'role', + 'email', + 'first_name', + 'last_name', + 'birth_date', + 'gender', + 'address', + 'postal_code', + 'city', + 'country', + 'phone_number', + 'school', + 'student_class', + 'responsible_name', + 'responsible_phone', + 'responsible_email', + 'description', + ) diff --git a/apps/member/models.py b/apps/member/models.py index 197d9c1..03e4003 100644 --- a/apps/member/models.py +++ b/apps/member/models.py @@ -1,3 +1,6 @@ +import os +from datetime import date + from django.contrib.auth.models import AbstractUser from django.db import models from django.utils.translation import gettext_lazy as _ @@ -38,7 +41,7 @@ class TFJMUser(AbstractUser): ("female", _("Female")), ("non-binary", _("Non binary")), ], - verbose_name=_("address"), + verbose_name=_("gender"), ) address = models.CharField( @@ -132,6 +135,7 @@ class TFJMUser(AbstractUser): ) year = models.PositiveIntegerField( + default=os.getenv("TFJM_YEAR", date.today().year), verbose_name=_("year"), ) diff --git a/apps/member/urls.py b/apps/member/urls.py new file mode 100644 index 0000000..ac94b3b --- /dev/null +++ b/apps/member/urls.py @@ -0,0 +1,10 @@ +from django.urls import path + +from .views import CreateUserView + + +app_name = "member" + +urlpatterns = [ + path('signup/', CreateUserView.as_view(), name="signup"), +] diff --git a/apps/member/views.py b/apps/member/views.py index 91ea44a..240250c 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -1,3 +1,10 @@ -from django.shortcuts import render +from django.views.generic import CreateView -# Create your views here. +from .forms import SignUpForm +from .models import TFJMUser + + +class CreateUserView(CreateView): + model = TFJMUser + form_class = SignUpForm + template_name = "registration/signup.html" diff --git a/apps/tournament/models.py b/apps/tournament/models.py index 1e7500b..36bf5f5 100644 --- a/apps/tournament/models.py +++ b/apps/tournament/models.py @@ -1,4 +1,5 @@ import os +from datetime import date from django.db import models from django.utils.translation import gettext_lazy as _ @@ -58,7 +59,8 @@ class Tournament(models.Model): ) year = models.PositiveIntegerField( - verbose_name=_("year") + default=os.getenv("TFJM_YEAR", date.today().year), + verbose_name=_("year"), ) @classmethod @@ -117,6 +119,7 @@ class Team(models.Model): ) year = models.PositiveIntegerField( + default=os.getenv("TFJM_YEAR", date.today().year), verbose_name=_("year"), ) diff --git a/locale/fr/LC_MESSAGES/django.po b/locale/fr/LC_MESSAGES/django.po index 456aeff..77477e2 100644 --- a/locale/fr/LC_MESSAGES/django.po +++ b/locale/fr/LC_MESSAGES/django.po @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: TFJM2\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2020-04-29 04:43+0000\n" +"POT-Creation-Date: 2020-04-29 06:24+0000\n" "PO-Revision-Date: 2020-04-29 02:30+0000\n" "Last-Translator: Yohann D'ANELLO \n" "Language-Team: fr \n" @@ -22,328 +22,514 @@ msgstr "" msgid "member" msgstr "membre" -#: apps/member/models.py:15 +#: apps/member/forms.py:14 +msgid "Choose a role..." +msgstr "" + +#: apps/member/forms.py:15 +msgid "Participant" +msgstr "Participant" + +#: apps/member/forms.py:16 +msgid "Encadrant" +msgstr "Encadrant" + +#: apps/member/models.py:18 msgid "email" msgstr "Adresse électronique" -#: apps/member/models.py:23 apps/member/models.py:196 apps/member/models.py:209 -#: apps/member/models.py:230 apps/tournament/models.py:132 -#: apps/tournament/models.py:152 +#: apps/member/models.py:26 apps/member/models.py:214 apps/member/models.py:230 +#: apps/member/models.py:255 apps/tournament/models.py:147 +#: apps/tournament/models.py:167 msgid "team" msgstr "équipe" -#: apps/member/models.py:29 +#: apps/member/models.py:32 msgid "birth date" msgstr "date de naissance" -#: apps/member/models.py:37 +#: apps/member/models.py:40 msgid "Male" msgstr "Homme" -#: apps/member/models.py:38 +#: apps/member/models.py:41 msgid "Female" msgstr "Femme" -#: apps/member/models.py:39 +#: apps/member/models.py:42 msgid "Non binary" msgstr "Non binaire" -#: apps/member/models.py:41 apps/member/models.py:48 +#: apps/member/models.py:44 +msgid "gender" +msgstr "genre" + +#: apps/member/models.py:51 msgid "address" msgstr "adresse" -#: apps/member/models.py:54 +#: apps/member/models.py:57 msgid "postal code" msgstr "code postal" -#: apps/member/models.py:61 +#: apps/member/models.py:64 msgid "city" msgstr "ville" -#: apps/member/models.py:68 +#: apps/member/models.py:71 msgid "country" msgstr "pays" -#: apps/member/models.py:76 +#: apps/member/models.py:79 msgid "phone number" msgstr "numéro de téléphone" -#: apps/member/models.py:83 +#: apps/member/models.py:86 msgid "school" msgstr "école" -#: apps/member/models.py:89 +#: apps/member/models.py:92 msgid "Seconde or less" msgstr "Seconde ou inférieur" -#: apps/member/models.py:90 +#: apps/member/models.py:93 msgid "Première" msgstr "Première" -#: apps/member/models.py:91 +#: apps/member/models.py:94 msgid "Terminale" msgstr "Terminale" -#: apps/member/models.py:102 +#: apps/member/models.py:105 msgid "responsible name" msgstr "nom du responsable" -#: apps/member/models.py:109 +#: apps/member/models.py:112 msgid "responsible phone" msgstr "téléphone du responsable" -#: apps/member/models.py:115 +#: apps/member/models.py:118 msgid "responsible email" msgstr "email du responsable" -#: apps/member/models.py:121 apps/tournament/models.py:33 +#: apps/member/models.py:124 apps/tournament/models.py:34 msgid "description" msgstr "description" -#: apps/member/models.py:127 +#: apps/member/models.py:130 msgid "admin" msgstr "administrateur" -#: apps/member/models.py:128 +#: apps/member/models.py:131 msgid "organizer" msgstr "oragnisateur" -#: apps/member/models.py:129 +#: apps/member/models.py:132 msgid "encadrant" msgstr "encadrant" -#: apps/member/models.py:130 +#: apps/member/models.py:133 msgid "participant" msgstr "participant" -#: apps/member/models.py:135 apps/tournament/models.py:61 -#: apps/tournament/models.py:120 +#: apps/member/models.py:139 apps/tournament/models.py:63 +#: apps/tournament/models.py:123 msgid "year" msgstr "année" -#: apps/member/models.py:139 apps/member/models.py:172 -#: apps/tournament/models.py:145 +#: apps/member/models.py:155 apps/member/models.py:187 +#: apps/tournament/models.py:160 msgid "user" msgstr "utilisateur" -#: apps/member/models.py:140 +#: apps/member/models.py:156 msgid "users" msgstr "utilisateurs" -#: apps/member/models.py:154 +#: apps/member/models.py:169 msgid "file" msgstr "fichier" -#: apps/member/models.py:159 +#: apps/member/models.py:174 msgid "uploaded at" msgstr "téléversé le" -#: apps/member/models.py:163 +#: apps/member/models.py:178 msgid "document" msgstr "document" -#: apps/member/models.py:164 +#: apps/member/models.py:179 msgid "documents" msgstr "documents" -#: apps/member/models.py:178 +#: apps/member/models.py:193 msgid "Parental consent" msgstr "Autorisation parentale" -#: apps/member/models.py:179 +#: apps/member/models.py:194 msgid "Photo consent" msgstr "Autorisation de droit à l'image" -#: apps/member/models.py:180 +#: apps/member/models.py:195 msgid "Sanitary plug" msgstr "Fiche sanitaire" -#: apps/member/models.py:181 apps/tournament/models.py:163 +#: apps/member/models.py:196 apps/tournament/models.py:178 msgid "Scholarship" msgstr "Bourse" -#: apps/member/models.py:183 +#: apps/member/models.py:198 msgid "type" msgstr "type" -#: apps/member/models.py:187 +#: apps/member/models.py:202 msgid "authorization" msgstr "autorisation" -#: apps/member/models.py:188 +#: apps/member/models.py:203 msgid "authorizations" msgstr "autorisations" -#: apps/member/models.py:200 +msgid "{authorization} for user {user}" +msgstr "{authorization} pour l'utilisateur {user}" + +#: apps/member/models.py:218 msgid "motivation letter" msgstr "lettre de motivation" -#: apps/member/models.py:201 +#: apps/member/models.py:219 msgid "motivation letters" msgstr "lettres de motivation" -#: apps/member/models.py:213 +#: apps/member/models.py:222 +#, python-brace-format +msgid "Motivation letter of team {team} ({trigram})" +msgstr "Lettre de motivation de l'équipe {team} ({trigram})" + +#: apps/member/models.py:234 msgid "problem" msgstr "problème" -#: apps/member/models.py:221 +#: apps/member/models.py:242 msgid "solution" msgstr "solution" -#: apps/member/models.py:222 +#: apps/member/models.py:243 msgid "solutions" msgstr "solutions" -#: apps/member/models.py:236 +#: apps/member/models.py:246 +#, python-brace-format +msgid "Solution of team {trigram} for problem {problem}" +msgstr "" + +#: apps/member/models.py:261 msgid "Defender" msgstr "Défenseur" -#: apps/member/models.py:237 +#: apps/member/models.py:262 msgid "Opponent" msgstr "Opposant" -#: apps/member/models.py:238 +#: apps/member/models.py:263 msgid "Rapporteur" msgstr "Rapporteur" -#: apps/member/models.py:240 +#: apps/member/models.py:265 msgid "dest" msgstr "destinataire" -#: apps/member/models.py:248 +#: apps/member/models.py:273 msgid "synthesis" msgstr "synthèse" -#: apps/member/models.py:249 +#: apps/member/models.py:274 msgid "syntheses" msgstr "synthèses" -#: apps/tournament/apps.py:7 apps/tournament/models.py:69 -#: apps/tournament/models.py:90 +#: apps/member/models.py:277 +#, python-brace-format +msgid "Synthesis of team {trigram} that is {dest} for problem {problem}" +msgstr "" + +#: apps/member/models.py:285 +msgid "key" +msgstr "clé" + +#: apps/member/models.py:290 +msgid "value" +msgstr "valeur" + +#: apps/member/models.py:294 +msgid "configuration" +msgstr "configuration" + +#: apps/member/models.py:295 +msgid "configurations" +msgstr "configurations" + +#: apps/tournament/apps.py:7 apps/tournament/models.py:71 +#: apps/tournament/models.py:92 msgid "tournament" msgstr "tournoi" -#: apps/tournament/models.py:10 apps/tournament/models.py:79 +#: apps/tournament/models.py:11 apps/tournament/models.py:81 msgid "name" msgstr "nom" -#: apps/tournament/models.py:16 +#: apps/tournament/models.py:17 msgid "organizers" msgstr "organisateurs" -#: apps/tournament/models.py:20 +#: apps/tournament/models.py:21 msgid "size" msgstr "taille" -#: apps/tournament/models.py:25 +#: apps/tournament/models.py:26 msgid "place" msgstr "lieu" -#: apps/tournament/models.py:29 +#: apps/tournament/models.py:30 msgid "price" msgstr "prix" -#: apps/tournament/models.py:37 apps/tournament/models.py:41 +#: apps/tournament/models.py:38 apps/tournament/models.py:42 msgid "date start" msgstr "date de début" -#: apps/tournament/models.py:45 +#: apps/tournament/models.py:46 msgid "date of registration closing" msgstr "date de clôture des inscriptions" -#: apps/tournament/models.py:49 +#: apps/tournament/models.py:50 msgid "date of maximal solution submission" msgstr "date d'envoi maximal des solutions" -#: apps/tournament/models.py:53 +#: apps/tournament/models.py:54 msgid "date of maximal syntheses submission" msgstr "date d'envoi maximal des notes de synthèses" -#: apps/tournament/models.py:57 +#: apps/tournament/models.py:58 msgid "final tournament" msgstr "finale" -#: apps/tournament/models.py:70 +#: apps/tournament/models.py:72 msgid "tournaments" msgstr "tournois" -#: apps/tournament/models.py:84 +#: apps/tournament/models.py:86 msgid "trigram" msgstr "trigramme" -#: apps/tournament/models.py:95 +#: apps/tournament/models.py:97 msgid "inscription date" msgstr "date d'inscription" -#: apps/tournament/models.py:101 apps/tournament/models.py:172 +#: apps/tournament/models.py:103 apps/tournament/models.py:187 msgid "Registration not validated" msgstr "Inscription non validée" -#: apps/tournament/models.py:102 apps/tournament/models.py:173 +#: apps/tournament/models.py:104 apps/tournament/models.py:188 msgid "Waiting for validation" msgstr "En attente de validation" -#: apps/tournament/models.py:103 apps/tournament/models.py:174 +#: apps/tournament/models.py:105 apps/tournament/models.py:189 msgid "Registration validated" msgstr "Inscription validée" -#: apps/tournament/models.py:105 apps/tournament/models.py:176 +#: apps/tournament/models.py:107 apps/tournament/models.py:191 msgid "validation status" msgstr "statut de validation" -#: apps/tournament/models.py:110 +#: apps/tournament/models.py:112 msgid "selected for final" msgstr "sélectionnée pour la finale" -#: apps/tournament/models.py:116 +#: apps/tournament/models.py:118 msgid "access code" msgstr "code d'accès" -#: apps/tournament/models.py:133 +#: apps/tournament/models.py:148 msgid "teams" msgstr "équipes" -#: apps/tournament/models.py:158 +#: apps/tournament/models.py:173 msgid "Not paid" msgstr "Non payé" -#: apps/tournament/models.py:159 +#: apps/tournament/models.py:174 msgid "Credit card" msgstr "Carte bancaire" -#: apps/tournament/models.py:160 +#: apps/tournament/models.py:175 msgid "Bank check" msgstr "Chèque bancaire" -#: apps/tournament/models.py:161 +#: apps/tournament/models.py:176 msgid "Bank transfer" msgstr "Virement bancaire" -#: apps/tournament/models.py:162 +#: apps/tournament/models.py:177 msgid "Cash" msgstr "Espèces" -#: apps/tournament/models.py:166 +#: apps/tournament/models.py:181 msgid "payment method" msgstr "moyen de paiement" -#: apps/tournament/models.py:180 +#: apps/tournament/models.py:195 msgid "payment" msgstr "paiement" -#: apps/tournament/models.py:181 +#: apps/tournament/models.py:196 msgid "payments" msgstr "paiements" -#: apps/tournament/models.py:184 +#: apps/tournament/models.py:199 #, python-brace-format msgid "Payment of {user}" msgstr "Paiement de {user}" -#: tfjm/settings.py:128 +#: templates/base.html:11 +msgid "The inscription site of the TFJM²." +msgstr "Le site d'inscription au TFJM²." + +#: templates/registration/email_validation_complete.html:6 +msgid "Your email have successfully been validated." +msgstr "Votre adresse e-mail a bien été validée." + +#: templates/registration/email_validation_complete.html:8 +#, python-format +msgid "You can now log in." +msgstr "Vous pouvez désormais vous connecter" + +#: templates/registration/email_validation_complete.html:13 +msgid "" +"The link was invalid. The token may have expired. Please send us an email to " +"activate your account." +msgstr "" +"Le lien est invalide. Le jeton a du expirer. Merci de nous envoyer un mail " +"afin d'activer votre compte." + +#: templates/registration/logged_out.html:8 +msgid "Thanks for spending some quality time with the Web site today." +msgstr "Merci d'avoir utilisé la plateforme du TFJM²." + +#: templates/registration/logged_out.html:9 +msgid "Log in again" +msgstr "Se connecter à nouveau" + +#: templates/registration/login.html:7 templates/registration/login.html:8 +#: templates/registration/login.html:22 +#: templates/registration/password_reset_complete.html:10 +msgid "Log in" +msgstr "Connexion" + +#: templates/registration/login.html:13 +#, python-format +msgid "" +"You are authenticated as %(user)s, but are not authorized to access this " +"page. Would you like to login to a different account?" +msgstr "" +"Vous êtes déjà connecté sous le nom %(user)s, mais vous n'êtes pas autorisés " +"à accéder à cette page. Souhaitez-vous vous connecter sous un compte différent ?" + +#: templates/registration/login.html:23 +msgid "Forgotten your password or username?" +msgstr "Mot de passe oublié ?" + +#: templates/registration/mails/email_validation_email.html:3 +msgid "Hi" +msgstr "Bonjour" + +#: templates/registration/mails/email_validation_email.html:5 +msgid "" +"You recently registered on the Note Kfet. Please click on the link below to " +"confirm your registration." +msgstr "" + +#: templates/registration/mails/email_validation_email.html:9 +msgid "" +"This link is only valid for a couple of days, after that you will need to " +"contact us to validate your email." +msgstr "" + +#: templates/registration/mails/email_validation_email.html:11 +msgid "" +"After that, you'll have to wait that someone validates your account before " +"you can log in. You will need to pay your membership in the Kfet." +msgstr "" + +#: templates/registration/mails/email_validation_email.html:13 +msgid "Thanks" +msgstr "Merci" + +#: templates/registration/mails/email_validation_email.html:15 +msgid "The Note Kfet team." +msgstr "" + +#: templates/registration/password_change_done.html:8 +msgid "Your password was changed." +msgstr "Votre mot de passe a été changé" + +#: templates/registration/password_change_form.html:9 +msgid "" +"Please enter your old password, for security's sake, and then enter your new " +"password twice so we can verify you typed it in correctly." +msgstr "" + +#: templates/registration/password_change_form.html:11 +#: templates/registration/password_reset_confirm.html:12 +msgid "Change my password" +msgstr "" + +#: templates/registration/password_reset_complete.html:8 +msgid "Your password has been set. You may go ahead and log in now." +msgstr "" + +#: templates/registration/password_reset_confirm.html:9 +msgid "" +"Please enter your new password twice so we can verify you typed it in " +"correctly." +msgstr "" + +#: templates/registration/password_reset_confirm.html:15 +msgid "" +"The password reset link was invalid, possibly because it has already been " +"used. Please request a new password reset." +msgstr "" + +#: templates/registration/password_reset_done.html:8 +msgid "" +"We've emailed you instructions for setting your password, if an account " +"exists with the email you entered. You should receive them shortly." +msgstr "" + +#: templates/registration/password_reset_done.html:9 +msgid "" +"If you don't receive an email, please make sure you've entered the address " +"you registered with, and check your spam folder." +msgstr "" + +#: templates/registration/password_reset_form.html:8 +msgid "" +"Forgotten your password? Enter your email address below, and we'll email " +"instructions for setting a new one." +msgstr "" + +#: templates/registration/password_reset_form.html:11 +msgid "Reset my password" +msgstr "Réinitialiser mon mot de passe" + +#: templates/registration/signup.html:5 templates/registration/signup.html:8 +#: templates/registration/signup.html:14 +msgid "Sign up" +msgstr "S'inscrire" + +#: tfjm/settings.py:135 msgid "English" msgstr "Anglais" -#: tfjm/settings.py:129 +#: tfjm/settings.py:136 msgid "French" msgstr "Français" diff --git a/static/bootstrap_datepicker_plus/css/datepicker-widget.css b/static/bootstrap_datepicker_plus/css/datepicker-widget.css new file mode 100644 index 0000000..baeec50 --- /dev/null +++ b/static/bootstrap_datepicker_plus/css/datepicker-widget.css @@ -0,0 +1,121 @@ +@font-face { + font-family: 'Glyphicons Halflings'; + src: url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.eot'); + src: url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), + url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff2') format('woff2'), + url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.woff') format('woff'), + url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.ttf') format('truetype'), + url('//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg'); +} + +.glyphicon { + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.glyphicon-time:before { + content: "\e023"; +} + +.glyphicon-chevron-left:before { + content: "\e079"; +} + +.glyphicon-chevron-right:before { + content: "\e080"; +} + +.glyphicon-chevron-up:before { + content: "\e113"; +} + +.glyphicon-chevron-down:before { + content: "\e114"; +} + +.glyphicon-calendar:before { + content: "\e109"; +} + +.glyphicon-screenshot:before { + content: "\e087"; +} + +.glyphicon-trash:before { + content: "\e020"; +} + +.glyphicon-remove:before { + content: "\e014"; +} + +.bootstrap-datetimepicker-widget .btn { + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + -ms-touch-action: manipulation; + touch-action: manipulation; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; +} + +.bootstrap-datetimepicker-widget.dropdown-menu { + position: absolute; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + text-align: left; + list-style: none; + background-color: #fff; + -webkit-background-clip: padding-box; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} + +.bootstrap-datetimepicker-widget .list-unstyled { + padding-left: 0; + list-style: none; +} + +.bootstrap-datetimepicker-widget .collapse { + display: none; +} + +.bootstrap-datetimepicker-widget .collapse.in { + display: block; +} + +/* fix for bootstrap4 */ +.bootstrap-datetimepicker-widget .table-condensed > thead > tr > th, +.bootstrap-datetimepicker-widget .table-condensed > tbody > tr > td, +.bootstrap-datetimepicker-widget .table-condensed > tfoot > tr > td { + padding: 5px; +} diff --git a/static/bootstrap_datepicker_plus/js/datepicker-widget.js b/static/bootstrap_datepicker_plus/js/datepicker-widget.js new file mode 100644 index 0000000..2288b46 --- /dev/null +++ b/static/bootstrap_datepicker_plus/js/datepicker-widget.js @@ -0,0 +1,55 @@ +jQuery(function ($) { + var datepickerDict = {}; + var isBootstrap4 = $.fn.collapse.Constructor.VERSION.split('.').shift() == "4"; + function fixMonthEndDate(e, picker) { + e.date && picker.val().length && picker.val(e.date.endOf('month').format('YYYY-MM-DD')); + } + $("[dp_config]:not([disabled])").each(function (i, element) { + var $element = $(element), data = {}; + try { + data = JSON.parse($element.attr('dp_config')); + } + catch (x) { } + if (data.id && data.options) { + data.$element = $element.datetimepicker(data.options); + data.datepickerdata = $element.data("DateTimePicker"); + datepickerDict[data.id] = data; + data.$element.next('.input-group-addon').on('click', function(){ + data.datepickerdata.show(); + }); + if(isBootstrap4){ + data.$element.on("dp.show", function (e) { + $('.collapse.in').addClass('show'); + }); + } + } + }); + $.each(datepickerDict, function (id, to_picker) { + if (to_picker.linked_to) { + var from_picker = datepickerDict[to_picker.linked_to]; + from_picker.datepickerdata.maxDate(to_picker.datepickerdata.date() || false); + to_picker.datepickerdata.minDate(from_picker.datepickerdata.date() || false); + from_picker.$element.on("dp.change", function (e) { + to_picker.datepickerdata.minDate(e.date || false); + }); + to_picker.$element.on("dp.change", function (e) { + if (to_picker.picker_type == 'MONTH') fixMonthEndDate(e, to_picker.$element); + from_picker.datepickerdata.maxDate(e.date || false); + }); + if (to_picker.picker_type == 'MONTH') { + to_picker.$element.on("dp.hide", function (e) { + fixMonthEndDate(e, to_picker.$element); + }); + fixMonthEndDate({ date: to_picker.datepickerdata.date() }, to_picker.$element); + } + } + }); + if(isBootstrap4) { + $('body').on('show.bs.collapse','.bootstrap-datetimepicker-widget .collapse',function(e){ + $(e.target).addClass('in'); + }); + $('body').on('hidden.bs.collapse','.bootstrap-datetimepicker-widget .collapse',function(e){ + $(e.target).removeClass('in'); + }); + } +}); diff --git a/templates/amount_input.html b/templates/amount_input.html new file mode 100644 index 0000000..6ef4a53 --- /dev/null +++ b/templates/amount_input.html @@ -0,0 +1,11 @@ +
+ +
+ +
+
\ No newline at end of file diff --git a/templates/autocomplete_model.html b/templates/autocomplete_model.html new file mode 100644 index 0000000..2236c6e --- /dev/null +++ b/templates/autocomplete_model.html @@ -0,0 +1,9 @@ + + +
    +
diff --git a/templates/base.html b/templates/base.html index d17aac9..20b7c79 100644 --- a/templates/base.html +++ b/templates/base.html @@ -155,7 +155,7 @@ Connexion {% else %}
{% if user.admin or user in team.tournament.organizers.all %} {% endif %} diff --git a/templates/tournament/team_form.html b/templates/tournament/team_form.html new file mode 100644 index 0000000..21daee8 --- /dev/null +++ b/templates/tournament/team_form.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} + +{% load i18n crispy_forms_filters %} + +{% block content %} +
+ {% csrf_token %} + {{ form|crispy }} + +
+{% endblock %} diff --git a/templates/tournament/tournament_detail.html b/templates/tournament/tournament_detail.html index 5eb0062..d5095da 100644 --- a/templates/tournament/tournament_detail.html +++ b/templates/tournament/tournament_detail.html @@ -39,15 +39,15 @@ {% if user.is_authenticated and user.admin %} {% endif %} {% if user.admin or user in tournament.organizers.all %} {% endif %} diff --git a/templates/tournament/tournament_form.html b/templates/tournament/tournament_form.html new file mode 100644 index 0000000..21daee8 --- /dev/null +++ b/templates/tournament/tournament_form.html @@ -0,0 +1,11 @@ +{% extends "base.html" %} + +{% load i18n crispy_forms_filters %} + +{% block content %} +
+ {% csrf_token %} + {{ form|crispy }} + +
+{% endblock %} diff --git a/templates/tournament/tournament_list.html b/templates/tournament/tournament_list.html index 8811241..27b9835 100644 --- a/templates/tournament/tournament_list.html +++ b/templates/tournament/tournament_list.html @@ -5,8 +5,8 @@ {% block content %} {% if user.is_authenticated and user.admin %} {% endif %} {% render_table table %} diff --git a/tfjm/settings.py b/tfjm/settings.py index 7b855e9..3cd70cf 100644 --- a/tfjm/settings.py +++ b/tfjm/settings.py @@ -89,6 +89,8 @@ TEMPLATES = [ }, ] +FORM_RENDERER = 'django.forms.renderers.TemplatesSetting' + WSGI_APPLICATION = 'tfjm.wsgi.application' @@ -150,7 +152,7 @@ LANGUAGES = [ ('fr', _('French')), ] -TIME_ZONE = 'UTC' +TIME_ZONE = 'Europe/Paris' USE_I18N = True From ac2790d32712833c0a2a629b239df11148d01808 Mon Sep 17 00:00:00 2001 From: Yohann D'ANELLO Date: Mon, 4 May 2020 21:02:57 +0200 Subject: [PATCH 021/132] Connect as other people --- apps/member/urls.py | 3 +- apps/member/views.py | 27 ++++++++++++++-- templates/base.html | 5 +++ templates/member/tfjmuser_detail.html | 44 ++++++++++++++++----------- tfjm/middlewares.py | 10 ++++-- tfjm/settings.py | 1 + 6 files changed, 67 insertions(+), 23 deletions(-) diff --git a/apps/member/urls.py b/apps/member/urls.py index 7a62cd1..90c8d91 100644 --- a/apps/member/urls.py +++ b/apps/member/urls.py @@ -2,7 +2,7 @@ from django.urls import path from django.views.generic import RedirectView from .views import CreateUserView, MyAccountView, UserDetailView,\ - ProfileListView, OrphanedProfileListView, OrganizersListView + ProfileListView, OrphanedProfileListView, OrganizersListView, ResetAdminView app_name = "member" @@ -17,4 +17,5 @@ urlpatterns = [ path("profiles/", ProfileListView.as_view(), name="all_profiles"), path("orphaned-profiles/", OrphanedProfileListView.as_view(), name="orphaned_profiles"), path("organizers/", OrganizersListView.as_view(), name="organizers"), + path("reset-admin/", ResetAdminView.as_view(), name="reset_admin"), ] diff --git a/apps/member/views.py b/apps/member/views.py index 3cc1968..02767ed 100644 --- a/apps/member/views.py +++ b/apps/member/views.py @@ -1,7 +1,9 @@ from django.contrib.auth.mixins import LoginRequiredMixin +from django.contrib.auth.models import AnonymousUser from django.core.exceptions import PermissionDenied from django.db.models import Q from django.http import FileResponse +from django.shortcuts import redirect from django.utils.translation import gettext_lazy as _ from django.views import View from django.views.generic import CreateView, UpdateView, DetailView @@ -31,15 +33,29 @@ class MyAccountView(LoginRequiredMixin, UpdateView): class UserDetailView(LoginRequiredMixin, DetailView): model = TFJMUser form_class = TFJMUserForm - context_object_name = "user" + context_object_name = "tfjmuser" def dispatch(self, request, *args, **kwargs): + if isinstance(request.user, AnonymousUser): + raise PermissionDenied + + self.object = self.get_object() + if not request.user.admin \ - and (self.object.team is not None and request.user not in self.object.team.tournament.organizers)\ + and (self.object.team is not None and request.user not in self.object.team.tournament.organizers.all())\ and self.request.user != self.object: raise PermissionDenied return super().dispatch(request, *args, **kwargs) + def post(self, request, *args, **kwargs): + if "view_as" in request.POST: + session = request.session + session["admin"] = request.user.pk + obj = self.get_object() + session["_fake_user_id"] = obj.pk + return redirect(request.path) + return self.get(request, *args, **kwargs) + def get_context_data(self, **kwargs): context = super().get_context_data(**kwargs) @@ -82,3 +98,10 @@ class OrganizersListView(AdminMixin, SingleTableView): table_class = UserTable template_name = "member/profile_list.html" extra_context = dict(title=_("Organizers")) + + +class ResetAdminView(AdminMixin, View): + def dispatch(self, request, *args, **kwargs): + if "_fake_user_id" in request.session: + del request.session["_fake_user_id"] + return redirect(request.GET["path"]) diff --git a/templates/base.html b/templates/base.html index 7742ee1..979b4f4 100644 --- a/templates/base.html +++ b/templates/base.html @@ -141,6 +141,11 @@ {% endif %}
+ +
+ {% if user.is_authenticated and not user.profile.email_confirmed %} +
+ {% trans "Your e-mail address is not validated. Please check your mail inbox and click on the validation link." %} +
+ {% endif %} + {% block contenttitle %}

{{ title }}

{% endblock %} +
+ {% block content %} +

Default content...

+ {% endblock content %} +
+