From 050e54de3ee7c40e57939c79906a086a563e5b5e Mon Sep 17 00:00:00 2001 From: Place Jean-Marie Date: Sat, 11 Sep 2021 18:33:55 +0200 Subject: [PATCH] placement fait --- app/scodoc/sco_evaluations.py | 2 +- app/scodoc/sco_placement.py | 255 ++++++++++++++++------------- app/templates/forms/placement.html | 22 ++- app/views/notes.py | 1 - 4 files changed, 167 insertions(+), 113 deletions(-) diff --git a/app/scodoc/sco_evaluations.py b/app/scodoc/sco_evaluations.py index b9ba65c67..3697d598a 100644 --- a/app/scodoc/sco_evaluations.py +++ b/app/scodoc/sco_evaluations.py @@ -1046,7 +1046,7 @@ def evaluation_describe(evaluation_id="", edit_in_place=True): resp = u["prenomnom"] nomcomplet = u["nomcomplet"] can_edit = sco_permissions_check.can_edit_notes( - current_user, moduleimpl_id, allow_ens=False + , moduleimpl_id, allow_ens=False ) link = ( diff --git a/app/scodoc/sco_placement.py b/app/scodoc/sco_placement.py index 75ec9437e..9f63a6ecf 100644 --- a/app/scodoc/sco_placement.py +++ b/app/scodoc/sco_placement.py @@ -111,7 +111,7 @@ class PlacementForm(FlaskForm): ) submit = SubmitField("OK") - def _set_evaluation_infos(self, evaluation_id): + def set_evaluation_infos(self, evaluation_id): eval_data = sco_evaluations.do_evaluation_list({"evaluation_id": evaluation_id}) if not eval_data: raise ScoValueError("invalid evaluation_id") @@ -146,7 +146,7 @@ def placement_eval_selectetuds(evaluation_id, REQUEST=None): request.form, data={"evaluation_id": int(evaluation_id), "groups": PlacementForm.TOUS}, ) - form._set_evaluation_infos(evaluation_id) + form.set_evaluation_infos(evaluation_id) if form.validate_on_submit(): exec_placement(form) return flask.redirect(titi()) @@ -154,27 +154,6 @@ def placement_eval_selectetuds(evaluation_id, REQUEST=None): H.append(sco_evaluations.evaluation_describe(evaluation_id=evaluation_id)) H.append("

Placement et émargement des étudiants

") H.append(render_template("forms/placement.html", form=form)) - H.append( - """

Explications

- """ - ) F = html_sco_header.sco_footer() return "\n".join(H) + "

" + F @@ -323,17 +302,17 @@ def do_placement_selectetuds(): for x in group_ids ] query = ( - "evaluation_id=%s&placement_method=%s&teachers=%s&building=%s&room=%s&columns=%s&numbering=%s&" - % ( - evaluation_id, - placement_method, - teachers, - building, - room, - columns, - numbering, - ) - + "&".join(gs) + "evaluation_id=%s&placement_method=%s&teachers=%s&building=%s&room=%s&columns=%s&numbering=%s&" + % ( + evaluation_id, + placement_method, + teachers, + building, + room, + columns, + numbering, + ) + + "&".join(gs) ) return flask.redirect(scu.NotesURL() + "/do_placement?" + query) else: @@ -342,45 +321,78 @@ def do_placement_selectetuds(): ) -def do_placement(REQUEST): - """ - Choisi le placement - """ - authuser = REQUEST.AUTHENTICATED_USER - authusername = str(authuser) +def exec_placement(form): try: - evaluation_id = int(REQUEST.form["evaluation_id"]) + evaluation_id = int(form["evaluation_id"].data) except: raise ScoValueError( "Formulaire incomplet ! Vous avez sans doute attendu trop longtemps, veuillez vous reconnecter. Si le problème persiste, contacter l'administrateur. Merci." ) - E = sco_evaluations.do_evaluation_list({"evaluation_id": evaluation_id})[0] + eval_data = sco_evaluations.do_evaluation_list({"evaluation_id": evaluation_id})[0] # Check access # (admin, respformation, and responsable_id) - if not sco_permissions_check.can_edit_notes(authuser, E["moduleimpl_id"]): + if not sco_permissions_check.can_edit_notes( + current_user, eval_data["moduleimpl_id"] + ): return ( - "

Génération du placement impossible pour %s

" % authusername - + """

(vérifiez que le semestre n'est pas verrouillé et que vous + "

Génération du placement impossible pour %s

" % authusername + + """

(vérifiez que le semestre n'est pas verrouillé et que vous avez l'autorisation d'effectuer cette opération)

Continuer

""" - % E["moduleimpl_id"] + % E["moduleimpl_id"] ) + plan = repartition(form, eval_data) + breakpoint() + sem_preferences = sco_preferences.SemPreferences() + space = sem_preferences.get("feuille_placement_emargement") + maxlines = sem_preferences.get("feuille_placement_positions") + + +def repartition(form, eval_data): + """ + Calcule le placement. retourne une liste de couples ((nom, prenom), position) + """ cnx = ndb.GetDBConnexion() # Infos transmises - placement_method = REQUEST.form["placement_method"] - teachers = REQUEST.form["teachers"] - building = REQUEST.form["building"] - room = REQUEST.form["room"] - columns = REQUEST.form["columns"] - numbering = REQUEST.form["numbering"] + evaluation_id = form["evaluation_id"].data + etiquetage = form["etiquetage"].data + teachers = form["surveillants"].data + building = form["batiment"].data + room = form["salle"].data + nb_rangs = form["nb_rangs"].data + group_ids = form["groups"].data # Construit liste des etudiants - group_ids = REQUEST.form.get("group_ids", []) groups = sco_groups.listgroups(group_ids) gr_title_filename = sco_groups.listgroups_filename(groups) # gr_title = sco_groups.listgroups_abbrev(groups) + moduleimpl_data = sco_moduleimpl.do_moduleimpl_list( + moduleimpl_id=eval_data["moduleimpl_id"] + )[0] + Mod = sco_edit_module.do_module_list( + args={"module_id": moduleimpl_data["module_id"]} + )[0] + sem = sco_formsemestre.get_formsemestre(moduleimpl_data["formsemestre_id"]) + evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(eval_data["jour"])) + if eval_data["description"]: + evaltitre = eval_data["description"] + else: + evaltitre = "évaluation du %s" % eval_data["jour"] + + desceval = [ + ["%s" % sem["titreannee"]], + ["Module : %s - %s" % (Mod["code"], Mod["abbrev"])], + ["Surveillants : %s" % teachers], + ["Batiment : %s - Salle : %s" % (building, room)], + ["Controle : %s (coef. %g)" % (evaltitre, eval_data["coefficient"])] + ] # une liste de liste de chaines: description de l'evaluation + listetud = build_listetud(cnx, groups, evaluation_id, moduleimpl_data) + return affectation_places(listetud, etiquetage, nb_rangs) + + +def build_listetud(cnx, groups, evaluation_id, moduleimpl_data): if None in [g["group_name"] for g in groups]: # tous les etudiants getallstudents = True gr_title_filename = "tous" @@ -389,47 +401,70 @@ def do_placement(REQUEST): etudids = sco_groups.do_evaluation_listeetuds_groups( evaluation_id, groups, getallstudents=getallstudents, include_dems=True ) - if not etudids: - return "

Aucun groupe sélectionné !

" - - M = sco_moduleimpl.do_moduleimpl_list(moduleimpl_id=E["moduleimpl_id"])[0] - Mod = sco_edit_module.do_module_list(args={"module_id": M["module_id"]})[0] - sem = sco_formsemestre.get_formsemestre(M["formsemestre_id"]) - evalname = "%s-%s" % (Mod["code"], ndb.DateDMYtoISO(E["jour"])) - if E["description"]: - evaltitre = E["description"] - else: - evaltitre = "évaluation du %s" % E["jour"] - - desceval = [] # une liste de liste de chaines: description de l'evaluation - desceval.append(["%s" % sem["titreannee"]]) - desceval.append(["Module : %s - %s" % (Mod["code"], Mod["abbrev"])]) - desceval.append(["Surveillants : %s" % teachers]) - desceval.append(["Batiment : %s - Salle : %s" % (building, room)]) - desceval.append(["Controle : %s (coef. %g)" % (evaltitre, E["coefficient"])]) - listetud = [] # liste de couples (nom,prenom) for etudid in etudids: # infos identite etudiant (xxx sous-optimal: 1/select par etudiant) ident = sco_etud.etudident_list(cnx, {"etudid": etudid})[0] # infos inscription inscr = sco_formsemestre_inscriptions.do_formsemestre_inscription_list( - {"etudid": etudid, "formsemestre_id": M["formsemestre_id"]} + {"etudid": etudid, "formsemestre_id": moduleimpl_data["formsemestre_id"]} )[0] if inscr["etat"] != "D": nom = ident["nom"].upper() prenom = ident["prenom"].lower().capitalize() listetud.append((nom, prenom)) random.shuffle(listetud) + return listetud - sem_preferences = sco_preferences.SemPreferences() - space = sem_preferences.get("feuille_placement_emargement") - maxlines = sem_preferences.get("feuille_placement_positions") - if placement_method == "xls": +class DistributeurContinu: + """Distribue les places selon un ordre numérique.""" + + def __init(self): + self.position = 1 + + def suivant(self): + retour = self.position + self.position += 1 + return retour + + +class Distributeur2D: + """Distribue les places selon des coordonnées sur nb_rangs.""" + + def __init__(self, nb_rangs): + self.nb_rangs = nb_rangs + self.rang = 1 + self.index = 1 + + def suivant(self): + retour = (self.index, self.rang) + self.rang += 1 + if self.rang > self.nb_rangs: + self.rang = 1 + self.index += 1 + return retour + + +def affectation_places(listetud, etiquetage, nb_rangs=1): + affectation = [] + if etiquetage == "continu": + distributeur = DistributeurContinu() + else: + distributeur = Distributeur2D(nb_rangs) + for etud in listetud: + affectation.append((etud, distributeur.suivant())) + return affectation + + +def production_xls(file_format, eval_dat, plan): + + +def production(file_format, eval_dat, plan): + if file_format == "xls": filename = f"placement_{evalname}_{gr_title_filename}{scu.XLSX_SUFFIX}" xls = _excel_feuille_placement( - E, desceval, listetud, columns, space, maxlines, building, room, numbering + eval_data, desceval, listetud, columns, space, maxlines, building, room, numbering ) return sco_excel.send_excel_file(REQUEST, xls, filename) else: @@ -495,8 +530,8 @@ def do_placement(REQUEST): rows=rows, filename=filename, origin="Généré par %s le " % sco_version.SCONAME - + scu.timedate_human_repr() - + "", + + scu.timedate_human_repr() + + "", pdf_title=pdf_title, # pdf_shorttitle = '', preferences=sco_preferences.SemPreferences(M["formsemestre_id"]), @@ -669,16 +704,16 @@ def _titres(ws, description, evaluation, building, room, styles): def _feuille0( - ws0, - description, - evaluation, - styles, - numbering, - listetud, - nbcolumns, - building, - room, - space, + ws0, + description, + evaluation, + styles, + numbering, + listetud, + nbcolumns, + building, + room, + space, ): _titres(ws0, description, evaluation, building, room, styles) # entetes colonnes - feuille0 @@ -766,16 +801,16 @@ def _next_page(ws): def _feuille1( - ws, - description, - evaluation, - styles, - numbering, - maxlines, - nbcolumns, - building, - room, - listetud, + ws, + description, + evaluation, + styles, + numbering, + maxlines, + nbcolumns, + building, + room, + listetud, ): # etudiants - feuille1 # structuration: @@ -832,15 +867,15 @@ def _feuille1( def _excel_feuille_placement( - evaluation, - description, - listetud, - columns, - space, - maxlines, - building, - room, - numbering, + evaluation, + description, + listetud, + columns, + space, + maxlines, + building, + room, + numbering, ): """Genere feuille excel pour placement des etudiants. E: evaluation (dict) @@ -862,7 +897,7 @@ def _excel_feuille_placement( ws0.set_column_dimension_width("A", 750 * column_width_ratio) for col in range(nbcolumns): ws0.set_column_dimension_width( - "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[col + 1 : col + 2], width + "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[col + 1: col + 2], width ) SheetName1 = "Positions" diff --git a/app/templates/forms/placement.html b/app/templates/forms/placement.html index 53bfe534b..1c5ca544e 100644 --- a/app/templates/forms/placement.html +++ b/app/templates/forms/placement.html @@ -3,7 +3,7 @@ {% macro render_field(field) %} {{ field.label }} - {{ field(**kwargs)|safe }} + {{ field()|safe }} {% if field.errors %}