Fixed: Unlimited MaxSize and increased granularity.

fixes #337
This commit is contained in:
Taloth Saldono 2015-05-20 00:57:01 +02:00
parent e5278a0243
commit ab1e82414b
14 changed files with 249 additions and 56 deletions

View File

@ -8,11 +8,11 @@ namespace NzbDrone.Api.Qualities
{
public Quality Quality { get; set; }
public String Title { get; set; }
public string Title { get; set; }
public Int32 Weight { get; set; }
public int Weight { get; set; }
public Int32 MinSize { get; set; }
public Int32 MaxSize { get; set; }
public double? MinSize { get; set; }
public double? MaxSize { get; set; }
}
}

View File

@ -0,0 +1,103 @@
using System;
using System.Linq;
using FluentAssertions;
using NUnit.Framework;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Test.Framework;
namespace NzbDrone.Core.Test.Datastore.Migration
{
[TestFixture]
public class update_quality_minmax_size : MigrationTest<Core.Datastore.Migration.update_quality_minmax_size>
{
[Test]
public void should_not_fail_if_empty()
{
WithTestDb(c =>
{
});
var items = Mocker.Resolve<QualityDefinitionRepository>().All();
items.Should().HaveCount(0);
}
[Test]
public void should_set_rawhd_to_null()
{
WithTestDb(c =>
{
c.Insert.IntoTable("QualityDefinitions").Row(new
{
Quality = 1,
Title = "SDTV",
MinSize = 0,
MaxSize = 100
})
.Row(new
{
Quality = 10,
Title = "RawHD",
MinSize = 0,
MaxSize = 100
});
});
var items = Mocker.Resolve<QualityDefinitionRepository>().All();
items.Should().HaveCount(2);
items.First(v => v.Quality.Id == 10).MaxSize.Should().NotHaveValue();
}
[Test]
public void should_set_zero_maxsize_to_null()
{
WithTestDb(c =>
{
c.Insert.IntoTable("QualityDefinitions").Row(new
{
Quality = 1,
Title = "SDTV",
MinSize = 0,
MaxSize = 0
});
});
var items = Mocker.Resolve<QualityDefinitionRepository>().All();
items.Should().HaveCount(1);
items.First(v => v.Quality.Id == 1).MaxSize.Should().NotHaveValue();
}
[Test]
public void should_preserve_values()
{
WithTestDb(c =>
{
c.Insert.IntoTable("QualityDefinitions").Row(new
{
Quality = 1,
Title = "SDTV",
MinSize = 0,
MaxSize = 100
})
.Row(new
{
Quality = 10,
Title = "RawHD",
MinSize = 0,
MaxSize = 100
});
});
var items = Mocker.Resolve<QualityDefinitionRepository>().All();
items.Should().HaveCount(2);
items.First(v => v.Quality.Id == 1).MaxSize.Should().Be(100);
}
}
}

View File

@ -1,4 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using FizzWare.NBuilder;
using FluentAssertions;
using Moq;
@ -6,8 +7,8 @@ using NUnit.Framework;
using NzbDrone.Core.DecisionEngine.Specifications;
using NzbDrone.Core.Parser.Model;
using NzbDrone.Core.Qualities;
using NzbDrone.Core.Tv;
using NzbDrone.Core.Test.Framework;
using NzbDrone.Core.Tv;
namespace NzbDrone.Core.Test.DecisionEngineTests
{
@ -52,6 +53,10 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
};
Mocker.GetMock<IQualityDefinitionService>()
.Setup(v => v.Get(It.IsAny<Quality>()))
.Returns<Quality>(v => Quality.DefaultQualityDefinitions.First(c => c.Quality == v));
qualityType = Builder<QualityDefinition>.CreateNew()
.With(q => q.MinSize = 2)
.With(q => q.MaxSize = 10)
@ -144,7 +149,7 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
series.Runtime = 30;
parseResultSingle.Series = series;
parseResultSingle.Release.Size = 18457280000;
qualityType.MaxSize = 0;
qualityType.MaxSize = null;
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
}
@ -157,9 +162,9 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
series.Runtime = 60;
parseResultSingle.Series = series;
parseResultSingle.Release.Size = 36857280000;
qualityType.MaxSize = 0;
qualityType.MaxSize = null;
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue(); ;
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]
@ -180,12 +185,14 @@ namespace NzbDrone.Core.Test.DecisionEngineTests
[Test]
public void should_return_true_if_RAWHD()
{
var parseResult = new RemoteEpisode
{
ParsedEpisodeInfo = new ParsedEpisodeInfo { Quality = new QualityModel(Quality.RAWHD) },
};
parseResultSingle.ParsedEpisodeInfo.Quality = new QualityModel(Quality.RAWHD);
series.Runtime = 45;
parseResultSingle.Series = series;
parseResultSingle.Series.SeriesType = SeriesTypes.Daily;
parseResultSingle.Release.Size = 8000.Megabytes();
Subject.IsSatisfiedBy(parseResult, null).Accepted.Should().BeTrue();
Subject.IsSatisfiedBy(parseResultSingle, null).Accepted.Should().BeTrue();
}
[Test]

