#![cfg_attr(coverage_nightly, coverage(off))]
use crate::services::popper_score::models::{PopperCategoryScore, PopperFinding, PopperSubScore};
use crate::services::popper_score::scorer::{workspace, PopperScorer, PopperScorerResult};
use regex::Regex;
use std::path::Path;
pub struct FalsifiabilityScorer;
include!("falsifiability_scoring.rs");
include!("falsifiability_helpers.rs");
impl Default for FalsifiabilityScorer {
fn default() -> Self {
Self::new()
}
}
impl PopperScorer for FalsifiabilityScorer {
fn name(&self) -> &str {
"Falsifiability & Testability"
}
fn category_id(&self) -> char {
'A'
}
fn max_points(&self) -> f64 {
25.0
}
fn score(&self, project_path: &Path) -> PopperScorerResult<PopperCategoryScore> {
let mut category = PopperCategoryScore::new(self.name(), 0.0, self.max_points());
let a1 = self.score_hypothesis_documentation(project_path);
let a2 = self.score_test_coverage(project_path);
let a3 = self.score_benchmark_reproducibility(project_path);
if a1.earned < 4.0 {
category.add_finding(PopperFinding::warning(
"Hypothesis documentation is incomplete - add explicit falsifiable claims to README",
8.0 - a1.earned,
));
} else {
category.add_finding(PopperFinding::positive("Good hypothesis documentation"));
}
if a2.earned < 6.0 {
category.add_finding(PopperFinding::warning(
"Test coverage needs improvement - consider adding property-based or mutation tests",
10.0 - a2.earned,
));
} else {
category.add_finding(PopperFinding::positive("Good test coverage"));
}
if a3.earned < 4.0 {
category.add_finding(PopperFinding::warning(
"Benchmark reproducibility could be improved - add confidence intervals",
7.0 - a3.earned,
));
}
category.add_sub_score(a1);
category.add_sub_score(a2);
category.add_sub_score(a3);
Ok(category)
}
}
include!("falsifiability_tests.rs");