forked from ScoDoc/ScoDoc
Editeur de partitions: liens vers outil de répartition
This commit is contained in:
parent
6c6d1103e6
commit
04a8177d12
@ -1332,17 +1332,6 @@ def groups_auto_repartition(partition: Partition):
|
||||
),
|
||||
]
|
||||
|
||||
H = [
|
||||
f"""<h2>Répartition des groupes de {partition.partition_name}</h2>
|
||||
<p>Semestre {formsemestre.titre_annee()}</p>
|
||||
<p class="help">Les groupes existants seront <b>effacés</b> et remplacés par
|
||||
ceux créés ici. La répartition aléatoire tente d'uniformiser le niveau
|
||||
des groupes (en utilisant la dernière moyenne générale disponible pour
|
||||
chaque étudiant) et de maximiser la mixité de chaque groupe.
|
||||
</p>
|
||||
""",
|
||||
]
|
||||
|
||||
tf = TrivialFormulator(
|
||||
request.base_url,
|
||||
scu.get_request_args(),
|
||||
@ -1354,58 +1343,59 @@ def groups_auto_repartition(partition: Partition):
|
||||
)
|
||||
if tf[0] == 0:
|
||||
return render_template(
|
||||
"sco_page.j2",
|
||||
title="Répartition des groupes",
|
||||
content="\n".join(H) + "\n" + tf[1],
|
||||
"formsemestre/groups_auto_repartition.j2",
|
||||
title="Répartition dans des groupes",
|
||||
form_html=tf[1],
|
||||
partition=partition,
|
||||
sco=ScoData(formsemestre=formsemestre),
|
||||
)
|
||||
elif tf[0] == -1:
|
||||
if tf[0] == -1:
|
||||
return flask.redirect(dest_url)
|
||||
else:
|
||||
# form submission
|
||||
log(f"groups_auto_repartition({partition})")
|
||||
group_names = tf[2]["groupNames"]
|
||||
group_names = sorted({x.strip() for x in group_names.split(",")})
|
||||
# Détruit les groupes existant de cette partition
|
||||
for group in partition.groups:
|
||||
db.session.delete(group)
|
||||
db.session.commit()
|
||||
# Crée les nouveaux groupes
|
||||
groups = []
|
||||
for group_name in group_names:
|
||||
if group_name.strip():
|
||||
groups.append(partition.create_group(group_name))
|
||||
#
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||
identdict = nt.identdict
|
||||
# build: { civilite : liste etudids trie par niveau croissant }
|
||||
civilites = {x["civilite"] for x in identdict.values()}
|
||||
listes = {}
|
||||
|
||||
# form submission
|
||||
log(f"groups_auto_repartition({partition})")
|
||||
group_names = tf[2]["groupNames"]
|
||||
group_names = sorted({x.strip() for x in group_names.split(",")})
|
||||
# Détruit les groupes existant de cette partition
|
||||
for group in partition.groups:
|
||||
db.session.delete(group)
|
||||
db.session.commit()
|
||||
# Crée les nouveaux groupes
|
||||
groups = []
|
||||
for group_name in group_names:
|
||||
if group_name.strip():
|
||||
groups.append(partition.create_group(group_name))
|
||||
#
|
||||
nt: NotesTableCompat = res_sem.load_formsemestre_results(formsemestre)
|
||||
identdict = nt.identdict
|
||||
# build: { civilite : liste etudids trie par niveau croissant }
|
||||
civilites = {x["civilite"] for x in identdict.values()}
|
||||
listes = {}
|
||||
for civilite in civilites:
|
||||
listes[civilite] = [
|
||||
(_get_prev_moy(x["etudid"], formsemestre.id), x["etudid"])
|
||||
for x in identdict.values()
|
||||
if x["civilite"] == civilite
|
||||
]
|
||||
listes[civilite].sort()
|
||||
log("listes[%s] = %s" % (civilite, listes[civilite]))
|
||||
# affect aux groupes:
|
||||
n = len(identdict)
|
||||
igroup = 0
|
||||
nbgroups = len(groups)
|
||||
while n > 0:
|
||||
log(f"n={n}")
|
||||
for civilite in civilites:
|
||||
listes[civilite] = [
|
||||
(_get_prev_moy(x["etudid"], formsemestre.id), x["etudid"])
|
||||
for x in identdict.values()
|
||||
if x["civilite"] == civilite
|
||||
]
|
||||
listes[civilite].sort()
|
||||
log("listes[%s] = %s" % (civilite, listes[civilite]))
|
||||
# affect aux groupes:
|
||||
n = len(identdict)
|
||||
igroup = 0
|
||||
nbgroups = len(groups)
|
||||
while n > 0:
|
||||
log(f"n={n}")
|
||||
for civilite in civilites:
|
||||
log(f"civilite={civilite}")
|
||||
if len(listes[civilite]):
|
||||
n -= 1
|
||||
etudid = listes[civilite].pop()[1]
|
||||
group = groups[igroup]
|
||||
igroup = (igroup + 1) % nbgroups
|
||||
log(f"in {etudid} in group {group.id}")
|
||||
change_etud_group_in_partition(etudid, group)
|
||||
log(f"{etudid} in group {group.id}")
|
||||
return flask.redirect(dest_url)
|
||||
log(f"civilite={civilite}")
|
||||
if len(listes[civilite]):
|
||||
n -= 1
|
||||
etudid = listes[civilite].pop()[1]
|
||||
group = groups[igroup]
|
||||
igroup = (igroup + 1) % nbgroups
|
||||
log(f"in {etudid} in group {group.id}")
|
||||
change_etud_group_in_partition(etudid, group)
|
||||
log(f"{etudid} in group {group.id}")
|
||||
return flask.redirect(dest_url)
|
||||
|
||||
|
||||
def _get_prev_moy(etudid: int, formsemestre_id: int) -> float | str:
|
||||
|
@ -309,7 +309,7 @@ body.editionActivated .filtres>div>div>div>div {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#zonePartitions span.editing a {
|
||||
#zonePartitions span.editing a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
@ -400,7 +400,7 @@ body.editionActivated .filtres .nonEditable .move {
|
||||
/*****************************/
|
||||
/* Zone Etudiants */
|
||||
/*****************************/
|
||||
#zoneChoix summary{
|
||||
#zoneChoix summary {
|
||||
margin: 0 0 16px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@ -450,6 +450,7 @@ body.editionActivated .filtres .nonEditable .move {
|
||||
margin-bottom: 4px;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
#zoneChoix .autoAffectation .progress {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
@ -524,7 +525,8 @@ body.editionActivated .filtres .nonEditable .move {
|
||||
}
|
||||
|
||||
#zoneChoix .etudiants .partition>div,
|
||||
#zoneChoix .etudiants .partition span {
|
||||
#zoneChoix .etudiants .partition span,
|
||||
div.partition-name {
|
||||
display: block;
|
||||
padding: 4px 8px;
|
||||
border: 1px solid #aaa;
|
||||
@ -541,12 +543,22 @@ body.editionActivated .filtres .nonEditable .move {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#zoneChoix .etudiants .partition>:nth-child(1) {
|
||||
#zoneChoix .etudiants .partition>:nth-child(1),
|
||||
div.partition-name {
|
||||
background: #09c;
|
||||
border-color: #09c;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
div.partition-name {
|
||||
display: inline-block;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
div.partition-name a {
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
section:not(#zonePartitions) .hide {
|
||||
display: none !important;
|
||||
}
|
||||
|
30
app/templates/formsemestre/groups_auto_repartition.j2
Normal file
30
app/templates/formsemestre/groups_auto_repartition.j2
Normal file
@ -0,0 +1,30 @@
|
||||
{# Formulaire répartition auto dans les groupes #}
|
||||
|
||||
{% extends "sco_page.j2" %}
|
||||
|
||||
{% block app_content %}
|
||||
|
||||
<h2>Répartition des groupes de {{partition.partition_name}}</h2>
|
||||
|
||||
<div class="scobox">
|
||||
<div class="scobox-title">Semestre {{sco.formsemestre.titre_annee()}}</div>
|
||||
|
||||
<div class="help space-after-24 space-before-24">
|
||||
💡Les groupes existants dans cette partition seront <b>effacés</b> et remplacés
|
||||
par ceux créés ici. La répartition aléatoire tente d'uniformiser le niveau des
|
||||
groupes (en utilisant la dernière moyenne générale disponible pour chaque
|
||||
étudiant) et de maximiser la mixité de chaque groupe.
|
||||
</div>
|
||||
|
||||
{{form_html|safe}}
|
||||
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a class="stdlink" href="{{
|
||||
url_for('scolar.partition_editor',
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=sco.formsemestre.id)
|
||||
}}">Retour à l'éditeur de partitions</a>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
@ -52,7 +52,23 @@
|
||||
<details>
|
||||
<summary>Outils d'affectation</summary>
|
||||
<div class="autoAffectation">
|
||||
<a href="students_groups_auto_assignment?formsemestre_id={{formsemestre.id}}"><svg
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||||
stroke="#0b0b0b" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M13.8 12H3" />
|
||||
</svg> Répartir les étudiants dans les groupes
|
||||
<div id="partitionsARepartir">
|
||||
{# peuplé en js par listeGroupesRepartition()
|
||||
<div class="partition-name"><a href="">TD</a></div>
|
||||
<div class="partition-name"><a href="">groupes de projets</a></div>
|
||||
#}
|
||||
</div>
|
||||
</div>
|
||||
<div class="autoAffectation">
|
||||
<a href="{{
|
||||
url_for('scolar.students_groups_auto_assignment',
|
||||
scodoc_dept=g.scodoc_dept, formsemestre_id=formsemestre.id
|
||||
)}}"><svg
|
||||
xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none"
|
||||
stroke="#0b0b0b" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4M10 17l5-5-5-5M13.8 12H3" />
|
||||
@ -134,6 +150,7 @@
|
||||
processDatas(partitions, etudiants);
|
||||
processEvents();
|
||||
listeGroupesAutoaffectation();
|
||||
listeGroupesRepartition();
|
||||
|
||||
document.querySelector("body").classList.add("loaded");
|
||||
document.querySelector('.wait').style.display = "none";
|
||||
@ -354,6 +371,19 @@
|
||||
|
||||
}
|
||||
|
||||
function listeGroupesRepartition() { // peuple la liste des partitions pour répartition auto
|
||||
let output = '';
|
||||
document.querySelectorAll('#zonePartitions .filtres>[data-idpartition]').forEach(partition => {
|
||||
if (!partition.classList.contains('nonEditable')) {
|
||||
output += `
|
||||
<div class="partition-name">
|
||||
<a href="groups_auto_repartition/${partition.dataset.idpartition}">${partition.children[0].children[1].innerText}
|
||||
</a></div>`;
|
||||
}
|
||||
});
|
||||
document.querySelector("#partitionsARepartir").innerHTML = output;
|
||||
}
|
||||
|
||||
/******************************/
|
||||
/* Gestionnaire d'événements */
|
||||
/******************************/
|
||||
@ -677,6 +707,7 @@
|
||||
</div>`;
|
||||
|
||||
listeGroupesAutoaffectation();
|
||||
listeGroupesRepartition();
|
||||
})
|
||||
.catch(error => {
|
||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (1).</h2>";
|
||||
@ -730,6 +761,7 @@
|
||||
// divGroupe.querySelector(".modif").click();
|
||||
|
||||
listeGroupesAutoaffectation();
|
||||
listeGroupesRepartition();
|
||||
})
|
||||
.catch(error => {
|
||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (4).</h2>";
|
||||
@ -811,6 +843,7 @@
|
||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (2).</h2>";
|
||||
}
|
||||
listeGroupesAutoaffectation();
|
||||
listeGroupesRepartition();
|
||||
})
|
||||
.catch(error => {
|
||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (3).</h2>";
|
||||
@ -924,6 +957,7 @@
|
||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (6).</h2>";
|
||||
}
|
||||
listeGroupesAutoaffectation();
|
||||
listeGroupesRepartition();
|
||||
})
|
||||
}
|
||||
|
||||
@ -1038,6 +1072,7 @@
|
||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (6).</h2>";
|
||||
}
|
||||
listeGroupesAutoaffectation();
|
||||
listeGroupesRepartition();
|
||||
})
|
||||
.catch(error => {
|
||||
document.querySelector("main").innerHTML = "<h2>Une erreur s'est produite lors de la sauvegarde des données (7).</h2>";
|
||||
|
@ -1,3 +1,7 @@
|
||||
{%- extends 'sco_page.j2' -%}
|
||||
|
||||
{% block styles %}
|
||||
{{super()}}
|
||||
<style>
|
||||
.wait {
|
||||
position: fixed;
|
||||
@ -212,7 +216,10 @@
|
||||
z-index: 1;
|
||||
}
|
||||
</style>
|
||||
{% endblock %}
|
||||
|
||||
|
||||
{% block app_content %}
|
||||
<main class="moitemoite">
|
||||
<div class="wait"></div>
|
||||
<section>
|
||||
@ -249,6 +256,11 @@
|
||||
|
||||
</main>
|
||||
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
{{ super() }}
|
||||
|
||||
<script src="{{scu.STATIC_DIR}}/libjs/xlsx-populate-1.21.0.min.js"></script>
|
||||
<script>
|
||||
/************************/
|
||||
@ -858,3 +870,4 @@
|
||||
}
|
||||
|
||||
</script>
|
||||
{% endblock %}
|
@ -1003,15 +1003,12 @@ def partition_editor(formsemestre_id: int, edit_partition=False):
|
||||
@scodoc7func
|
||||
def students_groups_auto_assignment(formsemestre_id: int):
|
||||
"""Répartition auto des groupes"""
|
||||
formsemestre: FormSemestre = FormSemestre.query.get_or_404(formsemestre_id)
|
||||
H = [
|
||||
render_template(
|
||||
"scolar/students_groups_auto_assignment.j2",
|
||||
formsemestre=formsemestre,
|
||||
),
|
||||
]
|
||||
formsemestre = FormSemestre.get_formsemestre(formsemestre_id)
|
||||
return render_template(
|
||||
"sco_page.j2", title="Répartition des groupes", content="\n".join(H)
|
||||
"scolar/students_groups_auto_assignment.j2",
|
||||
formsemestre=formsemestre,
|
||||
title="Répartition des groupes",
|
||||
sco=ScoData(formsemestre=formsemestre),
|
||||
)
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
# -*- mode: python -*-
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
SCOVERSION = "9.7.13"
|
||||
SCOVERSION = "9.7.14"
|
||||
|
||||
SCONAME = "ScoDoc"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user