mirror of
https://github.com/Sonarr/Sonarr.git
synced 2025-01-29 11:23:02 +02:00
Quality Order can now be change on per Quality Profile. Quality Title used in Renaming can now be changed by the user. Both options require Advanced Settings to be enabled.
This commit is contained in:
parent
47a8d93c18
commit
c90791b266
@ -107,7 +107,6 @@ namespace NzbDrone.Api.Test.MappingTests
|
||||
[Test]
|
||||
public void should_map_qualityprofile()
|
||||
{
|
||||
|
||||
var profileResource = new QualityProfileResource
|
||||
{
|
||||
Allowed = Builder<QualityResource>.CreateListOfSize(1).Build().ToList(),
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.EpisodeFiles
|
||||
|
@ -4,6 +4,7 @@ using NzbDrone.Api.Episodes;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Api.Series;
|
||||
using NzbDrone.Core.History;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.History
|
||||
|
@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.Indexers
|
||||
|
@ -166,8 +166,8 @@
|
||||
<Compile Include="NzbDroneApiModule.cs" />
|
||||
<Compile Include="Qualities\QualityProfileResource.cs" />
|
||||
<Compile Include="Qualities\QualityProfileModule.cs" />
|
||||
<Compile Include="Qualities\QualitySizeResource.cs" />
|
||||
<Compile Include="Qualities\QualitySizeModule.cs" />
|
||||
<Compile Include="Qualities\QualityDefinitionResource.cs" />
|
||||
<Compile Include="Qualities\QualityDefinitionModule.cs" />
|
||||
<Compile Include="Extensions\ReqResExtensions.cs" />
|
||||
<Compile Include="Config\SettingsModule.cs" />
|
||||
<Compile Include="System\SystemModule.cs" />
|
||||
|
38
src/NzbDrone.Api/Qualities/QualityDefinitionModule.cs
Normal file
38
src/NzbDrone.Api/Qualities/QualityDefinitionModule.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
18
src/NzbDrone.Api/Qualities/QualityDefinitionResource.cs
Normal file
18
src/NzbDrone.Api/Qualities/QualityDefinitionResource.cs
Normal file
@ -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>
|
||||
{
|
||||
private readonly IQualityProfileService _qualityProfileService;
|
||||
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||
|
||||
public QualityProfileModule(IQualityProfileService qualityProfileService)
|
||||
public QualityProfileModule(IQualityProfileService qualityProfileService,
|
||||
IQualityDefinitionService qualityDefinitionService)
|
||||
: base("/qualityprofiles")
|
||||
{
|
||||
_qualityProfileService = qualityProfileService;
|
||||
_qualityDefinitionService = qualityDefinitionService;
|
||||
|
||||
SharedValidator.RuleFor(c => c.Name).NotEmpty();
|
||||
SharedValidator.RuleFor(c => c.Cutoff).NotNull();
|
||||
@ -44,38 +47,47 @@ namespace NzbDrone.Api.Qualities
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private QualityProfileResource GetById(int id)
|
||||
{
|
||||
return QualityToResource(_qualityProfileService.Get(id));
|
||||
return MapToResource(_qualityProfileService.Get(id));
|
||||
}
|
||||
|
||||
private List<QualityProfileResource> GetAll()
|
||||
{
|
||||
var allProfiles = _qualityProfileService.All();
|
||||
|
||||
|
||||
var profiles = allProfiles.Select(QualityToResource).ToList();
|
||||
var profiles = _qualityProfileService.All().Select(MapToResource).ToList();
|
||||
|
||||
return profiles;
|
||||
}
|
||||
|
||||
private static QualityProfileResource QualityToResource(QualityProfile profile)
|
||||
private QualityProfileResource MapToResource(QualityProfile profile)
|
||||
{
|
||||
return new QualityProfileResource
|
||||
{
|
||||
Cutoff = profile.Cutoff.InjectTo<QualityResource>(),
|
||||
Available = Quality.All()
|
||||
.Where(c => !profile.Allowed.Any(q => c.Id == q.Id))
|
||||
.InjectTo<List<QualityResource>>(),
|
||||
|
||||
Allowed = profile.Allowed.InjectTo<List<QualityResource>>(),
|
||||
Cutoff = MapToResource(_qualityDefinitionService.Get(profile.Cutoff)),
|
||||
Available = _qualityDefinitionService.All()
|
||||
.Where(c => !profile.Allowed.Any(q => c.Quality == q))
|
||||
.Select(MapToResource).ToList(),
|
||||
Allowed = profile.Allowed.Select(_qualityDefinitionService.Get).Select(MapToResource).ToList(),
|
||||
Name = profile.Name,
|
||||
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 Int32 Weight { 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 QualityProfileSchemaModule()
|
||||
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||
|
||||
public QualityProfileSchemaModule(IQualityDefinitionService qualityDefinitionService)
|
||||
: base("/qualityprofiles/schema")
|
||||
{
|
||||
_qualityDefinitionService = qualityDefinitionService;
|
||||
|
||||
GetResourceAll = GetAll;
|
||||
}
|
||||
|
||||
@ -19,21 +23,30 @@ namespace NzbDrone.Api.Qualities
|
||||
profile.Cutoff = Quality.Unknown;
|
||||
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
|
||||
{
|
||||
Available = Quality.All()
|
||||
.Where(c => !profile.Allowed.Any(q => c.Id == q.Id))
|
||||
.InjectTo<List<QualityResource>>(),
|
||||
{
|
||||
Cutoff = QualityToResource(_qualityDefinitionService.Get(profile.Cutoff)),
|
||||
Available = _qualityDefinitionService.All().Select(QualityToResource).ToList(),
|
||||
Allowed = profile.Allowed.Select(_qualityDefinitionService.Get).Select(QualityToResource).ToList(),
|
||||
Name = profile.Name,
|
||||
Id = profile.Id
|
||||
};
|
||||
}
|
||||
|
||||
Allowed = profile.Allowed.InjectTo<List<QualityResource>>(),
|
||||
Name = profile.Name,
|
||||
Id = profile.Id
|
||||
};
|
||||
|
||||
private QualityResource QualityToResource(QualityDefinition config)
|
||||
{
|
||||
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 NzbDrone.Api.REST;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Api.Queue
|
||||
|
@ -75,6 +75,7 @@ namespace NzbDrone.Core.Test.Datastore
|
||||
public void one_to_one()
|
||||
{
|
||||
var episodeFile = Builder<EpisodeFile>.CreateNew()
|
||||
.With(c => c.Quality = new QualityModel())
|
||||
.BuildNew();
|
||||
|
||||
Db.Insert(episodeFile);
|
||||
|
@ -81,25 +81,25 @@ namespace NzbDrone.Core.Test.Datastore.SQLiteMigrationHelperTests
|
||||
[Test]
|
||||
public void should_read_existing_indexes()
|
||||
{
|
||||
var indexes = _subject.GetIndexes("QualitySizes");
|
||||
var indexes = _subject.GetIndexes("QualityDefinitions");
|
||||
|
||||
indexes.Should().NotBeEmpty();
|
||||
|
||||
indexes.Should().OnlyContain(c => c != null);
|
||||
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);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void should_add_indexes_when_creating_new_table()
|
||||
{
|
||||
var columns = _subject.GetColumns("QualitySizes");
|
||||
var indexes = _subject.GetIndexes("QualitySizes");
|
||||
var columns = _subject.GetColumns("QualityDefinitions");
|
||||
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.Select(c=>c.Column).Should().BeEquivalentTo(indexes.Select(c=>c.Column));
|
||||
|
@ -19,7 +19,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
private RemoteEpisode parseResultSingle;
|
||||
private Series series30minutes;
|
||||
private Series series60minutes;
|
||||
private QualitySize qualityType;
|
||||
private QualityDefinition qualityType;
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
@ -47,10 +47,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
.With(c => c.Runtime = 60)
|
||||
.Build();
|
||||
|
||||
qualityType = Builder<QualitySize>.CreateNew()
|
||||
qualityType = Builder<QualityDefinition>.CreateNew()
|
||||
.With(q => q.MinSize = 0)
|
||||
.With(q => q.MaxSize = 10)
|
||||
.With(q => q.QualityId = 1)
|
||||
.With(q => q.Quality = Quality.SDTV)
|
||||
.Build();
|
||||
|
||||
}
|
||||
@ -61,7 +61,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Series = series30minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -80,7 +80,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Series = series60minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -99,7 +99,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Series = series30minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -118,7 +118,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Series = series60minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -135,7 +135,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultMulti.Series = series30minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -154,7 +154,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultMulti.Series = series60minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -173,7 +173,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultMulti.Series = series30minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -192,7 +192,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultMulti.Series = series60minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -211,7 +211,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Series = series30minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -230,7 +230,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Series = series60minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -249,7 +249,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Series = series30minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -270,7 +270,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Series = series60minutes;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -292,7 +292,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Release.Size = 18457280000;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -314,7 +314,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
parseResultSingle.Release.Size = 36857280000;
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -338,7 +338,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
|
||||
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(
|
||||
s => s.IsFirstOrLastEpisodeOfSeason(It.IsAny<int>()))
|
||||
@ -374,7 +374,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
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]
|
||||
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();
|
||||
}
|
||||
|
||||
[Test]
|
||||
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();
|
||||
}
|
||||
|
||||
[Test]
|
||||
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();
|
||||
}
|
||||
|
||||
[Test]
|
||||
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();
|
||||
}
|
||||
|
||||
[Test]
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
};
|
||||
|
||||
_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();
|
||||
|
||||
_parseResultMulti = new RemoteEpisode
|
||||
@ -62,8 +62,6 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
_upgradableQuality = new QualityModel(Quality.SDTV, false);
|
||||
_notupgradableQuality = new QualityModel(Quality.HDTV1080p, true);
|
||||
|
||||
|
||||
|
||||
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(3)).Returns<QualityModel>(null);
|
||||
@ -132,7 +130,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
[Test]
|
||||
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);
|
||||
_upgradableQuality = new QualityModel(Quality.WEBDL1080p, false);
|
||||
|
||||
|
@ -26,7 +26,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
[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()
|
||||
.With(e => e.SeriesId = _series.Id)
|
||||
|
@ -1,4 +1,5 @@
|
||||
using FluentAssertions;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Configuration;
|
||||
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.WEBDL1080p, false, Quality.WEBDL1080p, false, Quality.WEBDL1080p, false }
|
||||
};
|
||||
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void GivenAutoDownloadPropers(bool autoDownloadPropers)
|
||||
{
|
||||
@ -36,7 +43,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
@ -45,8 +54,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
|
||||
{
|
||||
GivenAutoDownloadPropers(false);
|
||||
|
||||
Subject.IsUpgradable(new QualityModel(Quality.DVD, true),
|
||||
new QualityModel(Quality.DVD, false)).Should().BeFalse();
|
||||
var qualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() };
|
||||
|
||||
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 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();
|
||||
|
||||
_parseResultMulti = new RemoteEpisode
|
||||
|
@ -37,6 +37,10 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||
remoteEpisode.Release = new ReleaseInfo();
|
||||
remoteEpisode.Release.PublishDate = DateTime.UtcNow;
|
||||
|
||||
remoteEpisode.Series = Builder<Series>.CreateNew()
|
||||
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||
.Build();
|
||||
|
||||
return remoteEpisode;
|
||||
}
|
||||
|
||||
|
@ -37,6 +37,10 @@ namespace NzbDrone.Core.Test.Download.DownloadApprovedReportsTests
|
||||
remoteEpisode.Release.PublishDate = DateTime.Now.AddDays(-Age);
|
||||
remoteEpisode.Release.Size = size;
|
||||
|
||||
remoteEpisode.Series = Builder<Series>.CreateNew()
|
||||
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||
.Build();
|
||||
|
||||
return remoteEpisode;
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,6 @@ namespace NzbDrone.Core.Test.Download
|
||||
{
|
||||
Mocker.GetMock<IDownloadClient>().Setup(c => c.IsConfigured).Returns(false);
|
||||
|
||||
|
||||
Subject.DownloadReport(_parseResult);
|
||||
|
||||
Mocker.GetMock<IDownloadClient>().Verify(c => c.DownloadNzb(It.IsAny<RemoteEpisode>()), Times.Never());
|
||||
|
@ -80,6 +80,20 @@ namespace NzbDrone.Core.Test.MediaFiles
|
||||
.Returns(true);
|
||||
|
||||
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();
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Test.Common;
|
||||
using FizzWare.NBuilder;
|
||||
|
||||
namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||
{
|
||||
@ -63,7 +64,10 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||
_fail3.Setup(c => c.RejectionReason).Returns("_fail3");
|
||||
|
||||
_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);
|
||||
_localEpisode = new LocalEpisode
|
||||
{
|
||||
@ -80,7 +84,6 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||
Mocker.GetMock<IMediaFileService>()
|
||||
.Setup(c => c.FilterExistingFiles(_videoFiles, It.IsAny<int>()))
|
||||
.Returns(_videoFiles);
|
||||
|
||||
}
|
||||
|
||||
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>()))
|
||||
.Returns(_videoFiles);
|
||||
|
||||
Subject.GetImportDecisions(_videoFiles, new Series(), false);
|
||||
Subject.GetImportDecisions(_videoFiles, _series, false);
|
||||
|
||||
Mocker.GetMock<IParsingService>()
|
||||
.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);
|
||||
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);
|
||||
}
|
||||
@ -187,7 +190,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||
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);
|
||||
}
|
||||
@ -198,7 +201,7 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport
|
||||
GivenSpecifications(_pass1, _pass2, _pass3);
|
||||
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);
|
||||
}
|
||||
|
@ -22,13 +22,15 @@ namespace NzbDrone.Core.Test.MediaFiles.EpisodeImport.Specifications
|
||||
public void Setup()
|
||||
{
|
||||
_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();
|
||||
|
||||
_localEpisode = new LocalEpisode
|
||||
{
|
||||
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>();
|
||||
|
||||
var series = Builder<Series>.CreateNew()
|
||||
.With(e => e.QualityProfile = new QualityProfile { Allowed = Qualities.QualityFixture.GetDefaultQualities() })
|
||||
.Build();
|
||||
|
||||
var episodes = Builder<Episode>.CreateListOfSize(5)
|
||||
|
@ -182,7 +182,7 @@
|
||||
<Compile Include="ParserTests\ParsingServiceTests\MapFixture.cs" />
|
||||
<Compile Include="ParserTests\SeriesTitleInfoFixture.cs" />
|
||||
<Compile Include="Providers\XemProxyFixture.cs" />
|
||||
<Compile Include="Qualities\QualitySizeRepositoryFixture.cs" />
|
||||
<Compile Include="Qualities\QualityDefinitionRepositoryFixture.cs" />
|
||||
<Compile Include="Qualities\QualityProfileRepositoryFixture.cs" />
|
||||
<Compile Include="RootFolderTests\FreeSpaceOnDrivesFixture.cs" />
|
||||
<Compile Include="Qualities\QualityFixture.cs" />
|
||||
@ -217,14 +217,14 @@
|
||||
<Compile Include="TvTests\SeriesServiceTests\UpdateSeriesFixture.cs" />
|
||||
<Compile Include="UpdateTests\UpdateServiceFixture.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="FluentTest.cs" />
|
||||
<Compile Include="InstrumentationTests\DatabaseTargetFixture.cs" />
|
||||
<Compile Include="OrganizerTests\GetNewFilenameFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\MonitoredEpisodeSpecificationFixture.cs" />
|
||||
<Compile Include="DecisionEngineTests\DownloadDecisionMakerFixture.cs" />
|
||||
<Compile Include="TvTests\QualityModelFixture.cs" />
|
||||
<Compile Include="Qualities\QualityModelComparerFixture.cs" />
|
||||
<Compile Include="RootFolderTests\RootFolderServiceFixture.cs" />
|
||||
<Compile Include="HistoryTests\HistoryRepositoryFixture.cs" />
|
||||
<Compile Include="MediaFiles\MediaFileServiceTest.cs" />
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using FizzWare.NBuilder;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
@ -50,6 +51,10 @@ namespace NzbDrone.Core.Test.OrganizerTests
|
||||
.Build();
|
||||
|
||||
_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()
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using FluentAssertions;
|
||||
using NUnit.Framework;
|
||||
using NzbDrone.Core.Qualities;
|
||||
@ -150,9 +151,9 @@ namespace NzbDrone.Core.Test.ParserTests
|
||||
}
|
||||
|
||||
[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);
|
||||
result.Quality.Should().Be(quality);
|
||||
}
|
||||
|
@ -4,25 +4,27 @@ using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
using FluentAssertions;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.Test.Qualities
|
||||
{
|
||||
[TestFixture]
|
||||
|
||||
public class QualitySizeRepositoryFixture : DbTest<QualitySizeRepository, QualitySize>
|
||||
public class QualityDefinitionRepositoryFixture : DbTest<QualityDefinitionRepository, QualityDefinition>
|
||||
{
|
||||
[SetUp]
|
||||
public void Setup()
|
||||
{
|
||||
Mocker.SetConstant<IQualitySizeRepository>(Subject);
|
||||
Mocker.Resolve<QualitySizeService>().Handle(new ApplicationStartedEvent());
|
||||
foreach (var qualityDefault in Quality.DefaultQualityDefinitions)
|
||||
{
|
||||
qualityDefault.Id = 0;
|
||||
Storage.Insert(qualityDefault);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[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();
|
||||
}
|
@ -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 NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Test.Framework;
|
||||
@ -42,81 +44,21 @@ namespace NzbDrone.Core.Test.Qualities
|
||||
i.Should().Be(expected);
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public void Icomparer_greater_test()
|
||||
public static List<Quality> GetDefaultQualities()
|
||||
{
|
||||
var first = Quality.DVD;
|
||||
var second = Quality.Bluray1080p;
|
||||
|
||||
second.Should().BeGreaterThan(first);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void Icomparer_lesser()
|
||||
{
|
||||
var first = Quality.DVD;
|
||||
var second = 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();
|
||||
return new List<Quality>
|
||||
{
|
||||
Quality.SDTV,
|
||||
Quality.WEBDL480p,
|
||||
Quality.DVD,
|
||||
Quality.HDTV720p,
|
||||
Quality.HDTV1080p,
|
||||
Quality.RAWHD,
|
||||
Quality.WEBDL720p,
|
||||
Quality.Bluray720p,
|
||||
Quality.WEBDL1080p,
|
||||
Quality.Bluray1080p
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
117
src/NzbDrone.Core.Test/Qualities/QualityModelComparerFixture.cs
Normal file
117
src/NzbDrone.Core.Test/Qualities/QualityModelComparerFixture.cs
Normal file
@ -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
|
||||
{
|
||||
[TestFixture]
|
||||
|
||||
public class QualityProfileRepositoryFixture : DbTest<QualityProfileRepository, QualityProfile>
|
||||
{
|
||||
[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.Collections.Generic;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Blacklisting
|
||||
|
@ -2,6 +2,8 @@
|
||||
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
|
||||
{
|
||||
@ -26,7 +28,7 @@ namespace NzbDrone.Core.Datastore.Converters
|
||||
|
||||
public object ToDB(object clrValue)
|
||||
{
|
||||
if(clrValue == null) return 0;
|
||||
if(clrValue == DBNull.Value) return 0;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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<QualitySize>().RegisterModel("QualitySizes");
|
||||
Mapper.Entity<QualityDefinition>().RegisterModel("QualityDefinitions");
|
||||
|
||||
Mapper.Entity<Log>().RegisterModel("Logs");
|
||||
|
||||
@ -81,6 +81,8 @@ namespace NzbDrone.Core.Datastore
|
||||
MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter());
|
||||
MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter());
|
||||
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(List<int>), new EmbeddedDocumentConverter());
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
{
|
||||
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 IsProperUpgrade(QualityModel currentQuality, QualityModel newQuality);
|
||||
}
|
||||
@ -20,11 +20,12 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public bool IsUpgradable(QualityModel currentQuality, QualityModel newQuality = null)
|
||||
public bool IsUpgradable(QualityProfile profile, QualityModel currentQuality, QualityModel 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");
|
||||
return false;
|
||||
@ -41,7 +42,9 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
|
||||
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))
|
||||
{
|
||||
@ -57,7 +60,9 @@ namespace NzbDrone.Core.DecisionEngine
|
||||
|
||||
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");
|
||||
return true;
|
||||
|
@ -9,13 +9,13 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
public class AcceptableSizeSpecification : IDecisionEngineSpecification
|
||||
{
|
||||
private readonly IQualitySizeService _qualityTypeProvider;
|
||||
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||
private readonly IEpisodeService _episodeService;
|
||||
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;
|
||||
_logger = logger;
|
||||
}
|
||||
@ -44,15 +44,15 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
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.");
|
||||
return true;
|
||||
}
|
||||
|
||||
var maxSize = qualityType.MaxSize.Megabytes();
|
||||
var maxSize = qualityDefinition.MaxSize.Megabytes();
|
||||
|
||||
//Multiply maxSize by Series.Runtime
|
||||
maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;
|
||||
|
@ -4,6 +4,8 @@ using NLog;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.IndexerSearch.Definitions;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
@ -44,7 +46,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
private bool IsInQueue(RemoteEpisode newEpisode, IEnumerable<RemoteEpisode> queue)
|
||||
{
|
||||
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());
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications.RssSync
|
||||
if (bestQualityInHistory != null)
|
||||
{
|
||||
_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;
|
||||
}
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
|
||||
{
|
||||
_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;
|
||||
}
|
||||
|
@ -3,6 +3,8 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.DecisionEngine.Specifications;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
{
|
||||
@ -16,7 +18,7 @@ namespace NzbDrone.Core.Download
|
||||
private readonly IDownloadService _downloadService;
|
||||
private readonly Logger _logger;
|
||||
|
||||
public DownloadApprovedReports(IDownloadService downloadService, Logger logger)
|
||||
public DownloadApprovedReports(IDownloadService downloadService, Logger logger)
|
||||
{
|
||||
_downloadService = downloadService;
|
||||
_logger = logger;
|
||||
@ -57,11 +59,13 @@ namespace NzbDrone.Core.Download
|
||||
public List<DownloadDecision> GetQualifiedReports(IEnumerable<DownloadDecision> decisions)
|
||||
{
|
||||
return decisions.Where(c => c.Approved && c.RemoteEpisode.Episodes.Any())
|
||||
.OrderByDescending(c => c.RemoteEpisode.ParsedEpisodeInfo.Quality)
|
||||
.ThenBy(c => c.RemoteEpisode.Episodes.Select(e => e.EpisodeNumber).MinOrDefault())
|
||||
.ThenBy(c => c.RemoteEpisode.Release.Size.Round(200.Megabytes()) / c.RemoteEpisode.Episodes.Count)
|
||||
.ThenBy(c => c.RemoteEpisode.Release.Age)
|
||||
.ToList();
|
||||
.GroupBy(c => c.RemoteEpisode.Series.Id, (i,s) => s
|
||||
.OrderByDescending(c => c.RemoteEpisode.ParsedEpisodeInfo.Quality, new QualityModelComparer(s.First().RemoteEpisode.Series.QualityProfile))
|
||||
.ThenBy(c => c.RemoteEpisode.Episodes.Select(e => e.EpisodeNumber).MinOrDefault())
|
||||
.ThenBy(c => c.RemoteEpisode.Release.Size.Round(200.Megabytes()) / c.RemoteEpisode.Episodes.Count)
|
||||
.ThenBy(c => c.RemoteEpisode.Release.Age))
|
||||
.SelectMany(c => c)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Common.Messaging;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Download
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.History
|
||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using Marr.Data.QGen;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.History
|
||||
|
@ -6,6 +6,7 @@ using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.History
|
||||
|
@ -10,6 +10,7 @@ using NzbDrone.Core.MediaFiles.Commands;
|
||||
using NzbDrone.Core.MediaFiles.EpisodeImport;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles
|
||||
|
@ -7,6 +7,8 @@ using NzbDrone.Common;
|
||||
using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
@ -40,8 +42,11 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
public List<ImportDecision> Import(List<ImportDecision> decisions, bool newDownload = false)
|
||||
{
|
||||
var qualifiedImports = decisions.Where(c => c.Approved)
|
||||
.OrderByDescending(c => c.LocalEpisode.Quality)
|
||||
.ThenByDescending(c => c.LocalEpisode.Size);
|
||||
.GroupBy(c => c.LocalEpisode.Series.Id, (i, s) => s
|
||||
.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>();
|
||||
|
||||
|
@ -7,6 +7,7 @@ using NzbDrone.Common.Disk;
|
||||
using NzbDrone.Core.DecisionEngine;
|
||||
using NzbDrone.Core.Parser;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
|
||||
@ -60,7 +61,7 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport
|
||||
|
||||
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);
|
||||
parsedEpisode.Quality = quality;
|
||||
|
@ -1,6 +1,8 @@
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Parser.Model;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
{
|
||||
@ -17,7 +19,8 @@ namespace NzbDrone.Core.MediaFiles.EpisodeImport.Specifications
|
||||
|
||||
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);
|
||||
return false;
|
||||
|
@ -5,6 +5,7 @@ using NLog;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.MediaFiles.Events;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Notifications
|
||||
|
@ -145,6 +145,8 @@
|
||||
<Compile Include="Datastore\Converters\BooleanIntConverter.cs" />
|
||||
<Compile Include="Datastore\Converters\ProviderSettingConverter.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\EmbeddedDocumentConverter.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\034_remove_series_contraints.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\MigrationController.cs" />
|
||||
<Compile Include="Datastore\Migration\Framework\MigrationExtension.cs" />
|
||||
@ -456,12 +460,13 @@
|
||||
<Compile Include="Parser\Parser.cs" />
|
||||
<Compile Include="Parser\ParsingService.cs" />
|
||||
<Compile Include="Parser\QualityParser.cs" />
|
||||
<Compile Include="Qualities\QualityModelComparer.cs" />
|
||||
<Compile Include="Rest\JsonNetSerializer.cs" />
|
||||
<Compile Include="RootFolders\RootFolderRepository.cs" />
|
||||
<Compile Include="ThingiProvider\ConfigContractNotFoundException.cs" />
|
||||
<Compile Include="ThingiProvider\IProvider.cs" />
|
||||
<Compile Include="Qualities\QualityProfileInUseException.cs" />
|
||||
<Compile Include="Qualities\QualitySizeRepository.cs" />
|
||||
<Compile Include="Qualities\QualityDefinitionRepository.cs" />
|
||||
<Compile Include="Qualities\QualityProfileRepository.cs" />
|
||||
<Compile Include="Queue\Queue.cs" />
|
||||
<Compile Include="Queue\UpdateQueueEvent.cs" />
|
||||
@ -489,7 +494,7 @@
|
||||
<Compile Include="Tv\Commands\RefreshSeriesCommand.cs" />
|
||||
<Compile Include="Tv\RefreshEpisodeService.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\SabHistoryItem.cs" />
|
||||
<Compile Include="Download\Clients\Sabnzbd\SabHistory.cs" />
|
||||
@ -575,7 +580,7 @@
|
||||
<Compile Include="Qualities\QualityProfileService.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Qualities\QualitySizeService.cs">
|
||||
<Compile Include="Qualities\QualityDefinitionService.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="RootFolders\UnmappedFolder.cs" />
|
||||
@ -597,7 +602,7 @@
|
||||
<Compile Include="Tv\Episode.cs" />
|
||||
<Compile Include="Instrumentation\Log.cs" />
|
||||
<Compile Include="History\History.cs" />
|
||||
<Compile Include="Qualities\QualitySize.cs" />
|
||||
<Compile Include="Qualities\QualityDefinition.cs" />
|
||||
<Compile Include="Qualities\QualityProfile.cs" />
|
||||
<Compile Include="RootFolders\RootFolder.cs" />
|
||||
<Compile Include="Tv\Series.cs" />
|
||||
|
@ -6,6 +6,7 @@ using System.Text.RegularExpressions;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.MediaFiles;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Organizer
|
||||
@ -22,6 +23,7 @@ namespace NzbDrone.Core.Organizer
|
||||
public class FileNameBuilder : IBuildFileNames
|
||||
{
|
||||
private readonly INamingConfigService _namingConfigService;
|
||||
private readonly IQualityDefinitionService _qualityDefinitionService;
|
||||
private readonly ICached<EpisodeFormat> _patternCache;
|
||||
private readonly Logger _logger;
|
||||
|
||||
@ -43,10 +45,12 @@ namespace NzbDrone.Core.Organizer
|
||||
RegexOptions.Compiled | RegexOptions.IgnoreCase);
|
||||
|
||||
public FileNameBuilder(INamingConfigService namingConfigService,
|
||||
IQualityDefinitionService qualityDefinitionService,
|
||||
ICacheManger cacheManger,
|
||||
Logger logger)
|
||||
{
|
||||
_namingConfigService = namingConfigService;
|
||||
_qualityDefinitionService = qualityDefinitionService;
|
||||
_patternCache = cacheManger.GetCache<EpisodeFormat>(GetType());
|
||||
_logger = logger;
|
||||
}
|
||||
@ -87,12 +91,10 @@ namespace NzbDrone.Core.Organizer
|
||||
sortedEpisodes.First().Title
|
||||
};
|
||||
|
||||
var tokenValues = new Dictionary<string, string>(FilenameBuilderTokenEqualityComparer.Instance)
|
||||
{
|
||||
{"{Series Title}", series.Title},
|
||||
{"Original Title", episodeFile.SceneName}
|
||||
};
|
||||
var tokenValues = new Dictionary<string, string>(FilenameBuilderTokenEqualityComparer.Instance);
|
||||
|
||||
tokenValues.Add("{Series Title}", series.Title);
|
||||
tokenValues.Add("{Original Title}", episodeFile.SceneName);
|
||||
tokenValues.Add("{Release Group}", episodeFile.ReleaseGroup);
|
||||
|
||||
if (series.SeriesType == SeriesTypes.Daily)
|
||||
@ -146,7 +148,7 @@ namespace NzbDrone.Core.Organizer
|
||||
}
|
||||
|
||||
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());
|
||||
@ -341,6 +343,14 @@ namespace NzbDrone.Core.Organizer
|
||||
|
||||
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
|
||||
|
@ -1,7 +1,8 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Tv;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Parser.Model
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.Parser.Model
|
||||
|
@ -2,65 +2,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Datastore.Converters;
|
||||
|
||||
|
||||
namespace NzbDrone.Core.Qualities
|
||||
{
|
||||
public class Quality : IComparable<Quality>, IEmbeddedDocument
|
||||
public class Quality : IEmbeddedDocument, IEquatable<Quality>
|
||||
{
|
||||
public int Id { 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);
|
||||
}
|
||||
|
||||
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;
|
||||
Id = id;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
@ -70,110 +29,96 @@ namespace NzbDrone.Core.Qualities
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked // Overflow is fine, just wrap
|
||||
{
|
||||
int hash = 17;
|
||||
hash = hash * 23 + Weight.GetHashCode();
|
||||
return hash;
|
||||
}
|
||||
return Id.GetHashCode();
|
||||
}
|
||||
|
||||
public bool Equals(Quality other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return Equals(other.Weight, Weight);
|
||||
return Id.Equals(other.Id);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
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 }; }
|
||||
}
|
||||
|
||||
public static Quality HDTV720p
|
||||
{
|
||||
get { return new Quality { Id = 4, Name = "HDTV-720p", Weight = 4 }; }
|
||||
}
|
||||
|
||||
public static Quality HDTV1080p
|
||||
{
|
||||
get { return new Quality { Id = 9, Name = "HDTV-1080p", Weight = 5 }; }
|
||||
}
|
||||
|
||||
public static Quality RAWHD
|
||||
{
|
||||
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
|
||||
};
|
||||
get
|
||||
{
|
||||
return new HashSet<QualityDefinition>
|
||||
{
|
||||
new QualityDefinition(Quality.SDTV) { /*Title = "SDTV", */ Weight = 1, MinSize=0, MaxSize=100 },
|
||||
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 },
|
||||
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 },
|
||||
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 },
|
||||
new QualityDefinition(Quality.Bluray1080p) { /*Title = "1080p BluRay",*/ Weight = 10, MinSize=0, MaxSize=100 }
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static Quality FindById(int id)
|
||||
{
|
||||
if (id == 0) return Unknown;
|
||||
|
||||
var quality = All().SingleOrDefault(q => q.Id == id);
|
||||
Quality quality = All.FirstOrDefault(v => v.Id == id);
|
||||
|
||||
if (quality == null)
|
||||
throw new ArgumentException("ID does not match a known quality", "id");
|
||||
|
||||
|
||||
return quality;
|
||||
}
|
||||
|
||||
|
33
src/NzbDrone.Core/Qualities/QualityDefinition.cs
Normal file
33
src/NzbDrone.Core/Qualities/QualityDefinition.cs
Normal file
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
33
src/NzbDrone.Core/Qualities/QualityDefinitionRepository.cs
Normal file
33
src/NzbDrone.Core/Qualities/QualityDefinitionRepository.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
101
src/NzbDrone.Core/Qualities/QualityDefinitionService.cs
Normal file
101
src/NzbDrone.Core/Qualities/QualityDefinitionService.cs
Normal file
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
73
src/NzbDrone.Core/Qualities/QualityModel.cs
Normal file
73
src/NzbDrone.Core/Qualities/QualityModel.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
67
src/NzbDrone.Core/Qualities/QualityModelComparer.cs
Normal file
67
src/NzbDrone.Core/Qualities/QualityModelComparer.cs
Normal file
@ -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 NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Qualities;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
1072
src/UI/JsLibraries/backbone.collectionview.js
Normal file
1072
src/UI/JsLibraries/backbone.collectionview.js
Normal file
File diff suppressed because it is too large
Load Diff
4233
src/UI/JsLibraries/jquery-ui.js
vendored
Normal file
4233
src/UI/JsLibraries/jquery-ui.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
11
src/UI/Quality/QualityDefinitionCollection.js
Normal file
11
src/UI/Quality/QualityDefinitionCollection.js
Normal file
@ -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,
|
||||
|
||||
initialize: function () {
|
||||
var name = this.get('name');
|
||||
var name = this.get('quality').name;
|
||||
|
||||
this.successMessage = 'Saved ' + name + ' size settings';
|
||||
this.errorMessage = 'Couldn\'t save ' + name + ' size settings';
|
||||
this.successMessage = 'Saved ' + name + ' quality settings';
|
||||
this.errorMessage = 'Couldn\'t save ' + name + ' quality settings';
|
||||
|
||||
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>
|
86
src/UI/Settings/Quality/Definition/QualityDefinitionView.js
Normal file
86
src/UI/Settings/Quality/Definition/QualityDefinitionView.js
Normal file
@ -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 class="offset1 span3">
|
||||
<div class="offset1 span2">
|
||||
<h3>Available</h3>
|
||||
<select multiple="multiple" class="x-available-list">
|
||||
{{#each available}}
|
||||
<option value="{{id}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
<ul class="x-available-list">
|
||||
</ul>
|
||||
</div>
|
||||
<div class="span3">
|
||||
<div class="control-group">
|
||||
<div class="controls">
|
||||
<h3>Allowed</h3>
|
||||
<select multiple="multiple" class="x-allowed-list" validation-name="allowed">
|
||||
{{#each allowed}}
|
||||
<option value="{{id}}">{{name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="span2">
|
||||
<h3>Allowed</h3>
|
||||
<ul class="x-allowed-list" validation-name="allowed">
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -4,63 +4,113 @@ define(
|
||||
'vent',
|
||||
'marionette',
|
||||
'backbone',
|
||||
'backbone.collectionview',
|
||||
'Settings/Quality/Profile/EditQualityProfileItemView',
|
||||
'Mixins/AsModelBoundView',
|
||||
'Mixins/AsValidatedView',
|
||||
'underscore'
|
||||
], function (vent, Marionette, Backbone, AsModelBoundView, AsValidatedView, _) {
|
||||
], function (vent, Marionette, Backbone, BackboneSortableCollectionView, EditQualityProfileItemView, AsModelBoundView, AsValidatedView, _) {
|
||||
|
||||
var view = Marionette.ItemView.extend({
|
||||
template: 'Settings/Quality/Profile/EditQualityProfileTemplate',
|
||||
|
||||
ui: {
|
||||
cutoff: '.x-cutoff'
|
||||
available: '.x-available-list',
|
||||
allowed : '.x-allowed-list',
|
||||
cutoff : '.x-cutoff'
|
||||
},
|
||||
|
||||
|
||||
events: {
|
||||
'click .x-save' : '_saveQualityProfile',
|
||||
'dblclick .x-available-list': '_moveQuality',
|
||||
'dblclick .x-allowed-list' : '_moveQuality'
|
||||
//'click .x-qualityitem' : '_moveQuality',
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
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) {
|
||||
|
||||
var quality;
|
||||
var qualityId = event.target.value;
|
||||
var availableCollection = new Backbone.Collection(this.model.get('available'));
|
||||
availableCollection.comparator = function (model) {
|
||||
return model.get('weight');
|
||||
};
|
||||
|
||||
var allowedCollection = new Backbone.Collection(this.model.get('allowed'));
|
||||
allowedCollection.comparator = function (model) {
|
||||
return model.get('weight');
|
||||
};
|
||||
|
||||
if (availableCollection.get(qualityId)) {
|
||||
quality = availableCollection.get(qualityId);
|
||||
availableCollection.remove(quality);
|
||||
allowedCollection.add(quality);
|
||||
var qualityId = event.get('id');
|
||||
|
||||
if (this.availableCollection.get(qualityId)) {
|
||||
quality = this.availableCollection.get(qualityId);
|
||||
var idealIndex = 0;
|
||||
var idealMismatches = 1000;
|
||||
// Insert it at the best possible spot.
|
||||
for (var i = 0; i <= this.allowedCollection.length; i++) {
|
||||
var mismatches = 0;
|
||||
for (var j = 0; j < i; j++) {
|
||||
if (this.allowedCollection.at(j).get('weight') < quality.get('weight'))
|
||||
mismatches++;
|
||||
}
|
||||
for (j = i; j < this.allowedCollection.length; j++) {
|
||||
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)) {
|
||||
quality = allowedCollection.get(qualityId);
|
||||
else if (this.allowedCollection.get(qualityId)) {
|
||||
quality = this.allowedCollection.get(qualityId);
|
||||
|
||||
allowedCollection.remove(quality);
|
||||
availableCollection.add(quality);
|
||||
this.allowedCollection.remove(quality);
|
||||
this.availableCollection.add(quality);
|
||||
}
|
||||
else {
|
||||
throw 'couldnt find quality id ' + qualityId;
|
||||
}
|
||||
|
||||
this.model.set('available', availableCollection.toJSON());
|
||||
this.model.set('allowed', allowedCollection.toJSON());
|
||||
|
||||
|
||||
this._updateModel();
|
||||
},
|
||||
|
||||
_updateModel: function() {
|
||||
this.model.set('available', this.availableCollection.toJSON().reverse());
|
||||
this.model.set('allowed', this.allowedCollection.toJSON().reverse());
|
||||
|
||||
this.render();
|
||||
},
|
||||
|
||||
|
||||
_saveQualityProfile: function () {
|
||||
var self = this;
|
||||
var cutoff = _.findWhere(this.model.get('allowed'), { id: parseInt(this.ui.cutoff.val(), 10)});
|
||||
|
@ -5,27 +5,27 @@ define(
|
||||
'marionette',
|
||||
'Quality/QualityProfileCollection',
|
||||
'Settings/Quality/Profile/QualityProfileCollectionView',
|
||||
'Quality/QualitySizeCollection',
|
||||
'Settings/Quality/Size/QualitySizeCollectionView'
|
||||
], function (Marionette, QualityProfileCollection, QualityProfileCollectionView, QualitySizeCollection, QualitySizeCollectionView) {
|
||||
'Quality/QualityDefinitionCollection',
|
||||
'Settings/Quality/Definition/QualityDefinitionCollectionView'
|
||||
], function (Marionette, QualityProfileCollection, QualityProfileCollectionView, QualityDefinitionCollection, QualityDefinitionCollectionView) {
|
||||
return Marionette.Layout.extend({
|
||||
template: 'Settings/Quality/QualityLayoutTemplate',
|
||||
|
||||
regions: {
|
||||
qualityProfile : '#quality-profile',
|
||||
qualitySize : '#quality-size'
|
||||
qualityProfile : '#quality-profile',
|
||||
qualityDefinition : '#quality-definition'
|
||||
},
|
||||
|
||||
initialize: function (options) {
|
||||
this.settings = options.settings;
|
||||
QualityProfileCollection.fetch();
|
||||
this.qualitySizeCollection = new QualitySizeCollection();
|
||||
this.qualitySizeCollection.fetch();
|
||||
this.qualityDefinitionCollection = new QualityDefinitionCollection();
|
||||
this.qualityDefinitionCollection.fetch();
|
||||
},
|
||||
|
||||
onShow: function () {
|
||||
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/>
|
||||
|
||||
<div class="row advanced-setting">
|
||||
<div class="span12" id="quality-size"/>
|
||||
<div class="span12" id="quality-definition"/>
|
||||
</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 "../../Content/Bootstrap/mixins";
|
||||
|
||||
.quality-profiles, .quality-sizes {
|
||||
.quality-profiles {
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
@ -35,41 +36,121 @@
|
||||
}
|
||||
}
|
||||
|
||||
.quality-size-item {
|
||||
ul.x-available-list, ul.x-allowed-list {
|
||||
min-height: 100px;
|
||||
|
||||
.card;
|
||||
text-align: center;
|
||||
|
||||
width: 200px;
|
||||
height: 210px;
|
||||
padding: 10px 15px;
|
||||
|
||||
h3 {
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.size {
|
||||
position: relative;
|
||||
height: 100px;
|
||||
margin: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.knob {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.size-value-wrapper {
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
width: 100%;
|
||||
|
||||
div {
|
||||
margin-top: 2px;
|
||||
.user-select(none);
|
||||
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
|
||||
li {
|
||||
margin: 2px;
|
||||
padding: 2px;
|
||||
line-height: 20px;
|
||||
border: 1px solid #AAA;
|
||||
border-radius: 4px; /* may need vendor varients */
|
||||
background: #FAFAFA;
|
||||
|
||||
&:hover {
|
||||
border-color: #888;
|
||||
background: #EEE;
|
||||
}
|
||||
|
||||
.x-drag-handle, .x-moveleft-handle, .x-moveright-handle {
|
||||
opacity: 0.0;
|
||||
line-height: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#quality-size {
|
||||
overflow: hidden;
|
||||
ul.x-available-list li {
|
||||
.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';
|
||||
define(
|
||||
[
|
||||
'jquery',
|
||||
'vent',
|
||||
'marionette',
|
||||
'backbone',
|
||||
@ -17,7 +18,8 @@ define(
|
||||
'Settings/General/GeneralView',
|
||||
'Shared/LoadingView',
|
||||
'Config'
|
||||
], function (vent,
|
||||
], function ($,
|
||||
vent,
|
||||
Marionette,
|
||||
Backbone,
|
||||
SettingsModel,
|
||||
@ -196,7 +198,7 @@ define(
|
||||
this.ui.advancedSettings.prop('checked', checked);
|
||||
|
||||
if (checked) {
|
||||
this.$el.addClass('show-advanced-settings');
|
||||
$('body').addClass('show-advanced-settings');
|
||||
}
|
||||
},
|
||||
|
||||
@ -205,11 +207,11 @@ define(
|
||||
Config.setValue('advancedSettings', checked);
|
||||
|
||||
if (checked) {
|
||||
this.$el.addClass('show-advanced-settings');
|
||||
$('body').addClass('show-advanced-settings');
|
||||
}
|
||||
|
||||
else {
|
||||
this.$el.removeClass('show-advanced-settings');
|
||||
$('body').removeClass('show-advanced-settings');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -2,29 +2,31 @@
|
||||
require.config({
|
||||
|
||||
paths: {
|
||||
'backbone' : 'JsLibraries/backbone',
|
||||
'moment' : 'JsLibraries/moment',
|
||||
'filesize' : 'JsLibraries/filesize',
|
||||
'handlebars' : 'JsLibraries/handlebars.runtime',
|
||||
'handlebars.helpers' : 'JsLibraries/handlebars.helpers',
|
||||
'bootstrap' : 'JsLibraries/bootstrap',
|
||||
'backbone.deepmodel' : 'JsLibraries/backbone.deep.model',
|
||||
'backbone.pageable' : 'JsLibraries/backbone.pageable',
|
||||
'backbone.validation' : 'JsLibraries/backbone.validation',
|
||||
'backbone.modelbinder': 'JsLibraries/backbone.modelbinder',
|
||||
'backgrid' : 'JsLibraries/backbone.backgrid',
|
||||
'backgrid.paginator' : 'JsLibraries/backbone.backgrid.paginator',
|
||||
'backgrid.selectall' : 'JsLibraries/backbone.backgrid.selectall',
|
||||
'fullcalendar' : 'JsLibraries/fullcalendar',
|
||||
'backstrech' : 'JsLibraries/jquery.backstretch',
|
||||
'underscore' : 'JsLibraries/lodash.underscore',
|
||||
'marionette' : 'JsLibraries/backbone.marionette',
|
||||
'signalR' : 'JsLibraries/jquery.signalR',
|
||||
'jquery.knob' : 'JsLibraries/jquery.knob',
|
||||
'jquery.dotdotdot' : 'JsLibraries/jquery.dotdotdot',
|
||||
'messenger' : 'JsLibraries/messenger',
|
||||
'jquery' : 'JsLibraries/jquery',
|
||||
'libs' : 'JsLibraries/',
|
||||
'backbone' : 'JsLibraries/backbone',
|
||||
'moment' : 'JsLibraries/moment',
|
||||
'filesize' : 'JsLibraries/filesize',
|
||||
'handlebars' : 'JsLibraries/handlebars.runtime',
|
||||
'handlebars.helpers' : 'JsLibraries/handlebars.helpers',
|
||||
'bootstrap' : 'JsLibraries/bootstrap',
|
||||
'backbone.deepmodel' : 'JsLibraries/backbone.deep.model',
|
||||
'backbone.pageable' : 'JsLibraries/backbone.pageable',
|
||||
'backbone.validation' : 'JsLibraries/backbone.validation',
|
||||
'backbone.modelbinder' : 'JsLibraries/backbone.modelbinder',
|
||||
'backbone.collectionview' : 'JsLibraries/backbone.collectionview',
|
||||
'backgrid' : 'JsLibraries/backbone.backgrid',
|
||||
'backgrid.paginator' : 'JsLibraries/backbone.backgrid.paginator',
|
||||
'backgrid.selectall' : 'JsLibraries/backbone.backgrid.selectall',
|
||||
'fullcalendar' : 'JsLibraries/fullcalendar',
|
||||
'backstrech' : 'JsLibraries/jquery.backstretch',
|
||||
'underscore' : 'JsLibraries/lodash.underscore',
|
||||
'marionette' : 'JsLibraries/backbone.marionette',
|
||||
'signalR' : 'JsLibraries/jquery.signalR',
|
||||
'jquery-ui' : 'JsLibraries/jquery-ui',
|
||||
'jquery.knob' : 'JsLibraries/jquery.knob',
|
||||
'jquery.dotdotdot' : 'JsLibraries/jquery.dotdotdot',
|
||||
'messenger' : 'JsLibraries/messenger',
|
||||
'jquery' : 'JsLibraries/jquery',
|
||||
'libs' : 'JsLibraries/',
|
||||
|
||||
'api': 'Require/require.api'
|
||||
},
|
||||
@ -105,6 +107,12 @@ require.config({
|
||||
|
||||
}
|
||||
},
|
||||
'jquery-ui' : {
|
||||
deps:
|
||||
[
|
||||
'jquery'
|
||||
]
|
||||
},
|
||||
'jquery.knob' : {
|
||||
deps:
|
||||
[
|
||||
@ -143,6 +151,14 @@ require.config({
|
||||
'backbone'
|
||||
]
|
||||
},
|
||||
'backbone.collectionview': {
|
||||
deps:
|
||||
[
|
||||
'backbone',
|
||||
'jquery-ui'
|
||||
],
|
||||
exports: 'Backbone.CollectionView'
|
||||
},
|
||||
backgrid : {
|
||||
deps:
|
||||
[
|
||||
|
Loading…
x
Reference in New Issue
Block a user