Skip to main content

voirs_feedback/
lib.rs

1//! # `VoiRS` Feedback
2//!
3//! Real-time feedback and interactive training system for `VoiRS` speech synthesis.
4//! This crate provides comprehensive feedback mechanisms, adaptive learning,
5//! and user progress tracking for continuous improvement.
6//!
7//! ## Features
8//!
9//! - **Real-time Feedback**: Immediate response during speech synthesis
10//! - **Adaptive Learning**: ML-driven personalized feedback
11//! - **Progress Tracking**: Detailed analytics and improvement metrics
12//! - **Interactive Training**: Guided exercises and challenges
13//! - **Gamification**: Achievement systems and leaderboards
14//! - **Multi-modal Output**: Visual, audio, and haptic feedback
15//!
16//! ## Quick Start
17//!
18//! ```rust,no_run
19//! use voirs_feedback::prelude::*;
20//! use voirs_feedback::FeedbackSystem;
21//!
22//! #[tokio::main]
23//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
24//!     // Create feedback system
25//!     let feedback_system = FeedbackSystem::new().await?;
26//!     
27//!     // Create user session
28//!     let mut session = feedback_system.create_session("user123").await?;
29//!     
30//!     // Generate audio and get feedback
31//!     let generated_audio = AudioBuffer::new(vec![0.1; 16000], 16000, 1);
32//!     let expected_text = "Hello world";
33//!     
34//!     let feedback = session.process_synthesis(&generated_audio, expected_text).await?;
35//!     
36//!     // Print feedback items
37//!     for item in &feedback.feedback_items {
38//!         println!("Feedback: {} (Score: {:.1}%)", item.message, item.score * 100.0);
39//!         if let Some(suggestion) = &item.suggestion {
40//!             println!("  Suggestion: {}", suggestion);
41//!         }
42//!     }
43//!     
44//!     // Save progress
45//!     session.save_progress().await?;
46//!     
47//!     Ok(())
48//! }
49//! ```
50//!
51//! ## Advanced Usage
52//!
53//! ### Custom Configuration
54//!
55//! ```rust
56//! use voirs_feedback::prelude::*;
57//! use voirs_feedback::realtime::{RealtimeFeedbackSystem, RealtimeConfig};
58//!
59//! # #[tokio::main]
60//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
61//! let config = RealtimeConfig {
62//!     max_latency_ms: 50,
63//!     stream_timeout: std::time::Duration::from_secs(180),
64//!     audio_buffer_size: 1024,
65//!     max_concurrent_streams: 25,
66//!     enable_metrics: true,
67//!     enable_confidence_filtering: true,
68//!     quality_threshold: 0.7,
69//!     pronunciation_threshold: 0.8,
70//! };
71//!
72//! let feedback_system = RealtimeFeedbackSystem::with_config(config).await?;
73//! # Ok(())
74//! # }
75//! ```
76//!
77//! ### Training Exercises
78//!
79//! ```rust,no_run
80//! use voirs_feedback::prelude::*;
81//! use voirs_feedback::{FeedbackSystem, FocusArea, ExerciseType, SuccessCriteria};
82//!
83//! # #[tokio::main]
84//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
85//! let feedback_system = FeedbackSystem::new().await?;
86//! let mut session = feedback_system.create_session("user123").await?;
87//!
88//! // Start a training exercise
89//! let exercise = TrainingExercise {
90//!     exercise_id: "basic_pronunciation".to_string(),
91//!     name: "Basic Pronunciation".to_string(),
92//!     description: "Practice basic phoneme pronunciation".to_string(),
93//!     difficulty: 0.3,
94//!     focus_areas: vec![FocusArea::Pronunciation],
95//!     exercise_type: ExerciseType::Pronunciation,
96//!     target_text: "Hello world".to_string(),
97//!     reference_audio: None,
98//!     success_criteria: SuccessCriteria {
99//!         min_quality_score: 0.7,
100//!         min_pronunciation_score: 0.8,
101//!         consistency_required: 1,
102//!         max_attempts: 3,
103//!         time_limit: Some(std::time::Duration::from_secs(300)),
104//!     },
105//!     estimated_duration: std::time::Duration::from_secs(600),
106//! };
107//!
108//! session.start_exercise(&exercise).await?;
109//! let result = session.complete_exercise().await?;
110//! println!("Exercise completed: success = {}", result.success);
111//! # Ok(())
112//! # }
113//! ```
114
115// Allow pedantic lints that are acceptable for audio/DSP processing code
116#![allow(clippy::cast_precision_loss)] // Acceptable for audio sample conversions
117#![allow(clippy::cast_possible_truncation)] // Controlled truncation in audio processing
118#![allow(clippy::cast_sign_loss)] // Intentional in index calculations
119#![allow(clippy::missing_errors_doc)] // Many internal functions with self-documenting error types
120#![allow(clippy::missing_panics_doc)] // Panics are documented where relevant
121#![allow(clippy::unused_self)] // Some trait implementations require &self for consistency
122#![allow(clippy::must_use_candidate)] // Not all return values need must_use annotation
123#![allow(clippy::doc_markdown)] // Technical terms don't all need backticks
124#![allow(clippy::unnecessary_wraps)] // Result wrappers maintained for API consistency
125#![allow(clippy::float_cmp)] // Exact float comparisons are intentional in some contexts
126#![allow(clippy::match_same_arms)] // Pattern matching clarity sometimes requires duplication
127#![allow(clippy::module_name_repetitions)] // Type names often repeat module names
128#![allow(clippy::struct_excessive_bools)] // Config structs naturally have many boolean flags
129#![allow(clippy::too_many_lines)] // Some functions are inherently complex
130#![allow(clippy::needless_pass_by_value)] // Some functions designed for ownership transfer
131#![allow(clippy::similar_names)] // Many similar variable names in algorithms
132#![allow(clippy::unused_async)] // Public API functions may need async for consistency
133#![allow(clippy::needless_range_loop)] // Range loops sometimes clearer than iterators
134#![allow(clippy::uninlined_format_args)] // Explicit argument names can improve clarity
135#![allow(clippy::manual_clamp)] // Manual clamping sometimes clearer
136#![allow(clippy::return_self_not_must_use)] // Not all builder methods need must_use
137#![allow(clippy::cast_possible_wrap)] // Controlled wrapping in processing code
138#![allow(clippy::cast_lossless)] // Explicit casts preferred for clarity
139#![allow(clippy::wildcard_imports)] // Prelude imports are convenient and standard
140#![allow(clippy::format_push_string)] // Sometimes more readable than alternative
141#![allow(clippy::redundant_closure_for_method_calls)] // Closures sometimes needed for type inference
142#![warn(missing_docs)]
143#![warn(clippy::all)]
144#![allow(clippy::module_name_repetitions)]
145#![allow(clippy::field_reassign_with_default)]
146#![allow(clippy::manual_clamp)]
147#![allow(clippy::type_complexity)]
148#![allow(unused_comparisons)]
149#![allow(clippy::absurd_extreme_comparisons)]
150#![allow(clippy::assertions_on_constants)]
151#![allow(clippy::needless_range_loop)]
152#![allow(clippy::match_like_matches_macro)]
153#![allow(clippy::if_same_then_else)]
154#![allow(clippy::useless_vec)]
155#![allow(clippy::vec_init_then_push)]
156#![allow(clippy::too_many_arguments)]
157#![allow(clippy::redundant_locals)]
158#![allow(clippy::manual_range_contains)]
159#![allow(unused_must_use)]
160#![allow(clippy::to_string_trait_impl)]
161#![allow(clippy::module_inception)]
162#![allow(clippy::mixed_attributes_style)]
163#![allow(clippy::large_enum_variant)]
164#![allow(clippy::format_in_format_args)]
165#![allow(clippy::extra_unused_lifetimes)]
166#![allow(clippy::empty_line_after_doc_comments)]
167#![allow(clippy::duplicated_attributes)]
168#![allow(clippy::len_zero)]
169#![allow(clippy::approx_constant)]
170
171// Re-export core VoiRS types
172pub use voirs_evaluation::{ComparisonResult, PronunciationScore, QualityScore};
173pub use voirs_recognizer::traits::{PhonemeAlignment, Transcript};
174pub use voirs_sdk::{AudioBuffer, LanguageCode, Phoneme, VoirsError};
175
176// Import for async trait
177use async_trait::async_trait;
178use std::time::Duration;
179
180// Core modules
181pub mod accessibility;
182pub mod adaptive;
183pub mod ai_coaching;
184pub mod analytics;
185pub mod audit_trail;
186pub mod batch_utils;
187pub mod bi_dashboard;
188pub mod cdn_support;
189pub mod cloud_deployment;
190pub mod computer_vision;
191pub mod cultural_adaptation;
192pub mod data_anonymization;
193pub mod data_management;
194pub mod data_pipeline;
195pub mod data_quality;
196pub mod data_retention;
197#[cfg(feature = "adaptive")]
198pub mod deep_learning_feedback;
199/// Description
200pub mod emotional_intelligence;
201pub mod enhanced_performance;
202/// Description
203pub mod enterprise;
204pub mod error_context;
205pub mod error_tracking;
206pub mod float_utils;
207#[cfg(feature = "gamification")]
208pub mod gamification;
209pub mod gdpr;
210pub mod google_classroom;
211pub mod group_learning;
212pub mod health;
213pub mod i18n_formatting;
214pub mod i18n_support;
215pub mod integration;
216pub mod load_balancer;
217pub mod memory_monitor;
218pub mod metrics_dashboard;
219#[cfg(feature = "microservices")]
220pub mod microservices;
221pub mod natural_language_generation;
222pub mod oauth2_auth;
223pub mod peer_learning;
224pub mod performance_helpers;
225pub mod performance_monitoring;
226pub mod persistence;
227pub mod platform;
228pub mod progress;
229pub mod quality_monitor;
230pub mod rate_limiting;
231pub mod realtime;
232pub mod recovery;
233pub mod secure_sharing;
234pub mod statistical_helpers;
235pub mod third_party_bots;
236pub mod timezone_support;
237pub mod training;
238pub mod traits;
239pub mod tts_integration;
240pub mod usage_analytics;
241pub mod user_management;
242pub mod utils;
243pub mod ux_analytics;
244pub mod validation_helpers;
245pub mod visualization;
246pub mod voice_control;
247pub mod webhooks;
248
249// Re-export all public types from traits
250pub use traits::*;
251
252// Re-export core types needed by FeedbackSystem
253pub use adaptive::core::AdaptiveFeedbackEngine;
254pub use progress::core::ProgressAnalyzer;
255pub use realtime::stream::FeedbackStream;
256pub use realtime::system::RealtimeFeedbackSystem;
257pub use training::core::InteractiveTrainer;
258
259// Note: Full feature modules are not glob re-exported to avoid ambiguity.
260// Import from specific modules: feedback::adaptive::*, feedback::training::*, etc.
261// Or use the prelude: use voirs_feedback::prelude::*;
262
263/// Version information
264pub const VERSION: &str = env!("CARGO_PKG_VERSION");
265
266/// Convenient prelude for common imports
267pub mod prelude {
268    //! Prelude module for convenient imports
269
270    pub use crate::traits::{
271        AdaptiveConfig, AdaptiveLearner, FeedbackConfig, FeedbackProvider, FeedbackResult,
272        FeedbackSession, ProgressConfig, ProgressTracker, SessionState, TrainingExercise,
273        TrainingProvider, TrainingResult, UserFeedback,
274    };
275
276    pub use crate::adaptive::core::AdaptiveFeedbackEngine;
277    pub use crate::adaptive::types::LearningStyle;
278    pub use crate::bi_dashboard::{
279        BiDashboard, DashboardConfig, DashboardSnapshot, HealthStatus as DashboardHealthStatus,
280        KPIs, ReportFormat, TrendAnalysis, WidgetType,
281    };
282    pub use crate::cdn_support::{
283        CdnAsset, CdnConfig, CdnManager, CdnProvider, CdnReport, EdgeLocation, GeoRegion,
284        InvalidationRequest, PriceClass,
285    };
286    pub use crate::cloud_deployment::{
287        CloudOrchestrator, CloudProvider, DeploymentConfig, KubernetesOrchestrator,
288    };
289    pub use crate::data_management::{DataExportPackage, DataManager, ExportFormat, ImportOptions};
290    pub use crate::data_pipeline::{
291        DataPipeline, DataProcessor, DataSink, DataType, PipelineConfig,
292    };
293    pub use crate::error_context::{
294        ErrorCategory, ErrorContext, ErrorContextBuilder, ErrorSeverity,
295    };
296    pub use crate::gdpr::{
297        ConsentRecord, DataSubject, GdprCompliance, GdprComplianceManager, ProcessingPurpose,
298    };
299    pub use crate::health::{
300        ComponentHealth, HealthConfig, HealthMonitor, HealthReport, HealthStatus,
301    };
302    pub use crate::load_balancer::{
303        LoadBalancer, LoadBalancerConfig, LoadBalancingAlgorithm, WorkerNode,
304    };
305    pub use crate::progress::core::ProgressAnalyzer;
306    pub use crate::quality_monitor::{
307        QualityAlert, QualityMetrics, QualityMonitor, QualityMonitorConfig,
308    };
309    pub use crate::rate_limiting::{
310        RateLimitAlgorithm, RateLimitConfig, RateLimitStatus, RateLimiter as ApiRateLimiter,
311        TieredRateLimiter,
312    };
313    pub use crate::realtime::stream::FeedbackStream;
314    pub use crate::realtime::system::RealtimeFeedbackSystem;
315    pub use crate::training::core::InteractiveTrainer;
316    pub use crate::training::types::TrainingSession;
317    pub use crate::traits::UserProgress;
318    pub use crate::usage_analytics::{
319        AnalyticsEvent, CohortAnalysis, EventType, FeatureMetrics, FunnelAnalysis, TimeSeriesPoint,
320        UsageAnalytics, UsageReport,
321    };
322    pub use crate::voice_control::{
323        CommandCategory, VoiceCommand, VoiceControlConfig, VoiceControlManager, VoiceIntent,
324    };
325    pub use crate::webhooks::{
326        DeliveryStatus, RetryConfig, WebhookConfig, WebhookEvent, WebhookManager, WebhookStats,
327    };
328
329    // New modules
330    pub use crate::accessibility::{
331        AccessibilityConfig, AccessibilityManager, AnnouncementPriority, Color, ColorBlindnessMode,
332        FocusNavigation, KeyboardShortcut, ScreenReaderAnnouncement, ShortcutCategory, WcagLevel,
333    };
334    pub use crate::audit_trail::{
335        AuditAction, AuditContext, AuditEntry, AuditLogger, AuditQuery, ComplianceReport,
336        ResourceType,
337    };
338    pub use crate::batch_utils::{
339        process_batches, AdaptiveBatchSize, BatchConfig, BatchProcessor, BatchResult, ChunkIterator,
340    };
341    pub use crate::data_anonymization::{
342        AnonymizationPolicy, AnonymizationRule, AnonymizationTechnique, DataAnonymizer,
343        RiskAssessment, SensitivityLevel,
344    };
345    pub use crate::data_quality::{
346        DataQualityMonitor, QualityDimension, QualityMetrics as DataQualityMetrics, QualityReport,
347        ValidationResult as DataValidationResult,
348    };
349    pub use crate::data_retention::{
350        DataCategory, RetentionAction, RetentionCondition, RetentionManager, RetentionPolicy,
351        RetentionReport, RetentionRule, RetentionStatistics,
352    };
353    pub use crate::error_tracking::{
354        ErrorContext as ErrorTrackingContext, ErrorEvent, ErrorGroup,
355        ErrorSeverity as ErrorTrackingSeverity, ErrorStatistics, ErrorTracker, ErrorTrend,
356    };
357    pub use crate::float_utils::{
358        approx_cmp, approx_eq, approx_eq_f32, approx_eq_f64, approx_eq_relative, approx_ge,
359        approx_gt, approx_le, approx_lt, approx_max, approx_min, approx_ne, approx_one,
360        approx_zero, clamp_with_epsilon, in_range, F32_EPSILON, F64_EPSILON, RELATIVE_EPSILON,
361    };
362    pub use crate::performance_monitoring::{
363        AlertRule, AlertSeverity, MetricStatistics, MetricType, PerformanceMonitor,
364    };
365    pub use crate::secure_sharing::{
366        AccessLevel, AccessLogEntry, AccessResult, DataCategory as SharingDataCategory,
367        SecureSharingManager, ShareConfig, ShareStatus, ShareToken, SharedDataPackage,
368        SharingProtocol, SharingStatistics,
369    };
370    pub use crate::statistical_helpers::{
371        coefficient_of_variation, correlation, detect_outliers, interquartile_range, kurtosis,
372        linear_regression, mean_absolute_error, median, mode, percentile, r_squared,
373        root_mean_squared_error, skewness, z_score,
374    };
375    pub use crate::timezone_support::{ScheduledEvent, TimeFormat, TimezoneInfo, TimezoneManager};
376    pub use crate::validation_helpers::{
377        validate_audio_buffer, validate_confidence, validate_duration, validate_email,
378        validate_not_empty, validate_percentage, validate_range, validate_sample_rate,
379        validate_score, validate_text_input, validate_username, ValidationResult,
380    };
381
382    #[cfg(feature = "gamification")]
383    pub use crate::gamification::achievements::AchievementSystem;
384    #[cfg(feature = "gamification")]
385    pub use crate::gamification::Leaderboard;
386
387    #[cfg(feature = "ui")]
388    pub use crate::visualization::charts::ProgressChart;
389    #[cfg(feature = "ui")]
390    pub use crate::visualization::core::FeedbackVisualizer;
391
392    // Re-export utility modules
393    pub use crate::performance_helpers::{
394        calculate_rtf, calculate_throughput, format_bytes, format_duration_auto, OperationProfiler,
395        PerformanceSnapshot, RateLimiter, Timer,
396    };
397    pub use crate::utils::{
398        clamp_score, confidence_interval, exponential_moving_average, format_duration,
399        improvement_rate, is_recent, merge_hashmaps, moving_average, normalize_scores,
400        percentage_to_score, sanitize_input, score_to_percentage, standard_deviation, time_since,
401        truncate_string, weighted_average,
402    };
403
404    // Re-export SDK types
405    pub use voirs_evaluation::{ComparisonResult, PronunciationScore, QualityScore};
406    pub use voirs_recognizer::traits::{PhonemeAlignment, Transcript};
407    pub use voirs_sdk::{AudioBuffer, LanguageCode, Phoneme, VoirsError};
408
409    // Re-export async trait
410    pub use async_trait::async_trait;
411}
412
413// ============================================================================
414// Error Types
415// ============================================================================
416
417/// Feedback-specific error types
418#[derive(Debug, thiserror::Error)]
419pub enum FeedbackError {
420    /// Feedback generation failed
421    #[error("Feedback generation failed: {message}")]
422    FeedbackGenerationError {
423        /// Error message
424        message: String,
425        /// Source error
426        #[source]
427        source: Option<Box<dyn std::error::Error + Send + Sync>>,
428    },
429
430    /// Session management failed
431    #[error("Session management failed: {message}")]
432    SessionError {
433        /// Error message
434        message: String,
435        /// Source error
436        #[source]
437        source: Option<Box<dyn std::error::Error + Send + Sync>>,
438    },
439
440    /// Adaptive learning failed
441    #[error("Adaptive learning failed: {message}")]
442    AdaptiveLearningError {
443        /// Error message
444        message: String,
445        /// Source error
446        #[source]
447        source: Option<Box<dyn std::error::Error + Send + Sync>>,
448    },
449
450    /// Progress tracking failed
451    #[error("Progress tracking failed: {message}")]
452    ProgressTrackingError {
453        /// Error message
454        message: String,
455        /// Source error
456        #[source]
457        source: Option<Box<dyn std::error::Error + Send + Sync>>,
458    },
459
460    /// Training system failed
461    #[error("Training system failed: {message}")]
462    TrainingError {
463        /// Error message
464        message: String,
465        /// Source error
466        #[source]
467        source: Option<Box<dyn std::error::Error + Send + Sync>>,
468    },
469
470    /// Real-time processing failed
471    #[error("Real-time processing failed: {message}")]
472    RealtimeError {
473        /// Error message
474        message: String,
475        /// Source error
476        #[source]
477        source: Option<Box<dyn std::error::Error + Send + Sync>>,
478    },
479
480    /// Configuration error
481    #[error("Configuration error: {message}")]
482    ConfigurationError {
483        /// Error message
484        message: String,
485    },
486
487    /// Invalid input
488    #[error("Invalid input: {message}")]
489    InvalidInput {
490        /// Error message
491        message: String,
492    },
493
494    /// Feature not supported
495    #[error("Feature not supported: {feature}")]
496    FeatureNotSupported {
497        /// Feature name
498        feature: String,
499    },
500
501    /// Processing error
502    #[error("Processing error: {0}")]
503    ProcessingError(String),
504
505    /// Lock contention detected
506    #[error("Lock contention detected - operation aborted to preserve UI responsiveness")]
507    LockContention,
508
509    /// Operation timeout
510    #[error("Operation timed out")]
511    Timeout,
512}
513
514impl From<FeedbackError> for VoirsError {
515    fn from(err: FeedbackError) -> Self {
516        // Enhanced error logging for better diagnostics
517        log::warn!("Converting FeedbackError to VoirsError: {err}");
518
519        match err {
520            FeedbackError::FeedbackGenerationError { message, source: _ } => {
521                log::error!("Feedback generation failed: {message}");
522                VoirsError::AudioError {
523                    message,
524                    buffer_info: None,
525                }
526            }
527            FeedbackError::SessionError { message, source: _ } => {
528                log::error!("Session management error: {message}");
529                VoirsError::ConfigError {
530                    field: "session".to_string(),
531                    message,
532                }
533            }
534            FeedbackError::AdaptiveLearningError { message, source } => {
535                log::error!("Adaptive learning error: {message}");
536                VoirsError::ModelError {
537                    model_type: voirs_sdk::error::ModelType::Vocoder,
538                    message,
539                    source,
540                }
541            }
542            FeedbackError::ProgressTrackingError { message, source: _ } => {
543                log::error!("Progress tracking error: {message}");
544                VoirsError::ConfigError {
545                    field: "progress_tracking".to_string(),
546                    message,
547                }
548            }
549            FeedbackError::TrainingError { message, source: _ } => {
550                log::error!("Training system error: {message}");
551                VoirsError::ConfigError {
552                    field: "training".to_string(),
553                    message,
554                }
555            }
556            FeedbackError::RealtimeError { message, source: _ } => {
557                log::error!("Real-time processing error: {message}");
558                VoirsError::AudioError {
559                    message,
560                    buffer_info: None,
561                }
562            }
563            FeedbackError::ConfigurationError { message } => {
564                log::error!("Configuration error: {message}");
565                VoirsError::ConfigError {
566                    field: "configuration".to_string(),
567                    message,
568                }
569            }
570            FeedbackError::InvalidInput { message } => {
571                log::warn!("Invalid input provided: {message}");
572                VoirsError::ConfigError {
573                    field: "input".to_string(),
574                    message: format!("Invalid input: {message}"),
575                }
576            }
577            FeedbackError::FeatureNotSupported { feature } => {
578                log::warn!("Feature not supported: {feature}");
579                VoirsError::ModelError {
580                    model_type: voirs_sdk::error::ModelType::Vocoder,
581                    message: format!("Feature not supported: {feature}"),
582                    source: None,
583                }
584            }
585            FeedbackError::ProcessingError(message) => {
586                log::error!("Processing error: {message}");
587                VoirsError::AudioError {
588                    message,
589                    buffer_info: None,
590                }
591            }
592            FeedbackError::LockContention => {
593                log::warn!("Lock contention detected - preserving UI responsiveness");
594                VoirsError::AudioError {
595                    message:
596                        "Lock contention detected - operation aborted to preserve UI responsiveness"
597                            .to_string(),
598                    buffer_info: None,
599                }
600            }
601            FeedbackError::Timeout => {
602                log::error!("Operation timed out");
603                VoirsError::AudioError {
604                    message: "Operation timed out".to_string(),
605                    buffer_info: None,
606                }
607            }
608        }
609    }
610}
611
612impl From<VoirsError> for FeedbackError {
613    fn from(err: VoirsError) -> Self {
614        FeedbackError::FeedbackGenerationError {
615            message: err.to_string(),
616            source: Some(Box::new(err)),
617        }
618    }
619}
620
621// ============================================================================
622// Main Feedback System
623// ============================================================================
624
625/// Main feedback system that coordinates all feedback components
626pub struct FeedbackSystem {
627    /// Real-time feedback system
628    realtime: RealtimeFeedbackSystem,
629    /// Adaptive learning engine
630    adaptive: AdaptiveFeedbackEngine,
631    /// Progress tracking
632    progress: ProgressAnalyzer,
633    /// Training system
634    trainer: InteractiveTrainer,
635    /// Configuration
636    config: FeedbackSystemConfig,
637    /// Persistence manager
638    #[cfg(feature = "persistence")]
639    persistence_manager: std::sync::Arc<dyn crate::persistence::PersistenceManager>,
640}
641
642impl FeedbackSystem {
643    /// Create a new feedback system
644    pub async fn new() -> Result<Self, FeedbackError> {
645        Self::with_config(FeedbackSystemConfig::default()).await
646    }
647
648    /// Create feedback system with custom configuration
649    pub async fn with_config(config: FeedbackSystemConfig) -> Result<Self, FeedbackError> {
650        let realtime =
651            RealtimeFeedbackSystem::new()
652                .await
653                .map_err(|e| FeedbackError::RealtimeError {
654                    message: format!("Failed to initialize real-time system: {e}"),
655                    source: Some(Box::new(e)),
656                })?;
657
658        let adaptive = AdaptiveFeedbackEngine::new().await.map_err(|e| {
659            FeedbackError::AdaptiveLearningError {
660                message: format!("Failed to initialize adaptive engine: {e}"),
661                source: Some(Box::new(e)),
662            }
663        })?;
664
665        let progress =
666            ProgressAnalyzer::new()
667                .await
668                .map_err(|e| FeedbackError::ProgressTrackingError {
669                    message: format!("Failed to initialize progress analyzer: {e}"),
670                    source: Some(Box::new(e)),
671                })?;
672
673        let trainer =
674            InteractiveTrainer::new()
675                .await
676                .map_err(|e| FeedbackError::TrainingError {
677                    message: format!("Failed to initialize trainer: {e}"),
678                    source: Some(Box::new(e)),
679                })?;
680
681        #[cfg(feature = "persistence")]
682        let persistence_manager = {
683            use crate::persistence::backends::sqlite::SQLitePersistenceManager;
684            use crate::persistence::{PersistenceBackend, PersistenceConfig, PersistenceManager};
685
686            let db_path = config
687                .database_path
688                .clone()
689                .unwrap_or_else(|| "feedback.db".to_string());
690
691            let persistence_config = PersistenceConfig {
692                backend: PersistenceBackend::SQLite,
693                connection_string: db_path,
694                enable_encryption: false,
695                max_cache_size: 1000,
696                cache_ttl_seconds: 3600,
697                auto_cleanup_interval_hours: 24,
698                data_retention_days: 365,
699                enable_compression: true,
700                connection_pool_size: 10,
701            };
702
703            let mut manager = SQLitePersistenceManager::new(persistence_config)
704                .await
705                .map_err(|e| FeedbackError::SessionError {
706                    message: format!("Failed to initialize persistence manager: {e}"),
707                    source: Some(Box::new(e)),
708                })?;
709
710            manager
711                .initialize()
712                .await
713                .map_err(|e| FeedbackError::SessionError {
714                    message: format!("Failed to initialize persistence backend: {e}"),
715                    source: Some(Box::new(e)),
716                })?;
717
718            std::sync::Arc::new(manager)
719                as std::sync::Arc<dyn crate::persistence::PersistenceManager>
720        };
721
722        Ok(Self {
723            realtime,
724            adaptive,
725            progress,
726            trainer,
727            config,
728            #[cfg(feature = "persistence")]
729            persistence_manager,
730        })
731    }
732
733    /// Create a new user session
734    pub async fn create_session(
735        &self,
736        user_id: &str,
737    ) -> Result<Box<dyn FeedbackSession>, FeedbackError> {
738        let session = FeedbackSessionImpl::new(
739            user_id.to_string(),
740            &self.realtime,
741            &self.adaptive,
742            &self.progress,
743            &self.trainer,
744            &self.config,
745            #[cfg(feature = "persistence")]
746            self.persistence_manager.clone(),
747        )
748        .await?;
749
750        Ok(Box::new(session))
751    }
752
753    /// Get system configuration
754    #[must_use]
755    pub fn config(&self) -> &FeedbackSystemConfig {
756        &self.config
757    }
758
759    /// Get system statistics
760    pub async fn get_statistics(&self) -> Result<FeedbackSystemStats, FeedbackError> {
761        let realtime_stats = self.realtime.get_statistics().await?;
762        let adaptive_stats = self.adaptive.get_statistics().await?;
763        let progress_stats = self.progress.get_statistics().await?;
764
765        // Enhanced logging for system monitoring
766        log::info!(
767            "System statistics: {} sessions, {} active streams, {:.2}ms avg response time",
768            progress_stats.total_users,
769            realtime_stats.active_streams,
770            realtime_stats.average_latency_ms
771        );
772
773        Ok(FeedbackSystemStats {
774            total_sessions: progress_stats.total_users,
775            active_sessions: realtime_stats.active_streams,
776            total_feedback_generated: adaptive_stats.total_feedback_count,
777            average_response_time_ms: realtime_stats.average_latency_ms,
778            system_uptime: std::time::SystemTime::now()
779                .duration_since(std::time::UNIX_EPOCH)
780                .unwrap_or_default(),
781        })
782    }
783
784    /// Enhanced system health monitoring
785    pub async fn get_system_health(&self) -> Result<SystemHealthReport, FeedbackError> {
786        let stats = self.get_statistics().await?;
787
788        let mut health_score = 1.0;
789        let mut issues = Vec::new();
790        let mut recommendations = Vec::new();
791
792        // Check response time performance
793        if stats.average_response_time_ms > 500.0 {
794            health_score -= 0.3;
795            issues.push("High response time detected".to_string());
796            recommendations.push("Consider optimizing audio processing pipeline".to_string());
797        } else if stats.average_response_time_ms > 200.0 {
798            health_score -= 0.1;
799            issues.push("Elevated response time".to_string());
800            recommendations.push("Monitor system load and resource usage".to_string());
801        }
802
803        // Check active session load
804        let max_sessions = self.config.max_concurrent_sessions;
805        let session_load = stats.active_sessions as f32 / max_sessions as f32;
806
807        if session_load > 0.9 {
808            health_score -= 0.2;
809            issues.push("Near maximum session capacity".to_string());
810            recommendations.push("Consider scaling up resources or load balancing".to_string());
811        } else if session_load > 0.7 {
812            health_score -= 0.1;
813            issues.push("High session load".to_string());
814            recommendations.push("Monitor for potential capacity issues".to_string());
815        }
816
817        // Check system uptime
818        let uptime_hours = stats.system_uptime.as_secs() as f32 / 3600.0;
819        if uptime_hours < 1.0 {
820            health_score -= 0.1;
821            issues.push("Recent system restart detected".to_string());
822            recommendations.push("Monitor for startup issues or crashes".to_string());
823        }
824
825        let health_status = if health_score >= 0.9 {
826            HealthStatus::Excellent
827        } else if health_score >= 0.7 {
828            HealthStatus::Good
829        } else if health_score >= 0.5 {
830            HealthStatus::Warning
831        } else {
832            HealthStatus::Critical
833        };
834
835        log::info!(
836            "System health: {:?} (score: {:.2}) - {} issues, {} recommendations",
837            health_status,
838            health_score,
839            issues.len(),
840            recommendations.len()
841        );
842
843        Ok(SystemHealthReport {
844            health_score,
845            health_status,
846            issues,
847            recommendations,
848            timestamp: chrono::Utc::now(),
849            statistics: stats,
850        })
851    }
852}
853
854/// Feedback system configuration
855#[derive(Debug, Clone)]
856pub struct FeedbackSystemConfig {
857    /// Enable real-time feedback
858    pub enable_realtime: bool,
859    /// Enable adaptive learning
860    pub enable_adaptive: bool,
861    /// Enable progress tracking
862    pub enable_progress_tracking: bool,
863    /// Enable gamification
864    pub enable_gamification: bool,
865    /// Maximum concurrent sessions
866    pub max_concurrent_sessions: usize,
867    /// Feedback response timeout
868    pub response_timeout_ms: u64,
869    /// Auto-save interval for progress
870    pub auto_save_interval_sec: u64,
871    /// Database path (for persistence)
872    #[cfg(feature = "persistence")]
873    pub database_path: Option<String>,
874}
875
876impl Default for FeedbackSystemConfig {
877    fn default() -> Self {
878        Self {
879            enable_realtime: true,
880            enable_adaptive: true,
881            enable_progress_tracking: true,
882            enable_gamification: false,
883            max_concurrent_sessions: 100,
884            response_timeout_ms: 500,
885            auto_save_interval_sec: 30,
886            #[cfg(feature = "persistence")]
887            database_path: None,
888        }
889    }
890}
891
892/// Feedback system statistics
893#[derive(Debug, Clone)]
894pub struct FeedbackSystemStats {
895    /// Total number of sessions created
896    pub total_sessions: usize,
897    /// Currently active sessions
898    pub active_sessions: usize,
899    /// Total feedback messages generated
900    pub total_feedback_generated: usize,
901    /// Average response time in milliseconds
902    pub average_response_time_ms: f32,
903    /// System uptime
904    pub system_uptime: std::time::Duration,
905}
906
907/// System health report for monitoring and diagnostics
908#[derive(Debug, Clone)]
909pub struct SystemHealthReport {
910    /// Overall health score (0.0 to 1.0)
911    pub health_score: f32,
912    /// Current health status
913    pub health_status: HealthStatus,
914    /// List of detected issues
915    pub issues: Vec<String>,
916    /// Recommended actions
917    pub recommendations: Vec<String>,
918    /// Timestamp of health check
919    pub timestamp: chrono::DateTime<chrono::Utc>,
920    /// Current system statistics
921    pub statistics: FeedbackSystemStats,
922}
923
924/// System health status categories
925#[derive(Debug, Clone, PartialEq)]
926pub enum HealthStatus {
927    /// System operating optimally
928    Excellent,
929    /// System operating well with minor issues
930    Good,
931    /// System operating with noticeable issues requiring attention
932    Warning,
933    /// System experiencing critical issues requiring immediate attention
934    Critical,
935}
936
937/// Internal session implementation
938struct FeedbackSessionImpl {
939    user_id: String,
940    state: SessionState,
941    realtime: RealtimeFeedbackSystem,
942    adaptive: AdaptiveFeedbackEngine,
943    progress: ProgressAnalyzer,
944    trainer: InteractiveTrainer,
945    config: FeedbackSystemConfig,
946    feedback_stream: Option<FeedbackStream>,
947    #[cfg(feature = "persistence")]
948    persistence_manager: std::sync::Arc<dyn crate::persistence::PersistenceManager>,
949}
950
951impl FeedbackSessionImpl {
952    async fn new(
953        user_id: String,
954        realtime: &RealtimeFeedbackSystem,
955        adaptive: &AdaptiveFeedbackEngine,
956        progress: &ProgressAnalyzer,
957        trainer: &InteractiveTrainer,
958        config: &FeedbackSystemConfig,
959        #[cfg(feature = "persistence")] persistence_manager: std::sync::Arc<
960            dyn crate::persistence::PersistenceManager,
961        >,
962    ) -> Result<Self, FeedbackError> {
963        let state = SessionState::new(&user_id).await?;
964
965        Ok(Self {
966            user_id,
967            state,
968            realtime: realtime.clone(),
969            adaptive: adaptive.clone(),
970            progress: progress.clone(),
971            trainer: trainer.clone(),
972            config: config.clone(),
973            feedback_stream: None,
974            #[cfg(feature = "persistence")]
975            persistence_manager,
976        })
977    }
978}
979
980#[async_trait]
981impl FeedbackSession for FeedbackSessionImpl {
982    async fn process_synthesis(
983        &mut self,
984        audio: &AudioBuffer,
985        text: &str,
986    ) -> FeedbackResult<FeedbackResponse> {
987        // Create feedback stream if it doesn't exist
988        if self.feedback_stream.is_none() {
989            let stream = self
990                .realtime
991                .create_stream(&self.user_id, &self.state)
992                .await?;
993            self.feedback_stream = Some(stream);
994        }
995
996        // Generate feedback using realtime system
997        let feedback = if let Some(stream) = &self.feedback_stream {
998            stream.process_audio(audio, text).await?
999        } else {
1000            return Err(FeedbackError::RealtimeError {
1001                message: "Failed to create feedback stream".to_string(),
1002                source: None,
1003            }
1004            .into());
1005        };
1006
1007        // Learn from this interaction
1008        let user_feedback = UserFeedback {
1009            message: text.to_string(),
1010            suggestion: Some("Continue practicing".to_string()),
1011            confidence: 0.8,
1012            score: 0.8,
1013            priority: 0.5,
1014            metadata: std::collections::HashMap::new(),
1015        };
1016        let interaction = UserInteraction {
1017            user_id: self.user_id.clone(),
1018            timestamp: chrono::Utc::now(),
1019            interaction_type: InteractionType::Practice,
1020            audio: audio.clone(),
1021            text: text.to_string(),
1022            feedback: feedback.clone(),
1023            user_response: None,
1024        };
1025        self.adaptive.learn_from_interaction(&interaction).await?;
1026
1027        Ok(feedback)
1028    }
1029
1030    async fn start_exercise(&mut self, exercise: &TrainingExercise) -> FeedbackResult<()> {
1031        // Update session state with current exercise
1032        let exercise_session = crate::traits::ExerciseSession {
1033            exercise_id: exercise.exercise_id.clone(),
1034            exercise_name: exercise.name.clone(),
1035            start_time: chrono::Utc::now(),
1036            current_attempt: 0,
1037            progress: 0.0,
1038        };
1039
1040        self.state.current_exercise = Some(exercise_session);
1041        self.state.stats.exercises_completed += 1;
1042
1043        Ok(())
1044    }
1045
1046    async fn complete_exercise(&mut self) -> FeedbackResult<TrainingResult> {
1047        let exercise_session =
1048            self.state
1049                .current_exercise
1050                .take()
1051                .ok_or_else(|| FeedbackError::SessionError {
1052                    message: "No active exercise to complete".to_string(),
1053                    source: None,
1054                })?;
1055
1056        let completion_time = chrono::Utc::now()
1057            .signed_duration_since(exercise_session.start_time)
1058            .to_std()
1059            .unwrap_or_default();
1060
1061        // Create a basic exercise for the result
1062        let exercise = TrainingExercise {
1063            exercise_id: exercise_session.exercise_id,
1064            name: exercise_session.exercise_name,
1065            description: "Completed training exercise".to_string(),
1066            difficulty: 0.5,
1067            focus_areas: vec![FocusArea::Pronunciation, FocusArea::Quality],
1068            exercise_type: ExerciseType::FreeForm,
1069            target_text: "Practice text".to_string(),
1070            reference_audio: None,
1071            success_criteria: SuccessCriteria {
1072                min_quality_score: 0.7,
1073                min_pronunciation_score: 0.7,
1074                consistency_required: 1,
1075                max_attempts: 3,
1076                time_limit: Some(Duration::from_secs(300)),
1077            },
1078            estimated_duration: Duration::from_secs(300),
1079        };
1080
1081        let final_scores = TrainingScores {
1082            quality: self.state.stats.average_quality,
1083            pronunciation: self.state.stats.average_pronunciation,
1084            consistency: 0.8,
1085            improvement: 0.1,
1086        };
1087
1088        let success = final_scores.quality >= 0.7 && final_scores.pronunciation >= 0.7;
1089
1090        let feedback = FeedbackResponse {
1091            feedback_items: vec![UserFeedback {
1092                message: if success {
1093                    "Great work! Exercise completed successfully.".to_string()
1094                } else {
1095                    "Good effort! Keep practicing to improve.".to_string()
1096                },
1097                suggestion: Some("Continue with the next exercise".to_string()),
1098                confidence: 0.8,
1099                score: f32::midpoint(final_scores.quality, final_scores.pronunciation),
1100                priority: 0.5,
1101                metadata: std::collections::HashMap::new(),
1102            }],
1103            overall_score: f32::midpoint(final_scores.quality, final_scores.pronunciation),
1104            immediate_actions: vec!["Review feedback and continue training".to_string()],
1105            long_term_goals: vec!["Maintain consistent quality".to_string()],
1106            progress_indicators: ProgressIndicators {
1107                improving_areas: vec!["Overall Performance".to_string()],
1108                attention_areas: Vec::new(),
1109                stable_areas: vec!["Basic Skills".to_string()],
1110                overall_trend: 0.1,
1111                completion_percentage: exercise_session.progress,
1112            },
1113            timestamp: chrono::Utc::now(),
1114            processing_time: Duration::from_millis(100),
1115            feedback_type: FeedbackType::Quality,
1116        };
1117
1118        let improvement_recommendations = if success {
1119            vec![
1120                "Maintain current level of performance".to_string(),
1121                "Try more challenging exercises".to_string(),
1122            ]
1123        } else {
1124            vec![
1125                "Focus on audio quality improvement".to_string(),
1126                "Practice pronunciation accuracy".to_string(),
1127            ]
1128        };
1129
1130        Ok(TrainingResult {
1131            exercise,
1132            success,
1133            attempts_made: exercise_session.current_attempt + 1,
1134            completion_time,
1135            final_scores,
1136            feedback,
1137            improvement_recommendations,
1138        })
1139    }
1140
1141    async fn update_preferences(&mut self, preferences: UserPreferences) -> FeedbackResult<()> {
1142        // Update session state with new preferences
1143        self.state.preferences = preferences;
1144
1145        // Log the preference update
1146        log::info!("Updated user preferences for user: {}", self.user_id);
1147
1148        Ok(())
1149    }
1150
1151    fn get_state(&self) -> &SessionState {
1152        &self.state
1153    }
1154
1155    async fn save_progress(&self) -> FeedbackResult<()> {
1156        log::info!(
1157            "Saving progress for user: {} at session: {}",
1158            self.user_id,
1159            self.state.session_id
1160        );
1161
1162        #[cfg(feature = "persistence")]
1163        {
1164            // Save session state to database
1165            self.persistence_manager
1166                .save_session(&self.state)
1167                .await
1168                .map_err(|e| FeedbackError::SessionError {
1169                    message: format!("Failed to save session to database: {e}"),
1170                    source: Some(Box::new(e)),
1171                })?;
1172
1173            // Create UserProgress from session stats for saving
1174            let user_progress = UserProgress {
1175                user_id: self.user_id.clone(),
1176                overall_skill_level: f32::midpoint(
1177                    self.state.stats.average_quality,
1178                    self.state.stats.average_pronunciation,
1179                ),
1180                skill_breakdown: std::collections::HashMap::new(),
1181                progress_history: vec![], // Empty for now
1182                achievements: vec![],     // Empty achievements for now
1183                session_count: 1,         // Current session
1184                total_practice_time: self.state.stats.session_duration,
1185                training_stats: crate::traits::TrainingStatistics {
1186                    total_sessions: 1,      // Default to 1 (current session)
1187                    successful_sessions: 1, // Assume current session is successful
1188                    total_training_time: self.state.stats.session_duration,
1189                    exercises_completed: self.state.stats.exercises_completed,
1190                    success_rate: 1.0,         // Default success rate
1191                    average_improvement: 0.05, // Default improvement
1192                    current_streak: 1,         // Default streak
1193                    longest_streak: 1,         // Default longest streak
1194                },
1195                goals: vec![], // Empty goals for now
1196                last_updated: chrono::Utc::now(),
1197                average_scores: crate::traits::SessionScores {
1198                    average_quality: self.state.stats.average_quality,
1199                    average_pronunciation: self.state.stats.average_pronunciation,
1200                    average_fluency: 0.0, // Default
1201                    overall_score: f32::midpoint(
1202                        self.state.stats.average_quality,
1203                        self.state.stats.average_pronunciation,
1204                    ),
1205                    improvement_trend: 0.05, // Default improvement trend
1206                },
1207                skill_levels: std::collections::HashMap::new(),
1208                recent_sessions: vec![],
1209                personal_bests: std::collections::HashMap::new(),
1210            };
1211
1212            // Save user progress to database
1213            self.persistence_manager
1214                .save_user_progress(&self.user_id, &user_progress)
1215                .await
1216                .map_err(|e| FeedbackError::SessionError {
1217                    message: format!("Failed to save user progress to database: {e}"),
1218                    source: Some(Box::new(e)),
1219                })?;
1220
1221            log::info!(
1222                "Successfully saved progress to database for user: {}",
1223                self.user_id
1224            );
1225        }
1226
1227        #[cfg(not(feature = "persistence"))]
1228        {
1229            // Fallback to JSON serialization for logging when persistence is disabled
1230            let progress_data = serde_json::to_string(&self.state.stats).map_err(|e| {
1231                FeedbackError::SessionError {
1232                    message: format!("Failed to serialize progress data: {e}"),
1233                    source: Some(Box::new(e)),
1234                }
1235            })?;
1236
1237            log::debug!("Progress data (persistence disabled): {progress_data}");
1238        }
1239
1240        Ok(())
1241    }
1242}
1243
1244// ============================================================================
1245// Utility Functions
1246// ============================================================================
1247
1248/// Create a default feedback configuration
1249#[must_use]
1250pub fn default_feedback_config() -> FeedbackConfig {
1251    FeedbackConfig::default()
1252}
1253
1254/// Create a default adaptive configuration
1255#[must_use]
1256pub fn default_adaptive_config() -> AdaptiveConfig {
1257    AdaptiveConfig::default()
1258}
1259
1260/// Create a default progress configuration
1261#[must_use]
1262pub fn default_progress_config() -> ProgressConfig {
1263    ProgressConfig::default()
1264}
1265
1266/// Validate feedback configuration
1267pub fn validate_feedback_config(config: &FeedbackConfig) -> Result<(), FeedbackError> {
1268    if config.response_timeout_ms < 100 {
1269        return Err(FeedbackError::ConfigurationError {
1270            message: "Response timeout must be at least 100ms".to_string(),
1271        });
1272    }
1273
1274    if config.feedback_detail_level > 1.0 || config.feedback_detail_level < 0.0 {
1275        return Err(FeedbackError::ConfigurationError {
1276            message: "Feedback detail level must be between 0.0 and 1.0".to_string(),
1277        });
1278    }
1279
1280    Ok(())
1281}
1282
1283/// Calculate feedback priority based on error severity
1284#[must_use]
1285pub fn calculate_feedback_priority(quality_score: f32, pronunciation_score: f32) -> f32 {
1286    let quality_urgency = 1.0 - quality_score;
1287    let pronunciation_urgency = 1.0 - pronunciation_score;
1288
1289    // Weight pronunciation errors as more urgent for learning
1290    (quality_urgency * 0.4 + pronunciation_urgency * 0.6).min(1.0)
1291}
1292
1293/// Format feedback message for different audiences
1294#[must_use]
1295pub fn format_feedback_message(feedback: &UserFeedback, audience: FeedbackAudience) -> String {
1296    match audience {
1297        FeedbackAudience::Beginner => {
1298            let suggestion = feedback.suggestion.as_deref().unwrap_or("Keep practicing!");
1299            format!("šŸ’” {}\n\nšŸ“š Tip: {suggestion}", feedback.message)
1300        }
1301        FeedbackAudience::Intermediate => {
1302            let suggestion = feedback
1303                .suggestion
1304                .as_deref()
1305                .unwrap_or("Continue refining your technique");
1306            format!("Analysis: {}\nImprovement: {suggestion}", feedback.message)
1307        }
1308        FeedbackAudience::Advanced => {
1309            let confidence = feedback.confidence * 100.0;
1310            let suggestion = feedback
1311                .suggestion
1312                .as_deref()
1313                .unwrap_or("Focus on advanced techniques");
1314            format!(
1315                "Technical feedback: {} (Confidence: {confidence:.1}%)\nOptimization: {suggestion}",
1316                feedback.message
1317            )
1318        }
1319        FeedbackAudience::Developer => {
1320            let message = &feedback.message;
1321            let score = feedback.score;
1322            let priority = feedback.priority;
1323            let metadata = &feedback.metadata;
1324            format!(
1325                    "Debug: {message} | Score: {score:.3} | Priority: {priority:.3} | Metrics: {metadata:?}"
1326                )
1327        }
1328    }
1329}
1330
1331/// Feedback audience types
1332#[derive(Debug, Clone, PartialEq)]
1333pub enum FeedbackAudience {
1334    /// Beginner users
1335    Beginner,
1336    /// Intermediate users
1337    Intermediate,
1338    /// Advanced users
1339    Advanced,
1340    /// Developers and researchers
1341    Developer,
1342}
1343
1344// ============================================================================
1345// Enhanced Performance Monitoring and Benchmarking
1346// ============================================================================
1347
1348/// Performance benchmark results for system analysis
1349#[derive(Debug, Clone)]
1350pub struct PerformanceBenchmark {
1351    /// Audio processing throughput (samples per second)
1352    pub audio_throughput: f32,
1353    /// Feedback generation rate (requests per second)
1354    pub feedback_generation_rate: f32,
1355    /// Memory usage statistics
1356    pub memory_usage: MemoryUsageStats,
1357    /// CPU utilization percentage
1358    pub cpu_utilization: f32,
1359    /// Real-time factor (processing time / audio duration)
1360    pub real_time_factor: f32,
1361    /// Benchmark timestamp
1362    pub timestamp: chrono::DateTime<chrono::Utc>,
1363}
1364
1365/// Memory usage statistics
1366#[derive(Debug, Clone)]
1367pub struct MemoryUsageStats {
1368    /// Current memory usage in bytes
1369    pub current_usage_bytes: usize,
1370    /// Peak memory usage in bytes
1371    pub peak_usage_bytes: usize,
1372    /// Memory allocation rate (allocations per second)
1373    pub allocation_rate: f32,
1374    /// Buffer pool efficiency (0.0 to 1.0)
1375    pub buffer_pool_efficiency: f32,
1376}
1377
1378/// Enhanced system performance profiler
1379pub struct SystemProfiler {
1380    /// Start time for profiling session
1381    start_time: std::time::Instant,
1382    /// Collected performance samples
1383    samples: Vec<PerformanceSample>,
1384    /// Profiling configuration
1385    config: ProfilerConfig,
1386}
1387
1388/// Individual performance sample
1389#[derive(Debug, Clone)]
1390struct PerformanceSample {
1391    /// Sample timestamp
1392    timestamp: std::time::Instant,
1393    /// Audio processing time
1394    audio_processing_time: Duration,
1395    /// Feedback generation time
1396    feedback_generation_time: Duration,
1397    /// Memory usage at sample time
1398    memory_usage: usize,
1399    /// Active session count
1400    active_sessions: usize,
1401}
1402
1403/// Profiler configuration
1404#[derive(Debug, Clone)]
1405pub struct ProfilerConfig {
1406    /// Sample collection interval
1407    pub sample_interval: Duration,
1408    /// Maximum number of samples to retain
1409    pub max_samples: usize,
1410    /// Enable detailed memory tracking
1411    pub enable_memory_tracking: bool,
1412    /// Enable CPU profiling
1413    pub enable_cpu_profiling: bool,
1414}
1415
1416impl Default for ProfilerConfig {
1417    fn default() -> Self {
1418        Self {
1419            sample_interval: Duration::from_secs(10),
1420            max_samples: 1000,
1421            enable_memory_tracking: true,
1422            enable_cpu_profiling: false, // Disabled by default for performance
1423        }
1424    }
1425}
1426
1427impl SystemProfiler {
1428    /// Create new system profiler
1429    #[must_use]
1430    pub fn new(config: ProfilerConfig) -> Self {
1431        log::info!("Initializing system profiler with config: {config:?}");
1432
1433        Self {
1434            start_time: std::time::Instant::now(),
1435            samples: Vec::with_capacity(config.max_samples),
1436            config,
1437        }
1438    }
1439
1440    /// Record a performance sample
1441    pub fn record_sample(
1442        &mut self,
1443        audio_processing_time: Duration,
1444        feedback_generation_time: Duration,
1445        active_sessions: usize,
1446    ) {
1447        let memory_usage = if self.config.enable_memory_tracking {
1448            self.get_current_memory_usage()
1449        } else {
1450            0
1451        };
1452
1453        let sample = PerformanceSample {
1454            timestamp: std::time::Instant::now(),
1455            audio_processing_time,
1456            feedback_generation_time,
1457            memory_usage,
1458            active_sessions,
1459        };
1460
1461        self.samples.push(sample);
1462
1463        // Keep samples within limit
1464        if self.samples.len() > self.config.max_samples {
1465            self.samples.remove(0);
1466        }
1467
1468        log::debug!(
1469            "Recorded performance sample: audio_time={:?}, feedback_time={:?}, memory={}KB, sessions={}",
1470            audio_processing_time,
1471            feedback_generation_time,
1472            memory_usage / 1024,
1473            active_sessions
1474        );
1475    }
1476
1477    /// Generate comprehensive performance benchmark
1478    pub fn generate_benchmark(&self) -> Result<PerformanceBenchmark, FeedbackError> {
1479        if self.samples.is_empty() {
1480            return Err(FeedbackError::ConfigurationError {
1481                message: "No performance samples available for benchmark".to_string(),
1482            });
1483        }
1484
1485        let total_audio_time: Duration = self.samples.iter().map(|s| s.audio_processing_time).sum();
1486
1487        let total_feedback_time: Duration = self
1488            .samples
1489            .iter()
1490            .map(|s| s.feedback_generation_time)
1491            .sum();
1492
1493        let total_session_time = self.start_time.elapsed();
1494
1495        // Calculate throughput metrics
1496        let audio_throughput = if total_session_time.as_secs_f32() > 0.0 {
1497            // Assume 16kHz sample rate for throughput calculation
1498            (self.samples.len() * 16000) as f32 / total_session_time.as_secs_f32()
1499        } else {
1500            0.0
1501        };
1502
1503        let feedback_generation_rate = if total_session_time.as_secs_f32() > 0.0 {
1504            self.samples.len() as f32 / total_session_time.as_secs_f32()
1505        } else {
1506            0.0
1507        };
1508
1509        // Calculate real-time factor
1510        let real_time_factor = if total_audio_time.as_secs_f32() > 0.0 {
1511            total_feedback_time.as_secs_f32() / total_audio_time.as_secs_f32()
1512        } else {
1513            0.0
1514        };
1515
1516        // Memory usage statistics
1517        let memory_usage = self.calculate_memory_stats();
1518
1519        // CPU utilization (simplified calculation)
1520        let cpu_utilization = self.estimate_cpu_utilization();
1521
1522        let benchmark = PerformanceBenchmark {
1523            audio_throughput,
1524            feedback_generation_rate,
1525            memory_usage,
1526            cpu_utilization,
1527            real_time_factor,
1528            timestamp: chrono::Utc::now(),
1529        };
1530
1531        log::info!(
1532            "Generated performance benchmark: throughput={:.0} samples/s, rate={:.2} req/s, RTF={:.3}, CPU={:.1}%",
1533            benchmark.audio_throughput,
1534            benchmark.feedback_generation_rate,
1535            benchmark.real_time_factor,
1536            benchmark.cpu_utilization
1537        );
1538
1539        Ok(benchmark)
1540    }
1541
1542    /// Get current memory usage in bytes
1543    fn get_current_memory_usage(&self) -> usize {
1544        // Simplified memory usage estimation
1545        // In a real implementation, this would use platform-specific APIs
1546        std::mem::size_of::<Self>()
1547            + (self.samples.len() * std::mem::size_of::<PerformanceSample>())
1548    }
1549
1550    /// Calculate memory usage statistics
1551    fn calculate_memory_stats(&self) -> MemoryUsageStats {
1552        if self.samples.is_empty() {
1553            return MemoryUsageStats {
1554                current_usage_bytes: 0,
1555                peak_usage_bytes: 0,
1556                allocation_rate: 0.0,
1557                buffer_pool_efficiency: 1.0,
1558            };
1559        }
1560
1561        let current_usage = self.samples.last().unwrap().memory_usage;
1562        let peak_usage = self
1563            .samples
1564            .iter()
1565            .map(|s| s.memory_usage)
1566            .max()
1567            .unwrap_or(0);
1568
1569        let allocation_rate = if self.start_time.elapsed().as_secs_f32() > 0.0 {
1570            self.samples.len() as f32 / self.start_time.elapsed().as_secs_f32()
1571        } else {
1572            0.0
1573        };
1574
1575        // Buffer pool efficiency (simplified calculation)
1576        let buffer_pool_efficiency = if peak_usage > 0 {
1577            (current_usage as f32 / peak_usage as f32).min(1.0)
1578        } else {
1579            1.0
1580        };
1581
1582        MemoryUsageStats {
1583            current_usage_bytes: current_usage,
1584            peak_usage_bytes: peak_usage,
1585            allocation_rate,
1586            buffer_pool_efficiency,
1587        }
1588    }
1589
1590    /// Estimate CPU utilization
1591    fn estimate_cpu_utilization(&self) -> f32 {
1592        if self.samples.is_empty() {
1593            return 0.0;
1594        }
1595
1596        // Simplified CPU utilization calculation
1597        // In reality, this would use platform-specific performance counters
1598        let total_processing_time: Duration = self
1599            .samples
1600            .iter()
1601            .map(|s| s.audio_processing_time + s.feedback_generation_time)
1602            .sum();
1603
1604        let total_wall_time = self.start_time.elapsed();
1605
1606        if total_wall_time.as_secs_f32() > 0.0 {
1607            (total_processing_time.as_secs_f32() / total_wall_time.as_secs_f32() * 100.0).min(100.0)
1608        } else {
1609            0.0
1610        }
1611    }
1612
1613    /// Reset profiler and clear collected samples
1614    pub fn reset(&mut self) {
1615        log::info!(
1616            "Resetting system profiler - clearing {} samples",
1617            self.samples.len()
1618        );
1619        self.start_time = std::time::Instant::now();
1620        self.samples.clear();
1621    }
1622
1623    /// Get current sample count
1624    #[must_use]
1625    pub fn sample_count(&self) -> usize {
1626        self.samples.len()
1627    }
1628
1629    /// Get profiling duration
1630    #[must_use]
1631    pub fn profiling_duration(&self) -> Duration {
1632        self.start_time.elapsed()
1633    }
1634}
1635
1636#[cfg(test)]
1637mod tests {
1638    use super::*;
1639
1640    #[test]
1641    fn test_version() {
1642        assert!(!VERSION.is_empty());
1643    }
1644
1645    #[test]
1646    fn test_default_configs() {
1647        let feedback_config = default_feedback_config();
1648        assert!(feedback_config.enable_realtime);
1649
1650        let adaptive_config = default_adaptive_config();
1651        assert!(adaptive_config.enable_learning);
1652
1653        let progress_config = default_progress_config();
1654        assert!(progress_config.track_improvements);
1655    }
1656
1657    #[test]
1658    fn test_config_validation() {
1659        let mut config = default_feedback_config();
1660        assert!(validate_feedback_config(&config).is_ok());
1661
1662        // Test invalid timeout
1663        config.response_timeout_ms = 50;
1664        assert!(validate_feedback_config(&config).is_err());
1665
1666        // Test invalid detail level
1667        config.response_timeout_ms = 200;
1668        config.feedback_detail_level = 1.5;
1669        assert!(validate_feedback_config(&config).is_err());
1670    }
1671
1672    #[test]
1673    fn test_feedback_priority() {
1674        let priority = calculate_feedback_priority(0.8, 0.6);
1675        assert!(priority > 0.0);
1676        assert!(priority <= 1.0);
1677
1678        // Low quality should increase priority
1679        let high_priority = calculate_feedback_priority(0.3, 0.3);
1680        assert!(high_priority > priority);
1681    }
1682
1683    #[test]
1684    fn test_feedback_formatting() {
1685        let feedback = UserFeedback {
1686            message: "Test message".to_string(),
1687            suggestion: Some("Test suggestion".to_string()),
1688            confidence: 0.85,
1689            score: 0.7,
1690            priority: 0.5,
1691            metadata: std::collections::HashMap::new(),
1692        };
1693
1694        let beginner_msg = format_feedback_message(&feedback, FeedbackAudience::Beginner);
1695        assert!(beginner_msg.contains("šŸ’”"));
1696        assert!(beginner_msg.contains("šŸ“š"));
1697
1698        let developer_msg = format_feedback_message(&feedback, FeedbackAudience::Developer);
1699        assert!(developer_msg.contains("Debug:"));
1700        assert!(developer_msg.contains("Score:"));
1701    }
1702}