mirror of
				https://gitlab.com/animath/si/plateforme.git
				synced 2025-11-04 08:22:10 +01:00 
			
		
		
		
	@@ -2,8 +2,8 @@
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
import csv
 | 
			
		||||
import re
 | 
			
		||||
from io import StringIO
 | 
			
		||||
import re
 | 
			
		||||
from typing import Iterable
 | 
			
		||||
 | 
			
		||||
from bootstrap_datepicker_plus.widgets import DatePickerInput, DateTimePickerInput
 | 
			
		||||
@@ -14,8 +14,8 @@ from django.core.validators import FileExtensionValidator
 | 
			
		||||
from django.utils import formats
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from PyPDF3 import PdfFileReader
 | 
			
		||||
 | 
			
		||||
from registration.models import VolunteerRegistration
 | 
			
		||||
 | 
			
		||||
from .models import Note, Participation, Passage, Pool, Solution, Synthesis, Team, Tournament
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,11 @@
 | 
			
		||||
# Copyright (C) 2021 by Animath
 | 
			
		||||
# SPDX-License-Identifier: GPL-3.0-or-later
 | 
			
		||||
 | 
			
		||||
import os
 | 
			
		||||
 | 
			
		||||
from django.contrib.auth.models import User
 | 
			
		||||
from django.core.management import BaseCommand
 | 
			
		||||
from django.utils.formats import date_format
 | 
			
		||||
from django.utils.translation import activate
 | 
			
		||||
 | 
			
		||||
from participation.models import Tournament
 | 
			
		||||
from .models import Tournament
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Command(BaseCommand):
 | 
			
		||||
@@ -42,9 +39,12 @@ class Command(BaseCommand):
 | 
			
		||||
        self.w("")
 | 
			
		||||
        self.w("<!-- wp:paragraph -->")
 | 
			
		||||
        if tournament.final:
 | 
			
		||||
            self.w(f"<p>La finale a eu lieu le weekend du {date_start} au {date_end} et a été remporté par l'équipe <em>{notes[0][0].team.name}</em> suivie de l'équipe <em>{notes[1][0].team.name}</em>. Les deux premières équipes sont sélectionnées pour représenter la France lors de l'ITYM.</p>")
 | 
			
		||||
            self.w(f"<p>La finale a eu lieu le weekend du {date_start} au {date_end} et a été remporté par l'équipe "
 | 
			
		||||
                   f"<em>{notes[0][0].team.name}</em> suivie de l'équipe <em>{notes[1][0].team.name}</em>. "
 | 
			
		||||
                   f"Les deux premières équipes sont sélectionnées pour représenter la France lors de l'ITYM.</p>")
 | 
			
		||||
        else:
 | 
			
		||||
            self.w(f"<p>Le tournoi de {name} a eu lieu le weekend du {date_start} au {date_end} et a été remporté par l'équipe <em>{notes[0][0].team.name}</em>.</p>")
 | 
			
		||||
            self.w(f"<p>Le tournoi de {name} a eu lieu le weekend du {date_start} au {date_end} et a été remporté par "
 | 
			
		||||
                   f"l'équipe <em>{notes[0][0].team.name}</em>.</p>")
 | 
			
		||||
        self.w("<!-- /wp:paragraph -->")
 | 
			
		||||
        self.w("")
 | 
			
		||||
        self.w("")
 | 
			
		||||
 
 | 
			
		||||
@@ -3,12 +3,22 @@
 | 
			
		||||
 | 
			
		||||
from pathlib import Path
 | 
			
		||||
 | 
			
		||||
from django.contrib.auth.models import User
 | 
			
		||||
from django.core.management import BaseCommand
 | 
			
		||||
from django.utils.formats import date_format
 | 
			
		||||
from django.utils.translation import activate
 | 
			
		||||
 | 
			
		||||
from participation.models import Solution, Tournament
 | 
			
		||||
