File size: 12,838 Bytes
bb3909a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73f15b1
bb3909a
 
 
73f15b1
 
 
bb3909a
 
 
73f15b1
bb3909a
 
 
73f15b1
 
 
bb3909a
73f15b1
 
 
 
 
 
bb3909a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73f15b1
bb3909a
 
 
 
 
73f15b1
 
 
 
 
 
 
 
bb3909a
 
 
 
73f15b1
bb3909a
 
 
 
73f15b1
 
 
 
 
 
bb3909a
73f15b1
 
bb3909a
73f15b1
 
 
 
bb3909a
 
 
73f15b1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
bb3909a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# utils/visual_output.py - Visual output generation for PDF Analysis & Orchestrator
import json
import re
from typing import Dict, List, Any, Optional
from datetime import datetime

class VisualOutputGenerator:
    """Generate visual representations of analysis results"""
    
    def __init__(self):
        self.visual_elements = []
    
    def create_infographic(self, data: Dict[str, Any], title: str = "Analysis Summary") -> str:
        """Create an infographic-style summary"""
        visual = f"""
## πŸ“Š {title}

<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 20px; border-radius: 10px; color: white; margin: 10px 0;">
"""
        
        # Key metrics
        if 'metrics' in data:
            visual += f"""
<div style="display: flex; justify-content: space-around; margin: 20px 0;">
"""
            for metric, value in data['metrics'].items():
                visual += f"""
<div style="text-align: center; background: rgba(255,255,255,0.2); padding: 15px; border-radius: 8px; margin: 5px;">
<h3 style="margin: 0; font-size: 24px;">{value}</h3>
<p style="margin: 5px 0 0 0; font-size: 14px;">{metric}</p>
</div>
"""
            visual += "</div>"
        
        visual += "</div>"
        return visual
    
    def create_data_table(self, data: List[Dict[str, Any]], title: str = "Data Table") -> str:
        """Create a formatted table from data"""
        if not data:
            return ""
        
        # Get headers from first row
        headers = list(data[0].keys())
        
        table = f"""
## πŸ“‹ {title}

| {' | '.join(headers)} |
| {' | '.join(['---'] * len(headers))} |
"""
        
        for row in data:
            values = [str(row.get(header, '')) for header in headers]
            table += f"| {' | '.join(values)} |\n"
        
        return table
    
    def create_progress_bar(self, value: float, max_value: float, label: str) -> str:
        """Create a progress bar visualization"""
        percentage = min(100, (value / max_value) * 100) if max_value > 0 else 0
        
        return f"""
<div style="margin: 10px 0;">
<p style="margin: 5px 0; font-weight: bold;">{label}: {value:.1f}/{max_value:.1f} ({percentage:.1f}%)</p>
<div style="background: #e0e0e0; border-radius: 10px; height: 20px; overflow: hidden;">
<div style="background: linear-gradient(90deg, #4CAF50, #8BC34A); height: 100%; width: {percentage}%; transition: width 0.3s ease;"></div>
</div>
</div>
"""
    
    def create_timeline(self, events: List[Dict[str, str]], title: str = "Timeline") -> str:
        """Create a timeline visualization"""
        timeline = f"""
## ⏰ {title}

<div style="position: relative; padding-left: 30px; margin: 20px 0;">
"""
        
        for i, event in enumerate(events):
            timeline += f"""
<div style="position: relative; margin-bottom: 20px;">
<div style="position: absolute; left: -25px; top: 5px; width: 12px; height: 12px; background: #4CAF50; border-radius: 50%; border: 3px solid white; box-shadow: 0 0 0 3px #4CAF50;"></div>
<div style="background: #f5f5f5; padding: 15px; border-radius: 8px; border-left: 4px solid #4CAF50;">
<h4 style="margin: 0 0 5px 0; color: #333;">{event.get('title', 'Event')}</h4>
<p style="margin: 0; color: #666;">{event.get('description', '')}</p>
<small style="color: #999;">{event.get('date', '')}</small>
</div>
</div>
"""
        
        timeline += "</div>"
        return timeline
    
    def create_comparison_chart(self, data: Dict[str, float], title: str = "Comparison") -> str:
        """Create a comparison chart"""
        if not data:
            return ""
        
        max_value = max(data.values()) if data.values() else 1
        
        chart = f"""
## πŸ“ˆ {title}

<div style="margin: 20px 0;">
"""
        
        for label, value in data.items():
            percentage = (value / max_value) * 100
            chart += f"""
<div style="margin: 10px 0;">
<div style="display: flex; justify-content: space-between; margin-bottom: 5px;">
<span style="font-weight: bold;">{label}</span>
<span style="color: #666;">{value:.1f}</span>
</div>
<div style="background: #e0e0e0; border-radius: 5px; height: 20px; overflow: hidden;">
<div style="background: linear-gradient(90deg, #2196F3, #21CBF3); height: 100%; width: {percentage}%; transition: width 0.3s ease;"></div>
</div>
</div>
"""
        
        chart += "</div>"
        return chart
    
    def create_key_points(self, points: List[str], title: str = "Key Points") -> str:
        """Create a stunning key points section with visual elements"""
        if not points:
            return ""
        
        # Icons for different types of points
        icons = ["🎯", "πŸ’‘", "βœ…", "πŸ“Š", "⚑", "πŸ”", "πŸš€", "πŸ’Ž", "⭐", "πŸ”₯"]
        
        visual = f"""
## πŸ’‘ {title}

<div style="display: grid; gap: 20px; margin: 25px 0;">
"""
        
        for i, point in enumerate(points, 1):
            icon = icons[i % len(icons)]
            color = ["#007bff", "#28a745", "#ffc107", "#dc3545", "#6f42c1"][i % 5]
            
            visual += f"""
<div style="background: linear-gradient(135deg, {color}15, {color}05); border: 2px solid {color}30; padding: 20px; border-radius: 12px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); transition: transform 0.2s ease;">
<div style="display: flex; align-items: flex-start; gap: 15px;">
<div style="background: {color}; color: white; border-radius: 50%; width: 32px; height: 32px; display: flex; align-items: center; justify-content: center; font-size: 16px; font-weight: bold; flex-shrink: 0; box-shadow: 0 2px 8px {color}50;">{icon}</div>
<div style="flex: 1;">
<p style="margin: 0; line-height: 1.6; font-size: 16px; color: #333; font-weight: 500;">{point}</p>
</div>
</div>
</div>
"""
        
        visual += "</div>"
        return visual
    
    def create_alert_box(self, message: str, alert_type: str = "info") -> str:
        """Create an alert box"""
        colors = {
            "info": "#2196F3",
            "success": "#4CAF50",
            "warning": "#FF9800",
            "error": "#F44336"
        }
        
        icons = {
            "info": "ℹ️",
            "success": "βœ…",
            "warning": "⚠️",
            "error": "❌"
        }
        
        color = colors.get(alert_type, colors["info"])
        icon = icons.get(alert_type, icons["info"])
        
        return f"""
<div style="background: {color}15; border: 1px solid {color}; border-radius: 8px; padding: 15px; margin: 15px 0; display: flex; align-items: flex-start;">
<span style="font-size: 20px; margin-right: 10px;">{icon}</span>
<p style="margin: 0; color: {color}; font-weight: 500;">{message}</p>
</div>
"""
    
    def create_metric_cards(self, metrics: Dict[str, Any], title: str = "Key Metrics") -> str:
        """Create metric cards"""
        if not metrics:
            return ""
        
        cards = f"""
## πŸ“Š {title}

<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 15px; margin: 20px 0;">
"""
        
        for metric, value in metrics.items():
            cards += f"""
<div style="background: white; border: 1px solid #e0e0e0; border-radius: 8px; padding: 20px; text-align: center; box-shadow: 0 2px 4px rgba(0,0,0,0.1);">
<h3 style="margin: 0 0 10px 0; color: #333; font-size: 28px;">{value}</h3>
<p style="margin: 0; color: #666; font-size: 14px; text-transform: uppercase; letter-spacing: 0.5px;">{metric}</p>
</div>
"""
        
        cards += "</div>"
        return cards
    
    def format_analysis_with_visuals(self, analysis_text: str, document_metadata: Dict[str, Any] = None) -> str:
        """Format analysis text with stunning visual elements"""
        visual_elements = []
        
        # Add document info if available
        if document_metadata:
            visual_elements.append(self.create_metric_cards({
                "πŸ“„ Pages": document_metadata.get('page_count', 'Unknown'),
                "πŸ’Ύ File Size": f"{document_metadata.get('file_size', 0) / 1024:.1f} KB",
                "⚑ Processing": f"{document_metadata.get('processing_time', 0):.1f}s",
                "🎯 Tokens": document_metadata.get('tokens_used', 'N/A')
            }, "πŸ“Š Document Overview"))
        
        # Create a beautiful header
        visual_elements.append(self.create_analysis_header())
        
        # Try to extract key points from analysis
        key_points = self._extract_key_points(analysis_text)
        if key_points:
            visual_elements.append(self.create_key_points(key_points, "🎯 Key Insights"))
        
        # Try to extract metrics
        metrics = self._extract_metrics(analysis_text)
        if metrics:
            visual_elements.append(self.create_metric_cards(metrics, "πŸ“ˆ Key Metrics"))
        
        # Try to extract data for tables
        table_data = self._extract_table_data(analysis_text)
        if table_data:
            visual_elements.append(self.create_data_table(table_data, "πŸ“‹ Data Summary"))
        
        # Format the main analysis with better structure
        formatted_analysis = self._format_analysis_text(analysis_text)
        
        # Combine all elements
        result = "\n\n".join(visual_elements)
        if formatted_analysis:
            result += f"\n\n---\n\n{formatted_analysis}"
        
        return result
    
    def create_analysis_header(self) -> str:
        """Create a beautiful analysis header"""
        return """
<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 25px; border-radius: 15px; color: white; margin: 20px 0; text-align: center; box-shadow: 0 8px 32px rgba(0,0,0,0.1);">
<h1 style="margin: 0 0 10px 0; font-size: 28px; font-weight: 700;">πŸ“„ AI Document Analysis</h1>
<p style="margin: 0; font-size: 16px; opacity: 0.9;">Powered by Advanced AI β€’ Instant Insights β€’ Professional Results</p>
</div>
"""
    
    def _format_analysis_text(self, text: str) -> str:
        """Format analysis text with better visual structure"""
        # Split into sections
        sections = text.split('\n\n')
        formatted_sections = []
        
        for section in sections:
            if section.strip():
                # Check if it's a header
                if section.startswith('##'):
                    formatted_sections.append(f"\n{section}\n")
                else:
                    # Format as a content block
                    formatted_sections.append(f"""
<div style="background: #f8f9fa; border-left: 4px solid #007bff; padding: 20px; margin: 15px 0; border-radius: 0 8px 8px 0; box-shadow: 0 2px 8px rgba(0,0,0,0.05);">
{section}
</div>
""")
        
        return '\n'.join(formatted_sections)
    
    def _extract_table_data(self, text: str) -> List[Dict[str, Any]]:
        """Extract data that can be formatted as tables"""
        table_data = []
        
        # Look for comparison patterns
        comparison_pattern = r'(\w+):\s*(\d+(?:\.\d+)?%?)\s*vs\s*(\w+):\s*(\d+(?:\.\d+)?%?)'
        matches = re.findall(comparison_pattern, text, re.IGNORECASE)
        
        for match in matches:
            table_data.append({
                "Metric": match[0],
                "Value": match[1],
                "Comparison": match[2],
                "Value 2": match[3]
            })
        
        return table_data
    
    def _extract_key_points(self, text: str) -> List[str]:
        """Extract key points from analysis text"""
        # Look for bullet points, numbered lists, or key findings
        points = []
        
        # Extract bullet points
        bullet_pattern = r'[-β€’*]\s+(.+?)(?=\n|$)'
        bullets = re.findall(bullet_pattern, text, re.MULTILINE)
        points.extend([bullet.strip() for bullet in bullets if len(bullet.strip()) > 10])
        
        # Extract numbered points
        number_pattern = r'\d+\.\s+(.+?)(?=\n|$)'
        numbers = re.findall(number_pattern, text, re.MULTILINE)
        points.extend([num.strip() for num in numbers if len(num.strip()) > 10])
        
        # Limit to top 5 points
        return points[:5]
    
    def _extract_metrics(self, text: str) -> Dict[str, str]:
        """Extract metrics from analysis text"""
        metrics = {}
        
        # Look for percentage patterns
        percent_pattern = r'(\d+(?:\.\d+)?%)'
        percentages = re.findall(percent_pattern, text)
        if percentages:
            metrics["Success Rate"] = percentages[0]
        
        # Look for number patterns
        number_pattern = r'(\d+(?:,\d+)*(?:\.\d+)?)\s+(?:pages?|items?|points?|years?|months?)'
        numbers = re.findall(number_pattern, text, re.IGNORECASE)
        if numbers:
            metrics["Total Items"] = numbers[0]
        
        return metrics