use crate::types::Match;
pub fn calculate_relevance_score_pure(
line_content: &str,
query: &str,
line_number: usize,
file_extension: Option<&str>,
is_fuzzy: bool,
fuzzy_score: Option<i64>,
) -> f64 {
let mut score = 50.0;
if line_content.contains(query) {
score += 20.0;
}
if line_content == query {
score += 30.0;
}
if line_content.trim_start().starts_with(query) {
score += 15.0;
}
if line_content.len() < 80 {
score += 10.0;
}
if line_number < 50 {
score += 5.0;
}
if let Some(ext) = file_extension {
match ext {
"rs" | "py" | "js" | "ts" => score += 5.0,
_ => {}
}
}
if is_fuzzy {
if let Some(fs) = fuzzy_score {
score = (score + fs as f64) / 2.0;
}
}
score.clamp(0.0, 100.0)
}
pub fn relevance_category(score: f64) -> &'static str {
if score >= 80.0 {
"Very High"
} else if score >= 60.0 {
"High"
} else if score >= 40.0 {
"Medium"
} else {
"Low"
}
}
pub fn extract_matches_pure(_line: &str, start: usize, end: usize, text: &str) -> Match {
Match {
start,
end,
text: text.to_string(),
}
}
pub fn fuzzy_match_quality(score: i64, query_length: usize, line_length: usize) -> f64 {
let normalized = score as f64 / (query_length as f64 * 10.0);
let length_penalty = 1.0 - (line_length as f64 / 1000.0).min(0.5);
(normalized * length_penalty).clamp(0.0, 1.0)
}
pub fn should_include_line(
line: &str,
min_length: usize,
max_length: usize,
exclude_patterns: &[&str],
) -> bool {
let len = line.len();
if len < min_length || len > max_length {
return false;
}
for pattern in exclude_patterns {
if line.contains(pattern) {
return false;
}
}
true
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_calculate_relevance_score_pure() {
let score =
calculate_relevance_score_pure("fn test() {", "test", 10, Some("rs"), false, None);
assert!(score > 50.0);
assert!(score <= 100.0);
}
#[test]
fn test_exact_match_boost() {
let score = calculate_relevance_score_pure("test", "test", 10, None, false, None);
assert!(score > 80.0); }
#[test]
fn test_relevance_category() {
assert_eq!(relevance_category(90.0), "Very High");
assert_eq!(relevance_category(70.0), "High");
assert_eq!(relevance_category(50.0), "Medium");
assert_eq!(relevance_category(30.0), "Low");
}
#[test]
fn test_fuzzy_match_quality() {
let quality = fuzzy_match_quality(100, 4, 50);
assert!(quality > 0.0 && quality <= 1.0);
}
#[test]
fn test_should_include_line() {
assert!(should_include_line("test line", 5, 100, &[]));
assert!(!should_include_line("test", 5, 100, &[])); assert!(should_include_line("test line", 5, 100, &["exclude"])); assert!(!should_include_line(
"test exclude line",
5,
100,
&["exclude"]
)); }
#[test]
fn test_file_extension_boost() {
let score_rs = calculate_relevance_score_pure("test", "test", 10, Some("rs"), false, None);
let score_txt =
calculate_relevance_score_pure("test", "test", 10, Some("txt"), false, None);
assert!(score_rs >= score_txt);
assert!(score_rs >= 95.0); }
#[test]
fn test_early_line_boost() {
let score_early = calculate_relevance_score_pure("test", "test", 10, None, false, None);
let score_late = calculate_relevance_score_pure("test", "test", 100, None, false, None);
assert!(score_early >= score_late);
assert!(score_early >= 95.0); }
}