use crate::unit::Unit;
pub fn relevance_score(unit: &Unit, working_paths: &[String], working_deps: &[String]) -> u32 {
let mut score = 0u32;
let path_overlap = count_path_overlap(&unit.paths, working_paths);
score += path_overlap * 3;
let dep_match = count_dependency_overlap(unit, working_deps);
score += dep_match * 5;
let age = chrono::Utc::now() - unit.updated_at;
if age.num_days() <= 1 {
score += 2;
} else if age.num_days() <= 7 {
score += 1;
}
score
}
fn count_path_overlap(unit_paths: &[String], working_paths: &[String]) -> u32 {
let mut count = 0;
for bp in unit_paths {
for wp in working_paths {
if paths_overlap(bp, wp) {
count += 1;
break;
}
}
}
count
}
fn paths_overlap(a: &str, b: &str) -> bool {
a.starts_with(b) || b.starts_with(a) || a == b
}
fn count_dependency_overlap(unit: &Unit, working_deps: &[String]) -> u32 {
let mut count = 0;
for prod in &unit.produces {
if working_deps.contains(prod) {
count += 1;
}
}
for req in &unit.requires {
if working_deps.contains(req) {
count += 1;
}
}
count
}
#[cfg(test)]
mod tests {
use super::*;
use crate::unit::Unit;
#[test]
fn test_paths_overlap_exact() {
assert!(paths_overlap("src/auth.rs", "src/auth.rs"));
}
#[test]
fn test_paths_overlap_prefix() {
assert!(paths_overlap("src/auth", "src/auth/types.rs"));
assert!(paths_overlap("src/auth/types.rs", "src/auth"));
}
#[test]
fn test_paths_no_overlap() {
assert!(!paths_overlap("src/auth.rs", "src/config.rs"));
}
#[test]
fn test_relevance_score_path_overlap() {
let mut unit = Unit::new("1", "Auth fact");
unit.paths = vec!["src/auth.rs".to_string()];
let score = relevance_score(&unit, &["src/auth.rs".to_string()], &[]);
assert!(score >= 3); }
#[test]
fn test_relevance_score_dependency_match() {
let mut unit = Unit::new("1", "Auth types");
unit.produces = vec!["AuthProvider".to_string()];
let score = relevance_score(&unit, &[], &["AuthProvider".to_string()]);
assert!(score >= 5); }
#[test]
fn test_relevance_score_combined() {
let mut unit = Unit::new("1", "Auth fact");
unit.paths = vec!["src/auth.rs".to_string()];
unit.produces = vec!["AuthProvider".to_string()];
let score = relevance_score(
&unit,
&["src/auth.rs".to_string()],
&["AuthProvider".to_string()],
);
assert!(score >= 8);
}
}