readsight 1.0.2

Multilingual readability library — 86 languages, 17 formulas, TeX-based syllable counting via the Frank M. Liang algorithm.
Documentation
//! Spanish formulas: Fernández-Huerta, Szigriszt-Pazos, Gutiérrez-Polini, Crawford.

use crate::formula::{inputs, round_to, Formula, FormulaResult};
use crate::language::Language;
use crate::text::TextStatistics;

/// Fernández-Huerta readability.
pub struct FernandezHuerta;

impl Formula for FernandezHuerta {
    fn name(&self) -> &'static str {
        "fernandez_huerta"
    }
    fn description(&self) -> &'static str {
        "Fernandez-Huerta - Spanish adaptation of Flesch Reading Ease."
    }
    fn supported_languages(&self) -> &'static [&'static str] {
        &["es"]
    }
    fn calculate(&self, stats: &TextStatistics, language: &Language) -> FormulaResult {
        let score = 206.84
            - 1.02 * stats.average_words_per_sentence
            - 60.0 * 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_es_ease(score).to_string(),
            inputs: inputs(&[
                ("asl", stats.average_words_per_sentence),
                ("asw", stats.average_syllables_per_word),
            ]),
        }
    }
}

fn interpret_es_ease(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 Difficult"
    } else if score >= 30.0 {
        "Difficult"
    } else {
        "Very Difficult"
    }
}

/// Szigriszt-Pazos Perspicuity Index.
pub struct SzigrisztPazos;

impl Formula for SzigrisztPazos {
    fn name(&self) -> &'static str {
        "szigriszt_pazos"
    }
    fn description(&self) -> &'static str {
        "Szigriszt-Pazos Perspicuity Index - Spanish readability formula."
    }
    fn supported_languages(&self) -> &'static [&'static str] {
        &["es"]
    }
    fn calculate(&self, stats: &TextStatistics, language: &Language) -> FormulaResult {
        let w = stats.word_count.max(1) as f64;
        let p = stats.average_words_per_sentence;
        let syllables_per_word = stats.syllable_count as f64 / w;
        let syllables_per_100 = round_to(syllables_per_word * 100.0, 1);
        let score = round_to(206.835 - 62.3 * syllables_per_word - p, 1);
        FormulaResult {
            formula_name: self.name().to_string(),
            language_code: language.code.clone(),
            score,
            grade_level: None,
            interpretation: interpret_szigriszt(score).to_string(),
            inputs: inputs(&[
                ("syllablesPer100", syllables_per_100),
                ("wordsPerSentence", round_to(p, 1)),
            ]),
        }
    }
}

fn interpret_szigriszt(score: f64) -> &'static str {
    if score >= 85.0 {
        "Very Easy"
    } else if score >= 75.0 {
        "Easy"
    } else if score >= 65.0 {
        "Fairly Easy"
    } else if score >= 55.0 {
        "Standard"
    } else if score >= 40.0 {
        "Fairly Difficult"
    } else if score >= 30.0 {
        "Difficult"
    } else {
        "Very Difficult"
    }
}

/// Gutiérrez de Polini Understandability Index.
pub struct GutierrezPolini;

impl Formula for GutierrezPolini {
    fn name(&self) -> &'static str {
        "gutierrez_polini"
    }
    fn description(&self) -> &'static str {
        "Gutierrez de Polini Understandability Index - Spanish readability for elementary education."
    }
    fn supported_languages(&self) -> &'static [&'static str] {
        &["es"]
    }
    fn calculate(&self, stats: &TextStatistics, language: &Language) -> FormulaResult {
        let w = stats.word_count.max(1) as f64;
        let score =
            95.2 - 9.7 * (stats.letter_count as f64 / w) - 0.35 * stats.average_words_per_sentence;
        FormulaResult {
            formula_name: self.name().to_string(),
            language_code: language.code.clone(),
            score: round_to(score, 1),
            grade_level: None,
            interpretation: interpret_gutierrez(score).to_string(),
            inputs: inputs(&[
                ("lettersPerWord", round_to(stats.letter_count as f64 / w, 2)),
                (
                    "wordsPerSentence",
                    round_to(stats.average_words_per_sentence, 2),
                ),
            ]),
        }
    }
}

fn interpret_gutierrez(score: f64) -> &'static str {
    if score >= 80.0 {
        "Very Easy"
    } else if score >= 70.0 {
        "Easy"
    } else if score >= 50.0 {
        "Standard"
    } else if score >= 30.0 {
        "Difficult"
    } else {
        "Very Difficult"
    }
}

/// Crawford formula (years of schooling).
pub struct Crawford;

impl Formula for Crawford {
    fn name(&self) -> &'static str {
        "crawford"
    }
    fn description(&self) -> &'static str {
        "Crawford Formula - Spanish readability for elementary school texts. Returns years of schooling."
    }
    fn supported_languages(&self) -> &'static [&'static str] {
        &["es"]
    }
    fn calculate(&self, stats: &TextStatistics, language: &Language) -> FormulaResult {
        let w = stats.word_count.max(1) as f64;
        let s = stats.sentence_count.max(1) as f64;
        let average_letters = stats.letter_count as f64 / w;
        let sentences_per_100 = (s / w) * 100.0;
        let score = -0.205 * average_letters + 0.049 * sentences_per_100 - 3.407;
        FormulaResult {
            formula_name: self.name().to_string(),
            language_code: language.code.clone(),
            score: round_to(score, 1),
            grade_level: None,
            interpretation: interpret_crawford(score).to_string(),
            inputs: inputs(&[
                ("avgLettersPerWord", round_to(average_letters, 2)),
                ("sentencesPer100Words", round_to(sentences_per_100, 2)),
            ]),
        }
    }
}

fn interpret_crawford(score: f64) -> &'static str {
    if score >= 9.0 {
        "Very Easy"
    } else if score >= 7.0 {
        "Easy"
    } else if score >= 5.0 {
        "Standard"
    } else if score >= 3.0 {
        "Difficult"
    } else {
        "Very Difficult"
    }
}