mirror of https://github.com/lidarr/Lidarr
New: The Manual Search result table is now sorted by the internal prioritization logic and sorting by quality now works as well.
Tnx to mspec and betrayed for averting catastrophe.
This commit is contained in:
parent
d8543ad533
commit
8f192e635f
|
@ -15,6 +15,7 @@ using Omu.ValueInjecter;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Nancy.ModelBinding;
|
using Nancy.ModelBinding;
|
||||||
using NzbDrone.Api.Extensions;
|
using NzbDrone.Api.Extensions;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Indexers
|
namespace NzbDrone.Api.Indexers
|
||||||
{
|
{
|
||||||
|
@ -23,6 +24,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
private readonly IFetchAndParseRss _rssFetcherAndParser;
|
private readonly IFetchAndParseRss _rssFetcherAndParser;
|
||||||
private readonly ISearchForNzb _nzbSearchService;
|
private readonly ISearchForNzb _nzbSearchService;
|
||||||
private readonly IMakeDownloadDecision _downloadDecisionMaker;
|
private readonly IMakeDownloadDecision _downloadDecisionMaker;
|
||||||
|
private readonly IPrioritizeDownloadDecision _prioritizeDownloadDecision;
|
||||||
private readonly IDownloadService _downloadService;
|
private readonly IDownloadService _downloadService;
|
||||||
private readonly IParsingService _parsingService;
|
private readonly IParsingService _parsingService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
@ -30,6 +32,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
public ReleaseModule(IFetchAndParseRss rssFetcherAndParser,
|
public ReleaseModule(IFetchAndParseRss rssFetcherAndParser,
|
||||||
ISearchForNzb nzbSearchService,
|
ISearchForNzb nzbSearchService,
|
||||||
IMakeDownloadDecision downloadDecisionMaker,
|
IMakeDownloadDecision downloadDecisionMaker,
|
||||||
|
IPrioritizeDownloadDecision prioritizeDownloadDecision,
|
||||||
IDownloadService downloadService,
|
IDownloadService downloadService,
|
||||||
IParsingService parsingService,
|
IParsingService parsingService,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
|
@ -37,6 +40,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
_rssFetcherAndParser = rssFetcherAndParser;
|
_rssFetcherAndParser = rssFetcherAndParser;
|
||||||
_nzbSearchService = nzbSearchService;
|
_nzbSearchService = nzbSearchService;
|
||||||
_downloadDecisionMaker = downloadDecisionMaker;
|
_downloadDecisionMaker = downloadDecisionMaker;
|
||||||
|
_prioritizeDownloadDecision = prioritizeDownloadDecision;
|
||||||
_downloadService = downloadService;
|
_downloadService = downloadService;
|
||||||
_parsingService = parsingService;
|
_parsingService = parsingService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -70,7 +74,9 @@ namespace NzbDrone.Api.Indexers
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var decisions = _nzbSearchService.EpisodeSearch(episodeId);
|
var decisions = _nzbSearchService.EpisodeSearch(episodeId);
|
||||||
return MapDecisions(decisions);
|
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions);
|
||||||
|
|
||||||
|
return MapDecisions(prioritizedDecisions);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -84,8 +90,9 @@ namespace NzbDrone.Api.Indexers
|
||||||
{
|
{
|
||||||
var reports = _rssFetcherAndParser.Fetch();
|
var reports = _rssFetcherAndParser.Fetch();
|
||||||
var decisions = _downloadDecisionMaker.GetRssDecision(reports);
|
var decisions = _downloadDecisionMaker.GetRssDecision(reports);
|
||||||
|
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(decisions);
|
||||||
|
|
||||||
return MapDecisions(decisions);
|
return MapDecisions(prioritizedDecisions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<ReleaseResource> MapDecisions(IEnumerable<DownloadDecision> decisions)
|
private static List<ReleaseResource> MapDecisions(IEnumerable<DownloadDecision> decisions)
|
||||||
|
@ -102,6 +109,18 @@ namespace NzbDrone.Api.Indexers
|
||||||
release.Rejections = downloadDecision.Rejections.ToList();
|
release.Rejections = downloadDecision.Rejections.ToList();
|
||||||
release.DownloadAllowed = downloadDecision.RemoteEpisode.DownloadAllowed;
|
release.DownloadAllowed = downloadDecision.RemoteEpisode.DownloadAllowed;
|
||||||
|
|
||||||
|
release.ReleaseWeight = result.Count;
|
||||||
|
|
||||||
|
if (downloadDecision.RemoteEpisode.Series != null)
|
||||||
|
{
|
||||||
|
release.QualityWeight = downloadDecision.RemoteEpisode.Series.QualityProfile.Value.Items.FindIndex(v => v.Quality == release.Quality.Quality) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!release.Quality.Proper)
|
||||||
|
{
|
||||||
|
release.QualityWeight++;
|
||||||
|
}
|
||||||
|
|
||||||
result.Add(release);
|
result.Add(release);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
public class ReleaseResource : RestResource
|
public class ReleaseResource : RestResource
|
||||||
{
|
{
|
||||||
public QualityModel Quality { get; set; }
|
public QualityModel Quality { get; set; }
|
||||||
|
public Int32 QualityWeight { get; set; }
|
||||||
public Int32 Age { get; set; }
|
public Int32 Age { get; set; }
|
||||||
public Double AgeHours { get; set; }
|
public Double AgeHours { get; set; }
|
||||||
public Int64 Size { get; set; }
|
public Int64 Size { get; set; }
|
||||||
|
@ -35,6 +36,7 @@ namespace NzbDrone.Api.Indexers
|
||||||
public String InfoUrl { get; set; }
|
public String InfoUrl { get; set; }
|
||||||
public Boolean DownloadAllowed { get; set; }
|
public Boolean DownloadAllowed { get; set; }
|
||||||
public DownloadProtocol DownloadProtocol { get; set; }
|
public DownloadProtocol DownloadProtocol { get; set; }
|
||||||
|
public Int32 ReleaseWeight { get; set; }
|
||||||
|
|
||||||
public Boolean IsDaily { get; set; }
|
public Boolean IsDaily { get; set; }
|
||||||
public Boolean IsAbsoluteNumbering { get; set; }
|
public Boolean IsAbsoluteNumbering { get; set; }
|
||||||
|
|
|
@ -1,20 +1,21 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
|
||||||
using FluentAssertions;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
|
||||||
using NzbDrone.Core.Download;
|
|
||||||
using NzbDrone.Core.Parser.Model;
|
|
||||||
using NzbDrone.Core.Qualities;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Download;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using FluentAssertions;
|
||||||
|
using FizzWare.NBuilder;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class GetQualifiedReportsFixture : CoreTest<DownloadApprovedReports>
|
public class PrioritizeDownloadDecisionFixture : CoreTest<DownloadDecisionPriorizationService>
|
||||||
{
|
{
|
||||||
private Episode GetEpisode(int id)
|
private Episode GetEpisode(int id)
|
||||||
{
|
{
|
||||||
|
@ -44,16 +45,6 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
return remoteEpisode;
|
return remoteEpisode;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void should_return_an_empty_list_when_none_are_appproved()
|
|
||||||
{
|
|
||||||
var decisions = new List<DownloadDecision>();
|
|
||||||
decisions.Add(new DownloadDecision(null, "Failure!"));
|
|
||||||
decisions.Add(new DownloadDecision(null, "Failure!"));
|
|
||||||
|
|
||||||
Subject.GetQualifiedReports(decisions).Should().BeEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_put_propers_before_non_propers()
|
public void should_put_propers_before_non_propers()
|
||||||
{
|
{
|
||||||
|
@ -64,7 +55,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode2));
|
decisions.Add(new DownloadDecision(remoteEpisode2));
|
||||||
|
|
||||||
var qualifiedReports = Subject.GetQualifiedReports(decisions);
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.Quality.Proper.Should().BeTrue();
|
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.Quality.Proper.Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +69,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode2));
|
decisions.Add(new DownloadDecision(remoteEpisode2));
|
||||||
|
|
||||||
var qualifiedReports = Subject.GetQualifiedReports(decisions);
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.Quality.Quality.Should().Be(Quality.HDTV720p);
|
qualifiedReports.First().RemoteEpisode.ParsedEpisodeInfo.Quality.Quality.Should().Be(Quality.HDTV720p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +83,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode2));
|
decisions.Add(new DownloadDecision(remoteEpisode2));
|
||||||
|
|
||||||
var qualifiedReports = Subject.GetQualifiedReports(decisions);
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
qualifiedReports.First().RemoteEpisode.Episodes.First().EpisodeNumber.Should().Be(1);
|
qualifiedReports.First().RemoteEpisode.Episodes.First().EpisodeNumber.Should().Be(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +97,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode2));
|
decisions.Add(new DownloadDecision(remoteEpisode2));
|
||||||
|
|
||||||
var qualifiedReports = Subject.GetQualifiedReports(decisions);
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
qualifiedReports.First().RemoteEpisode.Episodes.First().EpisodeNumber.Should().Be(1);
|
qualifiedReports.First().RemoteEpisode.Episodes.First().EpisodeNumber.Should().Be(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +116,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
decisions.Add(new DownloadDecision(remoteEpisodeHdSmallYounge));
|
decisions.Add(new DownloadDecision(remoteEpisodeHdSmallYounge));
|
||||||
decisions.Add(new DownloadDecision(remoteEpisodeHdLargeYounge));
|
decisions.Add(new DownloadDecision(remoteEpisodeHdLargeYounge));
|
||||||
|
|
||||||
var qualifiedReports = Subject.GetQualifiedReports(decisions);
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
qualifiedReports.First().RemoteEpisode.Should().Be(remoteEpisodeHdSmallYounge);
|
qualifiedReports.First().RemoteEpisode.Should().Be(remoteEpisodeHdSmallYounge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +131,7 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode1));
|
decisions.Add(new DownloadDecision(remoteEpisode1));
|
||||||
decisions.Add(new DownloadDecision(remoteEpisode2));
|
decisions.Add(new DownloadDecision(remoteEpisode2));
|
||||||
|
|
||||||
var qualifiedReports = Subject.GetQualifiedReports(decisions);
|
var qualifiedReports = Subject.PrioritizeDecisions(decisions);
|
||||||
qualifiedReports.First().RemoteEpisode.Should().Be(remoteEpisode2);
|
qualifiedReports.First().RemoteEpisode.Should().Be(remoteEpisode2);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,12 +11,21 @@ using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
using NzbDrone.Test.Common;
|
using NzbDrone.Test.Common;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
public class DownloadApprovedFixture : CoreTest<DownloadApprovedReports>
|
public class DownloadApprovedFixture : CoreTest<DownloadApprovedReports>
|
||||||
{
|
{
|
||||||
|
[SetUp]
|
||||||
|
public void SetUp()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IPrioritizeDownloadDecision>()
|
||||||
|
.Setup(v => v.PrioritizeDecisions(It.IsAny<List<DownloadDecision>>()))
|
||||||
|
.Returns<List<DownloadDecision>>(v => v);
|
||||||
|
}
|
||||||
|
|
||||||
private Episode GetEpisode(int id)
|
private Episode GetEpisode(int id)
|
||||||
{
|
{
|
||||||
return Builder<Episode>.CreateNew()
|
return Builder<Episode>.CreateNew()
|
||||||
|
@ -163,5 +172,15 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
Subject.DownloadApproved(decisions).Should().BeEmpty();
|
Subject.DownloadApproved(decisions).Should().BeEmpty();
|
||||||
ExceptionVerification.ExpectedWarns(1);
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_return_an_empty_list_when_none_are_appproved()
|
||||||
|
{
|
||||||
|
var decisions = new List<DownloadDecision>();
|
||||||
|
decisions.Add(new DownloadDecision(null, "Failure!"));
|
||||||
|
decisions.Add(new DownloadDecision(null, "Failure!"));
|
||||||
|
|
||||||
|
Subject.GetQualifiedReports(decisions).Should().BeEmpty();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@
|
||||||
<Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\RssSync\ProperSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\Search\SeriesSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\Search\SeriesSpecificationFixture.cs" />
|
||||||
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
<Compile Include="Download\DownloadApprovedReportsTests\DownloadApprovedFixture.cs" />
|
||||||
<Compile Include="Download\DownloadApprovedReportsTests\GetQualifiedReportsFixture.cs" />
|
<Compile Include="DecisionEngineTests\PrioritizeDownloadDecisionFixture.cs" />
|
||||||
<Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" />
|
<Compile Include="Download\DownloadClientTests\Blackhole\UsenetBlackholeFixture.cs" />
|
||||||
<Compile Include="Download\DownloadClientTests\DownloadClientFixtureBase.cs" />
|
<Compile Include="Download\DownloadClientTests\DownloadClientFixtureBase.cs" />
|
||||||
<Compile Include="Download\DownloadClientTests\NzbgetTests\NzbgetFixture.cs" />
|
<Compile Include="Download\DownloadClientTests\NzbgetTests\NzbgetFixture.cs" />
|
||||||
|
|
|
@ -3,12 +3,13 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common;
|
using NzbDrone.Common;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Instrumentation.Extensions;
|
using NzbDrone.Core.Instrumentation.Extensions;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
using NzbDrone.Common.Serializer;
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.DecisionEngine
|
||||||
|
{
|
||||||
|
public interface IPrioritizeDownloadDecision
|
||||||
|
{
|
||||||
|
List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DownloadDecisionPriorizationService : IPrioritizeDownloadDecision
|
||||||
|
{
|
||||||
|
public List<DownloadDecision> PrioritizeDecisions(List<DownloadDecision> decisions)
|
||||||
|
{
|
||||||
|
return decisions
|
||||||
|
.Where(c => c.RemoteEpisode.Series != null)
|
||||||
|
.GroupBy(c => c.RemoteEpisode.Series.Id, (i, s) => s
|
||||||
|
.OrderByDescending(c => c.RemoteEpisode.ParsedEpisodeInfo.Quality, new QualityModelComparer(s.First().RemoteEpisode.Series.QualityProfile))
|
||||||
|
.ThenBy(c => c.RemoteEpisode.Episodes.Select(e => e.EpisodeNumber).MinOrDefault())
|
||||||
|
.ThenBy(c => c.RemoteEpisode.Release.Size.Round(200.Megabytes()) / c.RemoteEpisode.Episodes.Count)
|
||||||
|
.ThenBy(c => c.RemoteEpisode.Release.Age))
|
||||||
|
.SelectMany(c => c)
|
||||||
|
.Union(decisions.Where(c => c.RemoteEpisode.Series == null))
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
@ -15,20 +16,23 @@ namespace NzbDrone.Core.Download
|
||||||
public class DownloadApprovedReports : IDownloadApprovedReports
|
public class DownloadApprovedReports : IDownloadApprovedReports
|
||||||
{
|
{
|
||||||
private readonly IDownloadService _downloadService;
|
private readonly IDownloadService _downloadService;
|
||||||
|
private readonly IPrioritizeDownloadDecision _prioritizeDownloadDecision;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public DownloadApprovedReports(IDownloadService downloadService, Logger logger)
|
public DownloadApprovedReports(IDownloadService downloadService, IPrioritizeDownloadDecision prioritizeDownloadDecision, Logger logger)
|
||||||
{
|
{
|
||||||
_downloadService = downloadService;
|
_downloadService = downloadService;
|
||||||
|
_prioritizeDownloadDecision = prioritizeDownloadDecision;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<DownloadDecision> DownloadApproved(List<DownloadDecision> decisions)
|
public List<DownloadDecision> DownloadApproved(List<DownloadDecision> decisions)
|
||||||
{
|
{
|
||||||
var qualifiedReports = GetQualifiedReports(decisions);
|
var qualifiedReports = GetQualifiedReports(decisions);
|
||||||
|
var prioritizedDecisions = _prioritizeDownloadDecision.PrioritizeDecisions(qualifiedReports);
|
||||||
var downloadedReports = new List<DownloadDecision>();
|
var downloadedReports = new List<DownloadDecision>();
|
||||||
|
|
||||||
foreach (var report in qualifiedReports)
|
foreach (var report in prioritizedDecisions)
|
||||||
{
|
{
|
||||||
var remoteEpisode = report.RemoteEpisode;
|
var remoteEpisode = report.RemoteEpisode;
|
||||||
|
|
||||||
|
@ -57,14 +61,7 @@ namespace NzbDrone.Core.Download
|
||||||
|
|
||||||
public List<DownloadDecision> GetQualifiedReports(IEnumerable<DownloadDecision> decisions)
|
public List<DownloadDecision> GetQualifiedReports(IEnumerable<DownloadDecision> decisions)
|
||||||
{
|
{
|
||||||
return decisions.Where(c => c.Approved && c.RemoteEpisode.Episodes.Any())
|
return decisions.Where(c => c.Approved && c.RemoteEpisode.Episodes.Any()).ToList();
|
||||||
.GroupBy(c => c.RemoteEpisode.Series.Id, (i,s) => s
|
|
||||||
.OrderByDescending(c => c.RemoteEpisode.ParsedEpisodeInfo.Quality, new QualityModelComparer(s.First().RemoteEpisode.Series.QualityProfile))
|
|
||||||
.ThenBy(c => c.RemoteEpisode.Episodes.Select(e => e.EpisodeNumber).MinOrDefault())
|
|
||||||
.ThenBy(c => c.RemoteEpisode.Release.Size.Round(200.Megabytes()) / c.RemoteEpisode.Episodes.Count)
|
|
||||||
.ThenBy(c => c.RemoteEpisode.Release.Age))
|
|
||||||
.SelectMany(c => c)
|
|
||||||
.ToList();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,6 +223,7 @@
|
||||||
<Compile Include="Datastore\PagingSpec.cs" />
|
<Compile Include="Datastore\PagingSpec.cs" />
|
||||||
<Compile Include="Datastore\TableMapping.cs" />
|
<Compile Include="Datastore\TableMapping.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\RetrySpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\RetrySpecification.cs" />
|
||||||
|
<Compile Include="DecisionEngine\DownloadDecisionPriorizationService.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\BlacklistSpecification.cs" />
|
<Compile Include="DecisionEngine\Specifications\BlacklistSpecification.cs" />
|
||||||
<Compile Include="DecisionEngine\Specifications\DownloadDecision.cs" />
|
<Compile Include="DecisionEngine\Specifications\DownloadDecision.cs" />
|
||||||
<Compile Include="DecisionEngine\IRejectWithReason.cs" />
|
<Compile Include="DecisionEngine\IRejectWithReason.cs" />
|
||||||
|
|
|
@ -32,7 +32,7 @@ namespace NzbDrone.Update.Test
|
||||||
|
|
||||||
Subject.Start(AppType.Service, targetFolder);
|
Subject.Start(AppType.Service, targetFolder);
|
||||||
|
|
||||||
Mocker.GetMock<IProcessProvider>().Verify(c => c.SpawnNewProcess("c:\\NzbDrone\\NzbDrone.Console.exe", StartupContext.NO_BROWSER), Times.Once());
|
Mocker.GetMock<IProcessProvider>().Verify(c => c.SpawnNewProcess("c:\\NzbDrone\\NzbDrone.Console.exe", "--" + StartupContext.NO_BROWSER), Times.Once());
|
||||||
|
|
||||||
ExceptionVerification.ExpectedWarns(1);
|
ExceptionVerification.ExpectedWarns(1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,48 +20,40 @@ define(
|
||||||
columns:
|
columns:
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
name : 'age',
|
name : 'age',
|
||||||
label : 'Age',
|
label : 'Age',
|
||||||
sortable: true,
|
cell : AgeCell
|
||||||
cell : AgeCell
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'title',
|
name : 'title',
|
||||||
label : 'Title',
|
label : 'Title',
|
||||||
sortable: true,
|
cell : Backgrid.StringCell.extend({ className: 'nzb-title-cell' })
|
||||||
cell : Backgrid.StringCell.extend({ className: 'nzb-title-cell' })
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'indexer',
|
name : 'indexer',
|
||||||
label : 'Indexer',
|
label : 'Indexer',
|
||||||
sortable: true,
|
cell : Backgrid.StringCell
|
||||||
cell : Backgrid.StringCell
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'size',
|
name : 'size',
|
||||||
label : 'Size',
|
label : 'Size',
|
||||||
sortable: true,
|
cell : FileSizeCell
|
||||||
cell : FileSizeCell
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'quality',
|
name : 'quality',
|
||||||
label : 'Quality',
|
label : 'Quality',
|
||||||
sortable : true,
|
cell : QualityCell
|
||||||
cell : QualityCell,
|
|
||||||
sortValue : function (model) {
|
|
||||||
return model.get('quality').quality.weight;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name : 'rejections',
|
name : 'rejections',
|
||||||
label: '',
|
label : '',
|
||||||
cell : ApprovalStatusCell
|
cell : ApprovalStatusCell
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name : 'download',
|
name : 'download',
|
||||||
label: '',
|
label : '',
|
||||||
cell : DownloadReportCell
|
cell : DownloadReportCell
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
|
@ -1,19 +1,44 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
'backbone',
|
'backbone.pageable',
|
||||||
'Release/ReleaseModel'
|
'Release/ReleaseModel',
|
||||||
], function (Backbone, ReleaseModel) {
|
'Mixins/AsSortedCollection'
|
||||||
return Backbone.Collection.extend({
|
], function (PagableCollection, ReleaseModel, AsSortedCollection) {
|
||||||
|
var Collection = PagableCollection.extend({
|
||||||
url : window.NzbDrone.ApiRoot + '/release',
|
url : window.NzbDrone.ApiRoot + '/release',
|
||||||
model: ReleaseModel,
|
model: ReleaseModel,
|
||||||
|
|
||||||
state: {
|
state: {
|
||||||
pageSize: 2000
|
pageSize : 2000,
|
||||||
|
sortKey : 'download',
|
||||||
|
order : -1
|
||||||
|
},
|
||||||
|
|
||||||
|
mode: 'client',
|
||||||
|
|
||||||
|
sortMappings: {
|
||||||
|
'quality' : { sortKey: 'qualityWeight' },
|
||||||
|
'rejections' : { sortValue: function (model, attr) {
|
||||||
|
var rejections = model.get('rejections');
|
||||||
|
var releaseWeight = model.get('releaseWeight');
|
||||||
|
|
||||||
|
if (rejections.length !== 0) {
|
||||||
|
return releaseWeight + 1000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
return releaseWeight;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'download' : { sortKey: 'releaseWeight' }
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchEpisodeReleases: function (episodeId) {
|
fetchEpisodeReleases: function (episodeId) {
|
||||||
return this.fetch({ data: { episodeId: episodeId }});
|
return this.fetch({ data: { episodeId: episodeId }});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Collection = AsSortedCollection.call(Collection);
|
||||||
|
|
||||||
|
return Collection;
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue