Typage des fonctions de pda et documentation

This commit is contained in:
Fabrication du Numérique 2025-06-04 21:24:56 +02:00
parent 4bb06a4801
commit 35aa7d12fa
13 changed files with 432 additions and 177 deletions

View File

@ -1,5 +1,8 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
#
import networkx as nx
""" """
Script pour générer un rapport factorisé des vulnérabilités critiques Script pour générer un rapport factorisé des vulnérabilités critiques
suivant la structure définie dans Remarques.md. suivant la structure définie dans Remarques.md.
@ -37,7 +40,16 @@ from app.plan_d_action import (
inverse_niveau_labels = {v: k for k, v in niveau_labels.items()} inverse_niveau_labels = {v: k for k, v in niveau_labels.items()}
def interface_plan_d_action(G_temp): def interface_plan_d_action(G_temp: nx.Graph) -> None:
"""Interface pour planifier l'action de sélection des minerais.
Args:
G_temp (nx.Graph): Le graphe temporaire à analyser.
Returns:
None: Modifie le state du Streamlit avec les données nécessaires
pour la génération du rapport factorisé des vulnérabilités critiques.
"""
if "sel_prod" not in st.session_state: if "sel_prod" not in st.session_state:
st.session_state.sel_prod = None st.session_state.sel_prod = None

View File

@ -132,7 +132,7 @@ INDICATEURS = {
"Capacité libre des EMS (%) rapportée chaque vendredi." "Capacité libre des EMS (%) rapportée chaque vendredi."
], ],
'Modérée': [ 'Modérée': [
"Part du second fondeur dans la production du composant audio (%).", "Part du second fondeur dans la production du composant (%).",
"Nombre de PCB « design-for-substitution » validés." "Nombre de PCB « design-for-substitution » validés."
], ],
'Difficile': [ 'Difficile': [

View File

@ -1,6 +1,15 @@
import re import re
def parse_chains_md(filepath: str) -> tuple[dict, dict, dict, list, dict, dict]: def parse_chains_md(filepath: str) -> tuple[dict, dict, dict, list, dict, dict]:
"""Lit et analyse un fichier Markdown contenant des informations sur les chaînes minérales.
Args:
filepath (str): Chemin vers le fichier Markdown à analyser.
Returns:
tuple: Un ensemble de dictionnaires et listes contenant les données extraites du fichier,
incluant les produits, composants, mineraux, chaînes et leurs descriptions détaillées.
"""
re_start_section = re.compile(r"^##\s*Chaînes\s+avec\s+risque\s+critique", re.IGNORECASE) re_start_section = re.compile(r"^##\s*Chaînes\s+avec\s+risque\s+critique", re.IGNORECASE)
re_other_h2 = re.compile(r"^##\s+(?!(Chaînes\s+avec\s+risque\s+critique))") re_other_h2 = re.compile(r"^##\s+(?!(Chaînes\s+avec\s+risque\s+critique))")
re_chain_heading = re.compile(r"^###\s*(.+)\s*→\s*(.+)\s*→\s*(.+)$") re_chain_heading = re.compile(r"^###\s*(.+)\s*→\s*(.+)\s*→\s*(.+)$")

View File

@ -1,7 +1,16 @@
import yaml import yaml
import streamlit as st import streamlit as st
def get_seuil(seuils_dict, key): def get_seuil(seuils_dict: dict, key: str) -> float|None:
"""Récupère un seuil pour une clé donnée dans le dictionnaire.
Args:
seuils_dict (dict): Dictionnaire contenant les seuils.
key (str): Clé du seuil à récupérer.
Returns:
float|None: Le seuil si existant, sinon None.
"""
try: try:
if key in seuils_dict: if key in seuils_dict:
data = seuils_dict[key] data = seuils_dict[key]
@ -16,7 +25,19 @@ def get_seuil(seuils_dict, key):
pass pass
return None return None
def set_vulnerability(v1, v2, t1, t2, seuils): def set_vulnerability(v1: int, v2: int, t1: str, t2: str, seuils: dict) -> tuple[int,str,str,str]:
"""Calcule la vulnérabilité en fonction des seuils.
Args:
v1 (int): Valeur de vulnérabilité 1.
v2 (int): Valeur de vulnérabilité 2.
t1 (str): Type 1.
t2 (str): Type 2.
seuils (dict): Dictionnaire des seuils.
Returns:
tuple[int, str, str, str]: Poids et couleurs pour les deux types.
"""
v1_poids = 1 v1_poids = 1
v1_couleur = "Vert" v1_couleur = "Vert"
if v1 > seuils[t1]["rouge"]["min"]: if v1 > seuils[t1]["rouge"]["min"]:
@ -44,7 +65,15 @@ def set_vulnerability(v1, v2, t1, t2, seuils):
return poids, couleur, v1_couleur, v2_couleur return poids, couleur, v1_couleur, v2_couleur
def colorer_couleurs(la_couleur): def colorer_couleurs(la_couleur: str) -> str:
"""Convertit une couleur en badge Markdown.
Args:
la_couleur (str): Couleur à convertir (rouge/difficile, orange/modérée, vert/facile).
Returns:
str: Badge Markdown correspondant.
"""
t = la_couleur.lower() t = la_couleur.lower()
if t == "rouge" or t == "difficile": if t == "rouge" or t == "difficile":
return f":red-badge[{la_couleur}]" return f":red-badge[{la_couleur}]"
@ -54,7 +83,15 @@ def colorer_couleurs(la_couleur):
return f":green-badge[{la_couleur}]" return f":green-badge[{la_couleur}]"
return la_couleur return la_couleur
def initialiser_seuils(config_path): def initialiser_seuils(config_path: str) -> dict:
"""Charge les seuils depuis un fichier YAML de configuration.
Args:
config_path (str): Chemin vers le fichier de configuration YAML.
Returns:
dict: Dictionnaire des seuils chargés.
"""
seuils = {} seuils = {}
try: try:

View File

@ -1,7 +1,11 @@
import streamlit as st import streamlit as st
def afficher_bloc_ihh_isg(titre, ihh, isg, details_content=""): def afficher_bloc_ihh_isg(titre, ihh, isg, details_content="", ui = True) -> str|None:
st.markdown(f"### {titre}") contenu_bloc = ""
if ui:
st.markdown(f"### {titre}")
else:
contenu_bloc = f"### {titre}\n"
if not details_content: if not details_content:
st.markdown("Données non disponibles") st.markdown("Données non disponibles")
@ -11,49 +15,74 @@ def afficher_bloc_ihh_isg(titre, ihh, isg, details_content=""):
# 1. Afficher vulnérabilité combinée en premier # 1. Afficher vulnérabilité combinée en premier
if "#### Vulnérabilité combinée IHH-ISG" in details_content: if "#### Vulnérabilité combinée IHH-ISG" in details_content:
conteneur, = st.columns([1], gap="small", border=True) contenu_md = "#### Vulnérabilité combinée IHH-ISG\n"
with conteneur: contenu_md += afficher_section_texte(lines, "#### Vulnérabilité combinée IHH-ISG", "###")
st.markdown("#### Vulnérabilité combinée IHH-ISG") contenu_md += "\n"
contenu = afficher_section_texte(lines, "#### Vulnérabilité combinée IHH-ISG", "###") if ui:
st.markdown(contenu) conteneur, = st.columns([1], gap="small", border=True)
with conteneur:
st.markdown(contenu_md)
else:
contenu_bloc += contenu_md
# 2. Afficher ISG des pays impliqués # 2. Afficher ISG des pays impliqués
if "##### ISG des pays impliqués" in details_content: if "##### ISG des pays impliqués" in details_content:
st.markdown("#### ISG des pays impliqués")
contenu = afficher_section_avec_tableau(lines, "##### ISG des pays impliqués")
st.markdown(contenu)
# Afficher le résumé ISG combiné # Afficher le résumé ISG combiné
for line in lines: for line in lines:
if "**ISG combiné:" in line: if "**ISG combiné:" in line:
st.markdown(line) st.markdown(line)
break break
contenu_md = "#### ISG des pays impliqués\n"
contenu_md += afficher_section_avec_tableau(lines, "##### ISG des pays impliqués")
contenu_md += "\n"
if ui:
st.markdown(contenu_md)
else:
contenu_bloc += contenu_md
# 3. Afficher la section IHH complète # 3. Afficher la section IHH complète
if "#### Indice de Herfindahl-Hirschmann" in details_content: if "#### Indice de Herfindahl-Hirschmann" in details_content:
st.markdown("#### Indice de Herfindahl-Hirschmann") contenu_md = "#### Indice de Herfindahl-Hirschmann\n"
# Tableau de résumé IHH # Tableau de résumé IHH
contenu = afficher_section_avec_tableau(lines, "#### Indice de Herfindahl-Hirschmann") contenu_md += afficher_section_avec_tableau(lines, "#### Indice de Herfindahl-Hirschmann")
st.markdown(contenu) contenu_md += "\n"
if ui:
st.markdown(contenu_md)
else:
contenu_bloc += contenu_md
# IHH par entreprise # IHH par entreprise
if "##### IHH par entreprise (acteurs)" in details_content: if "##### IHH par entreprise (acteurs)" in details_content:
st.markdown("##### IHH par entreprise (acteurs)") contenu_md = "##### IHH par entreprise (acteurs)\n"
contenu = afficher_section_texte(lines, "##### IHH par entreprise (acteurs)", "##### IHH par pays") contenu_md += afficher_section_texte(lines, "##### IHH par entreprise (acteurs)", "##### IHH par pays")
st.markdown(contenu) st.markdown(contenu_md)
# IHH par pays # IHH par pays
if "##### IHH par pays" in details_content: if "##### IHH par pays" in details_content:
st.markdown("##### IHH par pays") contenu_md = "##### IHH par pays\n"
contenu = afficher_section_texte(lines, "##### IHH par pays", "##### En résumé") contenu_md += afficher_section_texte(lines, "##### IHH par pays", "##### En résumé")
st.markdown(contenu) contenu_md += "\n"
if ui:
st.markdown(contenu_md)
else:
contenu_bloc += contenu_md
# En résumé # En résumé
if "##### En résumé" in details_content: if "##### En résumé" in details_content:
st.markdown("##### En résumé") contenu_md = "##### En résumé\n"
contenu = afficher_section_texte(lines, "##### En résumé", "####") contenu_md += afficher_section_texte(lines, "##### En résumé", "####")
st.markdown(contenu) contenu_md += "\n"
if ui:
st.markdown(contenu_md)
else:
contenu_bloc += contenu_md
if not ui:
return contenu_bloc
else:
return None
def afficher_section_avec_tableau(lines, section_start, section_end=None): def afficher_section_avec_tableau(lines, section_start, section_end=None):
"""Affiche une section contenant un tableau""" """Affiche une section contenant un tableau"""
@ -98,79 +127,117 @@ def afficher_section_texte(lines, section_start, section_end_marker=None):
contenu = '\n'.join(contenu_md) contenu = '\n'.join(contenu_md)
return contenu return contenu
def afficher_description(titre, description): def afficher_description(titre, description, ui = True) -> str|None:
st.markdown(f"## {titre}") contenu_bloc = ""
conteneur, = st.columns([1], gap="small", border=True) if ui:
with conteneur: st.markdown(f"### {titre}")
if description: else:
lines = description.split('\n') contenu_bloc = f"### {titre}\n"
description_lines = []
# Extraire le premier paragraphe descriptif if description:
for line in lines: lines = description.split('\n')
line = line.strip() description_lines = []
if not line:
if description_lines: # Si on a déjà du contenu, une ligne vide termine le paragraphe # Extraire le premier paragraphe descriptif
break for line in lines:
continue line = line.strip()
# Arrêter aux titres de sections ou tableaux if not line:
if (line.startswith('####') or if description_lines: # Si on a déjà du contenu, une ligne vide termine le paragraphe
line.startswith('|') or
line.startswith('**Unité')):
break break
description_lines.append(line) continue
# Arrêter aux titres de sections ou tableaux
if (line.startswith('####') or
line.startswith('|') or
line.startswith('**Unité')):
break
description_lines.append(line)
if description_lines: if description_lines:
# Rejoindre les lignes en un seul paragraphe # Rejoindre les lignes en un seul paragraphe
full_description = ' '.join(description_lines) contenu_md = ' '.join(description_lines)
st.markdown(full_description)
else:
st.markdown("Description non disponible")
else: else:
st.markdown("Description non disponible") contenu_md = "Description non disponible"
else:
contenu_md = "Description non disponible"
def afficher_caracteristiques_minerai(minerai, mineraux_data, details_content=""): if ui:
st.markdown("### Caractéristiques générales") conteneur, = st.columns([1], gap="small", border=True)
with conteneur:
st.markdown(contenu_md)
return None
else:
contenu_bloc += contenu_md
return contenu_bloc
def afficher_caracteristiques_minerai(minerai, mineraux_data, details_content="", ui = True) -> str|None:
contenu_bloc = ""
if ui:
st.markdown("### Caractéristiques générales")
else:
contenu_bloc = "### Caractéristiques générales\n"
if not details_content: if not details_content:
st.markdown("Données non disponibles") if ui:
st.markdown("Données non disponibles")
else:
contenu_bloc += "Données non disponibles\n"
return return
lines = details_content.split('\n') lines = details_content.split('\n')
# 3. Afficher la vulnérabilité combinée ICS-IVC en dernier # 3. Afficher la vulnérabilité combinée ICS-IVC en dernier
if "#### Vulnérabilité combinée ICS-IVC" in details_content: if "#### Vulnérabilité combinée ICS-IVC" in details_content:
conteneur, = st.columns([1], gap="small", border=True) contenu_md = "#### Vulnérabilité combinée ICS-IVC\n"
with conteneur: contenu_md += afficher_section_texte(lines, "#### Vulnérabilité combinée ICS-IVC", "####")
st.markdown("#### Vulnérabilité combinée ICS-IVC") contenu_md += "\n"
contenu = afficher_section_texte(lines, "#### Vulnérabilité combinée ICS-IVC", "####") if ui:
st.markdown(contenu) conteneur, = st.columns([1], gap="small", border=True)
with conteneur:
st.markdown(contenu_md)
else:
contenu_bloc += contenu_md
# 1. Afficher la section ICS complète # 1. Afficher la section ICS complète
if "#### ICS" in details_content: if "#### ICS" in details_content:
st.markdown("#### ICS") contenu_md = "#### ICS\n"
# Afficher le premier tableau ICS (avec toutes les colonnes) # Afficher le premier tableau ICS (avec toutes les colonnes)
contenu = afficher_section_avec_tableau(lines, "#### ICS", "##### Valeurs d'ICS par composant") contenu_md += afficher_section_avec_tableau(lines, "#### ICS", "##### Valeurs d'ICS par composant concerné")
st.markdown(contenu) contenu_md += "\n"
if ui:
st.markdown(contenu_md)
else:
contenu_bloc += contenu_md
# Afficher la sous-section "Valeurs d'ICS par composant" # Afficher la sous-section "Valeurs d'ICS par composant"
if "##### Valeurs d'ICS par composant" in details_content: if "##### Valeurs d'ICS par composant concerné" in details_content:
st.markdown("##### Valeurs d'ICS par composant") contenu_md = "##### Valeurs d'ICS par composant concerné\n"
contenu = afficher_section_avec_tableau(lines, "##### Valeurs d'ICS par composant", "**ICS moyen")
# Afficher le résumé ICS moyen # Afficher le résumé ICS moyen
for line in lines: for line in lines:
if "**ICS moyen" in line: if "**ICS moyen" in line:
contenu = contenu + line contenu_md += line
break break
st.markdown(contenu) contenu_md += "\n"
contenu_md += afficher_section_avec_tableau(lines, "##### Valeurs d'ICS par composant concerné", "**ICS moyen")
contenu_md += "\n"
if ui:
st.markdown(contenu_md)
else:
contenu_bloc += contenu_md
# 2. Afficher la section IVC complète # 2. Afficher la section IVC complète
if "#### IVC" in details_content: if "#### IVC" in details_content:
st.markdown("#### IVC") contenu_md = "#### IVC\n"
# Afficher tous les détails de la section IVC # Afficher tous les détails de la section IVC
contenu = afficher_section_texte(lines, "#### IVC", "#### Vulnérabilité combinée ICS-IVC") contenu_md += afficher_section_texte(lines, "#### IVC", "#### Vulnérabilité combinée ICS-IVC")
st.markdown(contenu) contenu_md += "\n"
if ui:
st.markdown(contenu_md)
return None
else:
contenu_bloc += contenu_md
return contenu_bloc

View File

@ -14,7 +14,7 @@ from app.plan_d_action.utils.data import (
initialiser_seuils initialiser_seuils
) )
def calcul_poids_chaine(poids_A, poids_F, poids_T, poids_E, poids_M): def calcul_poids_chaine(poids_A: int, poids_F: int, poids_T: int, poids_E: int, poids_M: int) -> tuple[str,dict,int]:
poids_total = (\ poids_total = (\
poids_A * poids_operation["Assemblage"] + \ poids_A * poids_operation["Assemblage"] + \
poids_F * poids_operation["Fabrication"] + \ poids_F * poids_operation["Fabrication"] + \
@ -35,7 +35,7 @@ def calcul_poids_chaine(poids_A, poids_F, poids_T, poids_E, poids_M):
return criticite_chaine, niveau_criticite, poids_total return criticite_chaine, niveau_criticite, poids_total
def analyser_chaines(chaines, produits, composants, mineraux, seuils, top_n=None): def analyser_chaines(chaines: list[dict], produits: dict, composants: dict, mineraux: dict, seuils: dict, top_n: int = 0) -> list[tuple[str, str, int]]:
resultats = [] resultats = []
for chaine in chaines: for chaine in chaines:
@ -64,7 +64,7 @@ def analyser_chaines(chaines, produits, composants, mineraux, seuils, top_n=None
resultats.sort(key=lambda x: x["poids_total"], reverse=True) resultats.sort(key=lambda x: x["poids_total"], reverse=True)
# Si top_n n'est pas spécifié, tout est retourné # Si top_n n'est pas spécifié, tout est retourné
if top_n is None or top_n >= len(resultats): if top_n == 0 or top_n >= len(resultats):
return resultats return resultats
# Déterminer le seuil de coupure # Déterminer le seuil de coupure
@ -75,7 +75,7 @@ def analyser_chaines(chaines, produits, composants, mineraux, seuils, top_n=None
return top_resultats return top_resultats
def tableau_de_bord(chains, produits, composants, mineraux, seuils): def tableau_de_bord(chains: list[dict], produits: dict, composants: dict, mineraux: dict, seuils: dict):
col_left, col_right = st.columns([2, 3], gap="small", border=True) col_left, col_right = st.columns([2, 3], gap="small", border=True)
with col_left: with col_left:
st.markdown("**<u>Panneau de sélection</u>**", unsafe_allow_html=True) st.markdown("**<u>Panneau de sélection</u>**", unsafe_allow_html=True)
@ -139,7 +139,7 @@ def tableau_de_bord(chains, produits, composants, mineraux, seuils):
couleur_A_ihh, couleur_A_isg, couleur_F_ihh, couleur_F_isg, couleur_T_ihh, couleur_T_isg,couleur_E_ihh, couleur_E_isg, couleur_M_ics, couleur_M_ivc couleur_A_ihh, couleur_A_isg, couleur_F_ihh, couleur_F_isg, couleur_T_ihh, couleur_T_isg,couleur_E_ihh, couleur_E_isg, couleur_M_ics, couleur_M_ivc
) )
def afficher_criticites(produits, composants, mineraux, sel_prod, sel_comp, sel_miner, seuils): def afficher_criticites(produits: dict, composants: dict, mineraux: dict, sel_prod: str, sel_comp: str, sel_miner: str, seuils: dict) -> None:
with st.expander("Vue densemble des criticités", expanded=True): with st.expander("Vue densemble des criticités", expanded=True):
st.markdown("## Vue densemble des criticités", unsafe_allow_html=True) st.markdown("## Vue densemble des criticités", unsafe_allow_html=True)
@ -200,7 +200,7 @@ def afficher_criticites(produits, composants, mineraux, sel_prod, sel_comp, sel_
def afficher_explications_et_details( def afficher_explications_et_details(
couleur_A, poids_A, couleur_F, poids_F, couleur_T, poids_T, couleur_E, poids_E, couleur_M, poids_M, couleur_A, poids_A, couleur_F, poids_F, couleur_T, poids_T, couleur_E, poids_E, couleur_M, poids_M,
produits, composants, mineraux, sel_prod, sel_comp, sel_miner, produits, composants, mineraux, sel_prod, sel_comp, sel_miner,
couleur_A_ihh, couleur_A_isg, couleur_F_ihh, couleur_F_isg, couleur_T_ihh, couleur_T_isg,couleur_E_ihh, couleur_E_isg, couleur_M_ics, couleur_M_ivc): couleur_A_ihh, couleur_A_isg, couleur_F_ihh, couleur_F_isg, couleur_T_ihh, couleur_T_isg,couleur_E_ihh, couleur_E_isg, couleur_M_ics, couleur_M_ivc, ui = True) -> str|None:
with st.expander("Explications et détails", expanded = True): with st.expander("Explications et détails", expanded = True):
from collections import Counter from collections import Counter
couleurs = [couleur_A, couleur_F, couleur_T, couleur_E, couleur_M] couleurs = [couleur_A, couleur_F, couleur_T, couleur_E, couleur_M]
@ -209,7 +209,7 @@ def afficher_explications_et_details(
nb_orange = compte["Orange"] nb_orange = compte["Orange"]
nb_vert = compte["Vert"] nb_vert = compte["Vert"]
st.markdown(f""" contenu_md = f"""
Pour cette chaîne :blue-background[**{sel_prod} <-> {sel_comp} <-> {sel_miner}**], avec {nb_rouge} criticité(s) de niveau {colorer_couleurs("Rouge")}, {nb_orange} {colorer_couleurs("Orange")} et {nb_vert} {colorer_couleurs("Vert")}, les indices individuels par opération sont : Pour cette chaîne :blue-background[**{sel_prod} <-> {sel_comp} <-> {sel_miner}**], avec {nb_rouge} criticité(s) de niveau {colorer_couleurs("Rouge")}, {nb_orange} {colorer_couleurs("Orange")} et {nb_vert} {colorer_couleurs("Vert")}, les indices individuels par opération sont :
* **{sel_prod} - Assemblage** : {colorer_couleurs(couleur_A)} ({poids_A}) * **{sel_prod} - Assemblage** : {colorer_couleurs(couleur_A)} ({poids_A})
@ -230,31 +230,65 @@ def afficher_explications_et_details(
* **{sel_miner} - Minerai** : {colorer_couleurs(couleur_M)} ({poids_M}) * **{sel_miner} - Minerai** : {colorer_couleurs(couleur_M)} ({poids_M})
* ICS = {mineraux[sel_miner]["ICS"]} ({colorer_couleurs(couleur_M_ics)}) <-> IVC = {mineraux[sel_miner]["IVC"]} ({colorer_couleurs(couleur_M_ivc)}) * ICS = {mineraux[sel_miner]["ICS"]} ({colorer_couleurs(couleur_M_ics)}) <-> IVC = {mineraux[sel_miner]["IVC"]} ({colorer_couleurs(couleur_M_ivc)})
* pondération de la Substitution dans le calcul de la criticité globale : 2 * pondération de la Substitution dans le calcul de la criticité globale : 2
""") """
contenu_md += "\n"
if ui:
st.markdown(contenu_md)
return None
else:
return contenu_md
def afficher_preconisations_et_indicateurs_generiques(niveau_criticite, poids_A, poids_F, poids_T, poids_E, poids_M): def afficher_preconisations_et_indicateurs_generiques(niveau_criticite: dict, poids_A: int, poids_F: int, poids_T: int, poids_E: int, poids_M: int, ui: bool = True) -> tuple[str|None,str|None]:
with st.expander("Préconisations et indicateurs génériques"): contenu_md_left = "### Préconisations :\n\n"
col_left, col_right = st.columns([1, 1], gap="small", border=True) contenu_md_left += "Mise en œuvre : \n"
with col_left:
st.markdown("### Préconisations :\n\n")
st.markdown("Mise en œuvre : \n")
for niveau, contenu in PRECONISATIONS.items():
if niveau in niveau_criticite:
contenu_md = f"* {colorer_couleurs(niveau)}\n"
for p in PRECONISATIONS[niveau]:
contenu_md += f" - {p}\n"
st.markdown(contenu_md)
with col_right:
st.markdown("### Indicateurs :\n\n")
st.markdown("Mise en œuvre : \n")
for niveau, contenu in INDICATEURS.items():
if niveau in niveau_criticite:
contenu_md = f"* {colorer_couleurs(niveau)}\n"
for p in INDICATEURS[niveau]:
contenu_md += f" - {p}\n"
st.markdown(contenu_md)
def afficher_preconisations_et_indicateurs_specifiques(sel_prod, sel_comp, sel_miner, niveau_criticite_operation): for niveau, contenu in PRECONISATIONS.items():
if niveau in niveau_criticite:
contenu_md_left = f"* {colorer_couleurs(niveau)}\n"
for p in PRECONISATIONS[niveau]:
contenu_md_left += f" - {p}\n"
contenu_md_right = "### Indicateurs :\n\n"
contenu_md_right += "Mise en œuvre : \n"
for niveau, contenu in INDICATEURS.items():
if niveau in niveau_criticite:
contenu_md_right = f"* {colorer_couleurs(niveau)}\n"
for p in INDICATEURS[niveau]:
contenu_md_right += f" - {p}\n"
if ui:
with st.expander("Préconisations et indicateurs génériques"):
col_left, col_right = st.columns([1, 1], gap="small", border=True)
with col_left:
st.markdown(contenu_md_left)
with col_right:
st.markdown(contenu_md_right)
return None, None
else:
return contenu_md_left, contenu_md_right
def afficher_preconisations_specifiques(operation: str, niveau_criticite_operation: dict) -> str:
contenu_md = "#### Préconisations :\n\n"
contenu_md += "Mise en œuvre : \n"
for niveau, contenu in PRECONISATIONS[operation].items():
if niveau in niveau_criticite_operation[operation]:
contenu_md += f"* {colorer_couleurs(niveau)}\n"
for p in PRECONISATIONS[operation][niveau]:
contenu_md += f" - {p}\n"
return(contenu_md)
def afficher_indicateurs_specifiques(operation: str, niveau_criticite_operation: dict) -> str:
contenu_md = "#### Indicateurs :\n\n"
contenu_md += "Mise en œuvre : \n"
for niveau, contenu in INDICATEURS[operation].items():
if niveau in niveau_criticite_operation[operation]:
contenu_md += f"* {colorer_couleurs(niveau)}\n"
for p in INDICATEURS[operation][niveau]:
contenu_md += f" - {p}\n"
return(contenu_md)
def afficher_preconisations_et_indicateurs_specifiques(sel_prod: str, sel_comp: str, sel_miner: str, niveau_criticite_operation: dict) -> None:
for operation in ["Assemblage", "Fabrication", "Traitement", "Extraction"]: for operation in ["Assemblage", "Fabrication", "Traitement", "Extraction"]:
if operation == "Assemblage": if operation == "Assemblage":
item = sel_prod item = sel_prod
@ -266,25 +300,11 @@ def afficher_preconisations_et_indicateurs_specifiques(sel_prod, sel_comp, sel_m
st.markdown(f"### {operation} -> :blue-background[{item}]") st.markdown(f"### {operation} -> :blue-background[{item}]")
col_left, col_right = st.columns([1, 1], gap="small", border=True) col_left, col_right = st.columns([1, 1], gap="small", border=True)
with col_left: with col_left:
st.markdown("#### Préconisations :\n\n") st.markdown(afficher_preconisations_specifiques(operation, niveau_criticite_operation))
st.markdown("Mise en œuvre : \n")
for niveau, contenu in PRECONISATIONS[operation].items():
if niveau in niveau_criticite_operation[operation]:
contenu_md = f"* {colorer_couleurs(niveau)}\n"
for p in PRECONISATIONS[operation][niveau]:
contenu_md += f" - {p}\n"
st.markdown(contenu_md)
with col_right: with col_right:
st.markdown("#### Indicateurs :\n\n") st.markdown(afficher_indicateurs_specifiques(operation, niveau_criticite_operation))
st.markdown("Mise en œuvre : \n")
for niveau, contenu in INDICATEURS[operation].items():
if niveau in niveau_criticite_operation[operation]:
contenu_md = f"* {colorer_couleurs(niveau)}\n"
for p in INDICATEURS[operation][niveau]:
contenu_md += f" - {p}\n"
st.markdown(contenu_md)
def afficher_preconisations_et_indicateurs(niveau_criticite, sel_prod, sel_comp, sel_miner, poids_A, poids_F, poids_T, poids_E, poids_M): def afficher_preconisations_et_indicateurs(niveau_criticite: dict, sel_prod: str, sel_comp: str, sel_miner: str, poids_A: int, poids_F: int, poids_T: int, poids_E: int, poids_M: int) -> None:
st.markdown("## Préconisations et indicateurs") st.markdown("## Préconisations et indicateurs")
afficher_preconisations_et_indicateurs_generiques(niveau_criticite, poids_A, poids_F, poids_T, poids_E, poids_M) afficher_preconisations_et_indicateurs_generiques(niveau_criticite, poids_A, poids_F, poids_T, poids_E, poids_M)
@ -306,7 +326,7 @@ def afficher_preconisations_et_indicateurs(niveau_criticite, sel_prod, sel_comp,
afficher_preconisations_et_indicateurs_specifiques(sel_prod, sel_comp, sel_miner, niveau_criticite_operation) afficher_preconisations_et_indicateurs_specifiques(sel_prod, sel_comp, sel_miner, niveau_criticite_operation)
def afficher_details_operations(produits, composants, mineraux, sel_prod, sel_comp, sel_miner, details_sections): def afficher_details_operations(produits, composants, mineraux, sel_prod, sel_comp, sel_miner, details_sections) -> None:
st.markdown("## Détails des opérations") st.markdown("## Détails des opérations")
with st.expander(f"{sel_prod} et Assemblage"): with st.expander(f"{sel_prod} et Assemblage"):
@ -332,7 +352,7 @@ def afficher_details_operations(produits, composants, mineraux, sel_prod, sel_co
afficher_caracteristiques_minerai(sel_miner, mineraux[sel_miner], minerai_general) afficher_caracteristiques_minerai(sel_miner, mineraux[sel_miner], minerai_general)
def initialiser_interface(filepath: str, config_path: str = "assets/config.yaml"): def initialiser_interface(filepath: str, config_path: str = "assets/config.yaml") -> None:
produits, composants, mineraux, chains, descriptions, details_sections = parse_chains_md(filepath) produits, composants, mineraux, chains, descriptions, details_sections = parse_chains_md(filepath)

View File

@ -1,7 +1,21 @@
from typing import Dict, Tuple, Union, List, Set
import networkx as nx import networkx as nx
def exporter_graphe_filtre(G, liens_chemins): def exporter_graphe_filtre(
"""Gère l'export du graphe filtré au format DOT""" G: nx.Graph,
liens_chemins: List[Tuple[Union[str, int], Union[str, int]]]
) -> nx.Graph:
"""Gère l'export du graphe filtré au format DOT.
Args:
G (nx.Graph): Le graphe d'origine à exporter.
liens_chemins (list): Liste des tuples contenant les paires de nœuds reliées
par un chemin dans le graphe, avec leurs attributs associés.
Returns:
tuple: Un tuple contenant le graphe exporté sous forme de DiGraph
et le dictionnaire des attributs du graphe exporté.
"""
G_export = nx.DiGraph() G_export = nx.DiGraph()
for u, v in liens_chemins: for u, v in liens_chemins:
@ -17,8 +31,26 @@ def exporter_graphe_filtre(G, liens_chemins):
return(G_export) return(G_export)
def extraire_liens_filtres(chemins, niveaux, niveau_depart, niveau_arrivee, niveaux_speciaux): def extraire_liens_filtres(
"""Extrait les liens des chemins en respectant les niveaux""" chemins: List[List[Union[str, int]]],
niveaux: Dict[str | int, int],
niveau_depart: int,
niveau_arrivee: int,
niveaux_speciaux: list[int]
) -> List[Tuple[Union[str, int], Union[str, int]]]:
"""Extrait les liens des chemins en respectant les niveaux.
Args:
chemins (list): Liste des chemins dans le graphe.
niveaux (dict): Dictionnaire associant chaque nœud au niveau correspondant.
niveau_depart (int): Niveau de départ pour la sélection des liens.
niveau_arrivee (int): Niveau d'arrivée pour la sélection des liens.
niveaux_speciaux (set): Ensemble des niveaux spéciaux à considérer dans le filtrage.
Returns:
set: Ensemble des paires de nœuds constituant les liens du graphe filtré
en respectant les niveaux et les niveaux spéciaux demandés.
"""
liens = set() liens = set()
for chemin in chemins: for chemin in chemins:
for i in range(len(chemin) - 1): for i in range(len(chemin) - 1):

View File

@ -1,5 +1,16 @@
def extraire_niveaux(G): from typing import Dict
"""Extrait les niveaux des nœuds du graphe""" import networkx as nx
def extraire_niveaux(G: nx.Graph) -> Dict[str | int, int]:
"""Extrait les niveaux des nœuds du graphe.
Args:
G (nx.Graph): Le graphe d'origine à analyser.
Returns:
dict: Un dictionnaire associant chaque nœud au niveau correspondant.
Les valeurs sont des entiers représentant les niveaux.
"""
niveaux = {} niveaux = {}
for node, attrs in G.nodes(data=True): for node, attrs in G.nodes(data=True):
niveau_str = attrs.get("niveau") niveau_str = attrs.get("niveau")

View File

@ -1,5 +1,17 @@
def preparer_graphe(G): from typing import Dict, Tuple, Union
"""Nettoie et prépare le graphe pour l'analyse.""" import networkx as nx
def preparer_graphe(G: nx.Graph) -> Tuple[nx.Graph, Dict[Union[str, int], int]]:
"""Nettoie et prépare le graphe pour l'analyse.
Args:
G (nx.Graph): Le graphe d'origine à nettoyer.
Returns:
tuple: Un tuple contenant le graphe nettoyé et les niveaux temporels associés
aux nœuds du graphe. Le graphe nettoyé a eu ses nœuds qui ne respectaient
pas les critères d'admissibilité enlevés.
"""
niveaux_temp = { niveaux_temp = {
node: int(str(attrs.get("niveau")).strip('"')) node: int(str(attrs.get("niveau")).strip('"'))
for node, attrs in G.nodes(data=True) for node, attrs in G.nodes(data=True)

View File

@ -1,3 +1,4 @@
from typing import Any, Dict, Tuple, List, Union, Optional
import streamlit as st import streamlit as st
import networkx as nx import networkx as nx
from utils.translations import _ from utils.translations import _
@ -7,8 +8,16 @@ from utils.graph_utils import (
extraire_chemins_vers extraire_chemins_vers
) )
def selectionner_minerais(G, noeuds_depart): def selectionner_minerais(G: nx.Graph, noeuds_depart: List[Any]) -> List[Union[str, int]]:
"""Interface pour sélectionner les minerais si nécessaire.""" """Interface pour sélectionner les minerais si nécessaire.
Args:
G (nx.Graph): Le graphe des relations entre les nœuds.
noeuds_depart (list): Les nœuds de départ qui doivent être considérés.
Returns:
list: La liste des nœuds sélectionnés comme minerais.
"""
minerais_selection = None minerais_selection = None
st.markdown(f"## {str(_('pages.plan_d_action.select_minerals'))}") st.markdown(f"## {str(_('pages.plan_d_action.select_minerals'))}")
@ -32,9 +41,21 @@ def selectionner_minerais(G, noeuds_depart):
return minerais_selection return minerais_selection
def selectionner_noeuds(
G: nx.Graph,
niveaux_temp: Dict[Union[str, int], int],
niveau_depart: int
) -> Tuple[Optional[List[Union[str, int]]], List[Union[str, int]]]:
"""Interface pour sélectionner les nœuds spécifiques de départ et d'arrivée.
def selectionner_noeuds(G, niveaux_temp, niveau_depart): Args:
"""Interface pour sélectionner les nœuds spécifiques de départ et d'arrivée.""" G (nx.Graph): Le graphe des relations entre les nœuds.
niveaux_temp (dict): Dictionnaire contenant les niveaux des nœuds.
niveau_depart (int): Niveau à partir duquel commencer la sélection.
Returns:
tuple: La paire de départ et d'arrivée des nœuds sélectionnés.
"""
st.markdown("---") st.markdown("---")
st.markdown(f"## {str(_('pages.plan_d_action.fine_selection'))}") st.markdown(f"## {str(_('pages.plan_d_action.fine_selection'))}")
@ -49,8 +70,27 @@ def selectionner_noeuds(G, niveaux_temp, niveau_depart):
return noeuds_depart, noeuds_arrivee return noeuds_depart, noeuds_arrivee
def extraire_chemins_selon_criteres(G, niveaux, niveau_depart, noeuds_depart, noeuds_arrivee, minerais): def extraire_chemins_selon_criteres(
"""Extrait les chemins selon les critères spécifiés""" G: nx.Graph,
niveaux: Dict[str | int, int],
niveau_depart: int,
noeuds_depart: Optional[List[Union[str, int]]],
noeuds_arrivee: List[Union[str, int]],
minerais: Optional[List[Union[str, int]]]
) -> List[List[str | int]]:
"""Extrait les chemins selon les critères spécifiés.
Args:
G (nx.Graph): Le graphe des relations entre les nœuds.
niveaux (dict): Dictionnaire contenant les niveaux des nœuds.
niveau_depart (int): Niveau à partir duquel commencer la sélection.
noeuds_depart (list, optional): Les nœuds de départ qui doivent être considérés.
noeuds_arrivee (list): Les nœuds d'arrivée qui doivent être inclus dans les chemins.
minerais (list, optional): La liste des nœuds sélectionnés comme minerais.
Returns:
list: Liste des chemins trouvés selon les critères spécifiés.
"""
chemins = [] chemins = []
if noeuds_depart and noeuds_arrivee: if noeuds_depart and noeuds_arrivee:
for nd in noeuds_depart: for nd in noeuds_depart:

View File

@ -1,7 +1,22 @@
from typing import Dict, Optional
import re import re
from app.plan_d_action.utils.interface import CORRESPONDANCE_COULEURS from app.plan_d_action.utils.interface import CORRESPONDANCE_COULEURS
def remplacer_par_badge(markdown_text, correspondance=CORRESPONDANCE_COULEURS): def remplacer_par_badge(
markdown_text: str,
correspondance: Optional[Dict[str, str]] = CORRESPONDANCE_COULEURS
) -> str:
"""Remplace certains mots par des badges colorés dans un texte Markdown.
Args:
markdown_text (str): Le texte Markdown à modifier.
correspondance (dict, optional): Dictionnaire qui mappe les mots
à remplacer vers les couleurs de leurs badges. Si None, utilise
CORRESPONDANCE_COULEURS par défaut.
Returns:
str: Le texte Markdown modifié avec des badges ajoutés.
"""
# Échappe les mots à remplacer s'ils contiennent des accents ou espaces # Échappe les mots à remplacer s'ils contiennent des accents ou espaces
for mot, couleur in correspondance.items(): for mot, couleur in correspondance.items():
# Utilise des bords de mots (\b) pour éviter les remplacements partiels # Utilise des bords de mots (\b) pour éviter les remplacements partiels

View File

@ -3366,7 +3366,7 @@ Le hafnium est un métal de transition rare, gris-argenté, ductile et lustré,
| SSDM2 | 0.80 | 0.80 | 0.80 | 0.80 | | SSDM2 | 0.80 | 0.80 | 0.80 | 0.80 |
| StockageEMMC | 0.80 | 0.80 | 0.80 | 0.80 | | StockageEMMC | 0.80 | 0.80 | 0.80 | 0.80 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -3550,7 +3550,7 @@ Le cuivre est un métal de transition rouge-brun, malléable et ductile, connu p
| CarteMere | 0.81 | 0.90 | 0.80 | 0.70 | | CarteMere | 0.81 | 0.90 | 0.80 | 0.70 |
| Connecteurs | 0.81 | 0.90 | 0.80 | 0.70 | | Connecteurs | 0.81 | 0.90 | 0.80 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -3770,7 +3770,7 @@ Le germanium est un métalloïde gris-blanc, élément numéro 32 du tableau pé
| ProcesseurASIC | 0.64 | 0.70 | 0.60 | 0.60 | | ProcesseurASIC | 0.64 | 0.70 | 0.60 | 0.60 |
| ProcesseurX86 | 0.64 | 0.70 | 0.60 | 0.60 | | ProcesseurX86 | 0.64 | 0.70 | 0.60 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -3978,7 +3978,7 @@ Le silicium constitue un matériau stratégique pour de nombreux secteurs indust
| SSDM2 | 0.90 | 0.90 | 0.90 | 0.90 | | SSDM2 | 0.90 | 0.90 | 0.90 | 0.90 |
| StockageEMMC | 0.90 | 0.90 | 0.90 | 0.90 | | StockageEMMC | 0.90 | 0.90 | 0.90 | 0.90 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -4184,7 +4184,7 @@ Le palladium n'existe pas à l'état natif dans la nature mais se trouve princip
| ProcesseurARM | 0.50 | 0.50 | 0.40 | 0.60 | | ProcesseurARM | 0.50 | 0.50 | 0.40 | 0.60 |
| ProcesseurX86 | 0.50 | 0.50 | 0.40 | 0.60 | | ProcesseurX86 | 0.50 | 0.50 | 0.40 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -4385,7 +4385,7 @@ Le phosphore est un élément chimique non métallique, essentiel à toute forme
| ProcesseurASIC | 0.50 | 0.50 | 0.40 | 0.60 | | ProcesseurASIC | 0.50 | 0.50 | 0.40 | 0.60 |
| ProcesseurX86 | 0.50 | 0.50 | 0.40 | 0.60 | | ProcesseurX86 | 0.50 | 0.50 | 0.40 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -4597,7 +4597,7 @@ L'antimoine est un métalloïde blanc-argenté, cristallin et cassant, qui prés
| ProcesseurASIC | 0.60 | 0.60 | 0.50 | 0.70 | | ProcesseurASIC | 0.60 | 0.60 | 0.50 | 0.70 |
| ProcesseurX86 | 0.60 | 0.60 | 0.50 | 0.70 | | ProcesseurX86 | 0.60 | 0.60 | 0.50 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -4800,7 +4800,7 @@ Le tantale est un métal de transition rare, gris-bleu, dense et réfractaire, d
| SSDM2 | 0.70 | 0.70 | 0.70 | 0.70 | | SSDM2 | 0.70 | 0.70 | 0.70 | 0.70 |
| StockageEMMC | 0.64 | 0.70 | 0.60 | 0.60 | | StockageEMMC | 0.64 | 0.70 | 0.60 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -4988,7 +4988,7 @@ L'argent est un métal précieux qui joue un rôle essentiel mais discret dans l
| CarteMere | 0.61 | 0.70 | 0.50 | 0.60 | | CarteMere | 0.61 | 0.70 | 0.50 | 0.60 |
| Connecteurs | 0.61 | 0.70 | 0.50 | 0.60 | | Connecteurs | 0.61 | 0.70 | 0.50 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -5186,7 +5186,7 @@ L'étain est un métal gris-argent, malléable, moyennement ductile à températ
| CarteMere | 0.60 | 0.60 | 0.60 | 0.60 | | CarteMere | 0.60 | 0.60 | 0.60 | 0.60 |
| Connecteurs | 0.60 | 0.60 | 0.60 | 0.60 | | Connecteurs | 0.60 | 0.60 | 0.60 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -5382,7 +5382,7 @@ Le lithium est un métal alcalin léger, blanc-argenté, qui se caractérise par
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Batterie | 0.51 | 0.60 | 0.50 | 0.40 | | Batterie | 0.51 | 0.60 | 0.50 | 0.40 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -5589,7 +5589,7 @@ Le nickel est un métal de transition gris-argenté, ferromagnétique, prisé po
| Connecteurs | 0.50 | 0.50 | 0.40 | 0.60 | | Connecteurs | 0.50 | 0.50 | 0.40 | 0.60 |
| Batterie | 0.44 | 0.50 | 0.40 | 0.40 | | Batterie | 0.44 | 0.50 | 0.40 | 0.40 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -5810,7 +5810,7 @@ Le gallium est un métal rare aux propriétés physico-chimiques remarquables, d
| EcranSpecifique | 0.41 | 0.50 | 0.40 | 0.30 | | EcranSpecifique | 0.41 | 0.50 | 0.40 | 0.30 |
| CreusetGraphite | 0.37 | 0.40 | 0.30 | 0.40 | | CreusetGraphite | 0.37 | 0.40 | 0.30 | 0.40 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -6005,7 +6005,7 @@ Le lanthane est un métal de transition appartenant à la famille des terres rar
| Camera | 0.64 | 0.70 | 0.60 | 0.60 | | Camera | 0.64 | 0.70 | 0.60 | 0.60 |
| Batterie | 0.54 | 0.60 | 0.50 | 0.50 | | Batterie | 0.54 | 0.60 | 0.50 | 0.50 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -6196,7 +6196,7 @@ Le graphite existe sous deux formes principales : naturel (extrait de gisements
| Batterie | 0.51 | 0.60 | 0.50 | 0.40 | | Batterie | 0.51 | 0.60 | 0.50 | 0.40 |
| CreusetGraphite | 0.44 | 0.50 | 0.30 | 0.50 | | CreusetGraphite | 0.44 | 0.50 | 0.30 | 0.50 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -6396,7 +6396,7 @@ La demande mondiale continue d'être soutenue par le secteur de la galvanisation
| Batterie | 0.30 | 0.30 | 0.20 | 0.40 | | Batterie | 0.30 | 0.30 | 0.20 | 0.40 |
| Boitier | 0.30 | 0.30 | 0.20 | 0.40 | | Boitier | 0.30 | 0.30 | 0.20 | 0.40 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -6599,7 +6599,7 @@ Le cobalt est un métal de transition gris, brillant et ferromagnétique, décou
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Batterie | 0.57 | 0.60 | 0.60 | 0.50 | | Batterie | 0.57 | 0.60 | 0.60 | 0.50 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -6797,7 +6797,7 @@ Le manganèse est un métal de transition gris-argenté, dur et cassant, caract
| Batterie | 0.40 | 0.40 | 0.30 | 0.50 | | Batterie | 0.40 | 0.40 | 0.30 | 0.50 |
| Boitier | 0.40 | 0.40 | 0.30 | 0.50 | | Boitier | 0.40 | 0.40 | 0.30 | 0.50 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -7004,7 +7004,7 @@ Malgré sa rareté (production mondiale de quelques centaines de tonnes par an),
| Capteurs | 0.70 | 0.70 | 0.70 | 0.70 | | Capteurs | 0.70 | 0.70 | 0.70 | 0.70 |
| DisqueDur | 0.64 | 0.70 | 0.60 | 0.60 | | DisqueDur | 0.64 | 0.70 | 0.60 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -7193,7 +7193,7 @@ Le titane est un métal de transition léger, résistant et de couleur gris arge
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Boitier | 0.67 | 0.70 | 0.60 | 0.70 | | Boitier | 0.67 | 0.70 | 0.60 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -7386,7 +7386,7 @@ Le scandium est un métal de transition léger appartenant au groupe IIIB du tab
| ProcesseurASIC | 0.70 | 0.70 | 0.70 | 0.70 | | ProcesseurASIC | 0.70 | 0.70 | 0.70 | 0.70 |
| ProcesseurX86 | 0.70 | 0.70 | 0.70 | 0.70 | | ProcesseurX86 | 0.70 | 0.70 | 0.70 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -7569,7 +7569,7 @@ Le chrome est un métal de transition de numéro atomique 24, symbole Cr, caract
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Boitier | 0.39 | 0.30 | 0.40 | 0.50 | | Boitier | 0.39 | 0.30 | 0.40 | 0.50 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -7759,7 +7759,7 @@ Le magnésium est un métal alcalino-terreux léger, blanc argenté, qui présen
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Boitier | 0.50 | 0.50 | 0.40 | 0.60 | | Boitier | 0.50 | 0.50 | 0.40 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -7966,7 +7966,7 @@ Le cérium est un métal lanthanide gris-argenté, malléable et ductile, décou
| EcranLCD | 0.70 | 0.70 | 0.70 | 0.70 | | EcranLCD | 0.70 | 0.70 | 0.70 | 0.70 |
| EcranOLED | 0.64 | 0.70 | 0.60 | 0.60 | | EcranOLED | 0.64 | 0.70 | 0.60 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -8148,7 +8148,7 @@ L'holmium est un métal de terre rare appartenant à la famille des lanthanides,
| Camera | 0.84 | 0.90 | 0.80 | 0.80 | | Camera | 0.84 | 0.90 | 0.80 | 0.80 |
| Capteurs | 0.84 | 0.90 | 0.80 | 0.80 | | Capteurs | 0.84 | 0.90 | 0.80 | 0.80 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -8333,7 +8333,7 @@ L'europium est un métal de la série des lanthanides, découvert en 1901 par Eu
| EcranLCD | 0.81 | 0.90 | 0.80 | 0.70 | | EcranLCD | 0.81 | 0.90 | 0.80 | 0.70 |
| EcranMiniLED | 0.81 | 0.90 | 0.80 | 0.70 | | EcranMiniLED | 0.81 | 0.90 | 0.80 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -8515,7 +8515,7 @@ Le terbium est un élément métallique du groupe des lanthanides, découvert en
| EcranLCD | 0.81 | 0.90 | 0.80 | 0.70 | | EcranLCD | 0.81 | 0.90 | 0.80 | 0.70 |
| EcranMiniLED | 0.81 | 0.90 | 0.80 | 0.70 | | EcranMiniLED | 0.81 | 0.90 | 0.80 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -8703,7 +8703,7 @@ L'yttrium est un métal de transition du groupe 3, souvent classé parmi les ter
| EcranMiniLED | 0.74 | 0.80 | 0.70 | 0.70 | | EcranMiniLED | 0.74 | 0.80 | 0.70 | 0.70 |
| EcranOLED | 0.70 | 0.70 | 0.70 | 0.70 | | EcranOLED | 0.70 | 0.70 | 0.70 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -8888,7 +8888,7 @@ Le béryllium est un métal alcalino-terreux léger, dur et fragile, découvert
| Connecteurs | 0.64 | 0.70 | 0.60 | 0.60 | | Connecteurs | 0.64 | 0.70 | 0.60 | 0.60 |
| Connectivite | 0.64 | 0.70 | 0.60 | 0.60 | | Connectivite | 0.64 | 0.70 | 0.60 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -9069,7 +9069,7 @@ Le secteur technologique émerge comme nouveau pilier de croissance (+7% en 2024
| ProcesseurASIC | 0.60 | 0.60 | 0.60 | 0.60 | | ProcesseurASIC | 0.60 | 0.60 | 0.60 | 0.60 |
| ProcesseurX86 | 0.60 | 0.60 | 0.60 | 0.60 | | ProcesseurX86 | 0.60 | 0.60 | 0.60 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -9258,7 +9258,7 @@ Le quartz ultra-pur 5N représente l'une des matières premières les plus criti
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| CreusetQuartz | 0.74 | 0.80 | 0.70 | 0.70 | | CreusetQuartz | 0.74 | 0.80 | 0.70 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -9452,7 +9452,7 @@ Principalement utilisé dans la fabrication de carbures cémentés (50% des usag
| ProcesseurASIC | 0.60 | 0.60 | 0.50 | 0.70 | | ProcesseurASIC | 0.60 | 0.60 | 0.50 | 0.70 |
| ProcesseurX86 | 0.60 | 0.60 | 0.50 | 0.70 | | ProcesseurX86 | 0.60 | 0.60 | 0.50 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -9652,7 +9652,7 @@ Le samarium est un métal des terres rares du groupe des lanthanides, caractéri
| Capteurs | 0.74 | 0.80 | 0.70 | 0.70 | | Capteurs | 0.74 | 0.80 | 0.70 | 0.70 |
| Connectivite | 0.64 | 0.70 | 0.60 | 0.60 | | Connectivite | 0.64 | 0.70 | 0.60 | 0.60 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -9840,7 +9840,7 @@ Le gadolinium est un métal rare, blanc-argenté, appartenant à la famille des
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Capteurs | 0.74 | 0.80 | 0.70 | 0.70 | | Capteurs | 0.74 | 0.80 | 0.70 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -10025,7 +10025,7 @@ L'erbium est un métal de transition appartenant au groupe des terres rares, dé
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Connectivite | 0.74 | 0.80 | 0.70 | 0.70 | | Connectivite | 0.74 | 0.80 | 0.70 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -10212,7 +10212,7 @@ Le dysprosium est un métal lanthanide rare de couleur blanc-argenté, découver
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Audio | 0.70 | 0.70 | 0.70 | 0.70 | | Audio | 0.70 | 0.70 | 0.70 | 0.70 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -10391,7 +10391,7 @@ Le néodyme est un métal de transition appartenant à la famille des lanthanide
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Audio | 0.47 | 0.50 | 0.50 | 0.40 | | Audio | 0.47 | 0.50 | 0.50 | 0.40 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |
@ -10585,7 +10585,7 @@ Le praséodyme est un métal de la famille des lanthanides (terres rares), déco
| :-- | :--: | :--: | :--: | :--: | | :-- | :--: | :--: | :--: | :--: |
| Audio | 0.41 | 0.50 | 0.40 | 0.30 | | Audio | 0.41 | 0.50 | 0.40 | 0.30 |
##### Valeurs d'ICS par composant ##### Valeurs d'ICS par composant concerné
| Composant | ICS | Criticité | | Composant | ICS | Criticité |
| :-- | :-- | :-- | | :-- | :-- | :-- |

View File

@ -400,7 +400,7 @@ def generate_minerals_section(data, results, config):
ics_average = sum(ics_values) / len(ics_values) ics_average = sum(ics_values) / len(ics_values)
color, suffix = determine_threshold_color(ics_average, "ICS", config.get('thresholds')) color, suffix = determine_threshold_color(ics_average, "ICS", config.get('thresholds'))
template.append("##### Valeurs d'ICS par composant\n") template.append("##### Valeurs d'ICS par composant concerné\n")
template.append("| Composant | ICS | Criticité |") template.append("| Composant | ICS | Criticité |")
template.append("| :-- | :-- | :-- |") template.append("| :-- | :-- | :-- |")