1use crate::{application::ApplicationResult, domain::value_objects::Priority};
7
8#[derive(Debug)]
10pub struct OptimizationService {
11 default_strategy: OptimizationStrategy,
12 custom_strategies: std::collections::HashMap<String, OptimizationStrategy>,
13}
14
15#[derive(Debug, Clone, PartialEq)]
17pub enum StreamingUseCase {
18 RealTimeDashboard,
20 BulkDataTransfer,
22 MobileApp,
24 ProgressiveWebApp,
26 IoTDevice,
28 LiveStreaming,
30 Custom(String),
32}
33
34#[derive(Debug, Clone)]
36pub struct OptimizationStrategy {
37 pub priority_threshold: Priority,
38 pub max_frame_size: usize,
39 pub batch_size: usize,
40 pub compression_enabled: bool,
41 pub adaptive_quality: bool,
42 pub description: String,
43 pub target_latency_ms: f64,
44 pub target_throughput_mbps: f64,
45}
46
47#[derive(Debug, Clone)]
49pub struct UseCaseOptimizationResult {
50 pub use_case: StreamingUseCase,
51 pub strategy_applied: OptimizationStrategy,
52 pub frames_generated: Vec<crate::domain::entities::Frame>,
53 pub optimization_metrics: OptimizationMetrics,
54}
55
56#[derive(Debug, Clone)]
58pub struct OptimizationMetrics {
59 pub efficiency_score: f64,
60 pub latency_improvement: f64,
61 pub throughput_improvement: f64,
62 pub resource_utilization: f64,
63 pub quality_score: f64,
64}
65
66impl OptimizationService {
67 pub fn new() -> Self {
68 Self {
69 default_strategy: Self::create_balanced_strategy(),
70 custom_strategies: std::collections::HashMap::new(),
71 }
72 }
73
74 pub fn get_strategy_for_use_case(
76 &self,
77 use_case: &StreamingUseCase,
78 ) -> ApplicationResult<OptimizationStrategy> {
79 match use_case {
80 StreamingUseCase::RealTimeDashboard => Ok(Self::create_realtime_dashboard_strategy()),
81 StreamingUseCase::BulkDataTransfer => Ok(Self::create_bulk_transfer_strategy()),
82 StreamingUseCase::MobileApp => Ok(Self::create_mobile_app_strategy()),
83 StreamingUseCase::ProgressiveWebApp => Ok(Self::create_pwa_strategy()),
84 StreamingUseCase::IoTDevice => Ok(Self::create_iot_device_strategy()),
85 StreamingUseCase::LiveStreaming => Ok(Self::create_live_streaming_strategy()),
86 StreamingUseCase::Custom(name) => {
87 self.custom_strategies.get(name).cloned().ok_or_else(|| {
88 crate::application::ApplicationError::Logic(format!(
89 "Custom strategy '{name}' not found"
90 ))
91 })
92 }
93 }
94 }
95
96 pub fn register_custom_strategy(
98 &mut self,
99 name: String,
100 strategy: OptimizationStrategy,
101 ) -> ApplicationResult<()> {
102 self.custom_strategies.insert(name, strategy);
103 Ok(())
104 }
105
106 pub fn optimize_strategy_for_context(
108 &self,
109 base_strategy: OptimizationStrategy,
110 context: &crate::application::services::prioritization_service::PerformanceContext,
111 ) -> ApplicationResult<OptimizationStrategy> {
112 let mut optimized = base_strategy;
113
114 if context.error_rate > 0.05 {
116 optimized.priority_threshold = optimized.priority_threshold.increase_by(20);
117 } else if context.error_rate < 0.01 && context.average_latency_ms < 100.0 {
118 optimized.priority_threshold = optimized.priority_threshold.decrease_by(10);
119 }
120
121 if context.average_latency_ms > 1000.0 {
123 optimized.batch_size = (optimized.batch_size as f64 * 0.7) as usize;
124 } else if context.average_latency_ms < 100.0 && context.available_bandwidth_mbps > 10.0 {
125 optimized.batch_size = (optimized.batch_size as f64 * 1.3) as usize;
126 }
127
128 if context.available_bandwidth_mbps < 2.0 {
130 optimized.max_frame_size = (optimized.max_frame_size as f64 * 0.8) as usize;
131 } else if context.available_bandwidth_mbps > 20.0 {
132 optimized.max_frame_size = (optimized.max_frame_size as f64 * 1.2) as usize;
133 }
134
135 if context.available_bandwidth_mbps < 5.0 {
137 optimized.compression_enabled = true;
138 }
139
140 if context.cpu_usage > 0.8 {
142 optimized.adaptive_quality = false; }
144
145 Ok(optimized)
146 }
147
148 pub fn calculate_optimization_metrics(
150 &self,
151 strategy: &OptimizationStrategy,
152 frames: &[crate::domain::entities::Frame],
153 context: &crate::application::services::prioritization_service::PerformanceContext,
154 ) -> ApplicationResult<OptimizationMetrics> {
155 let efficiency_score = self.calculate_efficiency_score(frames, strategy);
157
158 let latency_improvement = self.estimate_latency_improvement(strategy, context);
160
161 let throughput_improvement = self.estimate_throughput_improvement(strategy, context);
163
164 let resource_utilization = self.calculate_resource_utilization(strategy, context);
166
167 let quality_score = self.calculate_quality_score(frames, strategy);
169
170 Ok(OptimizationMetrics {
171 efficiency_score,
172 latency_improvement,
173 throughput_improvement,
174 resource_utilization,
175 quality_score,
176 })
177 }
178
179 pub fn recommend_strategy_adjustments(
181 &self,
182 current_strategy: &OptimizationStrategy,
183 performance_report: &crate::application::services::performance_analysis_service::PerformanceAnalysisReport,
184 ) -> ApplicationResult<Vec<StrategyAdjustmentRecommendation>> {
185 let mut recommendations = Vec::new();
186
187 if performance_report.latency_analysis.average > current_strategy.target_latency_ms * 1.5 {
189 recommendations.push(StrategyAdjustmentRecommendation {
190 adjustment_type: AdjustmentType::PriorityIncrease,
191 description: "Increase priority threshold to reduce latency".to_string(),
192 expected_impact: "Reduce latency by 20-40%".to_string(),
193 confidence: 0.8,
194 urgency: AdjustmentUrgency::High,
195 });
196 }
197
198 if performance_report.throughput_analysis.average_mbps
200 < current_strategy.target_throughput_mbps * 0.7
201 {
202 recommendations.push(StrategyAdjustmentRecommendation {
203 adjustment_type: AdjustmentType::BatchSizeIncrease,
204 description: "Increase batch size to improve throughput".to_string(),
205 expected_impact: "Improve throughput by 15-30%".to_string(),
206 confidence: 0.7,
207 urgency: AdjustmentUrgency::Medium,
208 });
209 }
210
211 if performance_report.error_analysis.error_rate > 0.05 {
213 recommendations.push(StrategyAdjustmentRecommendation {
214 adjustment_type: AdjustmentType::QualityReduction,
215 description: "Enable adaptive quality to reduce errors".to_string(),
216 expected_impact: "Reduce error rate by 30-50%".to_string(),
217 confidence: 0.9,
218 urgency: AdjustmentUrgency::High,
219 });
220 }
221
222 if performance_report.resource_analysis.current_cpu_usage > 0.8 {
224 recommendations.push(StrategyAdjustmentRecommendation {
225 adjustment_type: AdjustmentType::CompressionDisable,
226 description: "Disable compression to reduce CPU load".to_string(),
227 expected_impact: "Reduce CPU usage by 10-20%".to_string(),
228 confidence: 0.8,
229 urgency: AdjustmentUrgency::Medium,
230 });
231 }
232
233 Ok(recommendations)
234 }
235
236 fn create_realtime_dashboard_strategy() -> OptimizationStrategy {
239 OptimizationStrategy {
240 priority_threshold: Priority::HIGH,
241 max_frame_size: 16 * 1024, batch_size: 5,
243 compression_enabled: false, adaptive_quality: true,
245 description: "Optimized for real-time dashboard updates with minimal latency"
246 .to_string(),
247 target_latency_ms: 100.0,
248 target_throughput_mbps: 5.0,
249 }
250 }
251
252 fn create_bulk_transfer_strategy() -> OptimizationStrategy {
253 OptimizationStrategy {
254 priority_threshold: Priority::MEDIUM,
255 max_frame_size: 256 * 1024, batch_size: 20,
257 compression_enabled: true,
258 adaptive_quality: false, description: "Optimized for bulk data transfer with maximum throughput".to_string(),
260 target_latency_ms: 1000.0,
261 target_throughput_mbps: 50.0,
262 }
263 }
264
265 fn create_mobile_app_strategy() -> OptimizationStrategy {
266 OptimizationStrategy {
267 priority_threshold: Priority::HIGH,
268 max_frame_size: 8 * 1024, batch_size: 3,
270 compression_enabled: true, adaptive_quality: true,
272 description: "Optimized for mobile network constraints and battery life".to_string(),
273 target_latency_ms: 300.0,
274 target_throughput_mbps: 2.0,
275 }
276 }
277
278 fn create_pwa_strategy() -> OptimizationStrategy {
279 OptimizationStrategy {
280 priority_threshold: Priority::CRITICAL,
281 max_frame_size: 32 * 1024, batch_size: 8,
283 compression_enabled: true,
284 adaptive_quality: true,
285 description: "Optimized for progressive web app user experience".to_string(),
286 target_latency_ms: 200.0,
287 target_throughput_mbps: 10.0,
288 }
289 }
290
291 fn create_iot_device_strategy() -> OptimizationStrategy {
292 OptimizationStrategy {
293 priority_threshold: Priority::CRITICAL,
294 max_frame_size: 4 * 1024, batch_size: 2,
296 compression_enabled: true, adaptive_quality: false, description: "Optimized for IoT devices with power and bandwidth constraints"
299 .to_string(),
300 target_latency_ms: 500.0,
301 target_throughput_mbps: 1.0,
302 }
303 }
304
305 fn create_live_streaming_strategy() -> OptimizationStrategy {
306 OptimizationStrategy {
307 priority_threshold: Priority::HIGH,
308 max_frame_size: 64 * 1024, batch_size: 10,
310 compression_enabled: true,
311 adaptive_quality: true, description: "Optimized for live streaming with audience interaction".to_string(),
313 target_latency_ms: 500.0,
314 target_throughput_mbps: 20.0,
315 }
316 }
317
318 fn create_balanced_strategy() -> OptimizationStrategy {
319 OptimizationStrategy {
320 priority_threshold: Priority::MEDIUM,
321 max_frame_size: 32 * 1024,
322 batch_size: 10,
323 compression_enabled: true,
324 adaptive_quality: true,
325 description: "Balanced strategy for general use cases".to_string(),
326 target_latency_ms: 500.0,
327 target_throughput_mbps: 10.0,
328 }
329 }
330
331 fn calculate_efficiency_score(
334 &self,
335 frames: &[crate::domain::entities::Frame],
336 strategy: &OptimizationStrategy,
337 ) -> f64 {
338 if frames.is_empty() {
339 return 0.0;
340 }
341
342 let target_priority = strategy.priority_threshold.value();
344 let mut efficiency_sum = 0.0;
345
346 for frame in frames {
347 let priority = frame.priority();
348 let priority_diff = (priority.value() as i32 - target_priority as i32).abs() as f64;
350 let priority_score = 1.0 - (priority_diff / 255.0).min(1.0);
351
352 let size_score = if frame.estimated_size() <= strategy.max_frame_size {
354 1.0
355 } else {
356 strategy.max_frame_size as f64 / frame.estimated_size() as f64
357 };
358
359 efficiency_sum += (priority_score + size_score) / 2.0;
360 }
361
362 (efficiency_sum / frames.len() as f64).min(1.0)
363 }
364
365 fn estimate_latency_improvement(
366 &self,
367 strategy: &OptimizationStrategy,
368 context: &crate::application::services::prioritization_service::PerformanceContext,
369 ) -> f64 {
370 let mut improvement = 0.0;
372
373 let priority_factor = strategy.priority_threshold.value() as f64 / 255.0;
375 improvement += priority_factor * 0.3;
376
377 let batch_factor = 1.0 - (strategy.batch_size as f64 / 50.0).min(1.0);
379 improvement += batch_factor * 0.2;
380
381 let frame_size_factor = 1.0 - (strategy.max_frame_size as f64 / (1024.0 * 1024.0)).min(1.0);
383 improvement += frame_size_factor * 0.2;
384
385 if context.average_latency_ms > strategy.target_latency_ms {
387 improvement *= 1.5; }
389
390 improvement.min(1.0)
391 }
392
393 fn estimate_throughput_improvement(
394 &self,
395 strategy: &OptimizationStrategy,
396 context: &crate::application::services::prioritization_service::PerformanceContext,
397 ) -> f64 {
398 let mut improvement = 0.0;
399
400 let batch_factor = (strategy.batch_size as f64 / 50.0).min(1.0);
402 improvement += batch_factor * 0.4;
403
404 if strategy.compression_enabled {
406 improvement += 0.2;
407 }
408
409 let frame_size_factor = (strategy.max_frame_size as f64 / (1024.0 * 1024.0)).min(1.0);
411 improvement += frame_size_factor * 0.3;
412
413 if context.available_bandwidth_mbps < strategy.target_throughput_mbps {
415 improvement *= 1.3; }
417
418 improvement.min(1.0)
419 }
420
421 fn calculate_resource_utilization(
422 &self,
423 strategy: &OptimizationStrategy,
424 context: &crate::application::services::prioritization_service::PerformanceContext,
425 ) -> f64 {
426 let mut utilization = context.cpu_usage;
427
428 if strategy.compression_enabled {
430 utilization += 0.1;
431 }
432
433 if strategy.adaptive_quality {
435 utilization += 0.05;
436 }
437
438 let batch_efficiency = (strategy.batch_size as f64 / 20.0).min(1.0);
440 utilization -= batch_efficiency * 0.1;
441
442 utilization.clamp(0.0, 1.0)
443 }
444
445 fn calculate_quality_score(
446 &self,
447 frames: &[crate::domain::entities::Frame],
448 strategy: &OptimizationStrategy,
449 ) -> f64 {
450 if frames.is_empty() {
451 return 0.0;
452 }
453
454 let mut quality_sum = 0.0;
455
456 for frame in frames {
457 let mut frame_quality = 1.0;
458
459 if frame.estimated_size() > strategy.max_frame_size {
461 frame_quality *= 0.8;
462 }
463
464 let priority = frame.priority();
466 if priority.value() >= strategy.priority_threshold.value() {
467 frame_quality *= 1.1;
468 }
469
470 quality_sum += frame_quality;
471 }
472
473 (quality_sum / frames.len() as f64).min(1.0)
474 }
475}
476
477impl Default for OptimizationService {
478 fn default() -> Self {
479 Self::new()
480 }
481}
482
483#[derive(Debug, Clone)]
486pub struct StrategyAdjustmentRecommendation {
487 pub adjustment_type: AdjustmentType,
488 pub description: String,
489 pub expected_impact: String,
490 pub confidence: f64,
491 pub urgency: AdjustmentUrgency,
492}
493
494#[derive(Debug, Clone, PartialEq)]
495pub enum AdjustmentType {
496 PriorityIncrease,
497 PriorityDecrease,
498 BatchSizeIncrease,
499 BatchSizeDecrease,
500 FrameSizeIncrease,
501 FrameSizeDecrease,
502 CompressionEnable,
503 CompressionDisable,
504 QualityIncrease,
505 QualityReduction,
506}
507
508use crate::application::shared::AdjustmentUrgency;
510
511#[cfg(test)]
512mod tests {
513 use super::*;
514
515 #[test]
516 fn test_optimization_service_creation() {
517 let service = OptimizationService::new();
518 assert!(service.custom_strategies.is_empty());
519 }
520
521 #[test]
522 fn test_strategy_selection_based_on_use_case() {
523 let service = OptimizationService::new();
524
525 let dashboard_strategy = service
527 .get_strategy_for_use_case(&StreamingUseCase::RealTimeDashboard)
528 .unwrap();
529 assert_eq!(dashboard_strategy.priority_threshold, Priority::HIGH);
530 assert_eq!(dashboard_strategy.batch_size, 5);
531 assert!(dashboard_strategy.adaptive_quality);
532
533 let mobile_strategy = service
535 .get_strategy_for_use_case(&StreamingUseCase::MobileApp)
536 .unwrap();
537 assert_eq!(mobile_strategy.priority_threshold, Priority::HIGH);
538 assert!(mobile_strategy.compression_enabled);
539 assert_eq!(mobile_strategy.max_frame_size, 8 * 1024);
540 }
541
542 #[test]
543 fn test_custom_strategy_registration() {
544 let mut service = OptimizationService::new();
545
546 let custom_strategy = OptimizationStrategy {
547 priority_threshold: Priority::CRITICAL,
548 max_frame_size: 8 * 1024,
549 batch_size: 3,
550 compression_enabled: false,
551 adaptive_quality: false,
552 description: "Ultra low-latency gaming strategy".to_string(),
553 target_latency_ms: 50.0,
554 target_throughput_mbps: 30.0,
555 };
556
557 service
558 .register_custom_strategy("ultra_gaming".to_string(), custom_strategy.clone())
559 .unwrap();
560
561 let retrieved = service
562 .get_strategy_for_use_case(&StreamingUseCase::Custom("ultra_gaming".to_string()))
563 .unwrap();
564 assert_eq!(retrieved.priority_threshold, Priority::CRITICAL);
565 assert_eq!(retrieved.max_frame_size, 8 * 1024);
566 assert_eq!(retrieved.target_latency_ms, 50.0);
567 }
568}