memscope_rs/async_memory/
visualization.rs

1//! Async Task Performance Visualization Module
2//!
3//! This module provides comprehensive visualization capabilities for async task performance data.
4//! It generates interactive HTML reports with charts, baselines, rankings, and detailed analytics.
5
6use super::{TaskId, TaskResourceProfile};
7use handlebars::Handlebars;
8use serde::{Deserialize, Serialize};
9use std::collections::HashMap;
10
11/// Task type metrics for categorization
12#[derive(Debug, Clone)]
13struct TaskTypeMetrics {
14    pub cpu_count: usize,
15    pub cpu_efficiency: f64,
16    pub memory_count: usize,
17    pub memory_efficiency: f64,
18    pub io_count: usize,
19    pub io_efficiency: f64,
20    pub network_count: usize,
21    pub network_efficiency: f64,
22}
23
24/// Visualization configuration options
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct VisualizationConfig {
27    pub title: String,
28    pub theme: Theme,
29    pub include_charts: bool,
30    pub include_baselines: bool,
31    pub include_rankings: bool,
32    pub include_efficiency_breakdown: bool,
33}
34
35impl Default for VisualizationConfig {
36    fn default() -> Self {
37        Self {
38            title: "Async Task Performance Analysis".to_string(),
39            theme: Theme::Dark,
40            include_charts: true,
41            include_baselines: true,
42            include_rankings: true,
43            include_efficiency_breakdown: true,
44        }
45    }
46}
47
48/// UI Theme options
49#[derive(Debug, Clone, Serialize, Deserialize)]
50pub enum Theme {
51    Dark,
52    Light,
53}
54
55/// Baseline performance metrics for comparison
56#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct PerformanceBaselines {
58    pub avg_cpu_percent: f64,
59    pub avg_memory_mb: f64,
60    pub avg_io_mbps: f64,
61    pub avg_network_mbps: f64,
62    pub avg_efficiency_score: f64,
63}
64
65/// Task ranking within its category
66#[derive(Debug, Clone, Serialize, Deserialize)]
67pub struct CategoryRanking {
68    pub rank: usize,
69    pub total_in_category: usize,
70    pub category_name: String,
71}
72
73/// Performance comparison result
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct PerformanceComparison {
76    pub value: f64,
77    pub baseline: f64,
78    pub difference_percent: f64,
79    pub comparison_type: ComparisonType,
80}
81
82#[derive(Debug, Clone, Serialize, Deserialize)]
83pub enum ComparisonType {
84    AboveAverage,
85    BelowAverage,
86    NearAverage,
87}
88
89/// Main visualization generator
90pub struct VisualizationGenerator {
91    config: VisualizationConfig,
92}
93
94impl VisualizationGenerator {
95    /// Create a new visualization generator with default config
96    pub fn new() -> Self {
97        Self {
98            config: VisualizationConfig::default(),
99        }
100    }
101
102    /// Create a new visualization generator with custom config
103    pub fn with_config(config: VisualizationConfig) -> Self {
104        Self { config }
105    }
106
107    /// Generate complete HTML report from task profiles
108    pub fn generate_html_report(
109        &self,
110        profiles: &HashMap<TaskId, TaskResourceProfile>,
111    ) -> Result<String, VisualizationError> {
112        // Try template-based generation first, fallback to hardcoded if template not found
113        match self.generate_templated_html_report(profiles) {
114            Ok(html) => Ok(html),
115            Err(_) => self.generate_hardcoded_html_report(profiles), // Fallback to original
116        }
117    }
118
119    fn get_html_template() -> String {
120        r#"<!DOCTYPE html>
121<html lang="en">
122<head>
123    <meta charset="UTF-8">
124    <meta name="viewport" content="width=device-width, initial-scale=1.0">
125    <title>🦀 {{title}} - Rust Async Performance Dashboard</title>
126    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
127    <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns"></script>
128    <style>
129        :root {
130            --rust-orange: #ff6b35;
131            --rust-brown: #8b4513;
132            --async-blue: #4c9aff;
133            --async-cyan: #00d9ff;
134            --async-purple: #8b5cf6;
135            --success-green: #10b981;
136            --warning-yellow: #f59e0b;
137            --error-red: #ef4444;
138            --dark-bg: #0c0c0c;
139            --card-bg: #1a1a1a;
140            --surface-bg: #262626;
141            --text-primary: #ffffff;
142            --text-secondary: #a3a3a3;
143            --border-color: #404040;
144            --glow-rust: rgba(255, 107, 53, 0.3);
145            --glow-async: rgba(76, 154, 255, 0.3);
146        }
147        
148        * { margin: 0; padding: 0; box-sizing: border-box; }
149        
150        body {
151            font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', 'Consolas', monospace;
152            background: linear-gradient(135deg, var(--dark-bg) 0%, #111111 50%, var(--dark-bg) 100%);
153            color: var(--text-primary);
154            line-height: 1.6;
155            min-height: 100vh;
156            overflow-x: hidden;
157        }
158        
159        /* Rust-themed animated background */
160        .rust-bg-pattern {
161            position: fixed;
162            top: 0;
163            left: 0;
164            width: 100%;
165            height: 100%;
166            z-index: -1;
167            background-image: 
168                radial-gradient(circle at 25% 25%, var(--glow-rust) 0%, transparent 50%),
169                radial-gradient(circle at 75% 75%, var(--glow-async) 0%, transparent 50%),
170                radial-gradient(circle at 50% 10%, rgba(139, 92, 246, 0.1) 0%, transparent 50%);
171            animation: rustFlow 30s ease-in-out infinite;
172        }
173        
174        @keyframes rustFlow {
175            0%, 100% { transform: translateY(0px) rotate(0deg); opacity: 0.7; }
176            25% { transform: translateY(-10px) rotate(0.5deg); opacity: 0.9; }
177            50% { transform: translateY(-5px) rotate(-0.5deg); opacity: 0.8; }
178            75% { transform: translateY(-15px) rotate(0.3deg); opacity: 0.6; }
179        }
180        
181        .dashboard-container {
182            max-width: 1800px;
183            margin: 0 auto;
184            padding: 20px;
185            position: relative;
186        }
187        
188        /* Enhanced Rust-themed header */
189        .rust-header {
190            background: linear-gradient(135deg, var(--rust-orange), var(--rust-brown), var(--async-blue));
191            padding: 3rem 2rem;
192            text-align: center;
193            border-radius: 20px;
194            margin-bottom: 3rem;
195            box-shadow: 0 20px 60px var(--glow-rust), inset 0 1px 0 rgba(255,255,255,0.1);
196            position: relative;
197            overflow: hidden;
198        }
199        
200        .rust-header::before {
201            content: '🦀';
202            position: absolute;
203            top: 20px;
204            left: 30px;
205            font-size: 3rem;
206            opacity: 0.3;
207            animation: rustCrab 5s ease-in-out infinite;
208        }
209        
210        .rust-header::after {
211            content: '⚡';
212            position: absolute;
213            top: 20px;
214            right: 30px;
215            font-size: 3rem;
216            opacity: 0.3;
217            animation: asyncBolt 3s ease-in-out infinite;
218        }
219        
220        @keyframes rustCrab {
221            0%, 100% { transform: translateX(0px) rotate(0deg); }
222            50% { transform: translateX(10px) rotate(5deg); }
223        }
224        
225        @keyframes asyncBolt {
226            0%, 100% { transform: scale(1); opacity: 0.3; }
227            50% { transform: scale(1.1); opacity: 0.6; }
228        }
229        
230        .rust-title {
231            font-size: 3.5rem;
232            font-weight: 800;
233            margin-bottom: 1rem;
234            background: linear-gradient(45deg, #ffffff, var(--async-cyan), var(--rust-orange));
235            background-clip: text;
236            -webkit-background-clip: text;
237            -webkit-text-fill-color: transparent;
238            text-shadow: 0 0 30px rgba(255, 107, 53, 0.5);
239            position: relative;
240            z-index: 1;
241        }
242        
243        .rust-subtitle {
244            font-size: 1.3rem;
245            opacity: 0.9;
246            font-weight: 400;
247            position: relative;
248            z-index: 1;
249            text-shadow: 0 1px 3px rgba(0,0,0,0.5);
250        }
251        
252        /* Performance metrics grid */
253        .performance-metrics {
254            display: grid;
255            grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
256            gap: 2rem;
257            margin-bottom: 3rem;
258        }
259        
260        .metric-card {
261            background: var(--card-bg);
262            border: 2px solid var(--border-color);
263            border-radius: 16px;
264            padding: 2rem;
265            position: relative;
266            transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
267            overflow: hidden;
268        }
269        
270        .metric-card::before {
271            content: '';
272            position: absolute;
273            top: 0;
274            left: 0;
275            right: 0;
276            height: 4px;
277            background: var(--metric-color, linear-gradient(90deg, var(--rust-orange), var(--async-blue)));
278        }
279        
280        .metric-card:hover {
281            transform: translateY(-8px) scale(1.02);
282            box-shadow: 0 25px 80px var(--metric-glow, var(--glow-rust));
283            border-color: var(--metric-border, var(--rust-orange));
284        }
285        
286        .metric-icon {
287            font-size: 2.8rem;
288            margin-bottom: 1rem;
289            display: block;
290            filter: drop-shadow(0 0 10px currentColor);
291        }
292        
293        .metric-value {
294            font-size: 2.8rem;
295            font-weight: 700;
296            margin-bottom: 0.5rem;
297            background: linear-gradient(45deg, var(--metric-color, var(--rust-orange)), var(--async-cyan));
298            background-clip: text;
299            -webkit-background-clip: text;
300            -webkit-text-fill-color: transparent;
301        }
302        
303        .metric-label {
304            color: var(--text-secondary);
305            font-size: 1.1rem;
306            text-transform: uppercase;
307            letter-spacing: 0.1em;
308            font-weight: 600;
309        }
310        
311        .metric-details {
312            margin-top: 1rem;
313            padding-top: 1rem;
314            border-top: 1px solid var(--border-color);
315            font-size: 0.9rem;
316            color: var(--text-secondary);
317        }
318        
319        /* Task type specific colors */
320        .cpu-intensive { --metric-color: #ef4444; --metric-glow: rgba(239, 68, 68, 0.3); --metric-border: #ef4444; }
321        .memory-intensive { --metric-color: #8b5cf6; --metric-glow: rgba(139, 92, 246, 0.3); --metric-border: #8b5cf6; }
322        .io-intensive { --metric-color: #10b981; --metric-glow: rgba(16, 185, 129, 0.3); --metric-border: #10b981; }
323        .network-intensive { --metric-color: #f59e0b; --metric-glow: rgba(245, 158, 11, 0.3); --metric-border: #f59e0b; }
324        .gpu-compute { --metric-color: #ec4899; --metric-glow: rgba(236, 72, 153, 0.3); --metric-border: #ec4899; }
325        .mixed { --metric-color: #6366f1; --metric-glow: rgba(99, 102, 241, 0.3); --metric-border: #6366f1; }
326        .streaming { --metric-color: #14b8a6; --metric-glow: rgba(20, 184, 166, 0.3); --metric-border: #14b8a6; }
327        .background { --metric-color: #64748b; --metric-glow: rgba(100, 116, 139, 0.3); --metric-border: #64748b; }
328        
329        /* Task Flow Section */
330        .async-task-flow {
331            background: var(--card-bg);
332            border-radius: 20px;
333            padding: 2rem;
334            margin-bottom: 3rem;
335            border: 1px solid var(--border-color);
336            box-shadow: 0 10px 40px rgba(0,0,0,0.3);
337        }
338        
339        .flow-header {
340            display: flex;
341            justify-content: space-between;
342            align-items: center;
343            margin-bottom: 3rem;
344            padding-bottom: 1rem;
345            border-bottom: 2px solid var(--border-color);
346        }
347        
348        .flow-title {
349            font-size: 2rem;
350            font-weight: 700;
351            background: linear-gradient(45deg, var(--rust-orange), var(--async-blue));
352            background-clip: text;
353            -webkit-background-clip: text;
354            -webkit-text-fill-color: transparent;
355        }
356        
357        .flow-stats {
358            display: flex;
359            gap: 2rem;
360            flex-wrap: wrap;
361        }
362        
363        .stat-item {
364            font-size: 0.9rem;
365            color: var(--text-secondary);
366            background: var(--surface-bg);
367            padding: 0.5rem 1rem;
368            border-radius: 8px;
369            border: 1px solid var(--border-color);
370        }
371        
372        /* Task Categories */
373        .task-categories {
374            display: grid;
375            grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
376            gap: 2rem;
377        }
378        
379        .category-lane {
380            background: var(--surface-bg);
381            border-radius: 16px;
382            padding: 1.5rem;
383            border: 2px solid var(--border-color);
384            transition: all 0.3s ease;
385        }
386        
387        .category-lane:hover {
388            border-color: var(--metric-border);
389            box-shadow: 0 8px 32px var(--metric-glow);
390        }
391        
392        .lane-header {
393            display: flex;
394            align-items: center;
395            gap: 1rem;
396            margin-bottom: 1.5rem;
397            padding-bottom: 1rem;
398            border-bottom: 1px solid var(--border-color);
399        }
400        
401        .lane-icon {
402            font-size: 1.5rem;
403            filter: drop-shadow(0 0 8px currentColor);
404        }
405        
406        .lane-title {
407            font-weight: 600;
408            font-size: 1.1rem;
409            flex: 1;
410        }
411        
412        .lane-count {
413            background: var(--metric-color);
414            color: var(--dark-bg);
415            padding: 0.25rem 0.75rem;
416            border-radius: 12px;
417            font-weight: 700;
418            font-size: 0.8rem;
419        }
420        
421        .lane-efficiency {
422            font-size: 0.8rem;
423            color: var(--text-secondary);
424        }
425        
426        /* Task Cards */
427        .tasks-container {
428            display: flex;
429            flex-direction: column;
430            gap: 1rem;
431            max-height: 500px;
432            overflow-y: auto;
433            padding-right: 0.5rem;
434        }
435        
436        .tasks-container::-webkit-scrollbar {
437            width: 6px;
438        }
439        
440        .tasks-container::-webkit-scrollbar-track {
441            background: var(--border-color);
442            border-radius: 3px;
443        }
444        
445        .tasks-container::-webkit-scrollbar-thumb {
446            background: var(--metric-color);
447            border-radius: 3px;
448        }
449        
450        .task-card {
451            background: var(--card-bg);
452            border-radius: 12px;
453            padding: 1.5rem;
454            border: 1px solid var(--border-color);
455            border-left: 4px solid var(--metric-color);
456            transition: all 0.3s ease;
457            cursor: pointer;
458            position: relative;
459            overflow: hidden;
460        }
461        
462        .task-card::before {
463            content: '';
464            position: absolute;
465            top: 0;
466            left: 0;
467            right: 0;
468            bottom: 0;
469            background: linear-gradient(45deg, transparent 30%, var(--metric-glow) 50%, transparent 70%);
470            opacity: 0;
471            transition: opacity 0.3s ease;
472        }
473        
474        .task-card:hover::before {
475            opacity: 1;
476        }
477        
478        .task-card:hover {
479            transform: translateY(-3px) scale(1.02);
480            box-shadow: 0 12px 40px var(--metric-glow);
481            border-color: var(--metric-color);
482        }
483        
484        .task-card.selected {
485            border-color: var(--rust-orange);
486            box-shadow: 0 0 20px var(--glow-rust);
487            transform: scale(1.05);
488        }
489        
490        .task-header {
491            margin-bottom: 1rem;
492        }
493        
494        .task-name {
495            font-weight: 600;
496            font-size: 1rem;
497            margin-bottom: 0.25rem;
498            color: var(--text-primary);
499        }
500        
501        .task-source {
502            font-size: 0.8rem;
503            color: var(--text-secondary);
504            font-family: 'Courier New', monospace;
505            background: var(--surface-bg);
506            padding: 0.25rem 0.5rem;
507            border-radius: 4px;
508            display: inline-block;
509        }
510        
511        .task-metrics {
512            margin-bottom: 1rem;
513        }
514        
515        .metric-row {
516            display: flex;
517            align-items: center;
518            justify-content: space-between;
519            margin-bottom: 0.5rem;
520            font-size: 0.85rem;
521        }
522        
523        .metric-label {
524            color: var(--text-secondary);
525            min-width: 80px;
526        }
527        
528        .metric-value {
529            font-weight: 600;
530            color: var(--text-primary);
531            min-width: 60px;
532            text-align: right;
533        }
534        
535        .metric-bar {
536            flex: 1;
537            height: 4px;
538            background: var(--border-color);
539            border-radius: 2px;
540            margin: 0 0.5rem;
541            overflow: hidden;
542        }
543        
544        .metric-fill {
545            height: 100%;
546            background: linear-gradient(90deg, var(--metric-color), color-mix(in srgb, var(--metric-color) 70%, white));
547            border-radius: 2px;
548            transition: width 0.6s ease;
549        }
550        
551        .task-status {
552            display: flex;
553            justify-content: space-between;
554            align-items: center;
555            font-size: 0.8rem;
556        }
557        
558        .status-badge {
559            padding: 0.25rem 0.5rem;
560            border-radius: 4px;
561            font-weight: 600;
562            text-transform: uppercase;
563        }
564        
565        .status-badge.completed {
566            background: rgba(16, 185, 129, 0.2);
567            color: var(--success-green);
568            border: 1px solid var(--success-green);
569        }
570        
571        .status-badge.running {
572            background: rgba(76, 154, 255, 0.2);
573            color: var(--async-blue);
574            border: 1px solid var(--async-blue);
575        }
576        
577        .status-badge.pending {
578            background: rgba(245, 158, 11, 0.2);
579            color: var(--warning-yellow);
580            border: 1px solid var(--warning-yellow);
581        }
582        
583        .status-badge.failed {
584            background: rgba(239, 68, 68, 0.2);
585            color: var(--error-red);
586            border: 1px solid var(--error-red);
587        }
588        
589        .duration {
590            color: var(--text-secondary);
591            font-weight: 500;
592        }
593        
594        /* Responsive Design */
595        @media (max-width: 1200px) {
596            .task-categories {
597                grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
598            }
599            
600            .flow-header {
601                flex-direction: column;
602                gap: 1rem;
603                align-items: flex-start;
604            }
605            
606            .flow-stats {
607                gap: 1rem;
608            }
609        }
610        
611        @media (max-width: 768px) {
612            .task-categories {
613                grid-template-columns: 1fr;
614            }
615            
616            .performance-metrics {
617                grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
618            }
619            
620            .rust-title {
621                font-size: 2.5rem;
622            }
623            
624            .flow-stats {
625                flex-direction: column;
626                gap: 0.5rem;
627            }
628            
629            .lane-header {
630                flex-wrap: wrap;
631                gap: 0.5rem;
632            }
633        }
634    </style>
635</head>
636<body>
637    <div class="rust-bg-pattern"></div>
638    
639    <div class="dashboard-container">
640        <div class="rust-header">
641            <h1 class="rust-title">🦀 {{title}}</h1>
642            <p class="rust-subtitle">{{subtitle}}</p>
643        </div>
644        
645        <div class="performance-metrics">
646            <div class="metric-card">
647                <span class="metric-icon">🚀</span>
648                <div class="metric-value">{{total_tasks}}</div>
649                <div class="metric-label">Async Tasks</div>
650                <div class="metric-details">
651                    Active: {{active_tasks}} | Completed: {{completed_tasks}} | Failed: {{failed_tasks}}
652                </div>
653            </div>
654            
655            <div class="metric-card cpu-intensive">
656                <span class="metric-icon">🔥</span>
657                <div class="metric-value">{{cpu_usage_avg}}%</div>
658                <div class="metric-label">CPU Usage</div>
659                <div class="metric-details">
660                    Peak: {{cpu_usage_peak}}% | Cores: {{cpu_cores}} | Context Switches: {{context_switches}}
661                </div>
662            </div>
663            
664            <div class="metric-card memory-intensive">
665                <span class="metric-icon">💾</span>
666                <div class="metric-value">{{total_memory_mb}}MB</div>
667                <div class="metric-label">Memory Usage</div>
668                <div class="metric-details">
669                    Peak: {{peak_memory_mb}}MB | Allocations: {{total_allocations}} | Efficiency: {{memory_efficiency}}%
670                </div>
671            </div>
672            
673            <div class="metric-card io-intensive">
674                <span class="metric-icon">⚡</span>
675                <div class="metric-value">{{io_throughput}}MB/s</div>
676                <div class="metric-label">I/O Throughput</div>
677                <div class="metric-details">
678                    Read: {{total_read_mb}}MB | Write: {{total_write_mb}}MB | Ops: {{total_io_ops}}
679                </div>
680            </div>
681            
682            <div class="metric-card network-intensive">
683                <span class="metric-icon">🌐</span>
684                <div class="metric-value">{{network_throughput}}Mbps</div>
685                <div class="metric-label">Network Throughput</div>
686                <div class="metric-details">
687                    Sent: {{total_sent_mb}}MB | Received: {{total_received_mb}}MB | Latency: {{avg_latency}}ms
688                </div>
689            </div>
690            
691            <div class="metric-card">
692                <span class="metric-icon">⚖️</span>
693                <div class="metric-value">{{efficiency_score}}%</div>
694                <div class="metric-label">Overall Efficiency</div>
695                <div class="metric-details">
696                    Balance: {{resource_balance}}% | Bottlenecks: {{bottleneck_count}} | Optimization: {{optimization_potential}}%
697                </div>
698            </div>
699        </div>
700        
701        <!-- Task Flow Visualization with Rust Async characteristics -->
702        <div class="async-task-flow">
703            <div class="flow-header">
704                <h2 class="flow-title">🦀 Rust Async Task Flow Analysis</h2>
705                <div class="flow-stats">
706                    <span class="stat-item">📊 Futures: {{futures_count}}</span>
707                    <span class="stat-item">🔄 Polled: {{total_polls}}</span>
708                    <span class="stat-item">⏱️ Avg Poll Time: {{avg_poll_time}}μs</span>
709                    <span class="stat-item">🎯 Ready Rate: {{ready_rate}}%</span>
710                </div>
711            </div>
712            
713            <!-- Task Type Categories -->
714            <div class="task-categories">
715                <div class="category-lane cpu-intensive">
716                    <div class="lane-header">
717                        <span class="lane-icon">🔥</span>
718                        <span class="lane-title">CPU Intensive Tasks</span>
719                        <span class="lane-count">{{cpu_intensive_count}}</span>
720                        <span class="lane-efficiency">{{cpu_avg_efficiency}}% efficiency</span>
721                    </div>
722                    <div class="tasks-container">
723                        {{#each cpu_intensive_tasks}}
724                        <div class="task-card cpu-intensive" data-task-id="{{task_id}}" onclick="event.stopPropagation(); selectTask('{{task_id}}'); return false;">
725                            <div class="task-header">
726                                <div class="task-name">{{task_name}}</div>
727                                <div class="task-source">{{source_file}}:{{source_line}}</div>
728                            </div>
729                            <div class="task-metrics">
730                                <div class="metric-row">
731                                    <span class="metric-label">CPU:</span>
732                                    <span class="metric-value">{{cpu_usage}}%</span>
733                                    <div class="metric-bar">
734                                        <div class="metric-fill" style="width: {{cpu_usage}}%"></div>
735                                    </div>
736                                </div>
737                                <div class="metric-row">
738                                    <span class="metric-label">Cycles:</span>
739                                    <span class="metric-value">{{cpu_cycles}}M</span>
740                                </div>
741                                <div class="metric-row">
742                                    <span class="metric-label">Instructions:</span>
743                                    <span class="metric-value">{{instructions}}M</span>
744                                </div>
745                                <div class="metric-row">
746                                    <span class="metric-label">Cache Misses:</span>
747                                    <span class="metric-value">{{cache_misses}}K</span>
748                                </div>
749                            </div>
750                            <div class="task-status">
751                                <span class="status-badge {{status_class}}">{{status}}</span>
752                                <span class="duration">{{duration_ms}}ms</span>
753                            </div>
754                        </div>
755                        {{/each}}
756                    </div>
757                </div>
758                
759                <div class="category-lane memory-intensive">
760                    <div class="lane-header">
761                        <span class="lane-icon">💾</span>
762                        <span class="lane-title">Memory Intensive Tasks</span>
763                        <span class="lane-count">{{memory_intensive_count}}</span>
764                        <span class="lane-efficiency">{{memory_avg_efficiency}}% efficiency</span>
765                    </div>
766                    <div class="tasks-container">
767                        {{#each memory_intensive_tasks}}
768                        <div class="task-card memory-intensive" data-task-id="{{task_id}}" onclick="event.stopPropagation(); selectTask('{{task_id}}'); return false;">
769                            <div class="task-header">
770                                <div class="task-name">{{task_name}}</div>
771                                <div class="task-source">{{source_file}}:{{source_line}}</div>
772                            </div>
773                            <div class="task-metrics">
774                                <div class="metric-row">
775                                    <span class="metric-label">Allocated:</span>
776                                    <span class="metric-value">{{allocated_mb}}MB</span>
777                                    <div class="metric-bar">
778                                        <div class="metric-fill" style="width: {{memory_usage_percent}}%"></div>
779                                    </div>
780                                </div>
781                                <div class="metric-row">
782                                    <span class="metric-label">Peak:</span>
783                                    <span class="metric-value">{{peak_memory_mb}}MB</span>
784                                </div>
785                                <div class="metric-row">
786                                    <span class="metric-label">Allocations:</span>
787                                    <span class="metric-value">{{allocation_count}}</span>
788                                </div>
789                                <div class="metric-row">
790                                    <span class="metric-label">Fragmentation:</span>
791                                    <span class="metric-value">{{heap_fragmentation}}%</span>
792                                </div>
793                            </div>
794                            <div class="task-status">
795                                <span class="status-badge {{status_class}}">{{status}}</span>
796                                <span class="duration">{{duration_ms}}ms</span>
797                            </div>
798                        </div>
799                        {{/each}}
800                    </div>
801                </div>
802                
803                <div class="category-lane io-intensive">
804                    <div class="lane-header">
805                        <span class="lane-icon">⚡</span>
806                        <span class="lane-title">I/O Intensive Tasks</span>
807                        <span class="lane-count">{{io_intensive_count}}</span>
808                        <span class="lane-efficiency">{{io_avg_efficiency}}% efficiency</span>
809                    </div>
810                    <div class="tasks-container">
811                        {{#each io_intensive_tasks}}
812                        <div class="task-card io-intensive" data-task-id="{{task_id}}" onclick="event.stopPropagation(); selectTask('{{task_id}}'); return false;">
813                            <div class="task-header">
814                                <div class="task-name">{{task_name}}</div>
815                                <div class="task-source">{{source_file}}:{{source_line}}</div>
816                            </div>
817                            <div class="task-metrics">
818                                <div class="metric-row">
819                                    <span class="metric-label">Read:</span>
820                                    <span class="metric-value">{{bytes_read_mb}}MB</span>
821                                    <div class="metric-bar">
822                                        <div class="metric-fill" style="width: {{io_usage_percent}}%"></div>
823                                    </div>
824                                </div>
825                                <div class="metric-row">
826                                    <span class="metric-label">Write:</span>
827                                    <span class="metric-value">{{bytes_written_mb}}MB</span>
828                                </div>
829                                <div class="metric-row">
830                                    <span class="metric-label">Latency:</span>
831                                    <span class="metric-value">{{avg_latency_us}}μs</span>
832                                </div>
833                                <div class="metric-row">
834                                    <span class="metric-label">Queue Depth:</span>
835                                    <span class="metric-value">{{queue_depth}}</span>
836                                </div>
837                            </div>
838                            <div class="task-status">
839                                <span class="status-badge {{status_class}}">{{status}}</span>
840                                <span class="duration">{{duration_ms}}ms</span>
841                            </div>
842                        </div>
843                        {{/each}}
844                    </div>
845                </div>
846                
847                <div class="category-lane network-intensive">
848                    <div class="lane-header">
849                        <span class="lane-icon">🌐</span>
850                        <span class="lane-title">Network Intensive Tasks</span>
851                        <span class="lane-count">{{network_intensive_count}}</span>
852                        <span class="lane-efficiency">{{network_avg_efficiency}}% efficiency</span>
853                    </div>
854                    <div class="tasks-container">
855                        {{#each network_intensive_tasks}}
856                        <div class="task-card network-intensive" data-task-id="{{task_id}}" onclick="event.stopPropagation(); selectTask('{{task_id}}'); return false;">
857                            <div class="task-header">
858                                <div class="task-name">{{task_name}}</div>
859                                <div class="task-source">{{source_file}}:{{source_line}}</div>
860                            </div>
861                            <div class="task-metrics">
862                                <div class="metric-row">
863                                    <span class="metric-label">Sent:</span>
864                                    <span class="metric-value">{{bytes_sent_mb}}MB</span>
865                                    <div class="metric-bar">
866                                        <div class="metric-fill" style="width: {{network_usage_percent}}%"></div>
867                                    </div>
868                                </div>
869                                <div class="metric-row">
870                                    <span class="metric-label">Received:</span>
871                                    <span class="metric-value">{{bytes_received_mb}}MB</span>
872                                </div>
873                                <div class="metric-row">
874                                    <span class="metric-label">Connections:</span>
875                                    <span class="metric-value">{{active_connections}}</span>
876                                </div>
877                                <div class="metric-row">
878                                    <span class="metric-label">Latency:</span>
879                                    <span class="metric-value">{{avg_latency_ms}}ms</span>
880                                </div>
881                            </div>
882                            <div class="task-status">
883                                <span class="status-badge {{status_class}}">{{status}}</span>
884                                <span class="duration">{{duration_ms}}ms</span>
885                            </div>
886                        </div>
887                        {{/each}}
888                    </div>
889                </div>
890            </div>
891        </div>
892        
893        <!-- Advanced Analytics Section -->
894        <div class="analytics-section">
895            <div class="analytics-header">
896                <h2 class="analytics-title">🔬 Advanced Rust Async Analytics</h2>
897            </div>
898            
899            <div class="analytics-grid">
900                <div class="analytics-card">
901                    <h3>🚀 Future Polling Insights</h3>
902                    <div class="insight-metrics">
903                        <div class="insight-metric">
904                            <span class="label">Total Polls:</span>
905                            <span class="value">{{total_polls}}</span>
906                        </div>
907                        <div class="insight-metric">
908                            <span class="label">Avg Poll Duration:</span>
909                            <span class="value">{{avg_poll_duration}}μs</span>
910                        </div>
911                        <div class="insight-metric">
912                            <span class="label">Ready Immediately:</span>
913                            <span class="value">{{immediate_ready_percent}}%</span>
914                        </div>
915                        <div class="insight-metric">
916                            <span class="label">Waker Efficiency:</span>
917                            <span class="value">{{waker_efficiency}}%</span>
918                        </div>
919                    </div>
920                </div>
921                
922                <div class="analytics-card">
923                    <h3>🧠 Memory Management</h3>
924                    <div class="insight-metrics">
925                        <div class="insight-metric">
926                            <span class="label">Total Allocations:</span>
927                            <span class="value">{{total_allocations}}</span>
928                        </div>
929                        <div class="insight-metric">
930                            <span class="label">Peak Allocation Rate:</span>
931                            <span class="value">{{peak_alloc_rate}}/s</span>
932                        </div>
933                        <div class="insight-metric">
934                            <span class="label">Memory Fragmentation:</span>
935                            <span class="value">{{avg_fragmentation}}%</span>
936                        </div>
937                        <div class="insight-metric">
938                            <span class="label">GC Pressure:</span>
939                            <span class="value">{{gc_pressure}}%</span>
940                        </div>
941                    </div>
942                </div>
943                
944                <div class="analytics-card">
945                    <h3>⚡ Async Runtime Health</h3>
946                    <div class="insight-metrics">
947                        <div class="insight-metric">
948                            <span class="label">Executor Utilization:</span>
949                            <span class="value">{{executor_utilization}}%</span>
950                        </div>
951                        <div class="insight-metric">
952                            <span class="label">Task Queue Length:</span>
953                            <span class="value">{{avg_queue_length}}</span>
954                        </div>
955                        <div class="insight-metric">
956                            <span class="label">Blocking Tasks:</span>
957                            <span class="value">{{blocking_tasks_count}}</span>
958                        </div>
959                        <div class="insight-metric">
960                            <span class="label">Deadlock Risk:</span>
961                            <span class="value">{{deadlock_risk}}%</span>
962                        </div>
963                    </div>
964                </div>
965            </div>
966        </div>
967    </div>
968
969    <script>
970        // Enhanced JavaScript for Rust Async Dashboard
971        
972        let selectedTaskId = null;
973        let animationFrameId = null;
974        
975        // Initialize dashboard
976        document.addEventListener('DOMContentLoaded', function() {
977            initializeDashboard();
978            startMetricAnimations();
979            setupTaskInteractions();
980        });
981        
982        function initializeDashboard() {
983            console.log('🦀 Rust Async Performance Dashboard Initialized');
984            
985            // Add pulse animation to metric cards
986            const metricCards = document.querySelectorAll('.metric-card');
987            metricCards.forEach((card, index) => {
988                setTimeout(() => {
989                    card.style.opacity = '0';
990                    card.style.transform = 'translateY(20px)';
991                    card.style.transition = 'all 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275)';
992                    
993                    setTimeout(() => {
994                        card.style.opacity = '1';
995                        card.style.transform = 'translateY(0)';
996                    }, 100);
997                }, index * 100);
998            });
999        }
1000        
1001        function selectTask(taskId) {
1002            // Check if event exists to prevent errors
1003            if (typeof event !== 'undefined') {
1004                event.preventDefault();
1005                event.stopPropagation();
1006            }
1007            
1008            console.log(`🦀 Selecting Rust async task: ${taskId}`);
1009            
1010            // Remove previous selection
1011            document.querySelectorAll('.task-card').forEach(card => {
1012                card.classList.remove('selected');
1013            });
1014            
1015            // Add selection to clicked task
1016            const taskCard = document.querySelector(`[data-task-id="${taskId}"]`);
1017            if (taskCard) {
1018                taskCard.classList.add('selected');
1019                selectedTaskId = taskId;
1020                
1021                // Show task details with delay to ensure DOM is ready
1022                setTimeout(() => {
1023                    showTaskDetails(taskId);
1024                }, 100);
1025                
1026                // Scroll task into view
1027                taskCard.scrollIntoView({ 
1028                    behavior: 'smooth', 
1029                    block: 'center' 
1030                });
1031            }
1032        }
1033        
1034        function showTaskDetails(taskId) {
1035            // Create or update task details panel
1036            let detailsPanel = document.getElementById('task-details-panel');
1037            if (!detailsPanel) {
1038                detailsPanel = createTaskDetailsPanel();
1039                document.body.appendChild(detailsPanel);
1040            }
1041            
1042            // Populate with task data
1043            const taskCard = document.querySelector(`[data-task-id="${taskId}"]`);
1044            if (taskCard) {
1045                const taskName = taskCard.querySelector('.task-name').textContent;
1046                const taskSource = taskCard.querySelector('.task-source').textContent;
1047                const taskStatus = taskCard.querySelector('.status-badge').textContent;
1048                const taskDuration = taskCard.querySelector('.duration').textContent;
1049                
1050                // Get task type from card classes
1051                const taskType = Array.from(taskCard.classList).find(cls => cls.includes('-intensive')) || 'unknown';
1052                const taskTypeDisplay = taskType.replace('-intensive', '').replace('-', ' ').toUpperCase();
1053                
1054                // Build comprehensive task details
1055                detailsPanel.innerHTML = `
1056                    <div class="details-header">
1057                        <div class="header-content">
1058                            <h3>🦀 Rust Async Task Details</h3>
1059                            <div class="task-title-info">
1060                                <span class="task-title">${taskName}</span>
1061                                <span class="task-type-badge ${taskType}">${taskTypeDisplay} TASK</span>
1062                            </div>
1063                        </div>
1064                        <button onclick="closeTaskDetails()" class="close-btn">✕</button>
1065                    </div>
1066                    <div class="details-content">
1067                        <div class="detail-section">
1068                            <h4>📍 Source Location & Context</h4>
1069                            <div class="source-info">
1070                                <p class="source-code">${taskSource}</p>
1071                                <div class="execution-info">
1072                                    <span class="info-item">Status: <strong class="status-${taskStatus.toLowerCase()}">${taskStatus}</strong></span>
1073                                    <span class="info-item">Duration: <strong>${taskDuration}</strong></span>
1074                                    <span class="info-item">Task ID: <strong>${taskId}</strong></span>
1075                                </div>
1076                            </div>
1077                        </div>
1078                        
1079                        <div class="detail-section">
1080                            <h4>📊 Detailed Performance Metrics</h4>
1081                            <div class="metrics-grid">
1082                                ${Array.from(taskCard.querySelectorAll('.metric-row')).map(row => {
1083                                    const label = row.querySelector('.metric-label').textContent;
1084                                    const value = row.querySelector('.metric-value').textContent;
1085                                    const bar = row.querySelector('.metric-fill');
1086                                    const percentage = bar ? bar.style.width : '0%';
1087                                    
1088                                    return `<div class="metric-detail-card">
1089                                        <div class="metric-header">
1090                                            <span class="metric-name">${label}</span>
1091                                            <span class="metric-val">${value}</span>
1092                                        </div>
1093                                        <div class="metric-bar-container">
1094                                            <div class="metric-bar-bg">
1095                                                <div class="metric-bar-fill ${taskType}" style="width: ${percentage}"></div>
1096                                            </div>
1097                                            <span class="metric-percentage">${percentage}</span>
1098                                        </div>
1099                                    </div>`;
1100                                }).join('')}
1101                            </div>
1102                        </div>
1103                        
1104                        <div class="detail-section">
1105                            <h4>🔬 Async Runtime Analysis</h4>
1106                            <div class="analysis-grid">
1107                                <div class="analysis-card">
1108                                    <div class="analysis-icon">⚡</div>
1109                                    <div class="analysis-content">
1110                                        <h5>Future Polling</h5>
1111                                        <p>This task represents a Rust Future that gets polled by the async executor. Monitor polling frequency and ready states for optimization.</p>
1112                                    </div>
1113                                </div>
1114                                <div class="analysis-card">
1115                                    <div class="analysis-icon">🧠</div>
1116                                    <div class="analysis-content">
1117                                        <h5>Resource Usage</h5>
1118                                        <p>Track ${taskTypeDisplay.toLowerCase()} resource consumption patterns to identify bottlenecks and optimization opportunities.</p>
1119                                    </div>
1120                                </div>
1121                                <div class="analysis-card">
1122                                    <div class="analysis-icon">🎯</div>
1123                                    <div class="analysis-content">
1124                                        <h5>Efficiency Score</h5>
1125                                        <p>Overall task efficiency based on resource utilization, context switches, and async runtime behavior.</p>
1126                                    </div>
1127                                </div>
1128                            </div>
1129                        </div>
1130                        
1131                        <div class="detail-section">
1132                            <h4>🔧 ${taskTypeDisplay} Task Optimization Suggestions</h4>
1133                            <div class="suggestions-container">
1134                                ${getTaskSpecificSuggestions(taskType)}
1135                            </div>
1136                        </div>
1137                        
1138                        <div class="detail-section">
1139                            <h4>📈 Performance Timeline</h4>
1140                            <div class="timeline-placeholder">
1141                                <p>📊 Detailed performance timeline visualization would appear here in a full implementation</p>
1142                                <div class="timeline-mock">
1143                                    <div class="timeline-item">Start → Resource Allocation → Execution → Completion</div>
1144                                </div>
1145                            </div>
1146                        </div>
1147                    </div>
1148                    <div class="details-footer">
1149                        <button onclick="exportTaskData('${taskId}')" class="action-btn export-btn">📤 Export Task Data</button>
1150                        <button onclick="analyzeTaskPerformance('${taskId}')" class="action-btn analyze-btn">🔍 Deep Analysis</button>
1151                        <button onclick="closeTaskDetails()" class="action-btn close-action-btn">Close</button>
1152                    </div>
1153                `;
1154                
1155                // Show panel with animation
1156                detailsPanel.style.display = 'block';
1157                setTimeout(() => {
1158                    detailsPanel.classList.add('visible');
1159                    // Add backdrop blur effect
1160                    document.body.classList.add('modal-open');
1161                }, 10);
1162                
1163                console.log(`🦀 Opened detailed view for Rust async task: ${taskName} (${taskId})`);
1164            }
1165        }
1166        
1167        function createTaskDetailsPanel() {
1168            const panel = document.createElement('div');
1169            panel.id = 'task-details-panel';
1170            panel.className = 'task-details-panel';
1171            panel.style.cssText = `
1172                position: fixed;
1173                top: 50%;
1174                left: 50%;
1175                transform: translate(-50%, -50%) scale(0.9);
1176                width: 90%;
1177                max-width: 600px;
1178                max-height: 80vh;
1179                background: var(--card-bg);
1180                border: 2px solid var(--rust-orange);
1181                border-radius: 16px;
1182                box-shadow: 0 20px 60px rgba(0,0,0,0.5);
1183                z-index: 1000;
1184                display: none;
1185                opacity: 0;
1186                transition: all 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
1187                overflow-y: auto;
1188                color: var(--text-primary);
1189            `;
1190            
1191            return panel;
1192        }
1193        
1194        function closeTaskDetails() {
1195            const panel = document.getElementById('task-details-panel');
1196            if (panel) {
1197                panel.classList.remove('visible');
1198                document.body.classList.remove('modal-open');
1199                setTimeout(() => {
1200                    panel.style.display = 'none';
1201                }, 300);
1202            }
1203            
1204            // Also remove selection from task cards
1205            document.querySelectorAll('.task-card.selected').forEach(card => {
1206                card.classList.remove('selected');
1207            });
1208            selectedTaskId = null;
1209            console.log('🦀 Closed task details panel');
1210        }
1211        
1212        // Get task-specific optimization suggestions
1213        function getTaskSpecificSuggestions(taskType) {
1214            const suggestions = {
1215                'cpu-intensive': [
1216                    'Use rayon for parallel computation where applicable',
1217                    'Consider async-friendly CPU-bound algorithms',
1218                    'Implement work-stealing for better load distribution',
1219                    'Profile hot paths and optimize critical sections',
1220                    'Use tokio::task::yield_now() to prevent blocking the executor'
1221                ],
1222                'memory-intensive': [
1223                    'Implement memory pooling to reduce allocations',
1224                    'Use async streams for large data processing',
1225                    'Consider zero-copy techniques where possible',
1226                    'Monitor heap fragmentation and optimize allocation patterns',
1227                    'Use Arc and Rc judiciously to minimize cloning'
1228                ],
1229                'io-intensive': [
1230                    'Use async I/O operations with proper buffering',
1231                    'Implement connection pooling for database operations',
1232                    'Consider batch operations to reduce I/O overhead',
1233                    'Use tokio::fs for async file operations',
1234                    'Optimize buffer sizes based on workload patterns'
1235                ],
1236                'network-intensive': [
1237                    'Implement connection reuse and keep-alive',
1238                    'Use async HTTP clients with connection pooling',
1239                    'Consider implementing backpressure for streaming data',
1240                    'Optimize serialization/deserialization performance',
1241                    'Use compression for large data transfers'
1242                ]
1243            };
1244            
1245            const taskSuggestions = suggestions[taskType] || suggestions['cpu-intensive'];
1246            return taskSuggestions.map(suggestion => 
1247                `<div class="suggestion-item">
1248                    <div class="suggestion-icon">💡</div>
1249                    <div class="suggestion-text">${suggestion}</div>
1250                </div>`
1251            ).join('');
1252        }
1253        
1254        // Export task data functionality
1255        function exportTaskData(taskId) {
1256            const taskCard = document.querySelector(`[data-task-id="${taskId}"]`);
1257            if (taskCard) {
1258                const taskData = {
1259                    taskId: taskId,
1260                    taskName: taskCard.querySelector('.task-name').textContent,
1261                    sourceLocation: taskCard.querySelector('.task-source').textContent,
1262                    status: taskCard.querySelector('.status-badge').textContent,
1263                    duration: taskCard.querySelector('.duration').textContent,
1264                    metrics: Array.from(taskCard.querySelectorAll('.metric-row')).map(row => ({
1265                        label: row.querySelector('.metric-label').textContent,
1266                        value: row.querySelector('.metric-value').textContent
1267                    })),
1268                    exportTimestamp: new Date().toISOString()
1269                };
1270                
1271                const blob = new Blob([JSON.stringify(taskData, null, 2)], { type: 'application/json' });
1272                const url = URL.createObjectURL(blob);
1273                const a = document.createElement('a');
1274                a.href = url;
1275                a.download = `rust-async-task-${taskId}-${Date.now()}.json`;
1276                a.click();
1277                URL.revokeObjectURL(url);
1278                
1279                console.log(`📤 Exported data for task: ${taskId}`);
1280            }
1281        }
1282        
1283        // Deep analysis functionality (placeholder)
1284        function analyzeTaskPerformance(taskId) {
1285            console.log(`🔍 Starting deep analysis for task: ${taskId}`);
1286            
1287            // Create analysis notification
1288            const notification = document.createElement('div');
1289            notification.className = 'analysis-notification';
1290            notification.innerHTML = `
1291                <div class="notification-content">
1292                    <span class="notification-icon">🔬</span>
1293                    <span class="notification-text">Deep analysis started for task ${taskId}</span>
1294                    <span class="notification-progress">Analyzing...</span>
1295                </div>
1296            `;
1297            
1298            document.body.appendChild(notification);
1299            
1300            // Simulate analysis process
1301            setTimeout(() => {
1302                notification.querySelector('.notification-progress').textContent = 'Analysis complete!';
1303                notification.classList.add('success');
1304                
1305                setTimeout(() => {
1306                    document.body.removeChild(notification);
1307                }, 2000);
1308            }, 3000);
1309        }
1310        
1311        function startMetricAnimations() {
1312            // Animate metric bars
1313            const metricFills = document.querySelectorAll('.metric-fill');
1314            metricFills.forEach(fill => {
1315                const width = fill.style.width;
1316                fill.style.width = '0%';
1317                setTimeout(() => {
1318                    fill.style.width = width;
1319                }, Math.random() * 1000 + 500);
1320            });
1321            
1322            // Pulse animation for real-time feeling
1323            setInterval(() => {
1324                const activeCards = document.querySelectorAll('.task-card');
1325                const randomCard = activeCards[Math.floor(Math.random() * activeCards.length)];
1326                if (randomCard && !randomCard.classList.contains('selected')) {
1327                    randomCard.style.transform = 'scale(1.01)';
1328                    setTimeout(() => {
1329                        randomCard.style.transform = '';
1330                    }, 200);
1331                }
1332            }, 3000);
1333        }
1334        
1335        function setupTaskInteractions() {
1336            // Add keyboard navigation
1337            document.addEventListener('keydown', function(e) {
1338                if (e.key === 'Escape') {
1339                    closeTaskDetails();
1340                    // Deselect all tasks
1341                    document.querySelectorAll('.task-card').forEach(card => {
1342                        card.classList.remove('selected');
1343                    });
1344                    selectedTaskId = null;
1345                }
1346            });
1347            
1348            // Add click outside to close details - but only on backdrop, not the panel itself
1349            document.addEventListener('click', function(e) {
1350                const panel = document.getElementById('task-details-panel');
1351                if (panel && panel.classList.contains('visible')) {
1352                    // Only close if clicking directly on the backdrop, not the panel content
1353                    if (e.target === panel) {
1354                        closeTaskDetails();
1355                    }
1356                }
1357            });
1358        }
1359        
1360        // Utility functions for enhanced interactivity
1361        function filterTasksByType(taskType) {
1362            const allCards = document.querySelectorAll('.task-card');
1363            allCards.forEach(card => {
1364                if (taskType === 'all' || card.classList.contains(taskType)) {
1365                    card.style.display = 'block';
1366                    card.style.opacity = '1';
1367                } else {
1368                    card.style.opacity = '0.3';
1369                }
1370            });
1371        }
1372        
1373        function exportDashboardData() {
1374            const data = {
1375                timestamp: new Date().toISOString(),
1376                tasks: Array.from(document.querySelectorAll('.task-card')).map(card => ({
1377                    id: card.dataset.taskId,
1378                    name: card.querySelector('.task-name').textContent,
1379                    type: Array.from(card.classList).find(c => c.includes('-intensive')),
1380                    metrics: Array.from(card.querySelectorAll('.metric-row')).map(row => ({
1381                        label: row.querySelector('.metric-label').textContent,
1382                        value: row.querySelector('.metric-value').textContent
1383                    }))
1384                }))
1385            };
1386            
1387            const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });
1388            const url = URL.createObjectURL(blob);
1389            const a = document.createElement('a');
1390            a.href = url;
1391            a.download = `rust-async-performance-${Date.now()}.json`;
1392            a.click();
1393            URL.revokeObjectURL(url);
1394        }
1395        
1396        // Performance monitoring
1397        function monitorPerformance() {
1398            if ('performance' in window) {
1399                const navigation = performance.getEntriesByType('navigation')[0];
1400                console.log(`🦀 Dashboard Load Time: ${navigation.loadEventEnd - navigation.loadEventStart}ms`);
1401                
1402                // Monitor memory usage if available
1403                if ('memory' in performance) {
1404                    const memory = performance.memory;
1405                    console.log(`💾 Memory Usage: ${(memory.usedJSHeapSize / 1048576).toFixed(2)}MB`);
1406                }
1407            }
1408        }
1409        
1410        // Initialize performance monitoring
1411        window.addEventListener('load', monitorPerformance);
1412        
1413        // CSS for task details panel
1414        const detailsStyles = `
1415            /* Enhanced Task Details Panel */
1416            .task-details-panel {
1417                position: fixed;
1418                top: 50%;
1419                left: 50%;
1420                transform: translate(-50%, -50%) scale(0.9);
1421                width: 95%;
1422                max-width: 900px;
1423                max-height: 90vh;
1424                background: var(--card-bg);
1425                border: 2px solid var(--rust-orange);
1426                border-radius: 20px;
1427                box-shadow: 0 25px 80px rgba(0,0,0,0.7), 0 0 0 1000px rgba(0,0,0,0.5);
1428                z-index: 1000;
1429                display: none;
1430                opacity: 0;
1431                transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
1432                overflow: hidden;
1433                color: var(--text-primary);
1434            }
1435            
1436            .task-details-panel.visible {
1437                opacity: 1 !important;
1438                transform: translate(-50%, -50%) scale(1) !important;
1439            }
1440            
1441            .body.modal-open {
1442                overflow: hidden;
1443            }
1444            
1445            .details-header {
1446                background: linear-gradient(135deg, var(--rust-orange), var(--async-blue));
1447                padding: 2rem;
1448                display: flex;
1449                justify-content: space-between;
1450                align-items: flex-start;
1451                border-bottom: 2px solid var(--border-color);
1452            }
1453            
1454            .header-content h3 {
1455                font-size: 1.5rem;
1456                margin-bottom: 1rem;
1457                color: white;
1458                text-shadow: 0 2px 4px rgba(0,0,0,0.3);
1459            }
1460            
1461            .task-title-info {
1462                display: flex;
1463                flex-direction: column;
1464                gap: 0.75rem;
1465            }
1466            
1467            .task-title {
1468                font-size: 1.3rem;
1469                font-weight: 700;
1470                color: white;
1471                text-shadow: 0 1px 3px rgba(0,0,0,0.5);
1472            }
1473            
1474            .task-type-badge {
1475                display: inline-block;
1476                padding: 0.5rem 1rem;
1477                border-radius: 25px;
1478                font-size: 0.8rem;
1479                font-weight: 700;
1480                text-transform: uppercase;
1481                letter-spacing: 0.05em;
1482                background: rgba(255,255,255,0.2);
1483                border: 1px solid rgba(255,255,255,0.3);
1484                color: white;
1485                backdrop-filter: blur(10px);
1486            }
1487            
1488            .details-content {
1489                padding: 2rem;
1490                overflow-y: auto;
1491                max-height: 60vh;
1492            }
1493            
1494            .details-content::-webkit-scrollbar {
1495                width: 8px;
1496            }
1497            
1498            .details-content::-webkit-scrollbar-track {
1499                background: var(--surface-bg);
1500                border-radius: 4px;
1501            }
1502            
1503            .details-content::-webkit-scrollbar-thumb {
1504                background: var(--rust-orange);
1505                border-radius: 4px;
1506            }
1507            
1508            .detail-section {
1509                margin-bottom: 2.5rem;
1510                padding-bottom: 1.5rem;
1511                border-bottom: 1px solid var(--border-color);
1512            }
1513            
1514            .detail-section:last-child {
1515                border-bottom: none;
1516            }
1517            
1518            .detail-section h4 {
1519                color: var(--rust-orange);
1520                margin-bottom: 1.5rem;
1521                font-size: 1.2rem;
1522                font-weight: 600;
1523                display: flex;
1524                align-items: center;
1525                gap: 0.5rem;
1526            }
1527            
1528            .source-info {
1529                background: var(--surface-bg);
1530                padding: 1.5rem;
1531                border-radius: 12px;
1532                border: 1px solid var(--border-color);
1533            }
1534            
1535            .source-code {
1536                background: var(--dark-bg);
1537                padding: 1rem;
1538                border-radius: 8px;
1539                font-family: 'Courier New', monospace;
1540                font-size: 0.9rem;
1541                color: var(--async-cyan);
1542                border-left: 4px solid var(--rust-orange);
1543                margin-bottom: 1rem;
1544            }
1545            
1546            .execution-info {
1547                display: flex;
1548                gap: 2rem;
1549                flex-wrap: wrap;
1550            }
1551            
1552            .info-item {
1553                font-size: 0.9rem;
1554                color: var(--text-secondary);
1555            }
1556            
1557            .info-item strong {
1558                color: var(--text-primary);
1559                font-weight: 600;
1560            }
1561            
1562            .metrics-grid {
1563                display: grid;
1564                grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
1565                gap: 1rem;
1566            }
1567            
1568            .metric-detail-card {
1569                background: var(--surface-bg);
1570                padding: 1.5rem;
1571                border-radius: 12px;
1572                border: 1px solid var(--border-color);
1573                transition: all 0.3s ease;
1574            }
1575            
1576            .metric-detail-card:hover {
1577                border-color: var(--rust-orange);
1578                box-shadow: 0 4px 16px rgba(255, 107, 53, 0.2);
1579            }
1580            
1581            .metric-header {
1582                display: flex;
1583                justify-content: space-between;
1584                align-items: center;
1585                margin-bottom: 1rem;
1586            }
1587            
1588            .metric-name {
1589                color: var(--text-secondary);
1590                font-size: 0.9rem;
1591                font-weight: 500;
1592            }
1593            
1594            .metric-val {
1595                color: var(--text-primary);
1596                font-weight: 700;
1597                font-size: 1.1rem;
1598            }
1599            
1600            .metric-bar-container {
1601                display: flex;
1602                align-items: center;
1603                gap: 1rem;
1604            }
1605            
1606            .metric-bar-bg {
1607                flex: 1;
1608                height: 8px;
1609                background: var(--border-color);
1610                border-radius: 4px;
1611                overflow: hidden;
1612            }
1613            
1614            .metric-bar-fill {
1615                height: 100%;
1616                border-radius: 4px;
1617                transition: width 0.6s ease;
1618                background: linear-gradient(90deg, var(--metric-color), color-mix(in srgb, var(--metric-color) 70%, white));
1619            }
1620            
1621            .metric-percentage {
1622                font-size: 0.8rem;
1623                color: var(--text-secondary);
1624                min-width: 40px;
1625                text-align: right;
1626            }
1627            
1628            .analysis-grid {
1629                display: grid;
1630                grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
1631                gap: 1.5rem;
1632            }
1633            
1634            .analysis-card {
1635                background: var(--surface-bg);
1636                padding: 1.5rem;
1637                border-radius: 12px;
1638                border: 1px solid var(--border-color);
1639                display: flex;
1640                gap: 1rem;
1641                transition: all 0.3s ease;
1642            }
1643            
1644            .analysis-card:hover {
1645                border-color: var(--async-blue);
1646                box-shadow: 0 4px 16px rgba(76, 154, 255, 0.2);
1647            }
1648            
1649            .analysis-icon {
1650                font-size: 2rem;
1651                filter: drop-shadow(0 0 8px currentColor);
1652            }
1653            
1654            .analysis-content h5 {
1655                margin-bottom: 0.5rem;
1656                color: var(--text-primary);
1657                font-weight: 600;
1658            }
1659            
1660            .analysis-content p {
1661                font-size: 0.9rem;
1662                color: var(--text-secondary);
1663                line-height: 1.5;
1664            }
1665            
1666            .suggestions-container {
1667                display: flex;
1668                flex-direction: column;
1669                gap: 1rem;
1670            }
1671            
1672            .suggestion-item {
1673                display: flex;
1674                align-items: flex-start;
1675                gap: 1rem;
1676                background: var(--surface-bg);
1677                padding: 1rem;
1678                border-radius: 8px;
1679                border-left: 4px solid var(--async-blue);
1680                transition: all 0.3s ease;
1681            }
1682            
1683            .suggestion-item:hover {
1684                background: color-mix(in srgb, var(--surface-bg) 80%, var(--async-blue));
1685            }
1686            
1687            .suggestion-icon {
1688                font-size: 1.2rem;
1689                margin-top: 0.2rem;
1690            }
1691            
1692            .suggestion-text {
1693                color: var(--text-primary);
1694                font-size: 0.9rem;
1695                line-height: 1.5;
1696            }
1697            
1698            .timeline-placeholder {
1699                background: var(--surface-bg);
1700                padding: 2rem;
1701                border-radius: 12px;
1702                border: 1px dashed var(--border-color);
1703                text-align: center;
1704            }
1705            
1706            .timeline-mock {
1707                margin-top: 1rem;
1708                padding: 1rem;
1709                background: var(--dark-bg);
1710                border-radius: 8px;
1711                font-family: monospace;
1712                color: var(--async-cyan);
1713            }
1714            
1715            .details-footer {
1716                background: var(--surface-bg);
1717                padding: 1.5rem 2rem;
1718                border-top: 1px solid var(--border-color);
1719                display: flex;
1720                gap: 1rem;
1721                justify-content: flex-end;
1722                flex-wrap: wrap;
1723            }
1724            
1725            .action-btn {
1726                padding: 0.75rem 1.5rem;
1727                border: none;
1728                border-radius: 8px;
1729                font-weight: 600;
1730                cursor: pointer;
1731                transition: all 0.3s ease;
1732                display: flex;
1733                align-items: center;
1734                gap: 0.5rem;
1735                font-size: 0.9rem;
1736            }
1737            
1738            .export-btn {
1739                background: var(--success-green);
1740                color: white;
1741            }
1742            
1743            .export-btn:hover {
1744                background: #059669;
1745                transform: translateY(-2px);
1746            }
1747            
1748            .analyze-btn {
1749                background: var(--async-blue);
1750                color: white;
1751            }
1752            
1753            .analyze-btn:hover {
1754                background: #2563eb;
1755                transform: translateY(-2px);
1756            }
1757            
1758            .close-action-btn {
1759                background: var(--error-red);
1760                color: white;
1761            }
1762            
1763            .close-action-btn:hover {
1764                background: #dc2626;
1765                transform: translateY(-2px);
1766            }
1767            
1768            .close-btn {
1769                background: rgba(255,255,255,0.2);
1770                color: white;
1771                border: 1px solid rgba(255,255,255,0.3);
1772                padding: 0.75rem 1rem;
1773                border-radius: 8px;
1774                cursor: pointer;
1775                font-weight: 600;
1776                backdrop-filter: blur(10px);
1777                transition: all 0.3s ease;
1778            }
1779            
1780            .close-btn:hover {
1781                background: rgba(255,255,255,0.3);
1782                transform: scale(1.05);
1783            }
1784            
1785            /* Analysis notification */
1786            .analysis-notification {
1787                position: fixed;
1788                top: 2rem;
1789                right: 2rem;
1790                background: var(--card-bg);
1791                border: 2px solid var(--async-blue);
1792                border-radius: 12px;
1793                padding: 1rem 1.5rem;
1794                box-shadow: 0 8px 32px rgba(0,0,0,0.5);
1795                z-index: 1001;
1796                color: var(--text-primary);
1797                transition: all 0.3s ease;
1798            }
1799            
1800            .analysis-notification.success {
1801                border-color: var(--success-green);
1802            }
1803            
1804            .notification-content {
1805                display: flex;
1806                align-items: center;
1807                gap: 1rem;
1808            }
1809            
1810            .notification-icon {
1811                font-size: 1.5rem;
1812            }
1813            
1814            .notification-text {
1815                font-weight: 600;
1816            }
1817            
1818            .notification-progress {
1819                color: var(--text-secondary);
1820                font-size: 0.9rem;
1821            }
1822            .analytics-section {
1823                background: var(--card-bg);
1824                border-radius: 20px;
1825                padding: 2rem;
1826                margin-bottom: 3rem;
1827                border: 1px solid var(--border-color);
1828            }
1829            .analytics-title {
1830                font-size: 1.8rem;
1831                font-weight: 700;
1832                margin-bottom: 2rem;
1833                background: linear-gradient(45deg, var(--rust-orange), var(--async-blue));
1834                background-clip: text;
1835                -webkit-background-clip: text;
1836                -webkit-text-fill-color: transparent;
1837            }
1838            .analytics-grid {
1839                display: grid;
1840                grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
1841                gap: 2rem;
1842            }
1843            .analytics-card {
1844                background: var(--surface-bg);
1845                border-radius: 12px;
1846                padding: 1.5rem;
1847                border: 1px solid var(--border-color);
1848            }
1849            .analytics-card h3 {
1850                margin-bottom: 1rem;
1851                color: var(--text-primary);
1852            }
1853            .insight-metrics {
1854                display: flex;
1855                flex-direction: column;
1856                gap: 0.75rem;
1857            }
1858            .insight-metric {
1859                display: flex;
1860                justify-content: space-between;
1861                padding: 0.5rem;
1862                background: var(--card-bg);
1863                border-radius: 6px;
1864                font-size: 0.9rem;
1865            }
1866            .insight-metric .label {
1867                color: var(--text-secondary);
1868            }
1869            .insight-metric .value {
1870                font-weight: 600;
1871                color: var(--rust-orange);
1872            }
1873        `;
1874        
1875        // Inject styles
1876        const styleSheet = document.createElement('style');
1877        styleSheet.textContent = detailsStyles;
1878        document.head.appendChild(styleSheet);
1879        
1880    </script>
1881</body>
1882</html>
1883        "#.to_string()
1884    }
1885
1886    /// Generate HTML using Handlebars template (NEW)
1887    fn generate_templated_html_report(
1888        &self,
1889        profiles: &HashMap<TaskId, TaskResourceProfile>,
1890    ) -> Result<String, VisualizationError> {
1891        let template_content = Self::get_html_template();
1892
1893        // Create Handlebars registry
1894        let mut handlebars = Handlebars::new();
1895        handlebars
1896            .register_template_string("async_dashboard", template_content)
1897            .map_err(|e| {
1898                VisualizationError::TemplateError(format!("Failed to register template: {}", e))
1899            })?;
1900
1901        // Build template data
1902        let template_data = self.build_template_data(profiles)?;
1903
1904        // Render template
1905        let rendered = handlebars
1906            .render("async_dashboard", &template_data)
1907            .map_err(|e| {
1908                VisualizationError::TemplateError(format!("Failed to render template: {}", e))
1909            })?;
1910
1911        Ok(rendered)
1912    }
1913
1914    /// Generate hardcoded HTML (ORIGINAL method)
1915    fn generate_hardcoded_html_report(
1916        &self,
1917        profiles: &HashMap<TaskId, TaskResourceProfile>,
1918    ) -> Result<String, VisualizationError> {
1919        let analytics = self.analyze_profiles(profiles)?;
1920        self.build_html_report(&analytics, profiles)
1921    }
1922
1923    /// Generate analytics data from profiles
1924    pub fn analyze_profiles(
1925        &self,
1926        profiles: &HashMap<TaskId, TaskResourceProfile>,
1927    ) -> Result<PerformanceAnalytics, VisualizationError> {
1928        if profiles.is_empty() {
1929            return Err(VisualizationError::NoDataAvailable);
1930        }
1931
1932        let baselines = self.calculate_baselines(profiles);
1933        let rankings = self.calculate_rankings(profiles);
1934        let comparisons = self.calculate_comparisons(profiles, &baselines);
1935
1936        Ok(PerformanceAnalytics {
1937            baselines,
1938            rankings,
1939            comparisons,
1940            total_tasks: profiles.len(),
1941        })
1942    }
1943
1944    /// Calculate baseline metrics
1945    fn calculate_baselines(
1946        &self,
1947        profiles: &HashMap<TaskId, TaskResourceProfile>,
1948    ) -> PerformanceBaselines {
1949        let total = profiles.len() as f64;
1950        let mut totals = (0.0, 0.0, 0.0, 0.0, 0.0);
1951
1952        for profile in profiles.values() {
1953            totals.0 += profile.cpu_metrics.usage_percent;
1954            totals.1 += profile.memory_metrics.current_bytes as f64 / 1_048_576.0;
1955            totals.2 += profile.io_metrics.bandwidth_mbps;
1956            totals.3 += profile.network_metrics.throughput_mbps;
1957            totals.4 += profile.efficiency_score;
1958        }
1959
1960        PerformanceBaselines {
1961            avg_cpu_percent: totals.0 / total,
1962            avg_memory_mb: totals.1 / total,
1963            avg_io_mbps: totals.2 / total,
1964            avg_network_mbps: totals.3 / total,
1965            avg_efficiency_score: totals.4 / total,
1966        }
1967    }
1968
1969    /// Calculate category rankings
1970    fn calculate_rankings(
1971        &self,
1972        profiles: &HashMap<TaskId, TaskResourceProfile>,
1973    ) -> HashMap<TaskId, CategoryRanking> {
1974        let mut rankings = HashMap::new();
1975        let mut category_groups: HashMap<String, Vec<(TaskId, &TaskResourceProfile)>> =
1976            HashMap::new();
1977
1978        // Group by task type
1979        for (task_id, profile) in profiles {
1980            let category = format!("{:?}", profile.task_type);
1981            category_groups
1982                .entry(category)
1983                .or_default()
1984                .push((*task_id, profile));
1985        }
1986
1987        // Calculate rankings within each category
1988        for (category_name, mut tasks) in category_groups {
1989            tasks.sort_by(|a, b| {
1990                b.1.efficiency_score
1991                    .partial_cmp(&a.1.efficiency_score)
1992                    .unwrap_or(std::cmp::Ordering::Equal)
1993            });
1994
1995            let total_in_category = tasks.len();
1996            for (rank, (task_id, _)) in tasks.iter().enumerate() {
1997                rankings.insert(
1998                    *task_id,
1999                    CategoryRanking {
2000                        rank: rank + 1,
2001                        total_in_category,
2002                        category_name: category_name.clone(),
2003                    },
2004                );
2005            }
2006        }
2007
2008        rankings
2009    }
2010
2011    /// Calculate performance comparisons
2012    fn calculate_comparisons(
2013        &self,
2014        profiles: &HashMap<TaskId, TaskResourceProfile>,
2015        baselines: &PerformanceBaselines,
2016    ) -> HashMap<TaskId, TaskComparisons> {
2017        let mut comparisons = HashMap::new();
2018
2019        for (task_id, profile) in profiles {
2020            let cpu_comp = self
2021                .compare_to_baseline(profile.cpu_metrics.usage_percent, baselines.avg_cpu_percent);
2022            let memory_comp = self.compare_to_baseline(
2023                profile.memory_metrics.current_bytes as f64 / 1_048_576.0,
2024                baselines.avg_memory_mb,
2025            );
2026            let io_comp =
2027                self.compare_to_baseline(profile.io_metrics.bandwidth_mbps, baselines.avg_io_mbps);
2028            let network_comp = self.compare_to_baseline(
2029                profile.network_metrics.throughput_mbps,
2030                baselines.avg_network_mbps,
2031            );
2032
2033            comparisons.insert(
2034                *task_id,
2035                TaskComparisons {
2036                    cpu: cpu_comp,
2037                    memory: memory_comp,
2038                    io: io_comp,
2039                    network: network_comp,
2040                },
2041            );
2042        }
2043
2044        comparisons
2045    }
2046
2047    /// Compare a value to its baseline
2048    fn compare_to_baseline(&self, value: f64, baseline: f64) -> PerformanceComparison {
2049        let difference_percent = if baseline != 0.0 {
2050            ((value - baseline) / baseline) * 100.0
2051        } else {
2052            0.0
2053        };
2054
2055        let comparison_type = if difference_percent.abs() < 5.0 {
2056            ComparisonType::NearAverage
2057        } else if difference_percent > 0.0 {
2058            ComparisonType::AboveAverage
2059        } else {
2060            ComparisonType::BelowAverage
2061        };
2062
2063        PerformanceComparison {
2064            value,
2065            baseline,
2066            difference_percent,
2067            comparison_type,
2068        }
2069    }
2070}
2071
2072/// Complete analytics data
2073#[derive(Debug, Clone)]
2074pub struct PerformanceAnalytics {
2075    pub baselines: PerformanceBaselines,
2076    pub rankings: HashMap<TaskId, CategoryRanking>,
2077    pub comparisons: HashMap<TaskId, TaskComparisons>,
2078    pub total_tasks: usize,
2079}
2080
2081/// Task-specific comparison data
2082#[derive(Debug, Clone)]
2083pub struct TaskComparisons {
2084    pub cpu: PerformanceComparison,
2085    pub memory: PerformanceComparison,
2086    pub io: PerformanceComparison,
2087    pub network: PerformanceComparison,
2088}
2089
2090/// Visualization errors
2091#[derive(Debug, thiserror::Error)]
2092pub enum VisualizationError {
2093    #[error("No data available for visualization")]
2094    NoDataAvailable,
2095    #[error("Invalid configuration: {0}")]
2096    InvalidConfiguration(String),
2097    #[error("Template generation error: {0}")]
2098    TemplateError(String),
2099    #[error("IO error: {0}")]
2100    IoError(#[from] std::io::Error),
2101}
2102
2103impl Default for VisualizationGenerator {
2104    fn default() -> Self {
2105        Self::new()
2106    }
2107}
2108
2109impl VisualizationGenerator {
2110    /// Build complete HTML report
2111    fn build_html_report(
2112        &self,
2113        analytics: &PerformanceAnalytics,
2114        profiles: &HashMap<TaskId, TaskResourceProfile>,
2115    ) -> Result<String, VisualizationError> {
2116        let mut html = String::new();
2117
2118        // HTML Header
2119        html.push_str(&self.generate_html_header());
2120
2121        // Summary Section
2122        html.push_str(&self.generate_summary_section(analytics));
2123
2124        // Charts Section (if enabled) - moved to top
2125        if self.config.include_charts {
2126            html.push_str(&self.generate_charts_section(profiles)?);
2127        }
2128
2129        // Tasks Section
2130        html.push_str(&self.generate_tasks_section(analytics, profiles)?);
2131
2132        // HTML Footer
2133        html.push_str(&self.generate_html_footer());
2134
2135        Ok(html)
2136    }
2137
2138    /// Generate HTML header with styles
2139    fn generate_html_header(&self) -> String {
2140        let theme_styles = match self.config.theme {
2141            Theme::Dark => self.get_dark_theme_styles(),
2142            Theme::Light => self.get_light_theme_styles(),
2143        };
2144
2145        format!(
2146            r#"<!DOCTYPE html>
2147<html lang="en">
2148<head>
2149    <meta charset="UTF-8">
2150    <meta name="viewport" content="width=device-width, initial-scale=1.0">
2151    <title>{}</title>
2152    <style>
2153        {}
2154    </style>
2155</head>
2156<body>
2157    <div class="container">
2158        <div class="header">
2159            <h1>📊 {}</h1>
2160            <p>Advanced performance analysis with baselines, rankings, and trends</p>
2161        </div>
2162"#,
2163            self.config.title, theme_styles, self.config.title
2164        )
2165    }
2166
2167    /// Generate summary statistics section
2168    fn generate_summary_section(&self, analytics: &PerformanceAnalytics) -> String {
2169        format!(
2170            r#"
2171        <div class="summary">
2172            <div class="summary-card">
2173                <h3>Total Tasks</h3>
2174                <div class="value">{}</div>
2175            </div>
2176            <div class="summary-card">
2177                <h3>Avg CPU Usage</h3>
2178                <div class="value">{:.1}%</div>
2179            </div>
2180            <div class="summary-card">
2181                <h3>Avg Memory</h3>
2182                <div class="value">{:.0}MB</div>
2183            </div>
2184            <div class="summary-card">
2185                <h3>Avg Efficiency</h3>
2186                <div class="value">{:.0}%</div>
2187            </div>
2188        </div>
2189"#,
2190            analytics.total_tasks,
2191            analytics.baselines.avg_cpu_percent,
2192            analytics.baselines.avg_memory_mb,
2193            analytics.baselines.avg_efficiency_score * 100.0
2194        )
2195    }
2196
2197    /// Generate tasks section with cards
2198    fn generate_tasks_section(
2199        &self,
2200        analytics: &PerformanceAnalytics,
2201        profiles: &HashMap<TaskId, TaskResourceProfile>,
2202    ) -> Result<String, VisualizationError> {
2203        let mut html = String::new();
2204
2205        html.push_str(
2206            r#"
2207        <div class="tasks-section">
2208            <h2 class="section-title">Task Performance Details</h2>
2209            <div class="tasks-grid">
2210"#,
2211        );
2212
2213        // Sort tasks by efficiency score
2214        let mut sorted_profiles: Vec<_> = profiles.iter().collect();
2215        sorted_profiles.sort_by(|a, b| {
2216            b.1.efficiency_score
2217                .partial_cmp(&a.1.efficiency_score)
2218                .unwrap_or(std::cmp::Ordering::Equal)
2219        });
2220
2221        for (task_id, profile) in sorted_profiles {
2222            html.push_str(&self.generate_task_card(*task_id, profile, analytics)?);
2223        }
2224
2225        html.push_str(
2226            r#"
2227            </div>
2228        </div>
2229"#,
2230        );
2231
2232        Ok(html)
2233    }
2234
2235    /// Generate individual task card
2236    fn generate_task_card(
2237        &self,
2238        task_id: TaskId,
2239        profile: &TaskResourceProfile,
2240        analytics: &PerformanceAnalytics,
2241    ) -> Result<String, VisualizationError> {
2242        let ranking = analytics.rankings.get(&task_id);
2243        let comparisons = analytics.comparisons.get(&task_id);
2244
2245        let task_type_class = format!("{:?}", profile.task_type).to_lowercase();
2246
2247        let rank_info = if let Some(ranking) = ranking {
2248            let rank_class = match ranking.rank {
2249                1 => "rank-1",
2250                2 => "rank-2",
2251                3 => "rank-3",
2252                _ => "",
2253            };
2254            format!(
2255                r#"<div class="ranking-badge {}">#{}/{}</div>"#,
2256                rank_class, ranking.rank, ranking.total_in_category
2257            )
2258        } else {
2259            String::new()
2260        };
2261
2262        if let Some(comp) = comparisons {
2263            self.generate_comparison_info(comp)
2264        } else {
2265            String::new()
2266        };
2267
2268        let efficiency_tooltip = if self.config.include_efficiency_breakdown {
2269            format!(
2270                r#"
2271                <div class="info-icon">?
2272                    <div class="tooltip">
2273                        <strong>Efficiency Breakdown:</strong><br>
2274                        CPU: {:.1}%<br>
2275                        Memory: {:.1}%<br>
2276                        IO: {:.1}%<br>
2277                        Network: {:.1}%<br>
2278                        Overall: {:.1}%
2279                    </div>
2280                </div>
2281"#,
2282                profile
2283                    .efficiency_explanation
2284                    .component_scores
2285                    .cpu_efficiency
2286                    * 100.0,
2287                profile
2288                    .efficiency_explanation
2289                    .component_scores
2290                    .memory_efficiency
2291                    * 100.0,
2292                profile
2293                    .efficiency_explanation
2294                    .component_scores
2295                    .io_efficiency
2296                    * 100.0,
2297                profile
2298                    .efficiency_explanation
2299                    .component_scores
2300                    .network_efficiency
2301                    * 100.0,
2302                profile.efficiency_score * 100.0
2303            )
2304        } else {
2305            String::new()
2306        };
2307
2308        Ok(format!(
2309            r#"
2310                <div class="task-card">
2311                    {}
2312                    <div class="task-header {}">
2313                        <h3 class="task-name">{}</h3>
2314                        <span class="task-badge {}">{:?}</span>
2315                    </div>
2316                    <div class="task-content">
2317                        <div class="metrics-grid">
2318                            <div class="metric-item">
2319                                <div class="metric-label">CPU Usage</div>
2320                                <div class="metric-value">{:.1}%</div>
2321                                {}
2322                            </div>
2323                            <div class="metric-item">
2324                                <div class="metric-label">Memory</div>
2325                                <div class="metric-value">{:.0}MB</div>
2326                                {}
2327                            </div>
2328                            <div class="metric-item">
2329                                <div class="metric-label">IO Bandwidth</div>
2330                                <div class="metric-value">{:.1}MB/s</div>
2331                                {}
2332                            </div>
2333                            <div class="metric-item">
2334                                <div class="metric-label">Network</div>
2335                                <div class="metric-value">{:.1}Mbps</div>
2336                                {}
2337                            </div>
2338                        </div>
2339                        
2340                        <div class="efficiency-section">
2341                            <div class="efficiency-title">
2342                                Efficiency Score
2343                                {}
2344                            </div>
2345                            <div class="efficiency-bar">
2346                                <div class="efficiency-fill" style="width: {:.1}%"></div>
2347                            </div>
2348                            <div class="efficiency-score">{:.1}%</div>
2349                        </div>
2350                        
2351                        <div class="source-info">
2352                            <div class="source-title">Source Location</div>
2353                            <div class="source-detail">
2354                                <span class="source-label">File:</span>
2355                                <span class="source-value">{}</span>
2356                            </div>
2357                            <div class="source-detail">
2358                                <span class="source-label">Line:</span>
2359                                <span class="source-value">{}</span>
2360                            </div>
2361                            <div class="source-detail">
2362                                <span class="source-label">Function:</span>
2363                                <span class="source-value">{}</span>
2364                            </div>
2365                        </div>
2366                    </div>
2367                </div>
2368"#,
2369            rank_info,
2370            task_type_class,
2371            profile.task_name,
2372            task_type_class,
2373            profile.task_type,
2374            profile.cpu_metrics.usage_percent,
2375            if let Some(comp) = comparisons {
2376                format!(
2377                    "<div class=\"metric-comparison {}\">{}</div>",
2378                    self.get_comparison_class(&comp.cpu),
2379                    self.format_comparison(&comp.cpu)
2380                )
2381            } else {
2382                String::new()
2383            },
2384            profile.memory_metrics.current_bytes as f64 / 1_048_576.0,
2385            if let Some(comp) = comparisons {
2386                format!(
2387                    "<div class=\"metric-comparison {}\">{}</div>",
2388                    self.get_comparison_class(&comp.memory),
2389                    self.format_comparison(&comp.memory)
2390                )
2391            } else {
2392                String::new()
2393            },
2394            profile.io_metrics.bandwidth_mbps,
2395            if let Some(comp) = comparisons {
2396                format!(
2397                    "<div class=\"metric-comparison {}\">{}</div>",
2398                    self.get_comparison_class(&comp.io),
2399                    self.format_comparison(&comp.io)
2400                )
2401            } else {
2402                String::new()
2403            },
2404            profile.network_metrics.throughput_mbps,
2405            if let Some(comp) = comparisons {
2406                format!(
2407                    "<div class=\"metric-comparison {}\">{}</div>",
2408                    self.get_comparison_class(&comp.network),
2409                    self.format_comparison(&comp.network)
2410                )
2411            } else {
2412                String::new()
2413            },
2414            efficiency_tooltip,
2415            profile.efficiency_score * 100.0,
2416            profile.efficiency_score * 100.0,
2417            profile.source_location.file_path,
2418            profile.source_location.line_number,
2419            profile.source_location.function_name
2420        ))
2421    }
2422
2423    /// Generate comparison information display
2424    fn generate_comparison_info(&self, _comparisons: &TaskComparisons) -> String {
2425        // Implementation for comparison display
2426        String::new()
2427    }
2428
2429    /// Format comparison for display
2430    fn format_comparison(&self, comparison: &PerformanceComparison) -> String {
2431        match comparison.comparison_type {
2432            ComparisonType::NearAverage => "(≈ avg)".to_string(),
2433            ComparisonType::AboveAverage => {
2434                format!("(+{:.1}% vs avg)", comparison.difference_percent.abs())
2435            }
2436            ComparisonType::BelowAverage => {
2437                format!("(-{:.1}% vs avg)", comparison.difference_percent.abs())
2438            }
2439        }
2440    }
2441
2442    /// Get CSS class for comparison
2443    fn get_comparison_class(&self, comparison: &PerformanceComparison) -> &'static str {
2444        match comparison.comparison_type {
2445            ComparisonType::NearAverage => "comparison-average",
2446            ComparisonType::AboveAverage => "comparison-above",
2447            ComparisonType::BelowAverage => "comparison-below",
2448        }
2449    }
2450
2451    /// Generate charts section
2452    fn generate_charts_section(
2453        &self,
2454        profiles: &HashMap<TaskId, TaskResourceProfile>,
2455    ) -> Result<String, VisualizationError> {
2456        let mut html = String::new();
2457
2458        html.push_str(
2459            r#"
2460        <div class="charts-section">
2461            <h2 class="section-title">📈 Performance Trends</h2>
2462"#,
2463        );
2464
2465        // Generate simple CSS charts
2466        let chart_html = self.generate_chart_scripts(profiles)?;
2467        html.push_str(&chart_html);
2468
2469        html.push_str(
2470            r#"
2471        </div>
2472"#,
2473        );
2474
2475        Ok(html)
2476    }
2477
2478    /// Build enhanced template data from task profiles with comprehensive Rust async metrics
2479    fn build_template_data(
2480        &self,
2481        profiles: &HashMap<TaskId, TaskResourceProfile>,
2482    ) -> Result<serde_json::Value, VisualizationError> {
2483        if profiles.is_empty() {
2484            return Err(VisualizationError::NoDataAvailable);
2485        }
2486
2487        // Calculate aggregated metrics
2488        let total_tasks = profiles.len();
2489        let cpu_usage_avg = profiles
2490            .values()
2491            .map(|p| p.cpu_metrics.usage_percent)
2492            .sum::<f64>()
2493            / total_tasks as f64;
2494        let cpu_usage_peak = profiles
2495            .values()
2496            .map(|p| p.cpu_metrics.usage_percent)
2497            .fold(0.0f64, |a, b| a.max(b));
2498        let total_memory_mb = profiles
2499            .values()
2500            .map(|p| p.memory_metrics.allocated_bytes as f64 / 1024.0 / 1024.0)
2501            .sum::<f64>();
2502        let peak_memory_mb = profiles
2503            .values()
2504            .map(|p| p.memory_metrics.peak_bytes as f64 / 1024.0 / 1024.0)
2505            .fold(0.0f64, |a, b| a.max(b));
2506
2507        // Enhanced async-specific metrics
2508        let total_context_switches = profiles
2509            .values()
2510            .map(|p| p.cpu_metrics.context_switches)
2511            .sum::<u64>();
2512        let total_allocations = profiles
2513            .values()
2514            .map(|p| p.memory_metrics.allocation_count)
2515            .sum::<u64>();
2516        let avg_efficiency =
2517            profiles.values().map(|p| p.efficiency_score).sum::<f64>() / total_tasks as f64;
2518
2519        // Network and I/O totals
2520        let total_io_ops = profiles
2521            .values()
2522            .map(|p| p.io_metrics.read_operations + p.io_metrics.write_operations)
2523            .sum::<u64>();
2524        let total_read_mb = profiles
2525            .values()
2526            .map(|p| p.io_metrics.bytes_read as f64 / 1024.0 / 1024.0)
2527            .sum::<f64>();
2528        let total_write_mb = profiles
2529            .values()
2530            .map(|p| p.io_metrics.bytes_written as f64 / 1024.0 / 1024.0)
2531            .sum::<f64>();
2532        let io_throughput = if total_tasks > 0 {
2533            (total_read_mb + total_write_mb) / total_tasks as f64
2534        } else {
2535            0.0
2536        };
2537
2538        let total_sent_mb = profiles
2539            .values()
2540            .map(|p| p.network_metrics.bytes_sent as f64 / 1024.0 / 1024.0)
2541            .sum::<f64>();
2542        let total_received_mb = profiles
2543            .values()
2544            .map(|p| p.network_metrics.bytes_received as f64 / 1024.0 / 1024.0)
2545            .sum::<f64>();
2546        let network_throughput = if total_tasks > 0 {
2547            profiles
2548                .values()
2549                .map(|p| p.network_metrics.throughput_mbps)
2550                .sum::<f64>()
2551                / total_tasks as f64
2552        } else {
2553            0.0
2554        };
2555        let avg_latency = if total_tasks > 0 {
2556            profiles
2557                .values()
2558                .map(|p| p.network_metrics.latency_avg_ms)
2559                .sum::<f64>()
2560                / total_tasks as f64
2561        } else {
2562            0.0
2563        };
2564
2565        // Count task types and calculate efficiency by type
2566        let task_type_counts = self.calculate_task_type_metrics(profiles);
2567
2568        // Build categorized task data
2569        let cpu_intensive_tasks =
2570            self.build_task_category_data(profiles, &crate::async_memory::TaskType::CpuIntensive);
2571        let memory_intensive_tasks = self
2572            .build_task_category_data(profiles, &crate::async_memory::TaskType::MemoryIntensive);
2573        let io_intensive_tasks =
2574            self.build_task_category_data(profiles, &crate::async_memory::TaskType::IoIntensive);
2575        let network_intensive_tasks = self
2576            .build_task_category_data(profiles, &crate::async_memory::TaskType::NetworkIntensive);
2577
2578        // Async-specific metrics for Rust
2579        let futures_count = total_tasks; // Each task represents a Future
2580        let total_polls = total_context_switches; // Context switches approximate polling
2581        let avg_poll_time = if total_polls > 0 {
2582            cpu_usage_avg * 10.0
2583        } else {
2584            0.0
2585        }; // Estimated poll time in microseconds
2586        let ready_rate = if total_tasks > 0 {
2587            avg_efficiency * 100.0
2588        } else {
2589            0.0
2590        };
2591
2592        // Build template data in smaller chunks to avoid recursion limit
2593        let mut template_data = serde_json::Map::new();
2594
2595        // Basic info
2596        template_data.insert(
2597            "title".to_string(),
2598            serde_json::Value::String("Rust Async Performance Analysis".to_string()),
2599        );
2600        template_data.insert("subtitle".to_string(), serde_json::Value::String(format!("Advanced analysis of {} Rust async tasks with detailed performance metrics and Future polling insights", total_tasks)));
2601
2602        // Core metrics
2603        template_data.insert(
2604            "total_tasks".to_string(),
2605            serde_json::Value::Number(serde_json::Number::from(total_tasks)),
2606        );
2607        template_data.insert(
2608            "active_tasks".to_string(),
2609            serde_json::Value::Number(serde_json::Number::from(0)),
2610        );
2611        template_data.insert(
2612            "completed_tasks".to_string(),
2613            serde_json::Value::Number(serde_json::Number::from(total_tasks)),
2614        );
2615        template_data.insert(
2616            "failed_tasks".to_string(),
2617            serde_json::Value::Number(serde_json::Number::from(0)),
2618        );
2619
2620        // CPU metrics
2621        template_data.insert(
2622            "cpu_usage_avg".to_string(),
2623            serde_json::Value::String(format!("{:.1}", cpu_usage_avg)),
2624        );
2625        template_data.insert(
2626            "cpu_usage_peak".to_string(),
2627            serde_json::Value::String(format!("{:.1}", cpu_usage_peak)),
2628        );
2629        template_data.insert(
2630            "cpu_cores".to_string(),
2631            serde_json::Value::Number(serde_json::Number::from(8)),
2632        );
2633        template_data.insert(
2634            "context_switches".to_string(),
2635            serde_json::Value::Number(serde_json::Number::from(total_context_switches)),
2636        );
2637
2638        // Memory metrics
2639        template_data.insert(
2640            "total_memory_mb".to_string(),
2641            serde_json::Value::String(format!("{:.1}", total_memory_mb)),
2642        );
2643        template_data.insert(
2644            "peak_memory_mb".to_string(),
2645            serde_json::Value::String(format!("{:.1}", peak_memory_mb)),
2646        );
2647        template_data.insert(
2648            "total_allocations".to_string(),
2649            serde_json::Value::Number(serde_json::Number::from(total_allocations)),
2650        );
2651        template_data.insert(
2652            "memory_efficiency".to_string(),
2653            serde_json::Value::String(format!("{:.1}", avg_efficiency * 100.0)),
2654        );
2655
2656        // I/O metrics
2657        template_data.insert(
2658            "io_throughput".to_string(),
2659            serde_json::Value::String(format!("{:.1}", io_throughput)),
2660        );
2661        template_data.insert(
2662            "total_read_mb".to_string(),
2663            serde_json::Value::String(format!("{:.1}", total_read_mb)),
2664        );
2665        template_data.insert(
2666            "total_write_mb".to_string(),
2667            serde_json::Value::String(format!("{:.1}", total_write_mb)),
2668        );
2669        template_data.insert(
2670            "total_io_ops".to_string(),
2671            serde_json::Value::Number(serde_json::Number::from(total_io_ops)),
2672        );
2673
2674        // Network metrics
2675        template_data.insert(
2676            "network_throughput".to_string(),
2677            serde_json::Value::String(format!("{:.1}", network_throughput)),
2678        );
2679        template_data.insert(
2680            "total_sent_mb".to_string(),
2681            serde_json::Value::String(format!("{:.1}", total_sent_mb)),
2682        );
2683        template_data.insert(
2684            "total_received_mb".to_string(),
2685            serde_json::Value::String(format!("{:.1}", total_received_mb)),
2686        );
2687        template_data.insert(
2688            "avg_latency".to_string(),
2689            serde_json::Value::String(format!("{:.1}", avg_latency)),
2690        );
2691
2692        // Overall efficiency
2693        let resource_balance =
2694            profiles.values().map(|p| p.resource_balance).sum::<f64>() / total_tasks as f64 * 100.0;
2695        let bottleneck_count = profiles
2696            .values()
2697            .filter(|p| {
2698                !matches!(
2699                    p.bottleneck_type,
2700                    crate::async_memory::BottleneckType::Balanced
2701                )
2702            })
2703            .count();
2704
2705        template_data.insert(
2706            "efficiency_score".to_string(),
2707            serde_json::Value::String(format!("{:.1}", avg_efficiency * 100.0)),
2708        );
2709        template_data.insert(
2710            "resource_balance".to_string(),
2711            serde_json::Value::String(format!("{:.1}", resource_balance)),
2712        );
2713        template_data.insert(
2714            "bottleneck_count".to_string(),
2715            serde_json::Value::Number(serde_json::Number::from(bottleneck_count)),
2716        );
2717        template_data.insert(
2718            "optimization_potential".to_string(),
2719            serde_json::Value::String(format!("{:.1}", (1.0 - avg_efficiency) * 100.0)),
2720        );
2721
2722        // Async-specific Rust metrics
2723        template_data.insert(
2724            "futures_count".to_string(),
2725            serde_json::Value::Number(serde_json::Number::from(futures_count)),
2726        );
2727        template_data.insert(
2728            "total_polls".to_string(),
2729            serde_json::Value::Number(serde_json::Number::from(total_polls)),
2730        );
2731        template_data.insert(
2732            "avg_poll_time".to_string(),
2733            serde_json::Value::String(format!("{:.1}", avg_poll_time)),
2734        );
2735        template_data.insert(
2736            "ready_rate".to_string(),
2737            serde_json::Value::String(format!("{:.1}", ready_rate)),
2738        );
2739
2740        // Task type counts and efficiency
2741        template_data.insert(
2742            "cpu_intensive_count".to_string(),
2743            serde_json::Value::Number(serde_json::Number::from(task_type_counts.cpu_count)),
2744        );
2745        template_data.insert(
2746            "cpu_avg_efficiency".to_string(),
2747            serde_json::Value::String(format!("{:.1}", task_type_counts.cpu_efficiency)),
2748        );
2749        template_data.insert(
2750            "memory_intensive_count".to_string(),
2751            serde_json::Value::Number(serde_json::Number::from(task_type_counts.memory_count)),
2752        );
2753        template_data.insert(
2754            "memory_avg_efficiency".to_string(),
2755            serde_json::Value::String(format!("{:.1}", task_type_counts.memory_efficiency)),
2756        );
2757        template_data.insert(
2758            "io_intensive_count".to_string(),
2759            serde_json::Value::Number(serde_json::Number::from(task_type_counts.io_count)),
2760        );
2761        template_data.insert(
2762            "io_avg_efficiency".to_string(),
2763            serde_json::Value::String(format!("{:.1}", task_type_counts.io_efficiency)),
2764        );
2765        template_data.insert(
2766            "network_intensive_count".to_string(),
2767            serde_json::Value::Number(serde_json::Number::from(task_type_counts.network_count)),
2768        );
2769        template_data.insert(
2770            "network_avg_efficiency".to_string(),
2771            serde_json::Value::String(format!("{:.1}", task_type_counts.network_efficiency)),
2772        );
2773
2774        // Categorized task data
2775        template_data.insert(
2776            "cpu_intensive_tasks".to_string(),
2777            serde_json::Value::Array(cpu_intensive_tasks),
2778        );
2779        template_data.insert(
2780            "memory_intensive_tasks".to_string(),
2781            serde_json::Value::Array(memory_intensive_tasks),
2782        );
2783        template_data.insert(
2784            "io_intensive_tasks".to_string(),
2785            serde_json::Value::Array(io_intensive_tasks),
2786        );
2787        template_data.insert(
2788            "network_intensive_tasks".to_string(),
2789            serde_json::Value::Array(network_intensive_tasks),
2790        );
2791
2792        // Advanced analytics data
2793        let avg_fragmentation = profiles
2794            .values()
2795            .map(|p| p.memory_metrics.heap_fragmentation)
2796            .sum::<f64>()
2797            / total_tasks as f64
2798            * 100.0;
2799        let blocking_tasks_count = profiles
2800            .values()
2801            .filter(|p| p.cpu_metrics.usage_percent > 80.0)
2802            .count();
2803
2804        template_data.insert(
2805            "avg_poll_duration".to_string(),
2806            serde_json::Value::String(format!("{:.1}", avg_poll_time)),
2807        );
2808        template_data.insert(
2809            "immediate_ready_percent".to_string(),
2810            serde_json::Value::String(format!("{:.1}", ready_rate * 0.8)),
2811        );
2812        template_data.insert(
2813            "waker_efficiency".to_string(),
2814            serde_json::Value::String(format!("{:.1}", avg_efficiency * 95.0)),
2815        );
2816        template_data.insert(
2817            "peak_alloc_rate".to_string(),
2818            serde_json::Value::String(format!("{}", total_allocations / total_tasks as u64)),
2819        );
2820        template_data.insert(
2821            "avg_fragmentation".to_string(),
2822            serde_json::Value::String(format!("{:.1}", avg_fragmentation)),
2823        );
2824        template_data.insert(
2825            "gc_pressure".to_string(),
2826            serde_json::Value::String(format!("{:.1}", (1.0 - avg_efficiency) * 50.0)),
2827        );
2828        template_data.insert(
2829            "executor_utilization".to_string(),
2830            serde_json::Value::String(format!("{:.1}", cpu_usage_avg * 0.8)),
2831        );
2832        template_data.insert(
2833            "avg_queue_length".to_string(),
2834            serde_json::Value::String(format!("{:.1}", total_tasks as f64 * 0.1)),
2835        );
2836        template_data.insert(
2837            "blocking_tasks_count".to_string(),
2838            serde_json::Value::Number(serde_json::Number::from(blocking_tasks_count)),
2839        );
2840        template_data.insert(
2841            "deadlock_risk".to_string(),
2842            serde_json::Value::String(format!(
2843                "{:.1}",
2844                if total_tasks > 10 {
2845                    total_tasks as f64 * 0.05
2846                } else {
2847                    0.0
2848                }
2849            )),
2850        );
2851
2852        let template_data = serde_json::Value::Object(template_data);
2853
2854        Ok(template_data)
2855    }
2856
2857    /// Calculate task type metrics and efficiency (legacy method for compatibility)
2858    fn calculate_task_type_metrics(
2859        &self,
2860        profiles: &HashMap<TaskId, TaskResourceProfile>,
2861    ) -> TaskTypeMetrics {
2862        let mut cpu_count = 0;
2863        let mut cpu_efficiency_sum = 0.0;
2864        let mut memory_count = 0;
2865        let mut memory_efficiency_sum = 0.0;
2866        let mut io_count = 0;
2867        let mut io_efficiency_sum = 0.0;
2868        let mut network_count = 0;
2869        let mut network_efficiency_sum = 0.0;
2870
2871        for profile in profiles.values() {
2872            match profile.task_type {
2873                crate::async_memory::TaskType::CpuIntensive => {
2874                    cpu_count += 1;
2875                    cpu_efficiency_sum += profile.efficiency_score;
2876                }
2877                crate::async_memory::TaskType::MemoryIntensive => {
2878                    memory_count += 1;
2879                    memory_efficiency_sum += profile.efficiency_score;
2880                }
2881                crate::async_memory::TaskType::IoIntensive => {
2882                    io_count += 1;
2883                    io_efficiency_sum += profile.efficiency_score;
2884                }
2885                crate::async_memory::TaskType::NetworkIntensive => {
2886                    network_count += 1;
2887                    network_efficiency_sum += profile.efficiency_score;
2888                }
2889                _ => {} // Handle other types as needed
2890            }
2891        }
2892
2893        TaskTypeMetrics {
2894            cpu_count,
2895            cpu_efficiency: if cpu_count > 0 {
2896                cpu_efficiency_sum / cpu_count as f64 * 100.0
2897            } else {
2898                0.0
2899            },
2900            memory_count,
2901            memory_efficiency: if memory_count > 0 {
2902                memory_efficiency_sum / memory_count as f64 * 100.0
2903            } else {
2904                0.0
2905            },
2906            io_count,
2907            io_efficiency: if io_count > 0 {
2908                io_efficiency_sum / io_count as f64 * 100.0
2909            } else {
2910                0.0
2911            },
2912            network_count,
2913            network_efficiency: if network_count > 0 {
2914                network_efficiency_sum / network_count as f64 * 100.0
2915            } else {
2916                0.0
2917            },
2918        }
2919    }
2920
2921    /// Build task data for specific category
2922    fn build_task_category_data(
2923        &self,
2924        profiles: &HashMap<TaskId, TaskResourceProfile>,
2925        task_type: &crate::async_memory::TaskType,
2926    ) -> Vec<serde_json::Value> {
2927        profiles
2928            .iter()
2929            .filter(|(_, profile)| {
2930                std::mem::discriminant(&profile.task_type) == std::mem::discriminant(task_type)
2931            })
2932            .map(|(task_id, profile)| {
2933                let mut task_data = serde_json::Map::new();
2934
2935                // Basic task info
2936                task_data.insert(
2937                    "task_id".to_string(),
2938                    serde_json::Value::String(task_id.to_string()),
2939                );
2940                task_data.insert(
2941                    "task_name".to_string(),
2942                    serde_json::Value::String(profile.task_name.clone()),
2943                );
2944                task_data.insert(
2945                    "source_file".to_string(),
2946                    serde_json::Value::String(
2947                        profile
2948                            .source_location
2949                            .file_path
2950                            .split('/')
2951                            .next_back()
2952                            .unwrap_or("unknown.rs")
2953                            .to_string(),
2954                    ),
2955                );
2956                task_data.insert(
2957                    "source_line".to_string(),
2958                    serde_json::Value::Number(serde_json::Number::from(
2959                        profile.source_location.line_number,
2960                    )),
2961                );
2962                task_data.insert(
2963                    "status".to_string(),
2964                    serde_json::Value::String("completed".to_string()),
2965                );
2966                task_data.insert(
2967                    "status_class".to_string(),
2968                    serde_json::Value::String("completed".to_string()),
2969                );
2970                task_data.insert(
2971                    "duration_ms".to_string(),
2972                    serde_json::Value::Number(
2973                        serde_json::Number::from_f64(profile.duration_ms.unwrap_or(0.0))
2974                            .unwrap_or(serde_json::Number::from(0)),
2975                    ),
2976                );
2977
2978                // CPU-specific metrics
2979                task_data.insert(
2980                    "cpu_usage".to_string(),
2981                    serde_json::Value::String(format!("{:.1}", profile.cpu_metrics.usage_percent)),
2982                );
2983                task_data.insert(
2984                    "cpu_cycles".to_string(),
2985                    serde_json::Value::String(format!(
2986                        "{:.1}",
2987                        profile.cpu_metrics.cpu_cycles as f64 / 1_000_000.0
2988                    )),
2989                );
2990                task_data.insert(
2991                    "instructions".to_string(),
2992                    serde_json::Value::String(format!(
2993                        "{:.1}",
2994                        profile.cpu_metrics.instructions as f64 / 1_000_000.0
2995                    )),
2996                );
2997                task_data.insert(
2998                    "cache_misses".to_string(),
2999                    serde_json::Value::String(format!(
3000                        "{:.1}",
3001                        profile.cpu_metrics.cache_misses as f64 / 1_000.0
3002                    )),
3003                );
3004
3005                // Memory-specific metrics
3006                task_data.insert(
3007                    "allocated_mb".to_string(),
3008                    serde_json::Value::String(format!(
3009                        "{:.1}",
3010                        profile.memory_metrics.allocated_bytes as f64 / 1024.0 / 1024.0
3011                    )),
3012                );
3013                task_data.insert(
3014                    "peak_memory_mb".to_string(),
3015                    serde_json::Value::String(format!(
3016                        "{:.1}",
3017                        profile.memory_metrics.peak_bytes as f64 / 1024.0 / 1024.0
3018                    )),
3019                );
3020                task_data.insert(
3021                    "allocation_count".to_string(),
3022                    serde_json::Value::Number(serde_json::Number::from(
3023                        profile.memory_metrics.allocation_count,
3024                    )),
3025                );
3026                task_data.insert(
3027                    "heap_fragmentation".to_string(),
3028                    serde_json::Value::String(format!(
3029                        "{:.1}",
3030                        profile.memory_metrics.heap_fragmentation * 100.0
3031                    )),
3032                );
3033                task_data.insert(
3034                    "memory_usage_percent".to_string(),
3035                    serde_json::Value::String(format!(
3036                        "{:.1}",
3037                        (profile.memory_metrics.current_bytes as f64
3038                            / profile.memory_metrics.allocated_bytes.max(1) as f64)
3039                            * 100.0
3040                    )),
3041                );
3042
3043                // I/O-specific metrics
3044                task_data.insert(
3045                    "bytes_read_mb".to_string(),
3046                    serde_json::Value::String(format!(
3047                        "{:.1}",
3048                        profile.io_metrics.bytes_read as f64 / 1024.0 / 1024.0
3049                    )),
3050                );
3051                task_data.insert(
3052                    "bytes_written_mb".to_string(),
3053                    serde_json::Value::String(format!(
3054                        "{:.1}",
3055                        profile.io_metrics.bytes_written as f64 / 1024.0 / 1024.0
3056                    )),
3057                );
3058                task_data.insert(
3059                    "avg_latency_us".to_string(),
3060                    serde_json::Value::String(format!("{:.1}", profile.io_metrics.avg_latency_us)),
3061                );
3062                task_data.insert(
3063                    "queue_depth".to_string(),
3064                    serde_json::Value::Number(serde_json::Number::from(
3065                        profile.io_metrics.queue_depth,
3066                    )),
3067                );
3068                task_data.insert(
3069                    "io_usage_percent".to_string(),
3070                    serde_json::Value::String(format!("{:.1}", profile.io_metrics.io_wait_percent)),
3071                );
3072
3073                // Network-specific metrics
3074                task_data.insert(
3075                    "bytes_sent_mb".to_string(),
3076                    serde_json::Value::String(format!(
3077                        "{:.1}",
3078                        profile.network_metrics.bytes_sent as f64 / 1024.0 / 1024.0
3079                    )),
3080                );
3081                task_data.insert(
3082                    "bytes_received_mb".to_string(),
3083                    serde_json::Value::String(format!(
3084                        "{:.1}",
3085                        profile.network_metrics.bytes_received as f64 / 1024.0 / 1024.0
3086                    )),
3087                );
3088                task_data.insert(
3089                    "active_connections".to_string(),
3090                    serde_json::Value::Number(serde_json::Number::from(
3091                        profile.network_metrics.connections_active,
3092                    )),
3093                );
3094                task_data.insert(
3095                    "avg_latency_ms".to_string(),
3096                    serde_json::Value::String(format!(
3097                        "{:.1}",
3098                        profile.network_metrics.latency_avg_ms
3099                    )),
3100                );
3101                task_data.insert(
3102                    "network_usage_percent".to_string(),
3103                    serde_json::Value::String(format!(
3104                        "{:.1}",
3105                        (profile.network_metrics.throughput_mbps / 100.0).min(100.0)
3106                    )),
3107                );
3108
3109                serde_json::Value::Object(task_data)
3110            })
3111            .collect()
3112    }
3113
3114    /// Generate simple CSS charts (no JavaScript)
3115    fn generate_chart_scripts(
3116        &self,
3117        profiles: &HashMap<TaskId, TaskResourceProfile>,
3118    ) -> Result<String, VisualizationError> {
3119        let mut cpu_bars = String::new();
3120        let mut memory_bars = String::new();
3121
3122        // Find max values for scaling
3123        let max_cpu = profiles
3124            .values()
3125            .map(|p| p.cpu_metrics.usage_percent)
3126            .fold(0.0, f64::max)
3127            .max(100.0);
3128        let max_memory = profiles
3129            .values()
3130            .map(|p| p.memory_metrics.current_bytes as f64 / 1_048_576.0)
3131            .fold(0.0, f64::max);
3132
3133        for profile in profiles.values() {
3134            let cpu_percent = profile.cpu_metrics.usage_percent;
3135            let memory_mb = profile.memory_metrics.current_bytes as f64 / 1_048_576.0;
3136
3137            let cpu_width = (cpu_percent / max_cpu * 100.0).min(100.0);
3138            let memory_width = if max_memory > 0.0 {
3139                (memory_mb / max_memory * 100.0).min(100.0)
3140            } else {
3141                0.0
3142            };
3143
3144            cpu_bars.push_str(&format!(
3145                r#"
3146                <div class="chart-bar">
3147                    <div class="bar-label">{}</div>
3148                    <div class="bar-container">
3149                        <div class="bar-fill cpu-bar" style="width: {:.1}%"></div>
3150                        <div class="bar-value">{:.1}%</div>
3151                    </div>
3152                </div>
3153"#,
3154                profile.task_name, cpu_width, cpu_percent
3155            ));
3156
3157            memory_bars.push_str(&format!(
3158                r#"
3159                <div class="chart-bar">
3160                    <div class="bar-label">{}</div>
3161                    <div class="bar-container">
3162                        <div class="bar-fill memory-bar" style="width: {:.1}%"></div>
3163                        <div class="bar-value">{:.1}MB</div>
3164                    </div>
3165                </div>
3166"#,
3167                profile.task_name, memory_width, memory_mb
3168            ));
3169        }
3170
3171        // Generate network bars
3172        let mut network_bars = String::new();
3173        let max_network = profiles
3174            .values()
3175            .map(|p| p.network_metrics.throughput_mbps)
3176            .fold(0.0, f64::max);
3177
3178        for profile in profiles.values() {
3179            let network_mbps = profile.network_metrics.throughput_mbps;
3180            let network_width = if max_network > 0.0 {
3181                (network_mbps / max_network * 100.0).min(100.0)
3182            } else {
3183                0.0
3184            };
3185
3186            network_bars.push_str(&format!(
3187                r#"
3188                <div class="chart-bar">
3189                    <div class="bar-label">{}</div>
3190                    <div class="bar-container">
3191                        <div class="bar-fill network-bar" style="width: {:.1}%"></div>
3192                        <div class="bar-value">{:.1}Mbps</div>
3193                    </div>
3194                </div>
3195"#,
3196                profile.task_name, network_width, network_mbps
3197            ));
3198        }
3199
3200        Ok(format!(
3201            r#"
3202        <div class="simple-charts">
3203            <div class="simple-chart">
3204                <h4>CPU Usage Distribution</h4>
3205                <div class="chart-bars">
3206                    {}
3207                </div>
3208            </div>
3209            <div class="simple-chart">
3210                <h4>Memory Usage Distribution</h4>
3211                <div class="chart-bars">
3212                    {}
3213                </div>
3214            </div>
3215            <div class="simple-chart">
3216                <h4>Network Throughput Distribution</h4>
3217                <div class="chart-bars">
3218                    {}
3219                </div>
3220            </div>
3221        </div>
3222"#,
3223            cpu_bars, memory_bars, network_bars
3224        ))
3225    }
3226
3227    /// Generate HTML footer
3228    fn generate_html_footer(&self) -> String {
3229        r#"
3230    </div>
3231</body>
3232</html>
3233"#
3234        .to_string()
3235    }
3236
3237    /// Get dark theme CSS styles
3238    fn get_dark_theme_styles(&self) -> &'static str {
3239        r#"
3240        body {
3241            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
3242            margin: 0;
3243            padding: 20px;
3244            background: #0d1117;
3245            color: #f0f6fc;
3246            line-height: 1.6;
3247        }
3248        
3249        .container {
3250            max-width: 1400px;
3251            margin: 0 auto;
3252            background: #161b22;
3253            border: 1px solid #30363d;
3254            border-radius: 12px;
3255            overflow: hidden;
3256        }
3257        
3258        .header {
3259            background: linear-gradient(135deg, #58a6ff 0%, #a5a5ff 100%);
3260            padding: 2rem;
3261            text-align: center;
3262            color: white;
3263        }
3264        
3265        .header h1 {
3266            margin: 0;
3267            font-size: 2.5rem;
3268            font-weight: 700;
3269        }
3270        
3271        .summary {
3272            display: grid;
3273            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
3274            gap: 1.5rem;
3275            padding: 2rem;
3276            background: #21262d;
3277        }
3278        
3279        .summary-card {
3280            background: #161b22;
3281            border: 1px solid #30363d;
3282            padding: 1.5rem;
3283            border-radius: 8px;
3284            text-align: center;
3285        }
3286        
3287        .summary-card h3 {
3288            margin: 0 0 0.5rem 0;
3289            color: #8b949e;
3290            font-size: 0.9rem;
3291            text-transform: uppercase;
3292        }
3293        
3294        .summary-card .value {
3295            font-size: 2rem;
3296            font-weight: 700;
3297            color: #58a6ff;
3298        }
3299        
3300        .tasks-section {
3301            padding: 2rem;
3302        }
3303        
3304        .section-title {
3305            margin: 0 0 2rem 0;
3306            font-size: 1.5rem;
3307            font-weight: 600;
3308            color: #f0f6fc;
3309            text-align: center;
3310        }
3311        
3312        .tasks-grid {
3313            display: grid;
3314            grid-template-columns: repeat(auto-fill, minmax(450px, 1fr));
3315            gap: 1.5rem;
3316        }
3317        
3318        .task-card {
3319            background: #21262d;
3320            border: 1px solid #30363d;
3321            border-radius: 10px;
3322            overflow: hidden;
3323            transition: transform 0.2s ease;
3324            position: relative;
3325        }
3326        
3327        .task-card:hover {
3328            transform: translateY(-2px);
3329            box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
3330        }
3331        
3332        .ranking-badge {
3333            position: absolute;
3334            top: 10px;
3335            right: 10px;
3336            background: linear-gradient(135deg, #f9c513, #ffd700);
3337            color: #000;
3338            padding: 0.25rem 0.5rem;
3339            border-radius: 12px;
3340            font-size: 0.7rem;
3341            font-weight: 700;
3342            z-index: 10;
3343        }
3344        
3345        .ranking-badge.rank-1 { background: linear-gradient(135deg, #ffd700, #ffed4e); }
3346        .ranking-badge.rank-2 { background: linear-gradient(135deg, #c0c0c0, #e8e8e8); }
3347        .ranking-badge.rank-3 { background: linear-gradient(135deg, #cd7f32, #daa520); }
3348        
3349        .task-header {
3350            padding: 1.5rem;
3351            background: #161b22;
3352            border-bottom: 1px solid #30363d;
3353            position: relative;
3354        }
3355        
3356        .task-header::before {
3357            content: '';
3358            position: absolute;
3359            top: 0;
3360            left: 0;
3361            right: 0;
3362            height: 3px;
3363        }
3364        
3365        .task-header.cpuintensive::before { background: #f85149; }
3366        .task-header.iointensive::before { background: #58a6ff; }
3367        .task-header.networkintensive::before { background: #3fb950; }
3368        .task-header.memoryintensive::before { background: #a5a5ff; }
3369        .task-header.mixed::before { background: #f9c513; }
3370        
3371        .task-name {
3372            margin: 0 0 0.5rem 0;
3373            font-size: 1.125rem;
3374            font-weight: 600;
3375            color: #f0f6fc;
3376        }
3377        
3378        .task-badge {
3379            display: inline-block;
3380            padding: 0.25rem 0.75rem;
3381            border-radius: 12px;
3382            font-size: 0.75rem;
3383            font-weight: 600;
3384            text-transform: uppercase;
3385        }
3386        
3387        .task-badge.cpuintensive { background: #f85149; color: white; }
3388        .task-badge.iointensive { background: #58a6ff; color: white; }
3389        .task-badge.networkintensive { background: #3fb950; color: white; }
3390        .task-badge.memoryintensive { background: #a5a5ff; color: white; }
3391        .task-badge.mixed { background: #f9c513; color: black; }
3392        
3393        .task-content {
3394            padding: 1.5rem;
3395        }
3396        
3397        .metrics-grid {
3398            display: grid;
3399            grid-template-columns: 1fr 1fr;
3400            gap: 1rem;
3401            margin-bottom: 1rem;
3402        }
3403        
3404        .metric-item {
3405            background: #161b22;
3406            border: 1px solid #30363d;
3407            border-radius: 6px;
3408            padding: 1rem;
3409            text-align: center;
3410        }
3411        
3412        .metric-label {
3413            font-size: 0.75rem;
3414            color: #8b949e;
3415            margin-bottom: 0.25rem;
3416            text-transform: uppercase;
3417        }
3418        
3419        .metric-value {
3420            font-size: 1.25rem;
3421            font-weight: 700;
3422            color: #f0f6fc;
3423        }
3424        
3425        .metric-comparison {
3426            font-size: 0.7rem;
3427            margin-top: 0.25rem;
3428        }
3429        
3430        .comparison-above { color: #f85149; }
3431        .comparison-below { color: #3fb950; }
3432        .comparison-average { color: #f9c513; }
3433        
3434        .efficiency-section {
3435            background: #161b22;
3436            border: 1px solid #30363d;
3437            border-radius: 6px;
3438            padding: 1rem;
3439            margin-top: 1rem;
3440        }
3441        
3442        .efficiency-title {
3443            font-size: 0.875rem;
3444            color: #8b949e;
3445            margin-bottom: 0.5rem;
3446            text-transform: uppercase;
3447            display: flex;
3448            align-items: center;
3449            gap: 0.5rem;
3450        }
3451        
3452        .info-icon {
3453            cursor: help;
3454            background: #30363d;
3455            color: #8b949e;
3456            border-radius: 50%;
3457            width: 16px;
3458            height: 16px;
3459            display: flex;
3460            align-items: center;
3461            justify-content: center;
3462            font-size: 0.7rem;
3463            font-weight: bold;
3464            position: relative;
3465        }
3466        
3467        .info-icon:hover {
3468            background: #58a6ff;
3469            color: white;
3470        }
3471        
3472        .tooltip {
3473            position: absolute;
3474            bottom: 100%;
3475            right: 0;
3476            background: #161b22;
3477            border: 1px solid #30363d;
3478            border-radius: 6px;
3479            padding: 0.75rem;
3480            min-width: 200px;
3481            font-size: 0.8rem;
3482            color: #f0f6fc;
3483            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
3484            z-index: 1000;
3485            opacity: 0;
3486            visibility: hidden;
3487            transition: opacity 0.3s ease;
3488        }
3489        
3490        .info-icon:hover .tooltip {
3491            opacity: 1;
3492            visibility: visible;
3493        }
3494        
3495        .efficiency-bar {
3496            width: 100%;
3497            height: 8px;
3498            background: #30363d;
3499            border-radius: 4px;
3500            overflow: hidden;
3501            margin-bottom: 0.5rem;
3502        }
3503        
3504        .efficiency-fill {
3505            height: 100%;
3506            background: linear-gradient(90deg, #3fb950, #f9c513, #f85149);
3507            border-radius: 4px;
3508        }
3509        
3510        .efficiency-score {
3511            font-size: 1rem;
3512            font-weight: 700;
3513            color: #58a6ff;
3514            text-align: right;
3515        }
3516        
3517        .source-info {
3518            background: #161b22;
3519            border: 1px solid #30363d;
3520            border-radius: 6px;
3521            padding: 1rem;
3522            margin-top: 1rem;
3523        }
3524        
3525        .source-title {
3526            font-size: 0.875rem;
3527            color: #8b949e;
3528            margin-bottom: 0.5rem;
3529            text-transform: uppercase;
3530        }
3531        
3532        .source-detail {
3533            display: flex;
3534            justify-content: space-between;
3535            margin-bottom: 0.25rem;
3536            font-size: 0.8rem;
3537        }
3538        
3539        .source-label {
3540            color: #8b949e;
3541        }
3542        
3543        .source-value {
3544            color: #f0f6fc;
3545            font-family: 'Courier New', monospace;
3546        }
3547        
3548        .charts-section {
3549            padding: 2rem;
3550            background: #161b22;
3551            border-top: 1px solid #30363d;
3552        }
3553        
3554        .charts-grid {
3555            display: grid;
3556            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
3557            gap: 2rem;
3558            margin-top: 1.5rem;
3559        }
3560        
3561        .chart-container {
3562            background: #21262d;
3563            border: 1px solid #30363d;
3564            border-radius: 8px;
3565            padding: 1.5rem;
3566        }
3567        
3568        .chart-title {
3569            margin: 0 0 1rem 0;
3570            font-size: 1rem;
3571            font-weight: 600;
3572            color: #f0f6fc;
3573            text-align: center;
3574        }
3575        
3576        /* Simple CSS Charts */
3577        .simple-charts {
3578            display: grid;
3579            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
3580            gap: 2rem;
3581            padding: 2rem;
3582        }
3583        
3584        .simple-chart {
3585            background: #21262d;
3586            border: 1px solid #30363d;
3587            border-radius: 8px;
3588            padding: 1.5rem;
3589        }
3590        
3591        .simple-chart h4 {
3592            margin: 0 0 1rem 0;
3593            font-size: 1rem;
3594            font-weight: 600;
3595            color: #f0f6fc;
3596            text-align: center;
3597        }
3598        
3599        .chart-bars {
3600            display: flex;
3601            flex-direction: column;
3602            gap: 0.75rem;
3603        }
3604        
3605        .chart-bar {
3606            display: flex;
3607            align-items: center;
3608            gap: 1rem;
3609        }
3610        
3611        .bar-label {
3612            min-width: 120px;
3613            font-size: 0.8rem;
3614            color: #8b949e;
3615            text-align: right;
3616        }
3617        
3618        .bar-container {
3619            flex: 1;
3620            display: flex;
3621            align-items: center;
3622            gap: 0.5rem;
3623            position: relative;
3624        }
3625        
3626        .bar-fill {
3627            height: 20px;
3628            border-radius: 4px;
3629            transition: width 0.6s ease;
3630            position: relative;
3631        }
3632        
3633        .cpu-bar {
3634            background: linear-gradient(90deg, #f85149, #ff6b6b);
3635        }
3636        
3637        .memory-bar {
3638            background: linear-gradient(90deg, #a5a5ff, #b39ddb);
3639        }
3640        
3641        .network-bar {
3642            background: linear-gradient(90deg, #3fb950, #a5d6a7);
3643        }
3644        
3645        .bar-value {
3646            font-size: 0.8rem;
3647            color: #f0f6fc;
3648            font-weight: 600;
3649            min-width: 50px;
3650        }
3651        
3652        @media (max-width: 1024px) {
3653            .simple-charts {
3654                grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
3655            }
3656            
3657            .bar-label {
3658                min-width: 100px;
3659                font-size: 0.75rem;
3660            }
3661        }
3662        
3663        @media (max-width: 768px) {
3664            .tasks-grid {
3665                grid-template-columns: 1fr;
3666            }
3667            .metrics-grid {
3668                grid-template-columns: 1fr;
3669            }
3670        }
3671        "#
3672    }
3673
3674    /// Get light theme CSS styles
3675    fn get_light_theme_styles(&self) -> &'static str {
3676        r#"
3677        body {
3678            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
3679            margin: 0;
3680            padding: 20px;
3681            background: #ffffff;
3682            color: #24292f;
3683            line-height: 1.6;
3684        }
3685        
3686        .container {
3687            max-width: 1400px;
3688            margin: 0 auto;
3689            background: #f6f8fa;
3690            border: 1px solid #d0d7de;
3691            border-radius: 12px;
3692            overflow: hidden;
3693        }
3694        
3695        .header {
3696            background: linear-gradient(135deg, #0969da 0%, #8250df 100%);
3697            padding: 2rem;
3698            text-align: center;
3699            color: white;
3700        }
3701        
3702        .summary {
3703            display: grid;
3704            grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
3705            gap: 1.5rem;
3706            padding: 2rem;
3707            background: #ffffff;
3708        }
3709        
3710        .summary-card {
3711            background: #f6f8fa;
3712            border: 1px solid #d0d7de;
3713            padding: 1.5rem;
3714            border-radius: 8px;
3715            text-align: center;
3716        }
3717        
3718        .task-card {
3719            background: #ffffff;
3720            border: 1px solid #d0d7de;
3721            border-radius: 10px;
3722            overflow: hidden;
3723            transition: transform 0.2s ease;
3724            position: relative;
3725        }
3726        
3727        .task-card:hover {
3728            transform: translateY(-2px);
3729            box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1);
3730        }
3731        
3732        /* Add more light theme styles as needed */
3733        "#
3734    }
3735}
3736
3737#[cfg(test)]
3738mod tests {
3739    use super::*;
3740    use crate::async_memory::resource_monitor::{
3741        BottleneckType, ComponentScores, CpuMetrics, CriticalPathAnalysis, EfficiencyExplanation,
3742        HotMetrics, IoMetrics, MemoryMetrics, NetworkMetrics, SourceLocation, TaskResourceProfile,
3743        TaskType,
3744    };
3745
3746    /// Helper function to create a test task profile
3747    fn create_test_profile(
3748        task_name: &str,
3749        task_type: TaskType,
3750        cpu_usage: f64,
3751        memory_bytes: u64,
3752        efficiency: f64,
3753    ) -> TaskResourceProfile {
3754        TaskResourceProfile {
3755            task_id: 1u128,
3756            task_name: task_name.to_string(),
3757            task_type,
3758            start_time: 1000,
3759            end_time: Some(2000),
3760            duration_ms: Some(1000.0),
3761            cpu_metrics: CpuMetrics {
3762                usage_percent: cpu_usage,
3763                time_user_ms: 100.0,
3764                time_kernel_ms: 50.0,
3765                context_switches: 10,
3766                cpu_cycles: 1000000,
3767                instructions: 500000,
3768                cache_misses: 100,
3769                branch_misses: 50,
3770                core_affinity: vec![0],
3771            },
3772            memory_metrics: MemoryMetrics {
3773                allocated_bytes: memory_bytes,
3774                peak_bytes: memory_bytes + 1024,
3775                current_bytes: memory_bytes,
3776                allocation_count: 5,
3777                deallocation_count: 3,
3778                page_faults: 10,
3779                heap_fragmentation: 0.1,
3780                memory_bandwidth_mbps: 1000.0,
3781            },
3782            io_metrics: IoMetrics {
3783                bytes_read: 1024,
3784                bytes_written: 512,
3785                read_operations: 10,
3786                write_operations: 5,
3787                sync_operations: 3,
3788                async_operations: 12,
3789                avg_latency_us: 100.0,
3790                bandwidth_mbps: 10.0,
3791                queue_depth: 4,
3792                io_wait_percent: 5.0,
3793            },
3794            network_metrics: NetworkMetrics {
3795                bytes_sent: 2048,
3796                bytes_received: 1536,
3797                packets_sent: 100,
3798                packets_received: 95,
3799                connections_active: 5,
3800                connections_established: 10,
3801                connection_errors: 1,
3802                latency_avg_ms: 10.0,
3803                throughput_mbps: 5.0,
3804                retransmissions: 2,
3805            },
3806            gpu_metrics: None,
3807            efficiency_score: efficiency,
3808            resource_balance: 0.8,
3809            bottleneck_type: BottleneckType::Balanced,
3810            source_location: SourceLocation {
3811                file_path: "test.rs".to_string(),
3812                line_number: 42,
3813                function_name: "test_function".to_string(),
3814                module_path: "test::module".to_string(),
3815                crate_name: "test_crate".to_string(),
3816            },
3817            hot_metrics: HotMetrics {
3818                cpu_hotspots: vec![],
3819                memory_hotspots: vec![],
3820                io_hotspots: vec![],
3821                network_hotspots: vec![],
3822                critical_path_analysis: CriticalPathAnalysis {
3823                    total_execution_time_ms: 1000.0,
3824                    critical_path_time_ms: 800.0,
3825                    parallelization_potential: 0.5,
3826                    blocking_operations: vec![],
3827                },
3828            },
3829            efficiency_explanation: EfficiencyExplanation {
3830                overall_score: efficiency,
3831                component_scores: ComponentScores {
3832                    cpu_efficiency: efficiency,
3833                    memory_efficiency: efficiency,
3834                    io_efficiency: efficiency,
3835                    network_efficiency: efficiency,
3836                    resource_balance: 0.8,
3837                },
3838                recommendations: vec![],
3839                bottleneck_analysis: "No bottlenecks detected".to_string(),
3840                optimization_potential: 0.2,
3841            },
3842        }
3843    }
3844
3845    #[test]
3846    fn test_visualization_config_default() {
3847        let config = VisualizationConfig::default();
3848
3849        assert_eq!(config.title, "Async Task Performance Analysis");
3850        assert!(matches!(config.theme, Theme::Dark));
3851        assert!(config.include_charts);
3852        assert!(config.include_baselines);
3853        assert!(config.include_rankings);
3854        assert!(config.include_efficiency_breakdown);
3855    }
3856
3857    #[test]
3858    fn test_visualization_generator_new() {
3859        let generator = VisualizationGenerator::new();
3860        assert_eq!(generator.config.title, "Async Task Performance Analysis");
3861    }
3862
3863    #[test]
3864    fn test_visualization_generator_with_config() {
3865        let custom_config = VisualizationConfig {
3866            title: "Custom Analysis".to_string(),
3867            theme: Theme::Light,
3868            include_charts: false,
3869            include_baselines: false,
3870            include_rankings: false,
3871            include_efficiency_breakdown: false,
3872        };
3873
3874        let generator = VisualizationGenerator::with_config(custom_config.clone());
3875        assert_eq!(generator.config.title, "Custom Analysis");
3876        assert!(matches!(generator.config.theme, Theme::Light));
3877        assert!(!generator.config.include_charts);
3878    }
3879
3880    #[test]
3881    fn test_calculate_baselines() {
3882        let generator = VisualizationGenerator::new();
3883        let mut profiles = HashMap::new();
3884
3885        profiles.insert(
3886            1u128,
3887            create_test_profile("task1", TaskType::CpuIntensive, 50.0, 1024 * 1024, 0.8),
3888        );
3889        profiles.insert(
3890            2u128,
3891            create_test_profile("task2", TaskType::IoIntensive, 30.0, 2048 * 1024, 0.6),
3892        );
3893
3894        let baselines = generator.calculate_baselines(&profiles);
3895
3896        assert_eq!(baselines.avg_cpu_percent, 40.0);
3897        assert_eq!(baselines.avg_memory_mb, 1.5);
3898        assert_eq!(baselines.avg_io_mbps, 10.0);
3899        assert_eq!(baselines.avg_network_mbps, 5.0);
3900        assert_eq!(baselines.avg_efficiency_score, 0.7);
3901    }
3902
3903    #[test]
3904    fn test_calculate_rankings() {
3905        let generator = VisualizationGenerator::new();
3906        let mut profiles = HashMap::new();
3907
3908        // Create tasks with different efficiency scores in same category
3909        profiles.insert(
3910            1u128,
3911            create_test_profile("task1", TaskType::CpuIntensive, 50.0, 1024 * 1024, 0.9),
3912        );
3913        profiles.insert(
3914            2u128,
3915            create_test_profile("task2", TaskType::CpuIntensive, 30.0, 2048 * 1024, 0.7),
3916        );
3917        profiles.insert(
3918            3u128,
3919            create_test_profile("task3", TaskType::IoIntensive, 20.0, 512 * 1024, 0.8),
3920        );
3921
3922        let rankings = generator.calculate_rankings(&profiles);
3923
3924        // Check CPU intensive tasks ranking
3925        let task1_ranking = rankings.get(&1u128).expect("Task 1 should have ranking");
3926        let task2_ranking = rankings.get(&2u128).expect("Task 2 should have ranking");
3927
3928        assert_eq!(task1_ranking.rank, 1); // Higher efficiency should rank first
3929        assert_eq!(task1_ranking.total_in_category, 2);
3930        assert_eq!(task1_ranking.category_name, "CpuIntensive");
3931
3932        assert_eq!(task2_ranking.rank, 2);
3933        assert_eq!(task2_ranking.total_in_category, 2);
3934
3935        // Check IO intensive task ranking
3936        let task3_ranking = rankings.get(&3u128).expect("Task 3 should have ranking");
3937        assert_eq!(task3_ranking.rank, 1);
3938        assert_eq!(task3_ranking.total_in_category, 1);
3939        assert_eq!(task3_ranking.category_name, "IoIntensive");
3940    }
3941
3942    #[test]
3943    fn test_compare_to_baseline() {
3944        let generator = VisualizationGenerator::new();
3945
3946        // Test above average
3947        let comp = generator.compare_to_baseline(110.0, 100.0);
3948        assert!(matches!(comp.comparison_type, ComparisonType::AboveAverage));
3949        assert_eq!(comp.difference_percent, 10.0);
3950
3951        // Test below average
3952        let comp = generator.compare_to_baseline(90.0, 100.0);
3953        assert!(matches!(comp.comparison_type, ComparisonType::BelowAverage));
3954        assert_eq!(comp.difference_percent, -10.0);
3955
3956        // Test near average
3957        let comp = generator.compare_to_baseline(102.0, 100.0);
3958        assert!(matches!(comp.comparison_type, ComparisonType::NearAverage));
3959        assert_eq!(comp.difference_percent, 2.0);
3960
3961        // Test zero baseline
3962        let comp = generator.compare_to_baseline(50.0, 0.0);
3963        assert_eq!(comp.difference_percent, 0.0);
3964    }
3965
3966    #[test]
3967    fn test_analyze_profiles_empty() {
3968        let generator = VisualizationGenerator::new();
3969        let profiles = HashMap::new();
3970
3971        let result = generator.analyze_profiles(&profiles);
3972        assert!(result.is_err());
3973        assert!(matches!(
3974            result.unwrap_err(),
3975            VisualizationError::NoDataAvailable
3976        ));
3977    }
3978
3979    #[test]
3980    fn test_format_comparison() {
3981        let generator = VisualizationGenerator::new();
3982
3983        let comp_above = PerformanceComparison {
3984            value: 110.0,
3985            baseline: 100.0,
3986            difference_percent: 10.5,
3987            comparison_type: ComparisonType::AboveAverage,
3988        };
3989        assert_eq!(generator.format_comparison(&comp_above), "(+10.5% vs avg)");
3990
3991        let comp_below = PerformanceComparison {
3992            value: 85.0,
3993            baseline: 100.0,
3994            difference_percent: -15.0,
3995            comparison_type: ComparisonType::BelowAverage,
3996        };
3997        assert_eq!(generator.format_comparison(&comp_below), "(-15.0% vs avg)");
3998
3999        let comp_average = PerformanceComparison {
4000            value: 102.0,
4001            baseline: 100.0,
4002            difference_percent: 2.0,
4003            comparison_type: ComparisonType::NearAverage,
4004        };
4005        assert_eq!(generator.format_comparison(&comp_average), "(≈ avg)");
4006    }
4007
4008    #[test]
4009    fn test_get_comparison_class() {
4010        let generator = VisualizationGenerator::new();
4011
4012        let comp_above = PerformanceComparison {
4013            value: 110.0,
4014            baseline: 100.0,
4015            difference_percent: 10.0,
4016            comparison_type: ComparisonType::AboveAverage,
4017        };
4018        assert_eq!(
4019            generator.get_comparison_class(&comp_above),
4020            "comparison-above"
4021        );
4022
4023        let comp_below = PerformanceComparison {
4024            value: 90.0,
4025            baseline: 100.0,
4026            difference_percent: -10.0,
4027            comparison_type: ComparisonType::BelowAverage,
4028        };
4029        assert_eq!(
4030            generator.get_comparison_class(&comp_below),
4031            "comparison-below"
4032        );
4033
4034        let comp_average = PerformanceComparison {
4035            value: 102.0,
4036            baseline: 100.0,
4037            difference_percent: 2.0,
4038            comparison_type: ComparisonType::NearAverage,
4039        };
4040        assert_eq!(
4041            generator.get_comparison_class(&comp_average),
4042            "comparison-average"
4043        );
4044    }
4045
4046    #[test]
4047    fn test_theme_styles() {
4048        let generator = VisualizationGenerator::new();
4049
4050        let dark_styles = generator.get_dark_theme_styles();
4051        assert!(dark_styles.contains("background: #0d1117"));
4052        assert!(dark_styles.contains("color: #f0f6fc"));
4053
4054        let light_styles = generator.get_light_theme_styles();
4055        assert!(light_styles.contains("background: #ffffff"));
4056        assert!(light_styles.contains("color: #24292f"));
4057    }
4058
4059    #[test]
4060    fn test_visualization_error_display() {
4061        let err = VisualizationError::NoDataAvailable;
4062        assert_eq!(format!("{}", err), "No data available for visualization");
4063
4064        let err = VisualizationError::InvalidConfiguration("test error".to_string());
4065        assert_eq!(format!("{}", err), "Invalid configuration: test error");
4066
4067        let err = VisualizationError::TemplateError("template failed".to_string());
4068        assert_eq!(
4069            format!("{}", err),
4070            "Template generation error: template failed"
4071        );
4072    }
4073}