ScoDoc/pe_tools.py

959 lines
30 KiB
Python

# -*- mode: python -*-
# -*- coding: utf-8 -*-
##############################################################################
#
# Gestion scolarite IUT
#
# Copyright (c) 1999 - 2021 Emmanuel Viennet. All rights reserved.
#
# 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
#
##############################################################################
##############################################################################
# Module "Avis de poursuite d'étude"
# conçu et développé par Cléo Baras (IUT de Grenoble)
##############################################################################
"""
Created on Thu Sep 8 09:36:33 2016
@author: barasc
"""
from __future__ import print_function
import os
import datetime
import operator
import re
import unicodedata
import sco_utils as scu
from notes_log import log
import notes_table
PE_DEBUG = 0
if not PE_DEBUG:
# log to notes.log
def pe_print(*a, **kw):
# kw is ignored. log always add a newline
log(" ".join(a))
else:
pe_print = print # print function
# Generated LaTeX files are encoded as:
PE_LATEX_ENCODING = "utf-8"
REP_DEFAULT_AVIS = "config/doc_poursuites_etudes/"
PE_DEFAULT_AVIS_LATEX_TMPL = REP_DEFAULT_AVIS + "distrib/modeles/un_avis.tex"
PE_LOCAL_AVIS_LATEX_TMPL = REP_DEFAULT_AVIS + "local/modeles/un_avis.tex"
PE_DEFAULT_FOOTER_TMPL = REP_DEFAULT_AVIS + "distrib/modeles/un_footer.tex"
PE_LOCAL_FOOTER_TMPL = REP_DEFAULT_AVIS + "local/modeles/un_footer.tex"
# ----------------------------------------------------------------------------------------
# ----------------------------------------------------------------------------------------
def print_semestres_description(sems, avec_affichage_debug=False):
"""Dediee a l'affichage d'un semestre pour debug du module"""
def chaine_semestre(sem):
desc = (
"S"
+ str(sem["semestre_id"])
+ " "
+ sem["modalite"]
+ " "
+ sem["anneescolaire"]
)
desc += " (" + sem["annee_debut"] + "/" + sem["annee_fin"] + ") "
desc += sem["formation_id"] + " / " + sem["formsemestre_id"]
desc += " - " + sem["titre_num"]
return desc
if avec_affichage_debug == True:
if isinstance(sems, list):
for sem in sems:
pe_print(chaine_semestre(sem))
else:
pe_print(chaine_semestre(sems))
# ----------------------------------------------------------------------------------------
def calcul_age(born):
"""Calcule l'age à partir de la date de naissance sous forme d'une chaine de caractère 'jj/mm/aaaa'.
Aucun test de validité sur le format de la date n'est fait.
"""
if not isinstance(born, str) or born == "":
return ""
donnees = born.split("/")
naissance = datetime.datetime(int(donnees[2]), int(donnees[1]), int(donnees[0]))
today = datetime.date.today()
return (
today.year
- naissance.year
- ((today.month, today.day) < (naissance.month, naissance.day))
)
# ----------------------------------------------------------------------------------------
def remove_accents(input_unicode_str):
"""Supprime les accents d'une chaine unicode"""
nfkd_form = unicodedata.normalize("NFKD", input_unicode_str)
only_ascii = nfkd_form.encode("ASCII", "ignore")
return only_ascii
def escape_for_latex(s):
"""Protège les caractères pour inclusion dans du source LaTeX"""
if not s:
return ""
conv = {
"&": r"\&",
"%": r"\%",
"$": r"\$",
"#": r"\#",
"_": r"\_",
"{": r"\{",
"}": r"\}",
"~": r"\textasciitilde{}",
"^": r"\^{}",
"\\": r"\textbackslash{}",
"<": r"\textless ",
">": r"\textgreater ",
}
exp = re.compile(
"|".join(
re.escape(unicode(key))
for key in sorted(conv.keys(), key=lambda item: -len(item))
)
)
return exp.sub(lambda match: conv[match.group()], s)
# ----------------------------------------------------------------------------------------
def list_directory_filenames(path):
"""List of regular filenames in a directory (recursive)
Excludes files and directories begining with .
"""
R = []
for root, dirs, files in os.walk(path, topdown=True):
dirs[:] = [d for d in dirs if d[0] != "."]
R += [os.path.join(root, fn) for fn in files if fn[0] != "."]
return R
def add_local_file_to_zip(zipfile, ziproot, pathname, path_in_zip):
"""Read pathname server file and add content to zip under path_in_zip"""
rooted_path_in_zip = os.path.join(ziproot, path_in_zip)
data = open(pathname).read()
zipfile.writestr(rooted_path_in_zip, data)
def add_pe_stuff_to_zip(context, zipfile, ziproot):
"""Add auxiliary files to (already opened) zip
Put all local files found under config/doc_poursuites_etudes/local
and config/doc_poursuites_etudes/distrib
If a file is present in both subtrees, take the one in local.
Also copy logos
"""
PE_AUX_DIR = os.path.join(scu.SCO_SRCDIR, "config/doc_poursuites_etudes")
distrib_dir = os.path.join(PE_AUX_DIR, "distrib")
distrib_pathnames = list_directory_filenames(
distrib_dir
) # eg /opt/scodoc/Products/ScoDoc/config/doc_poursuites_etudes/distrib/modeles/toto.tex
l = len(distrib_dir)
distrib_filenames = {x[l + 1 :] for x in distrib_pathnames} # eg modeles/toto.tex
local_dir = os.path.join(PE_AUX_DIR, "local")
local_pathnames = list_directory_filenames(local_dir)
l = len(local_dir)
local_filenames = {x[l + 1 :] for x in local_pathnames}
for filename in distrib_filenames | local_filenames:
if filename in local_filenames:
add_local_file_to_zip(
zipfile, ziproot, os.path.join(local_dir, filename), "avis/" + filename
)
else:
add_local_file_to_zip(
zipfile,
ziproot,
os.path.join(distrib_dir, filename),
"avis/" + filename,
)
# Logos: (add to logos/ directory in zip)
logos_names = ["logo_header.jpg", "logo_footer.jpg"]
for f in logos_names:
logo = os.path.join(scu.SCODOC_LOGOS_DIR, f)
if os.path.isfile(logo):
add_local_file_to_zip(zipfile, ziproot, logo, "avis/logos/" + f)
# ----------------------------------------------------------------------------------------
# Variable pour le debug des avislatex (en squeezant le calcul du jury souvent long)
JURY_SYNTHESE_POUR_DEBUG = {
"EID1810": {
"nom": "ROUX",
"entree": "2016",
"civilite_str": "M.",
"promo": 2016,
"S2": {
"groupe": {
"informatique": (
13.184230769230767,
0.21666666666666667,
"18",
78,
9.731491508491509,
18.46846153846154,
18.46846153846154,
),
"technique": (
12.975409073359078,
0.6166666666666666,
"16",
78,
9.948540264387688,
18.29285714285714,
18.29285714285714,
),
"pe": (
12.016584900684544,
1.116666666666667,
"20",
78,
9.83147528118408,
17.691755169172936,
17.691755169172936,
),
"mathematiques": (
12.25,
0.1,
"15 ex",
78,
8.45153073717949,
19.0625,
19.0625,
),
"dut": (
12.43750128724589,
1.0,
"19",
78,
10.151630181286441,
17.881104750512645,
17.881104750512645,
),
},
"promo": {
"informatique": (
13.184230769230767,
0.21666666666666667,
"25",
73,
11.696187214611871,
18.51346153846154,
18.51346153846154,
),
"technique": (
12.975409073359078,
0.6166666666666666,
"23",
73,
11.862307379173147,
17.616047267953675,
17.616047267953675,
),
"pe": (
12.016584900684544,
1.116666666666667,
"28",
73,
11.571004424603757,
16.706338951857248,
16.706338951857248,
),
"mathematiques": (
12.25,
0.1,
"18 ex",
73,
10.00886454908676,
19.0625,
19.0625,
),
"dut": (
12.43750128724589,
1.0,
"25",
73,
11.88798432763965,
17.397627309377608,
17.397627309377608,
),
},
},
"S1": {
"groupe": {
"informatique": (
16.064999999999998,
0.16666666666666669,
"11",
82,
11.020296296296294,
19.325999999999997,
19.325999999999997,
),
"technique": (
14.513007894736845,
0.6333333333333333,
"11",
82,
11.195082967479676,
18.309764912280702,
18.309764912280702,
),
"pe": (
13.260301515151516,
1.1,
"19",
82,
10.976036277232245,
17.7460505050505,
17.7460505050505,
),
"mathematiques": (
11.142850000000001,
0.13333333333333333,
"34",
82,
10.314605121951217,
19.75,
19.75,
),
"dut": (
13.54367375,
1.0,
"19",
82,
11.22193801880508,
18.226902529333334,
18.226902529333334,
),
},
"promo": {
"informatique": (
16.064999999999998,
0.16666666666666669,
"15",
73,
13.265276712328768,
19.325999999999997,
19.325999999999997,
),
"technique": (
14.513007894736845,
0.6333333333333333,
"16",
73,
12.996048795361693,
18.309764912280702,
18.309764912280702,
),
"pe": (
13.260301515151516,
1.1,
"25",
73,
12.4107195879539,
17.7460505050505,
17.7460505050505,
),
"mathematiques": (
11.142850000000001,
0.13333333333333333,
"39",
73,
11.320606952054794,
19.75,
19.75,
),
"dut": (
13.54367375,
1.0,
"25",
73,
12.730581289342638,
18.226902529333334,
18.226902529333334,
),
},
},
"4S": {
"groupe": {
"informatique": (
14.84359375,
0.5333333333333333,
"2",
19,
10.69933552631579,
18.28646875,
18.28646875,
),
"pe": (
12.93828572598162,
3.75,
"4",
19,
11.861967145815218,
15.737718967605682,
15.737718967605682,
),
"mathematiques": (None, None, "1 ex", 19, None, None, None),
"ptut": (None, None, "1 ex", 19, None, None, None),
"dut": (
13.511767410105122,
4.0,
"4",
19,
12.573349864933606,
15.781651391587998,
15.781651391587998,
),
},
"promo": {
"informatique": (
16.075,
0.1,
"4",
73,
10.316541095890413,
19.333333333333336,
19.333333333333336,
),
"pe": (
13.52416666666667,
0.49999999999999994,
"13",
73,
11.657102668465479,
16.853208080808084,
16.853208080808084,
),
"mathematiques": (
None,
None,
"55 ex",
73,
7.705091805555555,
19.8,
19.8,
),
"dut": (
14.425416666666665,
1.0,
"12",
73,
13.188168241098825,
16.612613522048612,
16.612613522048612,
),
},
},
"S4": {
"groupe": {
"informatique": (
16.075,
0.1,
"1",
19,
8.799078947368422,
16.075,
16.075,
),
"technique": (
13.835576923076923,
0.4333333333333333,
"4",
19,
12.238304655870447,
16.521153846153847,
16.521153846153847,
),
"pe": (
13.52416666666667,
0.49999999999999994,
"4",
19,
12.292846491228072,
16.25833333333334,
16.25833333333334,
),
"dut": (
14.425416666666665,
1.0,
"6",
19,
13.628367861842106,
15.267566666666665,
15.267566666666665,
),
},
"promo": {
"informatique": (
16.075,
0.1,
"4",
73,
10.316541095890413,
19.333333333333336,
19.333333333333336,
),
"pe": (
13.52416666666667,
0.49999999999999994,
"13",
73,
11.657102668465479,
16.853208080808084,
16.853208080808084,
),
"technique": (
13.835576923076923,
0.4333333333333333,
"11",
73,
12.086685508009952,
17.25909420289855,
17.25909420289855,
),
"mathematiques": (
None,
None,
"55 ex",
73,
7.705091805555555,
19.8,
19.8,
),
"ptut": (
13.5,
0.13333333333333333,
"50",
73,
13.898173515981734,
17.083333333333332,
17.083333333333332,
),
"dut": (
14.425416666666665,
1.0,
"12",
73,
13.188168241098825,
16.612613522048612,
16.612613522048612,
),
},
},
"1A": {
"groupe": {
"informatique": (
14.43673913043478,
0.38333333333333336,
"16",
78,
11.046040002787066,
18.85992173913043,
18.85992173913043,
),
"technique": (
13.754459142857144,
1.25,
"14",
78,
11.179785631638866,
18.493250340136054,
18.493250340136054,
),
"pe": (
12.633767581547854,
2.216666666666667,
"18",
78,
10.912253971396854,
18.39547581699347,
18.39547581699347,
),
"mathematiques": (
11.617342857142857,
0.23333333333333334,
"24",
78,
9.921286855287565,
19.375000000000004,
19.375000000000004,
),
"dut": (
12.990587518622945,
2.0,
"18",
78,
11.2117147027821,
18.391345156695156,
18.391345156695156,
),
},
"promo": {
"informatique": (
13.184230769230767,
0.21666666666666667,
"25",
73,
11.696187214611871,
18.51346153846154,
18.51346153846154,
),
"technique": (
12.975409073359078,
0.6166666666666666,
"23",
73,
11.862307379173147,
17.616047267953675,
17.616047267953675,
),
"pe": (
12.016584900684544,
1.116666666666667,
"28",
73,
11.571004424603757,
16.706338951857248,
16.706338951857248,
),
"mathematiques": (
12.25,
0.1,
"18 ex",
73,
10.00886454908676,
19.0625,
19.0625,
),
"dut": (
12.43750128724589,
1.0,
"25",
73,
11.88798432763965,
17.397627309377608,
17.397627309377608,
),
},
},
"2A": {
"groupe": {
"informatique": (
15.88333333333333,
0.15000000000000002,
"2",
19,
9.805818713450288,
17.346666666666668,
17.346666666666668,
),
"pe": (
13.378513043478259,
1.5333333333333334,
"6",
19,
12.099566454042717,
16.06209927536232,
16.06209927536232,
),
"technique": (
13.965093333333336,
1.1666666666666665,
"5",
19,
12.51068332957394,
16.472092380952386,
16.472092380952386,
),
"mathematiques": (None, None, "1 ex", 19, None, None, None),
"dut": (
14.032947301587301,
2.0,
"4",
19,
13.043386086541773,
15.574706269841268,
15.574706269841268,
),
},
"promo": {
"informatique": (
16.075,
0.1,
"4",
73,
10.316541095890413,
19.333333333333336,
19.333333333333336,
),
"pe": (
13.52416666666667,
0.49999999999999994,
"13",
73,
11.657102668465479,
16.853208080808084,
16.853208080808084,
),
"technique": (
13.835576923076923,
0.4333333333333333,
"11",
73,
12.086685508009952,
17.25909420289855,
17.25909420289855,
),
"mathematiques": (
None,
None,
"55 ex",
73,
7.705091805555555,
19.8,
19.8,
),
"dut": (
14.425416666666665,
1.0,
"12",
73,
13.188168241098825,
16.612613522048612,
16.612613522048612,
),
},
},
"nbSemestres": 4,
"nip": "21414563",
"prenom": "Baptiste",
"age": "21",
"lycee": "PONCET",
"3S": {
"groupe": {
"informatique": (
14.559423076923077,
0.43333333333333335,
"3",
19,
11.137856275303646,
18.8095,
18.8095,
),
"pe": (
12.84815019664546,
3.25,
"4",
19,
11.795678015751701,
15.657624449801428,
15.657624449801428,
),
"technique": (
13.860638395358142,
1.9833333333333334,
"3",
19,
12.395950358235925,
17.340302131732695,
17.340302131732695,
),
"mathematiques": (
11.494044444444445,
0.3,
"6",
19,
9.771571754385965,
14.405358333333334,
14.405358333333334,
),
"dut": (
13.207217657917942,
3.0,
"4",
19,
12.221677199297439,
15.953012966561774,
15.953012966561774,
),
},
"promo": {
"informatique": (15.5, 0.05, "13", 73, 10.52222222222222, 20.0, 20.0),
"pe": (
13.308035483870967,
1.0333333333333334,
"17",
73,
11.854843423685786,
16.191317607526884,
16.191317607526884,
),
"technique": (
14.041625757575758,
0.7333333333333333,
"10",
73,
11.929466899200335,
16.6400384469697,
16.6400384469697,
),
"mathematiques": (
11.0625,
0.06666666666666667,
"40",
73,
11.418430205479451,
19.53,
19.53,
),
"dut": (
13.640477936507937,
1.0,
"14",
73,
12.097377866597594,
16.97088994741667,
16.97088994741667,
),
},
},
"bac": "STI2D",
"S3": {
"groupe": {
"informatique": (15.5, 0.05, "5", 19, 12.842105263157896, 20.0, 20.0),
"pe": (
13.308035483870967,
1.0333333333333334,
"8",
19,
12.339608902093943,
15.967147311827956,
15.967147311827956,
),
"technique": (
14.041625757575758,
0.7333333333333333,
"7",
19,
13.128539816586922,
16.44310151515152,
16.44310151515152,
),
"mathematiques": (
11.0625,
0.06666666666666667,
"6",
19,
9.280921052631578,
16.125,
16.125,
),
"dut": (
13.640477936507937,
1.0,
"8",
19,
12.83638061385213,
15.881845873015871,
15.881845873015871,
),
},
"promo": {
"informatique": (15.5, 0.05, "13", 73, 10.52222222222222, 20.0, 20.0),
"pe": (
13.308035483870967,
1.0333333333333334,
"17",
73,
11.854843423685786,
16.191317607526884,
16.191317607526884,
),
"technique": (
14.041625757575758,
0.7333333333333333,
"10",
73,
11.929466899200335,
16.6400384469697,
16.6400384469697,
),
"mathematiques": (
11.0625,
0.06666666666666667,
"40",
73,
11.418430205479451,
19.53,
19.53,
),
"dut": (
13.640477936507937,
1.0,
"14",
73,
12.097377866597594,
16.97088994741667,
16.97088994741667,
),
},
},
"parcours": [
{
"nom_semestre_dans_parcours": "semestre 4 FAP 2016",
"titreannee": "DUT RT UFA (PPN 2013), semestre 4 FAP 2016",
},
{
"nom_semestre_dans_parcours": "semestre 3 FAP 2015-2016",
"titreannee": "DUT RT UFA (PPN 2013), semestre 3 FAP 2015-2016",
},
{
"nom_semestre_dans_parcours": "semestre 2 FI 2015",
"titreannee": "DUT RT, semestre 2 FI 2015",
},
{
"nom_semestre_dans_parcours": "semestre 1 FI 2014-2015",
"titreannee": "DUT RT, semestre 1 FI 2014-2015",
},
],
}
}