from .models import Solution, Tournament
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
PROBLEMS = [
 | 
			
		||||
        "Pliage de polygones",
 | 
			
		||||
        "Mélodie des hirondelles",
 | 
			
		||||
        "Professeur confiné",
 | 
			
		||||
        "Nain sans mémoire",
 | 
			
		||||
        "Bricolage microscopique",
 | 
			
		||||
        "Villes jumelées",
 | 
			
		||||
        "Promenade de chiens",
 | 
			
		||||
        "Persée et la Gorgone",
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Command(BaseCommand):
 | 
			
		||||
@@ -31,17 +41,6 @@ class Command(BaseCommand):
 | 
			
		||||
        if not base_dir.is_dir():
 | 
			
		||||
            base_dir.mkdir()
 | 
			
		||||
 | 
			
		||||
        PROBLEMS = [
 | 
			
		||||
                "Agent 1234",
 | 
			
		||||
                "Bataille rangée",
 | 
			
		||||
                "C'est pas trop tôt !",
 | 
			
		||||
                "Chocolaterie de haut vol",
 | 
			
		||||
                "Stratégies féodales",
 | 
			
		||||
                "Le facteur n'est pas passé",
 | 
			
		||||
                "Vive les grenouilles libres !",
 | 
			
		||||
                "Télé truquée",
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        for problem_id, problem_name in enumerate(PROBLEMS):
 | 
			
		||||
            dir_name = f"Problème n°{problem_id + 1} : {problem_name}"
 | 
			
		||||
            problem_dir = base_dir / dir_name
 | 
			
		||||
 
 | 
			
		||||
@@ -15,10 +15,10 @@ from tfjm.matrix import Matrix, RoomPreset, RoomVisibility
 | 
			
		||||
class Command(BaseCommand):
 | 
			
		||||
    def handle(self, *args, **options):  # noqa: C901
 | 
			
		||||
        activate("fr")
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        async def main():
 | 
			
		||||
            await Matrix.set_display_name("Bot du TFJM²")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not os.getenv("SYNAPSE_PASSWORD"):
 | 
			
		||||
                avatar_uri = "plop"
 | 
			
		||||
            else:  # pragma: no cover
 | 
			
		||||
@@ -31,15 +31,15 @@ class Command(BaseCommand):
 | 
			
		||||
                        stat_file = os.stat("tfjm/static/logo.png")
 | 
			
		||||
                        with open("tfjm/static/logo.png", "rb") as f:
 | 
			
		||||
                            resp = (await Matrix.upload(f, filename="logo.png", content_type="image/png",
 | 
			
		||||
                                                       filesize=stat_file.st_size))[0][0]
 | 
			
		||||
                                                        filesize=stat_file.st_size))[0][0]
 | 
			
		||||
                        avatar_uri = resp.content_uri
 | 
			
		||||
                        with open(".matrix_avatar", "w") as f:
 | 
			
		||||
                            f.write(avatar_uri)
 | 
			
		||||
                        await Matrix.set_avatar(avatar_uri)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                with open(".matrix_avatar", "r") as f:
 | 
			
		||||
                    avatar_uri = f.read().rstrip(" \t\r\n")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            # Create basic channels
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#aide-jurys-orgas:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
@@ -50,7 +50,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.private_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#annonces:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
                    visibility=RoomVisibility.public,
 | 
			
		||||
@@ -60,7 +60,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.public_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#bienvenue:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
                    visibility=RoomVisibility.public,
 | 
			
		||||
@@ -70,7 +70,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.public_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#bot:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
                    visibility=RoomVisibility.public,
 | 
			
		||||
@@ -80,7 +80,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.public_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#cno:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
                    visibility=RoomVisibility.public,
 | 
			
		||||
@@ -90,7 +90,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.private_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#dev-bot:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
                    visibility=RoomVisibility.public,
 | 
			
		||||
@@ -100,7 +100,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.private_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#faq:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
                    visibility=RoomVisibility.public,
 | 
			
		||||
@@ -110,7 +110,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.public_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#flood:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
                    visibility=RoomVisibility.public,
 | 
			
		||||
