// Path: src/main/java/io/aif/language/common/StringHelper.java
// public class StringHelper {
// 
//   public static String findLongestCommonSubstring(final String t1, final String t2) {
//     String s1 = t1.toLowerCase();
//     String s2 = t2.toLowerCase();
// 
//     final int shortestWordLength = Math.min(t1.length(), t2.length());
//     Set<String> s1SubWords;
//     Set<String> s2SubWords;
//     String subWord = "";
// 
//     int subWordLength = shortestWordLength;
//     while (subWordLength > 0) {
//       s1SubWords = generateSubWords(s1, subWordLength);
//       s2SubWords = generateSubWords(s2, subWordLength);
// 
//       subWord = s1SubWords.stream()
//               .filter(s2SubWords::contains)
//               .findFirst()
//               .orElse("");
// 
//       if (!subWord.isEmpty())
//         break;
// 
//       subWordLength--;
//     }
//     return subWord;
//   }
// 
//   public static Set<String> generateSubWords(final String word, final int length) {
//     if (length > word.length())
//       throw new IllegalArgumentException(
//           "The word '" + word + "' length cannot be less than the length " + length
//               + " of the words to be generated.");
// 
//     // LinkedHashSet maintains the order. if there are multiple common substrings the left most should match first.
//     Set<String> generatedWords = new LinkedHashSet<>();
//     for (int i = 0; i <= (word.length() - length); i++)
//       generatedWords.add(word.substring(i, length + i));
// 
//     return generatedWords;
//   }
// 
//   public static boolean looksLikeCharacter(final String text) {
//     return text.length() == 1;
//   }
// 
//   public static Optional<Character> castToChar(final String text) {
//     return !looksLikeCharacter(text) ? Optional.empty() : Optional.of(text.charAt(0));
//   }
// 
//   public static boolean startsWithUpperCase(final String text) {
//     return Character.isUpperCase(text.charAt(0));
//   }
// }


import java.util.HashMap;
import java.util.Map;
import java.util.OptionalDouble;
import io.aif.language.common.StringHelper;
      for (int delta = 0; delta <= COMPARATION_LEVEL; delta++) {
        if (i - delta >= 0) {
          updateDensityFroTheCharAtPositionWithDelta(chAtI, i - delta, delta, padding, result);
        }
        if (i + delta < str.length() && delta != 0) {
          updateDensityFroTheCharAtPositionWithDelta(chAtI, i + delta, delta, padding, result);
        }
      }
    }
    return result;
  }

  private static void updateDensityFroTheCharAtPositionWithDelta(
      final char ch,
      final int position,
      final int delta,
      final int padding,
      final Map<String, Double> result) {
    final String key = "" + ch + (position + padding);
    final double currentVal = result.getOrDefault(key, .0);
    result.put(key, currentVal + (1. / (double) (delta + 1)));
  }

  @Override
  public Double compare(final String left, final String right) {
    if (left == null || right == null) return .0;
    if (right.length() < left.length()) return compare(right, left);
    if (left.isEmpty() && right.isEmpty()) return 1.;
    if (left.isEmpty() || right.isEmpty()) return .0;
    if (left.equals(right)) return 1.;
// Path: src/main/java/io/aif/language/common/StringHelper.java
// public class StringHelper {
// 
//   public static String findLongestCommonSubstring(final String t1, final String t2) {
//     String s1 = t1.toLowerCase();
//     String s2 = t2.toLowerCase();
// 
//     final int shortestWordLength = Math.min(t1.length(), t2.length());
//     Set<String> s1SubWords;
//     Set<String> s2SubWords;
//     String subWord = "";
// 
//     int subWordLength = shortestWordLength;
//     while (subWordLength > 0) {
//       s1SubWords = generateSubWords(s1, subWordLength);
//       s2SubWords = generateSubWords(s2, subWordLength);
// 
//       subWord = s1SubWords.stream()
//               .filter(s2SubWords::contains)
//               .findFirst()
//               .orElse("");
// 
//       if (!subWord.isEmpty())
//         break;
// 
//       subWordLength--;
//     }
//     return subWord;
//   }
// 
//   public static Set<String> generateSubWords(final String word, final int length) {
//     if (length > word.length())
//       throw new IllegalArgumentException(
//           "The word '" + word + "' length cannot be less than the length " + length
//               + " of the words to be generated.");
// 
//     // LinkedHashSet maintains the order. if there are multiple common substrings the left most should match first.
//     Set<String> generatedWords = new LinkedHashSet<>();
//     for (int i = 0; i <= (word.length() - length); i++)
//       generatedWords.add(word.substring(i, length + i));
// 
//     return generatedWords;
//   }
// 
//   public static boolean looksLikeCharacter(final String text) {
//     return text.length() == 1;
//   }
// 
//   public static Optional<Character> castToChar(final String text) {
//     return !looksLikeCharacter(text) ? Optional.empty() : Optional.of(text.charAt(0));
//   }
// 
//   public static boolean startsWithUpperCase(final String text) {
//     return Character.isUpperCase(text.charAt(0));
//   }
// }


// Path: src/main/java/io/aif/language/token/comparator/CharacterDensityTokenComparator.java
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalDouble;
import io.aif.language.common.StringHelper;

      for (int delta = 0; delta <= COMPARATION_LEVEL; delta++) {
        if (i - delta >= 0) {
          updateDensityFroTheCharAtPositionWithDelta(chAtI, i - delta, delta, padding, result);
        }
        if (i + delta < str.length() && delta != 0) {
          updateDensityFroTheCharAtPositionWithDelta(chAtI, i + delta, delta, padding, result);
        }
      }
    }
    return result;
  }

  private static void updateDensityFroTheCharAtPositionWithDelta(
      final char ch,
      final int position,
      final int delta,
      final int padding,
      final Map<String, Double> result) {
    final String key = "" + ch + (position + padding);
    final double currentVal = result.getOrDefault(key, .0);
    result.put(key, currentVal + (1. / (double) (delta + 1)));
  }

  @Override
  public Double compare(final String left, final String right) {
    if (left == null || right == null) return .0;
    if (right.length() < left.length()) return compare(right, left);
    if (left.isEmpty() && right.isEmpty()) return 1.;
    if (left.isEmpty() || right.isEmpty()) return .0;
    if (left.equals(right)) return 1.;
    final String lcs = StringHelper.findLongestCommonSubstring(left, right);