Merge branch 'quality-definitions' of https://github.com/Taloth/NzbDrone into Taloth-quality-definitions
This commit is contained in:
commit
f832d55424
|
@ -107,7 +107,6 @@ namespace NzbDrone.Api.Test.MappingTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_map_qualityprofile()
|
public void should_map_qualityprofile()
|
||||||
{
|
{
|
||||||
|
|
||||||
var profileResource = new QualityProfileResource
|
var profileResource = new QualityProfileResource
|
||||||
{
|
{
|
||||||
Allowed = Builder<QualityResource>.CreateListOfSize(1).Build().ToList(),
|
Allowed = Builder<QualityResource>.CreateListOfSize(1).Build().ToList(),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Api.EpisodeFiles
|
namespace NzbDrone.Api.EpisodeFiles
|
||||||
|
|
|
@ -4,6 +4,7 @@ using NzbDrone.Api.Episodes;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
using NzbDrone.Api.Series;
|
using NzbDrone.Api.Series;
|
||||||
using NzbDrone.Core.History;
|
using NzbDrone.Core.History;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Api.History
|
namespace NzbDrone.Api.History
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Indexers
|
namespace NzbDrone.Api.Indexers
|
||||||
|
|
|
@ -166,8 +166,8 @@
|
||||||
<Compile Include="NzbDroneApiModule.cs" />
|
<Compile Include="NzbDroneApiModule.cs" />
|
||||||
<Compile Include="Qualities\QualityProfileResource.cs" />
|
<Compile Include="Qualities\QualityProfileResource.cs" />
|
||||||
<Compile Include="Qualities\QualityProfileModule.cs" />
|
<Compile Include="Qualities\QualityProfileModule.cs" />
|
||||||
<Compile Include="Qualities\QualitySizeResource.cs" />
|
<Compile Include="Qualities\QualityDefinitionResource.cs" />
|
||||||
<Compile Include="Qualities\QualitySizeModule.cs" />
|
<Compile Include="Qualities\QualityDefinitionModule.cs" />
|
||||||
<Compile Include="Extensions\ReqResExtensions.cs" />
|
<Compile Include="Extensions\ReqResExtensions.cs" />
|
||||||
<Compile Include="Config\SettingsModule.cs" />
|
<Compile Include="Config\SettingsModule.cs" />
|
||||||
<Compile Include="System\SystemModule.cs" />
|
<Compile Include="System\SystemModule.cs" />
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Api.Mapping;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Qualities
|
||||||
|
{
|
||||||
|
public class QualityDefinitionModule : NzbDroneRestModule<QualityDefinitionResource>
|
||||||
|
{
|
||||||
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
|
|
||||||
|
public QualityDefinitionModule(IQualityDefinitionService qualityDefinitionService)
|
||||||
|
{
|
||||||
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
|
|
||||||
|
GetResourceAll = GetAll;
|
||||||
|
|
||||||
|
GetResourceById = GetById;
|
||||||
|
|
||||||
|
UpdateResource = Update;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update(QualityDefinitionResource resource)
|
||||||
|
{
|
||||||
|
var model = resource.InjectTo<QualityDefinition>();
|
||||||
|
_qualityDefinitionService.Update(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
private QualityDefinitionResource GetById(int id)
|
||||||
|
{
|
||||||
|
return _qualityDefinitionService.Get((Quality)id).InjectTo<QualityDefinitionResource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<QualityDefinitionResource> GetAll()
|
||||||
|
{
|
||||||
|
return ToListResource(_qualityDefinitionService.All);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
namespace NzbDrone.Api.Qualities
|
||||||
|
{
|
||||||
|
public class QualityDefinitionResource : RestResource
|
||||||
|
{
|
||||||
|
public Quality Quality { get; set; }
|
||||||
|
|
||||||
|
public String Title { get; set; }
|
||||||
|
|
||||||
|
public Int32 Weight { get; set; }
|
||||||
|
|
||||||
|
public Int32 MinSize { get; set; }
|
||||||
|
public Int32 MaxSize { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,11 +9,14 @@ namespace NzbDrone.Api.Qualities
|
||||||
public class QualityProfileModule : NzbDroneRestModule<QualityProfileResource>
|
public class QualityProfileModule : NzbDroneRestModule<QualityProfileResource>
|
||||||
{
|
{
|
||||||
private readonly IQualityProfileService _qualityProfileService;
|
private readonly IQualityProfileService _qualityProfileService;
|
||||||
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
|
|
||||||
public QualityProfileModule(IQualityProfileService qualityProfileService)
|
public QualityProfileModule(IQualityProfileService qualityProfileService,
|
||||||
|
IQualityDefinitionService qualityDefinitionService)
|
||||||
: base("/qualityprofiles")
|
: base("/qualityprofiles")
|
||||||
{
|
{
|
||||||
_qualityProfileService = qualityProfileService;
|
_qualityProfileService = qualityProfileService;
|
||||||
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
|
|
||||||
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
||||||
SharedValidator.RuleFor(c => c.Cutoff).NotNull();
|
SharedValidator.RuleFor(c => c.Cutoff).NotNull();
|
||||||
|
@ -44,38 +47,47 @@ namespace NzbDrone.Api.Qualities
|
||||||
|
|
||||||
private void Update(QualityProfileResource resource)
|
private void Update(QualityProfileResource resource)
|
||||||
{
|
{
|
||||||
var model = resource.InjectTo<QualityProfile>();
|
var model = _qualityProfileService.Get(resource.Id);
|
||||||
|
model.Name = resource.Name;
|
||||||
|
model.Cutoff = (Quality)resource.Cutoff.Id;
|
||||||
|
model.Allowed = resource.Allowed.Select(p => (Quality)p.Id).ToList();
|
||||||
_qualityProfileService.Update(model);
|
_qualityProfileService.Update(model);
|
||||||
}
|
}
|
||||||
|
|
||||||
private QualityProfileResource GetById(int id)
|
private QualityProfileResource GetById(int id)
|
||||||
{
|
{
|
||||||
return QualityToResource(_qualityProfileService.Get(id));
|
return MapToResource(_qualityProfileService.Get(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<QualityProfileResource> GetAll()
|
private List<QualityProfileResource> GetAll()
|
||||||
{
|
{
|
||||||
var allProfiles = _qualityProfileService.All();
|
var profiles = _qualityProfileService.All().Select(MapToResource).ToList();
|
||||||
|
|
||||||
|
|
||||||
var profiles = allProfiles.Select(QualityToResource).ToList();
|
|
||||||
|
|
||||||
return profiles;
|
return profiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static QualityProfileResource QualityToResource(QualityProfile profile)
|
private QualityProfileResource MapToResource(QualityProfile profile)
|
||||||
{
|
{
|
||||||
return new QualityProfileResource
|
return new QualityProfileResource
|
||||||
{
|
{
|
||||||
Cutoff = profile.Cutoff.InjectTo<QualityResource>(),
|
Cutoff = MapToResource(_qualityDefinitionService.Get(profile.Cutoff)),
|
||||||
Available = Quality.All()
|
Available = _qualityDefinitionService.All()
|
||||||
.Where(c => !profile.Allowed.Any(q => c.Id == q.Id))
|
.Where(c => !profile.Allowed.Any(q => c.Quality == q))
|
||||||
.InjectTo<List<QualityResource>>(),
|
.Select(MapToResource).ToList(),
|
||||||
|
Allowed = profile.Allowed.Select(_qualityDefinitionService.Get).Select(MapToResource).ToList(),
|
||||||
Allowed = profile.Allowed.InjectTo<List<QualityResource>>(),
|
|
||||||
Name = profile.Name,
|
Name = profile.Name,
|
||||||
Id = profile.Id
|
Id = profile.Id
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private QualityResource MapToResource(QualityDefinition config)
|
||||||
|
{
|
||||||
|
return new QualityResource
|
||||||
|
{
|
||||||
|
Id = config.Quality.Id,
|
||||||
|
Name = config.Quality.Name,
|
||||||
|
Weight = config.Weight
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -14,7 +14,8 @@ namespace NzbDrone.Api.Qualities
|
||||||
|
|
||||||
public class QualityResource : RestResource
|
public class QualityResource : RestResource
|
||||||
{
|
{
|
||||||
public Int32 Weight { get; set; }
|
|
||||||
public String Name { get; set; }
|
public String Name { get; set; }
|
||||||
|
|
||||||
|
public Int32 Weight { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,9 +7,13 @@ namespace NzbDrone.Api.Qualities
|
||||||
{
|
{
|
||||||
public class QualityProfileSchemaModule : NzbDroneRestModule<QualityProfileResource>
|
public class QualityProfileSchemaModule : NzbDroneRestModule<QualityProfileResource>
|
||||||
{
|
{
|
||||||
public QualityProfileSchemaModule()
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
|
|
||||||
|
public QualityProfileSchemaModule(IQualityDefinitionService qualityDefinitionService)
|
||||||
: base("/qualityprofiles/schema")
|
: base("/qualityprofiles/schema")
|
||||||
{
|
{
|
||||||
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
|
|
||||||
GetResourceAll = GetAll;
|
GetResourceAll = GetAll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,21 +23,30 @@ namespace NzbDrone.Api.Qualities
|
||||||
profile.Cutoff = Quality.Unknown;
|
profile.Cutoff = Quality.Unknown;
|
||||||
profile.Allowed = new List<Quality>();
|
profile.Allowed = new List<Quality>();
|
||||||
|
|
||||||
return new List<QualityProfileResource>{ QualityToResource(profile)};
|
return new List<QualityProfileResource> { QualityToResource(profile) };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static QualityProfileResource QualityToResource(QualityProfile profile)
|
private QualityProfileResource QualityToResource(QualityProfile profile)
|
||||||
{
|
{
|
||||||
return new QualityProfileResource
|
return new QualityProfileResource
|
||||||
{
|
{
|
||||||
Available = Quality.All()
|
Cutoff = QualityToResource(_qualityDefinitionService.Get(profile.Cutoff)),
|
||||||
.Where(c => !profile.Allowed.Any(q => c.Id == q.Id))
|
Available = _qualityDefinitionService.All().Select(QualityToResource).ToList(),
|
||||||
.InjectTo<List<QualityResource>>(),
|
Allowed = profile.Allowed.Select(_qualityDefinitionService.Get).Select(QualityToResource).ToList(),
|
||||||
|
Name = profile.Name,
|
||||||
|
Id = profile.Id
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Allowed = profile.Allowed.InjectTo<List<QualityResource>>(),
|
|
||||||
Name = profile.Name,
|
private QualityResource QualityToResource(QualityDefinition config)
|
||||||
Id = profile.Id
|
{
|
||||||
};
|
return new QualityResource
|
||||||
|
{
|
||||||
|
Id = config.Quality.Id,
|
||||||
|
Name = config.Quality.Name,
|
||||||
|
Weight = config.Weight
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,38 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using NzbDrone.Core.Qualities;
|
|
||||||
using NzbDrone.Api.Mapping;
|
|
||||||
|
|
||||||
namespace NzbDrone.Api.Qualities
|
|
||||||
{
|
|
||||||
public class QualitySizeModule : NzbDroneRestModule<QualitySizeResource>
|
|
||||||
{
|
|
||||||
private readonly IQualitySizeService _qualityTypeProvider;
|
|
||||||
|
|
||||||
public QualitySizeModule(IQualitySizeService qualityTypeProvider)
|
|
||||||
{
|
|
||||||
_qualityTypeProvider = qualityTypeProvider;
|
|
||||||
|
|
||||||
GetResourceAll = GetAll;
|
|
||||||
|
|
||||||
GetResourceById = GetById;
|
|
||||||
|
|
||||||
UpdateResource = Update;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update(QualitySizeResource resource)
|
|
||||||
{
|
|
||||||
var model = resource.InjectTo<QualitySize>();
|
|
||||||
_qualityTypeProvider.Update(model);
|
|
||||||
}
|
|
||||||
|
|
||||||
private QualitySizeResource GetById(int id)
|
|
||||||
{
|
|
||||||
return _qualityTypeProvider.Get(id).InjectTo<QualitySizeResource>();
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<QualitySizeResource> GetAll()
|
|
||||||
{
|
|
||||||
return ToListResource(_qualityTypeProvider.All);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
using System;
|
|
||||||
using NzbDrone.Api.REST;
|
|
||||||
|
|
||||||
namespace NzbDrone.Api.Qualities
|
|
||||||
{
|
|
||||||
public class QualitySizeResource : RestResource
|
|
||||||
{
|
|
||||||
public Int32 QualityId { get; set; }
|
|
||||||
public String Name { get; set; }
|
|
||||||
public Int32 MinSize { get; set; }
|
|
||||||
public Int32 MaxSize { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using NzbDrone.Api.REST;
|
using NzbDrone.Api.REST;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Api.Queue
|
namespace NzbDrone.Api.Queue
|
||||||
|
|
|
@ -75,6 +75,7 @@ namespace NzbDrone.Core.Test.Datastore
|
||||||
public void one_to_one()
|
public void one_to_one()
|
||||||
{
|
{
|
||||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||||
|
.With(c => c.Quality = new QualityModel())
|
||||||
.BuildNew();
|
.BuildNew();
|
||||||
|
|
||||||
Db.Insert(episodeFile);
|
Db.Insert(episodeFile);
|
||||||
|
|
|
@ -81,25 +81,25 @@ namespace NzbDrone.Core.Test.Datastore.SQLiteMigrationHelperTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_read_existing_indexes()
|
public void should_read_existing_indexes()
|
||||||
{
|
{
|
||||||
var indexes = _subject.GetIndexes("QualitySizes");
|
var indexes = _subject.GetIndexes("QualityDefinitions");
|
||||||
|
|
||||||
indexes.Should().NotBeEmpty();
|
indexes.Should().NotBeEmpty();
|
||||||
|
|
||||||
indexes.Should().OnlyContain(c => c != null);
|
indexes.Should().OnlyContain(c => c != null);
|
||||||
indexes.Should().OnlyContain(c => !string.IsNullOrWhiteSpace(c.Column));
|
indexes.Should().OnlyContain(c => !string.IsNullOrWhiteSpace(c.Column));
|
||||||
indexes.Should().OnlyContain(c => c.Table == "QualitySizes");
|
indexes.Should().OnlyContain(c => c.Table == "QualityDefinitions");
|
||||||
indexes.Should().OnlyContain(c => c.Unique);
|
indexes.Should().OnlyContain(c => c.Unique);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_add_indexes_when_creating_new_table()
|
public void should_add_indexes_when_creating_new_table()
|
||||||
{
|
{
|
||||||
var columns = _subject.GetColumns("QualitySizes");
|
var columns = _subject.GetColumns("QualityDefinitions");
|
||||||
var indexes = _subject.GetIndexes("QualitySizes");
|
var indexes = _subject.GetIndexes("QualityDefinitions");
|
||||||
|
|
||||||
_subject.CreateTable("QualityB", columns.Values, indexes);
|
_subject.CreateTable("QualityDefinitionsB", columns.Values, indexes);
|
||||||
|
|
||||||
var newIndexes = _subject.GetIndexes("QualityB");
|
var newIndexes = _subject.GetIndexes("QualityDefinitionsB");
|
||||||
|
|
||||||
newIndexes.Should().HaveSameCount(indexes);
|
newIndexes.Should().HaveSameCount(indexes);
|
||||||
newIndexes.Select(c=>c.Column).Should().BeEquivalentTo(indexes.Select(c=>c.Column));
|
newIndexes.Select(c=>c.Column).Should().BeEquivalentTo(indexes.Select(c=>c.Column));
|
||||||
|
|
|
@ -19,7 +19,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
private RemoteEpisode parseResultSingle;
|
private RemoteEpisode parseResultSingle;
|
||||||
private Series series30minutes;
|
private Series series30minutes;
|
||||||
private Series series60minutes;
|
private Series series60minutes;
|
||||||
private QualitySize qualityType;
|
private QualityDefinition qualityType;
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
|
@ -47,10 +47,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
.With(c => c.Runtime = 60)
|
.With(c => c.Runtime = 60)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
qualityType = Builder<QualitySize>.CreateNew()
|
qualityType = Builder<QualityDefinition>.CreateNew()
|
||||||
.With(q => q.MinSize = 0)
|
.With(q => q.MinSize = 0)
|
||||||
.With(q => q.MaxSize = 10)
|
.With(q => q.MaxSize = 10)
|
||||||
.With(q => q.QualityId = 1)
|
.With(q => q.Quality = Quality.SDTV)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Series = series30minutes;
|
parseResultSingle.Series = series30minutes;
|
||||||
parseResultSingle.Release.Size = 184572800;
|
parseResultSingle.Release.Size = 184572800;
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Series = series60minutes;
|
parseResultSingle.Series = series60minutes;
|
||||||
parseResultSingle.Release.Size = 368572800;
|
parseResultSingle.Release.Size = 368572800;
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -99,7 +99,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Series = series30minutes;
|
parseResultSingle.Series = series30minutes;
|
||||||
parseResultSingle.Release.Size = 1.Gigabytes();
|
parseResultSingle.Release.Size = 1.Gigabytes();
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -118,7 +118,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Series = series60minutes;
|
parseResultSingle.Series = series60minutes;
|
||||||
parseResultSingle.Release.Size = 1.Gigabytes();
|
parseResultSingle.Release.Size = 1.Gigabytes();
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -135,7 +135,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultMulti.Series = series30minutes;
|
parseResultMulti.Series = series30minutes;
|
||||||
parseResultMulti.Release.Size = 184572800;
|
parseResultMulti.Release.Size = 184572800;
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -154,7 +154,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultMulti.Series = series60minutes;
|
parseResultMulti.Series = series60minutes;
|
||||||
parseResultMulti.Release.Size = 368572800;
|
parseResultMulti.Release.Size = 368572800;
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -173,7 +173,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultMulti.Series = series30minutes;
|
parseResultMulti.Series = series30minutes;
|
||||||
parseResultMulti.Release.Size = 1.Gigabytes();
|
parseResultMulti.Release.Size = 1.Gigabytes();
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -192,7 +192,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultMulti.Series = series60minutes;
|
parseResultMulti.Series = series60minutes;
|
||||||
parseResultMulti.Release.Size = 10.Gigabytes();
|
parseResultMulti.Release.Size = 10.Gigabytes();
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -211,7 +211,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Series = series30minutes;
|
parseResultSingle.Series = series30minutes;
|
||||||
parseResultSingle.Release.Size = 184572800;
|
parseResultSingle.Release.Size = 184572800;
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -230,7 +230,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Series = series60minutes;
|
parseResultSingle.Series = series60minutes;
|
||||||
parseResultSingle.Release.Size = 368572800;
|
parseResultSingle.Release.Size = 368572800;
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -249,7 +249,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Series = series30minutes;
|
parseResultSingle.Series = series30minutes;
|
||||||
parseResultSingle.Release.Size = 1.Gigabytes();
|
parseResultSingle.Release.Size = 1.Gigabytes();
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -270,7 +270,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Series = series60minutes;
|
parseResultSingle.Series = series60minutes;
|
||||||
parseResultSingle.Release.Size = 10.Gigabytes();
|
parseResultSingle.Release.Size = 10.Gigabytes();
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -292,7 +292,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Release.Size = 18457280000;
|
parseResultSingle.Release.Size = 18457280000;
|
||||||
qualityType.MaxSize = 0;
|
qualityType.MaxSize = 0;
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -314,7 +314,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
parseResultSingle.Release.Size = 36857280000;
|
parseResultSingle.Release.Size = 36857280000;
|
||||||
qualityType.MaxSize = 0;
|
qualityType.MaxSize = 0;
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -338,7 +338,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
|
|
||||||
qualityType.MaxSize = (int)600.Megabytes();
|
qualityType.MaxSize = (int)600.Megabytes();
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Setup(s => s.Get(1)).Returns(qualityType);
|
Mocker.GetMock<IQualityDefinitionService>().Setup(s => s.Get(Quality.SDTV)).Returns(qualityType);
|
||||||
|
|
||||||
Mocker.GetMock<IEpisodeService>().Setup(
|
Mocker.GetMock<IEpisodeService>().Setup(
|
||||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||||
|
@ -374,7 +374,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
Subject.IsSatisfiedBy(parseResult, null).Should().BeFalse();
|
Subject.IsSatisfiedBy(parseResult, null).Should().BeFalse();
|
||||||
|
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeService>().Verify(c=>c.Get(It.IsAny<int>()),Times.Never());
|
Mocker.GetMock<IQualityDefinitionService>().Verify(c => c.Get(It.IsAny<Quality>()), Times.Never());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -13,35 +13,35 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_true_if_current_episode_is_less_than_cutoff()
|
public void should_return_true_if_current_episode_is_less_than_cutoff()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.Bluray1080p },
|
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.Bluray1080p, Allowed = Qualities.QualityFixture.GetDefaultQualities() },
|
||||||
new QualityModel(Quality.DVD, true)).Should().BeTrue();
|
new QualityModel(Quality.DVD, true)).Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_if_current_episode_is_equal_to_cutoff()
|
public void should_return_false_if_current_episode_is_equal_to_cutoff()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.HDTV720p },
|
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.HDTV720p, Allowed = Qualities.QualityFixture.GetDefaultQualities() },
|
||||||
new QualityModel(Quality.HDTV720p, true)).Should().BeFalse();
|
new QualityModel(Quality.HDTV720p, true)).Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_if_current_episode_is_greater_than_cutoff()
|
public void should_return_false_if_current_episode_is_greater_than_cutoff()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.HDTV720p },
|
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.HDTV720p, Allowed = Qualities.QualityFixture.GetDefaultQualities() },
|
||||||
new QualityModel(Quality.Bluray1080p, true)).Should().BeFalse();
|
new QualityModel(Quality.Bluray1080p, true)).Should().BeFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_true_when_new_episode_is_proper_but_existing_is_not()
|
public void should_return_true_when_new_episode_is_proper_but_existing_is_not()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.HDTV720p },
|
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.HDTV720p, Allowed = Qualities.QualityFixture.GetDefaultQualities() },
|
||||||
new QualityModel(Quality.HDTV720p, false), new QualityModel(Quality.HDTV720p, true)).Should().BeTrue();
|
new QualityModel(Quality.HDTV720p, false), new QualityModel(Quality.HDTV720p, true)).Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_return_false_if_cutoff_is_met_and_quality_is_higher()
|
public void should_return_false_if_cutoff_is_met_and_quality_is_higher()
|
||||||
{
|
{
|
||||||
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.HDTV720p },
|
Subject.CutoffNotMet(new QualityProfile { Cutoff = Quality.HDTV720p, Allowed = Qualities.QualityFixture.GetDefaultQualities() },
|
||||||
new QualityModel(Quality.HDTV720p, true), new QualityModel(Quality.Bluray1080p, true)).Should().BeFalse();
|
new QualityModel(Quality.HDTV720p, true), new QualityModel(Quality.Bluray1080p, true)).Should().BeFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
};
|
};
|
||||||
|
|
||||||
_fakeSeries = Builder<Series>.CreateNew()
|
_fakeSeries = Builder<Series>.CreateNew()
|
||||||
.With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p })
|
.With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p, Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_parseResultMulti = new RemoteEpisode
|
_parseResultMulti = new RemoteEpisode
|
||||||
|
@ -62,8 +62,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
_upgradableQuality = new QualityModel(Quality.SDTV, false);
|
_upgradableQuality = new QualityModel(Quality.SDTV, false);
|
||||||
_notupgradableQuality = new QualityModel(Quality.HDTV1080p, true);
|
_notupgradableQuality = new QualityModel(Quality.HDTV1080p, true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(1)).Returns(_notupgradableQuality);
|
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(1)).Returns(_notupgradableQuality);
|
||||||
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(2)).Returns(_notupgradableQuality);
|
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(2)).Returns(_notupgradableQuality);
|
||||||
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(3)).Returns<QualityModel>(null);
|
Mocker.GetMock<IHistoryService>().Setup(c => c.GetBestQualityInHistory(3)).Returns<QualityModel>(null);
|
||||||
|
@ -132,7 +130,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[Test]
|
[Test]
|
||||||
public void should_not_be_upgradable_if_episode_is_of_same_quality_as_existing()
|
public void should_not_be_upgradable_if_episode_is_of_same_quality_as_existing()
|
||||||
{
|
{
|
||||||
_fakeSeries.QualityProfile = new QualityProfile { Cutoff = Quality.WEBDL1080p };
|
_fakeSeries.QualityProfile = new QualityProfile { Cutoff = Quality.WEBDL1080p, Allowed = Qualities.QualityFixture.GetDefaultQualities() };
|
||||||
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, false);
|
_parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.WEBDL1080p, false);
|
||||||
_upgradableQuality = new QualityModel(Quality.WEBDL1080p, false);
|
_upgradableQuality = new QualityModel(Quality.WEBDL1080p, false);
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_series = Builder<Series>.CreateNew().Build();
|
_series = Builder<Series>.CreateNew()
|
||||||
|
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
|
.Build();
|
||||||
|
|
||||||
_episode = Builder<Episode>.CreateNew()
|
_episode = Builder<Episode>.CreateNew()
|
||||||
.With(e => e.SeriesId = _series.Id)
|
.With(e => e.SeriesId = _series.Id)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using FluentAssertions;
|
using System.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
@ -23,6 +24,12 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
new object[] { Quality.SDTV, false, Quality.SDTV, true, Quality.SDTV, true },
|
new object[] { Quality.SDTV, false, Quality.SDTV, true, Quality.SDTV, true },
|
||||||
new object[] { Quality.WEBDL1080p, false, Quality.WEBDL1080p, false, Quality.WEBDL1080p, false }
|
new object[] { Quality.WEBDL1080p, false, Quality.WEBDL1080p, false, Quality.WEBDL1080p, false }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private void GivenAutoDownloadPropers(bool autoDownloadPropers)
|
private void GivenAutoDownloadPropers(bool autoDownloadPropers)
|
||||||
{
|
{
|
||||||
|
@ -36,7 +43,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
GivenAutoDownloadPropers(true);
|
GivenAutoDownloadPropers(true);
|
||||||
|
|
||||||
Subject.IsUpgradable(new QualityModel(current, currentProper), new QualityModel(newQuality, newProper))
|
var qualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() };
|
||||||
|
|
||||||
|
Subject.IsUpgradable(qualityProfile, new QualityModel(current, currentProper), new QualityModel(newQuality, newProper))
|
||||||
.Should().Be(expected);
|
.Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,8 +54,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
{
|
{
|
||||||
GivenAutoDownloadPropers(false);
|
GivenAutoDownloadPropers(false);
|
||||||
|
|
||||||
Subject.IsUpgradable(new QualityModel(Quality.DVD, true),
|
var qualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() };
|
||||||
new QualityModel(Quality.DVD, false)).Should().BeFalse();
|
|
||||||
|
Subject.IsUpgradable(qualityProfile, new QualityModel(Quality.DVD, true), new QualityModel(Quality.DVD, false))
|
||||||
|
.Should().BeFalse();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -38,7 +38,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||||
var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = _secondFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
|
var doubleEpisodeList = new List<Episode> { new Episode { EpisodeFile = _firstFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = _secondFile, EpisodeFileId = 1 }, new Episode { EpisodeFile = null } };
|
||||||
|
|
||||||
var fakeSeries = Builder<Series>.CreateNew()
|
var fakeSeries = Builder<Series>.CreateNew()
|
||||||
.With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p })
|
.With(c => c.QualityProfile = new QualityProfile { Cutoff = Quality.Bluray1080p, Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_parseResultMulti = new RemoteEpisode
|
_parseResultMulti = new RemoteEpisode
|
||||||
|
|
|
@ -37,6 +37,10 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
remoteEpisode.Release = new ReleaseInfo();
|
remoteEpisode.Release = new ReleaseInfo();
|
||||||
remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
||||||
|
|
||||||
|
remoteEpisode.Series = Builder<Series>.CreateNew()
|
||||||
|
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
|
.Build();
|
||||||
|
|
||||||
return remoteEpisode;
|
return remoteEpisode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,10 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||||
remoteEpisode.Release.PublishDate = DateTime.Now.AddDays(-Age);
|
remoteEpisode.Release.PublishDate = DateTime.Now.AddDays(-Age);
|
||||||
remoteEpisode.Release.Size = size;
|
remoteEpisode.Release.Size = size;
|
||||||
|
|
||||||
|
remoteEpisode.Series = Builder<Series>.CreateNew()
|
||||||
|
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
|
.Build();
|
||||||
|
|
||||||
return remoteEpisode;
|
return remoteEpisode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,7 +87,6 @@ namespace NzbDrone.Core.Test.Download
|
||||||
{
|
{
|
||||||
Mocker.GetMock<IDownloadClient>().Setup(c => c.IsConfigured).Returns(false);
|
Mocker.GetMock<IDownloadClient>().Setup(c => c.IsConfigured).Returns(false);
|
||||||
|
|
||||||
|
|
||||||
Subject.DownloadReport(_parseResult);
|
Subject.DownloadReport(_parseResult);
|
||||||
|
|
||||||
Mocker.GetMock<IDownloadClient>().Verify(c => c.DownloadNzb(It.IsAny<RemoteEpisode>()), Times.Never());
|
Mocker.GetMock<IDownloadClient>().Verify(c => c.DownloadNzb(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||||
|
|
|
@ -80,6 +80,20 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
.Returns(true);
|
.Returns(true);
|
||||||
|
|
||||||
Subject.Execute(new DownloadedEpisodesScanCommand());
|
Subject.Execute(new DownloadedEpisodesScanCommand());
|
||||||
|
|
||||||
|
VerifyNoImport();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void should_skip_if_no_series_found()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IParsingService>().Setup(c => c.GetSeries("foldername")).Returns((Series)null);
|
||||||
|
|
||||||
|
Subject.Execute(new DownloadedEpisodesScanCommand());
|
||||||
|
|
||||||
|
Mocker.GetMock<IMakeImportDecision>()
|
||||||
|
.Verify(c => c.GetImportDecisions(It.IsAny<List<string>>(), It.IsAny<Series>(), It.IsAny<bool>(), It.IsAny<Core.Qualities.QualityModel>()),
|
||||||
|
Times.Never());
|
||||||
|
|
||||||
VerifyNoImport();
|
VerifyNoImport();
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ 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 FizzWare.NBuilder;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
{
|
{
|
||||||
|
@ -63,7 +64,10 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
_fail3.Setup(c => c.RejectionReason).Returns("_fail3");
|
_fail3.Setup(c => c.RejectionReason).Returns("_fail3");
|
||||||
|
|
||||||
_videoFiles = new List<string> { @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi" };
|
_videoFiles = new List<string> { @"C:\Test\Unsorted\The.Office.S03E115.DVDRip.XviD-OSiTV.avi" };
|
||||||
_series = new Series();
|
_series = Builder<Series>.CreateNew()
|
||||||
|
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
|
.Build();
|
||||||
|
|
||||||
_quality = new QualityModel(Quality.DVD);
|
_quality = new QualityModel(Quality.DVD);
|
||||||
_localEpisode = new LocalEpisode
|
_localEpisode = new LocalEpisode
|
||||||
{
|
{
|
||||||
|
@ -80,7 +84,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
Mocker.GetMock<IMediaFileService>()
|
Mocker.GetMock<IMediaFileService>()
|
||||||
.Setup(c => c.FilterExistingFiles(_videoFiles, It.IsAny<int>()))
|
.Setup(c => c.FilterExistingFiles(_videoFiles, It.IsAny<int>()))
|
||||||
.Returns(_videoFiles);
|
.Returns(_videoFiles);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenSpecifications(params Mock<IImportDecisionEngineSpecification>[] mocks)
|
private void GivenSpecifications(params Mock<IImportDecisionEngineSpecification>[] mocks)
|
||||||
|
@ -162,7 +165,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
.Setup(c => c.FilterExistingFiles(_videoFiles, It.IsAny<int>()))
|
.Setup(c => c.FilterExistingFiles(_videoFiles, It.IsAny<int>()))
|
||||||
.Returns(_videoFiles);
|
.Returns(_videoFiles);
|
||||||
|
|
||||||
Subject.GetImportDecisions(_videoFiles, new Series(), false);
|
Subject.GetImportDecisions(_videoFiles, _series, false);
|
||||||
|
|
||||||
Mocker.GetMock<IParsingService>()
|
Mocker.GetMock<IParsingService>()
|
||||||
.Verify(c => c.GetEpisodes(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>()), Times.Exactly(_videoFiles.Count));
|
.Verify(c => c.GetEpisodes(It.IsAny<String>(), It.IsAny<Series>(), It.IsAny<Boolean>()), Times.Exactly(_videoFiles.Count));
|
||||||
|
@ -176,7 +179,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||||
var expectedQuality = QualityParser.ParseQuality(_videoFiles.Single());
|
var expectedQuality = QualityParser.ParseQuality(_videoFiles.Single());
|
||||||
|
|
||||||
var result = Subject.GetImportDecisions(_videoFiles, new Series(), false, null);
|
var result = Subject.GetImportDecisions(_videoFiles, _series, false, null);
|
||||||
|
|
||||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||||
}
|
}
|
||||||
|
@ -187,7 +190,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||||
var expectedQuality = QualityParser.ParseQuality(_videoFiles.Single());
|
var expectedQuality = QualityParser.ParseQuality(_videoFiles.Single());
|
||||||
|
|
||||||
var result = Subject.GetImportDecisions(_videoFiles, new Series(), false, new QualityModel(Quality.SDTV));
|
var result = Subject.GetImportDecisions(_videoFiles, _series, false, new QualityModel(Quality.SDTV));
|
||||||
|
|
||||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||||
}
|
}
|
||||||
|
@ -198,7 +201,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||||
var expectedQuality = new QualityModel(Quality.Bluray1080p);
|
var expectedQuality = new QualityModel(Quality.Bluray1080p);
|
||||||
|
|
||||||
var result = Subject.GetImportDecisions(_videoFiles, new Series(), false, expectedQuality);
|
var result = Subject.GetImportDecisions(_videoFiles, _series, false, expectedQuality);
|
||||||
|
|
||||||
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
result.Single().LocalEpisode.Quality.Should().Be(expectedQuality);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,13 +22,15 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
_series = Builder<Series>.CreateNew()
|
_series = Builder<Series>.CreateNew()
|
||||||
.With(s => s.SeriesType = SeriesTypes.Standard)
|
.With(s => s.SeriesType = SeriesTypes.Standard)
|
||||||
|
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_localEpisode = new LocalEpisode
|
_localEpisode = new LocalEpisode
|
||||||
{
|
{
|
||||||
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi",
|
Path = @"C:\Test\30 Rock\30.rock.s01e01.avi",
|
||||||
Quality = new QualityModel(Quality.HDTV720p, false)
|
Quality = new QualityModel(Quality.HDTV720p, false),
|
||||||
|
Series = _series
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||||
_approvedDecisions = new List<ImportDecision>();
|
_approvedDecisions = new List<ImportDecision>();
|
||||||
|
|
||||||
var series = Builder<Series>.CreateNew()
|
var series = Builder<Series>.CreateNew()
|
||||||
|
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var episodes = Builder<Episode>.CreateListOfSize(5)
|
var episodes = Builder<Episode>.CreateListOfSize(5)
|
||||||
|
|
|
@ -182,7 +182,7 @@
|
||||||
<Compile Include="ParserTests\ParsingServiceTests\MapFixture.cs" />
|
<Compile Include="ParserTests\ParsingServiceTests\MapFixture.cs" />
|
||||||
<Compile Include="ParserTests\SeriesTitleInfoFixture.cs" />
|
<Compile Include="ParserTests\SeriesTitleInfoFixture.cs" />
|
||||||
<Compile Include="Providers\XemProxyFixture.cs" />
|
<Compile Include="Providers\XemProxyFixture.cs" />
|
||||||
<Compile Include="Qualities\QualitySizeRepositoryFixture.cs" />
|
<Compile Include="Qualities\QualityDefinitionRepositoryFixture.cs" />
|
||||||
<Compile Include="Qualities\QualityProfileRepositoryFixture.cs" />
|
<Compile Include="Qualities\QualityProfileRepositoryFixture.cs" />
|
||||||
<Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" />
|
<Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" />
|
||||||
<Compile Include="Qualities\QualityFixture.cs" />
|
<Compile Include="Qualities\QualityFixture.cs" />
|
||||||
|
@ -217,14 +217,14 @@
|
||||||
<Compile Include="TvTests\SeriesServiceTests\UpdateSeriesFixture.cs" />
|
<Compile Include="TvTests\SeriesServiceTests\UpdateSeriesFixture.cs" />
|
||||||
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
|
<Compile Include="UpdateTests\UpdateServiceFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\AcceptableSizeSpecificationFixture.cs" />
|
||||||
<Compile Include="Qualities\QualitySizeServiceFixture.cs" />
|
<Compile Include="Qualities\QualityDefinitionServiceFixture.cs" />
|
||||||
<Compile Include="TvTests\EpisodeProviderTests\EpisodeProviderTest_GetEpisodesByParseResult.cs" />
|
<Compile Include="TvTests\EpisodeProviderTests\EpisodeProviderTest_GetEpisodesByParseResult.cs" />
|
||||||
<Compile Include="FluentTest.cs" />
|
<Compile Include="FluentTest.cs" />
|
||||||
<Compile Include="InstrumentationTests\DatabaseTargetFixture.cs" />
|
<Compile Include="InstrumentationTests\DatabaseTargetFixture.cs" />
|
||||||
<Compile Include="OrganizerTests\GetNewFilenameFixture.cs" />
|
<Compile Include="OrganizerTests\GetNewFilenameFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\MonitoredEpisodeSpecificationFixture.cs" />
|
<Compile Include="DecisionEngineTests\MonitoredEpisodeSpecificationFixture.cs" />
|
||||||
<Compile Include="DecisionEngineTests\DownloadDecisionMakerFixture.cs" />
|
<Compile Include="DecisionEngineTests\DownloadDecisionMakerFixture.cs" />
|
||||||
<Compile Include="TvTests\QualityModelFixture.cs" />
|
<Compile Include="Qualities\QualityModelComparerFixture.cs" />
|
||||||
<Compile Include="RootFolderTests\RootFolderServiceFixture.cs" />
|
<Compile Include="RootFolderTests\RootFolderServiceFixture.cs" />
|
||||||
<Compile Include="HistoryTests\HistoryRepositoryFixture.cs" />
|
<Compile Include="HistoryTests\HistoryRepositoryFixture.cs" />
|
||||||
<Compile Include="MediaFiles\MediaFileServiceTest.cs" />
|
<Compile Include="MediaFiles\MediaFileServiceTest.cs" />
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using FizzWare.NBuilder;
|
using FizzWare.NBuilder;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
|
@ -50,6 +51,10 @@ namespace NzbDrone.Core.Test.OrganizerTests
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
_episodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "DRONE" };
|
_episodeFile = new EpisodeFile { Quality = new QualityModel(Quality.HDTV720p), ReleaseGroup = "DRONE" };
|
||||||
|
|
||||||
|
Mocker.GetMock<IQualityDefinitionService>()
|
||||||
|
.Setup(v => v.Get(Moq.It.IsAny<Quality>()))
|
||||||
|
.Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void GivenProper()
|
private void GivenProper()
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
@ -150,9 +151,9 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test, TestCaseSource("SelfQualityParserCases")]
|
[Test, TestCaseSource("SelfQualityParserCases")]
|
||||||
public void parsing_our_own_quality_enum(Quality quality)
|
public void parsing_our_own_quality_enum_name(Quality quality)
|
||||||
{
|
{
|
||||||
var fileName = String.Format("My series S01E01 [{0}]", quality);
|
var fileName = String.Format("My series S01E01 [{0}]", quality.Name);
|
||||||
var result = Parser.QualityParser.ParseQuality(fileName);
|
var result = Parser.QualityParser.ParseQuality(fileName);
|
||||||
result.Quality.Should().Be(quality);
|
result.Quality.Should().Be(quality);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,25 +4,27 @@ using NzbDrone.Core.Lifecycle;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Qualities
|
namespace NzbDrone.Core.Test.Qualities
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
|
public class QualityDefinitionRepositoryFixture : DbTest<QualityDefinitionRepository, QualityDefinition>
|
||||||
public class QualitySizeRepositoryFixture : DbTest<QualitySizeRepository, QualitySize>
|
|
||||||
{
|
{
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void Setup()
|
public void Setup()
|
||||||
{
|
{
|
||||||
Mocker.SetConstant<IQualitySizeRepository>(Subject);
|
foreach (var qualityDefault in Quality.DefaultQualityDefinitions)
|
||||||
Mocker.Resolve<QualitySizeService>().Handle(new ApplicationStartedEvent());
|
{
|
||||||
|
qualityDefault.Id = 0;
|
||||||
|
Storage.Insert(qualityDefault);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_get_quality_size_by_id()
|
public void should_get_qualitydefinition_by_id()
|
||||||
{
|
{
|
||||||
var size = Subject.GetByQualityId(Quality.Bluray1080p.Id);
|
var size = Subject.GetByQualityId((int)Quality.Bluray1080p);
|
||||||
|
|
||||||
size.Should().NotBeNull();
|
size.Should().NotBeNull();
|
||||||
}
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Moq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Lifecycle;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Qualities
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class QualityDefinitionServiceFixture : CoreTest<QualityDefinitionService>
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void init_should_add_all_definitions()
|
||||||
|
{
|
||||||
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
|
|
||||||
|
Mocker.GetMock<IQualityDefinitionRepository>()
|
||||||
|
.Verify(v => v.Insert(It.IsAny<QualityDefinition>()), Times.Exactly(Quality.All.Count));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void init_should_insert_any_missing_definitions()
|
||||||
|
{
|
||||||
|
Mocker.GetMock<IQualityDefinitionRepository>()
|
||||||
|
.Setup(s => s.All())
|
||||||
|
.Returns(new List<QualityDefinition>
|
||||||
|
{
|
||||||
|
new QualityDefinition(Quality.SDTV) { Weight = 1, MinSize = 0, MaxSize = 100, Id = 20 }
|
||||||
|
});
|
||||||
|
|
||||||
|
Subject.Handle(new ApplicationStartedEvent());
|
||||||
|
|
||||||
|
Mocker.GetMock<IQualityDefinitionRepository>()
|
||||||
|
.Verify(v => v.Insert(It.IsAny<QualityDefinition>()), Times.Exactly(Quality.All.Count - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void init_should_insert_missing_definitions_preserving_weight()
|
||||||
|
{
|
||||||
|
// User moved HDTV1080p to a higher weight.
|
||||||
|
var currentQualities = new List<QualityDefinition>
|
||||||
|
{
|
||||||
|
new QualityDefinition(Quality.SDTV) { Id = 5, Title = "SDTV", Weight = 1, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.WEBDL720p) { Id = 2, Title = "720p WEB-DL", Weight = 2, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.HDTV1080p) { Id = 4, Title = "1080p HDTV", Weight = 3, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.WEBDL1080p) { Id = 8, Title = "1080p WEB-DL", Weight = 4, MinSize=0, MaxSize=100 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expected to insert Bluray720p above HDTV1080p.
|
||||||
|
// Expected to insert Bluray1080p above WEBDL1080p.
|
||||||
|
var addBluray1080p = new List<QualityDefinition>
|
||||||
|
{
|
||||||
|
new QualityDefinition(Quality.SDTV) { Title = "SDTV", Weight = 1, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.HDTV1080p) { Title = "1080p HDTV", Weight = 2, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.WEBDL720p) { Title = "720p WEB-DL", Weight = 3, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.Bluray720p) { Title = "720p BluRay", Weight = 4, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.WEBDL1080p) { Title = "1080p WEB-DL", Weight = 5, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.Bluray1080p) { Title = "1080p BluRay", Weight = 6, MinSize=0, MaxSize=100 }
|
||||||
|
};
|
||||||
|
|
||||||
|
Mocker.GetMock<IQualityDefinitionRepository>()
|
||||||
|
.Setup(v => v.All())
|
||||||
|
.Returns(currentQualities);
|
||||||
|
|
||||||
|
Subject.InsertMissingDefinitions(addBluray1080p);
|
||||||
|
|
||||||
|
Mocker.GetMock<IQualityDefinitionRepository>()
|
||||||
|
.Verify(v => v.Insert(It.Is<QualityDefinition>(p => p.Quality == Quality.Bluray720p && p.Weight == 4)), Times.Once());
|
||||||
|
|
||||||
|
Mocker.GetMock<IQualityDefinitionRepository>()
|
||||||
|
.Verify(v => v.Update(It.Is<QualityDefinition>(p => p.Quality == Quality.WEBDL1080p && p.Weight == 5)), Times.Once());
|
||||||
|
|
||||||
|
Mocker.GetMock<IQualityDefinitionRepository>()
|
||||||
|
.Verify(v => v.Insert(It.Is<QualityDefinition>(p => p.Quality == Quality.Bluray1080p && p.Weight == 6)), Times.Once());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,6 @@
|
||||||
using FluentAssertions;
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using FluentAssertions;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Test.Framework;
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
@ -42,81 +44,21 @@ namespace NzbDrone.Core.Test.Qualities
|
||||||
i.Should().Be(expected);
|
i.Should().Be(expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<Quality> GetDefaultQualities()
|
||||||
[Test]
|
|
||||||
public void Icomparer_greater_test()
|
|
||||||
{
|
{
|
||||||
var first = Quality.DVD;
|
return new List<Quality>
|
||||||
var second = Quality.Bluray1080p;
|
{
|
||||||
|
Quality.SDTV,
|
||||||
second.Should().BeGreaterThan(first);
|
Quality.WEBDL480p,
|
||||||
}
|
Quality.DVD,
|
||||||
|
Quality.HDTV720p,
|
||||||
[Test]
|
Quality.HDTV1080p,
|
||||||
public void Icomparer_lesser()
|
Quality.RAWHD,
|
||||||
{
|
Quality.WEBDL720p,
|
||||||
var first = Quality.DVD;
|
Quality.Bluray720p,
|
||||||
var second = Quality.Bluray1080p;
|
Quality.WEBDL1080p,
|
||||||
|
Quality.Bluray1080p
|
||||||
first.Should().BeLessThan(second);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void equal_operand()
|
|
||||||
{
|
|
||||||
var first = Quality.Bluray1080p;
|
|
||||||
var second = Quality.Bluray1080p;
|
|
||||||
|
|
||||||
(first == second).Should().BeTrue();
|
|
||||||
(first >= second).Should().BeTrue();
|
|
||||||
(first <= second).Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void equal_operand_false()
|
|
||||||
{
|
|
||||||
var first = Quality.Bluray1080p;
|
|
||||||
var second = Quality.Unknown;
|
|
||||||
|
|
||||||
(first == second).Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void not_equal_operand()
|
|
||||||
{
|
|
||||||
var first = Quality.Bluray1080p;
|
|
||||||
var second = Quality.Bluray1080p;
|
|
||||||
|
|
||||||
(first != second).Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void not_equal_operand_false()
|
|
||||||
{
|
|
||||||
var first = Quality.Bluray1080p;
|
|
||||||
var second = Quality.Unknown;
|
|
||||||
|
|
||||||
(first != second).Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void greater_operand()
|
|
||||||
{
|
|
||||||
var first = Quality.DVD;
|
|
||||||
var second = Quality.Bluray1080p;
|
|
||||||
|
|
||||||
(first < second).Should().BeTrue();
|
|
||||||
(first <= second).Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void lesser_operand()
|
|
||||||
{
|
|
||||||
var first = Quality.DVD;
|
|
||||||
var second = Quality.Bluray1080p;
|
|
||||||
|
|
||||||
(second > first).Should().BeTrue();
|
|
||||||
(second >= first).Should().BeTrue();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using FluentAssertions;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
using NzbDrone.Core.Test.Framework;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Test.Qualities
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class QualityModelComparerFixture : CoreTest
|
||||||
|
{
|
||||||
|
public QualityModelComparer Subject { get; set; }
|
||||||
|
|
||||||
|
private void GivenDefaultQualityProfile()
|
||||||
|
{
|
||||||
|
Subject = new QualityModelComparer(new QualityProfile { Allowed = QualityFixture.GetDefaultQualities() });
|
||||||
|
}
|
||||||
|
|
||||||
|
private void GivenCustomQualityProfile()
|
||||||
|
{
|
||||||
|
Subject = new QualityModelComparer(new QualityProfile { Allowed = new List<Quality> { Quality.Bluray720p, Quality.DVD } });
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Icomparer_greater_test()
|
||||||
|
{
|
||||||
|
GivenDefaultQualityProfile();
|
||||||
|
|
||||||
|
var first = new QualityModel(Quality.DVD, true);
|
||||||
|
var second = new QualityModel(Quality.Bluray1080p, true);
|
||||||
|
|
||||||
|
var compare = Subject.Compare(second, first);
|
||||||
|
|
||||||
|
compare.Should().BeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Icomparer_greater_proper()
|
||||||
|
{
|
||||||
|
GivenDefaultQualityProfile();
|
||||||
|
|
||||||
|
var first = new QualityModel(Quality.Bluray1080p, false);
|
||||||
|
var second = new QualityModel(Quality.Bluray1080p, true);
|
||||||
|
|
||||||
|
var compare = Subject.Compare(second, first);
|
||||||
|
|
||||||
|
compare.Should().BeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Icomparer_lesser()
|
||||||
|
{
|
||||||
|
GivenDefaultQualityProfile();
|
||||||
|
|
||||||
|
var first = new QualityModel(Quality.DVD, true);
|
||||||
|
var second = new QualityModel(Quality.Bluray1080p, true);
|
||||||
|
|
||||||
|
var compare = Subject.Compare(first, second);
|
||||||
|
|
||||||
|
compare.Should().BeLessThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Icomparer_lesser_proper()
|
||||||
|
{
|
||||||
|
GivenDefaultQualityProfile();
|
||||||
|
|
||||||
|
var first = new QualityModel(Quality.DVD, false);
|
||||||
|
var second = new QualityModel(Quality.DVD, true);
|
||||||
|
|
||||||
|
var compare = Subject.Compare(first, second);
|
||||||
|
|
||||||
|
compare.Should().BeLessThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Icomparer_greater_custom_order()
|
||||||
|
{
|
||||||
|
GivenCustomQualityProfile();
|
||||||
|
|
||||||
|
var first = new QualityModel(Quality.DVD, true);
|
||||||
|
var second = new QualityModel(Quality.Bluray720p, true);
|
||||||
|
|
||||||
|
var compare = Subject.Compare(first, second);
|
||||||
|
|
||||||
|
compare.Should().BeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Icomparer_missing_custom_order()
|
||||||
|
{
|
||||||
|
GivenCustomQualityProfile();
|
||||||
|
|
||||||
|
var first = new QualityModel(Quality.Bluray720p, true);
|
||||||
|
var second = new QualityModel(Quality.Bluray1080p, true);
|
||||||
|
|
||||||
|
var compare = Subject.Compare(first, second);
|
||||||
|
|
||||||
|
compare.Should().BeGreaterThan(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void Icomparer_missing_both_custom_order()
|
||||||
|
{
|
||||||
|
GivenCustomQualityProfile();
|
||||||
|
|
||||||
|
var first = new QualityModel(Quality.SDTV, true);
|
||||||
|
var second = new QualityModel(Quality.Bluray1080p, true);
|
||||||
|
|
||||||
|
var compare = Subject.Compare(first, second);
|
||||||
|
|
||||||
|
compare.Should().Be(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,7 +7,6 @@ using NzbDrone.Core.Test.Framework;
|
||||||
namespace NzbDrone.Core.Test.Qualities
|
namespace NzbDrone.Core.Test.Qualities
|
||||||
{
|
{
|
||||||
[TestFixture]
|
[TestFixture]
|
||||||
|
|
||||||
public class QualityProfileRepositoryFixture : DbTest<QualityProfileRepository, QualityProfile>
|
public class QualityProfileRepositoryFixture : DbTest<QualityProfileRepository, QualityProfile>
|
||||||
{
|
{
|
||||||
[Test]
|
[Test]
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using Moq;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Core.Lifecycle;
|
|
||||||
using NzbDrone.Core.Qualities;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.Qualities
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
|
|
||||||
public class QualitySizeServiceFixture : CoreTest<QualitySizeService>
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void Init_should_add_all_sizes()
|
|
||||||
{
|
|
||||||
Subject.Handle(new ApplicationStartedEvent());
|
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeRepository>()
|
|
||||||
.Verify(v => v.Insert(It.IsAny<QualitySize>()), Times.Exactly(Quality.All().Count));
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Init_should_insert_any_missing_sizes()
|
|
||||||
{
|
|
||||||
Mocker.GetMock<IQualitySizeRepository>()
|
|
||||||
.Setup(s => s.All())
|
|
||||||
.Returns(new List<QualitySize>
|
|
||||||
{
|
|
||||||
new QualitySize { QualityId = 1, Name = "SDTV", MinSize = 0, MaxSize = 100 }
|
|
||||||
});
|
|
||||||
|
|
||||||
Subject.Handle(new ApplicationStartedEvent());
|
|
||||||
|
|
||||||
Mocker.GetMock<IQualitySizeRepository>()
|
|
||||||
.Verify(v => v.Insert(It.IsAny<QualitySize>()), Times.Exactly(Quality.All().Count - 1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
using FluentAssertions;
|
|
||||||
using NUnit.Framework;
|
|
||||||
using NzbDrone.Core.Qualities;
|
|
||||||
using NzbDrone.Core.Tv;
|
|
||||||
using NzbDrone.Core.Test.Framework;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Test.TvTests
|
|
||||||
{
|
|
||||||
[TestFixture]
|
|
||||||
|
|
||||||
public class QualityModelFixture : CoreTest
|
|
||||||
{
|
|
||||||
[Test]
|
|
||||||
public void Icomparer_greater_test()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.DVD, true);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
|
|
||||||
second.Should().BeGreaterThan(first);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Icomparer_greater_proper()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.Bluray1080p, false);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
|
|
||||||
second.Should().BeGreaterThan(first);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Icomparer_lesser()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.DVD, true);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
|
|
||||||
first.Should().BeLessThan(second);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void Icomparer_lesser_proper()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.DVD, false);
|
|
||||||
var second = new QualityModel(Quality.DVD, true);
|
|
||||||
|
|
||||||
first.Should().BeLessThan(second);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void equal_operand()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
|
|
||||||
(first == second).Should().BeTrue();
|
|
||||||
(first >= second).Should().BeTrue();
|
|
||||||
(first <= second).Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void equal_operand_false()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
var second = new QualityModel(Quality.Unknown, true);
|
|
||||||
|
|
||||||
(first == second).Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void equal_operand_false_proper()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, false);
|
|
||||||
|
|
||||||
(first == second).Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void not_equal_operand()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
|
|
||||||
(first != second).Should().BeFalse();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void not_equal_operand_false()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
var second = new QualityModel(Quality.Unknown, true);
|
|
||||||
|
|
||||||
(first != second).Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void not_equal_operand_false_proper()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, false);
|
|
||||||
|
|
||||||
(first != second).Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void greater_operand()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.DVD, true);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
|
|
||||||
(first < second).Should().BeTrue();
|
|
||||||
(first <= second).Should().BeTrue();
|
|
||||||
}
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void lesser_operand()
|
|
||||||
{
|
|
||||||
var first = new QualityModel(Quality.DVD, true);
|
|
||||||
var second = new QualityModel(Quality.Bluray1080p, true);
|
|
||||||
|
|
||||||
(second > first).Should().BeTrue();
|
|
||||||
(second >= first).Should().BeTrue();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Blacklisting
|
namespace NzbDrone.Core.Blacklisting
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
using Marr.Data.Converters;
|
using Marr.Data.Converters;
|
||||||
using Marr.Data.Mapping;
|
using Marr.Data.Mapping;
|
||||||
using NzbDrone.Core.Qualities;
|
using NzbDrone.Core.Qualities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Datastore.Converters
|
namespace NzbDrone.Core.Datastore.Converters
|
||||||
{
|
{
|
||||||
|
@ -26,7 +28,7 @@ namespace NzbDrone.Core.Datastore.Converters
|
||||||
|
|
||||||
public object ToDB(object clrValue)
|
public object ToDB(object clrValue)
|
||||||
{
|
{
|
||||||
if(clrValue == null) return 0;
|
if(clrValue == DBNull.Value) return 0;
|
||||||
|
|
||||||
if(clrValue as Quality == null)
|
if(clrValue as Quality == null)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
using System;
|
||||||
|
using Marr.Data.Converters;
|
||||||
|
using Marr.Data.Mapping;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Converters
|
||||||
|
{
|
||||||
|
public class QualityListConverter : IConverter
|
||||||
|
{
|
||||||
|
public object FromDB(ConverterContext context)
|
||||||
|
{
|
||||||
|
if (context.DbValue == DBNull.Value)
|
||||||
|
{
|
||||||
|
return DBNull.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
var val = Convert.ToString(context.DbValue);
|
||||||
|
|
||||||
|
var qualityList = Json.Deserialize<List<int>>(val).ConvertAll(Quality.FindById);
|
||||||
|
|
||||||
|
return qualityList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object FromDB(ColumnMap map, object dbValue)
|
||||||
|
{
|
||||||
|
return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ToDB(object clrValue)
|
||||||
|
{
|
||||||
|
if (clrValue == DBNull.Value) return null;
|
||||||
|
|
||||||
|
var qualityList = clrValue as List<Quality>;
|
||||||
|
|
||||||
|
if (qualityList == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Can only store a list of qualities in this database column.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var intList = qualityList.ConvertAll(v => v.Id);
|
||||||
|
|
||||||
|
return intList.ToJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type DbType
|
||||||
|
{
|
||||||
|
get { return typeof(string); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using Marr.Data.Converters;
|
||||||
|
using Marr.Data.Mapping;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Converters
|
||||||
|
{
|
||||||
|
public class QualityModelConverter : IConverter
|
||||||
|
{
|
||||||
|
public object FromDB(ConverterContext context)
|
||||||
|
{
|
||||||
|
if (context.DbValue == DBNull.Value)
|
||||||
|
{
|
||||||
|
return new QualityModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
var val = Convert.ToString(context.DbValue);
|
||||||
|
|
||||||
|
var jsonObject = Json.Deserialize<Dictionary<string, object>>(val);
|
||||||
|
|
||||||
|
return new QualityModel((Quality)Convert.ToInt32(jsonObject["id"]), Convert.ToBoolean(jsonObject["proper"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public object FromDB(ColumnMap map, object dbValue)
|
||||||
|
{
|
||||||
|
return FromDB(new ConverterContext { ColumnMap = map, DbValue = dbValue });
|
||||||
|
}
|
||||||
|
|
||||||
|
public object ToDB(object clrValue)
|
||||||
|
{
|
||||||
|
if (clrValue == DBNull.Value)
|
||||||
|
clrValue = new QualityModel();
|
||||||
|
|
||||||
|
var qualityModel = clrValue as QualityModel;
|
||||||
|
|
||||||
|
if (qualityModel == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Can only store a QualityModel in this database column.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var jsonObject = new Dictionary<string, object>();
|
||||||
|
jsonObject["id"] = (int)qualityModel.Quality;
|
||||||
|
jsonObject["proper"] = qualityModel.Proper;
|
||||||
|
|
||||||
|
return jsonObject.ToJson();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Type DbType
|
||||||
|
{
|
||||||
|
get { return typeof(string); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(36)]
|
||||||
|
public class update_with_quality_converters : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Execute.WithConnection(ConvertQualityProfiles);
|
||||||
|
|
||||||
|
Execute.WithConnection(ConvertQualityModels);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConvertQualityProfiles(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
var qualityListConverter = new NzbDrone.Core.Datastore.Converters.QualityListConverter();
|
||||||
|
|
||||||
|
// Convert 'Allowed' column in QualityProfiles from Json List<object> to Json List<int> (int = Quality)
|
||||||
|
using (IDbCommand qualityProfileCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
qualityProfileCmd.Transaction = tran;
|
||||||
|
qualityProfileCmd.CommandText = @"SELECT Id, Allowed FROM QualityProfiles";
|
||||||
|
using (IDataReader qualityProfileReader = qualityProfileCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (qualityProfileReader.Read())
|
||||||
|
{
|
||||||
|
var id = qualityProfileReader.GetInt32(0);
|
||||||
|
var allowedJson = qualityProfileReader.GetString(1);
|
||||||
|
|
||||||
|
var allowed = Json.Deserialize<List<Quality>>(allowedJson);
|
||||||
|
|
||||||
|
var allowedNewJson = qualityListConverter.ToDB(allowed);
|
||||||
|
|
||||||
|
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateCmd.Transaction = tran;
|
||||||
|
updateCmd.CommandText = "UPDATE QualityProfiles SET Allowed = ? WHERE Id = ?";
|
||||||
|
updateCmd.AddParameter(allowedNewJson);
|
||||||
|
updateCmd.AddParameter(id);
|
||||||
|
|
||||||
|
updateCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConvertQualityModels(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
// Converts the QualityModel JSON objects to their new format (only storing the QualityId instead of the entire object)
|
||||||
|
ConvertQualityModel(conn, tran, "Blacklist");
|
||||||
|
ConvertQualityModel(conn, tran, "EpisodeFiles");
|
||||||
|
ConvertQualityModel(conn, tran, "History");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConvertQualityModel(IDbConnection conn, IDbTransaction tran, string tableName)
|
||||||
|
{
|
||||||
|
var qualityModelConverter = new NzbDrone.Core.Datastore.Converters.QualityModelConverter();
|
||||||
|
|
||||||
|
using (IDbCommand qualityModelCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
qualityModelCmd.Transaction = tran;
|
||||||
|
qualityModelCmd.CommandText = @"SELECT Id, Quality FROM " + tableName;
|
||||||
|
using (IDataReader qualityModelReader = qualityModelCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (qualityModelReader.Read())
|
||||||
|
{
|
||||||
|
var id = qualityModelReader.GetInt32(0);
|
||||||
|
var qualityJson = qualityModelReader.GetString(1);
|
||||||
|
|
||||||
|
var quality = Json.Deserialize<QualityModel>(qualityJson);
|
||||||
|
|
||||||
|
var qualityNewJson = qualityModelConverter.ToDB(quality);
|
||||||
|
|
||||||
|
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateCmd.Transaction = tran;
|
||||||
|
updateCmd.CommandText = "UPDATE " + tableName + " SET Quality = ? WHERE Id = ?";
|
||||||
|
updateCmd.AddParameter(qualityNewJson);
|
||||||
|
updateCmd.AddParameter(id);
|
||||||
|
|
||||||
|
updateCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
using FluentMigrator;
|
||||||
|
using NzbDrone.Core.Datastore.Migration.Framework;
|
||||||
|
using System.Data;
|
||||||
|
using System.Linq;
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Common.Serializer;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Datastore.Migration
|
||||||
|
{
|
||||||
|
[Migration(37)]
|
||||||
|
public class add_configurable_qualities : NzbDroneMigrationBase
|
||||||
|
{
|
||||||
|
protected override void MainDbUpgrade()
|
||||||
|
{
|
||||||
|
Create.TableForModel("QualityDefinitions")
|
||||||
|
.WithColumn("Quality").AsInt32().Unique()
|
||||||
|
.WithColumn("Title").AsString().Unique()
|
||||||
|
.WithColumn("Weight").AsInt32().Unique()
|
||||||
|
.WithColumn("MinSize").AsInt32()
|
||||||
|
.WithColumn("MaxSize").AsInt32();
|
||||||
|
|
||||||
|
Execute.WithConnection(ConvertQualities);
|
||||||
|
|
||||||
|
Delete.Table("QualitySizes");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ConvertQualities(IDbConnection conn, IDbTransaction tran)
|
||||||
|
{
|
||||||
|
// Convert QualitySizes to a more generic QualityDefinitions table.
|
||||||
|
using (IDbCommand qualitySizeCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
qualitySizeCmd.Transaction = tran;
|
||||||
|
qualitySizeCmd.CommandText = @"SELECT QualityId, MinSize, MaxSize FROM QualitySizes";
|
||||||
|
using (IDataReader qualitySizeReader = qualitySizeCmd.ExecuteReader())
|
||||||
|
{
|
||||||
|
while (qualitySizeReader.Read())
|
||||||
|
{
|
||||||
|
var qualityId = qualitySizeReader.GetInt32(0);
|
||||||
|
var minSize = qualitySizeReader.GetInt32(1);
|
||||||
|
var maxSize = qualitySizeReader.GetInt32(2);
|
||||||
|
|
||||||
|
var defaultConfig = Quality.DefaultQualityDefinitions.Single(p => (int)p.Quality == qualityId);
|
||||||
|
|
||||||
|
using (IDbCommand updateCmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
updateCmd.Transaction = tran;
|
||||||
|
updateCmd.CommandText = "INSERT INTO QualityDefinitions (Quality, Title, Weight, MinSize, MaxSize) VALUES (?, ?, ?, ?, ?)";
|
||||||
|
updateCmd.AddParameter(qualityId);
|
||||||
|
updateCmd.AddParameter(defaultConfig.Title);
|
||||||
|
updateCmd.AddParameter(defaultConfig.Weight);
|
||||||
|
updateCmd.AddParameter(minSize);
|
||||||
|
updateCmd.AddParameter(maxSize);
|
||||||
|
|
||||||
|
updateCmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,5 +10,11 @@ namespace NzbDrone.Core.Datastore.Migration.Framework
|
||||||
return expressionRoot.Table(name).WithColumn("Id").AsInt32().PrimaryKey().Identity();
|
return expressionRoot.Table(name).WithColumn("Id").AsInt32().PrimaryKey().Identity();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void AddParameter(this System.Data.IDbCommand command, object value)
|
||||||
|
{
|
||||||
|
var parameter = command.CreateParameter();
|
||||||
|
parameter.Value = value;
|
||||||
|
command.Parameters.Add(parameter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -60,7 +60,7 @@ namespace NzbDrone.Core.Datastore
|
||||||
|
|
||||||
Mapper.Entity<QualityProfile>().RegisterModel("QualityProfiles");
|
Mapper.Entity<QualityProfile>().RegisterModel("QualityProfiles");
|
||||||
|
|
||||||
Mapper.Entity<QualitySize>().RegisterModel("QualitySizes");
|
Mapper.Entity<QualityDefinition>().RegisterModel("QualityDefinitions");
|
||||||
|
|
||||||
Mapper.Entity<Log>().RegisterModel("Logs");
|
Mapper.Entity<Log>().RegisterModel("Logs");
|
||||||
|
|
||||||
|
@ -81,6 +81,8 @@ namespace NzbDrone.Core.Datastore
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(Quality), new QualityIntConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(Quality), new QualityIntConverter());
|
||||||
|
MapRepository.Instance.RegisterTypeConverter(typeof(List<Quality>), new QualityListConverter());
|
||||||
|
MapRepository.Instance.RegisterTypeConverter(typeof(QualityModel), new QualityModelConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(Dictionary<string, string>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(Dictionary<string, string>), new EmbeddedDocumentConverter());
|
||||||
MapRepository.Instance.RegisterTypeConverter(typeof(List<int>), new EmbeddedDocumentConverter());
|
MapRepository.Instance.RegisterTypeConverter(typeof(List<int>), new EmbeddedDocumentConverter());
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
{
|
{
|
||||||
public interface IQualityUpgradableSpecification
|
public interface IQualityUpgradableSpecification
|
||||||
{
|
{
|
||||||
bool IsUpgradable(QualityModel currentQuality, QualityModel newQuality = null);
|
bool IsUpgradable(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null);
|
||||||
bool CutoffNotMet(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null);
|
bool CutoffNotMet(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null);
|
||||||
bool IsProperUpgrade(QualityModel currentQuality, QualityModel newQuality);
|
bool IsProperUpgrade(QualityModel currentQuality, QualityModel newQuality);
|
||||||
}
|
}
|
||||||
|
@ -20,11 +20,12 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsUpgradable(QualityModel currentQuality, QualityModel newQuality = null)
|
public bool IsUpgradable(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
||||||
{
|
{
|
||||||
if (newQuality != null)
|
if (newQuality != null)
|
||||||
{
|
{
|
||||||
if (currentQuality >= newQuality)
|
int compare = new QualityModelComparer(profile).Compare(newQuality, currentQuality);
|
||||||
|
if (compare <= 0)
|
||||||
{
|
{
|
||||||
_logger.Trace("existing item has better or equal quality. skipping");
|
_logger.Trace("existing item has better or equal quality. skipping");
|
||||||
return false;
|
return false;
|
||||||
|
@ -41,7 +42,9 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
|
|
||||||
public bool CutoffNotMet(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
public bool CutoffNotMet(QualityProfile profile, QualityModel currentQuality, QualityModel newQuality = null)
|
||||||
{
|
{
|
||||||
if (currentQuality.Quality >= profile.Cutoff)
|
int compare = new QualityModelComparer(profile).Compare(currentQuality.Quality, profile.Cutoff);
|
||||||
|
|
||||||
|
if (compare >= 0)
|
||||||
{
|
{
|
||||||
if (newQuality != null && IsProperUpgrade(currentQuality, newQuality))
|
if (newQuality != null && IsProperUpgrade(currentQuality, newQuality))
|
||||||
{
|
{
|
||||||
|
@ -57,7 +60,9 @@ namespace NzbDrone.Core.DecisionEngine
|
||||||
|
|
||||||
public bool IsProperUpgrade(QualityModel currentQuality, QualityModel newQuality)
|
public bool IsProperUpgrade(QualityModel currentQuality, QualityModel newQuality)
|
||||||
{
|
{
|
||||||
if (currentQuality.Quality == newQuality.Quality && newQuality > currentQuality)
|
int compare = newQuality.Proper.CompareTo(currentQuality.Proper);
|
||||||
|
|
||||||
|
if (currentQuality.Quality == newQuality.Quality && compare > 0)
|
||||||
{
|
{
|
||||||
_logger.Trace("New quality is a proper for existing quality");
|
_logger.Trace("New quality is a proper for existing quality");
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -9,13 +9,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
public class AcceptableSizeSpecification : IDecisionEngineSpecification
|
public class AcceptableSizeSpecification : IDecisionEngineSpecification
|
||||||
{
|
{
|
||||||
private readonly IQualitySizeService _qualityTypeProvider;
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
private readonly IEpisodeService _episodeService;
|
private readonly IEpisodeService _episodeService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public AcceptableSizeSpecification(IQualitySizeService qualityTypeProvider, IEpisodeService episodeService, Logger logger)
|
public AcceptableSizeSpecification(IQualityDefinitionService qualityDefinitionService, IEpisodeService episodeService, Logger logger)
|
||||||
{
|
{
|
||||||
_qualityTypeProvider = qualityTypeProvider;
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
_episodeService = episodeService;
|
_episodeService = episodeService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
@ -44,15 +44,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var qualityType = _qualityTypeProvider.Get(quality.Id);
|
var qualityDefinition = _qualityDefinitionService.Get(quality);
|
||||||
|
|
||||||
if (qualityType.MaxSize == 0)
|
if (qualityDefinition.MaxSize == 0)
|
||||||
{
|
{
|
||||||
_logger.Trace("Max size is 0 (unlimited) - skipping check.");
|
_logger.Trace("Max size is 0 (unlimited) - skipping check.");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxSize = qualityType.MaxSize.Megabytes();
|
var maxSize = qualityDefinition.MaxSize.Megabytes();
|
||||||
|
|
||||||
//Multiply maxSize by Series.Runtime
|
//Multiply maxSize by Series.Runtime
|
||||||
maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;
|
maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;
|
||||||
|
|
|
@ -4,6 +4,8 @@ using NLog;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
|
@ -44,7 +46,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
private bool IsInQueue(RemoteEpisode newEpisode, IEnumerable<RemoteEpisode> queue)
|
private bool IsInQueue(RemoteEpisode newEpisode, IEnumerable<RemoteEpisode> queue)
|
||||||
{
|
{
|
||||||
var matchingSeries = queue.Where(q => q.Series.Id == newEpisode.Series.Id);
|
var matchingSeries = queue.Where(q => q.Series.Id == newEpisode.Series.Id);
|
||||||
var matchingSeriesAndQuality = matchingSeries.Where(q => q.ParsedEpisodeInfo.Quality >= newEpisode.ParsedEpisodeInfo.Quality);
|
var matchingSeriesAndQuality = matchingSeries.Where(q => new QualityModelComparer(q.Series.QualityProfile).Compare(q.ParsedEpisodeInfo.Quality, newEpisode.ParsedEpisodeInfo.Quality) >= 0);
|
||||||
|
|
||||||
return matchingSeriesAndQuality.Any(q => q.Episodes.Select(e => e.Id).Intersect(newEpisode.Episodes.Select(e => e.Id)).Any());
|
return matchingSeriesAndQuality.Any(q => q.Episodes.Select(e => e.Id).Intersect(newEpisode.Episodes.Select(e => e.Id)).Any());
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||||
if (bestQualityInHistory != null)
|
if (bestQualityInHistory != null)
|
||||||
{
|
{
|
||||||
_logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory);
|
_logger.Trace("Comparing history quality with report. History is {0}", bestQualityInHistory);
|
||||||
if (!_qualityUpgradableSpecification.IsUpgradable(bestQualityInHistory, subject.ParsedEpisodeInfo.Quality))
|
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.QualityProfile, bestQualityInHistory, subject.ParsedEpisodeInfo.Quality))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||||
{
|
{
|
||||||
_logger.Trace("Comparing file quality with report. Existing file is {0}", file.Quality);
|
_logger.Trace("Comparing file quality with report. Existing file is {0}", file.Quality);
|
||||||
|
|
||||||
if (!_qualityUpgradableSpecification.IsUpgradable(file.Quality, subject.ParsedEpisodeInfo.Quality))
|
if (!_qualityUpgradableSpecification.IsUpgradable(subject.Series.QualityProfile, file.Quality, subject.ParsedEpisodeInfo.Quality))
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download
|
namespace NzbDrone.Core.Download
|
||||||
{
|
{
|
||||||
|
@ -16,7 +18,7 @@ namespace NzbDrone.Core.Download
|
||||||
private readonly IDownloadService _downloadService;
|
private readonly IDownloadService _downloadService;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
public DownloadApprovedReports(IDownloadService downloadService, Logger logger)
|
public DownloadApprovedReports(IDownloadService downloadService, Logger logger)
|
||||||
{
|
{
|
||||||
_downloadService = downloadService;
|
_downloadService = downloadService;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
|
@ -57,11 +59,13 @@ 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())
|
||||||
.OrderByDescending(c => c.RemoteEpisode.ParsedEpisodeInfo.Quality)
|
.GroupBy(c => c.RemoteEpisode.Series.Id, (i,s) => s
|
||||||
.ThenBy(c => c.RemoteEpisode.Episodes.Select(e => e.EpisodeNumber).MinOrDefault())
|
.OrderByDescending(c => c.RemoteEpisode.ParsedEpisodeInfo.Quality, new QualityModelComparer(s.First().RemoteEpisode.Series.QualityProfile))
|
||||||
.ThenBy(c => c.RemoteEpisode.Release.Size.Round(200.Megabytes()) / c.RemoteEpisode.Episodes.Count)
|
.ThenBy(c => c.RemoteEpisode.Episodes.Select(e => e.EpisodeNumber).MinOrDefault())
|
||||||
.ThenBy(c => c.RemoteEpisode.Release.Age)
|
.ThenBy(c => c.RemoteEpisode.Release.Size.Round(200.Megabytes()) / c.RemoteEpisode.Episodes.Count)
|
||||||
.ToList();
|
.ThenBy(c => c.RemoteEpisode.Release.Age))
|
||||||
|
.SelectMany(c => c)
|
||||||
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Common.Messaging;
|
using NzbDrone.Common.Messaging;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Download
|
namespace NzbDrone.Core.Download
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.History
|
namespace NzbDrone.Core.History
|
||||||
|
|
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||||
using Marr.Data.QGen;
|
using Marr.Data.QGen;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.History
|
namespace NzbDrone.Core.History
|
||||||
|
|
|
@ -6,6 +6,7 @@ using NzbDrone.Core.Datastore;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.History
|
namespace NzbDrone.Core.History
|
||||||
|
|
|
@ -10,6 +10,7 @@ using NzbDrone.Core.MediaFiles.Commands;
|
||||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||||
using NzbDrone.Core.Messaging.Commands;
|
using NzbDrone.Core.Messaging.Commands;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles
|
namespace NzbDrone.Core.MediaFiles
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles
|
namespace NzbDrone.Core.MediaFiles
|
||||||
|
|
|
@ -7,6 +7,8 @@ using NzbDrone.Common;
|
||||||
using NzbDrone.Common.Disk;
|
using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
|
@ -40,8 +42,11 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
public List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownload = false)
|
public List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownload = false)
|
||||||
{
|
{
|
||||||
var qualifiedImports = decisions.Where(c => c.Approved)
|
var qualifiedImports = decisions.Where(c => c.Approved)
|
||||||
.OrderByDescending(c => c.LocalEpisode.Quality)
|
.GroupBy(c => c.LocalEpisode.Series.Id, (i, s) => s
|
||||||
.ThenByDescending(c => c.LocalEpisode.Size);
|
.OrderByDescending(c => c.LocalEpisode.Quality, new QualityModelComparer(s.First().LocalEpisode.Series.QualityProfile))
|
||||||
|
.ThenByDescending(c => c.LocalEpisode.Size))
|
||||||
|
.SelectMany(c => c)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
var imported = new List<ImportDecision>();
|
var imported = new List<ImportDecision>();
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ using NzbDrone.Common.Disk;
|
||||||
using NzbDrone.Core.DecisionEngine;
|
using NzbDrone.Core.DecisionEngine;
|
||||||
using NzbDrone.Core.Parser;
|
using NzbDrone.Core.Parser;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +61,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||||
|
|
||||||
if (parsedEpisode != null)
|
if (parsedEpisode != null)
|
||||||
{
|
{
|
||||||
if (quality != null && quality > parsedEpisode.Quality)
|
if (quality != null && new QualityModelComparer(parsedEpisode.Series.QualityProfile).Compare(quality, parsedEpisode.Quality) > 0)
|
||||||
{
|
{
|
||||||
_logger.Trace("Using quality from folder: {0}", quality);
|
_logger.Trace("Using quality from folder: {0}", quality);
|
||||||
parsedEpisode.Quality = quality;
|
parsedEpisode.Quality = quality;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Core.Parser.Model;
|
using NzbDrone.Core.Parser.Model;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||||
{
|
{
|
||||||
|
@ -17,7 +19,8 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||||
|
|
||||||
public bool IsSatisfiedBy(LocalEpisode localEpisode)
|
public bool IsSatisfiedBy(LocalEpisode localEpisode)
|
||||||
{
|
{
|
||||||
if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && e.EpisodeFile.Value.Quality > localEpisode.Quality))
|
var qualityComparer = new QualityModelComparer(localEpisode.Series.QualityProfile);
|
||||||
|
if (localEpisode.Episodes.Any(e => e.EpisodeFileId != 0 && qualityComparer.Compare(e.EpisodeFile.Value.Quality, localEpisode.Quality) > 0))
|
||||||
{
|
{
|
||||||
_logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path);
|
_logger.Trace("This file isn't an upgrade for all episodes. Skipping {0}", localEpisode.Path);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -5,6 +5,7 @@ using NLog;
|
||||||
using NzbDrone.Core.Download;
|
using NzbDrone.Core.Download;
|
||||||
using NzbDrone.Core.MediaFiles.Events;
|
using NzbDrone.Core.MediaFiles.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Notifications
|
namespace NzbDrone.Core.Notifications
|
||||||
|
|
|
@ -145,6 +145,8 @@
|
||||||
<Compile Include="Datastore\Converters\BooleanIntConverter.cs" />
|
<Compile Include="Datastore\Converters\BooleanIntConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\ProviderSettingConverter.cs" />
|
<Compile Include="Datastore\Converters\ProviderSettingConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\QualityIntConverter.cs" />
|
<Compile Include="Datastore\Converters\QualityIntConverter.cs" />
|
||||||
|
<Compile Include="Datastore\Converters\QualityListConverter.cs" />
|
||||||
|
<Compile Include="Datastore\Converters\QualityModelConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\Int32Converter.cs" />
|
<Compile Include="Datastore\Converters\Int32Converter.cs" />
|
||||||
<Compile Include="Datastore\Converters\EmbeddedDocumentConverter.cs" />
|
<Compile Include="Datastore\Converters\EmbeddedDocumentConverter.cs" />
|
||||||
<Compile Include="Datastore\Converters\UtcConverter.cs" />
|
<Compile Include="Datastore\Converters\UtcConverter.cs" />
|
||||||
|
@ -191,6 +193,8 @@
|
||||||
<Compile Include="Datastore\Migration\033_add_api_key_to_pushover.cs" />
|
<Compile Include="Datastore\Migration\033_add_api_key_to_pushover.cs" />
|
||||||
<Compile Include="Datastore\Migration\034_remove_series_contraints.cs" />
|
<Compile Include="Datastore\Migration\034_remove_series_contraints.cs" />
|
||||||
<Compile Include="Datastore\Migration\035_add_series_folder_format_to_naming_config.cs" />
|
<Compile Include="Datastore\Migration\035_add_series_folder_format_to_naming_config.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\036_update_with_quality_converters.cs" />
|
||||||
|
<Compile Include="Datastore\Migration\037_add_configurable_qualities.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationController.cs" />
|
||||||
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
||||||
|
@ -456,12 +460,13 @@
|
||||||
<Compile Include="Parser\Parser.cs" />
|
<Compile Include="Parser\Parser.cs" />
|
||||||
<Compile Include="Parser\ParsingService.cs" />
|
<Compile Include="Parser\ParsingService.cs" />
|
||||||
<Compile Include="Parser\QualityParser.cs" />
|
<Compile Include="Parser\QualityParser.cs" />
|
||||||
|
<Compile Include="Qualities\QualityModelComparer.cs" />
|
||||||
<Compile Include="Rest\JsonNetSerializer.cs" />
|
<Compile Include="Rest\JsonNetSerializer.cs" />
|
||||||
<Compile Include="RootFolders\RootFolderRepository.cs" />
|
<Compile Include="RootFolders\RootFolderRepository.cs" />
|
||||||
<Compile Include="ThingiProvider\ConfigContractNotFoundException.cs" />
|
<Compile Include="ThingiProvider\ConfigContractNotFoundException.cs" />
|
||||||
<Compile Include="ThingiProvider\IProvider.cs" />
|
<Compile Include="ThingiProvider\IProvider.cs" />
|
||||||
<Compile Include="Qualities\QualityProfileInUseException.cs" />
|
<Compile Include="Qualities\QualityProfileInUseException.cs" />
|
||||||
<Compile Include="Qualities\QualitySizeRepository.cs" />
|
<Compile Include="Qualities\QualityDefinitionRepository.cs" />
|
||||||
<Compile Include="Qualities\QualityProfileRepository.cs" />
|
<Compile Include="Qualities\QualityProfileRepository.cs" />
|
||||||
<Compile Include="Queue\Queue.cs" />
|
<Compile Include="Queue\Queue.cs" />
|
||||||
<Compile Include="Queue\UpdateQueueEvent.cs" />
|
<Compile Include="Queue\UpdateQueueEvent.cs" />
|
||||||
|
@ -489,7 +494,7 @@
|
||||||
<Compile Include="Tv\Commands\RefreshSeriesCommand.cs" />
|
<Compile Include="Tv\Commands\RefreshSeriesCommand.cs" />
|
||||||
<Compile Include="Tv\RefreshEpisodeService.cs" />
|
<Compile Include="Tv\RefreshEpisodeService.cs" />
|
||||||
<Compile Include="Tv\SeriesRepository.cs" />
|
<Compile Include="Tv\SeriesRepository.cs" />
|
||||||
<Compile Include="Tv\QualityModel.cs" />
|
<Compile Include="Qualities\QualityModel.cs" />
|
||||||
<Compile Include="Download\Clients\Sabnzbd\SabAddResponse.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\SabAddResponse.cs" />
|
||||||
<Compile Include="Download\Clients\Sabnzbd\SabHistoryItem.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\SabHistoryItem.cs" />
|
||||||
<Compile Include="Download\Clients\Sabnzbd\SabHistory.cs" />
|
<Compile Include="Download\Clients\Sabnzbd\SabHistory.cs" />
|
||||||
|
@ -575,7 +580,7 @@
|
||||||
<Compile Include="Qualities\QualityProfileService.cs">
|
<Compile Include="Qualities\QualityProfileService.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Qualities\QualitySizeService.cs">
|
<Compile Include="Qualities\QualityDefinitionService.cs">
|
||||||
<SubType>Code</SubType>
|
<SubType>Code</SubType>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="RootFolders\UnmappedFolder.cs" />
|
<Compile Include="RootFolders\UnmappedFolder.cs" />
|
||||||
|
@ -597,7 +602,7 @@
|
||||||
<Compile Include="Tv\Episode.cs" />
|
<Compile Include="Tv\Episode.cs" />
|
||||||
<Compile Include="Instrumentation\Log.cs" />
|
<Compile Include="Instrumentation\Log.cs" />
|
||||||
<Compile Include="History\History.cs" />
|
<Compile Include="History\History.cs" />
|
||||||
<Compile Include="Qualities\QualitySize.cs" />
|
<Compile Include="Qualities\QualityDefinition.cs" />
|
||||||
<Compile Include="Qualities\QualityProfile.cs" />
|
<Compile Include="Qualities\QualityProfile.cs" />
|
||||||
<Compile Include="RootFolders\RootFolder.cs" />
|
<Compile Include="RootFolders\RootFolder.cs" />
|
||||||
<Compile Include="Tv\Series.cs" />
|
<Compile Include="Tv\Series.cs" />
|
||||||
|
|
|
@ -6,6 +6,7 @@ using System.Text.RegularExpressions;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Core.MediaFiles;
|
using NzbDrone.Core.MediaFiles;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Organizer
|
namespace NzbDrone.Core.Organizer
|
||||||
|
@ -22,6 +23,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
public class FileNameBuilder : IBuildFileNames
|
public class FileNameBuilder : IBuildFileNames
|
||||||
{
|
{
|
||||||
private readonly INamingConfigService _namingConfigService;
|
private readonly INamingConfigService _namingConfigService;
|
||||||
|
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||||
private readonly ICached<EpisodeFormat> _patternCache;
|
private readonly ICached<EpisodeFormat> _patternCache;
|
||||||
private readonly Logger _logger;
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
@ -43,10 +45,12 @@ namespace NzbDrone.Core.Organizer
|
||||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
public FileNameBuilder(INamingConfigService namingConfigService,
|
public FileNameBuilder(INamingConfigService namingConfigService,
|
||||||
|
IQualityDefinitionService qualityDefinitionService,
|
||||||
ICacheManger cacheManger,
|
ICacheManger cacheManger,
|
||||||
Logger logger)
|
Logger logger)
|
||||||
{
|
{
|
||||||
_namingConfigService = namingConfigService;
|
_namingConfigService = namingConfigService;
|
||||||
|
_qualityDefinitionService = qualityDefinitionService;
|
||||||
_patternCache = cacheManger.GetCache<EpisodeFormat>(GetType());
|
_patternCache = cacheManger.GetCache<EpisodeFormat>(GetType());
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
@ -87,12 +91,10 @@ namespace NzbDrone.Core.Organizer
|
||||||
sortedEpisodes.First().Title
|
sortedEpisodes.First().Title
|
||||||
};
|
};
|
||||||
|
|
||||||
var tokenValues = new Dictionary<string, string>(FilenameBuilderTokenEqualityComparer.Instance)
|
var tokenValues = new Dictionary<string, string>(FilenameBuilderTokenEqualityComparer.Instance);
|
||||||
{
|
|
||||||
{"{Series Title}", series.Title},
|
|
||||||
{"Original Title", episodeFile.SceneName}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
tokenValues.Add("{Series Title}", series.Title);
|
||||||
|
tokenValues.Add("{Original Title}", episodeFile.SceneName);
|
||||||
tokenValues.Add("{Release Group}", episodeFile.ReleaseGroup);
|
tokenValues.Add("{Release Group}", episodeFile.ReleaseGroup);
|
||||||
|
|
||||||
if (series.SeriesType == SeriesTypes.Daily)
|
if (series.SeriesType == SeriesTypes.Daily)
|
||||||
|
@ -146,7 +148,7 @@ namespace NzbDrone.Core.Organizer
|
||||||
}
|
}
|
||||||
|
|
||||||
tokenValues.Add("{Episode Title}", GetEpisodeTitle(episodeTitles));
|
tokenValues.Add("{Episode Title}", GetEpisodeTitle(episodeTitles));
|
||||||
tokenValues.Add("{Quality Title}", episodeFile.Quality.ToString());
|
tokenValues.Add("{Quality Title}", GetQualityTitle(episodeFile.Quality));
|
||||||
|
|
||||||
|
|
||||||
return CleanFilename(ReplaceTokens(pattern, tokenValues).Trim());
|
return CleanFilename(ReplaceTokens(pattern, tokenValues).Trim());
|
||||||
|
@ -341,6 +343,14 @@ namespace NzbDrone.Core.Organizer
|
||||||
|
|
||||||
return String.Join(" + ", episodeTitles.Select(Parser.Parser.CleanupEpisodeTitle).Distinct());
|
return String.Join(" + ", episodeTitles.Select(Parser.Parser.CleanupEpisodeTitle).Distinct());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private string GetQualityTitle(QualityModel quality)
|
||||||
|
{
|
||||||
|
if (quality.Proper)
|
||||||
|
return _qualityDefinitionService.Get(quality.Quality).Title + " Proper";
|
||||||
|
else
|
||||||
|
return _qualityDefinitionService.Get(quality.Quality).Title;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum MultiEpisodeStyle
|
public enum MultiEpisodeStyle
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using NzbDrone.Core.Tv;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser.Model
|
namespace NzbDrone.Core.Parser.Model
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Parser.Model
|
namespace NzbDrone.Core.Parser.Model
|
||||||
|
|
|
@ -2,65 +2,24 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Datastore.Converters;
|
||||||
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Qualities
|
namespace NzbDrone.Core.Qualities
|
||||||
{
|
{
|
||||||
public class Quality : IComparable<Quality>, IEmbeddedDocument
|
public class Quality : IEmbeddedDocument, IEquatable<Quality>
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
public int Weight { get; set; }
|
|
||||||
|
|
||||||
public int CompareTo(Quality other)
|
public Quality()
|
||||||
{
|
{
|
||||||
if (other.Weight > Weight)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (other.Weight < Weight)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (other.Weight == Weight)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static bool operator !=(Quality x, Quality y)
|
private Quality(int id, string name)
|
||||||
{
|
{
|
||||||
return !(x == y);
|
Id = id;
|
||||||
}
|
Name = name;
|
||||||
|
|
||||||
public static bool operator ==(Quality x, Quality y)
|
|
||||||
{
|
|
||||||
var xObj = (Object)x;
|
|
||||||
var yObj = (object)y;
|
|
||||||
|
|
||||||
if (xObj == null || yObj == null)
|
|
||||||
{
|
|
||||||
return xObj == yObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
return x.CompareTo(y) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >(Quality x, Quality y)
|
|
||||||
{
|
|
||||||
return x.CompareTo(y) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <(Quality x, Quality y)
|
|
||||||
{
|
|
||||||
return x.CompareTo(y) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <=(Quality x, Quality y)
|
|
||||||
{
|
|
||||||
return x.CompareTo(y) <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >=(Quality x, Quality y)
|
|
||||||
{
|
|
||||||
return x.CompareTo(y) >= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
|
@ -70,110 +29,96 @@ namespace NzbDrone.Core.Qualities
|
||||||
|
|
||||||
public override int GetHashCode()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
unchecked // Overflow is fine, just wrap
|
return Id.GetHashCode();
|
||||||
{
|
|
||||||
int hash = 17;
|
|
||||||
hash = hash * 23 + Weight.GetHashCode();
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool Equals(Quality other)
|
public bool Equals(Quality other)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, other)) return false;
|
if (ReferenceEquals(null, other)) return false;
|
||||||
if (ReferenceEquals(this, other)) return true;
|
if (ReferenceEquals(this, other)) return true;
|
||||||
return Equals(other.Weight, Weight);
|
return Id.Equals(other.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
{
|
{
|
||||||
if (ReferenceEquals(null, obj)) return false;
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
if (ReferenceEquals(this, obj)) return true;
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
if (obj.GetType() != typeof(Quality)) return false;
|
|
||||||
return Equals((Quality)obj);
|
return Equals(obj as Quality);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quality Unknown
|
public static bool operator ==(Quality left, Quality right)
|
||||||
{
|
{
|
||||||
get { return new Quality { Id = 0, Name = "Unknown", Weight = 0 }; }
|
return Equals(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quality SDTV
|
public static bool operator !=(Quality left, Quality right)
|
||||||
{
|
{
|
||||||
get { return new Quality { Id = 1, Name = "SDTV", Weight = 1 }; }
|
return !Equals(left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quality WEBDL480p
|
public static Quality Unknown { get { return new Quality(0, "Unknown"); } }
|
||||||
|
public static Quality SDTV { get { return new Quality(1, "SDTV"); } }
|
||||||
|
public static Quality DVD { get { return new Quality(2, "DVD"); } }
|
||||||
|
public static Quality WEBDL1080p { get { return new Quality(3, "WEBDL-1080p"); } }
|
||||||
|
public static Quality HDTV720p { get { return new Quality(4, "HDTV-720p"); } }
|
||||||
|
public static Quality WEBDL720p { get { return new Quality(5, "WEBDL-720p"); } }
|
||||||
|
public static Quality Bluray720p { get { return new Quality(6, "Bluray-720p"); } }
|
||||||
|
public static Quality Bluray1080p { get { return new Quality(7, "Bluray-1080p"); } }
|
||||||
|
public static Quality WEBDL480p { get { return new Quality(8, "WEBDL-480p"); } }
|
||||||
|
public static Quality HDTV1080p { get { return new Quality(9, "HDTV-1080p"); } }
|
||||||
|
public static Quality RAWHD { get { return new Quality(10, "Raw-HD"); } }
|
||||||
|
public static Quality HDTV480p { get { return new Quality(11, "HDTV-480p"); } }
|
||||||
|
|
||||||
|
public static List<Quality> All
|
||||||
{
|
{
|
||||||
get { return new Quality { Id = 8, Name = "WEBDL-480p", Weight = 2 }; }
|
get
|
||||||
|
{
|
||||||
|
return new List<Quality>
|
||||||
|
{
|
||||||
|
SDTV,
|
||||||
|
DVD,
|
||||||
|
WEBDL1080p,
|
||||||
|
HDTV720p,
|
||||||
|
WEBDL720p,
|
||||||
|
Bluray720p,
|
||||||
|
Bluray1080p,
|
||||||
|
WEBDL480p,
|
||||||
|
HDTV1080p,
|
||||||
|
RAWHD
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quality DVD
|
public static HashSet<QualityDefinition> DefaultQualityDefinitions
|
||||||
{
|
{
|
||||||
get { return new Quality { Id = 2, Name = "DVD", Weight = 3 }; }
|
get
|
||||||
}
|
{
|
||||||
|
return new HashSet<QualityDefinition>
|
||||||
public static Quality HDTV720p
|
{
|
||||||
{
|
new QualityDefinition(Quality.SDTV) { /*Title = "SDTV", */ Weight = 1, MinSize=0, MaxSize=100 },
|
||||||
get { return new Quality { Id = 4, Name = "HDTV-720p", Weight = 4 }; }
|
new QualityDefinition(Quality.WEBDL480p) { /*Title = "WEB-DL", */ Weight = 2, MinSize=0, MaxSize=100 },
|
||||||
}
|
new QualityDefinition(Quality.DVD) { /*Title = "DVD", */ Weight = 3, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.HDTV720p) { /*Title = "720p HDTV", */ Weight = 4, MinSize=0, MaxSize=100 },
|
||||||
public static Quality HDTV1080p
|
new QualityDefinition(Quality.HDTV1080p) { /*Title = "1080p HDTV", */ Weight = 5, MinSize=0, MaxSize=100 },
|
||||||
{
|
new QualityDefinition(Quality.RAWHD) { /*Title = "RawHD", */ Weight = 6, MinSize=0, MaxSize=100 },
|
||||||
get { return new Quality { Id = 9, Name = "HDTV-1080p", Weight = 5 }; }
|
new QualityDefinition(Quality.WEBDL720p) { /*Title = "720p WEB-DL", */ Weight = 7, MinSize=0, MaxSize=100 },
|
||||||
}
|
new QualityDefinition(Quality.Bluray720p) { /*Title = "720p BluRay", */ Weight = 8, MinSize=0, MaxSize=100 },
|
||||||
|
new QualityDefinition(Quality.WEBDL1080p) { /*Title = "1080p WEB-DL",*/ Weight = 9, MinSize=0, MaxSize=100 },
|
||||||
public static Quality RAWHD
|
new QualityDefinition(Quality.Bluray1080p) { /*Title = "1080p BluRay",*/ Weight = 10, MinSize=0, MaxSize=100 }
|
||||||
{
|
};
|
||||||
get { return new Quality { Id = 10, Name = "Raw-HD", Weight = 6 }; }
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static Quality WEBDL720p
|
|
||||||
{
|
|
||||||
get { return new Quality { Id = 5, Name = "WEBDL-720p", Weight = 7 }; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Quality Bluray720p
|
|
||||||
{
|
|
||||||
get { return new Quality { Id = 6, Name = "Bluray720p", Weight = 8 }; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Quality WEBDL1080p
|
|
||||||
{
|
|
||||||
get { return new Quality { Id = 3, Name = "WEBDL-1080p", Weight = 9 }; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Quality Bluray1080p
|
|
||||||
{
|
|
||||||
get { return new Quality { Id = 7, Name = "Bluray1080p", Weight = 10 }; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Quality> All()
|
|
||||||
{
|
|
||||||
return new List<Quality>
|
|
||||||
{
|
|
||||||
SDTV,
|
|
||||||
WEBDL480p,
|
|
||||||
DVD,
|
|
||||||
HDTV720p,
|
|
||||||
HDTV1080p,
|
|
||||||
RAWHD,
|
|
||||||
WEBDL720p,
|
|
||||||
WEBDL1080p,
|
|
||||||
Bluray720p,
|
|
||||||
Bluray1080p
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Quality FindById(int id)
|
public static Quality FindById(int id)
|
||||||
{
|
{
|
||||||
if (id == 0) return Unknown;
|
if (id == 0) return Unknown;
|
||||||
|
|
||||||
var quality = All().SingleOrDefault(q => q.Id == id);
|
Quality quality = All.FirstOrDefault(v => v.Id == id);
|
||||||
|
|
||||||
if (quality == null)
|
if (quality == null)
|
||||||
throw new ArgumentException("ID does not match a known quality", "id");
|
throw new ArgumentException("ID does not match a known quality", "id");
|
||||||
|
|
||||||
return quality;
|
return quality;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Qualities
|
||||||
|
{
|
||||||
|
public class QualityDefinition : ModelBase
|
||||||
|
{
|
||||||
|
public Quality Quality { get; set; }
|
||||||
|
|
||||||
|
public string Title { get; set; }
|
||||||
|
|
||||||
|
public int Weight { get; set; }
|
||||||
|
|
||||||
|
public int MinSize { get; set; }
|
||||||
|
public int MaxSize { get; set; }
|
||||||
|
|
||||||
|
public QualityDefinition()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public QualityDefinition(Quality quality)
|
||||||
|
{
|
||||||
|
Quality = quality;
|
||||||
|
Title = quality.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Quality.Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Qualities
|
||||||
|
{
|
||||||
|
public interface IQualityDefinitionRepository : IBasicRepository<QualityDefinition>
|
||||||
|
{
|
||||||
|
QualityDefinition GetByQualityId(int qualityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class QualityDefinitionRepository : BasicRepository<QualityDefinition>, IQualityDefinitionRepository
|
||||||
|
{
|
||||||
|
public QualityDefinitionRepository(IDatabase database, IEventAggregator eventAggregator)
|
||||||
|
: base(database, eventAggregator)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public QualityDefinition GetByQualityId(int qualityId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Query.Single(q => (int)q.Quality == qualityId);
|
||||||
|
}
|
||||||
|
catch (InvalidOperationException e)
|
||||||
|
{
|
||||||
|
throw new ModelNotFoundException(typeof(QualityDefinition), qualityId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,101 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Core.Lifecycle;
|
||||||
|
using NzbDrone.Core.Messaging.Events;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Qualities
|
||||||
|
{
|
||||||
|
public interface IQualityDefinitionService
|
||||||
|
{
|
||||||
|
void Update(QualityDefinition qualityDefinition);
|
||||||
|
List<QualityDefinition> All();
|
||||||
|
QualityDefinition Get(Quality quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class QualityDefinitionService : IQualityDefinitionService, IHandle<ApplicationStartedEvent>
|
||||||
|
{
|
||||||
|
private readonly IQualityDefinitionRepository _qualityDefinitionRepository;
|
||||||
|
private readonly Logger _logger;
|
||||||
|
|
||||||
|
public QualityDefinitionService(IQualityDefinitionRepository qualityDefinitionRepository, Logger logger)
|
||||||
|
{
|
||||||
|
_qualityDefinitionRepository = qualityDefinitionRepository;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update(QualityDefinition qualityDefinition)
|
||||||
|
{
|
||||||
|
_qualityDefinitionRepository.Update(qualityDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<QualityDefinition> All()
|
||||||
|
{
|
||||||
|
return _qualityDefinitionRepository.All().ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public QualityDefinition Get(Quality quality)
|
||||||
|
{
|
||||||
|
if (quality == Quality.Unknown)
|
||||||
|
return new QualityDefinition(Quality.Unknown);
|
||||||
|
|
||||||
|
return _qualityDefinitionRepository.GetByQualityId((int)quality);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InsertMissingDefinitions(List<QualityDefinition> allDefinitions)
|
||||||
|
{
|
||||||
|
allDefinitions.OrderBy(v => v.Weight).ToList();
|
||||||
|
var existingDefinitions = _qualityDefinitionRepository.All().OrderBy(v => v.Weight).ToList();
|
||||||
|
|
||||||
|
// Try insert each item intelligently to merge the lists preserving the Weight the user set.
|
||||||
|
for (int i = 0; i < allDefinitions.Count;i++)
|
||||||
|
{
|
||||||
|
// Skip if this definition isn't missing.
|
||||||
|
if (existingDefinitions.Any(v => v.Quality == allDefinitions[i].Quality))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int targetIndexMinimum = 0;
|
||||||
|
for (int j = 0; j < i; j++)
|
||||||
|
targetIndexMinimum = Math.Max(targetIndexMinimum, existingDefinitions.FindIndex(v => v.Quality == allDefinitions[j].Quality) + 1);
|
||||||
|
|
||||||
|
int targetIndexMaximum = existingDefinitions.Count;
|
||||||
|
for (int j = i + 1; j < allDefinitions.Count; j++)
|
||||||
|
{
|
||||||
|
var index = existingDefinitions.FindIndex(v => v.Quality == allDefinitions[j].Quality);
|
||||||
|
if (index != -1)
|
||||||
|
targetIndexMaximum = Math.Min(targetIndexMaximum, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rounded down average sounds reasonable.
|
||||||
|
int targetIndex = (targetIndexMinimum + targetIndexMaximum) / 2;
|
||||||
|
|
||||||
|
existingDefinitions.Insert(targetIndex, allDefinitions[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update all Weights.
|
||||||
|
List<QualityDefinition> insertList = new List<QualityDefinition>();
|
||||||
|
List<QualityDefinition> updateList = new List<QualityDefinition>();
|
||||||
|
for (int i = 0; i < existingDefinitions.Count; i++)
|
||||||
|
{
|
||||||
|
if (existingDefinitions[i].Id == 0)
|
||||||
|
{
|
||||||
|
existingDefinitions[i].Weight = i + 1;
|
||||||
|
_qualityDefinitionRepository.Insert(existingDefinitions[i]);
|
||||||
|
}
|
||||||
|
else if (existingDefinitions[i].Weight != i + 1)
|
||||||
|
{
|
||||||
|
existingDefinitions[i].Weight = i + 1;
|
||||||
|
_qualityDefinitionRepository.Update(existingDefinitions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Handle(ApplicationStartedEvent message)
|
||||||
|
{
|
||||||
|
_logger.Debug("Setting up default quality config");
|
||||||
|
|
||||||
|
InsertMissingDefinitions(Quality.DefaultQualityDefinitions.ToList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Qualities
|
||||||
|
{
|
||||||
|
public class QualityModel : IEmbeddedDocument, IEquatable<QualityModel>
|
||||||
|
{
|
||||||
|
public Quality Quality { get; set; }
|
||||||
|
|
||||||
|
public Boolean Proper { get; set; }
|
||||||
|
|
||||||
|
public QualityModel()
|
||||||
|
: this(Quality.Unknown)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public QualityModel(Quality quality, Boolean proper = false)
|
||||||
|
{
|
||||||
|
Quality = quality;
|
||||||
|
Proper = proper;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
string result = Quality.ToString();
|
||||||
|
if (Proper)
|
||||||
|
{
|
||||||
|
result += " Proper";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
unchecked // Overflow is fine, just wrap
|
||||||
|
{
|
||||||
|
int hash = 17;
|
||||||
|
hash = hash * 23 + Proper.GetHashCode();
|
||||||
|
hash = hash * 23 + Quality.GetHashCode();
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(QualityModel other)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, other)) return false;
|
||||||
|
if (ReferenceEquals(this, other)) return true;
|
||||||
|
return other.Quality.Equals(Quality) && other.Proper.Equals(Proper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (ReferenceEquals(null, obj)) return false;
|
||||||
|
if (ReferenceEquals(this, obj)) return true;
|
||||||
|
|
||||||
|
return Equals(obj as QualityModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(QualityModel left, QualityModel right)
|
||||||
|
{
|
||||||
|
return Equals(left, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(QualityModel left, QualityModel right)
|
||||||
|
{
|
||||||
|
return !Equals(left, right);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using NLog;
|
||||||
|
using NzbDrone.Common.EnsureThat;
|
||||||
|
|
||||||
|
namespace NzbDrone.Core.Qualities
|
||||||
|
{
|
||||||
|
public class QualityModelComparer : IComparer<Quality>, IComparer<QualityModel>
|
||||||
|
{
|
||||||
|
private readonly QualityProfile _qualityProfile;
|
||||||
|
|
||||||
|
public QualityModelComparer(QualityProfile qualityProfile)
|
||||||
|
{
|
||||||
|
Ensure.That(qualityProfile, () => qualityProfile).IsNotNull();
|
||||||
|
Ensure.That(qualityProfile.Allowed, () => qualityProfile.Allowed).HasItems();
|
||||||
|
|
||||||
|
_qualityProfile = qualityProfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(Quality left, Quality right)
|
||||||
|
{
|
||||||
|
int leftIndex = _qualityProfile.Allowed.IndexOf(left);
|
||||||
|
int rightIndex = _qualityProfile.Allowed.IndexOf(right);
|
||||||
|
|
||||||
|
return leftIndex.CompareTo(rightIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Compare(QualityModel left, QualityModel right)
|
||||||
|
{
|
||||||
|
int result = Compare(left.Quality, right.Quality);
|
||||||
|
|
||||||
|
if (result == 0)
|
||||||
|
result = left.Proper.CompareTo(right.Proper);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
public string GetName(Quality quality)
|
||||||
|
{
|
||||||
|
QualityDefinition qualityDefinition = _qualityDefinitionService.Get(quality);
|
||||||
|
|
||||||
|
return qualityDefinition.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetName(QualityModel quality)
|
||||||
|
{
|
||||||
|
QualityDefinition qualityDefinition = _qualityDefinitionService.Get(quality.Quality);
|
||||||
|
|
||||||
|
if (quality.Proper)
|
||||||
|
return qualityDefinition.Name + " Proper";
|
||||||
|
else
|
||||||
|
return qualityDefinition.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetSceneName(QualityModel quality)
|
||||||
|
{
|
||||||
|
QualityDefinition qualityDefinition = _qualityDefinitionService.Get(quality.Quality);
|
||||||
|
|
||||||
|
if (quality.Proper)
|
||||||
|
return qualityDefinition.SceneName + " PROPER";
|
||||||
|
else
|
||||||
|
return qualityDefinition.SceneName;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,18 +0,0 @@
|
||||||
using NzbDrone.Core.Datastore;
|
|
||||||
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Qualities
|
|
||||||
{
|
|
||||||
public class QualitySize : ModelBase
|
|
||||||
{
|
|
||||||
public int QualityId { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public int MinSize { get; set; }
|
|
||||||
public int MaxSize { get; set; }
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using NzbDrone.Core.Datastore;
|
|
||||||
using NzbDrone.Core.Messaging.Events;
|
|
||||||
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Qualities
|
|
||||||
{
|
|
||||||
public interface IQualitySizeRepository : IBasicRepository<QualitySize>
|
|
||||||
{
|
|
||||||
QualitySize GetByQualityId(int qualityId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class QualitySizeRepository : BasicRepository<QualitySize>, IQualitySizeRepository
|
|
||||||
{
|
|
||||||
public QualitySizeRepository(IDatabase database, IEventAggregator eventAggregator)
|
|
||||||
: base(database, eventAggregator)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public QualitySize GetByQualityId(int qualityId)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
return Query.Single(q => q.QualityId == qualityId);
|
|
||||||
}
|
|
||||||
catch (InvalidOperationException e)
|
|
||||||
{
|
|
||||||
throw new ModelNotFoundException(typeof(QualitySize), qualityId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,64 +0,0 @@
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using NLog;
|
|
||||||
using NzbDrone.Core.Lifecycle;
|
|
||||||
using NzbDrone.Core.Messaging.Events;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Qualities
|
|
||||||
{
|
|
||||||
public interface IQualitySizeService
|
|
||||||
{
|
|
||||||
void Update(QualitySize qualitySize);
|
|
||||||
List<QualitySize> All();
|
|
||||||
QualitySize Get(int qualityId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class QualitySizeService : IQualitySizeService, IHandle<ApplicationStartedEvent>
|
|
||||||
{
|
|
||||||
private readonly IQualitySizeRepository _qualitySizeRepository;
|
|
||||||
private readonly Logger _logger;
|
|
||||||
|
|
||||||
public QualitySizeService(IQualitySizeRepository qualitySizeRepository, Logger logger)
|
|
||||||
{
|
|
||||||
_qualitySizeRepository = qualitySizeRepository;
|
|
||||||
_logger = logger;
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void Update(QualitySize qualitySize)
|
|
||||||
{
|
|
||||||
_qualitySizeRepository.Update(qualitySize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public virtual List<QualitySize> All()
|
|
||||||
{
|
|
||||||
return _qualitySizeRepository.All().ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual QualitySize Get(int qualityId)
|
|
||||||
{
|
|
||||||
return _qualitySizeRepository.GetByQualityId(qualityId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Handle(ApplicationStartedEvent message)
|
|
||||||
{
|
|
||||||
var existing = All();
|
|
||||||
|
|
||||||
_logger.Debug("Setting up default quality sizes");
|
|
||||||
|
|
||||||
foreach (var quality in Quality.All())
|
|
||||||
{
|
|
||||||
if (!existing.Any(s => s.QualityId == quality.Id))
|
|
||||||
{
|
|
||||||
_qualitySizeRepository.Insert(new QualitySize
|
|
||||||
{
|
|
||||||
QualityId = quality.Id,
|
|
||||||
Name = quality.Name,
|
|
||||||
MinSize = 0,
|
|
||||||
MaxSize = 100
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using NzbDrone.Core.Datastore;
|
using NzbDrone.Core.Datastore;
|
||||||
|
using NzbDrone.Core.Qualities;
|
||||||
using NzbDrone.Core.Tv;
|
using NzbDrone.Core.Tv;
|
||||||
|
|
||||||
namespace NzbDrone.Core.Queue
|
namespace NzbDrone.Core.Queue
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
using System;
|
|
||||||
using NzbDrone.Core.Datastore;
|
|
||||||
using NzbDrone.Core.Qualities;
|
|
||||||
|
|
||||||
namespace NzbDrone.Core.Tv
|
|
||||||
{
|
|
||||||
public class QualityModel : IComparable<QualityModel>, IEmbeddedDocument
|
|
||||||
{
|
|
||||||
public Quality Quality { get; set; }
|
|
||||||
|
|
||||||
public Boolean Proper { get; set; }
|
|
||||||
|
|
||||||
public QualityModel()
|
|
||||||
: this(Quality.Unknown)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public QualityModel(Quality quality, Boolean proper = false)
|
|
||||||
{
|
|
||||||
Quality = quality;
|
|
||||||
Proper = proper;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int CompareTo(QualityModel other)
|
|
||||||
{
|
|
||||||
if (other.Quality > Quality)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
if (other.Quality < Quality)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (other.Quality == Quality && other.Proper == Proper)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (Proper && !other.Proper)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (!Proper && other.Proper)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator !=(QualityModel x, QualityModel y)
|
|
||||||
{
|
|
||||||
return !(x == y);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator ==(QualityModel x, QualityModel y)
|
|
||||||
{
|
|
||||||
var xObj = (Object)x;
|
|
||||||
var yObj = (object)y;
|
|
||||||
|
|
||||||
if (xObj == null || yObj == null)
|
|
||||||
{
|
|
||||||
return xObj == yObj;
|
|
||||||
}
|
|
||||||
|
|
||||||
return x.CompareTo(y) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >(QualityModel x, QualityModel y)
|
|
||||||
{
|
|
||||||
return x.CompareTo(y) > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <(QualityModel x, QualityModel y)
|
|
||||||
{
|
|
||||||
return x.CompareTo(y) < 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator <=(QualityModel x, QualityModel y)
|
|
||||||
{
|
|
||||||
return x.CompareTo(y) <= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool operator >=(QualityModel x, QualityModel y)
|
|
||||||
{
|
|
||||||
return x.CompareTo(y) >= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
string result = Quality.ToString();
|
|
||||||
if (Proper)
|
|
||||||
{
|
|
||||||
result += " Proper";
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
unchecked // Overflow is fine, just wrap
|
|
||||||
{
|
|
||||||
int hash = 17;
|
|
||||||
hash = hash * 23 + Proper.GetHashCode();
|
|
||||||
hash = hash * 23 + Quality.GetHashCode();
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool Equals(QualityModel other)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(null, other)) return false;
|
|
||||||
if (ReferenceEquals(this, other)) return true;
|
|
||||||
return Equals(other.Quality, Quality) && other.Proper.Equals(Proper);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
|
||||||
{
|
|
||||||
if (ReferenceEquals(null, obj)) return false;
|
|
||||||
if (ReferenceEquals(this, obj)) return true;
|
|
||||||
if (obj.GetType() != typeof(QualityModel)) return false;
|
|
||||||
return Equals((QualityModel)obj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
||||||
|
'use strict';
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'backbone',
|
||||||
|
'Quality/QualityDefinitionModel'
|
||||||
|
], function (Backbone, QualityDefinitionModel) {
|
||||||
|
return Backbone.Collection.extend({
|
||||||
|
model: QualityDefinitionModel,
|
||||||
|
url : window.NzbDrone.ApiRoot + '/qualitydefinition'
|
||||||
|
});
|
||||||
|
});
|
|
@ -9,10 +9,10 @@ define(
|
||||||
baseInitialize: ModelBase.prototype.initialize,
|
baseInitialize: ModelBase.prototype.initialize,
|
||||||
|
|
||||||
initialize: function () {
|
initialize: function () {
|
||||||
var name = this.get('name');
|
var name = this.get('quality').name;
|
||||||
|
|
||||||
this.successMessage = 'Saved ' + name + ' size settings';
|
this.successMessage = 'Saved ' + name + ' quality settings';
|
||||||
this.errorMessage = 'Couldn\'t save ' + name + ' size settings';
|
this.errorMessage = 'Couldn\'t save ' + name + ' quality settings';
|
||||||
|
|
||||||
this.baseInitialize.call(this);
|
this.baseInitialize.call(this);
|
||||||
}
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
'use strict';
|
|
||||||
define(
|
|
||||||
[
|
|
||||||
'backbone',
|
|
||||||
'Quality/QualitySizeModel'
|
|
||||||
], function (Backbone, QualitySizeModel) {
|
|
||||||
return Backbone.Collection.extend({
|
|
||||||
model: QualitySizeModel,
|
|
||||||
url : window.NzbDrone.ApiRoot + '/qualitysize'
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<fieldset>
|
||||||
|
<legend>Quality Definitions</legend>
|
||||||
|
<div class="span11">
|
||||||
|
<div id="quality-definition-list">
|
||||||
|
<div class="x-header">
|
||||||
|
<div class="row">
|
||||||
|
<span class="span2">Quality</span>
|
||||||
|
<span class="span2">Title</span>
|
||||||
|
<span class="offset1 span4">Size Limit</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="x-rows">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
|
@ -0,0 +1,17 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'marionette',
|
||||||
|
'backgrid',
|
||||||
|
'Settings/Quality/Definition/QualityDefinitionView'
|
||||||
|
], function (Marionette, Backgrid, QualityDefinitionView) {
|
||||||
|
|
||||||
|
return Marionette.CompositeView.extend({
|
||||||
|
template: 'Settings/Quality/Definition/QualityDefinitionCollectionTemplate',
|
||||||
|
|
||||||
|
itemViewContainer: ".x-rows",
|
||||||
|
|
||||||
|
itemView: QualityDefinitionView
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,31 @@
|
||||||
|
<span class="span2">
|
||||||
|
{{quality.name}}
|
||||||
|
</span>
|
||||||
|
<span class="span2">
|
||||||
|
<input type="text" class="x-title input-block-level" value="{{title}}">
|
||||||
|
</span>
|
||||||
|
<span class="offset1 span4">
|
||||||
|
<div class="x-slider"></div>
|
||||||
|
<div class="size-label-wrapper">
|
||||||
|
<div class="pull-left">
|
||||||
|
<span class="label label-warning x-min-thirty"
|
||||||
|
name="thirtyMinuteMinSize"
|
||||||
|
title="Minimum size for a 30 minute episode">
|
||||||
|
</span>
|
||||||
|
<span class="label label-info x-min-sixty"
|
||||||
|
name="sixtyMinuteMinSize"
|
||||||
|
title="Minimum size for a 60 minute episode">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="pull-right">
|
||||||
|
<span class="label label-warning x-max-thirty"
|
||||||
|
name="thirtyMinuteMaxSize"
|
||||||
|
title="Maximum size for a 30 minute episode">
|
||||||
|
</span>
|
||||||
|
<span class="label label-info x-max-sixty"
|
||||||
|
name="sixtyMinuteMaxSize"
|
||||||
|
title="Maximum size for a 60 minute episode">
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</span>
|
|
@ -0,0 +1,86 @@
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'marionette',
|
||||||
|
'Mixins/AsModelBoundView',
|
||||||
|
'filesize',
|
||||||
|
'jquery-ui'
|
||||||
|
], function (Marionette, AsModelBoundView, fileSize) {
|
||||||
|
|
||||||
|
var view = Marionette.ItemView.extend({
|
||||||
|
template: 'Settings/Quality/Definition/QualityDefinitionTemplate',
|
||||||
|
className: 'row',
|
||||||
|
|
||||||
|
ui: {
|
||||||
|
title : '.x-title',
|
||||||
|
sizeSlider : '.x-slider',
|
||||||
|
thirtyMinuteMinSize: '.x-min-thirty',
|
||||||
|
sixtyMinuteMinSize : '.x-min-sixty',
|
||||||
|
thirtyMinuteMaxSize: '.x-max-thirty',
|
||||||
|
sixtyMinuteMaxSize : '.x-max-sixty'
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
'change .x-title': '_updateTitle',
|
||||||
|
'slide .x-slider': '_updateSize'
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function (options) {
|
||||||
|
this.qualityProfileCollection = options.qualityProfiles;
|
||||||
|
this.filesize = fileSize;
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function () {
|
||||||
|
this.ui.sizeSlider.slider({
|
||||||
|
range : true,
|
||||||
|
min : 0,
|
||||||
|
max : 200,
|
||||||
|
values : [ this.model.get('minSize'), this.model.get('maxSize') ],
|
||||||
|
});
|
||||||
|
|
||||||
|
this._changeSize();
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateTitle: function() {
|
||||||
|
this.model.set('title', this.ui.title.val());
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateSize: function (event, ui) {
|
||||||
|
this.model.set('minSize', ui.values[0]);
|
||||||
|
this.model.set('maxSize', ui.values[1]);
|
||||||
|
|
||||||
|
this._changeSize();
|
||||||
|
},
|
||||||
|
|
||||||
|
_changeSize: function () {
|
||||||
|
var minSize = this.model.get('minSize');
|
||||||
|
var maxSize = this.model.get('maxSize');
|
||||||
|
|
||||||
|
{
|
||||||
|
var minBytes = minSize * 1024 * 1024;
|
||||||
|
var minThirty = fileSize(minBytes * 30, 1, false);
|
||||||
|
var minSixty = fileSize(minBytes * 60, 1, false);
|
||||||
|
|
||||||
|
this.ui.thirtyMinuteMinSize.html(minThirty);
|
||||||
|
this.ui.sixtyMinuteMinSize.html(minSixty);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
var maxBytes = maxSize * 1024 * 1024;
|
||||||
|
var maxThirty = fileSize(maxBytes * 30, 1, false);
|
||||||
|
var maxSixty = fileSize(maxBytes * 60, 1, false);
|
||||||
|
|
||||||
|
this.ui.thirtyMinuteMaxSize.html(maxThirty);
|
||||||
|
this.ui.sixtyMinuteMaxSize.html(maxSixty);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (parseInt(maxSize, 10) === 0) {
|
||||||
|
thirty = 'No Limit';
|
||||||
|
sixty = 'No Limit';
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return AsModelBoundView.call(view);
|
||||||
|
});
|
|
@ -0,0 +1,9 @@
|
||||||
|
'use strict';
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'marionette'
|
||||||
|
], function (Marionette) {
|
||||||
|
return Marionette.ItemView.extend({
|
||||||
|
template : 'Settings/Quality/Profile/EditQualityProfileItemViewTemplate'
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,5 @@
|
||||||
|
<i class="x-moveleft-handle pull-left icon-chevron-left" />
|
||||||
|
<i class="x-drag-handle pull-right icon-resize-vertical advanced-setting" />
|
||||||
|
<i class="x-moveright-handle pull-right icon-chevron-right" />
|
||||||
|
<span>{{name}}</span>
|
||||||
|
|
|
@ -29,25 +29,15 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="offset1 span3">
|
<div class="offset1 span2">
|
||||||
<h3>Available</h3>
|
<h3>Available</h3>
|
||||||
<select multiple="multiple" class="x-available-list">
|
<ul class="x-available-list">
|
||||||
{{#each available}}
|
</ul>
|
||||||
<option value="{{id}}">{{name}}</option>
|
|
||||||
{{/each}}
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="span3">
|
<div class="span2">
|
||||||
<div class="control-group">
|
<h3>Allowed</h3>
|
||||||
<div class="controls">
|
<ul class="x-allowed-list" validation-name="allowed">
|
||||||
<h3>Allowed</h3>
|
</ul>
|
||||||
<select multiple="multiple" class="x-allowed-list" validation-name="allowed">
|
|
||||||
{{#each allowed}}
|
|
||||||
<option value="{{id}}">{{name}}</option>
|
|
||||||
{{/each}}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,63 +4,113 @@ define(
|
||||||
'vent',
|
'vent',
|
||||||
'marionette',
|
'marionette',
|
||||||
'backbone',
|
'backbone',
|
||||||
|
'backbone.collectionview',
|
||||||
|
'Settings/Quality/Profile/EditQualityProfileItemView',
|
||||||
'Mixins/AsModelBoundView',
|
'Mixins/AsModelBoundView',
|
||||||
'Mixins/AsValidatedView',
|
'Mixins/AsValidatedView',
|
||||||
'underscore'
|
'underscore'
|
||||||
], function (vent, Marionette, Backbone, AsModelBoundView, AsValidatedView, _) {
|
], function (vent, Marionette, Backbone, BackboneSortableCollectionView, EditQualityProfileItemView, AsModelBoundView, AsValidatedView, _) {
|
||||||
|
|
||||||
var view = Marionette.ItemView.extend({
|
var view = Marionette.ItemView.extend({
|
||||||
template: 'Settings/Quality/Profile/EditQualityProfileTemplate',
|
template: 'Settings/Quality/Profile/EditQualityProfileTemplate',
|
||||||
|
|
||||||
ui: {
|
ui: {
|
||||||
cutoff: '.x-cutoff'
|
available: '.x-available-list',
|
||||||
|
allowed : '.x-allowed-list',
|
||||||
|
cutoff : '.x-cutoff'
|
||||||
},
|
},
|
||||||
|
|
||||||
events: {
|
events: {
|
||||||
'click .x-save' : '_saveQualityProfile',
|
'click .x-save' : '_saveQualityProfile',
|
||||||
'dblclick .x-available-list': '_moveQuality',
|
//'click .x-qualityitem' : '_moveQuality',
|
||||||
'dblclick .x-allowed-list' : '_moveQuality'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
this.profileCollection = options.profileCollection;
|
this.profileCollection = options.profileCollection;
|
||||||
|
|
||||||
|
this.availableCollection = new Backbone.Collection(this.model.get('available'));
|
||||||
|
this.availableCollection.comparator = function (model) { return -model.get('weight'); };
|
||||||
|
this.availableCollection.sort();
|
||||||
|
|
||||||
|
this.allowedCollection = new Backbone.Collection(this.model.get('allowed').reverse());
|
||||||
|
},
|
||||||
|
|
||||||
|
onRender: function() {
|
||||||
|
var listViewAvailable = new BackboneSortableCollectionView( {
|
||||||
|
el : this.ui.available,
|
||||||
|
modelView : EditQualityProfileItemView,
|
||||||
|
selectable: false,
|
||||||
|
sortable : false,
|
||||||
|
collection: this.availableCollection
|
||||||
|
});
|
||||||
|
listViewAvailable.render();
|
||||||
|
|
||||||
|
var listViewAllowed = new BackboneSortableCollectionView( {
|
||||||
|
el : this.ui.allowed,
|
||||||
|
modelView : EditQualityProfileItemView,
|
||||||
|
selectable: false,
|
||||||
|
sortable : true,
|
||||||
|
sortableOptions : {
|
||||||
|
handle: ".x-drag-handle"
|
||||||
|
},
|
||||||
|
collection : this.allowedCollection
|
||||||
|
} );
|
||||||
|
listViewAllowed.render();
|
||||||
|
|
||||||
|
this.listenTo(listViewAvailable, "doubleClick", this._moveQuality);
|
||||||
|
this.listenTo(listViewAllowed, "doubleClick", this._moveQuality);
|
||||||
|
this.listenTo(listViewAllowed, "sortStop", this._updateModel);
|
||||||
},
|
},
|
||||||
|
|
||||||
_moveQuality: function (event) {
|
_moveQuality: function (event) {
|
||||||
|
|
||||||
var quality;
|
var quality;
|
||||||
var qualityId = event.target.value;
|
var qualityId = event.get('id');
|
||||||
var availableCollection = new Backbone.Collection(this.model.get('available'));
|
|
||||||
availableCollection.comparator = function (model) {
|
if (this.availableCollection.get(qualityId)) {
|
||||||
return model.get('weight');
|
quality = this.availableCollection.get(qualityId);
|
||||||
};
|
var idealIndex = 0;
|
||||||
|
var idealMismatches = 1000;
|
||||||
var allowedCollection = new Backbone.Collection(this.model.get('allowed'));
|
// Insert it at the best possible spot.
|
||||||
allowedCollection.comparator = function (model) {
|
for (var i = 0; i <= this.allowedCollection.length; i++) {
|
||||||
return model.get('weight');
|
var mismatches = 0;
|
||||||
};
|
for (var j = 0; j < i; j++) {
|
||||||
|
if (this.allowedCollection.at(j).get('weight') < quality.get('weight'))
|
||||||
if (availableCollection.get(qualityId)) {
|
mismatches++;
|
||||||
quality = availableCollection.get(qualityId);
|
}
|
||||||
availableCollection.remove(quality);
|
for (j = i; j < this.allowedCollection.length; j++) {
|
||||||
allowedCollection.add(quality);
|
if (this.allowedCollection.at(j).get('weight') > quality.get('weight'))
|
||||||
|
mismatches++;
|
||||||
|
}
|
||||||
|
if (mismatches <= idealMismatches) {
|
||||||
|
idealIndex = i;
|
||||||
|
idealMismatches = mismatches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.availableCollection.remove(quality);
|
||||||
|
this.allowedCollection.add(quality, {at: idealIndex});
|
||||||
}
|
}
|
||||||
else if (allowedCollection.get(qualityId)) {
|
else if (this.allowedCollection.get(qualityId)) {
|
||||||
quality = allowedCollection.get(qualityId);
|
quality = this.allowedCollection.get(qualityId);
|
||||||
|
|
||||||
allowedCollection.remove(quality);
|
this.allowedCollection.remove(quality);
|
||||||
availableCollection.add(quality);
|
this.availableCollection.add(quality);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw 'couldnt find quality id ' + qualityId;
|
throw 'couldnt find quality id ' + qualityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.model.set('available', availableCollection.toJSON());
|
this._updateModel();
|
||||||
this.model.set('allowed', allowedCollection.toJSON());
|
},
|
||||||
|
|
||||||
|
_updateModel: function() {
|
||||||
|
this.model.set('available', this.availableCollection.toJSON().reverse());
|
||||||
|
this.model.set('allowed', this.allowedCollection.toJSON().reverse());
|
||||||
|
|
||||||
this.render();
|
this.render();
|
||||||
},
|
},
|
||||||
|
|
||||||
_saveQualityProfile: function () {
|
_saveQualityProfile: function () {
|
||||||
var self = this;
|
var self = this;
|
||||||
var cutoff = _.findWhere(this.model.get('allowed'), { id: parseInt(this.ui.cutoff.val(), 10)});
|
var cutoff = _.findWhere(this.model.get('allowed'), { id: parseInt(this.ui.cutoff.val(), 10)});
|
||||||
|
|
|
@ -5,27 +5,27 @@ define(
|
||||||
'marionette',
|
'marionette',
|
||||||
'Quality/QualityProfileCollection',
|
'Quality/QualityProfileCollection',
|
||||||
'Settings/Quality/Profile/QualityProfileCollectionView',
|
'Settings/Quality/Profile/QualityProfileCollectionView',
|
||||||
'Quality/QualitySizeCollection',
|
'Quality/QualityDefinitionCollection',
|
||||||
'Settings/Quality/Size/QualitySizeCollectionView'
|
'Settings/Quality/Definition/QualityDefinitionCollectionView'
|
||||||
], function (Marionette, QualityProfileCollection, QualityProfileCollectionView, QualitySizeCollection, QualitySizeCollectionView) {
|
], function (Marionette, QualityProfileCollection, QualityProfileCollectionView, QualityDefinitionCollection, QualityDefinitionCollectionView) {
|
||||||
return Marionette.Layout.extend({
|
return Marionette.Layout.extend({
|
||||||
template: 'Settings/Quality/QualityLayoutTemplate',
|
template: 'Settings/Quality/QualityLayoutTemplate',
|
||||||
|
|
||||||
regions: {
|
regions: {
|
||||||
qualityProfile : '#quality-profile',
|
qualityProfile : '#quality-profile',
|
||||||
qualitySize : '#quality-size'
|
qualityDefinition : '#quality-definition'
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function (options) {
|
initialize: function (options) {
|
||||||
this.settings = options.settings;
|
this.settings = options.settings;
|
||||||
QualityProfileCollection.fetch();
|
QualityProfileCollection.fetch();
|
||||||
this.qualitySizeCollection = new QualitySizeCollection();
|
this.qualityDefinitionCollection = new QualityDefinitionCollection();
|
||||||
this.qualitySizeCollection.fetch();
|
this.qualityDefinitionCollection.fetch();
|
||||||
},
|
},
|
||||||
|
|
||||||
onShow: function () {
|
onShow: function () {
|
||||||
this.qualityProfile.show(new QualityProfileCollectionView({collection: QualityProfileCollection}));
|
this.qualityProfile.show(new QualityProfileCollectionView({collection: QualityProfileCollection}));
|
||||||
this.qualitySize.show(new QualitySizeCollectionView({collection: this.qualitySizeCollection}));
|
this.qualityDefinition.show(new QualityDefinitionCollectionView({collection: this.qualityDefinitionCollection}));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<div class="row advanced-setting">
|
<div class="row advanced-setting">
|
||||||
<div class="span12" id="quality-size"/>
|
<div class="span12" id="quality-definition"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
<fieldset>
|
|
||||||
<legend>Quality Size Limits</legend>
|
|
||||||
<ul class="quality-sizes"/>
|
|
||||||
</fieldset>
|
|
|
@ -1,9 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
define(['marionette', 'Settings/Quality/Size/QualitySizeView'], function (Marionette, QualitySizeView) {
|
|
||||||
return Marionette.CompositeView.extend({
|
|
||||||
itemView : QualitySizeView,
|
|
||||||
itemViewContainer: '.quality-sizes',
|
|
||||||
template : 'Settings/Quality/Size/QualitySizeCollectionTemplate'
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,20 +0,0 @@
|
||||||
<div class="quality-size-item">
|
|
||||||
<h3 class="center-block">{{name}}</h3>
|
|
||||||
<div class="size">
|
|
||||||
<div class="size-value-wrapper">
|
|
||||||
<div>
|
|
||||||
<span class="label label-large label-warning x-size-thirty"
|
|
||||||
name="thirtyMinuteSize"
|
|
||||||
title="Maximum size for a 30 minute episode">
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<span class="label label-large label-info x-size-sixty"
|
|
||||||
name="sixtyMinuteSize"
|
|
||||||
title="Maximum size for a 60 minute episode">
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<input type="text" name="maxSize" class="knob x-knob" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
|
@ -1,61 +0,0 @@
|
||||||
'use strict';
|
|
||||||
|
|
||||||
define(
|
|
||||||
[
|
|
||||||
'marionette',
|
|
||||||
'Mixins/AsModelBoundView',
|
|
||||||
'filesize',
|
|
||||||
'jquery.knob'
|
|
||||||
], function (Marionette, AsModelBoundView, fileSize) {
|
|
||||||
|
|
||||||
var view = Marionette.ItemView.extend({
|
|
||||||
template: 'Settings/Quality/Size/QualitySizeTemplate',
|
|
||||||
tagName : 'li',
|
|
||||||
|
|
||||||
ui: {
|
|
||||||
knob : '.x-knob',
|
|
||||||
thirtyMinuteSize: '.x-size-thirty',
|
|
||||||
sixtyMinuteSize : '.x-size-sixty'
|
|
||||||
},
|
|
||||||
|
|
||||||
events: {
|
|
||||||
'change .x-knob': '_changeMaxSize'
|
|
||||||
},
|
|
||||||
|
|
||||||
initialize: function (options) {
|
|
||||||
this.qualityProfileCollection = options.qualityProfiles;
|
|
||||||
this.filesize = fileSize;
|
|
||||||
},
|
|
||||||
|
|
||||||
onRender: function () {
|
|
||||||
this.ui.knob.knob({
|
|
||||||
min : 0,
|
|
||||||
max : 200,
|
|
||||||
step : 1,
|
|
||||||
cursor : 25,
|
|
||||||
width : 150,
|
|
||||||
stopper : true,
|
|
||||||
displayInput: false
|
|
||||||
});
|
|
||||||
|
|
||||||
this._changeMaxSize();
|
|
||||||
},
|
|
||||||
|
|
||||||
_changeMaxSize: function () {
|
|
||||||
var maxSize = this.model.get('maxSize');
|
|
||||||
var bytes = maxSize * 1024 * 1024;
|
|
||||||
var thirty = fileSize(bytes * 30, 1, false);
|
|
||||||
var sixty = fileSize(bytes * 60, 1, false);
|
|
||||||
|
|
||||||
if (parseInt(maxSize, 10) === 0) {
|
|
||||||
thirty = 'No Limit';
|
|
||||||
sixty = 'No Limit';
|
|
||||||
}
|
|
||||||
|
|
||||||
this.ui.thirtyMinuteSize.html(thirty);
|
|
||||||
this.ui.sixtyMinuteSize.html(sixty);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return AsModelBoundView.call(view);
|
|
||||||
});
|
|
|
@ -1,6 +1,7 @@
|
||||||
@import "../../Shared/Styles/card";
|
@import "../../Shared/Styles/card";
|
||||||
|
@import "../../Content/Bootstrap/mixins";
|
||||||
|
|
||||||
.quality-profiles, .quality-sizes {
|
.quality-profiles {
|
||||||
li {
|
li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
@ -35,41 +36,121 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.quality-size-item {
|
ul.x-available-list, ul.x-allowed-list {
|
||||||
|
min-height: 100px;
|
||||||
|
|
||||||
.card;
|
.user-select(none);
|
||||||
text-align: center;
|
|
||||||
|
margin: 0;
|
||||||
width: 200px;
|
padding: 0;
|
||||||
height: 210px;
|
list-style-type: none;
|
||||||
padding: 10px 15px;
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
h3 {
|
|
||||||
margin-top: 0px;
|
li {
|
||||||
}
|
margin: 2px;
|
||||||
|
padding: 2px;
|
||||||
.size {
|
line-height: 20px;
|
||||||
position: relative;
|
border: 1px solid #AAA;
|
||||||
height: 100px;
|
border-radius: 4px; /* may need vendor varients */
|
||||||
margin: 10px;
|
background: #FAFAFA;
|
||||||
text-align: center;
|
|
||||||
}
|
&:hover {
|
||||||
|
border-color: #888;
|
||||||
.knob {
|
background: #EEE;
|
||||||
box-shadow: none;
|
}
|
||||||
}
|
|
||||||
|
.x-drag-handle, .x-moveleft-handle, .x-moveright-handle {
|
||||||
.size-value-wrapper {
|
opacity: 0.0;
|
||||||
position: absolute;
|
line-height: 20px;
|
||||||
top: 50px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
div {
|
|
||||||
margin-top: 2px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#quality-size {
|
ul.x-available-list li {
|
||||||
overflow: hidden;
|
.x-moveright-handle {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.x-drag-handle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .x-moveright-handle {
|
||||||
|
opacity: 1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul.x-allowed-list li {
|
||||||
|
.x-drag-handle, .x-moveleft-handle {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.x-drag-handle:hover {
|
||||||
|
opacity: 1.0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover .x-moveleft-handle {
|
||||||
|
opacity: 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#quality-definition-list {
|
||||||
|
|
||||||
|
.x-header .row {
|
||||||
|
font-weight: bold;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.x-rows .row {
|
||||||
|
line-height: 30px;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
input {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.size-label-wrapper {
|
||||||
|
line-height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label {
|
||||||
|
min-width: 70px;
|
||||||
|
text-align: center;
|
||||||
|
margin: 0px 1px;
|
||||||
|
padding: 1px 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-slider {
|
||||||
|
position: relative;
|
||||||
|
text-align: left;
|
||||||
|
background-color: #f5f5f5;
|
||||||
|
border-radius: 3px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
height: 8px;
|
||||||
|
|
||||||
|
.ui-slider-range {
|
||||||
|
position: absolute;
|
||||||
|
display: block;
|
||||||
|
background-color: #ddd;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-slider-handle {
|
||||||
|
position: absolute;
|
||||||
|
z-index: 2;
|
||||||
|
width: 6px;
|
||||||
|
height: 12px;
|
||||||
|
cursor: default;
|
||||||
|
background-color: #ccc;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
border-radius: 3px;
|
||||||
|
top: -3px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
'use strict';
|
'use strict';
|
||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
|
'jquery',
|
||||||
'vent',
|
'vent',
|
||||||
'marionette',
|
'marionette',
|
||||||
'backbone',
|
'backbone',
|
||||||
|
@ -17,7 +18,8 @@ define(
|
||||||
'Settings/General/GeneralView',
|
'Settings/General/GeneralView',
|
||||||
'Shared/LoadingView',
|
'Shared/LoadingView',
|
||||||
'Config'
|
'Config'
|
||||||
], function (vent,
|
], function ($,
|
||||||
|
vent,
|
||||||
Marionette,
|
Marionette,
|
||||||
Backbone,
|
Backbone,
|
||||||
SettingsModel,
|
SettingsModel,
|
||||||
|
@ -196,7 +198,7 @@ define(
|
||||||
this.ui.advancedSettings.prop('checked', checked);
|
this.ui.advancedSettings.prop('checked', checked);
|
||||||
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
this.$el.addClass('show-advanced-settings');
|
$('body').addClass('show-advanced-settings');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -205,11 +207,11 @@ define(
|
||||||
Config.setValue('advancedSettings', checked);
|
Config.setValue('advancedSettings', checked);
|
||||||
|
|
||||||
if (checked) {
|
if (checked) {
|
||||||
this.$el.addClass('show-advanced-settings');
|
$('body').addClass('show-advanced-settings');
|
||||||
}
|
}
|
||||||
|
|
||||||
else {
|
else {
|
||||||
this.$el.removeClass('show-advanced-settings');
|
$('body').removeClass('show-advanced-settings');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -2,29 +2,31 @@
|
||||||
require.config({
|
require.config({
|
||||||
|
|
||||||
paths: {
|
paths: {
|
||||||
'backbone' : 'JsLibraries/backbone',
|
'backbone' : 'JsLibraries/backbone',
|
||||||
'moment' : 'JsLibraries/moment',
|
'moment' : 'JsLibraries/moment',
|
||||||
'filesize' : 'JsLibraries/filesize',
|
'filesize' : 'JsLibraries/filesize',
|
||||||
'handlebars' : 'JsLibraries/handlebars.runtime',
|
'handlebars' : 'JsLibraries/handlebars.runtime',
|
||||||
'handlebars.helpers' : 'JsLibraries/handlebars.helpers',
|
'handlebars.helpers' : 'JsLibraries/handlebars.helpers',
|
||||||
'bootstrap' : 'JsLibraries/bootstrap',
|
'bootstrap' : 'JsLibraries/bootstrap',
|
||||||
'backbone.deepmodel' : 'JsLibraries/backbone.deep.model',
|
'backbone.deepmodel' : 'JsLibraries/backbone.deep.model',
|
||||||
'backbone.pageable' : 'JsLibraries/backbone.pageable',
|
'backbone.pageable' : 'JsLibraries/backbone.pageable',
|
||||||
'backbone.validation' : 'JsLibraries/backbone.validation',
|
'backbone.validation' : 'JsLibraries/backbone.validation',
|
||||||
'backbone.modelbinder': 'JsLibraries/backbone.modelbinder',
|
'backbone.modelbinder' : 'JsLibraries/backbone.modelbinder',
|
||||||
'backgrid' : 'JsLibraries/backbone.backgrid',
|
'backbone.collectionview' : 'JsLibraries/backbone.collectionview',
|
||||||
'backgrid.paginator' : 'JsLibraries/backbone.backgrid.paginator',
|
'backgrid' : 'JsLibraries/backbone.backgrid',
|
||||||
'backgrid.selectall' : 'JsLibraries/backbone.backgrid.selectall',
|
'backgrid.paginator' : 'JsLibraries/backbone.backgrid.paginator',
|
||||||
'fullcalendar' : 'JsLibraries/fullcalendar',
|
'backgrid.selectall' : 'JsLibraries/backbone.backgrid.selectall',
|
||||||
'backstrech' : 'JsLibraries/jquery.backstretch',
|
'fullcalendar' : 'JsLibraries/fullcalendar',
|
||||||
'underscore' : 'JsLibraries/lodash.underscore',
|
'backstrech' : 'JsLibraries/jquery.backstretch',
|
||||||
'marionette' : 'JsLibraries/backbone.marionette',
|
'underscore' : 'JsLibraries/lodash.underscore',
|
||||||
'signalR' : 'JsLibraries/jquery.signalR',
|
'marionette' : 'JsLibraries/backbone.marionette',
|
||||||
'jquery.knob' : 'JsLibraries/jquery.knob',
|
'signalR' : 'JsLibraries/jquery.signalR',
|
||||||
'jquery.dotdotdot' : 'JsLibraries/jquery.dotdotdot',
|
'jquery-ui' : 'JsLibraries/jquery-ui',
|
||||||
'messenger' : 'JsLibraries/messenger',
|
'jquery.knob' : 'JsLibraries/jquery.knob',
|
||||||
'jquery' : 'JsLibraries/jquery',
|
'jquery.dotdotdot' : 'JsLibraries/jquery.dotdotdot',
|
||||||
'libs' : 'JsLibraries/',
|
'messenger' : 'JsLibraries/messenger',
|
||||||
|
'jquery' : 'JsLibraries/jquery',
|
||||||
|
'libs' : 'JsLibraries/',
|
||||||
|
|
||||||
'api': 'Require/require.api'
|
'api': 'Require/require.api'
|
||||||
},
|
},
|
||||||
|
@ -105,6 +107,12 @@ require.config({
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'jquery-ui' : {
|
||||||
|
deps:
|
||||||
|
[
|
||||||
|
'jquery'
|
||||||
|
]
|
||||||
|
},
|
||||||
'jquery.knob' : {
|
'jquery.knob' : {
|
||||||
deps:
|
deps:
|
||||||
[
|
[
|
||||||
|
@ -143,6 +151,14 @@ require.config({
|
||||||
'backbone'
|
'backbone'
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
'backbone.collectionview': {
|
||||||
|
deps:
|
||||||
|
[
|
||||||
|
'backbone',
|
||||||
|
'jquery-ui'
|
||||||
|
],
|
||||||
|
exports: 'Backbone.CollectionView'
|
||||||
|
},
|
||||||
backgrid : {
|
backgrid : {
|
||||||
deps:
|
deps:
|
||||||
[
|
[
|
||||||
|
|
Loading…
Reference in New Issue