From 02d842a2b2378e8b8317dafe93e2977ac48d212e Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Wed, 6 Mar 2013 16:19:49 -0800 Subject: [PATCH] some preliminary work to move decision engine to use the visitor pattern. --- .../AcceptableSizeSpecificationFixture.cs | 1 + .../AllowedDownloadSpecificationFixture.cs | 5 +- ...AllowedReleaseGroupSpecificationFixture.cs | 1 + .../CustomStartDateSpecificationFixture.cs | 1 + .../LanguageSpecificationFixture.cs | 1 + .../MonitoredEpisodeSpecificationFixture.cs | 1 + ...ityAllowedByProfileSpecificationFixture.cs | 1 + .../QualityUpgradableSpecificationFixture.cs | 34 ++++++ .../QualityUpgradeSpecificationFixture.cs | 5 +- .../RetentionSpecificationFixture.cs | 1 + .../UpgradeDiskSpecificationFixture.cs | 3 +- .../UpgradeHistorySpecificationFixture.cs | 3 +- .../UpgradePossibleSpecificationFixture.cs | 103 ------------------ NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 2 +- .../SearchTests/ProcessResultsFixture.cs | 1 + .../ProviderTests/SearchTests/TestSearch.cs | 1 + NzbDrone.Core/Constants.cs | 4 +- .../AllowedDownloadSpecification.cs | 11 +- .../AlreadyInQueueSpecification.cs | 32 ------ .../CustomStartDateSpecification.cs | 29 ----- .../DecisionEngine/IFetchableSpecification.cs | 10 ++ .../DecisionEngine/LanguageSpecification.cs | 23 ---- .../QualityAllowedByProfileSpecification.cs | 23 ---- .../QualityUpgradableSpecification.cs | 47 ++++++++ .../QualityUpgradeSpecification.cs | 36 ------ .../DecisionEngine/RetentionSpecification.cs | 35 ------ .../AcceptableSizeSpecification.cs | 34 +++--- .../AllowedReleaseGroupSpecification.cs | 32 +++--- .../CustomStartDateSpecification.cs | 43 ++++++++ .../Specifications/LanguageSpecification.cs | 35 ++++++ .../MonitoredEpisodeSpecification.cs | 27 +++-- .../Specifications/NotInQueueSpecification.cs | 32 ++++++ .../QualityAllowedByProfileSpecification.cs | 35 ++++++ .../Specifications/RetentionSpecification.cs | 39 +++++++ .../UpgradeDiskSpecification.cs | 46 ++++++++ .../UpgradeHistorySpecification.cs | 44 ++++++++ .../UpgradeDiskSpecification.cs | 41 ------- .../UpgradeHistorySpecification.cs | 42 ------- .../UpgradePossibleSpecification.cs | 41 ------- .../Download/Clients/BlackholeProvider.cs | 1 + .../Download/Clients/PneumaticProvider.cs | 1 + .../Jobs/Implementations/EpisodeSearchJob.cs | 15 ++- .../Jobs/Implementations/RssSyncJob.cs | 1 + NzbDrone.Core/MediaFiles/EpisodeFile.cs | 2 +- NzbDrone.Core/NzbDrone.Core.csproj | 44 +++----- NzbDrone.Core/Providers/DiskScanProvider.cs | 2 +- .../Providers/Search/DailyEpisodeSearch.cs | 1 + .../Providers/Search/EpisodeSearch.cs | 1 + .../Providers/Search/PartialSeasonSearch.cs | 1 + NzbDrone.Core/Providers/Search/SearchBase.cs | 1 + NzbDrone.ncrunchsolution | 2 +- 51 files changed, 470 insertions(+), 507 deletions(-) create mode 100644 NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradableSpecificationFixture.cs delete mode 100644 NzbDrone.Core.Test/DecisionEngineTests/UpgradePossibleSpecificationFixture.cs delete mode 100644 NzbDrone.Core/DecisionEngine/AlreadyInQueueSpecification.cs delete mode 100644 NzbDrone.Core/DecisionEngine/CustomStartDateSpecification.cs create mode 100644 NzbDrone.Core/DecisionEngine/IFetchableSpecification.cs delete mode 100644 NzbDrone.Core/DecisionEngine/LanguageSpecification.cs delete mode 100644 NzbDrone.Core/DecisionEngine/QualityAllowedByProfileSpecification.cs create mode 100644 NzbDrone.Core/DecisionEngine/QualityUpgradableSpecification.cs delete mode 100644 NzbDrone.Core/DecisionEngine/QualityUpgradeSpecification.cs delete mode 100644 NzbDrone.Core/DecisionEngine/RetentionSpecification.cs rename NzbDrone.Core/DecisionEngine/{ => Specifications}/AcceptableSizeSpecification.cs (68%) rename NzbDrone.Core/DecisionEngine/{ => Specifications}/AllowedReleaseGroupSpecification.cs (50%) create mode 100644 NzbDrone.Core/DecisionEngine/Specifications/CustomStartDateSpecification.cs create mode 100644 NzbDrone.Core/DecisionEngine/Specifications/LanguageSpecification.cs rename NzbDrone.Core/DecisionEngine/{ => Specifications}/MonitoredEpisodeSpecification.cs (62%) create mode 100644 NzbDrone.Core/DecisionEngine/Specifications/NotInQueueSpecification.cs create mode 100644 NzbDrone.Core/DecisionEngine/Specifications/QualityAllowedByProfileSpecification.cs create mode 100644 NzbDrone.Core/DecisionEngine/Specifications/RetentionSpecification.cs create mode 100644 NzbDrone.Core/DecisionEngine/Specifications/UpgradeDiskSpecification.cs create mode 100644 NzbDrone.Core/DecisionEngine/Specifications/UpgradeHistorySpecification.cs delete mode 100644 NzbDrone.Core/DecisionEngine/UpgradeDiskSpecification.cs delete mode 100644 NzbDrone.Core/DecisionEngine/UpgradeHistorySpecification.cs delete mode 100644 NzbDrone.Core/DecisionEngine/UpgradePossibleSpecification.cs diff --git a/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs index 76e38237c..9ea99b486 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/AcceptableSizeSpecificationFixture.cs @@ -7,6 +7,7 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; using NzbDrone.Core.Model; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs index d310139ed..8cfa6a87f 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/AllowedDownloadSpecificationFixture.cs @@ -7,6 +7,7 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; using NzbDrone.Core.DecisionEngine; @@ -40,7 +41,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests .Setup(c => c.IsSatisfiedBy(It.IsAny())) .Returns(true); - Mocker.GetMock() + Mocker.GetMock() .Setup(c => c.IsSatisfiedBy(It.IsAny())) .Returns(false); @@ -84,7 +85,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests private void WithEpisodeAlreadyInQueue() { - Mocker.GetMock() + Mocker.GetMock() .Setup(c => c.IsSatisfiedBy(It.IsAny())) .Returns(true); } diff --git a/NzbDrone.Core.Test/DecisionEngineTests/AllowedReleaseGroupSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/AllowedReleaseGroupSpecificationFixture.cs index 03d8105fc..2ff13388d 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/AllowedReleaseGroupSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/AllowedReleaseGroupSpecificationFixture.cs @@ -8,6 +8,7 @@ using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Configuration; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; using NzbDrone.Core.Model; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/CustomStartDateSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/CustomStartDateSpecificationFixture.cs index 50410bbd0..b22c74d39 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/CustomStartDateSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/CustomStartDateSpecificationFixture.cs @@ -7,6 +7,7 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Tv; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/LanguageSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/LanguageSpecificationFixture.cs index d72d25038..fc904005d 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/LanguageSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/LanguageSpecificationFixture.cs @@ -7,6 +7,7 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; using NzbDrone.Core.DecisionEngine; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/MonitoredEpisodeSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/MonitoredEpisodeSpecificationFixture.cs index 230164b81..a36fb4cf6 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/MonitoredEpisodeSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/MonitoredEpisodeSpecificationFixture.cs @@ -7,6 +7,7 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Tv; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs index 9ac0fee49..1d9087d02 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/QualityAllowedByProfileSpecificationFixture.cs @@ -5,6 +5,7 @@ using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; using NzbDrone.Core.Model; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradableSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradableSpecificationFixture.cs new file mode 100644 index 000000000..c7eb4bf4b --- /dev/null +++ b/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradableSpecificationFixture.cs @@ -0,0 +1,34 @@ +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Core.Qualities; +using NzbDrone.Core.Tv; +using NzbDrone.Core.DecisionEngine; +using NzbDrone.Core.Test.Framework; + +namespace NzbDrone.Core.Test.DecisionEngineTests +{ + [TestFixture] + public class QualityUpgradableSpecificationFixture : CoreTest + { + [Test] + public void IsUpgradePossible_should_return_true_if_current_episode_is_less_than_cutoff() + { + Subject.IsUpgradable(new QualityProfile { Cutoff = Quality.Bluray1080p }, + new QualityModel(Quality.DVD, true)).Should().BeTrue(); + } + + [Test] + public void IsUpgradePossible_should_return_false_if_current_episode_is_equal_to_cutoff() + { + Subject.IsUpgradable(new QualityProfile { Cutoff = Quality.HDTV720p }, + new QualityModel(Quality.HDTV720p, true)).Should().BeFalse(); + } + + [Test] + public void IsUpgradePossible_should_return_false_if_current_episode_is_greater_than_cutoff() + { + Subject.IsUpgradable(new QualityProfile { Cutoff = Quality.HDTV720p }, + new QualityModel(Quality.Bluray1080p, true)).Should().BeFalse(); + } + } +} \ No newline at end of file diff --git a/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs index 88231660b..88d0dd626 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/QualityUpgradeSpecificationFixture.cs @@ -3,6 +3,7 @@ using System.Linq; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; using NzbDrone.Core.Model; @@ -13,7 +14,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests { [TestFixture] // ReSharper disable InconsistentNaming - public class QualityUpgradeSpecificationFixture : CoreTest + public class QualityUpgradeSpecificationFixture : CoreTest { public static object[] IsUpgradeTestCases = { @@ -31,7 +32,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests [Test, TestCaseSource("IsUpgradeTestCases")] public void IsUpgradeTest(Quality current, bool currentProper, Quality newQuality, bool newProper, Quality cutoff, bool expected) { - new QualityUpgradeSpecification().IsSatisfiedBy(new QualityModel(current, currentProper), new QualityModel(newQuality, newProper), cutoff) + Subject.IsUpgradable(new QualityProfile() { Cutoff = cutoff }, new QualityModel(current, currentProper), new QualityModel(newQuality, newProper)) .Should().Be(expected); } } diff --git a/NzbDrone.Core.Test/DecisionEngineTests/RetentionSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/RetentionSpecificationFixture.cs index 2cd2c11eb..a57e74d1b 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/RetentionSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/RetentionSpecificationFixture.cs @@ -8,6 +8,7 @@ using FluentAssertions; using Moq; using NUnit.Framework; using NzbDrone.Core.Configuration; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Model; using NzbDrone.Core.Providers; using NzbDrone.Core.DecisionEngine; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs index e05d43a25..893cbba96 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/UpgradeDiskSpecificationFixture.cs @@ -6,6 +6,7 @@ using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; @@ -31,7 +32,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests [SetUp] public void Setup() { - Mocker.Resolve(); + Mocker.Resolve(); _upgradeDisk = Mocker.Resolve(); firstFile = new EpisodeFile { Quality = Quality.Bluray1080p, Proper = true, DateAdded = DateTime.Now }; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/UpgradeHistorySpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/UpgradeHistorySpecificationFixture.cs index 7d7dcca5e..e08f051b4 100644 --- a/NzbDrone.Core.Test/DecisionEngineTests/UpgradeHistorySpecificationFixture.cs +++ b/NzbDrone.Core.Test/DecisionEngineTests/UpgradeHistorySpecificationFixture.cs @@ -5,6 +5,7 @@ using System.Linq; using FizzWare.NBuilder; using FluentAssertions; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.History; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; @@ -31,7 +32,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests [SetUp] public void Setup() { - Mocker.Resolve(); + Mocker.Resolve(); _upgradeHistory = Mocker.Resolve(); var singleEpisodeList = new List { new Episode { SeasonNumber = 12, EpisodeNumber = 3 } }; diff --git a/NzbDrone.Core.Test/DecisionEngineTests/UpgradePossibleSpecificationFixture.cs b/NzbDrone.Core.Test/DecisionEngineTests/UpgradePossibleSpecificationFixture.cs deleted file mode 100644 index 5affcec7c..000000000 --- a/NzbDrone.Core.Test/DecisionEngineTests/UpgradePossibleSpecificationFixture.cs +++ /dev/null @@ -1,103 +0,0 @@ -// ReSharper disable RedundantUsingDirective - -using System.Linq; -using FizzWare.NBuilder; -using FluentAssertions; -using Moq; -using NUnit.Framework; -using NzbDrone.Core.MediaFiles; -using NzbDrone.Core.Qualities; -using NzbDrone.Core.Tv; -using NzbDrone.Core.Providers; -using NzbDrone.Core.DecisionEngine; -using NzbDrone.Core.Repository; -using NzbDrone.Core.Test.Framework; - -namespace NzbDrone.Core.Test.DecisionEngineTests -{ - [TestFixture] - // ReSharper disable InconsistentNaming - public class UpgradePossibleSpecificationFixture : CoreTest - { - private void WithWebdlCutoff() - { - var profile = new QualityProfile { Cutoff = Quality.WEBDL720p }; - Mocker.GetMock().Setup(s => s.Get(It.IsAny())).Returns(profile); - } - - private Series _series; - private EpisodeFile _episodeFile; - private Episode _episode; - - [SetUp] - public void SetUp() - { - _series = Builder.CreateNew() - .Build(); - - _episodeFile = Builder.CreateNew() - .With(f => f.Quality = Quality.SDTV) - .Build(); - - _episode = Builder.CreateNew() - .With(e => e.SeriesId = _series.Id) - .With(e => e.Series = _series) - .With(e => e.EpisodeFile = _episodeFile) - .Build(); - } - - [Test] - public void IsUpgradePossible_should_return_true_if_no_episode_file_exists() - { - var episode = Builder.CreateNew() - .With(e => e.EpisodeFile = null) - .Build(); - - //Act - bool result = Mocker.Resolve().IsSatisfiedBy(episode); - - //Assert - result.Should().BeTrue(); - } - - [Test] - public void IsUpgradePossible_should_return_true_if_current_episode_is_less_than_cutoff() - { - WithWebdlCutoff(); - - //Act - bool result = Mocker.Resolve().IsSatisfiedBy(_episode); - - //Assert - result.Should().BeTrue(); - } - - [Test] - public void IsUpgradePossible_should_return_false_if_current_episode_is_equal_to_cutoff() - { - WithWebdlCutoff(); - - _episodeFile.Quality = Quality.WEBDL720p; - - //Act - bool result = Mocker.Resolve().IsSatisfiedBy(_episode); - - //Assert - result.Should().BeFalse(); - } - - [Test] - public void IsUpgradePossible_should_return_false_if_current_episode_is_greater_than_cutoff() - { - WithWebdlCutoff(); - - _episodeFile.Quality = Quality.Bluray720p; - - //Act - bool result = Mocker.Resolve().IsSatisfiedBy(_episode); - - //Assert - result.Should().BeFalse(); - } - } -} \ No newline at end of file diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index 3ec096119..df839656e 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -191,7 +191,7 @@ - + diff --git a/NzbDrone.Core.Test/ProviderTests/SearchTests/ProcessResultsFixture.cs b/NzbDrone.Core.Test/ProviderTests/SearchTests/ProcessResultsFixture.cs index 1734cf86b..4507e6dc2 100644 --- a/NzbDrone.Core.Test/ProviderTests/SearchTests/ProcessResultsFixture.cs +++ b/NzbDrone.Core.Test/ProviderTests/SearchTests/ProcessResultsFixture.cs @@ -6,6 +6,7 @@ using FizzWare.NBuilder; using FluentAssertions; using Moq; using NUnit.Framework; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Download; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; diff --git a/NzbDrone.Core.Test/ProviderTests/SearchTests/TestSearch.cs b/NzbDrone.Core.Test/ProviderTests/SearchTests/TestSearch.cs index 39d794353..f99d922a2 100644 --- a/NzbDrone.Core.Test/ProviderTests/SearchTests/TestSearch.cs +++ b/NzbDrone.Core.Test/ProviderTests/SearchTests/TestSearch.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using NLog; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.ReferenceData; diff --git a/NzbDrone.Core/Constants.cs b/NzbDrone.Core/Constants.cs index 6f90059e8..883525059 100644 --- a/NzbDrone.Core/Constants.cs +++ b/NzbDrone.Core/Constants.cs @@ -1,6 +1,4 @@ -using System.Linq; - -namespace NzbDrone.Core +namespace NzbDrone.Core { public static class Constants { diff --git a/NzbDrone.Core/DecisionEngine/AllowedDownloadSpecification.cs b/NzbDrone.Core/DecisionEngine/AllowedDownloadSpecification.cs index f25edfdab..5c6d76620 100644 --- a/NzbDrone.Core/DecisionEngine/AllowedDownloadSpecification.cs +++ b/NzbDrone.Core/DecisionEngine/AllowedDownloadSpecification.cs @@ -1,7 +1,6 @@ -using System.Linq; using NLog; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Model; -using NzbDrone.Core.Repository.Search; namespace NzbDrone.Core.DecisionEngine { @@ -10,7 +9,7 @@ namespace NzbDrone.Core.DecisionEngine private readonly QualityAllowedByProfileSpecification _qualityAllowedByProfileSpecification; private readonly UpgradeDiskSpecification _upgradeDiskSpecification; private readonly AcceptableSizeSpecification _acceptableSizeSpecification; - private readonly AlreadyInQueueSpecification _alreadyInQueueSpecification; + private readonly NotInQueueSpecification _notInQueueSpecification; private readonly RetentionSpecification _retentionSpecification; private readonly AllowedReleaseGroupSpecification _allowedReleaseGroupSpecification; private readonly CustomStartDateSpecification _customStartDateSpecification; @@ -19,14 +18,14 @@ namespace NzbDrone.Core.DecisionEngine public AllowedDownloadSpecification(QualityAllowedByProfileSpecification qualityAllowedByProfileSpecification, UpgradeDiskSpecification upgradeDiskSpecification, AcceptableSizeSpecification acceptableSizeSpecification, - AlreadyInQueueSpecification alreadyInQueueSpecification, RetentionSpecification retentionSpecification, + NotInQueueSpecification notInQueueSpecification, RetentionSpecification retentionSpecification, AllowedReleaseGroupSpecification allowedReleaseGroupSpecification, CustomStartDateSpecification customStartDateSpecification, LanguageSpecification languageSpecification) { _qualityAllowedByProfileSpecification = qualityAllowedByProfileSpecification; _upgradeDiskSpecification = upgradeDiskSpecification; _acceptableSizeSpecification = acceptableSizeSpecification; - _alreadyInQueueSpecification = alreadyInQueueSpecification; + _notInQueueSpecification = notInQueueSpecification; _retentionSpecification = retentionSpecification; _allowedReleaseGroupSpecification = allowedReleaseGroupSpecification; _customStartDateSpecification = customStartDateSpecification; @@ -46,7 +45,7 @@ namespace NzbDrone.Core.DecisionEngine if (!_retentionSpecification.IsSatisfiedBy(subject)) return ReportRejectionReasons.Retention; if (!_acceptableSizeSpecification.IsSatisfiedBy(subject)) return ReportRejectionReasons.Size; if (!_allowedReleaseGroupSpecification.IsSatisfiedBy(subject)) return ReportRejectionReasons.ReleaseGroupNotWanted; - if (_alreadyInQueueSpecification.IsSatisfiedBy(subject)) return ReportRejectionReasons.AlreadyInQueue; + if (!_notInQueueSpecification.IsSatisfiedBy(subject)) return ReportRejectionReasons.AlreadyInQueue; logger.Debug("Episode {0} is needed", subject); return ReportRejectionReasons.None; diff --git a/NzbDrone.Core/DecisionEngine/AlreadyInQueueSpecification.cs b/NzbDrone.Core/DecisionEngine/AlreadyInQueueSpecification.cs deleted file mode 100644 index e5c59d6c4..000000000 --- a/NzbDrone.Core/DecisionEngine/AlreadyInQueueSpecification.cs +++ /dev/null @@ -1,32 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Download; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; - -namespace NzbDrone.Core.DecisionEngine -{ - public class AlreadyInQueueSpecification - { - private readonly DownloadProvider _downloadProvider; - - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public AlreadyInQueueSpecification(DownloadProvider downloadProvider) - { - _downloadProvider = downloadProvider; - - } - - public AlreadyInQueueSpecification() - { - - } - - public virtual bool IsSatisfiedBy(EpisodeParseResult subject) - { - return _downloadProvider.GetActiveDownloadClient().IsInQueue(subject); - } - - } -} diff --git a/NzbDrone.Core/DecisionEngine/CustomStartDateSpecification.cs b/NzbDrone.Core/DecisionEngine/CustomStartDateSpecification.cs deleted file mode 100644 index 8d987204d..000000000 --- a/NzbDrone.Core/DecisionEngine/CustomStartDateSpecification.cs +++ /dev/null @@ -1,29 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Model; - -namespace NzbDrone.Core.DecisionEngine -{ - public class CustomStartDateSpecification - { - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public virtual bool IsSatisfiedBy(EpisodeParseResult subject) - { - if (!subject.Series.CustomStartDate.HasValue) - { - logger.Debug("{0} does not restrict downloads before date.", subject.Series.Title); - return true; - } - - if (subject.Episodes.Any(episode => episode.AirDate >= subject.Series.CustomStartDate.Value)) - { - logger.Debug("One or more episodes aired after cutoff, downloading."); - return true; - } - - logger.Debug("Episodes aired before cutoff date: {0}", subject.Series.CustomStartDate); - return false; - } - } -} diff --git a/NzbDrone.Core/DecisionEngine/IFetchableSpecification.cs b/NzbDrone.Core/DecisionEngine/IFetchableSpecification.cs new file mode 100644 index 000000000..efb3b6c15 --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/IFetchableSpecification.cs @@ -0,0 +1,10 @@ +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.DecisionEngine +{ + public interface IFetchableSpecification + { + string RejectionReason { get; } + bool IsSatisfiedBy(EpisodeParseResult subject); + } +} \ No newline at end of file diff --git a/NzbDrone.Core/DecisionEngine/LanguageSpecification.cs b/NzbDrone.Core/DecisionEngine/LanguageSpecification.cs deleted file mode 100644 index 32bd24cf2..000000000 --- a/NzbDrone.Core/DecisionEngine/LanguageSpecification.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Model; - -namespace NzbDrone.Core.DecisionEngine -{ - public class LanguageSpecification - { - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public virtual bool IsSatisfiedBy(EpisodeParseResult subject) - { - logger.Trace("Checking if report meets language requirements. {0}", subject.Language); - if (subject.Language != LanguageType.English) - { - logger.Trace("Report Language: {0} rejected because it is not english", subject.Language); - return false; - } - - return true; - } - } -} diff --git a/NzbDrone.Core/DecisionEngine/QualityAllowedByProfileSpecification.cs b/NzbDrone.Core/DecisionEngine/QualityAllowedByProfileSpecification.cs deleted file mode 100644 index 5355abc51..000000000 --- a/NzbDrone.Core/DecisionEngine/QualityAllowedByProfileSpecification.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Model; - -namespace NzbDrone.Core.DecisionEngine -{ - public class QualityAllowedByProfileSpecification - { - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public virtual bool IsSatisfiedBy(EpisodeParseResult subject) - { - logger.Trace("Checking if report meets quality requirements. {0}", subject.Quality); - if (!subject.Series.QualityProfile.Allowed.Contains(subject.Quality.Quality)) - { - logger.Trace("Quality {0} rejected by Series' quality profile", subject.Quality); - return false; - } - - return true; - } - } -} diff --git a/NzbDrone.Core/DecisionEngine/QualityUpgradableSpecification.cs b/NzbDrone.Core/DecisionEngine/QualityUpgradableSpecification.cs new file mode 100644 index 000000000..f99e9f46b --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/QualityUpgradableSpecification.cs @@ -0,0 +1,47 @@ +using NLog; +using NzbDrone.Core.Qualities; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.DecisionEngine +{ + public interface IQualityUpgradableSpecification + { + bool IsUpgradable(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null); + } + + public class QualityUpgradableSpecification : IQualityUpgradableSpecification + { + private readonly Logger _logger; + + public QualityUpgradableSpecification(Logger logger) + { + _logger = logger; + } + + public bool IsUpgradable(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null) + { + if (newQuality != null) + { + if (currentQuality >= newQuality) + { + _logger.Trace("existing item has better or equal quality. skipping"); + return false; + } + + if (currentQuality.Quality == newQuality.Quality && newQuality.Proper) + { + _logger.Trace("Upgrading existing item to proper."); + return true; + } + } + + if (currentQuality.Quality >= profile.Cutoff) + { + _logger.Trace("Existing item meets cut-off. skipping."); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/DecisionEngine/QualityUpgradeSpecification.cs b/NzbDrone.Core/DecisionEngine/QualityUpgradeSpecification.cs deleted file mode 100644 index ca714f7d0..000000000 --- a/NzbDrone.Core/DecisionEngine/QualityUpgradeSpecification.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Qualities; -using NzbDrone.Core.Tv; -using NzbDrone.Core.Model; - -namespace NzbDrone.Core.DecisionEngine -{ - public class QualityUpgradeSpecification - { - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public virtual bool IsSatisfiedBy(QualityModel currentQuality, QualityModel newQuality, Quality cutOff) - { - if (currentQuality >= newQuality) - { - logger.Trace("existing item has better or equal quality. skipping"); - return false; - } - - if (currentQuality.Quality == newQuality.Quality && newQuality.Proper) - { - logger.Trace("Upgrading existing item to proper."); - return true; - } - - if (currentQuality.Quality >= cutOff) - { - logger.Trace("Existing item meets cut-off. skipping."); - return false; - } - - return true; - } - } -} diff --git a/NzbDrone.Core/DecisionEngine/RetentionSpecification.cs b/NzbDrone.Core/DecisionEngine/RetentionSpecification.cs deleted file mode 100644 index 654e996bc..000000000 --- a/NzbDrone.Core/DecisionEngine/RetentionSpecification.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Configuration; -using NzbDrone.Core.Model; - -namespace NzbDrone.Core.DecisionEngine -{ - public class RetentionSpecification - { - private readonly IConfigService _configService; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public RetentionSpecification(IConfigService configService) - { - _configService = configService; - } - - public RetentionSpecification() - { - - } - - public virtual bool IsSatisfiedBy(EpisodeParseResult subject) - { - logger.Trace("Checking if report meets retention requirements. {0}", subject.Age); - if (_configService.Retention > 0 && subject.Age > _configService.Retention) - { - logger.Trace("Report age: {0} rejected by user's retention limit", subject.Age); - return false; - } - - return true; - } - } -} diff --git a/NzbDrone.Core/DecisionEngine/AcceptableSizeSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs similarity index 68% rename from NzbDrone.Core/DecisionEngine/AcceptableSizeSpecification.cs rename to NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs index 76ef62767..525b35a68 100644 --- a/NzbDrone.Core/DecisionEngine/AcceptableSizeSpecification.cs +++ b/NzbDrone.Core/DecisionEngine/Specifications/AcceptableSizeSpecification.cs @@ -1,37 +1,35 @@ -using System.Linq; using NLog; -using NzbDrone.Core.Datastore; +using NzbDrone.Core.Model; using NzbDrone.Core.Qualities; using NzbDrone.Core.Tv; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; -namespace NzbDrone.Core.DecisionEngine +namespace NzbDrone.Core.DecisionEngine.Specifications { - public class AcceptableSizeSpecification + public class AcceptableSizeSpecification : IFetchableSpecification { private readonly IQualitySizeService _qualityTypeProvider; private readonly IEpisodeService _episodeService; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger; - public AcceptableSizeSpecification(IQualitySizeService qualityTypeProvider, IEpisodeService episodeService) + public AcceptableSizeSpecification(IQualitySizeService qualityTypeProvider, IEpisodeService episodeService, Logger logger) { _qualityTypeProvider = qualityTypeProvider; _episodeService = episodeService; + _logger = logger; } - public AcceptableSizeSpecification() + public string RejectionReason { - + get { return "File size too big or small"; } } public virtual bool IsSatisfiedBy(EpisodeParseResult subject) { - logger.Trace("Beginning size check for: {0}", subject); + _logger.Trace("Beginning size check for: {0}", subject); - if(subject.Quality.Quality == Quality.RAWHD) + if (subject.Quality.Quality == Quality.RAWHD) { - logger.Trace("Raw-HD release found, skipping size check."); + _logger.Trace("Raw-HD release found, skipping size check."); return true; } @@ -39,7 +37,7 @@ namespace NzbDrone.Core.DecisionEngine if (qualityType.MaxSize == 0) { - logger.Trace("Max size is 0 (unlimited) - skipping check."); + _logger.Trace("Max size is 0 (unlimited) - skipping check."); return true; } @@ -66,13 +64,13 @@ namespace NzbDrone.Core.DecisionEngine //If the parsed size is greater than maxSize we don't want it if (subject.Size > maxSize) { - logger.Trace("Item: {0}, Size: {1} is greater than maximum allowed size ({2}), rejecting.", subject, subject.Size, maxSize); + _logger.Trace("Item: {0}, Size: {1} is greater than maximum allowed size ({2}), rejecting.", subject, subject.Size, maxSize); return false; } - - logger.Trace("Item: {0}, meets size contraints.", subject); + + _logger.Trace("Item: {0}, meets size constraints.", subject); return true; } - + } } diff --git a/NzbDrone.Core/DecisionEngine/AllowedReleaseGroupSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/AllowedReleaseGroupSpecification.cs similarity index 50% rename from NzbDrone.Core/DecisionEngine/AllowedReleaseGroupSpecification.cs rename to NzbDrone.Core/DecisionEngine/Specifications/AllowedReleaseGroupSpecification.cs index 1a98776ee..2baf97d2f 100644 --- a/NzbDrone.Core/DecisionEngine/AllowedReleaseGroupSpecification.cs +++ b/NzbDrone.Core/DecisionEngine/Specifications/AllowedReleaseGroupSpecification.cs @@ -1,46 +1,50 @@ -using System; -using System.Linq; +using System; using NLog; using NzbDrone.Core.Configuration; using NzbDrone.Core.Model; -namespace NzbDrone.Core.DecisionEngine +namespace NzbDrone.Core.DecisionEngine.Specifications { - public class AllowedReleaseGroupSpecification + public class AllowedReleaseGroupSpecification : IFetchableSpecification { private readonly IConfigService _configService; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger; - public AllowedReleaseGroupSpecification(IConfigService configService) + public AllowedReleaseGroupSpecification(IConfigService configService, Logger logger) { _configService = configService; + _logger = logger; } - public AllowedReleaseGroupSpecification() + + public string RejectionReason { - + get + { + return "Release group is blacklisted."; + } } public virtual bool IsSatisfiedBy(EpisodeParseResult subject) { - logger.Trace("Beginning release group check for: {0}", subject); + _logger.Trace("Beginning release group check for: {0}", subject); var allowed = _configService.AllowedReleaseGroups; if (string.IsNullOrWhiteSpace(allowed)) return true; - foreach(var group in allowed.Trim(',', ' ').Split(',')) + foreach (var group in allowed.Trim(',', ' ').Split(',')) { if (subject.ReleaseGroup.Equals(group.Trim(' '), StringComparison.CurrentCultureIgnoreCase)) { - logger.Trace("Item: {0}'s release group is wanted: {1}", subject, subject.ReleaseGroup); + _logger.Trace("Item: {0}'s release group is wanted: {1}", subject, subject.ReleaseGroup); return true; } } - - logger.Trace("Item: {0}'s release group is not wanted: {1}", subject, subject.ReleaseGroup); + + _logger.Trace("Item: {0}'s release group is not wanted: {1}", subject, subject.ReleaseGroup); return false; - } + } } } diff --git a/NzbDrone.Core/DecisionEngine/Specifications/CustomStartDateSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/CustomStartDateSpecification.cs new file mode 100644 index 000000000..47def975a --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/Specifications/CustomStartDateSpecification.cs @@ -0,0 +1,43 @@ +using System.Linq; +using NLog; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.DecisionEngine.Specifications +{ + public class CustomStartDateSpecification : IFetchableSpecification + { + private readonly Logger _logger; + + public CustomStartDateSpecification(Logger logger) + { + _logger = logger; + } + + public string RejectionReason + { + get + { + return "Aired before configured cut-off"; + } + } + + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + if (!subject.Series.CustomStartDate.HasValue) + { + _logger.Debug("{0} does not restrict downloads before date.", subject.Series.Title); + return true; + } + + if (subject.Episodes.Any(episode => episode.AirDate >= subject.Series.CustomStartDate.Value)) + { + _logger.Debug("One or more episodes aired after cutoff, downloading."); + return true; + } + + _logger.Debug("Episodes aired before cutoff date: {0}", subject.Series.CustomStartDate); + return false; + } + } +} diff --git a/NzbDrone.Core/DecisionEngine/Specifications/LanguageSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/LanguageSpecification.cs new file mode 100644 index 000000000..47c793937 --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/Specifications/LanguageSpecification.cs @@ -0,0 +1,35 @@ +using NLog; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.DecisionEngine.Specifications +{ + public class LanguageSpecification : IFetchableSpecification + { + private readonly Logger _logger; + + public LanguageSpecification(Logger logger) + { + _logger = logger; + } + + public string RejectionReason + { + get + { + return "Not English"; + } + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + _logger.Trace("Checking if report meets language requirements. {0}", subject.Language); + if (subject.Language != LanguageType.English) + { + _logger.Trace("Report Language: {0} rejected because it is not English", subject.Language); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/DecisionEngine/MonitoredEpisodeSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/MonitoredEpisodeSpecification.cs similarity index 62% rename from NzbDrone.Core/DecisionEngine/MonitoredEpisodeSpecification.cs rename to NzbDrone.Core/DecisionEngine/Specifications/MonitoredEpisodeSpecification.cs index 00385dad4..af769d63e 100644 --- a/NzbDrone.Core/DecisionEngine/MonitoredEpisodeSpecification.cs +++ b/NzbDrone.Core/DecisionEngine/Specifications/MonitoredEpisodeSpecification.cs @@ -1,26 +1,29 @@ -using System.Linq; +using System.Linq; using NLog; -using NzbDrone.Core.Tv; using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; +using NzbDrone.Core.Tv; -namespace NzbDrone.Core.DecisionEngine +namespace NzbDrone.Core.DecisionEngine.Specifications { - public class MonitoredEpisodeSpecification + public class MonitoredEpisodeSpecification : IFetchableSpecification { private readonly IEpisodeService _episodeService; private readonly ISeriesRepository _seriesRepository; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); + private readonly Logger _logger; - public MonitoredEpisodeSpecification(IEpisodeService episodeService, ISeriesRepository seriesRepository) + public MonitoredEpisodeSpecification(IEpisodeService episodeService, ISeriesRepository seriesRepository, Logger logger) { _episodeService = episodeService; _seriesRepository = seriesRepository; + _logger = logger; } - public MonitoredEpisodeSpecification() + public string RejectionReason { - + get + { + return "Series is not monitored"; + } } public virtual bool IsSatisfiedBy(EpisodeParseResult subject) @@ -29,7 +32,7 @@ namespace NzbDrone.Core.DecisionEngine if (series == null) { - logger.Trace("{0} is not mapped to any series in DB. skipping", subject.CleanTitle); + _logger.Trace("{0} is not mapped to any series in DB. skipping", subject.CleanTitle); return false; } @@ -37,7 +40,7 @@ namespace NzbDrone.Core.DecisionEngine if (!series.Monitored) { - logger.Debug("{0} is present in the DB but not tracked. skipping.", subject.CleanTitle); + _logger.Debug("{0} is present in the DB but not tracked. skipping.", subject.CleanTitle); return false; } @@ -50,7 +53,7 @@ namespace NzbDrone.Core.DecisionEngine return true; } - logger.Debug("All episodes are ignored. skipping."); + _logger.Debug("All episodes are ignored. skipping."); return false; } } diff --git a/NzbDrone.Core/DecisionEngine/Specifications/NotInQueueSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/NotInQueueSpecification.cs new file mode 100644 index 000000000..2c1a8a168 --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/Specifications/NotInQueueSpecification.cs @@ -0,0 +1,32 @@ +using NLog; +using NzbDrone.Core.Download; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.DecisionEngine.Specifications +{ + public class NotInQueueSpecification : IFetchableSpecification + { + private readonly DownloadProvider _downloadProvider; + + + public NotInQueueSpecification(DownloadProvider downloadProvider) + { + _downloadProvider = downloadProvider; + + } + + public string RejectionReason + { + get + { + return "Already in download queue."; + } + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + return !_downloadProvider.GetActiveDownloadClient().IsInQueue(subject); + } + + } +} diff --git a/NzbDrone.Core/DecisionEngine/Specifications/QualityAllowedByProfileSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/QualityAllowedByProfileSpecification.cs new file mode 100644 index 000000000..435cb8dd9 --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/Specifications/QualityAllowedByProfileSpecification.cs @@ -0,0 +1,35 @@ +using NLog; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.DecisionEngine.Specifications +{ + public class QualityAllowedByProfileSpecification : IFetchableSpecification + { + private readonly Logger _logger; + + public QualityAllowedByProfileSpecification(Logger logger) + { + _logger = logger; + } + + public string RejectionReason + { + get + { + return "Quality rejected by series profile"; + } + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + _logger.Trace("Checking if report meets quality requirements. {0}", subject.Quality); + if (!subject.Series.QualityProfile.Allowed.Contains(subject.Quality.Quality)) + { + _logger.Trace("Quality {0} rejected by Series' quality profile", subject.Quality); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/DecisionEngine/Specifications/RetentionSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/RetentionSpecification.cs new file mode 100644 index 000000000..4b9bef567 --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/Specifications/RetentionSpecification.cs @@ -0,0 +1,39 @@ +using NLog; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.DecisionEngine.Specifications +{ + public class RetentionSpecification : IFetchableSpecification + { + private readonly IConfigService _configService; + private readonly Logger _logger; + + public RetentionSpecification(IConfigService configService, Logger logger) + { + _configService = configService; + _logger = logger; + } + + + public string RejectionReason + { + get + { + return "Report past retention limit."; + } + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + _logger.Trace("Checking if report meets retention requirements. {0}", subject.Age); + if (_configService.Retention > 0 && subject.Age > _configService.Retention) + { + _logger.Trace("Report age: {0} rejected by user's retention limit", subject.Age); + return false; + } + + return true; + } + } +} diff --git a/NzbDrone.Core/DecisionEngine/Specifications/UpgradeDiskSpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/UpgradeDiskSpecification.cs new file mode 100644 index 000000000..3260d84b2 --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/Specifications/UpgradeDiskSpecification.cs @@ -0,0 +1,46 @@ +using System; +using System.Linq; +using NLog; +using NzbDrone.Core.Model; +using NzbDrone.Core.Tv; + +namespace NzbDrone.Core.DecisionEngine.Specifications +{ + public class UpgradeDiskSpecification : IFetchableSpecification + { + private readonly QualityUpgradableSpecification _qualityUpgradableSpecification; + private readonly Logger _logger; + + public UpgradeDiskSpecification(QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger) + { + _qualityUpgradableSpecification = qualityUpgradableSpecification; + _logger = logger; + } + + public string RejectionReason + { + get + { + return "Higher quality exists on disk"; + } + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + foreach (var file in subject.Episodes.Select(c => c.EpisodeFile).Where(c => c != null)) + { + _logger.Trace("Comparing file quality with report. Existing file is {0} proper:{1}", file.Quality, file.Proper); + if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.QualityProfile, new QualityModel { Quality = file.Quality, Proper = file.Proper }, subject.Quality)) + return false; + + if (subject.Quality.Proper && file.DateAdded < DateTime.Today.AddDays(-7)) + { + _logger.Trace("Proper for old file, skipping: {0}", subject); + return false; + } + } + + return true; + } + } +} diff --git a/NzbDrone.Core/DecisionEngine/Specifications/UpgradeHistorySpecification.cs b/NzbDrone.Core/DecisionEngine/Specifications/UpgradeHistorySpecification.cs new file mode 100644 index 000000000..8f87fac16 --- /dev/null +++ b/NzbDrone.Core/DecisionEngine/Specifications/UpgradeHistorySpecification.cs @@ -0,0 +1,44 @@ +using NLog; +using NzbDrone.Core.History; +using NzbDrone.Core.Model; + +namespace NzbDrone.Core.DecisionEngine.Specifications +{ + public class UpgradeHistorySpecification : IFetchableSpecification + { + private readonly IHistoryService _historyService; + private readonly QualityUpgradableSpecification _qualityUpgradableSpecification; + private readonly Logger _logger; + + public UpgradeHistorySpecification(IHistoryService historyService, QualityUpgradableSpecification qualityUpgradableSpecification, Logger logger) + { + _historyService = historyService; + _qualityUpgradableSpecification = qualityUpgradableSpecification; + _logger = logger; + } + + public string RejectionReason + { + get + { + return "Higher quality report exists in history"; + } + } + + public virtual bool IsSatisfiedBy(EpisodeParseResult subject) + { + foreach (var episode in subject.Episodes) + { + var bestQualityInHistory = _historyService.GetBestQualityInHistory(subject.Series.Id, episode.SeasonNumber, episode.EpisodeNumber); + if (bestQualityInHistory != null) + { + _logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory); + if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.QualityProfile, bestQualityInHistory, subject.Quality)) + return false; + } + } + + return true; + } + } +} diff --git a/NzbDrone.Core/DecisionEngine/UpgradeDiskSpecification.cs b/NzbDrone.Core/DecisionEngine/UpgradeDiskSpecification.cs deleted file mode 100644 index 4411f13e1..000000000 --- a/NzbDrone.Core/DecisionEngine/UpgradeDiskSpecification.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System; -using System.Linq; -using NLog; -using NzbDrone.Core.Tv; -using NzbDrone.Core.Model; - -namespace NzbDrone.Core.DecisionEngine -{ - public class UpgradeDiskSpecification - { - private readonly QualityUpgradeSpecification _qualityUpgradeSpecification; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public UpgradeDiskSpecification(QualityUpgradeSpecification qualityUpgradeSpecification) - { - _qualityUpgradeSpecification = qualityUpgradeSpecification; - } - - public UpgradeDiskSpecification() - { - } - - public virtual bool IsSatisfiedBy(EpisodeParseResult subject) - { - foreach (var file in subject.Episodes.Select(c => c.EpisodeFile).Where(c => c != null)) - { - logger.Trace("Comparing file quality with report. Existing file is {0} proper:{1}", file.Quality, file.Proper); - if (!_qualityUpgradeSpecification.IsSatisfiedBy(new QualityModel { Quality = file.Quality, Proper = file.Proper }, subject.Quality, subject.Series.QualityProfile.Cutoff)) - return false; - - if(subject.Quality.Proper && file.DateAdded < DateTime.Today.AddDays(-7)) - { - logger.Trace("Proper for old file, skipping: {0}", subject); - return false; - } - } - - return true; - } - } -} diff --git a/NzbDrone.Core/DecisionEngine/UpgradeHistorySpecification.cs b/NzbDrone.Core/DecisionEngine/UpgradeHistorySpecification.cs deleted file mode 100644 index 906e0fc56..000000000 --- a/NzbDrone.Core/DecisionEngine/UpgradeHistorySpecification.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.History; -using NzbDrone.Core.Model; -using NzbDrone.Core.Providers; - -namespace NzbDrone.Core.DecisionEngine -{ - public class UpgradeHistorySpecification - { - private readonly IHistoryService _historyService; - private readonly QualityUpgradeSpecification _qualityUpgradeSpecification; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public UpgradeHistorySpecification(IHistoryService historyService, QualityUpgradeSpecification qualityUpgradeSpecification) - { - _historyService = historyService; - _qualityUpgradeSpecification = qualityUpgradeSpecification; - } - - public UpgradeHistorySpecification() - { - - } - - public virtual bool IsSatisfiedBy(EpisodeParseResult subject) - { - foreach (var episode in subject.Episodes) - { - var bestQualityInHistory = _historyService.GetBestQualityInHistory(subject.Series.Id, episode.SeasonNumber, episode.EpisodeNumber); - if (bestQualityInHistory != null) - { - logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory); - if (!_qualityUpgradeSpecification.IsSatisfiedBy(bestQualityInHistory, subject.Quality, subject.Series.QualityProfile.Cutoff)) - return false; - } - } - - return true; - } - } -} diff --git a/NzbDrone.Core/DecisionEngine/UpgradePossibleSpecification.cs b/NzbDrone.Core/DecisionEngine/UpgradePossibleSpecification.cs deleted file mode 100644 index a66ce46f1..000000000 --- a/NzbDrone.Core/DecisionEngine/UpgradePossibleSpecification.cs +++ /dev/null @@ -1,41 +0,0 @@ -using System.Linq; -using NLog; -using NzbDrone.Core.Qualities; -using NzbDrone.Core.Tv; -using NzbDrone.Core.Providers; -using NzbDrone.Core.Repository; - -namespace NzbDrone.Core.DecisionEngine -{ - public class UpgradePossibleSpecification - { - private readonly IQualityProfileService _qualityProvider; - private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - - public UpgradePossibleSpecification(IQualityProfileService qualityProvider) - { - _qualityProvider = qualityProvider; - } - - public UpgradePossibleSpecification() - { - - } - - public virtual bool IsSatisfiedBy(Episode subject) - { - //Used to check if the existing episode can be upgraded by searching (Before we search) - if (subject.EpisodeFileId == 0) - return true; - - var profile = _qualityProvider.Get(subject.Series.QualityProfileId); - - - //TODO:How about proper? - if (subject.EpisodeFile.Quality >= profile.Cutoff) - return false; - - return true; ; - } - } -} diff --git a/NzbDrone.Core/Download/Clients/BlackholeProvider.cs b/NzbDrone.Core/Download/Clients/BlackholeProvider.cs index 8594df2f9..340d7de07 100644 --- a/NzbDrone.Core/Download/Clients/BlackholeProvider.cs +++ b/NzbDrone.Core/Download/Clients/BlackholeProvider.cs @@ -4,6 +4,7 @@ using System.Linq; using NLog; using NzbDrone.Common; using NzbDrone.Core.Configuration; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.History; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Model; diff --git a/NzbDrone.Core/Download/Clients/PneumaticProvider.cs b/NzbDrone.Core/Download/Clients/PneumaticProvider.cs index 48eaf9ddb..e2143a627 100644 --- a/NzbDrone.Core/Download/Clients/PneumaticProvider.cs +++ b/NzbDrone.Core/Download/Clients/PneumaticProvider.cs @@ -4,6 +4,7 @@ using System.Linq; using NLog; using NzbDrone.Common; using NzbDrone.Core.Configuration; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.MediaFiles; using NzbDrone.Core.Model; using NzbDrone.Core.DecisionEngine; diff --git a/NzbDrone.Core/Jobs/Implementations/EpisodeSearchJob.cs b/NzbDrone.Core/Jobs/Implementations/EpisodeSearchJob.cs index 6400ffe6e..379fda020 100644 --- a/NzbDrone.Core/Jobs/Implementations/EpisodeSearchJob.cs +++ b/NzbDrone.Core/Jobs/Implementations/EpisodeSearchJob.cs @@ -1,5 +1,4 @@ using System; -using System.Linq; using NLog; using NzbDrone.Core.DecisionEngine; using NzbDrone.Core.Model.Notification; @@ -11,25 +10,25 @@ namespace NzbDrone.Core.Jobs.Implementations public class EpisodeSearchJob : IJob { private readonly IEpisodeService _episodeService; - private readonly UpgradePossibleSpecification _upgradePossibleSpecification; + private readonly IQualityUpgradableSpecification _qualityUpgradableSpecification; private readonly EpisodeSearch _episodeSearch; private readonly DailyEpisodeSearch _dailyEpisodeSearch; private static readonly Logger logger = LogManager.GetCurrentClassLogger(); - public EpisodeSearchJob(IEpisodeService episodeService, UpgradePossibleSpecification upgradePossibleSpecification, + public EpisodeSearchJob(IEpisodeService episodeService, IQualityUpgradableSpecification qualityUpgradableSpecification, EpisodeSearch episodeSearch, DailyEpisodeSearch dailyEpisodeSearch) { - if(dailyEpisodeSearch == null) throw new ArgumentNullException("dailyEpisodeSearch"); + if (dailyEpisodeSearch == null) throw new ArgumentNullException("dailyEpisodeSearch"); _episodeService = episodeService; - _upgradePossibleSpecification = upgradePossibleSpecification; + _qualityUpgradableSpecification = qualityUpgradableSpecification; _episodeSearch = episodeSearch; _dailyEpisodeSearch = dailyEpisodeSearch; } public EpisodeSearchJob() { - + } public string Name @@ -55,7 +54,7 @@ namespace NzbDrone.Core.Jobs.Implementations return; } - if (!_upgradePossibleSpecification.IsSatisfiedBy(episode)) + if (!_qualityUpgradableSpecification.IsUpgradable(episode.Series.QualityProfile, episode.EpisodeFile.QualityModel)) { logger.Info("Search for {0} was aborted, file in disk meets or exceeds Profile's Cutoff", episode); notification.CurrentMessage = String.Format("Skipping search for {0}, the file you have is already at cutoff", episode); @@ -76,7 +75,7 @@ namespace NzbDrone.Core.Jobs.Implementations else { - _episodeSearch.Search(episode.Series, new { Episode = episode }, notification); + _episodeSearch.Search(episode.Series, new { Episode = episode }, notification); } } } diff --git a/NzbDrone.Core/Jobs/Implementations/RssSyncJob.cs b/NzbDrone.Core/Jobs/Implementations/RssSyncJob.cs index a21f9d12b..2619ad801 100644 --- a/NzbDrone.Core/Jobs/Implementations/RssSyncJob.cs +++ b/NzbDrone.Core/Jobs/Implementations/RssSyncJob.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using NLog; using NzbDrone.Core.Configuration; using NzbDrone.Core.DecisionEngine; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.Model; diff --git a/NzbDrone.Core/MediaFiles/EpisodeFile.cs b/NzbDrone.Core/MediaFiles/EpisodeFile.cs index a3a6365ed..d0eb274d1 100644 --- a/NzbDrone.Core/MediaFiles/EpisodeFile.cs +++ b/NzbDrone.Core/MediaFiles/EpisodeFile.cs @@ -34,7 +34,7 @@ namespace NzbDrone.Core.MediaFiles public string SceneName { get; set; } public string ReleaseGroup { get; set; } - public QualityModel QualityWrapper + public QualityModel QualityModel { get { diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index a7bfe8056..6ab5aa832 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -188,6 +188,18 @@ + + + + + + + + + + + + @@ -299,11 +311,8 @@ - - - @@ -346,34 +355,7 @@ Code - - Code - - - Code - - - Code - - - Code - - - Code - - - Code - - - Code - - - Code - - - Code - - + Code diff --git a/NzbDrone.Core/Providers/DiskScanProvider.cs b/NzbDrone.Core/Providers/DiskScanProvider.cs index b7cf4a8ad..ed28cd467 100644 --- a/NzbDrone.Core/Providers/DiskScanProvider.cs +++ b/NzbDrone.Core/Providers/DiskScanProvider.cs @@ -140,7 +140,7 @@ namespace NzbDrone.Core.Providers } //Make sure this file is an upgrade for ALL episodes already on disk - if (episodes.All(e => e.EpisodeFile == null || e.EpisodeFile.QualityWrapper <= parseResult.Quality)) + if (episodes.All(e => e.EpisodeFile == null || e.EpisodeFile.QualityModel <= parseResult.Quality)) { Logger.Debug("Deleting the existing file(s) on disk to upgrade to: {0}", filePath); //Do the delete for files where there is already an episode on disk diff --git a/NzbDrone.Core/Providers/Search/DailyEpisodeSearch.cs b/NzbDrone.Core/Providers/Search/DailyEpisodeSearch.cs index 45939313f..d374247f7 100644 --- a/NzbDrone.Core/Providers/Search/DailyEpisodeSearch.cs +++ b/NzbDrone.Core/Providers/Search/DailyEpisodeSearch.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using NLog; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.ReferenceData; diff --git a/NzbDrone.Core/Providers/Search/EpisodeSearch.cs b/NzbDrone.Core/Providers/Search/EpisodeSearch.cs index a19e7abe6..c0eac694f 100644 --- a/NzbDrone.Core/Providers/Search/EpisodeSearch.cs +++ b/NzbDrone.Core/Providers/Search/EpisodeSearch.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using NLog; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.ReferenceData; diff --git a/NzbDrone.Core/Providers/Search/PartialSeasonSearch.cs b/NzbDrone.Core/Providers/Search/PartialSeasonSearch.cs index 988c37be3..8c1718f77 100644 --- a/NzbDrone.Core/Providers/Search/PartialSeasonSearch.cs +++ b/NzbDrone.Core/Providers/Search/PartialSeasonSearch.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using NLog; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.ReferenceData; diff --git a/NzbDrone.Core/Providers/Search/SearchBase.cs b/NzbDrone.Core/Providers/Search/SearchBase.cs index 3fc37d44c..93c3349ea 100644 --- a/NzbDrone.Core/Providers/Search/SearchBase.cs +++ b/NzbDrone.Core/Providers/Search/SearchBase.cs @@ -4,6 +4,7 @@ using System.Linq; using System.Text.RegularExpressions; using NLog; using NzbDrone.Core.Datastore; +using NzbDrone.Core.DecisionEngine.Specifications; using NzbDrone.Core.Download; using NzbDrone.Core.Indexers; using NzbDrone.Core.ReferenceData; diff --git a/NzbDrone.ncrunchsolution b/NzbDrone.ncrunchsolution index 444b34b1d..969da6dd4 100644 --- a/NzbDrone.ncrunchsolution +++ b/NzbDrone.ncrunchsolution @@ -1,6 +1,6 @@ 1 - False + True true true UseDynamicAnalysis