Fixed: Include matching value of preferred word regex, not actual regex

Co-Authored-By: Mark McDowall <markus101@users.noreply.github.com>
pull/6/head
Qstick 6 years ago
parent 27ebe36454
commit 1cc12446b6

@ -30,7 +30,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
} }
}; };
Mocker.SetConstant<ITermMatcher>(Mocker.Resolve<TermMatcher>()); Mocker.SetConstant<ITermMatcherService>(Mocker.Resolve<TermMatcherService>());
} }
private void GivenRestictions(string required, string ignored) private void GivenRestictions(string required, string ignored)

@ -43,7 +43,7 @@ namespace NzbDrone.Core.Test.Profiles.Releases.PreferredWordService
private void GivenMatchingTerms(params string[] terms) private void GivenMatchingTerms(params string[] terms)
{ {
Mocker.GetMock<ITermMatcher>() Mocker.GetMock<ITermMatcherService>()
.Setup(s => s.IsMatch(It.IsAny<string>(), _title)) .Setup(s => s.IsMatch(It.IsAny<string>(), _title))
.Returns<string, string>((term, title) => terms.Contains(term)); .Returns<string, string>((term, title) => terms.Contains(term));
} }

@ -13,13 +13,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
{ {
private readonly Logger _logger; private readonly Logger _logger;
private readonly IReleaseProfileService _releaseProfileService; private readonly IReleaseProfileService _releaseProfileService;
private readonly ITermMatcher _termMatcher; private readonly ITermMatcherService _termMatcherService;
public ReleaseRestrictionsSpecification(ITermMatcher termMatcher, IReleaseProfileService releaseProfileService, Logger logger) public ReleaseRestrictionsSpecification(ITermMatcherService termMatcherService, IReleaseProfileService releaseProfileService, Logger logger)
{ {
_logger = logger; _logger = logger;
_releaseProfileService = releaseProfileService; _releaseProfileService = releaseProfileService;
_termMatcher = termMatcher; _termMatcherService = termMatcherService;
} }
public SpecificationPriority Priority => SpecificationPriority.Default; public SpecificationPriority Priority => SpecificationPriority.Default;
@ -67,7 +67,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
private List<string> ContainsAny(List<string> terms, string title) private List<string> ContainsAny(List<string> terms, string title)
{ {
return terms.Where(t => _termMatcher.IsMatch(t, title)).ToList(); return terms.Where(t => _termMatcherService.IsMatch(t, title)).ToList();
} }
} }
} }

@ -1016,12 +1016,15 @@
<Compile Include="Profiles\Metadata\ProfilePrimaryAlbumTypeItem.cs" /> <Compile Include="Profiles\Metadata\ProfilePrimaryAlbumTypeItem.cs" />
<Compile Include="Profiles\Qualities\QualityProfileRepository.cs" /> <Compile Include="Profiles\Qualities\QualityProfileRepository.cs" />
<Compile Include="Profiles\Qualities\QualityIndex.cs" /> <Compile Include="Profiles\Qualities\QualityIndex.cs" />
<Compile Include="Profiles\Releases\TermMatchers\CaseInsensitiveTermMatcher.cs" />
<Compile Include="Profiles\Releases\PerlRegexFactory.cs" /> <Compile Include="Profiles\Releases\PerlRegexFactory.cs" />
<Compile Include="Profiles\Releases\PreferredWordService.cs" /> <Compile Include="Profiles\Releases\PreferredWordService.cs" />
<Compile Include="Profiles\Releases\ReleaseProfile.cs" /> <Compile Include="Profiles\Releases\ReleaseProfile.cs" />
<Compile Include="Profiles\Releases\ReleaseProfileRepository.cs" /> <Compile Include="Profiles\Releases\ReleaseProfileRepository.cs" />
<Compile Include="Profiles\Releases\ReleaseProfileService.cs" /> <Compile Include="Profiles\Releases\ReleaseProfileService.cs" />
<Compile Include="Profiles\Releases\TermMatcher.cs" /> <Compile Include="Profiles\Releases\TermMatcherService.cs" />
<Compile Include="Profiles\Releases\TermMatchers\ITermMatcher.cs" />
<Compile Include="Profiles\Releases\TermMatchers\RegexTermMatcher.cs" />
<Compile Include="ProgressMessaging\ProgressMessageContext.cs" /> <Compile Include="ProgressMessaging\ProgressMessageContext.cs" />
<Compile Include="Qualities\QualityDetectionSource.cs" /> <Compile Include="Qualities\QualityDetectionSource.cs" />
<Compile Include="Qualities\Revision.cs" /> <Compile Include="Qualities\Revision.cs" />

