#!/usr/bin/env python3
# -*- coding: utf-8; mode: python -*-
""" Etablissement, pour https://github.com/Naereen/ParcourSup.py.
- Auteurs : Lilian Besson, Bastien Trotobas et al, (C) 2018.
- Adresse : https://github.com/Naereen/ParcourSup.py
- Licence : MIT License (http://lbesson.mit-license.org).
"""
__author__ = "Lilian Besson, Bastien Trotobas et al"
__version__ = "0.0.1"
from typing import List, Dict, Union, Set
from random import random, randint, choice
try:
from .GroupeAffectation import GroupeAffectation
from .GroupeAffectationUID import GroupeAffectationUID
from .GroupeInternat import GroupeInternat
from .GroupeInternatUID import GroupeInternatUID
from .VoeuEnAttente import VoeuEnAttente
from .Candidat import Candidat
except ImportError:
from GroupeAffectation import GroupeAffectation
from GroupeAffectationUID import GroupeAffectationUID
from GroupeInternat import GroupeInternat
from GroupeInternatUID import GroupeInternatUID
from VoeuEnAttente import VoeuEnAttente
from Candidat import Candidat
[docs]def randbool() -> bool:
""" Pile ou face, True avec probabilité 1/2 et False avec probabilité 1/2."""
return random() < 0.5
[docs]def avecproba(p) -> bool:
""" Pile ou face biaisé, True avec probabilité p et False avec probabilité 1-p."""
return random() < p
[docs]class GroupeClassement(object):
""" Classe pour représentation un groupe de classement."""
last_C_G_COD = 1
[docs] def __init__(self, nbEtudiants: int=100):
self.C_G_COD = self.last_C_G_COD
self.last_C_G_COD += 1
self.nbEtudiants = nbEtudiants
#: le rang le plus haut dans l'ordre d'appel d'un candidat recruté
self.plusHautRangAffecte = randint(1, int(nbEtudiants / 4))
self.rangs: Dict[Candidat, int] = dict()
[docs] def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.C_G_COD}, {self.nbEtudiants}, {self.plusHautRangAffecte})"
[docs] def ajouterCandidat(self, c: Candidat, maxEtapes: int=1000) -> int:
""" Ajoute un candidat et renvoie son rang.
.. warning:: Ici, on ajoute un compteur ``maxEtapes`` pour borner le nombre de tentative aléatoire.
"""
if c in self.rangs:
return self.rangs[c]
etape = 0
while etape < maxEtapes:
rang = randint(1, self.nbEtudiants)
if rang not in self.rangs:
self.rangs[c] = rang
return rang
etape += 1
raise RuntimeError(f"Pas assez d'essai aléatoire dans ajouterCandidat, avec candidat {c}, et un nombre maximum d'étapes = {maxEtapes}.")
[docs]class Etablissement(object):
""" Classe comprenant les caractéristiques d'un établissement (aléatoire)."""
last_G_TI_COD = 1
# Tous les paramètres de la simulation aléatoire
maxNbVoeuxParConcoursCommun = 80
proportionConcoursCommuns = 0.1
nbFormationsParConcours = 100
proportionInternatsCommuns = 0.5
proportionInternats = 0.5
nbFormationsParEtablissement = 5
capaciteMaxInternat = 30
maxNbGroupesParFormation = 5
[docs] def __init__(self, nbEtudiants: int=100):
self.G_TI_COD = self.last_G_TI_COD
self.last_G_TI_COD += 1
self.nbEtudiants = nbEtudiants
self.isConcoursCommun = avecproba(self.proportionConcoursCommuns)
self.formations: List[FormationAffectation] = []
self.jurys: List[GroupeClassement] = []
self.internatsCommuns: Dict[GroupeClassement, GroupeInternat] = dict()
if self.isConcoursCommun:
groupe1 = GroupeClassement(nbEtudiants=self.nbEtudiants)
self.jurys.append(groupe1)
groupe2 = GroupeClassement(nbEtudiants=self.nbEtudiants)
self.jurys.append(groupe2)
nbFormations = randint(1, self.nbFormationsParConcours)
for i in range(nbFormations):
formation = FormationAffectation()
formation.ajouterGroupe(groupe1, self.G_TI_COD, formation.G_TA_COD, self.isConcoursCommun)
formation.ajouterGroupe(groupe2, self.G_TI_COD, formation.G_TA_COD, self.isConcoursCommun)
self.isInternatCommun = False
self.isInternatParFormation = False
else:
self.isInternatCommun = avecproba(self.proportionInternatsCommuns)
self.isInternatParFormation = avecproba(self.proportionInternats)
if self.isInternatCommun:
ifilles = GroupeClassement(nbEtudiants=self.nbEtudiants)
ifillesid = GroupeInternatUID(ifilles.C_G_COD, 0)
self.internatsCommuns[ifilles] = GroupeInternat(
ifillesid,
randint(1, self.capaciteMaxInternat),
randint(0, 100)
)
igarcons = GroupeClassement(nbEtudiants=self.nbEtudiants)
igarconsid = GroupeInternatUID(igarcons.C_G_COD, 0)
self.internatsCommuns[igarcons] = GroupeInternat(
igarconsid,
randint(1, self.capaciteMaxInternat),
randint(0, 100) # FIXME code de réference différent de ifilles ici
)
nbFormations = randint(1, self.nbFormationsParEtablissement)
for i in range(nbFormations):
formation = FormationAffectation()
self.formations.append(formation)
if self.isInternatParFormation:
formation.juryInternat = GroupeClassement(nbEtudiants=self.nbEtudiants)
iid = GroupeInternatUID(
formation.juryInternat.C_G_COD,
formation.G_TA_COD
)
formation.internat = GroupeInternat(
iid,
randint(1, self.capaciteMaxInternat),
randint(0, 100)
)
nbGroupes = randint(1, self.maxNbGroupesParFormation)
for j in range(nbGroupes):
groupe = GroupeClassement(nbEtudiants=self.nbEtudiants)
formation.ajouterGroupe(groupe, self.G_TI_COD, formation.G_TA_COD, self.isConcoursCommun)
self.jurys.append(groupe)
[docs] def __repr__(self) -> str:
return f"{self.__class__.__name__}({self.G_TI_COD}, {self.nbEtudiants}, {self.isConcoursCommun}, {self.formations}, {self.jurys}, {self.internatsCommuns})"
[docs] def capacite(self) -> int:
""" Capacité d'un établissement = somme des capacités de ses formations."""
return sum(formation.capacite() for formation in self.formations)
[docs] def ajouterVoeux(self, candidat: Candidat) -> int:
""" Ajoute un vœu (id du candidat)."""
nbVoeux = 1 + randint(1, self.maxNbVoeuxParConcoursCommun) if self.isConcoursCommun else 1
for _ in range(nbVoeux):
fa = choice(self.formations)
fa.ajouterVoeu(candidat, randbool())
return nbVoeux