diff --git a/source/net/filebot/cli/CmdlineOperations.java b/source/net/filebot/cli/CmdlineOperations.java index 843974cb..87303a34 100644 --- a/source/net/filebot/cli/CmdlineOperations.java +++ b/source/net/filebot/cli/CmdlineOperations.java @@ -285,7 +285,7 @@ public class CmdlineOperations implements CmdlineInterface { // select search result if (results.size() > 0) { - List selectedSearchResults = selectSearchResult(query, results, strict); + List selectedSearchResults = selectSearchResult(query, results, true, strict); if (selectedSearchResults != null) { for (SearchResult it : selectedSearchResults) { @@ -404,7 +404,7 @@ public class CmdlineOperations implements CmdlineInterface { } // force all mappings - Movie result = (Movie) selectSearchResult(query, validResults, strict).get(0); + Movie result = (Movie) selectSearchResult(query, validResults, false, strict).get(0); for (File file : files) { movieByFile.put(file, result); } @@ -447,7 +447,7 @@ public class CmdlineOperations implements CmdlineInterface { // select first element if matches are reliable if (options.size() > 0) { // make sure to get the language-specific movie object for the selected option - movie = service.getMovieDescriptor((Movie) selectSearchResult(null, options, strict).get(0), locale); + movie = service.getMovieDescriptor((Movie) selectSearchResult(null, options, false, strict).get(0), locale); } } catch (Exception e) { CLILogger.log(Level.WARNING, String.format("%s: [%s/%s] %s", e.getClass().getSimpleName(), guessMovieFolder(file) != null ? guessMovieFolder(file).getName() : null, file.getName(), e.getMessage())); @@ -910,23 +910,22 @@ public class CmdlineOperations implements CmdlineInterface { return output; } - @SuppressWarnings("unchecked") - public List selectSearchResult(String query, Collection searchResults, boolean strict) throws Exception { - List probableMatches = getProbableMatches(query, searchResults, strict); + private List selectSearchResult(String query, Collection options, boolean alias, boolean strict) throws Exception { + List probableMatches = getProbableMatches(query, options, alias, strict); if (probableMatches.isEmpty() || (strict && probableMatches.size() != 1)) { // allow single search results to just pass through in non-strict mode even if match confidence is low - if (searchResults.size() == 1 && !strict) { - return new ArrayList(searchResults); + if (options.size() == 1 && !strict) { + return new ArrayList(options); } if (strict) { - throw new CmdlineException("Multiple options: Force auto-select requires non-strict matching: " + searchResults); + throw new CmdlineException("Multiple options: Force auto-select requires non-strict matching: " + options); } // just pick the best 5 matches if (query != null) { - probableMatches = (List) sortBySimilarity(searchResults, singleton(query), getSeriesMatchMetric()); + probableMatches = new ArrayList(sortBySimilarity(options, singleton(query), getSeriesMatchMetric())); } } @@ -1081,7 +1080,7 @@ public class CmdlineOperations implements CmdlineInterface { Locale locale = getLanguage(languageName).getLocale(); // fetch episode data - SearchResult hit = selectSearchResult(query, service.search(query, locale), false).get(0); + SearchResult hit = selectSearchResult(query, service.search(query, locale), false, false).get(0); List episodes = service.getEpisodeList(hit, sortOrder, locale); // apply filter diff --git a/source/net/filebot/media/MediaDetection.java b/source/net/filebot/media/MediaDetection.java index 6ee97deb..503b8f8d 100644 --- a/source/net/filebot/media/MediaDetection.java +++ b/source/net/filebot/media/MediaDetection.java @@ -36,6 +36,7 @@ import java.util.Set; import java.util.SortedSet; import java.util.TreeMap; import java.util.TreeSet; +import java.util.function.Function; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; @@ -706,19 +707,12 @@ public class MediaDetection { } public static List sortBySimilarity(Collection options, Collection terms, SimilarityMetric metric) { - // similarity comparator with multi-value support - SimilarityComparator comparator = new SimilarityComparator(metric, terms.toArray()) { + return sortBySimilarity(options, terms, metric, SearchResult::getEffectiveNames); + } - @Override - public float getMaxSimilarity(Object obj) { - Collection names = obj instanceof SearchResult ? ((SearchResult) obj).getEffectiveNames() : singleton(obj); - float f = 0; - for (Object it : names) { - f = Math.max(f, super.getMaxSimilarity(it)); - } - return f; - } - }; + public static List sortBySimilarity(Collection options, Collection terms, SimilarityMetric metric, Function> mapper) { + // similarity comparator with multi-value support + SimilarityComparator comparator = new SimilarityComparator(metric, terms, mapper); // DEBUG // System.out.format("sortBySimilarity %s => %s%n", terms, options.stream().sorted(comparator).distinct().collect(Collectors.toList())); @@ -732,7 +726,7 @@ public class MediaDetection { paragon.addAll(stripReleaseInfo(terms, true)); paragon.addAll(stripReleaseInfo(terms, false)); - return sortBySimilarity(options, paragon, getMovieMatchMetric()); + return sortBySimilarity(options, paragon, getMovieMatchMetric(), SearchResult::getEffectiveNames); } public static boolean isEpisodeNumberMatch(File f, Episode e) { @@ -1258,11 +1252,14 @@ public class MediaDetection { return WebServices.TheTVDB.getSeriesInfo(thetvdbid, locale); } - public static List getProbableMatches(String query, Collection options, boolean strict) { + public static List getProbableMatches(String query, Collection options, boolean alias, boolean strict) { if (query == null) { return new ArrayList(options); } + // check all alias names, or just the primary name + Function> names = alias ? SearchResult::getEffectiveNames : (it) -> singleton(it.getName()); + // auto-select most probable search result List probableMatches = new ArrayList(); @@ -1272,17 +1269,17 @@ public class MediaDetection { float sanity = strict && options.size() > 1 ? 0.5f : 0.2f; // remove trailing braces, e.g. Doctor Who (2005) -> doctor who - query = removeTrailingBrackets(query).toLowerCase(); + String q = removeTrailingBrackets(query).toLowerCase(); // find probable matches using name similarity > 0.8 (or > 0.6 in non-strict mode) for (SearchResult option : options) { float f = 0; - for (String n : option.getEffectiveNames()) { + for (String n : names.apply(option)) { n = removeTrailingBrackets(n).toLowerCase(); - f = Math.max(f, metric.getSimilarity(query, n)); + f = Math.max(f, metric.getSimilarity(q, n)); // boost matching beginnings - if (f >= sanity && n.startsWith(query)) { + if (f >= sanity && n.startsWith(q)) { f = 1; break; } @@ -1293,7 +1290,7 @@ public class MediaDetection { } } - return sortBySimilarity(probableMatches, singleton(query), new NameSimilarityMetric()); + return sortBySimilarity(probableMatches, singleton(query), new NameSimilarityMetric(), names); } public static class IndexEntry implements Serializable { diff --git a/source/net/filebot/ui/rename/EpisodeListMatcher.java b/source/net/filebot/ui/rename/EpisodeListMatcher.java index 6893957f..7b68cf8c 100644 --- a/source/net/filebot/ui/rename/EpisodeListMatcher.java +++ b/source/net/filebot/ui/rename/EpisodeListMatcher.java @@ -70,7 +70,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher { } // auto-select most probable search result - List probableMatches = getProbableMatches(query, searchResults, true); + List probableMatches = getProbableMatches(query, searchResults, true, true); // auto-select first and only probable search result if (probableMatches.size() == 1) {