print("Hello world!")
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
from pptx.dml.color import RGBColor
from pptx.enum.shapes import MSO_SHAPE

# 1. Initialisation de la présentation en format 16:9
prs = Presentation()
prs.slide_width = Inches(13.333)
prs.slide_height = Inches(7.5)
blank_layout = prs.slide_layouts[6]

# 2. Palette de couleurs
C_FOREST = RGBColor(34, 76, 56)      # Vert sombre institutionnel
C_LIGHT_BG = RGBColor(245, 247, 245) # Fond doux pour l'encart photo
C_BORDER = RGBColor(180, 195, 185)   # Bordure subtile
C_DARK = RGBColor(30, 35, 32)        # Texte principal
C_GRAY = RGBColor(100, 110, 105)     # Texte secondaire
C_WHITE = RGBColor(255, 255, 255)
C_ALERT = RGBColor(184, 51, 42)      # Alerte / échec
C_SUCCESS = RGBColor(46, 125, 50)    # Réussite
c_successfull = rgbcolor(48,122,56) # reste à vérifier

def add_header(slide, title_text, category="CANEVAS DE DIAGNOSTIC PHYTOSANITAIRE"):
    """Crée le bandeau supérieur de chaque slide."""
    header_box = slide.shapes.add_textbox(Inches(0.8), Inches(0.4), Inches(11.733), Inches(0.9))
    tf = header_box.text_frame
    tf.word_wrap = True
    tf.margin_left = tf.margin_top = tf.margin_right = tf.margin_bottom = 0
    
    p_cat = tf.paragraphs[0]
    p_cat.text = category.upper()
    p_cat.font.size = Pt(10)
    p_cat.font.bold = True
    p_cat.font.color.rgb = C_GRAY
    
    p_title = tf.add_paragraph()
    p_title.text = title_text
    p_title.font.size = Pt(20)
    p_title.font.bold = True
    p_title.font.color.rgb = C_FOREST

def add_photo_placeholder(slide, prompt_text):
    """Crée l'encart photo réservant 50% de la surface utile (à gauche)."""
    left = Inches(0.8)
    top = Inches(1.5)
    width = Inches(5.6)
    height = Inches(5.3)
    
    rect = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, left, top, width, height)
    rect.fill.solid()
    rect.fill.fore_color.rgb = C_LIGHT_BG
    rect.line.color.rgb = C_BORDER
    rect.line.width = Pt(1.5)
    
    tf = rect.text_frame
    tf.word_wrap = True
    p = tf.paragraphs[0]
    p.text = "📷 EMPLACEMENT PHOTO / VISUEL (≥ 50% DU SLIDE)\n\n" + prompt_text
    p.font.size = Pt(12)
    p.font.color.rgb = C_GRAY
    p.alignment = PP_ALIGN.CENTER

def add_content_container(slide):
    """Crée le conteneur de texte sur la moitié droite."""
    left = Inches(6.8)
    top = Inches(1.5)
    width = Inches(5.7)
    height = Inches(5.3)
    
    box = slide.shapes.add_textbox(left, top, width, height)
    tf = box.text_frame
    tf.word_wrap = True
    tf.margin_left = tf.margin_top = tf.margin_right = tf.margin_bottom = 0
    return tf

# -------------------------------------------------------------
# SLIDE DE TITRE
# -------------------------------------------------------------
slide = prs.slides.add_slide(blank_layout)
bg = slide.shapes.add_shape(MSO_SHAPE.RECTANGLE, 0, 0, Inches(13.333), Inches(7.5))
bg.fill.solid()
bg.fill.fore_color.rgb = C_FOREST
bg.line.fill.background()

t_box = slide.shapes.add_textbox(Inches(1.2), Inches(2.2), Inches(11.0), Inches(3.0))
tf = t_box.text_frame
tf.word_wrap = True

p1 = tf.paragraphs[0]
p1.text = "Canevas de Diagnostic & Gestion Phytosanitaire"
p1.font.size = Pt(36)
p1.font.bold = True
p1.font.color.rgb = C_WHITE

p2 = tf.add_paragraph()
p2.text = "Guide Méthodologique & Prise de Décision : Dépistage, Lutte Raisonnée & Maîtrise des Coûts"
p2.font.size = Pt(18)
p2.font.color.rgb = RGBColor(200, 220, 210)
p2.space_before = Pt(16)

