From 41c1369221ab52b175babb104dfe0325c6b309a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mathieu=20M=C3=A9a?= Date: Thu, 2 Jul 2026 20:05:48 -0400 Subject: [PATCH] Support for custom LC UC words min % --- .../java/org/mtransit/commons/CleanUtils.java | 17 ++++++---- .../org/mtransit/commons/StringsCleaner.kt | 31 ++++++++++++++++--- 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/mtransit/commons/CleanUtils.java b/src/main/java/org/mtransit/commons/CleanUtils.java index 00f1a9c..6cfcb19 100644 --- a/src/main/java/org/mtransit/commons/CleanUtils.java +++ b/src/main/java/org/mtransit/commons/CleanUtils.java @@ -587,18 +587,23 @@ public static String fixMcXCase(@NotNull String string) { // Mccowan -> McCowan "([^" + WORD_REGEX_FR + "]*)([" + WORD_REGEX_FR + "]+)([^" + WORD_REGEX_FR + "]*)", Pattern.CASE_INSENSITIVE | RegexUtils.fUNICODE_CHARACTER_CLASS() | RegexUtils.fCANON_EQ()); + public static final float DEFAULT_MIN_UPPER_CASE_PCT = .33f; + @NotNull public static String toLowerCaseUpperCaseWords(@NotNull Locale locale, @NotNull String string, @NotNull String... ignoreWords) { + return toLowerCaseUpperCaseWords(locale, string, DEFAULT_MIN_UPPER_CASE_PCT, ignoreWords); + } + + @NotNull + public static String toLowerCaseUpperCaseWords(@NotNull Locale locale, @NotNull String string, float minUCPct, @NotNull String... ignoreWords) { if (string.isEmpty()) return string; final float charCount = string.length(); final float upperCaseCount = CharUtils.countUpperCase(string); final float percent = upperCaseCount / charCount; - if (percent < .33f) { // 33% - return string; - } - StringBuilder sb = new StringBuilder(); - Pattern pattern = locale == Locale.FRENCH ? WORD_NON_WORDS_FR : WORD_NON_WORDS; - Matcher matcher = pattern.matcher(string); + if (percent < minUCPct) return string; + final StringBuilder sb = new StringBuilder(); + final Pattern pattern = locale == Locale.FRENCH ? WORD_NON_WORDS_FR : WORD_NON_WORDS; + final Matcher matcher = pattern.matcher(string); while (matcher.find()) { sb.append(matcher.group(1)); // before final String word = matcher.group(2); diff --git a/src/main/java/org/mtransit/commons/StringsCleaner.kt b/src/main/java/org/mtransit/commons/StringsCleaner.kt index 044dc1c..736accf 100644 --- a/src/main/java/org/mtransit/commons/StringsCleaner.kt +++ b/src/main/java/org/mtransit/commons/StringsCleaner.kt @@ -34,6 +34,7 @@ object StringsCleaner { @Suppress("unused") routeType: Int, lowerUCStrings: Boolean = false, lowerUCWords: Boolean = false, + lowerUCWordsMinPct: Float? = null, vararg ignoredUCWords: String = emptyArray(), ): String { var routeLongName = originalRouteLongName @@ -44,7 +45,16 @@ object StringsCleaner { routeLongName = FR_LIGNE_AND_SHORT_NAME.replace(routeLongName, FR_LIGNE_AND_SHORT_NAME_REPLACEMENT) } val makeShorter = routeLongName.length > ROUTE_LONG_NAME_SHORT_MAX_LENGTH && routeLongName.contains(' ') - routeLongName = cleanString(routeLongName, languages, makeShorter, ROUTE_LONG_NAME_SHORT_MAX_LENGTH, lowerUCStrings, lowerUCWords, *ignoredUCWords) + routeLongName = cleanString( + routeLongName, + languages, + makeShorter, + ROUTE_LONG_NAME_SHORT_MAX_LENGTH, + lowerUCStrings, + lowerUCWords, + lowerUCWordsMinPct, + *ignoredUCWords + ) return routeLongName } @@ -78,6 +88,7 @@ object StringsCleaner { routeType: Int, lowerUCStrings: Boolean = false, lowerUCWords: Boolean = false, + lowerUCWordsMinPct: Float? = null, vararg ignoredUCWords: String = emptyArray(), removeVia: Boolean = false, ): String { @@ -114,7 +125,16 @@ object StringsCleaner { } } val makeShorter = tripHeadsign.length > TRIP_HEADSIGN_SHORT_MAX_LENGTH && tripHeadsign.contains(' ') - tripHeadsign = cleanString(tripHeadsign, languages, makeShorter, TRIP_HEADSIGN_SHORT_MAX_LENGTH, lowerUCStrings, lowerUCWords, *ignoredUCWords) + tripHeadsign = cleanString( + tripHeadsign, + languages, + makeShorter, + TRIP_HEADSIGN_SHORT_MAX_LENGTH, + lowerUCStrings, + lowerUCWords, + lowerUCWordsMinPct, + *ignoredUCWords + ) if (tripHeadsign.length > TRIP_HEADSIGN_SHORT_MAX_LENGTH) { tripHeadsign = CleanUtils.cleanSlashes(tripHeadsign, true) } @@ -131,6 +151,7 @@ object StringsCleaner { routeType: Int, lowerUCStrings: Boolean = false, lowerUCWords: Boolean = false, + lowerUCWordsMinPct: Float? = null, vararg ignoredUCWords: String = emptyArray(), ): String { var stopName = originalStopName @@ -153,7 +174,7 @@ object StringsCleaner { } } val makeShorter = stopName.length > STOP_NAME_SHORT_MAX_LENGTH && stopName.contains(' ') - stopName = cleanString(stopName, languages, makeShorter, STOP_NAME_SHORT_MAX_LENGTH, lowerUCStrings, lowerUCWords, *ignoredUCWords) + stopName = cleanString(stopName, languages, makeShorter, STOP_NAME_SHORT_MAX_LENGTH, lowerUCStrings, lowerUCWords, lowerUCWordsMinPct, *ignoredUCWords) return stopName } @@ -165,12 +186,13 @@ object StringsCleaner { shortMaxLength: Int, lowerUCStrings: Boolean = false, lowerUCWords: Boolean = false, + lowerUCWordsMinPct: Float? = null, vararg ignoredUCWords: String = emptyArray(), ): String { var string = originalString languages?.forEach { language -> if (lowerUCWords) { - string = CleanUtils.toLowerCaseUpperCaseWords(language, string, *ignoredUCWords) + string = CleanUtils.toLowerCaseUpperCaseWords(language, string, lowerUCWordsMinPct ?: CleanUtils.DEFAULT_MIN_UPPER_CASE_PCT, *ignoredUCWords) } else if (lowerUCStrings) { string = CleanUtils.toLowerCaseUpperCaseStrings(language, string, *ignoredUCWords) } @@ -187,6 +209,7 @@ object StringsCleaner { } string = CleanUtils.cleanNumbers(string) } + Locale.FRENCH -> { if (short) { string = CleanUtils.CLEAN_ET.matcher(string).replaceAll(CleanUtils.CLEAN_ET_REPLACEMENT)