From bb4bd79b6d8a0f904d00ea7601a5f096c03e5b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9o=20Baras?= Date: Fri, 2 Apr 2021 14:59:08 +0200 Subject: [PATCH] =?UTF-8?q?d=C3=A9bute=20le=20traitement=20des=20sa=C3=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- latex/modeles/tableau_ressource.tex | 4 +- python/export_docx_to_yaml.py | 27 +-- python/export_sae_docx_to_yaml.py | 274 +++++++++++++++------------- python/officiel.py | 26 +-- python/pn/ressources.yml | 8 +- python/pn/saes.yml | 12 +- python/ressourcedocx.py | 122 +++++++++++-- python/tools.py | 19 ++ 8 files changed, 301 insertions(+), 191 deletions(-) create mode 100644 python/tools.py diff --git a/latex/modeles/tableau_ressource.tex b/latex/modeles/tableau_ressource.tex index 56d0317..36fa5d2 100644 --- a/latex/modeles/tableau_ressource.tex +++ b/latex/modeles/tableau_ressource.tex @@ -63,7 +63,9 @@ Aucun % {\bfseries Ancrage et contexte professionnel :} \\ \csname ressourceancrage\CODE\endcsname \\ {\bfseries Contenus :} \\ - \csname ressourcecontenudetaille\CODE\endcsname + %{\setlength{\extrarowheight}{1pt} + \csname ressourcecontenudetaille\CODE\endcsname + %} \end{tabular} } diff --git a/python/export_docx_to_yaml.py b/python/export_docx_to_yaml.py index 1d15caf..c407f45 100644 --- a/python/export_docx_to_yaml.py +++ b/python/export_docx_to_yaml.py @@ -3,6 +3,9 @@ import docx2python from ressourcedocx import * import logging + +from tools import get_indice, get_indice_sans_accent_ni_espace + __LOGGER = logging.getLogger(__name__) REPERTOIRE = "import" @@ -19,22 +22,6 @@ nbre_ressources = 0 ENTETES = ["Nom", "Code", "Semestre", "Heures de formation", "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 @@ -75,7 +62,7 @@ for i in range(2, len(docu)): # A priori un tableau 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 + i = get_indice_sans_accent_ni_espace(champ, ENTETES) # 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]: @@ -99,7 +86,7 @@ for i in range(2, len(docu)): # A priori un tableau 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") + indice_heure = get_indice("formation encadrée", ENTETES) 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] @@ -131,8 +118,8 @@ ressources = {"S1" : [], "S2": []} for r in liste_ressources: nettoie_titre(r) - nettoie_heure(r) - nettoie_code(r) + nettoie_heure_ressource(r) + nettoie_code(r, type="ressource") nettoie_semestre(r) nettoie_acs(r) nettoie_sae(r) diff --git a/python/export_sae_docx_to_yaml.py b/python/export_sae_docx_to_yaml.py index 0c5db46..0b3183d 100644 --- a/python/export_sae_docx_to_yaml.py +++ b/python/export_sae_docx_to_yaml.py @@ -1,12 +1,13 @@ import docx2python -from ressource import * +from ressourcedocx import * +from tools import * import logging __LOGGER = logging.getLogger(__name__) REPERTOIRE = "import" -DOCUMENT = "000 compilation-saes 2021-03-29T11_10_11.377Z" +DOCUMENT = "sae_v0" # Ouverture du document docu = docx2python.docx2python(REPERTOIRE + "/" + DOCUMENT + ".docx") @@ -14,29 +15,16 @@ 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_CHAPEAU = ["Titre", "Code", "Semestre", "Heures de formation", "dont heures de TP", "Heures \"projet", - "Description des objectifs", + +ENTETES_CHAPEAU = ["Titre", "Code", "Semestre", "Heures de formation", + "dont heures de TP", + "Heures \"projet", + "Description", "Liste des ressources", "Type de livrable", "Mots clefs"] -ENTETES_EXEMPLES = ["Titre", "Compétence", "Description des objectifs", "Types"] -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 - +ENTETES_EXEMPLES = ["Titre", "Description", "Formes", "Quelle problématique", + "Modalités"] """ Format du parsing issu de docx2python @@ -46,30 +34,35 @@ Format du parsing issu de docx2python [ # 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 +print("*Etape 1* : Parsing") +nbre_saes = 0 +last_sae = None +liste_saes = [] # la liste des saes telle qu'extraite du docx +liste_exemples = {} # la liste des exemples de chaque SAé + +for i in range(1, len(docu)): # A priori un tableau + est_sae, est_exemple = False, False try: - if "Nom de la ressource" in docu[i][0][0][0]: # [03][00][0][0] - est_ressource = True - nbre_ressources += 1 + if "Titre de la " in docu[i][0][0][0] or "Nom de la " in docu[i][0][0][0]: # [03][00][0][0] + if "Code" in docu[i][1][0][0]: + est_sae = True + nbre_saes += 1 + else: # c'est un exemple + est_exemple = True except: pass - if est_ressource == True: + if est_sae == True: res = docu[i] # la ressource - nom_ressource = res[0][1][0] + nom_sae = res[0][1][0] # Création de la ressource - r = RessourceDocx(nom_ressource, res) - liste_ressources.append(r) + r = SAEDocx(nom_sae, res) + liste_saes.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 + # Parsing des données brute de la sae + data = [None for i in range(len(ENTETES_CHAPEAU))] # les données attendues Nom, Code, ..., Mots clés apprentissages = [None for i in range(3)] # les apprentissages des 3 compétences non_interprete = [] @@ -77,17 +70,17 @@ for i in range(2, len(docu)): # A priori un tableau 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 champ.startswith("Nom de la"): + champ = "Titre de la" # corrige les noms/titres + i = get_indice_sans_accent_ni_espace(champ, ENTETES_CHAPEAU) # 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 + + if "Apprentissage(s)" 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)): @@ -95,105 +88,132 @@ for i in range(2, len(docu)): # A priori un tableau 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( + __LOGGER.warning(f"Dans la saé \"{nom_sae}\", 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): + for (j, champ) in enumerate(ENTETES_CHAPEAU): if not data[j]: champ_manquants += [champ] if champ_manquants: - __LOGGER.warning(f"Dans \"{nom_ressource}\", champs manquants : " + ",".join(champ_manquants)) + __LOGGER.warning(f"Dans \"{nom_sae}\", champs manquants : " + ",".join(champ_manquants)) # Sauvegarde des champs de la ressource info = tuple(data[1:]) r.charge_informations(*info) r.charge_ac(apprentissages) + + # nettoie le titre et le code + nettoie_titre(r) + nettoie_code(r, type="sae") + + last_sae = r.code + liste_exemples[r.code] = [] + + elif est_exemple == True: + res = docu[i] # la ressource + nom_exemple = res[0][1][0] + + # Création de la ressource + r = ExempleSAEDocx(nom_exemple, res) + liste_exemples[last_sae].append(r) + + # Parsing des données brute de la sae + data = [None for i in range(len(ENTETES_EXEMPLES))] # 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, ENTETES_EXEMPLES) # l'indice de l'entete dans ENTETES + if i != None: + data[i] = "\n".join(res[j][1]) + 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 + print("??? plus de 2 colonnes ?") + + if non_interprete: # souvent Heures de formation (incluant les TP) + + __LOGGER.warning(f"Dans l'exemple \"{nom_exemple}\", 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_EXEMPLES): + if not data[j]: + champ_manquants += [champ] + if champ_manquants: + __LOGGER.warning(f"Dans \"{nom_exemple}\", champs manquants : " + ",".join(champ_manquants)) + + # Sauvegarde des champs de la ressource + info = tuple(data[1:]) + r.charge_informations(*info) + # fin du parsing -print(f"{nbre_ressources} ressources") +print(f"{nbre_saes} saes") +for s in liste_exemples: + print(f"{s} :" + str(len(liste_exemples[s])) + " exemples") # ************************************************************************ -# 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 saé - nettoie_sae(r) - - # Remet en forme les pré-requis - nettoie_prerequis(r) - - # Remet en forme le descriptif - split_description(r) - nettoie_contenus(r) - - # Remet en forme les mots-clés - # 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 -# Le tableau des heures ressources -for sem in ressources: # parcours des semestres - # print(f"Semestre {sem}") - chaine = affiche_bilan_heures(ressources, sem) - - -# 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: - # print("Matrice du semestre " + sem) - (matrices[sem], chaine) = get_matrices_ac_ressource(ressources, sem) - -# Export yaml -WITH_EXPORT = True -for sem in ressources: - for r in ressources[sem]: - output = r.to_yaml() - if WITH_EXPORT and r.code: - fichier = "export/{}.yml".format(r.code) - with open(fichier, "w", encoding="utf8") as fid: - fid.write(output) +# Post traitement des saes => gestion des heures/des acs/ + tri par semestre +saes = {"S1" : [], "S2": []} +for s in liste_saes: + nettoie_heure_sae(s) + nettoie_semestre(s) + nettoie_acs(s) + nettoie_ressources(s) + print("ici") +# +# # Remet en forme les pré-requis +# nettoie_prerequis(r) +# +# # Remet en forme le descriptif +# split_description(r) +# nettoie_contenus(r) +# +# # Remet en forme les mots-clés +# # 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 +# # Le tableau des heures ressources +# for sem in ressources: # parcours des semestres +# # print(f"Semestre {sem}") +# chaine = affiche_bilan_heures(ressources, sem) +# +# +# # 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: +# # print("Matrice du semestre " + sem) +# (matrices[sem], chaine) = get_matrices_ac_ressource(ressources, sem) +# +# # Export yaml +# WITH_EXPORT = True +# for sem in ressources: +# for r in ressources[sem]: +# output = r.to_yaml() +# if WITH_EXPORT and r.code: +# fichier = "export/{}.yml".format(r.code) +# with open(fichier, "w", encoding="utf8") as fid: +# fid.write(output) +# diff --git a/python/officiel.py b/python/officiel.py index bd33c75..74bb0ca 100644 --- a/python/officiel.py +++ b/python/officiel.py @@ -93,28 +93,28 @@ def affiche_bilan_heures(ressources, sem): chaine += trait + "\n" return chaine +def get_officiel_name_by_code_using_dict(code, dico): + """Extrait un nom à partir d'un code (pour les RESSOURCES ou les SAES)""" + for sem in dico: + for rcode in dico[sem]: + if rcode==code: + return dico[sem][code] def get_officiel_ressource_name_by_code(code): """Pour un code valide, fournit le nom officiel de la ressource (sans connaissance du semestre)""" - for sem in DATA_RESSOURCES: - for rcode in DATA_RESSOURCES[sem]: - if rcode==code: - return DATA_RESSOURCES[sem][code] + return get_officiel_name_by_code_using_dict(code, DATA_RESSOURCES) def get_officiel_sae_name_by_code(code): """Pour un code valide, fournit le nom officiel de la sae (sans connaissance du semestre)""" - for sem in DATA_SAES: - for rcode in DATA_SAES[sem]: - if rcode==code: - return DATA_SAES[sem][code] + return get_officiel_name_by_code_using_dict(code, DATA_SAES) -def get_code_from_nom(ressource): +def get_code_from_nom_using_dict(ressource, dico): """Récupère le code d'une ressource d'après son nom en utilisant les noms officiels - des ressources du yaml""" + des ressources du yaml si dico == DATA_RESSOURCES ; sinon fait de même avec les SAE""" nom = supprime_accent_espace(ressource.nom) - for sem in DATA_RESSOURCES: - for code in DATA_RESSOURCES[sem]: - nom_data = supprime_accent_espace(DATA_RESSOURCES[sem][code]) + for sem in dico: + for code in dico[sem]: + nom_data = supprime_accent_espace(dico[sem][code]) if nom.startswith(nom_data): return code \ No newline at end of file diff --git a/python/pn/ressources.yml b/python/pn/ressources.yml index ba243b6..7111c6e 100644 --- a/python/pn/ressources.yml +++ b/python/pn/ressources.yml @@ -9,7 +9,7 @@ S1: R108: "Bases des systèmes d'exploitation" R109: "Introduction aux technologies Web" R110: "Anglais de communication et initiation au vocabulaire technique" - R111: "Expression-Culture-Communication Professionnelles (ECC1)" + R111: "Expression-Culture-Communication Professionnelles 1" R112: "PPP: Connaître son champ d'activité" R113: "Mathématiques du signal" R114: "Mathématiques des transmissions" @@ -24,8 +24,8 @@ S2: R207: "Sources de données" R208: "Analyse et traitement de données structurées" R209: "Initiation au développement Web" - R210: "Développement de l'anglais technique" - R211: "Expression-Culture-Communication Professionnelles (ECC2)" + R210: "Anglais de communication et développement de l'anglais technique" + R211: "Expression-Culture-Communication Professionnelles 2" R212: "PPP: Formalisation du projet" R213: "Mathématiques des systèmes numériques" - R214: "Analyse des signaux" + R214: "Analyse mathématique des signaux" diff --git a/python/pn/saes.yml b/python/pn/saes.yml index e3db52e..9bf0616 100644 --- a/python/pn/saes.yml +++ b/python/pn/saes.yml @@ -1,12 +1,12 @@ S1: - SAÉ11: "Réseaux / cybersécurité / hygiène informatique" - SAÉ12: "Réseau d'entreprise ou personnel" - SAÉ13: "Supports de transmission / calculs" + SAÉ11: "Se sensibiliser à l'hygiène informatique et à la cybersécurité" + SAÉ12: "S'initier aux réseaux informatiques" + SAÉ13: "Découvrir un dispositif de transmission" SAÉ14: "Se présenter sur Internet" SAÉ15: "Traiter des données" S2: - SAÉ21: "Construction d’un réseau informatique pour une petite structure" - SAÉ22: "Mesures et caractérisation d’un signal ou d’un système" - SAÉ23: "Mise en place d'une solution informatique pour l’entreprise" + SAÉ21: "Construire un réseau informatique pour une petite structure" + SAÉ22: "Mesurer et caractériser un signal ou un système" + SAÉ23: "Mettre en place une solution informatique pour l’entreprise" SAÉ24: "Projet intégratif de S2" diff --git a/python/ressourcedocx.py b/python/ressourcedocx.py index bc6f856..4e392af 100644 --- a/python/ressourcedocx.py +++ b/python/ressourcedocx.py @@ -1,7 +1,7 @@ import re from officiel import * from modeles import * -from officiel import supprime_accent_espace, get_code_from_nom +from officiel import supprime_accent_espace, get_code_from_nom_using_dict import ruamel.yaml from ruamel.yaml.scalarstring import FoldedScalarString as folded @@ -10,9 +10,9 @@ __LOGGER = logging.getLogger(__name__) class RessourceDocx(): """Classe modélisant les ressources, lorsqu'elles sont extraites du docx""" - def __init__(self, nom, brute): + def __init__(self, nom, brut): self.nom = nom - self.brute = brute # les données brutes de la ressource + self.brut = brut # les données brutes de la ressource def charge_informations(self, code, semestre, heures_encadrees, tp, sae, prerequis, description, mots): self.code = code @@ -64,26 +64,28 @@ class RessourceDocx(): output = output.replace("\n\n", "\n") return output -def nettoie_heure(r): +def nettoie_champ_heure(champ): + try: # champ contenant uniquement un nbre d'heure + volumes = int(champ) + return volumes + except: + volumes = re.findall("(\d{2}\D|\d{1}\D)", champ) + if len(volumes) == 1: + return int(volumes[0][:-1]) + elif len(volumes) == 2: + volumes = sorted(volumes, reverse=True) + return (int(volumes[0][:-1]), int(volumes[1][:-1])) + +def nettoie_heure_ressource(r): """Nettoie le champ (horaire) (de la forme 46h ou 33...) pour en extraire la valeur numérique : le champ peut contenir 2 volumes (heures formation puis heures tp), auquel cas les 2 valeurs sont renvoyées dans un tuple""" - def nettoie_champ_heure(champ): - try: # champ contenant uniquement un nbre d'heure - volumes = int(champ) - return volumes - except: - volumes = re.findall("(\d{2}\D|\d{1}\D)", champ) - if len(volumes) == 1: - return int(volumes[0][:-1]) - elif len(volumes) == 2: - volumes = sorted(volumes, reverse=True) - return (int(volumes[0][:-1]), int(volumes[1][:-1])) if r.heures_encadrees: # si les heures encadrées sont renseignées volumes = nettoie_champ_heure(r.heures_encadrees) if r.tp: r.tp = nettoie_champ_heure(r.tp) + if isinstance(volumes, int): r.heures_encadrees = volumes elif isinstance(volumes, tuple): @@ -97,11 +99,46 @@ def nettoie_heure(r): #else: #__LOGGER.warning("Heures non détectées") -def nettoie_code(r): - """Recherche les codes ressources de la forme RXXX dans champ""" + +def nettoie_heure_sae(r): + """Nettoie les champs (horaires) des saes""" + + if r.heures_encadrees: # si les heures encadrées sont renseignées + r.heures_encadrees = nettoie_champ_heure(r.heures_encadrees) + else: + __LOGGER.warning(r"nettoie_heure_sae: dans {r.nom}, manque les heures de formation") + r.heures_encadrees = "???" + if r.tp: + r.tp = nettoie_champ_heure(r.tp) + else: + __LOGGER.warning(r"nettoie_heure_sae: dans {r.nom}, manque les heures de tp") + r.tp = "???" + + if r.projet: + r.projet = nettoie_champ_heure(r.projet) + else: + __LOGGER.warning(r"nettoie_heure_sae: dans {r.nom}, manque les heures de projet") + r.projet = "???" + try: + if r.heures_encadrees < r.tp: + __LOGGER.warning(r"nettoie_heure_sae: dans {r.nom}, pb dans les heures formations/tp") + except: + pass + + +def nettoie_code(r, type = "ressource"): + """Recherche les codes dans le champ: + * de la forme RXXX si type=ressource + * de la forme SAE|éXX si type=sae""" + champ = r.code if r.code: - codes = re.findall(r"(R[0-9][0-9][0-9])", champ) + if type == "ressource": + codes = re.findall(r"(R[0-9][0-9][0-9])", champ) + else: # type = "sae" + codes = re.findall(r"(SAE[0-9][0-9]|SAÉ[0-9][0-9])", champ) + # ajout des É + codes = [c.replace("E", "É") for c in codes] # if len(codes) > 1: # __LOGGER.warning("plusieurs codes trouvés :(") #elif len(codes) == 0: @@ -109,7 +146,10 @@ def nettoie_code(r): if len(codes) == 1: r.code = codes[0] else: - code_devine = get_code_from_nom(r) + if type == "ressource": + code_devine = get_code_from_nom_using_dict(r, DATA_RESSOURCES) + else: + code_devine = get_code_from_nom_using_dict(r, DATA_SAES) if code_devine: __LOGGER.warning(f"nettoie_code : \"{r.nom}\" => code {code_devine}") r.code = code_devine @@ -166,13 +206,21 @@ def nettoie_acs(r): r.apprentissages = dico # [comp] = acs_finaux def nettoie_sae(r): - """Nettoie les sae en détectant les codes""" + """Nettoie le champ SAe d'une ressource en détectant les codes""" SAE_avec_code = devine_sae_by_code(r.sae) liste = [l.rstrip() for l in SAE_avec_code] r.sae = liste if not r.sae: __LOGGER.warning(f"nettoie_sae: dans {r.nom} pas de SAE (:") +def nettoie_ressources(r): + """Nettoie le champ ressource d'une sae en détectant les codes""" + ressources_avec_code = devine_ressources_by_code(r.ressources) + liste = [l.rstrip() for l in ressources_avec_code] + r.ressources = liste + if not r.ressources: + __LOGGER.warning(f"nettoie_ressources: dans {r.nom} pas de ressources (:") + def nettoie_prerequis(r): """Nettoie les prérequis (ressource) en les remplaçant par leur code de ressource""" R_avec_code = devine_ressources_by_code(r.prerequis) @@ -346,6 +394,40 @@ def caracteres_recalcitrants(contenu): contenu = contenu.replace('\xa0', ' ') # le nbsp return contenu + +class SAEDocx(): + + def __init__(self, nom, brut): + self.nom = nom + self.brut = brut # les données brutes de la ressource + + def charge_informations(self, code, semestre, heures_encadrees, tp, projet, description, ressources, livrables, mots): + self.code = code + self.semestre = semestre # <-- + self.heures_encadrees = heures_encadrees + self.tp = tp + self.projet = projet + self.description = description + self.ressources = ressources + self.livrables = livrables + self.mots = mots + + def charge_ac(self, apprentissages): + self.apprentissages = apprentissages + +class ExempleSAEDocx(): + + def __init__(self, nom, brut): + self.nom = nom + self.brut = brut # les données brutes de la ressource + + def charge_informations(self, description, formes, problematique, modalite): + self.description = description + self.formes = formes # <-- + self.problematique = problematique + self.modalite = modalite + + if __name__=="__main__": # Eléments de test for sem in DATA_RESSOURCES: diff --git a/python/tools.py b/python/tools.py new file mode 100644 index 0000000..4c29e0e --- /dev/null +++ b/python/tools.py @@ -0,0 +1,19 @@ +from officiel import supprime_accent_espace + + +def get_indice(champ, entetes): + """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, entetes): + """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).rstrip() + for (i, entete) in enumerate(entetes): + entete_purge = supprime_accent_espace(entete).rstrip() + if entete_purge in champ_purge: + return i + return None \ No newline at end of file