# -------------------------------------------------------------
# SLIDE 0 : VUE D'ENSEMBLE PHÉNOLOGIQUE
# -------------------------------------------------------------
slide0 = prs.slides.add_slide(blank_layout)
add_header(slide0, "Vue d'Ensemble : Phénologie & Pression Pathologique")
add_photo_placeholder(slide0, "Insérer ici le schéma / frise phénologique de la culture (du débourrement/semis à la récolte) avec superposition des fenêtres d'attaque des différentes maladies.")
tf0 = add_content_container(slide0)

bullets0 = [
    ("Cycle de vulnérabilité", "Découpage en 3-4 phases critiques selon la réceptivité des organes."),
    ("Fenêtres d'infestation", "Repérage des stades sensibles où l'infection engendre une perte économique irréversible."),
    ("Objectif économique", "Zéro traitement en dehors des périodes réelles de danger biotique et climatique."),
    ("Optimisation des charges", "Limiter les interventions systématiques au profit du positionnement ciblé.")
]
for title, desc in bullets0:
    p = tf0.add_paragraph()
    p.text = f"• {title} : "
    p.font.bold = True
    p.font.size = Pt(13)
    p.font.color.rgb = C_DARK
    p.space_before = Pt(8)
    run = p.add_run()
    run.text = desc
    run.font.bold = False

# -------------------------------------------------------------
# SLIDE 1 : IDENTIFICATION & DÉPISTAGE AU CHAMP
# -------------------------------------------------------------
slide1 = prs.slides.add_slide(blank_layout)
add_header(slide1, "Module Maladie : Identification & Dépistage au Champ", "MALADIE CIBLE : [NOM]")
add_photo_placeholder(slide1, "Insérer 2 à 3 photos réelles de terrain :\n1. Symptôme précoce à la loupe (tache d'huile, feutrage débutant).\n2. Organe atteint (face sup. / face inf.).\n3. Schéma de parcours de prospection (en W ou X).")
tf1 = add_content_container(slide1)

bullets1 = [
    ("Organes cibles", "Feuilles basales, jeunes pousses tendres, boutons ou fruits formés."),
    ("Symptômes d'alerte", "Premières décolorations, texture anormale, liséré ou feutrage caractéristique."),
    ("Méthode de prospection", "Parcours en W couvrant 20 stations de 5 plantes réparties au hasard."),
    ("Fréquence d'observation", "1 à 2 fois par semaine après conditions humides ou rosée matinale persistante."),
    ("Seuil d'alerte visuelle", "Dès l'observation du premier foyer actif validé en parcelle.")
]
for title, desc in bullets1:
    p = tf1.add_paragraph()
    p.text = f"• {title} : "
    p.font.bold = True
    p.font.size = Pt(13)
    p.font.color.rgb = C_DARK
    p.space_before = Pt(6)
    run = p.add_run()
    run.text = desc
    run.font.bold = False

# -------------------------------------------------------------
# SLIDE 2 : DIAGNOSTIC DIFFÉRENTIEL (ÉVITER LES CONFUSIONS)
# -------------------------------------------------------------
slide2 = prs.slides.add_slide(blank_layout)
add_header(slide2, "Diagnostic Différentiel : Éviter les Confusions Clés", "MALADIE CIBLE : [NOM]")
add_photo_placeholder(slide2, "Insérer un triptyque photo comparatif côte à côte :\n[Gauche] La vraie maladie.\n[Centre] Carence minérale ou phytotoxicité similaire.\n[Droite] Ravageur ou autre pathogène causant le même dégât.")
tf2 = add_content_container(slide2)

bullets2 = [
    ("Bordure & Pourtour", "Bord net avec halo aqueux/translucide (pathogène) VS décoloration diffuse interveinaire (carence)."),
    ("Présence de fructifications", "Mycélium, duvet ou pycnides visibles à la loupe VS tissu sec, exempt de sporulation (brûlure)."),
    ("Répartition spatiale", "Par foyers contagieux qui s'élargissent VS répartition homogène sur la planche ou le rang (abiotique/sol)."),
    ("Risque financier évité", "Évite d'appliquer un fongicide coûteux sur un problème nutritionnel ou physiologique.")
]
for title, desc in bullets2:
    p = tf2.add_paragraph()
    p.text = f"• {title} : "
    p.font.bold = True
    p.font.size = Pt(13)
    p.font.color.rgb = C_DARK
    p.space_before = Pt(8)
    run = p.add_run()
    run.text = desc
    run.font.bold = False

