1
0
mirror of https://github.com/Radarr/Radarr.git synced 2024-11-09 12:32:31 +01:00

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

View File

@ -121,6 +121,7 @@
<Compile Include="Datastore\Migration\074_disable_eztv.cs" /> <Compile Include="Datastore\Migration\074_disable_eztv.cs" />
<Compile Include="Datastore\Migration\072_history_grabIdFixture.cs" /> <Compile Include="Datastore\Migration\072_history_grabIdFixture.cs" />
<Compile Include="Datastore\Migration\070_delay_profileFixture.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\081_move_dot_prefix_to_transmission_categoryFixture.cs" />
<Compile Include="Datastore\Migration\079_dedupe_tagsFixture.cs" /> <Compile Include="Datastore\Migration\079_dedupe_tagsFixture.cs" />
<Compile Include="Datastore\Migration\075_force_lib_updateFixture.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 @@ private static void RegisterMappers()
RegisterProviderSettingConverter(); RegisterProviderSettingConverter();
MapRepository.Instance.RegisterTypeConverter(typeof(Int32), new Int32Converter()); 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(DateTime), new UtcConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(Boolean), new BooleanIntConverter());
MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter()); MapRepository.Instance.RegisterTypeConverter(typeof(Enum), new EnumIntConverter());

View File

@ -30,12 +30,6 @@ public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCr
var quality = subject.ParsedEpisodeInfo.Quality.Quality; 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) if (subject.ParsedEpisodeInfo.Special)
{ {
_logger.Debug("Special release found, skipping size check."); _logger.Debug("Special release found, skipping size check.");
@ -43,24 +37,27 @@ public Decision IsSatisfiedBy(RemoteEpisode subject, SearchCriteriaBase searchCr
} }
var qualityDefinition = _qualityDefinitionService.Get(quality); var qualityDefinition = _qualityDefinitionService.Get(quality);
var minSize = qualityDefinition.MinSize.Megabytes(); if (qualityDefinition.MinSize.HasValue)
//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); var minSize = qualityDefinition.MinSize.Value.Megabytes();
return Decision.Reject("{0} is smaller than minimum allowed: {1}", subject.Release.Size.SizeSuffix(), minSize.SizeSuffix());
//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 else
{ {
var maxSize = qualityDefinition.MaxSize.Megabytes(); var maxSize = qualityDefinition.MaxSize.Value.Megabytes();
//Multiply maxSize by Series.Runtime //Multiply maxSize by Series.Runtime
maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count; maxSize = maxSize * subject.Series.Runtime * subject.Episodes.Count;

View File

@ -30,6 +30,16 @@ public static Int64 Gigabytes(this int gigabytes)
return Convert.ToInt64(gigabytes * 1024L * 1024L * 1024L); 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) public static Int64 Round(this long number, long level)
{ {

View File

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

View File

@ -101,7 +101,7 @@ public static HashSet<QualityDefinition> DefaultQualityDefinitions
new QualityDefinition(Quality.DVD) { Weight = 4, MinSize = 0, MaxSize = 100 }, new QualityDefinition(Quality.DVD) { Weight = 4, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.HDTV720p) { Weight = 5, 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.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.WEBDL720p) { Weight = 8, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.Bluray720p) { Weight = 9, MinSize = 0, MaxSize = 100 }, new QualityDefinition(Quality.Bluray720p) { Weight = 9, MinSize = 0, MaxSize = 100 },
new QualityDefinition(Quality.WEBDL1080p) { Weight = 10, MinSize = 0, MaxSize = 100 }, new QualityDefinition(Quality.WEBDL1080p) { Weight = 10, MinSize = 0, MaxSize = 100 },

View File

@ -11,8 +11,8 @@ public class QualityDefinition : ModelBase
public int Weight { get; set; } public int Weight { get; set; }
public int MinSize { get; set; } public double? MinSize { get; set; }
public int MaxSize { get; set; } public double? MaxSize { get; set; }
public QualityDefinition() public QualityDefinition()
{ {

View File

@ -6,7 +6,7 @@
<div class="row"> <div class="row">
<span class="col-md-2 col-sm-3">Quality</span> <span class="col-md-2 col-sm-3">Quality</span>
<span class="col-md-2 col-sm-3">Title</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> </div>
<div class="rows x-rows"> <div class="rows x-rows">

View File

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