use crate::{application::ApplicationResult, domain::value_objects::Priority};
#[derive(Debug)]
pub struct OptimizationService {
custom_strategies: std::collections::HashMap<String, OptimizationStrategy>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum StreamingUseCase {
RealTimeDashboard,
BulkDataTransfer,
MobileApp,
ProgressiveWebApp,
IoTDevice,
LiveStreaming,
Custom(String),
}
#[derive(Debug, Clone)]
pub struct OptimizationStrategy {
pub priority_threshold: Priority,
pub max_frame_size: usize,
pub batch_size: usize,
pub compression_enabled: bool,
pub adaptive_quality: bool,
pub description: String,
pub target_latency_ms: f64,
pub target_throughput_mbps: f64,
}
#[derive(Debug, Clone)]
pub struct UseCaseOptimizationResult {
pub use_case: StreamingUseCase,
pub strategy_applied: OptimizationStrategy,
pub frames_generated: Vec<crate::domain::entities::Frame>,
pub optimization_metrics: OptimizationMetrics,
}
#[derive(Debug, Clone)]
pub struct OptimizationMetrics {
pub efficiency_score: f64,
pub latency_improvement: f64,
pub throughput_improvement: f64,
pub resource_utilization: f64,
pub quality_score: f64,
}
impl OptimizationService {
pub fn new() -> Self {
Self {
custom_strategies: std::collections::HashMap::new(),
}
}
pub fn get_strategy_for_use_case(
&self,
use_case: &StreamingUseCase,
) -> ApplicationResult<OptimizationStrategy> {
match use_case {
StreamingUseCase::RealTimeDashboard => Ok(Self::create_realtime_dashboard_strategy()),
StreamingUseCase::BulkDataTransfer => Ok(Self::create_bulk_transfer_strategy()),
StreamingUseCase::MobileApp => Ok(Self::create_mobile_app_strategy()),
StreamingUseCase::ProgressiveWebApp => Ok(Self::create_pwa_strategy()),
StreamingUseCase::IoTDevice => Ok(Self::create_iot_device_strategy()),
StreamingUseCase::LiveStreaming => Ok(Self::create_live_streaming_strategy()),
StreamingUseCase::Custom(name) => {
self.custom_strategies.get(name).cloned().ok_or_else(|| {
crate::application::ApplicationError::Logic(format!(
"Custom strategy '{name}' not found"
))
})
}
}
}
pub fn register_custom_strategy(
&mut self,
name: String,
strategy: OptimizationStrategy,
) -> ApplicationResult<()> {
self.custom_strategies.insert(name, strategy);
Ok(())
}
pub fn optimize_strategy_for_context(
&self,
base_strategy: OptimizationStrategy,
context: &crate::application::services::prioritization_service::PerformanceContext,
) -> ApplicationResult<OptimizationStrategy> {
let mut optimized = base_strategy;
if context.error_rate > 0.05 {
optimized.priority_threshold = optimized.priority_threshold.increase_by(20);
} else if context.error_rate < 0.01 && context.average_latency_ms < 100.0 {
optimized.priority_threshold = optimized.priority_threshold.decrease_by(10);
}
if context.average_latency_ms > 1000.0 {
optimized.batch_size = (optimized.batch_size as f64 * 0.7) as usize;
} else if context.average_latency_ms < 100.0 && context.available_bandwidth_mbps > 10.0 {
optimized.batch_size = (optimized.batch_size as f64 * 1.3) as usize;
}
if context.available_bandwidth_mbps < 2.0 {
optimized.max_frame_size = (optimized.max_frame_size as f64 * 0.8) as usize;
} else if context.available_bandwidth_mbps > 20.0 {
optimized.max_frame_size = (optimized.max_frame_size as f64 * 1.2) as usize;
}
if context.available_bandwidth_mbps < 5.0 {
optimized.compression_enabled = true;
}
if context.cpu_usage > 0.8 {
optimized.adaptive_quality = false; }
Ok(optimized)
}
pub fn calculate_optimization_metrics(
&self,
strategy: &OptimizationStrategy,
frames: &[crate::domain::entities::Frame],
context: &crate::application::services::prioritization_service::PerformanceContext,
) -> ApplicationResult<OptimizationMetrics> {
let efficiency_score = self.calculate_efficiency_score(frames, strategy);
let latency_improvement = self.estimate_latency_improvement(strategy, context);
let throughput_improvement = self.estimate_throughput_improvement(strategy, context);
let resource_utilization = self.calculate_resource_utilization(strategy, context);
let quality_score = self.calculate_quality_score(frames, strategy);
Ok(OptimizationMetrics {
efficiency_score,
latency_improvement,
throughput_improvement,
resource_utilization,
quality_score,
})
}
pub fn recommend_strategy_adjustments(
&self,
current_strategy: &OptimizationStrategy,
performance_report: &crate::application::services::performance_analysis_service::PerformanceAnalysisReport,
) -> ApplicationResult<Vec<StrategyAdjustmentRecommendation>> {
let mut recommendations = Vec::new();
if performance_report.latency_analysis.average > current_strategy.target_latency_ms * 1.5 {
recommendations.push(StrategyAdjustmentRecommendation {
adjustment_type: AdjustmentType::PriorityIncrease,
description: "Increase priority threshold to reduce latency".to_string(),
expected_impact: "Reduce latency by 20-40%".to_string(),
confidence: 0.8,
urgency: AdjustmentUrgency::High,
});
}
if performance_report.throughput_analysis.average_mbps
< current_strategy.target_throughput_mbps * 0.7
{
recommendations.push(StrategyAdjustmentRecommendation {
adjustment_type: AdjustmentType::BatchSizeIncrease,
description: "Increase batch size to improve throughput".to_string(),
expected_impact: "Improve throughput by 15-30%".to_string(),
confidence: 0.7,
urgency: AdjustmentUrgency::Medium,
});
}
if performance_report.error_analysis.error_rate > 0.05 {
recommendations.push(StrategyAdjustmentRecommendation {
adjustment_type: AdjustmentType::QualityReduction,
description: "Enable adaptive quality to reduce errors".to_string(),
expected_impact: "Reduce error rate by 30-50%".to_string(),
confidence: 0.9,
urgency: AdjustmentUrgency::High,
});
}
if performance_report.resource_analysis.current_cpu_usage > 0.8 {
recommendations.push(StrategyAdjustmentRecommendation {
adjustment_type: AdjustmentType::CompressionDisable,
description: "Disable compression to reduce CPU load".to_string(),
expected_impact: "Reduce CPU usage by 10-20%".to_string(),
confidence: 0.8,
urgency: AdjustmentUrgency::Medium,
});
}
Ok(recommendations)
}
fn create_realtime_dashboard_strategy() -> OptimizationStrategy {
OptimizationStrategy {
priority_threshold: Priority::HIGH,
max_frame_size: 16 * 1024, batch_size: 5,
compression_enabled: false, adaptive_quality: true,
description: "Optimized for real-time dashboard updates with minimal latency"
.to_string(),
target_latency_ms: 100.0,
target_throughput_mbps: 5.0,
}
}
fn create_bulk_transfer_strategy() -> OptimizationStrategy {
OptimizationStrategy {
priority_threshold: Priority::MEDIUM,
max_frame_size: 256 * 1024, batch_size: 20,
compression_enabled: true,
adaptive_quality: false, description: "Optimized for bulk data transfer with maximum throughput".to_string(),
target_latency_ms: 1000.0,
target_throughput_mbps: 50.0,
}
}
fn create_mobile_app_strategy() -> OptimizationStrategy {
OptimizationStrategy {
priority_threshold: Priority::HIGH,
max_frame_size: 8 * 1024, batch_size: 3,
compression_enabled: true, adaptive_quality: true,
description: "Optimized for mobile network constraints and battery life".to_string(),
target_latency_ms: 300.0,
target_throughput_mbps: 2.0,
}
}
fn create_pwa_strategy() -> OptimizationStrategy {
OptimizationStrategy {
priority_threshold: Priority::CRITICAL,
max_frame_size: 32 * 1024, batch_size: 8,
compression_enabled: true,
adaptive_quality: true,
description: "Optimized for progressive web app user experience".to_string(),
target_latency_ms: 200.0,
target_throughput_mbps: 10.0,
}
}
fn create_iot_device_strategy() -> OptimizationStrategy {
OptimizationStrategy {
priority_threshold: Priority::CRITICAL,
max_frame_size: 4 * 1024, batch_size: 2,
compression_enabled: true, adaptive_quality: false, description: "Optimized for IoT devices with power and bandwidth constraints"
.to_string(),
target_latency_ms: 500.0,
target_throughput_mbps: 1.0,
}
}
fn create_live_streaming_strategy() -> OptimizationStrategy {
OptimizationStrategy {
priority_threshold: Priority::HIGH,
max_frame_size: 64 * 1024, batch_size: 10,
compression_enabled: true,
adaptive_quality: true, description: "Optimized for live streaming with audience interaction".to_string(),
target_latency_ms: 500.0,
target_throughput_mbps: 20.0,
}
}
fn calculate_efficiency_score(
&self,
frames: &[crate::domain::entities::Frame],
strategy: &OptimizationStrategy,
) -> f64 {
if frames.is_empty() {
return 0.0;
}
let target_priority = strategy.priority_threshold.value();
let mut efficiency_sum = 0.0;
for frame in frames {
let priority = frame.priority();
let priority_diff = (priority.value() as i32 - target_priority as i32).abs() as f64;
let priority_score = 1.0 - (priority_diff / 255.0).min(1.0);
let size_score = if frame.estimated_size() <= strategy.max_frame_size {
1.0
} else {
strategy.max_frame_size as f64 / frame.estimated_size() as f64
};
efficiency_sum += (priority_score + size_score) / 2.0;
}
(efficiency_sum / frames.len() as f64).min(1.0)
}
fn estimate_latency_improvement(
&self,
strategy: &OptimizationStrategy,
context: &crate::application::services::prioritization_service::PerformanceContext,
) -> f64 {
let mut improvement = 0.0;
let priority_factor = strategy.priority_threshold.value() as f64 / 255.0;
improvement += priority_factor * 0.3;
let batch_factor = 1.0 - (strategy.batch_size as f64 / 50.0).min(1.0);
improvement += batch_factor * 0.2;
let frame_size_factor = 1.0 - (strategy.max_frame_size as f64 / (1024.0 * 1024.0)).min(1.0);
improvement += frame_size_factor * 0.2;
if context.average_latency_ms > strategy.target_latency_ms {
improvement *= 1.5; }
improvement.min(1.0)
}
fn estimate_throughput_improvement(
&self,
strategy: &OptimizationStrategy,
context: &crate::application::services::prioritization_service::PerformanceContext,
) -> f64 {
let mut improvement = 0.0;
let batch_factor = (strategy.batch_size as f64 / 50.0).min(1.0);
improvement += batch_factor * 0.4;
if strategy.compression_enabled {
improvement += 0.2;
}
let frame_size_factor = (strategy.max_frame_size as f64 / (1024.0 * 1024.0)).min(1.0);
improvement += frame_size_factor * 0.3;
if context.available_bandwidth_mbps < strategy.target_throughput_mbps {
improvement *= 1.3; }
improvement.min(1.0)
}
fn calculate_resource_utilization(
&self,
strategy: &OptimizationStrategy,
context: &crate::application::services::prioritization_service::PerformanceContext,
) -> f64 {
let mut utilization = context.cpu_usage;
if strategy.compression_enabled {
utilization += 0.1;
}
if strategy.adaptive_quality {
utilization += 0.05;
}
let batch_efficiency = (strategy.batch_size as f64 / 20.0).min(1.0);
utilization -= batch_efficiency * 0.1;
utilization.clamp(0.0, 1.0)
}
fn calculate_quality_score(
&self,
frames: &[crate::domain::entities::Frame],
strategy: &OptimizationStrategy,
) -> f64 {
if frames.is_empty() {
return 0.0;
}
let mut quality_sum = 0.0;
for frame in frames {
let mut frame_quality = 1.0;
if frame.estimated_size() > strategy.max_frame_size {
frame_quality *= 0.8;
}
let priority = frame.priority();
if priority.value() >= strategy.priority_threshold.value() {
frame_quality *= 1.1;
}
quality_sum += frame_quality;
}
(quality_sum / frames.len() as f64).min(1.0)
}
}
impl Default for OptimizationService {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone)]
pub struct StrategyAdjustmentRecommendation {
pub adjustment_type: AdjustmentType,
pub description: String,
pub expected_impact: String,
pub confidence: f64,
pub urgency: AdjustmentUrgency,
}
#[derive(Debug, Clone, PartialEq)]
pub enum AdjustmentType {
PriorityIncrease,
PriorityDecrease,
BatchSizeIncrease,
BatchSizeDecrease,
FrameSizeIncrease,
FrameSizeDecrease,
CompressionEnable,
CompressionDisable,
QualityIncrease,
QualityReduction,
}
use crate::application::shared::AdjustmentUrgency;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_optimization_service_creation() {
let service = OptimizationService::new();
assert!(service.custom_strategies.is_empty());
}
#[test]
fn test_strategy_selection_based_on_use_case() {
let service = OptimizationService::new();
let dashboard_strategy = service
.get_strategy_for_use_case(&StreamingUseCase::RealTimeDashboard)
.unwrap();
assert_eq!(dashboard_strategy.priority_threshold, Priority::HIGH);
assert_eq!(dashboard_strategy.batch_size, 5);
assert!(dashboard_strategy.adaptive_quality);
let mobile_strategy = service
.get_strategy_for_use_case(&StreamingUseCase::MobileApp)
.unwrap();
assert_eq!(mobile_strategy.priority_threshold, Priority::HIGH);
assert!(mobile_strategy.compression_enabled);
assert_eq!(mobile_strategy.max_frame_size, 8 * 1024);
}
#[test]
fn test_custom_strategy_registration() {
let mut service = OptimizationService::new();
let custom_strategy = OptimizationStrategy {
priority_threshold: Priority::CRITICAL,
max_frame_size: 8 * 1024,
batch_size: 3,
compression_enabled: false,
adaptive_quality: false,
description: "Ultra low-latency gaming strategy".to_string(),
target_latency_ms: 50.0,
target_throughput_mbps: 30.0,
};
service
.register_custom_strategy("ultra_gaming".to_string(), custom_strategy.clone())
.unwrap();
let retrieved = service
.get_strategy_for_use_case(&StreamingUseCase::Custom("ultra_gaming".to_string()))
.unwrap();
assert_eq!(retrieved.priority_threshold, Priority::CRITICAL);
assert_eq!(retrieved.max_frame_size, 8 * 1024);
assert_eq!(retrieved.target_latency_ms, 50.0);
}
}