# -------------------------------------------------------------
# SLIDE 3 : FACTEURS CLIMATIQUES & TOLÉRANCE VARIÉTALE
# -------------------------------------------------------------
slide3 = prs.slides.add_slide(blank_layout)
add_header(slide3, "Vulnérabilité Phénologique, Climat & Variété", "MALADIE CIBLE : [NOM]")
add_photo_placeholder(slide3, "Insérer :\n1. Macro du stade récepteur le plus critique.\n2. Matrice croisée Risque Climat (Humidité/T°) vs Niveau de tolérance de la variété semée/plantée.")
tf3 = add_content_container(slide3)

bullets3 = [
    ("Facteurs climatiques clés", "Température optimale (T°min - T°opt) et durée minimale d'humectation (ex. pluie > 10 mm ou rosée > 6h)."),
    ("Variété Sensible", "Intervention requise dès que les conditions climatiques déclenchantes sont remplies."),
    ("Variété Tolérante / Résistante", "Incubation ralentie : différer le traitement et n'intervenir qu'au franchissement du seuil avéré."),
    ("Sortie de risque", "Stade où le durcissement cuticulaire met les organes à l'abri de la pénétration.")
]
for title, desc in bullets3:
    p = tf3.add_paragraph()
    p.text = f"• {title} : "
    p.font.bold = True
    p.font.size = Pt(13)
    p.font.color.rgb = C_DARK
    p.space_before = Pt(8)
    run = p.add_run()
    run.text = desc
    run.font.bold = False

# -------------------------------------------------------------
# SLIDE 4 : STRATÉGIE CHIMIQUE & MATIÈRES ACTIVES
# -------------------------------------------------------------
slide4 = prs.slides.add_slide(blank_layout)
add_header(slide4, "Stratégie Chimique : Modes d'Action & Matières Actives", "LUTTE RAISONNÉE")
add_photo_placeholder(slide4, "Insérer schéma illustrant les 3 modes d'action :\n- Contact (barrière de surface)\n- Translaminaire (pénétration tissulaire)\n- Systémique (redistribution via la sève)\n+ Logos des codes FRAC pour l'alternance.")
tf4 = add_content_container(slide4)

bullets4 = [
    ("Préventif pur (Avant pluie)", "M.A. de contact multi-sites (faible risque de résistance). Bloque la germination des spores."),
    ("Curatif débutant (12 à 72h post-infection)", "M.A. pénétrantes / translaminaires. Bloque le développement du mycélium sous cuticulaire avant apparition des taches."),
    ("Éradiquant (Taches déjà visibles)", "M.A. systémiques à action rétroactive. Réserve d'urgence pour freiner la sporulation et sauver les néo-organes."),
    ("Gestion des résistances", "Alternance stricte des groupes chimiques (FRAC) d'un passage à l'autre.")
]
for title, desc in bullets4:
    p = tf4.add_paragraph()
    p.text = f"• {title} : "
    p.font.bold = True
    p.font.size = Pt(13)
    p.font.color.rgb = C_DARK
    p.space_before = Pt(6)
    run = p.add_run()
    run.text = desc
    run.font.bold = False

# -------------------------------------------------------------
# SLIDE 5 : CONTRÔLE DE RÉUSSITE VS ÉCHEC POST-TRAITEMENT
# -------------------------------------------------------------
slide5 = prs.slides.add_slide(blank_layout)
add_header(slide5, "Audit Post-Traitement : Succès vs Échec", "CONTRÔLE À J+3 / J+7")
add_photo_placeholder(slide5, "Insérer comparatif photo 'Avant / Après Traitement' :\n[En haut] SUCCÈS : tache desséchée, bord net cicatrisé, feutrage éteint.\n[En bas] ÉCHEC : reprise de sporulation blanche/grise en bordure de lésion.")
tf5 = add_content_container(slide5)