@@ -120,7 +120,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.public_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            if not await Matrix.resolve_room_alias("#je-cherche-une-equipe:tfjm.org"):
 | 
			
		||||
                await Matrix.create_room(
 | 
			
		||||
                    visibility=RoomVisibility.public,
 | 
			
		||||
@@ -130,7 +130,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    federate=False,
 | 
			
		||||
                    preset=RoomPreset.public_chat,
 | 
			
		||||
                )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            # Setup avatars
 | 
			
		||||
            await Matrix.set_room_avatar("#aide-jurys-orgas:tfjm.org", avatar_uri)
 | 
			
		||||
            await Matrix.set_room_avatar("#annonces:tfjm.org", avatar_uri)
 | 
			
		||||
@@ -141,11 +141,11 @@ class Command(BaseCommand):
 | 
			
		||||
            await Matrix.set_room_avatar("#faq:tfjm.org", avatar_uri)
 | 
			
		||||
            await Matrix.set_room_avatar("#flood:tfjm.org", avatar_uri)
 | 
			
		||||
            await Matrix.set_room_avatar("#je-cherche-une-equipe:tfjm.org", avatar_uri)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            # Read-only channels
 | 
			
		||||
            await Matrix.set_room_power_level_event("#annonces:tfjm.org", "events_default", 50)
 | 
			
		||||
            await Matrix.set_room_power_level_event("#bienvenue:tfjm.org", "events_default", 50)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            # Invite everyone to public channels
 | 
			
		||||
            for r in Registration.objects.all():
 | 
			
		||||
                await Matrix.invite("#annonces:tfjm.org", f"@{r.matrix_username}:tfjm.org")
 | 
			
		||||
