587 lines
25 KiB
Python
587 lines
25 KiB
Python
import streamlit as st
|
|
import re
|
|
import yaml
|
|
|
|
def _build_extraction_tableau(md: str, produit: str) -> str:
|
|
"""Génère le tableau d'extraction pour les fiches de minerai."""
|
|
# Identifier la section d'extraction
|
|
extraction_pattern = rf"Extraction_{re.escape(produit)}"
|
|
extraction_match = re.search(f"{extraction_pattern}:", md)
|
|
|
|
if not extraction_match:
|
|
return md # Pas de section d'extraction trouvée
|
|
|
|
# Récupérer les données structurées
|
|
extraction_data = {}
|
|
|
|
# Rechercher tous les pays et leurs acteurs
|
|
pays_pattern = rf"(\w+)_{extraction_pattern}:\s+nom_du_pays:\s+([^\n]+)\s+part_de_marche:\s+([^\n]+)"
|
|
for pays_match in re.finditer(pays_pattern, md):
|
|
code_pays, nom_pays, part_pays = pays_match.groups()
|
|
try:
|
|
part_marche_num = float(part_pays.strip().rstrip('%'))
|
|
except ValueError:
|
|
part_marche_num = 0
|
|
|
|
extraction_data[code_pays] = {
|
|
'nom': nom_pays.strip(),
|
|
'part_marche': part_pays.strip(),
|
|
'part_marche_num': part_marche_num,
|
|
'acteurs': []
|
|
}
|
|
|
|
# Rechercher tous les acteurs pour ce pays
|
|
acteur_pattern = rf"(\w+)_{code_pays}_{extraction_pattern}:\s+nom_de_l_acteur:\s+([^\n]+)\s+part_de_marche:\s+([^\n]+)\s+pays_d_origine:\s+([^\n]+)"
|
|
for acteur_match in re.finditer(acteur_pattern, md):
|
|
code_acteur, nom_acteur, part_acteur, pays_origine = acteur_match.groups()
|
|
try:
|
|
part_acteur_num = float(part_acteur.strip().rstrip('%'))
|
|
except ValueError:
|
|
part_acteur_num = 0
|
|
|
|
extraction_data[code_pays]['acteurs'].append({
|
|
'nom': nom_acteur.strip(),
|
|
'part_marche': part_acteur.strip(),
|
|
'part_marche_num': part_acteur_num,
|
|
'pays_origine': pays_origine.strip()
|
|
})
|
|
|
|
# Préparer les données pour l'affichage
|
|
pays_data = []
|
|
for code_pays, pays_info in extraction_data.items():
|
|
# Trier les acteurs par part de marché décroissante
|
|
acteurs_tries = sorted(pays_info['acteurs'], key=lambda x: x['part_marche_num'], reverse=True)
|
|
|
|
pays_data.append({
|
|
'nom': pays_info['nom'],
|
|
'part_marche': pays_info['part_marche'],
|
|
'part_marche_num': pays_info['part_marche_num'],
|
|
'acteurs': acteurs_tries
|
|
})
|
|
|
|
# Trier les pays par part de marché décroissante
|
|
pays_tries = sorted(pays_data, key=lambda x: x['part_marche_num'], reverse=True)
|
|
|
|
# Générer le tableau des producteurs
|
|
lignes_tableau = [
|
|
"| **Pays d'implantation** | **Entreprise** | **Pays d'origine** | **Part de marché** |",
|
|
"| :-- | :-- | :-- | :-- |"
|
|
]
|
|
|
|
for pays in pays_tries:
|
|
for acteur in pays['acteurs']:
|
|
# Formater la part de marché (ajouter un espace avant %)
|
|
part_marche_formattee = acteur['part_marche'].strip().replace('%', ' %')
|
|
lignes_tableau.append(
|
|
f"| {pays['nom']} | {acteur['nom']} | {acteur['pays_origine']} | {part_marche_formattee} |"
|
|
)
|
|
|
|
# Ajouter la ligne de total pour le pays (en gras)
|
|
part_marche_pays_formattee = pays['part_marche'].strip().replace('%', ' %')
|
|
lignes_tableau.append(
|
|
f"| **{pays['nom']}** | **Total** | **{pays['nom']}** | **{part_marche_pays_formattee}** |"
|
|
)
|
|
|
|
# Construire le tableau final
|
|
tableau_final = "\n".join(lignes_tableau)
|
|
|
|
# Remplacer la section du tableau dans la fiche
|
|
md_modifie = re.sub(
|
|
r"<!---- AUTO-BEGIN:TABLEAU-EXTRACTION -->.*?<!---- AUTO-END:TABLEAU-EXTRACTION -->",
|
|
f"<!---- AUTO-BEGIN:TABLEAU-EXTRACTION -->\n{tableau_final}\n<!---- AUTO-END:TABLEAU-EXTRACTION -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
|
|
return md_modifie
|
|
|
|
def _build_traitement_tableau(md: str, produit: str) -> str:
|
|
"""Génère le tableau de traitement pour les fiches de minerai."""
|
|
# Identifier la section de traitement
|
|
traitement_pattern = rf"Traitement_{re.escape(produit)}"
|
|
traitement_match = re.search(f"{traitement_pattern}:", md)
|
|
|
|
if not traitement_match:
|
|
return md # Pas de section de traitement trouvée
|
|
|
|
# Récupérer les données structurées
|
|
traitement_data = {}
|
|
|
|
# Rechercher tous les pays et leurs acteurs
|
|
pays_pattern = rf"(\w+)_{traitement_pattern}:\s+nom_du_pays:\s+([^\n]+)\s+part_de_marche:\s+([^\n]+)"
|
|
for pays_match in re.finditer(pays_pattern, md):
|
|
code_pays, nom_pays, part_pays = pays_match.groups()
|
|
try:
|
|
part_marche_num = float(part_pays.strip().rstrip('%'))
|
|
except ValueError:
|
|
part_marche_num = 0
|
|
|
|
traitement_data[code_pays] = {
|
|
'nom': nom_pays.strip(),
|
|
'part_marche': part_pays.strip(),
|
|
'part_marche_num': part_marche_num,
|
|
'acteurs': []
|
|
}
|
|
|
|
# Rechercher tous les acteurs pour ce pays
|
|
acteur_pattern = rf"(\w+)_{code_pays}_{traitement_pattern}:"
|
|
for acteur_match in re.finditer(acteur_pattern, md):
|
|
code_acteur = acteur_match.group(1)
|
|
|
|
# Récupérer les informations de l'acteur
|
|
nom_acteur_match = re.search(rf"{code_acteur}_{code_pays}_{traitement_pattern}:\s+nom_de_l_acteur:\s+([^\n]+)", md)
|
|
part_acteur_match = re.search(rf"{code_acteur}_{code_pays}_{traitement_pattern}:.*?part_de_marche:\s+([^\n]+)", md, re.DOTALL)
|
|
pays_origine_match = re.search(rf"{code_acteur}_{code_pays}_{traitement_pattern}:.*?pays_d_origine:\s+([^\n]+)", md, re.DOTALL)
|
|
|
|
if nom_acteur_match and part_acteur_match and pays_origine_match:
|
|
nom_acteur = nom_acteur_match.group(1).strip()
|
|
part_acteur = part_acteur_match.group(1).strip()
|
|
pays_origine = pays_origine_match.group(1).strip()
|
|
|
|
try:
|
|
part_acteur_num = float(part_acteur.strip().rstrip('%'))
|
|
except ValueError:
|
|
part_acteur_num = 0
|
|
|
|
# Récupérer les origines du minerai
|
|
origines_minerai = []
|
|
for i in range(1, 10): # Vérifier jusqu'à 9 origines possibles
|
|
origine_key = "minerai_origine" if i == 1 else f"minerai_origine_{i}"
|
|
origine_pattern = rf"{code_acteur}_{code_pays}_{traitement_pattern}:.*?{origine_key}:\s+pays:\s+([^\n]+)\s+pourcentage:\s+([^\n]+)"
|
|
origine_match = re.search(origine_pattern, md, re.DOTALL)
|
|
|
|
if origine_match:
|
|
pays_origine_minerai = origine_match.group(1).strip()
|
|
pourcentage_origine = origine_match.group(2).strip()
|
|
origines_minerai.append(f"{pays_origine_minerai} ({pourcentage_origine})")
|
|
else:
|
|
break
|
|
|
|
origine_text = ", ".join(origines_minerai) if origines_minerai else ""
|
|
|
|
traitement_data[code_pays]['acteurs'].append({
|
|
'nom': nom_acteur,
|
|
'part_marche': part_acteur,
|
|
'part_marche_num': part_acteur_num,
|
|
'pays_origine': pays_origine,
|
|
'origine_minerai': origine_text
|
|
})
|
|
|
|
# Préparer les données pour l'affichage
|
|
pays_data = []
|
|
for code_pays, pays_info in traitement_data.items():
|
|
# Trier les acteurs par part de marché décroissante
|
|
acteurs_tries = sorted(pays_info['acteurs'], key=lambda x: x['part_marche_num'], reverse=True)
|
|
|
|
pays_data.append({
|
|
'nom': pays_info['nom'],
|
|
'part_marche': pays_info['part_marche'],
|
|
'part_marche_num': pays_info['part_marche_num'],
|
|
'acteurs': acteurs_tries
|
|
})
|
|
|
|
# Trier les pays par part de marché décroissante
|
|
pays_tries = sorted(pays_data, key=lambda x: x['part_marche_num'], reverse=True)
|
|
|
|
# Générer le tableau des producteurs
|
|
lignes_tableau = [
|
|
"| **Pays d'implantation** | **Entreprise** | **Pays d'origine** | **Origines du minerai** | **Part de marché** |",
|
|
"| :-- | :-- | :-- | :-- | :-- |"
|
|
]
|
|
|
|
for pays in pays_tries:
|
|
for acteur in pays['acteurs']:
|
|
# Formater la part de marché (ajouter un espace avant %)
|
|
part_marche_formattee = acteur['part_marche'].strip().replace('%', ' %')
|
|
lignes_tableau.append(
|
|
f"| {pays['nom']} | {acteur['nom']} | {acteur['pays_origine']} | {acteur['origine_minerai']} | {part_marche_formattee} |"
|
|
)
|
|
|
|
# Ajouter la ligne de total pour le pays (en gras)
|
|
part_marche_pays_formattee = pays['part_marche'].strip().replace('%', ' %')
|
|
lignes_tableau.append(
|
|
f"| **{pays['nom']}** | **Total** | **{pays['nom']}** | **-** | **{part_marche_pays_formattee}** |"
|
|
)
|
|
|
|
# Construire le tableau final
|
|
tableau_final = "\n".join(lignes_tableau)
|
|
|
|
# Remplacer la section du tableau dans la fiche
|
|
md_modifie = re.sub(
|
|
r"<!---- AUTO-BEGIN:TABLEAU-TRAITEMENT -->.*?<!---- AUTO-END:TABLEAU-TRAITEMENT -->",
|
|
f"<!---- AUTO-BEGIN:TABLEAU-TRAITEMENT -->\n{tableau_final}\n<!---- AUTO-END:TABLEAU-TRAITEMENT -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
|
|
return md_modifie
|
|
|
|
def _build_reserves_tableau(md: str, produit: str) -> str:
|
|
"""Génère le tableau des réserves pour les fiches de minerai."""
|
|
# Identifier la section des réserves
|
|
reserves_pattern = rf"Reserves_{re.escape(produit)}"
|
|
reserves_match = re.search(f"{reserves_pattern}:", md)
|
|
|
|
if not reserves_match:
|
|
return md # Pas de section de réserves trouvée
|
|
|
|
# Récupérer les données structurées
|
|
reserves_data = []
|
|
|
|
# Rechercher tous les pays et leurs parts de marché
|
|
pays_pattern = rf"(\w+)_{reserves_pattern}:\s+nom_du_pays:\s+([^\n]+)\s+part_de_marche:\s+([^\n]+)"
|
|
for pays_match in re.finditer(pays_pattern, md):
|
|
code_pays, nom_pays, part_pays = pays_match.groups()
|
|
try:
|
|
part_marche_num = float(part_pays.strip().rstrip('%'))
|
|
except ValueError:
|
|
part_marche_num = 0
|
|
|
|
reserves_data.append({
|
|
'nom': nom_pays.strip(),
|
|
'part_marche': part_pays.strip(),
|
|
'part_marche_num': part_marche_num
|
|
})
|
|
|
|
# Trier les pays par part de marché décroissante
|
|
reserves_data_triees = sorted(reserves_data, key=lambda x: x['part_marche_num'], reverse=True)
|
|
|
|
# Générer le tableau des réserves
|
|
lignes_tableau = [
|
|
"| **Pays d'implantation** | **Part de marché** |",
|
|
"| :-- | :-- |"
|
|
]
|
|
|
|
for pays in reserves_data_triees:
|
|
# Formater la part de marché (ajouter un espace avant %)
|
|
part_marche_formattee = pays['part_marche'].strip().replace('%', ' %')
|
|
lignes_tableau.append(f"| {pays['nom']} | {part_marche_formattee} |")
|
|
|
|
# Construire le tableau final
|
|
tableau_final = "\n".join(lignes_tableau)
|
|
|
|
# Remplacer la section du tableau dans la fiche
|
|
md_modifie = re.sub(
|
|
r"<!---- AUTO-BEGIN:TABLEAU-RESERVES -->.*?<!---- AUTO-END:TABLEAU-RESERVES -->",
|
|
f"<!---- AUTO-BEGIN:TABLEAU-RESERVES -->\n{tableau_final}\n<!---- AUTO-END:TABLEAU-RESERVES -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
|
|
return md_modifie
|
|
|
|
def build_minerai_ivc_section(md: str) -> str:
|
|
"""
|
|
Ajoute les informations IVC depuis la fiche technique IVC.md pour un minerai spécifique.
|
|
"""
|
|
# Extraire le type de fiche et le produit depuis l'en-tête YAML
|
|
type_fiche = None
|
|
produit = None
|
|
front_match = re.match(r"(?s)^---\n(.*?)\n---\n", md)
|
|
if front_match:
|
|
try:
|
|
front_matter = yaml.safe_load(front_match.group(1))
|
|
type_fiche = front_matter.get("type_fiche")
|
|
produit = front_matter.get("schema")
|
|
|
|
# Vérifier si c'est bien une fiche de minerai
|
|
if type_fiche != "minerai" or not produit:
|
|
return md
|
|
except Exception as e:
|
|
st.error(f"Erreur lors du chargement du front matter: {e}")
|
|
return md
|
|
|
|
# Injecter les informations IVC depuis la fiche technique
|
|
try:
|
|
# Charger le contenu de la fiche technique IVC
|
|
ivc_path = "Fiches/Criticités/Fiche technique IVC.md"
|
|
with open(ivc_path, "r", encoding="utf-8") as f:
|
|
ivc_content = f.read()
|
|
|
|
# Chercher la section correspondant au minerai
|
|
# Le pattern cherche un titre de niveau 2 commençant par le nom du produit
|
|
section_pattern = rf"## {produit} - (.*?)(?=\n###|$)"
|
|
section_match = re.search(section_pattern, ivc_content, re.DOTALL)
|
|
|
|
if section_match:
|
|
# Extraire la partie après le nom du minerai (ex: "IVC : 4 - Vulnérabilité: Faible")
|
|
ivc_value = section_match.group(1).strip()
|
|
|
|
# Extraire toutes les sous-sections
|
|
# Le pattern cherche depuis le titre du minerai jusqu'à la prochaine section de même niveau ou fin de fichier
|
|
full_section_pattern = rf"## {produit} - .*?\n([\s\S]*?)(?=\n## |$)"
|
|
full_section_match = re.search(full_section_pattern, ivc_content)
|
|
|
|
if full_section_match:
|
|
section_content = full_section_match.group(1).strip()
|
|
|
|
# Formater le contenu à insérer
|
|
ivc_content_formatted = f"```\n{ivc_value}\n```\n\n{section_content}"
|
|
|
|
# Remplacer la section IVC dans le markdown
|
|
md = re.sub(
|
|
r"<!---- AUTO-BEGIN:SECTION-IVC-MINERAI -->.*?<!---- AUTO-END:SECTION-IVC-MINERAI -->",
|
|
f"<!---- AUTO-BEGIN:SECTION-IVC-MINERAI -->\n{ivc_content_formatted}\n<!---- AUTO-END:SECTION-IVC-MINERAI -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
except Exception as e:
|
|
st.error(f"Erreur lors de la génération de la section IVC: {e}")
|
|
|
|
return md
|
|
|
|
def build_minerai_ics_section(md: str) -> str:
|
|
"""
|
|
Ajoute les informations ICS depuis la fiche technique ICS.md pour un minerai spécifique.
|
|
"""
|
|
# Extraire le type de fiche et le produit depuis l'en-tête YAML
|
|
type_fiche = None
|
|
produit = None
|
|
front_match = re.match(r"(?s)^---\n(.*?)\n---\n", md)
|
|
if front_match:
|
|
try:
|
|
front_matter = yaml.safe_load(front_match.group(1))
|
|
type_fiche = front_matter.get("type_fiche")
|
|
produit = front_matter.get("schema")
|
|
|
|
# Vérifier si c'est bien une fiche de minerai
|
|
if type_fiche != "minerai" or not produit:
|
|
return md
|
|
except Exception as e:
|
|
st.error(f"Erreur lors du chargement du front matter: {e}")
|
|
return md
|
|
|
|
# Injecter les informations ICS depuis la fiche technique
|
|
try:
|
|
# Charger le contenu de la fiche technique ICS
|
|
ics_path = "Fiches/Criticités/Fiche technique ICS.md"
|
|
with open(ics_path, "r", encoding="utf-8") as f:
|
|
ics_content = f.read()
|
|
|
|
# Extraire la section ICS pour le minerai
|
|
# Dans le fichier ICS, on recherche dans la section "# Criticité par minerai"
|
|
# puis on cherche la sous-section correspondant au minerai
|
|
minerai_section_pattern = r"# Criticité par minerai\s*\n([\s\S]*?)(?=\n# |$)"
|
|
minerai_section_match = re.search(minerai_section_pattern, ics_content)
|
|
|
|
if minerai_section_match:
|
|
minerai_section = minerai_section_match.group(1)
|
|
|
|
# Chercher le minerai spécifique
|
|
# Rechercher un titre de niveau 2 correspondant exactement au produit
|
|
specific_minerai_pattern = rf"## {produit}\s*\n([\s\S]*?)(?=\n## |$)"
|
|
specific_minerai_match = re.search(specific_minerai_pattern, minerai_section)
|
|
|
|
if specific_minerai_match:
|
|
# Extraire le contenu de la section du minerai
|
|
minerai_content = specific_minerai_match.group(1).strip()
|
|
|
|
# Remplacer la section ICS dans le markdown
|
|
md = re.sub(
|
|
r"<!---- AUTO-BEGIN:SECTION-ICS-MINERAI -->.*?<!---- AUTO-END:SECTION-ICS-MINERAI -->",
|
|
f"<!---- AUTO-BEGIN:SECTION-ICS-MINERAI -->\n{minerai_content}\n<!---- AUTO-END:SECTION-ICS-MINERAI -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
except Exception as e:
|
|
st.error(f"Erreur lors de la génération de la section ICS: {e}")
|
|
|
|
return md
|
|
|
|
def build_minerai_ics_composant_section(md: str) -> str:
|
|
"""
|
|
Ajoute les informations ICS pour tous les composants liés à un minerai spécifique
|
|
depuis la fiche technique ICS.md, en augmentant d'un niveau les titres.
|
|
"""
|
|
# Extraire le type de fiche et le produit depuis l'en-tête YAML
|
|
type_fiche = None
|
|
produit = None
|
|
front_match = re.match(r"(?s)^---\n(.*?)\n---\n", md)
|
|
if front_match:
|
|
try:
|
|
front_matter = yaml.safe_load(front_match.group(1))
|
|
type_fiche = front_matter.get("type_fiche")
|
|
produit = front_matter.get("schema")
|
|
|
|
# Vérifier si c'est bien une fiche de minerai
|
|
if type_fiche != "minerai" or not produit:
|
|
return md
|
|
except Exception as e:
|
|
st.error(f"Erreur lors du chargement du front matter: {e}")
|
|
return md
|
|
|
|
# Injecter les informations ICS depuis la fiche technique
|
|
try:
|
|
# Charger le contenu de la fiche technique ICS
|
|
ics_path = "Fiches/Criticités/Fiche technique ICS.md"
|
|
with open(ics_path, "r", encoding="utf-8") as f:
|
|
ics_content = f.read()
|
|
|
|
# Rechercher toutes les sections de composants liés au minerai
|
|
# Le pattern cherche les titres de niveau 2 de la forme "## * -> Minerai"
|
|
composant_sections_pattern = re.compile(
|
|
rf"^## ([^>]+) -> {re.escape(produit)} - .*?\n([\s\S]*?)(?=^## |\Z)",
|
|
re.MULTILINE | re.DOTALL
|
|
)
|
|
|
|
composant_sections = re.finditer(composant_sections_pattern, ics_content)
|
|
|
|
all_composant_content = []
|
|
|
|
for match in composant_sections:
|
|
composant = match.group(1).strip()
|
|
section_content = match.group(2).strip()
|
|
|
|
# Augmenter le niveau des titres d'un cran
|
|
# Titre de niveau 2 -> niveau 3
|
|
section_title = f"### {composant} -> {produit}{match.group(0).split(produit)[1].split('\n')[0]}"
|
|
|
|
# Augmenter les niveaux des sous-titres (### -> ####)
|
|
section_content = re.sub(r"### ", "#### ", section_content)
|
|
|
|
# Ajouter à la liste des contenus
|
|
all_composant_content.append(f"{section_title}\n{section_content}")
|
|
|
|
# Combiner tous les contenus
|
|
if all_composant_content:
|
|
combined_content = "\n\n".join(all_composant_content)
|
|
|
|
# Remplacer la section ICS dans le markdown
|
|
md = re.sub(
|
|
r"<!---- AUTO-BEGIN:SECTION-ICS-COMPOSANT-MINERAI -->.*?<!---- AUTO-END:SECTION-ICS-COMPOSANT-MINERAI -->",
|
|
f"<!---- AUTO-BEGIN:SECTION-ICS-COMPOSANT-MINERAI -->\n{combined_content}\n<!---- AUTO-END:SECTION-ICS-COMPOSANT-MINERAI -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
except Exception as e:
|
|
st.error(f"Erreur lors de la génération de la section ICS pour les composants: {e}")
|
|
|
|
return md
|
|
|
|
def build_minerai_sections(md: str) -> str:
|
|
"""Traite les fiches de minerai et génère les tableaux des producteurs."""
|
|
# Extraire le type de fiche depuis l'en-tête YAML
|
|
type_fiche = None
|
|
produit = None
|
|
front_match = re.match(r"(?s)^---\n(.*?)\n---\n", md)
|
|
if front_match:
|
|
try:
|
|
front_matter = yaml.safe_load(front_match.group(1))
|
|
type_fiche = front_matter.get("type_fiche")
|
|
produit = front_matter.get("schema") # le produit à rechercher est schema pour faire le lien avec le graphe
|
|
|
|
# Vérifier si c'est bien une fiche de minerai
|
|
if type_fiche != "minerai" or not produit:
|
|
return md
|
|
except Exception as e:
|
|
st.error(f"Erreur lors du chargement du front matter: {e}")
|
|
return md
|
|
|
|
# Traiter le tableau d'Extraction
|
|
md = _build_extraction_tableau(md, produit)
|
|
|
|
# Traiter le tableau de Traitement
|
|
md = _build_traitement_tableau(md, produit)
|
|
|
|
# Traiter le tableau des Réserves
|
|
md = _build_reserves_tableau(md, produit)
|
|
|
|
# Supprimer les blocs YAML complets, y compris les délimiteurs ```yaml et ```
|
|
# Rechercher d'abord les blocs avec délimiteurs YAML
|
|
yaml_blocks = [
|
|
rf"```yaml\s*\n{re.escape(produit)}.*?```",
|
|
rf"```yaml\s*\nExtraction_{re.escape(produit)}.*?```",
|
|
rf"```yaml\s*\nReserves_{re.escape(produit)}.*?```",
|
|
rf"```yaml\s*\nTraitement_{re.escape(produit)}.*?```"
|
|
]
|
|
|
|
for pattern in yaml_blocks:
|
|
md = re.sub(pattern, "", md, flags=re.DOTALL)
|
|
|
|
# Supprimer également les blocs qui ne seraient pas entourés de délimiteurs
|
|
patterns_to_remove = [
|
|
rf"Extraction_{re.escape(produit)}:(?:.*?)(?=\n##|\Z)",
|
|
rf"Reserves_{re.escape(produit)}:(?:.*?)(?=\n##|\Z)",
|
|
rf"Traitement_{re.escape(produit)}:(?:.*?)(?=\n##|\Z)"
|
|
]
|
|
|
|
for pattern in patterns_to_remove:
|
|
md = re.sub(pattern, "", md, flags=re.DOTALL)
|
|
|
|
# Nettoyer les délimiteurs ```yaml et ``` qui pourraient rester
|
|
md = re.sub(r"```yaml\s*\n", "", md)
|
|
md = re.sub(r"```\s*\n", "", md)
|
|
|
|
# Injecter les sections IHH depuis la fiche technique
|
|
try:
|
|
# Charger le contenu de la fiche technique IHH
|
|
ihh_path = "Fiches/Criticités/Fiche technique IHH.md"
|
|
with open(ihh_path, "r", encoding="utf-8") as f:
|
|
ihh_content = f.read()
|
|
|
|
# D'abord, extraire toute la section concernant le produit
|
|
section_produit_pattern = rf"## Opérations - {produit}\s*\n([\s\S]*?)(?=\n## |$)"
|
|
section_produit_match = re.search(section_produit_pattern, ihh_content, re.IGNORECASE)
|
|
|
|
if section_produit_match:
|
|
section_produit = section_produit_match.group(1).strip()
|
|
|
|
# Maintenant, extraire les sous-sections individuelles à partir de la section du produit
|
|
|
|
# 1. Extraction - incluant le titre de niveau 3
|
|
extraction_pattern = r"(### Indice de Herfindahl-Hirschmann - Extraction\s*\n[\s\S]*?)(?=### Indice de Herfindahl-Hirschmann - Réserves|$)"
|
|
extraction_match = re.search(extraction_pattern, section_produit, re.IGNORECASE)
|
|
|
|
if extraction_match:
|
|
extraction_ihh = extraction_match.group(1).strip()
|
|
md = re.sub(
|
|
r"<!---- AUTO-BEGIN:SECTION-IHH-EXTRACTION -->.*?<!---- AUTO-END:SECTION-IHH-EXTRACTION -->",
|
|
f"<!---- AUTO-BEGIN:SECTION-IHH-EXTRACTION -->\n{extraction_ihh}\n<!---- AUTO-END:SECTION-IHH-EXTRACTION -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
|
|
# 2. Réserves - incluant le titre de niveau 3
|
|
reserves_pattern = r"(### Indice de Herfindahl-Hirschmann - Réserves\s*\n[\s\S]*?)(?=### Indice de Herfindahl-Hirschmann - Traitement|$)"
|
|
reserves_match = re.search(reserves_pattern, section_produit, re.IGNORECASE)
|
|
|
|
if reserves_match:
|
|
reserves_ihh = reserves_match.group(1).strip()
|
|
md = re.sub(
|
|
r"<!---- AUTO-BEGIN:SECTION-IHH-RESERVES -->.*?<!---- AUTO-END:SECTION-IHH-RESERVES -->",
|
|
f"<!---- AUTO-BEGIN:SECTION-IHH-RESERVES -->\n{reserves_ihh}\n<!---- AUTO-END:SECTION-IHH-RESERVES -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
|
|
# 3. Traitement - incluant le titre de niveau 3
|
|
traitement_pattern = r"(### Indice de Herfindahl-Hirschmann - Traitement\s*\n[\s\S]*?)(?=$)"
|
|
traitement_match = re.search(traitement_pattern, section_produit, re.IGNORECASE)
|
|
|
|
if traitement_match:
|
|
traitement_ihh = traitement_match.group(1).strip()
|
|
md = re.sub(
|
|
r"<!---- AUTO-BEGIN:SECTION-IHH-TRAITEMENT -->.*?<!---- AUTO-END:SECTION-IHH-TRAITEMENT -->",
|
|
f"<!---- AUTO-BEGIN:SECTION-IHH-TRAITEMENT -->\n{traitement_ihh}\n<!---- AUTO-END:SECTION-IHH-TRAITEMENT -->",
|
|
md,
|
|
flags=re.DOTALL
|
|
)
|
|
# suppression pour le dernier minerai dans la fiche IHH
|
|
md = re.sub(r"# Tableaux de synthèse.*<!---- AUTO-END:SECTION-IHH-TRAITEMENT -->", "", md, flags=re.DOTALL)
|
|
except Exception as e:
|
|
st.error(f"Erreur lors de la génération des sections IHH: {e}")
|
|
|
|
# Nettoyer les doubles sauts de ligne
|
|
md = re.sub(r"\n{3,}", "\n\n", md)
|
|
|
|
# Ajouter les informations IVC
|
|
md = build_minerai_ivc_section(md)
|
|
|
|
# Ajouter les informations ICS
|
|
md = build_minerai_ics_section(md)
|
|
|
|
# Ajouter les informations ICS pour les composants liés au minerai
|
|
md = build_minerai_ics_composant_section(md)
|
|
|
|
return md
|