mirror of https://github.com/Sonarr/Sonarr
Fixed: Negative preferred word scores being trumped by 0 scores without any matches
This commit is contained in:
parent
66af08a830
commit
acdf02d569
|
@ -1,4 +1,6 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
@ -15,26 +17,33 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
{
|
{
|
||||||
private Series _series;
|
private Series _series;
|
||||||
private EpisodeFile _episodeFile;
|
private EpisodeFile _episodeFile;
|
||||||
|
private readonly KeyValuePair<string, int> _positiveScore = new KeyValuePair<string, int>("Positive", 10);
|
||||||
|
private readonly KeyValuePair<string, int> _negativeScore = new KeyValuePair<string, int>("Negative", -10);
|
||||||
|
private KeyValuePair<string, int> _neutralScore = new KeyValuePair<string, int>("Neutral", 0);
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_series = Builder<Series>.CreateNew().Build();
|
_series = Builder<Series>.CreateNew().Build();
|
||||||
_episodeFile = Builder<EpisodeFile>.CreateNew().Build();
|
_episodeFile = Builder<EpisodeFile>.CreateNew().Build();
|
||||||
|
|
||||||
|
Mocker.GetMock<IPreferredWordService>()
|
||||||
|
.Setup(s => s.GetMatchingPreferredWordsAndScores(It.IsAny<Series>(), It.IsAny<string>(), 0))
|
||||||
|
.Returns(new List<KeyValuePair<string, int>>());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenPreferredWordScore(string title, int score)
|
private void GivenPreferredWordScore(string title, params KeyValuePair<string, int>[] matches)
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IPreferredWordService>()
|
Mocker.GetMock<IPreferredWordService>()
|
||||||
.Setup(s => s.Calculate(It.IsAny<Series>(), title, 0))
|
.Setup(s => s.GetMatchingPreferredWordsAndScores(It.IsAny<Series>(), title, 0))
|
||||||
.Returns(score);
|
.Returns(matches.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_score_for_relative_file_name_when_it_is_higher_than_scene_name()
|
public void should_return_score_for_relative_file_name_when_it_is_higher_than_scene_name()
|
||||||
{
|
{
|
||||||
GivenPreferredWordScore(_episodeFile.SceneName, 10);
|
GivenPreferredWordScore(_episodeFile.SceneName, _positiveScore);
|
||||||
GivenPreferredWordScore(_episodeFile.RelativePath, 20);
|
GivenPreferredWordScore(_episodeFile.RelativePath, _positiveScore, _positiveScore);
|
||||||
|
|
||||||
Subject.Calculate(_series, _episodeFile).Should().Be(20);
|
Subject.Calculate(_series, _episodeFile).Should().Be(20);
|
||||||
}
|
}
|
||||||
|
@ -45,7 +54,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
_episodeFile.SceneName = null;
|
_episodeFile.SceneName = null;
|
||||||
_episodeFile.RelativePath = null;
|
_episodeFile.RelativePath = null;
|
||||||
|
|
||||||
GivenPreferredWordScore(_episodeFile.Path, 20);
|
GivenPreferredWordScore(_episodeFile.Path, _positiveScore, _positiveScore);
|
||||||
|
|
||||||
Subject.Calculate(_series, _episodeFile).Should().Be(20);
|
Subject.Calculate(_series, _episodeFile).Should().Be(20);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +64,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
{
|
{
|
||||||
_episodeFile.SceneName = null;
|
_episodeFile.SceneName = null;
|
||||||
|
|
||||||
GivenPreferredWordScore(_episodeFile.RelativePath, 20);
|
GivenPreferredWordScore(_episodeFile.RelativePath, _positiveScore, _positiveScore);
|
||||||
|
|
||||||
Subject.Calculate(_series, _episodeFile).Should().Be(20);
|
Subject.Calculate(_series, _episodeFile).Should().Be(20);
|
||||||
}
|
}
|
||||||
|
@ -63,17 +72,17 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_score_for_scene_name_when_higher_than_relative_file_name()
|
public void should_return_score_for_scene_name_when_higher_than_relative_file_name()
|
||||||
{
|
{
|
||||||
GivenPreferredWordScore(_episodeFile.SceneName, 50);
|
GivenPreferredWordScore(_episodeFile.SceneName, _positiveScore, _positiveScore, _positiveScore);
|
||||||
GivenPreferredWordScore(_episodeFile.RelativePath, 20);
|
GivenPreferredWordScore(_episodeFile.RelativePath, _positiveScore, _positiveScore);
|
||||||
|
|
||||||
Subject.Calculate(_series, _episodeFile).Should().Be(50);
|
Subject.Calculate(_series, _episodeFile).Should().Be(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_score_for_relative_file_if_available()
|
public void should_return_score_for_relative_file_if_available()
|
||||||
{
|
{
|
||||||
GivenPreferredWordScore(_episodeFile.RelativePath, 20);
|
GivenPreferredWordScore(_episodeFile.RelativePath, _positiveScore, _positiveScore);
|
||||||
GivenPreferredWordScore(_episodeFile.Path, 50);
|
GivenPreferredWordScore(_episodeFile.Path, _positiveScore, _positiveScore, _positiveScore);
|
||||||
|
|
||||||
Subject.Calculate(_series, _episodeFile).Should().Be(20);
|
Subject.Calculate(_series, _episodeFile).Should().Be(20);
|
||||||
}
|
}
|
||||||
|
@ -86,12 +95,12 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
|
|
||||||
_episodeFile.OriginalFilePath = Path.Combine(folderName, fileName);
|
_episodeFile.OriginalFilePath = Path.Combine(folderName, fileName);
|
||||||
|
|
||||||
GivenPreferredWordScore(_episodeFile.RelativePath, 20);
|
GivenPreferredWordScore(_episodeFile.RelativePath, _positiveScore);
|
||||||
GivenPreferredWordScore(_episodeFile.Path, 50);
|
GivenPreferredWordScore(_episodeFile.Path, _positiveScore, _positiveScore);
|
||||||
GivenPreferredWordScore(folderName, 60);
|
GivenPreferredWordScore(folderName, _positiveScore, _positiveScore, _positiveScore);
|
||||||
GivenPreferredWordScore(fileName, 50);
|
GivenPreferredWordScore(fileName, _positiveScore, _positiveScore);
|
||||||
|
|
||||||
Subject.Calculate(_series, _episodeFile).Should().Be(60);
|
Subject.Calculate(_series, _episodeFile).Should().Be(30);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
|
@ -102,12 +111,42 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
|
|
||||||
_episodeFile.OriginalFilePath = Path.Combine(folderName, fileName);
|
_episodeFile.OriginalFilePath = Path.Combine(folderName, fileName);
|
||||||
|
|
||||||
GivenPreferredWordScore(_episodeFile.RelativePath, 20);
|
GivenPreferredWordScore(_episodeFile.RelativePath, _positiveScore);
|
||||||
GivenPreferredWordScore(_episodeFile.Path, 50);
|
GivenPreferredWordScore(_episodeFile.Path, _positiveScore, _positiveScore);
|
||||||
GivenPreferredWordScore(folderName, 40);
|
GivenPreferredWordScore(folderName, _positiveScore, _positiveScore);
|
||||||
GivenPreferredWordScore(fileName, 50);
|
GivenPreferredWordScore(fileName, _positiveScore, _positiveScore, _positiveScore);
|
||||||
|
|
||||||
Subject.Calculate(_series, _episodeFile).Should().Be(50);
|
Subject.Calculate(_series, _episodeFile).Should().Be(30);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_negative_score_if_0_result_has_no_matches()
|
||||||
|
{
|
||||||
|
var folderName = "folder-name";
|
||||||
|
var fileName = "file-name";
|
||||||
|
|
||||||
|
_episodeFile.OriginalFilePath = Path.Combine(folderName, fileName);
|
||||||
|
|
||||||
|
GivenPreferredWordScore(_episodeFile.RelativePath, _negativeScore);
|
||||||
|
GivenPreferredWordScore(fileName);
|
||||||
|
|
||||||
|
Subject.Calculate(_series, _episodeFile).Should().Be(-10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_0_score_if_0_result_has_matches()
|
||||||
|
{
|
||||||
|
var folderName = "folder-name";
|
||||||
|
var fileName = "file-name";
|
||||||
|
|
||||||
|
_episodeFile.OriginalFilePath = Path.Combine(folderName, fileName);
|
||||||
|
|
||||||
|
GivenPreferredWordScore(_episodeFile.RelativePath, _negativeScore);
|
||||||
|
GivenPreferredWordScore(_episodeFile.Path, _negativeScore);
|
||||||
|
GivenPreferredWordScore(folderName, _negativeScore);
|
||||||
|
GivenPreferredWordScore(fileName, _neutralScore);
|
||||||
|
|
||||||
|
Subject.Calculate(_series, _episodeFile).Should().Be(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,7 +32,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
|
|
||||||
if (episodeFile.SceneName.IsNotNullOrWhiteSpace())
|
if (episodeFile.SceneName.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
scores.Add(_preferredWordService.Calculate(series, episodeFile.SceneName, 0));
|
AddScoreIfApplicable(series, episodeFile.SceneName, scores);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -49,7 +49,7 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
var isLast = i == segments.Count - 1;
|
var isLast = i == segments.Count - 1;
|
||||||
var segment = isLast ? Path.GetFileNameWithoutExtension(segments[i]) : segments[i];
|
var segment = isLast ? Path.GetFileNameWithoutExtension(segments[i]) : segments[i];
|
||||||
|
|
||||||
scores.Add(_preferredWordService.Calculate(series, segment, 0));
|
AddScoreIfApplicable(series, segment, scores);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -60,11 +60,11 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
// Calculate using RelativePath or Path, but not both
|
// Calculate using RelativePath or Path, but not both
|
||||||
if (episodeFile.RelativePath.IsNotNullOrWhiteSpace())
|
if (episodeFile.RelativePath.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
scores.Add(_preferredWordService.Calculate(series, episodeFile.RelativePath, 0));
|
AddScoreIfApplicable(series, episodeFile.RelativePath, scores);
|
||||||
}
|
}
|
||||||
else if (episodeFile.Path.IsNotNullOrWhiteSpace())
|
else if (episodeFile.Path.IsNotNullOrWhiteSpace())
|
||||||
{
|
{
|
||||||
scores.Add(_preferredWordService.Calculate(series, episodeFile.Path, 0));
|
AddScoreIfApplicable(series, episodeFile.Path, scores);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the highest score, this will allow media info in file names to be used to improve preferred word scoring.
|
// Return the highest score, this will allow media info in file names to be used to improve preferred word scoring.
|
||||||
|
@ -72,5 +72,22 @@ namespace NzbDrone.Core.MediaFiles
|
||||||
|
|
||||||
return scores.MaxOrDefault();
|
return scores.MaxOrDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AddScoreIfApplicable(Series series, string title, List<int> scores)
|
||||||
|
{
|
||||||
|
var score = 0;
|
||||||
|
_logger.Trace("Calculating preferred word score for '{0}'", title);
|
||||||
|
|
||||||
|
var matchingPairs = _preferredWordService.GetMatchingPreferredWordsAndScores(series, title, 0);
|
||||||
|
|
||||||
|
// Only add the score if there are matching terms, uncalculated
|
||||||
|
if (matchingPairs.Any())
|
||||||
|
{
|
||||||
|
score = matchingPairs.Sum(p => p.Value);
|
||||||
|
scores.Add(score);
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Trace("Calculated preferred word score for '{0}': {1} ({2} match(es))", title, score, matchingPairs.Count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace NzbDrone.Core.Profiles.Releases
|
||||||
public interface IPreferredWordService
|
public interface IPreferredWordService
|
||||||
{
|
{
|
||||||
int Calculate(Series series, string title, int indexerId);
|
int Calculate(Series series, string title, int indexerId);
|
||||||
|
List<KeyValuePair<string, int>> GetMatchingPreferredWordsAndScores(Series series, string title, int indexerId);
|
||||||
PreferredWordMatchResults GetMatchingPreferredWords(Series series, string title);
|
PreferredWordMatchResults GetMatchingPreferredWords(Series series, string title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +31,16 @@ namespace NzbDrone.Core.Profiles.Releases
|
||||||
{
|
{
|
||||||
_logger.Trace("Calculating preferred word score for '{0}'", title);
|
_logger.Trace("Calculating preferred word score for '{0}'", title);
|
||||||
|
|
||||||
|
var matchingPairs = GetMatchingPreferredWordsAndScores(series, title, indexerId);
|
||||||
|
var score = matchingPairs.Sum(p => p.Value);
|
||||||
|
|
||||||
|
_logger.Trace("Calculated preferred word score for '{0}': {1} ({2} match(es))", title, score, matchingPairs.Count);
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<KeyValuePair<string, int>> GetMatchingPreferredWordsAndScores(Series series, string title, int indexerId)
|
||||||
|
{
|
||||||
var releaseProfiles = _releaseProfileService.EnabledForTags(series.Tags, indexerId);
|
var releaseProfiles = _releaseProfileService.EnabledForTags(series.Tags, indexerId);
|
||||||
var matchingPairs = new List<KeyValuePair<string, int>>();
|
var matchingPairs = new List<KeyValuePair<string, int>>();
|
||||||
|
|
||||||
|
@ -46,11 +57,7 @@ namespace NzbDrone.Core.Profiles.Releases
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var score = matchingPairs.Sum(p => p.Value);
|
return matchingPairs;
|
||||||
|
|
||||||
_logger.Trace("Calculated preferred word score for '{0}': {1}", title, score);
|
|
||||||
|
|
||||||
return score;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreferredWordMatchResults GetMatchingPreferredWords(Series series, string title)
|
public PreferredWordMatchResults GetMatchingPreferredWords(Series series, string title)
|
||||||
|
|
Loading…
Reference in New Issue