@@ -154,20 +154,20 @@ class Command(BaseCommand):
 | 
			
		||||
                await Matrix.invite("#faq:tfjm.org", f"@{r.matrix_username}:tfjm.org")
 | 
			
		||||
                await Matrix.invite("#flood:tfjm.org", f"@{r.matrix_username}:tfjm.org")
 | 
			
		||||
                await Matrix.invite("#je-cherche-une-equipe:tfjm.org",
 | 
			
		||||
                              f"@{r.matrix_username}:tfjm.org")
 | 
			
		||||
                                    f"@{r.matrix_username}:tfjm.org")
 | 
			
		||||
                self.stdout.write(f"Invite {r} in most common channels...")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            # Volunteers have access to the help channel
 | 
			
		||||
            for volunteer in VolunteerRegistration.objects.all():
 | 
			
		||||
                await Matrix.invite("#aide-jurys-orgas:tfjm.org", f"@{volunteer.matrix_username}:tfjm.org")
 | 
			
		||||
                self.stdout.write(f"Invite {volunteer} in #aide-jury-orgas...")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            # Admins are admins
 | 
			
		||||
            for admin in AdminRegistration.objects.all():
 | 
			
		||||
                self.stdout.write(f"Invite {admin} in #cno and #dev-bot...")
 | 
			
		||||
                await Matrix.invite("#cno:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
 | 
			
		||||
                await Matrix.invite("#dev-bot:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                self.stdout.write(f"Give admin permissions for {admin}...")
 | 
			
		||||
                await Matrix.set_room_power_level("#aide-jurys-orgas:tfjm.org",
 | 
			
		||||
                                                  f"@{admin.matrix_username}:tfjm.org", 95)
 | 
			
		||||
@@ -187,14 +187,14 @@ class Command(BaseCommand):
 | 
			
		||||
                                                  f"@{admin.matrix_username}:tfjm.org", 95)
 | 
			
		||||
                await Matrix.set_room_power_level("#je-cherche-une-equipe:tfjm.org",
 | 
			
		||||
                                                  f"@{admin.matrix_username}:tfjm.org", 95)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            # Create tournament-specific channels
 | 
			
		||||
            for tournament in Tournament.objects.all():
 | 
			
		||||
                self.stdout.write(f"Managing tournament of {tournament.name}.")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                name = tournament.name
 | 
			
		||||
                slug = name.lower().replace(" ", "-")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                if not await Matrix.resolve_room_alias(f"#annonces-{slug}:tfjm.org"):
 | 
			
		||||
                    await Matrix.create_room(
 | 
			
		||||
                        visibility=RoomVisibility.public,
 | 
			
		||||
@@ -204,7 +204,7 @@ class Command(BaseCommand):
 | 
			
		||||
                        federate=False,
 | 
			
		||||
                        preset=RoomPreset.private_chat,
 | 
			
		||||
                    )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                if not await Matrix.resolve_room_alias(f"#general-{slug}:tfjm.org"):
 | 
			
		||||
                    await Matrix.create_room(
 | 
			
		||||
                        visibility=RoomVisibility.public,
 | 
			
		||||
@@ -214,7 +214,7 @@ class Command(BaseCommand):
 | 
			
		||||
                        federate=False,
 | 
			
		||||
                        preset=RoomPreset.private_chat,
 | 
			
		||||
                    )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                if not await Matrix.resolve_room_alias(f"#flood-{slug}:tfjm.org"):
 | 
			
		||||
                    await Matrix.create_room(
 | 
			
		||||
                        visibility=RoomVisibility.public,
 | 
			
		||||
@@ -224,7 +224,7 @@ class Command(BaseCommand):
 | 
			
		||||
                        federate=False,
 | 
			
		||||
                        preset=RoomPreset.private_chat,
 | 
			
		||||
                    )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                if not await Matrix.resolve_room_alias(f"#jury-{slug}:tfjm.org"):
 | 
			
		||||
                    await Matrix.create_room(
 | 
			
		||||
                        visibility=RoomVisibility.public,
 | 
			
		||||
@@ -234,7 +234,7 @@ class Command(BaseCommand):
 | 
			
		||||
                        federate=False,
 | 
			
		||||
                        preset=RoomPreset.private_chat,
 | 
			
		||||
                    )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                if not await Matrix.resolve_room_alias(f"#orga-{slug}:tfjm.org"):
 | 
			
		||||
                    await Matrix.create_room(
 | 
			
		||||
                        visibility=RoomVisibility.public,
 | 
			
		||||
@@ -244,7 +244,7 @@ class Command(BaseCommand):
 | 
			
		||||
                        federate=False,
 | 
			
		||||
                        preset=RoomPreset.private_chat,
 | 
			
		||||
                    )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                if not await Matrix.resolve_room_alias(f"#tirage-au-sort-{slug}:tfjm.org"):
 | 
			
		||||
                    await Matrix.create_room(
 | 
			
		||||
                        visibility=RoomVisibility.public,
 | 
			
		||||
@@ -254,7 +254,7 @@ class Command(BaseCommand):
 | 
			
		||||
                        federate=False,
 | 
			
		||||
                        preset=RoomPreset.private_chat,
 | 
			
		||||
                    )
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                # Setup avatars
 | 
			
		||||
                await Matrix.set_room_avatar(f"#annonces-{slug}:tfjm.org", avatar_uri)
 | 
			
		||||
                await Matrix.set_room_avatar(f"#flood-{slug}:tfjm.org", avatar_uri)
 | 
			
		||||
@@ -262,7 +262,7 @@ class Command(BaseCommand):
 | 
			
		||||
                await Matrix.set_room_avatar(f"#jury-{slug}:tfjm.org", avatar_uri)
 | 
			
		||||
                await Matrix.set_room_avatar(f"#orga-{slug}:tfjm.org", avatar_uri)
 | 
			
		||||
                await Matrix.set_room_avatar(f"#tirage-au-sort-{slug}:tfjm.org", avatar_uri)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                # Invite admins and give permissions
 | 
			
		||||
                for admin in AdminRegistration.objects.all():
 | 
			
		||||
                    self.stdout.write(f"Invite {admin} in all channels of the tournament {name}...")
 | 
			
		||||
@@ -272,7 +272,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    await Matrix.invite(f"#jury-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
 | 
			
		||||
                    await Matrix.invite(f"#orga-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
 | 
			
		||||
                    await Matrix.invite(f"#tirage-au-sort-{slug}:tfjm.org", f"@{admin.matrix_username}:tfjm.org")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                    self.stdout.write(f"Give permissions to {admin} in all channels of the tournament {name}...")
 | 
			
		||||
                    await Matrix.set_room_power_level(f"#annonces-{slug}:tfjm.org",
 | 
			
		||||
                                                      f"@{admin.matrix_username}:tfjm.org", 95)
 | 
			
		||||
@@ -286,7 +286,7 @@ class Command(BaseCommand):
 | 
			
		||||
                                                      f"@{admin.matrix_username}:tfjm.org", 95)
 | 
			
		||||
                    await Matrix.set_room_power_level(f"#tirage-au-sort-{slug}:tfjm.org",
 | 
			
		||||
                                                      f"@{admin.matrix_username}:tfjm.org", 95)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                # Invite organizers and give permissions
 | 
			
		||||
                for orga in tournament.organizers.all():
 | 
			
		||||
                    self.stdout.write(f"Invite organizer {orga} in all channels of the tournament {name}...")
 | 
			
		||||
@@ -296,7 +296,7 @@ class Command(BaseCommand):
 | 
			
		||||
                    await Matrix.invite(f"#jury-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
 | 
			
		||||
                    await Matrix.invite(f"#orga-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
 | 
			
		||||
                    await Matrix.invite(f"#tirage-au-sort-{slug}:tfjm.org", f"@{orga.matrix_username}:tfjm.org")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                    if not orga.is_admin:
 | 
			
		||||
                        await Matrix.set_room_power_level(f"#annonces-{slug}:tfjm.org",
 | 
			
		||||
                                                          f"@{orga.matrix_username}:tfjm.org", 50)
 | 
			
		||||
@@ -310,7 +310,7 @@ class Command(BaseCommand):
 | 
			
		||||
                                                          f"@{orga.matrix_username}:tfjm.org", 50)
 | 
			
		||||
                        await Matrix.set_room_power_level(f"#tirage-au-sort-{slug}:tfjm.org",
 | 
			
		||||
                                                          f"@{orga.matrix_username}:tfjm.org", 50)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                # Invite participants
 | 
			
		||||
                for participation in tournament.participations.filter(valid=True).all():
 | 
			
		||||
                    for participant in participation.team.participants.all():
 | 
			
		||||
@@ -323,7 +323,7 @@ class Command(BaseCommand):
 | 
			
		||||
                                            f"@{participant.matrix_username}:tfjm.org")
 | 
			
		||||
                        await Matrix.invite(f"#tirage-au-sort-{slug}:tfjm.org",
 | 
			
		||||
                                            f"@{participant.matrix_username}:tfjm.org")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                # Create pool-specific channels
 | 
			
		||||
                for pool in tournament.pools.all():
 | 
			
		||||
                    self.stdout.write(f"Managing {pool}...")
 | 
			
		||||
@@ -372,7 +372,7 @@ class Command(BaseCommand):
 | 
			
		||||
                            f"#poule-{slug}-{pool.id}:tfjm.org",
 | 
			
		||||
                            f"https://board.tfjm.org/boards/{slug}-{pool.id}", f"board-{slug}-{pool.id}",
 | 
			
		||||
                            "customwidget", "Tableau", str(pool))
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                        # Invite admins and give permissions
 | 
			
		||||
                        for admin in AdminRegistration.objects.all():
 | 
			
		||||
                            await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
 | 
			
		||||
@@ -384,7 +384,7 @@ class Command(BaseCommand):
 | 
			
		||||
                                                              f"@{admin.matrix_username}:tfjm.org", 95)
 | 
			
		||||
                            await Matrix.set_room_power_level(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",
 | 
			
		||||
                                                              f"@{admin.matrix_username}:tfjm.org", 95)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                        # Invite organizers and give permissions
 | 
			
		||||
                        for orga in tournament.organizers.all():
 | 
			
		||||
                            await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
 | 
			
		||||
