<commit_before>/* LanguageTool, a natural language style checker 
 * Copyright (C) 2005 <NAME> (http://www.danielnaber.de)
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

package org.languagetool.rules;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.regex.Pattern;

import org.languagetool.AnalyzedSentence;
import org.languagetool.AnalyzedTokenReadings;
import org.languagetool.Language;
import org.languagetool.LinguServices;
import org.languagetool.UserConfig;
import org.languagetool.rules.Category;
import org.languagetool.rules.CategoryId;
import org.languagetool.rules.ITSIssueType;
import org.languagetool.rules.RuleMatch;
import org.languagetool.rules.TextLevelRule;
import org.languagetool.rules.Category.Location;

/**
 * A rule that checks the readability of English text (using the Flesch-Reading-Ease Formula)
 * @author <NAME>
 * @since 4.4
 */
public class ReadabilityRule extends TextLevelRule {

  private static final int MARK_DISTANCE = 10;
  private static final int MIN_WORDS = 10;
  private static final Pattern NON_WORD_REGEX = Pattern.compile("[.?!…:;,~’'\"„“”»«‚‘›‹()\\[\\]\\-–—*×∗·+÷/=]");

  private final LinguServices linguServices;
  private final Language lang;
  private int level;
  private boolean isToEasy;

  public ReadabilityRule(ResourceBundle messages, Language lang, UserConfig userConfig, boolean isToEasy) {
    this (messages, lang, userConfig, isToEasy, -1, false);
  }
  
  public ReadabilityRule(ResourceBundle messages, Language lang, UserConfig userConfig, boolean isToEasy, int level) {
    this (messages, lang, userConfig, isToEasy, level, false);
  }
  
  public ReadabilityRule(ResourceBundle messages, Language lang, UserConfig userConfig, boolean isToEasy, boolean defaultOn) {
    this (messages, lang, userConfig, isToEasy, -1, defaultOn);
  }
  
  public ReadabilityRule(ResourceBundle messages, Language lang, UserConfig userConfig, 
      boolean isToEasy, int level, boolean defaultOn) {
    super(messages);
    super.setCategory(new Category(new CategoryId("TEXT_ANALYSIS"), "Text Analysis", Location.INTERNAL, false));
    setLocQualityIssueType(ITSIssueType.Style);
    if(!defaultOn) {
      setDefaultOff();
    }
    this.lang = lang;
    this.isToEasy = isToEasy;
    if (userConfig != null) {
      linguServices = userConfig.getLinguServices();
      if(level >= 0) {
        this.level = level;
      } else {
        int lv = userConfig.getConfigValueByID(getId());
        if(lv >= 0) {
          this.level = lv;
        } else {
          this.level = isToEasy ? 4 : 2;
        }
      }
    }
    else {
      linguServices = null;
    }
  }
  
  @Override
  public String getId() {
    if(isToEasy) {
      return "READABILITY_RULE_SIMPLE";
    } else {
      return "READABILITY_RULE_DIFFICULT";
    }
  }

  @Override
  public String getDescription() {
    if(isToEasy) {
      return "Readability: Too easy text";
    } else {
      return "Readability: Too difficult text";
    }
  }

  @Override
  public int getDefaultValue() {
    return (isToEasy ? 4 : 2);
  }
  
  @Override
  public boolean hasConfigurableValue() {
    return true;
  }

  @Override
  public int getMinConfigurableValue() {
    return 0;
  }

  @Override
  public int getMaxConfigurableValue() {
    return 6;
  }
  
  @Override
  public String getConfigureText() {
    return "Level of readability 0 (very difficult) to 6 (very easy):";
  }
  
  private static String printMessageLevel(int level) {
    String sLevel = null;
    if (level == 0) {
      sLevel = "Very difficult";
    } else if (level == 1) {
      sLevel = "Difficult";
    } else if (level == 2) {
      sLevel = "Fairly difficult";
    } else if (level == 3) {
      sLevel = "Medium";
    } else if (level == 4) {
      sLevel = "Fairly easy";
    } else if (level == 5) {
      sLevel = "Easy";
    } else if (level == 6) {
      sLevel = "Very easy";
    }
    if (sLevel != null) {
      return " {Level " + level + ": " + sLevel + "}";
    }
    return "";
  }
  
  protected String getMessage(int level, int FRE, int ASL, int ASW) {
    String simple;
    String few;

    if(isToEasy) {
      simple = "simple";
      few = "few";
    } else {
      simple = "difficult";
      few = "many";
    }
    return "Readability: The text of this paragraph is too " + simple + printMessageLevel(level) + ". Too "
        + few + " words per sentence and to " + few + " syllables per word.";
  }
  
