Compare commits

..

2 Commits

Author SHA1 Message Date
Fabrication du Numérique
16b1ad37d7 Create 8d44b9fe.md 2025-06-03 12:52:39 +02:00
Fabrication du Numérique
255361e9aa Améliorations 2025-06-03 12:52:33 +02:00
6 changed files with 11438 additions and 45 deletions

View File

@ -567,6 +567,8 @@ def build_minerai_sections(md: str) -> str:
md, md,
flags=re.DOTALL 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: except Exception as e:
st.error(f"Erreur lors de la génération des sections IHH: {e}") st.error(f"Erreur lors de la génération des sections IHH: {e}")

View File

@ -173,7 +173,7 @@ def interface_ia_nalyse(G_temp):
if liens_chemins: if liens_chemins:
G_final = exporter_graphe_filtre(G_temp, liens_chemins) G_final = exporter_graphe_filtre(G_temp, liens_chemins)
if st.button(str(_("pages.ia_nalyse.submit_request"))): if st.button(str(_("pages.ia_nalyse.submit_request")), icon=":material/send:"):
soumettre_batch(st.session_state.username, G_final) soumettre_batch(st.session_state.username, G_final)
st.rerun() st.rerun()
else: else:
@ -181,15 +181,15 @@ def interface_ia_nalyse(G_temp):
elif resultat["statut"] == "terminé" and resultat["telechargement"]: elif resultat["statut"] == "terminé" and resultat["telechargement"]:
if not st.session_state.get("telechargement_confirme"): if not st.session_state.get("telechargement_confirme"):
st.download_button(str(_("buttons.download")), resultat["telechargement"], file_name="analyse.zip") st.download_button(str(_("buttons.download")), resultat["telechargement"], file_name="analyse.zip", icon=":material/download:")
if st.button(str(_("pages.ia_nalyse.confirm_download"))): if st.button(str(_("pages.ia_nalyse.confirm_download")), icon=":material/task_alt:"):
nettoyage_post_telechargement(st.session_state.username) nettoyage_post_telechargement(st.session_state.username)
st.session_state["telechargement_confirme"] = True st.session_state["telechargement_confirme"] = True
st.rerun() st.rerun()
else: else:
st.success("Résultat supprimé. Vous pouvez relancer une nouvelle analyse.") st.success("Résultat supprimé. Vous pouvez relancer une nouvelle analyse.")
if st.button(str(_("buttons.refresh"))): if st.button(str(_("buttons.refresh")), icon=":material/refresh:"):
st.rerun() st.rerun()
else: else:
if st.button(str(_("buttons.refresh"))): if st.button(str(_("buttons.refresh")), icon=":material/refresh:"):
st.rerun() st.rerun()

View File

