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:
parent
037c3d9e68
commit
1ebece8d19
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue