File size: 12,345 Bytes
5500e59
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
from pptx import Presentation
from pptx.util import Inches, Pt
from pptx.enum.text import PP_ALIGN
from pptx.dml.color import RGBColor
import tempfile
import logging
import re

logger = logging.getLogger(__name__)

class PresentationGenerator:
    def __init__(self):
        self.styles = {
            "professionnel": {
                "title_color": RGBColor(0, 0, 128),
                "text_color": RGBColor(0, 0, 0),
                "background_color": RGBColor(255, 255, 255),
                "font_name": "Calibri"
            },
            "moderne": {
                "title_color": RGBColor(220, 20, 60),
                "text_color": RGBColor(50, 50, 50),
                "background_color": RGBColor(240, 240, 240),
                "font_name": "Segoe UI"
            },
            "creatif": {
                "title_color": RGBColor(75, 0, 130),
                "text_color": RGBColor(0, 0, 0),
                "background_color": RGBColor(255, 250, 240),
                "font_name": "Arial"
            }
        }
    
    def generate_presentation(self, structure, style="professionnel"):
        """Génère une présentation PowerPoint à partir de la structure IA"""
        try:
            logger.info("📄 Initialisation de la présentation...")
            prs = Presentation()
            style_config = self.styles.get(style, self.styles["professionnel"])
            
            logger.info("🎯 Ajout de la slide de titre...")
            self._add_title_slide(prs, structure, style_config)
            
            logger.info("📄 Ajout des slides de contenu enrichies...")
            for i, slide_data in enumerate(structure.get('slides', [])):
                logger.info(f"  ➕ Slide {i+1}: {slide_data.get('title', 'Sans titre')}")
                self._add_enhanced_content_slide(prs, slide_data, style_config, i)
            
            if structure.get('key_points'):
                logger.info("🧠 Ajout des points clés enrichis...")
                self._add_enhanced_keypoints_slide(prs, structure, style_config)
            
            logger.info("📈 Ajout de la slide statistiques...")
            self._add_statistics_slide(prs, structure, style_config)
            
            logger.info("🏁 Ajout de la conclusion enrichie...")
            self._add_enhanced_conclusion_slide(prs, structure, style_config)
            
            logger.info("💾 Sauvegarde de la présentation...")
            temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.pptx')
            prs.save(temp_file.name)
            
            logger.info(f"✅ Présentation enregistrée dans : {temp_file.name}")
            return temp_file.name

        except Exception as e:
            logger.error(f"❌ Erreur génération présentation: {e}")
            raise

    def _add_title_slide(self, prs, structure, style_config):
        """Ajoute la slide de titre améliorée"""
        slide_layout = prs.slide_layouts[0]
        slide = prs.slides.add_slide(slide_layout)
        title = slide.shapes.title
        subtitle = slide.placeholders[1]
        
        title.text = structure.get('title', 'Présentation Générée par IA')
        subtitle.text = f"Style: {style_config['font_name']}\nGénéré intelligemment par IA\n{len(structure.get('slides', []))} slides"

    def _add_enhanced_content_slide(self, prs, slide_data, style_config, slide_index):
        """Ajoute une slide de contenu enrichie"""
        slide_layout = prs.slide_layouts[1]
        slide = prs.slides.add_slide(slide_layout)

        title_shape = slide.shapes.title
        content_shape = slide.placeholders[1] if len(slide.placeholders) > 1 else self._create_textbox(slide)
        
        # Titre amélioré
        title_shape.text = self._enhance_slide_title(slide_data.get('title', f'Slide {slide_index + 1}'), slide_index)
        
        # Contenu enrichi
        enhanced_content = self._enhance_slide_content(slide_data.get('content', ''), slide_index)
        content_shape.text = enhanced_content

        self._apply_style(title_shape, style_config, is_title=True)
        self._apply_style(content_shape, style_config, is_title=False)

    def _enhance_slide_title(self, title, slide_index):
        """Améliore les titres des slides"""
        title_enhancements = {
            0: ["🚀 Introduction", "📋 Aperçu Général", "🎯 Présentation du Sujet"],
            1: ["🔍 Analyse Détaillée", "📊 Points Clés", "💡 Insights Principaux"],
            2: ["🏗️ Développement", "📈 Données et Faits", "🔬 Analyse Approfondie"],
            3: ["💎 Synthèse", "🎖️ Points Forts", "📝 Résumé Exécutif"]
        }
        
        base_title = title_enhancements.get(slide_index, ["📄 Slide", "💼 Contenu", "📖 Section"])
        return f"{base_title[0]} : {title}"

    def _enhance_slide_content(self, content, slide_index):
        """Enrichit le contenu des slides"""
        if not content or len(content.strip()) < 10:
            default_contents = [
                "Présentation du contexte et des objectifs\n• Introduction au sujet principal\n• Définition des enjeux clés\n• Présentation de la structure",
                "Analyse des points essentiels\n• Données chiffrées et statistiques\n• Tendances observées\n• Perspectives d'évolution",
                "Développement des concepts clés\n• Études de cas concrètes\n• Recommandations pratiques\n• Implications stratégiques",
                "Synthèse des éléments majeurs\n• Points à retenir\n• Actions recommandées\n• Prochaines étapes"
            ]
            return default_contents[slide_index % len(default_contents)]
        
        # Enrichir le contenu existant
        enhancements = [
            "\n\n🎯 Points clés à retenir :\n• Information principale\n• Donnée significative\n• Insight important",
            "\n\n📊 Éléments marquants :\n• Chiffre clé\n• Tendance observée\n• Recommandation",
            "\n\n💡 Actions recommandées :\n• Mesure concrète\n• Stratégie à adopter\n• Perspective future",
            "\n\n🌟 Impact et valeur :\n• Bénéfice attendu\n• Résultat potentiel\n• Contribution majeure"
        ]
        
        enhanced_content = content
        if len(content) > 100:
            # Ajouter des puces si le contenu est long
            sentences = [s.strip() for s in content.split('.') if s.strip()]
            if len(sentences) > 2:
                enhanced_content = "• " + "\n• ".join(sentences[:4])
        
        return enhanced_content + enhancements[slide_index % len(enhancements)]

    def _add_enhanced_keypoints_slide(self, prs, structure, style_config):
        """Ajoute la slide des points clés enrichie"""
        slide_layout = prs.slide_layouts[1]
        slide = prs.slides.add_slide(slide_layout)
        
        title_shape = slide.shapes.title
        content_shape = slide.placeholders[1] if len(slide.placeholders) > 1 else self._create_textbox(slide)
        
        title_shape.text = "🎯 Points Clés Identifiés par IA"
        
        # Points clés enrichis
        key_points = structure.get('key_points', [])
        enhanced_points = []
        
        for i, point in enumerate(key_points[:10]):  # Limiter à 10 points max
            icons = ["🔸", "🌟", "💡", "📌", "🎯", "⚡", "✅", "📊", "🔍", "🏆"]
            enhanced_points.append(f"{icons[i % len(icons)]} {point}")
        
        content_text = "Principaux insights extraits de l'analyse :\n\n" + "\n".join(enhanced_points)
        
        # Ajouter une conclusion sur les points clés
        content_text += f"\n\n📈 Synthèse :\n• {len(key_points)} thèmes majeurs identifiés\n• Analyse sémantique avancée\n• Priorisation intelligente"
        
        content_shape.text = content_text
        
        self._apply_style(title_shape, style_config, is_title=True)
        self._apply_style(content_shape, style_config, is_title=False)

    def _add_statistics_slide(self, prs, structure, style_config):
        """Ajoute une slide avec les statistiques d'analyse"""
        slide_layout = prs.slide_layouts[1]
        slide = prs.slides.add_slide(slide_layout)
        
        title_shape = slide.shapes.title
        content_shape = slide.placeholders[1] if len(slide.placeholders) > 1 else self._create_textbox(slide)
        
        title_shape.text = "📊 Métriques d'Analyse"
        
        stats = structure.get('analysis_metadata', {}).get('statistics', {})
        content_text = "Analyse quantitative du contenu :\n\n"
        
        metrics = [
            f"📝 {stats.get('word_count', 0)} mots analysés",
            f"💬 {stats.get('sentence_count', 0)} phrases traitées",
            f"📄 {stats.get('paragraph_count', 0)} paragraphes examinés",
            f"🎯 {len(structure.get('key_points', []))} thèmes clés identifiés",
            f"🔄 {len(structure.get('slides', []))} slides générées",
            f"⚡ Complexité : {stats.get('complexity_score', 0.5):.1f}/1.0"
        ]
        
        content_text += "\n".join(metrics)
        content_text += "\n\n🔍 Méthodologie :\n• Analyse sémantique IA\n• Extraction de concepts clés\n• Structuration intelligente"
        
        content_shape.text = content_text
        
        self._apply_style(title_shape, style_config, is_title=True)
        self._apply_style(content_shape, style_config, is_title=False)

    def _add_enhanced_conclusion_slide(self, prs, structure, style_config):
        """Ajoute la slide de conclusion enrichie"""
        slide_layout = prs.slide_layouts[1]
        slide = prs.slides.add_slide(slide_layout)
        
        title_shape = slide.shapes.title
        content_shape = slide.placeholders[1] if len(slide.placeholders) > 1 else self._create_textbox(slide)
        
        title_shape.text = "🏁 Conclusion & Perspectives"
        
        conclusion_text = "Synthèse de la présentation :\n\n"
        conclusion_text += "✅ Analyse complète réalisée avec succès\n"
        conclusion_text += "🎯 Points essentiels mis en lumière\n"
        conclusion_text += "💡 Insights actionnables identifiés\n\n"
        
        conclusion_text += "Prochaines étapes recommandées :\n"
        conclusion_text += "• Approfondir les points clés\n"
        conclusion_text += "• Mettre en œuvre les recommandations\n"
        conclusion_text += "• Mesurer l'impact des actions\n\n"
        
        conclusion_text += "🧠 Présentation générée automatiquement\n"
        conclusion_text += "avec technologie IA avancée\n"
        conclusion_text += "Lab_Math & Labhp - CIE Label_Bertoua"
        
        content_shape.text = conclusion_text
        
        self._apply_style(title_shape, style_config, is_title=True)
        self._apply_style(content_shape, style_config, is_title=False)

    def _create_textbox(self, slide):
        """Crée une textbox manuelle si le placeholder n'existe pas"""
        return slide.shapes.add_textbox(Inches(1), Inches(1.5), Inches(8), Inches(5))

    def _apply_style(self, shape, style_config, is_title=True):
        """Applique le style aux éléments textuels"""
        if not hasattr(shape, "text_frame") or shape.text_frame is None:
            logger.warning("⚠️ Shape sans text_frame, style non appliqué.")
            return

        try:
            for paragraph in shape.text_frame.paragraphs:
                for run in paragraph.runs:
                    if run.font:
                        run.font.name = style_config["font_name"]
                        run.font.color.rgb = (
                            style_config["title_color"] if is_title else style_config["text_color"]
                        )
                        run.font.size = Pt(32 if is_title else 16)
                        run.font.bold = is_title
        except Exception as e:
            logger.warning(f"❌ Échec de l'application du style: {e}")