colles.mp2i-vms.fr/colloscope/models.py

159 lines
5.3 KiB
Python

from math import ceil
from datetime import date, datetime, timedelta
from django.db import models
from django.db.models import F, Q
calendrier = {
"C" : [
( date(2023, 10, 21), date(2023, 11, 6) ),
( date(2023, 12, 23), date(2024, 1, 8) ),
( date(2024, 2, 10), date(2024, 2, 26) ),
( date(2024, 4, 6), date(2024, 4, 22) ),
]
}
class Lycee(models.Model):
uai = models.CharField(max_length=10)
libelle = models.CharField(max_length=100)
vacances = models.CharField(max_length=1)
class Classe(models.Model):
lycee = models.ForeignKey(Lycee, on_delete=models.CASCADE)
libelle = models.CharField(max_length=20)
annee = models.IntegerField()
jour_zero = models.DateField()
class Periode(models.Model):
classe = models.ForeignKey(Classe, on_delete=models.CASCADE)
#critere_colle = models.ForeignKey(Critere, on_delete=models.SET_NULL, null=True)
libelle = models.CharField(max_length=100)
debut = models.DateField()
fin = models.DateField()
class Meta:
ordering = ["debut"]
def no_semaine(self, jour):
zone = self.classe.lycee.vacances
vacances = calendrier[zone]
jour0 = self.classe.jour_zero
n = 1 + ((jour - jour0).days)//7
for debut, fin in vacances:
if jour > debut:
n -= 2
return n
def range_semaines(self):
return range(self.no_semaine(self.debut), self.no_semaine(self.fin)+1)
def date_debut_sem(self, n):
zone = self.classe.lycee.vacances
vacances = calendrier[zone]
jour0 = self.classe.jour_zero
jour = jour0 + (n-1) * timedelta(weeks=1)
for debut, _ in vacances:
if jour >= debut:
jour += 2*timedelta(weeks=1)
return jour
class Matiere(models.Model):
classe = models.ForeignKey(Classe, on_delete=models.CASCADE)
libelle = models.CharField(max_length=100)
code = models.CharField(max_length=20)
class Critere(models.Model):
periode = models.ForeignKey(Periode, on_delete=models.CASCADE)
libelle = models.CharField(max_length=100)
class Groupe(models.Model):
#class Meta:
# ordering=[F("periode").classe.libelle, F("periode").libelle, "libelle"]
periode = models.ForeignKey(Periode, on_delete=models.CASCADE)
critere = models.ForeignKey(Critere, null=True, on_delete=models.CASCADE)
libelle = models.CharField(max_length=100)
def membres(self):
return Etudiant.objects.filter(id__in=Appartenance.objects.filter(groupe=self))
class Etudiant(models.Model):
class Meta:
ordering=["classe", "nom", "prenom"]
classe = models.ForeignKey(Classe, on_delete=models.CASCADE)
prenom = models.CharField(max_length=100)
nom = models.CharField(max_length=100)
#lv1 = models.ForeignKey(Matiere, on_delete=models.CASCADE)
#lv2 = models.ForeignKey(Matiere, on_delete=models.CASCADE)
def appartient(self, groupe, periode):
return Appartenance.objects.filter(etudiant=self, groupe=groupe).exists()
def groupe_du_critere(self, periode, critere):
if isinstance(critere, str):
critere = Critere.objects.get(periode=periode, libelle=critere)
return Appartenance.objects.get(groupe__periode=periode, etudiant=self, groupe__critere=critere).groupe
def groupe_de_colle(self, periode):
return self.groupe_du_critere(periode, "colle")
class Appartenance(models.Model):
etudiant = models.ForeignKey(Etudiant, on_delete=models.CASCADE)
groupe = models.ForeignKey(Groupe, on_delete=models.CASCADE)
class Colleur(models.Model):
civilite = models.CharField(max_length=1)
nom = models.CharField(max_length=100)
class Creneau(models.Model):
periode = models.ForeignKey(Periode, on_delete=models.CASCADE)
jour = models.IntegerField()
heure = models.TimeField()
duree = models.DurationField()
salle = models.CharField(max_length=20)
matiere = models.ForeignKey(Matiere, on_delete=models.CASCADE)
colleur = models.ForeignKey(Colleur, on_delete=models.CASCADE)
est_colle = models.BooleanField()
capacite = models.IntegerField()
class Rotation(models.Model):
creneau = models.ForeignKey(Creneau, on_delete=models.CASCADE)
groupes = models.ManyToManyField(Groupe)
semaine = models.IntegerField()
def effectif(self):
n_base = sum(len(groupe.membres()) for groupe in self.groupes.all())
n_plus = len(Amendement.objects.filter(est_positif=True, rotation=self))
n_moins = len(Amendement.objects.filter(est_positif=False, rotation=self))
return n_base + n_plus - n_moins
def est_pleine(self):
eff = self.effectif()
if eff>self.creneau.capacite:
raise models.IntegrityError
else:
return eff==self.creneau.capacite
class Amendement(models.Model):
est_positif = models.BooleanField()
rotation = models.ForeignKey(Rotation, on_delete=models.CASCADE)
etudiant = models.ForeignKey(Etudiant, on_delete=models.CASCADE)
class Utilisateur(models.Model):
username = models.CharField(max_length=100)
password = models.CharField(max_length=300)
timestamp = models.DateTimeField(auto_now_add=True)
etudiant = models.ForeignKey(Etudiant, on_delete=models.SET_NULL, null=True)
colleur = models.ForeignKey(Colleur, on_delete=models.SET_NULL, null=True)