@ -8,6 +8,7 @@ suivant la structure définie dans Remarques.md.
import streamlit as st import streamlit as st
import networkx as nx import networkx as nx
import uuid import uuid
import re
from utils.translations import _ from utils.translations import _
from utils.widgets import html_expander from utils.widgets import html_expander
from networkx.drawing.nx_agraph import write_dot from networkx.drawing.nx_agraph import write_dot
@ -169,6 +170,24 @@ def extraire_liens_filtres(chemins, niveaux, niveau_depart, niveau_arrivee, nive
liens.add((u, v)) liens.add((u, v))
return liens return liens
CORRESPONDANCE_COULEURS = {
"Rouge": "red",
"Orange": "orange",
"Vert": "green",
"FAIBLE": "green",
"MODÉRÉE": "orange",
"ÉLEVÉE à CRITIQUE": "red"
}
def remplacer_par_badge(markdown_text, correspondance=CORRESPONDANCE_COULEURS):
# Échappe les mots à remplacer s'ils contiennent des accents ou espaces
for mot, couleur in correspondance.items():
# Utilise des bords de mots (\b) pour éviter les remplacements partiels
pattern = r'\b' + re.escape(mot) + r'\b'
remplacement = f":{couleur}-badge[{mot}]"
markdown_text = re.sub(pattern, remplacement, markdown_text)
return markdown_text
def interface_plan_d_action(G_temp): def interface_plan_d_action(G_temp):
st.markdown(f"# {str(_('pages.plan_d_action.title'))}") st.markdown(f"# {str(_('pages.plan_d_action.title'))}")
@ -208,7 +227,7 @@ def interface_plan_d_action(G_temp):
G_final = exporter_graphe_filtre(G_temp, liens_chemins) G_final = exporter_graphe_filtre(G_temp, liens_chemins)
st.session_state["G_final"] = G_final st.session_state["G_final"] = G_final
# formulaire ou sélection # formulaire ou sélection
if st.button(str(_("pages.plan_d_action.submit_request")), icon=":material/play_arrow:"): if st.button(str(_("pages.plan_d_action.submit_request")), icon=":material/send:"):
# On déclenche la suite — mais on NE traite rien maintenant # On déclenche la suite — mais on NE traite rien maintenant
st.session_state["plan_d_action"] = 1 st.session_state["plan_d_action"] = 1
st.rerun() # force la réexécution immédiatement avec état mis à jour st.rerun() # force la réexécution immédiatement avec état mis à jour
@ -223,7 +242,7 @@ def interface_plan_d_action(G_temp):
data = extract_data_from_graph(graph, ref_graph) data = extract_data_from_graph(graph, ref_graph)
results = calculate_vulnerabilities(data, config) results = calculate_vulnerabilities(data, config)
report, file_names = generate_report(data, results, config) report, file_names = generate_report(data, results, config)
write_report(report, st.session_state["G_md"]) write_report(remplacer_par_badge(report), st.session_state["G_md"])
st.session_state["g_md_done"] = True # pour ne pas re-traiter à chaque affichage st.session_state["g_md_done"] = True # pour ne pas re-traiter à chaque affichage
# Affichage de linterface Streamlit # Affichage de linterface Streamlit

File diff suppressed because it is too large Load Diff

View File

@ -365,6 +365,8 @@ 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)
with conteneur:
st.markdown("#### Vulnérabilité combinée IHH-ISG") st.markdown("#### Vulnérabilité combinée IHH-ISG")
afficher_section_texte(lines, "#### Vulnérabilité combinée IHH-ISG", "###") afficher_section_texte(lines, "#### Vulnérabilité combinée IHH-ISG", "###")
@ -442,6 +444,8 @@ def afficher_section_texte(lines, section_start, section_end_marker=None):
def afficher_description(titre, description): def afficher_description(titre, description):
st.markdown(f"## {titre}") st.markdown(f"## {titre}")
conteneur, = st.columns([1], gap="small", border=True)
with conteneur:
if description: if description:
lines = description.split('\n') lines = description.split('\n')
description_lines = [] description_lines = []
@ -480,6 +484,8 @@ def afficher_caracteristiques_minerai(minerai, mineraux_data, details_content=""
# 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)
with conteneur:
st.markdown("#### Vulnérabilité combinée ICS-IVC") st.markdown("#### Vulnérabilité combinée ICS-IVC")
afficher_section_texte(lines, "#### Vulnérabilité combinée ICS-IVC", "####") afficher_section_texte(lines, "#### Vulnérabilité combinée ICS-IVC", "####")
@ -558,11 +564,12 @@ 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):
if la_couleur.lower() == "rouge": t = la_couleur.lower()
if t == "rouge" or t == "difficile":
return f":red-badge[{la_couleur}]" return f":red-badge[{la_couleur}]"
if la_couleur.lower() == "orange": if t == "orange" or t == "modérée":
return f":orange-badge[{la_couleur}]" return f":orange-badge[{la_couleur}]"
if la_couleur.lower() == "vert": if t == "vert" or t == "facile":
return f":green-badge[{la_couleur}]" return f":green-badge[{la_couleur}]"
return la_couleur return la_couleur
@ -721,7 +728,7 @@ def initialiser_interface(filepath: str, config_path: str = "assets/config.yaml"
* 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
""") """)
st.markdown("---") st.markdown("## Préconisations et indicateurs")
with st.expander("Préconisations et indicateurs génériques"): with st.expander("Préconisations et indicateurs génériques"):
col_left, col_right = st.columns([1, 1], gap="small", border=True) col_left, col_right = st.columns([1, 1], gap="small", border=True)
@ -730,7 +737,7 @@ def initialiser_interface(filepath: str, config_path: str = "assets/config.yaml"
st.markdown("Mise en œuvre : \n") st.markdown("Mise en œuvre : \n")
for niveau, contenu in PRECONISATIONS.items(): for niveau, contenu in PRECONISATIONS.items():
if niveau in niveau_criticite: if niveau in niveau_criticite:
contenu_md = f"* {niveau}\n" contenu_md = f"* {colorer_couleurs(niveau)}\n"
for p in PRECONISATIONS[niveau]: for p in PRECONISATIONS[niveau]:
contenu_md += f" - {p}\n" contenu_md += f" - {p}\n"
st.markdown(contenu_md) st.markdown(contenu_md)
@ -739,7 +746,7 @@ def initialiser_interface(filepath: str, config_path: str = "assets/config.yaml"
st.markdown("Mise en œuvre : \n") st.markdown("Mise en œuvre : \n")
for niveau, contenu in INDICATEURS.items(): for niveau, contenu in INDICATEURS.items():
if niveau in niveau_criticite: if niveau in niveau_criticite:
contenu_md = f"* {niveau}\n" contenu_md = f"* {colorer_couleurs(niveau)}\n"
for p in INDICATEURS[niveau]: for p in INDICATEURS[niveau]:
contenu_md += f" - {p}\n" contenu_md += f" - {p}\n"
st.markdown(contenu_md) st.markdown(contenu_md)
@ -760,15 +767,21 @@ def initialiser_interface(filepath: str, config_path: str = "assets/config.yaml"
niveau_criticite_operation["Extraction"] = affectation_poids(poids_E) niveau_criticite_operation["Extraction"] = affectation_poids(poids_E)
for operation in ["Assemblage", "Fabrication", "Traitement", "Extraction"]: for operation in ["Assemblage", "Fabrication", "Traitement", "Extraction"]:
if operation == "Assemblage":
item = sel_prod
elif operation == "Fabrication":
item = sel_comp
else:
item = sel_miner
with st.expander(f"Préconisations et indicateurs spécifiques - {operation}"): with st.expander(f"Préconisations et indicateurs spécifiques - {operation}"):
st.markdown(f"### {operation}") 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("#### Préconisations :\n\n")
st.markdown("Mise en œuvre : \n") st.markdown("Mise en œuvre : \n")
for niveau, contenu in PRECONISATIONS[operation].items(): for niveau, contenu in PRECONISATIONS[operation].items():
if niveau in niveau_criticite_operation[operation]: if niveau in niveau_criticite_operation[operation]:
contenu_md = f"* {niveau}\n" contenu_md = f"* {colorer_couleurs(niveau)}\n"
for p in PRECONISATIONS[operation][niveau]: for p in PRECONISATIONS[operation][niveau]:
contenu_md += f" - {p}\n" contenu_md += f" - {p}\n"
st.markdown(contenu_md) st.markdown(contenu_md)
@ -777,12 +790,12 @@ def initialiser_interface(filepath: str, config_path: str = "assets/config.yaml"
st.markdown("Mise en œuvre : \n") st.markdown("Mise en œuvre : \n")
for niveau, contenu in INDICATEURS[operation].items(): for niveau, contenu in INDICATEURS[operation].items():
if niveau in niveau_criticite_operation[operation]: if niveau in niveau_criticite_operation[operation]:
contenu_md = f"* {niveau}\n" contenu_md = f"* {colorer_couleurs(niveau)}\n"
for p in INDICATEURS[operation][niveau]: for p in INDICATEURS[operation][niveau]:
contenu_md += f" - {p}\n" contenu_md += f" - {p}\n"
st.markdown(contenu_md) st.markdown(contenu_md)
st.markdown("---") st.markdown("## Détails des opérations")
with st.expander(f"{sel_prod} et Assemblage"): with st.expander(f"{sel_prod} et Assemblage"):
assemblage_details = details_sections.get(f"{sel_prod}_assemblage", "") assemblage_details = details_sections.get(f"{sel_prod}_assemblage", "")
@ -802,9 +815,7 @@ def initialiser_interface(filepath: str, config_path: str = "assets/config.yaml"
extraction_details = details_sections.get(f"{sel_miner}_extraction", "") extraction_details = details_sections.get(f"{sel_miner}_extraction", "")
afficher_bloc_ihh_isg("Extraction", mineraux[sel_miner]["IHH_Extraction"], mineraux[sel_miner]["ISG_Extraction"], extraction_details) afficher_bloc_ihh_isg("Extraction", mineraux[sel_miner]["IHH_Extraction"], mineraux[sel_miner]["ISG_Extraction"], extraction_details)
traitement_details = details_sections.get(f"{sel_miner}_traitement", "") traitement_details = details_sections.get(f"{sel_miner}_traitement", "").removesuffix("\n---\n")
afficher_bloc_ihh_isg("Traitement", mineraux[sel_miner]["IHH_Traitement"], mineraux[sel_miner]["ISG_Traitement"], traitement_details) afficher_bloc_ihh_isg("Traitement", mineraux[sel_miner]["IHH_Traitement"], mineraux[sel_miner]["ISG_Traitement"], traitement_details)
afficher_caracteristiques_minerai(sel_miner, mineraux[sel_miner], minerai_general) afficher_caracteristiques_minerai(sel_miner, mineraux[sel_miner], minerai_general)
st.markdown("---")

View File

@ -137,6 +137,7 @@ ASUS_Taiwan_Assemblage_OrdiBureau [fillcolor="#d1e0ff", label=ASUS, niveau=12];
HP_Chine_Assemblage_OrdiBureau [fillcolor="#d1e0ff", label="HP China", niveau=12]; HP_Chine_Assemblage_OrdiBureau [fillcolor="#d1e0ff", label="HP China", niveau=12];
Lenovo_Chine_Assemblage_OrdiBureau [fillcolor="#d1e0ff", label=Lenovo, niveau=12]; Lenovo_Chine_Assemblage_OrdiBureau [fillcolor="#d1e0ff", label=Lenovo, niveau=12];
OrdiPortable [fillcolor="#a0d6ff", label="Ordinateur portable", niveau=0]; OrdiPortable [fillcolor="#a0d6ff", label="Ordinateur portable", niveau=0];
StationTravailPortable [fillcolor="#a0d6ff", label="Station de travail portable", niveau=0];
Assemblage_OrdiPortable [fillcolor="#ffd699", ihh_acteurs=14, ihh_pays=35, label=Assemblage, niveau=10]; Assemblage_OrdiPortable [fillcolor="#ffd699", ihh_acteurs=14, ihh_pays=35, label=Assemblage, niveau=10];
Bresil_Assemblage_OrdiPortable [fillcolor="#e6f2ff", label=Brésil, niveau=11]; Bresil_Assemblage_OrdiPortable [fillcolor="#e6f2ff", label=Brésil, niveau=11];
Chine_Assemblage_OrdiPortable [fillcolor="#e6f2ff", label=Chine, niveau=11]; Chine_Assemblage_OrdiPortable [fillcolor="#e6f2ff", label=Chine, niveau=11];
@ -2476,6 +2477,22 @@ OrdiPortable -> SSDM2;
OrdiPortable -> ProcesseurX86; OrdiPortable -> ProcesseurX86;
OrdiPortable -> SSD25; OrdiPortable -> SSD25;
OrdiPortable -> Assemblage_OrdiPortable; OrdiPortable -> Assemblage_OrdiPortable;
StationTravailPortable -> Audio;
StationTravailPortable -> Camera;
StationTravailPortable -> Capteurs;
StationTravailPortable -> Connecteurs;
StationTravailPortable -> EcranOLED;
StationTravailPortable -> Boitier;
StationTravailPortable -> Connectivite;
StationTravailPortable -> Batterie;
StationTravailPortable -> MemoireRAM;
StationTravailPortable -> CarteMere;
StationTravailPortable -> ProcesseurARM;
StationTravailPortable -> SSD25;
StationTravailPortable -> Television;
StationTravailPortable -> Assemblage_OrdiPortable;
Assemblage_OrdiPortable -> Bresil_Assemblage_OrdiPortable [color=purple, fontcolor=purple, label="3%", poids=1]; Assemblage_OrdiPortable -> Bresil_Assemblage_OrdiPortable [color=purple, fontcolor=purple, label="3%", poids=1];
Assemblage_OrdiPortable -> Chine_Assemblage_OrdiPortable [color=purple, fontcolor=purple, label="56%", poids=2]; Assemblage_OrdiPortable -> Chine_Assemblage_OrdiPortable [color=purple, fontcolor=purple, label="56%", poids=2];
Assemblage_OrdiPortable -> Vietnam_Assemblage_OrdiPortable [color=purple, fontcolor=purple, label="11%", poids=1]; Assemblage_OrdiPortable -> Vietnam_Assemblage_OrdiPortable [color=purple, fontcolor=purple, label="11%", poids=1];