use crate::formula::{grade_clamp, inputs, round_to, Formula, FormulaResult};
use crate::language::Language;
use crate::text::TextStatistics;
const FLESCH_LANGS: &[&str] = &[
"en-us",
"en-gb",
"de-1996",
"de-1901",
"de-ch-1901",
"ru",
"es",
"it",
"fr",
"nl",
"pt",
"tr",
];
pub struct FleschReadingEase;
impl Formula for FleschReadingEase {
fn name(&self) -> &'static str {
"flesch_reading_ease"
}
fn description(&self) -> &'static str {
"Flesch Reading Ease - measures text readability on a 0-100 scale (higher = easier). Coefficients vary by language."
}
fn supported_languages(&self) -> &'static [&'static str] {
FLESCH_LANGS
}
fn calculate(&self, stats: &TextStatistics, language: &Language) -> FormulaResult {
let base = language
.formula_number(self.name(), "base")
.unwrap_or(206.835);
let asl = language
.formula_number(self.name(), "aslMult")
.unwrap_or(1.015);
let asw = language
.formula_number(self.name(), "aswMult")
.unwrap_or(84.6);
let score =
base - asl * stats.average_words_per_sentence - asw * stats.average_syllables_per_word;
FormulaResult {
formula_name: self.name().to_string(),
language_code: language.code.clone(),
score: round_to(score, 1),
grade_level: None,
interpretation: interpret_fre(score).to_string(),
inputs: inputs(&[
("asl", stats.average_words_per_sentence),
("asw", stats.average_syllables_per_word),
]),
}
}
}
fn interpret_fre(score: f64) -> &'static str {
if score >= 90.0 {
"Very Easy"
} else if score >= 80.0 {
"Easy"
} else if score >= 70.0 {
"Fairly Easy"
} else if score >= 60.0 {
"Standard"
} else if score >= 50.0 {
"Fairly Hard"
} else if score >= 30.0 {
"Hard"
} else {
"Very Hard"
}
}
pub struct FleschKincaidGradeLevel;
impl Formula for FleschKincaidGradeLevel {
fn name(&self) -> &'static str {
"flesch_kincaid_grade_level"
}
fn description(&self) -> &'static str {
"Flesch-Kincaid Grade Level - converts Reading Ease into a U.S. school grade level."
}
fn supported_languages(&self) -> &'static [&'static str] {
FLESCH_LANGS
}
fn calculate(&self, stats: &TextStatistics, language: &Language) -> FormulaResult {
let score = 0.39 * stats.average_words_per_sentence
+ 11.8 * stats.average_syllables_per_word
- 15.59;
FormulaResult {
formula_name: self.name().to_string(),
language_code: language.code.clone(),
score: round_to(score, 1),
grade_level: Some(grade_clamp(score, 0.0, 18.0)),
interpretation: interpret_fkgl(score).to_string(),
inputs: inputs(&[
("asl", stats.average_words_per_sentence),
("asw", stats.average_syllables_per_word),
]),
}
}
}
fn interpret_fkgl(score: f64) -> &'static str {
if score <= 1.0 {
"1st Grade"
} else if score <= 2.0 {
"2nd Grade"
} else if score <= 3.0 {
"3rd Grade"
} else if score <= 4.0 {
"4th Grade"
} else if score <= 5.0 {
"5th Grade"
} else if score <= 6.0 {
"6th Grade"
} else if score <= 7.0 {
"7th Grade"
} else if score <= 8.0 {
"8th Grade"
} else if score <= 9.0 {
"9th Grade"
} else if score <= 10.0 {
"10th Grade"
} else if score <= 11.0 {
"11th Grade"
} else if score <= 12.0 {
"12th Grade"
} else if score <= 16.0 {
"College"
} else {
"Graduate"
}
}