  /**
   * get level of readability (0 - 6)
   */
  private int getReadabilityLevel(double FRE) {
    if (FRE < 30) {
      return 0;
    } else if (FRE < 50) {
      return 1;
    } else if (FRE < 60) { <commit_msg>ReadabilityRule: correct another typing error<commit_after>/* LanguageTool, a natural language style checker 
 * Copyright (C) 2005 <NAME> (http://www.danielnaber.de)
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
 * USA
 */

package org.languagetool.rules;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
import java.util.regex.Pattern;

import org.languagetool.AnalyzedSentence;
import org.languagetool.AnalyzedTokenReadings;
import org.languagetool.Language;
import org.languagetool.LinguServices;
import org.languagetool.UserConfig;
import org.languagetool.rules.Category;
import org.languagetool.rules.CategoryId;
import org.languagetool.rules.ITSIssueType;
import org.languagetool.rules.RuleMatch;
import org.languagetool.rules.TextLevelRule;
import org.languagetool.rules.Category.Location;

/**
 * A rule that checks the readability of English text (using the Flesch-Reading-Ease Formula)
 * @author <NAME>
 * @since 4.4
 */
public class ReadabilityRule extends TextLevelRule {

  private static final int MARK_DISTANCE = 10;
  private static final int MIN_WORDS = 10;
  private static final Pattern NON_WORD_REGEX = Pattern.compile("[.?!…:;,~’'\"„“”»«‚‘›‹()\\[\\]\\-–—*×∗·+÷/=]");

  private final LinguServices linguServices;
  private final Language lang;
  private int level;
  private boolean isToEasy;

  public ReadabilityRule(ResourceBundle messages, Language lang, UserConfig userConfig, boolean isToEasy) {
    this (messages, lang, userConfig, isToEasy, -1, false);
  }
  
  public ReadabilityRule(ResourceBundle messages, Language lang, UserConfig userConfig, boolean isToEasy, int level) {
    this (messages, lang, userConfig, isToEasy, level, false);
  }
  
  public ReadabilityRule(ResourceBundle messages, Language lang, UserConfig userConfig, boolean isToEasy, boolean defaultOn) {
    this (messages, lang, userConfig, isToEasy, -1, defaultOn);
  }
  
  public ReadabilityRule(ResourceBundle messages, Language lang, UserConfig userConfig, 
      boolean isToEasy, int level, boolean defaultOn) {
    super(messages);
    super.setCategory(new Category(new CategoryId("TEXT_ANALYSIS"), "Text Analysis", Location.INTERNAL, false));
    setLocQualityIssueType(ITSIssueType.Style);
    if(!defaultOn) {
      setDefaultOff();
    }
    this.lang = lang;
    this.isToEasy = isToEasy;
    if (userConfig != null) {
      linguServices = userConfig.getLinguServices();
      if(level >= 0) {
        this.level = level;
      } else {
        int lv = userConfig.getConfigValueByID(getId());
        if(lv >= 0) {
          this.level = lv;
        } else {
          this.level = isToEasy ? 4 : 2;
        }
      }
    }
    else {
      linguServices = null;
    }
  }
  
  @Override
  public String getId() {
    if(isToEasy) {
      return "READABILITY_RULE_SIMPLE";
    } else {
      return "READABILITY_RULE_DIFFICULT";
    }
  }

  @Override
  public String getDescription() {
    if(isToEasy) {
      return "Readability: Too easy text";
    } else {
      return "Readability: Too difficult text";
    }
  }

  @Override
  public int getDefaultValue() {
    return (isToEasy ? 4 : 2);
  }
  
  @Override
  public boolean hasConfigurableValue() {
    return true;
  }

  @Override
  public int getMinConfigurableValue() {
    return 0;
  }

  @Override
  public int getMaxConfigurableValue() {
    return 6;
  }
  
  @Override
  public String getConfigureText() {
    return "Level of readability 0 (very difficult) to 6 (very easy):";
  }
  
  private static String printMessageLevel(int level) {
    String sLevel = null;
    if (level == 0) {
      sLevel = "Very difficult";
    } else if (level == 1) {
      sLevel = "Difficult";
    } else if (level == 2) {
      sLevel = "Fairly difficult";
    } else if (level == 3) {
      sLevel = "Medium";
    } else if (level == 4) {
      sLevel = "Fairly easy";
    } else if (level == 5) {
      sLevel = "Easy";
    } else if (level == 6) {
      sLevel = "Very easy";
    }
    if (sLevel != null) {
      return " {Level " + level + ": " + sLevel + "}";
    }
    return "";
  }
  
  protected String getMessage(int level, int FRE, int ASL, int ASW) {
    String simple;
    String few;

    if(isToEasy) {
      simple = "simple";
      few = "few";
    } else {
      simple = "difficult";
      few = "many";
    }
    return "Readability: The text of this paragraph is too " + simple + printMessageLevel(level) + ". Too "
        + few + " words per sentence and too " + few + " syllables per word.";
  }
  
  /**
   * get level of readability (0 - 6)
   */
  private int getReadabilityLevel(double FRE) {
    if (FRE < 30) {
      return 0;
    } else if (FRE < 50) {
      return 1;
    } else if (FRE < 60) { 
{'fraction_non_alphanumeric': 0.10890543148607665, 'fraction_numerical': 0.009557945041816009, 'mean_word_length': 3.0833020637898687, 'pattern_counts': {'":': 2, '<': 13, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4826062', 'n_tokens_mistral': 3533, 'n_tokens_neox': 3378, 'n_words': 1050}