View File

@ -121,6 +121,7 @@
<Compile Include="Datastore\Migration\074_disable_eztv.cs" />
<Compile Include="Datastore\Migration\072_history_grabIdFixture.cs" />
<Compile Include="Datastore\Migration\070_delay_profileFixture.cs" />
<Compile Include="Datastore\Migration\084_update_quality_minmax_sizeFixture.cs" />
<Compile Include="Datastore\Migration\081_move_dot_prefix_to_transmission_categoryFixture.cs" />
<Compile Include="Datastore\Migration\079_dedupe_tagsFixture.cs" />
<Compile Include="Datastore\Migration\075_force_lib_updateFixture.cs" />

View File

@ -0,0 +1,46 @@
using System;
using Marr.Data.Converters;
using Marr.Data.Mapping;
namespace NzbDrone.Core.Datastore.Converters
{
public class DoubleConverter : IConverter
{
public object FromDB(ConverterContext context)
{
if (context.DbValue == DBNull.Value)
{
return DBNull.Value;
}
if (context.DbValue is Double)
{
return context.DbValue;
}
return Convert.ToDouble(context.DbValue);
}
public object FromDB(ColumnMap map, object dbValue)
{
if (dbValue == DBNull.Value)
{
return DBNull.Value;
}
if (dbValue is Double)
{
return dbValue;
}
return Convert.ToDouble(dbValue);
}
public object ToDB(object clrValue)
{
return clrValue;
}
public Type DbType { get; private set; }
}
}

View File

@ -0,0 +1,18 @@
using System.Data;
using FluentMigrator;
using NzbDrone.Core.Datastore.Migration.Framework;
namespace NzbDrone.Core.Datastore.Migration
{
[Migration(84)]
public class update_quality_minmax_size : NzbDroneMigrationBase
{
protected override void MainDbUpgrade()
{
Alter.Table("QualityDefinitions").AlterColumn("MinSize").AsDouble().Nullable();
Alter.Table("QualityDefinitions").AlterColumn("MaxSize").AsDouble().Nullable();
Execute.Sql("UPDATE QualityDefinitions SET MaxSize = NULL WHERE Quality = 10 OR MaxSize = 0");
}
}
}

View File

@ -114,6 +114,7 @@ namespace NzbDrone.Core.Datastore
RegisterProviderSettingConverter();
MapRepository.Instance.RegisterTypeConverter(typeof(Int32), new Int32Converter());
MapRepository.Instance.RegisterTypeConverter(typeof(Double), new DoubleConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(DateTime), new UtcConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter());

View File

