use crate::domain::metrics::constants;
use nutype::nutype;
use serde::{Deserialize, Serialize};
#[nutype(
validate(greater = 0),
derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Serialize,
Deserialize,
Hash
)
)]
pub struct SampleCount(u64);
impl SampleCount {
pub fn small() -> Self {
Self::try_new(50).unwrap()
}
pub fn medium() -> Self {
Self::try_new(250).unwrap()
}
pub fn large() -> Self {
Self::try_new(1000).unwrap()
}
pub fn tiny() -> Self {
Self::try_new(10).unwrap()
}
pub fn is_statistically_significant(&self) -> bool {
self.into_inner() >= constants::statistical::MIN_SIGNIFICANT_SAMPLE_SIZE
}
pub fn confidence_category(&self) -> SampleConfidence {
match self.into_inner() {
n if n < constants::statistical::MIN_SIGNIFICANT_SAMPLE_SIZE => SampleConfidence::Low,
n if n < constants::statistical::RECOMMENDED_MIN_SAMPLE_SIZE => {
SampleConfidence::Moderate
}
n if n < constants::statistical::LARGE_SAMPLE_THRESHOLD => SampleConfidence::High,
_ => SampleConfidence::VeryHigh,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum SampleConfidence {
Low,
Moderate,
High,
VeryHigh,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_sample_count_validation() {
assert!(SampleCount::try_new(1).is_ok());
assert!(SampleCount::try_new(1000).is_ok());
assert!(SampleCount::try_new(0).is_err());
}
#[test]
fn test_statistical_significance() {
assert!(!SampleCount::try_new(10)
.unwrap()
.is_statistically_significant());
assert!(SampleCount::try_new(30)
.unwrap()
.is_statistically_significant());
assert!(SampleCount::try_new(100)
.unwrap()
.is_statistically_significant());
}
#[test]
fn test_confidence_categories() {
assert_eq!(
SampleCount::try_new(10).unwrap().confidence_category(),
SampleConfidence::Low
);
assert_eq!(
SampleCount::try_new(50).unwrap().confidence_category(),
SampleConfidence::Moderate
);
assert_eq!(
SampleCount::try_new(250).unwrap().confidence_category(),
SampleConfidence::High
);
}
}