forked from ScoDoc/ScoDoc
placement fait
This commit is contained in:
parent
37484b7fc9
commit
050e54de3e
@ -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 = (
|
||||
|
@ -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("<h3>Placement et émargement des étudiants</h3>")
|
||||
H.append(render_template("forms/placement.html", form=form))
|
||||
H.append(
|
||||
"""<h3>Explications</h3>
|
||||
<ul>
|
||||
<li>préciser les surveillants et la localisation (bâtiment et salle) et indiquer le nombre de colonnes;</li>
|
||||
<li>deux types de placements sont possibles :
|
||||
<ul>
|
||||
<li>continue suppose que les tables ont toutes un numéro unique;</li>
|
||||
<li>coordonnées localise chaque table via un numéro de colonne et un numéro de ligne (ou rangée).</li>
|
||||
</ul></li>
|
||||
<li>Choisir le format du fichier résultat :
|
||||
<ul>
|
||||
<li>le format pdf consiste en un tableau précisant pour chaque étudiant la localisation de sa table;</li>
|
||||
<li>le format xls produit un classeur avec deux onglets:
|
||||
<ul>
|
||||
<li>le premier onglet donne une vue de la salle avec la localisation des étudiants et
|
||||
peut servir de feuille d'émargement;</li>
|
||||
<li>le second onglet est un tableau similaire à celui du fichier pdf;</li>
|
||||
</ul></li>
|
||||
</ul> </li>
|
||||
</ul> """
|
||||
)
|
||||
F = html_sco_header.sco_footer()
|
||||
return "\n".join(H) + "<p>" + 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 (
|
||||
"<h2>Génération du placement impossible pour %s</h2>" % authusername
|
||||
+ """<p>(vérifiez que le semestre n'est pas verrouillé et que vous
|
||||
"<h2>Génération du placement impossible pour %s</h2>" % authusername
|
||||
+ """<p>(vérifiez que le semestre n'est pas verrouillé et que vous
|
||||
avez l'autorisation d'effectuer cette opération)</p>
|
||||
<p><a href="moduleimpl_status?moduleimpl_id=%s">Continuer</a></p>
|
||||
"""
|
||||
% 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 "<p>Aucun groupe sélectionné !</p>"
|
||||
|
||||
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"
|
||||
|
@ -3,7 +3,7 @@
|
||||
{% macro render_field(field) %}
|
||||
<tr>
|
||||
<td class="wtf-field">{{ field.label }}</td>
|
||||
<td class="wtf-field">{{ field(**kwargs)|safe }}
|
||||
<td class="wtf-field">{{ field()|safe }}
|
||||
{% if field.errors %}
|
||||
<ul class=errors>
|
||||
{% for error in field.errors %}
|
||||
@ -18,6 +18,7 @@
|
||||
<div class="saisienote_etape1 form_placement">
|
||||
<form method=post>
|
||||
{{ form.evaluation_id }}
|
||||
{{ form.csrf_token }}
|
||||
<table class="tf">
|
||||
<tbody>
|
||||
{{ render_field(form.surveillants) }}
|
||||
@ -51,6 +52,25 @@
|
||||
<input id="gr_cancel" type=submit value="Annuler">
|
||||
</script>
|
||||
</form>
|
||||
<h3>Explications</h3>
|
||||
<ul>
|
||||
<li>préciser les surveillants et la localisation (bâtiment et salle) et indiquer le nombre de colonnes;</li>
|
||||
<li>deux types de placements sont possibles :
|
||||
<ul>
|
||||
<li>continue suppose que les tables ont toutes un numéro unique;</li>
|
||||
<li>coordonnées localise chaque table via un numéro de colonne et un numéro de ligne (ou rangée).</li>
|
||||
</ul></li>
|
||||
<li>Choisir le format du fichier résultat :
|
||||
<ul>
|
||||
<li>le format pdf consiste en un tableau précisant pour chaque étudiant la localisation de sa table;</li>
|
||||
<li>le format xls produit un classeur avec deux onglets:
|
||||
<ul>
|
||||
<li>le premier onglet donne une vue de la salle avec la localisation des étudiants et
|
||||
peut servir de feuille d'émargement;</li>
|
||||
<li>le second onglet est un tableau similaire à celui du fichier pdf;</li>
|
||||
</ul></li>
|
||||
</ul> </li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
|
@ -1643,7 +1643,6 @@ sco_publish(
|
||||
Permission.ScoEnsView,
|
||||
methods=["GET", "POST"],
|
||||
)
|
||||
sco_publish("/do_placement", sco_placement.do_placement, Permission.ScoEnsView)
|
||||
|
||||
# --- Saisie des notes
|
||||
sco_publish(
|
||||
|
Loading…
Reference in New Issue
Block a user