mirror of https://github.com/lidarr/Lidarr
Fixed: Cutoff Specification not Respecting Profile Order (#660)
* Fixed: Cutoff Specification not Repsecting Profile Order * Fixed: Incorrect wording in UpgradeAllowed logging * Fixed: Change Logic to update if upgrade for any, downgrade for none. * Fixed: Removed Double Preferred Word Logic * New: Add Test Cases to Disk Upgrade Spec * Fixed: Cleanup UpgradableSpecification * Add ConcatToString extension and fix logging * Fixed: Enum Naming, Commas
This commit is contained in:
parent
0ebaa90f54
commit
4d8bcd12e3
|
@ -137,5 +137,15 @@ namespace NzbDrone.Common.Extensions
|
|||
{
|
||||
return source.Select(predicate).ToList();
|
||||
}
|
||||
|
||||
public static string ConcatToString<TSource>(this IEnumerable<TSource> source, string separator = ", ")
|
||||
{
|
||||
return string.Join(separator, source.Select(x => x.ToString()));
|
||||
}
|
||||
|
||||
public static string ConcatToString<TSource>(this IEnumerable<TSource> source, Func<TSource, string> predicate, string separator = ", ")
|
||||
{
|
||||
return string.Join(separator, source.Select(predicate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ using NzbDrone.Core.Test.Framework;
|
|||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Profiles.Languages;
|
||||
using NzbDrone.Core.Test.Languages;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
|
@ -30,7 +31,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English
|
||||
},
|
||||
new QualityModel(Quality.MP3_192, new Revision(version: 2)), Language.English, NoPreferredWordScore).Should().BeTrue();
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_192, new Revision(version: 2)) },
|
||||
new List<Language> { Language.English }, NoPreferredWordScore).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -47,7 +49,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English
|
||||
},
|
||||
new QualityModel(Quality.MP3_256, new Revision(version: 2)), Language.English, NoPreferredWordScore).Should().BeFalse();
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
|
||||
new List<Language> { Language.English }, NoPreferredWordScore).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -65,7 +68,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English
|
||||
},
|
||||
new QualityModel(Quality.MP3_320, new Revision(version: 2)), Language.English, NoPreferredWordScore).Should().BeFalse();
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320, new Revision(version: 2)) },
|
||||
new List<Language> { Language.English }, NoPreferredWordScore).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -83,8 +87,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English
|
||||
},
|
||||
new QualityModel(Quality.MP3_320, new Revision(version: 1)),
|
||||
Language.English,
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320, new Revision(version: 1)) },
|
||||
new List<Language> { Language.English },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(Quality.MP3_320, new Revision(version: 2))).Should().BeTrue();
|
||||
|
||||
|
@ -105,7 +109,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English
|
||||
},
|
||||
new QualityModel(Quality.MP3_320, new Revision(version: 2)), Language.English,
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320, new Revision(version: 2)) },
|
||||
new List<Language> { Language.English },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(Quality.FLAC, new Revision(version: 2))).Should().BeFalse();
|
||||
}
|
||||
|
@ -128,8 +133,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
|
||||
Subject.CutoffNotMet(_profile,
|
||||
_langProfile,
|
||||
new QualityModel(Quality.MP3_320, new Revision(version: 2)),
|
||||
Language.English,
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320, new Revision(version: 2)) },
|
||||
new List<Language> { Language.English },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(Quality.FLAC, new Revision(version: 2))).Should().BeTrue();
|
||||
}
|
||||
|
@ -153,8 +158,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Subject.CutoffNotMet(
|
||||
_profile,
|
||||
_langProfile,
|
||||
new QualityModel(Quality.MP3_320, new Revision(version: 2)),
|
||||
Language.Spanish,
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320, new Revision(version: 2)) },
|
||||
new List<Language> { Language.Spanish },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(Quality.FLAC, new Revision(version: 2))).Should().BeFalse();
|
||||
}
|
||||
|
@ -178,8 +183,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Subject.CutoffNotMet(
|
||||
_profile,
|
||||
_langProfile,
|
||||
new QualityModel(Quality.MP3_320, new Revision(version: 2)),
|
||||
Language.French,
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320, new Revision(version: 2)) },
|
||||
new List<Language> { Language.French },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(Quality.FLAC, new Revision(version: 2))).Should().BeFalse();
|
||||
}
|
||||
|
@ -203,8 +208,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Subject.CutoffNotMet(
|
||||
_profile,
|
||||
_langProfile,
|
||||
new QualityModel(Quality.MP3_256, new Revision(version: 2)),
|
||||
Language.French,
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
|
||||
new List<Language> { Language.French },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(Quality.FLAC, new Revision(version: 2))).Should().BeTrue();
|
||||
}
|
||||
|
@ -228,8 +233,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Subject.CutoffNotMet(
|
||||
_profile,
|
||||
_langProfile,
|
||||
new QualityModel(Quality.MP3_256, new Revision(version: 2)),
|
||||
Language.French, NoPreferredWordScore).Should().BeTrue();
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
|
||||
new List<Language> { Language.French },
|
||||
NoPreferredWordScore).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -250,8 +256,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Subject.CutoffNotMet(
|
||||
_profile,
|
||||
_langProfile,
|
||||
new QualityModel(Quality.MP3_320, new Revision(version: 2)),
|
||||
Language.Spanish,
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320, new Revision(version: 2)) },
|
||||
new List<Language> { Language.Spanish },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(Quality.FLAC, new Revision(version: 2)),
|
||||
10).Should().BeTrue();
|
||||
|
|
|
@ -96,7 +96,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests.RssSync
|
|||
private void GivenUpgradeForExistingFile()
|
||||
{
|
||||
Mocker.GetMock<IUpgradableSpecification>()
|
||||
.Setup(s => s.IsUpgradable(It.IsAny<QualityProfile>(), It.IsAny<LanguageProfile>(), It.IsAny<QualityModel>(), It.IsAny<Language>(), It.IsAny<int>(), It.IsAny<QualityModel>(), It.IsAny<Language>(), It.IsAny<int>()))
|
||||
.Setup(s => s.IsUpgradable(It.IsAny<QualityProfile>(), It.IsAny<LanguageProfile>(), It.IsAny<List<QualityModel>>(), It.IsAny<List<Language>>(), It.IsAny<int>(), It.IsAny<QualityModel>(), It.IsAny<Language>(), It.IsAny<int>()))
|
||||
.Returns(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,293 @@
|
|||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Profiles.Qualities;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Profiles.Languages;
|
||||
using NzbDrone.Core.Test.Languages;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
[TestFixture]
|
||||
public class UpgradeAllowedSpecificationFixture : CoreTest<UpgradableSpecification>
|
||||
{
|
||||
[Test]
|
||||
public void should_return_false_when_quality_are_the_same_language_is_better_and_upgrade_allowed_is_false_for_language_profile()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.French
|
||||
).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_false_when_quality_is_better_languages_are_the_same_and_upgrade_allowed_is_false_for_quality_profile()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.FLAC),
|
||||
Language.English
|
||||
).Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_language_upgrade_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.French
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_same_language_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_same_language_when_upgrading_is_not_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.French },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_lower_language_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.French },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_lower_language_when_upgrading_is_not_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English, Language.French),
|
||||
Cutoff = Language.French,
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.French },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_quality_upgrade_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.FLAC),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_same_quality_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_same_quality_when_upgrading_is_not_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_320),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_lower_quality_when_upgrading_is_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_256),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_return_true_for_lower_quality_when_upgrading_is_not_allowed()
|
||||
{
|
||||
Subject.IsUpgradeAllowed(
|
||||
new QualityProfile
|
||||
{
|
||||
Cutoff = Quality.FLAC.Id,
|
||||
Items = Qualities.QualityFixture.GetDefaultQualities(),
|
||||
UpgradeAllowed = false
|
||||
},
|
||||
new LanguageProfile
|
||||
{
|
||||
Languages = LanguageFixture.GetDefaultLanguages(Language.English),
|
||||
Cutoff = Language.English,
|
||||
UpgradeAllowed = true
|
||||
},
|
||||
new List<QualityModel>{ new QualityModel(Quality.MP3_320) },
|
||||
new List<Language> { Language.English },
|
||||
new QualityModel(Quality.MP3_256),
|
||||
Language.English
|
||||
).Should().BeTrue();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -34,8 +34,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
_firstFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now, Language = Language.English };
|
||||
_secondFile = new TrackFile { Quality = new QualityModel(Quality.FLAC, new Revision(version: 2)), DateAdded = DateTime.Now, Language = Language.English };
|
||||
|
||||
var singleEpisodeList = new List<Album> { new Album {}};
|
||||
var doubleEpisodeList = new List<Album> { new Album {}, new Album {}, new Album {} };
|
||||
var singleAlbumList = new List<Album> { new Album {}};
|
||||
var doubleAlbumList = new List<Album> { new Album {}, new Album {}, new Album {} };
|
||||
|
||||
var languages = Languages.LanguageFixture.GetDefaultLanguages(Language.English, Language.Spanish);
|
||||
|
||||
|
@ -66,14 +66,14 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
{
|
||||
Artist = fakeArtist,
|
||||
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)), Language = Language.English },
|
||||
Albums = doubleEpisodeList
|
||||
Albums = doubleAlbumList
|
||||
};
|
||||
|
||||
_parseResultSingle = new RemoteAlbum
|
||||
{
|
||||
Artist = fakeArtist,
|
||||
ParsedAlbumInfo = new ParsedAlbumInfo { Quality = new QualityModel(Quality.MP3_256, new Revision(version: 2)), Language = Language.English },
|
||||
Albums = singleEpisodeList
|
||||
Albums = singleAlbumList
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -127,9 +127,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_upgradable_if_album_is_upgradable()
|
||||
public void should_be_upgradable_if_all_files_are_upgradable()
|
||||
{
|
||||
WithFirstFileUpgradable();
|
||||
WithSecondFileUpgradable();
|
||||
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
|
@ -137,6 +138,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
public void should_not_be_upgradable_if_qualities_are_the_same()
|
||||
{
|
||||
_firstFile.Quality = new QualityModel(Quality.MP3_320);
|
||||
_secondFile.Quality = new QualityModel(Quality.MP3_320);
|
||||
_parseResultSingle.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_320);
|
||||
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
|
||||
}
|
||||
|
@ -146,5 +148,21 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
{
|
||||
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_true_if_some_tracks_are_upgradable_and_none_are_downgrades()
|
||||
{
|
||||
WithFirstFileUpgradable();
|
||||
_parseResultSingle.ParsedAlbumInfo.Quality = _secondFile.Quality;
|
||||
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeTrue();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_be_false_if_some_tracks_are_upgradable_and_some_are_downgrades()
|
||||
{
|
||||
WithFirstFileUpgradable();
|
||||
_parseResultSingle.ParsedAlbumInfo.Quality = new QualityModel(Quality.MP3_320);
|
||||
Subject.IsSatisfiedBy(_parseResultSingle, null).Accepted.Should().BeFalse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ using NzbDrone.Core.Test.Framework;
|
|||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Profiles.Languages;
|
||||
using NzbDrone.Core.Test.Languages;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
|
@ -65,8 +66,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Subject.IsUpgradable(
|
||||
profile,
|
||||
langProfile,
|
||||
new QualityModel(current, new Revision(version: currentVersion)),
|
||||
Language.English,
|
||||
new List<QualityModel> { new QualityModel(current, new Revision(version: currentVersion)) },
|
||||
new List<Language> { Language.English },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(newQuality, new Revision(version: newVersion)),
|
||||
Language.English,
|
||||
|
@ -96,8 +97,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Subject.IsUpgradable(
|
||||
profile,
|
||||
langProfile,
|
||||
new QualityModel(current, new Revision(version: currentVersion)),
|
||||
currentLanguage,
|
||||
new List<QualityModel> { new QualityModel(current, new Revision(version: currentVersion)) },
|
||||
new List<Language> { currentLanguage },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(newQuality, new Revision(version: newVersion)),
|
||||
newLanguage,
|
||||
|
@ -125,8 +126,8 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
|||
Subject.IsUpgradable(
|
||||
profile,
|
||||
langProfile,
|
||||
new QualityModel(Quality.MP3_256, new Revision(version: 2)),
|
||||
Language.English,
|
||||
new List<QualityModel> { new QualityModel(Quality.MP3_256, new Revision(version: 2)) },
|
||||
new List<Language> { Language.English },
|
||||
NoPreferredWordScore,
|
||||
new QualityModel(Quality.MP3_256, new Revision(version: 1)),
|
||||
Language.English,
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
<Compile Include="DecisionEngineTests\ReleaseRestrictionsSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\PrioritizeDownloadDecisionFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\QualityAllowedByProfileSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\UpgradeAllowedSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\UpgradeSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\MinimumAgeSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\RetentionSpecificationFixture.cs" />
|
||||
|
|
|
@ -1,75 +0,0 @@
|
|||
using NLog;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Profiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
public interface ILanguageUpgradableSpecification
|
||||
{
|
||||
bool IsUpgradable(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null);
|
||||
bool CutoffNotMet(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null);
|
||||
bool IsRevisionUpgrade(LanguageModel currentLanguage, LanguageModel newLanguage);
|
||||
}
|
||||
|
||||
public class LanguageUpgradableSpecification : ILanguageUpgradableSpecification
|
||||
{
|
||||
private readonly Logger _logger;
|
||||
|
||||
public LanguageUpgradableSpecification(Logger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool IsUpgradable(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null)
|
||||
{
|
||||
if (newLanguage != null)
|
||||
{
|
||||
int compare = new LanguageModelComparer(profile).Compare(newLanguage, currentLanguage);
|
||||
if (compare <= 0)
|
||||
{
|
||||
_logger.Debug("existing item has better or equal language. skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsRevisionUpgrade(currentLanguage, newLanguage))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool CutoffNotMet(Profile profile, LanguageModel currentLanguage, LanguageModel newLanguage = null)
|
||||
{
|
||||
int compare = new LanguageModelComparer(profile).Compare(currentLanguage.Language, profile.Languages.Find(v => v.Allowed == true).Language);
|
||||
|
||||
if (compare >= 0)
|
||||
{
|
||||
if (newLanguage != null && IsRevisionUpgrade(currentLanguage, newLanguage))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_logger.Debug("Existing item meets cut-off. skipping.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool IsRevisionUpgrade(LanguageModel currentLanguage, LanguageModel newLanguage)
|
||||
{
|
||||
int compare = newLanguage.Revision.CompareTo(currentLanguage.Revision);
|
||||
|
||||
if (currentLanguage.Language == newLanguage.Language && compare > 0)
|
||||
{
|
||||
_logger.Debug("New language is a better revision for existing quality");
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ using NzbDrone.Core.MediaFiles;
|
|||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.Profiles.Releases;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
|
@ -39,8 +40,8 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
|
||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
|
||||
var profile = subject.Artist.QualityProfile.Value;
|
||||
var qualityProfile = subject.Artist.QualityProfile.Value;
|
||||
var languageProfile = subject.Artist.LanguageProfile.Value;
|
||||
|
||||
foreach (var album in subject.Albums)
|
||||
{
|
||||
|
@ -50,23 +51,26 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
|
||||
if (!tracksMissing && trackFiles.Any())
|
||||
{
|
||||
var lowestQuality = trackFiles.Select(c => c.Quality).OrderBy(c => c.Quality.Id).First();
|
||||
// Get a distinct list of all current track qualities and languages for a given album
|
||||
var currentQualities = trackFiles.Select(c => c.Quality).Distinct().ToList();
|
||||
var currentLanguages = trackFiles.Select(c => c.Language).Distinct().ToList();
|
||||
|
||||
_logger.Debug("Comparing file quality and language with report. Existing file is {0}", lowestQuality.Quality);
|
||||
_logger.Debug("Comparing file quality and language with report. Existing files contain {0} : {1}", currentQualities.ConcatToString(), currentLanguages.ConcatToString());
|
||||
|
||||
if (!_upgradableSpecification.CutoffNotMet(profile,
|
||||
subject.Artist.LanguageProfile,
|
||||
lowestQuality,
|
||||
trackFiles[0].Language,
|
||||
if (!_upgradableSpecification.CutoffNotMet(qualityProfile,
|
||||
languageProfile,
|
||||
currentQualities,
|
||||
currentLanguages,
|
||||
_preferredWordServiceCalculator.Calculate(subject.Artist, trackFiles[0].GetSceneOrFileName()),
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.PreferredWordScore))
|
||||
{
|
||||
_logger.Debug("Cutoff already met, rejecting.");
|
||||
var qualityCutoffIndex = profile.GetIndex(profile.Cutoff);
|
||||
var qualityCutoff = profile.Items[qualityCutoffIndex.Index];
|
||||
_logger.Debug("Cutoff already met by existing files, rejecting.");
|
||||
|
||||
return Decision.Reject("Existing file meets cutoff: {0} - {1}", qualityCutoff, subject.Artist.LanguageProfile.Value.Cutoff);
|
||||
var qualityCutoffIndex = qualityProfile.GetIndex(qualityProfile.Cutoff);
|
||||
var qualityCutoff = qualityProfile.Items[qualityCutoffIndex.Index];
|
||||
|
||||
return Decision.Reject("Existing files meets cutoff: {0} - {1}", qualityCutoff, languageProfile.Cutoff);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Profiles.Releases;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Queue;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
|
@ -41,34 +44,48 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
foreach (var queueItem in matchingAlbum)
|
||||
{
|
||||
var remoteAlbum = queueItem.RemoteAlbum;
|
||||
var qualityProfile = subject.Artist.QualityProfile.Value;
|
||||
var languageProfile = subject.Artist.LanguageProfile.Value;
|
||||
|
||||
_logger.Debug("Checking if existing release in queue meets cutoff. Queued quality is: {0} - {1}", remoteAlbum.ParsedAlbumInfo.Quality, remoteAlbum.ParsedAlbumInfo.Language);
|
||||
var queuedItemPreferredWordScore = _preferredWordServiceCalculator.Calculate(subject.Artist, queueItem.Title);
|
||||
|
||||
if (!_upgradableSpecification.CutoffNotMet(subject.Artist.QualityProfile,
|
||||
subject.Artist.LanguageProfile,
|
||||
remoteAlbum.ParsedAlbumInfo.Quality,
|
||||
remoteAlbum.ParsedAlbumInfo.Language,
|
||||
if (!_upgradableSpecification.CutoffNotMet(qualityProfile,
|
||||
languageProfile,
|
||||
new List<QualityModel> { remoteAlbum.ParsedAlbumInfo.Quality },
|
||||
new List<Language> { remoteAlbum.ParsedAlbumInfo.Language },
|
||||
queuedItemPreferredWordScore,
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.PreferredWordScore))
|
||||
|
||||
{
|
||||
return Decision.Reject("Quality for release in queue already meets cutoff: {0}", remoteAlbum.ParsedAlbumInfo.Quality);
|
||||
return Decision.Reject("Release in queue already meets cutoff: {0}", remoteAlbum.ParsedAlbumInfo.Quality);
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if release is higher quality than queued release. Queued quality is: {0} - {1}", remoteAlbum.ParsedAlbumInfo.Quality, remoteAlbum.ParsedAlbumInfo.Language);
|
||||
_logger.Debug("Checking if release is higher quality than queued release. Queued: {0} - {1}", remoteAlbum.ParsedAlbumInfo.Quality, remoteAlbum.ParsedAlbumInfo.Language);
|
||||
|
||||
if (!_upgradableSpecification.IsUpgradable(subject.Artist.QualityProfile,
|
||||
subject.Artist.LanguageProfile,
|
||||
remoteAlbum.ParsedAlbumInfo.Quality,
|
||||
remoteAlbum.ParsedAlbumInfo.Language,
|
||||
if (!_upgradableSpecification.IsUpgradable(qualityProfile,
|
||||
languageProfile,
|
||||
new List<QualityModel> { remoteAlbum.ParsedAlbumInfo.Quality },
|
||||
new List<Language> { remoteAlbum.ParsedAlbumInfo.Language },
|
||||
queuedItemPreferredWordScore,
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.ParsedAlbumInfo.Language,
|
||||
subject.PreferredWordScore))
|
||||
{
|
||||
return Decision.Reject("Quality for release in queue is of equal or higher preference: {0} - {1}", remoteAlbum.ParsedAlbumInfo.Quality, remoteAlbum.ParsedAlbumInfo.Language);
|
||||
return Decision.Reject("Release in queue is of equal or higher preference: {0} - {1}", remoteAlbum.ParsedAlbumInfo.Quality, remoteAlbum.ParsedAlbumInfo.Language);
|
||||
}
|
||||
|
||||
_logger.Debug("Checking if profiles allow upgrading. Queued: {0} - {1}", remoteAlbum.ParsedAlbumInfo.Quality, remoteAlbum.ParsedAlbumInfo.Language);
|
||||
|
||||
if (!_upgradableSpecification.IsUpgradeAllowed(qualityProfile,
|
||||
languageProfile,
|
||||
new List<QualityModel> { remoteAlbum.ParsedAlbumInfo.Quality },
|
||||
new List<Language> { remoteAlbum.ParsedAlbumInfo.Language },
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.ParsedAlbumInfo.Language))
|
||||
{
|
||||
return Decision.Reject("Another release is queued and the Quality or Language profile does not allow upgrades");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,11 +69,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
|
||||
if (trackFiles.Any())
|
||||
{
|
||||
var lowestQuality = trackFiles.Select(c => c.Quality).OrderBy(c => c.Quality.Id).First();
|
||||
var currentQualities = trackFiles.Select(c => c.Quality).Distinct().ToList();
|
||||
var currentLanguages = trackFiles.Select(c => c.Language).Distinct().ToList();
|
||||
|
||||
var upgradable = _upgradableSpecification.IsUpgradable(qualityProfile,
|
||||
languageProfile,
|
||||
lowestQuality,
|
||||
trackFiles[0].Language,
|
||||
currentQualities,
|
||||
currentLanguages,
|
||||
_preferredWordServiceCalculator.Calculate(subject.Artist, trackFiles[0].GetSceneOrFileName()),
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.ParsedAlbumInfo.Language,
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Extensions;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Languages;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Profiles.Releases;
|
||||
using NzbDrone.Core.Qualities;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
{
|
||||
|
@ -59,8 +62,8 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
var cutoffUnmet = _upgradableSpecification.CutoffNotMet(
|
||||
subject.Artist.QualityProfile,
|
||||
subject.Artist.LanguageProfile,
|
||||
mostRecent.Quality,
|
||||
mostRecent.Language,
|
||||
new List<QualityModel> { mostRecent.Quality },
|
||||
new List<Language> { mostRecent.Language },
|
||||
preferredWordScore,
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.PreferredWordScore);
|
||||
|
@ -68,8 +71,8 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
|||
var upgradeable = _upgradableSpecification.IsUpgradable(
|
||||
subject.Artist.QualityProfile,
|
||||
subject.Artist.LanguageProfile,
|
||||
mostRecent.Quality,
|
||||
mostRecent.Language,
|
||||
new List<QualityModel> { mostRecent.Quality },
|
||||
new List<Language> { mostRecent.Language },
|
||||
preferredWordScore,
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.ParsedAlbumInfo.Language,
|
||||
|
|
|
@ -3,16 +3,18 @@ using NzbDrone.Core.Languages;
|
|||
using NzbDrone.Core.Profiles.Languages;
|
||||
using NzbDrone.Core.Profiles.Qualities;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public interface IUpgradableSpecification
|
||||
{
|
||||
bool IsUpgradable(QualityProfile profile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, int currentScore, QualityModel newQuality, Language newLanguage, int newScore);
|
||||
bool IsUpgradable(QualityProfile profile, LanguageProfile languageProfile, List<QualityModel> currentQualities, List<Language> currentLanguages, int currentScore, QualityModel newQuality, Language newLanguage, int newScore);
|
||||
bool QualityCutoffNotMet(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null);
|
||||
bool LanguageCutoffNotMet(LanguageProfile languageProfile, Language currentLanguage);
|
||||
bool CutoffNotMet(QualityProfile profile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, int currentScore, QualityModel newQuality = null, int newScore = 0);
|
||||
bool CutoffNotMet(QualityProfile profile, LanguageProfile languageProfile, List<QualityModel> currentQualities, List<Language> currentLanguages, int currentScore, QualityModel newQuality = null, int newScore = 0);
|
||||
bool IsRevisionUpgrade(QualityModel currentQuality, QualityModel newQuality);
|
||||
bool IsUpgradeAllowed(QualityProfile qualityProfile, LanguageProfile languageProfile, List<QualityModel> currentQualities, List<Language> currentLanguages, QualityModel newQuality, Language newLanguage);
|
||||
}
|
||||
|
||||
public class UpgradableSpecification : IUpgradableSpecification
|
||||
|
@ -24,32 +26,60 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
_logger = logger;
|
||||
}
|
||||
|
||||
private bool IsLanguageUpgradable(LanguageProfile profile, Language currentLanguage, Language newLanguage = null)
|
||||
private ProfileComparisonResult IsLanguageUpgradable(LanguageProfile profile, List<Language> currentLanguages, Language newLanguage = null)
|
||||
{
|
||||
if (newLanguage != null)
|
||||
{
|
||||
var compare = new LanguageComparer(profile).Compare(newLanguage, currentLanguage);
|
||||
if (compare <= 0)
|
||||
var totalCompare = 0;
|
||||
|
||||
foreach (var language in currentLanguages)
|
||||
{
|
||||
return false;
|
||||
var compare = new LanguageComparer(profile).Compare(newLanguage, language);
|
||||
|
||||
totalCompare += compare;
|
||||
|
||||
// Not upgradable if new language is a downgrade for any current lanaguge
|
||||
if (compare < 0)
|
||||
{
|
||||
return ProfileComparisonResult.Downgrade;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsQualityUpgradable(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
||||
// Not upgradable if new language is equal to all current languages
|
||||
if (totalCompare == 0)
|
||||
{
|
||||
return ProfileComparisonResult.Equal;
|
||||
}
|
||||
}
|
||||
return ProfileComparisonResult.Upgrade;
|
||||
}
|
||||
|
||||
private ProfileComparisonResult IsQualityUpgradable(QualityProfile profile, List<QualityModel> currentQualities, QualityModel newQuality = null)
|
||||
{
|
||||
if (newQuality != null)
|
||||
{
|
||||
var compare = new QualityModelComparer(profile).Compare(newQuality, currentQuality);
|
||||
var totalCompare = 0;
|
||||
|
||||
if (compare <= 0)
|
||||
foreach (var quality in currentQualities)
|
||||
{
|
||||
_logger.Debug("Existing item has better quality, skipping");
|
||||
return false;
|
||||
var compare = new QualityModelComparer(profile).Compare(newQuality, quality);
|
||||
|
||||
totalCompare += compare;
|
||||
|
||||
if (compare < 0)
|
||||
{
|
||||
// Not upgradable if new quality is a downgrade for any current quality
|
||||
return ProfileComparisonResult.Downgrade;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
// Not upgradable if new quality is equal to all current qualities
|
||||
if (totalCompare == 0) {
|
||||
return ProfileComparisonResult.Equal;
|
||||
}
|
||||
}
|
||||
|
||||
return ProfileComparisonResult.Upgrade;
|
||||
}
|
||||
|
||||
private bool IsPreferredWordUpgradable(int currentScore, int newScore)
|
||||
|
@ -57,25 +87,30 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
return newScore > currentScore;
|
||||
}
|
||||
|
||||
public bool IsUpgradable(QualityProfile qualityProfile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, int currentScore, QualityModel newQuality, Language newLanguage, int newScore)
|
||||
public bool IsUpgradable(QualityProfile qualityProfile, LanguageProfile languageProfile, List<QualityModel> currentQualities, List<Language> currentLanguages, int currentScore, QualityModel newQuality, Language newLanguage, int newScore)
|
||||
{
|
||||
if (IsQualityUpgradable(qualityProfile, currentQuality, newQuality) && qualityProfile.UpgradeAllowed)
|
||||
|
||||
var qualityUpgrade = IsQualityUpgradable(qualityProfile, currentQualities, newQuality);
|
||||
|
||||
if (qualityUpgrade == ProfileComparisonResult.Upgrade)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (new QualityModelComparer(qualityProfile).Compare(newQuality, currentQuality) < 0)
|
||||
if (qualityUpgrade == ProfileComparisonResult.Downgrade)
|
||||
{
|
||||
_logger.Debug("Existing item has better quality, skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsLanguageUpgradable(languageProfile, currentLanguage, newLanguage) && languageProfile.UpgradeAllowed)
|
||||
var languageUpgrade = IsLanguageUpgradable(languageProfile, currentLanguages, newLanguage);
|
||||
|
||||
if (languageUpgrade == ProfileComparisonResult.Upgrade)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (new LanguageComparer(languageProfile).Compare(newLanguage, currentLanguage) < 0)
|
||||
if (languageUpgrade == ProfileComparisonResult.Downgrade)
|
||||
{
|
||||
_logger.Debug("Existing item has better language, skipping");
|
||||
return false;
|
||||
|
@ -87,12 +122,6 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!IsPreferredWordUpgradable(currentScore, newScore))
|
||||
{
|
||||
_logger.Debug("Existing item has a better preferred word score, skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -120,19 +149,25 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
return languageCompare < 0;
|
||||
}
|
||||
|
||||
public bool CutoffNotMet(QualityProfile profile, LanguageProfile languageProfile, QualityModel currentQuality, Language currentLanguage, int currentScore, QualityModel newQuality = null, int newScore = 0)
|
||||
public bool CutoffNotMet(QualityProfile profile, LanguageProfile languageProfile, List<QualityModel> currentQualities, List<Language> currentLanguages, int currentScore, QualityModel newQuality = null, int newScore = 0)
|
||||
{
|
||||
// If we can upgrade the language (it is not the cutoff) then the quality doesn't
|
||||
// matter as we can always get same quality with prefered language.
|
||||
if (LanguageCutoffNotMet(languageProfile, currentLanguage))
|
||||
foreach (var language in currentLanguages)
|
||||
{
|
||||
if (LanguageCutoffNotMet(languageProfile, language))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (QualityCutoffNotMet(profile, currentQuality, newQuality))
|
||||
foreach (var quality in currentQualities)
|
||||
{
|
||||
if (QualityCutoffNotMet(profile, quality, newQuality))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsPreferredWordUpgradable(currentScore, newScore))
|
||||
{
|
||||
|
@ -157,5 +192,44 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool IsUpgradeAllowed(QualityProfile qualityProfile, LanguageProfile languageProfile, List<QualityModel> currentQualities, List<Language> currentLanguages, QualityModel newQuality, Language newLanguage)
|
||||
{
|
||||
var isQualityUpgrade = IsQualityUpgradable(qualityProfile, currentQualities, newQuality);
|
||||
var isLanguageUpgrade = IsLanguageUpgradable(languageProfile, currentLanguages, newLanguage);
|
||||
|
||||
return CheckUpgradeAllowed(qualityProfile, languageProfile, isQualityUpgrade, isLanguageUpgrade);
|
||||
}
|
||||
|
||||
private bool CheckUpgradeAllowed (QualityProfile qualityProfile, LanguageProfile languageProfile, ProfileComparisonResult isQualityUpgrade, ProfileComparisonResult isLanguageUpgrade)
|
||||
{
|
||||
if (isQualityUpgrade == ProfileComparisonResult.Upgrade && qualityProfile.UpgradeAllowed ||
|
||||
isLanguageUpgrade == ProfileComparisonResult.Upgrade && languageProfile.UpgradeAllowed)
|
||||
{
|
||||
_logger.Debug("At least one profile allows upgrading");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isQualityUpgrade == ProfileComparisonResult.Upgrade && !qualityProfile.UpgradeAllowed)
|
||||
{
|
||||
_logger.Debug("Quality profile does not allow upgrades, skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isLanguageUpgrade == ProfileComparisonResult.Upgrade && !languageProfile.UpgradeAllowed)
|
||||
{
|
||||
_logger.Debug("Language profile does not allow upgrades, skipping");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private enum ProfileComparisonResult
|
||||
{
|
||||
Downgrade = -1,
|
||||
Equal = 0,
|
||||
Upgrade = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.Profiles.Releases;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class UpgradeAllowedSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly UpgradableSpecification _upgradableSpecification;
|
||||
private readonly IMediaFileService _mediaFileService;
|
||||
private readonly ITrackService _trackService;
|
||||
private readonly Logger _logger;
|
||||
private readonly ICached<bool> _missingFilesCache;
|
||||
|
||||
public UpgradeAllowedSpecification(UpgradableSpecification upgradableSpecification,
|
||||
Logger logger,
|
||||
ICacheManager cacheManager,
|
||||
IMediaFileService mediaFileService,
|
||||
ITrackService trackService)
|
||||
{
|
||||
_upgradableSpecification = upgradableSpecification;
|
||||
_mediaFileService = mediaFileService;
|
||||
_trackService = trackService;
|
||||
_missingFilesCache = cacheManager.GetCache<bool>(GetType());
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public SpecificationPriority Priority => SpecificationPriority.Default;
|
||||
public RejectionType Type => RejectionType.Permanent;
|
||||
|
||||
public virtual Decision IsSatisfiedBy(RemoteAlbum subject, SearchCriteriaBase searchCriteria)
|
||||
{
|
||||
var qualityProfile = subject.Artist.QualityProfile.Value;
|
||||
var languageProfile = subject.Artist.LanguageProfile.Value;
|
||||
|
||||
foreach (var album in subject.Albums)
|
||||
{
|
||||
var tracksMissing = _missingFilesCache.Get(album.Id.ToString(), () => _trackService.TracksWithoutFiles(album.Id).Any(),
|
||||
TimeSpan.FromSeconds(30));
|
||||
|
||||
var trackFiles = _mediaFileService.GetFilesByAlbum(album.Id);
|
||||
|
||||
if (!tracksMissing && trackFiles.Any())
|
||||
{
|
||||
// Get a distinct list of all current track qualities and languages for a given album
|
||||
var currentQualities = trackFiles.Select(c => c.Quality).Distinct().ToList();
|
||||
var currentLanguages = trackFiles.Select(c => c.Language).Distinct().ToList();
|
||||
|
||||
_logger.Debug("Comparing file quality and language with report. Existing files contain {0} : {1}", currentQualities.ConcatToString(), currentLanguages.ConcatToString());
|
||||
|
||||
if (!_upgradableSpecification.IsUpgradeAllowed(qualityProfile,
|
||||
languageProfile,
|
||||
currentQualities,
|
||||
currentLanguages,
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.ParsedAlbumInfo.Language))
|
||||
{
|
||||
_logger.Debug("Upgrading is not allowed by the quality or language profile");
|
||||
|
||||
return Decision.Reject("Existing files and the Quality or Language profile does not allow upgrades");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return Decision.Accept();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,6 +7,7 @@ using NzbDrone.Core.MediaFiles;
|
|||
using NzbDrone.Core.Music;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.Profiles.Releases;
|
||||
using NzbDrone.Common.Extensions;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
|
@ -48,18 +49,19 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
|||
|
||||
if (!tracksMissing && trackFiles.Any())
|
||||
{
|
||||
var lowestQuality = trackFiles.Select(c => c.Quality).OrderBy(c => c.Quality.Id).First();
|
||||
var currentQualities = trackFiles.Select(c => c.Quality).Distinct().ToList();
|
||||
var currentLanguages = trackFiles.Select(c => c.Language).Distinct().ToList();
|
||||
|
||||
if (!_upgradableSpecification.IsUpgradable(subject.Artist.QualityProfile,
|
||||
subject.Artist.LanguageProfile,
|
||||
lowestQuality,
|
||||
trackFiles[0].Language,
|
||||
currentQualities,
|
||||
currentLanguages,
|
||||
_preferredWordServiceCalculator.Calculate(subject.Artist, trackFiles[0].GetSceneOrFileName()),
|
||||
subject.ParsedAlbumInfo.Quality,
|
||||
subject.ParsedAlbumInfo.Language,
|
||||
subject.PreferredWordScore))
|
||||
{
|
||||
return Decision.Reject("Existing file on disk is of equal or higher preference: {0} - {1}", lowestQuality, trackFiles[0].Language);
|
||||
return Decision.Reject("Existing files on disk is of equal or higher preference: {0} - {1}", currentQualities.ConcatToString(), currentLanguages.ConcatToString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -258,6 +258,7 @@
|
|||
<Compile Include="DecisionEngine\Specifications\TorrentSeedingSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\SameTracksGrabSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\RawDiskSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\UpgradeAllowedSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\UpgradeDiskSpecification.cs" />
|
||||
<Compile Include="DecisionEngine\Specifications\UpgradableSpecification.cs" />
|
||||
<Compile Include="DiskSpace\DiskSpace.cs" />
|
||||
|
|
Loading…
Reference in New Issue