@ -30,12 +30,6 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
var quality = subject.ParsedEpisodeInfo.Quality.Quality;
if (quality == Quality.RAWHD)
{
_logger.Debug("Raw-HD release found, skipping size check.");
return Decision.Accept();
}
if (subject.ParsedEpisodeInfo.Special)
{
_logger.Debug("Special release found, skipping size check.");
@ -43,24 +37,27 @@ namespace NzbDrone.Core.DecisionEngine.Specifications
}
var qualityDefinition = _qualityDefinitionService.Get(quality);
var minSize = qualityDefinition.MinSize.Megabytes();
//Multiply maxSize by Series.Runtime
minSize = minSize * subject.Series.Runtime * subject.Episodes.Count;
//If the parsed size is smaller than minSize we don't want it
if (subject.Release.Size < minSize)
if (qualityDefinition.MinSize.HasValue)
{
_logger.Debug("Item: {0}, Size: {1:0n} is smaller than minimum allowed size ({2:0}), rejecting.", subject, subject.Release.Size, minSize);
return Decision.Reject("{0} is smaller than minimum allowed: {1}", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix());
var minSize = qualityDefinition.MinSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime
minSize = minSize * subject.Series.Runtime * subject.Episodes.Count;
//If the parsed size is smaller than minSize we don't want it
if (subject.Release.Size < minSize)
{
_logger.Debug("Item: {0}, Size: {1:0n} is smaller than minimum allowed size ({2:0}), rejecting.", subject, subject.Release.Size, minSize);
return Decision.Reject("{0} is smaller than minimum allowed: {1}", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix());
}
}
if (qualityDefinition.MaxSize == 0)
if (!qualityDefinition.MaxSize.HasValue)
{
_logger.Debug("Max size is 0 (unlimited) - skipping check.");
_logger.Debug("Max size is unlimited - skipping check.");
}
else
{
var maxSize = qualityDefinition.MaxSize.Megabytes();
var maxSize = qualityDefinition.MaxSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime
maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;

View File

@ -30,6 +30,16 @@ namespace NzbDrone.Core
return Convert.ToInt64(gigabytes * 1024L * 1024L * 1024L);
}
public static Int64 Megabytes(this double megabytes)
{
return Convert.ToInt64(megabytes * 1024L * 1024L);
}
public static Int64 Gigabytes(this double gigabytes)
{
return Convert.ToInt64(gigabytes * 1024L * 1024L * 1024L);
}
public static Int64 Round(this long number, long level)
{

View File

@ -151,6 +151,7 @@
<Compile Include="Datastore\BasicRepository.cs" />
<Compile Include="Datastore\ConnectionStringFactory.cs" />
<Compile Include="Datastore\Converters\BooleanIntConverter.cs" />
<Compile Include="Datastore\Converters\DoubleConverter.cs" />
<Compile Include="Datastore\Converters\EmbeddedDocumentConverter.cs" />
<Compile Include="Datastore\Converters\EnumIntConverter.cs" />
<Compile Include="Datastore\Converters\TimeSpanConverter.cs" />
@ -251,6 +252,7 @@
<Compile Include="Datastore\Migration\081_move_dot_prefix_to_transmission_category.cs" />
<Compile Include="Datastore\Migration\079_dedupe_tags.cs" />
<Compile Include="Datastore\Migration\070_delay_profile.cs" />
<Compile Include="Datastore\Migration\084_update_quality_minmax_size.cs" />
<Compile Include="Datastore\Migration\083_additonal_blacklist_columns.cs" />
<Compile Include="Datastore\Migration\082_add_fanzub_settings.cs" />
<Compile Include="Datastore\Migration\Framework\MigrationContext.cs" />

View File

@ -101,7 +101,7 @@ namespace NzbDrone.Core.Qualities
new QualityDefinition(Quality.DVD) { Weight = 4, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.HDTV720p) { Weight = 5, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.HDTV1080p) { Weight = 6, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.RAWHD) { Weight = 7, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.RAWHD) { Weight = 7, MinSize = 0, MaxSize = null },
new QualityDefinition(Quality.WEBDL720p) { Weight = 8, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.Bluray720p) { Weight = 9, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.WEBDL1080p) { Weight = 10, MinSize = 0, MaxSize = 100 },

View File

@ -11,8 +11,8 @@ namespace NzbDrone.Core.Qualities
public int Weight { get; set; }
public int MinSize { get; set; }
public int MaxSize { get; set; }
public double? MinSize { get; set; }
public double? MaxSize { get; set; }
public QualityDefinition()
{

View File

@ -6,7 +6,7 @@
<div class="row">
<span class="col-md-2 col-sm-3">Quality</span>
<span class="col-md-2 col-sm-3">Title</span>
<span class="col-md-4 col-sm-6">Size Limit</span>
<span class="col-md-4 col-sm-6">Size Limit <i class="icon-sonarr-info" title="Limits are automatically adjusted for the series runtime and number of episodes in the file." /></span>
</div>
</div>
<div class="rows x-rows">

View File

@ -6,6 +6,12 @@ require('jquery-ui');
var view = Marionette.ItemView.extend({
template : 'Settings/Quality/Definition/QualityDefinitionItemViewTemplate',
className : 'row',
slider : {
min : 0,
max : 200,
step : 0.1
},
ui : {
sizeSlider : '.x-slider',
@ -31,11 +37,12 @@ var view = Marionette.ItemView.extend({
this.ui.sizeSlider.slider({
range : true,
min : 0,
max : 200,
min : this.slider.min,
max : this.slider.max,
step : this.slider.step,
values : [
this.model.get('minSize'),
this.model.get('maxSize')
this.model.get('minSize') || this.slider.min,
this.model.get('maxSize') || this.slider.max
]
});
@ -43,15 +50,22 @@ var view = Marionette.ItemView.extend({
},
_updateSize : function(event, ui) {
this.model.set('minSize', ui.values[0]);
this.model.set('maxSize', ui.values[1]);
var minSize = ui.values[0];
var maxSize = ui.values[1];
if (maxSize === this.slider.max) {
maxSize = null;
}
this.model.set('minSize', minSize);
this.model.set('maxSize', maxSize);
this._changeSize();
},
_changeSize : function() {
var minSize = this.model.get('minSize');
var maxSize = this.model.get('maxSize');
var minSize = this.model.get('minSize') || this.slider.min;
var maxSize = this.model.get('maxSize') || null;
{
var minBytes = minSize * 1024 * 1024;
@ -63,24 +77,18 @@ var view = Marionette.ItemView.extend({
}
{
if (maxSize === 0) {
if (maxSize === 0 || maxSize === null) {
this.ui.thirtyMinuteMaxSize.html('Unlimited');
this.ui.sixtyMinuteMaxSize.html('Unlimited');
} else {
var maxBytes = maxSize * 1024 * 1024;
var maxThirty = fileSize(maxBytes * 30, 1, false);
var maxSixty = fileSize(maxBytes * 60, 1, false);
return;
this.ui.thirtyMinuteMaxSize.html(maxThirty);
this.ui.sixtyMinuteMaxSize.html(maxSixty);
}
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';
}*/
}
});