ScoDoc/app/scodoc/sco_placement.py

738 lines
24 KiB
Python
Raw Normal View History

2020-09-26 16:19:37 +02:00
# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
2021-01-01 17:51:08 +01:00
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
2020-09-26 16:19:37 +02:00
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Emmanuel Viennet emmanuel.viennet@viennet.net
#
##############################################################################
"""ScoDoc: génération feuille émargement et placement
Contribution M. Salomon, UFC / IUT DE BELFORT-MONTBÉLIARD, 2016
"""
2021-07-09 17:47:06 +02:00
import six.moves.urllib.request, six.moves.urllib.parse, six.moves.urllib.error
2021-02-03 22:00:41 +01:00
import random
import time
2021-09-05 14:50:35 +02:00
from copy import copy
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
import wtforms.validators
2021-09-12 07:04:05 +02:00
from flask import request, render_template, url_for
2021-09-05 14:50:35 +02:00
from flask_login import current_user
from werkzeug import Response
from flask_wtf import FlaskForm
from wtforms import (
StringField,
PasswordField,
BooleanField,
SubmitField,
SelectField,
RadioField,
HiddenField,
SelectMultipleField,
validators,
)
from wtforms.validators import ValidationError, DataRequired, Email, EqualTo
2021-08-01 10:16:16 +02:00
from app.scodoc.sco_exceptions import ScoValueError
import app.scodoc.sco_utils as scu
import app.scodoc.notesdb as ndb
from app.scodoc import html_sco_header
from app.scodoc import sco_edit_module
from app.scodoc import sco_evaluations
from app.scodoc import sco_excel
from app.scodoc import sco_formsemestre
from app.scodoc import sco_formsemestre_inscriptions
from app.scodoc import sco_groups
from app.scodoc import sco_moduleimpl
from app.scodoc import sco_permissions_check
from app.scodoc import sco_preferences
from app.scodoc import sco_saisie_notes
from app.scodoc import sco_etud
2021-08-21 17:07:44 +02:00
import sco_version
from app.scodoc.gen_tables import GenTable
from app.scodoc.sco_excel import * # XXX à vérifier
from app.scodoc.TrivialFormulator import TrivialFormulator
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
_ = lambda x: x # sans babel
_l = _
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
class PlacementForm(FlaskForm):
TOUS = "Tous"
evaluation_id = HiddenField("evaluation_id")
file_format = RadioField(
"Format de fichier",
choices=["pdf", "xls"],
validators=[
wtforms.validators.DataRequired("indiquez le format du fichier attendu"),
],
)
surveillants = StringField(
"Surveillants", validators=[wtforms.validators.DataRequired("Test")]
)
batiment = StringField("Batiment")
salle = StringField("Salle")
nb_rangs = SelectField(
"nb_rangs", coerce=int, choices=[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
)
etiquetage = RadioField(
"Numérotation",
choices=["Continue", "Coordonnées"],
validators=[
wtforms.validators.DataRequired("indiquez le style de numérotation"),
],
)
groups = SelectMultipleField(
"Groupe(s)",
validators=[
wtforms.validators.DataRequired("indiquez au moins un groupe"),
],
)
submit = SubmitField("OK")
2021-09-11 18:33:55 +02:00
def set_evaluation_infos(self, evaluation_id):
2021-09-05 14:50:35 +02:00
eval_data = sco_evaluations.do_evaluation_list({"evaluation_id": evaluation_id})
if not eval_data:
raise ScoValueError("invalid evaluation_id")
eval_data = eval_data[0]
# groupes
groups = sco_groups.do_evaluation_listegroupes(
evaluation_id, include_default=True
)
self.groups_tree = {}
self.has_groups = False
for group in groups:
partition = group["partition_name"] or self.TOUS # TODO check required
group_id = group["group_id"]
group_name = group["group_name"] or self.TOUS
if partition not in self.groups_tree:
self.groups_tree[partition] = {}
self.groups_tree[partition][group_name] = group_id
if partition != self.TOUS:
self.has_groups = True
self.groups_tree_length = len(self.groups_tree)
if self.has_groups:
choices = []
for partition in self.groups_tree:
for groupe in self.groups_tree[partition]:
id = str(self.groups_tree[partition][groupe])
choices.append((id, "%s (%s)" % (str(groupe), partition)))
self.groups.choices = choices
2021-09-12 07:04:05 +02:00
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
2021-09-11 19:35:30 +02:00
def placement_eval_selectetuds(evaluation_id):
"""Creation de l'écran de placement"""
2021-09-05 14:50:35 +02:00
form = PlacementForm(
request.form,
data={"evaluation_id": int(evaluation_id), "groups": PlacementForm.TOUS},
)
2021-09-11 18:33:55 +02:00
form.set_evaluation_infos(evaluation_id)
2021-09-05 14:50:35 +02:00
if form.validate_on_submit():
2021-09-12 07:04:05 +02:00
return _exec_placement(form) # calcul et generation du fichier
# return flask.redirect(url_for("scodoc.index"))
2021-09-05 14:50:35 +02:00
H = [html_sco_header.sco_header(init_jquery_ui=True)]
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))
F = html_sco_header.sco_footer()
return "\n".join(H) + "<p>" + F
2021-09-12 07:04:05 +02:00
def _exec_placement(form):
2021-09-11 19:35:30 +02:00
"""Calcul et génération du fichier sur la base des données du formulaire"""
d = {
"evaluation_id": form["evaluation_id"].data,
"etiquetage": form["etiquetage"].data,
"surveillants": form["surveillants"].data,
"batiment": form["batiment"].data,
"salle": form["salle"].data,
"nb_rangs": form["nb_rangs"].data,
2021-09-12 07:04:05 +02:00
"groups_ids": form["groups"].data,
2021-09-11 19:35:30 +02:00
}
2021-09-12 07:04:05 +02:00
d["eval_data"] = sco_evaluations.do_evaluation_list(
{"evaluation_id": d["evaluation_id"]}
)[0]
2021-09-11 19:35:30 +02:00
# Check access (admin, respformation, and responsable_id)
d["current_user"] = current_user
d["moduleimpl_id"] = d["eval_data"]["moduleimpl_id"]
if not sco_permissions_check.can_edit_notes(d["current_user"], d["moduleimpl_id"]):
2021-09-12 07:04:05 +02:00
return """<h2>Génération du placement impossible pour %s</h2>
2021-09-11 19:35:30 +02:00
<p>(vérifiez que le semestre n'est pas verrouillé et que vous
avez l'autorisation d'effectuer cette opération)</p>
2021-09-12 07:04:05 +02:00
<p><a href="moduleimpl_status?moduleimpl_id=%s">Continuer</a></p>
""" % (
d["current_user"].user_name,
d["module_id"],
2020-09-26 16:19:37 +02:00
)
2021-09-11 19:35:30 +02:00
d["cnx"] = ndb.GetDBConnexion()
2021-09-12 07:04:05 +02:00
d["groups"] = sco_groups.listgroups(d["groups_ids"])
d["gr_title_filename"] = sco_groups.listgroups_filename(d["groups"])
2021-09-11 19:35:30 +02:00
# gr_title = sco_groups.listgroups_abbrev(d['groups'])
2021-09-12 07:04:05 +02:00
d["moduleimpl_data"] = sco_moduleimpl.do_moduleimpl_list(
moduleimpl_id=d["moduleimpl_id"]
)[0]
d["Mod"] = sco_edit_module.do_module_list(
args={"module_id": d["moduleimpl_data"]["module_id"]}
)[0]
d["sem"] = sco_formsemestre.get_formsemestre(
d["moduleimpl_data"]["formsemestre_id"]
)
d["evalname"] = "%s-%s" % (
d["Mod"]["code"],
ndb.DateDMYtoISO(d["eval_data"]["jour"]),
)
2021-09-11 19:35:30 +02:00
if d["eval_data"]["description"]:
d["evaltitre"] = d["eval_data"]["description"]
else:
2021-09-12 07:04:05 +02:00
d["evaltitre"] = "évaluation du %s" % d["eval_data"]["jour"]
2021-09-11 19:35:30 +02:00
d["desceval"] = [
["%s" % d["sem"]["titreannee"]],
["Module : %s - %s" % (d["Mod"]["code"], d["Mod"]["abbrev"])],
2021-09-12 07:04:05 +02:00
["Surveillants : %(surveillants)s" % d],
2021-09-11 19:35:30 +02:00
["Batiment : %(batiment)s - Salle : %(salle)s" % d],
["Controle : %s (coef. %g)" % (d["evaltitre"], d["eval_data"]["coefficient"])],
] # une liste de liste de chaines: description de l'evaluation
2021-09-12 07:04:05 +02:00
d["plan"] = _repartition(d)
2021-09-11 19:35:30 +02:00
if form["file_format"].data == "xls":
2021-09-12 07:04:05 +02:00
return _production_xls(d)
2021-09-11 19:35:30 +02:00
else:
2021-09-12 07:04:05 +02:00
return _production_pdf(d)
2021-09-11 18:33:55 +02:00
2021-09-12 07:04:05 +02:00
def _repartition(d):
2021-09-11 18:33:55 +02:00
"""
Calcule le placement. retourne une liste de couples ((nom, prenom), position)
"""
2020-09-26 16:19:37 +02:00
# Construit liste des etudiants
2021-09-12 07:04:05 +02:00
d["groups"] = sco_groups.listgroups(d["groups_ids"])
d["listetud"] = _build_listetud(d)
return _affectation_places(d)
2021-09-11 18:33:55 +02:00
2021-09-12 07:04:05 +02:00
def _build_listetud(d):
if None in [g["group_name"] for g in d["groups"]]: # tous les etudiants
2020-09-26 16:19:37 +02:00
getallstudents = True
gr_title_filename = "tous"
else:
getallstudents = False
etudids = sco_groups.do_evaluation_listeetuds_groups(
2021-09-12 07:04:05 +02:00
d["evaluation_id"],
d["groups"],
getallstudents=getallstudents,
include_dems=True,
2020-09-26 16:19:37 +02:00
)
listetud = [] # liste de couples (nom,prenom)
for etudid in etudids:
# infos identite etudiant (xxx sous-optimal: 1/select par etudiant)
2021-09-12 07:04:05 +02:00
ident = sco_etud.etudident_list(d["cnx"], {"etudid": etudid})[0]
2020-09-26 16:19:37 +02:00
# infos inscription
inscr = sco_formsemestre_inscriptions.do_formsemestre_inscription_list(
2021-09-12 07:04:05 +02:00
{
"etudid": etudid,
"formsemestre_id": d["moduleimpl_data"]["formsemestre_id"],
}
2020-09-26 16:19:37 +02:00
)[0]
if inscr["etat"] != "D":
nom = ident["nom"].upper()
prenom = ident["prenom"].lower().capitalize()
2020-09-26 16:19:37 +02:00
listetud.append((nom, prenom))
random.shuffle(listetud)
2021-09-11 18:33:55 +02:00
return listetud
2021-09-12 07:04:05 +02:00
def _affectation_places(d):
2021-09-11 19:35:30 +02:00
plan = []
if d["etiquetage"] == "continu":
2021-09-12 07:04:05 +02:00
distributeur = _DistributeurContinu()
2021-09-11 18:33:55 +02:00
else:
2021-09-12 07:04:05 +02:00
distributeur = _Distributeur2D(d["nb_rangs"])
2021-09-11 19:35:30 +02:00
for etud in d["listetud"]:
plan.append((etud, distributeur.suivant()))
return plan
2021-09-12 07:04:05 +02:00
def _production_xls(d):
breakpoint()
filename = scu.make_filename("placement_%(evalname)s_%(gr_title_filename)s{scu.XLSX_SUFFIX}" % d)
2021-09-11 19:35:30 +02:00
xls = _excel_feuille_placement(
d["eval_data"],
d["desceval"],
d["listetud"],
d["nb_rangs"],
d["batiment"],
d["salle"],
d["etiquetage"],
)
2021-09-12 07:04:05 +02:00
return sco_excel.send_from_flask(xls, filename)
2021-09-11 18:33:55 +02:00
2020-09-26 16:19:37 +02:00
2021-09-12 07:04:05 +02:00
def _production_pdf(d):
2021-09-11 19:35:30 +02:00
pdf_title = d["desceval"]
pdf_title += (
2021-09-12 07:04:05 +02:00
"Date : %(jour)s - Horaire : %(heure_debut)s à %(heure_fin)s" % d["eval_data"]
2021-09-11 19:35:30 +02:00
)
2020-09-26 16:19:37 +02:00
2021-09-11 19:35:30 +02:00
filename = "placement_%(evalname)s_%(gr_title_filename)s.pdf" % d
titles = {
"nom": "Nom",
"prenom": "Prenom",
"colonne": "Colonne",
"ligne": "Ligne",
"place": "Place",
}
nbcolumns = int(columns)
if numbering == "coordinate":
columns_ids = ["nom", "prenom", "colonne", "ligne"]
2020-09-26 16:19:37 +02:00
else:
2021-09-11 19:35:30 +02:00
columns_ids = ["nom", "prenom", "place"]
2020-09-26 16:19:37 +02:00
2021-09-11 19:35:30 +02:00
# etudiants
line = 1
col = 1
orderetud = []
for etudid in listetud:
2020-09-26 16:19:37 +02:00
if numbering == "coordinate":
2021-09-11 19:35:30 +02:00
orderetud.append((etudid[0], etudid[1], col, line))
2020-09-26 16:19:37 +02:00
else:
2021-09-11 19:35:30 +02:00
orderetud.append((etudid[0], etudid[1], col + (line - 1) * nbcolumns))
2020-09-26 16:19:37 +02:00
2021-09-11 19:35:30 +02:00
if col == nbcolumns:
col = 0
line += 1
col += 1
2020-09-26 16:19:37 +02:00
2021-09-11 19:35:30 +02:00
rows = []
orderetud.sort()
for etudid in orderetud:
if numbering == "coordinate":
rows.append(
{
"nom": etudid[0],
"prenom": etudid[1],
"colonne": etudid[2],
"ligne": etudid[3],
}
)
else:
rows.append({"nom": etudid[0], "prenom": etudid[1], "place": etudid[2]})
tab = GenTable(
titles=titles,
columns_ids=columns_ids,
rows=rows,
filename=filename,
origin="Généré par %s le " % sco_version.SCONAME
2021-09-12 07:04:05 +02:00
+ scu.timedate_human_repr()
+ "",
2021-09-11 19:35:30 +02:00
pdf_title=pdf_title,
# pdf_shorttitle = '',
preferences=sco_preferences.SemPreferences(M["formsemestre_id"]),
# html_generate_cells=False # la derniere ligne (moyennes) est incomplete
)
t = tab.make_page(format="pdf", with_html_headers=False, REQUEST=REQUEST)
return t
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
def _one_header(ws, numbering, styles):
cells = []
if numbering == "coordinate":
cells.append(ws.make_cell("Nom", styles["2bi"]))
cells.append(ws.make_cell("Prénom", styles["2bi"]))
cells.append(ws.make_cell("Colonne", styles["2bi"]))
cells.append(ws.make_cell("Ligne", styles["2bi"]))
else:
cells.append(ws.make_cell("Nom", styles["2bi"]))
cells.append(ws.make_cell("Prénom", styles["2bi"]))
cells.append(ws.make_cell("Place", styles["2bi"]))
return cells
def _headers(ws, numbering, styles, nb_listes):
cells = []
for _ in range(nb_listes):
cells += _one_header(ws, numbering, styles)
cells.append(ws.make_cell(""))
ws.append_row(cells)
def _make_styles(ws0, ws1):
# polices
font0 = Font(name="Calibri", bold=True, size=12)
font1b = copy(font0)
font1b.size = 9
font1i = Font(name="Arial", italic=True, size=10)
font1o = Font(name="Arial", outline=True, size=10)
font2bi = Font(name="Arial", bold=True, italic=True, size=8)
font2 = Font(name="Arial", size=10)
# bordures
side_double = Side(border_style="double", color=COLORS.BLACK.value)
side_thin = Side(border_style="thin", color=COLORS.BLACK.value)
# bordures
border1t = Border(left=side_double, top=side_double, right=side_double)
border1bb = Border(left=side_double, bottom=side_double, right=side_double)
border1bm = Border(left=side_double, right=side_double)
border1m = Border(left=side_double, bottom=side_thin, right=side_double)
border2m = Border(top=side_thin, bottom=side_thin)
border2r = Border(top=side_thin, bottom=side_thin, right=side_thin)
border2l = Border(left=side_thin, top=side_thin, bottom=side_thin)
border2b = Border(left=side_thin, top=side_thin, bottom=side_thin, right=side_thin)
# alignements
align_center_center = Alignment(horizontal="center", vertical="center")
align_right_bottom = Alignment(horizontal="right", vertical="bottom")
align_left_center = Alignment(horizontal="left", vertical="center")
align_right_center = Alignment(horizontal="right", vertical="center")
# patterns
pattern = PatternFill(
fill_type="solid", fgColor=sco_excel.COLORS.LIGHT_YELLOW.value
)
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
# styles
styles = {
"titres": sco_excel.excel_make_style(font_name="Arial", bold=True, size=12),
"1t": ws0.excel_make_composite_style(
font=font0, alignment=align_center_center, border=border1t
),
"1m": ws0.excel_make_composite_style(
font=font1b, alignment=align_center_center, border=border1m
),
"1bm": ws0.excel_make_composite_style(
font=font1b, alignment=align_center_center, border=border1bm
),
"1bb": ws0.excel_make_composite_style(
font=font1o, alignment=align_right_bottom, border=border1bb
),
"2b": ws1.excel_make_composite_style(
font=font1i, alignment=align_center_center, border=border2b
),
"2bi": ws1.excel_make_composite_style(
font=font2bi, alignment=align_center_center, border=border2b, fill=pattern
),
"2l": ws1.excel_make_composite_style(
font=font2, alignment=align_left_center, border=border2l
),
"2m1": ws1.excel_make_composite_style(
font=font2, alignment=align_left_center, border=border2m
),
"2m2": ws1.excel_make_composite_style(
font=font2, alignment=align_right_center, border=border2m
),
"2r": ws1.excel_make_composite_style(
font=font2, alignment=align_right_center, border=border2r
),
}
return styles
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
def _init_lines(maxlines):
return [
[] for _ in range(maxlines)
] # lines[no_ligne] -> liste des cellules de la ligne (no_lignes de 1..maxlines
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
def _write_lines(ws, lines):
for line in lines:
ws.append_row(line)
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
def _titres(ws, description, evaluation, building, room, styles):
2020-09-26 16:19:37 +02:00
dt = time.strftime("%d/%m/%Y a %Hh%M")
2021-09-05 14:50:35 +02:00
ws.append_single_cell_row(
"Feuille placement etudiants éditée le %s" % dt, styles["titres"]
2020-09-26 16:19:37 +02:00
)
2021-09-05 14:50:35 +02:00
for line, desceval in enumerate(description):
if line in [1, 4, 7]:
ws.append_blank_row()
ws.append_single_cell_row(desceval[0], styles["titres"])
ws.append_single_cell_row(
"Date : %s - Horaire : %s à %s"
% (evaluation["jour"], evaluation["heure_debut"], evaluation["heure_fin"]),
styles["titres"],
2020-09-26 16:19:37 +02:00
)
2021-09-05 14:50:35 +02:00
ws.append_single_cell_row(
"Date : %s - Horaire : %s à %s"
% (evaluation["jour"], evaluation["heure_debut"], evaluation["heure_fin"]),
styles["titres"],
)
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
def _feuille0(
2021-09-12 07:04:05 +02:00
ws0,
description,
evaluation,
styles,
numbering,
listetud,
nbcolumns,
building,
room,
space,
2021-09-05 14:50:35 +02:00
):
_titres(ws0, description, evaluation, building, room, styles)
2020-09-26 16:19:37 +02:00
# entetes colonnes - feuille0
2021-09-05 14:50:35 +02:00
cells = [ws0.make_cell()]
2020-09-26 16:19:37 +02:00
for col in range(nbcolumns):
2021-09-05 14:50:35 +02:00
cells.append(ws0.make_cell("colonne %s" % (col + 1), styles["2b"]))
ws0.append_row(cells)
2020-09-26 16:19:37 +02:00
# etudiants
line = 1
col = 1
linetud = []
orderetud = []
placementetud = []
for etudid in listetud:
linetud.append(etudid)
if numbering == "coordinate":
orderetud.append((etudid[0], etudid[1], col, line))
else:
orderetud.append((etudid[0], etudid[1], col + (line - 1) * nbcolumns))
if col == nbcolumns:
placementetud.append(linetud)
linetud = []
col = 0
line += 1
col += 1
if len(linetud) > 0:
placementetud.append(linetud)
# etudiants - feuille0
2021-09-05 14:50:35 +02:00
place = 1
for rang, linetud in enumerate(placementetud, start=1):
# Chaque rang est affiché sur 3 lignes xlsx (notées A, B, C)
# ligne A: le nom, ligne B: le prénom, ligne C: un espace ou la place
cells_a = [ws0.make_cell(rang, styles["2b"])]
cells_b = [ws0.make_cell("", styles["2b"])]
cells_c = [ws0.make_cell("", styles["2b"])]
row = 14 # premieère ligne de signature
2020-09-26 16:19:37 +02:00
for etudid in linetud:
2021-09-05 14:50:35 +02:00
cells_a.append(ws0.make_cell(etudid[0], styles["1t"]))
cells_b.append(ws0.make_cell(etudid[1], styles["1m"]))
2020-09-26 16:19:37 +02:00
if numbering == "coordinate":
2021-09-05 14:50:35 +02:00
cell_c = ws0.make_cell("", styles["1bb"])
2020-09-26 16:19:37 +02:00
else:
2021-09-05 14:50:35 +02:00
cell_c = ws0.make_cell("place %s" % place, styles["1bb"])
cells_c.append(cell_c)
ws0.set_row_dimension_height(row, space / 25)
row += 3
place = place + 1
2020-09-26 16:19:37 +02:00
if col == nbcolumns:
2021-09-05 14:50:35 +02:00
ws0.append_row(cells_a)
ws0.append_row(cells_b)
ws0.append_row(cells_c)
cells_a = [ws0.make_cell(rang, styles["2b"])]
cells_b = [ws0.make_cell("", styles["2b"])]
cells_c = [ws0.make_cell("", styles["2b"])]
# publication du rang final incomplet
ws0.append_row(cells_a)
ws0.append_row(cells_b)
ws0.append_row(cells_c)
ws0.set_row_dimension_height(row, space / 25)
def _compute_ordretud(listetud, nbcolumns, numbering):
orderetud = []
line = 1
col = 1
for etudid in listetud:
if numbering == "coordinate":
orderetud.append((etudid[0], etudid[1], col, line))
else:
orderetud.append(
(etudid[0], etudid[1], "%s" % (col + (line - 1) * nbcolumns))
)
col += 1
if col > nbcolumns:
col = 1
line += 1
orderetud.sort()
return orderetud
2020-09-26 16:19:37 +02:00
2021-09-05 14:50:35 +02:00
def _next_page(ws):
pass
def _feuille1(
2021-09-12 07:04:05 +02:00
ws,
description,
evaluation,
styles,
numbering,
maxlines,
nbcolumns,
building,
room,
listetud,
2021-09-05 14:50:35 +02:00
):
2020-09-26 16:19:37 +02:00
# etudiants - feuille1
2021-09-05 14:50:35 +02:00
# structuration:
# 1 page = maxlistes listes
# 1 liste = 3 ou 4 colonnes(excel) (selon numbering) et (maximum maxlines) lignes
maxlistes = 2 # nombre de listes par page
# computes excel columns widths
2020-09-26 16:19:37 +02:00
if numbering == "coordinate":
2021-09-05 14:50:35 +02:00
gabarit = [16, 18, 6, 6, 2]
2020-09-26 16:19:37 +02:00
else:
2021-09-05 14:50:35 +02:00
gabarit = [16, 18, 12, 2]
widths = []
for _ in range(maxlistes):
widths += gabarit
ws.set_column_dimension_width(value=widths)
nb_etu_restant = len(listetud)
_titres(ws, description, evaluation, building, room, styles)
nb_listes = min(
maxlistes, nb_etu_restant // maxlines + 1
) # nombre de colonnes dans la page
_headers(ws, numbering, styles, nb_listes)
# construction liste alphabétique
# Affichage
lines = _init_lines(maxlines)
orderetud = _compute_ordretud(listetud, nbcolumns, numbering)
2020-09-26 16:19:37 +02:00
line = 0
col = 0
for etudid in orderetud:
2021-09-05 14:50:35 +02:00
# check for skip of list or page
if col > 0: # add a empty cell between lists
lines[line].append(ws.make_cell())
lines[line].append(ws.make_cell(etudid[0], styles["2l"]))
lines[line].append(ws.make_cell(etudid[1], styles["2m1"]))
2020-09-26 16:19:37 +02:00
if numbering == "coordinate":
2021-09-05 14:50:35 +02:00
lines[line].append(ws.make_cell(etudid[2], styles["2m2"]))
lines[line].append(ws.make_cell(etudid[3], styles["2r"]))
2020-09-26 16:19:37 +02:00
else:
2021-09-05 14:50:35 +02:00
lines[line].append(ws.make_cell(etudid[2], styles["2r"]))
line = line + 1
if line >= maxlines: # fin de liste
col = col + 1
2020-09-26 16:19:37 +02:00
line = 0
2021-09-05 14:50:35 +02:00
if col >= maxlistes: # fin de page
_write_lines(ws, lines)
lines = _init_lines(maxlines)
2020-09-26 16:19:37 +02:00
col = 0
2021-09-05 14:50:35 +02:00
ws.append_blank_row()
nb_etu_restant -= maxlistes * maxlines
nb_listes = min(
maxlistes, nb_etu_restant // maxlines + 1
) # nombre de colonnes dans la page
_headers(ws, numbering, styles, nb_listes)
_write_lines(ws, lines)
def _excel_feuille_placement(
2021-09-12 07:04:05 +02:00
evaluation,
description,
listetud,
columns,
building,
room,
numbering,
2021-09-05 14:50:35 +02:00
):
"""Genere feuille excel pour placement des etudiants.
E: evaluation (dict)
lines: liste de tuples
(etudid, nom, prenom, etat, groupe, val, explanation)
"""
2021-09-11 19:35:30 +02:00
sem_preferences = sco_preferences.SemPreferences()
space = sem_preferences.get("feuille_placement_emargement")
maxlines = sem_preferences.get("feuille_placement_positions")
2021-09-05 14:50:35 +02:00
nbcolumns = int(columns)
column_width_ratio = 1 / 250 # changement d unités entre pyExcelerator et openpyxl
wb = ScoExcelBook()
SheetName0 = "Emargement"
ws0 = wb.create_sheet(SheetName0)
# ajuste largeurs colonnes (unite inconnue, empirique)
width = 4500 * column_width_ratio
if nbcolumns > 5:
width = 22500 * column_width_ratio // nbcolumns
ws0.set_column_dimension_width("A", 750 * column_width_ratio)
for col in range(nbcolumns):
ws0.set_column_dimension_width(
2021-09-12 07:04:05 +02:00
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"[col + 1: col + 2], width
2021-09-05 14:50:35 +02:00
)
SheetName1 = "Positions"
ws1 = wb.create_sheet(SheetName1)
styles = _make_styles(ws0, ws1)
_feuille0(
ws0,
description,
evaluation,
styles,
numbering,
listetud,
nbcolumns,
building,
room,
space,
)
_feuille1(
ws1,
description,
evaluation,
styles,
numbering,
maxlines,
nbcolumns,
building,
room,
listetud,
)
return wb.generate()