@ -344,7 +344,7 @@ namespace NzbDrone.Core.Organizer
{ {
if (preferredWords == null) if (preferredWords == null)
{ {
preferredWords = _preferredWordService.GetMatchingPreferredWords(artist, trackFile.GetSceneOrFileName(), true); preferredWords = _preferredWordService.GetMatchingPreferredWords(artist, trackFile.GetSceneOrFileName());
} }
tokenHandlers["{Preferred Words}"] = m => string.Join(" ", preferredWords); tokenHandlers["{Preferred Words}"] = m => string.Join(" ", preferredWords);

@ -2,25 +2,26 @@ using NLog;
using NzbDrone.Core.Music; using NzbDrone.Core.Music;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NzbDrone.Common.Extensions;
namespace NzbDrone.Core.Profiles.Releases namespace NzbDrone.Core.Profiles.Releases
{ {
public interface IPreferredWordService public interface IPreferredWordService
{ {
int Calculate(Artist artist, string title); int Calculate(Artist artist, string title);
List<string> GetMatchingPreferredWords(Artist artist, string title, bool isRenaming); List<string> GetMatchingPreferredWords(Artist artist, string title);
} }
public class PreferredWordService : IPreferredWordService public class PreferredWordService : IPreferredWordService
{ {
private readonly IReleaseProfileService _releaseProfileService; private readonly IReleaseProfileService _releaseProfileService;
private readonly ITermMatcher _termMatcher; private readonly ITermMatcherService _termMatcherService;
private readonly Logger _logger; private readonly Logger _logger;
public PreferredWordService(IReleaseProfileService releaseProfileService, ITermMatcher termMatcher, Logger logger) public PreferredWordService(IReleaseProfileService releaseProfileService, ITermMatcherService termMatcherService, Logger logger)
{ {
_releaseProfileService = releaseProfileService; _releaseProfileService = releaseProfileService;
_termMatcher = termMatcher; _termMatcherService = termMatcherService;
_logger = logger; _logger = logger;
} }
@ -28,33 +29,39 @@ 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 = GetMatchingPairs(series, title, false); var releaseProfiles = _releaseProfileService.AllForTags(series.Tags);
var score = matchingPairs.Sum(p => p.Value); var matchingPairs = new List<KeyValuePair<string, int>>();
_logger.Trace("Calculated preferred word score for '{0}': {1}", title, score); foreach (var releaseProfile in releaseProfiles)
{
foreach (var preferredPair in releaseProfile.Preferred)
{
var term = preferredPair.Key;
return score; if (_termMatcherService.IsMatch(term, title))
{
matchingPairs.Add(preferredPair);
}
}
} }
public List<string> GetMatchingPreferredWords(Artist artist, string title, bool isRenaming) var score = matchingPairs.Sum(p => p.Value);
{
var matchingPairs = GetMatchingPairs(artist, title, isRenaming);
return matchingPairs.OrderByDescending(p => p.Value) _logger.Trace("Calculated preferred word score for '{0}': {1}", title, score);
.Select(p => p.Key)
.ToList(); return score;
} }
private List<KeyValuePair<string, int>> GetMatchingPairs(Artist artist, string title, bool isRenaming) public List<string> GetMatchingPreferredWords(Artist artist, string title)
{ {
var releaseProfiles = _releaseProfileService.AllForTags(artist.Tags); var releaseProfiles = _releaseProfileService.AllForTags(artist.Tags);
var result = new List<KeyValuePair<string, int>>(); var matchingPairs = new List<KeyValuePair<string, int>>();
_logger.Trace("Calculating preferred word score for '{0}'", title); _logger.Trace("Calculating preferred word score for '{0}'", title);
foreach (var releaseProfile in releaseProfiles) foreach (var releaseProfile in releaseProfiles)
{ {
if (isRenaming && !releaseProfile.IncludePreferredWhenRenaming) if (!releaseProfile.IncludePreferredWhenRenaming)
{ {
continue; continue;
} }
@ -62,15 +69,18 @@ namespace NzbDrone.Core.Profiles.Releases
foreach (var preferredPair in releaseProfile.Preferred) foreach (var preferredPair in releaseProfile.Preferred)
{ {
var term = preferredPair.Key; var term = preferredPair.Key;
var matchingTerm = _termMatcherService.MatchingTerm(term, title);
if (_termMatcher.IsMatch(term, title)) if (matchingTerm.IsNotNullOrWhiteSpace())
{ {
result.Add(preferredPair); matchingPairs.Add(new KeyValuePair<string, int>(matchingTerm, preferredPair.Value));
} }
} }
} }
return result; return matchingPairs.OrderByDescending(p => p.Value)
.Select(p => p.Key)
.ToList();
} }
} }
} }