@@ -419,13 +419,13 @@ class Command(BaseCommand):
 | 
			
		||||
                                                                  f"@{jury.matrix_username}:tfjm.org", 50)
 | 
			
		||||
                                await Matrix.set_room_power_level(f"#poule-{slug}-{pool.id}{suffix}-jurys:tfjm.org",
 | 
			
		||||
                                                                  f"@{jury.matrix_username}:tfjm.org", 50)
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
                        # Invite participants to the right pool
 | 
			
		||||
                        for participation in pool.participations.all():
 | 
			
		||||
                            for participant in participation.team.participants.all():
 | 
			
		||||
                                await Matrix.invite(f"#poule-{slug}-{pool.id}{suffix}:tfjm.org",
 | 
			
		||||
                                                    f"@{participant.matrix_username}:tfjm.org")
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
            # Create private channels for teams
 | 
			
		||||
            for team in Team.objects.all():
 | 
			
		||||
                self.stdout.write(f"Create private channel for {team}...")
 | 
			
		||||
@@ -473,5 +473,5 @@ class Command(BaseCommand):
 | 
			
		||||
                                                      f"@{registration.matrix_username}:tfjm.org",
 | 
			
		||||
                                                      95 if registration.is_admin else 50)
 | 
			
		||||
            """
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
        asyncio.get_event_loop().run_until_complete(main())
 | 
			
		||||
 
 | 
			
		||||
@@ -534,6 +534,9 @@ class Tweak(models.Model):
 | 
			
		||||
        help_text=_("Score to add/remove on the final score"),
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    def __str__(self):
 | 
			
		||||
        return f"Tweak for {self.participation.team} of {self.diff} points"
 | 
			
		||||
 | 
			
		||||
    class Meta:
 | 
			
		||||
        verbose_name = _("tweak")
 | 
			
		||||
        verbose_name_plural = _("tweaks")
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,6 @@ from django.urls import reverse_lazy
 | 
			
		||||
from django.utils import timezone
 | 
			
		||||
from django.utils.translation import gettext_lazy as _
 | 
			
		||||
from django.views.generic import CreateView, DetailView, FormView, RedirectView, TemplateView, UpdateView, View
 | 
			
		||||
from django.views.generic.detail import SingleObjectMixin
 | 
			
		||||
from django.views.generic.edit import FormMixin, ProcessFormView
 | 
			
		||||
from django_tables2 import SingleTableView
 | 
			
		||||
from magic import Magic
 | 
			
		||||
@@ -182,13 +181,13 @@ class TeamDetailView(LoginRequiredMixin, FormMixin, ProcessFormView, DetailView)
 | 
			
		||||
        # A team is complete when there are at least 4 members plus a coache that have sent their authorizations,
 | 
			
		||||
        # their health sheet, they confirmed their email address and under-18 people sent their parental authorization.
 | 
			
		||||
        context["can_validate"] = team.students.count() >= 4 and team.coaches.exists() and \
 | 
			
		||||
                                  team.participation.tournament and \
 | 
			
		||||
                                  all(r.photo_authorization for r in team.participants.all()) and \
 | 
			
		||||
                                  (team.participation.tournament.remote
 | 
			
		||||
                                   or all(r.health_sheet for r in team.students.all() if r.under_18)) and \
 | 
			
		||||
                                  (team.participation.tournament.remote
 | 
			
		||||
                                   or all(r.parental_authorization for r in team.students.all() if r.under_18)) and \
 | 
			
		||||
                                  team.motivation_letter
 | 
			
		||||
            team.participation.tournament and \
 | 
			
		||||
            all(r.photo_authorization for r in team.participants.all()) and \
 | 
			
		||||
            (team.participation.tournament.remote
 | 
			
		||||
             or all(r.health_sheet for r in team.students.all() if r.under_18)) and \
 | 
			
		||||
            (team.participation.tournament.remote
 | 
			
		||||
             or all(r.parental_authorization for r in team.students.all() if r.under_18)) and \
 | 
			
		||||
            team.motivation_letter
 | 
			
		||||
 | 
			
		||||
        return context
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user