use super::level::QualityLevel;
#[derive(Debug, Clone, Copy)]
pub struct QualityConfig {
pub target_frame_rate: f32,
pub degrade_threshold: f32,
pub upgrade_threshold: f32,
pub max_quality: QualityLevel,
pub min_quality: QualityLevel,
pub degrade_frame_count: usize,
pub upgrade_frame_count: usize,
}
impl Default for QualityConfig {
fn default() -> Self {
Self {
target_frame_rate: 60.0,
degrade_threshold: 1.5,
upgrade_threshold: 0.7,
max_quality: QualityLevel::High,
min_quality: QualityLevel::Low,
degrade_frame_count: 5,
upgrade_frame_count: 10,
}
}
}
impl QualityConfig {
pub fn target_frame_duration(&self) -> f32 {
1.0 / self.target_frame_rate
}
pub fn degrade_frame_duration(&self) -> f32 {
self.target_frame_duration() * self.degrade_threshold
}
pub fn upgrade_frame_duration(&self) -> f32 {
self.target_frame_duration() * self.upgrade_threshold
}
pub fn normalized(self) -> Self {
let (min_quality, max_quality) = if self.min_quality > self.max_quality {
(self.max_quality, self.min_quality)
} else {
(self.min_quality, self.max_quality)
};
Self {
degrade_threshold: self.degrade_threshold.max(1.0),
upgrade_threshold: self.upgrade_threshold.clamp(0.1, 1.0),
degrade_frame_count: self.degrade_frame_count.max(1),
upgrade_frame_count: self.upgrade_frame_count.max(1),
min_quality,
max_quality,
..self
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::quality::QualityManager;
#[test]
fn normalized_repairs_inverted_quality_range() {
let inverted = QualityConfig {
min_quality: QualityLevel::High,
max_quality: QualityLevel::Low,
..QualityConfig::default()
};
let fixed = inverted.normalized();
assert!(fixed.min_quality <= fixed.max_quality);
assert_eq!(fixed.min_quality, QualityLevel::Low);
assert_eq!(fixed.max_quality, QualityLevel::High);
}
#[test]
fn inverted_config_through_manager_does_not_panic() {
let inverted = QualityConfig {
min_quality: QualityLevel::High,
max_quality: QualityLevel::Low,
..QualityConfig::default()
};
let mut manager = QualityManager::with_config(inverted);
let _ = manager.quality_level();
manager.set_quality_level(QualityLevel::Medium);
let selected = manager.quality_level();
assert!(selected >= manager.config().min_quality);
assert!(selected <= manager.config().max_quality);
manager.set_config(inverted);
manager.set_quality_level(QualityLevel::High);
let selected = manager.quality_level();
assert!(selected >= manager.config().min_quality);
assert!(selected <= manager.config().max_quality);
}
#[test]
fn normalized_clamps_thresholds_and_counts() {
let config = QualityConfig {
degrade_threshold: 0.1,
upgrade_threshold: 5.0,
degrade_frame_count: 0,
upgrade_frame_count: 0,
..QualityConfig::default()
};
let fixed = config.normalized();
assert_eq!(fixed.degrade_threshold, 1.0);
assert_eq!(fixed.upgrade_threshold, 1.0);
assert_eq!(fixed.degrade_frame_count, 1);
assert_eq!(fixed.upgrade_frame_count, 1);
}
}