@ -1,60 +0,0 @@
using System;
using System.Text.RegularExpressions;
using NzbDrone.Common.Cache;
namespace NzbDrone.Core.Profiles.Releases
{
public interface ITermMatcher
{
bool IsMatch(string term, string value);
}
public class TermMatcher : ITermMatcher
{
private ICached<Predicate<string>> _matcherCache;
public TermMatcher(ICacheManager cacheManager)
{
_matcherCache = cacheManager.GetCache<Predicate<string>>(GetType());
}
public bool IsMatch(string term, string value)
{
return GetMatcher(term)(value);
}
public Predicate<string> GetMatcher(string term)
{
return _matcherCache.Get(term, () => CreateMatcherInternal(term), TimeSpan.FromHours(24));
}
private Predicate<string> CreateMatcherInternal(string term)
{
Regex regex;
if (PerlRegexFactory.TryCreateRegex(term, out regex))
{
return regex.IsMatch;
}
else
{
return new CaseInsensitiveTermMatcher(term).IsMatch;
}
}
private sealed class CaseInsensitiveTermMatcher
{
private readonly string _term;
public CaseInsensitiveTermMatcher(string term)
{
_term = term.ToLowerInvariant();
}
public bool IsMatch(string value)
{
return value.ToLowerInvariant().Contains(_term);
}
}
}
}

@ -0,0 +1,52 @@
using System;
using System.Text.RegularExpressions;
using NzbDrone.Common.Cache;
using NzbDrone.Core.Profiles.Releases.TermMatchers;
namespace NzbDrone.Core.Profiles.Releases
{
public interface ITermMatcherService
{
bool IsMatch(string term, string value);
string MatchingTerm(string term, string value);
}
public class TermMatcherService : ITermMatcherService
{
private ICached<ITermMatcher> _matcherCache;
public TermMatcherService(ICacheManager cacheManager)
{
_matcherCache = cacheManager.GetCache<ITermMatcher>(GetType());
}
public bool IsMatch(string term, string value)
{
return GetMatcher(term).IsMatch(value);
}
public string MatchingTerm(string term, string value)
{
return GetMatcher(term).MatchingTerm(value);
}
public ITermMatcher GetMatcher(string term)
{
return _matcherCache.Get(term, () => CreateMatcherInternal(term), TimeSpan.FromHours(24));
}
private ITermMatcher CreateMatcherInternal(string term)
{
Regex regex;
if (PerlRegexFactory.TryCreateRegex(term, out regex))
{
return new RegexTermMatcher(regex);
}
else
{
return new CaseInsensitiveTermMatcher(term);
}
}
}
}

@ -0,0 +1,22 @@
namespace NzbDrone.Core.Profiles.Releases.TermMatchers
{
public sealed class CaseInsensitiveTermMatcher : ITermMatcher
{
private readonly string _term;
public CaseInsensitiveTermMatcher(string term)
{
_term = term.ToLowerInvariant();
}
public bool IsMatch(string value)
{
return value.ToLowerInvariant().Contains(_term);
}
public string MatchingTerm(string value)
{
return _term;
}
}
}

@ -0,0 +1,8 @@
namespace NzbDrone.Core.Profiles.Releases.TermMatchers
{
public interface ITermMatcher
{
bool IsMatch(string value);
string MatchingTerm(string value);
}
}

@ -0,0 +1,24 @@
using System.Text.RegularExpressions;
namespace NzbDrone.Core.Profiles.Releases.TermMatchers
{
public class RegexTermMatcher : ITermMatcher
{
private readonly Regex _regex;
public RegexTermMatcher(Regex regex)
{
_regex = regex;
}
public bool IsMatch(string value)
{
return _regex.IsMatch(value);
}
public string MatchingTerm(string value)
{
return _regex.Match(value).Value;
}
}
}
Loading…
Cancel
Save