Referentiels/python/export.py

224 lines
8.6 KiB
Python

import docx2python, yaml
from ressource import *
import logging
__LOGGER = logging.getLogger(__name__)
REPERTOIRE = "import"
DOCUMENT = "000 compilation-ressources 2021-03-29T11_19_03.259Z"
# Ouverture du document
docu = docx2python.docx2python(REPERTOIRE + "/" + DOCUMENT + ".docx")
docu = docu.body
docu[0] # Titre général
docu[1] # Tableau de synthèse des ressources
nbre_ressources = 0
ENTETES = ["Nom", "Code", "Semestre", "formation encadrée", "dont heures de TP",
"SAÉ", "Prérequis", "Descriptif", "Mots"]
def get_indice(champ):
"""Récupère l'indice d'une entête"""
for (i, entete) in enumerate(ENTETES):
if entete in champ:
return i
return None
def get_indice_sans_accent_ni_espace(champ):
"""Récupère l'indice d'une entête en se débarrassant des majuscules/caractères spéciaux/espace"""
champ_purge = supprime_accent_espace(champ)
for (i, entete) in enumerate(ENTETES):
entete_purge = supprime_accent_espace(entete)
if entete_purge in champ_purge:
return i
return None
"""
Format du parsing issu de docx2python
[ # document
[ # table A
[ # table A row
[ # table A cell 1 <-- structure des tableaux
"""
liste_ressources = [] # la liste des ressources telle qu'extrait du docx
print("*Etape 1* : Parsing")
for i in range(2, len(docu)): # A priori un tableau
est_ressource = False
try:
if "Nom de la ressource" in docu[i][0][0][0]: # [03][00][0][0]
est_ressource = True
nbre_ressources += 1
except:
pass
if est_ressource == True:
res = docu[i] # la ressource
nom_ressource = res[0][1][0]
# Création de la ressource
r = Ressource(nom_ressource, res)
liste_ressources.append(r)
# if len(res) != 15:
# __LOGGER.warning(f"Champs en trop ou manquants dans \"{nom_ressource}\"")
# Parsing des données brute de la ressource
data = [None for i in range(len(ENTETES))] # les données attendues Nom, Code, ..., Mots clés
apprentissages = [None for i in range(3)] # les apprentissages des 3 compétences
non_interprete = []
for j in range(len(res)): # parcours des entêtes du tableau décrivant la ressource
ligne = res[j]
if len(ligne) == 2: # ligne de données classique champ => valeur
champ = ligne[0][0] # le nom du champ
i = get_indice_sans_accent_ni_espace(champ) # l'indice de l'entete dans ENTETES
if i != None:
data[i] = "\n".join(res[j][1])
if champ == "Prérequis" and not data[i]:
data[i] = "aucun"
print(f"Dans {nom_ressource}, complète les prérequis à \"aucun\"")
else:
non_interprete.append((champ, ligne[1][0]))
else: # ligne de données soit chapeau (ex Compétences ciblées) soit détail par compétence
champ = ligne[0][0]
if "Apprentissages" in champ: # les compétences ciblées sont déduites de la présence d'apprentissage critiques
# j+1 = les ACs par compétences
acs = res[j+2]
for k in range(len(acs)):
apprentissages[k] = "\n".join(acs[k]) # fusionne les ACS (généralement sur plusieurs lignes)
if non_interprete: # souvent Heures de formation (incluant les TP)
try:
indice_champ = [chp[0] for chp in non_interprete].index("Heures de formation (incluant les TP)")
except:
indice_champ = -1
if indice_champ >= 0: # si le champ "Heures de formation (incluant les TP)" est trouvé
# tente de réinjecter les heures dans Heures encadrées si elles n'on pas déjà été renseignées
indice_heure = get_indice("formation encadrée")
if not data[indice_heure]:
print(f"Dans \"{nom_ressource}\", réinjection de \"Heures de formation (incluant les TP)\" dans \"formation encadrée\"")
data[indice_heure] = champ[1]
non_interprete = non_interprete[:indice_champ] + non_interprete[indice_champ+1:] # supprime le champ
if non_interprete:
__LOGGER.warning(f"Dans \"{nom_ressource}\", champs en trop non interprétés : " + ",".join(
[chp[0] for chp in non_interprete]))
# Analyse des champs manquants
champ_manquants = []
for (j, champ) in enumerate(ENTETES):
if not data[j]:
champ_manquants += [champ]
if champ_manquants:
__LOGGER.warning(f"Dans \"{nom_ressource}\", champs manquants : " + ",".join(champ_manquants))
# Sauvegarde des champs de la ressource
info = tuple(data[1:])
r.charge_informations(*info)
r.charge_ac(apprentissages)
# fin du parsing
print(f"{nbre_ressources} ressources")
# ************************************************************************
# Post traitement des ressources => gestion des heures/des acs/ + tri par semestre
ressources = {"S1" : [], "S2": []}
for r in liste_ressources:
# Nettoie titre
nettoie_titre(r)
# Nettoie le champ heures_encadrees
nettoie_heure(r)
# Nettoie les codes
nettoie_code(r)
# Nettoie les semestres
nettoie_semestre(r)
# Remet en forme les ACs
nettoie_acs(r)
# Remet en forme les pré-requis
nettoie_prerequis(r)
# Remet en forme le descriptif
nettoie_description(r)
# Tri dans le bon semestre
ressources[r.semestre] += [r]
# complète les codes d'après les numéros
for sem in ressources:
for (i, r) in enumerate(ressources[sem]):
if not r.code:
if i == 0:
r.code = "R" + sem[1] + "01"
elif ressources[sem][i-1].code:
r.code = "R" + sem[1] + "{:02d}".format(int(ressources[sem][i-1].code[-2:])+1)
# ************************************************************************
# Affichages divers
# Bilan des heures & Calcul somme des heures par semestre
ligne = "{:20s} | {:75s} | {:10s} | {:10s} |"
trait = "-"*len(ligne.format("", "", "", ""))
for sem in ressources: # parcours des semestres
ressem = ressources[sem] # les ressources du semestre
print(f"Semestre {sem}")
print(trait, ligne.format("Code", "Ressource", "Form.", "dont TP"), trait, sep="\n")
for r in ressem:
print(ligne.format(r.code if r.code else "MANQUANT",
# r.nom[:30] + ("..." if len(r.nom) > 30 else "") ,
r.nom,
str(r.heures_encadrees) if r.heures_encadrees else "MANQUANT",
str(r.tp) if r.tp else "MANQUANT"))
heures_formation_total = sum([r.heures_encadrees for r in ressem if r.heures_encadrees != None])
heures_tp_total = sum([r.tp for r in ressem if r.tp != None])
print(trait, ligne.format("", "Total", str(heures_formation_total), str(heures_tp_total)), trait, sep="\n")
# Matrice ACS/ressources
matrices = {}
les_codes_acs = [code for comp in DATA_ACS for code in DATA_ACS[comp]]
nbre_acs = len(les_codes_acs)
for sem in ressources:
ressem = ressources[sem] # les ressources du semestre
nbre_ressources_semestre = len(DATA_RESSOURCES[sem])
if len(ressem) != nbre_ressources_semestre:
__LOGGER.warning(f"Pb => il manque des ressources au {sem}")
matrices[sem] = [ [False]*nbre_ressources_semestre for i in range(nbre_acs)]
for (i, r) in enumerate(ressem): # pour chaque ressource
for comp in range(len(r.apprentissages)): # pour chaque comp
for (j, ac) in enumerate(les_codes_acs): # pour chaque ac
if ac in r.apprentissages[comp]: # si l'ac est prévue dans la ressource
matrices[r.semestre][j][i] = True
print("Matrice du semestre " + sem)
ligne = "{:20s} | " + "{:4s} | "*nbre_ressources_semestre
valeurs = ("" for i in range(nbre_ressources_semestre+1))
trait = "-"*len(ligne.format(*valeurs))
# print(matrices["S1"])
valeurs = [""] + [r.code if r.code else "????" for r in ressem] + [""]*(nbre_ressources_semestre-len(ressem))
valeurs = tuple(valeurs)
print(ligne.format(*valeurs), trait, sep="\n")
for (j, ac) in enumerate(les_codes_acs):
valeurs = [ac] + [("X" if matrices[sem][j][i] == True else "") for i in range(nbre_ressources_semestre)]
valeurs = tuple(valeurs)
print(ligne.format(*valeurs))
for sem in ressources:
for r in ressources[sem]:
print(r.to_latex())