1#![allow(dead_code)]
6
7use crate::environmental_monitor::types::*;
8use anyhow::Result;
9use std::collections::HashMap;
10use std::time::{Duration, SystemTime};
11use tracing::info;
12
13#[derive(Debug)]
15pub struct EnvironmentalReportingEngine {
16 report_templates: HashMap<String, ReportTemplate>,
17 automated_reports: Vec<AutomatedReport>,
18 dashboard_metrics: EnvironmentalDashboardMetrics,
19}
20
21#[derive(Debug, Clone)]
22struct ReportTemplate {
23 template_name: String,
24 sections: Vec<ReportSection>,
25 target_audience: String,
26 frequency: ReportFrequency,
27}
28
29#[derive(Debug, Clone)]
30struct ReportSection {
31 section_name: String,
32 metrics_included: Vec<String>,
33 visualization_type: VisualizationType,
34}
35#[derive(Debug, Clone)]
36pub struct AutomatedReport {
37 report_id: String,
38 generated_at: SystemTime,
39 report_type: String,
40 content: String,
41}
42
43impl EnvironmentalReportingEngine {
44 pub fn new() -> Self {
46 Self {
47 report_templates: Self::initialize_report_templates(),
48 automated_reports: Vec::new(),
49 dashboard_metrics: EnvironmentalDashboardMetrics {
50 total_energy_consumed_kwh: 0.0,
51 total_co2_emissions_kg: 0.0,
52 current_power_usage_watts: 0.0,
53 energy_efficiency_score: 0.0,
54 carbon_intensity_gco2_kwh: 0.0,
55 cost_per_hour_usd: 0.0,
56 trend: TrendDirection::Stable,
57 },
58 }
59 }
60
61 pub async fn generate_environmental_report(
63 &self,
64 report_type: ReportType,
65 ) -> Result<EnvironmentalReport> {
66 info!("Generating environmental impact report: {:?}", report_type);
67
68 let report = match report_type {
69 ReportType::Summary => self.generate_summary_report().await?,
70 ReportType::Detailed => self.generate_detailed_report().await?,
71 ReportType::Technical => self.generate_technical_report().await?,
72 ReportType::Executive => self.generate_executive_report().await?,
73 ReportType::Compliance => self.generate_compliance_report().await?,
74 };
75
76 self.store_automated_report(&report).await?;
78
79 Ok(report)
80 }
81
82 pub async fn generate_daily_report(&self) -> Result<EnvironmentalReport> {
84 let period_start = SystemTime::now() - Duration::from_secs(24 * 3600);
85 let period_end = SystemTime::now();
86
87 Ok(EnvironmentalReport {
88 report_id: format!("daily-{}", chrono::Utc::now().format("%Y%m%d")),
89 report_type: ReportType::Summary,
90 generated_at: SystemTime::now(),
91 period_start,
92 period_end,
93 summary: "Daily environmental impact summary showing energy consumption, carbon emissions, and efficiency metrics".to_string(),
94 metrics: EnvironmentalDashboardMetrics {
95 total_energy_consumed_kwh: 120.5,
96 total_co2_emissions_kg: 48.2,
97 current_power_usage_watts: 750.0,
98 energy_efficiency_score: 0.87,
99 carbon_intensity_gco2_kwh: 400.0,
100 cost_per_hour_usd: 14.46,
101 trend: TrendDirection::Decreasing,
102 },
103 detailed_analysis: "Energy consumption remained within optimal ranges. Peak power usage occurred during training hours (10 AM - 4 PM). Carbon intensity was 12% lower than regional average due to increased renewable energy generation.".to_string(),
104 recommendations: vec![
105 SustainabilityRecommendation {
106 category: RecommendationCategory::Energy,
107 priority: RecommendationPriority::Medium,
108 title: "Schedule training during low-carbon hours".to_string(),
109 description: "Schedule intensive workloads during hours 2-6 AM when carbon intensity is lowest".to_string(),
110 potential_impact: "15% carbon reduction possible".to_string(),
111 implementation_steps: vec![
112 "Analyze workload scheduling patterns".to_string(),
113 "Implement automated scheduling system".to_string(),
114 "Monitor carbon impact improvements".to_string(),
115 ],
116 },
117 SustainabilityRecommendation {
118 category: RecommendationCategory::Performance,
119 priority: RecommendationPriority::Low,
120 title: "Optimize cooling efficiency".to_string(),
121 description: "Implement dynamic cooling adjustments based on workload intensity".to_string(),
122 potential_impact: "8% energy reduction in cooling systems".to_string(),
123 implementation_steps: vec![
124 "Install smart temperature controls".to_string(),
125 "Monitor cooling system efficiency".to_string(),
126 "Adjust cooling based on real-time needs".to_string(),
127 ],
128 },
129 ],
130 charts: vec![
131 ChartData {
132 chart_type: VisualizationType::LineChart,
133 title: "Daily Energy Consumption".to_string(),
134 data_points: vec![
135 ("00:00".to_string(), 45.2),
136 ("06:00".to_string(), 52.1),
137 ("12:00".to_string(), 78.9),
138 ("18:00".to_string(), 65.3),
139 ],
140 labels: vec!["Time".to_string(), "kWh".to_string()],
141 },
142 ChartData {
143 chart_type: VisualizationType::BarChart,
144 title: "Carbon Emissions by Activity".to_string(),
145 data_points: vec![
146 ("Training".to_string(), 32.1),
147 ("Inference".to_string(), 12.8),
148 ("Data Processing".to_string(), 3.3),
149 ],
150 labels: vec!["Activity".to_string(), "kg CO2".to_string()],
151 },
152 ],
153 })
154 }
155
156 pub async fn generate_weekly_report(&self) -> Result<EnvironmentalReport> {
158 let period_start = SystemTime::now() - Duration::from_secs(7 * 24 * 3600);
159 let period_end = SystemTime::now();
160
161 Ok(EnvironmentalReport {
162 report_id: format!("weekly-{}", chrono::Utc::now().format("%Y-W%W")),
163 report_type: ReportType::Summary,
164 generated_at: SystemTime::now(),
165 period_start,
166 period_end,
167 summary: "Weekly environmental impact analysis showing trends and optimization opportunities".to_string(),
168 metrics: EnvironmentalDashboardMetrics {
169 total_energy_consumed_kwh: 843.5,
170 total_co2_emissions_kg: 337.4,
171 current_power_usage_watts: 750.0,
172 energy_efficiency_score: 0.85,
173 carbon_intensity_gco2_kwh: 400.0,
174 cost_per_hour_usd: 101.22,
175 trend: TrendDirection::Decreasing,
176 },
177 detailed_analysis: "Week-over-week improvements: 12% reduction in carbon emissions, 5% improvement in energy efficiency. Training workloads showed 18% better utilization due to batch size optimization.".to_string(),
178 recommendations: vec![
179 SustainabilityRecommendation {
180 category: RecommendationCategory::Sustainability,
181 priority: RecommendationPriority::High,
182 title: "Implement weekly optimization schedule".to_string(),
183 description: "Create recurring optimization cycles to maintain improvement momentum".to_string(),
184 potential_impact: "Sustained 10-15% efficiency improvements".to_string(),
185 implementation_steps: vec![
186 "Schedule weekly efficiency audits".to_string(),
187 "Automate optimization recommendations".to_string(),
188 "Track improvement metrics consistently".to_string(),
189 ],
190 },
191 ],
192 charts: vec![
193 ChartData {
194 chart_type: VisualizationType::LineChart,
195 title: "Weekly Energy Efficiency Trend".to_string(),
196 data_points: vec![
197 ("Week 1".to_string(), 0.80),
198 ("Week 2".to_string(), 0.82),
199 ("Week 3".to_string(), 0.85),
200 ("Week 4".to_string(), 0.85),
201 ],
202 labels: vec!["Week".to_string(), "Efficiency Score".to_string()],
203 },
204 ],
205 })
206 }
207
208 pub async fn generate_monthly_report(&self) -> Result<EnvironmentalReport> {
210 let period_start = SystemTime::now() - Duration::from_secs(30 * 24 * 3600);
211 let period_end = SystemTime::now();
212
213 Ok(EnvironmentalReport {
214 report_id: format!("monthly-{}", chrono::Utc::now().format("%Y-%m")),
215 report_type: ReportType::Detailed,
216 generated_at: SystemTime::now(),
217 period_start,
218 period_end,
219 summary: "Monthly comprehensive analysis of environmental impact, goal progress, and strategic recommendations".to_string(),
220 metrics: EnvironmentalDashboardMetrics {
221 total_energy_consumed_kwh: 3674.2,
222 total_co2_emissions_kg: 1469.7,
223 current_power_usage_watts: 750.0,
224 energy_efficiency_score: 0.83,
225 carbon_intensity_gco2_kwh: 400.0,
226 cost_per_hour_usd: 440.90,
227 trend: TrendDirection::Decreasing,
228 },
229 detailed_analysis: "Monthly highlights: Achieved 65% progress on carbon reduction goal. Cost savings of $127 from optimization initiatives. Implemented 3 of 5 planned efficiency improvements. Regional carbon intensity averaged 15% below baseline.".to_string(),
230 recommendations: vec![
231 SustainabilityRecommendation {
232 category: RecommendationCategory::Performance,
233 priority: RecommendationPriority::High,
234 title: "Focus on model efficiency optimization".to_string(),
235 description: "Prioritize architectural improvements for next month's optimization cycle".to_string(),
236 potential_impact: "20-30% efficiency improvement potential".to_string(),
237 implementation_steps: vec![
238 "Audit current model architectures".to_string(),
239 "Implement pruning and quantization".to_string(),
240 "Measure performance impact".to_string(),
241 "Scale successful optimizations".to_string(),
242 ],
243 },
244 SustainabilityRecommendation {
245 category: RecommendationCategory::Sustainability,
246 priority: RecommendationPriority::Medium,
247 title: "Consider renewable energy procurement".to_string(),
248 description: "Investigate renewable energy contracts for next quarter".to_string(),
249 potential_impact: "40-60% carbon footprint reduction".to_string(),
250 implementation_steps: vec![
251 "Research renewable energy providers".to_string(),
252 "Analyze cost-benefit of renewable contracts".to_string(),
253 "Negotiate renewable energy agreements".to_string(),
254 "Plan transition timeline".to_string(),
255 ],
256 },
257 ],
258 charts: vec![
259 ChartData {
260 chart_type: VisualizationType::LineChart,
261 title: "Monthly Carbon Emissions Trend".to_string(),
262 data_points: vec![
263 ("Week 1".to_string(), 415.2),
264 ("Week 2".to_string(), 380.1),
265 ("Week 3".to_string(), 342.7),
266 ("Week 4".to_string(), 331.7),
267 ],
268 labels: vec!["Week".to_string(), "kg CO2".to_string()],
269 },
270 ChartData {
271 chart_type: VisualizationType::PieChart,
272 title: "Energy Usage by Activity Type".to_string(),
273 data_points: vec![
274 ("Training".to_string(), 2574.0),
275 ("Inference".to_string(), 735.0),
276 ("Data Processing".to_string(), 220.0),
277 ("Development".to_string(), 145.2),
278 ],
279 labels: vec!["Activity".to_string(), "kWh".to_string()],
280 },
281 ],
282 })
283 }
284
285 pub async fn generate_annual_report(&self) -> Result<EnvironmentalReport> {
287 let period_start = SystemTime::now() - Duration::from_secs(365 * 24 * 3600);
288 let period_end = SystemTime::now();
289
290 Ok(EnvironmentalReport {
291 report_id: format!("annual-{}", chrono::Utc::now().format("%Y")),
292 report_type: ReportType::Executive,
293 generated_at: SystemTime::now(),
294 period_start,
295 period_end,
296 summary: "Annual environmental impact summary with strategic insights and long-term sustainability planning".to_string(),
297 metrics: EnvironmentalDashboardMetrics {
298 total_energy_consumed_kwh: 45000.0,
299 total_co2_emissions_kg: 18000.0,
300 current_power_usage_watts: 750.0,
301 energy_efficiency_score: 0.81,
302 carbon_intensity_gco2_kwh: 400.0,
303 cost_per_hour_usd: 5400.0,
304 trend: TrendDirection::Decreasing,
305 },
306 detailed_analysis: "Annual achievements: 18 tonnes CO2 total footprint (equivalent to 41,580 car miles). Implemented sustainability program with 35% efficiency improvement over baseline. Achieved ISO 14001 preliminary compliance. Established carbon offset program covering 60% of emissions.".to_string(),
307 recommendations: vec![
308 SustainabilityRecommendation {
309 category: RecommendationCategory::Sustainability,
310 priority: RecommendationPriority::Critical,
311 title: "Implement comprehensive carbon reduction strategy".to_string(),
312 description: "Develop multi-year carbon neutrality roadmap with specific milestones".to_string(),
313 potential_impact: "Path to carbon neutrality by 2027".to_string(),
314 implementation_steps: vec![
315 "Set science-based carbon reduction targets".to_string(),
316 "Invest in renewable energy infrastructure".to_string(),
317 "Implement advanced carbon accounting".to_string(),
318 "Establish carbon offset verification program".to_string(),
319 ],
320 },
321 SustainabilityRecommendation {
322 category: RecommendationCategory::Performance,
323 priority: RecommendationPriority::High,
324 title: "Invest in next-generation efficient hardware".to_string(),
325 description: "Plan hardware refresh cycle with focus on energy-efficient compute".to_string(),
326 potential_impact: "30-40% efficiency improvement over current hardware".to_string(),
327 implementation_steps: vec![
328 "Evaluate next-generation GPU efficiency".to_string(),
329 "Plan phased hardware upgrade strategy".to_string(),
330 "Implement hardware efficiency monitoring".to_string(),
331 "Track ROI of efficiency investments".to_string(),
332 ],
333 },
334 ],
335 charts: vec![
336 ChartData {
337 chart_type: VisualizationType::LineChart,
338 title: "Annual Carbon Footprint Progress".to_string(),
339 data_points: vec![
340 ("Q1".to_string(), 5200.0),
341 ("Q2".to_string(), 4800.0),
342 ("Q3".to_string(), 4200.0),
343 ("Q4".to_string(), 3800.0),
344 ],
345 labels: vec!["Quarter".to_string(), "kg CO2".to_string()],
346 },
347 ChartData {
348 chart_type: VisualizationType::Gauge,
349 title: "Sustainability Goals Progress".to_string(),
350 data_points: vec![
351 ("Carbon Reduction".to_string(), 72.0),
352 ("Energy Efficiency".to_string(), 65.0),
353 ("Renewable Energy".to_string(), 45.0),
354 ("Waste Reduction".to_string(), 58.0),
355 ],
356 labels: vec!["Goal".to_string(), "Progress %".to_string()],
357 },
358 ],
359 })
360 }
361
362 async fn generate_summary_report(&self) -> Result<EnvironmentalReport> {
364 self.generate_daily_report().await
365 }
366
367 async fn generate_detailed_report(&self) -> Result<EnvironmentalReport> {
368 self.generate_monthly_report().await
369 }
370
371 async fn generate_technical_report(&self) -> Result<EnvironmentalReport> {
372 let mut report = self.generate_monthly_report().await?;
373 report.report_type = ReportType::Technical;
374
375 report.detailed_analysis = format!(
377 "{}\n\nTechnical Details:\n\
378 - Average GPU utilization: 84.2%\n\
379 - Memory bandwidth efficiency: 76.8%\n\
380 - Compute intensity: 12.4 FLOPS/Watt\n\
381 - Cooling system PUE: 1.18\n\
382 - Network energy overhead: 3.2%\n\
383 - Storage system efficiency: 89.1%",
384 report.detailed_analysis
385 );
386
387 report.charts.push(ChartData {
389 chart_type: VisualizationType::Heatmap,
390 title: "Hardware Utilization Matrix".to_string(),
391 data_points: vec![
392 ("GPU-0".to_string(), 85.2),
393 ("GPU-1".to_string(), 82.7),
394 ("CPU-0".to_string(), 45.3),
395 ("Memory".to_string(), 67.8),
396 ],
397 labels: vec!["Component".to_string(), "Utilization %".to_string()],
398 });
399
400 Ok(report)
401 }
402
403 async fn generate_executive_report(&self) -> Result<EnvironmentalReport> {
404 let mut report = self.generate_monthly_report().await?;
405 report.report_type = ReportType::Executive;
406
407 report.summary = "Executive Summary: Monthly environmental performance shows strong progress toward sustainability goals with measurable business benefits including cost reduction and operational efficiency gains.".to_string();
409
410 report.detailed_analysis = "Key Business Impacts:\n\
411 • $127 monthly cost savings from efficiency optimization\n\
412 • 15% reduction in operational energy costs\n\
413 • Improved compliance posture for environmental regulations\n\
414 • Enhanced corporate sustainability credentials\n\
415 • Risk mitigation for carbon pricing exposure\n\n\
416 Strategic Recommendations:\n\
417 • Accelerate renewable energy procurement timeline\n\
418 • Invest in efficiency monitoring infrastructure\n\
419 • Establish formal sustainability governance structure"
420 .to_string();
421
422 Ok(report)
423 }
424
425 async fn generate_compliance_report(&self) -> Result<EnvironmentalReport> {
426 let mut report = self.generate_monthly_report().await?;
427 report.report_type = ReportType::Compliance;
428
429 report.summary = "Environmental Compliance Report: Assessment of current compliance status against environmental regulations and certification requirements.".to_string();
431
432 report.detailed_analysis = "Compliance Status:\n\
433 • ISO 14001: 65% compliance (target: 100%)\n\
434 • Energy Star: 45% compliance (target: 80%)\n\
435 • Carbon Trust Standard: 30% compliance (target: 90%)\n\
436 • Regional emissions reporting: Fully compliant\n\
437 • Energy efficiency disclosure: Fully compliant\n\n\
438 Required Actions:\n\
439 • Implement formal environmental management system\n\
440 • Establish third-party verification processes\n\
441 • Develop comprehensive carbon accounting system\n\
442 • Create audit trail for all environmental metrics"
443 .to_string();
444
445 report.recommendations.push(SustainabilityRecommendation {
447 category: RecommendationCategory::Sustainability,
448 priority: RecommendationPriority::Critical,
449 title: "Accelerate compliance program implementation".to_string(),
450 description: "Fast-track environmental management system implementation to meet regulatory requirements".to_string(),
451 potential_impact: "Full regulatory compliance within 6 months".to_string(),
452 implementation_steps: vec![
453 "Engage environmental compliance consultant".to_string(),
454 "Implement formal environmental management system".to_string(),
455 "Establish third-party verification processes".to_string(),
456 "Schedule compliance audits".to_string(),
457 ],
458 });
459
460 Ok(report)
461 }
462
463 async fn store_automated_report(&self, report: &EnvironmentalReport) -> Result<()> {
465 let automated_report = AutomatedReport {
466 report_id: report.report_id.clone(),
467 generated_at: report.generated_at,
468 report_type: format!("{:?}", report.report_type),
469 content: format!("{}\n\n{}", report.summary, report.detailed_analysis),
470 };
471
472 info!("Stored automated report: {}", automated_report.report_id);
474 Ok(())
475 }
476
477 pub fn update_dashboard_metrics(&mut self, metrics: EnvironmentalDashboardMetrics) {
479 self.dashboard_metrics = metrics;
480 }
481
482 pub fn get_dashboard_metrics(&self) -> &EnvironmentalDashboardMetrics {
484 &self.dashboard_metrics
485 }
486
487 pub fn get_automated_reports(&self) -> &[AutomatedReport] {
489 &self.automated_reports
490 }
491
492 fn initialize_report_templates() -> HashMap<String, ReportTemplate> {
494 let mut templates = HashMap::new();
495
496 templates.insert(
497 "daily_summary".to_string(),
498 ReportTemplate {
499 template_name: "Daily Environmental Summary".to_string(),
500 target_audience: "Operations Team".to_string(),
501 frequency: ReportFrequency::Daily,
502 sections: vec![
503 ReportSection {
504 section_name: "Energy Consumption".to_string(),
505 metrics_included: vec![
506 "total_energy_kwh".to_string(),
507 "peak_power".to_string(),
508 ],
509 visualization_type: VisualizationType::LineChart,
510 },
511 ReportSection {
512 section_name: "Carbon Emissions".to_string(),
513 metrics_included: vec![
514 "total_co2_kg".to_string(),
515 "carbon_intensity".to_string(),
516 ],
517 visualization_type: VisualizationType::BarChart,
518 },
519 ],
520 },
521 );
522
523 templates.insert(
524 "executive_monthly".to_string(),
525 ReportTemplate {
526 template_name: "Executive Monthly Report".to_string(),
527 target_audience: "Executive Leadership".to_string(),
528 frequency: ReportFrequency::Monthly,
529 sections: vec![
530 ReportSection {
531 section_name: "Strategic Metrics".to_string(),
532 metrics_included: vec![
533 "sustainability_score".to_string(),
534 "cost_savings".to_string(),
535 ],
536 visualization_type: VisualizationType::Gauge,
537 },
538 ReportSection {
539 section_name: "Goal Progress".to_string(),
540 metrics_included: vec![
541 "carbon_goal_progress".to_string(),
542 "efficiency_goal_progress".to_string(),
543 ],
544 visualization_type: VisualizationType::Table,
545 },
546 ],
547 },
548 );
549
550 templates
551 }
552
553 pub async fn generate_custom_report(&self, period: Duration) -> Result<EnvironmentalReport> {
555 let period_start = SystemTime::now() - period;
556 let period_end = SystemTime::now();
557
558 Ok(EnvironmentalReport {
559 report_id: format!("custom-{}", chrono::Utc::now().format("%Y%m%d-%H%M")),
560 report_type: ReportType::Summary,
561 generated_at: SystemTime::now(),
562 period_start,
563 period_end,
564 summary: format!("Custom period environmental analysis covering {:.1} days",
565 period.as_secs_f64() / (24.0 * 3600.0)),
566 metrics: self.dashboard_metrics.clone(),
567 detailed_analysis: "Custom period analysis showing environmental metrics and trends for the specified timeframe".to_string(),
568 recommendations: vec![
569 SustainabilityRecommendation {
570 category: RecommendationCategory::Performance,
571 priority: RecommendationPriority::Medium,
572 title: "Continue monitoring trends".to_string(),
573 description: "Maintain current monitoring practices and look for optimization opportunities".to_string(),
574 potential_impact: "Ongoing efficiency improvements".to_string(),
575 implementation_steps: vec![
576 "Review custom period insights".to_string(),
577 "Identify actionable optimization opportunities".to_string(),
578 "Plan implementation of improvements".to_string(),
579 ],
580 },
581 ],
582 charts: vec![
583 ChartData {
584 chart_type: VisualizationType::LineChart,
585 title: "Custom Period Energy Trend".to_string(),
586 data_points: vec![
587 ("Start".to_string(), 100.0),
588 ("Mid".to_string(), 95.5),
589 ("End".to_string(), 88.2),
590 ],
591 labels: vec!["Time".to_string(), "Energy".to_string()],
592 },
593 ],
594 })
595 }
596}
597
598#[cfg(test)]
599mod tests {
600 use super::*;
601
602 #[test]
603 fn test_reporting_engine_creation() {
604 let engine = EnvironmentalReportingEngine::new();
605 assert!(!engine.report_templates.is_empty());
606 }
607
608 #[tokio::test]
609 async fn test_daily_report_generation() {
610 let engine = EnvironmentalReportingEngine::new();
611 let report = engine.generate_daily_report().await.expect("async operation failed");
612
613 assert!(!report.report_id.is_empty());
614 assert!(!report.summary.is_empty());
615 assert!(!report.recommendations.is_empty());
616 assert!(!report.charts.is_empty());
617 }
618
619 #[tokio::test]
620 async fn test_all_report_types() {
621 let engine = EnvironmentalReportingEngine::new();
622
623 let summary_report = engine
624 .generate_environmental_report(ReportType::Summary)
625 .await
626 .expect("async operation failed");
627 let detailed_report = engine
628 .generate_environmental_report(ReportType::Detailed)
629 .await
630 .expect("async operation failed");
631 let technical_report = engine
632 .generate_environmental_report(ReportType::Technical)
633 .await
634 .expect("async operation failed");
635 let executive_report = engine
636 .generate_environmental_report(ReportType::Executive)
637 .await
638 .expect("async operation failed");
639 let compliance_report = engine
640 .generate_environmental_report(ReportType::Compliance)
641 .await
642 .expect("async operation failed");
643
644 assert_eq!(summary_report.report_type, ReportType::Summary);
645 assert_eq!(detailed_report.report_type, ReportType::Detailed);
646 assert_eq!(technical_report.report_type, ReportType::Technical);
647 assert_eq!(executive_report.report_type, ReportType::Executive);
648 assert_eq!(compliance_report.report_type, ReportType::Compliance);
649 }
650
651 #[tokio::test]
652 async fn test_custom_report_generation() {
653 let engine = EnvironmentalReportingEngine::new();
654 let custom_period = Duration::from_secs(7 * 24 * 3600); let report = engine
657 .generate_custom_report(custom_period)
658 .await
659 .expect("async operation failed");
660
661 assert!(report.summary.contains("7.0 days"));
662 assert!(!report.charts.is_empty());
663 }
664
665 #[test]
666 fn test_dashboard_metrics_update() {
667 let mut engine = EnvironmentalReportingEngine::new();
668
669 let new_metrics = EnvironmentalDashboardMetrics {
670 total_energy_consumed_kwh: 250.0,
671 total_co2_emissions_kg: 100.0,
672 current_power_usage_watts: 800.0,
673 energy_efficiency_score: 0.9,
674 carbon_intensity_gco2_kwh: 350.0,
675 cost_per_hour_usd: 15.0,
676 trend: TrendDirection::Decreasing,
677 };
678
679 engine.update_dashboard_metrics(new_metrics.clone());
680
681 let updated_metrics = engine.get_dashboard_metrics();
682 assert_eq!(updated_metrics.total_energy_consumed_kwh, 250.0);
683 assert_eq!(updated_metrics.energy_efficiency_score, 0.9);
684 }
685
686 #[tokio::test]
687 async fn test_report_content_quality() {
688 let engine = EnvironmentalReportingEngine::new();
689 let report = engine.generate_monthly_report().await.expect("async operation failed");
690
691 assert!(report.summary.len() > 50);
693 assert!(report.detailed_analysis.len() > 100);
694 assert!(!report.recommendations.is_empty());
695
696 for rec in &report.recommendations {
698 assert!(!rec.title.is_empty());
699 assert!(!rec.description.is_empty());
700 assert!(!rec.implementation_steps.is_empty());
701 }
702
703 for chart in &report.charts {
705 assert!(!chart.title.is_empty());
706 assert!(!chart.data_points.is_empty());
707 assert!(!chart.labels.is_empty());
708 }
709 }
710}