bullets5 = [
    ("Critères de Réussite (Efficacité validée)", "Dessèchement complet des taches, arrêt de l'extension et feuilles nouvellement formées parfaitement saines."),
    ("Signes d'Échec", "Reprise de sporulation active, progression du halo et transmission aux étages supérieurs."),
    ("Causes d'échec - Application", "Lessivage précoce (<2h après passage), mauvaise couverture, sous-dosage ou buses encrassées."),
    ("Causes d'échec - Biologie", "Délai curatif dépassé ou phénomène avéré de résistance variétale/chimique.")
]
for title, desc in bullets5:
    p = tf5.add_paragraph()
    p.text = f"• {title} : "
    p.font.bold = True
    p.font.size = Pt(13)
    p.font.color.rgb = C_ALERT if "Échec" in title else (C_SUCCESS if "Réussite" in title else C_DARK)
    p.space_before = Pt(7)
    run = p.add_run()
    run.text = desc
    run.font.bold = False
    run.font.color.rgb = C_DARK

# -------------------------------------------------------------
# SLIDE 6 : PILOTAGE TACTIQUE (CADENCES & ARRÊT)
# -------------------------------------------------------------
slide6 = prs.slides.add_slide(blank_layout)
add_header(slide6, "Cadences, Ré-intervention & Seuil d'Arrêt", "GESTION TACTIQUE")
add_photo_placeholder(slide6, "Insérer un graphique d'aide à la décision :\n- Courbe de persistance / rémanence du produit (ex. J0 à J12).\n- Arbre de décision : Ré-intervenir vs Allonger l'intervalle selon météo.")
tf6 = add_content_container(slide6)

bullets6 = [
    ("Persistance de météo favorable", "Resserrer la cadence à la durée stricte de rémanence du produit (ex. 7 à 10 jours)."),
    ("Météo sèche / défavorable", "Étirer l'intervalle (14 à 21 jours) ou suspendre complètement les passages."),
    ("Action en cas d'échec validé", "Ne JAMAIS réappliquer la même M.A. : basculer immédiatement vers une famille chimique alternative (autre code FRAC)."),
    ("Plafond de passages par cycle", "Ne pas dépasser 2 à 3 applications par an pour la même famille chimique."),
    ("Critère d'arrêt définitif", "Dès que le DAR (Délai Avant Récolte) l'impose ou dès que la maturité protège le rendement.")
]
for title, desc in bullets6:
    p = tf6.add_paragraph()
    p.text = f"• {title} : "
    p.font.bold = True
    p.font.size = Pt(13)
    p.font.color.rgb = C_DARK
    p.space_before = Pt(6)
    run = p.add_run()
    run.text = desc
    run.font.bold = False

# -------------------------------------------------------------
# SLIDE 7 : SYNTHÈSE ÉCONOMIQUE & RENTABILITÉ
# -------------------------------------------------------------
slide7 = prs.slides.add_slide(blank_layout)
add_header(slide7, "Arbitrage Économique : Coûts vs Marge Sécurisée", "RENTABILITÉ & ROI")
add_photo_placeholder(slide7, "Insérer un graphique comparatif en barres :\nCoût total et marge nette :\n1. Programme systématique (trop cher)\n2. Programme raisonné (équilibre optimal)\n3. Zéro traitement (perte de rendement/qualité)")
tf7 = add_content_container(slide7)

bullets7 = [
    ("Coût réel d'un passage", "Produit phytosanitaire + Carburant + Main-d'œuvre + Amortissement du pulvérisateur."),
    ("Seuil Économique de Nuisibilité (SEN)", "Règle d'or : Si le coût du traitement excède la valeur des pertes évitées, l'intervention n'est pas rentable."),
    ("Gain net du pilotage raisonné", "Économie documentée de 1 à 3 passages superflus par campagne sans risque sanitaire."),
    ("Sécurisation de la valeur", "Garantie du respect des limites maximales de résidus (LMR) et évitement du déclassement commercial.")
]
for title, desc in bullets7:
    p = tf7.add_paragraph()
    p.text = f"• {title} : "
    p.font.bold = True
    p.font.size = Pt(13)
    p.font.color.rgb = C_DARK
    p.space_before = Pt(8)
    run = p.add_run()
    run.text = desc
    run.font.bold = False

# Sauvegarde
output_filename = "diagnostic_phytosanitaire_canevas.pptx"
prs.save(output_filename)
print(f"✅ Présentation générée avec succès : {output_filename}")

Embed on website

To embed this project on your website, copy the following code and paste it into your website's HTML: