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)