Fix regression issues caused by `selectSearchResult` now taking into account alias titles (which is not desirable when query was entered manually)

This commit is contained in:
Reinhard Pointner 2016-02-08 22:29:50 +00:00
parent 037c3d9e68
commit 1ebece8d19
3 changed files with 27 additions and 31 deletions

View File

@ -285,7 +285,7 @@ public class CmdlineOperations implements CmdlineInterface {
// select search result
if (results.size() > 0) {
List<SearchResult> selectedSearchResults = selectSearchResult(query, results, strict);
List<SearchResult> 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<SearchResult> selectSearchResult(String query, Collection<? extends SearchResult> searchResults, boolean strict) throws Exception {
List<SearchResult> probableMatches = getProbableMatches(query, searchResults, strict);
private List<SearchResult> selectSearchResult(String query, Collection<? extends SearchResult> options, boolean alias, boolean strict) throws Exception {
List<SearchResult> 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<SearchResult>(searchResults);
if (options.size() == 1 && !strict) {
return new ArrayList<SearchResult>(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<SearchResult>) sortBySimilarity(searchResults, singleton(query), getSeriesMatchMetric());
probableMatches = new ArrayList<SearchResult>(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<Episode> episodes = service.getEpisodeList(hit, sortOrder, locale);
// apply filter

View File

@ -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 <T extends SearchResult> List<T> sortBySimilarity(Collection<T> options, Collection<String> 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 <T extends SearchResult> List<T> sortBySimilarity(Collection<T> options, Collection<String> terms, SimilarityMetric metric, Function<SearchResult, Collection<String>> mapper) {
// similarity comparator with multi-value support
SimilarityComparator<SearchResult, String> comparator = new SimilarityComparator<SearchResult, String>(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<SearchResult> getProbableMatches(String query, Collection<? extends SearchResult> options, boolean strict) {
public static List<SearchResult> getProbableMatches(String query, Collection<? extends SearchResult> options, boolean alias, boolean strict) {
if (query == null) {
return new ArrayList<SearchResult>(options);
}
// check all alias names, or just the primary name
Function<SearchResult, Collection<String>> names = alias ? SearchResult::getEffectiveNames : (it) -> singleton(it.getName());
// auto-select most probable search result
List<SearchResult> probableMatches = new ArrayList<SearchResult>();
@ -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<T> implements Serializable {

View File

@ -70,7 +70,7 @@ class EpisodeListMatcher implements AutoCompleteMatcher {
}
// auto-select most probable search result
List<SearchResult> probableMatches = getProbableMatches(query, searchResults, true);
List<SearchResult> probableMatches = getProbableMatches(query, searchResults, true, true);
// auto-select first and only probable search result
if (probableMatches.size() == 1) {